diff options
author | John W. Linville <linville@tuxdriver.com> | 2011-12-19 13:54:26 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-12-19 13:54:26 -0500 |
commit | 9f6e20cee6253c4ca5faacba8dbd09ebe70132ed (patch) | |
tree | 0dbcdabca91864daaf174bb014a5f46316880403 | |
parent | d1d182e00d72300e05b18e28372fab003d8d4a58 (diff) | |
parent | 5bd5e9a6ae5137a61d0b5c277eac61892d89fc4f (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
168 files changed, 6761 insertions, 3754 deletions
diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h index 30a3085d3354..fda56bde36b8 100644 --- a/drivers/bcma/bcma_private.h +++ b/drivers/bcma/bcma_private.h | |||
@@ -18,6 +18,9 @@ void bcma_bus_unregister(struct bcma_bus *bus); | |||
18 | int __init bcma_bus_early_register(struct bcma_bus *bus, | 18 | int __init bcma_bus_early_register(struct bcma_bus *bus, |
19 | struct bcma_device *core_cc, | 19 | struct bcma_device *core_cc, |
20 | struct bcma_device *core_mips); | 20 | struct bcma_device *core_mips); |
21 | #ifdef CONFIG_PM | ||
22 | int bcma_bus_resume(struct bcma_bus *bus); | ||
23 | #endif | ||
21 | 24 | ||
22 | /* scan.c */ | 25 | /* scan.c */ |
23 | int bcma_bus_scan(struct bcma_bus *bus); | 26 | int bcma_bus_scan(struct bcma_bus *bus); |
diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c index b0994c0e05dc..443b83a2fd7a 100644 --- a/drivers/bcma/host_pci.c +++ b/drivers/bcma/host_pci.c | |||
@@ -234,6 +234,41 @@ static void bcma_host_pci_remove(struct pci_dev *dev) | |||
234 | pci_set_drvdata(dev, NULL); | 234 | pci_set_drvdata(dev, NULL); |
235 | } | 235 | } |
236 | 236 | ||
237 | #ifdef CONFIG_PM | ||
238 | static int bcma_host_pci_suspend(struct pci_dev *dev, pm_message_t state) | ||
239 | { | ||
240 | /* Host specific */ | ||
241 | pci_save_state(dev); | ||
242 | pci_disable_device(dev); | ||
243 | pci_set_power_state(dev, pci_choose_state(dev, state)); | ||
244 | |||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | static int bcma_host_pci_resume(struct pci_dev *dev) | ||
249 | { | ||
250 | struct bcma_bus *bus = pci_get_drvdata(dev); | ||
251 | int err; | ||
252 | |||
253 | /* Host specific */ | ||
254 | pci_set_power_state(dev, 0); | ||
255 | err = pci_enable_device(dev); | ||
256 | if (err) | ||
257 | return err; | ||
258 | pci_restore_state(dev); | ||
259 | |||
260 | /* Bus specific */ | ||
261 | err = bcma_bus_resume(bus); | ||
262 | if (err) | ||
263 | return err; | ||
264 | |||
265 | return 0; | ||
266 | } | ||
267 | #else /* CONFIG_PM */ | ||
268 | # define bcma_host_pci_suspend NULL | ||
269 | # define bcma_host_pci_resume NULL | ||
270 | #endif /* CONFIG_PM */ | ||
271 | |||
237 | static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = { | 272 | static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = { |
238 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, | 273 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, |
239 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) }, | 274 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) }, |
@@ -249,6 +284,8 @@ static struct pci_driver bcma_pci_bridge_driver = { | |||
249 | .id_table = bcma_pci_bridge_tbl, | 284 | .id_table = bcma_pci_bridge_tbl, |
250 | .probe = bcma_host_pci_probe, | 285 | .probe = bcma_host_pci_probe, |
251 | .remove = bcma_host_pci_remove, | 286 | .remove = bcma_host_pci_remove, |
287 | .suspend = bcma_host_pci_suspend, | ||
288 | .resume = bcma_host_pci_resume, | ||
252 | }; | 289 | }; |
253 | 290 | ||
254 | int __init bcma_host_pci_init(void) | 291 | int __init bcma_host_pci_init(void) |
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index 70c84b951098..10f92b371e58 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c | |||
@@ -240,6 +240,22 @@ int __init bcma_bus_early_register(struct bcma_bus *bus, | |||
240 | return 0; | 240 | return 0; |
241 | } | 241 | } |
242 | 242 | ||
243 | #ifdef CONFIG_PM | ||
244 | int bcma_bus_resume(struct bcma_bus *bus) | ||
245 | { | ||
246 | struct bcma_device *core; | ||
247 | |||
248 | /* Init CC core */ | ||
249 | core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON); | ||
250 | if (core) { | ||
251 | bus->drv_cc.setup_done = false; | ||
252 | bcma_core_chipcommon_init(&bus->drv_cc); | ||
253 | } | ||
254 | |||
255 | return 0; | ||
256 | } | ||
257 | #endif | ||
258 | |||
243 | int __bcma_driver_register(struct bcma_driver *drv, struct module *owner) | 259 | int __bcma_driver_register(struct bcma_driver *drv, struct module *owner) |
244 | { | 260 | { |
245 | drv->drv.name = drv->name; | 261 | drv->drv.name = drv->name; |
diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c index d7292390d236..6f230fb087c5 100644 --- a/drivers/bcma/sprom.c +++ b/drivers/bcma/sprom.c | |||
@@ -129,6 +129,9 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom) | |||
129 | u16 v; | 129 | u16 v; |
130 | int i; | 130 | int i; |
131 | 131 | ||
132 | bus->sprom.revision = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & | ||
133 | SSB_SPROM_REVISION_REV; | ||
134 | |||
132 | for (i = 0; i < 3; i++) { | 135 | for (i = 0; i < 3; i++) { |
133 | v = sprom[SPOFF(SSB_SPROM8_IL0MAC) + i]; | 136 | v = sprom[SPOFF(SSB_SPROM8_IL0MAC) + i]; |
134 | *(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v); | 137 | *(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v); |
@@ -136,12 +139,70 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom) | |||
136 | 139 | ||
137 | bus->sprom.board_rev = sprom[SPOFF(SSB_SPROM8_BOARDREV)]; | 140 | bus->sprom.board_rev = sprom[SPOFF(SSB_SPROM8_BOARDREV)]; |
138 | 141 | ||
142 | bus->sprom.txpid2g[0] = (sprom[SPOFF(SSB_SPROM4_TXPID2G01)] & | ||
143 | SSB_SPROM4_TXPID2G0) >> SSB_SPROM4_TXPID2G0_SHIFT; | ||
144 | bus->sprom.txpid2g[1] = (sprom[SPOFF(SSB_SPROM4_TXPID2G01)] & | ||
145 | SSB_SPROM4_TXPID2G1) >> SSB_SPROM4_TXPID2G1_SHIFT; | ||
146 | bus->sprom.txpid2g[2] = (sprom[SPOFF(SSB_SPROM4_TXPID2G23)] & | ||
147 | SSB_SPROM4_TXPID2G2) >> SSB_SPROM4_TXPID2G2_SHIFT; | ||
148 | bus->sprom.txpid2g[3] = (sprom[SPOFF(SSB_SPROM4_TXPID2G23)] & | ||
149 | SSB_SPROM4_TXPID2G3) >> SSB_SPROM4_TXPID2G3_SHIFT; | ||
150 | |||
151 | bus->sprom.txpid5gl[0] = (sprom[SPOFF(SSB_SPROM4_TXPID5GL01)] & | ||
152 | SSB_SPROM4_TXPID5GL0) >> SSB_SPROM4_TXPID5GL0_SHIFT; | ||
153 | bus->sprom.txpid5gl[1] = (sprom[SPOFF(SSB_SPROM4_TXPID5GL01)] & | ||
154 | SSB_SPROM4_TXPID5GL1) >> SSB_SPROM4_TXPID5GL1_SHIFT; | ||
155 | bus->sprom.txpid5gl[2] = (sprom[SPOFF(SSB_SPROM4_TXPID5GL23)] & | ||
156 | SSB_SPROM4_TXPID5GL2) >> SSB_SPROM4_TXPID5GL2_SHIFT; | ||
157 | bus->sprom.txpid5gl[3] = (sprom[SPOFF(SSB_SPROM4_TXPID5GL23)] & | ||
158 | SSB_SPROM4_TXPID5GL3) >> SSB_SPROM4_TXPID5GL3_SHIFT; | ||
159 | |||
160 | bus->sprom.txpid5g[0] = (sprom[SPOFF(SSB_SPROM4_TXPID5G01)] & | ||
161 | SSB_SPROM4_TXPID5G0) >> SSB_SPROM4_TXPID5G0_SHIFT; | ||
162 | bus->sprom.txpid5g[1] = (sprom[SPOFF(SSB_SPROM4_TXPID5G01)] & | ||
163 | SSB_SPROM4_TXPID5G1) >> SSB_SPROM4_TXPID5G1_SHIFT; | ||
164 | bus->sprom.txpid5g[2] = (sprom[SPOFF(SSB_SPROM4_TXPID5G23)] & | ||
165 | SSB_SPROM4_TXPID5G2) >> SSB_SPROM4_TXPID5G2_SHIFT; | ||
166 | bus->sprom.txpid5g[3] = (sprom[SPOFF(SSB_SPROM4_TXPID5G23)] & | ||
167 | SSB_SPROM4_TXPID5G3) >> SSB_SPROM4_TXPID5G3_SHIFT; | ||
168 | |||
169 | bus->sprom.txpid5gh[0] = (sprom[SPOFF(SSB_SPROM4_TXPID5GH01)] & | ||
170 | SSB_SPROM4_TXPID5GH0) >> SSB_SPROM4_TXPID5GH0_SHIFT; | ||
171 | bus->sprom.txpid5gh[1] = (sprom[SPOFF(SSB_SPROM4_TXPID5GH01)] & | ||
172 | SSB_SPROM4_TXPID5GH1) >> SSB_SPROM4_TXPID5GH1_SHIFT; | ||
173 | bus->sprom.txpid5gh[2] = (sprom[SPOFF(SSB_SPROM4_TXPID5GH23)] & | ||
174 | SSB_SPROM4_TXPID5GH2) >> SSB_SPROM4_TXPID5GH2_SHIFT; | ||
175 | bus->sprom.txpid5gh[3] = (sprom[SPOFF(SSB_SPROM4_TXPID5GH23)] & | ||
176 | SSB_SPROM4_TXPID5GH3) >> SSB_SPROM4_TXPID5GH3_SHIFT; | ||
177 | |||
139 | bus->sprom.boardflags_lo = sprom[SPOFF(SSB_SPROM8_BFLLO)]; | 178 | bus->sprom.boardflags_lo = sprom[SPOFF(SSB_SPROM8_BFLLO)]; |
140 | bus->sprom.boardflags_hi = sprom[SPOFF(SSB_SPROM8_BFLHI)]; | 179 | bus->sprom.boardflags_hi = sprom[SPOFF(SSB_SPROM8_BFLHI)]; |
141 | bus->sprom.boardflags2_lo = sprom[SPOFF(SSB_SPROM8_BFL2LO)]; | 180 | bus->sprom.boardflags2_lo = sprom[SPOFF(SSB_SPROM8_BFL2LO)]; |
142 | bus->sprom.boardflags2_hi = sprom[SPOFF(SSB_SPROM8_BFL2HI)]; | 181 | bus->sprom.boardflags2_hi = sprom[SPOFF(SSB_SPROM8_BFL2HI)]; |
143 | 182 | ||
144 | bus->sprom.country_code = sprom[SPOFF(SSB_SPROM8_CCODE)]; | 183 | bus->sprom.country_code = sprom[SPOFF(SSB_SPROM8_CCODE)]; |
184 | |||
185 | bus->sprom.fem.ghz2.tssipos = (sprom[SPOFF(SSB_SPROM8_FEM2G)] & | ||
186 | SSB_SROM8_FEM_TSSIPOS) >> SSB_SROM8_FEM_TSSIPOS_SHIFT; | ||
187 | bus->sprom.fem.ghz2.extpa_gain = (sprom[SPOFF(SSB_SPROM8_FEM2G)] & | ||
188 | SSB_SROM8_FEM_EXTPA_GAIN) >> SSB_SROM8_FEM_EXTPA_GAIN_SHIFT; | ||
189 | bus->sprom.fem.ghz2.pdet_range = (sprom[SPOFF(SSB_SPROM8_FEM2G)] & | ||
190 | SSB_SROM8_FEM_PDET_RANGE) >> SSB_SROM8_FEM_PDET_RANGE_SHIFT; | ||
191 | bus->sprom.fem.ghz2.tr_iso = (sprom[SPOFF(SSB_SPROM8_FEM2G)] & | ||
192 | SSB_SROM8_FEM_TR_ISO) >> SSB_SROM8_FEM_TR_ISO_SHIFT; | ||
193 | bus->sprom.fem.ghz2.antswlut = (sprom[SPOFF(SSB_SPROM8_FEM2G)] & | ||
194 | SSB_SROM8_FEM_ANTSWLUT) >> SSB_SROM8_FEM_ANTSWLUT_SHIFT; | ||
195 | |||
196 | bus->sprom.fem.ghz5.tssipos = (sprom[SPOFF(SSB_SPROM8_FEM5G)] & | ||
197 | SSB_SROM8_FEM_TSSIPOS) >> SSB_SROM8_FEM_TSSIPOS_SHIFT; | ||
198 | bus->sprom.fem.ghz5.extpa_gain = (sprom[SPOFF(SSB_SPROM8_FEM5G)] & | ||
199 | SSB_SROM8_FEM_EXTPA_GAIN) >> SSB_SROM8_FEM_EXTPA_GAIN_SHIFT; | ||
200 | bus->sprom.fem.ghz5.pdet_range = (sprom[SPOFF(SSB_SPROM8_FEM5G)] & | ||
201 | SSB_SROM8_FEM_PDET_RANGE) >> SSB_SROM8_FEM_PDET_RANGE_SHIFT; | ||
202 | bus->sprom.fem.ghz5.tr_iso = (sprom[SPOFF(SSB_SPROM8_FEM5G)] & | ||
203 | SSB_SROM8_FEM_TR_ISO) >> SSB_SROM8_FEM_TR_ISO_SHIFT; | ||
204 | bus->sprom.fem.ghz5.antswlut = (sprom[SPOFF(SSB_SPROM8_FEM5G)] & | ||
205 | SSB_SROM8_FEM_ANTSWLUT) >> SSB_SROM8_FEM_ANTSWLUT_SHIFT; | ||
145 | } | 206 | } |
146 | 207 | ||
147 | int bcma_sprom_get(struct bcma_bus *bus) | 208 | int bcma_sprom_get(struct bcma_bus *bus) |
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index 4596c33a7a69..c1d699fd5717 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h | |||
@@ -152,6 +152,7 @@ struct ath_common { | |||
152 | struct ath_cycle_counters cc_survey; | 152 | struct ath_cycle_counters cc_survey; |
153 | 153 | ||
154 | struct ath_regulatory regulatory; | 154 | struct ath_regulatory regulatory; |
155 | struct ath_regulatory reg_world_copy; | ||
155 | const struct ath_ops *ops; | 156 | const struct ath_ops *ops; |
156 | const struct ath_bus_ops *bus_ops; | 157 | const struct ath_bus_ops *bus_ops; |
157 | 158 | ||
@@ -214,6 +215,10 @@ do { \ | |||
214 | * @ATH_DBG_HWTIMER: hardware timer handling | 215 | * @ATH_DBG_HWTIMER: hardware timer handling |
215 | * @ATH_DBG_BTCOEX: bluetooth coexistance | 216 | * @ATH_DBG_BTCOEX: bluetooth coexistance |
216 | * @ATH_DBG_BSTUCK: stuck beacons | 217 | * @ATH_DBG_BSTUCK: stuck beacons |
218 | * @ATH_DBG_MCI: Message Coexistence Interface, a private protocol | ||
219 | * used exclusively for WLAN-BT coexistence starting from | ||
220 | * AR9462. | ||
221 | * @ATH_DBG_DFS: radar datection | ||
217 | * @ATH_DBG_ANY: enable all debugging | 222 | * @ATH_DBG_ANY: enable all debugging |
218 | * | 223 | * |
219 | * The debug level is used to control the amount and type of debugging output | 224 | * The debug level is used to control the amount and type of debugging output |
@@ -240,6 +245,7 @@ enum ATH_DEBUG { | |||
240 | ATH_DBG_WMI = 0x00004000, | 245 | ATH_DBG_WMI = 0x00004000, |
241 | ATH_DBG_BSTUCK = 0x00008000, | 246 | ATH_DBG_BSTUCK = 0x00008000, |
242 | ATH_DBG_MCI = 0x00010000, | 247 | ATH_DBG_MCI = 0x00010000, |
248 | ATH_DBG_DFS = 0x00020000, | ||
243 | ATH_DBG_ANY = 0xffffffff | 249 | ATH_DBG_ANY = 0xffffffff |
244 | }; | 250 | }; |
245 | 251 | ||
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig index 7b4c074e12fa..1b4786ae00ac 100644 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig | |||
@@ -2,6 +2,9 @@ config ATH9K_HW | |||
2 | tristate | 2 | tristate |
3 | config ATH9K_COMMON | 3 | config ATH9K_COMMON |
4 | tristate | 4 | tristate |
5 | config ATH9K_DFS_DEBUGFS | ||
6 | def_bool y | ||
7 | depends on ATH9K_DEBUGFS && ATH9K_DFS_CERTIFIED | ||
5 | 8 | ||
6 | config ATH9K | 9 | config ATH9K |
7 | tristate "Atheros 802.11n wireless cards support" | 10 | tristate "Atheros 802.11n wireless cards support" |
@@ -51,6 +54,25 @@ config ATH9K_DEBUGFS | |||
51 | 54 | ||
52 | Also required for changing debug message flags at run time. | 55 | Also required for changing debug message flags at run time. |
53 | 56 | ||
57 | config ATH9K_DFS_CERTIFIED | ||
58 | bool "Atheros DFS support for certified platforms" | ||
59 | depends on ATH9K && EXPERT | ||
60 | default n | ||
61 | ---help--- | ||
62 | This option enables DFS support for initiating radiation on | ||
63 | ath9k. There is no way to dynamically detect if a card was DFS | ||
64 | certified and as such this is left as a build time option. This | ||
65 | option should only be enabled by system integrators that can | ||
66 | guarantee that all the platforms that their kernel will run on | ||
67 | have obtained appropriate regulatory body certification for a | ||
68 | respective Atheros card by using ath9k on the target shipping | ||
69 | platforms. | ||
70 | |||
71 | This is currently only a placeholder for future DFS support, | ||
72 | as DFS support requires more components that still need to be | ||
73 | developed. At this point enabling this option won't do anything | ||
74 | except increase code size. | ||
75 | |||
54 | config ATH9K_RATE_CONTROL | 76 | config ATH9K_RATE_CONTROL |
55 | bool "Atheros ath9k rate control" | 77 | bool "Atheros ath9k rate control" |
56 | depends on ATH9K | 78 | depends on ATH9K |
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 390797db5273..da02242499af 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile | |||
@@ -10,6 +10,8 @@ ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o | |||
10 | ath9k-$(CONFIG_ATH9K_PCI) += pci.o | 10 | ath9k-$(CONFIG_ATH9K_PCI) += pci.o |
11 | ath9k-$(CONFIG_ATH9K_AHB) += ahb.o | 11 | ath9k-$(CONFIG_ATH9K_AHB) += ahb.o |
12 | ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o | 12 | ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o |
13 | ath9k-$(CONFIG_ATH9K_DFS_DEBUGFS) += dfs_debug.o | ||
14 | ath9k-$(CONFIG_ATH9K_DFS_CERTIFIED) += dfs.o | ||
13 | 15 | ||
14 | obj-$(CONFIG_ATH9K) += ath9k.o | 16 | obj-$(CONFIG_ATH9K) += ath9k.o |
15 | 17 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index 95587e36ab9c..631fe4f2e495 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c | |||
@@ -187,40 +187,12 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) | |||
187 | isr = REG_READ(ah, AR_ISR); | 187 | isr = REG_READ(ah, AR_ISR); |
188 | } | 188 | } |
189 | 189 | ||
190 | if (async_cause & AR_INTR_ASYNC_MASK_MCI) { | ||
191 | u32 raw_intr, rx_msg_intr; | ||
192 | |||
193 | rx_msg_intr = REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW); | ||
194 | raw_intr = REG_READ(ah, AR_MCI_INTERRUPT_RAW); | ||
195 | |||
196 | if ((raw_intr == 0xdeadbeef) || (rx_msg_intr == 0xdeadbeef)) | ||
197 | ath_dbg(common, ATH_DBG_MCI, | ||
198 | "MCI gets 0xdeadbeef during MCI int processing" | ||
199 | "new raw_intr=0x%08x, new rx_msg_raw=0x%08x, " | ||
200 | "raw_intr=0x%08x, rx_msg_raw=0x%08x\n", | ||
201 | raw_intr, rx_msg_intr, mci->raw_intr, | ||
202 | mci->rx_msg_intr); | ||
203 | else { | ||
204 | mci->rx_msg_intr |= rx_msg_intr; | ||
205 | mci->raw_intr |= raw_intr; | ||
206 | *masked |= ATH9K_INT_MCI; | ||
207 | |||
208 | if (rx_msg_intr & AR_MCI_INTERRUPT_RX_MSG_CONT_INFO) | ||
209 | mci->cont_status = | ||
210 | REG_READ(ah, AR_MCI_CONT_STATUS); | ||
211 | |||
212 | REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, rx_msg_intr); | ||
213 | REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, raw_intr); | ||
214 | ath_dbg(common, ATH_DBG_MCI, "AR_INTR_SYNC_MCI\n"); | ||
215 | |||
216 | } | ||
217 | } | ||
218 | 190 | ||
219 | sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) & AR_INTR_SYNC_DEFAULT; | 191 | sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) & AR_INTR_SYNC_DEFAULT; |
220 | 192 | ||
221 | *masked = 0; | 193 | *masked = 0; |
222 | 194 | ||
223 | if (!isr && !sync_cause) | 195 | if (!isr && !sync_cause && !async_cause) |
224 | return false; | 196 | return false; |
225 | 197 | ||
226 | if (isr) { | 198 | if (isr) { |
@@ -326,6 +298,35 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) | |||
326 | ar9003_hw_bb_watchdog_read(ah); | 298 | ar9003_hw_bb_watchdog_read(ah); |
327 | } | 299 | } |
328 | 300 | ||
301 | if (async_cause & AR_INTR_ASYNC_MASK_MCI) { | ||
302 | u32 raw_intr, rx_msg_intr; | ||
303 | |||
304 | rx_msg_intr = REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW); | ||
305 | raw_intr = REG_READ(ah, AR_MCI_INTERRUPT_RAW); | ||
306 | |||
307 | if ((raw_intr == 0xdeadbeef) || (rx_msg_intr == 0xdeadbeef)) | ||
308 | ath_dbg(common, ATH_DBG_MCI, | ||
309 | "MCI gets 0xdeadbeef during MCI int processing" | ||
310 | "new raw_intr=0x%08x, new rx_msg_raw=0x%08x, " | ||
311 | "raw_intr=0x%08x, rx_msg_raw=0x%08x\n", | ||
312 | raw_intr, rx_msg_intr, mci->raw_intr, | ||
313 | mci->rx_msg_intr); | ||
314 | else { | ||
315 | mci->rx_msg_intr |= rx_msg_intr; | ||
316 | mci->raw_intr |= raw_intr; | ||
317 | *masked |= ATH9K_INT_MCI; | ||
318 | |||
319 | if (rx_msg_intr & AR_MCI_INTERRUPT_RX_MSG_CONT_INFO) | ||
320 | mci->cont_status = | ||
321 | REG_READ(ah, AR_MCI_CONT_STATUS); | ||
322 | |||
323 | REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, rx_msg_intr); | ||
324 | REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, raw_intr); | ||
325 | ath_dbg(common, ATH_DBG_MCI, "AR_INTR_SYNC_MCI\n"); | ||
326 | |||
327 | } | ||
328 | } | ||
329 | |||
329 | if (sync_cause) { | 330 | if (sync_cause) { |
330 | if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { | 331 | if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { |
331 | REG_WRITE(ah, AR_RC, AR_RC_HOSTIF); | 332 | REG_WRITE(ah, AR_RC, AR_RC_HOSTIF); |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index afc156a0a2e3..130e5dba9555 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -159,6 +159,9 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd, | |||
159 | /* return block-ack bitmap index given sequence and starting sequence */ | 159 | /* return block-ack bitmap index given sequence and starting sequence */ |
160 | #define ATH_BA_INDEX(_st, _seq) (((_seq) - (_st)) & (IEEE80211_SEQ_MAX - 1)) | 160 | #define ATH_BA_INDEX(_st, _seq) (((_seq) - (_st)) & (IEEE80211_SEQ_MAX - 1)) |
161 | 161 | ||
162 | /* return the seqno for _start + _offset */ | ||
163 | #define ATH_BA_INDEX2SEQ(_seq, _offset) (((_seq) + (_offset)) & (IEEE80211_SEQ_MAX - 1)) | ||
164 | |||
162 | /* returns delimiter padding required given the packet length */ | 165 | /* returns delimiter padding required given the packet length */ |
163 | #define ATH_AGGR_GET_NDELIM(_len) \ | 166 | #define ATH_AGGR_GET_NDELIM(_len) \ |
164 | (((_len) >= ATH_AGGR_MINPLEN) ? 0 : \ | 167 | (((_len) >= ATH_AGGR_MINPLEN) ? 0 : \ |
@@ -238,6 +241,7 @@ struct ath_atx_tid { | |||
238 | struct ath_node *an; | 241 | struct ath_node *an; |
239 | struct ath_atx_ac *ac; | 242 | struct ath_atx_ac *ac; |
240 | unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)]; | 243 | unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)]; |
244 | int bar_index; | ||
241 | u16 seq_start; | 245 | u16 seq_start; |
242 | u16 seq_next; | 246 | u16 seq_next; |
243 | u16 baw_size; | 247 | u16 baw_size; |
@@ -252,9 +256,9 @@ struct ath_atx_tid { | |||
252 | struct ath_node { | 256 | struct ath_node { |
253 | #ifdef CONFIG_ATH9K_DEBUGFS | 257 | #ifdef CONFIG_ATH9K_DEBUGFS |
254 | struct list_head list; /* for sc->nodes */ | 258 | struct list_head list; /* for sc->nodes */ |
259 | #endif | ||
255 | struct ieee80211_sta *sta; /* station struct we're part of */ | 260 | struct ieee80211_sta *sta; /* station struct we're part of */ |
256 | struct ieee80211_vif *vif; /* interface with which we're associated */ | 261 | struct ieee80211_vif *vif; /* interface with which we're associated */ |
257 | #endif | ||
258 | struct ath_atx_tid tid[WME_NUM_TID]; | 262 | struct ath_atx_tid tid[WME_NUM_TID]; |
259 | struct ath_atx_ac ac[WME_NUM_AC]; | 263 | struct ath_atx_ac ac[WME_NUM_AC]; |
260 | int ps_key; | 264 | int ps_key; |
@@ -276,7 +280,6 @@ struct ath_tx_control { | |||
276 | }; | 280 | }; |
277 | 281 | ||
278 | #define ATH_TX_ERROR 0x01 | 282 | #define ATH_TX_ERROR 0x01 |
279 | #define ATH_TX_BAR 0x02 | ||
280 | 283 | ||
281 | /** | 284 | /** |
282 | * @txq_map: Index is mac80211 queue number. This is | 285 | * @txq_map: Index is mac80211 queue number. This is |
@@ -542,7 +545,7 @@ struct ath_ant_comb { | |||
542 | #define DEFAULT_CACHELINE 32 | 545 | #define DEFAULT_CACHELINE 32 |
543 | #define ATH_REGCLASSIDS_MAX 10 | 546 | #define ATH_REGCLASSIDS_MAX 10 |
544 | #define ATH_CABQ_READY_TIME 80 /* % of beacon interval */ | 547 | #define ATH_CABQ_READY_TIME 80 /* % of beacon interval */ |
545 | #define ATH_MAX_SW_RETRIES 10 | 548 | #define ATH_MAX_SW_RETRIES 30 |
546 | #define ATH_CHAN_MAX 255 | 549 | #define ATH_CHAN_MAX 255 |
547 | 550 | ||
548 | #define ATH_TXPOWER_MAX 100 /* .5 dBm units */ | 551 | #define ATH_TXPOWER_MAX 100 /* .5 dBm units */ |
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 6fb719d85b37..68d972bf232d 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -856,7 +856,7 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, | |||
856 | sc->debug.stats.txstats[qnum].tx_bytes_all += bf->bf_mpdu->len; | 856 | sc->debug.stats.txstats[qnum].tx_bytes_all += bf->bf_mpdu->len; |
857 | 857 | ||
858 | if (bf_isampdu(bf)) { | 858 | if (bf_isampdu(bf)) { |
859 | if (flags & ATH_TX_BAR) | 859 | if (flags & ATH_TX_ERROR) |
860 | TX_STAT_INC(qnum, a_xretries); | 860 | TX_STAT_INC(qnum, a_xretries); |
861 | else | 861 | else |
862 | TX_STAT_INC(qnum, a_completed); | 862 | TX_STAT_INC(qnum, a_completed); |
@@ -1630,6 +1630,9 @@ int ath9k_init_debug(struct ath_hw *ah) | |||
1630 | debugfs_create_file("debug", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, | 1630 | debugfs_create_file("debug", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, |
1631 | sc, &fops_debug); | 1631 | sc, &fops_debug); |
1632 | #endif | 1632 | #endif |
1633 | |||
1634 | ath9k_dfs_init_debug(sc); | ||
1635 | |||
1633 | debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, sc, | 1636 | debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, sc, |
1634 | &fops_dma); | 1637 | &fops_dma); |
1635 | debugfs_create_file("interrupt", S_IRUSR, sc->debug.debugfs_phy, sc, | 1638 | debugfs_create_file("interrupt", S_IRUSR, sc->debug.debugfs_phy, sc, |
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 356352ac2d6e..776a24ada600 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h | |||
@@ -19,6 +19,7 @@ | |||
19 | 19 | ||
20 | #include "hw.h" | 20 | #include "hw.h" |
21 | #include "rc.h" | 21 | #include "rc.h" |
22 | #include "dfs_debug.h" | ||
22 | 23 | ||
23 | struct ath_txq; | 24 | struct ath_txq; |
24 | struct ath_buf; | 25 | struct ath_buf; |
@@ -187,6 +188,7 @@ struct ath_stats { | |||
187 | struct ath_interrupt_stats istats; | 188 | struct ath_interrupt_stats istats; |
188 | struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES]; | 189 | struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES]; |
189 | struct ath_rx_stats rxstats; | 190 | struct ath_rx_stats rxstats; |
191 | struct ath_dfs_stats dfs_stats; | ||
190 | u32 reset[__RESET_TYPE_MAX]; | 192 | u32 reset[__RESET_TYPE_MAX]; |
191 | }; | 193 | }; |
192 | 194 | ||
diff --git a/drivers/net/wireless/ath/ath9k/dfs.c b/drivers/net/wireless/ath/ath9k/dfs.c new file mode 100644 index 000000000000..e4e84a9e6273 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/dfs.c | |||
@@ -0,0 +1,215 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-2011 Atheros Communications Inc. | ||
3 | * Copyright (c) 2011 Neratec Solutions AG | ||
4 | * | ||
5 | * Permission to use, copy, modify, and/or distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | #include "hw.h" | ||
19 | #include "hw-ops.h" | ||
20 | #include "ath9k.h" | ||
21 | #include "dfs.h" | ||
22 | #include "dfs_debug.h" | ||
23 | |||
24 | /* | ||
25 | * TODO: move into or synchronize this with generic header | ||
26 | * as soon as IF is defined | ||
27 | */ | ||
28 | struct dfs_radar_pulse { | ||
29 | u16 freq; | ||
30 | u64 ts; | ||
31 | u32 width; | ||
32 | u8 rssi; | ||
33 | }; | ||
34 | |||
35 | /* internal struct to pass radar data */ | ||
36 | struct ath_radar_data { | ||
37 | u8 pulse_bw_info; | ||
38 | u8 rssi; | ||
39 | u8 ext_rssi; | ||
40 | u8 pulse_length_ext; | ||
41 | u8 pulse_length_pri; | ||
42 | }; | ||
43 | |||
44 | /* convert pulse duration to usecs, considering clock mode */ | ||
45 | static u32 dur_to_usecs(struct ath_hw *ah, u32 dur) | ||
46 | { | ||
47 | const u32 AR93X_NSECS_PER_DUR = 800; | ||
48 | const u32 AR93X_NSECS_PER_DUR_FAST = (8000 / 11); | ||
49 | u32 nsecs; | ||
50 | |||
51 | if (IS_CHAN_A_FAST_CLOCK(ah, ah->curchan)) | ||
52 | nsecs = dur * AR93X_NSECS_PER_DUR_FAST; | ||
53 | else | ||
54 | nsecs = dur * AR93X_NSECS_PER_DUR; | ||
55 | |||
56 | return (nsecs + 500) / 1000; | ||
57 | } | ||
58 | |||
59 | #define PRI_CH_RADAR_FOUND 0x01 | ||
60 | #define EXT_CH_RADAR_FOUND 0x02 | ||
61 | static bool | ||
62 | ath9k_postprocess_radar_event(struct ath_softc *sc, | ||
63 | struct ath_radar_data *are, | ||
64 | struct dfs_radar_pulse *drp) | ||
65 | { | ||
66 | u8 rssi; | ||
67 | u16 dur; | ||
68 | |||
69 | ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_DFS, | ||
70 | "pulse_bw_info=0x%x, pri,ext len/rssi=(%u/%u, %u/%u)\n", | ||
71 | are->pulse_bw_info, | ||
72 | are->pulse_length_pri, are->rssi, | ||
73 | are->pulse_length_ext, are->ext_rssi); | ||
74 | |||
75 | /* | ||
76 | * Only the last 2 bits of the BW info are relevant, they indicate | ||
77 | * which channel the radar was detected in. | ||
78 | */ | ||
79 | are->pulse_bw_info &= 0x03; | ||
80 | |||
81 | switch (are->pulse_bw_info) { | ||
82 | case PRI_CH_RADAR_FOUND: | ||
83 | /* radar in ctrl channel */ | ||
84 | dur = are->pulse_length_pri; | ||
85 | DFS_STAT_INC(sc, pri_phy_errors); | ||
86 | /* | ||
87 | * cannot use ctrl channel RSSI | ||
88 | * if extension channel is stronger | ||
89 | */ | ||
90 | rssi = (are->ext_rssi >= (are->rssi + 3)) ? 0 : are->rssi; | ||
91 | break; | ||
92 | case EXT_CH_RADAR_FOUND: | ||
93 | /* radar in extension channel */ | ||
94 | dur = are->pulse_length_ext; | ||
95 | DFS_STAT_INC(sc, ext_phy_errors); | ||
96 | /* | ||
97 | * cannot use extension channel RSSI | ||
98 | * if control channel is stronger | ||
99 | */ | ||
100 | rssi = (are->rssi >= (are->ext_rssi + 12)) ? 0 : are->ext_rssi; | ||
101 | break; | ||
102 | case (PRI_CH_RADAR_FOUND | EXT_CH_RADAR_FOUND): | ||
103 | /* | ||
104 | * Conducted testing, when pulse is on DC, both pri and ext | ||
105 | * durations are reported to be same | ||
106 | * | ||
107 | * Radiated testing, when pulse is on DC, different pri and | ||
108 | * ext durations are reported, so take the larger of the two | ||
109 | */ | ||
110 | if (are->pulse_length_ext >= are->pulse_length_pri) | ||
111 | dur = are->pulse_length_ext; | ||
112 | else | ||
113 | dur = are->pulse_length_pri; | ||
114 | DFS_STAT_INC(sc, dc_phy_errors); | ||
115 | |||
116 | /* when both are present use stronger one */ | ||
117 | rssi = (are->rssi < are->ext_rssi) ? are->ext_rssi : are->rssi; | ||
118 | break; | ||
119 | default: | ||
120 | /* | ||
121 | * Bogus bandwidth info was received in descriptor, | ||
122 | * so ignore this PHY error | ||
123 | */ | ||
124 | DFS_STAT_INC(sc, bwinfo_discards); | ||
125 | return false; | ||
126 | } | ||
127 | |||
128 | if (rssi == 0) { | ||
129 | DFS_STAT_INC(sc, rssi_discards); | ||
130 | return false; | ||
131 | } | ||
132 | |||
133 | /* | ||
134 | * TODO: check chirping pulses | ||
135 | * checks for chirping are dependent on the DFS regulatory domain | ||
136 | * used, which is yet TBD | ||
137 | */ | ||
138 | |||
139 | /* convert duration to usecs */ | ||
140 | drp->width = dur_to_usecs(sc->sc_ah, dur); | ||
141 | drp->rssi = rssi; | ||
142 | |||
143 | DFS_STAT_INC(sc, pulses_detected); | ||
144 | return true; | ||
145 | } | ||
146 | #undef PRI_CH_RADAR_FOUND | ||
147 | #undef EXT_CH_RADAR_FOUND | ||
148 | |||
149 | /* | ||
150 | * DFS: check PHY-error for radar pulse and feed the detector | ||
151 | */ | ||
152 | void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data, | ||
153 | struct ath_rx_status *rs, u64 mactime) | ||
154 | { | ||
155 | struct ath_radar_data ard; | ||
156 | u16 datalen; | ||
157 | char *vdata_end; | ||
158 | struct dfs_radar_pulse drp; | ||
159 | struct ath_hw *ah = sc->sc_ah; | ||
160 | struct ath_common *common = ath9k_hw_common(ah); | ||
161 | |||
162 | if ((!(rs->rs_phyerr != ATH9K_PHYERR_RADAR)) && | ||
163 | (!(rs->rs_phyerr != ATH9K_PHYERR_FALSE_RADAR_EXT))) { | ||
164 | ath_dbg(common, ATH_DBG_DFS, | ||
165 | "Error: rs_phyer=0x%x not a radar error\n", | ||
166 | rs->rs_phyerr); | ||
167 | return; | ||
168 | } | ||
169 | |||
170 | datalen = rs->rs_datalen; | ||
171 | if (datalen == 0) { | ||
172 | DFS_STAT_INC(sc, datalen_discards); | ||
173 | return; | ||
174 | } | ||
175 | |||
176 | ard.rssi = rs->rs_rssi_ctl0; | ||
177 | ard.ext_rssi = rs->rs_rssi_ext0; | ||
178 | |||
179 | /* | ||
180 | * hardware stores this as 8 bit signed value. | ||
181 | * we will cap it at 0 if it is a negative number | ||
182 | */ | ||
183 | if (ard.rssi & 0x80) | ||
184 | ard.rssi = 0; | ||
185 | if (ard.ext_rssi & 0x80) | ||
186 | ard.ext_rssi = 0; | ||
187 | |||
188 | vdata_end = (char *)data + datalen; | ||
189 | ard.pulse_bw_info = vdata_end[-1]; | ||
190 | ard.pulse_length_ext = vdata_end[-2]; | ||
191 | ard.pulse_length_pri = vdata_end[-3]; | ||
192 | |||
193 | ath_dbg(common, ATH_DBG_DFS, | ||
194 | "bw_info=%d, length_pri=%d, length_ext=%d, " | ||
195 | "rssi_pri=%d, rssi_ext=%d\n", | ||
196 | ard.pulse_bw_info, ard.pulse_length_pri, ard.pulse_length_ext, | ||
197 | ard.rssi, ard.ext_rssi); | ||
198 | |||
199 | drp.freq = ah->curchan->channel; | ||
200 | drp.ts = mactime; | ||
201 | if (ath9k_postprocess_radar_event(sc, &ard, &drp)) { | ||
202 | static u64 last_ts; | ||
203 | ath_dbg(common, ATH_DBG_DFS, | ||
204 | "ath9k_dfs_process_phyerr: channel=%d, ts=%llu, " | ||
205 | "width=%d, rssi=%d, delta_ts=%llu\n", | ||
206 | drp.freq, drp.ts, drp.width, drp.rssi, drp.ts-last_ts); | ||
207 | last_ts = drp.ts; | ||
208 | /* | ||
209 | * TODO: forward pulse to pattern detector | ||
210 | * | ||
211 | * ieee80211_add_radar_pulse(drp.freq, drp.ts, | ||
212 | * drp.width, drp.rssi); | ||
213 | */ | ||
214 | } | ||
215 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/dfs.h b/drivers/net/wireless/ath/ath9k/dfs.h new file mode 100644 index 000000000000..c2412857f122 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/dfs.h | |||
@@ -0,0 +1,43 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-2011 Atheros Communications Inc. | ||
3 | * Copyright (c) 2011 Neratec Solutions AG | ||
4 | * | ||
5 | * Permission to use, copy, modify, and/or distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | #ifndef ATH9K_DFS_H | ||
19 | #define ATH9K_DFS_H | ||
20 | |||
21 | #if defined(CONFIG_ATH9K_DFS_CERTIFIED) | ||
22 | /** | ||
23 | * ath9k_dfs_process_phyerr - process radar PHY error | ||
24 | * @sc: ath_softc | ||
25 | * @data: RX payload data | ||
26 | * @rs: RX status after processing descriptor | ||
27 | * @mactime: receive time | ||
28 | * | ||
29 | * This function is called whenever the HW DFS module detects a radar | ||
30 | * pulse and reports it as a PHY error. | ||
31 | * | ||
32 | * The radar information provided as raw payload data is validated and | ||
33 | * filtered for false pulses. Events passing all tests are forwarded to | ||
34 | * the upper layer for pattern detection. | ||
35 | */ | ||
36 | void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data, | ||
37 | struct ath_rx_status *rs, u64 mactime); | ||
38 | #else | ||
39 | static inline void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data, | ||
40 | struct ath_rx_status *rs, u64 mactime) { } | ||
41 | #endif | ||
42 | |||
43 | #endif /* ATH9K_DFS_H */ | ||
diff --git a/drivers/net/wireless/ath/ath9k/dfs_debug.c b/drivers/net/wireless/ath/ath9k/dfs_debug.c new file mode 100644 index 000000000000..106d031d834a --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/dfs_debug.c | |||
@@ -0,0 +1,81 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-2011 Atheros Communications Inc. | ||
3 | * Copyright (c) 2011 Neratec Solutions AG | ||
4 | * | ||
5 | * Permission to use, copy, modify, and/or distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | #include <linux/debugfs.h> | ||
19 | #include <linux/export.h> | ||
20 | |||
21 | #include "ath9k.h" | ||
22 | #include "dfs_debug.h" | ||
23 | |||
24 | #define ATH9K_DFS_STAT(s, p) \ | ||
25 | len += snprintf(buf + len, size - len, "%28s : %10u\n", s, \ | ||
26 | sc->debug.stats.dfs_stats.p); | ||
27 | |||
28 | static ssize_t read_file_dfs(struct file *file, char __user *user_buf, | ||
29 | size_t count, loff_t *ppos) | ||
30 | { | ||
31 | struct ath_softc *sc = file->private_data; | ||
32 | struct ath9k_hw_version *hw_ver = &sc->sc_ah->hw_version; | ||
33 | char *buf; | ||
34 | unsigned int len = 0, size = 8000; | ||
35 | ssize_t retval = 0; | ||
36 | |||
37 | buf = kzalloc(size, GFP_KERNEL); | ||
38 | if (buf == NULL) | ||
39 | return -ENOMEM; | ||
40 | |||
41 | len += snprintf(buf + len, size - len, "DFS support for " | ||
42 | "macVersion = 0x%x, macRev = 0x%x: %s\n", | ||
43 | hw_ver->macVersion, hw_ver->macRev, | ||
44 | (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_DFS) ? | ||
45 | "enabled" : "disabled"); | ||
46 | ATH9K_DFS_STAT("DFS pulses detected ", pulses_detected); | ||
47 | ATH9K_DFS_STAT("Datalen discards ", datalen_discards); | ||
48 | ATH9K_DFS_STAT("RSSI discards ", rssi_discards); | ||
49 | ATH9K_DFS_STAT("BW info discards ", bwinfo_discards); | ||
50 | ATH9K_DFS_STAT("Primary channel pulses ", pri_phy_errors); | ||
51 | ATH9K_DFS_STAT("Secondary channel pulses", ext_phy_errors); | ||
52 | ATH9K_DFS_STAT("Dual channel pulses ", dc_phy_errors); | ||
53 | |||
54 | if (len > size) | ||
55 | len = size; | ||
56 | |||
57 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
58 | kfree(buf); | ||
59 | |||
60 | return retval; | ||
61 | } | ||
62 | |||
63 | static int ath9k_dfs_debugfs_open(struct inode *inode, struct file *file) | ||
64 | { | ||
65 | file->private_data = inode->i_private; | ||
66 | |||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | static const struct file_operations fops_dfs_stats = { | ||
71 | .read = read_file_dfs, | ||
72 | .open = ath9k_dfs_debugfs_open, | ||
73 | .owner = THIS_MODULE, | ||
74 | .llseek = default_llseek, | ||
75 | }; | ||
76 | |||
77 | void ath9k_dfs_init_debug(struct ath_softc *sc) | ||
78 | { | ||
79 | debugfs_create_file("dfs_stats", S_IRUSR, | ||
80 | sc->debug.debugfs_phy, sc, &fops_dfs_stats); | ||
81 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/dfs_debug.h b/drivers/net/wireless/ath/ath9k/dfs_debug.h new file mode 100644 index 000000000000..6e1e2a71659e --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/dfs_debug.h | |||
@@ -0,0 +1,57 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-2011 Atheros Communications Inc. | ||
3 | * Copyright (c) 2011 Neratec Solutions AG | ||
4 | * | ||
5 | * Permission to use, copy, modify, and/or distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | |||
19 | #ifndef DFS_DEBUG_H | ||
20 | #define DFS_DEBUG_H | ||
21 | |||
22 | #include "hw.h" | ||
23 | |||
24 | /** | ||
25 | * struct ath_dfs_stats - DFS Statistics | ||
26 | * | ||
27 | * @pulses_detected: No. of pulses detected so far | ||
28 | * @datalen_discards: No. of pulses discarded due to invalid datalen | ||
29 | * @rssi_discards: No. of pulses discarded due to invalid RSSI | ||
30 | * @bwinfo_discards: No. of pulses discarded due to invalid BW info | ||
31 | * @pri_phy_errors: No. of pulses reported for primary channel | ||
32 | * @ext_phy_errors: No. of pulses reported for extension channel | ||
33 | * @dc_phy_errors: No. of pulses reported for primary + extension channel | ||
34 | */ | ||
35 | struct ath_dfs_stats { | ||
36 | u32 pulses_detected; | ||
37 | u32 datalen_discards; | ||
38 | u32 rssi_discards; | ||
39 | u32 bwinfo_discards; | ||
40 | u32 pri_phy_errors; | ||
41 | u32 ext_phy_errors; | ||
42 | u32 dc_phy_errors; | ||
43 | }; | ||
44 | |||
45 | #if defined(CONFIG_ATH9K_DFS_DEBUGFS) | ||
46 | |||
47 | #define DFS_STAT_INC(sc, c) (sc->debug.stats.dfs_stats.c++) | ||
48 | void ath9k_dfs_init_debug(struct ath_softc *sc); | ||
49 | |||
50 | #else | ||
51 | |||
52 | #define DFS_STAT_INC(sc, c) do { } while (0) | ||
53 | static inline void ath9k_dfs_init_debug(struct ath_softc *sc) { } | ||
54 | |||
55 | #endif /* CONFIG_ATH9K_DFS_DEBUGFS */ | ||
56 | |||
57 | #endif /* DFS_DEBUG_H */ | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index e74c233757a2..c4ad0b06bdbc 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h | |||
@@ -212,4 +212,13 @@ static inline int ath9k_hw_fast_chan_change(struct ath_hw *ah, | |||
212 | return ath9k_hw_private_ops(ah)->fast_chan_change(ah, chan, | 212 | return ath9k_hw_private_ops(ah)->fast_chan_change(ah, chan, |
213 | ini_reloaded); | 213 | ini_reloaded); |
214 | } | 214 | } |
215 | |||
216 | static inline void ath9k_hw_set_radar_params(struct ath_hw *ah) | ||
217 | { | ||
218 | if (!ath9k_hw_private_ops(ah)->set_radar_params) | ||
219 | return; | ||
220 | |||
221 | ath9k_hw_private_ops(ah)->set_radar_params(ah, &ah->radar_conf); | ||
222 | } | ||
223 | |||
215 | #endif /* ATH9K_HW_OPS_H */ | 224 | #endif /* ATH9K_HW_OPS_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 7f8fc65f2cb4..8cda9a1513a7 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -2277,6 +2277,30 @@ static u8 fixup_chainmask(u8 chip_chainmask, u8 eeprom_chainmask) | |||
2277 | return chip_chainmask; | 2277 | return chip_chainmask; |
2278 | } | 2278 | } |
2279 | 2279 | ||
2280 | /** | ||
2281 | * ath9k_hw_dfs_tested - checks if DFS has been tested with used chipset | ||
2282 | * @ah: the atheros hardware data structure | ||
2283 | * | ||
2284 | * We enable DFS support upstream on chipsets which have passed a series | ||
2285 | * of tests. The testing requirements are going to be documented. Desired | ||
2286 | * test requirements are documented at: | ||
2287 | * | ||
2288 | * http://wireless.kernel.org/en/users/Drivers/ath9k/dfs | ||
2289 | * | ||
2290 | * Once a new chipset gets properly tested an individual commit can be used | ||
2291 | * to document the testing for DFS for that chipset. | ||
2292 | */ | ||
2293 | static bool ath9k_hw_dfs_tested(struct ath_hw *ah) | ||
2294 | { | ||
2295 | |||
2296 | switch (ah->hw_version.macVersion) { | ||
2297 | /* AR9580 will likely be our first target to get testing on */ | ||
2298 | case AR_SREV_VERSION_9580: | ||
2299 | default: | ||
2300 | return false; | ||
2301 | } | ||
2302 | } | ||
2303 | |||
2280 | int ath9k_hw_fill_cap_info(struct ath_hw *ah) | 2304 | int ath9k_hw_fill_cap_info(struct ath_hw *ah) |
2281 | { | 2305 | { |
2282 | struct ath9k_hw_capabilities *pCap = &ah->caps; | 2306 | struct ath9k_hw_capabilities *pCap = &ah->caps; |
@@ -2375,12 +2399,10 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2375 | else | 2399 | else |
2376 | pCap->num_gpio_pins = AR_NUM_GPIO; | 2400 | pCap->num_gpio_pins = AR_NUM_GPIO; |
2377 | 2401 | ||
2378 | if (AR_SREV_9160_10_OR_LATER(ah) || AR_SREV_9100(ah)) { | 2402 | if (AR_SREV_9160_10_OR_LATER(ah) || AR_SREV_9100(ah)) |
2379 | pCap->hw_caps |= ATH9K_HW_CAP_CST; | ||
2380 | pCap->rts_aggr_limit = ATH_AMPDU_LIMIT_MAX; | 2403 | pCap->rts_aggr_limit = ATH_AMPDU_LIMIT_MAX; |
2381 | } else { | 2404 | else |
2382 | pCap->rts_aggr_limit = (8 * 1024); | 2405 | pCap->rts_aggr_limit = (8 * 1024); |
2383 | } | ||
2384 | 2406 | ||
2385 | #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) | 2407 | #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) |
2386 | ah->rfsilent = ah->eep_ops->get_eeprom(ah, EEP_RF_SILENT); | 2408 | ah->rfsilent = ah->eep_ops->get_eeprom(ah, EEP_RF_SILENT); |
@@ -2490,6 +2512,9 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2490 | pCap->pcie_lcr_offset = 0x80; | 2512 | pCap->pcie_lcr_offset = 0x80; |
2491 | } | 2513 | } |
2492 | 2514 | ||
2515 | if (ath9k_hw_dfs_tested(ah)) | ||
2516 | pCap->hw_caps |= ATH9K_HW_CAP_DFS; | ||
2517 | |||
2493 | tx_chainmask = pCap->tx_chainmask; | 2518 | tx_chainmask = pCap->tx_chainmask; |
2494 | rx_chainmask = pCap->rx_chainmask; | 2519 | rx_chainmask = pCap->rx_chainmask; |
2495 | while (tx_chainmask || rx_chainmask) { | 2520 | while (tx_chainmask || rx_chainmask) { |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 36968c046119..615cc839f0de 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -196,21 +196,21 @@ enum ath_ini_subsys { | |||
196 | enum ath9k_hw_caps { | 196 | enum ath9k_hw_caps { |
197 | ATH9K_HW_CAP_HT = BIT(0), | 197 | ATH9K_HW_CAP_HT = BIT(0), |
198 | ATH9K_HW_CAP_RFSILENT = BIT(1), | 198 | ATH9K_HW_CAP_RFSILENT = BIT(1), |
199 | ATH9K_HW_CAP_CST = BIT(2), | 199 | ATH9K_HW_CAP_AUTOSLEEP = BIT(2), |
200 | ATH9K_HW_CAP_AUTOSLEEP = BIT(4), | 200 | ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(3), |
201 | ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(5), | 201 | ATH9K_HW_CAP_EDMA = BIT(4), |
202 | ATH9K_HW_CAP_EDMA = BIT(6), | 202 | ATH9K_HW_CAP_RAC_SUPPORTED = BIT(5), |
203 | ATH9K_HW_CAP_RAC_SUPPORTED = BIT(7), | 203 | ATH9K_HW_CAP_LDPC = BIT(6), |
204 | ATH9K_HW_CAP_LDPC = BIT(8), | 204 | ATH9K_HW_CAP_FASTCLOCK = BIT(7), |
205 | ATH9K_HW_CAP_FASTCLOCK = BIT(9), | 205 | ATH9K_HW_CAP_SGI_20 = BIT(8), |
206 | ATH9K_HW_CAP_SGI_20 = BIT(10), | 206 | ATH9K_HW_CAP_PAPRD = BIT(9), |
207 | ATH9K_HW_CAP_PAPRD = BIT(11), | 207 | ATH9K_HW_CAP_ANT_DIV_COMB = BIT(10), |
208 | ATH9K_HW_CAP_ANT_DIV_COMB = BIT(12), | 208 | ATH9K_HW_CAP_2GHZ = BIT(11), |
209 | ATH9K_HW_CAP_2GHZ = BIT(13), | 209 | ATH9K_HW_CAP_5GHZ = BIT(12), |
210 | ATH9K_HW_CAP_5GHZ = BIT(14), | 210 | ATH9K_HW_CAP_APM = BIT(13), |
211 | ATH9K_HW_CAP_APM = BIT(15), | 211 | ATH9K_HW_CAP_RTT = BIT(14), |
212 | ATH9K_HW_CAP_RTT = BIT(16), | 212 | ATH9K_HW_CAP_MCI = BIT(15), |
213 | ATH9K_HW_CAP_MCI = BIT(17), | 213 | ATH9K_HW_CAP_DFS = BIT(16), |
214 | }; | 214 | }; |
215 | 215 | ||
216 | struct ath9k_hw_capabilities { | 216 | struct ath9k_hw_capabilities { |
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 41b72faca77f..c5df98139c4d 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -297,9 +297,22 @@ static int ath9k_reg_notifier(struct wiphy *wiphy, | |||
297 | { | 297 | { |
298 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); | 298 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); |
299 | struct ath_softc *sc = hw->priv; | 299 | struct ath_softc *sc = hw->priv; |
300 | struct ath_regulatory *reg = ath9k_hw_regulatory(sc->sc_ah); | 300 | struct ath_hw *ah = sc->sc_ah; |
301 | struct ath_regulatory *reg = ath9k_hw_regulatory(ah); | ||
302 | int ret; | ||
303 | |||
304 | ret = ath_reg_notifier_apply(wiphy, request, reg); | ||
305 | |||
306 | /* Set tx power */ | ||
307 | if (ah->curchan) { | ||
308 | sc->config.txpowlimit = 2 * ah->curchan->chan->max_power; | ||
309 | ath9k_ps_wakeup(sc); | ||
310 | ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false); | ||
311 | sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit; | ||
312 | ath9k_ps_restore(sc); | ||
313 | } | ||
301 | 314 | ||
302 | return ath_reg_notifier_apply(wiphy, request, reg); | 315 | return ret; |
303 | } | 316 | } |
304 | 317 | ||
305 | /* | 318 | /* |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 7d920044d031..7fbc4bdd4efe 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -644,9 +644,9 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta, | |||
644 | spin_lock(&sc->nodes_lock); | 644 | spin_lock(&sc->nodes_lock); |
645 | list_add(&an->list, &sc->nodes); | 645 | list_add(&an->list, &sc->nodes); |
646 | spin_unlock(&sc->nodes_lock); | 646 | spin_unlock(&sc->nodes_lock); |
647 | #endif | ||
647 | an->sta = sta; | 648 | an->sta = sta; |
648 | an->vif = vif; | 649 | an->vif = vif; |
649 | #endif | ||
650 | if (sc->sc_flags & SC_OP_TXAGGR) { | 650 | if (sc->sc_flags & SC_OP_TXAGGR) { |
651 | ath_tx_node_init(sc, an); | 651 | ath_tx_node_init(sc, an); |
652 | an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + | 652 | an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + |
@@ -1873,7 +1873,8 @@ static int ath9k_set_key(struct ieee80211_hw *hw, | |||
1873 | if (ath9k_modparam_nohwcrypt) | 1873 | if (ath9k_modparam_nohwcrypt) |
1874 | return -ENOSPC; | 1874 | return -ENOSPC; |
1875 | 1875 | ||
1876 | if (vif->type == NL80211_IFTYPE_ADHOC && | 1876 | if ((vif->type == NL80211_IFTYPE_ADHOC || |
1877 | vif->type == NL80211_IFTYPE_MESH_POINT) && | ||
1877 | (key->cipher == WLAN_CIPHER_SUITE_TKIP || | 1878 | (key->cipher == WLAN_CIPHER_SUITE_TKIP || |
1878 | key->cipher == WLAN_CIPHER_SUITE_CCMP) && | 1879 | key->cipher == WLAN_CIPHER_SUITE_CCMP) && |
1879 | !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { | 1880 | !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { |
diff --git a/drivers/net/wireless/ath/ath9k/mci.c b/drivers/net/wireless/ath/ath9k/mci.c index d6780405d6f5..691bf47906e2 100644 --- a/drivers/net/wireless/ath/ath9k/mci.c +++ b/drivers/net/wireless/ath/ath9k/mci.c | |||
@@ -234,8 +234,8 @@ static void ath_mci_cal_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload) | |||
234 | } | 234 | } |
235 | } | 235 | } |
236 | 236 | ||
237 | void ath_mci_process_profile(struct ath_softc *sc, | 237 | static void ath_mci_process_profile(struct ath_softc *sc, |
238 | struct ath_mci_profile_info *info) | 238 | struct ath_mci_profile_info *info) |
239 | { | 239 | { |
240 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 240 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
241 | struct ath_btcoex *btcoex = &sc->btcoex; | 241 | struct ath_btcoex *btcoex = &sc->btcoex; |
@@ -261,8 +261,8 @@ void ath_mci_process_profile(struct ath_softc *sc, | |||
261 | ath_mci_update_scheme(sc); | 261 | ath_mci_update_scheme(sc); |
262 | } | 262 | } |
263 | 263 | ||
264 | void ath_mci_process_status(struct ath_softc *sc, | 264 | static void ath_mci_process_status(struct ath_softc *sc, |
265 | struct ath_mci_profile_status *status) | 265 | struct ath_mci_profile_status *status) |
266 | { | 266 | { |
267 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 267 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
268 | struct ath_btcoex *btcoex = &sc->btcoex; | 268 | struct ath_btcoex *btcoex = &sc->btcoex; |
diff --git a/drivers/net/wireless/ath/ath9k/mci.h b/drivers/net/wireless/ath/ath9k/mci.h index b71bdeda7c78..29e3e51d078f 100644 --- a/drivers/net/wireless/ath/ath9k/mci.h +++ b/drivers/net/wireless/ath/ath9k/mci.h | |||
@@ -128,10 +128,6 @@ struct ath_mci_coex { | |||
128 | }; | 128 | }; |
129 | 129 | ||
130 | void ath_mci_flush_profile(struct ath_mci_profile *mci); | 130 | void ath_mci_flush_profile(struct ath_mci_profile *mci); |
131 | void ath_mci_process_profile(struct ath_softc *sc, | ||
132 | struct ath_mci_profile_info *info); | ||
133 | void ath_mci_process_status(struct ath_softc *sc, | ||
134 | struct ath_mci_profile_status *status); | ||
135 | int ath_mci_setup(struct ath_softc *sc); | 131 | int ath_mci_setup(struct ath_softc *sc); |
136 | void ath_mci_cleanup(struct ath_softc *sc); | 132 | void ath_mci_cleanup(struct ath_softc *sc); |
137 | void ath_mci_intr(struct ath_softc *sc); | 133 | void ath_mci_intr(struct ath_softc *sc); |
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 888abc2be3a5..528d5f3e868c 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c | |||
@@ -1271,7 +1271,9 @@ static void ath_rc_init(struct ath_softc *sc, | |||
1271 | 1271 | ||
1272 | ath_rc_priv->max_valid_rate = k; | 1272 | ath_rc_priv->max_valid_rate = k; |
1273 | ath_rc_sort_validrates(rate_table, ath_rc_priv); | 1273 | ath_rc_sort_validrates(rate_table, ath_rc_priv); |
1274 | ath_rc_priv->rate_max_phy = ath_rc_priv->valid_rate_index[k-4]; | 1274 | ath_rc_priv->rate_max_phy = (k > 4) ? |
1275 | ath_rc_priv->valid_rate_index[k-4] : | ||
1276 | ath_rc_priv->valid_rate_index[k-1]; | ||
1275 | ath_rc_priv->rate_table = rate_table; | 1277 | ath_rc_priv->rate_table = rate_table; |
1276 | 1278 | ||
1277 | ath_dbg(common, ATH_DBG_CONFIG, | 1279 | ath_dbg(common, ATH_DBG_CONFIG, |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index e0318415c2a0..ad5176de07dc 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -1823,6 +1823,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1823 | hdr = (struct ieee80211_hdr *) (hdr_skb->data + rx_status_len); | 1823 | hdr = (struct ieee80211_hdr *) (hdr_skb->data + rx_status_len); |
1824 | rxs = IEEE80211_SKB_RXCB(hdr_skb); | 1824 | rxs = IEEE80211_SKB_RXCB(hdr_skb); |
1825 | if (ieee80211_is_beacon(hdr->frame_control) && | 1825 | if (ieee80211_is_beacon(hdr->frame_control) && |
1826 | !is_zero_ether_addr(common->curbssid) && | ||
1826 | !compare_ether_addr(hdr->addr3, common->curbssid)) | 1827 | !compare_ether_addr(hdr->addr3, common->curbssid)) |
1827 | rs.is_mybeacon = true; | 1828 | rs.is_mybeacon = true; |
1828 | else | 1829 | else |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 9e65c3198ca7..23e80e63bca9 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -53,7 +53,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
53 | int tx_flags, struct ath_txq *txq); | 53 | int tx_flags, struct ath_txq *txq); |
54 | static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, | 54 | static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, |
55 | struct ath_txq *txq, struct list_head *bf_q, | 55 | struct ath_txq *txq, struct list_head *bf_q, |
56 | struct ath_tx_status *ts, int txok, int sendbar); | 56 | struct ath_tx_status *ts, int txok); |
57 | static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, | 57 | static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, |
58 | struct list_head *head, bool internal); | 58 | struct list_head *head, bool internal); |
59 | static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf, | 59 | static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf, |
@@ -150,6 +150,12 @@ static struct ath_frame_info *get_frame_info(struct sk_buff *skb) | |||
150 | return (struct ath_frame_info *) &tx_info->rate_driver_data[0]; | 150 | return (struct ath_frame_info *) &tx_info->rate_driver_data[0]; |
151 | } | 151 | } |
152 | 152 | ||
153 | static void ath_send_bar(struct ath_atx_tid *tid, u16 seqno) | ||
154 | { | ||
155 | ieee80211_send_bar(tid->an->vif, tid->an->sta->addr, tid->tidno, | ||
156 | seqno << IEEE80211_SEQ_SEQ_SHIFT); | ||
157 | } | ||
158 | |||
153 | static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) | 159 | static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) |
154 | { | 160 | { |
155 | struct ath_txq *txq = tid->ac->txq; | 161 | struct ath_txq *txq = tid->ac->txq; |
@@ -158,25 +164,24 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) | |||
158 | struct list_head bf_head; | 164 | struct list_head bf_head; |
159 | struct ath_tx_status ts; | 165 | struct ath_tx_status ts; |
160 | struct ath_frame_info *fi; | 166 | struct ath_frame_info *fi; |
167 | bool sendbar = false; | ||
161 | 168 | ||
162 | INIT_LIST_HEAD(&bf_head); | 169 | INIT_LIST_HEAD(&bf_head); |
163 | 170 | ||
164 | memset(&ts, 0, sizeof(ts)); | 171 | memset(&ts, 0, sizeof(ts)); |
165 | spin_lock_bh(&txq->axq_lock); | ||
166 | 172 | ||
167 | while ((skb = __skb_dequeue(&tid->buf_q))) { | 173 | while ((skb = __skb_dequeue(&tid->buf_q))) { |
168 | fi = get_frame_info(skb); | 174 | fi = get_frame_info(skb); |
169 | bf = fi->bf; | 175 | bf = fi->bf; |
170 | 176 | ||
171 | spin_unlock_bh(&txq->axq_lock); | ||
172 | if (bf && fi->retries) { | 177 | if (bf && fi->retries) { |
173 | list_add_tail(&bf->list, &bf_head); | 178 | list_add_tail(&bf->list, &bf_head); |
174 | ath_tx_update_baw(sc, tid, bf->bf_state.seqno); | 179 | ath_tx_update_baw(sc, tid, bf->bf_state.seqno); |
175 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 1); | 180 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0); |
181 | sendbar = true; | ||
176 | } else { | 182 | } else { |
177 | ath_tx_send_normal(sc, txq, NULL, skb); | 183 | ath_tx_send_normal(sc, txq, NULL, skb); |
178 | } | 184 | } |
179 | spin_lock_bh(&txq->axq_lock); | ||
180 | } | 185 | } |
181 | 186 | ||
182 | if (tid->baw_head == tid->baw_tail) { | 187 | if (tid->baw_head == tid->baw_tail) { |
@@ -184,7 +189,8 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) | |||
184 | tid->state &= ~AGGR_CLEANUP; | 189 | tid->state &= ~AGGR_CLEANUP; |
185 | } | 190 | } |
186 | 191 | ||
187 | spin_unlock_bh(&txq->axq_lock); | 192 | if (sendbar) |
193 | ath_send_bar(tid, tid->seq_start); | ||
188 | } | 194 | } |
189 | 195 | ||
190 | static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, | 196 | static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, |
@@ -200,6 +206,8 @@ static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, | |||
200 | while (tid->baw_head != tid->baw_tail && !test_bit(tid->baw_head, tid->tx_buf)) { | 206 | while (tid->baw_head != tid->baw_tail && !test_bit(tid->baw_head, tid->tx_buf)) { |
201 | INCR(tid->seq_start, IEEE80211_SEQ_MAX); | 207 | INCR(tid->seq_start, IEEE80211_SEQ_MAX); |
202 | INCR(tid->baw_head, ATH_TID_MAX_BUFS); | 208 | INCR(tid->baw_head, ATH_TID_MAX_BUFS); |
209 | if (tid->bar_index >= 0) | ||
210 | tid->bar_index--; | ||
203 | } | 211 | } |
204 | } | 212 | } |
205 | 213 | ||
@@ -243,9 +251,7 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, | |||
243 | bf = fi->bf; | 251 | bf = fi->bf; |
244 | 252 | ||
245 | if (!bf) { | 253 | if (!bf) { |
246 | spin_unlock(&txq->axq_lock); | ||
247 | ath_tx_complete(sc, skb, ATH_TX_ERROR, txq); | 254 | ath_tx_complete(sc, skb, ATH_TX_ERROR, txq); |
248 | spin_lock(&txq->axq_lock); | ||
249 | continue; | 255 | continue; |
250 | } | 256 | } |
251 | 257 | ||
@@ -254,24 +260,26 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, | |||
254 | if (fi->retries) | 260 | if (fi->retries) |
255 | ath_tx_update_baw(sc, tid, bf->bf_state.seqno); | 261 | ath_tx_update_baw(sc, tid, bf->bf_state.seqno); |
256 | 262 | ||
257 | spin_unlock(&txq->axq_lock); | 263 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0); |
258 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); | ||
259 | spin_lock(&txq->axq_lock); | ||
260 | } | 264 | } |
261 | 265 | ||
262 | tid->seq_next = tid->seq_start; | 266 | tid->seq_next = tid->seq_start; |
263 | tid->baw_tail = tid->baw_head; | 267 | tid->baw_tail = tid->baw_head; |
268 | tid->bar_index = -1; | ||
264 | } | 269 | } |
265 | 270 | ||
266 | static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq, | 271 | static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq, |
267 | struct sk_buff *skb) | 272 | struct sk_buff *skb, int count) |
268 | { | 273 | { |
269 | struct ath_frame_info *fi = get_frame_info(skb); | 274 | struct ath_frame_info *fi = get_frame_info(skb); |
270 | struct ath_buf *bf = fi->bf; | 275 | struct ath_buf *bf = fi->bf; |
271 | struct ieee80211_hdr *hdr; | 276 | struct ieee80211_hdr *hdr; |
277 | int prev = fi->retries; | ||
272 | 278 | ||
273 | TX_STAT_INC(txq->axq_qnum, a_retries); | 279 | TX_STAT_INC(txq->axq_qnum, a_retries); |
274 | if (fi->retries++ > 0) | 280 | fi->retries += count; |
281 | |||
282 | if (prev > 0) | ||
275 | return; | 283 | return; |
276 | 284 | ||
277 | hdr = (struct ieee80211_hdr *)skb->data; | 285 | hdr = (struct ieee80211_hdr *)skb->data; |
@@ -370,7 +378,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
370 | struct ath_buf *bf_next, *bf_last = bf->bf_lastbf; | 378 | struct ath_buf *bf_next, *bf_last = bf->bf_lastbf; |
371 | struct list_head bf_head; | 379 | struct list_head bf_head; |
372 | struct sk_buff_head bf_pending; | 380 | struct sk_buff_head bf_pending; |
373 | u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0; | 381 | u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0, seq_first; |
374 | u32 ba[WME_BA_BMP_SIZE >> 5]; | 382 | u32 ba[WME_BA_BMP_SIZE >> 5]; |
375 | int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; | 383 | int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; |
376 | bool rc_update = true; | 384 | bool rc_update = true; |
@@ -379,6 +387,8 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
379 | int nframes; | 387 | int nframes; |
380 | u8 tidno; | 388 | u8 tidno; |
381 | bool flush = !!(ts->ts_status & ATH9K_TX_FLUSH); | 389 | bool flush = !!(ts->ts_status & ATH9K_TX_FLUSH); |
390 | int i, retries; | ||
391 | int bar_index = -1; | ||
382 | 392 | ||
383 | skb = bf->bf_mpdu; | 393 | skb = bf->bf_mpdu; |
384 | hdr = (struct ieee80211_hdr *)skb->data; | 394 | hdr = (struct ieee80211_hdr *)skb->data; |
@@ -387,6 +397,10 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
387 | 397 | ||
388 | memcpy(rates, tx_info->control.rates, sizeof(rates)); | 398 | memcpy(rates, tx_info->control.rates, sizeof(rates)); |
389 | 399 | ||
400 | retries = ts->ts_longretry + 1; | ||
401 | for (i = 0; i < ts->ts_rateindex; i++) | ||
402 | retries += rates[i].count; | ||
403 | |||
390 | rcu_read_lock(); | 404 | rcu_read_lock(); |
391 | 405 | ||
392 | sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2); | 406 | sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2); |
@@ -400,8 +414,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
400 | if (!bf->bf_stale || bf_next != NULL) | 414 | if (!bf->bf_stale || bf_next != NULL) |
401 | list_move_tail(&bf->list, &bf_head); | 415 | list_move_tail(&bf->list, &bf_head); |
402 | 416 | ||
403 | ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, | 417 | ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, 0); |
404 | 0, 0); | ||
405 | 418 | ||
406 | bf = bf_next; | 419 | bf = bf_next; |
407 | } | 420 | } |
@@ -411,6 +424,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
411 | an = (struct ath_node *)sta->drv_priv; | 424 | an = (struct ath_node *)sta->drv_priv; |
412 | tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK; | 425 | tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK; |
413 | tid = ATH_AN_2_TID(an, tidno); | 426 | tid = ATH_AN_2_TID(an, tidno); |
427 | seq_first = tid->seq_start; | ||
414 | 428 | ||
415 | /* | 429 | /* |
416 | * The hardware occasionally sends a tx status for the wrong TID. | 430 | * The hardware occasionally sends a tx status for the wrong TID. |
@@ -460,25 +474,25 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
460 | } else if (!isaggr && txok) { | 474 | } else if (!isaggr && txok) { |
461 | /* transmit completion */ | 475 | /* transmit completion */ |
462 | acked_cnt++; | 476 | acked_cnt++; |
477 | } else if ((tid->state & AGGR_CLEANUP) || !retry) { | ||
478 | /* | ||
479 | * cleanup in progress, just fail | ||
480 | * the un-acked sub-frames | ||
481 | */ | ||
482 | txfail = 1; | ||
483 | } else if (flush) { | ||
484 | txpending = 1; | ||
485 | } else if (fi->retries < ATH_MAX_SW_RETRIES) { | ||
486 | if (txok || !an->sleeping) | ||
487 | ath_tx_set_retry(sc, txq, bf->bf_mpdu, | ||
488 | retries); | ||
489 | |||
490 | txpending = 1; | ||
463 | } else { | 491 | } else { |
464 | if ((tid->state & AGGR_CLEANUP) || !retry) { | 492 | txfail = 1; |
465 | /* | 493 | txfail_cnt++; |
466 | * cleanup in progress, just fail | 494 | bar_index = max_t(int, bar_index, |
467 | * the un-acked sub-frames | 495 | ATH_BA_INDEX(seq_first, seqno)); |
468 | */ | ||
469 | txfail = 1; | ||
470 | } else if (flush) { | ||
471 | txpending = 1; | ||
472 | } else if (fi->retries < ATH_MAX_SW_RETRIES) { | ||
473 | if (txok || !an->sleeping) | ||
474 | ath_tx_set_retry(sc, txq, bf->bf_mpdu); | ||
475 | |||
476 | txpending = 1; | ||
477 | } else { | ||
478 | txfail = 1; | ||
479 | sendbar = 1; | ||
480 | txfail_cnt++; | ||
481 | } | ||
482 | } | 496 | } |
483 | 497 | ||
484 | /* | 498 | /* |
@@ -495,9 +509,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
495 | * complete the acked-ones/xretried ones; update | 509 | * complete the acked-ones/xretried ones; update |
496 | * block-ack window | 510 | * block-ack window |
497 | */ | 511 | */ |
498 | spin_lock_bh(&txq->axq_lock); | ||
499 | ath_tx_update_baw(sc, tid, seqno); | 512 | ath_tx_update_baw(sc, tid, seqno); |
500 | spin_unlock_bh(&txq->axq_lock); | ||
501 | 513 | ||
502 | if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) { | 514 | if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) { |
503 | memcpy(tx_info->control.rates, rates, sizeof(rates)); | 515 | memcpy(tx_info->control.rates, rates, sizeof(rates)); |
@@ -506,33 +518,30 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
506 | } | 518 | } |
507 | 519 | ||
508 | ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, | 520 | ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, |
509 | !txfail, sendbar); | 521 | !txfail); |
510 | } else { | 522 | } else { |
511 | /* retry the un-acked ones */ | 523 | /* retry the un-acked ones */ |
512 | if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) { | 524 | if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) && |
513 | if (bf->bf_next == NULL && bf_last->bf_stale) { | 525 | bf->bf_next == NULL && bf_last->bf_stale) { |
514 | struct ath_buf *tbf; | 526 | struct ath_buf *tbf; |
515 | 527 | ||
516 | tbf = ath_clone_txbuf(sc, bf_last); | 528 | tbf = ath_clone_txbuf(sc, bf_last); |
517 | /* | 529 | /* |
518 | * Update tx baw and complete the | 530 | * Update tx baw and complete the |
519 | * frame with failed status if we | 531 | * frame with failed status if we |
520 | * run out of tx buf. | 532 | * run out of tx buf. |
521 | */ | 533 | */ |
522 | if (!tbf) { | 534 | if (!tbf) { |
523 | spin_lock_bh(&txq->axq_lock); | 535 | ath_tx_update_baw(sc, tid, seqno); |
524 | ath_tx_update_baw(sc, tid, seqno); | 536 | |
525 | spin_unlock_bh(&txq->axq_lock); | 537 | ath_tx_complete_buf(sc, bf, txq, |
526 | 538 | &bf_head, ts, 0); | |
527 | ath_tx_complete_buf(sc, bf, txq, | 539 | bar_index = max_t(int, bar_index, |
528 | &bf_head, | 540 | ATH_BA_INDEX(seq_first, seqno)); |
529 | ts, 0, | 541 | break; |
530 | !flush); | ||
531 | break; | ||
532 | } | ||
533 | |||
534 | fi->bf = tbf; | ||
535 | } | 542 | } |
543 | |||
544 | fi->bf = tbf; | ||
536 | } | 545 | } |
537 | 546 | ||
538 | /* | 547 | /* |
@@ -545,12 +554,18 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
545 | bf = bf_next; | 554 | bf = bf_next; |
546 | } | 555 | } |
547 | 556 | ||
557 | if (bar_index >= 0) { | ||
558 | u16 bar_seq = ATH_BA_INDEX2SEQ(seq_first, bar_index); | ||
559 | ath_send_bar(tid, ATH_BA_INDEX2SEQ(seq_first, bar_index + 1)); | ||
560 | if (BAW_WITHIN(tid->seq_start, tid->baw_size, bar_seq)) | ||
561 | tid->bar_index = ATH_BA_INDEX(tid->seq_start, bar_seq); | ||
562 | } | ||
563 | |||
548 | /* prepend un-acked frames to the beginning of the pending frame queue */ | 564 | /* prepend un-acked frames to the beginning of the pending frame queue */ |
549 | if (!skb_queue_empty(&bf_pending)) { | 565 | if (!skb_queue_empty(&bf_pending)) { |
550 | if (an->sleeping) | 566 | if (an->sleeping) |
551 | ieee80211_sta_set_buffered(sta, tid->tidno, true); | 567 | ieee80211_sta_set_buffered(sta, tid->tidno, true); |
552 | 568 | ||
553 | spin_lock_bh(&txq->axq_lock); | ||
554 | skb_queue_splice(&bf_pending, &tid->buf_q); | 569 | skb_queue_splice(&bf_pending, &tid->buf_q); |
555 | if (!an->sleeping) { | 570 | if (!an->sleeping) { |
556 | ath_tx_queue_tid(txq, tid); | 571 | ath_tx_queue_tid(txq, tid); |
@@ -558,7 +573,6 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
558 | if (ts->ts_status & ATH9K_TXERR_FILT) | 573 | if (ts->ts_status & ATH9K_TXERR_FILT) |
559 | tid->ac->clear_ps_filter = true; | 574 | tid->ac->clear_ps_filter = true; |
560 | } | 575 | } |
561 | spin_unlock_bh(&txq->axq_lock); | ||
562 | } | 576 | } |
563 | 577 | ||
564 | if (tid->state & AGGR_CLEANUP) | 578 | if (tid->state & AGGR_CLEANUP) |
@@ -617,24 +631,26 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, | |||
617 | max_4ms_framelen = ATH_AMPDU_LIMIT_MAX; | 631 | max_4ms_framelen = ATH_AMPDU_LIMIT_MAX; |
618 | 632 | ||
619 | for (i = 0; i < 4; i++) { | 633 | for (i = 0; i < 4; i++) { |
620 | if (rates[i].count) { | 634 | int modeidx; |
621 | int modeidx; | ||
622 | if (!(rates[i].flags & IEEE80211_TX_RC_MCS)) { | ||
623 | legacy = 1; | ||
624 | break; | ||
625 | } | ||
626 | |||
627 | if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) | ||
628 | modeidx = MCS_HT40; | ||
629 | else | ||
630 | modeidx = MCS_HT20; | ||
631 | 635 | ||
632 | if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI) | 636 | if (!rates[i].count) |
633 | modeidx++; | 637 | continue; |
634 | 638 | ||
635 | frmlen = ath_max_4ms_framelen[modeidx][rates[i].idx]; | 639 | if (!(rates[i].flags & IEEE80211_TX_RC_MCS)) { |
636 | max_4ms_framelen = min(max_4ms_framelen, frmlen); | 640 | legacy = 1; |
641 | break; | ||
637 | } | 642 | } |
643 | |||
644 | if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) | ||
645 | modeidx = MCS_HT40; | ||
646 | else | ||
647 | modeidx = MCS_HT20; | ||
648 | |||
649 | if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI) | ||
650 | modeidx++; | ||
651 | |||
652 | frmlen = ath_max_4ms_framelen[modeidx][rates[i].idx]; | ||
653 | max_4ms_framelen = min(max_4ms_framelen, frmlen); | ||
638 | } | 654 | } |
639 | 655 | ||
640 | /* | 656 | /* |
@@ -770,8 +786,6 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, | |||
770 | 786 | ||
771 | bf->bf_state.bf_type = BUF_AMPDU | BUF_AGGR; | 787 | bf->bf_state.bf_type = BUF_AMPDU | BUF_AGGR; |
772 | seqno = bf->bf_state.seqno; | 788 | seqno = bf->bf_state.seqno; |
773 | if (!bf_first) | ||
774 | bf_first = bf; | ||
775 | 789 | ||
776 | /* do not step over block-ack window */ | 790 | /* do not step over block-ack window */ |
777 | if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno)) { | 791 | if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno)) { |
@@ -779,6 +793,21 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, | |||
779 | break; | 793 | break; |
780 | } | 794 | } |
781 | 795 | ||
796 | if (tid->bar_index > ATH_BA_INDEX(tid->seq_start, seqno)) { | ||
797 | struct ath_tx_status ts = {}; | ||
798 | struct list_head bf_head; | ||
799 | |||
800 | INIT_LIST_HEAD(&bf_head); | ||
801 | list_add(&bf->list, &bf_head); | ||
802 | __skb_unlink(skb, &tid->buf_q); | ||
803 | ath_tx_update_baw(sc, tid, seqno); | ||
804 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0); | ||
805 | continue; | ||
806 | } | ||
807 | |||
808 | if (!bf_first) | ||
809 | bf_first = bf; | ||
810 | |||
782 | if (!rl) { | 811 | if (!rl) { |
783 | aggr_limit = ath_lookup_rate(sc, bf, tid); | 812 | aggr_limit = ath_lookup_rate(sc, bf, tid); |
784 | rl = 1; | 813 | rl = 1; |
@@ -1121,6 +1150,7 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, | |||
1121 | txtid->state |= AGGR_ADDBA_PROGRESS; | 1150 | txtid->state |= AGGR_ADDBA_PROGRESS; |
1122 | txtid->paused = true; | 1151 | txtid->paused = true; |
1123 | *ssn = txtid->seq_start = txtid->seq_next; | 1152 | *ssn = txtid->seq_start = txtid->seq_next; |
1153 | txtid->bar_index = -1; | ||
1124 | 1154 | ||
1125 | memset(txtid->tx_buf, 0, sizeof(txtid->tx_buf)); | 1155 | memset(txtid->tx_buf, 0, sizeof(txtid->tx_buf)); |
1126 | txtid->baw_head = txtid->baw_tail = 0; | 1156 | txtid->baw_head = txtid->baw_tail = 0; |
@@ -1155,9 +1185,9 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) | |||
1155 | txtid->state |= AGGR_CLEANUP; | 1185 | txtid->state |= AGGR_CLEANUP; |
1156 | else | 1186 | else |
1157 | txtid->state &= ~AGGR_ADDBA_COMPLETE; | 1187 | txtid->state &= ~AGGR_ADDBA_COMPLETE; |
1158 | spin_unlock_bh(&txq->axq_lock); | ||
1159 | 1188 | ||
1160 | ath_tx_flush_tid(sc, txtid); | 1189 | ath_tx_flush_tid(sc, txtid); |
1190 | spin_unlock_bh(&txq->axq_lock); | ||
1161 | } | 1191 | } |
1162 | 1192 | ||
1163 | void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc, | 1193 | void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc, |
@@ -1399,8 +1429,6 @@ static bool bf_is_ampdu_not_probing(struct ath_buf *bf) | |||
1399 | 1429 | ||
1400 | static void ath_drain_txq_list(struct ath_softc *sc, struct ath_txq *txq, | 1430 | static void ath_drain_txq_list(struct ath_softc *sc, struct ath_txq *txq, |
1401 | struct list_head *list, bool retry_tx) | 1431 | struct list_head *list, bool retry_tx) |
1402 | __releases(txq->axq_lock) | ||
1403 | __acquires(txq->axq_lock) | ||
1404 | { | 1432 | { |
1405 | struct ath_buf *bf, *lastbf; | 1433 | struct ath_buf *bf, *lastbf; |
1406 | struct list_head bf_head; | 1434 | struct list_head bf_head; |
@@ -1427,13 +1455,11 @@ static void ath_drain_txq_list(struct ath_softc *sc, struct ath_txq *txq, | |||
1427 | if (bf_is_ampdu_not_probing(bf)) | 1455 | if (bf_is_ampdu_not_probing(bf)) |
1428 | txq->axq_ampdu_depth--; | 1456 | txq->axq_ampdu_depth--; |
1429 | 1457 | ||
1430 | spin_unlock_bh(&txq->axq_lock); | ||
1431 | if (bf_isampdu(bf)) | 1458 | if (bf_isampdu(bf)) |
1432 | ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0, | 1459 | ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0, |
1433 | retry_tx); | 1460 | retry_tx); |
1434 | else | 1461 | else |
1435 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); | 1462 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0); |
1436 | spin_lock_bh(&txq->axq_lock); | ||
1437 | } | 1463 | } |
1438 | } | 1464 | } |
1439 | 1465 | ||
@@ -1560,11 +1586,9 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) | |||
1560 | break; | 1586 | break; |
1561 | } | 1587 | } |
1562 | 1588 | ||
1563 | if (!list_empty(&ac->tid_q)) { | 1589 | if (!list_empty(&ac->tid_q) && !ac->sched) { |
1564 | if (!ac->sched) { | 1590 | ac->sched = true; |
1565 | ac->sched = true; | 1591 | list_add_tail(&ac->list, &txq->axq_acq); |
1566 | list_add_tail(&ac->list, &txq->axq_acq); | ||
1567 | } | ||
1568 | } | 1592 | } |
1569 | 1593 | ||
1570 | if (ac == last_ac || | 1594 | if (ac == last_ac || |
@@ -1707,10 +1731,6 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, | |||
1707 | list_add_tail(&bf->list, &bf_head); | 1731 | list_add_tail(&bf->list, &bf_head); |
1708 | bf->bf_state.bf_type = 0; | 1732 | bf->bf_state.bf_type = 0; |
1709 | 1733 | ||
1710 | /* update starting sequence number for subsequent ADDBA request */ | ||
1711 | if (tid) | ||
1712 | INCR(tid->seq_start, IEEE80211_SEQ_MAX); | ||
1713 | |||
1714 | bf->bf_lastbf = bf; | 1734 | bf->bf_lastbf = bf; |
1715 | ath_tx_fill_desc(sc, bf, txq, fi->framelen); | 1735 | ath_tx_fill_desc(sc, bf, txq, fi->framelen); |
1716 | ath_tx_txqaddbuf(sc, txq, &bf_head, false); | 1736 | ath_tx_txqaddbuf(sc, txq, &bf_head, false); |
@@ -1818,7 +1838,6 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb, | |||
1818 | struct ath_buf *bf; | 1838 | struct ath_buf *bf; |
1819 | u8 tidno; | 1839 | u8 tidno; |
1820 | 1840 | ||
1821 | spin_lock_bh(&txctl->txq->axq_lock); | ||
1822 | if ((sc->sc_flags & SC_OP_TXAGGR) && txctl->an && | 1841 | if ((sc->sc_flags & SC_OP_TXAGGR) && txctl->an && |
1823 | ieee80211_is_data_qos(hdr->frame_control)) { | 1842 | ieee80211_is_data_qos(hdr->frame_control)) { |
1824 | tidno = ieee80211_get_qos_ctl(hdr)[0] & | 1843 | tidno = ieee80211_get_qos_ctl(hdr)[0] & |
@@ -1837,7 +1856,7 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb, | |||
1837 | } else { | 1856 | } else { |
1838 | bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb); | 1857 | bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb); |
1839 | if (!bf) | 1858 | if (!bf) |
1840 | goto out; | 1859 | return; |
1841 | 1860 | ||
1842 | bf->bf_state.bfs_paprd = txctl->paprd; | 1861 | bf->bf_state.bfs_paprd = txctl->paprd; |
1843 | 1862 | ||
@@ -1846,9 +1865,6 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb, | |||
1846 | 1865 | ||
1847 | ath_tx_send_normal(sc, txctl->txq, tid, skb); | 1866 | ath_tx_send_normal(sc, txctl->txq, tid, skb); |
1848 | } | 1867 | } |
1849 | |||
1850 | out: | ||
1851 | spin_unlock_bh(&txctl->txq->axq_lock); | ||
1852 | } | 1868 | } |
1853 | 1869 | ||
1854 | /* Upon failure caller should free skb */ | 1870 | /* Upon failure caller should free skb */ |
@@ -1915,9 +1931,11 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1915 | ieee80211_stop_queue(sc->hw, q); | 1931 | ieee80211_stop_queue(sc->hw, q); |
1916 | txq->stopped = 1; | 1932 | txq->stopped = 1; |
1917 | } | 1933 | } |
1918 | spin_unlock_bh(&txq->axq_lock); | ||
1919 | 1934 | ||
1920 | ath_tx_start_dma(sc, skb, txctl); | 1935 | ath_tx_start_dma(sc, skb, txctl); |
1936 | |||
1937 | spin_unlock_bh(&txq->axq_lock); | ||
1938 | |||
1921 | return 0; | 1939 | return 0; |
1922 | } | 1940 | } |
1923 | 1941 | ||
@@ -1936,9 +1954,6 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
1936 | 1954 | ||
1937 | ath_dbg(common, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb); | 1955 | ath_dbg(common, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb); |
1938 | 1956 | ||
1939 | if (tx_flags & ATH_TX_BAR) | ||
1940 | tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; | ||
1941 | |||
1942 | if (!(tx_flags & ATH_TX_ERROR)) | 1957 | if (!(tx_flags & ATH_TX_ERROR)) |
1943 | /* Frame was ACKed */ | 1958 | /* Frame was ACKed */ |
1944 | tx_info->flags |= IEEE80211_TX_STAT_ACK; | 1959 | tx_info->flags |= IEEE80211_TX_STAT_ACK; |
@@ -1966,7 +1981,6 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
1966 | 1981 | ||
1967 | q = skb_get_queue_mapping(skb); | 1982 | q = skb_get_queue_mapping(skb); |
1968 | if (txq == sc->tx.txq_map[q]) { | 1983 | if (txq == sc->tx.txq_map[q]) { |
1969 | spin_lock_bh(&txq->axq_lock); | ||
1970 | if (WARN_ON(--txq->pending_frames < 0)) | 1984 | if (WARN_ON(--txq->pending_frames < 0)) |
1971 | txq->pending_frames = 0; | 1985 | txq->pending_frames = 0; |
1972 | 1986 | ||
@@ -1974,7 +1988,6 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
1974 | ieee80211_wake_queue(sc->hw, q); | 1988 | ieee80211_wake_queue(sc->hw, q); |
1975 | txq->stopped = 0; | 1989 | txq->stopped = 0; |
1976 | } | 1990 | } |
1977 | spin_unlock_bh(&txq->axq_lock); | ||
1978 | } | 1991 | } |
1979 | 1992 | ||
1980 | ieee80211_tx_status(hw, skb); | 1993 | ieee80211_tx_status(hw, skb); |
@@ -1982,16 +1995,13 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
1982 | 1995 | ||
1983 | static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, | 1996 | static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, |
1984 | struct ath_txq *txq, struct list_head *bf_q, | 1997 | struct ath_txq *txq, struct list_head *bf_q, |
1985 | struct ath_tx_status *ts, int txok, int sendbar) | 1998 | struct ath_tx_status *ts, int txok) |
1986 | { | 1999 | { |
1987 | struct sk_buff *skb = bf->bf_mpdu; | 2000 | struct sk_buff *skb = bf->bf_mpdu; |
1988 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 2001 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
1989 | unsigned long flags; | 2002 | unsigned long flags; |
1990 | int tx_flags = 0; | 2003 | int tx_flags = 0; |
1991 | 2004 | ||
1992 | if (sendbar) | ||
1993 | tx_flags = ATH_TX_BAR; | ||
1994 | |||
1995 | if (!txok) | 2005 | if (!txok) |
1996 | tx_flags |= ATH_TX_ERROR; | 2006 | tx_flags |= ATH_TX_ERROR; |
1997 | 2007 | ||
@@ -2083,8 +2093,6 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf, | |||
2083 | static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq, | 2093 | static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq, |
2084 | struct ath_tx_status *ts, struct ath_buf *bf, | 2094 | struct ath_tx_status *ts, struct ath_buf *bf, |
2085 | struct list_head *bf_head) | 2095 | struct list_head *bf_head) |
2086 | __releases(txq->axq_lock) | ||
2087 | __acquires(txq->axq_lock) | ||
2088 | { | 2096 | { |
2089 | int txok; | 2097 | int txok; |
2090 | 2098 | ||
@@ -2094,16 +2102,12 @@ static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq, | |||
2094 | if (bf_is_ampdu_not_probing(bf)) | 2102 | if (bf_is_ampdu_not_probing(bf)) |
2095 | txq->axq_ampdu_depth--; | 2103 | txq->axq_ampdu_depth--; |
2096 | 2104 | ||
2097 | spin_unlock_bh(&txq->axq_lock); | ||
2098 | |||
2099 | if (!bf_isampdu(bf)) { | 2105 | if (!bf_isampdu(bf)) { |
2100 | ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok); | 2106 | ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok); |
2101 | ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok, 0); | 2107 | ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok); |
2102 | } else | 2108 | } else |
2103 | ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok, true); | 2109 | ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok, true); |
2104 | 2110 | ||
2105 | spin_lock_bh(&txq->axq_lock); | ||
2106 | |||
2107 | if (sc->sc_flags & SC_OP_TXAGGR) | 2111 | if (sc->sc_flags & SC_OP_TXAGGR) |
2108 | ath_txq_schedule(sc, txq); | 2112 | ath_txq_schedule(sc, txq); |
2109 | } | 2113 | } |
diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index 65ecb5bab25a..10dea37431b3 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c | |||
@@ -21,6 +21,8 @@ | |||
21 | #include "regd.h" | 21 | #include "regd.h" |
22 | #include "regd_common.h" | 22 | #include "regd_common.h" |
23 | 23 | ||
24 | static int __ath_regd_init(struct ath_regulatory *reg); | ||
25 | |||
24 | /* | 26 | /* |
25 | * This is a set of common rules used by our world regulatory domains. | 27 | * This is a set of common rules used by our world regulatory domains. |
26 | * We have 12 world regulatory domains. To save space we consolidate | 28 | * We have 12 world regulatory domains. To save space we consolidate |
@@ -347,10 +349,26 @@ static void ath_reg_apply_world_flags(struct wiphy *wiphy, | |||
347 | } | 349 | } |
348 | } | 350 | } |
349 | 351 | ||
352 | static u16 ath_regd_find_country_by_name(char *alpha2) | ||
353 | { | ||
354 | unsigned int i; | ||
355 | |||
356 | for (i = 0; i < ARRAY_SIZE(allCountries); i++) { | ||
357 | if (!memcmp(allCountries[i].isoName, alpha2, 2)) | ||
358 | return allCountries[i].countryCode; | ||
359 | } | ||
360 | |||
361 | return -1; | ||
362 | } | ||
363 | |||
350 | int ath_reg_notifier_apply(struct wiphy *wiphy, | 364 | int ath_reg_notifier_apply(struct wiphy *wiphy, |
351 | struct regulatory_request *request, | 365 | struct regulatory_request *request, |
352 | struct ath_regulatory *reg) | 366 | struct ath_regulatory *reg) |
353 | { | 367 | { |
368 | struct ath_common *common = container_of(reg, struct ath_common, | ||
369 | regulatory); | ||
370 | u16 country_code; | ||
371 | |||
354 | /* We always apply this */ | 372 | /* We always apply this */ |
355 | ath_reg_apply_radar_flags(wiphy); | 373 | ath_reg_apply_radar_flags(wiphy); |
356 | 374 | ||
@@ -363,14 +381,37 @@ int ath_reg_notifier_apply(struct wiphy *wiphy, | |||
363 | return 0; | 381 | return 0; |
364 | 382 | ||
365 | switch (request->initiator) { | 383 | switch (request->initiator) { |
366 | case NL80211_REGDOM_SET_BY_DRIVER: | ||
367 | case NL80211_REGDOM_SET_BY_CORE: | 384 | case NL80211_REGDOM_SET_BY_CORE: |
385 | /* | ||
386 | * If common->reg_world_copy is world roaming it means we *were* | ||
387 | * world roaming... so we now have to restore that data. | ||
388 | */ | ||
389 | if (!ath_is_world_regd(&common->reg_world_copy)) | ||
390 | break; | ||
391 | |||
392 | memcpy(reg, &common->reg_world_copy, | ||
393 | sizeof(struct ath_regulatory)); | ||
394 | break; | ||
395 | case NL80211_REGDOM_SET_BY_DRIVER: | ||
368 | case NL80211_REGDOM_SET_BY_USER: | 396 | case NL80211_REGDOM_SET_BY_USER: |
369 | break; | 397 | break; |
370 | case NL80211_REGDOM_SET_BY_COUNTRY_IE: | 398 | case NL80211_REGDOM_SET_BY_COUNTRY_IE: |
371 | if (ath_is_world_regd(reg)) | 399 | if (!ath_is_world_regd(reg)) |
372 | ath_reg_apply_world_flags(wiphy, request->initiator, | 400 | break; |
373 | reg); | 401 | |
402 | country_code = ath_regd_find_country_by_name(request->alpha2); | ||
403 | if (country_code == (u16) -1) | ||
404 | break; | ||
405 | |||
406 | reg->current_rd = COUNTRY_ERD_FLAG; | ||
407 | reg->current_rd |= country_code; | ||
408 | |||
409 | printk(KERN_DEBUG "ath: regdomain 0x%0x updated by CountryIE\n", | ||
410 | reg->current_rd); | ||
411 | __ath_regd_init(reg); | ||
412 | |||
413 | ath_reg_apply_world_flags(wiphy, request->initiator, reg); | ||
414 | |||
374 | break; | 415 | break; |
375 | } | 416 | } |
376 | 417 | ||
@@ -508,11 +549,7 @@ static void ath_regd_sanitize(struct ath_regulatory *reg) | |||
508 | reg->current_rd = 0x64; | 549 | reg->current_rd = 0x64; |
509 | } | 550 | } |
510 | 551 | ||
511 | int | 552 | static int __ath_regd_init(struct ath_regulatory *reg) |
512 | ath_regd_init(struct ath_regulatory *reg, | ||
513 | struct wiphy *wiphy, | ||
514 | int (*reg_notifier)(struct wiphy *wiphy, | ||
515 | struct regulatory_request *request)) | ||
516 | { | 553 | { |
517 | struct country_code_to_enum_rd *country = NULL; | 554 | struct country_code_to_enum_rd *country = NULL; |
518 | u16 regdmn; | 555 | u16 regdmn; |
@@ -583,7 +620,29 @@ ath_regd_init(struct ath_regulatory *reg, | |||
583 | printk(KERN_DEBUG "ath: Regpair used: 0x%0x\n", | 620 | printk(KERN_DEBUG "ath: Regpair used: 0x%0x\n", |
584 | reg->regpair->regDmnEnum); | 621 | reg->regpair->regDmnEnum); |
585 | 622 | ||
623 | return 0; | ||
624 | } | ||
625 | |||
626 | int | ||
627 | ath_regd_init(struct ath_regulatory *reg, | ||
628 | struct wiphy *wiphy, | ||
629 | int (*reg_notifier)(struct wiphy *wiphy, | ||
630 | struct regulatory_request *request)) | ||
631 | { | ||
632 | struct ath_common *common = container_of(reg, struct ath_common, | ||
633 | regulatory); | ||
634 | int r; | ||
635 | |||
636 | r = __ath_regd_init(reg); | ||
637 | if (r) | ||
638 | return r; | ||
639 | |||
640 | if (ath_is_world_regd(reg)) | ||
641 | memcpy(&common->reg_world_copy, reg, | ||
642 | sizeof(struct ath_regulatory)); | ||
643 | |||
586 | ath_regd_init_wiphy(reg, wiphy, reg_notifier); | 644 | ath_regd_init_wiphy(reg, wiphy, reg_notifier); |
645 | |||
587 | return 0; | 646 | return 0; |
588 | } | 647 | } |
589 | EXPORT_SYMBOL(ath_regd_init); | 648 | EXPORT_SYMBOL(ath_regd_init); |
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index b17d9b6c33a5..c8fa2cd97e64 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c | |||
@@ -228,10 +228,98 @@ static void b43_chantab_radio_2056_upload(struct b43_wldev *dev, | |||
228 | static void b43_radio_2056_setup(struct b43_wldev *dev, | 228 | static void b43_radio_2056_setup(struct b43_wldev *dev, |
229 | const struct b43_nphy_channeltab_entry_rev3 *e) | 229 | const struct b43_nphy_channeltab_entry_rev3 *e) |
230 | { | 230 | { |
231 | struct ssb_sprom *sprom = dev->dev->bus_sprom; | ||
232 | enum ieee80211_band band = b43_current_band(dev->wl); | ||
233 | u16 offset; | ||
234 | u8 i; | ||
235 | u16 bias, cbias, pag_boost, pgag_boost, mixg_boost, padg_boost; | ||
236 | |||
231 | B43_WARN_ON(dev->phy.rev < 3); | 237 | B43_WARN_ON(dev->phy.rev < 3); |
232 | 238 | ||
233 | b43_chantab_radio_2056_upload(dev, e); | 239 | b43_chantab_radio_2056_upload(dev, e); |
234 | /* TODO */ | 240 | b2056_upload_syn_pll_cp2(dev, band == IEEE80211_BAND_5GHZ); |
241 | |||
242 | if (sprom->boardflags2_lo & B43_BFL2_GPLL_WAR && | ||
243 | b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { | ||
244 | b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1, 0x1F); | ||
245 | b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2, 0x1F); | ||
246 | if (dev->dev->chip_id == 0x4716) { | ||
247 | b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x14); | ||
248 | b43_radio_write(dev, B2056_SYN_PLL_CP2, 0); | ||
249 | } else { | ||
250 | b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x0B); | ||
251 | b43_radio_write(dev, B2056_SYN_PLL_CP2, 0x14); | ||
252 | } | ||
253 | } | ||
254 | if (sprom->boardflags2_lo & B43_BFL2_APLL_WAR && | ||
255 | b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { | ||
256 | b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1, 0x1F); | ||
257 | b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2, 0x1F); | ||
258 | b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x05); | ||
259 | b43_radio_write(dev, B2056_SYN_PLL_CP2, 0x0C); | ||
260 | } | ||
261 | |||
262 | if (dev->phy.n->ipa2g_on && band == IEEE80211_BAND_2GHZ) { | ||
263 | for (i = 0; i < 2; i++) { | ||
264 | offset = i ? B2056_TX1 : B2056_TX0; | ||
265 | if (dev->phy.rev >= 5) { | ||
266 | b43_radio_write(dev, | ||
267 | offset | B2056_TX_PADG_IDAC, 0xcc); | ||
268 | |||
269 | if (dev->dev->chip_id == 0x4716) { | ||
270 | bias = 0x40; | ||
271 | cbias = 0x45; | ||
272 | pag_boost = 0x5; | ||
273 | pgag_boost = 0x33; | ||
274 | mixg_boost = 0x55; | ||
275 | } else { | ||
276 | bias = 0x25; | ||
277 | cbias = 0x20; | ||
278 | pag_boost = 0x4; | ||
279 | pgag_boost = 0x03; | ||
280 | mixg_boost = 0x65; | ||
281 | } | ||
282 | padg_boost = 0x77; | ||
283 | |||
284 | b43_radio_write(dev, | ||
285 | offset | B2056_TX_INTPAG_IMAIN_STAT, | ||
286 | bias); | ||
287 | b43_radio_write(dev, | ||
288 | offset | B2056_TX_INTPAG_IAUX_STAT, | ||
289 | bias); | ||
290 | b43_radio_write(dev, | ||
291 | offset | B2056_TX_INTPAG_CASCBIAS, | ||
292 | cbias); | ||
293 | b43_radio_write(dev, | ||
294 | offset | B2056_TX_INTPAG_BOOST_TUNE, | ||
295 | pag_boost); | ||
296 | b43_radio_write(dev, | ||
297 | offset | B2056_TX_PGAG_BOOST_TUNE, | ||
298 | pgag_boost); | ||
299 | b43_radio_write(dev, | ||
300 | offset | B2056_TX_PADG_BOOST_TUNE, | ||
301 | padg_boost); | ||
302 | b43_radio_write(dev, | ||
303 | offset | B2056_TX_MIXG_BOOST_TUNE, | ||
304 | mixg_boost); | ||
305 | } else { | ||
306 | bias = dev->phy.is_40mhz ? 0x40 : 0x20; | ||
307 | b43_radio_write(dev, | ||
308 | offset | B2056_TX_INTPAG_IMAIN_STAT, | ||
309 | bias); | ||
310 | b43_radio_write(dev, | ||
311 | offset | B2056_TX_INTPAG_IAUX_STAT, | ||
312 | bias); | ||
313 | b43_radio_write(dev, | ||
314 | offset | B2056_TX_INTPAG_CASCBIAS, | ||
315 | 0x30); | ||
316 | } | ||
317 | b43_radio_write(dev, offset | B2056_TX_PA_SPARE1, 0xee); | ||
318 | } | ||
319 | } else if (dev->phy.n->ipa5g_on && band == IEEE80211_BAND_5GHZ) { | ||
320 | /* TODO */ | ||
321 | } | ||
322 | |||
235 | udelay(50); | 323 | udelay(50); |
236 | /* VCO calibration */ | 324 | /* VCO calibration */ |
237 | b43_radio_write(dev, B2056_SYN_PLL_VCOCAL12, 0x00); | 325 | b43_radio_write(dev, B2056_SYN_PLL_VCOCAL12, 0x00); |
@@ -387,7 +475,9 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev) | |||
387 | if (nphy->hang_avoid) | 475 | if (nphy->hang_avoid) |
388 | b43_nphy_stay_in_carrier_search(dev, 1); | 476 | b43_nphy_stay_in_carrier_search(dev, 1); |
389 | 477 | ||
390 | if (dev->phy.rev >= 3) { | 478 | if (dev->phy.rev >= 7) { |
479 | txpi[0] = txpi[1] = 30; | ||
480 | } else if (dev->phy.rev >= 3) { | ||
391 | txpi[0] = 40; | 481 | txpi[0] = 40; |
392 | txpi[1] = 40; | 482 | txpi[1] = 40; |
393 | } else if (sprom->revision < 4) { | 483 | } else if (sprom->revision < 4) { |
@@ -411,6 +501,9 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev) | |||
411 | txpi[1] = 91; | 501 | txpi[1] = 91; |
412 | } | 502 | } |
413 | } | 503 | } |
504 | if (dev->phy.rev < 7 && | ||
505 | (txpi[0] < 40 || txpi[0] > 100 || txpi[1] < 40 || txpi[1] > 10)) | ||
506 | txpi[0] = txpi[1] = 91; | ||
414 | 507 | ||
415 | /* | 508 | /* |
416 | for (i = 0; i < 2; i++) { | 509 | for (i = 0; i < 2; i++) { |
@@ -421,15 +514,31 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev) | |||
421 | 514 | ||
422 | for (i = 0; i < 2; i++) { | 515 | for (i = 0; i < 2; i++) { |
423 | if (dev->phy.rev >= 3) { | 516 | if (dev->phy.rev >= 3) { |
424 | /* FIXME: support 5GHz */ | 517 | if (b43_nphy_ipa(dev)) { |
425 | txgain = b43_ntab_tx_gain_rev3plus_2ghz[txpi[i]]; | 518 | txgain = *(b43_nphy_get_ipa_gain_table(dev) + |
519 | txpi[i]); | ||
520 | } else if (b43_current_band(dev->wl) == | ||
521 | IEEE80211_BAND_5GHZ) { | ||
522 | /* FIXME: use 5GHz tables */ | ||
523 | txgain = | ||
524 | b43_ntab_tx_gain_rev3plus_2ghz[txpi[i]]; | ||
525 | } else { | ||
526 | if (dev->phy.rev >= 5 && | ||
527 | sprom->fem.ghz5.extpa_gain == 3) | ||
528 | ; /* FIXME: 5GHz_txgain_HiPwrEPA */ | ||
529 | txgain = | ||
530 | b43_ntab_tx_gain_rev3plus_2ghz[txpi[i]]; | ||
531 | } | ||
426 | radio_gain = (txgain >> 16) & 0x1FFFF; | 532 | radio_gain = (txgain >> 16) & 0x1FFFF; |
427 | } else { | 533 | } else { |
428 | txgain = b43_ntab_tx_gain_rev0_1_2[txpi[i]]; | 534 | txgain = b43_ntab_tx_gain_rev0_1_2[txpi[i]]; |
429 | radio_gain = (txgain >> 16) & 0x1FFF; | 535 | radio_gain = (txgain >> 16) & 0x1FFF; |
430 | } | 536 | } |
431 | 537 | ||
432 | dac_gain = (txgain >> 8) & 0x3F; | 538 | if (dev->phy.rev >= 7) |
539 | dac_gain = (txgain >> 8) & 0x7; | ||
540 | else | ||
541 | dac_gain = (txgain >> 8) & 0x3F; | ||
433 | bbmult = txgain & 0xFF; | 542 | bbmult = txgain & 0xFF; |
434 | 543 | ||
435 | if (dev->phy.rev >= 3) { | 544 | if (dev->phy.rev >= 3) { |
@@ -459,7 +568,8 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev) | |||
459 | u32 tmp32; | 568 | u32 tmp32; |
460 | u16 reg = (i == 0) ? | 569 | u16 reg = (i == 0) ? |
461 | B43_NPHY_PAPD_EN0 : B43_NPHY_PAPD_EN1; | 570 | B43_NPHY_PAPD_EN0 : B43_NPHY_PAPD_EN1; |
462 | tmp32 = b43_ntab_read(dev, B43_NTAB32(26 + i, txpi[i])); | 571 | tmp32 = b43_ntab_read(dev, B43_NTAB32(26 + i, |
572 | 576 + txpi[i])); | ||
463 | b43_phy_maskset(dev, reg, 0xE00F, (u32) tmp32 << 4); | 573 | b43_phy_maskset(dev, reg, 0xE00F, (u32) tmp32 << 4); |
464 | b43_phy_set(dev, reg, 0x4); | 574 | b43_phy_set(dev, reg, 0x4); |
465 | } | 575 | } |
@@ -1493,8 +1603,8 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev) | |||
1493 | struct ssb_sprom *sprom = dev->dev->bus_sprom; | 1603 | struct ssb_sprom *sprom = dev->dev->bus_sprom; |
1494 | 1604 | ||
1495 | /* TX to RX */ | 1605 | /* TX to RX */ |
1496 | u8 tx2rx_events[9] = { 0x4, 0x3, 0x6, 0x5, 0x2, 0x1, 0x8, 0x1F }; | 1606 | u8 tx2rx_events[8] = { 0x4, 0x3, 0x6, 0x5, 0x2, 0x1, 0x8, 0x1F }; |
1497 | u8 tx2rx_delays[9] = { 8, 4, 2, 2, 4, 4, 6, 1 }; | 1607 | u8 tx2rx_delays[8] = { 8, 4, 2, 2, 4, 4, 6, 1 }; |
1498 | /* RX to TX */ | 1608 | /* RX to TX */ |
1499 | u8 rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3, | 1609 | u8 rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3, |
1500 | 0x1F }; | 1610 | 0x1F }; |
@@ -1505,6 +1615,9 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev) | |||
1505 | u16 tmp16; | 1615 | u16 tmp16; |
1506 | u32 tmp32; | 1616 | u32 tmp32; |
1507 | 1617 | ||
1618 | b43_phy_write(dev, 0x23f, 0x1f8); | ||
1619 | b43_phy_write(dev, 0x240, 0x1f8); | ||
1620 | |||
1508 | tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0)); | 1621 | tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0)); |
1509 | tmp32 &= 0xffffff; | 1622 | tmp32 &= 0xffffff; |
1510 | b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32); | 1623 | b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32); |
@@ -1520,12 +1633,13 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev) | |||
1520 | b43_phy_write(dev, 0x2AE, 0x000C); | 1633 | b43_phy_write(dev, 0x2AE, 0x000C); |
1521 | 1634 | ||
1522 | /* TX to RX */ | 1635 | /* TX to RX */ |
1523 | b43_nphy_set_rf_sequence(dev, 1, tx2rx_events, tx2rx_delays, 9); | 1636 | b43_nphy_set_rf_sequence(dev, 1, tx2rx_events, tx2rx_delays, |
1637 | ARRAY_SIZE(tx2rx_events)); | ||
1524 | 1638 | ||
1525 | /* RX to TX */ | 1639 | /* RX to TX */ |
1526 | if (b43_nphy_ipa(dev)) | 1640 | if (b43_nphy_ipa(dev)) |
1527 | b43_nphy_set_rf_sequence(dev, 1, rx2tx_events_ipa, | 1641 | b43_nphy_set_rf_sequence(dev, 0, rx2tx_events_ipa, |
1528 | rx2tx_delays_ipa, 9); | 1642 | rx2tx_delays_ipa, ARRAY_SIZE(rx2tx_events_ipa)); |
1529 | if (nphy->hw_phyrxchain != 3 && | 1643 | if (nphy->hw_phyrxchain != 3 && |
1530 | nphy->hw_phyrxchain != nphy->hw_phytxchain) { | 1644 | nphy->hw_phyrxchain != nphy->hw_phytxchain) { |
1531 | if (b43_nphy_ipa(dev)) { | 1645 | if (b43_nphy_ipa(dev)) { |
@@ -1533,7 +1647,8 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev) | |||
1533 | rx2tx_delays[6] = 1; | 1647 | rx2tx_delays[6] = 1; |
1534 | rx2tx_events[7] = 0x1F; | 1648 | rx2tx_events[7] = 0x1F; |
1535 | } | 1649 | } |
1536 | b43_nphy_set_rf_sequence(dev, 1, rx2tx_events, rx2tx_delays, 9); | 1650 | b43_nphy_set_rf_sequence(dev, 1, rx2tx_events, rx2tx_delays, |
1651 | ARRAY_SIZE(rx2tx_events)); | ||
1537 | } | 1652 | } |
1538 | 1653 | ||
1539 | tmp16 = (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) ? | 1654 | tmp16 = (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) ? |
@@ -1547,8 +1662,8 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev) | |||
1547 | 1662 | ||
1548 | b43_nphy_gain_ctrl_workarounds(dev); | 1663 | b43_nphy_gain_ctrl_workarounds(dev); |
1549 | 1664 | ||
1550 | b43_ntab_write(dev, B43_NTAB32(8, 0), 2); | 1665 | b43_ntab_write(dev, B43_NTAB16(8, 0), 2); |
1551 | b43_ntab_write(dev, B43_NTAB32(8, 16), 2); | 1666 | b43_ntab_write(dev, B43_NTAB16(8, 16), 2); |
1552 | 1667 | ||
1553 | /* TODO */ | 1668 | /* TODO */ |
1554 | 1669 | ||
@@ -1560,6 +1675,8 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev) | |||
1560 | b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_AUX, 0x07); | 1675 | b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_AUX, 0x07); |
1561 | b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_LOB_BIAS, 0x88); | 1676 | b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_LOB_BIAS, 0x88); |
1562 | b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_LOB_BIAS, 0x88); | 1677 | b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_LOB_BIAS, 0x88); |
1678 | b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_CMFB_IDAC, 0x00); | ||
1679 | b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_CMFB_IDAC, 0x00); | ||
1563 | b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXG_CMFB_IDAC, 0x00); | 1680 | b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXG_CMFB_IDAC, 0x00); |
1564 | b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXG_CMFB_IDAC, 0x00); | 1681 | b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXG_CMFB_IDAC, 0x00); |
1565 | 1682 | ||
@@ -1584,18 +1701,18 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev) | |||
1584 | 0x70); | 1701 | 0x70); |
1585 | } | 1702 | } |
1586 | 1703 | ||
1587 | b43_phy_write(dev, 0x224, 0x039C); | 1704 | b43_phy_write(dev, 0x224, 0x03eb); |
1588 | b43_phy_write(dev, 0x225, 0x0357); | 1705 | b43_phy_write(dev, 0x225, 0x03eb); |
1589 | b43_phy_write(dev, 0x226, 0x0317); | 1706 | b43_phy_write(dev, 0x226, 0x0341); |
1590 | b43_phy_write(dev, 0x227, 0x02D7); | 1707 | b43_phy_write(dev, 0x227, 0x0341); |
1591 | b43_phy_write(dev, 0x228, 0x039C); | 1708 | b43_phy_write(dev, 0x228, 0x042b); |
1592 | b43_phy_write(dev, 0x229, 0x0357); | 1709 | b43_phy_write(dev, 0x229, 0x042b); |
1593 | b43_phy_write(dev, 0x22A, 0x0317); | 1710 | b43_phy_write(dev, 0x22a, 0x0381); |
1594 | b43_phy_write(dev, 0x22B, 0x02D7); | 1711 | b43_phy_write(dev, 0x22b, 0x0381); |
1595 | b43_phy_write(dev, 0x22C, 0x039C); | 1712 | b43_phy_write(dev, 0x22c, 0x042b); |
1596 | b43_phy_write(dev, 0x22D, 0x0357); | 1713 | b43_phy_write(dev, 0x22d, 0x042b); |
1597 | b43_phy_write(dev, 0x22E, 0x0317); | 1714 | b43_phy_write(dev, 0x22e, 0x0381); |
1598 | b43_phy_write(dev, 0x22F, 0x02D7); | 1715 | b43_phy_write(dev, 0x22f, 0x0381); |
1599 | } | 1716 | } |
1600 | 1717 | ||
1601 | static void b43_nphy_workarounds_rev1_2(struct b43_wldev *dev) | 1718 | static void b43_nphy_workarounds_rev1_2(struct b43_wldev *dev) |
@@ -3928,6 +4045,76 @@ int b43_phy_initn(struct b43_wldev *dev) | |||
3928 | return 0; | 4045 | return 0; |
3929 | } | 4046 | } |
3930 | 4047 | ||
4048 | /* http://bcm-v4.sipsolutions.net/802.11/PmuSpurAvoid */ | ||
4049 | static void b43_nphy_pmu_spur_avoid(struct b43_wldev *dev, bool avoid) | ||
4050 | { | ||
4051 | struct bcma_drv_cc *cc; | ||
4052 | u32 pmu_ctl; | ||
4053 | |||
4054 | switch (dev->dev->bus_type) { | ||
4055 | #ifdef CONFIG_B43_BCMA | ||
4056 | case B43_BUS_BCMA: | ||
4057 | cc = &dev->dev->bdev->bus->drv_cc; | ||
4058 | if (dev->dev->chip_id == 43224 || dev->dev->chip_id == 43225) { | ||
4059 | if (avoid) { | ||
4060 | bcma_chipco_pll_write(cc, 0x0, 0x11500010); | ||
4061 | bcma_chipco_pll_write(cc, 0x1, 0x000C0C06); | ||
4062 | bcma_chipco_pll_write(cc, 0x2, 0x0F600a08); | ||
4063 | bcma_chipco_pll_write(cc, 0x3, 0x00000000); | ||
4064 | bcma_chipco_pll_write(cc, 0x4, 0x2001E920); | ||
4065 | bcma_chipco_pll_write(cc, 0x5, 0x88888815); | ||
4066 | } else { | ||
4067 | bcma_chipco_pll_write(cc, 0x0, 0x11100010); | ||
4068 | bcma_chipco_pll_write(cc, 0x1, 0x000c0c06); | ||
4069 | bcma_chipco_pll_write(cc, 0x2, 0x03000a08); | ||
4070 | bcma_chipco_pll_write(cc, 0x3, 0x00000000); | ||
4071 | bcma_chipco_pll_write(cc, 0x4, 0x200005c0); | ||
4072 | bcma_chipco_pll_write(cc, 0x5, 0x88888815); | ||
4073 | } | ||
4074 | pmu_ctl = BCMA_CC_PMU_CTL_PLL_UPD; | ||
4075 | } else if (dev->dev->chip_id == 0x4716) { | ||
4076 | if (avoid) { | ||
4077 | bcma_chipco_pll_write(cc, 0x0, 0x11500060); | ||
4078 | bcma_chipco_pll_write(cc, 0x1, 0x080C0C06); | ||
4079 | bcma_chipco_pll_write(cc, 0x2, 0x0F600000); | ||
4080 | bcma_chipco_pll_write(cc, 0x3, 0x00000000); | ||
4081 | bcma_chipco_pll_write(cc, 0x4, 0x2001E924); | ||
4082 | bcma_chipco_pll_write(cc, 0x5, 0x88888815); | ||
4083 | } else { | ||
4084 | bcma_chipco_pll_write(cc, 0x0, 0x11100060); | ||
4085 | bcma_chipco_pll_write(cc, 0x1, 0x080c0c06); | ||
4086 | bcma_chipco_pll_write(cc, 0x2, 0x03000000); | ||
4087 | bcma_chipco_pll_write(cc, 0x3, 0x00000000); | ||
4088 | bcma_chipco_pll_write(cc, 0x4, 0x200005c0); | ||
4089 | bcma_chipco_pll_write(cc, 0x5, 0x88888815); | ||
4090 | } | ||
4091 | pmu_ctl = BCMA_CC_PMU_CTL_PLL_UPD | | ||
4092 | BCMA_CC_PMU_CTL_NOILPONW; | ||
4093 | } else if (dev->dev->chip_id == 0x4322 || | ||
4094 | dev->dev->chip_id == 0x4340 || | ||
4095 | dev->dev->chip_id == 0x4341) { | ||
4096 | bcma_chipco_pll_write(cc, 0x0, 0x11100070); | ||
4097 | bcma_chipco_pll_write(cc, 0x1, 0x1014140a); | ||
4098 | bcma_chipco_pll_write(cc, 0x5, 0x88888854); | ||
4099 | if (avoid) | ||
4100 | bcma_chipco_pll_write(cc, 0x2, 0x05201828); | ||
4101 | else | ||
4102 | bcma_chipco_pll_write(cc, 0x2, 0x05001828); | ||
4103 | pmu_ctl = BCMA_CC_PMU_CTL_PLL_UPD; | ||
4104 | } else { | ||
4105 | return; | ||
4106 | } | ||
4107 | bcma_cc_set32(cc, BCMA_CC_PMU_CTL, pmu_ctl); | ||
4108 | break; | ||
4109 | #endif | ||
4110 | #ifdef CONFIG_B43_SSB | ||
4111 | case B43_BUS_SSB: | ||
4112 | /* FIXME */ | ||
4113 | break; | ||
4114 | #endif | ||
4115 | } | ||
4116 | } | ||
4117 | |||
3931 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ChanspecSetup */ | 4118 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ChanspecSetup */ |
3932 | static void b43_nphy_channel_setup(struct b43_wldev *dev, | 4119 | static void b43_nphy_channel_setup(struct b43_wldev *dev, |
3933 | const struct b43_phy_n_sfo_cfg *e, | 4120 | const struct b43_phy_n_sfo_cfg *e, |
@@ -3935,6 +4122,7 @@ static void b43_nphy_channel_setup(struct b43_wldev *dev, | |||
3935 | { | 4122 | { |
3936 | struct b43_phy *phy = &dev->phy; | 4123 | struct b43_phy *phy = &dev->phy; |
3937 | struct b43_phy_n *nphy = dev->phy.n; | 4124 | struct b43_phy_n *nphy = dev->phy.n; |
4125 | int ch = new_channel->hw_value; | ||
3938 | 4126 | ||
3939 | u16 old_band_5ghz; | 4127 | u16 old_band_5ghz; |
3940 | u32 tmp32; | 4128 | u32 tmp32; |
@@ -3974,8 +4162,41 @@ static void b43_nphy_channel_setup(struct b43_wldev *dev, | |||
3974 | 4162 | ||
3975 | b43_nphy_tx_lp_fbw(dev); | 4163 | b43_nphy_tx_lp_fbw(dev); |
3976 | 4164 | ||
3977 | if (dev->phy.rev >= 3 && 0) { | 4165 | if (dev->phy.rev >= 3 && |
3978 | /* TODO */ | 4166 | dev->phy.n->spur_avoid != B43_SPUR_AVOID_DISABLE) { |
4167 | bool avoid = false; | ||
4168 | if (dev->phy.n->spur_avoid == B43_SPUR_AVOID_FORCE) { | ||
4169 | avoid = true; | ||
4170 | } else if (!b43_channel_type_is_40mhz(phy->channel_type)) { | ||
4171 | if ((ch >= 5 && ch <= 8) || ch == 13 || ch == 14) | ||
4172 | avoid = true; | ||
4173 | } else { /* 40MHz */ | ||
4174 | if (nphy->aband_spurwar_en && | ||
4175 | (ch == 38 || ch == 102 || ch == 118)) | ||
4176 | avoid = dev->dev->chip_id == 0x4716; | ||
4177 | } | ||
4178 | |||
4179 | b43_nphy_pmu_spur_avoid(dev, avoid); | ||
4180 | |||
4181 | if (dev->dev->chip_id == 43222 || dev->dev->chip_id == 43224 || | ||
4182 | dev->dev->chip_id == 43225) { | ||
4183 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, | ||
4184 | avoid ? 0x5341 : 0x8889); | ||
4185 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8); | ||
4186 | } | ||
4187 | |||
4188 | if (dev->phy.rev == 3 || dev->phy.rev == 4) | ||
4189 | ; /* TODO: reset PLL */ | ||
4190 | |||
4191 | if (avoid) | ||
4192 | b43_phy_set(dev, B43_NPHY_BBCFG, B43_NPHY_BBCFG_RSTRX); | ||
4193 | else | ||
4194 | b43_phy_mask(dev, B43_NPHY_BBCFG, | ||
4195 | ~B43_NPHY_BBCFG_RSTRX & 0xFFFF); | ||
4196 | |||
4197 | b43_nphy_reset_cca(dev); | ||
4198 | |||
4199 | /* wl sets useless phy_isspuravoid here */ | ||
3979 | } | 4200 | } |
3980 | 4201 | ||
3981 | b43_phy_write(dev, B43_NPHY_NDATAT_DUP40, 0x3830); | 4202 | b43_phy_write(dev, B43_NPHY_NDATAT_DUP40, 0x3830); |
@@ -4055,10 +4276,13 @@ static void b43_nphy_op_prepare_structs(struct b43_wldev *dev) | |||
4055 | { | 4276 | { |
4056 | struct b43_phy *phy = &dev->phy; | 4277 | struct b43_phy *phy = &dev->phy; |
4057 | struct b43_phy_n *nphy = phy->n; | 4278 | struct b43_phy_n *nphy = phy->n; |
4279 | struct ssb_sprom *sprom = dev->dev->bus_sprom; | ||
4058 | 4280 | ||
4059 | memset(nphy, 0, sizeof(*nphy)); | 4281 | memset(nphy, 0, sizeof(*nphy)); |
4060 | 4282 | ||
4061 | nphy->hang_avoid = (phy->rev == 3 || phy->rev == 4); | 4283 | nphy->hang_avoid = (phy->rev == 3 || phy->rev == 4); |
4284 | nphy->spur_avoid = (phy->rev >= 3) ? | ||
4285 | B43_SPUR_AVOID_AUTO : B43_SPUR_AVOID_DISABLE; | ||
4062 | nphy->gain_boost = true; /* this way we follow wl, assume it is true */ | 4286 | nphy->gain_boost = true; /* this way we follow wl, assume it is true */ |
4063 | nphy->txrx_chain = 2; /* sth different than 0 and 1 for now */ | 4287 | nphy->txrx_chain = 2; /* sth different than 0 and 1 for now */ |
4064 | nphy->phyrxchain = 3; /* to avoid b43_nphy_set_rx_core_state like wl */ | 4288 | nphy->phyrxchain = 3; /* to avoid b43_nphy_set_rx_core_state like wl */ |
@@ -4067,6 +4291,38 @@ static void b43_nphy_op_prepare_structs(struct b43_wldev *dev) | |||
4067 | * 0x7f == 127 and we check for 128 when restoring TX pwr ctl. */ | 4291 | * 0x7f == 127 and we check for 128 when restoring TX pwr ctl. */ |
4068 | nphy->tx_pwr_idx[0] = 128; | 4292 | nphy->tx_pwr_idx[0] = 128; |
4069 | nphy->tx_pwr_idx[1] = 128; | 4293 | nphy->tx_pwr_idx[1] = 128; |
4294 | |||
4295 | /* Hardware TX power control and 5GHz power gain */ | ||
4296 | nphy->txpwrctrl = false; | ||
4297 | nphy->pwg_gain_5ghz = false; | ||
4298 | if (dev->phy.rev >= 3 || | ||
4299 | (dev->dev->board_vendor == PCI_VENDOR_ID_APPLE && | ||
4300 | (dev->dev->core_rev == 11 || dev->dev->core_rev == 12))) { | ||
4301 | nphy->txpwrctrl = true; | ||
4302 | nphy->pwg_gain_5ghz = true; | ||
4303 | } else if (sprom->revision >= 4) { | ||
4304 | if (dev->phy.rev >= 2 && | ||
4305 | (sprom->boardflags2_lo & B43_BFL2_TXPWRCTRL_EN)) { | ||
4306 | nphy->txpwrctrl = true; | ||
4307 | #ifdef CONFIG_B43_SSB | ||
4308 | if (dev->dev->bus_type == B43_BUS_SSB && | ||
4309 | dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI) { | ||
4310 | struct pci_dev *pdev = | ||
4311 | dev->dev->sdev->bus->host_pci; | ||
4312 | if (pdev->device == 0x4328 || | ||
4313 | pdev->device == 0x432a) | ||
4314 | nphy->pwg_gain_5ghz = true; | ||
4315 | } | ||
4316 | #endif | ||
4317 | } else if (sprom->boardflags2_lo & B43_BFL2_5G_PWRGAIN) { | ||
4318 | nphy->pwg_gain_5ghz = true; | ||
4319 | } | ||
4320 | } | ||
4321 | |||
4322 | if (dev->phy.rev >= 3) { | ||
4323 | nphy->ipa2g_on = sprom->fem.ghz2.extpa_gain == 2; | ||
4324 | nphy->ipa5g_on = sprom->fem.ghz5.extpa_gain == 2; | ||
4325 | } | ||
4070 | } | 4326 | } |
4071 | 4327 | ||
4072 | static void b43_nphy_op_free(struct b43_wldev *dev) | 4328 | static void b43_nphy_op_free(struct b43_wldev *dev) |
diff --git a/drivers/net/wireless/b43/phy_n.h b/drivers/net/wireless/b43/phy_n.h index fbf520285bd1..56ef97b5b815 100644 --- a/drivers/net/wireless/b43/phy_n.h +++ b/drivers/net/wireless/b43/phy_n.h | |||
@@ -716,6 +716,12 @@ | |||
716 | 716 | ||
717 | struct b43_wldev; | 717 | struct b43_wldev; |
718 | 718 | ||
719 | enum b43_nphy_spur_avoid { | ||
720 | B43_SPUR_AVOID_DISABLE, | ||
721 | B43_SPUR_AVOID_AUTO, | ||
722 | B43_SPUR_AVOID_FORCE, | ||
723 | }; | ||
724 | |||
719 | struct b43_chanspec { | 725 | struct b43_chanspec { |
720 | u16 center_freq; | 726 | u16 center_freq; |
721 | enum nl80211_channel_type channel_type; | 727 | enum nl80211_channel_type channel_type; |
@@ -785,6 +791,7 @@ struct b43_phy_n { | |||
785 | u16 mphase_txcal_bestcoeffs[11]; | 791 | u16 mphase_txcal_bestcoeffs[11]; |
786 | 792 | ||
787 | bool txpwrctrl; | 793 | bool txpwrctrl; |
794 | bool pwg_gain_5ghz; | ||
788 | u8 tx_pwr_idx[2]; | 795 | u8 tx_pwr_idx[2]; |
789 | u16 adj_pwr_tbl[84]; | 796 | u16 adj_pwr_tbl[84]; |
790 | u16 txcal_bbmult; | 797 | u16 txcal_bbmult; |
@@ -803,6 +810,7 @@ struct b43_phy_n { | |||
803 | u16 classifier_state; | 810 | u16 classifier_state; |
804 | u16 clip_state[2]; | 811 | u16 clip_state[2]; |
805 | 812 | ||
813 | enum b43_nphy_spur_avoid spur_avoid; | ||
806 | bool aband_spurwar_en; | 814 | bool aband_spurwar_en; |
807 | bool gband_spurwar_en; | 815 | bool gband_spurwar_en; |
808 | 816 | ||
diff --git a/drivers/net/wireless/b43/radio_2056.c b/drivers/net/wireless/b43/radio_2056.c index a01f776ca4de..ce037fb6789a 100644 --- a/drivers/net/wireless/b43/radio_2056.c +++ b/drivers/net/wireless/b43/radio_2056.c | |||
@@ -1572,14 +1572,14 @@ static const struct b2056_inittab_entry b2056_inittab_rev6_syn[] = { | |||
1572 | [B2056_SYN_PLL_XTAL5] = { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, }, | 1572 | [B2056_SYN_PLL_XTAL5] = { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, }, |
1573 | [B2056_SYN_PLL_XTAL6] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, | 1573 | [B2056_SYN_PLL_XTAL6] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, |
1574 | [B2056_SYN_PLL_REFDIV] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, | 1574 | [B2056_SYN_PLL_REFDIV] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, |
1575 | [B2056_SYN_PLL_PFD] = { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, }, | 1575 | [B2056_SYN_PLL_PFD] = { .ghz5 = 0x0006, .ghz2 = 0x0006, UPLOAD, }, |
1576 | [B2056_SYN_PLL_CP1] = { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, }, | 1576 | [B2056_SYN_PLL_CP1] = { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, }, |
1577 | [B2056_SYN_PLL_CP2] = { .ghz5 = 0x0030, .ghz2 = 0x0030, NOUPLOAD, }, | 1577 | [B2056_SYN_PLL_CP2] = { .ghz5 = 0x003f, .ghz2 = 0x003f, UPLOAD, }, |
1578 | [B2056_SYN_PLL_CP3] = { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, }, | 1578 | [B2056_SYN_PLL_CP3] = { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, }, |
1579 | [B2056_SYN_PLL_LOOPFILTER1] = { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, }, | 1579 | [B2056_SYN_PLL_LOOPFILTER1] = { .ghz5 = 0x0006, .ghz2 = 0x0006, UPLOAD, }, |
1580 | [B2056_SYN_PLL_LOOPFILTER2] = { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, }, | 1580 | [B2056_SYN_PLL_LOOPFILTER2] = { .ghz5 = 0x0006, .ghz2 = 0x0006, UPLOAD, }, |
1581 | [B2056_SYN_PLL_LOOPFILTER3] = { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, }, | 1581 | [B2056_SYN_PLL_LOOPFILTER3] = { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, }, |
1582 | [B2056_SYN_PLL_LOOPFILTER4] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, | 1582 | [B2056_SYN_PLL_LOOPFILTER4] = { .ghz5 = 0x002b, .ghz2 = 0x002b, UPLOAD, }, |
1583 | [B2056_SYN_PLL_LOOPFILTER5] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, | 1583 | [B2056_SYN_PLL_LOOPFILTER5] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, |
1584 | [B2056_SYN_PLL_MMD1] = { .ghz5 = 0x001c, .ghz2 = 0x001c, NOUPLOAD, }, | 1584 | [B2056_SYN_PLL_MMD1] = { .ghz5 = 0x001c, .ghz2 = 0x001c, NOUPLOAD, }, |
1585 | [B2056_SYN_PLL_MMD2] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, | 1585 | [B2056_SYN_PLL_MMD2] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, |
@@ -9055,6 +9055,21 @@ void b2056_upload_inittabs(struct b43_wldev *dev, | |||
9055 | B2056_RX1, pts->rx, pts->rx_length); | 9055 | B2056_RX1, pts->rx, pts->rx_length); |
9056 | } | 9056 | } |
9057 | 9057 | ||
9058 | void b2056_upload_syn_pll_cp2(struct b43_wldev *dev, bool ghz5) | ||
9059 | { | ||
9060 | struct b2056_inittabs_pts *pts; | ||
9061 | const struct b2056_inittab_entry *e; | ||
9062 | |||
9063 | if (dev->phy.rev >= ARRAY_SIZE(b2056_inittabs)) { | ||
9064 | B43_WARN_ON(1); | ||
9065 | return; | ||
9066 | } | ||
9067 | pts = &b2056_inittabs[dev->phy.rev]; | ||
9068 | e = &pts->syn[B2056_SYN_PLL_CP2]; | ||
9069 | |||
9070 | b43_radio_write(dev, B2056_SYN_PLL_CP2, ghz5 ? e->ghz5 : e->ghz2); | ||
9071 | } | ||
9072 | |||
9058 | const struct b43_nphy_channeltab_entry_rev3 * | 9073 | const struct b43_nphy_channeltab_entry_rev3 * |
9059 | b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq) | 9074 | b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq) |
9060 | { | 9075 | { |
diff --git a/drivers/net/wireless/b43/radio_2056.h b/drivers/net/wireless/b43/radio_2056.h index a7159d8578be..5b86673459fa 100644 --- a/drivers/net/wireless/b43/radio_2056.h +++ b/drivers/net/wireless/b43/radio_2056.h | |||
@@ -1090,6 +1090,7 @@ struct b43_nphy_channeltab_entry_rev3 { | |||
1090 | 1090 | ||
1091 | void b2056_upload_inittabs(struct b43_wldev *dev, | 1091 | void b2056_upload_inittabs(struct b43_wldev *dev, |
1092 | bool ghz5, bool ignore_uploadflag); | 1092 | bool ghz5, bool ignore_uploadflag); |
1093 | void b2056_upload_syn_pll_cp2(struct b43_wldev *dev, bool ghz5); | ||
1093 | 1094 | ||
1094 | /* Get the NPHY Channel Switch Table entry for a channel. | 1095 | /* Get the NPHY Channel Switch Table entry for a channel. |
1095 | * Returns NULL on failure to find an entry. */ | 1096 | * Returns NULL on failure to find an entry. */ |
diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c index 7b326f2efdc9..3252560e9fa1 100644 --- a/drivers/net/wireless/b43/tables_nphy.c +++ b/drivers/net/wireless/b43/tables_nphy.c | |||
@@ -2171,6 +2171,48 @@ static const u16 b43_ntab_loftlt1_r3[] = { | |||
2171 | 0x0000, 0x0000, | 2171 | 0x0000, 0x0000, |
2172 | }; | 2172 | }; |
2173 | 2173 | ||
2174 | /* volatile tables, PHY revision >= 3 */ | ||
2175 | |||
2176 | /* indexed by antswctl2g */ | ||
2177 | static const u16 b43_ntab_antswctl2g_r3[4][32] = { | ||
2178 | { | ||
2179 | 0x0082, 0x0082, 0x0211, 0x0222, 0x0328, | ||
2180 | 0x0000, 0x0000, 0x0000, 0x0144, 0x0000, | ||
2181 | 0x0000, 0x0000, 0x0188, 0x0000, 0x0000, | ||
2182 | 0x0000, 0x0082, 0x0082, 0x0211, 0x0222, | ||
2183 | 0x0328, 0x0000, 0x0000, 0x0000, 0x0144, | ||
2184 | 0x0000, 0x0000, 0x0000, 0x0188, 0x0000, | ||
2185 | 0x0000, 0x0000, | ||
2186 | }, | ||
2187 | { | ||
2188 | 0x0022, 0x0022, 0x0011, 0x0022, 0x0022, | ||
2189 | 0x0000, 0x0000, 0x0000, 0x0011, 0x0000, | ||
2190 | 0x0000, 0x0000, 0x0022, 0x0000, 0x0000, | ||
2191 | 0x0000, 0x0022, 0x0022, 0x0011, 0x0022, | ||
2192 | 0x0022, 0x0000, 0x0000, 0x0000, 0x0011, | ||
2193 | 0x0000, 0x0000, 0x0000, 0x0022, 0x0000, | ||
2194 | 0x0000, 0x0000, | ||
2195 | }, | ||
2196 | { | ||
2197 | 0x0088, 0x0088, 0x0044, 0x0088, 0x0088, | ||
2198 | 0x0000, 0x0000, 0x0000, 0x0044, 0x0000, | ||
2199 | 0x0000, 0x0000, 0x0088, 0x0000, 0x0000, | ||
2200 | 0x0000, 0x0088, 0x0088, 0x0044, 0x0088, | ||
2201 | 0x0088, 0x0000, 0x0000, 0x0000, 0x0044, | ||
2202 | 0x0000, 0x0000, 0x0000, 0x0088, 0x0000, | ||
2203 | 0x0000, 0x0000, | ||
2204 | }, | ||
2205 | { | ||
2206 | 0x0022, 0x0022, 0x0011, 0x0022, 0x0000, | ||
2207 | 0x0000, 0x0000, 0x0000, 0x0011, 0x0000, | ||
2208 | 0x0000, 0x0000, 0x0022, 0x0000, 0x0000, | ||
2209 | 0x03cc, 0x0022, 0x0022, 0x0011, 0x0022, | ||
2210 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0011, | ||
2211 | 0x0000, 0x0000, 0x0000, 0x0022, 0x0000, | ||
2212 | 0x0000, 0x03cc, | ||
2213 | } | ||
2214 | }; | ||
2215 | |||
2174 | /* TX gain tables */ | 2216 | /* TX gain tables */ |
2175 | const u32 b43_ntab_tx_gain_rev0_1_2[] = { | 2217 | const u32 b43_ntab_tx_gain_rev0_1_2[] = { |
2176 | 0x03cc2b44, 0x03cc2b42, 0x03cc2a44, 0x03cc2a42, | 2218 | 0x03cc2b44, 0x03cc2b42, 0x03cc2a44, 0x03cc2a42, |
@@ -2652,7 +2694,7 @@ const u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[] = { | |||
2652 | const s16 tbl_tx_filter_coef_rev4[7][15] = { | 2694 | const s16 tbl_tx_filter_coef_rev4[7][15] = { |
2653 | { -377, 137, -407, 208, -1527, | 2695 | { -377, 137, -407, 208, -1527, |
2654 | 956, 93, 186, 93, 230, | 2696 | 956, 93, 186, 93, 230, |
2655 | -44, 230, 20, -191, 201 }, | 2697 | -44, 230, 201, -191, 201 }, |
2656 | { -77, 20, -98, 49, -93, | 2698 | { -77, 20, -98, 49, -93, |
2657 | 60, 56, 111, 56, 26, | 2699 | 60, 56, 111, 56, 26, |
2658 | -5, 26, 34, -32, 34 }, | 2700 | -5, 26, 34, -32, 34 }, |
@@ -2838,9 +2880,8 @@ u32 b43_ntab_read(struct b43_wldev *dev, u32 offset) | |||
2838 | break; | 2880 | break; |
2839 | case B43_NTAB_32BIT: | 2881 | case B43_NTAB_32BIT: |
2840 | b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset); | 2882 | b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset); |
2841 | value = b43_phy_read(dev, B43_NPHY_TABLE_DATAHI); | 2883 | value = b43_phy_read(dev, B43_NPHY_TABLE_DATALO); |
2842 | value <<= 16; | 2884 | value |= b43_phy_read(dev, B43_NPHY_TABLE_DATAHI) << 16; |
2843 | value |= b43_phy_read(dev, B43_NPHY_TABLE_DATALO); | ||
2844 | break; | 2885 | break; |
2845 | default: | 2886 | default: |
2846 | B43_WARN_ON(1); | 2887 | B43_WARN_ON(1); |
@@ -2864,6 +2905,12 @@ void b43_ntab_read_bulk(struct b43_wldev *dev, u32 offset, | |||
2864 | b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset); | 2905 | b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset); |
2865 | 2906 | ||
2866 | for (i = 0; i < nr_elements; i++) { | 2907 | for (i = 0; i < nr_elements; i++) { |
2908 | /* Auto increment broken + caching issue on BCM43224? */ | ||
2909 | if (dev->dev->chip_id == 43224 && dev->dev->chip_rev == 1) { | ||
2910 | b43_phy_read(dev, B43_NPHY_TABLE_DATALO); | ||
2911 | b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset + i); | ||
2912 | } | ||
2913 | |||
2867 | switch (type) { | 2914 | switch (type) { |
2868 | case B43_NTAB_8BIT: | 2915 | case B43_NTAB_8BIT: |
2869 | *data = b43_phy_read(dev, B43_NPHY_TABLE_DATALO) & 0xFF; | 2916 | *data = b43_phy_read(dev, B43_NPHY_TABLE_DATALO) & 0xFF; |
@@ -2874,9 +2921,10 @@ void b43_ntab_read_bulk(struct b43_wldev *dev, u32 offset, | |||
2874 | data += 2; | 2921 | data += 2; |
2875 | break; | 2922 | break; |
2876 | case B43_NTAB_32BIT: | 2923 | case B43_NTAB_32BIT: |
2877 | *((u32 *)data) = b43_phy_read(dev, B43_NPHY_TABLE_DATAHI); | 2924 | *((u32 *)data) = |
2878 | *((u32 *)data) <<= 16; | 2925 | b43_phy_read(dev, B43_NPHY_TABLE_DATALO); |
2879 | *((u32 *)data) |= b43_phy_read(dev, B43_NPHY_TABLE_DATALO); | 2926 | *((u32 *)data) |= |
2927 | b43_phy_read(dev, B43_NPHY_TABLE_DATAHI) << 16; | ||
2880 | data += 4; | 2928 | data += 4; |
2881 | break; | 2929 | break; |
2882 | default: | 2930 | default: |
@@ -2932,6 +2980,13 @@ void b43_ntab_write_bulk(struct b43_wldev *dev, u32 offset, | |||
2932 | b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset); | 2980 | b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset); |
2933 | 2981 | ||
2934 | for (i = 0; i < nr_elements; i++) { | 2982 | for (i = 0; i < nr_elements; i++) { |
2983 | /* Auto increment broken + caching issue on BCM43224? */ | ||
2984 | if ((offset >> 10) == 9 && dev->dev->chip_id == 43224 && | ||
2985 | dev->dev->chip_rev == 1) { | ||
2986 | b43_phy_read(dev, B43_NPHY_TABLE_DATALO); | ||
2987 | b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset + i); | ||
2988 | } | ||
2989 | |||
2935 | switch (type) { | 2990 | switch (type) { |
2936 | case B43_NTAB_8BIT: | 2991 | case B43_NTAB_8BIT: |
2937 | value = *data; | 2992 | value = *data; |
@@ -2999,6 +3054,8 @@ void b43_nphy_rev0_1_2_tables_init(struct b43_wldev *dev) | |||
2999 | } while (0) | 3054 | } while (0) |
3000 | void b43_nphy_rev3plus_tables_init(struct b43_wldev *dev) | 3055 | void b43_nphy_rev3plus_tables_init(struct b43_wldev *dev) |
3001 | { | 3056 | { |
3057 | struct ssb_sprom *sprom = dev->dev->bus_sprom; | ||
3058 | |||
3002 | /* Static tables */ | 3059 | /* Static tables */ |
3003 | ntab_upload_r3(dev, B43_NTAB_FRAMESTRUCT_R3, b43_ntab_framestruct_r3); | 3060 | ntab_upload_r3(dev, B43_NTAB_FRAMESTRUCT_R3, b43_ntab_framestruct_r3); |
3004 | ntab_upload_r3(dev, B43_NTAB_PILOT_R3, b43_ntab_pilot_r3); | 3061 | ntab_upload_r3(dev, B43_NTAB_PILOT_R3, b43_ntab_pilot_r3); |
@@ -3029,7 +3086,11 @@ void b43_nphy_rev3plus_tables_init(struct b43_wldev *dev) | |||
3029 | ntab_upload_r3(dev, B43_NTAB_C1_LOFEEDTH_R3, b43_ntab_loftlt1_r3); | 3086 | ntab_upload_r3(dev, B43_NTAB_C1_LOFEEDTH_R3, b43_ntab_loftlt1_r3); |
3030 | 3087 | ||
3031 | /* Volatile tables */ | 3088 | /* Volatile tables */ |
3032 | /* TODO */ | 3089 | if (sprom->fem.ghz2.antswlut < ARRAY_SIZE(b43_ntab_antswctl2g_r3)) |
3090 | ntab_upload_r3(dev, B43_NTAB_ANT_SW_CTL_R3, | ||
3091 | b43_ntab_antswctl2g_r3[sprom->fem.ghz2.antswlut]); | ||
3092 | else | ||
3093 | B43_WARN_ON(1); | ||
3033 | } | 3094 | } |
3034 | 3095 | ||
3035 | struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent( | 3096 | struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent( |
diff --git a/drivers/net/wireless/b43/tables_nphy.h b/drivers/net/wireless/b43/tables_nphy.h index a81696bff0ed..97038c481930 100644 --- a/drivers/net/wireless/b43/tables_nphy.h +++ b/drivers/net/wireless/b43/tables_nphy.h | |||
@@ -126,26 +126,29 @@ struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent( | |||
126 | #define B43_NTAB_C1_LOFEEDTH B43_NTAB16(0x1B, 0x1C0) /* Local Oscillator Feed Through Lookup Table Core 1 */ | 126 | #define B43_NTAB_C1_LOFEEDTH B43_NTAB16(0x1B, 0x1C0) /* Local Oscillator Feed Through Lookup Table Core 1 */ |
127 | #define B43_NTAB_C1_LOFEEDTH_SIZE 128 | 127 | #define B43_NTAB_C1_LOFEEDTH_SIZE 128 |
128 | 128 | ||
129 | /* Volatile N-PHY tables, PHY revision >= 3 */ | ||
130 | #define B43_NTAB_ANT_SW_CTL_R3 B43_NTAB16( 9, 0) /* antenna software control */ | ||
131 | |||
129 | /* Static N-PHY tables, PHY revision >= 3 */ | 132 | /* Static N-PHY tables, PHY revision >= 3 */ |
130 | #define B43_NTAB_FRAMESTRUCT_R3 B43_NTAB32(10, 000) /* frame struct */ | 133 | #define B43_NTAB_FRAMESTRUCT_R3 B43_NTAB32(10, 0) /* frame struct */ |
131 | #define B43_NTAB_PILOT_R3 B43_NTAB16(11, 000) /* pilot */ | 134 | #define B43_NTAB_PILOT_R3 B43_NTAB16(11, 0) /* pilot */ |
132 | #define B43_NTAB_TMAP_R3 B43_NTAB32(12, 000) /* TM AP */ | 135 | #define B43_NTAB_TMAP_R3 B43_NTAB32(12, 0) /* TM AP */ |
133 | #define B43_NTAB_INTLEVEL_R3 B43_NTAB32(13, 000) /* INT LV */ | 136 | #define B43_NTAB_INTLEVEL_R3 B43_NTAB32(13, 0) /* INT LV */ |
134 | #define B43_NTAB_TDTRN_R3 B43_NTAB32(14, 000) /* TD TRN */ | 137 | #define B43_NTAB_TDTRN_R3 B43_NTAB32(14, 0) /* TD TRN */ |
135 | #define B43_NTAB_NOISEVAR0_R3 B43_NTAB32(16, 000) /* noise variance 0 */ | 138 | #define B43_NTAB_NOISEVAR0_R3 B43_NTAB32(16, 0) /* noise variance 0 */ |
136 | #define B43_NTAB_NOISEVAR1_R3 B43_NTAB32(16, 128) /* noise variance 1 */ | 139 | #define B43_NTAB_NOISEVAR1_R3 B43_NTAB32(16, 128) /* noise variance 1 */ |
137 | #define B43_NTAB_MCS_R3 B43_NTAB16(18, 000) /* MCS */ | 140 | #define B43_NTAB_MCS_R3 B43_NTAB16(18, 0) /* MCS */ |
138 | #define B43_NTAB_TDI20A0_R3 B43_NTAB32(19, 128) /* TDI 20/0 */ | 141 | #define B43_NTAB_TDI20A0_R3 B43_NTAB32(19, 128) /* TDI 20/0 */ |
139 | #define B43_NTAB_TDI20A1_R3 B43_NTAB32(19, 256) /* TDI 20/1 */ | 142 | #define B43_NTAB_TDI20A1_R3 B43_NTAB32(19, 256) /* TDI 20/1 */ |
140 | #define B43_NTAB_TDI40A0_R3 B43_NTAB32(19, 640) /* TDI 40/0 */ | 143 | #define B43_NTAB_TDI40A0_R3 B43_NTAB32(19, 640) /* TDI 40/0 */ |
141 | #define B43_NTAB_TDI40A1_R3 B43_NTAB32(19, 768) /* TDI 40/1 */ | 144 | #define B43_NTAB_TDI40A1_R3 B43_NTAB32(19, 768) /* TDI 40/1 */ |
142 | #define B43_NTAB_PILOTLT_R3 B43_NTAB32(20, 000) /* PLT lookup */ | 145 | #define B43_NTAB_PILOTLT_R3 B43_NTAB32(20, 0) /* PLT lookup */ |
143 | #define B43_NTAB_CHANEST_R3 B43_NTAB32(22, 000) /* channel estimate */ | 146 | #define B43_NTAB_CHANEST_R3 B43_NTAB32(22, 0) /* channel estimate */ |
144 | #define B43_NTAB_FRAMELT_R3 B43_NTAB8 (24, 000) /* frame lookup */ | 147 | #define B43_NTAB_FRAMELT_R3 B43_NTAB8(24, 0) /* frame lookup */ |
145 | #define B43_NTAB_C0_ESTPLT_R3 B43_NTAB8 (26, 000) /* estimated power lookup 0 */ | 148 | #define B43_NTAB_C0_ESTPLT_R3 B43_NTAB8(26, 0) /* estimated power lookup 0 */ |
146 | #define B43_NTAB_C1_ESTPLT_R3 B43_NTAB8 (27, 000) /* estimated power lookup 1 */ | 149 | #define B43_NTAB_C1_ESTPLT_R3 B43_NTAB8(27, 0) /* estimated power lookup 1 */ |
147 | #define B43_NTAB_C0_ADJPLT_R3 B43_NTAB8 (26, 064) /* adjusted power lookup 0 */ | 150 | #define B43_NTAB_C0_ADJPLT_R3 B43_NTAB8(26, 64) /* adjusted power lookup 0 */ |
148 | #define B43_NTAB_C1_ADJPLT_R3 B43_NTAB8 (27, 064) /* adjusted power lookup 1 */ | 151 | #define B43_NTAB_C1_ADJPLT_R3 B43_NTAB8(27, 64) /* adjusted power lookup 1 */ |
149 | #define B43_NTAB_C0_GAINCTL_R3 B43_NTAB32(26, 192) /* gain control lookup 0 */ | 152 | #define B43_NTAB_C0_GAINCTL_R3 B43_NTAB32(26, 192) /* gain control lookup 0 */ |
150 | #define B43_NTAB_C1_GAINCTL_R3 B43_NTAB32(27, 192) /* gain control lookup 1 */ | 153 | #define B43_NTAB_C1_GAINCTL_R3 B43_NTAB32(27, 192) /* gain control lookup 1 */ |
151 | #define B43_NTAB_C0_IQLT_R3 B43_NTAB32(26, 320) /* I/Q lookup 0 */ | 154 | #define B43_NTAB_C0_IQLT_R3 B43_NTAB32(26, 320) /* I/Q lookup 0 */ |
diff --git a/drivers/net/wireless/brcm80211/Kconfig b/drivers/net/wireless/brcm80211/Kconfig index 2069fc8f7ad1..8f54c2eb6824 100644 --- a/drivers/net/wireless/brcm80211/Kconfig +++ b/drivers/net/wireless/brcm80211/Kconfig | |||
@@ -3,9 +3,8 @@ config BRCMUTIL | |||
3 | 3 | ||
4 | config BRCMSMAC | 4 | config BRCMSMAC |
5 | tristate "Broadcom IEEE802.11n PCIe SoftMAC WLAN driver" | 5 | tristate "Broadcom IEEE802.11n PCIe SoftMAC WLAN driver" |
6 | depends on PCI | ||
7 | depends on MAC80211 | 6 | depends on MAC80211 |
8 | depends on BCMA=n | 7 | depends on BCMA |
9 | select BRCMUTIL | 8 | select BRCMUTIL |
10 | select FW_LOADER | 9 | select FW_LOADER |
11 | select CRC_CCITT | 10 | select CRC_CCITT |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index 74933dccf69e..6c85d668c9d7 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | |||
@@ -40,8 +40,7 @@ | |||
40 | 40 | ||
41 | static void brcmf_sdioh_irqhandler(struct sdio_func *func) | 41 | static void brcmf_sdioh_irqhandler(struct sdio_func *func) |
42 | { | 42 | { |
43 | struct brcmf_bus *bus_if = dev_get_drvdata(&func->card->dev); | 43 | struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev); |
44 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv; | ||
45 | 44 | ||
46 | brcmf_dbg(TRACE, "***IRQHandler\n"); | 45 | brcmf_dbg(TRACE, "***IRQHandler\n"); |
47 | 46 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c index b416e274c677..b895f198a950 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #define DMA_ALIGN_MASK 0x03 | 40 | #define DMA_ALIGN_MASK 0x03 |
41 | 41 | ||
42 | #define SDIO_DEVICE_ID_BROADCOM_4329 0x4329 | 42 | #define SDIO_DEVICE_ID_BROADCOM_4329 0x4329 |
43 | #define SDIO_DEVICE_ID_BROADCOM_4330 0x4330 | ||
43 | 44 | ||
44 | #define SDIO_FUNC1_BLOCKSIZE 64 | 45 | #define SDIO_FUNC1_BLOCKSIZE 64 |
45 | #define SDIO_FUNC2_BLOCKSIZE 512 | 46 | #define SDIO_FUNC2_BLOCKSIZE 512 |
@@ -47,6 +48,7 @@ | |||
47 | /* devices we support, null terminated */ | 48 | /* devices we support, null terminated */ |
48 | static const struct sdio_device_id brcmf_sdmmc_ids[] = { | 49 | static const struct sdio_device_id brcmf_sdmmc_ids[] = { |
49 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)}, | 50 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)}, |
51 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330)}, | ||
50 | { /* end: all zeroes */ }, | 52 | { /* end: all zeroes */ }, |
51 | }; | 53 | }; |
52 | MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); | 54 | MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); |
@@ -481,12 +483,12 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, | |||
481 | kfree(bus_if); | 483 | kfree(bus_if); |
482 | return -ENOMEM; | 484 | return -ENOMEM; |
483 | } | 485 | } |
484 | sdiodev->dev = &func->card->dev; | ||
485 | sdiodev->func[0] = func->card->sdio_func[0]; | 486 | sdiodev->func[0] = func->card->sdio_func[0]; |
486 | sdiodev->func[1] = func; | 487 | sdiodev->func[1] = func; |
488 | sdiodev->bus_if = bus_if; | ||
487 | bus_if->bus_priv = sdiodev; | 489 | bus_if->bus_priv = sdiodev; |
488 | bus_if->type = SDIO_BUS; | 490 | bus_if->type = SDIO_BUS; |
489 | dev_set_drvdata(&func->card->dev, bus_if); | 491 | dev_set_drvdata(&func->card->dev, sdiodev); |
490 | 492 | ||
491 | atomic_set(&sdiodev->suspend, false); | 493 | atomic_set(&sdiodev->suspend, false); |
492 | init_waitqueue_head(&sdiodev->request_byte_wait); | 494 | init_waitqueue_head(&sdiodev->request_byte_wait); |
@@ -496,12 +498,15 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, | |||
496 | } | 498 | } |
497 | 499 | ||
498 | if (func->num == 2) { | 500 | if (func->num == 2) { |
499 | bus_if = dev_get_drvdata(&func->card->dev); | 501 | sdiodev = dev_get_drvdata(&func->card->dev); |
500 | sdiodev = bus_if->bus_priv; | ||
501 | if ((!sdiodev) || (sdiodev->func[1]->card != func->card)) | 502 | if ((!sdiodev) || (sdiodev->func[1]->card != func->card)) |
502 | return -ENODEV; | 503 | return -ENODEV; |
503 | sdiodev->func[2] = func; | 504 | sdiodev->func[2] = func; |
504 | 505 | ||
506 | bus_if = sdiodev->bus_if; | ||
507 | sdiodev->dev = &func->dev; | ||
508 | dev_set_drvdata(&func->dev, bus_if); | ||
509 | |||
505 | brcmf_dbg(TRACE, "F2 found, calling brcmf_sdio_probe...\n"); | 510 | brcmf_dbg(TRACE, "F2 found, calling brcmf_sdio_probe...\n"); |
506 | ret = brcmf_sdio_probe(sdiodev); | 511 | ret = brcmf_sdio_probe(sdiodev); |
507 | } | 512 | } |
@@ -520,11 +525,12 @@ static void brcmf_ops_sdio_remove(struct sdio_func *func) | |||
520 | brcmf_dbg(INFO, "Function#: 0x%04x\n", func->num); | 525 | brcmf_dbg(INFO, "Function#: 0x%04x\n", func->num); |
521 | 526 | ||
522 | if (func->num == 2) { | 527 | if (func->num == 2) { |
523 | bus_if = dev_get_drvdata(&func->card->dev); | 528 | bus_if = dev_get_drvdata(&func->dev); |
524 | sdiodev = bus_if->bus_priv; | 529 | sdiodev = bus_if->bus_priv; |
525 | brcmf_dbg(TRACE, "F2 found, calling brcmf_sdio_remove...\n"); | 530 | brcmf_dbg(TRACE, "F2 found, calling brcmf_sdio_remove...\n"); |
526 | brcmf_sdio_remove(sdiodev); | 531 | brcmf_sdio_remove(sdiodev); |
527 | dev_set_drvdata(&func->card->dev, NULL); | 532 | dev_set_drvdata(&func->card->dev, NULL); |
533 | dev_set_drvdata(&func->dev, NULL); | ||
528 | kfree(bus_if); | 534 | kfree(bus_if); |
529 | kfree(sdiodev); | 535 | kfree(sdiodev); |
530 | } | 536 | } |
@@ -534,15 +540,12 @@ static void brcmf_ops_sdio_remove(struct sdio_func *func) | |||
534 | static int brcmf_sdio_suspend(struct device *dev) | 540 | static int brcmf_sdio_suspend(struct device *dev) |
535 | { | 541 | { |
536 | mmc_pm_flag_t sdio_flags; | 542 | mmc_pm_flag_t sdio_flags; |
537 | struct brcmf_sdio_dev *sdiodev; | ||
538 | struct sdio_func *func = dev_to_sdio_func(dev); | 543 | struct sdio_func *func = dev_to_sdio_func(dev); |
539 | struct brcmf_bus *bus_if = dev_get_drvdata(&func->card->dev); | 544 | struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev); |
540 | int ret = 0; | 545 | int ret = 0; |
541 | 546 | ||
542 | brcmf_dbg(TRACE, "\n"); | 547 | brcmf_dbg(TRACE, "\n"); |
543 | 548 | ||
544 | sdiodev = bus_if->bus_priv; | ||
545 | |||
546 | atomic_set(&sdiodev->suspend, true); | 549 | atomic_set(&sdiodev->suspend, true); |
547 | 550 | ||
548 | sdio_flags = sdio_get_host_pm_caps(sdiodev->func[1]); | 551 | sdio_flags = sdio_get_host_pm_caps(sdiodev->func[1]); |
@@ -564,11 +567,9 @@ static int brcmf_sdio_suspend(struct device *dev) | |||
564 | 567 | ||
565 | static int brcmf_sdio_resume(struct device *dev) | 568 | static int brcmf_sdio_resume(struct device *dev) |
566 | { | 569 | { |
567 | struct brcmf_sdio_dev *sdiodev; | ||
568 | struct sdio_func *func = dev_to_sdio_func(dev); | 570 | struct sdio_func *func = dev_to_sdio_func(dev); |
569 | struct brcmf_bus *bus_if = dev_get_drvdata(&func->card->dev); | 571 | struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev); |
570 | 572 | ||
571 | sdiodev = bus_if->bus_priv; | ||
572 | brcmf_sdio_wdtmr_enable(sdiodev, true); | 573 | brcmf_sdio_wdtmr_enable(sdiodev, true); |
573 | atomic_set(&sdiodev->suspend, false); | 574 | atomic_set(&sdiodev->suspend, false); |
574 | return 0; | 575 | return 0; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h index b68d1363105c..ed60f4d69627 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h | |||
@@ -87,7 +87,7 @@ | |||
87 | #define TOE_TX_CSUM_OL 0x00000001 | 87 | #define TOE_TX_CSUM_OL 0x00000001 |
88 | #define TOE_RX_CSUM_OL 0x00000002 | 88 | #define TOE_RX_CSUM_OL 0x00000002 |
89 | 89 | ||
90 | #define BRCMF_BSS_INFO_VERSION 108 /* curr ver of brcmf_bss_info_le struct */ | 90 | #define BRCMF_BSS_INFO_VERSION 109 /* curr ver of brcmf_bss_info_le struct */ |
91 | 91 | ||
92 | /* size of brcmf_scan_params not including variable length array */ | 92 | /* size of brcmf_scan_params not including variable length array */ |
93 | #define BRCMF_SCAN_PARAMS_FIXED_SIZE 64 | 93 | #define BRCMF_SCAN_PARAMS_FIXED_SIZE 64 |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c index a527d5d4cc4e..ebd53aa7202b 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c | |||
@@ -58,7 +58,7 @@ struct brcmf_proto_cdc_dcmd { | |||
58 | * Used on data packets to convey priority across USB. | 58 | * Used on data packets to convey priority across USB. |
59 | */ | 59 | */ |
60 | #define BDC_HEADER_LEN 4 | 60 | #define BDC_HEADER_LEN 4 |
61 | #define BDC_PROTO_VER 1 /* Protocol version */ | 61 | #define BDC_PROTO_VER 2 /* Protocol version */ |
62 | #define BDC_FLAG_VER_MASK 0xf0 /* Protocol version mask */ | 62 | #define BDC_FLAG_VER_MASK 0xf0 /* Protocol version mask */ |
63 | #define BDC_FLAG_VER_SHIFT 4 /* Protocol version shift */ | 63 | #define BDC_FLAG_VER_SHIFT 4 /* Protocol version shift */ |
64 | #define BDC_FLAG_SUM_GOOD 0x04 /* Good RX checksums */ | 64 | #define BDC_FLAG_SUM_GOOD 0x04 /* Good RX checksums */ |
@@ -77,7 +77,7 @@ struct brcmf_proto_bdc_header { | |||
77 | u8 flags; | 77 | u8 flags; |
78 | u8 priority; /* 802.1d Priority, 4:7 flow control info for usb */ | 78 | u8 priority; /* 802.1d Priority, 4:7 flow control info for usb */ |
79 | u8 flags2; | 79 | u8 flags2; |
80 | u8 rssi; | 80 | u8 data_offset; |
81 | }; | 81 | }; |
82 | 82 | ||
83 | 83 | ||
@@ -372,7 +372,7 @@ void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx, | |||
372 | 372 | ||
373 | h->priority = (pktbuf->priority & BDC_PRIORITY_MASK); | 373 | h->priority = (pktbuf->priority & BDC_PRIORITY_MASK); |
374 | h->flags2 = 0; | 374 | h->flags2 = 0; |
375 | h->rssi = 0; | 375 | h->data_offset = 0; |
376 | BDC_SET_IF_IDX(h, ifidx); | 376 | BDC_SET_IF_IDX(h, ifidx); |
377 | } | 377 | } |
378 | 378 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index 18597fe5dfd6..43ba0dd48354 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | |||
@@ -3636,6 +3636,8 @@ static bool brcmf_sdbrcm_chipmatch(u16 chipid) | |||
3636 | { | 3636 | { |
3637 | if (chipid == BCM4329_CHIP_ID) | 3637 | if (chipid == BCM4329_CHIP_ID) |
3638 | return true; | 3638 | return true; |
3639 | if (chipid == BCM4330_CHIP_ID) | ||
3640 | return true; | ||
3639 | return false; | 3641 | return false; |
3640 | } | 3642 | } |
3641 | 3643 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c index f6b1822031fe..a6048d78d294 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c | |||
@@ -59,37 +59,17 @@ struct sdiod_drive_str { | |||
59 | u8 strength; /* Pad Drive Strength in mA */ | 59 | u8 strength; /* Pad Drive Strength in mA */ |
60 | u8 sel; /* Chip-specific select value */ | 60 | u8 sel; /* Chip-specific select value */ |
61 | }; | 61 | }; |
62 | /* SDIO Drive Strength to sel value table for PMU Rev 1 */ | 62 | /* SDIO Drive Strength to sel value table for PMU Rev 11 (1.8V) */ |
63 | static const struct sdiod_drive_str sdiod_drive_strength_tab1[] = { | 63 | static const struct sdiod_drive_str sdiod_drvstr_tab1_1v8[] = { |
64 | { | 64 | {32, 0x6}, |
65 | 4, 0x2}, { | 65 | {26, 0x7}, |
66 | 2, 0x3}, { | 66 | {22, 0x4}, |
67 | 1, 0x0}, { | 67 | {16, 0x5}, |
68 | 0, 0x0} | 68 | {12, 0x2}, |
69 | }; | 69 | {8, 0x3}, |
70 | /* SDIO Drive Strength to sel value table for PMU Rev 2, 3 */ | 70 | {4, 0x0}, |
71 | static const struct sdiod_drive_str sdiod_drive_strength_tab2[] = { | 71 | {0, 0x1} |
72 | { | 72 | }; |
73 | 12, 0x7}, { | ||
74 | 10, 0x6}, { | ||
75 | 8, 0x5}, { | ||
76 | 6, 0x4}, { | ||
77 | 4, 0x2}, { | ||
78 | 2, 0x1}, { | ||
79 | 0, 0x0} | ||
80 | }; | ||
81 | /* SDIO Drive Strength to sel value table for PMU Rev 8 (1.8V) */ | ||
82 | static const struct sdiod_drive_str sdiod_drive_strength_tab3[] = { | ||
83 | { | ||
84 | 32, 0x7}, { | ||
85 | 26, 0x6}, { | ||
86 | 22, 0x5}, { | ||
87 | 16, 0x4}, { | ||
88 | 12, 0x3}, { | ||
89 | 8, 0x2}, { | ||
90 | 4, 0x1}, { | ||
91 | 0, 0x0} | ||
92 | }; | ||
93 | 73 | ||
94 | u8 | 74 | u8 |
95 | brcmf_sdio_chip_getinfidx(struct chip_info *ci, u16 coreid) | 75 | brcmf_sdio_chip_getinfidx(struct chip_info *ci, u16 coreid) |
@@ -396,6 +376,23 @@ static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev, | |||
396 | ci->c_inf[3].base = BCM4329_CORE_ARM_BASE; | 376 | ci->c_inf[3].base = BCM4329_CORE_ARM_BASE; |
397 | ci->ramsize = BCM4329_RAMSIZE; | 377 | ci->ramsize = BCM4329_RAMSIZE; |
398 | break; | 378 | break; |
379 | case BCM4330_CHIP_ID: | ||
380 | ci->c_inf[0].wrapbase = 0x18100000; | ||
381 | ci->c_inf[0].cib = 0x27004211; | ||
382 | ci->c_inf[1].id = BCMA_CORE_SDIO_DEV; | ||
383 | ci->c_inf[1].base = 0x18002000; | ||
384 | ci->c_inf[1].wrapbase = 0x18102000; | ||
385 | ci->c_inf[1].cib = 0x07004211; | ||
386 | ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM; | ||
387 | ci->c_inf[2].base = 0x18004000; | ||
388 | ci->c_inf[2].wrapbase = 0x18104000; | ||
389 | ci->c_inf[2].cib = 0x0d080401; | ||
390 | ci->c_inf[3].id = BCMA_CORE_ARM_CM3; | ||
391 | ci->c_inf[3].base = 0x18003000; | ||
392 | ci->c_inf[3].wrapbase = 0x18103000; | ||
393 | ci->c_inf[3].cib = 0x03004211; | ||
394 | ci->ramsize = 0x48000; | ||
395 | break; | ||
399 | default: | 396 | default: |
400 | brcmf_dbg(ERROR, "chipid 0x%x is not supported\n", ci->chip); | 397 | brcmf_dbg(ERROR, "chipid 0x%x is not supported\n", ci->chip); |
401 | return -ENODEV; | 398 | return -ENODEV; |
@@ -569,19 +566,8 @@ brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev, | |||
569 | return; | 566 | return; |
570 | 567 | ||
571 | switch (SDIOD_DRVSTR_KEY(ci->chip, ci->pmurev)) { | 568 | switch (SDIOD_DRVSTR_KEY(ci->chip, ci->pmurev)) { |
572 | case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 1): | 569 | case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID, 12): |
573 | str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab1; | 570 | str_tab = (struct sdiod_drive_str *)&sdiod_drvstr_tab1_1v8; |
574 | str_mask = 0x30000000; | ||
575 | str_shift = 28; | ||
576 | break; | ||
577 | case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 2): | ||
578 | case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 3): | ||
579 | str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab2; | ||
580 | str_mask = 0x00003800; | ||
581 | str_shift = 11; | ||
582 | break; | ||
583 | case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 8): | ||
584 | str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab3; | ||
585 | str_mask = 0x00003800; | 571 | str_mask = 0x00003800; |
586 | str_shift = 11; | 572 | str_shift = 11; |
587 | break; | 573 | break; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h index c4c2543438ec..d36a2a855a65 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h | |||
@@ -135,6 +135,7 @@ struct brcmf_sdio_dev { | |||
135 | wait_queue_head_t request_chain_wait; | 135 | wait_queue_head_t request_chain_wait; |
136 | wait_queue_head_t request_buffer_wait; | 136 | wait_queue_head_t request_buffer_wait; |
137 | struct device *dev; | 137 | struct device *dev; |
138 | struct brcmf_bus *bus_if; | ||
138 | }; | 139 | }; |
139 | 140 | ||
140 | /* Register/deregister device interrupt handler. */ | 141 | /* Register/deregister device interrupt handler. */ |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c index 39e305443d7e..ab9bb11abfbb 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c | |||
@@ -318,37 +318,13 @@ | |||
318 | 318 | ||
319 | #define BADIDX (SI_MAXCORES + 1) | 319 | #define BADIDX (SI_MAXCORES + 1) |
320 | 320 | ||
321 | /* Newer chips can access PCI/PCIE and CC core without requiring to change | ||
322 | * PCI BAR0 WIN | ||
323 | */ | ||
324 | #define SI_FAST(si) (((si)->pub.buscoretype == PCIE_CORE_ID) || \ | ||
325 | (((si)->pub.buscoretype == PCI_CORE_ID) && \ | ||
326 | (si)->pub.buscorerev >= 13)) | ||
327 | |||
328 | #define CCREGS_FAST(si) (((char __iomem *)((si)->curmap) + \ | ||
329 | PCI_16KB0_CCREGS_OFFSET)) | ||
330 | |||
331 | #define IS_SIM(chippkg) \ | 321 | #define IS_SIM(chippkg) \ |
332 | ((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID)) | 322 | ((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID)) |
333 | 323 | ||
334 | /* | 324 | #define PCI(sih) (ai_get_buscoretype(sih) == PCI_CORE_ID) |
335 | * Macros to disable/restore function core(D11, ENET, ILINE20, etc) interrupts | 325 | #define PCIE(sih) (ai_get_buscoretype(sih) == PCIE_CORE_ID) |
336 | * before after core switching to avoid invalid register accesss inside ISR. | ||
337 | */ | ||
338 | #define INTR_OFF(si, intr_val) \ | ||
339 | if ((si)->intrsoff_fn && \ | ||
340 | (si)->coreid[(si)->curidx] == (si)->dev_coreid) \ | ||
341 | intr_val = (*(si)->intrsoff_fn)((si)->intr_arg) | ||
342 | |||
343 | #define INTR_RESTORE(si, intr_val) \ | ||
344 | if ((si)->intrsrestore_fn && \ | ||
345 | (si)->coreid[(si)->curidx] == (si)->dev_coreid) \ | ||
346 | (*(si)->intrsrestore_fn)((si)->intr_arg, intr_val) | ||
347 | 326 | ||
348 | #define PCI(si) ((si)->pub.buscoretype == PCI_CORE_ID) | 327 | #define PCI_FORCEHT(sih) (PCIE(sih) && (ai_get_chip_id(sih) == BCM4716_CHIP_ID)) |
349 | #define PCIE(si) ((si)->pub.buscoretype == PCIE_CORE_ID) | ||
350 | |||
351 | #define PCI_FORCEHT(si) (PCIE(si) && (si->pub.chip == BCM4716_CHIP_ID)) | ||
352 | 328 | ||
353 | #ifdef BCMDBG | 329 | #ifdef BCMDBG |
354 | #define SI_MSG(fmt, ...) pr_debug(fmt, ##__VA_ARGS__) | 330 | #define SI_MSG(fmt, ...) pr_debug(fmt, ##__VA_ARGS__) |
@@ -360,9 +336,6 @@ | |||
360 | (((x) >= (b)) && ((x) < ((b) + SI_MAXCORES * SI_CORE_SIZE)) && \ | 336 | (((x) >= (b)) && ((x) < ((b) + SI_MAXCORES * SI_CORE_SIZE)) && \ |
361 | IS_ALIGNED((x), SI_CORE_SIZE)) | 337 | IS_ALIGNED((x), SI_CORE_SIZE)) |
362 | 338 | ||
363 | #define PCIEREGS(si) ((__iomem char *)((si)->curmap) + \ | ||
364 | PCI_16KB0_PCIREGS_OFFSET) | ||
365 | |||
366 | struct aidmp { | 339 | struct aidmp { |
367 | u32 oobselina30; /* 0x000 */ | 340 | u32 oobselina30; /* 0x000 */ |
368 | u32 oobselina74; /* 0x004 */ | 341 | u32 oobselina74; /* 0x004 */ |
@@ -481,406 +454,13 @@ struct aidmp { | |||
481 | u32 componentid3; /* 0xffc */ | 454 | u32 componentid3; /* 0xffc */ |
482 | }; | 455 | }; |
483 | 456 | ||
484 | /* EROM parsing */ | ||
485 | |||
486 | static u32 | ||
487 | get_erom_ent(struct si_pub *sih, u32 __iomem **eromptr, u32 mask, u32 match) | ||
488 | { | ||
489 | u32 ent; | ||
490 | uint inv = 0, nom = 0; | ||
491 | |||
492 | while (true) { | ||
493 | ent = R_REG(*eromptr); | ||
494 | (*eromptr)++; | ||
495 | |||
496 | if (mask == 0) | ||
497 | break; | ||
498 | |||
499 | if ((ent & ER_VALID) == 0) { | ||
500 | inv++; | ||
501 | continue; | ||
502 | } | ||
503 | |||
504 | if (ent == (ER_END | ER_VALID)) | ||
505 | break; | ||
506 | |||
507 | if ((ent & mask) == match) | ||
508 | break; | ||
509 | |||
510 | nom++; | ||
511 | } | ||
512 | |||
513 | return ent; | ||
514 | } | ||
515 | |||
516 | static u32 | ||
517 | get_asd(struct si_pub *sih, u32 __iomem **eromptr, uint sp, uint ad, uint st, | ||
518 | u32 *addrl, u32 *addrh, u32 *sizel, u32 *sizeh) | ||
519 | { | ||
520 | u32 asd, sz, szd; | ||
521 | |||
522 | asd = get_erom_ent(sih, eromptr, ER_VALID, ER_VALID); | ||
523 | if (((asd & ER_TAG1) != ER_ADD) || | ||
524 | (((asd & AD_SP_MASK) >> AD_SP_SHIFT) != sp) || | ||
525 | ((asd & AD_ST_MASK) != st)) { | ||
526 | /* This is not what we want, "push" it back */ | ||
527 | (*eromptr)--; | ||
528 | return 0; | ||
529 | } | ||
530 | *addrl = asd & AD_ADDR_MASK; | ||
531 | if (asd & AD_AG32) | ||
532 | *addrh = get_erom_ent(sih, eromptr, 0, 0); | ||
533 | else | ||
534 | *addrh = 0; | ||
535 | *sizeh = 0; | ||
536 | sz = asd & AD_SZ_MASK; | ||
537 | if (sz == AD_SZ_SZD) { | ||
538 | szd = get_erom_ent(sih, eromptr, 0, 0); | ||
539 | *sizel = szd & SD_SZ_MASK; | ||
540 | if (szd & SD_SG32) | ||
541 | *sizeh = get_erom_ent(sih, eromptr, 0, 0); | ||
542 | } else | ||
543 | *sizel = AD_SZ_BASE << (sz >> AD_SZ_SHIFT); | ||
544 | |||
545 | return asd; | ||
546 | } | ||
547 | |||
548 | static void ai_hwfixup(struct si_info *sii) | ||
549 | { | ||
550 | } | ||
551 | |||
552 | /* parse the enumeration rom to identify all cores */ | ||
553 | static void ai_scan(struct si_pub *sih, struct chipcregs __iomem *cc) | ||
554 | { | ||
555 | struct si_info *sii = (struct si_info *)sih; | ||
556 | |||
557 | u32 erombase; | ||
558 | u32 __iomem *eromptr, *eromlim; | ||
559 | void __iomem *regs = cc; | ||
560 | |||
561 | erombase = R_REG(&cc->eromptr); | ||
562 | |||
563 | /* Set wrappers address */ | ||
564 | sii->curwrap = (void *)((unsigned long)cc + SI_CORE_SIZE); | ||
565 | |||
566 | /* Now point the window at the erom */ | ||
567 | pci_write_config_dword(sii->pbus, PCI_BAR0_WIN, erombase); | ||
568 | eromptr = regs; | ||
569 | eromlim = eromptr + (ER_REMAPCONTROL / sizeof(u32)); | ||
570 | |||
571 | while (eromptr < eromlim) { | ||
572 | u32 cia, cib, cid, mfg, crev, nmw, nsw, nmp, nsp; | ||
573 | u32 mpd, asd, addrl, addrh, sizel, sizeh; | ||
574 | u32 __iomem *base; | ||
575 | uint i, j, idx; | ||
576 | bool br; | ||
577 | |||
578 | br = false; | ||
579 | |||
580 | /* Grok a component */ | ||
581 | cia = get_erom_ent(sih, &eromptr, ER_TAG, ER_CI); | ||
582 | if (cia == (ER_END | ER_VALID)) { | ||
583 | /* Found END of erom */ | ||
584 | ai_hwfixup(sii); | ||
585 | return; | ||
586 | } | ||
587 | base = eromptr - 1; | ||
588 | cib = get_erom_ent(sih, &eromptr, 0, 0); | ||
589 | |||
590 | if ((cib & ER_TAG) != ER_CI) { | ||
591 | /* CIA not followed by CIB */ | ||
592 | goto error; | ||
593 | } | ||
594 | |||
595 | cid = (cia & CIA_CID_MASK) >> CIA_CID_SHIFT; | ||
596 | mfg = (cia & CIA_MFG_MASK) >> CIA_MFG_SHIFT; | ||
597 | crev = (cib & CIB_REV_MASK) >> CIB_REV_SHIFT; | ||
598 | nmw = (cib & CIB_NMW_MASK) >> CIB_NMW_SHIFT; | ||
599 | nsw = (cib & CIB_NSW_MASK) >> CIB_NSW_SHIFT; | ||
600 | nmp = (cib & CIB_NMP_MASK) >> CIB_NMP_SHIFT; | ||
601 | nsp = (cib & CIB_NSP_MASK) >> CIB_NSP_SHIFT; | ||
602 | |||
603 | if (((mfg == MFGID_ARM) && (cid == DEF_AI_COMP)) || (nsp == 0)) | ||
604 | continue; | ||
605 | if ((nmw + nsw == 0)) { | ||
606 | /* A component which is not a core */ | ||
607 | if (cid == OOB_ROUTER_CORE_ID) { | ||
608 | asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE, | ||
609 | &addrl, &addrh, &sizel, &sizeh); | ||
610 | if (asd != 0) | ||
611 | sii->oob_router = addrl; | ||
612 | } | ||
613 | continue; | ||
614 | } | ||
615 | |||
616 | idx = sii->numcores; | ||
617 | /* sii->eromptr[idx] = base; */ | ||
618 | sii->cia[idx] = cia; | ||
619 | sii->cib[idx] = cib; | ||
620 | sii->coreid[idx] = cid; | ||
621 | |||
622 | for (i = 0; i < nmp; i++) { | ||
623 | mpd = get_erom_ent(sih, &eromptr, ER_VALID, ER_VALID); | ||
624 | if ((mpd & ER_TAG) != ER_MP) { | ||
625 | /* Not enough MP entries for component */ | ||
626 | goto error; | ||
627 | } | ||
628 | } | ||
629 | |||
630 | /* First Slave Address Descriptor should be port 0: | ||
631 | * the main register space for the core | ||
632 | */ | ||
633 | asd = | ||
634 | get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE, &addrl, &addrh, | ||
635 | &sizel, &sizeh); | ||
636 | if (asd == 0) { | ||
637 | /* Try again to see if it is a bridge */ | ||
638 | asd = | ||
639 | get_asd(sih, &eromptr, 0, 0, AD_ST_BRIDGE, &addrl, | ||
640 | &addrh, &sizel, &sizeh); | ||
641 | if (asd != 0) | ||
642 | br = true; | ||
643 | else if ((addrh != 0) || (sizeh != 0) | ||
644 | || (sizel != SI_CORE_SIZE)) { | ||
645 | /* First Slave ASD for core malformed */ | ||
646 | goto error; | ||
647 | } | ||
648 | } | ||
649 | sii->coresba[idx] = addrl; | ||
650 | sii->coresba_size[idx] = sizel; | ||
651 | /* Get any more ASDs in port 0 */ | ||
652 | j = 1; | ||
653 | do { | ||
654 | asd = | ||
655 | get_asd(sih, &eromptr, 0, j, AD_ST_SLAVE, &addrl, | ||
656 | &addrh, &sizel, &sizeh); | ||
657 | if ((asd != 0) && (j == 1) && (sizel == SI_CORE_SIZE)) { | ||
658 | sii->coresba2[idx] = addrl; | ||
659 | sii->coresba2_size[idx] = sizel; | ||
660 | } | ||
661 | j++; | ||
662 | } while (asd != 0); | ||
663 | |||
664 | /* Go through the ASDs for other slave ports */ | ||
665 | for (i = 1; i < nsp; i++) { | ||
666 | j = 0; | ||
667 | do { | ||
668 | asd = | ||
669 | get_asd(sih, &eromptr, i, j++, AD_ST_SLAVE, | ||
670 | &addrl, &addrh, &sizel, &sizeh); | ||
671 | } while (asd != 0); | ||
672 | if (j == 0) { | ||
673 | /* SP has no address descriptors */ | ||
674 | goto error; | ||
675 | } | ||
676 | } | ||
677 | |||
678 | /* Now get master wrappers */ | ||
679 | for (i = 0; i < nmw; i++) { | ||
680 | asd = | ||
681 | get_asd(sih, &eromptr, i, 0, AD_ST_MWRAP, &addrl, | ||
682 | &addrh, &sizel, &sizeh); | ||
683 | if (asd == 0) { | ||
684 | /* Missing descriptor for MW */ | ||
685 | goto error; | ||
686 | } | ||
687 | if ((sizeh != 0) || (sizel != SI_CORE_SIZE)) { | ||
688 | /* Master wrapper %d is not 4KB */ | ||
689 | goto error; | ||
690 | } | ||
691 | if (i == 0) | ||
692 | sii->wrapba[idx] = addrl; | ||
693 | } | ||
694 | |||
695 | /* And finally slave wrappers */ | ||
696 | for (i = 0; i < nsw; i++) { | ||
697 | uint fwp = (nsp == 1) ? 0 : 1; | ||
698 | asd = | ||
699 | get_asd(sih, &eromptr, fwp + i, 0, AD_ST_SWRAP, | ||
700 | &addrl, &addrh, &sizel, &sizeh); | ||
701 | if (asd == 0) { | ||
702 | /* Missing descriptor for SW */ | ||
703 | goto error; | ||
704 | } | ||
705 | if ((sizeh != 0) || (sizel != SI_CORE_SIZE)) { | ||
706 | /* Slave wrapper is not 4KB */ | ||
707 | goto error; | ||
708 | } | ||
709 | if ((nmw == 0) && (i == 0)) | ||
710 | sii->wrapba[idx] = addrl; | ||
711 | } | ||
712 | |||
713 | /* Don't record bridges */ | ||
714 | if (br) | ||
715 | continue; | ||
716 | |||
717 | /* Done with core */ | ||
718 | sii->numcores++; | ||
719 | } | ||
720 | |||
721 | error: | ||
722 | /* Reached end of erom without finding END */ | ||
723 | sii->numcores = 0; | ||
724 | return; | ||
725 | } | ||
726 | |||
727 | /* | ||
728 | * This function changes the logical "focus" to the indicated core. | ||
729 | * Return the current core's virtual address. Since each core starts with the | ||
730 | * same set of registers (BIST, clock control, etc), the returned address | ||
731 | * contains the first register of this 'common' register block (not to be | ||
732 | * confused with 'common core'). | ||
733 | */ | ||
734 | void __iomem *ai_setcoreidx(struct si_pub *sih, uint coreidx) | ||
735 | { | ||
736 | struct si_info *sii = (struct si_info *)sih; | ||
737 | u32 addr = sii->coresba[coreidx]; | ||
738 | u32 wrap = sii->wrapba[coreidx]; | ||
739 | |||
740 | if (coreidx >= sii->numcores) | ||
741 | return NULL; | ||
742 | |||
743 | /* point bar0 window */ | ||
744 | pci_write_config_dword(sii->pbus, PCI_BAR0_WIN, addr); | ||
745 | /* point bar0 2nd 4KB window */ | ||
746 | pci_write_config_dword(sii->pbus, PCI_BAR0_WIN2, wrap); | ||
747 | sii->curidx = coreidx; | ||
748 | |||
749 | return sii->curmap; | ||
750 | } | ||
751 | |||
752 | /* Return the number of address spaces in current core */ | ||
753 | int ai_numaddrspaces(struct si_pub *sih) | ||
754 | { | ||
755 | return 2; | ||
756 | } | ||
757 | |||
758 | /* Return the address of the nth address space in the current core */ | ||
759 | u32 ai_addrspace(struct si_pub *sih, uint asidx) | ||
760 | { | ||
761 | struct si_info *sii; | ||
762 | uint cidx; | ||
763 | |||
764 | sii = (struct si_info *)sih; | ||
765 | cidx = sii->curidx; | ||
766 | |||
767 | if (asidx == 0) | ||
768 | return sii->coresba[cidx]; | ||
769 | else if (asidx == 1) | ||
770 | return sii->coresba2[cidx]; | ||
771 | else { | ||
772 | /* Need to parse the erom again to find addr space */ | ||
773 | return 0; | ||
774 | } | ||
775 | } | ||
776 | |||
777 | /* Return the size of the nth address space in the current core */ | ||
778 | u32 ai_addrspacesize(struct si_pub *sih, uint asidx) | ||
779 | { | ||
780 | struct si_info *sii; | ||
781 | uint cidx; | ||
782 | |||
783 | sii = (struct si_info *)sih; | ||
784 | cidx = sii->curidx; | ||
785 | |||
786 | if (asidx == 0) | ||
787 | return sii->coresba_size[cidx]; | ||
788 | else if (asidx == 1) | ||
789 | return sii->coresba2_size[cidx]; | ||
790 | else { | ||
791 | /* Need to parse the erom again to find addr */ | ||
792 | return 0; | ||
793 | } | ||
794 | } | ||
795 | |||
796 | uint ai_flag(struct si_pub *sih) | ||
797 | { | ||
798 | struct si_info *sii; | ||
799 | struct aidmp *ai; | ||
800 | |||
801 | sii = (struct si_info *)sih; | ||
802 | ai = sii->curwrap; | ||
803 | |||
804 | return R_REG(&ai->oobselouta30) & 0x1f; | ||
805 | } | ||
806 | |||
807 | void ai_setint(struct si_pub *sih, int siflag) | ||
808 | { | ||
809 | } | ||
810 | |||
811 | uint ai_corevendor(struct si_pub *sih) | ||
812 | { | ||
813 | struct si_info *sii; | ||
814 | u32 cia; | ||
815 | |||
816 | sii = (struct si_info *)sih; | ||
817 | cia = sii->cia[sii->curidx]; | ||
818 | return (cia & CIA_MFG_MASK) >> CIA_MFG_SHIFT; | ||
819 | } | ||
820 | |||
821 | uint ai_corerev(struct si_pub *sih) | ||
822 | { | ||
823 | struct si_info *sii; | ||
824 | u32 cib; | ||
825 | |||
826 | sii = (struct si_info *)sih; | ||
827 | cib = sii->cib[sii->curidx]; | ||
828 | return (cib & CIB_REV_MASK) >> CIB_REV_SHIFT; | ||
829 | } | ||
830 | |||
831 | bool ai_iscoreup(struct si_pub *sih) | ||
832 | { | ||
833 | struct si_info *sii; | ||
834 | struct aidmp *ai; | ||
835 | |||
836 | sii = (struct si_info *)sih; | ||
837 | ai = sii->curwrap; | ||
838 | |||
839 | return (((R_REG(&ai->ioctrl) & (SICF_FGC | SICF_CLOCK_EN)) == | ||
840 | SICF_CLOCK_EN) | ||
841 | && ((R_REG(&ai->resetctrl) & AIRC_RESET) == 0)); | ||
842 | } | ||
843 | |||
844 | void ai_core_cflags_wo(struct si_pub *sih, u32 mask, u32 val) | ||
845 | { | ||
846 | struct si_info *sii; | ||
847 | struct aidmp *ai; | ||
848 | u32 w; | ||
849 | |||
850 | sii = (struct si_info *)sih; | ||
851 | |||
852 | ai = sii->curwrap; | ||
853 | |||
854 | if (mask || val) { | ||
855 | w = ((R_REG(&ai->ioctrl) & ~mask) | val); | ||
856 | W_REG(&ai->ioctrl, w); | ||
857 | } | ||
858 | } | ||
859 | |||
860 | u32 ai_core_cflags(struct si_pub *sih, u32 mask, u32 val) | ||
861 | { | ||
862 | struct si_info *sii; | ||
863 | struct aidmp *ai; | ||
864 | u32 w; | ||
865 | |||
866 | sii = (struct si_info *)sih; | ||
867 | ai = sii->curwrap; | ||
868 | |||
869 | if (mask || val) { | ||
870 | w = ((R_REG(&ai->ioctrl) & ~mask) | val); | ||
871 | W_REG(&ai->ioctrl, w); | ||
872 | } | ||
873 | |||
874 | return R_REG(&ai->ioctrl); | ||
875 | } | ||
876 | |||
877 | /* return true if PCIE capability exists in the pci config space */ | 457 | /* return true if PCIE capability exists in the pci config space */ |
878 | static bool ai_ispcie(struct si_info *sii) | 458 | static bool ai_ispcie(struct si_info *sii) |
879 | { | 459 | { |
880 | u8 cap_ptr; | 460 | u8 cap_ptr; |
881 | 461 | ||
882 | cap_ptr = | 462 | cap_ptr = |
883 | pcicore_find_pci_capability(sii->pbus, PCI_CAP_ID_EXP, NULL, | 463 | pcicore_find_pci_capability(sii->pcibus, PCI_CAP_ID_EXP, NULL, |
884 | NULL); | 464 | NULL); |
885 | if (!cap_ptr) | 465 | if (!cap_ptr) |
886 | return false; | 466 | return false; |
@@ -896,117 +476,69 @@ static bool ai_buscore_prep(struct si_info *sii) | |||
896 | return true; | 476 | return true; |
897 | } | 477 | } |
898 | 478 | ||
899 | u32 ai_core_sflags(struct si_pub *sih, u32 mask, u32 val) | ||
900 | { | ||
901 | struct si_info *sii; | ||
902 | struct aidmp *ai; | ||
903 | u32 w; | ||
904 | |||
905 | sii = (struct si_info *)sih; | ||
906 | ai = sii->curwrap; | ||
907 | |||
908 | if (mask || val) { | ||
909 | w = ((R_REG(&ai->iostatus) & ~mask) | val); | ||
910 | W_REG(&ai->iostatus, w); | ||
911 | } | ||
912 | |||
913 | return R_REG(&ai->iostatus); | ||
914 | } | ||
915 | |||
916 | static bool | 479 | static bool |
917 | ai_buscore_setup(struct si_info *sii, u32 savewin, uint *origidx) | 480 | ai_buscore_setup(struct si_info *sii, struct bcma_device *cc) |
918 | { | 481 | { |
919 | bool pci, pcie; | 482 | struct bcma_device *pci = NULL; |
920 | uint i; | 483 | struct bcma_device *pcie = NULL; |
921 | uint pciidx, pcieidx, pcirev, pcierev; | 484 | struct bcma_device *core; |
922 | struct chipcregs __iomem *cc; | ||
923 | 485 | ||
924 | cc = ai_setcoreidx(&sii->pub, SI_CC_IDX); | 486 | |
487 | /* no cores found, bail out */ | ||
488 | if (cc->bus->nr_cores == 0) | ||
489 | return false; | ||
925 | 490 | ||
926 | /* get chipcommon rev */ | 491 | /* get chipcommon rev */ |
927 | sii->pub.ccrev = (int)ai_corerev(&sii->pub); | 492 | sii->pub.ccrev = cc->id.rev; |
928 | 493 | ||
929 | /* get chipcommon chipstatus */ | 494 | /* get chipcommon chipstatus */ |
930 | if (sii->pub.ccrev >= 11) | 495 | if (ai_get_ccrev(&sii->pub) >= 11) |
931 | sii->pub.chipst = R_REG(&cc->chipstatus); | 496 | sii->chipst = bcma_read32(cc, CHIPCREGOFFS(chipstatus)); |
932 | 497 | ||
933 | /* get chipcommon capabilites */ | 498 | /* get chipcommon capabilites */ |
934 | sii->pub.cccaps = R_REG(&cc->capabilities); | 499 | sii->pub.cccaps = bcma_read32(cc, CHIPCREGOFFS(capabilities)); |
935 | /* get chipcommon extended capabilities */ | ||
936 | |||
937 | if (sii->pub.ccrev >= 35) | ||
938 | sii->pub.cccaps_ext = R_REG(&cc->capabilities_ext); | ||
939 | 500 | ||
940 | /* get pmu rev and caps */ | 501 | /* get pmu rev and caps */ |
941 | if (sii->pub.cccaps & CC_CAP_PMU) { | 502 | if (ai_get_cccaps(&sii->pub) & CC_CAP_PMU) { |
942 | sii->pub.pmucaps = R_REG(&cc->pmucapabilities); | 503 | sii->pub.pmucaps = bcma_read32(cc, |
504 | CHIPCREGOFFS(pmucapabilities)); | ||
943 | sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK; | 505 | sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK; |
944 | } | 506 | } |
945 | 507 | ||
946 | /* figure out bus/orignal core idx */ | 508 | /* figure out buscore */ |
947 | sii->pub.buscoretype = NODEV_CORE_ID; | 509 | list_for_each_entry(core, &cc->bus->cores, list) { |
948 | sii->pub.buscorerev = NOREV; | ||
949 | sii->pub.buscoreidx = BADIDX; | ||
950 | |||
951 | pci = pcie = false; | ||
952 | pcirev = pcierev = NOREV; | ||
953 | pciidx = pcieidx = BADIDX; | ||
954 | |||
955 | for (i = 0; i < sii->numcores; i++) { | ||
956 | uint cid, crev; | 510 | uint cid, crev; |
957 | 511 | ||
958 | ai_setcoreidx(&sii->pub, i); | 512 | cid = core->id.id; |
959 | cid = ai_coreid(&sii->pub); | 513 | crev = core->id.rev; |
960 | crev = ai_corerev(&sii->pub); | ||
961 | 514 | ||
962 | if (cid == PCI_CORE_ID) { | 515 | if (cid == PCI_CORE_ID) { |
963 | pciidx = i; | 516 | pci = core; |
964 | pcirev = crev; | ||
965 | pci = true; | ||
966 | } else if (cid == PCIE_CORE_ID) { | 517 | } else if (cid == PCIE_CORE_ID) { |
967 | pcieidx = i; | 518 | pcie = core; |
968 | pcierev = crev; | ||
969 | pcie = true; | ||
970 | } | 519 | } |
971 | |||
972 | /* find the core idx before entering this func. */ | ||
973 | if ((savewin && (savewin == sii->coresba[i])) || | ||
974 | (cc == sii->regs[i])) | ||
975 | *origidx = i; | ||
976 | } | 520 | } |
977 | 521 | ||
978 | if (pci && pcie) { | 522 | if (pci && pcie) { |
979 | if (ai_ispcie(sii)) | 523 | if (ai_ispcie(sii)) |
980 | pci = false; | 524 | pci = NULL; |
981 | else | 525 | else |
982 | pcie = false; | 526 | pcie = NULL; |
983 | } | 527 | } |
984 | if (pci) { | 528 | if (pci) { |
985 | sii->pub.buscoretype = PCI_CORE_ID; | 529 | sii->buscore = pci; |
986 | sii->pub.buscorerev = pcirev; | ||
987 | sii->pub.buscoreidx = pciidx; | ||
988 | } else if (pcie) { | 530 | } else if (pcie) { |
989 | sii->pub.buscoretype = PCIE_CORE_ID; | 531 | sii->buscore = pcie; |
990 | sii->pub.buscorerev = pcierev; | ||
991 | sii->pub.buscoreidx = pcieidx; | ||
992 | } | 532 | } |
993 | 533 | ||
994 | /* fixup necessary chip/core configurations */ | 534 | /* fixup necessary chip/core configurations */ |
995 | if (SI_FAST(sii)) { | 535 | if (!sii->pch) { |
996 | if (!sii->pch) { | 536 | sii->pch = pcicore_init(&sii->pub, sii->icbus->drv_pci.core); |
997 | sii->pch = pcicore_init(&sii->pub, sii->pbus, | 537 | if (sii->pch == NULL) |
998 | (__iomem void *)PCIEREGS(sii)); | 538 | return false; |
999 | if (sii->pch == NULL) | ||
1000 | return false; | ||
1001 | } | ||
1002 | } | 539 | } |
1003 | if (ai_pci_fixcfg(&sii->pub)) { | 540 | if (ai_pci_fixcfg(&sii->pub)) |
1004 | /* si_doattach: si_pci_fixcfg failed */ | ||
1005 | return false; | 541 | return false; |
1006 | } | ||
1007 | |||
1008 | /* return to the original core */ | ||
1009 | ai_setcoreidx(&sii->pub, *origidx); | ||
1010 | 542 | ||
1011 | return true; | 543 | return true; |
1012 | } | 544 | } |
@@ -1019,39 +551,27 @@ static __used void ai_nvram_process(struct si_info *sii) | |||
1019 | uint w = 0; | 551 | uint w = 0; |
1020 | 552 | ||
1021 | /* do a pci config read to get subsystem id and subvendor id */ | 553 | /* do a pci config read to get subsystem id and subvendor id */ |
1022 | pci_read_config_dword(sii->pbus, PCI_SUBSYSTEM_VENDOR_ID, &w); | 554 | pci_read_config_dword(sii->pcibus, PCI_SUBSYSTEM_VENDOR_ID, &w); |
1023 | 555 | ||
1024 | sii->pub.boardvendor = w & 0xffff; | 556 | sii->pub.boardvendor = w & 0xffff; |
1025 | sii->pub.boardtype = (w >> 16) & 0xffff; | 557 | sii->pub.boardtype = (w >> 16) & 0xffff; |
1026 | sii->pub.boardflags = getintvar(&sii->pub, BRCMS_SROM_BOARDFLAGS); | ||
1027 | } | 558 | } |
1028 | 559 | ||
1029 | static struct si_info *ai_doattach(struct si_info *sii, | 560 | static struct si_info *ai_doattach(struct si_info *sii, |
1030 | void __iomem *regs, struct pci_dev *pbus) | 561 | struct bcma_bus *pbus) |
1031 | { | 562 | { |
1032 | struct si_pub *sih = &sii->pub; | 563 | struct si_pub *sih = &sii->pub; |
1033 | u32 w, savewin; | 564 | u32 w, savewin; |
1034 | struct chipcregs __iomem *cc; | 565 | struct bcma_device *cc; |
1035 | uint socitype; | 566 | uint socitype; |
1036 | uint origidx; | ||
1037 | |||
1038 | memset((unsigned char *) sii, 0, sizeof(struct si_info)); | ||
1039 | 567 | ||
1040 | savewin = 0; | 568 | savewin = 0; |
1041 | 569 | ||
1042 | sih->buscoreidx = BADIDX; | 570 | sii->icbus = pbus; |
1043 | 571 | sii->pcibus = pbus->host_pci; | |
1044 | sii->curmap = regs; | ||
1045 | sii->pbus = pbus; | ||
1046 | 572 | ||
1047 | /* find Chipcommon address */ | 573 | /* switch to Chipcommon core */ |
1048 | pci_read_config_dword(sii->pbus, PCI_BAR0_WIN, &savewin); | 574 | cc = pbus->drv_cc.core; |
1049 | if (!GOODCOREADDR(savewin, SI_ENUM_BASE)) | ||
1050 | savewin = SI_ENUM_BASE; | ||
1051 | |||
1052 | pci_write_config_dword(sii->pbus, PCI_BAR0_WIN, | ||
1053 | SI_ENUM_BASE); | ||
1054 | cc = (struct chipcregs __iomem *) regs; | ||
1055 | 575 | ||
1056 | /* bus/core/clk setup for register access */ | 576 | /* bus/core/clk setup for register access */ |
1057 | if (!ai_buscore_prep(sii)) | 577 | if (!ai_buscore_prep(sii)) |
@@ -1064,89 +584,69 @@ static struct si_info *ai_doattach(struct si_info *sii, | |||
1064 | * hosts w/o chipcommon), some way of recognizing them needs to | 584 | * hosts w/o chipcommon), some way of recognizing them needs to |
1065 | * be added here. | 585 | * be added here. |
1066 | */ | 586 | */ |
1067 | w = R_REG(&cc->chipid); | 587 | w = bcma_read32(cc, CHIPCREGOFFS(chipid)); |
1068 | socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT; | 588 | socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT; |
1069 | /* Might as wll fill in chip id rev & pkg */ | 589 | /* Might as wll fill in chip id rev & pkg */ |
1070 | sih->chip = w & CID_ID_MASK; | 590 | sih->chip = w & CID_ID_MASK; |
1071 | sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT; | 591 | sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT; |
1072 | sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT; | 592 | sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT; |
1073 | 593 | ||
1074 | sih->issim = false; | ||
1075 | |||
1076 | /* scan for cores */ | 594 | /* scan for cores */ |
1077 | if (socitype == SOCI_AI) { | 595 | if (socitype != SOCI_AI) |
1078 | SI_MSG("Found chip type AI (0x%08x)\n", w); | ||
1079 | /* pass chipc address instead of original core base */ | ||
1080 | ai_scan(&sii->pub, cc); | ||
1081 | } else { | ||
1082 | /* Found chip of unknown type */ | ||
1083 | return NULL; | ||
1084 | } | ||
1085 | /* no cores found, bail out */ | ||
1086 | if (sii->numcores == 0) | ||
1087 | return NULL; | 596 | return NULL; |
1088 | 597 | ||
1089 | /* bus/core/clk setup */ | 598 | SI_MSG("Found chip type AI (0x%08x)\n", w); |
1090 | origidx = SI_CC_IDX; | 599 | if (!ai_buscore_setup(sii, cc)) |
1091 | if (!ai_buscore_setup(sii, savewin, &origidx)) | ||
1092 | goto exit; | 600 | goto exit; |
1093 | 601 | ||
1094 | /* Init nvram from sprom/otp if they exist */ | 602 | /* Init nvram from sprom/otp if they exist */ |
1095 | if (srom_var_init(&sii->pub, cc)) | 603 | if (srom_var_init(&sii->pub)) |
1096 | goto exit; | 604 | goto exit; |
1097 | 605 | ||
1098 | ai_nvram_process(sii); | 606 | ai_nvram_process(sii); |
1099 | 607 | ||
1100 | /* === NVRAM, clock is ready === */ | 608 | /* === NVRAM, clock is ready === */ |
1101 | cc = (struct chipcregs __iomem *) ai_setcore(sih, CC_CORE_ID, 0); | 609 | bcma_write32(cc, CHIPCREGOFFS(gpiopullup), 0); |
1102 | W_REG(&cc->gpiopullup, 0); | 610 | bcma_write32(cc, CHIPCREGOFFS(gpiopulldown), 0); |
1103 | W_REG(&cc->gpiopulldown, 0); | ||
1104 | ai_setcoreidx(sih, origidx); | ||
1105 | 611 | ||
1106 | /* PMU specific initializations */ | 612 | /* PMU specific initializations */ |
1107 | if (sih->cccaps & CC_CAP_PMU) { | 613 | if (ai_get_cccaps(sih) & CC_CAP_PMU) { |
1108 | u32 xtalfreq; | ||
1109 | si_pmu_init(sih); | 614 | si_pmu_init(sih); |
1110 | si_pmu_chip_init(sih); | 615 | (void)si_pmu_measure_alpclk(sih); |
1111 | |||
1112 | xtalfreq = si_pmu_measure_alpclk(sih); | ||
1113 | si_pmu_pll_init(sih, xtalfreq); | ||
1114 | si_pmu_res_init(sih); | 616 | si_pmu_res_init(sih); |
1115 | si_pmu_swreg_init(sih); | ||
1116 | } | 617 | } |
1117 | 618 | ||
1118 | /* setup the GPIO based LED powersave register */ | 619 | /* setup the GPIO based LED powersave register */ |
1119 | w = getintvar(sih, BRCMS_SROM_LEDDC); | 620 | w = getintvar(sih, BRCMS_SROM_LEDDC); |
1120 | if (w == 0) | 621 | if (w == 0) |
1121 | w = DEFAULT_GPIOTIMERVAL; | 622 | w = DEFAULT_GPIOTIMERVAL; |
1122 | ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, gpiotimerval), | 623 | ai_cc_reg(sih, offsetof(struct chipcregs, gpiotimerval), |
1123 | ~0, w); | 624 | ~0, w); |
1124 | 625 | ||
1125 | if (PCIE(sii)) | 626 | if (PCIE(sih)) |
1126 | pcicore_attach(sii->pch, SI_DOATTACH); | 627 | pcicore_attach(sii->pch, SI_DOATTACH); |
1127 | 628 | ||
1128 | if (sih->chip == BCM43224_CHIP_ID) { | 629 | if (ai_get_chip_id(sih) == BCM43224_CHIP_ID) { |
1129 | /* | 630 | /* |
1130 | * enable 12 mA drive strenth for 43224 and | 631 | * enable 12 mA drive strenth for 43224 and |
1131 | * set chipControl register bit 15 | 632 | * set chipControl register bit 15 |
1132 | */ | 633 | */ |
1133 | if (sih->chiprev == 0) { | 634 | if (ai_get_chiprev(sih) == 0) { |
1134 | SI_MSG("Applying 43224A0 WARs\n"); | 635 | SI_MSG("Applying 43224A0 WARs\n"); |
1135 | ai_corereg(sih, SI_CC_IDX, | 636 | ai_cc_reg(sih, offsetof(struct chipcregs, chipcontrol), |
1136 | offsetof(struct chipcregs, chipcontrol), | 637 | CCTRL43224_GPIO_TOGGLE, |
1137 | CCTRL43224_GPIO_TOGGLE, | 638 | CCTRL43224_GPIO_TOGGLE); |
1138 | CCTRL43224_GPIO_TOGGLE); | ||
1139 | si_pmu_chipcontrol(sih, 0, CCTRL_43224A0_12MA_LED_DRIVE, | 639 | si_pmu_chipcontrol(sih, 0, CCTRL_43224A0_12MA_LED_DRIVE, |
1140 | CCTRL_43224A0_12MA_LED_DRIVE); | 640 | CCTRL_43224A0_12MA_LED_DRIVE); |
1141 | } | 641 | } |
1142 | if (sih->chiprev >= 1) { | 642 | if (ai_get_chiprev(sih) >= 1) { |
1143 | SI_MSG("Applying 43224B0+ WARs\n"); | 643 | SI_MSG("Applying 43224B0+ WARs\n"); |
1144 | si_pmu_chipcontrol(sih, 0, CCTRL_43224B0_12MA_LED_DRIVE, | 644 | si_pmu_chipcontrol(sih, 0, CCTRL_43224B0_12MA_LED_DRIVE, |
1145 | CCTRL_43224B0_12MA_LED_DRIVE); | 645 | CCTRL_43224B0_12MA_LED_DRIVE); |
1146 | } | 646 | } |
1147 | } | 647 | } |
1148 | 648 | ||
1149 | if (sih->chip == BCM4313_CHIP_ID) { | 649 | if (ai_get_chip_id(sih) == BCM4313_CHIP_ID) { |
1150 | /* | 650 | /* |
1151 | * enable 12 mA drive strenth for 4313 and | 651 | * enable 12 mA drive strenth for 4313 and |
1152 | * set chipControl register bit 1 | 652 | * set chipControl register bit 1 |
@@ -1167,22 +667,19 @@ static struct si_info *ai_doattach(struct si_info *sii, | |||
1167 | } | 667 | } |
1168 | 668 | ||
1169 | /* | 669 | /* |
1170 | * Allocate a si handle. | 670 | * Allocate a si handle and do the attach. |
1171 | * devid - pci device id (used to determine chip#) | ||
1172 | * osh - opaque OS handle | ||
1173 | * regs - virtual address of initial core registers | ||
1174 | */ | 671 | */ |
1175 | struct si_pub * | 672 | struct si_pub * |
1176 | ai_attach(void __iomem *regs, struct pci_dev *sdh) | 673 | ai_attach(struct bcma_bus *pbus) |
1177 | { | 674 | { |
1178 | struct si_info *sii; | 675 | struct si_info *sii; |
1179 | 676 | ||
1180 | /* alloc struct si_info */ | 677 | /* alloc struct si_info */ |
1181 | sii = kmalloc(sizeof(struct si_info), GFP_ATOMIC); | 678 | sii = kzalloc(sizeof(struct si_info), GFP_ATOMIC); |
1182 | if (sii == NULL) | 679 | if (sii == NULL) |
1183 | return NULL; | 680 | return NULL; |
1184 | 681 | ||
1185 | if (ai_doattach(sii, regs, sdh) == NULL) { | 682 | if (ai_doattach(sii, pbus) == NULL) { |
1186 | kfree(sii); | 683 | kfree(sii); |
1187 | return NULL; | 684 | return NULL; |
1188 | } | 685 | } |
@@ -1211,292 +708,66 @@ void ai_detach(struct si_pub *sih) | |||
1211 | kfree(sii); | 708 | kfree(sii); |
1212 | } | 709 | } |
1213 | 710 | ||
1214 | /* register driver interrupt disabling and restoring callback functions */ | ||
1215 | void | ||
1216 | ai_register_intr_callback(struct si_pub *sih, void *intrsoff_fn, | ||
1217 | void *intrsrestore_fn, | ||
1218 | void *intrsenabled_fn, void *intr_arg) | ||
1219 | { | ||
1220 | struct si_info *sii; | ||
1221 | |||
1222 | sii = (struct si_info *)sih; | ||
1223 | sii->intr_arg = intr_arg; | ||
1224 | sii->intrsoff_fn = (u32 (*)(void *)) intrsoff_fn; | ||
1225 | sii->intrsrestore_fn = (void (*) (void *, u32)) intrsrestore_fn; | ||
1226 | sii->intrsenabled_fn = (bool (*)(void *)) intrsenabled_fn; | ||
1227 | /* save current core id. when this function called, the current core | ||
1228 | * must be the core which provides driver functions(il, et, wl, etc.) | ||
1229 | */ | ||
1230 | sii->dev_coreid = sii->coreid[sii->curidx]; | ||
1231 | } | ||
1232 | |||
1233 | void ai_deregister_intr_callback(struct si_pub *sih) | ||
1234 | { | ||
1235 | struct si_info *sii; | ||
1236 | |||
1237 | sii = (struct si_info *)sih; | ||
1238 | sii->intrsoff_fn = NULL; | ||
1239 | } | ||
1240 | |||
1241 | uint ai_coreid(struct si_pub *sih) | ||
1242 | { | ||
1243 | struct si_info *sii; | ||
1244 | |||
1245 | sii = (struct si_info *)sih; | ||
1246 | return sii->coreid[sii->curidx]; | ||
1247 | } | ||
1248 | |||
1249 | uint ai_coreidx(struct si_pub *sih) | ||
1250 | { | ||
1251 | struct si_info *sii; | ||
1252 | |||
1253 | sii = (struct si_info *)sih; | ||
1254 | return sii->curidx; | ||
1255 | } | ||
1256 | |||
1257 | bool ai_backplane64(struct si_pub *sih) | ||
1258 | { | ||
1259 | return (sih->cccaps & CC_CAP_BKPLN64) != 0; | ||
1260 | } | ||
1261 | |||
1262 | /* return index of coreid or BADIDX if not found */ | 711 | /* return index of coreid or BADIDX if not found */ |
1263 | uint ai_findcoreidx(struct si_pub *sih, uint coreid, uint coreunit) | 712 | struct bcma_device *ai_findcore(struct si_pub *sih, u16 coreid, u16 coreunit) |
1264 | { | 713 | { |
714 | struct bcma_device *core; | ||
1265 | struct si_info *sii; | 715 | struct si_info *sii; |
1266 | uint found; | 716 | uint found; |
1267 | uint i; | ||
1268 | 717 | ||
1269 | sii = (struct si_info *)sih; | 718 | sii = (struct si_info *)sih; |
1270 | 719 | ||
1271 | found = 0; | 720 | found = 0; |
1272 | 721 | ||
1273 | for (i = 0; i < sii->numcores; i++) | 722 | list_for_each_entry(core, &sii->icbus->cores, list) |
1274 | if (sii->coreid[i] == coreid) { | 723 | if (core->id.id == coreid) { |
1275 | if (found == coreunit) | 724 | if (found == coreunit) |
1276 | return i; | 725 | return core; |
1277 | found++; | 726 | found++; |
1278 | } | 727 | } |
1279 | 728 | ||
1280 | return BADIDX; | 729 | return NULL; |
1281 | } | ||
1282 | |||
1283 | /* | ||
1284 | * This function changes logical "focus" to the indicated core; | ||
1285 | * must be called with interrupts off. | ||
1286 | * Moreover, callers should keep interrupts off during switching | ||
1287 | * out of and back to d11 core. | ||
1288 | */ | ||
1289 | void __iomem *ai_setcore(struct si_pub *sih, uint coreid, uint coreunit) | ||
1290 | { | ||
1291 | uint idx; | ||
1292 | |||
1293 | idx = ai_findcoreidx(sih, coreid, coreunit); | ||
1294 | if (idx >= SI_MAXCORES) | ||
1295 | return NULL; | ||
1296 | |||
1297 | return ai_setcoreidx(sih, idx); | ||
1298 | } | ||
1299 | |||
1300 | /* Turn off interrupt as required by ai_setcore, before switch core */ | ||
1301 | void __iomem *ai_switch_core(struct si_pub *sih, uint coreid, uint *origidx, | ||
1302 | uint *intr_val) | ||
1303 | { | ||
1304 | void __iomem *cc; | ||
1305 | struct si_info *sii; | ||
1306 | |||
1307 | sii = (struct si_info *)sih; | ||
1308 | |||
1309 | if (SI_FAST(sii)) { | ||
1310 | /* Overloading the origidx variable to remember the coreid, | ||
1311 | * this works because the core ids cannot be confused with | ||
1312 | * core indices. | ||
1313 | */ | ||
1314 | *origidx = coreid; | ||
1315 | if (coreid == CC_CORE_ID) | ||
1316 | return CCREGS_FAST(sii); | ||
1317 | else if (coreid == sih->buscoretype) | ||
1318 | return PCIEREGS(sii); | ||
1319 | } | ||
1320 | INTR_OFF(sii, *intr_val); | ||
1321 | *origidx = sii->curidx; | ||
1322 | cc = ai_setcore(sih, coreid, 0); | ||
1323 | return cc; | ||
1324 | } | ||
1325 | |||
1326 | /* restore coreidx and restore interrupt */ | ||
1327 | void ai_restore_core(struct si_pub *sih, uint coreid, uint intr_val) | ||
1328 | { | ||
1329 | struct si_info *sii; | ||
1330 | |||
1331 | sii = (struct si_info *)sih; | ||
1332 | if (SI_FAST(sii) | ||
1333 | && ((coreid == CC_CORE_ID) || (coreid == sih->buscoretype))) | ||
1334 | return; | ||
1335 | |||
1336 | ai_setcoreidx(sih, coreid); | ||
1337 | INTR_RESTORE(sii, intr_val); | ||
1338 | } | ||
1339 | |||
1340 | void ai_write_wrapperreg(struct si_pub *sih, u32 offset, u32 val) | ||
1341 | { | ||
1342 | struct si_info *sii = (struct si_info *)sih; | ||
1343 | u32 *w = (u32 *) sii->curwrap; | ||
1344 | W_REG(w + (offset / 4), val); | ||
1345 | return; | ||
1346 | } | 730 | } |
1347 | 731 | ||
1348 | /* | 732 | /* |
1349 | * Switch to 'coreidx', issue a single arbitrary 32bit register mask&set | 733 | * read/modify chipcommon core register. |
1350 | * operation, switch back to the original core, and return the new value. | ||
1351 | * | ||
1352 | * When using the silicon backplane, no fiddling with interrupts or core | ||
1353 | * switches is needed. | ||
1354 | * | ||
1355 | * Also, when using pci/pcie, we can optimize away the core switching for pci | ||
1356 | * registers and (on newer pci cores) chipcommon registers. | ||
1357 | */ | 734 | */ |
1358 | uint ai_corereg(struct si_pub *sih, uint coreidx, uint regoff, uint mask, | 735 | uint ai_cc_reg(struct si_pub *sih, uint regoff, u32 mask, u32 val) |
1359 | uint val) | ||
1360 | { | 736 | { |
1361 | uint origidx = 0; | 737 | struct bcma_device *cc; |
1362 | u32 __iomem *r = NULL; | 738 | u32 w; |
1363 | uint w; | ||
1364 | uint intr_val = 0; | ||
1365 | bool fast = false; | ||
1366 | struct si_info *sii; | 739 | struct si_info *sii; |
1367 | 740 | ||
1368 | sii = (struct si_info *)sih; | 741 | sii = (struct si_info *)sih; |
1369 | 742 | cc = sii->icbus->drv_cc.core; | |
1370 | if (coreidx >= SI_MAXCORES) | ||
1371 | return 0; | ||
1372 | |||
1373 | /* | ||
1374 | * If pci/pcie, we can get at pci/pcie regs | ||
1375 | * and on newer cores to chipc | ||
1376 | */ | ||
1377 | if ((sii->coreid[coreidx] == CC_CORE_ID) && SI_FAST(sii)) { | ||
1378 | /* Chipc registers are mapped at 12KB */ | ||
1379 | fast = true; | ||
1380 | r = (u32 __iomem *)((__iomem char *)sii->curmap + | ||
1381 | PCI_16KB0_CCREGS_OFFSET + regoff); | ||
1382 | } else if (sii->pub.buscoreidx == coreidx) { | ||
1383 | /* | ||
1384 | * pci registers are at either in the last 2KB of | ||
1385 | * an 8KB window or, in pcie and pci rev 13 at 8KB | ||
1386 | */ | ||
1387 | fast = true; | ||
1388 | if (SI_FAST(sii)) | ||
1389 | r = (u32 __iomem *)((__iomem char *)sii->curmap + | ||
1390 | PCI_16KB0_PCIREGS_OFFSET + regoff); | ||
1391 | else | ||
1392 | r = (u32 __iomem *)((__iomem char *)sii->curmap + | ||
1393 | ((regoff >= SBCONFIGOFF) ? | ||
1394 | PCI_BAR0_PCISBR_OFFSET : | ||
1395 | PCI_BAR0_PCIREGS_OFFSET) + regoff); | ||
1396 | } | ||
1397 | |||
1398 | if (!fast) { | ||
1399 | INTR_OFF(sii, intr_val); | ||
1400 | |||
1401 | /* save current core index */ | ||
1402 | origidx = ai_coreidx(&sii->pub); | ||
1403 | |||
1404 | /* switch core */ | ||
1405 | r = (u32 __iomem *) ((unsigned char __iomem *) | ||
1406 | ai_setcoreidx(&sii->pub, coreidx) + regoff); | ||
1407 | } | ||
1408 | 743 | ||
1409 | /* mask and set */ | 744 | /* mask and set */ |
1410 | if (mask || val) { | 745 | if (mask || val) { |
1411 | w = (R_REG(r) & ~mask) | val; | 746 | bcma_maskset32(cc, regoff, ~mask, val); |
1412 | W_REG(r, w); | ||
1413 | } | 747 | } |
1414 | 748 | ||
1415 | /* readback */ | 749 | /* readback */ |
1416 | w = R_REG(r); | 750 | w = bcma_read32(cc, regoff); |
1417 | |||
1418 | if (!fast) { | ||
1419 | /* restore core index */ | ||
1420 | if (origidx != coreidx) | ||
1421 | ai_setcoreidx(&sii->pub, origidx); | ||
1422 | |||
1423 | INTR_RESTORE(sii, intr_val); | ||
1424 | } | ||
1425 | 751 | ||
1426 | return w; | 752 | return w; |
1427 | } | 753 | } |
1428 | 754 | ||
1429 | void ai_core_disable(struct si_pub *sih, u32 bits) | ||
1430 | { | ||
1431 | struct si_info *sii; | ||
1432 | u32 dummy; | ||
1433 | struct aidmp *ai; | ||
1434 | |||
1435 | sii = (struct si_info *)sih; | ||
1436 | |||
1437 | ai = sii->curwrap; | ||
1438 | |||
1439 | /* if core is already in reset, just return */ | ||
1440 | if (R_REG(&ai->resetctrl) & AIRC_RESET) | ||
1441 | return; | ||
1442 | |||
1443 | W_REG(&ai->ioctrl, bits); | ||
1444 | dummy = R_REG(&ai->ioctrl); | ||
1445 | udelay(10); | ||
1446 | |||
1447 | W_REG(&ai->resetctrl, AIRC_RESET); | ||
1448 | udelay(1); | ||
1449 | } | ||
1450 | |||
1451 | /* reset and re-enable a core | ||
1452 | * inputs: | ||
1453 | * bits - core specific bits that are set during and after reset sequence | ||
1454 | * resetbits - core specific bits that are set only during reset sequence | ||
1455 | */ | ||
1456 | void ai_core_reset(struct si_pub *sih, u32 bits, u32 resetbits) | ||
1457 | { | ||
1458 | struct si_info *sii; | ||
1459 | struct aidmp *ai; | ||
1460 | u32 dummy; | ||
1461 | |||
1462 | sii = (struct si_info *)sih; | ||
1463 | ai = sii->curwrap; | ||
1464 | |||
1465 | /* | ||
1466 | * Must do the disable sequence first to work | ||
1467 | * for arbitrary current core state. | ||
1468 | */ | ||
1469 | ai_core_disable(sih, (bits | resetbits)); | ||
1470 | |||
1471 | /* | ||
1472 | * Now do the initialization sequence. | ||
1473 | */ | ||
1474 | W_REG(&ai->ioctrl, (bits | SICF_FGC | SICF_CLOCK_EN)); | ||
1475 | dummy = R_REG(&ai->ioctrl); | ||
1476 | W_REG(&ai->resetctrl, 0); | ||
1477 | udelay(1); | ||
1478 | |||
1479 | W_REG(&ai->ioctrl, (bits | SICF_CLOCK_EN)); | ||
1480 | dummy = R_REG(&ai->ioctrl); | ||
1481 | udelay(1); | ||
1482 | } | ||
1483 | |||
1484 | /* return the slow clock source - LPO, XTAL, or PCI */ | 755 | /* return the slow clock source - LPO, XTAL, or PCI */ |
1485 | static uint ai_slowclk_src(struct si_info *sii) | 756 | static uint ai_slowclk_src(struct si_pub *sih, struct bcma_device *cc) |
1486 | { | 757 | { |
1487 | struct chipcregs __iomem *cc; | 758 | struct si_info *sii; |
1488 | u32 val; | 759 | u32 val; |
1489 | 760 | ||
1490 | if (sii->pub.ccrev < 6) { | 761 | sii = (struct si_info *)sih; |
1491 | pci_read_config_dword(sii->pbus, PCI_GPIO_OUT, | 762 | if (ai_get_ccrev(&sii->pub) < 6) { |
763 | pci_read_config_dword(sii->pcibus, PCI_GPIO_OUT, | ||
1492 | &val); | 764 | &val); |
1493 | if (val & PCI_CFG_GPIO_SCS) | 765 | if (val & PCI_CFG_GPIO_SCS) |
1494 | return SCC_SS_PCI; | 766 | return SCC_SS_PCI; |
1495 | return SCC_SS_XTAL; | 767 | return SCC_SS_XTAL; |
1496 | } else if (sii->pub.ccrev < 10) { | 768 | } else if (ai_get_ccrev(&sii->pub) < 10) { |
1497 | cc = (struct chipcregs __iomem *) | 769 | return bcma_read32(cc, CHIPCREGOFFS(slow_clk_ctl)) & |
1498 | ai_setcoreidx(&sii->pub, sii->curidx); | 770 | SCC_SS_MASK; |
1499 | return R_REG(&cc->slow_clk_ctl) & SCC_SS_MASK; | ||
1500 | } else /* Insta-clock */ | 771 | } else /* Insta-clock */ |
1501 | return SCC_SS_XTAL; | 772 | return SCC_SS_XTAL; |
1502 | } | 773 | } |
@@ -1505,24 +776,24 @@ static uint ai_slowclk_src(struct si_info *sii) | |||
1505 | * return the ILP (slowclock) min or max frequency | 776 | * return the ILP (slowclock) min or max frequency |
1506 | * precondition: we've established the chip has dynamic clk control | 777 | * precondition: we've established the chip has dynamic clk control |
1507 | */ | 778 | */ |
1508 | static uint ai_slowclk_freq(struct si_info *sii, bool max_freq, | 779 | static uint ai_slowclk_freq(struct si_pub *sih, bool max_freq, |
1509 | struct chipcregs __iomem *cc) | 780 | struct bcma_device *cc) |
1510 | { | 781 | { |
1511 | u32 slowclk; | 782 | u32 slowclk; |
1512 | uint div; | 783 | uint div; |
1513 | 784 | ||
1514 | slowclk = ai_slowclk_src(sii); | 785 | slowclk = ai_slowclk_src(sih, cc); |
1515 | if (sii->pub.ccrev < 6) { | 786 | if (ai_get_ccrev(sih) < 6) { |
1516 | if (slowclk == SCC_SS_PCI) | 787 | if (slowclk == SCC_SS_PCI) |
1517 | return max_freq ? (PCIMAXFREQ / 64) | 788 | return max_freq ? (PCIMAXFREQ / 64) |
1518 | : (PCIMINFREQ / 64); | 789 | : (PCIMINFREQ / 64); |
1519 | else | 790 | else |
1520 | return max_freq ? (XTALMAXFREQ / 32) | 791 | return max_freq ? (XTALMAXFREQ / 32) |
1521 | : (XTALMINFREQ / 32); | 792 | : (XTALMINFREQ / 32); |
1522 | } else if (sii->pub.ccrev < 10) { | 793 | } else if (ai_get_ccrev(sih) < 10) { |
1523 | div = 4 * | 794 | div = 4 * |
1524 | (((R_REG(&cc->slow_clk_ctl) & SCC_CD_MASK) >> | 795 | (((bcma_read32(cc, CHIPCREGOFFS(slow_clk_ctl)) & |
1525 | SCC_CD_SHIFT) + 1); | 796 | SCC_CD_MASK) >> SCC_CD_SHIFT) + 1); |
1526 | if (slowclk == SCC_SS_LPO) | 797 | if (slowclk == SCC_SS_LPO) |
1527 | return max_freq ? LPOMAXFREQ : LPOMINFREQ; | 798 | return max_freq ? LPOMAXFREQ : LPOMINFREQ; |
1528 | else if (slowclk == SCC_SS_XTAL) | 799 | else if (slowclk == SCC_SS_XTAL) |
@@ -1533,15 +804,15 @@ static uint ai_slowclk_freq(struct si_info *sii, bool max_freq, | |||
1533 | : (PCIMINFREQ / div); | 804 | : (PCIMINFREQ / div); |
1534 | } else { | 805 | } else { |
1535 | /* Chipc rev 10 is InstaClock */ | 806 | /* Chipc rev 10 is InstaClock */ |
1536 | div = R_REG(&cc->system_clk_ctl) >> SYCC_CD_SHIFT; | 807 | div = bcma_read32(cc, CHIPCREGOFFS(system_clk_ctl)); |
1537 | div = 4 * (div + 1); | 808 | div = 4 * ((div >> SYCC_CD_SHIFT) + 1); |
1538 | return max_freq ? XTALMAXFREQ : (XTALMINFREQ / div); | 809 | return max_freq ? XTALMAXFREQ : (XTALMINFREQ / div); |
1539 | } | 810 | } |
1540 | return 0; | 811 | return 0; |
1541 | } | 812 | } |
1542 | 813 | ||
1543 | static void | 814 | static void |
1544 | ai_clkctl_setdelay(struct si_info *sii, struct chipcregs __iomem *cc) | 815 | ai_clkctl_setdelay(struct si_pub *sih, struct bcma_device *cc) |
1545 | { | 816 | { |
1546 | uint slowmaxfreq, pll_delay, slowclk; | 817 | uint slowmaxfreq, pll_delay, slowclk; |
1547 | uint pll_on_delay, fref_sel_delay; | 818 | uint pll_on_delay, fref_sel_delay; |
@@ -1554,55 +825,40 @@ ai_clkctl_setdelay(struct si_info *sii, struct chipcregs __iomem *cc) | |||
1554 | * powered down by dynamic clk control logic. | 825 | * powered down by dynamic clk control logic. |
1555 | */ | 826 | */ |
1556 | 827 | ||
1557 | slowclk = ai_slowclk_src(sii); | 828 | slowclk = ai_slowclk_src(sih, cc); |
1558 | if (slowclk != SCC_SS_XTAL) | 829 | if (slowclk != SCC_SS_XTAL) |
1559 | pll_delay += XTAL_ON_DELAY; | 830 | pll_delay += XTAL_ON_DELAY; |
1560 | 831 | ||
1561 | /* Starting with 4318 it is ILP that is used for the delays */ | 832 | /* Starting with 4318 it is ILP that is used for the delays */ |
1562 | slowmaxfreq = | 833 | slowmaxfreq = |
1563 | ai_slowclk_freq(sii, (sii->pub.ccrev >= 10) ? false : true, cc); | 834 | ai_slowclk_freq(sih, |
835 | (ai_get_ccrev(sih) >= 10) ? false : true, cc); | ||
1564 | 836 | ||
1565 | pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000; | 837 | pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000; |
1566 | fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000; | 838 | fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000; |
1567 | 839 | ||
1568 | W_REG(&cc->pll_on_delay, pll_on_delay); | 840 | bcma_write32(cc, CHIPCREGOFFS(pll_on_delay), pll_on_delay); |
1569 | W_REG(&cc->fref_sel_delay, fref_sel_delay); | 841 | bcma_write32(cc, CHIPCREGOFFS(fref_sel_delay), fref_sel_delay); |
1570 | } | 842 | } |
1571 | 843 | ||
1572 | /* initialize power control delay registers */ | 844 | /* initialize power control delay registers */ |
1573 | void ai_clkctl_init(struct si_pub *sih) | 845 | void ai_clkctl_init(struct si_pub *sih) |
1574 | { | 846 | { |
1575 | struct si_info *sii; | 847 | struct bcma_device *cc; |
1576 | uint origidx = 0; | ||
1577 | struct chipcregs __iomem *cc; | ||
1578 | bool fast; | ||
1579 | 848 | ||
1580 | if (!(sih->cccaps & CC_CAP_PWR_CTL)) | 849 | if (!(ai_get_cccaps(sih) & CC_CAP_PWR_CTL)) |
1581 | return; | 850 | return; |
1582 | 851 | ||
1583 | sii = (struct si_info *)sih; | 852 | cc = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0); |
1584 | fast = SI_FAST(sii); | 853 | if (cc == NULL) |
1585 | if (!fast) { | 854 | return; |
1586 | origidx = sii->curidx; | ||
1587 | cc = (struct chipcregs __iomem *) | ||
1588 | ai_setcore(sih, CC_CORE_ID, 0); | ||
1589 | if (cc == NULL) | ||
1590 | return; | ||
1591 | } else { | ||
1592 | cc = (struct chipcregs __iomem *) CCREGS_FAST(sii); | ||
1593 | if (cc == NULL) | ||
1594 | return; | ||
1595 | } | ||
1596 | 855 | ||
1597 | /* set all Instaclk chip ILP to 1 MHz */ | 856 | /* set all Instaclk chip ILP to 1 MHz */ |
1598 | if (sih->ccrev >= 10) | 857 | if (ai_get_ccrev(sih) >= 10) |
1599 | SET_REG(&cc->system_clk_ctl, SYCC_CD_MASK, | 858 | bcma_maskset32(cc, CHIPCREGOFFS(system_clk_ctl), SYCC_CD_MASK, |
1600 | (ILP_DIV_1MHZ << SYCC_CD_SHIFT)); | 859 | (ILP_DIV_1MHZ << SYCC_CD_SHIFT)); |
1601 | 860 | ||
1602 | ai_clkctl_setdelay(sii, cc); | 861 | ai_clkctl_setdelay(sih, cc); |
1603 | |||
1604 | if (!fast) | ||
1605 | ai_setcoreidx(sih, origidx); | ||
1606 | } | 862 | } |
1607 | 863 | ||
1608 | /* | 864 | /* |
@@ -1612,47 +868,25 @@ void ai_clkctl_init(struct si_pub *sih) | |||
1612 | u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih) | 868 | u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih) |
1613 | { | 869 | { |
1614 | struct si_info *sii; | 870 | struct si_info *sii; |
1615 | uint origidx = 0; | 871 | struct bcma_device *cc; |
1616 | struct chipcregs __iomem *cc; | ||
1617 | uint slowminfreq; | 872 | uint slowminfreq; |
1618 | u16 fpdelay; | 873 | u16 fpdelay; |
1619 | uint intr_val = 0; | ||
1620 | bool fast; | ||
1621 | 874 | ||
1622 | sii = (struct si_info *)sih; | 875 | sii = (struct si_info *)sih; |
1623 | if (sih->cccaps & CC_CAP_PMU) { | 876 | if (ai_get_cccaps(sih) & CC_CAP_PMU) { |
1624 | INTR_OFF(sii, intr_val); | ||
1625 | fpdelay = si_pmu_fast_pwrup_delay(sih); | 877 | fpdelay = si_pmu_fast_pwrup_delay(sih); |
1626 | INTR_RESTORE(sii, intr_val); | ||
1627 | return fpdelay; | 878 | return fpdelay; |
1628 | } | 879 | } |
1629 | 880 | ||
1630 | if (!(sih->cccaps & CC_CAP_PWR_CTL)) | 881 | if (!(ai_get_cccaps(sih) & CC_CAP_PWR_CTL)) |
1631 | return 0; | 882 | return 0; |
1632 | 883 | ||
1633 | fast = SI_FAST(sii); | ||
1634 | fpdelay = 0; | 884 | fpdelay = 0; |
1635 | if (!fast) { | 885 | cc = ai_findcore(sih, CC_CORE_ID, 0); |
1636 | origidx = sii->curidx; | 886 | if (cc) { |
1637 | INTR_OFF(sii, intr_val); | 887 | slowminfreq = ai_slowclk_freq(sih, false, cc); |
1638 | cc = (struct chipcregs __iomem *) | 888 | fpdelay = (((bcma_read32(cc, CHIPCREGOFFS(pll_on_delay)) + 2) |
1639 | ai_setcore(sih, CC_CORE_ID, 0); | 889 | * 1000000) + (slowminfreq - 1)) / slowminfreq; |
1640 | if (cc == NULL) | ||
1641 | goto done; | ||
1642 | } else { | ||
1643 | cc = (struct chipcregs __iomem *) CCREGS_FAST(sii); | ||
1644 | if (cc == NULL) | ||
1645 | goto done; | ||
1646 | } | ||
1647 | |||
1648 | slowminfreq = ai_slowclk_freq(sii, false, cc); | ||
1649 | fpdelay = (((R_REG(&cc->pll_on_delay) + 2) * 1000000) + | ||
1650 | (slowminfreq - 1)) / slowminfreq; | ||
1651 | |||
1652 | done: | ||
1653 | if (!fast) { | ||
1654 | ai_setcoreidx(sih, origidx); | ||
1655 | INTR_RESTORE(sii, intr_val); | ||
1656 | } | 890 | } |
1657 | return fpdelay; | 891 | return fpdelay; |
1658 | } | 892 | } |
@@ -1666,12 +900,12 @@ int ai_clkctl_xtal(struct si_pub *sih, uint what, bool on) | |||
1666 | sii = (struct si_info *)sih; | 900 | sii = (struct si_info *)sih; |
1667 | 901 | ||
1668 | /* pcie core doesn't have any mapping to control the xtal pu */ | 902 | /* pcie core doesn't have any mapping to control the xtal pu */ |
1669 | if (PCIE(sii)) | 903 | if (PCIE(sih)) |
1670 | return -1; | 904 | return -1; |
1671 | 905 | ||
1672 | pci_read_config_dword(sii->pbus, PCI_GPIO_IN, &in); | 906 | pci_read_config_dword(sii->pcibus, PCI_GPIO_IN, &in); |
1673 | pci_read_config_dword(sii->pbus, PCI_GPIO_OUT, &out); | 907 | pci_read_config_dword(sii->pcibus, PCI_GPIO_OUT, &out); |
1674 | pci_read_config_dword(sii->pbus, PCI_GPIO_OUTEN, &outen); | 908 | pci_read_config_dword(sii->pcibus, PCI_GPIO_OUTEN, &outen); |
1675 | 909 | ||
1676 | /* | 910 | /* |
1677 | * Avoid glitching the clock if GPRS is already using it. | 911 | * Avoid glitching the clock if GPRS is already using it. |
@@ -1692,9 +926,9 @@ int ai_clkctl_xtal(struct si_pub *sih, uint what, bool on) | |||
1692 | out |= PCI_CFG_GPIO_XTAL; | 926 | out |= PCI_CFG_GPIO_XTAL; |
1693 | if (what & PLL) | 927 | if (what & PLL) |
1694 | out |= PCI_CFG_GPIO_PLL; | 928 | out |= PCI_CFG_GPIO_PLL; |
1695 | pci_write_config_dword(sii->pbus, | 929 | pci_write_config_dword(sii->pcibus, |
1696 | PCI_GPIO_OUT, out); | 930 | PCI_GPIO_OUT, out); |
1697 | pci_write_config_dword(sii->pbus, | 931 | pci_write_config_dword(sii->pcibus, |
1698 | PCI_GPIO_OUTEN, outen); | 932 | PCI_GPIO_OUTEN, outen); |
1699 | udelay(XTAL_ON_DELAY); | 933 | udelay(XTAL_ON_DELAY); |
1700 | } | 934 | } |
@@ -1702,7 +936,7 @@ int ai_clkctl_xtal(struct si_pub *sih, uint what, bool on) | |||
1702 | /* turn pll on */ | 936 | /* turn pll on */ |
1703 | if (what & PLL) { | 937 | if (what & PLL) { |
1704 | out &= ~PCI_CFG_GPIO_PLL; | 938 | out &= ~PCI_CFG_GPIO_PLL; |
1705 | pci_write_config_dword(sii->pbus, | 939 | pci_write_config_dword(sii->pcibus, |
1706 | PCI_GPIO_OUT, out); | 940 | PCI_GPIO_OUT, out); |
1707 | mdelay(2); | 941 | mdelay(2); |
1708 | } | 942 | } |
@@ -1711,9 +945,9 @@ int ai_clkctl_xtal(struct si_pub *sih, uint what, bool on) | |||
1711 | out &= ~PCI_CFG_GPIO_XTAL; | 945 | out &= ~PCI_CFG_GPIO_XTAL; |
1712 | if (what & PLL) | 946 | if (what & PLL) |
1713 | out |= PCI_CFG_GPIO_PLL; | 947 | out |= PCI_CFG_GPIO_PLL; |
1714 | pci_write_config_dword(sii->pbus, | 948 | pci_write_config_dword(sii->pcibus, |
1715 | PCI_GPIO_OUT, out); | 949 | PCI_GPIO_OUT, out); |
1716 | pci_write_config_dword(sii->pbus, | 950 | pci_write_config_dword(sii->pcibus, |
1717 | PCI_GPIO_OUTEN, outen); | 951 | PCI_GPIO_OUTEN, outen); |
1718 | } | 952 | } |
1719 | 953 | ||
@@ -1723,63 +957,52 @@ int ai_clkctl_xtal(struct si_pub *sih, uint what, bool on) | |||
1723 | /* clk control mechanism through chipcommon, no policy checking */ | 957 | /* clk control mechanism through chipcommon, no policy checking */ |
1724 | static bool _ai_clkctl_cc(struct si_info *sii, uint mode) | 958 | static bool _ai_clkctl_cc(struct si_info *sii, uint mode) |
1725 | { | 959 | { |
1726 | uint origidx = 0; | 960 | struct bcma_device *cc; |
1727 | struct chipcregs __iomem *cc; | ||
1728 | u32 scc; | 961 | u32 scc; |
1729 | uint intr_val = 0; | ||
1730 | bool fast = SI_FAST(sii); | ||
1731 | 962 | ||
1732 | /* chipcommon cores prior to rev6 don't support dynamic clock control */ | 963 | /* chipcommon cores prior to rev6 don't support dynamic clock control */ |
1733 | if (sii->pub.ccrev < 6) | 964 | if (ai_get_ccrev(&sii->pub) < 6) |
1734 | return false; | 965 | return false; |
1735 | 966 | ||
1736 | if (!fast) { | 967 | cc = ai_findcore(&sii->pub, BCMA_CORE_CHIPCOMMON, 0); |
1737 | INTR_OFF(sii, intr_val); | ||
1738 | origidx = sii->curidx; | ||
1739 | cc = (struct chipcregs __iomem *) | ||
1740 | ai_setcore(&sii->pub, CC_CORE_ID, 0); | ||
1741 | } else { | ||
1742 | cc = (struct chipcregs __iomem *) CCREGS_FAST(sii); | ||
1743 | if (cc == NULL) | ||
1744 | goto done; | ||
1745 | } | ||
1746 | 968 | ||
1747 | if (!(sii->pub.cccaps & CC_CAP_PWR_CTL) && (sii->pub.ccrev < 20)) | 969 | if (!(ai_get_cccaps(&sii->pub) & CC_CAP_PWR_CTL) && |
1748 | goto done; | 970 | (ai_get_ccrev(&sii->pub) < 20)) |
971 | return mode == CLK_FAST; | ||
1749 | 972 | ||
1750 | switch (mode) { | 973 | switch (mode) { |
1751 | case CLK_FAST: /* FORCEHT, fast (pll) clock */ | 974 | case CLK_FAST: /* FORCEHT, fast (pll) clock */ |
1752 | if (sii->pub.ccrev < 10) { | 975 | if (ai_get_ccrev(&sii->pub) < 10) { |
1753 | /* | 976 | /* |
1754 | * don't forget to force xtal back | 977 | * don't forget to force xtal back |
1755 | * on before we clear SCC_DYN_XTAL.. | 978 | * on before we clear SCC_DYN_XTAL.. |
1756 | */ | 979 | */ |
1757 | ai_clkctl_xtal(&sii->pub, XTAL, ON); | 980 | ai_clkctl_xtal(&sii->pub, XTAL, ON); |
1758 | SET_REG(&cc->slow_clk_ctl, | 981 | bcma_maskset32(cc, CHIPCREGOFFS(slow_clk_ctl), |
1759 | (SCC_XC | SCC_FS | SCC_IP), SCC_IP); | 982 | (SCC_XC | SCC_FS | SCC_IP), SCC_IP); |
1760 | } else if (sii->pub.ccrev < 20) { | 983 | } else if (ai_get_ccrev(&sii->pub) < 20) { |
1761 | OR_REG(&cc->system_clk_ctl, SYCC_HR); | 984 | bcma_set32(cc, CHIPCREGOFFS(system_clk_ctl), SYCC_HR); |
1762 | } else { | 985 | } else { |
1763 | OR_REG(&cc->clk_ctl_st, CCS_FORCEHT); | 986 | bcma_set32(cc, CHIPCREGOFFS(clk_ctl_st), CCS_FORCEHT); |
1764 | } | 987 | } |
1765 | 988 | ||
1766 | /* wait for the PLL */ | 989 | /* wait for the PLL */ |
1767 | if (sii->pub.cccaps & CC_CAP_PMU) { | 990 | if (ai_get_cccaps(&sii->pub) & CC_CAP_PMU) { |
1768 | u32 htavail = CCS_HTAVAIL; | 991 | u32 htavail = CCS_HTAVAIL; |
1769 | SPINWAIT(((R_REG(&cc->clk_ctl_st) & htavail) | 992 | SPINWAIT(((bcma_read32(cc, CHIPCREGOFFS(clk_ctl_st)) & |
1770 | == 0), PMU_MAX_TRANSITION_DLY); | 993 | htavail) == 0), PMU_MAX_TRANSITION_DLY); |
1771 | } else { | 994 | } else { |
1772 | udelay(PLL_DELAY); | 995 | udelay(PLL_DELAY); |
1773 | } | 996 | } |
1774 | break; | 997 | break; |
1775 | 998 | ||
1776 | case CLK_DYNAMIC: /* enable dynamic clock control */ | 999 | case CLK_DYNAMIC: /* enable dynamic clock control */ |
1777 | if (sii->pub.ccrev < 10) { | 1000 | if (ai_get_ccrev(&sii->pub) < 10) { |
1778 | scc = R_REG(&cc->slow_clk_ctl); | 1001 | scc = bcma_read32(cc, CHIPCREGOFFS(slow_clk_ctl)); |
1779 | scc &= ~(SCC_FS | SCC_IP | SCC_XC); | 1002 | scc &= ~(SCC_FS | SCC_IP | SCC_XC); |
1780 | if ((scc & SCC_SS_MASK) != SCC_SS_XTAL) | 1003 | if ((scc & SCC_SS_MASK) != SCC_SS_XTAL) |
1781 | scc |= SCC_XC; | 1004 | scc |= SCC_XC; |
1782 | W_REG(&cc->slow_clk_ctl, scc); | 1005 | bcma_write32(cc, CHIPCREGOFFS(slow_clk_ctl), scc); |
1783 | 1006 | ||
1784 | /* | 1007 | /* |
1785 | * for dynamic control, we have to | 1008 | * for dynamic control, we have to |
@@ -1787,11 +1010,11 @@ static bool _ai_clkctl_cc(struct si_info *sii, uint mode) | |||
1787 | */ | 1010 | */ |
1788 | if (scc & SCC_XC) | 1011 | if (scc & SCC_XC) |
1789 | ai_clkctl_xtal(&sii->pub, XTAL, OFF); | 1012 | ai_clkctl_xtal(&sii->pub, XTAL, OFF); |
1790 | } else if (sii->pub.ccrev < 20) { | 1013 | } else if (ai_get_ccrev(&sii->pub) < 20) { |
1791 | /* Instaclock */ | 1014 | /* Instaclock */ |
1792 | AND_REG(&cc->system_clk_ctl, ~SYCC_HR); | 1015 | bcma_mask32(cc, CHIPCREGOFFS(system_clk_ctl), ~SYCC_HR); |
1793 | } else { | 1016 | } else { |
1794 | AND_REG(&cc->clk_ctl_st, ~CCS_FORCEHT); | 1017 | bcma_mask32(cc, CHIPCREGOFFS(clk_ctl_st), ~CCS_FORCEHT); |
1795 | } | 1018 | } |
1796 | break; | 1019 | break; |
1797 | 1020 | ||
@@ -1799,11 +1022,6 @@ static bool _ai_clkctl_cc(struct si_info *sii, uint mode) | |||
1799 | break; | 1022 | break; |
1800 | } | 1023 | } |
1801 | 1024 | ||
1802 | done: | ||
1803 | if (!fast) { | ||
1804 | ai_setcoreidx(&sii->pub, origidx); | ||
1805 | INTR_RESTORE(sii, intr_val); | ||
1806 | } | ||
1807 | return mode == CLK_FAST; | 1025 | return mode == CLK_FAST; |
1808 | } | 1026 | } |
1809 | 1027 | ||
@@ -1822,46 +1040,25 @@ bool ai_clkctl_cc(struct si_pub *sih, uint mode) | |||
1822 | sii = (struct si_info *)sih; | 1040 | sii = (struct si_info *)sih; |
1823 | 1041 | ||
1824 | /* chipcommon cores prior to rev6 don't support dynamic clock control */ | 1042 | /* chipcommon cores prior to rev6 don't support dynamic clock control */ |
1825 | if (sih->ccrev < 6) | 1043 | if (ai_get_ccrev(sih) < 6) |
1826 | return false; | 1044 | return false; |
1827 | 1045 | ||
1828 | if (PCI_FORCEHT(sii)) | 1046 | if (PCI_FORCEHT(sih)) |
1829 | return mode == CLK_FAST; | 1047 | return mode == CLK_FAST; |
1830 | 1048 | ||
1831 | return _ai_clkctl_cc(sii, mode); | 1049 | return _ai_clkctl_cc(sii, mode); |
1832 | } | 1050 | } |
1833 | 1051 | ||
1834 | /* Build device path */ | ||
1835 | int ai_devpath(struct si_pub *sih, char *path, int size) | ||
1836 | { | ||
1837 | int slen; | ||
1838 | |||
1839 | if (!path || size <= 0) | ||
1840 | return -1; | ||
1841 | |||
1842 | slen = snprintf(path, (size_t) size, "pci/%u/%u/", | ||
1843 | ((struct si_info *)sih)->pbus->bus->number, | ||
1844 | PCI_SLOT(((struct pci_dev *) | ||
1845 | (((struct si_info *)(sih))->pbus))->devfn)); | ||
1846 | |||
1847 | if (slen < 0 || slen >= size) { | ||
1848 | path[0] = '\0'; | ||
1849 | return -1; | ||
1850 | } | ||
1851 | |||
1852 | return 0; | ||
1853 | } | ||
1854 | |||
1855 | void ai_pci_up(struct si_pub *sih) | 1052 | void ai_pci_up(struct si_pub *sih) |
1856 | { | 1053 | { |
1857 | struct si_info *sii; | 1054 | struct si_info *sii; |
1858 | 1055 | ||
1859 | sii = (struct si_info *)sih; | 1056 | sii = (struct si_info *)sih; |
1860 | 1057 | ||
1861 | if (PCI_FORCEHT(sii)) | 1058 | if (PCI_FORCEHT(sih)) |
1862 | _ai_clkctl_cc(sii, CLK_FAST); | 1059 | _ai_clkctl_cc(sii, CLK_FAST); |
1863 | 1060 | ||
1864 | if (PCIE(sii)) | 1061 | if (PCIE(sih)) |
1865 | pcicore_up(sii->pch, SI_PCIUP); | 1062 | pcicore_up(sii->pch, SI_PCIUP); |
1866 | 1063 | ||
1867 | } | 1064 | } |
@@ -1884,7 +1081,7 @@ void ai_pci_down(struct si_pub *sih) | |||
1884 | sii = (struct si_info *)sih; | 1081 | sii = (struct si_info *)sih; |
1885 | 1082 | ||
1886 | /* release FORCEHT since chip is going to "down" state */ | 1083 | /* release FORCEHT since chip is going to "down" state */ |
1887 | if (PCI_FORCEHT(sii)) | 1084 | if (PCI_FORCEHT(sih)) |
1888 | _ai_clkctl_cc(sii, CLK_DYNAMIC); | 1085 | _ai_clkctl_cc(sii, CLK_DYNAMIC); |
1889 | 1086 | ||
1890 | pcicore_down(sii->pch, SI_PCIDOWN); | 1087 | pcicore_down(sii->pch, SI_PCIDOWN); |
@@ -1897,42 +1094,23 @@ void ai_pci_down(struct si_pub *sih) | |||
1897 | void ai_pci_setup(struct si_pub *sih, uint coremask) | 1094 | void ai_pci_setup(struct si_pub *sih, uint coremask) |
1898 | { | 1095 | { |
1899 | struct si_info *sii; | 1096 | struct si_info *sii; |
1900 | struct sbpciregs __iomem *regs = NULL; | 1097 | u32 w; |
1901 | u32 siflag = 0, w; | ||
1902 | uint idx = 0; | ||
1903 | 1098 | ||
1904 | sii = (struct si_info *)sih; | 1099 | sii = (struct si_info *)sih; |
1905 | 1100 | ||
1906 | if (PCI(sii)) { | ||
1907 | /* get current core index */ | ||
1908 | idx = sii->curidx; | ||
1909 | |||
1910 | /* we interrupt on this backplane flag number */ | ||
1911 | siflag = ai_flag(sih); | ||
1912 | |||
1913 | /* switch over to pci core */ | ||
1914 | regs = ai_setcoreidx(sih, sii->pub.buscoreidx); | ||
1915 | } | ||
1916 | |||
1917 | /* | 1101 | /* |
1918 | * Enable sb->pci interrupts. Assume | 1102 | * Enable sb->pci interrupts. Assume |
1919 | * PCI rev 2.3 support was added in pci core rev 6 and things changed.. | 1103 | * PCI rev 2.3 support was added in pci core rev 6 and things changed.. |
1920 | */ | 1104 | */ |
1921 | if (PCIE(sii) || (PCI(sii) && ((sii->pub.buscorerev) >= 6))) { | 1105 | if (PCIE(sih) || (PCI(sih) && (ai_get_buscorerev(sih) >= 6))) { |
1922 | /* pci config write to set this core bit in PCIIntMask */ | 1106 | /* pci config write to set this core bit in PCIIntMask */ |
1923 | pci_read_config_dword(sii->pbus, PCI_INT_MASK, &w); | 1107 | pci_read_config_dword(sii->pcibus, PCI_INT_MASK, &w); |
1924 | w |= (coremask << PCI_SBIM_SHIFT); | 1108 | w |= (coremask << PCI_SBIM_SHIFT); |
1925 | pci_write_config_dword(sii->pbus, PCI_INT_MASK, w); | 1109 | pci_write_config_dword(sii->pcibus, PCI_INT_MASK, w); |
1926 | } else { | ||
1927 | /* set sbintvec bit for our flag number */ | ||
1928 | ai_setint(sih, siflag); | ||
1929 | } | 1110 | } |
1930 | 1111 | ||
1931 | if (PCI(sii)) { | 1112 | if (PCI(sih)) { |
1932 | pcicore_pci_setup(sii->pch, regs); | 1113 | pcicore_pci_setup(sii->pch); |
1933 | |||
1934 | /* switch back to previous core */ | ||
1935 | ai_setcoreidx(sih, idx); | ||
1936 | } | 1114 | } |
1937 | } | 1115 | } |
1938 | 1116 | ||
@@ -1942,25 +1120,11 @@ void ai_pci_setup(struct si_pub *sih, uint coremask) | |||
1942 | */ | 1120 | */ |
1943 | int ai_pci_fixcfg(struct si_pub *sih) | 1121 | int ai_pci_fixcfg(struct si_pub *sih) |
1944 | { | 1122 | { |
1945 | uint origidx; | ||
1946 | void __iomem *regs = NULL; | ||
1947 | struct si_info *sii = (struct si_info *)sih; | 1123 | struct si_info *sii = (struct si_info *)sih; |
1948 | 1124 | ||
1949 | /* Fixup PI in SROM shadow area to enable the correct PCI core access */ | 1125 | /* Fixup PI in SROM shadow area to enable the correct PCI core access */ |
1950 | /* save the current index */ | ||
1951 | origidx = ai_coreidx(&sii->pub); | ||
1952 | |||
1953 | /* check 'pi' is correct and fix it if not */ | 1126 | /* check 'pi' is correct and fix it if not */ |
1954 | regs = ai_setcore(&sii->pub, sii->pub.buscoretype, 0); | 1127 | pcicore_fixcfg(sii->pch); |
1955 | if (sii->pub.buscoretype == PCIE_CORE_ID) | ||
1956 | pcicore_fixcfg_pcie(sii->pch, | ||
1957 | (struct sbpcieregs __iomem *)regs); | ||
1958 | else if (sii->pub.buscoretype == PCI_CORE_ID) | ||
1959 | pcicore_fixcfg_pci(sii->pch, (struct sbpciregs __iomem *)regs); | ||
1960 | |||
1961 | /* restore the original index */ | ||
1962 | ai_setcoreidx(&sii->pub, origidx); | ||
1963 | |||
1964 | pcicore_hwup(sii->pch); | 1128 | pcicore_hwup(sii->pch); |
1965 | return 0; | 1129 | return 0; |
1966 | } | 1130 | } |
@@ -1971,58 +1135,42 @@ u32 ai_gpiocontrol(struct si_pub *sih, u32 mask, u32 val, u8 priority) | |||
1971 | uint regoff; | 1135 | uint regoff; |
1972 | 1136 | ||
1973 | regoff = offsetof(struct chipcregs, gpiocontrol); | 1137 | regoff = offsetof(struct chipcregs, gpiocontrol); |
1974 | return ai_corereg(sih, SI_CC_IDX, regoff, mask, val); | 1138 | return ai_cc_reg(sih, regoff, mask, val); |
1975 | } | 1139 | } |
1976 | 1140 | ||
1977 | void ai_chipcontrl_epa4331(struct si_pub *sih, bool on) | 1141 | void ai_chipcontrl_epa4331(struct si_pub *sih, bool on) |
1978 | { | 1142 | { |
1979 | struct si_info *sii; | 1143 | struct bcma_device *cc; |
1980 | struct chipcregs __iomem *cc; | ||
1981 | uint origidx; | ||
1982 | u32 val; | 1144 | u32 val; |
1983 | 1145 | ||
1984 | sii = (struct si_info *)sih; | 1146 | cc = ai_findcore(sih, CC_CORE_ID, 0); |
1985 | origidx = ai_coreidx(sih); | ||
1986 | |||
1987 | cc = (struct chipcregs __iomem *) ai_setcore(sih, CC_CORE_ID, 0); | ||
1988 | |||
1989 | val = R_REG(&cc->chipcontrol); | ||
1990 | 1147 | ||
1991 | if (on) { | 1148 | if (on) { |
1992 | if (sih->chippkg == 9 || sih->chippkg == 0xb) | 1149 | if (ai_get_chippkg(sih) == 9 || ai_get_chippkg(sih) == 0xb) |
1993 | /* Ext PA Controls for 4331 12x9 Package */ | 1150 | /* Ext PA Controls for 4331 12x9 Package */ |
1994 | W_REG(&cc->chipcontrol, val | | 1151 | bcma_set32(cc, CHIPCREGOFFS(chipcontrol), |
1995 | CCTRL4331_EXTPA_EN | | 1152 | CCTRL4331_EXTPA_EN | |
1996 | CCTRL4331_EXTPA_ON_GPIO2_5); | 1153 | CCTRL4331_EXTPA_ON_GPIO2_5); |
1997 | else | 1154 | else |
1998 | /* Ext PA Controls for 4331 12x12 Package */ | 1155 | /* Ext PA Controls for 4331 12x12 Package */ |
1999 | W_REG(&cc->chipcontrol, | 1156 | bcma_set32(cc, CHIPCREGOFFS(chipcontrol), |
2000 | val | CCTRL4331_EXTPA_EN); | 1157 | CCTRL4331_EXTPA_EN); |
2001 | } else { | 1158 | } else { |
2002 | val &= ~(CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5); | 1159 | val &= ~(CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5); |
2003 | W_REG(&cc->chipcontrol, val); | 1160 | bcma_mask32(cc, CHIPCREGOFFS(chipcontrol), |
1161 | ~(CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5)); | ||
2004 | } | 1162 | } |
2005 | |||
2006 | ai_setcoreidx(sih, origidx); | ||
2007 | } | 1163 | } |
2008 | 1164 | ||
2009 | /* Enable BT-COEX & Ex-PA for 4313 */ | 1165 | /* Enable BT-COEX & Ex-PA for 4313 */ |
2010 | void ai_epa_4313war(struct si_pub *sih) | 1166 | void ai_epa_4313war(struct si_pub *sih) |
2011 | { | 1167 | { |
2012 | struct si_info *sii; | 1168 | struct bcma_device *cc; |
2013 | struct chipcregs __iomem *cc; | ||
2014 | uint origidx; | ||
2015 | 1169 | ||
2016 | sii = (struct si_info *)sih; | 1170 | cc = ai_findcore(sih, CC_CORE_ID, 0); |
2017 | origidx = ai_coreidx(sih); | ||
2018 | |||
2019 | cc = ai_setcore(sih, CC_CORE_ID, 0); | ||
2020 | 1171 | ||
2021 | /* EPA Fix */ | 1172 | /* EPA Fix */ |
2022 | W_REG(&cc->gpiocontrol, | 1173 | bcma_set32(cc, CHIPCREGOFFS(gpiocontrol), GPIO_CTRL_EPA_EN_MASK); |
2023 | R_REG(&cc->gpiocontrol) | GPIO_CTRL_EPA_EN_MASK); | ||
2024 | |||
2025 | ai_setcoreidx(sih, origidx); | ||
2026 | } | 1174 | } |
2027 | 1175 | ||
2028 | /* check if the device is removed */ | 1176 | /* check if the device is removed */ |
@@ -2033,7 +1181,7 @@ bool ai_deviceremoved(struct si_pub *sih) | |||
2033 | 1181 | ||
2034 | sii = (struct si_info *)sih; | 1182 | sii = (struct si_info *)sih; |
2035 | 1183 | ||
2036 | pci_read_config_dword(sii->pbus, PCI_VENDOR_ID, &w); | 1184 | pci_read_config_dword(sii->pcibus, PCI_VENDOR_ID, &w); |
2037 | if ((w & 0xFFFF) != PCI_VENDOR_ID_BROADCOM) | 1185 | if ((w & 0xFFFF) != PCI_VENDOR_ID_BROADCOM) |
2038 | return true; | 1186 | return true; |
2039 | 1187 | ||
@@ -2042,26 +1190,23 @@ bool ai_deviceremoved(struct si_pub *sih) | |||
2042 | 1190 | ||
2043 | bool ai_is_sprom_available(struct si_pub *sih) | 1191 | bool ai_is_sprom_available(struct si_pub *sih) |
2044 | { | 1192 | { |
2045 | if (sih->ccrev >= 31) { | 1193 | struct si_info *sii = (struct si_info *)sih; |
2046 | struct si_info *sii; | 1194 | |
2047 | uint origidx; | 1195 | if (ai_get_ccrev(sih) >= 31) { |
2048 | struct chipcregs __iomem *cc; | 1196 | struct bcma_device *cc; |
2049 | u32 sromctrl; | 1197 | u32 sromctrl; |
2050 | 1198 | ||
2051 | if ((sih->cccaps & CC_CAP_SROM) == 0) | 1199 | if ((ai_get_cccaps(sih) & CC_CAP_SROM) == 0) |
2052 | return false; | 1200 | return false; |
2053 | 1201 | ||
2054 | sii = (struct si_info *)sih; | 1202 | cc = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0); |
2055 | origidx = sii->curidx; | 1203 | sromctrl = bcma_read32(cc, CHIPCREGOFFS(sromcontrol)); |
2056 | cc = ai_setcoreidx(sih, SI_CC_IDX); | ||
2057 | sromctrl = R_REG(&cc->sromcontrol); | ||
2058 | ai_setcoreidx(sih, origidx); | ||
2059 | return sromctrl & SRC_PRESENT; | 1204 | return sromctrl & SRC_PRESENT; |
2060 | } | 1205 | } |
2061 | 1206 | ||
2062 | switch (sih->chip) { | 1207 | switch (ai_get_chip_id(sih)) { |
2063 | case BCM4313_CHIP_ID: | 1208 | case BCM4313_CHIP_ID: |
2064 | return (sih->chipst & CST4313_SPROM_PRESENT) != 0; | 1209 | return (sii->chipst & CST4313_SPROM_PRESENT) != 0; |
2065 | default: | 1210 | default: |
2066 | return true; | 1211 | return true; |
2067 | } | 1212 | } |
@@ -2069,9 +1214,11 @@ bool ai_is_sprom_available(struct si_pub *sih) | |||
2069 | 1214 | ||
2070 | bool ai_is_otp_disabled(struct si_pub *sih) | 1215 | bool ai_is_otp_disabled(struct si_pub *sih) |
2071 | { | 1216 | { |
2072 | switch (sih->chip) { | 1217 | struct si_info *sii = (struct si_info *)sih; |
1218 | |||
1219 | switch (ai_get_chip_id(sih)) { | ||
2073 | case BCM4313_CHIP_ID: | 1220 | case BCM4313_CHIP_ID: |
2074 | return (sih->chipst & CST4313_OTP_PRESENT) == 0; | 1221 | return (sii->chipst & CST4313_OTP_PRESENT) == 0; |
2075 | /* These chips always have their OTP on */ | 1222 | /* These chips always have their OTP on */ |
2076 | case BCM43224_CHIP_ID: | 1223 | case BCM43224_CHIP_ID: |
2077 | case BCM43225_CHIP_ID: | 1224 | case BCM43225_CHIP_ID: |
@@ -2079,3 +1226,15 @@ bool ai_is_otp_disabled(struct si_pub *sih) | |||
2079 | return false; | 1226 | return false; |
2080 | } | 1227 | } |
2081 | } | 1228 | } |
1229 | |||
1230 | uint ai_get_buscoretype(struct si_pub *sih) | ||
1231 | { | ||
1232 | struct si_info *sii = (struct si_info *)sih; | ||
1233 | return sii->buscore->id.id; | ||
1234 | } | ||
1235 | |||
1236 | uint ai_get_buscorerev(struct si_pub *sih) | ||
1237 | { | ||
1238 | struct si_info *sii = (struct si_info *)sih; | ||
1239 | return sii->buscore->id.rev; | ||
1240 | } | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h index b51d1e421e24..f84c6f781692 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h | |||
@@ -17,6 +17,8 @@ | |||
17 | #ifndef _BRCM_AIUTILS_H_ | 17 | #ifndef _BRCM_AIUTILS_H_ |
18 | #define _BRCM_AIUTILS_H_ | 18 | #define _BRCM_AIUTILS_H_ |
19 | 19 | ||
20 | #include <linux/bcma/bcma.h> | ||
21 | |||
20 | #include "types.h" | 22 | #include "types.h" |
21 | 23 | ||
22 | /* | 24 | /* |
@@ -144,26 +146,15 @@ | |||
144 | * public (read-only) portion of aiutils handle returned by si_attach() | 146 | * public (read-only) portion of aiutils handle returned by si_attach() |
145 | */ | 147 | */ |
146 | struct si_pub { | 148 | struct si_pub { |
147 | uint buscoretype; /* PCI_CORE_ID, PCIE_CORE_ID, PCMCIA_CORE_ID */ | ||
148 | uint buscorerev; /* buscore rev */ | ||
149 | uint buscoreidx; /* buscore index */ | ||
150 | int ccrev; /* chip common core rev */ | 149 | int ccrev; /* chip common core rev */ |
151 | u32 cccaps; /* chip common capabilities */ | 150 | u32 cccaps; /* chip common capabilities */ |
152 | u32 cccaps_ext; /* chip common capabilities extension */ | ||
153 | int pmurev; /* pmu core rev */ | 151 | int pmurev; /* pmu core rev */ |
154 | u32 pmucaps; /* pmu capabilities */ | 152 | u32 pmucaps; /* pmu capabilities */ |
155 | uint boardtype; /* board type */ | 153 | uint boardtype; /* board type */ |
156 | uint boardvendor; /* board vendor */ | 154 | uint boardvendor; /* board vendor */ |
157 | uint boardflags; /* board flags */ | ||
158 | uint boardflags2; /* board flags2 */ | ||
159 | uint chip; /* chip number */ | 155 | uint chip; /* chip number */ |
160 | uint chiprev; /* chip revision */ | 156 | uint chiprev; /* chip revision */ |
161 | uint chippkg; /* chip package option */ | 157 | uint chippkg; /* chip package option */ |
162 | u32 chipst; /* chip status */ | ||
163 | bool issim; /* chip is in simulation or emulation */ | ||
164 | uint socirev; /* SOC interconnect rev */ | ||
165 | bool pci_pr32414; | ||
166 | |||
167 | }; | 158 | }; |
168 | 159 | ||
169 | struct pci_dev; | 160 | struct pci_dev; |
@@ -179,38 +170,13 @@ struct gpioh_item { | |||
179 | /* misc si info needed by some of the routines */ | 170 | /* misc si info needed by some of the routines */ |
180 | struct si_info { | 171 | struct si_info { |
181 | struct si_pub pub; /* back plane public state (must be first) */ | 172 | struct si_pub pub; /* back plane public state (must be first) */ |
182 | struct pci_dev *pbus; /* handle to pci bus */ | 173 | struct bcma_bus *icbus; /* handle to soc interconnect bus */ |
183 | uint dev_coreid; /* the core provides driver functions */ | 174 | struct pci_dev *pcibus; /* handle to pci bus */ |
184 | void *intr_arg; /* interrupt callback function arg */ | ||
185 | u32 (*intrsoff_fn) (void *intr_arg); /* turns chip interrupts off */ | ||
186 | /* restore chip interrupts */ | ||
187 | void (*intrsrestore_fn) (void *intr_arg, u32 arg); | ||
188 | /* check if interrupts are enabled */ | ||
189 | bool (*intrsenabled_fn) (void *intr_arg); | ||
190 | |||
191 | struct pcicore_info *pch; /* PCI/E core handle */ | 175 | struct pcicore_info *pch; /* PCI/E core handle */ |
192 | 176 | struct bcma_device *buscore; | |
193 | struct list_head var_list; /* list of srom variables */ | 177 | struct list_head var_list; /* list of srom variables */ |
194 | 178 | ||
195 | void __iomem *curmap; /* current regs va */ | 179 | u32 chipst; /* chip status */ |
196 | void __iomem *regs[SI_MAXCORES]; /* other regs va */ | ||
197 | |||
198 | uint curidx; /* current core index */ | ||
199 | uint numcores; /* # discovered cores */ | ||
200 | uint coreid[SI_MAXCORES]; /* id of each core */ | ||
201 | u32 coresba[SI_MAXCORES]; /* backplane address of each core */ | ||
202 | void *regs2[SI_MAXCORES]; /* 2nd virtual address per core (usbh20) */ | ||
203 | u32 coresba2[SI_MAXCORES]; /* 2nd phys address per core (usbh20) */ | ||
204 | u32 coresba_size[SI_MAXCORES]; /* backplane address space size */ | ||
205 | u32 coresba2_size[SI_MAXCORES]; /* second address space size */ | ||
206 | |||
207 | void *curwrap; /* current wrapper va */ | ||
208 | void *wrappers[SI_MAXCORES]; /* other cores wrapper va */ | ||
209 | u32 wrapba[SI_MAXCORES]; /* address of controlling wrapper */ | ||
210 | |||
211 | u32 cia[SI_MAXCORES]; /* erom cia entry for each core */ | ||
212 | u32 cib[SI_MAXCORES]; /* erom cia entry for each core */ | ||
213 | u32 oob_router; /* oob router registers for axi */ | ||
214 | }; | 180 | }; |
215 | 181 | ||
216 | /* | 182 | /* |
@@ -223,52 +189,15 @@ struct si_info { | |||
223 | 189 | ||
224 | 190 | ||
225 | /* AMBA Interconnect exported externs */ | 191 | /* AMBA Interconnect exported externs */ |
226 | extern uint ai_flag(struct si_pub *sih); | 192 | extern struct bcma_device *ai_findcore(struct si_pub *sih, |
227 | extern void ai_setint(struct si_pub *sih, int siflag); | 193 | u16 coreid, u16 coreunit); |
228 | extern uint ai_coreidx(struct si_pub *sih); | 194 | extern u32 ai_core_cflags(struct bcma_device *core, u32 mask, u32 val); |
229 | extern uint ai_corevendor(struct si_pub *sih); | ||
230 | extern uint ai_corerev(struct si_pub *sih); | ||
231 | extern bool ai_iscoreup(struct si_pub *sih); | ||
232 | extern u32 ai_core_cflags(struct si_pub *sih, u32 mask, u32 val); | ||
233 | extern void ai_core_cflags_wo(struct si_pub *sih, u32 mask, u32 val); | ||
234 | extern u32 ai_core_sflags(struct si_pub *sih, u32 mask, u32 val); | ||
235 | extern uint ai_corereg(struct si_pub *sih, uint coreidx, uint regoff, uint mask, | ||
236 | uint val); | ||
237 | extern void ai_core_reset(struct si_pub *sih, u32 bits, u32 resetbits); | ||
238 | extern void ai_core_disable(struct si_pub *sih, u32 bits); | ||
239 | extern int ai_numaddrspaces(struct si_pub *sih); | ||
240 | extern u32 ai_addrspace(struct si_pub *sih, uint asidx); | ||
241 | extern u32 ai_addrspacesize(struct si_pub *sih, uint asidx); | ||
242 | extern void ai_write_wrap_reg(struct si_pub *sih, u32 offset, u32 val); | ||
243 | 195 | ||
244 | /* === exported functions === */ | 196 | /* === exported functions === */ |
245 | extern struct si_pub *ai_attach(void __iomem *regs, struct pci_dev *sdh); | 197 | extern struct si_pub *ai_attach(struct bcma_bus *pbus); |
246 | extern void ai_detach(struct si_pub *sih); | 198 | extern void ai_detach(struct si_pub *sih); |
247 | extern uint ai_coreid(struct si_pub *sih); | 199 | extern uint ai_cc_reg(struct si_pub *sih, uint regoff, u32 mask, u32 val); |
248 | extern uint ai_corerev(struct si_pub *sih); | ||
249 | extern uint ai_corereg(struct si_pub *sih, uint coreidx, uint regoff, uint mask, | ||
250 | uint val); | ||
251 | extern void ai_write_wrapperreg(struct si_pub *sih, u32 offset, u32 val); | ||
252 | extern u32 ai_core_cflags(struct si_pub *sih, u32 mask, u32 val); | ||
253 | extern u32 ai_core_sflags(struct si_pub *sih, u32 mask, u32 val); | ||
254 | extern bool ai_iscoreup(struct si_pub *sih); | ||
255 | extern uint ai_findcoreidx(struct si_pub *sih, uint coreid, uint coreunit); | ||
256 | extern void __iomem *ai_setcoreidx(struct si_pub *sih, uint coreidx); | ||
257 | extern void __iomem *ai_setcore(struct si_pub *sih, uint coreid, uint coreunit); | ||
258 | extern void __iomem *ai_switch_core(struct si_pub *sih, uint coreid, | ||
259 | uint *origidx, uint *intr_val); | ||
260 | extern void ai_restore_core(struct si_pub *sih, uint coreid, uint intr_val); | ||
261 | extern void ai_core_reset(struct si_pub *sih, u32 bits, u32 resetbits); | ||
262 | extern void ai_core_disable(struct si_pub *sih, u32 bits); | ||
263 | extern u32 ai_alp_clock(struct si_pub *sih); | ||
264 | extern u32 ai_ilp_clock(struct si_pub *sih); | ||
265 | extern void ai_pci_setup(struct si_pub *sih, uint coremask); | 200 | extern void ai_pci_setup(struct si_pub *sih, uint coremask); |
266 | extern void ai_setint(struct si_pub *sih, int siflag); | ||
267 | extern bool ai_backplane64(struct si_pub *sih); | ||
268 | extern void ai_register_intr_callback(struct si_pub *sih, void *intrsoff_fn, | ||
269 | void *intrsrestore_fn, | ||
270 | void *intrsenabled_fn, void *intr_arg); | ||
271 | extern void ai_deregister_intr_callback(struct si_pub *sih); | ||
272 | extern void ai_clkctl_init(struct si_pub *sih); | 201 | extern void ai_clkctl_init(struct si_pub *sih); |
273 | extern u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih); | 202 | extern u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih); |
274 | extern bool ai_clkctl_cc(struct si_pub *sih, uint mode); | 203 | extern bool ai_clkctl_cc(struct si_pub *sih, uint mode); |
@@ -283,13 +212,6 @@ extern bool ai_is_otp_disabled(struct si_pub *sih); | |||
283 | /* SPROM availability */ | 212 | /* SPROM availability */ |
284 | extern bool ai_is_sprom_available(struct si_pub *sih); | 213 | extern bool ai_is_sprom_available(struct si_pub *sih); |
285 | 214 | ||
286 | /* | ||
287 | * Build device path. Path size must be >= SI_DEVPATH_BUFSZ. | ||
288 | * The returned path is NULL terminated and has trailing '/'. | ||
289 | * Return 0 on success, nonzero otherwise. | ||
290 | */ | ||
291 | extern int ai_devpath(struct si_pub *sih, char *path, int size); | ||
292 | |||
293 | extern void ai_pci_sleep(struct si_pub *sih); | 215 | extern void ai_pci_sleep(struct si_pub *sih); |
294 | extern void ai_pci_down(struct si_pub *sih); | 216 | extern void ai_pci_down(struct si_pub *sih); |
295 | extern void ai_pci_up(struct si_pub *sih); | 217 | extern void ai_pci_up(struct si_pub *sih); |
@@ -299,4 +221,52 @@ extern void ai_chipcontrl_epa4331(struct si_pub *sih, bool on); | |||
299 | /* Enable Ex-PA for 4313 */ | 221 | /* Enable Ex-PA for 4313 */ |
300 | extern void ai_epa_4313war(struct si_pub *sih); | 222 | extern void ai_epa_4313war(struct si_pub *sih); |
301 | 223 | ||
224 | extern uint ai_get_buscoretype(struct si_pub *sih); | ||
225 | extern uint ai_get_buscorerev(struct si_pub *sih); | ||
226 | |||
227 | static inline int ai_get_ccrev(struct si_pub *sih) | ||
228 | { | ||
229 | return sih->ccrev; | ||
230 | } | ||
231 | |||
232 | static inline u32 ai_get_cccaps(struct si_pub *sih) | ||
233 | { | ||
234 | return sih->cccaps; | ||
235 | } | ||
236 | |||
237 | static inline int ai_get_pmurev(struct si_pub *sih) | ||
238 | { | ||
239 | return sih->pmurev; | ||
240 | } | ||
241 | |||
242 | static inline u32 ai_get_pmucaps(struct si_pub *sih) | ||
243 | { | ||
244 | return sih->pmucaps; | ||
245 | } | ||
246 | |||
247 | static inline uint ai_get_boardtype(struct si_pub *sih) | ||
248 | { | ||
249 | return sih->boardtype; | ||
250 | } | ||
251 | |||
252 | static inline uint ai_get_boardvendor(struct si_pub *sih) | ||
253 | { | ||
254 | return sih->boardvendor; | ||
255 | } | ||
256 | |||
257 | static inline uint ai_get_chip_id(struct si_pub *sih) | ||
258 | { | ||
259 | return sih->chip; | ||
260 | } | ||
261 | |||
262 | static inline uint ai_get_chiprev(struct si_pub *sih) | ||
263 | { | ||
264 | return sih->chiprev; | ||
265 | } | ||
266 | |||
267 | static inline uint ai_get_chippkg(struct si_pub *sih) | ||
268 | { | ||
269 | return sih->chippkg; | ||
270 | } | ||
271 | |||
302 | #endif /* _BRCM_AIUTILS_H_ */ | 272 | #endif /* _BRCM_AIUTILS_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c index 43f7a724dda8..90911eec0cf5 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c | |||
@@ -1118,14 +1118,17 @@ brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb, | |||
1118 | u8 status_delay = 0; | 1118 | u8 status_delay = 0; |
1119 | 1119 | ||
1120 | /* wait till the next 8 bytes of txstatus is available */ | 1120 | /* wait till the next 8 bytes of txstatus is available */ |
1121 | while (((s1 = R_REG(&wlc->regs->frmtxstatus)) & TXS_V) == 0) { | 1121 | s1 = bcma_read32(wlc->hw->d11core, D11REGOFFS(frmtxstatus)); |
1122 | while ((s1 & TXS_V) == 0) { | ||
1122 | udelay(1); | 1123 | udelay(1); |
1123 | status_delay++; | 1124 | status_delay++; |
1124 | if (status_delay > 10) | 1125 | if (status_delay > 10) |
1125 | return; /* error condition */ | 1126 | return; /* error condition */ |
1127 | s1 = bcma_read32(wlc->hw->d11core, | ||
1128 | D11REGOFFS(frmtxstatus)); | ||
1126 | } | 1129 | } |
1127 | 1130 | ||
1128 | s2 = R_REG(&wlc->regs->frmtxstatus2); | 1131 | s2 = bcma_read32(wlc->hw->d11core, D11REGOFFS(frmtxstatus2)); |
1129 | } | 1132 | } |
1130 | 1133 | ||
1131 | if (scb) { | 1134 | if (scb) { |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/d11.h b/drivers/net/wireless/brcm80211/brcmsmac/d11.h index ed51616abc85..1948cb2771e9 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/d11.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/d11.h | |||
@@ -430,6 +430,9 @@ struct d11regs { | |||
430 | u16 PAD[0x380]; /* 0x800 - 0xEFE */ | 430 | u16 PAD[0x380]; /* 0x800 - 0xEFE */ |
431 | }; | 431 | }; |
432 | 432 | ||
433 | /* d11 register field offset */ | ||
434 | #define D11REGOFFS(field) offsetof(struct d11regs, field) | ||
435 | |||
433 | #define PIHR_BASE 0x0400 /* byte address of packed IHR region */ | 436 | #define PIHR_BASE 0x0400 /* byte address of packed IHR region */ |
434 | 437 | ||
435 | /* biststatus */ | 438 | /* biststatus */ |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/dma.c b/drivers/net/wireless/brcm80211/brcmsmac/dma.c index b55b1f6bb4ba..b4cf617276c9 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/dma.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/dma.c | |||
@@ -27,6 +27,13 @@ | |||
27 | #include "soc.h" | 27 | #include "soc.h" |
28 | 28 | ||
29 | /* | 29 | /* |
30 | * dma register field offset calculation | ||
31 | */ | ||
32 | #define DMA64REGOFFS(field) offsetof(struct dma64regs, field) | ||
33 | #define DMA64TXREGOFFS(di, field) (di->d64txregbase + DMA64REGOFFS(field)) | ||
34 | #define DMA64RXREGOFFS(di, field) (di->d64rxregbase + DMA64REGOFFS(field)) | ||
35 | |||
36 | /* | ||
30 | * DMA hardware requires each descriptor ring to be 8kB aligned, and fit within | 37 | * DMA hardware requires each descriptor ring to be 8kB aligned, and fit within |
31 | * a contiguous 8kB physical address. | 38 | * a contiguous 8kB physical address. |
32 | */ | 39 | */ |
@@ -220,15 +227,16 @@ struct dma_info { | |||
220 | uint *msg_level; /* message level pointer */ | 227 | uint *msg_level; /* message level pointer */ |
221 | char name[MAXNAMEL]; /* callers name for diag msgs */ | 228 | char name[MAXNAMEL]; /* callers name for diag msgs */ |
222 | 229 | ||
223 | struct pci_dev *pbus; /* bus handle */ | 230 | struct bcma_device *core; |
231 | struct device *dmadev; | ||
224 | 232 | ||
225 | bool dma64; /* this dma engine is operating in 64-bit mode */ | 233 | bool dma64; /* this dma engine is operating in 64-bit mode */ |
226 | bool addrext; /* this dma engine supports DmaExtendedAddrChanges */ | 234 | bool addrext; /* this dma engine supports DmaExtendedAddrChanges */ |
227 | 235 | ||
228 | /* 64-bit dma tx engine registers */ | 236 | /* 64-bit dma tx engine registers */ |
229 | struct dma64regs __iomem *d64txregs; | 237 | uint d64txregbase; |
230 | /* 64-bit dma rx engine registers */ | 238 | /* 64-bit dma rx engine registers */ |
231 | struct dma64regs __iomem *d64rxregs; | 239 | uint d64rxregbase; |
232 | /* pointer to dma64 tx descriptor ring */ | 240 | /* pointer to dma64 tx descriptor ring */ |
233 | struct dma64desc *txd64; | 241 | struct dma64desc *txd64; |
234 | /* pointer to dma64 rx descriptor ring */ | 242 | /* pointer to dma64 rx descriptor ring */ |
@@ -375,15 +383,16 @@ static uint _dma_ctrlflags(struct dma_info *di, uint mask, uint flags) | |||
375 | if (dmactrlflags & DMA_CTRL_PEN) { | 383 | if (dmactrlflags & DMA_CTRL_PEN) { |
376 | u32 control; | 384 | u32 control; |
377 | 385 | ||
378 | control = R_REG(&di->d64txregs->control); | 386 | control = bcma_read32(di->core, DMA64TXREGOFFS(di, control)); |
379 | W_REG(&di->d64txregs->control, | 387 | bcma_write32(di->core, DMA64TXREGOFFS(di, control), |
380 | control | D64_XC_PD); | 388 | control | D64_XC_PD); |
381 | if (R_REG(&di->d64txregs->control) & D64_XC_PD) | 389 | if (bcma_read32(di->core, DMA64TXREGOFFS(di, control)) & |
390 | D64_XC_PD) | ||
382 | /* We *can* disable it so it is supported, | 391 | /* We *can* disable it so it is supported, |
383 | * restore control register | 392 | * restore control register |
384 | */ | 393 | */ |
385 | W_REG(&di->d64txregs->control, | 394 | bcma_write32(di->core, DMA64TXREGOFFS(di, control), |
386 | control); | 395 | control); |
387 | else | 396 | else |
388 | /* Not supported, don't allow it to be enabled */ | 397 | /* Not supported, don't allow it to be enabled */ |
389 | dmactrlflags &= ~DMA_CTRL_PEN; | 398 | dmactrlflags &= ~DMA_CTRL_PEN; |
@@ -394,12 +403,12 @@ static uint _dma_ctrlflags(struct dma_info *di, uint mask, uint flags) | |||
394 | return dmactrlflags; | 403 | return dmactrlflags; |
395 | } | 404 | } |
396 | 405 | ||
397 | static bool _dma64_addrext(struct dma64regs __iomem *dma64regs) | 406 | static bool _dma64_addrext(struct dma_info *di, uint ctrl_offset) |
398 | { | 407 | { |
399 | u32 w; | 408 | u32 w; |
400 | OR_REG(&dma64regs->control, D64_XC_AE); | 409 | bcma_set32(di->core, ctrl_offset, D64_XC_AE); |
401 | w = R_REG(&dma64regs->control); | 410 | w = bcma_read32(di->core, ctrl_offset); |
402 | AND_REG(&dma64regs->control, ~D64_XC_AE); | 411 | bcma_mask32(di->core, ctrl_offset, ~D64_XC_AE); |
403 | return (w & D64_XC_AE) == D64_XC_AE; | 412 | return (w & D64_XC_AE) == D64_XC_AE; |
404 | } | 413 | } |
405 | 414 | ||
@@ -412,13 +421,13 @@ static bool _dma_isaddrext(struct dma_info *di) | |||
412 | /* DMA64 supports full 32- or 64-bit operation. AE is always valid */ | 421 | /* DMA64 supports full 32- or 64-bit operation. AE is always valid */ |
413 | 422 | ||
414 | /* not all tx or rx channel are available */ | 423 | /* not all tx or rx channel are available */ |
415 | if (di->d64txregs != NULL) { | 424 | if (di->d64txregbase != 0) { |
416 | if (!_dma64_addrext(di->d64txregs)) | 425 | if (!_dma64_addrext(di, DMA64TXREGOFFS(di, control))) |
417 | DMA_ERROR("%s: DMA64 tx doesn't have AE set\n", | 426 | DMA_ERROR("%s: DMA64 tx doesn't have AE set\n", |
418 | di->name); | 427 | di->name); |
419 | return true; | 428 | return true; |
420 | } else if (di->d64rxregs != NULL) { | 429 | } else if (di->d64rxregbase != 0) { |
421 | if (!_dma64_addrext(di->d64rxregs)) | 430 | if (!_dma64_addrext(di, DMA64RXREGOFFS(di, control))) |
422 | DMA_ERROR("%s: DMA64 rx doesn't have AE set\n", | 431 | DMA_ERROR("%s: DMA64 rx doesn't have AE set\n", |
423 | di->name); | 432 | di->name); |
424 | return true; | 433 | return true; |
@@ -432,14 +441,14 @@ static bool _dma_descriptor_align(struct dma_info *di) | |||
432 | u32 addrl; | 441 | u32 addrl; |
433 | 442 | ||
434 | /* Check to see if the descriptors need to be aligned on 4K/8K or not */ | 443 | /* Check to see if the descriptors need to be aligned on 4K/8K or not */ |
435 | if (di->d64txregs != NULL) { | 444 | if (di->d64txregbase != 0) { |
436 | W_REG(&di->d64txregs->addrlow, 0xff0); | 445 | bcma_write32(di->core, DMA64TXREGOFFS(di, addrlow), 0xff0); |
437 | addrl = R_REG(&di->d64txregs->addrlow); | 446 | addrl = bcma_read32(di->core, DMA64TXREGOFFS(di, addrlow)); |
438 | if (addrl != 0) | 447 | if (addrl != 0) |
439 | return false; | 448 | return false; |
440 | } else if (di->d64rxregs != NULL) { | 449 | } else if (di->d64rxregbase != 0) { |
441 | W_REG(&di->d64rxregs->addrlow, 0xff0); | 450 | bcma_write32(di->core, DMA64RXREGOFFS(di, addrlow), 0xff0); |
442 | addrl = R_REG(&di->d64rxregs->addrlow); | 451 | addrl = bcma_read32(di->core, DMA64RXREGOFFS(di, addrlow)); |
443 | if (addrl != 0) | 452 | if (addrl != 0) |
444 | return false; | 453 | return false; |
445 | } | 454 | } |
@@ -450,7 +459,7 @@ static bool _dma_descriptor_align(struct dma_info *di) | |||
450 | * Descriptor table must start at the DMA hardware dictated alignment, so | 459 | * Descriptor table must start at the DMA hardware dictated alignment, so |
451 | * allocated memory must be large enough to support this requirement. | 460 | * allocated memory must be large enough to support this requirement. |
452 | */ | 461 | */ |
453 | static void *dma_alloc_consistent(struct pci_dev *pdev, uint size, | 462 | static void *dma_alloc_consistent(struct dma_info *di, uint size, |
454 | u16 align_bits, uint *alloced, | 463 | u16 align_bits, uint *alloced, |
455 | dma_addr_t *pap) | 464 | dma_addr_t *pap) |
456 | { | 465 | { |
@@ -460,7 +469,7 @@ static void *dma_alloc_consistent(struct pci_dev *pdev, uint size, | |||
460 | size += align; | 469 | size += align; |
461 | *alloced = size; | 470 | *alloced = size; |
462 | } | 471 | } |
463 | return pci_alloc_consistent(pdev, size, pap); | 472 | return dma_alloc_coherent(di->dmadev, size, pap, GFP_ATOMIC); |
464 | } | 473 | } |
465 | 474 | ||
466 | static | 475 | static |
@@ -486,7 +495,7 @@ static void *dma_ringalloc(struct dma_info *di, u32 boundary, uint size, | |||
486 | u32 desc_strtaddr; | 495 | u32 desc_strtaddr; |
487 | u32 alignbytes = 1 << *alignbits; | 496 | u32 alignbytes = 1 << *alignbits; |
488 | 497 | ||
489 | va = dma_alloc_consistent(di->pbus, size, *alignbits, alloced, descpa); | 498 | va = dma_alloc_consistent(di, size, *alignbits, alloced, descpa); |
490 | 499 | ||
491 | if (NULL == va) | 500 | if (NULL == va) |
492 | return NULL; | 501 | return NULL; |
@@ -495,8 +504,8 @@ static void *dma_ringalloc(struct dma_info *di, u32 boundary, uint size, | |||
495 | if (((desc_strtaddr + size - 1) & boundary) != (desc_strtaddr | 504 | if (((desc_strtaddr + size - 1) & boundary) != (desc_strtaddr |
496 | & boundary)) { | 505 | & boundary)) { |
497 | *alignbits = dma_align_sizetobits(size); | 506 | *alignbits = dma_align_sizetobits(size); |
498 | pci_free_consistent(di->pbus, size, va, *descpa); | 507 | dma_free_coherent(di->dmadev, size, va, *descpa); |
499 | va = dma_alloc_consistent(di->pbus, size, *alignbits, | 508 | va = dma_alloc_consistent(di, size, *alignbits, |
500 | alloced, descpa); | 509 | alloced, descpa); |
501 | } | 510 | } |
502 | return va; | 511 | return va; |
@@ -556,12 +565,13 @@ static bool _dma_alloc(struct dma_info *di, uint direction) | |||
556 | } | 565 | } |
557 | 566 | ||
558 | struct dma_pub *dma_attach(char *name, struct si_pub *sih, | 567 | struct dma_pub *dma_attach(char *name, struct si_pub *sih, |
559 | void __iomem *dmaregstx, void __iomem *dmaregsrx, | 568 | struct bcma_device *core, |
560 | uint ntxd, uint nrxd, | 569 | uint txregbase, uint rxregbase, uint ntxd, uint nrxd, |
561 | uint rxbufsize, int rxextheadroom, | 570 | uint rxbufsize, int rxextheadroom, |
562 | uint nrxpost, uint rxoffset, uint *msg_level) | 571 | uint nrxpost, uint rxoffset, uint *msg_level) |
563 | { | 572 | { |
564 | struct dma_info *di; | 573 | struct dma_info *di; |
574 | u8 rev = core->id.rev; | ||
565 | uint size; | 575 | uint size; |
566 | 576 | ||
567 | /* allocate private info structure */ | 577 | /* allocate private info structure */ |
@@ -572,11 +582,13 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih, | |||
572 | di->msg_level = msg_level ? msg_level : &dma_msg_level; | 582 | di->msg_level = msg_level ? msg_level : &dma_msg_level; |
573 | 583 | ||
574 | 584 | ||
575 | di->dma64 = ((ai_core_sflags(sih, 0, 0) & SISF_DMA64) == SISF_DMA64); | 585 | di->dma64 = |
586 | ((bcma_aread32(core, BCMA_IOST) & SISF_DMA64) == SISF_DMA64); | ||
576 | 587 | ||
577 | /* init dma reg pointer */ | 588 | /* init dma reg info */ |
578 | di->d64txregs = (struct dma64regs __iomem *) dmaregstx; | 589 | di->core = core; |
579 | di->d64rxregs = (struct dma64regs __iomem *) dmaregsrx; | 590 | di->d64txregbase = txregbase; |
591 | di->d64rxregbase = rxregbase; | ||
580 | 592 | ||
581 | /* | 593 | /* |
582 | * Default flags (which can be changed by the driver calling | 594 | * Default flags (which can be changed by the driver calling |
@@ -585,16 +597,17 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih, | |||
585 | */ | 597 | */ |
586 | _dma_ctrlflags(di, DMA_CTRL_ROC | DMA_CTRL_PEN, 0); | 598 | _dma_ctrlflags(di, DMA_CTRL_ROC | DMA_CTRL_PEN, 0); |
587 | 599 | ||
588 | DMA_TRACE("%s: %s flags 0x%x ntxd %d nrxd %d rxbufsize %d rxextheadroom %d nrxpost %d rxoffset %d dmaregstx %p dmaregsrx %p\n", | 600 | DMA_TRACE("%s: %s flags 0x%x ntxd %d nrxd %d " |
589 | name, "DMA64", | 601 | "rxbufsize %d rxextheadroom %d nrxpost %d rxoffset %d " |
602 | "txregbase %u rxregbase %u\n", name, "DMA64", | ||
590 | di->dma.dmactrlflags, ntxd, nrxd, rxbufsize, | 603 | di->dma.dmactrlflags, ntxd, nrxd, rxbufsize, |
591 | rxextheadroom, nrxpost, rxoffset, dmaregstx, dmaregsrx); | 604 | rxextheadroom, nrxpost, rxoffset, txregbase, rxregbase); |
592 | 605 | ||
593 | /* make a private copy of our callers name */ | 606 | /* make a private copy of our callers name */ |
594 | strncpy(di->name, name, MAXNAMEL); | 607 | strncpy(di->name, name, MAXNAMEL); |
595 | di->name[MAXNAMEL - 1] = '\0'; | 608 | di->name[MAXNAMEL - 1] = '\0'; |
596 | 609 | ||
597 | di->pbus = ((struct si_info *)sih)->pbus; | 610 | di->dmadev = core->dma_dev; |
598 | 611 | ||
599 | /* save tunables */ | 612 | /* save tunables */ |
600 | di->ntxd = (u16) ntxd; | 613 | di->ntxd = (u16) ntxd; |
@@ -626,11 +639,11 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih, | |||
626 | di->dataoffsetlow = di->ddoffsetlow; | 639 | di->dataoffsetlow = di->ddoffsetlow; |
627 | di->dataoffsethigh = di->ddoffsethigh; | 640 | di->dataoffsethigh = di->ddoffsethigh; |
628 | /* WAR64450 : DMACtl.Addr ext fields are not supported in SDIOD core. */ | 641 | /* WAR64450 : DMACtl.Addr ext fields are not supported in SDIOD core. */ |
629 | if ((ai_coreid(sih) == SDIOD_CORE_ID) | 642 | if ((core->id.id == SDIOD_CORE_ID) |
630 | && ((ai_corerev(sih) > 0) && (ai_corerev(sih) <= 2))) | 643 | && ((rev > 0) && (rev <= 2))) |
631 | di->addrext = 0; | 644 | di->addrext = 0; |
632 | else if ((ai_coreid(sih) == I2S_CORE_ID) && | 645 | else if ((core->id.id == I2S_CORE_ID) && |
633 | ((ai_corerev(sih) == 0) || (ai_corerev(sih) == 1))) | 646 | ((rev == 0) || (rev == 1))) |
634 | di->addrext = 0; | 647 | di->addrext = 0; |
635 | else | 648 | else |
636 | di->addrext = _dma_isaddrext(di); | 649 | di->addrext = _dma_isaddrext(di); |
@@ -749,13 +762,13 @@ void dma_detach(struct dma_pub *pub) | |||
749 | 762 | ||
750 | /* free dma descriptor rings */ | 763 | /* free dma descriptor rings */ |
751 | if (di->txd64) | 764 | if (di->txd64) |
752 | pci_free_consistent(di->pbus, di->txdalloc, | 765 | dma_free_coherent(di->dmadev, di->txdalloc, |
753 | ((s8 *)di->txd64 - di->txdalign), | 766 | ((s8 *)di->txd64 - di->txdalign), |
754 | (di->txdpaorig)); | 767 | (di->txdpaorig)); |
755 | if (di->rxd64) | 768 | if (di->rxd64) |
756 | pci_free_consistent(di->pbus, di->rxdalloc, | 769 | dma_free_coherent(di->dmadev, di->rxdalloc, |
757 | ((s8 *)di->rxd64 - di->rxdalign), | 770 | ((s8 *)di->rxd64 - di->rxdalign), |
758 | (di->rxdpaorig)); | 771 | (di->rxdpaorig)); |
759 | 772 | ||
760 | /* free packet pointer vectors */ | 773 | /* free packet pointer vectors */ |
761 | kfree(di->txp); | 774 | kfree(di->txp); |
@@ -780,11 +793,15 @@ _dma_ddtable_init(struct dma_info *di, uint direction, dma_addr_t pa) | |||
780 | if ((di->ddoffsetlow == 0) | 793 | if ((di->ddoffsetlow == 0) |
781 | || !(pa & PCI32ADDR_HIGH)) { | 794 | || !(pa & PCI32ADDR_HIGH)) { |
782 | if (direction == DMA_TX) { | 795 | if (direction == DMA_TX) { |
783 | W_REG(&di->d64txregs->addrlow, pa + di->ddoffsetlow); | 796 | bcma_write32(di->core, DMA64TXREGOFFS(di, addrlow), |
784 | W_REG(&di->d64txregs->addrhigh, di->ddoffsethigh); | 797 | pa + di->ddoffsetlow); |
798 | bcma_write32(di->core, DMA64TXREGOFFS(di, addrhigh), | ||
799 | di->ddoffsethigh); | ||
785 | } else { | 800 | } else { |
786 | W_REG(&di->d64rxregs->addrlow, pa + di->ddoffsetlow); | 801 | bcma_write32(di->core, DMA64RXREGOFFS(di, addrlow), |
787 | W_REG(&di->d64rxregs->addrhigh, di->ddoffsethigh); | 802 | pa + di->ddoffsetlow); |
803 | bcma_write32(di->core, DMA64RXREGOFFS(di, addrhigh), | ||
804 | di->ddoffsethigh); | ||
788 | } | 805 | } |
789 | } else { | 806 | } else { |
790 | /* DMA64 32bits address extension */ | 807 | /* DMA64 32bits address extension */ |
@@ -795,15 +812,19 @@ _dma_ddtable_init(struct dma_info *di, uint direction, dma_addr_t pa) | |||
795 | pa &= ~PCI32ADDR_HIGH; | 812 | pa &= ~PCI32ADDR_HIGH; |
796 | 813 | ||
797 | if (direction == DMA_TX) { | 814 | if (direction == DMA_TX) { |
798 | W_REG(&di->d64txregs->addrlow, pa + di->ddoffsetlow); | 815 | bcma_write32(di->core, DMA64TXREGOFFS(di, addrlow), |
799 | W_REG(&di->d64txregs->addrhigh, di->ddoffsethigh); | 816 | pa + di->ddoffsetlow); |
800 | SET_REG(&di->d64txregs->control, | 817 | bcma_write32(di->core, DMA64TXREGOFFS(di, addrhigh), |
801 | D64_XC_AE, (ae << D64_XC_AE_SHIFT)); | 818 | di->ddoffsethigh); |
819 | bcma_maskset32(di->core, DMA64TXREGOFFS(di, control), | ||
820 | D64_XC_AE, (ae << D64_XC_AE_SHIFT)); | ||
802 | } else { | 821 | } else { |
803 | W_REG(&di->d64rxregs->addrlow, pa + di->ddoffsetlow); | 822 | bcma_write32(di->core, DMA64RXREGOFFS(di, addrlow), |
804 | W_REG(&di->d64rxregs->addrhigh, di->ddoffsethigh); | 823 | pa + di->ddoffsetlow); |
805 | SET_REG(&di->d64rxregs->control, | 824 | bcma_write32(di->core, DMA64RXREGOFFS(di, addrhigh), |
806 | D64_RC_AE, (ae << D64_RC_AE_SHIFT)); | 825 | di->ddoffsethigh); |
826 | bcma_maskset32(di->core, DMA64RXREGOFFS(di, control), | ||
827 | D64_RC_AE, (ae << D64_RC_AE_SHIFT)); | ||
807 | } | 828 | } |
808 | } | 829 | } |
809 | } | 830 | } |
@@ -815,9 +836,9 @@ static void _dma_rxenable(struct dma_info *di) | |||
815 | 836 | ||
816 | DMA_TRACE("%s:\n", di->name); | 837 | DMA_TRACE("%s:\n", di->name); |
817 | 838 | ||
818 | control = | 839 | control = D64_RC_RE | (bcma_read32(di->core, |
819 | (R_REG(&di->d64rxregs->control) & D64_RC_AE) | | 840 | DMA64RXREGOFFS(di, control)) & |
820 | D64_RC_RE; | 841 | D64_RC_AE); |
821 | 842 | ||
822 | if ((dmactrlflags & DMA_CTRL_PEN) == 0) | 843 | if ((dmactrlflags & DMA_CTRL_PEN) == 0) |
823 | control |= D64_RC_PD; | 844 | control |= D64_RC_PD; |
@@ -825,7 +846,7 @@ static void _dma_rxenable(struct dma_info *di) | |||
825 | if (dmactrlflags & DMA_CTRL_ROC) | 846 | if (dmactrlflags & DMA_CTRL_ROC) |
826 | control |= D64_RC_OC; | 847 | control |= D64_RC_OC; |
827 | 848 | ||
828 | W_REG(&di->d64rxregs->control, | 849 | bcma_write32(di->core, DMA64RXREGOFFS(di, control), |
829 | ((di->rxoffset << D64_RC_RO_SHIFT) | control)); | 850 | ((di->rxoffset << D64_RC_RO_SHIFT) | control)); |
830 | } | 851 | } |
831 | 852 | ||
@@ -868,7 +889,8 @@ static struct sk_buff *dma64_getnextrxp(struct dma_info *di, bool forceall) | |||
868 | return NULL; | 889 | return NULL; |
869 | 890 | ||
870 | curr = | 891 | curr = |
871 | B2I(((R_REG(&di->d64rxregs->status0) & D64_RS0_CD_MASK) - | 892 | B2I(((bcma_read32(di->core, |
893 | DMA64RXREGOFFS(di, status0)) & D64_RS0_CD_MASK) - | ||
872 | di->rcvptrbase) & D64_RS0_CD_MASK, struct dma64desc); | 894 | di->rcvptrbase) & D64_RS0_CD_MASK, struct dma64desc); |
873 | 895 | ||
874 | /* ignore curr if forceall */ | 896 | /* ignore curr if forceall */ |
@@ -882,7 +904,7 @@ static struct sk_buff *dma64_getnextrxp(struct dma_info *di, bool forceall) | |||
882 | pa = le32_to_cpu(di->rxd64[i].addrlow) - di->dataoffsetlow; | 904 | pa = le32_to_cpu(di->rxd64[i].addrlow) - di->dataoffsetlow; |
883 | 905 | ||
884 | /* clear this packet from the descriptor ring */ | 906 | /* clear this packet from the descriptor ring */ |
885 | pci_unmap_single(di->pbus, pa, di->rxbufsize, PCI_DMA_FROMDEVICE); | 907 | dma_unmap_single(di->dmadev, pa, di->rxbufsize, DMA_FROM_DEVICE); |
886 | 908 | ||
887 | di->rxd64[i].addrlow = cpu_to_le32(0xdeadbeef); | 909 | di->rxd64[i].addrlow = cpu_to_le32(0xdeadbeef); |
888 | di->rxd64[i].addrhigh = cpu_to_le32(0xdeadbeef); | 910 | di->rxd64[i].addrhigh = cpu_to_le32(0xdeadbeef); |
@@ -950,12 +972,12 @@ int dma_rx(struct dma_pub *pub, struct sk_buff_head *skb_list) | |||
950 | if (resid > 0) { | 972 | if (resid > 0) { |
951 | uint cur; | 973 | uint cur; |
952 | cur = | 974 | cur = |
953 | B2I(((R_REG(&di->d64rxregs->status0) & | 975 | B2I(((bcma_read32(di->core, |
954 | D64_RS0_CD_MASK) - | 976 | DMA64RXREGOFFS(di, status0)) & |
955 | di->rcvptrbase) & D64_RS0_CD_MASK, | 977 | D64_RS0_CD_MASK) - di->rcvptrbase) & |
956 | struct dma64desc); | 978 | D64_RS0_CD_MASK, struct dma64desc); |
957 | DMA_ERROR("rxin %d rxout %d, hw_curr %d\n", | 979 | DMA_ERROR("rxin %d rxout %d, hw_curr %d\n", |
958 | di->rxin, di->rxout, cur); | 980 | di->rxin, di->rxout, cur); |
959 | } | 981 | } |
960 | #endif /* BCMDBG */ | 982 | #endif /* BCMDBG */ |
961 | 983 | ||
@@ -983,8 +1005,10 @@ static bool dma64_rxidle(struct dma_info *di) | |||
983 | if (di->nrxd == 0) | 1005 | if (di->nrxd == 0) |
984 | return true; | 1006 | return true; |
985 | 1007 | ||
986 | return ((R_REG(&di->d64rxregs->status0) & D64_RS0_CD_MASK) == | 1008 | return ((bcma_read32(di->core, |
987 | (R_REG(&di->d64rxregs->ptr) & D64_RS0_CD_MASK)); | 1009 | DMA64RXREGOFFS(di, status0)) & D64_RS0_CD_MASK) == |
1010 | (bcma_read32(di->core, DMA64RXREGOFFS(di, ptr)) & | ||
1011 | D64_RS0_CD_MASK)); | ||
988 | } | 1012 | } |
989 | 1013 | ||
990 | /* | 1014 | /* |
@@ -1048,8 +1072,8 @@ bool dma_rxfill(struct dma_pub *pub) | |||
1048 | */ | 1072 | */ |
1049 | *(u32 *) (p->data) = 0; | 1073 | *(u32 *) (p->data) = 0; |
1050 | 1074 | ||
1051 | pa = pci_map_single(di->pbus, p->data, | 1075 | pa = dma_map_single(di->dmadev, p->data, di->rxbufsize, |
1052 | di->rxbufsize, PCI_DMA_FROMDEVICE); | 1076 | DMA_FROM_DEVICE); |
1053 | 1077 | ||
1054 | /* save the free packet pointer */ | 1078 | /* save the free packet pointer */ |
1055 | di->rxp[rxout] = p; | 1079 | di->rxp[rxout] = p; |
@@ -1067,7 +1091,7 @@ bool dma_rxfill(struct dma_pub *pub) | |||
1067 | di->rxout = rxout; | 1091 | di->rxout = rxout; |
1068 | 1092 | ||
1069 | /* update the chip lastdscr pointer */ | 1093 | /* update the chip lastdscr pointer */ |
1070 | W_REG(&di->d64rxregs->ptr, | 1094 | bcma_write32(di->core, DMA64RXREGOFFS(di, ptr), |
1071 | di->rcvptrbase + I2B(rxout, struct dma64desc)); | 1095 | di->rcvptrbase + I2B(rxout, struct dma64desc)); |
1072 | 1096 | ||
1073 | return ring_empty; | 1097 | return ring_empty; |
@@ -1128,7 +1152,7 @@ void dma_txinit(struct dma_pub *pub) | |||
1128 | 1152 | ||
1129 | if ((di->dma.dmactrlflags & DMA_CTRL_PEN) == 0) | 1153 | if ((di->dma.dmactrlflags & DMA_CTRL_PEN) == 0) |
1130 | control |= D64_XC_PD; | 1154 | control |= D64_XC_PD; |
1131 | OR_REG(&di->d64txregs->control, control); | 1155 | bcma_set32(di->core, DMA64TXREGOFFS(di, control), control); |
1132 | 1156 | ||
1133 | /* DMA engine with alignment requirement requires table to be inited | 1157 | /* DMA engine with alignment requirement requires table to be inited |
1134 | * before enabling the engine | 1158 | * before enabling the engine |
@@ -1146,7 +1170,7 @@ void dma_txsuspend(struct dma_pub *pub) | |||
1146 | if (di->ntxd == 0) | 1170 | if (di->ntxd == 0) |
1147 | return; | 1171 | return; |
1148 | 1172 | ||
1149 | OR_REG(&di->d64txregs->control, D64_XC_SE); | 1173 | bcma_set32(di->core, DMA64TXREGOFFS(di, control), D64_XC_SE); |
1150 | } | 1174 | } |
1151 | 1175 | ||
1152 | void dma_txresume(struct dma_pub *pub) | 1176 | void dma_txresume(struct dma_pub *pub) |
@@ -1158,7 +1182,7 @@ void dma_txresume(struct dma_pub *pub) | |||
1158 | if (di->ntxd == 0) | 1182 | if (di->ntxd == 0) |
1159 | return; | 1183 | return; |
1160 | 1184 | ||
1161 | AND_REG(&di->d64txregs->control, ~D64_XC_SE); | 1185 | bcma_mask32(di->core, DMA64TXREGOFFS(di, control), ~D64_XC_SE); |
1162 | } | 1186 | } |
1163 | 1187 | ||
1164 | bool dma_txsuspended(struct dma_pub *pub) | 1188 | bool dma_txsuspended(struct dma_pub *pub) |
@@ -1166,8 +1190,9 @@ bool dma_txsuspended(struct dma_pub *pub) | |||
1166 | struct dma_info *di = (struct dma_info *)pub; | 1190 | struct dma_info *di = (struct dma_info *)pub; |
1167 | 1191 | ||
1168 | return (di->ntxd == 0) || | 1192 | return (di->ntxd == 0) || |
1169 | ((R_REG(&di->d64txregs->control) & D64_XC_SE) == | 1193 | ((bcma_read32(di->core, |
1170 | D64_XC_SE); | 1194 | DMA64TXREGOFFS(di, control)) & D64_XC_SE) == |
1195 | D64_XC_SE); | ||
1171 | } | 1196 | } |
1172 | 1197 | ||
1173 | void dma_txreclaim(struct dma_pub *pub, enum txd_range range) | 1198 | void dma_txreclaim(struct dma_pub *pub, enum txd_range range) |
@@ -1200,16 +1225,17 @@ bool dma_txreset(struct dma_pub *pub) | |||
1200 | return true; | 1225 | return true; |
1201 | 1226 | ||
1202 | /* suspend tx DMA first */ | 1227 | /* suspend tx DMA first */ |
1203 | W_REG(&di->d64txregs->control, D64_XC_SE); | 1228 | bcma_write32(di->core, DMA64TXREGOFFS(di, control), D64_XC_SE); |
1204 | SPINWAIT(((status = | 1229 | SPINWAIT(((status = |
1205 | (R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK)) | 1230 | (bcma_read32(di->core, DMA64TXREGOFFS(di, status0)) & |
1206 | != D64_XS0_XS_DISABLED) && (status != D64_XS0_XS_IDLE) | 1231 | D64_XS0_XS_MASK)) != D64_XS0_XS_DISABLED) && |
1207 | && (status != D64_XS0_XS_STOPPED), 10000); | 1232 | (status != D64_XS0_XS_IDLE) && (status != D64_XS0_XS_STOPPED), |
1233 | 10000); | ||
1208 | 1234 | ||
1209 | W_REG(&di->d64txregs->control, 0); | 1235 | bcma_write32(di->core, DMA64TXREGOFFS(di, control), 0); |
1210 | SPINWAIT(((status = | 1236 | SPINWAIT(((status = |
1211 | (R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK)) | 1237 | (bcma_read32(di->core, DMA64TXREGOFFS(di, status0)) & |
1212 | != D64_XS0_XS_DISABLED), 10000); | 1238 | D64_XS0_XS_MASK)) != D64_XS0_XS_DISABLED), 10000); |
1213 | 1239 | ||
1214 | /* wait for the last transaction to complete */ | 1240 | /* wait for the last transaction to complete */ |
1215 | udelay(300); | 1241 | udelay(300); |
@@ -1225,10 +1251,10 @@ bool dma_rxreset(struct dma_pub *pub) | |||
1225 | if (di->nrxd == 0) | 1251 | if (di->nrxd == 0) |
1226 | return true; | 1252 | return true; |
1227 | 1253 | ||
1228 | W_REG(&di->d64rxregs->control, 0); | 1254 | bcma_write32(di->core, DMA64RXREGOFFS(di, control), 0); |
1229 | SPINWAIT(((status = | 1255 | SPINWAIT(((status = |
1230 | (R_REG(&di->d64rxregs->status0) & D64_RS0_RS_MASK)) | 1256 | (bcma_read32(di->core, DMA64RXREGOFFS(di, status0)) & |
1231 | != D64_RS0_RS_DISABLED), 10000); | 1257 | D64_RS0_RS_MASK)) != D64_RS0_RS_DISABLED), 10000); |
1232 | 1258 | ||
1233 | return status == D64_RS0_RS_DISABLED; | 1259 | return status == D64_RS0_RS_DISABLED; |
1234 | } | 1260 | } |
@@ -1267,7 +1293,7 @@ int dma_txfast(struct dma_pub *pub, struct sk_buff *p, bool commit) | |||
1267 | goto outoftxd; | 1293 | goto outoftxd; |
1268 | 1294 | ||
1269 | /* get physical address of buffer start */ | 1295 | /* get physical address of buffer start */ |
1270 | pa = pci_map_single(di->pbus, data, len, PCI_DMA_TODEVICE); | 1296 | pa = dma_map_single(di->dmadev, data, len, DMA_TO_DEVICE); |
1271 | 1297 | ||
1272 | /* With a DMA segment list, Descriptor table is filled | 1298 | /* With a DMA segment list, Descriptor table is filled |
1273 | * using the segment list instead of looping over | 1299 | * using the segment list instead of looping over |
@@ -1290,7 +1316,7 @@ int dma_txfast(struct dma_pub *pub, struct sk_buff *p, bool commit) | |||
1290 | 1316 | ||
1291 | /* kick the chip */ | 1317 | /* kick the chip */ |
1292 | if (commit) | 1318 | if (commit) |
1293 | W_REG(&di->d64txregs->ptr, | 1319 | bcma_write32(di->core, DMA64TXREGOFFS(di, ptr), |
1294 | di->xmtptrbase + I2B(txout, struct dma64desc)); | 1320 | di->xmtptrbase + I2B(txout, struct dma64desc)); |
1295 | 1321 | ||
1296 | /* tx flow control */ | 1322 | /* tx flow control */ |
@@ -1338,16 +1364,15 @@ struct sk_buff *dma_getnexttxp(struct dma_pub *pub, enum txd_range range) | |||
1338 | if (range == DMA_RANGE_ALL) | 1364 | if (range == DMA_RANGE_ALL) |
1339 | end = di->txout; | 1365 | end = di->txout; |
1340 | else { | 1366 | else { |
1341 | struct dma64regs __iomem *dregs = di->d64txregs; | 1367 | end = (u16) (B2I(((bcma_read32(di->core, |
1342 | 1368 | DMA64TXREGOFFS(di, status0)) & | |
1343 | end = (u16) (B2I(((R_REG(&dregs->status0) & | 1369 | D64_XS0_CD_MASK) - di->xmtptrbase) & |
1344 | D64_XS0_CD_MASK) - | 1370 | D64_XS0_CD_MASK, struct dma64desc)); |
1345 | di->xmtptrbase) & D64_XS0_CD_MASK, | ||
1346 | struct dma64desc)); | ||
1347 | 1371 | ||
1348 | if (range == DMA_RANGE_TRANSFERED) { | 1372 | if (range == DMA_RANGE_TRANSFERED) { |
1349 | active_desc = | 1373 | active_desc = |
1350 | (u16) (R_REG(&dregs->status1) & | 1374 | (u16)(bcma_read32(di->core, |
1375 | DMA64TXREGOFFS(di, status1)) & | ||
1351 | D64_XS1_AD_MASK); | 1376 | D64_XS1_AD_MASK); |
1352 | active_desc = | 1377 | active_desc = |
1353 | (active_desc - di->xmtptrbase) & D64_XS0_CD_MASK; | 1378 | (active_desc - di->xmtptrbase) & D64_XS0_CD_MASK; |
@@ -1376,7 +1401,7 @@ struct sk_buff *dma_getnexttxp(struct dma_pub *pub, enum txd_range range) | |||
1376 | txp = di->txp[i]; | 1401 | txp = di->txp[i]; |
1377 | di->txp[i] = NULL; | 1402 | di->txp[i] = NULL; |
1378 | 1403 | ||
1379 | pci_unmap_single(di->pbus, pa, size, PCI_DMA_TODEVICE); | 1404 | dma_unmap_single(di->dmadev, pa, size, DMA_TO_DEVICE); |
1380 | } | 1405 | } |
1381 | 1406 | ||
1382 | di->txin = i; | 1407 | di->txin = i; |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/dma.h b/drivers/net/wireless/brcm80211/brcmsmac/dma.h index d317c7c12f91..cc269ee5c499 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/dma.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/dma.h | |||
@@ -75,10 +75,11 @@ struct dma_pub { | |||
75 | }; | 75 | }; |
76 | 76 | ||
77 | extern struct dma_pub *dma_attach(char *name, struct si_pub *sih, | 77 | extern struct dma_pub *dma_attach(char *name, struct si_pub *sih, |
78 | void __iomem *dmaregstx, void __iomem *dmaregsrx, | 78 | struct bcma_device *d11core, |
79 | uint ntxd, uint nrxd, | 79 | uint txregbase, uint rxregbase, |
80 | uint rxbufsize, int rxextheadroom, | 80 | uint ntxd, uint nrxd, |
81 | uint nrxpost, uint rxoffset, uint *msg_level); | 81 | uint rxbufsize, int rxextheadroom, |
82 | uint nrxpost, uint rxoffset, uint *msg_level); | ||
82 | 83 | ||
83 | void dma_rxinit(struct dma_pub *pub); | 84 | void dma_rxinit(struct dma_pub *pub); |
84 | int dma_rx(struct dma_pub *pub, struct sk_buff_head *skb_list); | 85 | int dma_rx(struct dma_pub *pub, struct sk_buff_head *skb_list); |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index 76376eb112fe..77fdc45b43ef 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | |||
@@ -17,11 +17,11 @@ | |||
17 | #define __UNDEF_NO_VERSION__ | 17 | #define __UNDEF_NO_VERSION__ |
18 | 18 | ||
19 | #include <linux/etherdevice.h> | 19 | #include <linux/etherdevice.h> |
20 | #include <linux/pci.h> | ||
21 | #include <linux/sched.h> | 20 | #include <linux/sched.h> |
22 | #include <linux/firmware.h> | 21 | #include <linux/firmware.h> |
23 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
24 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/bcma/bcma.h> | ||
25 | #include <net/mac80211.h> | 25 | #include <net/mac80211.h> |
26 | #include <defs.h> | 26 | #include <defs.h> |
27 | #include "nicpci.h" | 27 | #include "nicpci.h" |
@@ -87,16 +87,14 @@ MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN driver."); | |||
87 | MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN cards"); | 87 | MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN cards"); |
88 | MODULE_LICENSE("Dual BSD/GPL"); | 88 | MODULE_LICENSE("Dual BSD/GPL"); |
89 | 89 | ||
90 | /* recognized PCI IDs */ | ||
91 | static DEFINE_PCI_DEVICE_TABLE(brcms_pci_id_table) = { | ||
92 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) }, /* 43225 2G */ | ||
93 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) }, /* 43224 DUAL */ | ||
94 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, /* 4313 DUAL */ | ||
95 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, /* 43224 Ven */ | ||
96 | {0} | ||
97 | }; | ||
98 | 90 | ||
99 | MODULE_DEVICE_TABLE(pci, brcms_pci_id_table); | 91 | /* recognized BCMA Core IDs */ |
92 | static struct bcma_device_id brcms_coreid_table[] = { | ||
93 | BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 23, BCMA_ANY_CLASS), | ||
94 | BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 24, BCMA_ANY_CLASS), | ||
95 | BCMA_CORETABLE_END | ||
96 | }; | ||
97 | MODULE_DEVICE_TABLE(bcma, brcms_coreid_table); | ||
100 | 98 | ||
101 | #ifdef BCMDBG | 99 | #ifdef BCMDBG |
102 | static int msglevel = 0xdeadbeef; | 100 | static int msglevel = 0xdeadbeef; |
@@ -724,7 +722,7 @@ static const struct ieee80211_ops brcms_ops = { | |||
724 | }; | 722 | }; |
725 | 723 | ||
726 | /* | 724 | /* |
727 | * is called in brcms_pci_probe() context, therefore no locking required. | 725 | * is called in brcms_bcma_probe() context, therefore no locking required. |
728 | */ | 726 | */ |
729 | static int brcms_set_hint(struct brcms_info *wl, char *abbrev) | 727 | static int brcms_set_hint(struct brcms_info *wl, char *abbrev) |
730 | { | 728 | { |
@@ -864,25 +862,15 @@ static void brcms_free(struct brcms_info *wl) | |||
864 | #endif | 862 | #endif |
865 | kfree(t); | 863 | kfree(t); |
866 | } | 864 | } |
867 | |||
868 | /* | ||
869 | * unregister_netdev() calls get_stats() which may read chip | ||
870 | * registers so we cannot unmap the chip registers until | ||
871 | * after calling unregister_netdev() . | ||
872 | */ | ||
873 | if (wl->regsva) | ||
874 | iounmap(wl->regsva); | ||
875 | |||
876 | wl->regsva = NULL; | ||
877 | } | 865 | } |
878 | 866 | ||
879 | /* | 867 | /* |
880 | * called from both kernel as from this kernel module (error flow on attach) | 868 | * called from both kernel as from this kernel module (error flow on attach) |
881 | * precondition: perimeter lock is not acquired. | 869 | * precondition: perimeter lock is not acquired. |
882 | */ | 870 | */ |
883 | static void brcms_remove(struct pci_dev *pdev) | 871 | static void brcms_remove(struct bcma_device *pdev) |
884 | { | 872 | { |
885 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | 873 | struct ieee80211_hw *hw = bcma_get_drvdata(pdev); |
886 | struct brcms_info *wl = hw->priv; | 874 | struct brcms_info *wl = hw->priv; |
887 | 875 | ||
888 | if (wl->wlc) { | 876 | if (wl->wlc) { |
@@ -890,11 +878,10 @@ static void brcms_remove(struct pci_dev *pdev) | |||
890 | wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy); | 878 | wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy); |
891 | ieee80211_unregister_hw(hw); | 879 | ieee80211_unregister_hw(hw); |
892 | } | 880 | } |
893 | pci_disable_device(pdev); | ||
894 | 881 | ||
895 | brcms_free(wl); | 882 | brcms_free(wl); |
896 | 883 | ||
897 | pci_set_drvdata(pdev, NULL); | 884 | bcma_set_drvdata(pdev, NULL); |
898 | ieee80211_free_hw(hw); | 885 | ieee80211_free_hw(hw); |
899 | } | 886 | } |
900 | 887 | ||
@@ -1002,11 +989,9 @@ static int ieee_hw_init(struct ieee80211_hw *hw) | |||
1002 | * it as static. | 989 | * it as static. |
1003 | * | 990 | * |
1004 | * | 991 | * |
1005 | * is called in brcms_pci_probe() context, therefore no locking required. | 992 | * is called in brcms_bcma_probe() context, therefore no locking required. |
1006 | */ | 993 | */ |
1007 | static struct brcms_info *brcms_attach(u16 vendor, u16 device, | 994 | static struct brcms_info *brcms_attach(struct bcma_device *pdev) |
1008 | resource_size_t regs, | ||
1009 | struct pci_dev *btparam, uint irq) | ||
1010 | { | 995 | { |
1011 | struct brcms_info *wl = NULL; | 996 | struct brcms_info *wl = NULL; |
1012 | int unit, err; | 997 | int unit, err; |
@@ -1020,7 +1005,7 @@ static struct brcms_info *brcms_attach(u16 vendor, u16 device, | |||
1020 | return NULL; | 1005 | return NULL; |
1021 | 1006 | ||
1022 | /* allocate private info */ | 1007 | /* allocate private info */ |
1023 | hw = pci_get_drvdata(btparam); /* btparam == pdev */ | 1008 | hw = bcma_get_drvdata(pdev); |
1024 | if (hw != NULL) | 1009 | if (hw != NULL) |
1025 | wl = hw->priv; | 1010 | wl = hw->priv; |
1026 | if (WARN_ON(hw == NULL) || WARN_ON(wl == NULL)) | 1011 | if (WARN_ON(hw == NULL) || WARN_ON(wl == NULL)) |
@@ -1032,26 +1017,20 @@ static struct brcms_info *brcms_attach(u16 vendor, u16 device, | |||
1032 | /* setup the bottom half handler */ | 1017 | /* setup the bottom half handler */ |
1033 | tasklet_init(&wl->tasklet, brcms_dpc, (unsigned long) wl); | 1018 | tasklet_init(&wl->tasklet, brcms_dpc, (unsigned long) wl); |
1034 | 1019 | ||
1035 | wl->regsva = ioremap_nocache(regs, PCI_BAR0_WINSZ); | ||
1036 | if (wl->regsva == NULL) { | ||
1037 | wiphy_err(wl->wiphy, "wl%d: ioremap() failed\n", unit); | ||
1038 | goto fail; | ||
1039 | } | ||
1040 | spin_lock_init(&wl->lock); | 1020 | spin_lock_init(&wl->lock); |
1041 | spin_lock_init(&wl->isr_lock); | 1021 | spin_lock_init(&wl->isr_lock); |
1042 | 1022 | ||
1043 | /* prepare ucode */ | 1023 | /* prepare ucode */ |
1044 | if (brcms_request_fw(wl, btparam) < 0) { | 1024 | if (brcms_request_fw(wl, pdev->bus->host_pci) < 0) { |
1045 | wiphy_err(wl->wiphy, "%s: Failed to find firmware usually in " | 1025 | wiphy_err(wl->wiphy, "%s: Failed to find firmware usually in " |
1046 | "%s\n", KBUILD_MODNAME, "/lib/firmware/brcm"); | 1026 | "%s\n", KBUILD_MODNAME, "/lib/firmware/brcm"); |
1047 | brcms_release_fw(wl); | 1027 | brcms_release_fw(wl); |
1048 | brcms_remove(btparam); | 1028 | brcms_remove(pdev); |
1049 | return NULL; | 1029 | return NULL; |
1050 | } | 1030 | } |
1051 | 1031 | ||
1052 | /* common load-time initialization */ | 1032 | /* common load-time initialization */ |
1053 | wl->wlc = brcms_c_attach(wl, vendor, device, unit, false, | 1033 | wl->wlc = brcms_c_attach((void *)wl, pdev, unit, false, &err); |
1054 | wl->regsva, btparam, &err); | ||
1055 | brcms_release_fw(wl); | 1034 | brcms_release_fw(wl); |
1056 | if (!wl->wlc) { | 1035 | if (!wl->wlc) { |
1057 | wiphy_err(wl->wiphy, "%s: attach() failed with code %d\n", | 1036 | wiphy_err(wl->wiphy, "%s: attach() failed with code %d\n", |
@@ -1063,11 +1042,12 @@ static struct brcms_info *brcms_attach(u16 vendor, u16 device, | |||
1063 | wl->pub->ieee_hw = hw; | 1042 | wl->pub->ieee_hw = hw; |
1064 | 1043 | ||
1065 | /* register our interrupt handler */ | 1044 | /* register our interrupt handler */ |
1066 | if (request_irq(irq, brcms_isr, IRQF_SHARED, KBUILD_MODNAME, wl)) { | 1045 | if (request_irq(pdev->bus->host_pci->irq, brcms_isr, |
1046 | IRQF_SHARED, KBUILD_MODNAME, wl)) { | ||
1067 | wiphy_err(wl->wiphy, "wl%d: request_irq() failed\n", unit); | 1047 | wiphy_err(wl->wiphy, "wl%d: request_irq() failed\n", unit); |
1068 | goto fail; | 1048 | goto fail; |
1069 | } | 1049 | } |
1070 | wl->irq = irq; | 1050 | wl->irq = pdev->bus->host_pci->irq; |
1071 | 1051 | ||
1072 | /* register module */ | 1052 | /* register module */ |
1073 | brcms_c_module_register(wl->pub, "linux", wl, NULL); | 1053 | brcms_c_module_register(wl->pub, "linux", wl, NULL); |
@@ -1114,37 +1094,18 @@ fail: | |||
1114 | * | 1094 | * |
1115 | * Perimeter lock is initialized in the course of this function. | 1095 | * Perimeter lock is initialized in the course of this function. |
1116 | */ | 1096 | */ |
1117 | static int __devinit | 1097 | static int __devinit brcms_bcma_probe(struct bcma_device *pdev) |
1118 | brcms_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | ||
1119 | { | 1098 | { |
1120 | int rc; | ||
1121 | struct brcms_info *wl; | 1099 | struct brcms_info *wl; |
1122 | struct ieee80211_hw *hw; | 1100 | struct ieee80211_hw *hw; |
1123 | u32 val; | ||
1124 | |||
1125 | dev_info(&pdev->dev, "bus %d slot %d func %d irq %d\n", | ||
1126 | pdev->bus->number, PCI_SLOT(pdev->devfn), | ||
1127 | PCI_FUNC(pdev->devfn), pdev->irq); | ||
1128 | 1101 | ||
1129 | if ((pdev->vendor != PCI_VENDOR_ID_BROADCOM) || | 1102 | dev_info(&pdev->dev, "mfg %x core %x rev %d class %d irq %d\n", |
1130 | ((pdev->device != 0x0576) && | 1103 | pdev->id.manuf, pdev->id.id, pdev->id.rev, pdev->id.class, |
1131 | ((pdev->device & 0xff00) != 0x4300) && | 1104 | pdev->bus->host_pci->irq); |
1132 | ((pdev->device & 0xff00) != 0x4700) && | ||
1133 | ((pdev->device < 43000) || (pdev->device > 43999)))) | ||
1134 | return -ENODEV; | ||
1135 | 1105 | ||
1136 | rc = pci_enable_device(pdev); | 1106 | if ((pdev->id.manuf != BCMA_MANUF_BCM) || |
1137 | if (rc) { | 1107 | (pdev->id.id != BCMA_CORE_80211)) |
1138 | pr_err("%s: Cannot enable device %d-%d_%d\n", | ||
1139 | __func__, pdev->bus->number, PCI_SLOT(pdev->devfn), | ||
1140 | PCI_FUNC(pdev->devfn)); | ||
1141 | return -ENODEV; | 1108 | return -ENODEV; |
1142 | } | ||
1143 | pci_set_master(pdev); | ||
1144 | |||
1145 | pci_read_config_dword(pdev, 0x40, &val); | ||
1146 | if ((val & 0x0000ff00) != 0) | ||
1147 | pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); | ||
1148 | 1109 | ||
1149 | hw = ieee80211_alloc_hw(sizeof(struct brcms_info), &brcms_ops); | 1110 | hw = ieee80211_alloc_hw(sizeof(struct brcms_info), &brcms_ops); |
1150 | if (!hw) { | 1111 | if (!hw) { |
@@ -1154,14 +1115,11 @@ brcms_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1154 | 1115 | ||
1155 | SET_IEEE80211_DEV(hw, &pdev->dev); | 1116 | SET_IEEE80211_DEV(hw, &pdev->dev); |
1156 | 1117 | ||
1157 | pci_set_drvdata(pdev, hw); | 1118 | bcma_set_drvdata(pdev, hw); |
1158 | 1119 | ||
1159 | memset(hw->priv, 0, sizeof(*wl)); | 1120 | memset(hw->priv, 0, sizeof(*wl)); |
1160 | 1121 | ||
1161 | wl = brcms_attach(pdev->vendor, pdev->device, | 1122 | wl = brcms_attach(pdev); |
1162 | pci_resource_start(pdev, 0), pdev, | ||
1163 | pdev->irq); | ||
1164 | |||
1165 | if (!wl) { | 1123 | if (!wl) { |
1166 | pr_err("%s: %s: brcms_attach failed!\n", KBUILD_MODNAME, | 1124 | pr_err("%s: %s: brcms_attach failed!\n", KBUILD_MODNAME, |
1167 | __func__); | 1125 | __func__); |
@@ -1170,16 +1128,23 @@ brcms_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1170 | return 0; | 1128 | return 0; |
1171 | } | 1129 | } |
1172 | 1130 | ||
1173 | static int brcms_suspend(struct pci_dev *pdev, pm_message_t state) | 1131 | static int brcms_pci_suspend(struct pci_dev *pdev) |
1132 | { | ||
1133 | pci_save_state(pdev); | ||
1134 | pci_disable_device(pdev); | ||
1135 | return pci_set_power_state(pdev, PCI_D3hot); | ||
1136 | } | ||
1137 | |||
1138 | static int brcms_suspend(struct bcma_device *pdev, pm_message_t state) | ||
1174 | { | 1139 | { |
1175 | struct brcms_info *wl; | 1140 | struct brcms_info *wl; |
1176 | struct ieee80211_hw *hw; | 1141 | struct ieee80211_hw *hw; |
1177 | 1142 | ||
1178 | hw = pci_get_drvdata(pdev); | 1143 | hw = bcma_get_drvdata(pdev); |
1179 | wl = hw->priv; | 1144 | wl = hw->priv; |
1180 | if (!wl) { | 1145 | if (!wl) { |
1181 | wiphy_err(wl->wiphy, | 1146 | wiphy_err(wl->wiphy, |
1182 | "brcms_suspend: pci_get_drvdata failed\n"); | 1147 | "brcms_suspend: bcma_get_drvdata failed\n"); |
1183 | return -ENODEV; | 1148 | return -ENODEV; |
1184 | } | 1149 | } |
1185 | 1150 | ||
@@ -1188,25 +1153,14 @@ static int brcms_suspend(struct pci_dev *pdev, pm_message_t state) | |||
1188 | wl->pub->hw_up = false; | 1153 | wl->pub->hw_up = false; |
1189 | spin_unlock_bh(&wl->lock); | 1154 | spin_unlock_bh(&wl->lock); |
1190 | 1155 | ||
1191 | pci_save_state(pdev); | 1156 | /* temporarily do suspend ourselves */ |
1192 | pci_disable_device(pdev); | 1157 | return brcms_pci_suspend(pdev->bus->host_pci); |
1193 | return pci_set_power_state(pdev, PCI_D3hot); | ||
1194 | } | 1158 | } |
1195 | 1159 | ||
1196 | static int brcms_resume(struct pci_dev *pdev) | 1160 | static int brcms_pci_resume(struct pci_dev *pdev) |
1197 | { | 1161 | { |
1198 | struct brcms_info *wl; | ||
1199 | struct ieee80211_hw *hw; | ||
1200 | int err = 0; | 1162 | int err = 0; |
1201 | u32 val; | 1163 | uint val; |
1202 | |||
1203 | hw = pci_get_drvdata(pdev); | ||
1204 | wl = hw->priv; | ||
1205 | if (!wl) { | ||
1206 | wiphy_err(wl->wiphy, | ||
1207 | "wl: brcms_resume: pci_get_drvdata failed\n"); | ||
1208 | return -ENODEV; | ||
1209 | } | ||
1210 | 1164 | ||
1211 | err = pci_set_power_state(pdev, PCI_D0); | 1165 | err = pci_set_power_state(pdev, PCI_D0); |
1212 | if (err) | 1166 | if (err) |
@@ -1224,24 +1178,28 @@ static int brcms_resume(struct pci_dev *pdev) | |||
1224 | if ((val & 0x0000ff00) != 0) | 1178 | if ((val & 0x0000ff00) != 0) |
1225 | pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); | 1179 | pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); |
1226 | 1180 | ||
1181 | return 0; | ||
1182 | } | ||
1183 | |||
1184 | static int brcms_resume(struct bcma_device *pdev) | ||
1185 | { | ||
1227 | /* | 1186 | /* |
1228 | * done. driver will be put in up state | 1187 | * just do pci resume for now until bcma supports it. |
1229 | * in brcms_ops_add_interface() call. | ||
1230 | */ | 1188 | */ |
1231 | return err; | 1189 | return brcms_pci_resume(pdev->bus->host_pci); |
1232 | } | 1190 | } |
1233 | 1191 | ||
1234 | static struct pci_driver brcms_pci_driver = { | 1192 | static struct bcma_driver brcms_bcma_driver = { |
1235 | .name = KBUILD_MODNAME, | 1193 | .name = KBUILD_MODNAME, |
1236 | .probe = brcms_pci_probe, | 1194 | .probe = brcms_bcma_probe, |
1237 | .suspend = brcms_suspend, | 1195 | .suspend = brcms_suspend, |
1238 | .resume = brcms_resume, | 1196 | .resume = brcms_resume, |
1239 | .remove = __devexit_p(brcms_remove), | 1197 | .remove = __devexit_p(brcms_remove), |
1240 | .id_table = brcms_pci_id_table, | 1198 | .id_table = brcms_coreid_table, |
1241 | }; | 1199 | }; |
1242 | 1200 | ||
1243 | /** | 1201 | /** |
1244 | * This is the main entry point for the WL driver. | 1202 | * This is the main entry point for the brcmsmac driver. |
1245 | * | 1203 | * |
1246 | * This function determines if a device pointed to by pdev is a WL device, | 1204 | * This function determines if a device pointed to by pdev is a WL device, |
1247 | * and if so, performs a brcms_attach() on it. | 1205 | * and if so, performs a brcms_attach() on it. |
@@ -1256,26 +1214,24 @@ static int __init brcms_module_init(void) | |||
1256 | brcm_msg_level = msglevel; | 1214 | brcm_msg_level = msglevel; |
1257 | #endif /* BCMDBG */ | 1215 | #endif /* BCMDBG */ |
1258 | 1216 | ||
1259 | error = pci_register_driver(&brcms_pci_driver); | 1217 | error = bcma_driver_register(&brcms_bcma_driver); |
1218 | printk(KERN_ERR "%s: register returned %d\n", __func__, error); | ||
1260 | if (!error) | 1219 | if (!error) |
1261 | return 0; | 1220 | return 0; |
1262 | 1221 | ||
1263 | |||
1264 | |||
1265 | return error; | 1222 | return error; |
1266 | } | 1223 | } |
1267 | 1224 | ||
1268 | /** | 1225 | /** |
1269 | * This function unloads the WL driver from the system. | 1226 | * This function unloads the brcmsmac driver from the system. |
1270 | * | 1227 | * |
1271 | * This function unconditionally unloads the WL driver module from the | 1228 | * This function unconditionally unloads the brcmsmac driver module from the |
1272 | * system. | 1229 | * system. |
1273 | * | 1230 | * |
1274 | */ | 1231 | */ |
1275 | static void __exit brcms_module_exit(void) | 1232 | static void __exit brcms_module_exit(void) |
1276 | { | 1233 | { |
1277 | pci_unregister_driver(&brcms_pci_driver); | 1234 | bcma_driver_unregister(&brcms_bcma_driver); |
1278 | |||
1279 | } | 1235 | } |
1280 | 1236 | ||
1281 | module_init(brcms_module_init); | 1237 | module_init(brcms_module_init); |
@@ -1562,7 +1518,7 @@ fail: | |||
1562 | } | 1518 | } |
1563 | 1519 | ||
1564 | /* | 1520 | /* |
1565 | * Precondition: Since this function is called in brcms_pci_probe() context, | 1521 | * Precondition: Since this function is called in brcms_bcma_probe() context, |
1566 | * no locking is required. | 1522 | * no locking is required. |
1567 | */ | 1523 | */ |
1568 | int brcms_ucode_init_uint(struct brcms_info *wl, size_t *n_bytes, u32 idx) | 1524 | int brcms_ucode_init_uint(struct brcms_info *wl, size_t *n_bytes, u32 idx) |
@@ -1602,7 +1558,7 @@ void brcms_ucode_free_buf(void *p) | |||
1602 | /* | 1558 | /* |
1603 | * checks validity of all firmware images loaded from user space | 1559 | * checks validity of all firmware images loaded from user space |
1604 | * | 1560 | * |
1605 | * Precondition: Since this function is called in brcms_pci_probe() context, | 1561 | * Precondition: Since this function is called in brcms_bcma_probe() context, |
1606 | * no locking is required. | 1562 | * no locking is required. |
1607 | */ | 1563 | */ |
1608 | int brcms_check_firmwares(struct brcms_info *wl) | 1564 | int brcms_check_firmwares(struct brcms_info *wl) |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h index 6242f188b717..8f60419c37bf 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h | |||
@@ -68,8 +68,6 @@ struct brcms_info { | |||
68 | spinlock_t lock; /* per-device perimeter lock */ | 68 | spinlock_t lock; /* per-device perimeter lock */ |
69 | spinlock_t isr_lock; /* per-device ISR synchronization lock */ | 69 | spinlock_t isr_lock; /* per-device ISR synchronization lock */ |
70 | 70 | ||
71 | /* regsva for unmap in brcms_free() */ | ||
72 | void __iomem *regsva; /* opaque chip registers virtual address */ | ||
73 | 71 | ||
74 | /* timer related fields */ | 72 | /* timer related fields */ |
75 | atomic_t callbacks; /* # outstanding callback functions */ | 73 | atomic_t callbacks; /* # outstanding callback functions */ |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c index 87f8f5d3d91f..f7ed34034f88 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c | |||
@@ -388,10 +388,13 @@ static u16 get_sifs(struct brcms_band *band) | |||
388 | */ | 388 | */ |
389 | static bool brcms_deviceremoved(struct brcms_c_info *wlc) | 389 | static bool brcms_deviceremoved(struct brcms_c_info *wlc) |
390 | { | 390 | { |
391 | u32 macctrl; | ||
392 | |||
391 | if (!wlc->hw->clk) | 393 | if (!wlc->hw->clk) |
392 | return ai_deviceremoved(wlc->hw->sih); | 394 | return ai_deviceremoved(wlc->hw->sih); |
393 | return (R_REG(&wlc->hw->regs->maccontrol) & | 395 | macctrl = bcma_read32(wlc->hw->d11core, |
394 | (MCTL_PSM_JMP_0 | MCTL_IHR_EN)) != MCTL_IHR_EN; | 396 | D11REGOFFS(maccontrol)); |
397 | return (macctrl & (MCTL_PSM_JMP_0 | MCTL_IHR_EN)) != MCTL_IHR_EN; | ||
395 | } | 398 | } |
396 | 399 | ||
397 | /* sum the individual fifo tx pending packet counts */ | 400 | /* sum the individual fifo tx pending packet counts */ |
@@ -582,17 +585,15 @@ brcms_c_attach_malloc(uint unit, uint *err, uint devid) | |||
582 | static void brcms_b_update_slot_timing(struct brcms_hardware *wlc_hw, | 585 | static void brcms_b_update_slot_timing(struct brcms_hardware *wlc_hw, |
583 | bool shortslot) | 586 | bool shortslot) |
584 | { | 587 | { |
585 | struct d11regs __iomem *regs; | 588 | struct bcma_device *core = wlc_hw->d11core; |
586 | |||
587 | regs = wlc_hw->regs; | ||
588 | 589 | ||
589 | if (shortslot) { | 590 | if (shortslot) { |
590 | /* 11g short slot: 11a timing */ | 591 | /* 11g short slot: 11a timing */ |
591 | W_REG(®s->ifs_slot, 0x0207); /* APHY_SLOT_TIME */ | 592 | bcma_write16(core, D11REGOFFS(ifs_slot), 0x0207); |
592 | brcms_b_write_shm(wlc_hw, M_DOT11_SLOT, APHY_SLOT_TIME); | 593 | brcms_b_write_shm(wlc_hw, M_DOT11_SLOT, APHY_SLOT_TIME); |
593 | } else { | 594 | } else { |
594 | /* 11g long slot: 11b timing */ | 595 | /* 11g long slot: 11b timing */ |
595 | W_REG(®s->ifs_slot, 0x0212); /* BPHY_SLOT_TIME */ | 596 | bcma_write16(core, D11REGOFFS(ifs_slot), 0x0212); |
596 | brcms_b_write_shm(wlc_hw, M_DOT11_SLOT, BPHY_SLOT_TIME); | 597 | brcms_b_write_shm(wlc_hw, M_DOT11_SLOT, BPHY_SLOT_TIME); |
597 | } | 598 | } |
598 | } | 599 | } |
@@ -672,24 +673,22 @@ static uint brcms_c_calc_frame_time(struct brcms_c_info *wlc, u32 ratespec, | |||
672 | static void brcms_c_write_inits(struct brcms_hardware *wlc_hw, | 673 | static void brcms_c_write_inits(struct brcms_hardware *wlc_hw, |
673 | const struct d11init *inits) | 674 | const struct d11init *inits) |
674 | { | 675 | { |
676 | struct bcma_device *core = wlc_hw->d11core; | ||
675 | int i; | 677 | int i; |
676 | u8 __iomem *base; | 678 | uint offset; |
677 | u8 __iomem *addr; | ||
678 | u16 size; | 679 | u16 size; |
679 | u32 value; | 680 | u32 value; |
680 | 681 | ||
681 | BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); | 682 | BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); |
682 | 683 | ||
683 | base = (u8 __iomem *)wlc_hw->regs; | ||
684 | |||
685 | for (i = 0; inits[i].addr != cpu_to_le16(0xffff); i++) { | 684 | for (i = 0; inits[i].addr != cpu_to_le16(0xffff); i++) { |
686 | size = le16_to_cpu(inits[i].size); | 685 | size = le16_to_cpu(inits[i].size); |
687 | addr = base + le16_to_cpu(inits[i].addr); | 686 | offset = le16_to_cpu(inits[i].addr); |
688 | value = le32_to_cpu(inits[i].value); | 687 | value = le32_to_cpu(inits[i].value); |
689 | if (size == 2) | 688 | if (size == 2) |
690 | W_REG((u16 __iomem *)addr, value); | 689 | bcma_write16(core, offset, value); |
691 | else if (size == 4) | 690 | else if (size == 4) |
692 | W_REG((u32 __iomem *)addr, value); | 691 | bcma_write32(core, offset, value); |
693 | else | 692 | else |
694 | break; | 693 | break; |
695 | } | 694 | } |
@@ -739,6 +738,14 @@ static void brcms_c_ucode_bsinit(struct brcms_hardware *wlc_hw) | |||
739 | } | 738 | } |
740 | } | 739 | } |
741 | 740 | ||
741 | static void brcms_b_core_ioctl(struct brcms_hardware *wlc_hw, u32 m, u32 v) | ||
742 | { | ||
743 | struct bcma_device *core = wlc_hw->d11core; | ||
744 | u32 ioctl = bcma_aread32(core, BCMA_IOCTL) & ~m; | ||
745 | |||
746 | bcma_awrite32(core, BCMA_IOCTL, ioctl | v); | ||
747 | } | ||
748 | |||
742 | static void brcms_b_core_phy_clk(struct brcms_hardware *wlc_hw, bool clk) | 749 | static void brcms_b_core_phy_clk(struct brcms_hardware *wlc_hw, bool clk) |
743 | { | 750 | { |
744 | BCMMSG(wlc_hw->wlc->wiphy, "wl%d: clk %d\n", wlc_hw->unit, clk); | 751 | BCMMSG(wlc_hw->wlc->wiphy, "wl%d: clk %d\n", wlc_hw->unit, clk); |
@@ -747,17 +754,17 @@ static void brcms_b_core_phy_clk(struct brcms_hardware *wlc_hw, bool clk) | |||
747 | 754 | ||
748 | if (OFF == clk) { /* clear gmode bit, put phy into reset */ | 755 | if (OFF == clk) { /* clear gmode bit, put phy into reset */ |
749 | 756 | ||
750 | ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC | SICF_GMODE), | 757 | brcms_b_core_ioctl(wlc_hw, (SICF_PRST | SICF_FGC | SICF_GMODE), |
751 | (SICF_PRST | SICF_FGC)); | 758 | (SICF_PRST | SICF_FGC)); |
752 | udelay(1); | 759 | udelay(1); |
753 | ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC), SICF_PRST); | 760 | brcms_b_core_ioctl(wlc_hw, (SICF_PRST | SICF_FGC), SICF_PRST); |
754 | udelay(1); | 761 | udelay(1); |
755 | 762 | ||
756 | } else { /* take phy out of reset */ | 763 | } else { /* take phy out of reset */ |
757 | 764 | ||
758 | ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC), SICF_FGC); | 765 | brcms_b_core_ioctl(wlc_hw, (SICF_PRST | SICF_FGC), SICF_FGC); |
759 | udelay(1); | 766 | udelay(1); |
760 | ai_core_cflags(wlc_hw->sih, (SICF_FGC), 0); | 767 | brcms_b_core_ioctl(wlc_hw, SICF_FGC, 0); |
761 | udelay(1); | 768 | udelay(1); |
762 | 769 | ||
763 | } | 770 | } |
@@ -778,9 +785,14 @@ static void brcms_c_setxband(struct brcms_hardware *wlc_hw, uint bandunit) | |||
778 | wlc_hw->wlc->band = wlc_hw->wlc->bandstate[bandunit]; | 785 | wlc_hw->wlc->band = wlc_hw->wlc->bandstate[bandunit]; |
779 | 786 | ||
780 | /* set gmode core flag */ | 787 | /* set gmode core flag */ |
781 | if (wlc_hw->sbclk && !wlc_hw->noreset) | 788 | if (wlc_hw->sbclk && !wlc_hw->noreset) { |
782 | ai_core_cflags(wlc_hw->sih, SICF_GMODE, | 789 | u32 gmode = 0; |
783 | ((bandunit == 0) ? SICF_GMODE : 0)); | 790 | |
791 | if (bandunit == 0) | ||
792 | gmode = SICF_GMODE; | ||
793 | |||
794 | brcms_b_core_ioctl(wlc_hw, SICF_GMODE, gmode); | ||
795 | } | ||
784 | } | 796 | } |
785 | 797 | ||
786 | /* switch to new band but leave it inactive */ | 798 | /* switch to new band but leave it inactive */ |
@@ -788,10 +800,12 @@ static u32 brcms_c_setband_inact(struct brcms_c_info *wlc, uint bandunit) | |||
788 | { | 800 | { |
789 | struct brcms_hardware *wlc_hw = wlc->hw; | 801 | struct brcms_hardware *wlc_hw = wlc->hw; |
790 | u32 macintmask; | 802 | u32 macintmask; |
803 | u32 macctrl; | ||
791 | 804 | ||
792 | BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit); | 805 | BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit); |
793 | 806 | macctrl = bcma_read32(wlc_hw->d11core, | |
794 | WARN_ON((R_REG(&wlc_hw->regs->maccontrol) & MCTL_EN_MAC) != 0); | 807 | D11REGOFFS(maccontrol)); |
808 | WARN_ON((macctrl & MCTL_EN_MAC) != 0); | ||
795 | 809 | ||
796 | /* disable interrupts */ | 810 | /* disable interrupts */ |
797 | macintmask = brcms_intrsoff(wlc->wl); | 811 | macintmask = brcms_intrsoff(wlc->wl); |
@@ -982,7 +996,7 @@ brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal) | |||
982 | { | 996 | { |
983 | bool morepending = false; | 997 | bool morepending = false; |
984 | struct brcms_c_info *wlc = wlc_hw->wlc; | 998 | struct brcms_c_info *wlc = wlc_hw->wlc; |
985 | struct d11regs __iomem *regs; | 999 | struct bcma_device *core; |
986 | struct tx_status txstatus, *txs; | 1000 | struct tx_status txstatus, *txs; |
987 | u32 s1, s2; | 1001 | u32 s1, s2; |
988 | uint n = 0; | 1002 | uint n = 0; |
@@ -995,18 +1009,18 @@ brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal) | |||
995 | BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit); | 1009 | BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit); |
996 | 1010 | ||
997 | txs = &txstatus; | 1011 | txs = &txstatus; |
998 | regs = wlc_hw->regs; | 1012 | core = wlc_hw->d11core; |
999 | *fatal = false; | 1013 | *fatal = false; |
1014 | s1 = bcma_read32(core, D11REGOFFS(frmtxstatus)); | ||
1000 | while (!(*fatal) | 1015 | while (!(*fatal) |
1001 | && (s1 = R_REG(®s->frmtxstatus)) & TXS_V) { | 1016 | && (s1 & TXS_V)) { |
1002 | 1017 | ||
1003 | if (s1 == 0xffffffff) { | 1018 | if (s1 == 0xffffffff) { |
1004 | wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n", | 1019 | wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n", |
1005 | wlc_hw->unit, __func__); | 1020 | wlc_hw->unit, __func__); |
1006 | return morepending; | 1021 | return morepending; |
1007 | } | 1022 | } |
1008 | 1023 | s2 = bcma_read32(core, D11REGOFFS(frmtxstatus2)); | |
1009 | s2 = R_REG(®s->frmtxstatus2); | ||
1010 | 1024 | ||
1011 | txs->status = s1 & TXS_STATUS_MASK; | 1025 | txs->status = s1 & TXS_STATUS_MASK; |
1012 | txs->frameid = (s1 & TXS_FID_MASK) >> TXS_FID_SHIFT; | 1026 | txs->frameid = (s1 & TXS_FID_MASK) >> TXS_FID_SHIFT; |
@@ -1019,6 +1033,7 @@ brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal) | |||
1019 | /* !give others some time to run! */ | 1033 | /* !give others some time to run! */ |
1020 | if (++n >= max_tx_num) | 1034 | if (++n >= max_tx_num) |
1021 | break; | 1035 | break; |
1036 | s1 = bcma_read32(core, D11REGOFFS(frmtxstatus)); | ||
1022 | } | 1037 | } |
1023 | 1038 | ||
1024 | if (*fatal) | 1039 | if (*fatal) |
@@ -1063,12 +1078,12 @@ brcms_c_mhfdef(struct brcms_c_info *wlc, u16 *mhfs, u16 mhf2_init) | |||
1063 | } | 1078 | } |
1064 | } | 1079 | } |
1065 | 1080 | ||
1066 | static struct dma64regs __iomem * | 1081 | static uint |
1067 | dmareg(struct brcms_hardware *hw, uint direction, uint fifonum) | 1082 | dmareg(uint direction, uint fifonum) |
1068 | { | 1083 | { |
1069 | if (direction == DMA_TX) | 1084 | if (direction == DMA_TX) |
1070 | return &(hw->regs->fifo64regs[fifonum].dmaxmt); | 1085 | return offsetof(struct d11regs, fifo64regs[fifonum].dmaxmt); |
1071 | return &(hw->regs->fifo64regs[fifonum].dmarcv); | 1086 | return offsetof(struct d11regs, fifo64regs[fifonum].dmarcv); |
1072 | } | 1087 | } |
1073 | 1088 | ||
1074 | static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme) | 1089 | static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme) |
@@ -1094,9 +1109,9 @@ static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme) | |||
1094 | * TX: TX_AC_BK_FIFO (TX AC Background data packets) | 1109 | * TX: TX_AC_BK_FIFO (TX AC Background data packets) |
1095 | * RX: RX_FIFO (RX data packets) | 1110 | * RX: RX_FIFO (RX data packets) |
1096 | */ | 1111 | */ |
1097 | wlc_hw->di[0] = dma_attach(name, wlc_hw->sih, | 1112 | wlc_hw->di[0] = dma_attach(name, wlc_hw->sih, wlc_hw->d11core, |
1098 | (wme ? dmareg(wlc_hw, DMA_TX, 0) : | 1113 | (wme ? dmareg(DMA_TX, 0) : 0), |
1099 | NULL), dmareg(wlc_hw, DMA_RX, 0), | 1114 | dmareg(DMA_RX, 0), |
1100 | (wme ? NTXD : 0), NRXD, | 1115 | (wme ? NTXD : 0), NRXD, |
1101 | RXBUFSZ, -1, NRXBUFPOST, | 1116 | RXBUFSZ, -1, NRXBUFPOST, |
1102 | BRCMS_HWRXOFF, &brcm_msg_level); | 1117 | BRCMS_HWRXOFF, &brcm_msg_level); |
@@ -1108,8 +1123,8 @@ static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme) | |||
1108 | * (legacy) TX_DATA_FIFO (TX data packets) | 1123 | * (legacy) TX_DATA_FIFO (TX data packets) |
1109 | * RX: UNUSED | 1124 | * RX: UNUSED |
1110 | */ | 1125 | */ |
1111 | wlc_hw->di[1] = dma_attach(name, wlc_hw->sih, | 1126 | wlc_hw->di[1] = dma_attach(name, wlc_hw->sih, wlc_hw->d11core, |
1112 | dmareg(wlc_hw, DMA_TX, 1), NULL, | 1127 | dmareg(DMA_TX, 1), 0, |
1113 | NTXD, 0, 0, -1, 0, 0, | 1128 | NTXD, 0, 0, -1, 0, 0, |
1114 | &brcm_msg_level); | 1129 | &brcm_msg_level); |
1115 | dma_attach_err |= (NULL == wlc_hw->di[1]); | 1130 | dma_attach_err |= (NULL == wlc_hw->di[1]); |
@@ -1119,8 +1134,8 @@ static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme) | |||
1119 | * TX: TX_AC_VI_FIFO (TX AC Video data packets) | 1134 | * TX: TX_AC_VI_FIFO (TX AC Video data packets) |
1120 | * RX: UNUSED | 1135 | * RX: UNUSED |
1121 | */ | 1136 | */ |
1122 | wlc_hw->di[2] = dma_attach(name, wlc_hw->sih, | 1137 | wlc_hw->di[2] = dma_attach(name, wlc_hw->sih, wlc_hw->d11core, |
1123 | dmareg(wlc_hw, DMA_TX, 2), NULL, | 1138 | dmareg(DMA_TX, 2), 0, |
1124 | NTXD, 0, 0, -1, 0, 0, | 1139 | NTXD, 0, 0, -1, 0, 0, |
1125 | &brcm_msg_level); | 1140 | &brcm_msg_level); |
1126 | dma_attach_err |= (NULL == wlc_hw->di[2]); | 1141 | dma_attach_err |= (NULL == wlc_hw->di[2]); |
@@ -1129,9 +1144,9 @@ static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme) | |||
1129 | * TX: TX_AC_VO_FIFO (TX AC Voice data packets) | 1144 | * TX: TX_AC_VO_FIFO (TX AC Voice data packets) |
1130 | * (legacy) TX_CTL_FIFO (TX control & mgmt packets) | 1145 | * (legacy) TX_CTL_FIFO (TX control & mgmt packets) |
1131 | */ | 1146 | */ |
1132 | wlc_hw->di[3] = dma_attach(name, wlc_hw->sih, | 1147 | wlc_hw->di[3] = dma_attach(name, wlc_hw->sih, wlc_hw->d11core, |
1133 | dmareg(wlc_hw, DMA_TX, 3), | 1148 | dmareg(DMA_TX, 3), |
1134 | NULL, NTXD, 0, 0, -1, | 1149 | 0, NTXD, 0, 0, -1, |
1135 | 0, 0, &brcm_msg_level); | 1150 | 0, 0, &brcm_msg_level); |
1136 | dma_attach_err |= (NULL == wlc_hw->di[3]); | 1151 | dma_attach_err |= (NULL == wlc_hw->di[3]); |
1137 | /* Cleaner to leave this as if with AP defined */ | 1152 | /* Cleaner to leave this as if with AP defined */ |
@@ -1205,7 +1220,7 @@ static void brcms_b_wait_for_wake(struct brcms_hardware *wlc_hw) | |||
1205 | /* control chip clock to save power, enable dynamic clock or force fast clock */ | 1220 | /* control chip clock to save power, enable dynamic clock or force fast clock */ |
1206 | static void brcms_b_clkctl_clk(struct brcms_hardware *wlc_hw, uint mode) | 1221 | static void brcms_b_clkctl_clk(struct brcms_hardware *wlc_hw, uint mode) |
1207 | { | 1222 | { |
1208 | if (wlc_hw->sih->cccaps & CC_CAP_PMU) { | 1223 | if (ai_get_cccaps(wlc_hw->sih) & CC_CAP_PMU) { |
1209 | /* new chips with PMU, CCS_FORCEHT will distribute the HT clock | 1224 | /* new chips with PMU, CCS_FORCEHT will distribute the HT clock |
1210 | * on backplane, but mac core will still run on ALP(not HT) when | 1225 | * on backplane, but mac core will still run on ALP(not HT) when |
1211 | * it enters powersave mode, which means the FCA bit may not be | 1226 | * it enters powersave mode, which means the FCA bit may not be |
@@ -1214,29 +1229,33 @@ static void brcms_b_clkctl_clk(struct brcms_hardware *wlc_hw, uint mode) | |||
1214 | 1229 | ||
1215 | if (wlc_hw->clk) { | 1230 | if (wlc_hw->clk) { |
1216 | if (mode == CLK_FAST) { | 1231 | if (mode == CLK_FAST) { |
1217 | OR_REG(&wlc_hw->regs->clk_ctl_st, | 1232 | bcma_set32(wlc_hw->d11core, |
1218 | CCS_FORCEHT); | 1233 | D11REGOFFS(clk_ctl_st), |
1234 | CCS_FORCEHT); | ||
1219 | 1235 | ||
1220 | udelay(64); | 1236 | udelay(64); |
1221 | 1237 | ||
1222 | SPINWAIT(((R_REG | 1238 | SPINWAIT( |
1223 | (&wlc_hw->regs-> | 1239 | ((bcma_read32(wlc_hw->d11core, |
1224 | clk_ctl_st) & CCS_HTAVAIL) == 0), | 1240 | D11REGOFFS(clk_ctl_st)) & |
1225 | PMU_MAX_TRANSITION_DLY); | 1241 | CCS_HTAVAIL) == 0), |
1226 | WARN_ON(!(R_REG | 1242 | PMU_MAX_TRANSITION_DLY); |
1227 | (&wlc_hw->regs-> | 1243 | WARN_ON(!(bcma_read32(wlc_hw->d11core, |
1228 | clk_ctl_st) & CCS_HTAVAIL)); | 1244 | D11REGOFFS(clk_ctl_st)) & |
1245 | CCS_HTAVAIL)); | ||
1229 | } else { | 1246 | } else { |
1230 | if ((wlc_hw->sih->pmurev == 0) && | 1247 | if ((ai_get_pmurev(wlc_hw->sih) == 0) && |
1231 | (R_REG | 1248 | (bcma_read32(wlc_hw->d11core, |
1232 | (&wlc_hw->regs-> | 1249 | D11REGOFFS(clk_ctl_st)) & |
1233 | clk_ctl_st) & (CCS_FORCEHT | CCS_HTAREQ))) | 1250 | (CCS_FORCEHT | CCS_HTAREQ))) |
1234 | SPINWAIT(((R_REG | 1251 | SPINWAIT( |
1235 | (&wlc_hw->regs-> | 1252 | ((bcma_read32(wlc_hw->d11core, |
1236 | clk_ctl_st) & CCS_HTAVAIL) | 1253 | offsetof(struct d11regs, |
1237 | == 0), | 1254 | clk_ctl_st)) & |
1238 | PMU_MAX_TRANSITION_DLY); | 1255 | CCS_HTAVAIL) == 0), |
1239 | AND_REG(&wlc_hw->regs->clk_ctl_st, | 1256 | PMU_MAX_TRANSITION_DLY); |
1257 | bcma_mask32(wlc_hw->d11core, | ||
1258 | D11REGOFFS(clk_ctl_st), | ||
1240 | ~CCS_FORCEHT); | 1259 | ~CCS_FORCEHT); |
1241 | } | 1260 | } |
1242 | } | 1261 | } |
@@ -1251,7 +1270,7 @@ static void brcms_b_clkctl_clk(struct brcms_hardware *wlc_hw, uint mode) | |||
1251 | 1270 | ||
1252 | /* check fast clock is available (if core is not in reset) */ | 1271 | /* check fast clock is available (if core is not in reset) */ |
1253 | if (wlc_hw->forcefastclk && wlc_hw->clk) | 1272 | if (wlc_hw->forcefastclk && wlc_hw->clk) |
1254 | WARN_ON(!(ai_core_sflags(wlc_hw->sih, 0, 0) & | 1273 | WARN_ON(!(bcma_aread32(wlc_hw->d11core, BCMA_IOST) & |
1255 | SISF_FCLKA)); | 1274 | SISF_FCLKA)); |
1256 | 1275 | ||
1257 | /* | 1276 | /* |
@@ -1368,7 +1387,8 @@ static void brcms_c_mctrl_write(struct brcms_hardware *wlc_hw) | |||
1368 | maccontrol |= MCTL_INFRA; | 1387 | maccontrol |= MCTL_INFRA; |
1369 | } | 1388 | } |
1370 | 1389 | ||
1371 | W_REG(&wlc_hw->regs->maccontrol, maccontrol); | 1390 | bcma_write32(wlc_hw->d11core, D11REGOFFS(maccontrol), |
1391 | maccontrol); | ||
1372 | } | 1392 | } |
1373 | 1393 | ||
1374 | /* set or clear maccontrol bits */ | 1394 | /* set or clear maccontrol bits */ |
@@ -1462,7 +1482,7 @@ static void | |||
1462 | brcms_b_set_addrmatch(struct brcms_hardware *wlc_hw, int match_reg_offset, | 1482 | brcms_b_set_addrmatch(struct brcms_hardware *wlc_hw, int match_reg_offset, |
1463 | const u8 *addr) | 1483 | const u8 *addr) |
1464 | { | 1484 | { |
1465 | struct d11regs __iomem *regs; | 1485 | struct bcma_device *core = wlc_hw->d11core; |
1466 | u16 mac_l; | 1486 | u16 mac_l; |
1467 | u16 mac_m; | 1487 | u16 mac_m; |
1468 | u16 mac_h; | 1488 | u16 mac_h; |
@@ -1470,38 +1490,36 @@ brcms_b_set_addrmatch(struct brcms_hardware *wlc_hw, int match_reg_offset, | |||
1470 | BCMMSG(wlc_hw->wlc->wiphy, "wl%d: brcms_b_set_addrmatch\n", | 1490 | BCMMSG(wlc_hw->wlc->wiphy, "wl%d: brcms_b_set_addrmatch\n", |
1471 | wlc_hw->unit); | 1491 | wlc_hw->unit); |
1472 | 1492 | ||
1473 | regs = wlc_hw->regs; | ||
1474 | mac_l = addr[0] | (addr[1] << 8); | 1493 | mac_l = addr[0] | (addr[1] << 8); |
1475 | mac_m = addr[2] | (addr[3] << 8); | 1494 | mac_m = addr[2] | (addr[3] << 8); |
1476 | mac_h = addr[4] | (addr[5] << 8); | 1495 | mac_h = addr[4] | (addr[5] << 8); |
1477 | 1496 | ||
1478 | /* enter the MAC addr into the RXE match registers */ | 1497 | /* enter the MAC addr into the RXE match registers */ |
1479 | W_REG(®s->rcm_ctl, RCM_INC_DATA | match_reg_offset); | 1498 | bcma_write16(core, D11REGOFFS(rcm_ctl), |
1480 | W_REG(®s->rcm_mat_data, mac_l); | 1499 | RCM_INC_DATA | match_reg_offset); |
1481 | W_REG(®s->rcm_mat_data, mac_m); | 1500 | bcma_write16(core, D11REGOFFS(rcm_mat_data), mac_l); |
1482 | W_REG(®s->rcm_mat_data, mac_h); | 1501 | bcma_write16(core, D11REGOFFS(rcm_mat_data), mac_m); |
1483 | 1502 | bcma_write16(core, D11REGOFFS(rcm_mat_data), mac_h); | |
1484 | } | 1503 | } |
1485 | 1504 | ||
1486 | void | 1505 | void |
1487 | brcms_b_write_template_ram(struct brcms_hardware *wlc_hw, int offset, int len, | 1506 | brcms_b_write_template_ram(struct brcms_hardware *wlc_hw, int offset, int len, |
1488 | void *buf) | 1507 | void *buf) |
1489 | { | 1508 | { |
1490 | struct d11regs __iomem *regs; | 1509 | struct bcma_device *core = wlc_hw->d11core; |
1491 | u32 word; | 1510 | u32 word; |
1492 | __le32 word_le; | 1511 | __le32 word_le; |
1493 | __be32 word_be; | 1512 | __be32 word_be; |
1494 | bool be_bit; | 1513 | bool be_bit; |
1495 | BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); | 1514 | BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); |
1496 | 1515 | ||
1497 | regs = wlc_hw->regs; | 1516 | bcma_write32(core, D11REGOFFS(tplatewrptr), offset); |
1498 | W_REG(®s->tplatewrptr, offset); | ||
1499 | 1517 | ||
1500 | /* if MCTL_BIGEND bit set in mac control register, | 1518 | /* if MCTL_BIGEND bit set in mac control register, |
1501 | * the chip swaps data in fifo, as well as data in | 1519 | * the chip swaps data in fifo, as well as data in |
1502 | * template ram | 1520 | * template ram |
1503 | */ | 1521 | */ |
1504 | be_bit = (R_REG(®s->maccontrol) & MCTL_BIGEND) != 0; | 1522 | be_bit = (bcma_read32(core, D11REGOFFS(maccontrol)) & MCTL_BIGEND) != 0; |
1505 | 1523 | ||
1506 | while (len > 0) { | 1524 | while (len > 0) { |
1507 | memcpy(&word, buf, sizeof(u32)); | 1525 | memcpy(&word, buf, sizeof(u32)); |
@@ -1514,7 +1532,7 @@ brcms_b_write_template_ram(struct brcms_hardware *wlc_hw, int offset, int len, | |||
1514 | word = *(u32 *)&word_le; | 1532 | word = *(u32 *)&word_le; |
1515 | } | 1533 | } |
1516 | 1534 | ||
1517 | W_REG(®s->tplatewrdata, word); | 1535 | bcma_write32(core, D11REGOFFS(tplatewrdata), word); |
1518 | 1536 | ||
1519 | buf = (u8 *) buf + sizeof(u32); | 1537 | buf = (u8 *) buf + sizeof(u32); |
1520 | len -= sizeof(u32); | 1538 | len -= sizeof(u32); |
@@ -1525,18 +1543,20 @@ static void brcms_b_set_cwmin(struct brcms_hardware *wlc_hw, u16 newmin) | |||
1525 | { | 1543 | { |
1526 | wlc_hw->band->CWmin = newmin; | 1544 | wlc_hw->band->CWmin = newmin; |
1527 | 1545 | ||
1528 | W_REG(&wlc_hw->regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_CWMIN); | 1546 | bcma_write32(wlc_hw->d11core, D11REGOFFS(objaddr), |
1529 | (void)R_REG(&wlc_hw->regs->objaddr); | 1547 | OBJADDR_SCR_SEL | S_DOT11_CWMIN); |
1530 | W_REG(&wlc_hw->regs->objdata, newmin); | 1548 | (void)bcma_read32(wlc_hw->d11core, D11REGOFFS(objaddr)); |
1549 | bcma_write32(wlc_hw->d11core, D11REGOFFS(objdata), newmin); | ||
1531 | } | 1550 | } |
1532 | 1551 | ||
1533 | static void brcms_b_set_cwmax(struct brcms_hardware *wlc_hw, u16 newmax) | 1552 | static void brcms_b_set_cwmax(struct brcms_hardware *wlc_hw, u16 newmax) |
1534 | { | 1553 | { |
1535 | wlc_hw->band->CWmax = newmax; | 1554 | wlc_hw->band->CWmax = newmax; |
1536 | 1555 | ||
1537 | W_REG(&wlc_hw->regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_CWMAX); | 1556 | bcma_write32(wlc_hw->d11core, D11REGOFFS(objaddr), |
1538 | (void)R_REG(&wlc_hw->regs->objaddr); | 1557 | OBJADDR_SCR_SEL | S_DOT11_CWMAX); |
1539 | W_REG(&wlc_hw->regs->objdata, newmax); | 1558 | (void)bcma_read32(wlc_hw->d11core, D11REGOFFS(objaddr)); |
1559 | bcma_write32(wlc_hw->d11core, D11REGOFFS(objdata), newmax); | ||
1540 | } | 1560 | } |
1541 | 1561 | ||
1542 | void brcms_b_bw_set(struct brcms_hardware *wlc_hw, u16 bw) | 1562 | void brcms_b_bw_set(struct brcms_hardware *wlc_hw, u16 bw) |
@@ -1702,17 +1722,17 @@ void brcms_b_core_phypll_reset(struct brcms_hardware *wlc_hw) | |||
1702 | { | 1722 | { |
1703 | BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); | 1723 | BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); |
1704 | 1724 | ||
1705 | ai_corereg(wlc_hw->sih, SI_CC_IDX, | 1725 | ai_cc_reg(wlc_hw->sih, offsetof(struct chipcregs, chipcontrol_addr), |
1706 | offsetof(struct chipcregs, chipcontrol_addr), ~0, 0); | 1726 | ~0, 0); |
1707 | udelay(1); | 1727 | udelay(1); |
1708 | ai_corereg(wlc_hw->sih, SI_CC_IDX, | 1728 | ai_cc_reg(wlc_hw->sih, offsetof(struct chipcregs, chipcontrol_data), |
1709 | offsetof(struct chipcregs, chipcontrol_data), 0x4, 0); | 1729 | 0x4, 0); |
1710 | udelay(1); | 1730 | udelay(1); |
1711 | ai_corereg(wlc_hw->sih, SI_CC_IDX, | 1731 | ai_cc_reg(wlc_hw->sih, offsetof(struct chipcregs, chipcontrol_data), |
1712 | offsetof(struct chipcregs, chipcontrol_data), 0x4, 4); | 1732 | 0x4, 4); |
1713 | udelay(1); | 1733 | udelay(1); |
1714 | ai_corereg(wlc_hw->sih, SI_CC_IDX, | 1734 | ai_cc_reg(wlc_hw->sih, offsetof(struct chipcregs, chipcontrol_data), |
1715 | offsetof(struct chipcregs, chipcontrol_data), 0x4, 0); | 1735 | 0x4, 0); |
1716 | udelay(1); | 1736 | udelay(1); |
1717 | } | 1737 | } |
1718 | 1738 | ||
@@ -1726,18 +1746,18 @@ void brcms_b_phyclk_fgc(struct brcms_hardware *wlc_hw, bool clk) | |||
1726 | return; | 1746 | return; |
1727 | 1747 | ||
1728 | if (ON == clk) | 1748 | if (ON == clk) |
1729 | ai_core_cflags(wlc_hw->sih, SICF_FGC, SICF_FGC); | 1749 | brcms_b_core_ioctl(wlc_hw, SICF_FGC, SICF_FGC); |
1730 | else | 1750 | else |
1731 | ai_core_cflags(wlc_hw->sih, SICF_FGC, 0); | 1751 | brcms_b_core_ioctl(wlc_hw, SICF_FGC, 0); |
1732 | 1752 | ||
1733 | } | 1753 | } |
1734 | 1754 | ||
1735 | void brcms_b_macphyclk_set(struct brcms_hardware *wlc_hw, bool clk) | 1755 | void brcms_b_macphyclk_set(struct brcms_hardware *wlc_hw, bool clk) |
1736 | { | 1756 | { |
1737 | if (ON == clk) | 1757 | if (ON == clk) |
1738 | ai_core_cflags(wlc_hw->sih, SICF_MPCLKE, SICF_MPCLKE); | 1758 | brcms_b_core_ioctl(wlc_hw, SICF_MPCLKE, SICF_MPCLKE); |
1739 | else | 1759 | else |
1740 | ai_core_cflags(wlc_hw->sih, SICF_MPCLKE, 0); | 1760 | brcms_b_core_ioctl(wlc_hw, SICF_MPCLKE, 0); |
1741 | } | 1761 | } |
1742 | 1762 | ||
1743 | void brcms_b_phy_reset(struct brcms_hardware *wlc_hw) | 1763 | void brcms_b_phy_reset(struct brcms_hardware *wlc_hw) |
@@ -1757,7 +1777,7 @@ void brcms_b_phy_reset(struct brcms_hardware *wlc_hw) | |||
1757 | if (BRCMS_ISNPHY(wlc_hw->band) && NREV_GE(wlc_hw->band->phyrev, 3) && | 1777 | if (BRCMS_ISNPHY(wlc_hw->band) && NREV_GE(wlc_hw->band->phyrev, 3) && |
1758 | NREV_LE(wlc_hw->band->phyrev, 4)) { | 1778 | NREV_LE(wlc_hw->band->phyrev, 4)) { |
1759 | /* Set the PHY bandwidth */ | 1779 | /* Set the PHY bandwidth */ |
1760 | ai_core_cflags(wlc_hw->sih, SICF_BWMASK, phy_bw_clkbits); | 1780 | brcms_b_core_ioctl(wlc_hw, SICF_BWMASK, phy_bw_clkbits); |
1761 | 1781 | ||
1762 | udelay(1); | 1782 | udelay(1); |
1763 | 1783 | ||
@@ -1765,13 +1785,13 @@ void brcms_b_phy_reset(struct brcms_hardware *wlc_hw) | |||
1765 | brcms_b_core_phypll_reset(wlc_hw); | 1785 | brcms_b_core_phypll_reset(wlc_hw); |
1766 | 1786 | ||
1767 | /* reset the PHY */ | 1787 | /* reset the PHY */ |
1768 | ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_PCLKE), | 1788 | brcms_b_core_ioctl(wlc_hw, (SICF_PRST | SICF_PCLKE), |
1769 | (SICF_PRST | SICF_PCLKE)); | 1789 | (SICF_PRST | SICF_PCLKE)); |
1770 | phy_in_reset = true; | 1790 | phy_in_reset = true; |
1771 | } else { | 1791 | } else { |
1772 | ai_core_cflags(wlc_hw->sih, | 1792 | brcms_b_core_ioctl(wlc_hw, |
1773 | (SICF_PRST | SICF_PCLKE | SICF_BWMASK), | 1793 | (SICF_PRST | SICF_PCLKE | SICF_BWMASK), |
1774 | (SICF_PRST | SICF_PCLKE | phy_bw_clkbits)); | 1794 | (SICF_PRST | SICF_PCLKE | phy_bw_clkbits)); |
1775 | } | 1795 | } |
1776 | 1796 | ||
1777 | udelay(2); | 1797 | udelay(2); |
@@ -1788,8 +1808,8 @@ static void brcms_b_setband(struct brcms_hardware *wlc_hw, uint bandunit, | |||
1788 | u32 macintmask; | 1808 | u32 macintmask; |
1789 | 1809 | ||
1790 | /* Enable the d11 core before accessing it */ | 1810 | /* Enable the d11 core before accessing it */ |
1791 | if (!ai_iscoreup(wlc_hw->sih)) { | 1811 | if (!bcma_core_is_enabled(wlc_hw->d11core)) { |
1792 | ai_core_reset(wlc_hw->sih, 0, 0); | 1812 | bcma_core_enable(wlc_hw->d11core, 0); |
1793 | brcms_c_mctrl_reset(wlc_hw); | 1813 | brcms_c_mctrl_reset(wlc_hw); |
1794 | } | 1814 | } |
1795 | 1815 | ||
@@ -1815,7 +1835,8 @@ static void brcms_b_setband(struct brcms_hardware *wlc_hw, uint bandunit, | |||
1815 | brcms_intrsrestore(wlc->wl, macintmask); | 1835 | brcms_intrsrestore(wlc->wl, macintmask); |
1816 | 1836 | ||
1817 | /* ucode should still be suspended.. */ | 1837 | /* ucode should still be suspended.. */ |
1818 | WARN_ON((R_REG(&wlc_hw->regs->maccontrol) & MCTL_EN_MAC) != 0); | 1838 | WARN_ON((bcma_read32(wlc_hw->d11core, D11REGOFFS(maccontrol)) & |
1839 | MCTL_EN_MAC) != 0); | ||
1819 | } | 1840 | } |
1820 | 1841 | ||
1821 | static bool brcms_c_isgoodchip(struct brcms_hardware *wlc_hw) | 1842 | static bool brcms_c_isgoodchip(struct brcms_hardware *wlc_hw) |
@@ -1843,7 +1864,7 @@ static bool brcms_c_validboardtype(struct brcms_hardware *wlc_hw) | |||
1843 | uint b2 = boardrev & 0xf; | 1864 | uint b2 = boardrev & 0xf; |
1844 | 1865 | ||
1845 | /* voards from other vendors are always considered valid */ | 1866 | /* voards from other vendors are always considered valid */ |
1846 | if (wlc_hw->sih->boardvendor != PCI_VENDOR_ID_BROADCOM) | 1867 | if (ai_get_boardvendor(wlc_hw->sih) != PCI_VENDOR_ID_BROADCOM) |
1847 | return true; | 1868 | return true; |
1848 | 1869 | ||
1849 | /* do some boardrev sanity checks when boardvendor is Broadcom */ | 1870 | /* do some boardrev sanity checks when boardvendor is Broadcom */ |
@@ -1915,7 +1936,7 @@ static void brcms_b_xtal(struct brcms_hardware *wlc_hw, bool want) | |||
1915 | static bool brcms_b_radio_read_hwdisabled(struct brcms_hardware *wlc_hw) | 1936 | static bool brcms_b_radio_read_hwdisabled(struct brcms_hardware *wlc_hw) |
1916 | { | 1937 | { |
1917 | bool v, clk, xtal; | 1938 | bool v, clk, xtal; |
1918 | u32 resetbits = 0, flags = 0; | 1939 | u32 flags = 0; |
1919 | 1940 | ||
1920 | xtal = wlc_hw->sbclk; | 1941 | xtal = wlc_hw->sbclk; |
1921 | if (!xtal) | 1942 | if (!xtal) |
@@ -1932,22 +1953,22 @@ static bool brcms_b_radio_read_hwdisabled(struct brcms_hardware *wlc_hw) | |||
1932 | flags |= SICF_PCLKE; | 1953 | flags |= SICF_PCLKE; |
1933 | 1954 | ||
1934 | /* | 1955 | /* |
1956 | * TODO: test suspend/resume | ||
1957 | * | ||
1935 | * AI chip doesn't restore bar0win2 on | 1958 | * AI chip doesn't restore bar0win2 on |
1936 | * hibernation/resume, need sw fixup | 1959 | * hibernation/resume, need sw fixup |
1937 | */ | 1960 | */ |
1938 | if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) || | 1961 | |
1939 | (wlc_hw->sih->chip == BCM43225_CHIP_ID)) | 1962 | bcma_core_enable(wlc_hw->d11core, flags); |
1940 | wlc_hw->regs = (struct d11regs __iomem *) | ||
1941 | ai_setcore(wlc_hw->sih, D11_CORE_ID, 0); | ||
1942 | ai_core_reset(wlc_hw->sih, flags, resetbits); | ||
1943 | brcms_c_mctrl_reset(wlc_hw); | 1963 | brcms_c_mctrl_reset(wlc_hw); |
1944 | } | 1964 | } |
1945 | 1965 | ||
1946 | v = ((R_REG(&wlc_hw->regs->phydebug) & PDBG_RFD) != 0); | 1966 | v = ((bcma_read32(wlc_hw->d11core, |
1967 | D11REGOFFS(phydebug)) & PDBG_RFD) != 0); | ||
1947 | 1968 | ||
1948 | /* put core back into reset */ | 1969 | /* put core back into reset */ |
1949 | if (!clk) | 1970 | if (!clk) |
1950 | ai_core_disable(wlc_hw->sih, 0); | 1971 | bcma_core_disable(wlc_hw->d11core, 0); |
1951 | 1972 | ||
1952 | if (!xtal) | 1973 | if (!xtal) |
1953 | brcms_b_xtal(wlc_hw, OFF); | 1974 | brcms_b_xtal(wlc_hw, OFF); |
@@ -1971,25 +1992,21 @@ static bool wlc_dma_rxreset(struct brcms_hardware *wlc_hw, uint fifo) | |||
1971 | */ | 1992 | */ |
1972 | void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags) | 1993 | void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags) |
1973 | { | 1994 | { |
1974 | struct d11regs __iomem *regs; | ||
1975 | uint i; | 1995 | uint i; |
1976 | bool fastclk; | 1996 | bool fastclk; |
1977 | u32 resetbits = 0; | ||
1978 | 1997 | ||
1979 | if (flags == BRCMS_USE_COREFLAGS) | 1998 | if (flags == BRCMS_USE_COREFLAGS) |
1980 | flags = (wlc_hw->band->pi ? wlc_hw->band->core_flags : 0); | 1999 | flags = (wlc_hw->band->pi ? wlc_hw->band->core_flags : 0); |
1981 | 2000 | ||
1982 | BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); | 2001 | BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); |
1983 | 2002 | ||
1984 | regs = wlc_hw->regs; | ||
1985 | |||
1986 | /* request FAST clock if not on */ | 2003 | /* request FAST clock if not on */ |
1987 | fastclk = wlc_hw->forcefastclk; | 2004 | fastclk = wlc_hw->forcefastclk; |
1988 | if (!fastclk) | 2005 | if (!fastclk) |
1989 | brcms_b_clkctl_clk(wlc_hw, CLK_FAST); | 2006 | brcms_b_clkctl_clk(wlc_hw, CLK_FAST); |
1990 | 2007 | ||
1991 | /* reset the dma engines except first time thru */ | 2008 | /* reset the dma engines except first time thru */ |
1992 | if (ai_iscoreup(wlc_hw->sih)) { | 2009 | if (bcma_core_is_enabled(wlc_hw->d11core)) { |
1993 | for (i = 0; i < NFIFO; i++) | 2010 | for (i = 0; i < NFIFO; i++) |
1994 | if ((wlc_hw->di[i]) && (!dma_txreset(wlc_hw->di[i]))) | 2011 | if ((wlc_hw->di[i]) && (!dma_txreset(wlc_hw->di[i]))) |
1995 | wiphy_err(wlc_hw->wlc->wiphy, "wl%d: %s: " | 2012 | wiphy_err(wlc_hw->wlc->wiphy, "wl%d: %s: " |
@@ -2027,14 +2044,14 @@ void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags) | |||
2027 | * they may touch chipcommon as well. | 2044 | * they may touch chipcommon as well. |
2028 | */ | 2045 | */ |
2029 | wlc_hw->clk = false; | 2046 | wlc_hw->clk = false; |
2030 | ai_core_reset(wlc_hw->sih, flags, resetbits); | 2047 | bcma_core_enable(wlc_hw->d11core, flags); |
2031 | wlc_hw->clk = true; | 2048 | wlc_hw->clk = true; |
2032 | if (wlc_hw->band && wlc_hw->band->pi) | 2049 | if (wlc_hw->band && wlc_hw->band->pi) |
2033 | wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, true); | 2050 | wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, true); |
2034 | 2051 | ||
2035 | brcms_c_mctrl_reset(wlc_hw); | 2052 | brcms_c_mctrl_reset(wlc_hw); |
2036 | 2053 | ||
2037 | if (wlc_hw->sih->cccaps & CC_CAP_PMU) | 2054 | if (ai_get_cccaps(wlc_hw->sih) & CC_CAP_PMU) |
2038 | brcms_b_clkctl_clk(wlc_hw, CLK_FAST); | 2055 | brcms_b_clkctl_clk(wlc_hw, CLK_FAST); |
2039 | 2056 | ||
2040 | brcms_b_phy_reset(wlc_hw); | 2057 | brcms_b_phy_reset(wlc_hw); |
@@ -2055,7 +2072,7 @@ void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags) | |||
2055 | */ | 2072 | */ |
2056 | static void brcms_b_corerev_fifofixup(struct brcms_hardware *wlc_hw) | 2073 | static void brcms_b_corerev_fifofixup(struct brcms_hardware *wlc_hw) |
2057 | { | 2074 | { |
2058 | struct d11regs __iomem *regs = wlc_hw->regs; | 2075 | struct bcma_device *core = wlc_hw->d11core; |
2059 | u16 fifo_nu; | 2076 | u16 fifo_nu; |
2060 | u16 txfifo_startblk = TXFIFO_START_BLK, txfifo_endblk; | 2077 | u16 txfifo_startblk = TXFIFO_START_BLK, txfifo_endblk; |
2061 | u16 txfifo_def, txfifo_def1; | 2078 | u16 txfifo_def, txfifo_def1; |
@@ -2076,11 +2093,11 @@ static void brcms_b_corerev_fifofixup(struct brcms_hardware *wlc_hw) | |||
2076 | txfifo_cmd = | 2093 | txfifo_cmd = |
2077 | TXFIFOCMD_RESET_MASK | (fifo_nu << TXFIFOCMD_FIFOSEL_SHIFT); | 2094 | TXFIFOCMD_RESET_MASK | (fifo_nu << TXFIFOCMD_FIFOSEL_SHIFT); |
2078 | 2095 | ||
2079 | W_REG(®s->xmtfifocmd, txfifo_cmd); | 2096 | bcma_write16(core, D11REGOFFS(xmtfifocmd), txfifo_cmd); |
2080 | W_REG(®s->xmtfifodef, txfifo_def); | 2097 | bcma_write16(core, D11REGOFFS(xmtfifodef), txfifo_def); |
2081 | W_REG(®s->xmtfifodef1, txfifo_def1); | 2098 | bcma_write16(core, D11REGOFFS(xmtfifodef1), txfifo_def1); |
2082 | 2099 | ||
2083 | W_REG(®s->xmtfifocmd, txfifo_cmd); | 2100 | bcma_write16(core, D11REGOFFS(xmtfifocmd), txfifo_cmd); |
2084 | 2101 | ||
2085 | txfifo_startblk += wlc_hw->xmtfifo_sz[fifo_nu]; | 2102 | txfifo_startblk += wlc_hw->xmtfifo_sz[fifo_nu]; |
2086 | } | 2103 | } |
@@ -2115,27 +2132,27 @@ static void brcms_b_corerev_fifofixup(struct brcms_hardware *wlc_hw) | |||
2115 | 2132 | ||
2116 | void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode) | 2133 | void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode) |
2117 | { | 2134 | { |
2118 | struct d11regs __iomem *regs = wlc_hw->regs; | 2135 | struct bcma_device *core = wlc_hw->d11core; |
2119 | 2136 | ||
2120 | if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) || | 2137 | if ((ai_get_chip_id(wlc_hw->sih) == BCM43224_CHIP_ID) || |
2121 | (wlc_hw->sih->chip == BCM43225_CHIP_ID)) { | 2138 | (ai_get_chip_id(wlc_hw->sih) == BCM43225_CHIP_ID)) { |
2122 | if (spurmode == WL_SPURAVOID_ON2) { /* 126Mhz */ | 2139 | if (spurmode == WL_SPURAVOID_ON2) { /* 126Mhz */ |
2123 | W_REG(®s->tsf_clk_frac_l, 0x2082); | 2140 | bcma_write16(core, D11REGOFFS(tsf_clk_frac_l), 0x2082); |
2124 | W_REG(®s->tsf_clk_frac_h, 0x8); | 2141 | bcma_write16(core, D11REGOFFS(tsf_clk_frac_h), 0x8); |
2125 | } else if (spurmode == WL_SPURAVOID_ON1) { /* 123Mhz */ | 2142 | } else if (spurmode == WL_SPURAVOID_ON1) { /* 123Mhz */ |
2126 | W_REG(®s->tsf_clk_frac_l, 0x5341); | 2143 | bcma_write16(core, D11REGOFFS(tsf_clk_frac_l), 0x5341); |
2127 | W_REG(®s->tsf_clk_frac_h, 0x8); | 2144 | bcma_write16(core, D11REGOFFS(tsf_clk_frac_h), 0x8); |
2128 | } else { /* 120Mhz */ | 2145 | } else { /* 120Mhz */ |
2129 | W_REG(®s->tsf_clk_frac_l, 0x8889); | 2146 | bcma_write16(core, D11REGOFFS(tsf_clk_frac_l), 0x8889); |
2130 | W_REG(®s->tsf_clk_frac_h, 0x8); | 2147 | bcma_write16(core, D11REGOFFS(tsf_clk_frac_h), 0x8); |
2131 | } | 2148 | } |
2132 | } else if (BRCMS_ISLCNPHY(wlc_hw->band)) { | 2149 | } else if (BRCMS_ISLCNPHY(wlc_hw->band)) { |
2133 | if (spurmode == WL_SPURAVOID_ON1) { /* 82Mhz */ | 2150 | if (spurmode == WL_SPURAVOID_ON1) { /* 82Mhz */ |
2134 | W_REG(®s->tsf_clk_frac_l, 0x7CE0); | 2151 | bcma_write16(core, D11REGOFFS(tsf_clk_frac_l), 0x7CE0); |
2135 | W_REG(®s->tsf_clk_frac_h, 0xC); | 2152 | bcma_write16(core, D11REGOFFS(tsf_clk_frac_h), 0xC); |
2136 | } else { /* 80Mhz */ | 2153 | } else { /* 80Mhz */ |
2137 | W_REG(®s->tsf_clk_frac_l, 0xCCCD); | 2154 | bcma_write16(core, D11REGOFFS(tsf_clk_frac_l), 0xCCCD); |
2138 | W_REG(®s->tsf_clk_frac_h, 0xC); | 2155 | bcma_write16(core, D11REGOFFS(tsf_clk_frac_h), 0xC); |
2139 | } | 2156 | } |
2140 | } | 2157 | } |
2141 | } | 2158 | } |
@@ -2144,11 +2161,8 @@ void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode) | |||
2144 | static void brcms_c_gpio_init(struct brcms_c_info *wlc) | 2161 | static void brcms_c_gpio_init(struct brcms_c_info *wlc) |
2145 | { | 2162 | { |
2146 | struct brcms_hardware *wlc_hw = wlc->hw; | 2163 | struct brcms_hardware *wlc_hw = wlc->hw; |
2147 | struct d11regs __iomem *regs; | ||
2148 | u32 gc, gm; | 2164 | u32 gc, gm; |
2149 | 2165 | ||
2150 | regs = wlc_hw->regs; | ||
2151 | |||
2152 | /* use GPIO select 0 to get all gpio signals from the gpio out reg */ | 2166 | /* use GPIO select 0 to get all gpio signals from the gpio out reg */ |
2153 | brcms_b_mctrl(wlc_hw, MCTL_GPOUT_SEL_MASK, 0); | 2167 | brcms_b_mctrl(wlc_hw, MCTL_GPOUT_SEL_MASK, 0); |
2154 | 2168 | ||
@@ -2179,10 +2193,10 @@ static void brcms_c_gpio_init(struct brcms_c_info *wlc) | |||
2179 | * The board itself is powered by these GPIOs | 2193 | * The board itself is powered by these GPIOs |
2180 | * (when not sending pattern) so set them high | 2194 | * (when not sending pattern) so set them high |
2181 | */ | 2195 | */ |
2182 | OR_REG(®s->psm_gpio_oe, | 2196 | bcma_set16(wlc_hw->d11core, D11REGOFFS(psm_gpio_oe), |
2183 | (BOARD_GPIO_12 | BOARD_GPIO_13)); | 2197 | (BOARD_GPIO_12 | BOARD_GPIO_13)); |
2184 | OR_REG(®s->psm_gpio_out, | 2198 | bcma_set16(wlc_hw->d11core, D11REGOFFS(psm_gpio_out), |
2185 | (BOARD_GPIO_12 | BOARD_GPIO_13)); | 2199 | (BOARD_GPIO_12 | BOARD_GPIO_13)); |
2186 | 2200 | ||
2187 | /* Enable antenna diversity, use 2x4 mode */ | 2201 | /* Enable antenna diversity, use 2x4 mode */ |
2188 | brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_EN, | 2202 | brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_EN, |
@@ -2209,7 +2223,7 @@ static void brcms_c_gpio_init(struct brcms_c_info *wlc) | |||
2209 | static void brcms_ucode_write(struct brcms_hardware *wlc_hw, | 2223 | static void brcms_ucode_write(struct brcms_hardware *wlc_hw, |
2210 | const __le32 ucode[], const size_t nbytes) | 2224 | const __le32 ucode[], const size_t nbytes) |
2211 | { | 2225 | { |
2212 | struct d11regs __iomem *regs = wlc_hw->regs; | 2226 | struct bcma_device *core = wlc_hw->d11core; |
2213 | uint i; | 2227 | uint i; |
2214 | uint count; | 2228 | uint count; |
2215 | 2229 | ||
@@ -2217,10 +2231,11 @@ static void brcms_ucode_write(struct brcms_hardware *wlc_hw, | |||
2217 | 2231 | ||
2218 | count = (nbytes / sizeof(u32)); | 2232 | count = (nbytes / sizeof(u32)); |
2219 | 2233 | ||
2220 | W_REG(®s->objaddr, (OBJADDR_AUTO_INC | OBJADDR_UCM_SEL)); | 2234 | bcma_write32(core, D11REGOFFS(objaddr), |
2221 | (void)R_REG(®s->objaddr); | 2235 | OBJADDR_AUTO_INC | OBJADDR_UCM_SEL); |
2236 | (void)bcma_read32(core, D11REGOFFS(objaddr)); | ||
2222 | for (i = 0; i < count; i++) | 2237 | for (i = 0; i < count; i++) |
2223 | W_REG(®s->objdata, le32_to_cpu(ucode[i])); | 2238 | bcma_write32(core, D11REGOFFS(objdata), le32_to_cpu(ucode[i])); |
2224 | 2239 | ||
2225 | } | 2240 | } |
2226 | 2241 | ||
@@ -2286,7 +2301,7 @@ static void brcms_b_fifoerrors(struct brcms_hardware *wlc_hw) | |||
2286 | bool fatal = false; | 2301 | bool fatal = false; |
2287 | uint unit; | 2302 | uint unit; |
2288 | uint intstatus, idx; | 2303 | uint intstatus, idx; |
2289 | struct d11regs __iomem *regs = wlc_hw->regs; | 2304 | struct bcma_device *core = wlc_hw->d11core; |
2290 | struct wiphy *wiphy = wlc_hw->wlc->wiphy; | 2305 | struct wiphy *wiphy = wlc_hw->wlc->wiphy; |
2291 | 2306 | ||
2292 | unit = wlc_hw->unit; | 2307 | unit = wlc_hw->unit; |
@@ -2294,7 +2309,9 @@ static void brcms_b_fifoerrors(struct brcms_hardware *wlc_hw) | |||
2294 | for (idx = 0; idx < NFIFO; idx++) { | 2309 | for (idx = 0; idx < NFIFO; idx++) { |
2295 | /* read intstatus register and ignore any non-error bits */ | 2310 | /* read intstatus register and ignore any non-error bits */ |
2296 | intstatus = | 2311 | intstatus = |
2297 | R_REG(®s->intctrlregs[idx].intstatus) & I_ERRORS; | 2312 | bcma_read32(core, |
2313 | D11REGOFFS(intctrlregs[idx].intstatus)) & | ||
2314 | I_ERRORS; | ||
2298 | if (!intstatus) | 2315 | if (!intstatus) |
2299 | continue; | 2316 | continue; |
2300 | 2317 | ||
@@ -2339,8 +2356,9 @@ static void brcms_b_fifoerrors(struct brcms_hardware *wlc_hw) | |||
2339 | brcms_fatal_error(wlc_hw->wlc->wl); /* big hammer */ | 2356 | brcms_fatal_error(wlc_hw->wlc->wl); /* big hammer */ |
2340 | break; | 2357 | break; |
2341 | } else | 2358 | } else |
2342 | W_REG(®s->intctrlregs[idx].intstatus, | 2359 | bcma_write32(core, |
2343 | intstatus); | 2360 | D11REGOFFS(intctrlregs[idx].intstatus), |
2361 | intstatus); | ||
2344 | } | 2362 | } |
2345 | } | 2363 | } |
2346 | 2364 | ||
@@ -2348,28 +2366,7 @@ void brcms_c_intrson(struct brcms_c_info *wlc) | |||
2348 | { | 2366 | { |
2349 | struct brcms_hardware *wlc_hw = wlc->hw; | 2367 | struct brcms_hardware *wlc_hw = wlc->hw; |
2350 | wlc->macintmask = wlc->defmacintmask; | 2368 | wlc->macintmask = wlc->defmacintmask; |
2351 | W_REG(&wlc_hw->regs->macintmask, wlc->macintmask); | 2369 | bcma_write32(wlc_hw->d11core, D11REGOFFS(macintmask), wlc->macintmask); |
2352 | } | ||
2353 | |||
2354 | /* | ||
2355 | * callback for siutils.c, which has only wlc handler, no wl they both check | ||
2356 | * up, not only because there is no need to off/restore d11 interrupt but also | ||
2357 | * because per-port code may require sync with valid interrupt. | ||
2358 | */ | ||
2359 | static u32 brcms_c_wlintrsoff(struct brcms_c_info *wlc) | ||
2360 | { | ||
2361 | if (!wlc->hw->up) | ||
2362 | return 0; | ||
2363 | |||
2364 | return brcms_intrsoff(wlc->wl); | ||
2365 | } | ||
2366 | |||
2367 | static void brcms_c_wlintrsrestore(struct brcms_c_info *wlc, u32 macintmask) | ||
2368 | { | ||
2369 | if (!wlc->hw->up) | ||
2370 | return; | ||
2371 | |||
2372 | brcms_intrsrestore(wlc->wl, macintmask); | ||
2373 | } | 2370 | } |
2374 | 2371 | ||
2375 | u32 brcms_c_intrsoff(struct brcms_c_info *wlc) | 2372 | u32 brcms_c_intrsoff(struct brcms_c_info *wlc) |
@@ -2382,8 +2379,8 @@ u32 brcms_c_intrsoff(struct brcms_c_info *wlc) | |||
2382 | 2379 | ||
2383 | macintmask = wlc->macintmask; /* isr can still happen */ | 2380 | macintmask = wlc->macintmask; /* isr can still happen */ |
2384 | 2381 | ||
2385 | W_REG(&wlc_hw->regs->macintmask, 0); | 2382 | bcma_write32(wlc_hw->d11core, D11REGOFFS(macintmask), 0); |
2386 | (void)R_REG(&wlc_hw->regs->macintmask); /* sync readback */ | 2383 | (void)bcma_read32(wlc_hw->d11core, D11REGOFFS(macintmask)); |
2387 | udelay(1); /* ensure int line is no longer driven */ | 2384 | udelay(1); /* ensure int line is no longer driven */ |
2388 | wlc->macintmask = 0; | 2385 | wlc->macintmask = 0; |
2389 | 2386 | ||
@@ -2398,7 +2395,7 @@ void brcms_c_intrsrestore(struct brcms_c_info *wlc, u32 macintmask) | |||
2398 | return; | 2395 | return; |
2399 | 2396 | ||
2400 | wlc->macintmask = macintmask; | 2397 | wlc->macintmask = macintmask; |
2401 | W_REG(&wlc_hw->regs->macintmask, wlc->macintmask); | 2398 | bcma_write32(wlc_hw->d11core, D11REGOFFS(macintmask), wlc->macintmask); |
2402 | } | 2399 | } |
2403 | 2400 | ||
2404 | /* assumes that the d11 MAC is enabled */ | 2401 | /* assumes that the d11 MAC is enabled */ |
@@ -2510,11 +2507,11 @@ brcms_c_mute(struct brcms_c_info *wlc, bool mute_tx) | |||
2510 | static inline u32 wlc_intstatus(struct brcms_c_info *wlc, bool in_isr) | 2507 | static inline u32 wlc_intstatus(struct brcms_c_info *wlc, bool in_isr) |
2511 | { | 2508 | { |
2512 | struct brcms_hardware *wlc_hw = wlc->hw; | 2509 | struct brcms_hardware *wlc_hw = wlc->hw; |
2513 | struct d11regs __iomem *regs = wlc_hw->regs; | 2510 | struct bcma_device *core = wlc_hw->d11core; |
2514 | u32 macintstatus; | 2511 | u32 macintstatus; |
2515 | 2512 | ||
2516 | /* macintstatus includes a DMA interrupt summary bit */ | 2513 | /* macintstatus includes a DMA interrupt summary bit */ |
2517 | macintstatus = R_REG(®s->macintstatus); | 2514 | macintstatus = bcma_read32(core, D11REGOFFS(macintstatus)); |
2518 | 2515 | ||
2519 | BCMMSG(wlc->wiphy, "wl%d: macintstatus: 0x%x\n", wlc_hw->unit, | 2516 | BCMMSG(wlc->wiphy, "wl%d: macintstatus: 0x%x\n", wlc_hw->unit, |
2520 | macintstatus); | 2517 | macintstatus); |
@@ -2541,12 +2538,12 @@ static inline u32 wlc_intstatus(struct brcms_c_info *wlc, bool in_isr) | |||
2541 | * consequences | 2538 | * consequences |
2542 | */ | 2539 | */ |
2543 | /* turn off the interrupts */ | 2540 | /* turn off the interrupts */ |
2544 | W_REG(®s->macintmask, 0); | 2541 | bcma_write32(core, D11REGOFFS(macintmask), 0); |
2545 | (void)R_REG(®s->macintmask); /* sync readback */ | 2542 | (void)bcma_read32(core, D11REGOFFS(macintmask)); |
2546 | wlc->macintmask = 0; | 2543 | wlc->macintmask = 0; |
2547 | 2544 | ||
2548 | /* clear device interrupts */ | 2545 | /* clear device interrupts */ |
2549 | W_REG(®s->macintstatus, macintstatus); | 2546 | bcma_write32(core, D11REGOFFS(macintstatus), macintstatus); |
2550 | 2547 | ||
2551 | /* MI_DMAINT is indication of non-zero intstatus */ | 2548 | /* MI_DMAINT is indication of non-zero intstatus */ |
2552 | if (macintstatus & MI_DMAINT) | 2549 | if (macintstatus & MI_DMAINT) |
@@ -2555,8 +2552,8 @@ static inline u32 wlc_intstatus(struct brcms_c_info *wlc, bool in_isr) | |||
2555 | * RX_FIFO. If MI_DMAINT is set, assume it | 2552 | * RX_FIFO. If MI_DMAINT is set, assume it |
2556 | * is set and clear the interrupt. | 2553 | * is set and clear the interrupt. |
2557 | */ | 2554 | */ |
2558 | W_REG(®s->intctrlregs[RX_FIFO].intstatus, | 2555 | bcma_write32(core, D11REGOFFS(intctrlregs[RX_FIFO].intstatus), |
2559 | DEF_RXINTMASK); | 2556 | DEF_RXINTMASK); |
2560 | 2557 | ||
2561 | return macintstatus; | 2558 | return macintstatus; |
2562 | } | 2559 | } |
@@ -2619,7 +2616,7 @@ bool brcms_c_isr(struct brcms_c_info *wlc, bool *wantdpc) | |||
2619 | void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc) | 2616 | void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc) |
2620 | { | 2617 | { |
2621 | struct brcms_hardware *wlc_hw = wlc->hw; | 2618 | struct brcms_hardware *wlc_hw = wlc->hw; |
2622 | struct d11regs __iomem *regs = wlc_hw->regs; | 2619 | struct bcma_device *core = wlc_hw->d11core; |
2623 | u32 mc, mi; | 2620 | u32 mc, mi; |
2624 | struct wiphy *wiphy = wlc->wiphy; | 2621 | struct wiphy *wiphy = wlc->wiphy; |
2625 | 2622 | ||
@@ -2636,7 +2633,7 @@ void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc) | |||
2636 | /* force the core awake */ | 2633 | /* force the core awake */ |
2637 | brcms_c_ucode_wake_override_set(wlc_hw, BRCMS_WAKE_OVERRIDE_MACSUSPEND); | 2634 | brcms_c_ucode_wake_override_set(wlc_hw, BRCMS_WAKE_OVERRIDE_MACSUSPEND); |
2638 | 2635 | ||
2639 | mc = R_REG(®s->maccontrol); | 2636 | mc = bcma_read32(core, D11REGOFFS(maccontrol)); |
2640 | 2637 | ||
2641 | if (mc == 0xffffffff) { | 2638 | if (mc == 0xffffffff) { |
2642 | wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit, | 2639 | wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit, |
@@ -2648,7 +2645,7 @@ void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc) | |||
2648 | WARN_ON(!(mc & MCTL_PSM_RUN)); | 2645 | WARN_ON(!(mc & MCTL_PSM_RUN)); |
2649 | WARN_ON(!(mc & MCTL_EN_MAC)); | 2646 | WARN_ON(!(mc & MCTL_EN_MAC)); |
2650 | 2647 | ||
2651 | mi = R_REG(®s->macintstatus); | 2648 | mi = bcma_read32(core, D11REGOFFS(macintstatus)); |
2652 | if (mi == 0xffffffff) { | 2649 | if (mi == 0xffffffff) { |
2653 | wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit, | 2650 | wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit, |
2654 | __func__); | 2651 | __func__); |
@@ -2659,21 +2656,21 @@ void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc) | |||
2659 | 2656 | ||
2660 | brcms_b_mctrl(wlc_hw, MCTL_EN_MAC, 0); | 2657 | brcms_b_mctrl(wlc_hw, MCTL_EN_MAC, 0); |
2661 | 2658 | ||
2662 | SPINWAIT(!(R_REG(®s->macintstatus) & MI_MACSSPNDD), | 2659 | SPINWAIT(!(bcma_read32(core, D11REGOFFS(macintstatus)) & MI_MACSSPNDD), |
2663 | BRCMS_MAX_MAC_SUSPEND); | 2660 | BRCMS_MAX_MAC_SUSPEND); |
2664 | 2661 | ||
2665 | if (!(R_REG(®s->macintstatus) & MI_MACSSPNDD)) { | 2662 | if (!(bcma_read32(core, D11REGOFFS(macintstatus)) & MI_MACSSPNDD)) { |
2666 | wiphy_err(wiphy, "wl%d: wlc_suspend_mac_and_wait: waited %d uS" | 2663 | wiphy_err(wiphy, "wl%d: wlc_suspend_mac_and_wait: waited %d uS" |
2667 | " and MI_MACSSPNDD is still not on.\n", | 2664 | " and MI_MACSSPNDD is still not on.\n", |
2668 | wlc_hw->unit, BRCMS_MAX_MAC_SUSPEND); | 2665 | wlc_hw->unit, BRCMS_MAX_MAC_SUSPEND); |
2669 | wiphy_err(wiphy, "wl%d: psmdebug 0x%08x, phydebug 0x%08x, " | 2666 | wiphy_err(wiphy, "wl%d: psmdebug 0x%08x, phydebug 0x%08x, " |
2670 | "psm_brc 0x%04x\n", wlc_hw->unit, | 2667 | "psm_brc 0x%04x\n", wlc_hw->unit, |
2671 | R_REG(®s->psmdebug), | 2668 | bcma_read32(core, D11REGOFFS(psmdebug)), |
2672 | R_REG(®s->phydebug), | 2669 | bcma_read32(core, D11REGOFFS(phydebug)), |
2673 | R_REG(®s->psm_brc)); | 2670 | bcma_read16(core, D11REGOFFS(psm_brc))); |
2674 | } | 2671 | } |
2675 | 2672 | ||
2676 | mc = R_REG(®s->maccontrol); | 2673 | mc = bcma_read32(core, D11REGOFFS(maccontrol)); |
2677 | if (mc == 0xffffffff) { | 2674 | if (mc == 0xffffffff) { |
2678 | wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit, | 2675 | wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit, |
2679 | __func__); | 2676 | __func__); |
@@ -2688,7 +2685,7 @@ void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc) | |||
2688 | void brcms_c_enable_mac(struct brcms_c_info *wlc) | 2685 | void brcms_c_enable_mac(struct brcms_c_info *wlc) |
2689 | { | 2686 | { |
2690 | struct brcms_hardware *wlc_hw = wlc->hw; | 2687 | struct brcms_hardware *wlc_hw = wlc->hw; |
2691 | struct d11regs __iomem *regs = wlc_hw->regs; | 2688 | struct bcma_device *core = wlc_hw->d11core; |
2692 | u32 mc, mi; | 2689 | u32 mc, mi; |
2693 | 2690 | ||
2694 | BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit, | 2691 | BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit, |
@@ -2701,20 +2698,20 @@ void brcms_c_enable_mac(struct brcms_c_info *wlc) | |||
2701 | if (wlc_hw->mac_suspend_depth > 0) | 2698 | if (wlc_hw->mac_suspend_depth > 0) |
2702 | return; | 2699 | return; |
2703 | 2700 | ||
2704 | mc = R_REG(®s->maccontrol); | 2701 | mc = bcma_read32(core, D11REGOFFS(maccontrol)); |
2705 | WARN_ON(mc & MCTL_PSM_JMP_0); | 2702 | WARN_ON(mc & MCTL_PSM_JMP_0); |
2706 | WARN_ON(mc & MCTL_EN_MAC); | 2703 | WARN_ON(mc & MCTL_EN_MAC); |
2707 | WARN_ON(!(mc & MCTL_PSM_RUN)); | 2704 | WARN_ON(!(mc & MCTL_PSM_RUN)); |
2708 | 2705 | ||
2709 | brcms_b_mctrl(wlc_hw, MCTL_EN_MAC, MCTL_EN_MAC); | 2706 | brcms_b_mctrl(wlc_hw, MCTL_EN_MAC, MCTL_EN_MAC); |
2710 | W_REG(®s->macintstatus, MI_MACSSPNDD); | 2707 | bcma_write32(core, D11REGOFFS(macintstatus), MI_MACSSPNDD); |
2711 | 2708 | ||
2712 | mc = R_REG(®s->maccontrol); | 2709 | mc = bcma_read32(core, D11REGOFFS(maccontrol)); |
2713 | WARN_ON(mc & MCTL_PSM_JMP_0); | 2710 | WARN_ON(mc & MCTL_PSM_JMP_0); |
2714 | WARN_ON(!(mc & MCTL_EN_MAC)); | 2711 | WARN_ON(!(mc & MCTL_EN_MAC)); |
2715 | WARN_ON(!(mc & MCTL_PSM_RUN)); | 2712 | WARN_ON(!(mc & MCTL_PSM_RUN)); |
2716 | 2713 | ||
2717 | mi = R_REG(®s->macintstatus); | 2714 | mi = bcma_read32(core, D11REGOFFS(macintstatus)); |
2718 | WARN_ON(mi & MI_MACSSPNDD); | 2715 | WARN_ON(mi & MI_MACSSPNDD); |
2719 | 2716 | ||
2720 | brcms_c_ucode_wake_override_clear(wlc_hw, | 2717 | brcms_c_ucode_wake_override_clear(wlc_hw, |
@@ -2731,55 +2728,53 @@ void brcms_b_band_stf_ss_set(struct brcms_hardware *wlc_hw, u8 stf_mode) | |||
2731 | 2728 | ||
2732 | static bool brcms_b_validate_chip_access(struct brcms_hardware *wlc_hw) | 2729 | static bool brcms_b_validate_chip_access(struct brcms_hardware *wlc_hw) |
2733 | { | 2730 | { |
2734 | struct d11regs __iomem *regs; | 2731 | struct bcma_device *core = wlc_hw->d11core; |
2735 | u32 w, val; | 2732 | u32 w, val; |
2736 | struct wiphy *wiphy = wlc_hw->wlc->wiphy; | 2733 | struct wiphy *wiphy = wlc_hw->wlc->wiphy; |
2737 | 2734 | ||
2738 | BCMMSG(wiphy, "wl%d\n", wlc_hw->unit); | 2735 | BCMMSG(wiphy, "wl%d\n", wlc_hw->unit); |
2739 | 2736 | ||
2740 | regs = wlc_hw->regs; | ||
2741 | |||
2742 | /* Validate dchip register access */ | 2737 | /* Validate dchip register access */ |
2743 | 2738 | ||
2744 | W_REG(®s->objaddr, OBJADDR_SHM_SEL | 0); | 2739 | bcma_write32(core, D11REGOFFS(objaddr), OBJADDR_SHM_SEL | 0); |
2745 | (void)R_REG(®s->objaddr); | 2740 | (void)bcma_read32(core, D11REGOFFS(objaddr)); |
2746 | w = R_REG(®s->objdata); | 2741 | w = bcma_read32(core, D11REGOFFS(objdata)); |
2747 | 2742 | ||
2748 | /* Can we write and read back a 32bit register? */ | 2743 | /* Can we write and read back a 32bit register? */ |
2749 | W_REG(®s->objaddr, OBJADDR_SHM_SEL | 0); | 2744 | bcma_write32(core, D11REGOFFS(objaddr), OBJADDR_SHM_SEL | 0); |
2750 | (void)R_REG(®s->objaddr); | 2745 | (void)bcma_read32(core, D11REGOFFS(objaddr)); |
2751 | W_REG(®s->objdata, (u32) 0xaa5555aa); | 2746 | bcma_write32(core, D11REGOFFS(objdata), (u32) 0xaa5555aa); |
2752 | 2747 | ||
2753 | W_REG(®s->objaddr, OBJADDR_SHM_SEL | 0); | 2748 | bcma_write32(core, D11REGOFFS(objaddr), OBJADDR_SHM_SEL | 0); |
2754 | (void)R_REG(®s->objaddr); | 2749 | (void)bcma_read32(core, D11REGOFFS(objaddr)); |
2755 | val = R_REG(®s->objdata); | 2750 | val = bcma_read32(core, D11REGOFFS(objdata)); |
2756 | if (val != (u32) 0xaa5555aa) { | 2751 | if (val != (u32) 0xaa5555aa) { |
2757 | wiphy_err(wiphy, "wl%d: validate_chip_access: SHM = 0x%x, " | 2752 | wiphy_err(wiphy, "wl%d: validate_chip_access: SHM = 0x%x, " |
2758 | "expected 0xaa5555aa\n", wlc_hw->unit, val); | 2753 | "expected 0xaa5555aa\n", wlc_hw->unit, val); |
2759 | return false; | 2754 | return false; |
2760 | } | 2755 | } |
2761 | 2756 | ||
2762 | W_REG(®s->objaddr, OBJADDR_SHM_SEL | 0); | 2757 | bcma_write32(core, D11REGOFFS(objaddr), OBJADDR_SHM_SEL | 0); |
2763 | (void)R_REG(®s->objaddr); | 2758 | (void)bcma_read32(core, D11REGOFFS(objaddr)); |
2764 | W_REG(®s->objdata, (u32) 0x55aaaa55); | 2759 | bcma_write32(core, D11REGOFFS(objdata), (u32) 0x55aaaa55); |
2765 | 2760 | ||
2766 | W_REG(®s->objaddr, OBJADDR_SHM_SEL | 0); | 2761 | bcma_write32(core, D11REGOFFS(objaddr), OBJADDR_SHM_SEL | 0); |
2767 | (void)R_REG(®s->objaddr); | 2762 | (void)bcma_read32(core, D11REGOFFS(objaddr)); |
2768 | val = R_REG(®s->objdata); | 2763 | val = bcma_read32(core, D11REGOFFS(objdata)); |
2769 | if (val != (u32) 0x55aaaa55) { | 2764 | if (val != (u32) 0x55aaaa55) { |
2770 | wiphy_err(wiphy, "wl%d: validate_chip_access: SHM = 0x%x, " | 2765 | wiphy_err(wiphy, "wl%d: validate_chip_access: SHM = 0x%x, " |
2771 | "expected 0x55aaaa55\n", wlc_hw->unit, val); | 2766 | "expected 0x55aaaa55\n", wlc_hw->unit, val); |
2772 | return false; | 2767 | return false; |
2773 | } | 2768 | } |
2774 | 2769 | ||
2775 | W_REG(®s->objaddr, OBJADDR_SHM_SEL | 0); | 2770 | bcma_write32(core, D11REGOFFS(objaddr), OBJADDR_SHM_SEL | 0); |
2776 | (void)R_REG(®s->objaddr); | 2771 | (void)bcma_read32(core, D11REGOFFS(objaddr)); |
2777 | W_REG(®s->objdata, w); | 2772 | bcma_write32(core, D11REGOFFS(objdata), w); |
2778 | 2773 | ||
2779 | /* clear CFPStart */ | 2774 | /* clear CFPStart */ |
2780 | W_REG(®s->tsf_cfpstart, 0); | 2775 | bcma_write32(core, D11REGOFFS(tsf_cfpstart), 0); |
2781 | 2776 | ||
2782 | w = R_REG(®s->maccontrol); | 2777 | w = bcma_read32(core, D11REGOFFS(maccontrol)); |
2783 | if ((w != (MCTL_IHR_EN | MCTL_WAKE)) && | 2778 | if ((w != (MCTL_IHR_EN | MCTL_WAKE)) && |
2784 | (w != (MCTL_IHR_EN | MCTL_GMODE | MCTL_WAKE))) { | 2779 | (w != (MCTL_IHR_EN | MCTL_GMODE | MCTL_WAKE))) { |
2785 | wiphy_err(wiphy, "wl%d: validate_chip_access: maccontrol = " | 2780 | wiphy_err(wiphy, "wl%d: validate_chip_access: maccontrol = " |
@@ -2796,38 +2791,38 @@ static bool brcms_b_validate_chip_access(struct brcms_hardware *wlc_hw) | |||
2796 | 2791 | ||
2797 | void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on) | 2792 | void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on) |
2798 | { | 2793 | { |
2799 | struct d11regs __iomem *regs; | 2794 | struct bcma_device *core = wlc_hw->d11core; |
2800 | u32 tmp; | 2795 | u32 tmp; |
2801 | 2796 | ||
2802 | BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); | 2797 | BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); |
2803 | 2798 | ||
2804 | tmp = 0; | 2799 | tmp = 0; |
2805 | regs = wlc_hw->regs; | ||
2806 | 2800 | ||
2807 | if (on) { | 2801 | if (on) { |
2808 | if ((wlc_hw->sih->chip == BCM4313_CHIP_ID)) { | 2802 | if ((ai_get_chip_id(wlc_hw->sih) == BCM4313_CHIP_ID)) { |
2809 | OR_REG(®s->clk_ctl_st, | 2803 | bcma_set32(core, D11REGOFFS(clk_ctl_st), |
2810 | (CCS_ERSRC_REQ_HT | CCS_ERSRC_REQ_D11PLL | | 2804 | CCS_ERSRC_REQ_HT | |
2811 | CCS_ERSRC_REQ_PHYPLL)); | 2805 | CCS_ERSRC_REQ_D11PLL | |
2812 | SPINWAIT((R_REG(®s->clk_ctl_st) & | 2806 | CCS_ERSRC_REQ_PHYPLL); |
2813 | (CCS_ERSRC_AVAIL_HT)) != (CCS_ERSRC_AVAIL_HT), | 2807 | SPINWAIT((bcma_read32(core, D11REGOFFS(clk_ctl_st)) & |
2808 | CCS_ERSRC_AVAIL_HT) != CCS_ERSRC_AVAIL_HT, | ||
2814 | PHYPLL_WAIT_US); | 2809 | PHYPLL_WAIT_US); |
2815 | 2810 | ||
2816 | tmp = R_REG(®s->clk_ctl_st); | 2811 | tmp = bcma_read32(core, D11REGOFFS(clk_ctl_st)); |
2817 | if ((tmp & (CCS_ERSRC_AVAIL_HT)) != | 2812 | if ((tmp & CCS_ERSRC_AVAIL_HT) != CCS_ERSRC_AVAIL_HT) |
2818 | (CCS_ERSRC_AVAIL_HT)) | ||
2819 | wiphy_err(wlc_hw->wlc->wiphy, "%s: turn on PHY" | 2813 | wiphy_err(wlc_hw->wlc->wiphy, "%s: turn on PHY" |
2820 | " PLL failed\n", __func__); | 2814 | " PLL failed\n", __func__); |
2821 | } else { | 2815 | } else { |
2822 | OR_REG(®s->clk_ctl_st, | 2816 | bcma_set32(core, D11REGOFFS(clk_ctl_st), |
2823 | (CCS_ERSRC_REQ_D11PLL | CCS_ERSRC_REQ_PHYPLL)); | 2817 | tmp | CCS_ERSRC_REQ_D11PLL | |
2824 | SPINWAIT((R_REG(®s->clk_ctl_st) & | 2818 | CCS_ERSRC_REQ_PHYPLL); |
2819 | SPINWAIT((bcma_read32(core, D11REGOFFS(clk_ctl_st)) & | ||
2825 | (CCS_ERSRC_AVAIL_D11PLL | | 2820 | (CCS_ERSRC_AVAIL_D11PLL | |
2826 | CCS_ERSRC_AVAIL_PHYPLL)) != | 2821 | CCS_ERSRC_AVAIL_PHYPLL)) != |
2827 | (CCS_ERSRC_AVAIL_D11PLL | | 2822 | (CCS_ERSRC_AVAIL_D11PLL | |
2828 | CCS_ERSRC_AVAIL_PHYPLL), PHYPLL_WAIT_US); | 2823 | CCS_ERSRC_AVAIL_PHYPLL), PHYPLL_WAIT_US); |
2829 | 2824 | ||
2830 | tmp = R_REG(®s->clk_ctl_st); | 2825 | tmp = bcma_read32(core, D11REGOFFS(clk_ctl_st)); |
2831 | if ((tmp & | 2826 | if ((tmp & |
2832 | (CCS_ERSRC_AVAIL_D11PLL | CCS_ERSRC_AVAIL_PHYPLL)) | 2827 | (CCS_ERSRC_AVAIL_D11PLL | CCS_ERSRC_AVAIL_PHYPLL)) |
2833 | != | 2828 | != |
@@ -2841,8 +2836,9 @@ void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on) | |||
2841 | * be requesting it; so we'll deassert the request but | 2836 | * be requesting it; so we'll deassert the request but |
2842 | * not wait for status to comply. | 2837 | * not wait for status to comply. |
2843 | */ | 2838 | */ |
2844 | AND_REG(®s->clk_ctl_st, ~CCS_ERSRC_REQ_PHYPLL); | 2839 | bcma_mask32(core, D11REGOFFS(clk_ctl_st), |
2845 | tmp = R_REG(®s->clk_ctl_st); | 2840 | ~CCS_ERSRC_REQ_PHYPLL); |
2841 | (void)bcma_read32(core, D11REGOFFS(clk_ctl_st)); | ||
2846 | } | 2842 | } |
2847 | } | 2843 | } |
2848 | 2844 | ||
@@ -2870,7 +2866,7 @@ static void brcms_c_coredisable(struct brcms_hardware *wlc_hw) | |||
2870 | brcms_b_core_phypll_ctl(wlc_hw, false); | 2866 | brcms_b_core_phypll_ctl(wlc_hw, false); |
2871 | 2867 | ||
2872 | wlc_hw->clk = false; | 2868 | wlc_hw->clk = false; |
2873 | ai_core_disable(wlc_hw->sih, 0); | 2869 | bcma_core_disable(wlc_hw->d11core, 0); |
2874 | wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false); | 2870 | wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false); |
2875 | } | 2871 | } |
2876 | 2872 | ||
@@ -2894,35 +2890,31 @@ static void brcms_c_flushqueues(struct brcms_c_info *wlc) | |||
2894 | static u16 | 2890 | static u16 |
2895 | brcms_b_read_objmem(struct brcms_hardware *wlc_hw, uint offset, u32 sel) | 2891 | brcms_b_read_objmem(struct brcms_hardware *wlc_hw, uint offset, u32 sel) |
2896 | { | 2892 | { |
2897 | struct d11regs __iomem *regs = wlc_hw->regs; | 2893 | struct bcma_device *core = wlc_hw->d11core; |
2898 | u16 __iomem *objdata_lo = (u16 __iomem *)®s->objdata; | 2894 | u16 objoff = D11REGOFFS(objdata); |
2899 | u16 __iomem *objdata_hi = objdata_lo + 1; | ||
2900 | u16 v; | ||
2901 | 2895 | ||
2902 | W_REG(®s->objaddr, sel | (offset >> 2)); | 2896 | bcma_write32(core, D11REGOFFS(objaddr), sel | (offset >> 2)); |
2903 | (void)R_REG(®s->objaddr); | 2897 | (void)bcma_read32(core, D11REGOFFS(objaddr)); |
2904 | if (offset & 2) | 2898 | if (offset & 2) |
2905 | v = R_REG(objdata_hi); | 2899 | objoff += 2; |
2906 | else | ||
2907 | v = R_REG(objdata_lo); | ||
2908 | 2900 | ||
2909 | return v; | 2901 | return bcma_read16(core, objoff); |
2902 | ; | ||
2910 | } | 2903 | } |
2911 | 2904 | ||
2912 | static void | 2905 | static void |
2913 | brcms_b_write_objmem(struct brcms_hardware *wlc_hw, uint offset, u16 v, | 2906 | brcms_b_write_objmem(struct brcms_hardware *wlc_hw, uint offset, u16 v, |
2914 | u32 sel) | 2907 | u32 sel) |
2915 | { | 2908 | { |
2916 | struct d11regs __iomem *regs = wlc_hw->regs; | 2909 | struct bcma_device *core = wlc_hw->d11core; |
2917 | u16 __iomem *objdata_lo = (u16 __iomem *)®s->objdata; | 2910 | u16 objoff = D11REGOFFS(objdata); |
2918 | u16 __iomem *objdata_hi = objdata_lo + 1; | ||
2919 | 2911 | ||
2920 | W_REG(®s->objaddr, sel | (offset >> 2)); | 2912 | bcma_write32(core, D11REGOFFS(objaddr), sel | (offset >> 2)); |
2921 | (void)R_REG(®s->objaddr); | 2913 | (void)bcma_read32(core, D11REGOFFS(objaddr)); |
2922 | if (offset & 2) | 2914 | if (offset & 2) |
2923 | W_REG(objdata_hi, v); | 2915 | objoff += 2; |
2924 | else | 2916 | |
2925 | W_REG(objdata_lo, v); | 2917 | bcma_write16(core, objoff, v); |
2926 | } | 2918 | } |
2927 | 2919 | ||
2928 | /* | 2920 | /* |
@@ -3008,14 +3000,14 @@ static void brcms_b_retrylimit_upd(struct brcms_hardware *wlc_hw, | |||
3008 | 3000 | ||
3009 | /* write retry limit to SCR, shouldn't need to suspend */ | 3001 | /* write retry limit to SCR, shouldn't need to suspend */ |
3010 | if (wlc_hw->up) { | 3002 | if (wlc_hw->up) { |
3011 | W_REG(&wlc_hw->regs->objaddr, | 3003 | bcma_write32(wlc_hw->d11core, D11REGOFFS(objaddr), |
3012 | OBJADDR_SCR_SEL | S_DOT11_SRC_LMT); | 3004 | OBJADDR_SCR_SEL | S_DOT11_SRC_LMT); |
3013 | (void)R_REG(&wlc_hw->regs->objaddr); | 3005 | (void)bcma_read32(wlc_hw->d11core, D11REGOFFS(objaddr)); |
3014 | W_REG(&wlc_hw->regs->objdata, wlc_hw->SRL); | 3006 | bcma_write32(wlc_hw->d11core, D11REGOFFS(objdata), wlc_hw->SRL); |
3015 | W_REG(&wlc_hw->regs->objaddr, | 3007 | bcma_write32(wlc_hw->d11core, D11REGOFFS(objaddr), |
3016 | OBJADDR_SCR_SEL | S_DOT11_LRC_LMT); | 3008 | OBJADDR_SCR_SEL | S_DOT11_LRC_LMT); |
3017 | (void)R_REG(&wlc_hw->regs->objaddr); | 3009 | (void)bcma_read32(wlc_hw->d11core, D11REGOFFS(objaddr)); |
3018 | W_REG(&wlc_hw->regs->objdata, wlc_hw->LRL); | 3010 | bcma_write32(wlc_hw->d11core, D11REGOFFS(objdata), wlc_hw->LRL); |
3019 | } | 3011 | } |
3020 | } | 3012 | } |
3021 | 3013 | ||
@@ -3197,9 +3189,9 @@ void brcms_c_init_scb(struct scb *scb) | |||
3197 | static void brcms_b_coreinit(struct brcms_c_info *wlc) | 3189 | static void brcms_b_coreinit(struct brcms_c_info *wlc) |
3198 | { | 3190 | { |
3199 | struct brcms_hardware *wlc_hw = wlc->hw; | 3191 | struct brcms_hardware *wlc_hw = wlc->hw; |
3200 | struct d11regs __iomem *regs; | 3192 | struct bcma_device *core = wlc_hw->d11core; |
3201 | u32 sflags; | 3193 | u32 sflags; |
3202 | uint bcnint_us; | 3194 | u32 bcnint_us; |
3203 | uint i = 0; | 3195 | uint i = 0; |
3204 | bool fifosz_fixup = false; | 3196 | bool fifosz_fixup = false; |
3205 | int err = 0; | 3197 | int err = 0; |
@@ -3207,8 +3199,6 @@ static void brcms_b_coreinit(struct brcms_c_info *wlc) | |||
3207 | struct wiphy *wiphy = wlc->wiphy; | 3199 | struct wiphy *wiphy = wlc->wiphy; |
3208 | struct brcms_ucode *ucode = &wlc_hw->wlc->wl->ucode; | 3200 | struct brcms_ucode *ucode = &wlc_hw->wlc->wl->ucode; |
3209 | 3201 | ||
3210 | regs = wlc_hw->regs; | ||
3211 | |||
3212 | BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit); | 3202 | BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit); |
3213 | 3203 | ||
3214 | /* reset PSM */ | 3204 | /* reset PSM */ |
@@ -3221,20 +3211,20 @@ static void brcms_b_coreinit(struct brcms_c_info *wlc) | |||
3221 | fifosz_fixup = true; | 3211 | fifosz_fixup = true; |
3222 | 3212 | ||
3223 | /* let the PSM run to the suspended state, set mode to BSS STA */ | 3213 | /* let the PSM run to the suspended state, set mode to BSS STA */ |
3224 | W_REG(®s->macintstatus, -1); | 3214 | bcma_write32(core, D11REGOFFS(macintstatus), -1); |
3225 | brcms_b_mctrl(wlc_hw, ~0, | 3215 | brcms_b_mctrl(wlc_hw, ~0, |
3226 | (MCTL_IHR_EN | MCTL_INFRA | MCTL_PSM_RUN | MCTL_WAKE)); | 3216 | (MCTL_IHR_EN | MCTL_INFRA | MCTL_PSM_RUN | MCTL_WAKE)); |
3227 | 3217 | ||
3228 | /* wait for ucode to self-suspend after auto-init */ | 3218 | /* wait for ucode to self-suspend after auto-init */ |
3229 | SPINWAIT(((R_REG(®s->macintstatus) & MI_MACSSPNDD) == 0), | 3219 | SPINWAIT(((bcma_read32(core, D11REGOFFS(macintstatus)) & |
3230 | 1000 * 1000); | 3220 | MI_MACSSPNDD) == 0), 1000 * 1000); |
3231 | if ((R_REG(®s->macintstatus) & MI_MACSSPNDD) == 0) | 3221 | if ((bcma_read32(core, D11REGOFFS(macintstatus)) & MI_MACSSPNDD) == 0) |
3232 | wiphy_err(wiphy, "wl%d: wlc_coreinit: ucode did not self-" | 3222 | wiphy_err(wiphy, "wl%d: wlc_coreinit: ucode did not self-" |
3233 | "suspend!\n", wlc_hw->unit); | 3223 | "suspend!\n", wlc_hw->unit); |
3234 | 3224 | ||
3235 | brcms_c_gpio_init(wlc); | 3225 | brcms_c_gpio_init(wlc); |
3236 | 3226 | ||
3237 | sflags = ai_core_sflags(wlc_hw->sih, 0, 0); | 3227 | sflags = bcma_aread32(core, BCMA_IOST); |
3238 | 3228 | ||
3239 | if (D11REV_IS(wlc_hw->corerev, 23)) { | 3229 | if (D11REV_IS(wlc_hw->corerev, 23)) { |
3240 | if (BRCMS_ISNPHY(wlc_hw->band)) | 3230 | if (BRCMS_ISNPHY(wlc_hw->band)) |
@@ -3298,7 +3288,7 @@ static void brcms_b_coreinit(struct brcms_c_info *wlc) | |||
3298 | wlc_hw->xmtfifo_sz[i], i); | 3288 | wlc_hw->xmtfifo_sz[i], i); |
3299 | 3289 | ||
3300 | /* make sure we can still talk to the mac */ | 3290 | /* make sure we can still talk to the mac */ |
3301 | WARN_ON(R_REG(®s->maccontrol) == 0xffffffff); | 3291 | WARN_ON(bcma_read32(core, D11REGOFFS(maccontrol)) == 0xffffffff); |
3302 | 3292 | ||
3303 | /* band-specific inits done by wlc_bsinit() */ | 3293 | /* band-specific inits done by wlc_bsinit() */ |
3304 | 3294 | ||
@@ -3307,7 +3297,7 @@ static void brcms_b_coreinit(struct brcms_c_info *wlc) | |||
3307 | brcms_b_write_shm(wlc_hw, M_MAX_ANTCNT, ANTCNT); | 3297 | brcms_b_write_shm(wlc_hw, M_MAX_ANTCNT, ANTCNT); |
3308 | 3298 | ||
3309 | /* enable one rx interrupt per received frame */ | 3299 | /* enable one rx interrupt per received frame */ |
3310 | W_REG(®s->intrcvlazy[0], (1 << IRL_FC_SHIFT)); | 3300 | bcma_write32(core, D11REGOFFS(intrcvlazy[0]), (1 << IRL_FC_SHIFT)); |
3311 | 3301 | ||
3312 | /* set the station mode (BSS STA) */ | 3302 | /* set the station mode (BSS STA) */ |
3313 | brcms_b_mctrl(wlc_hw, | 3303 | brcms_b_mctrl(wlc_hw, |
@@ -3316,19 +3306,21 @@ static void brcms_b_coreinit(struct brcms_c_info *wlc) | |||
3316 | 3306 | ||
3317 | /* set up Beacon interval */ | 3307 | /* set up Beacon interval */ |
3318 | bcnint_us = 0x8000 << 10; | 3308 | bcnint_us = 0x8000 << 10; |
3319 | W_REG(®s->tsf_cfprep, (bcnint_us << CFPREP_CBI_SHIFT)); | 3309 | bcma_write32(core, D11REGOFFS(tsf_cfprep), |
3320 | W_REG(®s->tsf_cfpstart, bcnint_us); | 3310 | (bcnint_us << CFPREP_CBI_SHIFT)); |
3321 | W_REG(®s->macintstatus, MI_GP1); | 3311 | bcma_write32(core, D11REGOFFS(tsf_cfpstart), bcnint_us); |
3312 | bcma_write32(core, D11REGOFFS(macintstatus), MI_GP1); | ||
3322 | 3313 | ||
3323 | /* write interrupt mask */ | 3314 | /* write interrupt mask */ |
3324 | W_REG(®s->intctrlregs[RX_FIFO].intmask, DEF_RXINTMASK); | 3315 | bcma_write32(core, D11REGOFFS(intctrlregs[RX_FIFO].intmask), |
3316 | DEF_RXINTMASK); | ||
3325 | 3317 | ||
3326 | /* allow the MAC to control the PHY clock (dynamic on/off) */ | 3318 | /* allow the MAC to control the PHY clock (dynamic on/off) */ |
3327 | brcms_b_macphyclk_set(wlc_hw, ON); | 3319 | brcms_b_macphyclk_set(wlc_hw, ON); |
3328 | 3320 | ||
3329 | /* program dynamic clock control fast powerup delay register */ | 3321 | /* program dynamic clock control fast powerup delay register */ |
3330 | wlc->fastpwrup_dly = ai_clkctl_fast_pwrup_delay(wlc_hw->sih); | 3322 | wlc->fastpwrup_dly = ai_clkctl_fast_pwrup_delay(wlc_hw->sih); |
3331 | W_REG(®s->scc_fastpwrup_dly, wlc->fastpwrup_dly); | 3323 | bcma_write16(core, D11REGOFFS(scc_fastpwrup_dly), wlc->fastpwrup_dly); |
3332 | 3324 | ||
3333 | /* tell the ucode the corerev */ | 3325 | /* tell the ucode the corerev */ |
3334 | brcms_b_write_shm(wlc_hw, M_MACHW_VER, (u16) wlc_hw->corerev); | 3326 | brcms_b_write_shm(wlc_hw, M_MACHW_VER, (u16) wlc_hw->corerev); |
@@ -3341,19 +3333,21 @@ static void brcms_b_coreinit(struct brcms_c_info *wlc) | |||
3341 | machwcap >> 16) & 0xffff)); | 3333 | machwcap >> 16) & 0xffff)); |
3342 | 3334 | ||
3343 | /* write retry limits to SCR, this done after PSM init */ | 3335 | /* write retry limits to SCR, this done after PSM init */ |
3344 | W_REG(®s->objaddr, OBJADDR_SCR_SEL | S_DOT11_SRC_LMT); | 3336 | bcma_write32(core, D11REGOFFS(objaddr), |
3345 | (void)R_REG(®s->objaddr); | 3337 | OBJADDR_SCR_SEL | S_DOT11_SRC_LMT); |
3346 | W_REG(®s->objdata, wlc_hw->SRL); | 3338 | (void)bcma_read32(core, D11REGOFFS(objaddr)); |
3347 | W_REG(®s->objaddr, OBJADDR_SCR_SEL | S_DOT11_LRC_LMT); | 3339 | bcma_write32(core, D11REGOFFS(objdata), wlc_hw->SRL); |
3348 | (void)R_REG(®s->objaddr); | 3340 | bcma_write32(core, D11REGOFFS(objaddr), |
3349 | W_REG(®s->objdata, wlc_hw->LRL); | 3341 | OBJADDR_SCR_SEL | S_DOT11_LRC_LMT); |
3342 | (void)bcma_read32(core, D11REGOFFS(objaddr)); | ||
3343 | bcma_write32(core, D11REGOFFS(objdata), wlc_hw->LRL); | ||
3350 | 3344 | ||
3351 | /* write rate fallback retry limits */ | 3345 | /* write rate fallback retry limits */ |
3352 | brcms_b_write_shm(wlc_hw, M_SFRMTXCNTFBRTHSD, wlc_hw->SFBL); | 3346 | brcms_b_write_shm(wlc_hw, M_SFRMTXCNTFBRTHSD, wlc_hw->SFBL); |
3353 | brcms_b_write_shm(wlc_hw, M_LFRMTXCNTFBRTHSD, wlc_hw->LFBL); | 3347 | brcms_b_write_shm(wlc_hw, M_LFRMTXCNTFBRTHSD, wlc_hw->LFBL); |
3354 | 3348 | ||
3355 | AND_REG(®s->ifs_ctl, 0x0FFF); | 3349 | bcma_mask16(core, D11REGOFFS(ifs_ctl), 0x0FFF); |
3356 | W_REG(®s->ifs_aifsn, EDCF_AIFSN_MIN); | 3350 | bcma_write16(core, D11REGOFFS(ifs_aifsn), EDCF_AIFSN_MIN); |
3357 | 3351 | ||
3358 | /* init the tx dma engines */ | 3352 | /* init the tx dma engines */ |
3359 | for (i = 0; i < NFIFO; i++) { | 3353 | for (i = 0; i < NFIFO; i++) { |
@@ -3810,7 +3804,7 @@ static void brcms_c_set_ps_ctrl(struct brcms_c_info *wlc) | |||
3810 | 3804 | ||
3811 | BCMMSG(wlc->wiphy, "wl%d: hps %d\n", wlc->pub->unit, hps); | 3805 | BCMMSG(wlc->wiphy, "wl%d: hps %d\n", wlc->pub->unit, hps); |
3812 | 3806 | ||
3813 | v1 = R_REG(&wlc->regs->maccontrol); | 3807 | v1 = bcma_read32(wlc->hw->d11core, D11REGOFFS(maccontrol)); |
3814 | v2 = MCTL_WAKE; | 3808 | v2 = MCTL_WAKE; |
3815 | if (hps) | 3809 | if (hps) |
3816 | v2 |= MCTL_HPS; | 3810 | v2 |= MCTL_HPS; |
@@ -4129,7 +4123,8 @@ void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci, | |||
4129 | acp_shm.cwmax = params->cw_max; | 4123 | acp_shm.cwmax = params->cw_max; |
4130 | acp_shm.cwcur = acp_shm.cwmin; | 4124 | acp_shm.cwcur = acp_shm.cwmin; |
4131 | acp_shm.bslots = | 4125 | acp_shm.bslots = |
4132 | R_REG(&wlc->regs->tsf_random) & acp_shm.cwcur; | 4126 | bcma_read16(wlc->hw->d11core, D11REGOFFS(tsf_random)) & |
4127 | acp_shm.cwcur; | ||
4133 | acp_shm.reggap = acp_shm.bslots + acp_shm.aifs; | 4128 | acp_shm.reggap = acp_shm.bslots + acp_shm.aifs; |
4134 | /* Indicate the new params to the ucode */ | 4129 | /* Indicate the new params to the ucode */ |
4135 | acp_shm.status = brcms_b_read_shm(wlc->hw, (M_EDCF_QINFO + | 4130 | acp_shm.status = brcms_b_read_shm(wlc->hw, (M_EDCF_QINFO + |
@@ -4437,21 +4432,21 @@ struct brcms_pub *brcms_c_pub(struct brcms_c_info *wlc) | |||
4437 | * initialize software state for each core and band | 4432 | * initialize software state for each core and band |
4438 | * put the whole chip in reset(driver down state), no clock | 4433 | * put the whole chip in reset(driver down state), no clock |
4439 | */ | 4434 | */ |
4440 | static int brcms_b_attach(struct brcms_c_info *wlc, u16 vendor, u16 device, | 4435 | static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core, |
4441 | uint unit, bool piomode, void __iomem *regsva, | 4436 | uint unit, bool piomode) |
4442 | struct pci_dev *btparam) | ||
4443 | { | 4437 | { |
4444 | struct brcms_hardware *wlc_hw; | 4438 | struct brcms_hardware *wlc_hw; |
4445 | struct d11regs __iomem *regs; | ||
4446 | char *macaddr = NULL; | 4439 | char *macaddr = NULL; |
4447 | uint err = 0; | 4440 | uint err = 0; |
4448 | uint j; | 4441 | uint j; |
4449 | bool wme = false; | 4442 | bool wme = false; |
4450 | struct shared_phy_params sha_params; | 4443 | struct shared_phy_params sha_params; |
4451 | struct wiphy *wiphy = wlc->wiphy; | 4444 | struct wiphy *wiphy = wlc->wiphy; |
4445 | struct pci_dev *pcidev = core->bus->host_pci; | ||
4452 | 4446 | ||
4453 | BCMMSG(wlc->wiphy, "wl%d: vendor 0x%x device 0x%x\n", unit, vendor, | 4447 | BCMMSG(wlc->wiphy, "wl%d: vendor 0x%x device 0x%x\n", unit, |
4454 | device); | 4448 | pcidev->vendor, |
4449 | pcidev->device); | ||
4455 | 4450 | ||
4456 | wme = true; | 4451 | wme = true; |
4457 | 4452 | ||
@@ -4468,7 +4463,7 @@ static int brcms_b_attach(struct brcms_c_info *wlc, u16 vendor, u16 device, | |||
4468 | * Do the hardware portion of the attach. Also initialize software | 4463 | * Do the hardware portion of the attach. Also initialize software |
4469 | * state that depends on the particular hardware we are running. | 4464 | * state that depends on the particular hardware we are running. |
4470 | */ | 4465 | */ |
4471 | wlc_hw->sih = ai_attach(regsva, btparam); | 4466 | wlc_hw->sih = ai_attach(core->bus); |
4472 | if (wlc_hw->sih == NULL) { | 4467 | if (wlc_hw->sih == NULL) { |
4473 | wiphy_err(wiphy, "wl%d: brcms_b_attach: si_attach failed\n", | 4468 | wiphy_err(wiphy, "wl%d: brcms_b_attach: si_attach failed\n", |
4474 | unit); | 4469 | unit); |
@@ -4477,25 +4472,19 @@ static int brcms_b_attach(struct brcms_c_info *wlc, u16 vendor, u16 device, | |||
4477 | } | 4472 | } |
4478 | 4473 | ||
4479 | /* verify again the device is supported */ | 4474 | /* verify again the device is supported */ |
4480 | if (!brcms_c_chipmatch(vendor, device)) { | 4475 | if (!brcms_c_chipmatch(pcidev->vendor, pcidev->device)) { |
4481 | wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported " | 4476 | wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported " |
4482 | "vendor/device (0x%x/0x%x)\n", | 4477 | "vendor/device (0x%x/0x%x)\n", |
4483 | unit, vendor, device); | 4478 | unit, pcidev->vendor, pcidev->device); |
4484 | err = 12; | 4479 | err = 12; |
4485 | goto fail; | 4480 | goto fail; |
4486 | } | 4481 | } |
4487 | 4482 | ||
4488 | wlc_hw->vendorid = vendor; | 4483 | wlc_hw->vendorid = pcidev->vendor; |
4489 | wlc_hw->deviceid = device; | 4484 | wlc_hw->deviceid = pcidev->device; |
4490 | 4485 | ||
4491 | /* set bar0 window to point at D11 core */ | 4486 | wlc_hw->d11core = core; |
4492 | wlc_hw->regs = (struct d11regs __iomem *) | 4487 | wlc_hw->corerev = core->id.rev; |
4493 | ai_setcore(wlc_hw->sih, D11_CORE_ID, 0); | ||
4494 | wlc_hw->corerev = ai_corerev(wlc_hw->sih); | ||
4495 | |||
4496 | regs = wlc_hw->regs; | ||
4497 | |||
4498 | wlc->regs = wlc_hw->regs; | ||
4499 | 4488 | ||
4500 | /* validate chip, chiprev and corerev */ | 4489 | /* validate chip, chiprev and corerev */ |
4501 | if (!brcms_c_isgoodchip(wlc_hw)) { | 4490 | if (!brcms_c_isgoodchip(wlc_hw)) { |
@@ -4530,8 +4519,9 @@ static int brcms_b_attach(struct brcms_c_info *wlc, u16 vendor, u16 device, | |||
4530 | wlc_hw->boardrev = (u16) j; | 4519 | wlc_hw->boardrev = (u16) j; |
4531 | if (!brcms_c_validboardtype(wlc_hw)) { | 4520 | if (!brcms_c_validboardtype(wlc_hw)) { |
4532 | wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported Broadcom " | 4521 | wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported Broadcom " |
4533 | "board type (0x%x)" " or revision level (0x%x)\n", | 4522 | "board type (0x%x)" " or revision level (0x%x)\n", |
4534 | unit, wlc_hw->sih->boardtype, wlc_hw->boardrev); | 4523 | unit, ai_get_boardtype(wlc_hw->sih), |
4524 | wlc_hw->boardrev); | ||
4535 | err = 15; | 4525 | err = 15; |
4536 | goto fail; | 4526 | goto fail; |
4537 | } | 4527 | } |
@@ -4552,7 +4542,7 @@ static int brcms_b_attach(struct brcms_c_info *wlc, u16 vendor, u16 device, | |||
4552 | else | 4542 | else |
4553 | wlc_hw->_nbands = 1; | 4543 | wlc_hw->_nbands = 1; |
4554 | 4544 | ||
4555 | if ((wlc_hw->sih->chip == BCM43225_CHIP_ID)) | 4545 | if ((ai_get_chip_id(wlc_hw->sih) == BCM43225_CHIP_ID)) |
4556 | wlc_hw->_nbands = 1; | 4546 | wlc_hw->_nbands = 1; |
4557 | 4547 | ||
4558 | /* BMAC_NOTE: remove init of pub values when brcms_c_attach() | 4548 | /* BMAC_NOTE: remove init of pub values when brcms_c_attach() |
@@ -4584,16 +4574,14 @@ static int brcms_b_attach(struct brcms_c_info *wlc, u16 vendor, u16 device, | |||
4584 | sha_params.corerev = wlc_hw->corerev; | 4574 | sha_params.corerev = wlc_hw->corerev; |
4585 | sha_params.vid = wlc_hw->vendorid; | 4575 | sha_params.vid = wlc_hw->vendorid; |
4586 | sha_params.did = wlc_hw->deviceid; | 4576 | sha_params.did = wlc_hw->deviceid; |
4587 | sha_params.chip = wlc_hw->sih->chip; | 4577 | sha_params.chip = ai_get_chip_id(wlc_hw->sih); |
4588 | sha_params.chiprev = wlc_hw->sih->chiprev; | 4578 | sha_params.chiprev = ai_get_chiprev(wlc_hw->sih); |
4589 | sha_params.chippkg = wlc_hw->sih->chippkg; | 4579 | sha_params.chippkg = ai_get_chippkg(wlc_hw->sih); |
4590 | sha_params.sromrev = wlc_hw->sromrev; | 4580 | sha_params.sromrev = wlc_hw->sromrev; |
4591 | sha_params.boardtype = wlc_hw->sih->boardtype; | 4581 | sha_params.boardtype = ai_get_boardtype(wlc_hw->sih); |
4592 | sha_params.boardrev = wlc_hw->boardrev; | 4582 | sha_params.boardrev = wlc_hw->boardrev; |
4593 | sha_params.boardvendor = wlc_hw->sih->boardvendor; | ||
4594 | sha_params.boardflags = wlc_hw->boardflags; | 4583 | sha_params.boardflags = wlc_hw->boardflags; |
4595 | sha_params.boardflags2 = wlc_hw->boardflags2; | 4584 | sha_params.boardflags2 = wlc_hw->boardflags2; |
4596 | sha_params.buscorerev = wlc_hw->sih->buscorerev; | ||
4597 | 4585 | ||
4598 | /* alloc and save pointer to shared phy state area */ | 4586 | /* alloc and save pointer to shared phy state area */ |
4599 | wlc_hw->phy_sh = wlc_phy_shared_attach(&sha_params); | 4587 | wlc_hw->phy_sh = wlc_phy_shared_attach(&sha_params); |
@@ -4615,9 +4603,9 @@ static int brcms_b_attach(struct brcms_c_info *wlc, u16 vendor, u16 device, | |||
4615 | wlc_hw->band->bandtype = j ? BRCM_BAND_5G : BRCM_BAND_2G; | 4603 | wlc_hw->band->bandtype = j ? BRCM_BAND_5G : BRCM_BAND_2G; |
4616 | wlc->band->bandunit = j; | 4604 | wlc->band->bandunit = j; |
4617 | wlc->band->bandtype = j ? BRCM_BAND_5G : BRCM_BAND_2G; | 4605 | wlc->band->bandtype = j ? BRCM_BAND_5G : BRCM_BAND_2G; |
4618 | wlc->core->coreidx = ai_coreidx(wlc_hw->sih); | 4606 | wlc->core->coreidx = core->core_index; |
4619 | 4607 | ||
4620 | wlc_hw->machwcap = R_REG(®s->machwcap); | 4608 | wlc_hw->machwcap = bcma_read32(core, D11REGOFFS(machwcap)); |
4621 | wlc_hw->machwcap_backup = wlc_hw->machwcap; | 4609 | wlc_hw->machwcap_backup = wlc_hw->machwcap; |
4622 | 4610 | ||
4623 | /* init tx fifo size */ | 4611 | /* init tx fifo size */ |
@@ -4626,7 +4614,7 @@ static int brcms_b_attach(struct brcms_c_info *wlc, u16 vendor, u16 device, | |||
4626 | 4614 | ||
4627 | /* Get a phy for this band */ | 4615 | /* Get a phy for this band */ |
4628 | wlc_hw->band->pi = | 4616 | wlc_hw->band->pi = |
4629 | wlc_phy_attach(wlc_hw->phy_sh, regs, | 4617 | wlc_phy_attach(wlc_hw->phy_sh, core, |
4630 | wlc_hw->band->bandtype, | 4618 | wlc_hw->band->bandtype, |
4631 | wlc->wiphy); | 4619 | wlc->wiphy); |
4632 | if (wlc_hw->band->pi == NULL) { | 4620 | if (wlc_hw->band->pi == NULL) { |
@@ -4700,10 +4688,6 @@ static int brcms_b_attach(struct brcms_c_info *wlc, u16 vendor, u16 device, | |||
4700 | /* Match driver "down" state */ | 4688 | /* Match driver "down" state */ |
4701 | ai_pci_down(wlc_hw->sih); | 4689 | ai_pci_down(wlc_hw->sih); |
4702 | 4690 | ||
4703 | /* register sb interrupt callback functions */ | ||
4704 | ai_register_intr_callback(wlc_hw->sih, (void *)brcms_c_wlintrsoff, | ||
4705 | (void *)brcms_c_wlintrsrestore, NULL, wlc); | ||
4706 | |||
4707 | /* turn off pll and xtal to match driver "down" state */ | 4691 | /* turn off pll and xtal to match driver "down" state */ |
4708 | brcms_b_xtal(wlc_hw, OFF); | 4692 | brcms_b_xtal(wlc_hw, OFF); |
4709 | 4693 | ||
@@ -4734,10 +4718,9 @@ static int brcms_b_attach(struct brcms_c_info *wlc, u16 vendor, u16 device, | |||
4734 | goto fail; | 4718 | goto fail; |
4735 | } | 4719 | } |
4736 | 4720 | ||
4737 | BCMMSG(wlc->wiphy, | 4721 | BCMMSG(wlc->wiphy, "deviceid 0x%x nbands %d board 0x%x macaddr: %s\n", |
4738 | "deviceid 0x%x nbands %d board 0x%x macaddr: %s\n", | 4722 | wlc_hw->deviceid, wlc_hw->_nbands, ai_get_boardtype(wlc_hw->sih), |
4739 | wlc_hw->deviceid, wlc_hw->_nbands, | 4723 | macaddr); |
4740 | wlc_hw->sih->boardtype, macaddr); | ||
4741 | 4724 | ||
4742 | return err; | 4725 | return err; |
4743 | 4726 | ||
@@ -4975,7 +4958,6 @@ static int brcms_b_detach(struct brcms_c_info *wlc) | |||
4975 | * and per-port interrupt object may has been freed. this must | 4958 | * and per-port interrupt object may has been freed. this must |
4976 | * be done before sb core switch | 4959 | * be done before sb core switch |
4977 | */ | 4960 | */ |
4978 | ai_deregister_intr_callback(wlc_hw->sih); | ||
4979 | ai_pci_sleep(wlc_hw->sih); | 4961 | ai_pci_sleep(wlc_hw->sih); |
4980 | } | 4962 | } |
4981 | 4963 | ||
@@ -5070,13 +5052,11 @@ static void brcms_b_hw_up(struct brcms_hardware *wlc_hw) | |||
5070 | ai_pci_fixcfg(wlc_hw->sih); | 5052 | ai_pci_fixcfg(wlc_hw->sih); |
5071 | 5053 | ||
5072 | /* | 5054 | /* |
5055 | * TODO: test suspend/resume | ||
5056 | * | ||
5073 | * AI chip doesn't restore bar0win2 on | 5057 | * AI chip doesn't restore bar0win2 on |
5074 | * hibernation/resume, need sw fixup | 5058 | * hibernation/resume, need sw fixup |
5075 | */ | 5059 | */ |
5076 | if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) || | ||
5077 | (wlc_hw->sih->chip == BCM43225_CHIP_ID)) | ||
5078 | wlc_hw->regs = (struct d11regs __iomem *) | ||
5079 | ai_setcore(wlc_hw->sih, D11_CORE_ID, 0); | ||
5080 | 5060 | ||
5081 | /* | 5061 | /* |
5082 | * Inform phy that a POR reset has occurred so | 5062 | * Inform phy that a POR reset has occurred so |
@@ -5088,7 +5068,7 @@ static void brcms_b_hw_up(struct brcms_hardware *wlc_hw) | |||
5088 | wlc_hw->wlc->pub->hw_up = true; | 5068 | wlc_hw->wlc->pub->hw_up = true; |
5089 | 5069 | ||
5090 | if ((wlc_hw->boardflags & BFL_FEM) | 5070 | if ((wlc_hw->boardflags & BFL_FEM) |
5091 | && (wlc_hw->sih->chip == BCM4313_CHIP_ID)) { | 5071 | && (ai_get_chip_id(wlc_hw->sih) == BCM4313_CHIP_ID)) { |
5092 | if (! | 5072 | if (! |
5093 | (wlc_hw->boardrev >= 0x1250 | 5073 | (wlc_hw->boardrev >= 0x1250 |
5094 | && (wlc_hw->boardflags & BFL_FEM_BT))) | 5074 | && (wlc_hw->boardflags & BFL_FEM_BT))) |
@@ -5183,7 +5163,7 @@ int brcms_c_up(struct brcms_c_info *wlc) | |||
5183 | } | 5163 | } |
5184 | 5164 | ||
5185 | if ((wlc->pub->boardflags & BFL_FEM) | 5165 | if ((wlc->pub->boardflags & BFL_FEM) |
5186 | && (wlc->pub->sih->chip == BCM4313_CHIP_ID)) { | 5166 | && (ai_get_chip_id(wlc->hw->sih) == BCM4313_CHIP_ID)) { |
5187 | if (wlc->pub->boardrev >= 0x1250 | 5167 | if (wlc->pub->boardrev >= 0x1250 |
5188 | && (wlc->pub->boardflags & BFL_FEM_BT)) | 5168 | && (wlc->pub->boardflags & BFL_FEM_BT)) |
5189 | brcms_b_mhf(wlc->hw, MHF5, MHF5_4313_GPIOCTRL, | 5169 | brcms_b_mhf(wlc->hw, MHF5, MHF5_4313_GPIOCTRL, |
@@ -5320,9 +5300,9 @@ static int brcms_b_down_finish(struct brcms_hardware *wlc_hw) | |||
5320 | } else { | 5300 | } else { |
5321 | 5301 | ||
5322 | /* Reset and disable the core */ | 5302 | /* Reset and disable the core */ |
5323 | if (ai_iscoreup(wlc_hw->sih)) { | 5303 | if (bcma_core_is_enabled(wlc_hw->d11core)) { |
5324 | if (R_REG(&wlc_hw->regs->maccontrol) & | 5304 | if (bcma_read32(wlc_hw->d11core, |
5325 | MCTL_EN_MAC) | 5305 | D11REGOFFS(maccontrol)) & MCTL_EN_MAC) |
5326 | brcms_c_suspend_mac_and_wait(wlc_hw->wlc); | 5306 | brcms_c_suspend_mac_and_wait(wlc_hw->wlc); |
5327 | callbacks += brcms_reset(wlc_hw->wlc->wl); | 5307 | callbacks += brcms_reset(wlc_hw->wlc->wl); |
5328 | brcms_c_coredisable(wlc_hw); | 5308 | brcms_c_coredisable(wlc_hw); |
@@ -7479,11 +7459,11 @@ static void | |||
7479 | brcms_b_read_tsf(struct brcms_hardware *wlc_hw, u32 *tsf_l_ptr, | 7459 | brcms_b_read_tsf(struct brcms_hardware *wlc_hw, u32 *tsf_l_ptr, |
7480 | u32 *tsf_h_ptr) | 7460 | u32 *tsf_h_ptr) |
7481 | { | 7461 | { |
7482 | struct d11regs __iomem *regs = wlc_hw->regs; | 7462 | struct bcma_device *core = wlc_hw->d11core; |
7483 | 7463 | ||
7484 | /* read the tsf timer low, then high to get an atomic read */ | 7464 | /* read the tsf timer low, then high to get an atomic read */ |
7485 | *tsf_l_ptr = R_REG(®s->tsf_timerlow); | 7465 | *tsf_l_ptr = bcma_read32(core, D11REGOFFS(tsf_timerlow)); |
7486 | *tsf_h_ptr = R_REG(®s->tsf_timerhigh); | 7466 | *tsf_h_ptr = bcma_read32(core, D11REGOFFS(tsf_timerhigh)); |
7487 | } | 7467 | } |
7488 | 7468 | ||
7489 | /* | 7469 | /* |
@@ -8156,7 +8136,7 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded) | |||
8156 | { | 8136 | { |
8157 | u32 macintstatus; | 8137 | u32 macintstatus; |
8158 | struct brcms_hardware *wlc_hw = wlc->hw; | 8138 | struct brcms_hardware *wlc_hw = wlc->hw; |
8159 | struct d11regs __iomem *regs = wlc_hw->regs; | 8139 | struct bcma_device *core = wlc_hw->d11core; |
8160 | struct wiphy *wiphy = wlc->wiphy; | 8140 | struct wiphy *wiphy = wlc->wiphy; |
8161 | 8141 | ||
8162 | if (brcms_deviceremoved(wlc)) { | 8142 | if (brcms_deviceremoved(wlc)) { |
@@ -8192,7 +8172,7 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded) | |||
8192 | /* ATIM window end */ | 8172 | /* ATIM window end */ |
8193 | if (macintstatus & MI_ATIMWINEND) { | 8173 | if (macintstatus & MI_ATIMWINEND) { |
8194 | BCMMSG(wlc->wiphy, "end of ATIM window\n"); | 8174 | BCMMSG(wlc->wiphy, "end of ATIM window\n"); |
8195 | OR_REG(®s->maccommand, wlc->qvalid); | 8175 | bcma_set32(core, D11REGOFFS(maccommand), wlc->qvalid); |
8196 | wlc->qvalid = 0; | 8176 | wlc->qvalid = 0; |
8197 | } | 8177 | } |
8198 | 8178 | ||
@@ -8210,17 +8190,17 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded) | |||
8210 | 8190 | ||
8211 | if (macintstatus & MI_GP0) { | 8191 | if (macintstatus & MI_GP0) { |
8212 | wiphy_err(wiphy, "wl%d: PSM microcode watchdog fired at %d " | 8192 | wiphy_err(wiphy, "wl%d: PSM microcode watchdog fired at %d " |
8213 | "(seconds). Resetting.\n", wlc_hw->unit, wlc_hw->now); | 8193 | "(seconds). Resetting.\n", wlc_hw->unit, wlc_hw->now); |
8214 | 8194 | ||
8215 | printk_once("%s : PSM Watchdog, chipid 0x%x, chiprev 0x%x\n", | 8195 | printk_once("%s : PSM Watchdog, chipid 0x%x, chiprev 0x%x\n", |
8216 | __func__, wlc_hw->sih->chip, | 8196 | __func__, ai_get_chip_id(wlc_hw->sih), |
8217 | wlc_hw->sih->chiprev); | 8197 | ai_get_chiprev(wlc_hw->sih)); |
8218 | brcms_fatal_error(wlc_hw->wlc->wl); | 8198 | brcms_fatal_error(wlc_hw->wlc->wl); |
8219 | } | 8199 | } |
8220 | 8200 | ||
8221 | /* gptimer timeout */ | 8201 | /* gptimer timeout */ |
8222 | if (macintstatus & MI_TO) | 8202 | if (macintstatus & MI_TO) |
8223 | W_REG(®s->gptimer, 0); | 8203 | bcma_write32(core, D11REGOFFS(gptimer), 0); |
8224 | 8204 | ||
8225 | if (macintstatus & MI_RFDISABLE) { | 8205 | if (macintstatus & MI_RFDISABLE) { |
8226 | BCMMSG(wlc->wiphy, "wl%d: BMAC Detected a change on the" | 8206 | BCMMSG(wlc->wiphy, "wl%d: BMAC Detected a change on the" |
@@ -8242,13 +8222,11 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded) | |||
8242 | 8222 | ||
8243 | void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx) | 8223 | void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx) |
8244 | { | 8224 | { |
8245 | struct d11regs __iomem *regs; | 8225 | struct bcma_device *core = wlc->hw->d11core; |
8246 | u16 chanspec; | 8226 | u16 chanspec; |
8247 | 8227 | ||
8248 | BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); | 8228 | BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); |
8249 | 8229 | ||
8250 | regs = wlc->regs; | ||
8251 | |||
8252 | /* | 8230 | /* |
8253 | * This will happen if a big-hammer was executed. In | 8231 | * This will happen if a big-hammer was executed. In |
8254 | * that case, we want to go back to the channel that | 8232 | * that case, we want to go back to the channel that |
@@ -8278,8 +8256,8 @@ void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx) | |||
8278 | * update since init path would reset | 8256 | * update since init path would reset |
8279 | * to default value | 8257 | * to default value |
8280 | */ | 8258 | */ |
8281 | W_REG(®s->tsf_cfprep, | 8259 | bcma_write32(core, D11REGOFFS(tsf_cfprep), |
8282 | (bi << CFPREP_CBI_SHIFT)); | 8260 | bi << CFPREP_CBI_SHIFT); |
8283 | 8261 | ||
8284 | /* Update maccontrol PM related bits */ | 8262 | /* Update maccontrol PM related bits */ |
8285 | brcms_c_set_ps_ctrl(wlc); | 8263 | brcms_c_set_ps_ctrl(wlc); |
@@ -8309,7 +8287,7 @@ void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx) | |||
8309 | brcms_c_bsinit(wlc); | 8287 | brcms_c_bsinit(wlc); |
8310 | 8288 | ||
8311 | /* Enable EDCF mode (while the MAC is suspended) */ | 8289 | /* Enable EDCF mode (while the MAC is suspended) */ |
8312 | OR_REG(®s->ifs_ctl, IFS_USEEDCF); | 8290 | bcma_set16(core, D11REGOFFS(ifs_ctl), IFS_USEEDCF); |
8313 | brcms_c_edcf_setparams(wlc, false); | 8291 | brcms_c_edcf_setparams(wlc, false); |
8314 | 8292 | ||
8315 | /* Init precedence maps for empty FIFOs */ | 8293 | /* Init precedence maps for empty FIFOs */ |
@@ -8333,7 +8311,7 @@ void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx) | |||
8333 | brcms_c_txflowcontrol_reset(wlc); | 8311 | brcms_c_txflowcontrol_reset(wlc); |
8334 | 8312 | ||
8335 | /* enable the RF Disable Delay timer */ | 8313 | /* enable the RF Disable Delay timer */ |
8336 | W_REG(&wlc->regs->rfdisabledly, RFDISABLE_DEFAULT); | 8314 | bcma_write32(core, D11REGOFFS(rfdisabledly), RFDISABLE_DEFAULT); |
8337 | 8315 | ||
8338 | /* | 8316 | /* |
8339 | * Initialize WME parameters; if they haven't been set by some other | 8317 | * Initialize WME parameters; if they haven't been set by some other |
@@ -8353,9 +8331,8 @@ void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx) | |||
8353 | * The common driver entry routine. Error codes should be unique | 8331 | * The common driver entry routine. Error codes should be unique |
8354 | */ | 8332 | */ |
8355 | struct brcms_c_info * | 8333 | struct brcms_c_info * |
8356 | brcms_c_attach(struct brcms_info *wl, u16 vendor, u16 device, uint unit, | 8334 | brcms_c_attach(struct brcms_info *wl, struct bcma_device *core, uint unit, |
8357 | bool piomode, void __iomem *regsva, struct pci_dev *btparam, | 8335 | bool piomode, uint *perr) |
8358 | uint *perr) | ||
8359 | { | 8336 | { |
8360 | struct brcms_c_info *wlc; | 8337 | struct brcms_c_info *wlc; |
8361 | uint err = 0; | 8338 | uint err = 0; |
@@ -8363,7 +8340,7 @@ brcms_c_attach(struct brcms_info *wl, u16 vendor, u16 device, uint unit, | |||
8363 | struct brcms_pub *pub; | 8340 | struct brcms_pub *pub; |
8364 | 8341 | ||
8365 | /* allocate struct brcms_c_info state and its substructures */ | 8342 | /* allocate struct brcms_c_info state and its substructures */ |
8366 | wlc = (struct brcms_c_info *) brcms_c_attach_malloc(unit, &err, device); | 8343 | wlc = (struct brcms_c_info *) brcms_c_attach_malloc(unit, &err, 0); |
8367 | if (wlc == NULL) | 8344 | if (wlc == NULL) |
8368 | goto fail; | 8345 | goto fail; |
8369 | wlc->wiphy = wl->wiphy; | 8346 | wlc->wiphy = wl->wiphy; |
@@ -8390,8 +8367,7 @@ brcms_c_attach(struct brcms_info *wl, u16 vendor, u16 device, uint unit, | |||
8390 | * low level attach steps(all hw accesses go | 8367 | * low level attach steps(all hw accesses go |
8391 | * inside, no more in rest of the attach) | 8368 | * inside, no more in rest of the attach) |
8392 | */ | 8369 | */ |
8393 | err = brcms_b_attach(wlc, vendor, device, unit, piomode, regsva, | 8370 | err = brcms_b_attach(wlc, core, unit, piomode); |
8394 | btparam); | ||
8395 | if (err) | 8371 | if (err) |
8396 | goto fail; | 8372 | goto fail; |
8397 | 8373 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.h b/drivers/net/wireless/brcm80211/brcmsmac/main.h index e2de97d93635..adb136ec1f04 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/main.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.h | |||
@@ -334,7 +334,7 @@ struct brcms_hardware { | |||
334 | u32 machwcap_backup; /* backup of machwcap */ | 334 | u32 machwcap_backup; /* backup of machwcap */ |
335 | 335 | ||
336 | struct si_pub *sih; /* SI handle (cookie for siutils calls) */ | 336 | struct si_pub *sih; /* SI handle (cookie for siutils calls) */ |
337 | struct d11regs __iomem *regs; /* pointer to device registers */ | 337 | struct bcma_device *d11core; /* pointer to 802.11 core */ |
338 | struct phy_shim_info *physhim; /* phy shim layer handler */ | 338 | struct phy_shim_info *physhim; /* phy shim layer handler */ |
339 | struct shared_phy *phy_sh; /* pointer to shared phy state */ | 339 | struct shared_phy *phy_sh; /* pointer to shared phy state */ |
340 | struct brcms_hw_band *band;/* pointer to active per-band state */ | 340 | struct brcms_hw_band *band;/* pointer to active per-band state */ |
@@ -400,7 +400,6 @@ struct brcms_txq_info { | |||
400 | * | 400 | * |
401 | * pub: pointer to driver public state. | 401 | * pub: pointer to driver public state. |
402 | * wl: pointer to specific private state. | 402 | * wl: pointer to specific private state. |
403 | * regs: pointer to device registers. | ||
404 | * hw: HW related state. | 403 | * hw: HW related state. |
405 | * clkreq_override: setting for clkreq for PCIE : Auto, 0, 1. | 404 | * clkreq_override: setting for clkreq for PCIE : Auto, 0, 1. |
406 | * fastpwrup_dly: time in us needed to bring up d11 fast clock. | 405 | * fastpwrup_dly: time in us needed to bring up d11 fast clock. |
@@ -477,7 +476,6 @@ struct brcms_txq_info { | |||
477 | struct brcms_c_info { | 476 | struct brcms_c_info { |
478 | struct brcms_pub *pub; | 477 | struct brcms_pub *pub; |
479 | struct brcms_info *wl; | 478 | struct brcms_info *wl; |
480 | struct d11regs __iomem *regs; | ||
481 | struct brcms_hardware *hw; | 479 | struct brcms_hardware *hw; |
482 | 480 | ||
483 | /* clock */ | 481 | /* clock */ |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/nicpci.c b/drivers/net/wireless/brcm80211/brcmsmac/nicpci.c index 0bcb26792046..7fad6dc19258 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/nicpci.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/nicpci.c | |||
@@ -139,6 +139,9 @@ | |||
139 | #define SRSH_PI_MASK 0xf000 /* bit 15:12 */ | 139 | #define SRSH_PI_MASK 0xf000 /* bit 15:12 */ |
140 | #define SRSH_PI_SHIFT 12 /* bit 15:12 */ | 140 | #define SRSH_PI_SHIFT 12 /* bit 15:12 */ |
141 | 141 | ||
142 | #define PCIREGOFFS(field) offsetof(struct sbpciregs, field) | ||
143 | #define PCIEREGOFFS(field) offsetof(struct sbpcieregs, field) | ||
144 | |||
142 | /* Sonics side: PCI core and host control registers */ | 145 | /* Sonics side: PCI core and host control registers */ |
143 | struct sbpciregs { | 146 | struct sbpciregs { |
144 | u32 control; /* PCI control */ | 147 | u32 control; /* PCI control */ |
@@ -205,11 +208,7 @@ struct sbpcieregs { | |||
205 | }; | 208 | }; |
206 | 209 | ||
207 | struct pcicore_info { | 210 | struct pcicore_info { |
208 | union { | 211 | struct bcma_device *core; |
209 | struct sbpcieregs __iomem *pcieregs; | ||
210 | struct sbpciregs __iomem *pciregs; | ||
211 | } regs; /* Memory mapped register to the core */ | ||
212 | |||
213 | struct si_pub *sih; /* System interconnect handle */ | 212 | struct si_pub *sih; /* System interconnect handle */ |
214 | struct pci_dev *dev; | 213 | struct pci_dev *dev; |
215 | u8 pciecap_lcreg_offset;/* PCIE capability LCreg offset | 214 | u8 pciecap_lcreg_offset;/* PCIE capability LCreg offset |
@@ -224,9 +223,9 @@ struct pcicore_info { | |||
224 | }; | 223 | }; |
225 | 224 | ||
226 | #define PCIE_ASPM(sih) \ | 225 | #define PCIE_ASPM(sih) \ |
227 | (((sih)->buscoretype == PCIE_CORE_ID) && \ | 226 | ((ai_get_buscoretype(sih) == PCIE_CORE_ID) && \ |
228 | (((sih)->buscorerev >= 3) && \ | 227 | ((ai_get_buscorerev(sih) >= 3) && \ |
229 | ((sih)->buscorerev <= 5))) | 228 | (ai_get_buscorerev(sih) <= 5))) |
230 | 229 | ||
231 | 230 | ||
232 | /* delay needed between the mdio control/ mdiodata register data access */ | 231 | /* delay needed between the mdio control/ mdiodata register data access */ |
@@ -238,8 +237,7 @@ static void pr28829_delay(void) | |||
238 | /* Initialize the PCI core. | 237 | /* Initialize the PCI core. |
239 | * It's caller's responsibility to make sure that this is done only once | 238 | * It's caller's responsibility to make sure that this is done only once |
240 | */ | 239 | */ |
241 | struct pcicore_info *pcicore_init(struct si_pub *sih, struct pci_dev *pdev, | 240 | struct pcicore_info *pcicore_init(struct si_pub *sih, struct bcma_device *core) |
242 | void __iomem *regs) | ||
243 | { | 241 | { |
244 | struct pcicore_info *pi; | 242 | struct pcicore_info *pi; |
245 | 243 | ||
@@ -249,17 +247,15 @@ struct pcicore_info *pcicore_init(struct si_pub *sih, struct pci_dev *pdev, | |||
249 | return NULL; | 247 | return NULL; |
250 | 248 | ||
251 | pi->sih = sih; | 249 | pi->sih = sih; |
252 | pi->dev = pdev; | 250 | pi->dev = core->bus->host_pci; |
251 | pi->core = core; | ||
253 | 252 | ||
254 | if (sih->buscoretype == PCIE_CORE_ID) { | 253 | if (core->id.id == PCIE_CORE_ID) { |
255 | u8 cap_ptr; | 254 | u8 cap_ptr; |
256 | pi->regs.pcieregs = regs; | ||
257 | cap_ptr = pcicore_find_pci_capability(pi->dev, PCI_CAP_ID_EXP, | 255 | cap_ptr = pcicore_find_pci_capability(pi->dev, PCI_CAP_ID_EXP, |
258 | NULL, NULL); | 256 | NULL, NULL); |
259 | pi->pciecap_lcreg_offset = cap_ptr + PCIE_CAP_LINKCTRL_OFFSET; | 257 | pi->pciecap_lcreg_offset = cap_ptr + PCIE_CAP_LINKCTRL_OFFSET; |
260 | } else | 258 | } |
261 | pi->regs.pciregs = regs; | ||
262 | |||
263 | return pi; | 259 | return pi; |
264 | } | 260 | } |
265 | 261 | ||
@@ -334,37 +330,37 @@ end: | |||
334 | 330 | ||
335 | /* ***** Register Access API */ | 331 | /* ***** Register Access API */ |
336 | static uint | 332 | static uint |
337 | pcie_readreg(struct sbpcieregs __iomem *pcieregs, uint addrtype, uint offset) | 333 | pcie_readreg(struct bcma_device *core, uint addrtype, uint offset) |
338 | { | 334 | { |
339 | uint retval = 0xFFFFFFFF; | 335 | uint retval = 0xFFFFFFFF; |
340 | 336 | ||
341 | switch (addrtype) { | 337 | switch (addrtype) { |
342 | case PCIE_CONFIGREGS: | 338 | case PCIE_CONFIGREGS: |
343 | W_REG(&pcieregs->configaddr, offset); | 339 | bcma_write32(core, PCIEREGOFFS(configaddr), offset); |
344 | (void)R_REG((&pcieregs->configaddr)); | 340 | (void)bcma_read32(core, PCIEREGOFFS(configaddr)); |
345 | retval = R_REG(&pcieregs->configdata); | 341 | retval = bcma_read32(core, PCIEREGOFFS(configdata)); |
346 | break; | 342 | break; |
347 | case PCIE_PCIEREGS: | 343 | case PCIE_PCIEREGS: |
348 | W_REG(&pcieregs->pcieindaddr, offset); | 344 | bcma_write32(core, PCIEREGOFFS(pcieindaddr), offset); |
349 | (void)R_REG(&pcieregs->pcieindaddr); | 345 | (void)bcma_read32(core, PCIEREGOFFS(pcieindaddr)); |
350 | retval = R_REG(&pcieregs->pcieinddata); | 346 | retval = bcma_read32(core, PCIEREGOFFS(pcieinddata)); |
351 | break; | 347 | break; |
352 | } | 348 | } |
353 | 349 | ||
354 | return retval; | 350 | return retval; |
355 | } | 351 | } |
356 | 352 | ||
357 | static uint pcie_writereg(struct sbpcieregs __iomem *pcieregs, uint addrtype, | 353 | static uint pcie_writereg(struct bcma_device *core, uint addrtype, |
358 | uint offset, uint val) | 354 | uint offset, uint val) |
359 | { | 355 | { |
360 | switch (addrtype) { | 356 | switch (addrtype) { |
361 | case PCIE_CONFIGREGS: | 357 | case PCIE_CONFIGREGS: |
362 | W_REG((&pcieregs->configaddr), offset); | 358 | bcma_write32(core, PCIEREGOFFS(configaddr), offset); |
363 | W_REG((&pcieregs->configdata), val); | 359 | bcma_write32(core, PCIEREGOFFS(configdata), val); |
364 | break; | 360 | break; |
365 | case PCIE_PCIEREGS: | 361 | case PCIE_PCIEREGS: |
366 | W_REG((&pcieregs->pcieindaddr), offset); | 362 | bcma_write32(core, PCIEREGOFFS(pcieindaddr), offset); |
367 | W_REG((&pcieregs->pcieinddata), val); | 363 | bcma_write32(core, PCIEREGOFFS(pcieinddata), val); |
368 | break; | 364 | break; |
369 | default: | 365 | default: |
370 | break; | 366 | break; |
@@ -374,7 +370,6 @@ static uint pcie_writereg(struct sbpcieregs __iomem *pcieregs, uint addrtype, | |||
374 | 370 | ||
375 | static bool pcie_mdiosetblock(struct pcicore_info *pi, uint blk) | 371 | static bool pcie_mdiosetblock(struct pcicore_info *pi, uint blk) |
376 | { | 372 | { |
377 | struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs; | ||
378 | uint mdiodata, i = 0; | 373 | uint mdiodata, i = 0; |
379 | uint pcie_serdes_spinwait = 200; | 374 | uint pcie_serdes_spinwait = 200; |
380 | 375 | ||
@@ -382,12 +377,13 @@ static bool pcie_mdiosetblock(struct pcicore_info *pi, uint blk) | |||
382 | (MDIODATA_DEV_ADDR << MDIODATA_DEVADDR_SHF) | | 377 | (MDIODATA_DEV_ADDR << MDIODATA_DEVADDR_SHF) | |
383 | (MDIODATA_BLK_ADDR << MDIODATA_REGADDR_SHF) | | 378 | (MDIODATA_BLK_ADDR << MDIODATA_REGADDR_SHF) | |
384 | (blk << 4)); | 379 | (blk << 4)); |
385 | W_REG(&pcieregs->mdiodata, mdiodata); | 380 | bcma_write32(pi->core, PCIEREGOFFS(mdiodata), mdiodata); |
386 | 381 | ||
387 | pr28829_delay(); | 382 | pr28829_delay(); |
388 | /* retry till the transaction is complete */ | 383 | /* retry till the transaction is complete */ |
389 | while (i < pcie_serdes_spinwait) { | 384 | while (i < pcie_serdes_spinwait) { |
390 | if (R_REG(&pcieregs->mdiocontrol) & MDIOCTL_ACCESS_DONE) | 385 | if (bcma_read32(pi->core, PCIEREGOFFS(mdiocontrol)) & |
386 | MDIOCTL_ACCESS_DONE) | ||
391 | break; | 387 | break; |
392 | 388 | ||
393 | udelay(1000); | 389 | udelay(1000); |
@@ -404,15 +400,15 @@ static int | |||
404 | pcie_mdioop(struct pcicore_info *pi, uint physmedia, uint regaddr, bool write, | 400 | pcie_mdioop(struct pcicore_info *pi, uint physmedia, uint regaddr, bool write, |
405 | uint *val) | 401 | uint *val) |
406 | { | 402 | { |
407 | struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs; | ||
408 | uint mdiodata; | 403 | uint mdiodata; |
409 | uint i = 0; | 404 | uint i = 0; |
410 | uint pcie_serdes_spinwait = 10; | 405 | uint pcie_serdes_spinwait = 10; |
411 | 406 | ||
412 | /* enable mdio access to SERDES */ | 407 | /* enable mdio access to SERDES */ |
413 | W_REG(&pcieregs->mdiocontrol, MDIOCTL_PREAM_EN | MDIOCTL_DIVISOR_VAL); | 408 | bcma_write32(pi->core, PCIEREGOFFS(mdiocontrol), |
409 | MDIOCTL_PREAM_EN | MDIOCTL_DIVISOR_VAL); | ||
414 | 410 | ||
415 | if (pi->sih->buscorerev >= 10) { | 411 | if (ai_get_buscorerev(pi->sih) >= 10) { |
416 | /* new serdes is slower in rw, | 412 | /* new serdes is slower in rw, |
417 | * using two layers of reg address mapping | 413 | * using two layers of reg address mapping |
418 | */ | 414 | */ |
@@ -432,20 +428,22 @@ pcie_mdioop(struct pcicore_info *pi, uint physmedia, uint regaddr, bool write, | |||
432 | mdiodata |= (MDIODATA_START | MDIODATA_WRITE | MDIODATA_TA | | 428 | mdiodata |= (MDIODATA_START | MDIODATA_WRITE | MDIODATA_TA | |
433 | *val); | 429 | *val); |
434 | 430 | ||
435 | W_REG(&pcieregs->mdiodata, mdiodata); | 431 | bcma_write32(pi->core, PCIEREGOFFS(mdiodata), mdiodata); |
436 | 432 | ||
437 | pr28829_delay(); | 433 | pr28829_delay(); |
438 | 434 | ||
439 | /* retry till the transaction is complete */ | 435 | /* retry till the transaction is complete */ |
440 | while (i < pcie_serdes_spinwait) { | 436 | while (i < pcie_serdes_spinwait) { |
441 | if (R_REG(&pcieregs->mdiocontrol) & MDIOCTL_ACCESS_DONE) { | 437 | if (bcma_read32(pi->core, PCIEREGOFFS(mdiocontrol)) & |
438 | MDIOCTL_ACCESS_DONE) { | ||
442 | if (!write) { | 439 | if (!write) { |
443 | pr28829_delay(); | 440 | pr28829_delay(); |
444 | *val = (R_REG(&pcieregs->mdiodata) & | 441 | *val = (bcma_read32(pi->core, |
442 | PCIEREGOFFS(mdiodata)) & | ||
445 | MDIODATA_MASK); | 443 | MDIODATA_MASK); |
446 | } | 444 | } |
447 | /* Disable mdio access to SERDES */ | 445 | /* Disable mdio access to SERDES */ |
448 | W_REG(&pcieregs->mdiocontrol, 0); | 446 | bcma_write32(pi->core, PCIEREGOFFS(mdiocontrol), 0); |
449 | return 0; | 447 | return 0; |
450 | } | 448 | } |
451 | udelay(1000); | 449 | udelay(1000); |
@@ -453,7 +451,7 @@ pcie_mdioop(struct pcicore_info *pi, uint physmedia, uint regaddr, bool write, | |||
453 | } | 451 | } |
454 | 452 | ||
455 | /* Timed out. Disable mdio access to SERDES. */ | 453 | /* Timed out. Disable mdio access to SERDES. */ |
456 | W_REG(&pcieregs->mdiocontrol, 0); | 454 | bcma_write32(pi->core, PCIEREGOFFS(mdiocontrol), 0); |
457 | return 1; | 455 | return 1; |
458 | } | 456 | } |
459 | 457 | ||
@@ -502,18 +500,18 @@ static void pcie_extendL1timer(struct pcicore_info *pi, bool extend) | |||
502 | { | 500 | { |
503 | u32 w; | 501 | u32 w; |
504 | struct si_pub *sih = pi->sih; | 502 | struct si_pub *sih = pi->sih; |
505 | struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs; | ||
506 | 503 | ||
507 | if (sih->buscoretype != PCIE_CORE_ID || sih->buscorerev < 7) | 504 | if (ai_get_buscoretype(sih) != PCIE_CORE_ID || |
505 | ai_get_buscorerev(sih) < 7) | ||
508 | return; | 506 | return; |
509 | 507 | ||
510 | w = pcie_readreg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG); | 508 | w = pcie_readreg(pi->core, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG); |
511 | if (extend) | 509 | if (extend) |
512 | w |= PCIE_ASPMTIMER_EXTEND; | 510 | w |= PCIE_ASPMTIMER_EXTEND; |
513 | else | 511 | else |
514 | w &= ~PCIE_ASPMTIMER_EXTEND; | 512 | w &= ~PCIE_ASPMTIMER_EXTEND; |
515 | pcie_writereg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG, w); | 513 | pcie_writereg(pi->core, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG, w); |
516 | w = pcie_readreg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG); | 514 | w = pcie_readreg(pi->core, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG); |
517 | } | 515 | } |
518 | 516 | ||
519 | /* centralized clkreq control policy */ | 517 | /* centralized clkreq control policy */ |
@@ -527,25 +525,27 @@ static void pcie_clkreq_upd(struct pcicore_info *pi, uint state) | |||
527 | pcie_clkreq(pi, 1, 0); | 525 | pcie_clkreq(pi, 1, 0); |
528 | break; | 526 | break; |
529 | case SI_PCIDOWN: | 527 | case SI_PCIDOWN: |
530 | if (sih->buscorerev == 6) { /* turn on serdes PLL down */ | 528 | /* turn on serdes PLL down */ |
531 | ai_corereg(sih, SI_CC_IDX, | 529 | if (ai_get_buscorerev(sih) == 6) { |
532 | offsetof(struct chipcregs, chipcontrol_addr), | 530 | ai_cc_reg(sih, |
533 | ~0, 0); | 531 | offsetof(struct chipcregs, chipcontrol_addr), |
534 | ai_corereg(sih, SI_CC_IDX, | 532 | ~0, 0); |
535 | offsetof(struct chipcregs, chipcontrol_data), | 533 | ai_cc_reg(sih, |
536 | ~0x40, 0); | 534 | offsetof(struct chipcregs, chipcontrol_data), |
535 | ~0x40, 0); | ||
537 | } else if (pi->pcie_pr42767) { | 536 | } else if (pi->pcie_pr42767) { |
538 | pcie_clkreq(pi, 1, 1); | 537 | pcie_clkreq(pi, 1, 1); |
539 | } | 538 | } |
540 | break; | 539 | break; |
541 | case SI_PCIUP: | 540 | case SI_PCIUP: |
542 | if (sih->buscorerev == 6) { /* turn off serdes PLL down */ | 541 | /* turn off serdes PLL down */ |
543 | ai_corereg(sih, SI_CC_IDX, | 542 | if (ai_get_buscorerev(sih) == 6) { |
544 | offsetof(struct chipcregs, chipcontrol_addr), | 543 | ai_cc_reg(sih, |
545 | ~0, 0); | 544 | offsetof(struct chipcregs, chipcontrol_addr), |
546 | ai_corereg(sih, SI_CC_IDX, | 545 | ~0, 0); |
547 | offsetof(struct chipcregs, chipcontrol_data), | 546 | ai_cc_reg(sih, |
548 | ~0x40, 0x40); | 547 | offsetof(struct chipcregs, chipcontrol_data), |
548 | ~0x40, 0x40); | ||
549 | } else if (PCIE_ASPM(sih)) { /* disable clkreq */ | 549 | } else if (PCIE_ASPM(sih)) { /* disable clkreq */ |
550 | pcie_clkreq(pi, 1, 0); | 550 | pcie_clkreq(pi, 1, 0); |
551 | } | 551 | } |
@@ -562,7 +562,7 @@ static void pcie_war_polarity(struct pcicore_info *pi) | |||
562 | if (pi->pcie_polarity != 0) | 562 | if (pi->pcie_polarity != 0) |
563 | return; | 563 | return; |
564 | 564 | ||
565 | w = pcie_readreg(pi->regs.pcieregs, PCIE_PCIEREGS, PCIE_PLP_STATUSREG); | 565 | w = pcie_readreg(pi->core, PCIE_PCIEREGS, PCIE_PLP_STATUSREG); |
566 | 566 | ||
567 | /* Detect the current polarity at attach and force that polarity and | 567 | /* Detect the current polarity at attach and force that polarity and |
568 | * disable changing the polarity | 568 | * disable changing the polarity |
@@ -581,18 +581,15 @@ static void pcie_war_polarity(struct pcicore_info *pi) | |||
581 | */ | 581 | */ |
582 | static void pcie_war_aspm_clkreq(struct pcicore_info *pi) | 582 | static void pcie_war_aspm_clkreq(struct pcicore_info *pi) |
583 | { | 583 | { |
584 | struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs; | ||
585 | struct si_pub *sih = pi->sih; | 584 | struct si_pub *sih = pi->sih; |
586 | u16 val16; | 585 | u16 val16; |
587 | u16 __iomem *reg16; | ||
588 | u32 w; | 586 | u32 w; |
589 | 587 | ||
590 | if (!PCIE_ASPM(sih)) | 588 | if (!PCIE_ASPM(sih)) |
591 | return; | 589 | return; |
592 | 590 | ||
593 | /* bypass this on QT or VSIM */ | 591 | /* bypass this on QT or VSIM */ |
594 | reg16 = &pcieregs->sprom[SRSH_ASPM_OFFSET]; | 592 | val16 = bcma_read16(pi->core, PCIEREGOFFS(sprom[SRSH_ASPM_OFFSET])); |
595 | val16 = R_REG(reg16); | ||
596 | 593 | ||
597 | val16 &= ~SRSH_ASPM_ENB; | 594 | val16 &= ~SRSH_ASPM_ENB; |
598 | if (pi->pcie_war_aspm_ovr == PCIE_ASPM_ENAB) | 595 | if (pi->pcie_war_aspm_ovr == PCIE_ASPM_ENAB) |
@@ -602,15 +599,15 @@ static void pcie_war_aspm_clkreq(struct pcicore_info *pi) | |||
602 | else if (pi->pcie_war_aspm_ovr == PCIE_ASPM_L0s_ENAB) | 599 | else if (pi->pcie_war_aspm_ovr == PCIE_ASPM_L0s_ENAB) |
603 | val16 |= SRSH_ASPM_L0s_ENB; | 600 | val16 |= SRSH_ASPM_L0s_ENB; |
604 | 601 | ||
605 | W_REG(reg16, val16); | 602 | bcma_write16(pi->core, PCIEREGOFFS(sprom[SRSH_ASPM_OFFSET]), val16); |
606 | 603 | ||
607 | pci_read_config_dword(pi->dev, pi->pciecap_lcreg_offset, &w); | 604 | pci_read_config_dword(pi->dev, pi->pciecap_lcreg_offset, &w); |
608 | w &= ~PCIE_ASPM_ENAB; | 605 | w &= ~PCIE_ASPM_ENAB; |
609 | w |= pi->pcie_war_aspm_ovr; | 606 | w |= pi->pcie_war_aspm_ovr; |
610 | pci_write_config_dword(pi->dev, pi->pciecap_lcreg_offset, w); | 607 | pci_write_config_dword(pi->dev, pi->pciecap_lcreg_offset, w); |
611 | 608 | ||
612 | reg16 = &pcieregs->sprom[SRSH_CLKREQ_OFFSET_REV5]; | 609 | val16 = bcma_read16(pi->core, |
613 | val16 = R_REG(reg16); | 610 | PCIEREGOFFS(sprom[SRSH_CLKREQ_OFFSET_REV5])); |
614 | 611 | ||
615 | if (pi->pcie_war_aspm_ovr != PCIE_ASPM_DISAB) { | 612 | if (pi->pcie_war_aspm_ovr != PCIE_ASPM_DISAB) { |
616 | val16 |= SRSH_CLKREQ_ENB; | 613 | val16 |= SRSH_CLKREQ_ENB; |
@@ -618,7 +615,8 @@ static void pcie_war_aspm_clkreq(struct pcicore_info *pi) | |||
618 | } else | 615 | } else |
619 | val16 &= ~SRSH_CLKREQ_ENB; | 616 | val16 &= ~SRSH_CLKREQ_ENB; |
620 | 617 | ||
621 | W_REG(reg16, val16); | 618 | bcma_write16(pi->core, PCIEREGOFFS(sprom[SRSH_CLKREQ_OFFSET_REV5]), |
619 | val16); | ||
622 | } | 620 | } |
623 | 621 | ||
624 | /* Apply the polarity determined at the start */ | 622 | /* Apply the polarity determined at the start */ |
@@ -642,16 +640,15 @@ static void pcie_war_serdes(struct pcicore_info *pi) | |||
642 | /* Needs to happen when coming out of 'standby'/'hibernate' */ | 640 | /* Needs to happen when coming out of 'standby'/'hibernate' */ |
643 | static void pcie_misc_config_fixup(struct pcicore_info *pi) | 641 | static void pcie_misc_config_fixup(struct pcicore_info *pi) |
644 | { | 642 | { |
645 | struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs; | ||
646 | u16 val16; | 643 | u16 val16; |
647 | u16 __iomem *reg16; | ||
648 | 644 | ||
649 | reg16 = &pcieregs->sprom[SRSH_PCIE_MISC_CONFIG]; | 645 | val16 = bcma_read16(pi->core, |
650 | val16 = R_REG(reg16); | 646 | PCIEREGOFFS(sprom[SRSH_PCIE_MISC_CONFIG])); |
651 | 647 | ||
652 | if ((val16 & SRSH_L23READY_EXIT_NOPERST) == 0) { | 648 | if ((val16 & SRSH_L23READY_EXIT_NOPERST) == 0) { |
653 | val16 |= SRSH_L23READY_EXIT_NOPERST; | 649 | val16 |= SRSH_L23READY_EXIT_NOPERST; |
654 | W_REG(reg16, val16); | 650 | bcma_write16(pi->core, |
651 | PCIEREGOFFS(sprom[SRSH_PCIE_MISC_CONFIG]), val16); | ||
655 | } | 652 | } |
656 | } | 653 | } |
657 | 654 | ||
@@ -659,62 +656,57 @@ static void pcie_misc_config_fixup(struct pcicore_info *pi) | |||
659 | /* Needs to happen when coming out of 'standby'/'hibernate' */ | 656 | /* Needs to happen when coming out of 'standby'/'hibernate' */ |
660 | static void pcie_war_noplldown(struct pcicore_info *pi) | 657 | static void pcie_war_noplldown(struct pcicore_info *pi) |
661 | { | 658 | { |
662 | struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs; | ||
663 | u16 __iomem *reg16; | ||
664 | |||
665 | /* turn off serdes PLL down */ | 659 | /* turn off serdes PLL down */ |
666 | ai_corereg(pi->sih, SI_CC_IDX, offsetof(struct chipcregs, chipcontrol), | 660 | ai_cc_reg(pi->sih, offsetof(struct chipcregs, chipcontrol), |
667 | CHIPCTRL_4321_PLL_DOWN, CHIPCTRL_4321_PLL_DOWN); | 661 | CHIPCTRL_4321_PLL_DOWN, CHIPCTRL_4321_PLL_DOWN); |
668 | 662 | ||
669 | /* clear srom shadow backdoor */ | 663 | /* clear srom shadow backdoor */ |
670 | reg16 = &pcieregs->sprom[SRSH_BD_OFFSET]; | 664 | bcma_write16(pi->core, PCIEREGOFFS(sprom[SRSH_BD_OFFSET]), 0); |
671 | W_REG(reg16, 0); | ||
672 | } | 665 | } |
673 | 666 | ||
674 | /* Needs to happen when coming out of 'standby'/'hibernate' */ | 667 | /* Needs to happen when coming out of 'standby'/'hibernate' */ |
675 | static void pcie_war_pci_setup(struct pcicore_info *pi) | 668 | static void pcie_war_pci_setup(struct pcicore_info *pi) |
676 | { | 669 | { |
677 | struct si_pub *sih = pi->sih; | 670 | struct si_pub *sih = pi->sih; |
678 | struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs; | ||
679 | u32 w; | 671 | u32 w; |
680 | 672 | ||
681 | if (sih->buscorerev == 0 || sih->buscorerev == 1) { | 673 | if (ai_get_buscorerev(sih) == 0 || ai_get_buscorerev(sih) == 1) { |
682 | w = pcie_readreg(pcieregs, PCIE_PCIEREGS, | 674 | w = pcie_readreg(pi->core, PCIE_PCIEREGS, |
683 | PCIE_TLP_WORKAROUNDSREG); | 675 | PCIE_TLP_WORKAROUNDSREG); |
684 | w |= 0x8; | 676 | w |= 0x8; |
685 | pcie_writereg(pcieregs, PCIE_PCIEREGS, | 677 | pcie_writereg(pi->core, PCIE_PCIEREGS, |
686 | PCIE_TLP_WORKAROUNDSREG, w); | 678 | PCIE_TLP_WORKAROUNDSREG, w); |
687 | } | 679 | } |
688 | 680 | ||
689 | if (sih->buscorerev == 1) { | 681 | if (ai_get_buscorerev(sih) == 1) { |
690 | w = pcie_readreg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_LCREG); | 682 | w = pcie_readreg(pi->core, PCIE_PCIEREGS, PCIE_DLLP_LCREG); |
691 | w |= 0x40; | 683 | w |= 0x40; |
692 | pcie_writereg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_LCREG, w); | 684 | pcie_writereg(pi->core, PCIE_PCIEREGS, PCIE_DLLP_LCREG, w); |
693 | } | 685 | } |
694 | 686 | ||
695 | if (sih->buscorerev == 0) { | 687 | if (ai_get_buscorerev(sih) == 0) { |
696 | pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_TIMER1, 0x8128); | 688 | pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_TIMER1, 0x8128); |
697 | pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CDR, 0x0100); | 689 | pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CDR, 0x0100); |
698 | pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CDRBW, 0x1466); | 690 | pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CDRBW, 0x1466); |
699 | } else if (PCIE_ASPM(sih)) { | 691 | } else if (PCIE_ASPM(sih)) { |
700 | /* Change the L1 threshold for better performance */ | 692 | /* Change the L1 threshold for better performance */ |
701 | w = pcie_readreg(pcieregs, PCIE_PCIEREGS, | 693 | w = pcie_readreg(pi->core, PCIE_PCIEREGS, |
702 | PCIE_DLLP_PMTHRESHREG); | 694 | PCIE_DLLP_PMTHRESHREG); |
703 | w &= ~PCIE_L1THRESHOLDTIME_MASK; | 695 | w &= ~PCIE_L1THRESHOLDTIME_MASK; |
704 | w |= PCIE_L1THRESHOLD_WARVAL << PCIE_L1THRESHOLDTIME_SHIFT; | 696 | w |= PCIE_L1THRESHOLD_WARVAL << PCIE_L1THRESHOLDTIME_SHIFT; |
705 | pcie_writereg(pcieregs, PCIE_PCIEREGS, | 697 | pcie_writereg(pi->core, PCIE_PCIEREGS, |
706 | PCIE_DLLP_PMTHRESHREG, w); | 698 | PCIE_DLLP_PMTHRESHREG, w); |
707 | 699 | ||
708 | pcie_war_serdes(pi); | 700 | pcie_war_serdes(pi); |
709 | 701 | ||
710 | pcie_war_aspm_clkreq(pi); | 702 | pcie_war_aspm_clkreq(pi); |
711 | } else if (pi->sih->buscorerev == 7) | 703 | } else if (ai_get_buscorerev(pi->sih) == 7) |
712 | pcie_war_noplldown(pi); | 704 | pcie_war_noplldown(pi); |
713 | 705 | ||
714 | /* Note that the fix is actually in the SROM, | 706 | /* Note that the fix is actually in the SROM, |
715 | * that's why this is open-ended | 707 | * that's why this is open-ended |
716 | */ | 708 | */ |
717 | if (pi->sih->buscorerev >= 6) | 709 | if (ai_get_buscorerev(pi->sih) >= 6) |
718 | pcie_misc_config_fixup(pi); | 710 | pcie_misc_config_fixup(pi); |
719 | } | 711 | } |
720 | 712 | ||
@@ -745,7 +737,7 @@ void pcicore_attach(struct pcicore_info *pi, int state) | |||
745 | 737 | ||
746 | void pcicore_hwup(struct pcicore_info *pi) | 738 | void pcicore_hwup(struct pcicore_info *pi) |
747 | { | 739 | { |
748 | if (!pi || pi->sih->buscoretype != PCIE_CORE_ID) | 740 | if (!pi || ai_get_buscoretype(pi->sih) != PCIE_CORE_ID) |
749 | return; | 741 | return; |
750 | 742 | ||
751 | pcie_war_pci_setup(pi); | 743 | pcie_war_pci_setup(pi); |
@@ -753,7 +745,7 @@ void pcicore_hwup(struct pcicore_info *pi) | |||
753 | 745 | ||
754 | void pcicore_up(struct pcicore_info *pi, int state) | 746 | void pcicore_up(struct pcicore_info *pi, int state) |
755 | { | 747 | { |
756 | if (!pi || pi->sih->buscoretype != PCIE_CORE_ID) | 748 | if (!pi || ai_get_buscoretype(pi->sih) != PCIE_CORE_ID) |
757 | return; | 749 | return; |
758 | 750 | ||
759 | /* Restore L1 timer for better performance */ | 751 | /* Restore L1 timer for better performance */ |
@@ -781,7 +773,7 @@ void pcicore_sleep(struct pcicore_info *pi) | |||
781 | 773 | ||
782 | void pcicore_down(struct pcicore_info *pi, int state) | 774 | void pcicore_down(struct pcicore_info *pi, int state) |
783 | { | 775 | { |
784 | if (!pi || pi->sih->buscoretype != PCIE_CORE_ID) | 776 | if (!pi || ai_get_buscoretype(pi->sih) != PCIE_CORE_ID) |
785 | return; | 777 | return; |
786 | 778 | ||
787 | pcie_clkreq_upd(pi, state); | 779 | pcie_clkreq_upd(pi, state); |
@@ -790,46 +782,45 @@ void pcicore_down(struct pcicore_info *pi, int state) | |||
790 | pcie_extendL1timer(pi, false); | 782 | pcie_extendL1timer(pi, false); |
791 | } | 783 | } |
792 | 784 | ||
793 | /* precondition: current core is sii->buscoretype */ | 785 | void pcicore_fixcfg(struct pcicore_info *pi) |
794 | static void pcicore_fixcfg(struct pcicore_info *pi, u16 __iomem *reg16) | ||
795 | { | 786 | { |
796 | struct si_info *sii = (struct si_info *)(pi->sih); | 787 | struct bcma_device *core = pi->core; |
797 | u16 val16; | 788 | u16 val16; |
798 | uint pciidx; | 789 | uint regoff; |
799 | 790 | ||
800 | pciidx = ai_coreidx(&sii->pub); | 791 | switch (pi->core->id.id) { |
801 | val16 = R_REG(reg16); | 792 | case BCMA_CORE_PCI: |
802 | if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) != (u16)pciidx) { | 793 | regoff = PCIREGOFFS(sprom[SRSH_PI_OFFSET]); |
803 | val16 = (u16)(pciidx << SRSH_PI_SHIFT) | | 794 | break; |
804 | (val16 & ~SRSH_PI_MASK); | ||
805 | W_REG(reg16, val16); | ||
806 | } | ||
807 | } | ||
808 | 795 | ||
809 | void | 796 | case BCMA_CORE_PCIE: |
810 | pcicore_fixcfg_pci(struct pcicore_info *pi, struct sbpciregs __iomem *pciregs) | 797 | regoff = PCIEREGOFFS(sprom[SRSH_PI_OFFSET]); |
811 | { | 798 | break; |
812 | pcicore_fixcfg(pi, &pciregs->sprom[SRSH_PI_OFFSET]); | ||
813 | } | ||
814 | 799 | ||
815 | void pcicore_fixcfg_pcie(struct pcicore_info *pi, | 800 | default: |
816 | struct sbpcieregs __iomem *pcieregs) | 801 | return; |
817 | { | 802 | } |
818 | pcicore_fixcfg(pi, &pcieregs->sprom[SRSH_PI_OFFSET]); | 803 | |
804 | val16 = bcma_read16(pi->core, regoff); | ||
805 | if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) != | ||
806 | (u16)core->core_index) { | ||
807 | val16 = ((u16)core->core_index << SRSH_PI_SHIFT) | | ||
808 | (val16 & ~SRSH_PI_MASK); | ||
809 | bcma_write16(pi->core, regoff, val16); | ||
810 | } | ||
819 | } | 811 | } |
820 | 812 | ||
821 | /* precondition: current core is pci core */ | 813 | /* precondition: current core is pci core */ |
822 | void | 814 | void |
823 | pcicore_pci_setup(struct pcicore_info *pi, struct sbpciregs __iomem *pciregs) | 815 | pcicore_pci_setup(struct pcicore_info *pi) |
824 | { | 816 | { |
825 | u32 w; | 817 | bcma_set32(pi->core, PCIREGOFFS(sbtopci2), |
826 | 818 | SBTOPCI_PREF | SBTOPCI_BURST); | |
827 | OR_REG(&pciregs->sbtopci2, SBTOPCI_PREF | SBTOPCI_BURST); | 819 | |
828 | 820 | if (pi->core->id.rev >= 11) { | |
829 | if (((struct si_info *)(pi->sih))->pub.buscorerev >= 11) { | 821 | bcma_set32(pi->core, PCIREGOFFS(sbtopci2), |
830 | OR_REG(&pciregs->sbtopci2, SBTOPCI_RC_READMULTI); | 822 | SBTOPCI_RC_READMULTI); |
831 | w = R_REG(&pciregs->clkrun); | 823 | bcma_set32(pi->core, PCIREGOFFS(clkrun), PCI_CLKRUN_DSBL); |
832 | W_REG(&pciregs->clkrun, w | PCI_CLKRUN_DSBL); | 824 | (void)bcma_read32(pi->core, PCIREGOFFS(clkrun)); |
833 | w = R_REG(&pciregs->clkrun); | ||
834 | } | 825 | } |
835 | } | 826 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/nicpci.h b/drivers/net/wireless/brcm80211/brcmsmac/nicpci.h index 58aa80dc3329..9fc3ead540a8 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/nicpci.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/nicpci.h | |||
@@ -62,8 +62,7 @@ struct sbpciregs; | |||
62 | struct sbpcieregs; | 62 | struct sbpcieregs; |
63 | 63 | ||
64 | extern struct pcicore_info *pcicore_init(struct si_pub *sih, | 64 | extern struct pcicore_info *pcicore_init(struct si_pub *sih, |
65 | struct pci_dev *pdev, | 65 | struct bcma_device *core); |
66 | void __iomem *regs); | ||
67 | extern void pcicore_deinit(struct pcicore_info *pch); | 66 | extern void pcicore_deinit(struct pcicore_info *pch); |
68 | extern void pcicore_attach(struct pcicore_info *pch, int state); | 67 | extern void pcicore_attach(struct pcicore_info *pch, int state); |
69 | extern void pcicore_hwup(struct pcicore_info *pch); | 68 | extern void pcicore_hwup(struct pcicore_info *pch); |
@@ -72,11 +71,7 @@ extern void pcicore_sleep(struct pcicore_info *pch); | |||
72 | extern void pcicore_down(struct pcicore_info *pch, int state); | 71 | extern void pcicore_down(struct pcicore_info *pch, int state); |
73 | extern u8 pcicore_find_pci_capability(struct pci_dev *dev, u8 req_cap_id, | 72 | extern u8 pcicore_find_pci_capability(struct pci_dev *dev, u8 req_cap_id, |
74 | unsigned char *buf, u32 *buflen); | 73 | unsigned char *buf, u32 *buflen); |
75 | extern void pcicore_fixcfg_pci(struct pcicore_info *pch, | 74 | extern void pcicore_fixcfg(struct pcicore_info *pch); |
76 | struct sbpciregs __iomem *pciregs); | 75 | extern void pcicore_pci_setup(struct pcicore_info *pch); |
77 | extern void pcicore_fixcfg_pcie(struct pcicore_info *pch, | ||
78 | struct sbpcieregs __iomem *pciregs); | ||
79 | extern void pcicore_pci_setup(struct pcicore_info *pch, | ||
80 | struct sbpciregs __iomem *pciregs); | ||
81 | 76 | ||
82 | #endif /* _BRCM_NICPCI_H_ */ | 77 | #endif /* _BRCM_NICPCI_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/otp.c b/drivers/net/wireless/brcm80211/brcmsmac/otp.c index edf551561fd8..f1ca12625860 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/otp.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/otp.c | |||
@@ -77,7 +77,7 @@ struct otp_fn_s { | |||
77 | }; | 77 | }; |
78 | 78 | ||
79 | struct otpinfo { | 79 | struct otpinfo { |
80 | uint ccrev; /* chipc revision */ | 80 | struct bcma_device *core; /* chipc core */ |
81 | const struct otp_fn_s *fn; /* OTP functions */ | 81 | const struct otp_fn_s *fn; /* OTP functions */ |
82 | struct si_pub *sih; /* Saved sb handle */ | 82 | struct si_pub *sih; /* Saved sb handle */ |
83 | 83 | ||
@@ -133,9 +133,10 @@ struct otpinfo { | |||
133 | #define OTP_SZ_FU_144 (144/8) /* 144 bits */ | 133 | #define OTP_SZ_FU_144 (144/8) /* 144 bits */ |
134 | 134 | ||
135 | static u16 | 135 | static u16 |
136 | ipxotp_otpr(struct otpinfo *oi, struct chipcregs __iomem *cc, uint wn) | 136 | ipxotp_otpr(struct otpinfo *oi, uint wn) |
137 | { | 137 | { |
138 | return R_REG(&cc->sromotp[wn]); | 138 | return bcma_read16(oi->core, |
139 | CHIPCREGOFFS(sromotp[wn])); | ||
139 | } | 140 | } |
140 | 141 | ||
141 | /* | 142 | /* |
@@ -146,7 +147,7 @@ static int ipxotp_max_rgnsz(struct si_pub *sih, int osizew) | |||
146 | { | 147 | { |
147 | int ret = 0; | 148 | int ret = 0; |
148 | 149 | ||
149 | switch (sih->chip) { | 150 | switch (ai_get_chip_id(sih)) { |
150 | case BCM43224_CHIP_ID: | 151 | case BCM43224_CHIP_ID: |
151 | case BCM43225_CHIP_ID: | 152 | case BCM43225_CHIP_ID: |
152 | ret = osizew * 2 - OTP_SZ_FU_72 - OTP_SZ_CHECKSUM; | 153 | ret = osizew * 2 - OTP_SZ_FU_72 - OTP_SZ_CHECKSUM; |
@@ -161,19 +162,21 @@ static int ipxotp_max_rgnsz(struct si_pub *sih, int osizew) | |||
161 | return ret; | 162 | return ret; |
162 | } | 163 | } |
163 | 164 | ||
164 | static void _ipxotp_init(struct otpinfo *oi, struct chipcregs __iomem *cc) | 165 | static void _ipxotp_init(struct otpinfo *oi) |
165 | { | 166 | { |
166 | uint k; | 167 | uint k; |
167 | u32 otpp, st; | 168 | u32 otpp, st; |
169 | int ccrev = ai_get_ccrev(oi->sih); | ||
170 | |||
168 | 171 | ||
169 | /* | 172 | /* |
170 | * record word offset of General Use Region | 173 | * record word offset of General Use Region |
171 | * for various chipcommon revs | 174 | * for various chipcommon revs |
172 | */ | 175 | */ |
173 | if (oi->sih->ccrev == 21 || oi->sih->ccrev == 24 | 176 | if (ccrev == 21 || ccrev == 24 |
174 | || oi->sih->ccrev == 27) { | 177 | || ccrev == 27) { |
175 | oi->otpgu_base = REVA4_OTPGU_BASE; | 178 | oi->otpgu_base = REVA4_OTPGU_BASE; |
176 | } else if (oi->sih->ccrev == 36) { | 179 | } else if (ccrev == 36) { |
177 | /* | 180 | /* |
178 | * OTP size greater than equal to 2KB (128 words), | 181 | * OTP size greater than equal to 2KB (128 words), |
179 | * otpgu_base is similar to rev23 | 182 | * otpgu_base is similar to rev23 |
@@ -182,7 +185,7 @@ static void _ipxotp_init(struct otpinfo *oi, struct chipcregs __iomem *cc) | |||
182 | oi->otpgu_base = REVB8_OTPGU_BASE; | 185 | oi->otpgu_base = REVB8_OTPGU_BASE; |
183 | else | 186 | else |
184 | oi->otpgu_base = REV36_OTPGU_BASE; | 187 | oi->otpgu_base = REV36_OTPGU_BASE; |
185 | } else if (oi->sih->ccrev == 23 || oi->sih->ccrev >= 25) { | 188 | } else if (ccrev == 23 || ccrev >= 25) { |
186 | oi->otpgu_base = REVB8_OTPGU_BASE; | 189 | oi->otpgu_base = REVB8_OTPGU_BASE; |
187 | } | 190 | } |
188 | 191 | ||
@@ -190,24 +193,21 @@ static void _ipxotp_init(struct otpinfo *oi, struct chipcregs __iomem *cc) | |||
190 | otpp = | 193 | otpp = |
191 | OTPP_START_BUSY | ((OTPPOC_INIT << OTPP_OC_SHIFT) & OTPP_OC_MASK); | 194 | OTPP_START_BUSY | ((OTPPOC_INIT << OTPP_OC_SHIFT) & OTPP_OC_MASK); |
192 | 195 | ||
193 | W_REG(&cc->otpprog, otpp); | 196 | bcma_write32(oi->core, CHIPCREGOFFS(otpprog), otpp); |
194 | for (k = 0; | 197 | st = bcma_read32(oi->core, CHIPCREGOFFS(otpprog)); |
195 | ((st = R_REG(&cc->otpprog)) & OTPP_START_BUSY) | 198 | for (k = 0; (st & OTPP_START_BUSY) && (k < OTPP_TRIES); k++) |
196 | && (k < OTPP_TRIES); k++) | 199 | st = bcma_read32(oi->core, CHIPCREGOFFS(otpprog)); |
197 | ; | ||
198 | if (k >= OTPP_TRIES) | 200 | if (k >= OTPP_TRIES) |
199 | return; | 201 | return; |
200 | 202 | ||
201 | /* Read OTP lock bits and subregion programmed indication bits */ | 203 | /* Read OTP lock bits and subregion programmed indication bits */ |
202 | oi->status = R_REG(&cc->otpstatus); | 204 | oi->status = bcma_read32(oi->core, CHIPCREGOFFS(otpstatus)); |
203 | 205 | ||
204 | if ((oi->sih->chip == BCM43224_CHIP_ID) | 206 | if ((ai_get_chip_id(oi->sih) == BCM43224_CHIP_ID) |
205 | || (oi->sih->chip == BCM43225_CHIP_ID)) { | 207 | || (ai_get_chip_id(oi->sih) == BCM43225_CHIP_ID)) { |
206 | u32 p_bits; | 208 | u32 p_bits; |
207 | p_bits = | 209 | p_bits = (ipxotp_otpr(oi, oi->otpgu_base + OTPGU_P_OFF) & |
208 | (ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_P_OFF) & | 210 | OTPGU_P_MSK) >> OTPGU_P_SHIFT; |
209 | OTPGU_P_MSK) | ||
210 | >> OTPGU_P_SHIFT; | ||
211 | oi->status |= (p_bits << OTPS_GUP_SHIFT); | 211 | oi->status |= (p_bits << OTPS_GUP_SHIFT); |
212 | } | 212 | } |
213 | 213 | ||
@@ -220,7 +220,7 @@ static void _ipxotp_init(struct otpinfo *oi, struct chipcregs __iomem *cc) | |||
220 | oi->hwlim = oi->wsize; | 220 | oi->hwlim = oi->wsize; |
221 | if (oi->status & OTPS_GUP_HW) { | 221 | if (oi->status & OTPS_GUP_HW) { |
222 | oi->hwlim = | 222 | oi->hwlim = |
223 | ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF) / 16; | 223 | ipxotp_otpr(oi, oi->otpgu_base + OTPGU_HSB_OFF) / 16; |
224 | oi->swbase = oi->hwlim; | 224 | oi->swbase = oi->hwlim; |
225 | } else | 225 | } else |
226 | oi->swbase = oi->hwbase; | 226 | oi->swbase = oi->hwbase; |
@@ -230,7 +230,7 @@ static void _ipxotp_init(struct otpinfo *oi, struct chipcregs __iomem *cc) | |||
230 | 230 | ||
231 | if (oi->status & OTPS_GUP_SW) { | 231 | if (oi->status & OTPS_GUP_SW) { |
232 | oi->swlim = | 232 | oi->swlim = |
233 | ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_SFB_OFF) / 16; | 233 | ipxotp_otpr(oi, oi->otpgu_base + OTPGU_SFB_OFF) / 16; |
234 | oi->fbase = oi->swlim; | 234 | oi->fbase = oi->swlim; |
235 | } else | 235 | } else |
236 | oi->fbase = oi->swbase; | 236 | oi->fbase = oi->swbase; |
@@ -240,11 +240,8 @@ static void _ipxotp_init(struct otpinfo *oi, struct chipcregs __iomem *cc) | |||
240 | 240 | ||
241 | static int ipxotp_init(struct si_pub *sih, struct otpinfo *oi) | 241 | static int ipxotp_init(struct si_pub *sih, struct otpinfo *oi) |
242 | { | 242 | { |
243 | uint idx; | ||
244 | struct chipcregs __iomem *cc; | ||
245 | |||
246 | /* Make sure we're running IPX OTP */ | 243 | /* Make sure we're running IPX OTP */ |
247 | if (!OTPTYPE_IPX(sih->ccrev)) | 244 | if (!OTPTYPE_IPX(ai_get_ccrev(sih))) |
248 | return -EBADE; | 245 | return -EBADE; |
249 | 246 | ||
250 | /* Make sure OTP is not disabled */ | 247 | /* Make sure OTP is not disabled */ |
@@ -252,7 +249,7 @@ static int ipxotp_init(struct si_pub *sih, struct otpinfo *oi) | |||
252 | return -EBADE; | 249 | return -EBADE; |
253 | 250 | ||
254 | /* Check for otp size */ | 251 | /* Check for otp size */ |
255 | switch ((sih->cccaps & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT) { | 252 | switch ((ai_get_cccaps(sih) & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT) { |
256 | case 0: | 253 | case 0: |
257 | /* Nothing there */ | 254 | /* Nothing there */ |
258 | return -EBADE; | 255 | return -EBADE; |
@@ -282,21 +279,13 @@ static int ipxotp_init(struct si_pub *sih, struct otpinfo *oi) | |||
282 | } | 279 | } |
283 | 280 | ||
284 | /* Retrieve OTP region info */ | 281 | /* Retrieve OTP region info */ |
285 | idx = ai_coreidx(sih); | 282 | _ipxotp_init(oi); |
286 | cc = ai_setcoreidx(sih, SI_CC_IDX); | ||
287 | |||
288 | _ipxotp_init(oi, cc); | ||
289 | |||
290 | ai_setcoreidx(sih, idx); | ||
291 | |||
292 | return 0; | 283 | return 0; |
293 | } | 284 | } |
294 | 285 | ||
295 | static int | 286 | static int |
296 | ipxotp_read_region(struct otpinfo *oi, int region, u16 *data, uint *wlen) | 287 | ipxotp_read_region(struct otpinfo *oi, int region, u16 *data, uint *wlen) |
297 | { | 288 | { |
298 | uint idx; | ||
299 | struct chipcregs __iomem *cc; | ||
300 | uint base, i, sz; | 289 | uint base, i, sz; |
301 | 290 | ||
302 | /* Validate region selection */ | 291 | /* Validate region selection */ |
@@ -365,14 +354,10 @@ ipxotp_read_region(struct otpinfo *oi, int region, u16 *data, uint *wlen) | |||
365 | return -EINVAL; | 354 | return -EINVAL; |
366 | } | 355 | } |
367 | 356 | ||
368 | idx = ai_coreidx(oi->sih); | ||
369 | cc = ai_setcoreidx(oi->sih, SI_CC_IDX); | ||
370 | |||
371 | /* Read the data */ | 357 | /* Read the data */ |
372 | for (i = 0; i < sz; i++) | 358 | for (i = 0; i < sz; i++) |
373 | data[i] = ipxotp_otpr(oi, cc, base + i); | 359 | data[i] = ipxotp_otpr(oi, base + i); |
374 | 360 | ||
375 | ai_setcoreidx(oi->sih, idx); | ||
376 | *wlen = sz; | 361 | *wlen = sz; |
377 | return 0; | 362 | return 0; |
378 | } | 363 | } |
@@ -384,14 +369,13 @@ static const struct otp_fn_s ipxotp_fn = { | |||
384 | 369 | ||
385 | static int otp_init(struct si_pub *sih, struct otpinfo *oi) | 370 | static int otp_init(struct si_pub *sih, struct otpinfo *oi) |
386 | { | 371 | { |
387 | |||
388 | int ret; | 372 | int ret; |
389 | 373 | ||
390 | memset(oi, 0, sizeof(struct otpinfo)); | 374 | memset(oi, 0, sizeof(struct otpinfo)); |
391 | 375 | ||
392 | oi->ccrev = sih->ccrev; | 376 | oi->core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0); |
393 | 377 | ||
394 | if (OTPTYPE_IPX(oi->ccrev)) | 378 | if (OTPTYPE_IPX(ai_get_ccrev(sih))) |
395 | oi->fn = &ipxotp_fn; | 379 | oi->fn = &ipxotp_fn; |
396 | 380 | ||
397 | if (oi->fn == NULL) | 381 | if (oi->fn == NULL) |
@@ -399,7 +383,7 @@ static int otp_init(struct si_pub *sih, struct otpinfo *oi) | |||
399 | 383 | ||
400 | oi->sih = sih; | 384 | oi->sih = sih; |
401 | 385 | ||
402 | ret = (oi->fn->init) (sih, oi); | 386 | ret = (oi->fn->init)(sih, oi); |
403 | 387 | ||
404 | return ret; | 388 | return ret; |
405 | } | 389 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c index 008aab9c777c..264f8c4c703d 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c | |||
@@ -149,9 +149,8 @@ void wlc_radioreg_enter(struct brcms_phy_pub *pih) | |||
149 | void wlc_radioreg_exit(struct brcms_phy_pub *pih) | 149 | void wlc_radioreg_exit(struct brcms_phy_pub *pih) |
150 | { | 150 | { |
151 | struct brcms_phy *pi = (struct brcms_phy *) pih; | 151 | struct brcms_phy *pi = (struct brcms_phy *) pih; |
152 | u16 dummy; | ||
153 | 152 | ||
154 | dummy = R_REG(&pi->regs->phyversion); | 153 | (void)bcma_read16(pi->d11core, D11REGOFFS(phyversion)); |
155 | pi->phy_wreg = 0; | 154 | pi->phy_wreg = 0; |
156 | wlapi_bmac_mctrl(pi->sh->physhim, MCTL_LOCK_RADIO, 0); | 155 | wlapi_bmac_mctrl(pi->sh->physhim, MCTL_LOCK_RADIO, 0); |
157 | } | 156 | } |
@@ -186,11 +185,11 @@ u16 read_radio_reg(struct brcms_phy *pi, u16 addr) | |||
186 | if ((D11REV_GE(pi->sh->corerev, 24)) || | 185 | if ((D11REV_GE(pi->sh->corerev, 24)) || |
187 | (D11REV_IS(pi->sh->corerev, 22) | 186 | (D11REV_IS(pi->sh->corerev, 22) |
188 | && (pi->pubpi.phy_type != PHY_TYPE_SSN))) { | 187 | && (pi->pubpi.phy_type != PHY_TYPE_SSN))) { |
189 | W_REG_FLUSH(&pi->regs->radioregaddr, addr); | 188 | bcma_wflush16(pi->d11core, D11REGOFFS(radioregaddr), addr); |
190 | data = R_REG(&pi->regs->radioregdata); | 189 | data = bcma_read16(pi->d11core, D11REGOFFS(radioregdata)); |
191 | } else { | 190 | } else { |
192 | W_REG_FLUSH(&pi->regs->phy4waddr, addr); | 191 | bcma_wflush16(pi->d11core, D11REGOFFS(phy4waddr), addr); |
193 | data = R_REG(&pi->regs->phy4wdatalo); | 192 | data = bcma_read16(pi->d11core, D11REGOFFS(phy4wdatalo)); |
194 | } | 193 | } |
195 | pi->phy_wreg = 0; | 194 | pi->phy_wreg = 0; |
196 | 195 | ||
@@ -203,15 +202,15 @@ void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val) | |||
203 | (D11REV_IS(pi->sh->corerev, 22) | 202 | (D11REV_IS(pi->sh->corerev, 22) |
204 | && (pi->pubpi.phy_type != PHY_TYPE_SSN))) { | 203 | && (pi->pubpi.phy_type != PHY_TYPE_SSN))) { |
205 | 204 | ||
206 | W_REG_FLUSH(&pi->regs->radioregaddr, addr); | 205 | bcma_wflush16(pi->d11core, D11REGOFFS(radioregaddr), addr); |
207 | W_REG(&pi->regs->radioregdata, val); | 206 | bcma_write16(pi->d11core, D11REGOFFS(radioregdata), val); |
208 | } else { | 207 | } else { |
209 | W_REG_FLUSH(&pi->regs->phy4waddr, addr); | 208 | bcma_wflush16(pi->d11core, D11REGOFFS(phy4waddr), addr); |
210 | W_REG(&pi->regs->phy4wdatalo, val); | 209 | bcma_write16(pi->d11core, D11REGOFFS(phy4wdatalo), val); |
211 | } | 210 | } |
212 | 211 | ||
213 | if (++pi->phy_wreg >= pi->phy_wreg_limit) { | 212 | if (++pi->phy_wreg >= pi->phy_wreg_limit) { |
214 | (void)R_REG(&pi->regs->maccontrol); | 213 | (void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol)); |
215 | pi->phy_wreg = 0; | 214 | pi->phy_wreg = 0; |
216 | } | 215 | } |
217 | } | 216 | } |
@@ -223,19 +222,20 @@ static u32 read_radio_id(struct brcms_phy *pi) | |||
223 | if (D11REV_GE(pi->sh->corerev, 24)) { | 222 | if (D11REV_GE(pi->sh->corerev, 24)) { |
224 | u32 b0, b1, b2; | 223 | u32 b0, b1, b2; |
225 | 224 | ||
226 | W_REG_FLUSH(&pi->regs->radioregaddr, 0); | 225 | bcma_wflush16(pi->d11core, D11REGOFFS(radioregaddr), 0); |
227 | b0 = (u32) R_REG(&pi->regs->radioregdata); | 226 | b0 = (u32) bcma_read16(pi->d11core, D11REGOFFS(radioregdata)); |
228 | W_REG_FLUSH(&pi->regs->radioregaddr, 1); | 227 | bcma_wflush16(pi->d11core, D11REGOFFS(radioregaddr), 1); |
229 | b1 = (u32) R_REG(&pi->regs->radioregdata); | 228 | b1 = (u32) bcma_read16(pi->d11core, D11REGOFFS(radioregdata)); |
230 | W_REG_FLUSH(&pi->regs->radioregaddr, 2); | 229 | bcma_wflush16(pi->d11core, D11REGOFFS(radioregaddr), 2); |
231 | b2 = (u32) R_REG(&pi->regs->radioregdata); | 230 | b2 = (u32) bcma_read16(pi->d11core, D11REGOFFS(radioregdata)); |
232 | 231 | ||
233 | id = ((b0 & 0xf) << 28) | (((b2 << 8) | b1) << 12) | ((b0 >> 4) | 232 | id = ((b0 & 0xf) << 28) | (((b2 << 8) | b1) << 12) | ((b0 >> 4) |
234 | & 0xf); | 233 | & 0xf); |
235 | } else { | 234 | } else { |
236 | W_REG_FLUSH(&pi->regs->phy4waddr, RADIO_IDCODE); | 235 | bcma_wflush16(pi->d11core, D11REGOFFS(phy4waddr), RADIO_IDCODE); |
237 | id = (u32) R_REG(&pi->regs->phy4wdatalo); | 236 | id = (u32) bcma_read16(pi->d11core, D11REGOFFS(phy4wdatalo)); |
238 | id |= (u32) R_REG(&pi->regs->phy4wdatahi) << 16; | 237 | id |= (u32) bcma_read16(pi->d11core, |
238 | D11REGOFFS(phy4wdatahi)) << 16; | ||
239 | } | 239 | } |
240 | pi->phy_wreg = 0; | 240 | pi->phy_wreg = 0; |
241 | return id; | 241 | return id; |
@@ -275,75 +275,52 @@ void mod_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val) | |||
275 | 275 | ||
276 | void write_phy_channel_reg(struct brcms_phy *pi, uint val) | 276 | void write_phy_channel_reg(struct brcms_phy *pi, uint val) |
277 | { | 277 | { |
278 | W_REG(&pi->regs->phychannel, val); | 278 | bcma_write16(pi->d11core, D11REGOFFS(phychannel), val); |
279 | } | 279 | } |
280 | 280 | ||
281 | u16 read_phy_reg(struct brcms_phy *pi, u16 addr) | 281 | u16 read_phy_reg(struct brcms_phy *pi, u16 addr) |
282 | { | 282 | { |
283 | struct d11regs __iomem *regs; | 283 | bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), addr); |
284 | |||
285 | regs = pi->regs; | ||
286 | |||
287 | W_REG_FLUSH(®s->phyregaddr, addr); | ||
288 | 284 | ||
289 | pi->phy_wreg = 0; | 285 | pi->phy_wreg = 0; |
290 | return R_REG(®s->phyregdata); | 286 | return bcma_read16(pi->d11core, D11REGOFFS(phyregdata)); |
291 | } | 287 | } |
292 | 288 | ||
293 | void write_phy_reg(struct brcms_phy *pi, u16 addr, u16 val) | 289 | void write_phy_reg(struct brcms_phy *pi, u16 addr, u16 val) |
294 | { | 290 | { |
295 | struct d11regs __iomem *regs; | ||
296 | |||
297 | regs = pi->regs; | ||
298 | |||
299 | #ifdef CONFIG_BCM47XX | 291 | #ifdef CONFIG_BCM47XX |
300 | W_REG_FLUSH(®s->phyregaddr, addr); | 292 | bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), addr); |
301 | W_REG(®s->phyregdata, val); | 293 | bcma_write16(pi->d11core, D11REGOFFS(phyregdata), val); |
302 | if (addr == 0x72) | 294 | if (addr == 0x72) |
303 | (void)R_REG(®s->phyregdata); | 295 | (void)bcma_read16(pi->d11core, D11REGOFFS(phyversion)); |
304 | #else | 296 | #else |
305 | W_REG((u32 __iomem *)(®s->phyregaddr), addr | (val << 16)); | 297 | bcma_write32(pi->d11core, D11REGOFFS(phyregaddr), addr | (val << 16)); |
306 | if (++pi->phy_wreg >= pi->phy_wreg_limit) { | 298 | if (++pi->phy_wreg >= pi->phy_wreg_limit) { |
307 | pi->phy_wreg = 0; | 299 | pi->phy_wreg = 0; |
308 | (void)R_REG(®s->phyversion); | 300 | (void)bcma_read16(pi->d11core, D11REGOFFS(phyversion)); |
309 | } | 301 | } |
310 | #endif | 302 | #endif |
311 | } | 303 | } |
312 | 304 | ||
313 | void and_phy_reg(struct brcms_phy *pi, u16 addr, u16 val) | 305 | void and_phy_reg(struct brcms_phy *pi, u16 addr, u16 val) |
314 | { | 306 | { |
315 | struct d11regs __iomem *regs; | 307 | bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), addr); |
316 | 308 | bcma_mask16(pi->d11core, D11REGOFFS(phyregdata), val); | |
317 | regs = pi->regs; | ||
318 | |||
319 | W_REG_FLUSH(®s->phyregaddr, addr); | ||
320 | |||
321 | W_REG(®s->phyregdata, (R_REG(®s->phyregdata) & val)); | ||
322 | pi->phy_wreg = 0; | 309 | pi->phy_wreg = 0; |
323 | } | 310 | } |
324 | 311 | ||
325 | void or_phy_reg(struct brcms_phy *pi, u16 addr, u16 val) | 312 | void or_phy_reg(struct brcms_phy *pi, u16 addr, u16 val) |
326 | { | 313 | { |
327 | struct d11regs __iomem *regs; | 314 | bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), addr); |
328 | 315 | bcma_set16(pi->d11core, D11REGOFFS(phyregdata), val); | |
329 | regs = pi->regs; | ||
330 | |||
331 | W_REG_FLUSH(®s->phyregaddr, addr); | ||
332 | |||
333 | W_REG(®s->phyregdata, (R_REG(®s->phyregdata) | val)); | ||
334 | pi->phy_wreg = 0; | 316 | pi->phy_wreg = 0; |
335 | } | 317 | } |
336 | 318 | ||
337 | void mod_phy_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val) | 319 | void mod_phy_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val) |
338 | { | 320 | { |
339 | struct d11regs __iomem *regs; | 321 | val &= mask; |
340 | 322 | bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), addr); | |
341 | regs = pi->regs; | 323 | bcma_maskset16(pi->d11core, D11REGOFFS(phyregdata), ~mask, val); |
342 | |||
343 | W_REG_FLUSH(®s->phyregaddr, addr); | ||
344 | |||
345 | W_REG(®s->phyregdata, | ||
346 | ((R_REG(®s->phyregdata) & ~mask) | (val & mask))); | ||
347 | pi->phy_wreg = 0; | 324 | pi->phy_wreg = 0; |
348 | } | 325 | } |
349 | 326 | ||
@@ -404,10 +381,8 @@ struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp) | |||
404 | sh->sromrev = shp->sromrev; | 381 | sh->sromrev = shp->sromrev; |
405 | sh->boardtype = shp->boardtype; | 382 | sh->boardtype = shp->boardtype; |
406 | sh->boardrev = shp->boardrev; | 383 | sh->boardrev = shp->boardrev; |
407 | sh->boardvendor = shp->boardvendor; | ||
408 | sh->boardflags = shp->boardflags; | 384 | sh->boardflags = shp->boardflags; |
409 | sh->boardflags2 = shp->boardflags2; | 385 | sh->boardflags2 = shp->boardflags2; |
410 | sh->buscorerev = shp->buscorerev; | ||
411 | 386 | ||
412 | sh->fast_timer = PHY_SW_TIMER_FAST; | 387 | sh->fast_timer = PHY_SW_TIMER_FAST; |
413 | sh->slow_timer = PHY_SW_TIMER_SLOW; | 388 | sh->slow_timer = PHY_SW_TIMER_SLOW; |
@@ -450,7 +425,7 @@ static u32 wlc_phy_get_radio_ver(struct brcms_phy *pi) | |||
450 | } | 425 | } |
451 | 426 | ||
452 | struct brcms_phy_pub * | 427 | struct brcms_phy_pub * |
453 | wlc_phy_attach(struct shared_phy *sh, struct d11regs __iomem *regs, | 428 | wlc_phy_attach(struct shared_phy *sh, struct bcma_device *d11core, |
454 | int bandtype, struct wiphy *wiphy) | 429 | int bandtype, struct wiphy *wiphy) |
455 | { | 430 | { |
456 | struct brcms_phy *pi; | 431 | struct brcms_phy *pi; |
@@ -462,7 +437,7 @@ wlc_phy_attach(struct shared_phy *sh, struct d11regs __iomem *regs, | |||
462 | if (D11REV_IS(sh->corerev, 4)) | 437 | if (D11REV_IS(sh->corerev, 4)) |
463 | sflags = SISF_2G_PHY | SISF_5G_PHY; | 438 | sflags = SISF_2G_PHY | SISF_5G_PHY; |
464 | else | 439 | else |
465 | sflags = ai_core_sflags(sh->sih, 0, 0); | 440 | sflags = bcma_aread32(d11core, BCMA_IOST); |
466 | 441 | ||
467 | if (bandtype == BRCM_BAND_5G) { | 442 | if (bandtype == BRCM_BAND_5G) { |
468 | if ((sflags & (SISF_5G_PHY | SISF_DB_PHY)) == 0) | 443 | if ((sflags & (SISF_5G_PHY | SISF_DB_PHY)) == 0) |
@@ -480,7 +455,7 @@ wlc_phy_attach(struct shared_phy *sh, struct d11regs __iomem *regs, | |||
480 | if (pi == NULL) | 455 | if (pi == NULL) |
481 | return NULL; | 456 | return NULL; |
482 | pi->wiphy = wiphy; | 457 | pi->wiphy = wiphy; |
483 | pi->regs = regs; | 458 | pi->d11core = d11core; |
484 | pi->sh = sh; | 459 | pi->sh = sh; |
485 | pi->phy_init_por = true; | 460 | pi->phy_init_por = true; |
486 | pi->phy_wreg_limit = PHY_WREG_LIMIT; | 461 | pi->phy_wreg_limit = PHY_WREG_LIMIT; |
@@ -495,7 +470,7 @@ wlc_phy_attach(struct shared_phy *sh, struct d11regs __iomem *regs, | |||
495 | pi->pubpi.coreflags = SICF_GMODE; | 470 | pi->pubpi.coreflags = SICF_GMODE; |
496 | 471 | ||
497 | wlapi_bmac_corereset(pi->sh->physhim, pi->pubpi.coreflags); | 472 | wlapi_bmac_corereset(pi->sh->physhim, pi->pubpi.coreflags); |
498 | phyversion = R_REG(&pi->regs->phyversion); | 473 | phyversion = bcma_read16(pi->d11core, D11REGOFFS(phyversion)); |
499 | 474 | ||
500 | pi->pubpi.phy_type = PHY_TYPE(phyversion); | 475 | pi->pubpi.phy_type = PHY_TYPE(phyversion); |
501 | pi->pubpi.phy_rev = phyversion & PV_PV_MASK; | 476 | pi->pubpi.phy_rev = phyversion & PV_PV_MASK; |
@@ -507,8 +482,8 @@ wlc_phy_attach(struct shared_phy *sh, struct d11regs __iomem *regs, | |||
507 | pi->pubpi.phy_corenum = PHY_CORE_NUM_2; | 482 | pi->pubpi.phy_corenum = PHY_CORE_NUM_2; |
508 | pi->pubpi.ana_rev = (phyversion & PV_AV_MASK) >> PV_AV_SHIFT; | 483 | pi->pubpi.ana_rev = (phyversion & PV_AV_MASK) >> PV_AV_SHIFT; |
509 | 484 | ||
510 | if (!pi->pubpi.phy_type == PHY_TYPE_N && | 485 | if (pi->pubpi.phy_type != PHY_TYPE_N && |
511 | !pi->pubpi.phy_type == PHY_TYPE_LCN) | 486 | pi->pubpi.phy_type != PHY_TYPE_LCN) |
512 | goto err; | 487 | goto err; |
513 | 488 | ||
514 | if (bandtype == BRCM_BAND_5G) { | 489 | if (bandtype == BRCM_BAND_5G) { |
@@ -779,14 +754,14 @@ void wlc_phy_init(struct brcms_phy_pub *pih, u16 chanspec) | |||
779 | 754 | ||
780 | pi->radio_chanspec = chanspec; | 755 | pi->radio_chanspec = chanspec; |
781 | 756 | ||
782 | mc = R_REG(&pi->regs->maccontrol); | 757 | mc = bcma_read32(pi->d11core, D11REGOFFS(maccontrol)); |
783 | if (WARN(mc & MCTL_EN_MAC, "HW error MAC running on init")) | 758 | if (WARN(mc & MCTL_EN_MAC, "HW error MAC running on init")) |
784 | return; | 759 | return; |
785 | 760 | ||
786 | if (!(pi->measure_hold & PHY_HOLD_FOR_SCAN)) | 761 | if (!(pi->measure_hold & PHY_HOLD_FOR_SCAN)) |
787 | pi->measure_hold |= PHY_HOLD_FOR_NOT_ASSOC; | 762 | pi->measure_hold |= PHY_HOLD_FOR_NOT_ASSOC; |
788 | 763 | ||
789 | if (WARN(!(ai_core_sflags(pi->sh->sih, 0, 0) & SISF_FCLKA), | 764 | if (WARN(!(bcma_aread32(pi->d11core, BCMA_IOST) & SISF_FCLKA), |
790 | "HW error SISF_FCLKA\n")) | 765 | "HW error SISF_FCLKA\n")) |
791 | return; | 766 | return; |
792 | 767 | ||
@@ -825,8 +800,8 @@ void wlc_phy_cal_init(struct brcms_phy_pub *pih) | |||
825 | struct brcms_phy *pi = (struct brcms_phy *) pih; | 800 | struct brcms_phy *pi = (struct brcms_phy *) pih; |
826 | void (*cal_init)(struct brcms_phy *) = NULL; | 801 | void (*cal_init)(struct brcms_phy *) = NULL; |
827 | 802 | ||
828 | if (WARN((R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC) != 0, | 803 | if (WARN((bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) & |
829 | "HW error: MAC enabled during phy cal\n")) | 804 | MCTL_EN_MAC) != 0, "HW error: MAC enabled during phy cal\n")) |
830 | return; | 805 | return; |
831 | 806 | ||
832 | if (!pi->initialized) { | 807 | if (!pi->initialized) { |
@@ -1017,7 +992,7 @@ wlc_phy_init_radio_regs(struct brcms_phy *pi, | |||
1017 | void wlc_phy_do_dummy_tx(struct brcms_phy *pi, bool ofdm, bool pa_on) | 992 | void wlc_phy_do_dummy_tx(struct brcms_phy *pi, bool ofdm, bool pa_on) |
1018 | { | 993 | { |
1019 | #define DUMMY_PKT_LEN 20 | 994 | #define DUMMY_PKT_LEN 20 |
1020 | struct d11regs __iomem *regs = pi->regs; | 995 | struct bcma_device *core = pi->d11core; |
1021 | int i, count; | 996 | int i, count; |
1022 | u8 ofdmpkt[DUMMY_PKT_LEN] = { | 997 | u8 ofdmpkt[DUMMY_PKT_LEN] = { |
1023 | 0xcc, 0x01, 0x02, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, | 998 | 0xcc, 0x01, 0x02, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, |
@@ -1033,26 +1008,28 @@ void wlc_phy_do_dummy_tx(struct brcms_phy *pi, bool ofdm, bool pa_on) | |||
1033 | wlapi_bmac_write_template_ram(pi->sh->physhim, 0, DUMMY_PKT_LEN, | 1008 | wlapi_bmac_write_template_ram(pi->sh->physhim, 0, DUMMY_PKT_LEN, |
1034 | dummypkt); | 1009 | dummypkt); |
1035 | 1010 | ||
1036 | W_REG(®s->xmtsel, 0); | 1011 | bcma_write16(core, D11REGOFFS(xmtsel), 0); |
1037 | 1012 | ||
1038 | if (D11REV_GE(pi->sh->corerev, 11)) | 1013 | if (D11REV_GE(pi->sh->corerev, 11)) |
1039 | W_REG(®s->wepctl, 0x100); | 1014 | bcma_write16(core, D11REGOFFS(wepctl), 0x100); |
1040 | else | 1015 | else |
1041 | W_REG(®s->wepctl, 0); | 1016 | bcma_write16(core, D11REGOFFS(wepctl), 0); |
1042 | 1017 | ||
1043 | W_REG(®s->txe_phyctl, (ofdm ? 1 : 0) | PHY_TXC_ANT_0); | 1018 | bcma_write16(core, D11REGOFFS(txe_phyctl), |
1019 | (ofdm ? 1 : 0) | PHY_TXC_ANT_0); | ||
1044 | if (ISNPHY(pi) || ISLCNPHY(pi)) | 1020 | if (ISNPHY(pi) || ISLCNPHY(pi)) |
1045 | W_REG(®s->txe_phyctl1, 0x1A02); | 1021 | bcma_write16(core, D11REGOFFS(txe_phyctl1), 0x1A02); |
1046 | 1022 | ||
1047 | W_REG(®s->txe_wm_0, 0); | 1023 | bcma_write16(core, D11REGOFFS(txe_wm_0), 0); |
1048 | W_REG(®s->txe_wm_1, 0); | 1024 | bcma_write16(core, D11REGOFFS(txe_wm_1), 0); |
1049 | 1025 | ||
1050 | W_REG(®s->xmttplatetxptr, 0); | 1026 | bcma_write16(core, D11REGOFFS(xmttplatetxptr), 0); |
1051 | W_REG(®s->xmttxcnt, DUMMY_PKT_LEN); | 1027 | bcma_write16(core, D11REGOFFS(xmttxcnt), DUMMY_PKT_LEN); |
1052 | 1028 | ||
1053 | W_REG(®s->xmtsel, ((8 << 8) | (1 << 5) | (1 << 2) | 2)); | 1029 | bcma_write16(core, D11REGOFFS(xmtsel), |
1030 | ((8 << 8) | (1 << 5) | (1 << 2) | 2)); | ||
1054 | 1031 | ||
1055 | W_REG(®s->txe_ctl, 0); | 1032 | bcma_write16(core, D11REGOFFS(txe_ctl), 0); |
1056 | 1033 | ||
1057 | if (!pa_on) { | 1034 | if (!pa_on) { |
1058 | if (ISNPHY(pi)) | 1035 | if (ISNPHY(pi)) |
@@ -1060,27 +1037,28 @@ void wlc_phy_do_dummy_tx(struct brcms_phy *pi, bool ofdm, bool pa_on) | |||
1060 | } | 1037 | } |
1061 | 1038 | ||
1062 | if (ISNPHY(pi) || ISLCNPHY(pi)) | 1039 | if (ISNPHY(pi) || ISLCNPHY(pi)) |
1063 | W_REG(®s->txe_aux, 0xD0); | 1040 | bcma_write16(core, D11REGOFFS(txe_aux), 0xD0); |
1064 | else | 1041 | else |
1065 | W_REG(®s->txe_aux, ((1 << 5) | (1 << 4))); | 1042 | bcma_write16(core, D11REGOFFS(txe_aux), ((1 << 5) | (1 << 4))); |
1066 | 1043 | ||
1067 | (void)R_REG(®s->txe_aux); | 1044 | (void)bcma_read16(core, D11REGOFFS(txe_aux)); |
1068 | 1045 | ||
1069 | i = 0; | 1046 | i = 0; |
1070 | count = ofdm ? 30 : 250; | 1047 | count = ofdm ? 30 : 250; |
1071 | while ((i++ < count) | 1048 | while ((i++ < count) |
1072 | && (R_REG(®s->txe_status) & (1 << 7))) | 1049 | && (bcma_read16(core, D11REGOFFS(txe_status)) & (1 << 7))) |
1073 | udelay(10); | 1050 | udelay(10); |
1074 | 1051 | ||
1075 | i = 0; | 1052 | i = 0; |
1076 | 1053 | ||
1077 | while ((i++ < 10) | 1054 | while ((i++ < 10) && |
1078 | && ((R_REG(®s->txe_status) & (1 << 10)) == 0)) | 1055 | ((bcma_read16(core, D11REGOFFS(txe_status)) & (1 << 10)) == 0)) |
1079 | udelay(10); | 1056 | udelay(10); |
1080 | 1057 | ||
1081 | i = 0; | 1058 | i = 0; |
1082 | 1059 | ||
1083 | while ((i++ < 10) && ((R_REG(®s->ifsstat) & (1 << 8)))) | 1060 | while ((i++ < 10) && |
1061 | ((bcma_read16(core, D11REGOFFS(ifsstat)) & (1 << 8)))) | ||
1084 | udelay(10); | 1062 | udelay(10); |
1085 | 1063 | ||
1086 | if (!pa_on) { | 1064 | if (!pa_on) { |
@@ -1137,7 +1115,7 @@ static bool wlc_phy_cal_txpower_recalc_sw(struct brcms_phy *pi) | |||
1137 | void wlc_phy_switch_radio(struct brcms_phy_pub *pih, bool on) | 1115 | void wlc_phy_switch_radio(struct brcms_phy_pub *pih, bool on) |
1138 | { | 1116 | { |
1139 | struct brcms_phy *pi = (struct brcms_phy *) pih; | 1117 | struct brcms_phy *pi = (struct brcms_phy *) pih; |
1140 | (void)R_REG(&pi->regs->maccontrol); | 1118 | (void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol)); |
1141 | 1119 | ||
1142 | if (ISNPHY(pi)) { | 1120 | if (ISNPHY(pi)) { |
1143 | wlc_phy_switch_radio_nphy(pi, on); | 1121 | wlc_phy_switch_radio_nphy(pi, on); |
@@ -1377,7 +1355,7 @@ void wlc_phy_txpower_target_set(struct brcms_phy_pub *ppi, | |||
1377 | memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_SDM], | 1355 | memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_SDM], |
1378 | &txpwr->mcs_40_mimo[0], BRCMS_NUM_RATES_MCS_2_STREAM); | 1356 | &txpwr->mcs_40_mimo[0], BRCMS_NUM_RATES_MCS_2_STREAM); |
1379 | 1357 | ||
1380 | if (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC) | 1358 | if (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) & MCTL_EN_MAC) |
1381 | mac_enabled = true; | 1359 | mac_enabled = true; |
1382 | 1360 | ||
1383 | if (mac_enabled) | 1361 | if (mac_enabled) |
@@ -1407,7 +1385,8 @@ int wlc_phy_txpower_set(struct brcms_phy_pub *ppi, uint qdbm, bool override) | |||
1407 | if (!SCAN_INPROG_PHY(pi)) { | 1385 | if (!SCAN_INPROG_PHY(pi)) { |
1408 | bool suspend; | 1386 | bool suspend; |
1409 | 1387 | ||
1410 | suspend = (0 == (R_REG(&pi->regs->maccontrol) & | 1388 | suspend = (0 == (bcma_read32(pi->d11core, |
1389 | D11REGOFFS(maccontrol)) & | ||
1411 | MCTL_EN_MAC)); | 1390 | MCTL_EN_MAC)); |
1412 | 1391 | ||
1413 | if (!suspend) | 1392 | if (!suspend) |
@@ -1860,18 +1839,17 @@ void wlc_phy_runbist_config(struct brcms_phy_pub *ppi, bool start_end) | |||
1860 | 1839 | ||
1861 | if (NREV_IS(pi->pubpi.phy_rev, 3) | 1840 | if (NREV_IS(pi->pubpi.phy_rev, 3) |
1862 | || NREV_IS(pi->pubpi.phy_rev, 4)) { | 1841 | || NREV_IS(pi->pubpi.phy_rev, 4)) { |
1863 | W_REG(&pi->regs->phyregaddr, 0xa0); | 1842 | bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), |
1864 | (void)R_REG(&pi->regs->phyregaddr); | 1843 | 0xa0); |
1865 | rxc = R_REG(&pi->regs->phyregdata); | 1844 | bcma_set16(pi->d11core, D11REGOFFS(phyregdata), |
1866 | W_REG(&pi->regs->phyregdata, | 1845 | 0x1 << 15); |
1867 | (0x1 << 15) | rxc); | ||
1868 | } | 1846 | } |
1869 | } else { | 1847 | } else { |
1870 | if (NREV_IS(pi->pubpi.phy_rev, 3) | 1848 | if (NREV_IS(pi->pubpi.phy_rev, 3) |
1871 | || NREV_IS(pi->pubpi.phy_rev, 4)) { | 1849 | || NREV_IS(pi->pubpi.phy_rev, 4)) { |
1872 | W_REG(&pi->regs->phyregaddr, 0xa0); | 1850 | bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), |
1873 | (void)R_REG(&pi->regs->phyregaddr); | 1851 | 0xa0); |
1874 | W_REG(&pi->regs->phyregdata, rxc); | 1852 | bcma_write16(pi->d11core, D11REGOFFS(phyregdata), rxc); |
1875 | } | 1853 | } |
1876 | 1854 | ||
1877 | wlc_phy_por_inform(ppi); | 1855 | wlc_phy_por_inform(ppi); |
@@ -1991,7 +1969,9 @@ void wlc_phy_txpower_hw_ctrl_set(struct brcms_phy_pub *ppi, bool hwpwrctrl) | |||
1991 | pi->txpwrctrl = hwpwrctrl; | 1969 | pi->txpwrctrl = hwpwrctrl; |
1992 | 1970 | ||
1993 | if (ISNPHY(pi)) { | 1971 | if (ISNPHY(pi)) { |
1994 | suspend = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); | 1972 | suspend = (0 == (bcma_read32(pi->d11core, |
1973 | D11REGOFFS(maccontrol)) & | ||
1974 | MCTL_EN_MAC)); | ||
1995 | if (!suspend) | 1975 | if (!suspend) |
1996 | wlapi_suspend_mac_and_wait(pi->sh->physhim); | 1976 | wlapi_suspend_mac_and_wait(pi->sh->physhim); |
1997 | 1977 | ||
@@ -2193,7 +2173,8 @@ void wlc_phy_ant_rxdiv_set(struct brcms_phy_pub *ppi, u8 val) | |||
2193 | if (!pi->sh->clk) | 2173 | if (!pi->sh->clk) |
2194 | return; | 2174 | return; |
2195 | 2175 | ||
2196 | suspend = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); | 2176 | suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) & |
2177 | MCTL_EN_MAC)); | ||
2197 | if (!suspend) | 2178 | if (!suspend) |
2198 | wlapi_suspend_mac_and_wait(pi->sh->physhim); | 2179 | wlapi_suspend_mac_and_wait(pi->sh->physhim); |
2199 | 2180 | ||
@@ -2411,8 +2392,8 @@ wlc_phy_noise_sample_request(struct brcms_phy_pub *pih, u8 reason, u8 ch) | |||
2411 | wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP2, 0); | 2392 | wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP2, 0); |
2412 | wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP3, 0); | 2393 | wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP3, 0); |
2413 | 2394 | ||
2414 | OR_REG(&pi->regs->maccommand, | 2395 | bcma_set32(pi->d11core, D11REGOFFS(maccommand), |
2415 | MCMD_BG_NOISE); | 2396 | MCMD_BG_NOISE); |
2416 | } else { | 2397 | } else { |
2417 | wlapi_suspend_mac_and_wait(pi->sh->physhim); | 2398 | wlapi_suspend_mac_and_wait(pi->sh->physhim); |
2418 | wlc_lcnphy_deaf_mode(pi, (bool) 0); | 2399 | wlc_lcnphy_deaf_mode(pi, (bool) 0); |
@@ -2430,8 +2411,8 @@ wlc_phy_noise_sample_request(struct brcms_phy_pub *pih, u8 reason, u8 ch) | |||
2430 | wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP2, 0); | 2411 | wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP2, 0); |
2431 | wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP3, 0); | 2412 | wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP3, 0); |
2432 | 2413 | ||
2433 | OR_REG(&pi->regs->maccommand, | 2414 | bcma_set32(pi->d11core, D11REGOFFS(maccommand), |
2434 | MCMD_BG_NOISE); | 2415 | MCMD_BG_NOISE); |
2435 | } else { | 2416 | } else { |
2436 | struct phy_iq_est est[PHY_CORE_MAX]; | 2417 | struct phy_iq_est est[PHY_CORE_MAX]; |
2437 | u32 cmplx_pwr[PHY_CORE_MAX]; | 2418 | u32 cmplx_pwr[PHY_CORE_MAX]; |
@@ -2924,29 +2905,29 @@ void wlc_lcnphy_epa_switch(struct brcms_phy *pi, bool mode) | |||
2924 | mod_phy_reg(pi, 0x44c, (0x1 << 2), (1) << 2); | 2905 | mod_phy_reg(pi, 0x44c, (0x1 << 2), (1) << 2); |
2925 | 2906 | ||
2926 | } | 2907 | } |
2927 | ai_corereg(pi->sh->sih, SI_CC_IDX, | 2908 | ai_cc_reg(pi->sh->sih, |
2928 | offsetof(struct chipcregs, gpiocontrol), | 2909 | offsetof(struct chipcregs, gpiocontrol), |
2929 | ~0x0, 0x0); | 2910 | ~0x0, 0x0); |
2930 | ai_corereg(pi->sh->sih, SI_CC_IDX, | 2911 | ai_cc_reg(pi->sh->sih, |
2931 | offsetof(struct chipcregs, gpioout), 0x40, | 2912 | offsetof(struct chipcregs, gpioout), |
2932 | 0x40); | 2913 | 0x40, 0x40); |
2933 | ai_corereg(pi->sh->sih, SI_CC_IDX, | 2914 | ai_cc_reg(pi->sh->sih, |
2934 | offsetof(struct chipcregs, gpioouten), 0x40, | 2915 | offsetof(struct chipcregs, gpioouten), |
2935 | 0x40); | 2916 | 0x40, 0x40); |
2936 | } else { | 2917 | } else { |
2937 | mod_phy_reg(pi, 0x44c, (0x1 << 2), (0) << 2); | 2918 | mod_phy_reg(pi, 0x44c, (0x1 << 2), (0) << 2); |
2938 | 2919 | ||
2939 | mod_phy_reg(pi, 0x44d, (0x1 << 2), (0) << 2); | 2920 | mod_phy_reg(pi, 0x44d, (0x1 << 2), (0) << 2); |
2940 | 2921 | ||
2941 | ai_corereg(pi->sh->sih, SI_CC_IDX, | 2922 | ai_cc_reg(pi->sh->sih, |
2942 | offsetof(struct chipcregs, gpioout), 0x40, | 2923 | offsetof(struct chipcregs, gpioout), |
2943 | 0x00); | 2924 | 0x40, 0x00); |
2944 | ai_corereg(pi->sh->sih, SI_CC_IDX, | 2925 | ai_cc_reg(pi->sh->sih, |
2945 | offsetof(struct chipcregs, gpioouten), 0x40, | 2926 | offsetof(struct chipcregs, gpioouten), |
2946 | 0x0); | 2927 | 0x40, 0x0); |
2947 | ai_corereg(pi->sh->sih, SI_CC_IDX, | 2928 | ai_cc_reg(pi->sh->sih, |
2948 | offsetof(struct chipcregs, gpiocontrol), | 2929 | offsetof(struct chipcregs, gpiocontrol), |
2949 | ~0x0, 0x40); | 2930 | ~0x0, 0x40); |
2950 | } | 2931 | } |
2951 | } | 2932 | } |
2952 | } | 2933 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_hal.h b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_hal.h index 96e15163222b..e34a71e7d242 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_hal.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_hal.h | |||
@@ -166,7 +166,6 @@ struct shared_phy_params { | |||
166 | struct phy_shim_info *physhim; | 166 | struct phy_shim_info *physhim; |
167 | uint unit; | 167 | uint unit; |
168 | uint corerev; | 168 | uint corerev; |
169 | uint buscorerev; | ||
170 | u16 vid; | 169 | u16 vid; |
171 | u16 did; | 170 | u16 did; |
172 | uint chip; | 171 | uint chip; |
@@ -175,7 +174,6 @@ struct shared_phy_params { | |||
175 | uint sromrev; | 174 | uint sromrev; |
176 | uint boardtype; | 175 | uint boardtype; |
177 | uint boardrev; | 176 | uint boardrev; |
178 | uint boardvendor; | ||
179 | u32 boardflags; | 177 | u32 boardflags; |
180 | u32 boardflags2; | 178 | u32 boardflags2; |
181 | }; | 179 | }; |
@@ -183,7 +181,7 @@ struct shared_phy_params { | |||
183 | 181 | ||
184 | extern struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp); | 182 | extern struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp); |
185 | extern struct brcms_phy_pub *wlc_phy_attach(struct shared_phy *sh, | 183 | extern struct brcms_phy_pub *wlc_phy_attach(struct shared_phy *sh, |
186 | struct d11regs __iomem *regs, | 184 | struct bcma_device *d11core, |
187 | int bandtype, struct wiphy *wiphy); | 185 | int bandtype, struct wiphy *wiphy); |
188 | extern void wlc_phy_detach(struct brcms_phy_pub *ppi); | 186 | extern void wlc_phy_detach(struct brcms_phy_pub *ppi); |
189 | 187 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h index 5f9478b1c993..af00e2c2b266 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h | |||
@@ -503,10 +503,8 @@ struct shared_phy { | |||
503 | uint sromrev; | 503 | uint sromrev; |
504 | uint boardtype; | 504 | uint boardtype; |
505 | uint boardrev; | 505 | uint boardrev; |
506 | uint boardvendor; | ||
507 | u32 boardflags; | 506 | u32 boardflags; |
508 | u32 boardflags2; | 507 | u32 boardflags2; |
509 | uint buscorerev; | ||
510 | uint fast_timer; | 508 | uint fast_timer; |
511 | uint slow_timer; | 509 | uint slow_timer; |
512 | uint glacial_timer; | 510 | uint glacial_timer; |
@@ -559,7 +557,7 @@ struct brcms_phy { | |||
559 | } u; | 557 | } u; |
560 | bool user_txpwr_at_rfport; | 558 | bool user_txpwr_at_rfport; |
561 | 559 | ||
562 | struct d11regs __iomem *regs; | 560 | struct bcma_device *d11core; |
563 | struct brcms_phy *next; | 561 | struct brcms_phy *next; |
564 | struct brcms_phy_pub pubpi; | 562 | struct brcms_phy_pub pubpi; |
565 | 563 | ||
@@ -1090,7 +1088,7 @@ extern void wlc_phy_table_write_nphy(struct brcms_phy *pi, u32, u32, u32, | |||
1090 | 1088 | ||
1091 | #define BRCMS_PHY_WAR_PR51571(pi) \ | 1089 | #define BRCMS_PHY_WAR_PR51571(pi) \ |
1092 | if (NREV_LT((pi)->pubpi.phy_rev, 3)) \ | 1090 | if (NREV_LT((pi)->pubpi.phy_rev, 3)) \ |
1093 | (void)R_REG(&(pi)->regs->maccontrol) | 1091 | (void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) |
1094 | 1092 | ||
1095 | extern void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype); | 1093 | extern void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype); |
1096 | extern void wlc_phy_aci_reset_nphy(struct brcms_phy *pi); | 1094 | extern void wlc_phy_aci_reset_nphy(struct brcms_phy *pi); |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c index a63aa99d9810..efa0142bdad5 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c | |||
@@ -2813,10 +2813,8 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi) | |||
2813 | u16 SAVE_jtag_auxpga = read_radio_reg(pi, RADIO_2064_REG0FF) & 0x10; | 2813 | u16 SAVE_jtag_auxpga = read_radio_reg(pi, RADIO_2064_REG0FF) & 0x10; |
2814 | u16 SAVE_iqadc_aux_en = read_radio_reg(pi, RADIO_2064_REG11F) & 4; | 2814 | u16 SAVE_iqadc_aux_en = read_radio_reg(pi, RADIO_2064_REG11F) & 4; |
2815 | idleTssi = read_phy_reg(pi, 0x4ab); | 2815 | idleTssi = read_phy_reg(pi, 0x4ab); |
2816 | suspend = | 2816 | suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) & |
2817 | (0 == | 2817 | MCTL_EN_MAC)); |
2818 | (R_REG(&((struct brcms_phy *) pi)->regs->maccontrol) & | ||
2819 | MCTL_EN_MAC)); | ||
2820 | if (!suspend) | 2818 | if (!suspend) |
2821 | wlapi_suspend_mac_and_wait(pi->sh->physhim); | 2819 | wlapi_suspend_mac_and_wait(pi->sh->physhim); |
2822 | wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); | 2820 | wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); |
@@ -2890,7 +2888,8 @@ static void wlc_lcnphy_vbat_temp_sense_setup(struct brcms_phy *pi, u8 mode) | |||
2890 | 2888 | ||
2891 | for (i = 0; i < 14; i++) | 2889 | for (i = 0; i < 14; i++) |
2892 | values_to_save[i] = read_phy_reg(pi, tempsense_phy_regs[i]); | 2890 | values_to_save[i] = read_phy_reg(pi, tempsense_phy_regs[i]); |
2893 | suspend = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); | 2891 | suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) & |
2892 | MCTL_EN_MAC)); | ||
2894 | if (!suspend) | 2893 | if (!suspend) |
2895 | wlapi_suspend_mac_and_wait(pi->sh->physhim); | 2894 | wlapi_suspend_mac_and_wait(pi->sh->physhim); |
2896 | save_txpwrCtrlEn = read_radio_reg(pi, 0x4a4); | 2895 | save_txpwrCtrlEn = read_radio_reg(pi, 0x4a4); |
@@ -3016,8 +3015,8 @@ static void wlc_lcnphy_tx_pwr_ctrl_init(struct brcms_phy_pub *ppi) | |||
3016 | bool suspend; | 3015 | bool suspend; |
3017 | struct brcms_phy *pi = (struct brcms_phy *) ppi; | 3016 | struct brcms_phy *pi = (struct brcms_phy *) ppi; |
3018 | 3017 | ||
3019 | suspend = | 3018 | suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) & |
3020 | (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); | 3019 | MCTL_EN_MAC)); |
3021 | if (!suspend) | 3020 | if (!suspend) |
3022 | wlapi_suspend_mac_and_wait(pi->sh->physhim); | 3021 | wlapi_suspend_mac_and_wait(pi->sh->physhim); |
3023 | 3022 | ||
@@ -3535,15 +3534,17 @@ wlc_lcnphy_samp_cap(struct brcms_phy *pi, int clip_detect_algo, u16 thresh, | |||
3535 | timer = 0; | 3534 | timer = 0; |
3536 | old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da); | 3535 | old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da); |
3537 | 3536 | ||
3538 | curval1 = R_REG(&pi->regs->psm_corectlsts); | 3537 | curval1 = bcma_read16(pi->d11core, D11REGOFFS(psm_corectlsts)); |
3539 | ptr[130] = 0; | 3538 | ptr[130] = 0; |
3540 | W_REG(&pi->regs->psm_corectlsts, ((1 << 6) | curval1)); | 3539 | bcma_write16(pi->d11core, D11REGOFFS(psm_corectlsts), |
3540 | ((1 << 6) | curval1)); | ||
3541 | 3541 | ||
3542 | W_REG(&pi->regs->smpl_clct_strptr, 0x7E00); | 3542 | bcma_write16(pi->d11core, D11REGOFFS(smpl_clct_strptr), 0x7E00); |
3543 | W_REG(&pi->regs->smpl_clct_stpptr, 0x8000); | 3543 | bcma_write16(pi->d11core, D11REGOFFS(smpl_clct_stpptr), 0x8000); |
3544 | udelay(20); | 3544 | udelay(20); |
3545 | curval2 = R_REG(&pi->regs->psm_phy_hdr_param); | 3545 | curval2 = bcma_read16(pi->d11core, D11REGOFFS(psm_phy_hdr_param)); |
3546 | W_REG(&pi->regs->psm_phy_hdr_param, curval2 | 0x30); | 3546 | bcma_write16(pi->d11core, D11REGOFFS(psm_phy_hdr_param), |
3547 | curval2 | 0x30); | ||
3547 | 3548 | ||
3548 | write_phy_reg(pi, 0x555, 0x0); | 3549 | write_phy_reg(pi, 0x555, 0x0); |
3549 | write_phy_reg(pi, 0x5a6, 0x5); | 3550 | write_phy_reg(pi, 0x5a6, 0x5); |
@@ -3560,19 +3561,19 @@ wlc_lcnphy_samp_cap(struct brcms_phy *pi, int clip_detect_algo, u16 thresh, | |||
3560 | 3561 | ||
3561 | sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da); | 3562 | sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da); |
3562 | write_phy_reg(pi, 0x6da, (u32) (sslpnCalibClkEnCtrl | 0x2008)); | 3563 | write_phy_reg(pi, 0x6da, (u32) (sslpnCalibClkEnCtrl | 0x2008)); |
3563 | stpptr = R_REG(&pi->regs->smpl_clct_stpptr); | 3564 | stpptr = bcma_read16(pi->d11core, D11REGOFFS(smpl_clct_stpptr)); |
3564 | curptr = R_REG(&pi->regs->smpl_clct_curptr); | 3565 | curptr = bcma_read16(pi->d11core, D11REGOFFS(smpl_clct_curptr)); |
3565 | do { | 3566 | do { |
3566 | udelay(10); | 3567 | udelay(10); |
3567 | curptr = R_REG(&pi->regs->smpl_clct_curptr); | 3568 | curptr = bcma_read16(pi->d11core, D11REGOFFS(smpl_clct_curptr)); |
3568 | timer++; | 3569 | timer++; |
3569 | } while ((curptr != stpptr) && (timer < 500)); | 3570 | } while ((curptr != stpptr) && (timer < 500)); |
3570 | 3571 | ||
3571 | W_REG(&pi->regs->psm_phy_hdr_param, 0x2); | 3572 | bcma_write16(pi->d11core, D11REGOFFS(psm_phy_hdr_param), 0x2); |
3572 | strptr = 0x7E00; | 3573 | strptr = 0x7E00; |
3573 | W_REG(&pi->regs->tplatewrptr, strptr); | 3574 | bcma_write32(pi->d11core, D11REGOFFS(tplatewrptr), strptr); |
3574 | while (strptr < 0x8000) { | 3575 | while (strptr < 0x8000) { |
3575 | val = R_REG(&pi->regs->tplatewrdata); | 3576 | val = bcma_read32(pi->d11core, D11REGOFFS(tplatewrdata)); |
3576 | imag = ((val >> 16) & 0x3ff); | 3577 | imag = ((val >> 16) & 0x3ff); |
3577 | real = ((val) & 0x3ff); | 3578 | real = ((val) & 0x3ff); |
3578 | if (imag > 511) | 3579 | if (imag > 511) |
@@ -3597,8 +3598,8 @@ wlc_lcnphy_samp_cap(struct brcms_phy *pi, int clip_detect_algo, u16 thresh, | |||
3597 | } | 3598 | } |
3598 | 3599 | ||
3599 | write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl); | 3600 | write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl); |
3600 | W_REG(&pi->regs->psm_phy_hdr_param, curval2); | 3601 | bcma_write16(pi->d11core, D11REGOFFS(psm_phy_hdr_param), curval2); |
3601 | W_REG(&pi->regs->psm_corectlsts, curval1); | 3602 | bcma_write16(pi->d11core, D11REGOFFS(psm_corectlsts), curval1); |
3602 | } | 3603 | } |
3603 | 3604 | ||
3604 | static void | 3605 | static void |
@@ -3968,9 +3969,9 @@ s16 wlc_lcnphy_tempsense_new(struct brcms_phy *pi, bool mode) | |||
3968 | bool suspend = 0; | 3969 | bool suspend = 0; |
3969 | 3970 | ||
3970 | if (mode == 1) { | 3971 | if (mode == 1) { |
3971 | suspend = | 3972 | suspend = (0 == (bcma_read32(pi->d11core, |
3972 | (0 == | 3973 | D11REGOFFS(maccontrol)) & |
3973 | (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); | 3974 | MCTL_EN_MAC)); |
3974 | if (!suspend) | 3975 | if (!suspend) |
3975 | wlapi_suspend_mac_and_wait(pi->sh->physhim); | 3976 | wlapi_suspend_mac_and_wait(pi->sh->physhim); |
3976 | wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE); | 3977 | wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE); |
@@ -4012,9 +4013,9 @@ u16 wlc_lcnphy_tempsense(struct brcms_phy *pi, bool mode) | |||
4012 | struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; | 4013 | struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; |
4013 | 4014 | ||
4014 | if (mode == 1) { | 4015 | if (mode == 1) { |
4015 | suspend = | 4016 | suspend = (0 == (bcma_read32(pi->d11core, |
4016 | (0 == | 4017 | D11REGOFFS(maccontrol)) & |
4017 | (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); | 4018 | MCTL_EN_MAC)); |
4018 | if (!suspend) | 4019 | if (!suspend) |
4019 | wlapi_suspend_mac_and_wait(pi->sh->physhim); | 4020 | wlapi_suspend_mac_and_wait(pi->sh->physhim); |
4020 | wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE); | 4021 | wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE); |
@@ -4078,9 +4079,9 @@ s8 wlc_lcnphy_vbatsense(struct brcms_phy *pi, bool mode) | |||
4078 | bool suspend = 0; | 4079 | bool suspend = 0; |
4079 | 4080 | ||
4080 | if (mode == 1) { | 4081 | if (mode == 1) { |
4081 | suspend = | 4082 | suspend = (0 == (bcma_read32(pi->d11core, |
4082 | (0 == | 4083 | D11REGOFFS(maccontrol)) & |
4083 | (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); | 4084 | MCTL_EN_MAC)); |
4084 | if (!suspend) | 4085 | if (!suspend) |
4085 | wlapi_suspend_mac_and_wait(pi->sh->physhim); | 4086 | wlapi_suspend_mac_and_wait(pi->sh->physhim); |
4086 | wlc_lcnphy_vbat_temp_sense_setup(pi, VBATSENSE); | 4087 | wlc_lcnphy_vbat_temp_sense_setup(pi, VBATSENSE); |
@@ -4127,8 +4128,8 @@ static void wlc_lcnphy_glacial_timer_based_cal(struct brcms_phy *pi) | |||
4127 | s8 index; | 4128 | s8 index; |
4128 | u16 SAVE_pwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); | 4129 | u16 SAVE_pwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); |
4129 | struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; | 4130 | struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; |
4130 | suspend = | 4131 | suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) & |
4131 | (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); | 4132 | MCTL_EN_MAC)); |
4132 | if (!suspend) | 4133 | if (!suspend) |
4133 | wlapi_suspend_mac_and_wait(pi->sh->physhim); | 4134 | wlapi_suspend_mac_and_wait(pi->sh->physhim); |
4134 | wlc_lcnphy_deaf_mode(pi, true); | 4135 | wlc_lcnphy_deaf_mode(pi, true); |
@@ -4166,8 +4167,8 @@ static void wlc_lcnphy_periodic_cal(struct brcms_phy *pi) | |||
4166 | pi_lcn->lcnphy_full_cal_channel = CHSPEC_CHANNEL(pi->radio_chanspec); | 4167 | pi_lcn->lcnphy_full_cal_channel = CHSPEC_CHANNEL(pi->radio_chanspec); |
4167 | index = pi_lcn->lcnphy_current_index; | 4168 | index = pi_lcn->lcnphy_current_index; |
4168 | 4169 | ||
4169 | suspend = | 4170 | suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) & |
4170 | (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); | 4171 | MCTL_EN_MAC)); |
4171 | if (!suspend) { | 4172 | if (!suspend) { |
4172 | wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION, 10000); | 4173 | wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION, 10000); |
4173 | wlapi_suspend_mac_and_wait(pi->sh->physhim); | 4174 | wlapi_suspend_mac_and_wait(pi->sh->physhim); |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c index ec9b56639d54..a16f1ab292fd 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c | |||
@@ -17802,7 +17802,7 @@ static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi) | |||
17802 | 17802 | ||
17803 | if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) { | 17803 | if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) { |
17804 | wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK); | 17804 | wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK); |
17805 | (void)R_REG(&pi->regs->maccontrol); | 17805 | (void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol)); |
17806 | udelay(1); | 17806 | udelay(1); |
17807 | } | 17807 | } |
17808 | 17808 | ||
@@ -17953,7 +17953,7 @@ static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi) | |||
17953 | 17953 | ||
17954 | if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) { | 17954 | if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) { |
17955 | wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK); | 17955 | wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK); |
17956 | (void)R_REG(&pi->regs->maccontrol); | 17956 | (void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol)); |
17957 | udelay(1); | 17957 | udelay(1); |
17958 | } | 17958 | } |
17959 | 17959 | ||
@@ -19447,8 +19447,6 @@ void wlc_phy_init_nphy(struct brcms_phy *pi) | |||
19447 | u8 tx_pwr_ctrl_state; | 19447 | u8 tx_pwr_ctrl_state; |
19448 | bool do_nphy_cal = false; | 19448 | bool do_nphy_cal = false; |
19449 | uint core; | 19449 | uint core; |
19450 | uint origidx, intr_val; | ||
19451 | struct d11regs __iomem *regs; | ||
19452 | u32 d11_clk_ctl_st; | 19450 | u32 d11_clk_ctl_st; |
19453 | bool do_rssi_cal = false; | 19451 | bool do_rssi_cal = false; |
19454 | 19452 | ||
@@ -19462,25 +19460,21 @@ void wlc_phy_init_nphy(struct brcms_phy *pi) | |||
19462 | (pi->sh->chippkg == BCM4718_PKG_ID))) { | 19460 | (pi->sh->chippkg == BCM4718_PKG_ID))) { |
19463 | if ((pi->sh->boardflags & BFL_EXTLNA) && | 19461 | if ((pi->sh->boardflags & BFL_EXTLNA) && |
19464 | (CHSPEC_IS2G(pi->radio_chanspec))) | 19462 | (CHSPEC_IS2G(pi->radio_chanspec))) |
19465 | ai_corereg(pi->sh->sih, SI_CC_IDX, | 19463 | ai_cc_reg(pi->sh->sih, |
19466 | offsetof(struct chipcregs, chipcontrol), | 19464 | offsetof(struct chipcregs, chipcontrol), |
19467 | 0x40, 0x40); | 19465 | 0x40, 0x40); |
19468 | } | 19466 | } |
19469 | 19467 | ||
19470 | if ((pi->nphy_gband_spurwar2_en) && CHSPEC_IS2G(pi->radio_chanspec) && | 19468 | if ((pi->nphy_gband_spurwar2_en) && CHSPEC_IS2G(pi->radio_chanspec) && |
19471 | CHSPEC_IS40(pi->radio_chanspec)) { | 19469 | CHSPEC_IS40(pi->radio_chanspec)) { |
19472 | 19470 | ||
19473 | regs = (struct d11regs __iomem *) | 19471 | d11_clk_ctl_st = bcma_read32(pi->d11core, |
19474 | ai_switch_core(pi->sh->sih, | 19472 | D11REGOFFS(clk_ctl_st)); |
19475 | D11_CORE_ID, &origidx, | 19473 | bcma_mask32(pi->d11core, D11REGOFFS(clk_ctl_st), |
19476 | &intr_val); | 19474 | ~(CCS_FORCEHT | CCS_HTAREQ)); |
19477 | d11_clk_ctl_st = R_REG(®s->clk_ctl_st); | ||
19478 | AND_REG(®s->clk_ctl_st, | ||
19479 | ~(CCS_FORCEHT | CCS_HTAREQ)); | ||
19480 | 19475 | ||
19481 | W_REG(®s->clk_ctl_st, d11_clk_ctl_st); | 19476 | bcma_write32(pi->d11core, D11REGOFFS(clk_ctl_st), |
19482 | 19477 | d11_clk_ctl_st); | |
19483 | ai_restore_core(pi->sh->sih, origidx, intr_val); | ||
19484 | } | 19478 | } |
19485 | 19479 | ||
19486 | pi->use_int_tx_iqlo_cal_nphy = | 19480 | pi->use_int_tx_iqlo_cal_nphy = |
@@ -19885,7 +19879,8 @@ void wlc_phy_rxcore_setstate_nphy(struct brcms_phy_pub *pih, u8 rxcore_bitmask) | |||
19885 | if (!pi->sh->clk) | 19879 | if (!pi->sh->clk) |
19886 | return; | 19880 | return; |
19887 | 19881 | ||
19888 | suspend = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); | 19882 | suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) & |
19883 | MCTL_EN_MAC)); | ||
19889 | if (!suspend) | 19884 | if (!suspend) |
19890 | wlapi_suspend_mac_and_wait(pi->sh->physhim); | 19885 | wlapi_suspend_mac_and_wait(pi->sh->physhim); |
19891 | 19886 | ||
@@ -21263,28 +21258,28 @@ wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, u16 chanspec, | |||
21263 | val = read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand; | 21258 | val = read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand; |
21264 | if (CHSPEC_IS5G(chanspec) && !val) { | 21259 | if (CHSPEC_IS5G(chanspec) && !val) { |
21265 | 21260 | ||
21266 | val = R_REG(&pi->regs->psm_phy_hdr_param); | 21261 | val = bcma_read16(pi->d11core, D11REGOFFS(psm_phy_hdr_param)); |
21267 | W_REG(&pi->regs->psm_phy_hdr_param, | 21262 | bcma_write16(pi->d11core, D11REGOFFS(psm_phy_hdr_param), |
21268 | (val | MAC_PHY_FORCE_CLK)); | 21263 | (val | MAC_PHY_FORCE_CLK)); |
21269 | 21264 | ||
21270 | or_phy_reg(pi, (NPHY_TO_BPHY_OFF + BPHY_BB_CONFIG), | 21265 | or_phy_reg(pi, (NPHY_TO_BPHY_OFF + BPHY_BB_CONFIG), |
21271 | (BBCFG_RESETCCA | BBCFG_RESETRX)); | 21266 | (BBCFG_RESETCCA | BBCFG_RESETRX)); |
21272 | 21267 | ||
21273 | W_REG(&pi->regs->psm_phy_hdr_param, val); | 21268 | bcma_write16(pi->d11core, D11REGOFFS(psm_phy_hdr_param), val); |
21274 | 21269 | ||
21275 | or_phy_reg(pi, 0x09, NPHY_BandControl_currentBand); | 21270 | or_phy_reg(pi, 0x09, NPHY_BandControl_currentBand); |
21276 | } else if (!CHSPEC_IS5G(chanspec) && val) { | 21271 | } else if (!CHSPEC_IS5G(chanspec) && val) { |
21277 | 21272 | ||
21278 | and_phy_reg(pi, 0x09, ~NPHY_BandControl_currentBand); | 21273 | and_phy_reg(pi, 0x09, ~NPHY_BandControl_currentBand); |
21279 | 21274 | ||
21280 | val = R_REG(&pi->regs->psm_phy_hdr_param); | 21275 | val = bcma_read16(pi->d11core, D11REGOFFS(psm_phy_hdr_param)); |
21281 | W_REG(&pi->regs->psm_phy_hdr_param, | 21276 | bcma_write16(pi->d11core, D11REGOFFS(psm_phy_hdr_param), |
21282 | (val | MAC_PHY_FORCE_CLK)); | 21277 | (val | MAC_PHY_FORCE_CLK)); |
21283 | 21278 | ||
21284 | and_phy_reg(pi, (NPHY_TO_BPHY_OFF + BPHY_BB_CONFIG), | 21279 | and_phy_reg(pi, (NPHY_TO_BPHY_OFF + BPHY_BB_CONFIG), |
21285 | (u16) (~(BBCFG_RESETCCA | BBCFG_RESETRX))); | 21280 | (u16) (~(BBCFG_RESETCCA | BBCFG_RESETRX))); |
21286 | 21281 | ||
21287 | W_REG(&pi->regs->psm_phy_hdr_param, val); | 21282 | bcma_write16(pi->d11core, D11REGOFFS(psm_phy_hdr_param), val); |
21288 | } | 21283 | } |
21289 | 21284 | ||
21290 | write_phy_reg(pi, 0x1ce, ci->PHY_BW1a); | 21285 | write_phy_reg(pi, 0x1ce, ci->PHY_BW1a); |
@@ -21342,24 +21337,23 @@ wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, u16 chanspec, | |||
21342 | spuravoid = 1; | 21337 | spuravoid = 1; |
21343 | 21338 | ||
21344 | wlapi_bmac_core_phypll_ctl(pi->sh->physhim, false); | 21339 | wlapi_bmac_core_phypll_ctl(pi->sh->physhim, false); |
21345 | si_pmu_spuravoid(pi->sh->sih, spuravoid); | 21340 | si_pmu_spuravoid_pllupdate(pi->sh->sih, spuravoid); |
21346 | wlapi_bmac_core_phypll_ctl(pi->sh->physhim, true); | 21341 | wlapi_bmac_core_phypll_ctl(pi->sh->physhim, true); |
21347 | 21342 | ||
21348 | if ((pi->sh->chip == BCM43224_CHIP_ID) || | 21343 | if ((pi->sh->chip == BCM43224_CHIP_ID) || |
21349 | (pi->sh->chip == BCM43225_CHIP_ID)) { | 21344 | (pi->sh->chip == BCM43225_CHIP_ID)) { |
21350 | |||
21351 | if (spuravoid == 1) { | 21345 | if (spuravoid == 1) { |
21352 | 21346 | bcma_write16(pi->d11core, | |
21353 | W_REG(&pi->regs->tsf_clk_frac_l, | 21347 | D11REGOFFS(tsf_clk_frac_l), |
21354 | 0x5341); | 21348 | 0x5341); |
21355 | W_REG(&pi->regs->tsf_clk_frac_h, | 21349 | bcma_write16(pi->d11core, |
21356 | 0x8); | 21350 | D11REGOFFS(tsf_clk_frac_h), 0x8); |
21357 | } else { | 21351 | } else { |
21358 | 21352 | bcma_write16(pi->d11core, | |
21359 | W_REG(&pi->regs->tsf_clk_frac_l, | 21353 | D11REGOFFS(tsf_clk_frac_l), |
21360 | 0x8889); | 21354 | 0x8889); |
21361 | W_REG(&pi->regs->tsf_clk_frac_h, | 21355 | bcma_write16(pi->d11core, |
21362 | 0x8); | 21356 | D11REGOFFS(tsf_clk_frac_h), 0x8); |
21363 | } | 21357 | } |
21364 | } | 21358 | } |
21365 | 21359 | ||
@@ -21499,13 +21493,13 @@ void wlc_phy_antsel_init(struct brcms_phy_pub *ppi, bool lut_init) | |||
21499 | 21493 | ||
21500 | ai_gpiocontrol(pi->sh->sih, mask, mask, GPIO_DRV_PRIORITY); | 21494 | ai_gpiocontrol(pi->sh->sih, mask, mask, GPIO_DRV_PRIORITY); |
21501 | 21495 | ||
21502 | mc = R_REG(&pi->regs->maccontrol); | 21496 | mc = bcma_read32(pi->d11core, D11REGOFFS(maccontrol)); |
21503 | mc &= ~MCTL_GPOUT_SEL_MASK; | 21497 | mc &= ~MCTL_GPOUT_SEL_MASK; |
21504 | W_REG(&pi->regs->maccontrol, mc); | 21498 | bcma_write32(pi->d11core, D11REGOFFS(maccontrol), mc); |
21505 | 21499 | ||
21506 | OR_REG(&pi->regs->psm_gpio_oe, mask); | 21500 | bcma_set16(pi->d11core, D11REGOFFS(psm_gpio_oe), mask); |
21507 | 21501 | ||
21508 | AND_REG(&pi->regs->psm_gpio_out, ~mask); | 21502 | bcma_mask16(pi->d11core, D11REGOFFS(psm_gpio_out), ~mask); |
21509 | 21503 | ||
21510 | if (lut_init) { | 21504 | if (lut_init) { |
21511 | write_phy_reg(pi, 0xf8, 0x02d8); | 21505 | write_phy_reg(pi, 0xf8, 0x02d8); |
@@ -21522,9 +21516,8 @@ u16 wlc_phy_classifier_nphy(struct brcms_phy *pi, u16 mask, u16 val) | |||
21522 | bool suspended = false; | 21516 | bool suspended = false; |
21523 | 21517 | ||
21524 | if (D11REV_IS(pi->sh->corerev, 16)) { | 21518 | if (D11REV_IS(pi->sh->corerev, 16)) { |
21525 | suspended = | 21519 | suspended = (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) & |
21526 | (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC) ? | 21520 | MCTL_EN_MAC) ? false : true; |
21527 | false : true; | ||
21528 | if (!suspended) | 21521 | if (!suspended) |
21529 | wlapi_suspend_mac_and_wait(pi->sh->physhim); | 21522 | wlapi_suspend_mac_and_wait(pi->sh->physhim); |
21530 | } | 21523 | } |
@@ -25383,7 +25376,8 @@ static void wlc_phy_a4(struct brcms_phy *pi, bool full_cal) | |||
25383 | if (pi->nphy_papd_skip == 1) | 25376 | if (pi->nphy_papd_skip == 1) |
25384 | return; | 25377 | return; |
25385 | 25378 | ||
25386 | phy_b3 = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); | 25379 | phy_b3 = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) & |
25380 | MCTL_EN_MAC)); | ||
25387 | if (!phy_b3) | 25381 | if (!phy_b3) |
25388 | wlapi_suspend_mac_and_wait(pi->sh->physhim); | 25382 | wlapi_suspend_mac_and_wait(pi->sh->physhim); |
25389 | 25383 | ||
@@ -28357,7 +28351,7 @@ void wlc_phy_txpower_recalc_target_nphy(struct brcms_phy *pi) | |||
28357 | 28351 | ||
28358 | if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) { | 28352 | if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) { |
28359 | wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK); | 28353 | wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK); |
28360 | (void)R_REG(&pi->regs->maccontrol); | 28354 | (void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol)); |
28361 | udelay(1); | 28355 | udelay(1); |
28362 | } | 28356 | } |
28363 | 28357 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pmu.c b/drivers/net/wireless/brcm80211/brcmsmac/pmu.c index 12ba575f5785..4931d29d077b 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/pmu.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/pmu.c | |||
@@ -115,10 +115,10 @@ static void si_pmu_res_masks(struct si_pub *sih, u32 * pmin, u32 * pmax) | |||
115 | uint rsrcs; | 115 | uint rsrcs; |
116 | 116 | ||
117 | /* # resources */ | 117 | /* # resources */ |
118 | rsrcs = (sih->pmucaps & PCAP_RC_MASK) >> PCAP_RC_SHIFT; | 118 | rsrcs = (ai_get_pmucaps(sih) & PCAP_RC_MASK) >> PCAP_RC_SHIFT; |
119 | 119 | ||
120 | /* determine min/max rsrc masks */ | 120 | /* determine min/max rsrc masks */ |
121 | switch (sih->chip) { | 121 | switch (ai_get_chip_id(sih)) { |
122 | case BCM43224_CHIP_ID: | 122 | case BCM43224_CHIP_ID: |
123 | case BCM43225_CHIP_ID: | 123 | case BCM43225_CHIP_ID: |
124 | /* ??? */ | 124 | /* ??? */ |
@@ -139,75 +139,84 @@ static void si_pmu_res_masks(struct si_pub *sih, u32 * pmin, u32 * pmax) | |||
139 | *pmax = max_mask; | 139 | *pmax = max_mask; |
140 | } | 140 | } |
141 | 141 | ||
142 | static void | 142 | void si_pmu_spuravoid_pllupdate(struct si_pub *sih, u8 spuravoid) |
143 | si_pmu_spuravoid_pllupdate(struct si_pub *sih, struct chipcregs __iomem *cc, | ||
144 | u8 spuravoid) | ||
145 | { | 143 | { |
146 | u32 tmp = 0; | 144 | u32 tmp = 0; |
145 | struct bcma_device *core; | ||
147 | 146 | ||
148 | switch (sih->chip) { | 147 | /* switch to chipc */ |
148 | core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0); | ||
149 | |||
150 | switch (ai_get_chip_id(sih)) { | ||
149 | case BCM43224_CHIP_ID: | 151 | case BCM43224_CHIP_ID: |
150 | case BCM43225_CHIP_ID: | 152 | case BCM43225_CHIP_ID: |
151 | if (spuravoid == 1) { | 153 | if (spuravoid == 1) { |
152 | W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0); | 154 | bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), |
153 | W_REG(&cc->pllcontrol_data, 0x11500010); | 155 | PMU1_PLL0_PLLCTL0); |
154 | W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1); | 156 | bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), |
155 | W_REG(&cc->pllcontrol_data, 0x000C0C06); | 157 | 0x11500010); |
156 | W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2); | 158 | bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), |
157 | W_REG(&cc->pllcontrol_data, 0x0F600a08); | 159 | PMU1_PLL0_PLLCTL1); |
158 | W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3); | 160 | bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), |
159 | W_REG(&cc->pllcontrol_data, 0x00000000); | 161 | 0x000C0C06); |
160 | W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4); | 162 | bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), |
161 | W_REG(&cc->pllcontrol_data, 0x2001E920); | 163 | PMU1_PLL0_PLLCTL2); |
162 | W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5); | 164 | bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), |
163 | W_REG(&cc->pllcontrol_data, 0x88888815); | 165 | 0x0F600a08); |
166 | bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), | ||
167 | PMU1_PLL0_PLLCTL3); | ||
168 | bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), | ||
169 | 0x00000000); | ||
170 | bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), | ||
171 | PMU1_PLL0_PLLCTL4); | ||
172 | bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), | ||
173 | 0x2001E920); | ||
174 | bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), | ||
175 | PMU1_PLL0_PLLCTL5); | ||
176 | bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), | ||
177 | 0x88888815); | ||
164 | } else { | 178 | } else { |
165 | W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0); | 179 | bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), |
166 | W_REG(&cc->pllcontrol_data, 0x11100010); | 180 | PMU1_PLL0_PLLCTL0); |
167 | W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1); | 181 | bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), |
168 | W_REG(&cc->pllcontrol_data, 0x000c0c06); | 182 | 0x11100010); |
169 | W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2); | 183 | bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), |
170 | W_REG(&cc->pllcontrol_data, 0x03000a08); | 184 | PMU1_PLL0_PLLCTL1); |
171 | W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3); | 185 | bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), |
172 | W_REG(&cc->pllcontrol_data, 0x00000000); | 186 | 0x000c0c06); |
173 | W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4); | 187 | bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), |
174 | W_REG(&cc->pllcontrol_data, 0x200005c0); | 188 | PMU1_PLL0_PLLCTL2); |
175 | W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5); | 189 | bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), |
176 | W_REG(&cc->pllcontrol_data, 0x88888815); | 190 | 0x03000a08); |
191 | bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), | ||
192 | PMU1_PLL0_PLLCTL3); | ||
193 | bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), | ||
194 | 0x00000000); | ||
195 | bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), | ||
196 | PMU1_PLL0_PLLCTL4); | ||
197 | bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), | ||
198 | 0x200005c0); | ||
199 | bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), | ||
200 | PMU1_PLL0_PLLCTL5); | ||
201 | bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), | ||
202 | 0x88888815); | ||
177 | } | 203 | } |
178 | tmp = 1 << 10; | 204 | tmp = 1 << 10; |
179 | break; | 205 | break; |
180 | 206 | ||
181 | W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0); | ||
182 | W_REG(&cc->pllcontrol_data, 0x11100008); | ||
183 | W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1); | ||
184 | W_REG(&cc->pllcontrol_data, 0x0c000c06); | ||
185 | W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2); | ||
186 | W_REG(&cc->pllcontrol_data, 0x03000a08); | ||
187 | W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3); | ||
188 | W_REG(&cc->pllcontrol_data, 0x00000000); | ||
189 | W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4); | ||
190 | W_REG(&cc->pllcontrol_data, 0x200005c0); | ||
191 | W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5); | ||
192 | W_REG(&cc->pllcontrol_data, 0x88888855); | ||
193 | |||
194 | tmp = 1 << 10; | ||
195 | break; | ||
196 | |||
197 | default: | 207 | default: |
198 | /* bail out */ | 208 | /* bail out */ |
199 | return; | 209 | return; |
200 | } | 210 | } |
201 | 211 | ||
202 | tmp |= R_REG(&cc->pmucontrol); | 212 | bcma_set32(core, CHIPCREGOFFS(pmucontrol), tmp); |
203 | W_REG(&cc->pmucontrol, tmp); | ||
204 | } | 213 | } |
205 | 214 | ||
206 | u16 si_pmu_fast_pwrup_delay(struct si_pub *sih) | 215 | u16 si_pmu_fast_pwrup_delay(struct si_pub *sih) |
207 | { | 216 | { |
208 | uint delay = PMU_MAX_TRANSITION_DLY; | 217 | uint delay = PMU_MAX_TRANSITION_DLY; |
209 | 218 | ||
210 | switch (sih->chip) { | 219 | switch (ai_get_chip_id(sih)) { |
211 | case BCM43224_CHIP_ID: | 220 | case BCM43224_CHIP_ID: |
212 | case BCM43225_CHIP_ID: | 221 | case BCM43225_CHIP_ID: |
213 | case BCM4313_CHIP_ID: | 222 | case BCM4313_CHIP_ID: |
@@ -220,54 +229,35 @@ u16 si_pmu_fast_pwrup_delay(struct si_pub *sih) | |||
220 | return (u16) delay; | 229 | return (u16) delay; |
221 | } | 230 | } |
222 | 231 | ||
223 | void si_pmu_sprom_enable(struct si_pub *sih, bool enable) | ||
224 | { | ||
225 | struct chipcregs __iomem *cc; | ||
226 | uint origidx; | ||
227 | |||
228 | /* Remember original core before switch to chipc */ | ||
229 | origidx = ai_coreidx(sih); | ||
230 | cc = ai_setcoreidx(sih, SI_CC_IDX); | ||
231 | |||
232 | /* Return to original core */ | ||
233 | ai_setcoreidx(sih, origidx); | ||
234 | } | ||
235 | |||
236 | /* Read/write a chipcontrol reg */ | 232 | /* Read/write a chipcontrol reg */ |
237 | u32 si_pmu_chipcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val) | 233 | u32 si_pmu_chipcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val) |
238 | { | 234 | { |
239 | ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, chipcontrol_addr), | 235 | ai_cc_reg(sih, offsetof(struct chipcregs, chipcontrol_addr), ~0, reg); |
240 | ~0, reg); | 236 | return ai_cc_reg(sih, offsetof(struct chipcregs, chipcontrol_data), |
241 | return ai_corereg(sih, SI_CC_IDX, | 237 | mask, val); |
242 | offsetof(struct chipcregs, chipcontrol_data), mask, | ||
243 | val); | ||
244 | } | 238 | } |
245 | 239 | ||
246 | /* Read/write a regcontrol reg */ | 240 | /* Read/write a regcontrol reg */ |
247 | u32 si_pmu_regcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val) | 241 | u32 si_pmu_regcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val) |
248 | { | 242 | { |
249 | ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, regcontrol_addr), | 243 | ai_cc_reg(sih, offsetof(struct chipcregs, regcontrol_addr), ~0, reg); |
250 | ~0, reg); | 244 | return ai_cc_reg(sih, offsetof(struct chipcregs, regcontrol_data), |
251 | return ai_corereg(sih, SI_CC_IDX, | 245 | mask, val); |
252 | offsetof(struct chipcregs, regcontrol_data), mask, | ||
253 | val); | ||
254 | } | 246 | } |
255 | 247 | ||
256 | /* Read/write a pllcontrol reg */ | 248 | /* Read/write a pllcontrol reg */ |
257 | u32 si_pmu_pllcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val) | 249 | u32 si_pmu_pllcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val) |
258 | { | 250 | { |
259 | ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, pllcontrol_addr), | 251 | ai_cc_reg(sih, offsetof(struct chipcregs, pllcontrol_addr), ~0, reg); |
260 | ~0, reg); | 252 | return ai_cc_reg(sih, offsetof(struct chipcregs, pllcontrol_data), |
261 | return ai_corereg(sih, SI_CC_IDX, | 253 | mask, val); |
262 | offsetof(struct chipcregs, pllcontrol_data), mask, | ||
263 | val); | ||
264 | } | 254 | } |
265 | 255 | ||
266 | /* PMU PLL update */ | 256 | /* PMU PLL update */ |
267 | void si_pmu_pllupd(struct si_pub *sih) | 257 | void si_pmu_pllupd(struct si_pub *sih) |
268 | { | 258 | { |
269 | ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, pmucontrol), | 259 | ai_cc_reg(sih, offsetof(struct chipcregs, pmucontrol), |
270 | PCTL_PLL_PLLCTL_UPD, PCTL_PLL_PLLCTL_UPD); | 260 | PCTL_PLL_PLLCTL_UPD, PCTL_PLL_PLLCTL_UPD); |
271 | } | 261 | } |
272 | 262 | ||
273 | /* query alp/xtal clock frequency */ | 263 | /* query alp/xtal clock frequency */ |
@@ -276,10 +266,10 @@ u32 si_pmu_alp_clock(struct si_pub *sih) | |||
276 | u32 clock = ALP_CLOCK; | 266 | u32 clock = ALP_CLOCK; |
277 | 267 | ||
278 | /* bail out with default */ | 268 | /* bail out with default */ |
279 | if (!(sih->cccaps & CC_CAP_PMU)) | 269 | if (!(ai_get_cccaps(sih) & CC_CAP_PMU)) |
280 | return clock; | 270 | return clock; |
281 | 271 | ||
282 | switch (sih->chip) { | 272 | switch (ai_get_chip_id(sih)) { |
283 | case BCM43224_CHIP_ID: | 273 | case BCM43224_CHIP_ID: |
284 | case BCM43225_CHIP_ID: | 274 | case BCM43225_CHIP_ID: |
285 | case BCM4313_CHIP_ID: | 275 | case BCM4313_CHIP_ID: |
@@ -293,95 +283,29 @@ u32 si_pmu_alp_clock(struct si_pub *sih) | |||
293 | return clock; | 283 | return clock; |
294 | } | 284 | } |
295 | 285 | ||
296 | void si_pmu_spuravoid(struct si_pub *sih, u8 spuravoid) | ||
297 | { | ||
298 | struct chipcregs __iomem *cc; | ||
299 | uint origidx, intr_val; | ||
300 | |||
301 | /* Remember original core before switch to chipc */ | ||
302 | cc = (struct chipcregs __iomem *) | ||
303 | ai_switch_core(sih, CC_CORE_ID, &origidx, &intr_val); | ||
304 | |||
305 | /* update the pll changes */ | ||
306 | si_pmu_spuravoid_pllupdate(sih, cc, spuravoid); | ||
307 | |||
308 | /* Return to original core */ | ||
309 | ai_restore_core(sih, origidx, intr_val); | ||
310 | } | ||
311 | |||
312 | /* initialize PMU */ | 286 | /* initialize PMU */ |
313 | void si_pmu_init(struct si_pub *sih) | 287 | void si_pmu_init(struct si_pub *sih) |
314 | { | 288 | { |
315 | struct chipcregs __iomem *cc; | 289 | struct bcma_device *core; |
316 | uint origidx; | ||
317 | 290 | ||
318 | /* Remember original core before switch to chipc */ | 291 | /* select chipc */ |
319 | origidx = ai_coreidx(sih); | 292 | core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0); |
320 | cc = ai_setcoreidx(sih, SI_CC_IDX); | ||
321 | |||
322 | if (sih->pmurev == 1) | ||
323 | AND_REG(&cc->pmucontrol, ~PCTL_NOILP_ON_WAIT); | ||
324 | else if (sih->pmurev >= 2) | ||
325 | OR_REG(&cc->pmucontrol, PCTL_NOILP_ON_WAIT); | ||
326 | 293 | ||
327 | /* Return to original core */ | 294 | if (ai_get_pmurev(sih) == 1) |
328 | ai_setcoreidx(sih, origidx); | 295 | bcma_mask32(core, CHIPCREGOFFS(pmucontrol), |
329 | } | 296 | ~PCTL_NOILP_ON_WAIT); |
330 | 297 | else if (ai_get_pmurev(sih) >= 2) | |
331 | /* initialize PMU chip controls and other chip level stuff */ | 298 | bcma_set32(core, CHIPCREGOFFS(pmucontrol), PCTL_NOILP_ON_WAIT); |
332 | void si_pmu_chip_init(struct si_pub *sih) | ||
333 | { | ||
334 | uint origidx; | ||
335 | |||
336 | /* Gate off SPROM clock and chip select signals */ | ||
337 | si_pmu_sprom_enable(sih, false); | ||
338 | |||
339 | /* Remember original core */ | ||
340 | origidx = ai_coreidx(sih); | ||
341 | |||
342 | /* Return to original core */ | ||
343 | ai_setcoreidx(sih, origidx); | ||
344 | } | ||
345 | |||
346 | /* initialize PMU switch/regulators */ | ||
347 | void si_pmu_swreg_init(struct si_pub *sih) | ||
348 | { | ||
349 | } | ||
350 | |||
351 | /* initialize PLL */ | ||
352 | void si_pmu_pll_init(struct si_pub *sih, uint xtalfreq) | ||
353 | { | ||
354 | struct chipcregs __iomem *cc; | ||
355 | uint origidx; | ||
356 | |||
357 | /* Remember original core before switch to chipc */ | ||
358 | origidx = ai_coreidx(sih); | ||
359 | cc = ai_setcoreidx(sih, SI_CC_IDX); | ||
360 | |||
361 | switch (sih->chip) { | ||
362 | case BCM4313_CHIP_ID: | ||
363 | case BCM43224_CHIP_ID: | ||
364 | case BCM43225_CHIP_ID: | ||
365 | /* ??? */ | ||
366 | break; | ||
367 | default: | ||
368 | break; | ||
369 | } | ||
370 | |||
371 | /* Return to original core */ | ||
372 | ai_setcoreidx(sih, origidx); | ||
373 | } | 299 | } |
374 | 300 | ||
375 | /* initialize PMU resources */ | 301 | /* initialize PMU resources */ |
376 | void si_pmu_res_init(struct si_pub *sih) | 302 | void si_pmu_res_init(struct si_pub *sih) |
377 | { | 303 | { |
378 | struct chipcregs __iomem *cc; | 304 | struct bcma_device *core; |
379 | uint origidx; | ||
380 | u32 min_mask = 0, max_mask = 0; | 305 | u32 min_mask = 0, max_mask = 0; |
381 | 306 | ||
382 | /* Remember original core before switch to chipc */ | 307 | /* select to chipc */ |
383 | origidx = ai_coreidx(sih); | 308 | core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0); |
384 | cc = ai_setcoreidx(sih, SI_CC_IDX); | ||
385 | 309 | ||
386 | /* Determine min/max rsrc masks */ | 310 | /* Determine min/max rsrc masks */ |
387 | si_pmu_res_masks(sih, &min_mask, &max_mask); | 311 | si_pmu_res_masks(sih, &min_mask, &max_mask); |
@@ -391,55 +315,50 @@ void si_pmu_res_init(struct si_pub *sih) | |||
391 | /* Program max resource mask */ | 315 | /* Program max resource mask */ |
392 | 316 | ||
393 | if (max_mask) | 317 | if (max_mask) |
394 | W_REG(&cc->max_res_mask, max_mask); | 318 | bcma_write32(core, CHIPCREGOFFS(max_res_mask), max_mask); |
395 | 319 | ||
396 | /* Program min resource mask */ | 320 | /* Program min resource mask */ |
397 | 321 | ||
398 | if (min_mask) | 322 | if (min_mask) |
399 | W_REG(&cc->min_res_mask, min_mask); | 323 | bcma_write32(core, CHIPCREGOFFS(min_res_mask), min_mask); |
400 | 324 | ||
401 | /* Add some delay; allow resources to come up and settle. */ | 325 | /* Add some delay; allow resources to come up and settle. */ |
402 | mdelay(2); | 326 | mdelay(2); |
403 | |||
404 | /* Return to original core */ | ||
405 | ai_setcoreidx(sih, origidx); | ||
406 | } | 327 | } |
407 | 328 | ||
408 | u32 si_pmu_measure_alpclk(struct si_pub *sih) | 329 | u32 si_pmu_measure_alpclk(struct si_pub *sih) |
409 | { | 330 | { |
410 | struct chipcregs __iomem *cc; | 331 | struct bcma_device *core; |
411 | uint origidx; | ||
412 | u32 alp_khz; | 332 | u32 alp_khz; |
413 | 333 | ||
414 | if (sih->pmurev < 10) | 334 | if (ai_get_pmurev(sih) < 10) |
415 | return 0; | 335 | return 0; |
416 | 336 | ||
417 | /* Remember original core before switch to chipc */ | 337 | /* Remember original core before switch to chipc */ |
418 | origidx = ai_coreidx(sih); | 338 | core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0); |
419 | cc = ai_setcoreidx(sih, SI_CC_IDX); | ||
420 | 339 | ||
421 | if (R_REG(&cc->pmustatus) & PST_EXTLPOAVAIL) { | 340 | if (bcma_read32(core, CHIPCREGOFFS(pmustatus)) & PST_EXTLPOAVAIL) { |
422 | u32 ilp_ctr, alp_hz; | 341 | u32 ilp_ctr, alp_hz; |
423 | 342 | ||
424 | /* | 343 | /* |
425 | * Enable the reg to measure the freq, | 344 | * Enable the reg to measure the freq, |
426 | * in case it was disabled before | 345 | * in case it was disabled before |
427 | */ | 346 | */ |
428 | W_REG(&cc->pmu_xtalfreq, | 347 | bcma_write32(core, CHIPCREGOFFS(pmu_xtalfreq), |
429 | 1U << PMU_XTALFREQ_REG_MEASURE_SHIFT); | 348 | 1U << PMU_XTALFREQ_REG_MEASURE_SHIFT); |
430 | 349 | ||
431 | /* Delay for well over 4 ILP clocks */ | 350 | /* Delay for well over 4 ILP clocks */ |
432 | udelay(1000); | 351 | udelay(1000); |
433 | 352 | ||
434 | /* Read the latched number of ALP ticks per 4 ILP ticks */ | 353 | /* Read the latched number of ALP ticks per 4 ILP ticks */ |
435 | ilp_ctr = | 354 | ilp_ctr = bcma_read32(core, CHIPCREGOFFS(pmu_xtalfreq)) & |
436 | R_REG(&cc->pmu_xtalfreq) & PMU_XTALFREQ_REG_ILPCTR_MASK; | 355 | PMU_XTALFREQ_REG_ILPCTR_MASK; |
437 | 356 | ||
438 | /* | 357 | /* |
439 | * Turn off the PMU_XTALFREQ_REG_MEASURE_SHIFT | 358 | * Turn off the PMU_XTALFREQ_REG_MEASURE_SHIFT |
440 | * bit to save power | 359 | * bit to save power |
441 | */ | 360 | */ |
442 | W_REG(&cc->pmu_xtalfreq, 0); | 361 | bcma_write32(core, CHIPCREGOFFS(pmu_xtalfreq), 0); |
443 | 362 | ||
444 | /* Calculate ALP frequency */ | 363 | /* Calculate ALP frequency */ |
445 | alp_hz = (ilp_ctr * EXT_ILP_HZ) / 4; | 364 | alp_hz = (ilp_ctr * EXT_ILP_HZ) / 4; |
@@ -452,8 +371,5 @@ u32 si_pmu_measure_alpclk(struct si_pub *sih) | |||
452 | } else | 371 | } else |
453 | alp_khz = 0; | 372 | alp_khz = 0; |
454 | 373 | ||
455 | /* Return to original core */ | ||
456 | ai_setcoreidx(sih, origidx); | ||
457 | |||
458 | return alp_khz; | 374 | return alp_khz; |
459 | } | 375 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pmu.h b/drivers/net/wireless/brcm80211/brcmsmac/pmu.h index 3a08c620640e..3e39c5e0f9ff 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/pmu.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/pmu.h | |||
@@ -26,13 +26,10 @@ extern u32 si_pmu_chipcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val); | |||
26 | extern u32 si_pmu_regcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val); | 26 | extern u32 si_pmu_regcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val); |
27 | extern u32 si_pmu_alp_clock(struct si_pub *sih); | 27 | extern u32 si_pmu_alp_clock(struct si_pub *sih); |
28 | extern void si_pmu_pllupd(struct si_pub *sih); | 28 | extern void si_pmu_pllupd(struct si_pub *sih); |
29 | extern void si_pmu_spuravoid(struct si_pub *sih, u8 spuravoid); | 29 | extern void si_pmu_spuravoid_pllupdate(struct si_pub *sih, u8 spuravoid); |
30 | extern u32 si_pmu_pllcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val); | 30 | extern u32 si_pmu_pllcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val); |
31 | extern void si_pmu_init(struct si_pub *sih); | 31 | extern void si_pmu_init(struct si_pub *sih); |
32 | extern void si_pmu_chip_init(struct si_pub *sih); | ||
33 | extern void si_pmu_pll_init(struct si_pub *sih, u32 xtalfreq); | ||
34 | extern void si_pmu_res_init(struct si_pub *sih); | 32 | extern void si_pmu_res_init(struct si_pub *sih); |
35 | extern void si_pmu_swreg_init(struct si_pub *sih); | ||
36 | extern u32 si_pmu_measure_alpclk(struct si_pub *sih); | 33 | extern u32 si_pmu_measure_alpclk(struct si_pub *sih); |
37 | 34 | ||
38 | #endif /* _BRCM_PMU_H_ */ | 35 | #endif /* _BRCM_PMU_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pub.h b/drivers/net/wireless/brcm80211/brcmsmac/pub.h index 21ccf3a03987..f0038ad7d7bf 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/pub.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/pub.h | |||
@@ -17,6 +17,7 @@ | |||
17 | #ifndef _BRCM_PUB_H_ | 17 | #ifndef _BRCM_PUB_H_ |
18 | #define _BRCM_PUB_H_ | 18 | #define _BRCM_PUB_H_ |
19 | 19 | ||
20 | #include <linux/bcma/bcma.h> | ||
20 | #include <brcmu_wifi.h> | 21 | #include <brcmu_wifi.h> |
21 | #include "types.h" | 22 | #include "types.h" |
22 | #include "defs.h" | 23 | #include "defs.h" |
@@ -530,9 +531,8 @@ struct brcms_antselcfg { | |||
530 | 531 | ||
531 | /* common functions for every port */ | 532 | /* common functions for every port */ |
532 | extern struct brcms_c_info * | 533 | extern struct brcms_c_info * |
533 | brcms_c_attach(struct brcms_info *wl, u16 vendor, u16 device, uint unit, | 534 | brcms_c_attach(struct brcms_info *wl, struct bcma_device *core, uint unit, |
534 | bool piomode, void __iomem *regsva, struct pci_dev *btparam, | 535 | bool piomode, uint *perr); |
535 | uint *perr); | ||
536 | extern uint brcms_c_detach(struct brcms_c_info *wlc); | 536 | extern uint brcms_c_detach(struct brcms_c_info *wlc); |
537 | extern int brcms_c_up(struct brcms_c_info *wlc); | 537 | extern int brcms_c_up(struct brcms_c_info *wlc); |
538 | extern uint brcms_c_down(struct brcms_c_info *wlc); | 538 | extern uint brcms_c_down(struct brcms_c_info *wlc); |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/srom.c b/drivers/net/wireless/brcm80211/brcmsmac/srom.c index b6987ea9fc68..61092156755e 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/srom.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/srom.c | |||
@@ -586,17 +586,6 @@ static const struct brcms_sromvar perpath_pci_sromvars[] = { | |||
586 | * shared between devices. */ | 586 | * shared between devices. */ |
587 | static u8 brcms_srom_crc8_table[CRC8_TABLE_SIZE]; | 587 | static u8 brcms_srom_crc8_table[CRC8_TABLE_SIZE]; |
588 | 588 | ||
589 | static u8 __iomem * | ||
590 | srom_window_address(struct si_pub *sih, u8 __iomem *curmap) | ||
591 | { | ||
592 | if (sih->ccrev < 32) | ||
593 | return curmap + PCI_BAR0_SPROM_OFFSET; | ||
594 | if (sih->cccaps & CC_CAP_SROM) | ||
595 | return curmap + PCI_16KB0_CCREGS_OFFSET + CC_SROM_OTP; | ||
596 | |||
597 | return NULL; | ||
598 | } | ||
599 | |||
600 | static uint mask_shift(u16 mask) | 589 | static uint mask_shift(u16 mask) |
601 | { | 590 | { |
602 | uint i; | 591 | uint i; |
@@ -779,17 +768,27 @@ _initvars_srom_pci(u8 sromrev, u16 *srom, struct list_head *var_list) | |||
779 | * Return 0 on success, nonzero on error. | 768 | * Return 0 on success, nonzero on error. |
780 | */ | 769 | */ |
781 | static int | 770 | static int |
782 | sprom_read_pci(struct si_pub *sih, u8 __iomem *sprom, uint wordoff, | 771 | sprom_read_pci(struct si_pub *sih, u16 *buf, uint nwords, bool check_crc) |
783 | u16 *buf, uint nwords, bool check_crc) | ||
784 | { | 772 | { |
785 | int err = 0; | 773 | int err = 0; |
786 | uint i; | 774 | uint i; |
787 | u8 *bbuf = (u8 *)buf; /* byte buffer */ | 775 | u8 *bbuf = (u8 *)buf; /* byte buffer */ |
788 | uint nbytes = nwords << 1; | 776 | uint nbytes = nwords << 1; |
777 | struct bcma_device *core; | ||
778 | uint sprom_offset; | ||
779 | |||
780 | /* determine core to read */ | ||
781 | if (ai_get_ccrev(sih) < 32) { | ||
782 | core = ai_findcore(sih, BCMA_CORE_80211, 0); | ||
783 | sprom_offset = PCI_BAR0_SPROM_OFFSET; | ||
784 | } else { | ||
785 | core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0); | ||
786 | sprom_offset = CHIPCREGOFFS(sromotp); | ||
787 | } | ||
789 | 788 | ||
790 | /* read the sprom in bytes */ | 789 | /* read the sprom in bytes */ |
791 | for (i = 0; i < nbytes; i++) | 790 | for (i = 0; i < nbytes; i++) |
792 | bbuf[i] = readb(sprom+i); | 791 | bbuf[i] = bcma_read8(core, sprom_offset+i); |
793 | 792 | ||
794 | if (buf[0] == 0xffff) | 793 | if (buf[0] == 0xffff) |
795 | /* | 794 | /* |
@@ -851,10 +850,9 @@ static int otp_read_pci(struct si_pub *sih, u16 *buf, uint nwords) | |||
851 | * Initialize nonvolatile variable table from sprom. | 850 | * Initialize nonvolatile variable table from sprom. |
852 | * Return 0 on success, nonzero on error. | 851 | * Return 0 on success, nonzero on error. |
853 | */ | 852 | */ |
854 | static int initvars_srom_pci(struct si_pub *sih, void __iomem *curmap) | 853 | int srom_var_init(struct si_pub *sih) |
855 | { | 854 | { |
856 | u16 *srom; | 855 | u16 *srom; |
857 | u8 __iomem *sromwindow; | ||
858 | u8 sromrev = 0; | 856 | u8 sromrev = 0; |
859 | u32 sr; | 857 | u32 sr; |
860 | int err = 0; | 858 | int err = 0; |
@@ -866,12 +864,9 @@ static int initvars_srom_pci(struct si_pub *sih, void __iomem *curmap) | |||
866 | if (!srom) | 864 | if (!srom) |
867 | return -ENOMEM; | 865 | return -ENOMEM; |
868 | 866 | ||
869 | sromwindow = srom_window_address(sih, curmap); | ||
870 | |||
871 | crc8_populate_lsb(brcms_srom_crc8_table, SROM_CRC8_POLY); | 867 | crc8_populate_lsb(brcms_srom_crc8_table, SROM_CRC8_POLY); |
872 | if (ai_is_sprom_available(sih)) { | 868 | if (ai_is_sprom_available(sih)) { |
873 | err = sprom_read_pci(sih, sromwindow, 0, srom, | 869 | err = sprom_read_pci(sih, srom, SROM4_WORDS, true); |
874 | SROM4_WORDS, true); | ||
875 | 870 | ||
876 | if (err == 0) | 871 | if (err == 0) |
877 | /* srom read and passed crc */ | 872 | /* srom read and passed crc */ |
@@ -921,21 +916,6 @@ void srom_free_vars(struct si_pub *sih) | |||
921 | kfree(entry); | 916 | kfree(entry); |
922 | } | 917 | } |
923 | } | 918 | } |
924 | /* | ||
925 | * Initialize local vars from the right source for this platform. | ||
926 | * Return 0 on success, nonzero on error. | ||
927 | */ | ||
928 | int srom_var_init(struct si_pub *sih, void __iomem *curmap) | ||
929 | { | ||
930 | uint len; | ||
931 | |||
932 | len = 0; | ||
933 | |||
934 | if (curmap != NULL) | ||
935 | return initvars_srom_pci(sih, curmap); | ||
936 | |||
937 | return -EINVAL; | ||
938 | } | ||
939 | 919 | ||
940 | /* | 920 | /* |
941 | * Search the name=value vars for a specific one and return its value. | 921 | * Search the name=value vars for a specific one and return its value. |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/srom.h b/drivers/net/wireless/brcm80211/brcmsmac/srom.h index c81df9798e50..f2a58f262c99 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/srom.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/srom.h | |||
@@ -20,7 +20,7 @@ | |||
20 | #include "types.h" | 20 | #include "types.h" |
21 | 21 | ||
22 | /* Prototypes */ | 22 | /* Prototypes */ |
23 | extern int srom_var_init(struct si_pub *sih, void __iomem *curmap); | 23 | extern int srom_var_init(struct si_pub *sih); |
24 | extern void srom_free_vars(struct si_pub *sih); | 24 | extern void srom_free_vars(struct si_pub *sih); |
25 | 25 | ||
26 | extern int srom_read(struct si_pub *sih, uint bus, void *curmap, | 26 | extern int srom_read(struct si_pub *sih, uint bus, void *curmap, |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/types.h b/drivers/net/wireless/brcm80211/brcmsmac/types.h index 27a814b07462..e11ae83111e4 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/types.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/types.h | |||
@@ -250,66 +250,18 @@ do { \ | |||
250 | wiphy_err(dev, "%s: " fmt, __func__, ##args); \ | 250 | wiphy_err(dev, "%s: " fmt, __func__, ##args); \ |
251 | } while (0) | 251 | } while (0) |
252 | 252 | ||
253 | /* | ||
254 | * Register access macros. | ||
255 | * | ||
256 | * These macro's take a pointer to the address to read as one of their | ||
257 | * arguments. The macro itself deduces the size of the IO transaction (u8, u16 | ||
258 | * or u32). Advantage of this approach in combination with using a struct to | ||
259 | * define the registers in a register block, is that access size and access | ||
260 | * location are defined in only one spot. This reduces the risk of the | ||
261 | * programmer trying to use an unsupported transaction size on a register. | ||
262 | * | ||
263 | */ | ||
264 | |||
265 | #define R_REG(r) \ | ||
266 | ({ \ | ||
267 | __typeof(*(r)) __osl_v; \ | ||
268 | switch (sizeof(*(r))) { \ | ||
269 | case sizeof(u8): \ | ||
270 | __osl_v = readb((u8 __iomem *)(r)); \ | ||
271 | break; \ | ||
272 | case sizeof(u16): \ | ||
273 | __osl_v = readw((u16 __iomem *)(r)); \ | ||
274 | break; \ | ||
275 | case sizeof(u32): \ | ||
276 | __osl_v = readl((u32 __iomem *)(r)); \ | ||
277 | break; \ | ||
278 | } \ | ||
279 | __osl_v; \ | ||
280 | }) | ||
281 | |||
282 | #define W_REG(r, v) do { \ | ||
283 | switch (sizeof(*(r))) { \ | ||
284 | case sizeof(u8): \ | ||
285 | writeb((u8)((v) & 0xFF), (u8 __iomem *)(r)); \ | ||
286 | break; \ | ||
287 | case sizeof(u16): \ | ||
288 | writew((u16)((v) & 0xFFFF), (u16 __iomem *)(r)); \ | ||
289 | break; \ | ||
290 | case sizeof(u32): \ | ||
291 | writel((u32)(v), (u32 __iomem *)(r)); \ | ||
292 | break; \ | ||
293 | } \ | ||
294 | } while (0) | ||
295 | |||
296 | #ifdef CONFIG_BCM47XX | 253 | #ifdef CONFIG_BCM47XX |
297 | /* | 254 | /* |
298 | * bcm4716 (which includes 4717 & 4718), plus 4706 on PCIe can reorder | 255 | * bcm4716 (which includes 4717 & 4718), plus 4706 on PCIe can reorder |
299 | * transactions. As a fix, a read after write is performed on certain places | 256 | * transactions. As a fix, a read after write is performed on certain places |
300 | * in the code. Older chips and the newer 5357 family don't require this fix. | 257 | * in the code. Older chips and the newer 5357 family don't require this fix. |
301 | */ | 258 | */ |
302 | #define W_REG_FLUSH(r, v) ({ W_REG((r), (v)); (void)R_REG(r); }) | 259 | #define bcma_wflush16(c, o, v) \ |
260 | ({ bcma_write16(c, o, v); (void)bcma_read16(c, o); }) | ||
303 | #else | 261 | #else |
304 | #define W_REG_FLUSH(r, v) W_REG((r), (v)) | 262 | #define bcma_wflush16(c, o, v) bcma_write16(c, o, v) |
305 | #endif /* CONFIG_BCM47XX */ | 263 | #endif /* CONFIG_BCM47XX */ |
306 | 264 | ||
307 | #define AND_REG(r, v) W_REG((r), R_REG(r) & (v)) | ||
308 | #define OR_REG(r, v) W_REG((r), R_REG(r) | (v)) | ||
309 | |||
310 | #define SET_REG(r, mask, val) \ | ||
311 | W_REG((r), ((R_REG(r) & ~(mask)) | (val))) | ||
312 | |||
313 | /* multi-bool data type: set of bools, mbool is true if any is set */ | 265 | /* multi-bool data type: set of bools, mbool is true if any is set */ |
314 | 266 | ||
315 | /* set one bool */ | 267 | /* set one bool */ |
diff --git a/drivers/net/wireless/brcm80211/include/chipcommon.h b/drivers/net/wireless/brcm80211/include/chipcommon.h index fefabc39e646..f96834a7c055 100644 --- a/drivers/net/wireless/brcm80211/include/chipcommon.h +++ b/drivers/net/wireless/brcm80211/include/chipcommon.h | |||
@@ -19,6 +19,8 @@ | |||
19 | 19 | ||
20 | #include "defs.h" /* for PAD macro */ | 20 | #include "defs.h" /* for PAD macro */ |
21 | 21 | ||
22 | #define CHIPCREGOFFS(field) offsetof(struct chipcregs, field) | ||
23 | |||
22 | struct chipcregs { | 24 | struct chipcregs { |
23 | u32 chipid; /* 0x0 */ | 25 | u32 chipid; /* 0x0 */ |
24 | u32 capabilities; | 26 | u32 capabilities; |
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index 57703d5209d7..ae08498dfcad 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig | |||
@@ -102,12 +102,28 @@ config IWLWIFI_DEVICE_TRACING | |||
102 | occur. | 102 | occur. |
103 | endmenu | 103 | endmenu |
104 | 104 | ||
105 | config IWLWIFI_DEVICE_SVTOOL | 105 | config IWLWIFI_DEVICE_TESTMODE |
106 | bool "iwlwifi device svtool support" | 106 | def_bool y |
107 | depends on IWLWIFI | 107 | depends on IWLWIFI |
108 | select NL80211_TESTMODE | 108 | depends on NL80211_TESTMODE |
109 | help | 109 | help |
110 | This option enables the svtool support for iwlwifi device through | 110 | This option enables the testmode support for iwlwifi device through |
111 | NL80211_TESTMODE. svtool is a software validation tool that runs in | 111 | NL80211_TESTMODE. This provide the capabilities of enable user space |
112 | the user space and interacts with the device in the kernel space | 112 | validation applications to interacts with the device through the |
113 | through the generic netlink message via NL80211_TESTMODE channel. | 113 | generic netlink message via NL80211_TESTMODE channel. |
114 | |||
115 | config IWLWIFI_P2P | ||
116 | bool "iwlwifi experimental P2P support" | ||
117 | depends on IWLWIFI | ||
118 | help | ||
119 | This option enables experimental P2P support for some devices | ||
120 | based on microcode support. Since P2P support is still under | ||
121 | development, this option may even enable it for some devices | ||
122 | now that turn out to not support it in the future due to | ||
123 | microcode restrictions. | ||
124 | |||
125 | To determine if your microcode supports the experimental P2P | ||
126 | offered by this option, check if the driver advertises AP | ||
127 | support when it is loaded. | ||
128 | |||
129 | Say Y only if you want to experiment with P2P. | ||
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 86344cefd32f..9dc84a7354db 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile | |||
@@ -18,7 +18,7 @@ iwlwifi-objs += iwl-trans-pcie.o iwl-trans-pcie-rx.o iwl-trans-pcie-tx.o | |||
18 | 18 | ||
19 | iwlwifi-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o | 19 | iwlwifi-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o |
20 | iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o | 20 | iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o |
21 | iwlwifi-$(CONFIG_IWLWIFI_DEVICE_SVTOOL) += iwl-testmode.o | 21 | iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TESTMODE) += iwl-testmode.o |
22 | 22 | ||
23 | CFLAGS_iwl-devtrace.o := -I$(src) | 23 | CFLAGS_iwl-devtrace.o := -I$(src) |
24 | 24 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index cf2fb47529b3..6706d7c10bd8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -134,10 +134,10 @@ static struct iwl_sensitivity_ranges iwl5150_sensitivity = { | |||
134 | 134 | ||
135 | #define IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF (-5) | 135 | #define IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF (-5) |
136 | 136 | ||
137 | static s32 iwl_temp_calib_to_offset(struct iwl_priv *priv) | 137 | static s32 iwl_temp_calib_to_offset(struct iwl_shared *shrd) |
138 | { | 138 | { |
139 | u16 temperature, voltage; | 139 | u16 temperature, voltage; |
140 | __le16 *temp_calib = (__le16 *)iwl_eeprom_query_addr(priv, | 140 | __le16 *temp_calib = (__le16 *)iwl_eeprom_query_addr(shrd, |
141 | EEPROM_KELVIN_TEMPERATURE); | 141 | EEPROM_KELVIN_TEMPERATURE); |
142 | 142 | ||
143 | temperature = le16_to_cpu(temp_calib[0]); | 143 | temperature = le16_to_cpu(temp_calib[0]); |
@@ -151,7 +151,7 @@ static void iwl5150_set_ct_threshold(struct iwl_priv *priv) | |||
151 | { | 151 | { |
152 | const s32 volt2temp_coef = IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF; | 152 | const s32 volt2temp_coef = IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF; |
153 | s32 threshold = (s32)CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD_LEGACY) - | 153 | s32 threshold = (s32)CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD_LEGACY) - |
154 | iwl_temp_calib_to_offset(priv); | 154 | iwl_temp_calib_to_offset(priv->shrd); |
155 | 155 | ||
156 | hw_params(priv).ct_kill_threshold = threshold * volt2temp_coef; | 156 | hw_params(priv).ct_kill_threshold = threshold * volt2temp_coef; |
157 | } | 157 | } |
@@ -223,7 +223,7 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv) | |||
223 | static void iwl5150_temperature(struct iwl_priv *priv) | 223 | static void iwl5150_temperature(struct iwl_priv *priv) |
224 | { | 224 | { |
225 | u32 vt = 0; | 225 | u32 vt = 0; |
226 | s32 offset = iwl_temp_calib_to_offset(priv); | 226 | s32 offset = iwl_temp_calib_to_offset(priv->shrd); |
227 | 227 | ||
228 | vt = le32_to_cpu(priv->statistics.common.temperature); | 228 | vt = le32_to_cpu(priv->statistics.common.temperature); |
229 | vt = vt / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF + offset; | 229 | vt = vt / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF + offset; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 617ad1c0df61..3e277b6774f1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c | |||
@@ -81,7 +81,7 @@ static void iwl6000_set_ct_threshold(struct iwl_priv *priv) | |||
81 | static void iwl6050_additional_nic_config(struct iwl_priv *priv) | 81 | static void iwl6050_additional_nic_config(struct iwl_priv *priv) |
82 | { | 82 | { |
83 | /* Indicate calibration version to uCode. */ | 83 | /* Indicate calibration version to uCode. */ |
84 | if (iwlagn_eeprom_calib_version(priv) >= 6) | 84 | if (iwl_eeprom_calib_version(priv->shrd) >= 6) |
85 | iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG, | 85 | iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG, |
86 | CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); | 86 | CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); |
87 | } | 87 | } |
@@ -89,7 +89,7 @@ static void iwl6050_additional_nic_config(struct iwl_priv *priv) | |||
89 | static void iwl6150_additional_nic_config(struct iwl_priv *priv) | 89 | static void iwl6150_additional_nic_config(struct iwl_priv *priv) |
90 | { | 90 | { |
91 | /* Indicate calibration version to uCode. */ | 91 | /* Indicate calibration version to uCode. */ |
92 | if (iwlagn_eeprom_calib_version(priv) >= 6) | 92 | if (iwl_eeprom_calib_version(priv->shrd) >= 6) |
93 | iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG, | 93 | iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG, |
94 | CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); | 94 | CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); |
95 | iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG, | 95 | iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index 4d0210594956..16971a020297 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c | |||
@@ -82,7 +82,7 @@ struct statistics_general_data { | |||
82 | u32 beacon_energy_c; | 82 | u32 beacon_energy_c; |
83 | }; | 83 | }; |
84 | 84 | ||
85 | int iwl_send_calib_results(struct iwl_priv *priv) | 85 | int iwl_send_calib_results(struct iwl_trans *trans) |
86 | { | 86 | { |
87 | struct iwl_host_cmd hcmd = { | 87 | struct iwl_host_cmd hcmd = { |
88 | .id = REPLY_PHY_CALIBRATION_CMD, | 88 | .id = REPLY_PHY_CALIBRATION_CMD, |
@@ -90,15 +90,15 @@ int iwl_send_calib_results(struct iwl_priv *priv) | |||
90 | }; | 90 | }; |
91 | struct iwl_calib_result *res; | 91 | struct iwl_calib_result *res; |
92 | 92 | ||
93 | list_for_each_entry(res, &priv->calib_results, list) { | 93 | list_for_each_entry(res, &trans->calib_results, list) { |
94 | int ret; | 94 | int ret; |
95 | 95 | ||
96 | hcmd.len[0] = res->cmd_len; | 96 | hcmd.len[0] = res->cmd_len; |
97 | hcmd.data[0] = &res->hdr; | 97 | hcmd.data[0] = &res->hdr; |
98 | hcmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; | 98 | hcmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; |
99 | ret = iwl_trans_send_cmd(trans(priv), &hcmd); | 99 | ret = iwl_trans_send_cmd(trans, &hcmd); |
100 | if (ret) { | 100 | if (ret) { |
101 | IWL_ERR(priv, "Error %d on calib cmd %d\n", | 101 | IWL_ERR(trans, "Error %d on calib cmd %d\n", |
102 | ret, res->hdr.op_code); | 102 | ret, res->hdr.op_code); |
103 | return ret; | 103 | return ret; |
104 | } | 104 | } |
@@ -107,7 +107,7 @@ int iwl_send_calib_results(struct iwl_priv *priv) | |||
107 | return 0; | 107 | return 0; |
108 | } | 108 | } |
109 | 109 | ||
110 | int iwl_calib_set(struct iwl_priv *priv, | 110 | int iwl_calib_set(struct iwl_trans *trans, |
111 | const struct iwl_calib_hdr *cmd, int len) | 111 | const struct iwl_calib_hdr *cmd, int len) |
112 | { | 112 | { |
113 | struct iwl_calib_result *res, *tmp; | 113 | struct iwl_calib_result *res, *tmp; |
@@ -119,7 +119,7 @@ int iwl_calib_set(struct iwl_priv *priv, | |||
119 | memcpy(&res->hdr, cmd, len); | 119 | memcpy(&res->hdr, cmd, len); |
120 | res->cmd_len = len; | 120 | res->cmd_len = len; |
121 | 121 | ||
122 | list_for_each_entry(tmp, &priv->calib_results, list) { | 122 | list_for_each_entry(tmp, &trans->calib_results, list) { |
123 | if (tmp->hdr.op_code == res->hdr.op_code) { | 123 | if (tmp->hdr.op_code == res->hdr.op_code) { |
124 | list_replace(&tmp->list, &res->list); | 124 | list_replace(&tmp->list, &res->list); |
125 | kfree(tmp); | 125 | kfree(tmp); |
@@ -128,16 +128,16 @@ int iwl_calib_set(struct iwl_priv *priv, | |||
128 | } | 128 | } |
129 | 129 | ||
130 | /* wasn't in list already */ | 130 | /* wasn't in list already */ |
131 | list_add_tail(&res->list, &priv->calib_results); | 131 | list_add_tail(&res->list, &trans->calib_results); |
132 | 132 | ||
133 | return 0; | 133 | return 0; |
134 | } | 134 | } |
135 | 135 | ||
136 | void iwl_calib_free_results(struct iwl_priv *priv) | 136 | void iwl_calib_free_results(struct iwl_trans *trans) |
137 | { | 137 | { |
138 | struct iwl_calib_result *res, *tmp; | 138 | struct iwl_calib_result *res, *tmp; |
139 | 139 | ||
140 | list_for_each_entry_safe(res, tmp, &priv->calib_results, list) { | 140 | list_for_each_entry_safe(res, tmp, &trans->calib_results, list) { |
141 | list_del(&res->list); | 141 | list_del(&res->list); |
142 | kfree(res); | 142 | kfree(res); |
143 | } | 143 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.h b/drivers/net/wireless/iwlwifi/iwl-agn-calib.h index 6ed806c8f80f..10275ce92bde 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.h | |||
@@ -72,9 +72,4 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv); | |||
72 | void iwl_init_sensitivity(struct iwl_priv *priv); | 72 | void iwl_init_sensitivity(struct iwl_priv *priv); |
73 | void iwl_reset_run_time_calib(struct iwl_priv *priv); | 73 | void iwl_reset_run_time_calib(struct iwl_priv *priv); |
74 | 74 | ||
75 | int iwl_send_calib_results(struct iwl_priv *priv); | ||
76 | int iwl_calib_set(struct iwl_priv *priv, | ||
77 | const struct iwl_calib_hdr *cmd, int len); | ||
78 | void iwl_calib_free_results(struct iwl_priv *priv); | ||
79 | |||
80 | #endif /* __iwl_calib_h__ */ | 75 | #endif /* __iwl_calib_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 575d1bb8e8cc..057f95233567 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c | |||
@@ -92,11 +92,11 @@ void iwlagn_temperature(struct iwl_priv *priv) | |||
92 | iwl_tt_handler(priv); | 92 | iwl_tt_handler(priv); |
93 | } | 93 | } |
94 | 94 | ||
95 | u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv) | 95 | u16 iwl_eeprom_calib_version(struct iwl_shared *shrd) |
96 | { | 96 | { |
97 | struct iwl_eeprom_calib_hdr *hdr; | 97 | struct iwl_eeprom_calib_hdr *hdr; |
98 | 98 | ||
99 | hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv, | 99 | hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(shrd, |
100 | EEPROM_CALIB_ALL); | 100 | EEPROM_CALIB_ALL); |
101 | return hdr->version; | 101 | return hdr->version; |
102 | 102 | ||
@@ -105,7 +105,7 @@ u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv) | |||
105 | /* | 105 | /* |
106 | * EEPROM | 106 | * EEPROM |
107 | */ | 107 | */ |
108 | static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address) | 108 | static u32 eeprom_indirect_address(const struct iwl_shared *shrd, u32 address) |
109 | { | 109 | { |
110 | u16 offset = 0; | 110 | u16 offset = 0; |
111 | 111 | ||
@@ -114,31 +114,31 @@ static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address) | |||
114 | 114 | ||
115 | switch (address & INDIRECT_TYPE_MSK) { | 115 | switch (address & INDIRECT_TYPE_MSK) { |
116 | case INDIRECT_HOST: | 116 | case INDIRECT_HOST: |
117 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_HOST); | 117 | offset = iwl_eeprom_query16(shrd, EEPROM_LINK_HOST); |
118 | break; | 118 | break; |
119 | case INDIRECT_GENERAL: | 119 | case INDIRECT_GENERAL: |
120 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_GENERAL); | 120 | offset = iwl_eeprom_query16(shrd, EEPROM_LINK_GENERAL); |
121 | break; | 121 | break; |
122 | case INDIRECT_REGULATORY: | 122 | case INDIRECT_REGULATORY: |
123 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_REGULATORY); | 123 | offset = iwl_eeprom_query16(shrd, EEPROM_LINK_REGULATORY); |
124 | break; | 124 | break; |
125 | case INDIRECT_TXP_LIMIT: | 125 | case INDIRECT_TXP_LIMIT: |
126 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_TXP_LIMIT); | 126 | offset = iwl_eeprom_query16(shrd, EEPROM_LINK_TXP_LIMIT); |
127 | break; | 127 | break; |
128 | case INDIRECT_TXP_LIMIT_SIZE: | 128 | case INDIRECT_TXP_LIMIT_SIZE: |
129 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_TXP_LIMIT_SIZE); | 129 | offset = iwl_eeprom_query16(shrd, EEPROM_LINK_TXP_LIMIT_SIZE); |
130 | break; | 130 | break; |
131 | case INDIRECT_CALIBRATION: | 131 | case INDIRECT_CALIBRATION: |
132 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_CALIBRATION); | 132 | offset = iwl_eeprom_query16(shrd, EEPROM_LINK_CALIBRATION); |
133 | break; | 133 | break; |
134 | case INDIRECT_PROCESS_ADJST: | 134 | case INDIRECT_PROCESS_ADJST: |
135 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_PROCESS_ADJST); | 135 | offset = iwl_eeprom_query16(shrd, EEPROM_LINK_PROCESS_ADJST); |
136 | break; | 136 | break; |
137 | case INDIRECT_OTHERS: | 137 | case INDIRECT_OTHERS: |
138 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_OTHERS); | 138 | offset = iwl_eeprom_query16(shrd, EEPROM_LINK_OTHERS); |
139 | break; | 139 | break; |
140 | default: | 140 | default: |
141 | IWL_ERR(priv, "illegal indirect type: 0x%X\n", | 141 | IWL_ERR(shrd->trans, "illegal indirect type: 0x%X\n", |
142 | address & INDIRECT_TYPE_MSK); | 142 | address & INDIRECT_TYPE_MSK); |
143 | break; | 143 | break; |
144 | } | 144 | } |
@@ -147,11 +147,11 @@ static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address) | |||
147 | return (address & ADDRESS_MSK) + (offset << 1); | 147 | return (address & ADDRESS_MSK) + (offset << 1); |
148 | } | 148 | } |
149 | 149 | ||
150 | const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset) | 150 | const u8 *iwl_eeprom_query_addr(const struct iwl_shared *shrd, size_t offset) |
151 | { | 151 | { |
152 | u32 address = eeprom_indirect_address(priv, offset); | 152 | u32 address = eeprom_indirect_address(shrd, offset); |
153 | BUG_ON(address >= priv->cfg->base_params->eeprom_size); | 153 | BUG_ON(address >= shrd->priv->cfg->base_params->eeprom_size); |
154 | return &priv->eeprom[address]; | 154 | return &shrd->eeprom[address]; |
155 | } | 155 | } |
156 | 156 | ||
157 | struct iwl_mod_params iwlagn_mod_params = { | 157 | struct iwl_mod_params iwlagn_mod_params = { |
@@ -1157,7 +1157,7 @@ int iwlagn_suspend(struct iwl_priv *priv, | |||
1157 | * For QoS counters, we store the one to use next, so subtract 0x10 | 1157 | * For QoS counters, we store the one to use next, so subtract 0x10 |
1158 | * since the uCode will add 0x10 before using the value. | 1158 | * since the uCode will add 0x10 before using the value. |
1159 | */ | 1159 | */ |
1160 | for (i = 0; i < 8; i++) { | 1160 | for (i = 0; i < IWL_MAX_TID_COUNT; i++) { |
1161 | seq = priv->shrd->tid_data[IWL_AP_ID][i].seq_number; | 1161 | seq = priv->shrd->tid_data[IWL_AP_ID][i].seq_number; |
1162 | seq -= 0x10; | 1162 | seq -= 0x10; |
1163 | wakeup_filter_cmd.qos_seq[i] = cpu_to_le16(seq); | 1163 | wakeup_filter_cmd.qos_seq[i] = cpu_to_le16(seq); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 359c47a4fcea..a23835a7797a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |||
@@ -298,7 +298,7 @@ static u8 rs_tl_add_packet(struct iwl_lq_sta *lq_data, | |||
298 | } else | 298 | } else |
299 | return IWL_MAX_TID_COUNT; | 299 | return IWL_MAX_TID_COUNT; |
300 | 300 | ||
301 | if (unlikely(tid >= TID_MAX_LOAD_COUNT)) | 301 | if (unlikely(tid >= IWL_MAX_TID_COUNT)) |
302 | return IWL_MAX_TID_COUNT; | 302 | return IWL_MAX_TID_COUNT; |
303 | 303 | ||
304 | tl = &lq_data->load[tid]; | 304 | tl = &lq_data->load[tid]; |
@@ -352,7 +352,7 @@ static void rs_program_fix_rate(struct iwl_priv *priv, | |||
352 | lq_sta->active_mimo2_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ | 352 | lq_sta->active_mimo2_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ |
353 | lq_sta->active_mimo3_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ | 353 | lq_sta->active_mimo3_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ |
354 | 354 | ||
355 | #ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL | 355 | #ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE |
356 | /* testmode has higher priority to overwirte the fixed rate */ | 356 | /* testmode has higher priority to overwirte the fixed rate */ |
357 | if (priv->tm_fixed_rate) | 357 | if (priv->tm_fixed_rate) |
358 | lq_sta->dbg_fixed_rate = priv->tm_fixed_rate; | 358 | lq_sta->dbg_fixed_rate = priv->tm_fixed_rate; |
@@ -379,7 +379,7 @@ static u32 rs_tl_get_load(struct iwl_lq_sta *lq_data, u8 tid) | |||
379 | s32 index; | 379 | s32 index; |
380 | struct iwl_traffic_load *tl = NULL; | 380 | struct iwl_traffic_load *tl = NULL; |
381 | 381 | ||
382 | if (tid >= TID_MAX_LOAD_COUNT) | 382 | if (tid >= IWL_MAX_TID_COUNT) |
383 | return 0; | 383 | return 0; |
384 | 384 | ||
385 | tl = &(lq_data->load[tid]); | 385 | tl = &(lq_data->load[tid]); |
@@ -444,11 +444,11 @@ static void rs_tl_turn_on_agg(struct iwl_priv *priv, u8 tid, | |||
444 | struct iwl_lq_sta *lq_data, | 444 | struct iwl_lq_sta *lq_data, |
445 | struct ieee80211_sta *sta) | 445 | struct ieee80211_sta *sta) |
446 | { | 446 | { |
447 | if (tid < TID_MAX_LOAD_COUNT) | 447 | if (tid < IWL_MAX_TID_COUNT) |
448 | rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta); | 448 | rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta); |
449 | else | 449 | else |
450 | IWL_ERR(priv, "tid exceeds max load count: %d/%d\n", | 450 | IWL_ERR(priv, "tid exceeds max TID count: %d/%d\n", |
451 | tid, TID_MAX_LOAD_COUNT); | 451 | tid, IWL_MAX_TID_COUNT); |
452 | } | 452 | } |
453 | 453 | ||
454 | static inline int get_num_of_ant_from_rate(u32 rate_n_flags) | 454 | static inline int get_num_of_ant_from_rate(u32 rate_n_flags) |
@@ -1081,7 +1081,7 @@ done: | |||
1081 | if (sta && sta->supp_rates[sband->band]) | 1081 | if (sta && sta->supp_rates[sband->band]) |
1082 | rs_rate_scale_perform(priv, skb, sta, lq_sta); | 1082 | rs_rate_scale_perform(priv, skb, sta, lq_sta); |
1083 | 1083 | ||
1084 | #if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_IWLWIFI_DEVICE_SVTOOL) | 1084 | #if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_IWLWIFI_DEVICE_TESTMODE) |
1085 | if ((priv->tm_fixed_rate) && | 1085 | if ((priv->tm_fixed_rate) && |
1086 | (priv->tm_fixed_rate != lq_sta->dbg_fixed_rate)) | 1086 | (priv->tm_fixed_rate != lq_sta->dbg_fixed_rate)) |
1087 | rs_program_fix_rate(priv, lq_sta); | 1087 | rs_program_fix_rate(priv, lq_sta); |
@@ -2904,7 +2904,7 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i | |||
2904 | if (sband->band == IEEE80211_BAND_5GHZ) | 2904 | if (sband->band == IEEE80211_BAND_5GHZ) |
2905 | lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; | 2905 | lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; |
2906 | lq_sta->is_agg = 0; | 2906 | lq_sta->is_agg = 0; |
2907 | #ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL | 2907 | #ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE |
2908 | priv->tm_fixed_rate = 0; | 2908 | priv->tm_fixed_rate = 0; |
2909 | #endif | 2909 | #endif |
2910 | #ifdef CONFIG_MAC80211_DEBUGFS | 2910 | #ifdef CONFIG_MAC80211_DEBUGFS |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h index f4f6deb829ae..6675b3c816d9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h | |||
@@ -281,7 +281,6 @@ enum { | |||
281 | #define TID_QUEUE_CELL_SPACING 50 /*mS */ | 281 | #define TID_QUEUE_CELL_SPACING 50 /*mS */ |
282 | #define TID_QUEUE_MAX_SIZE 20 | 282 | #define TID_QUEUE_MAX_SIZE 20 |
283 | #define TID_ROUND_VALUE 5 /* mS */ | 283 | #define TID_ROUND_VALUE 5 /* mS */ |
284 | #define TID_MAX_LOAD_COUNT 8 | ||
285 | 284 | ||
286 | #define TID_MAX_TIME_DIFF ((TID_QUEUE_MAX_SIZE - 1) * TID_QUEUE_CELL_SPACING) | 285 | #define TID_MAX_TIME_DIFF ((TID_QUEUE_MAX_SIZE - 1) * TID_QUEUE_CELL_SPACING) |
287 | #define TIME_WRAP_AROUND(x, y) (((y) > (x)) ? (y) - (x) : (0-(x)) + (y)) | 286 | #define TIME_WRAP_AROUND(x, y) (((y) > (x)) ? (y) - (x) : (0-(x)) + (y)) |
@@ -402,7 +401,7 @@ struct iwl_lq_sta { | |||
402 | 401 | ||
403 | struct iwl_link_quality_cmd lq; | 402 | struct iwl_link_quality_cmd lq; |
404 | struct iwl_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */ | 403 | struct iwl_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */ |
405 | struct iwl_traffic_load load[TID_MAX_LOAD_COUNT]; | 404 | struct iwl_traffic_load load[IWL_MAX_TID_COUNT]; |
406 | u8 tx_agg_tid_en; | 405 | u8 tx_agg_tid_en; |
407 | #ifdef CONFIG_MAC80211_DEBUGFS | 406 | #ifdef CONFIG_MAC80211_DEBUGFS |
408 | struct dentry *rs_sta_dbgfs_scale_table_file; | 407 | struct dentry *rs_sta_dbgfs_scale_table_file; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c index 90c55ea4cc39..9001c23f27bb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c | |||
@@ -1165,7 +1165,7 @@ int iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, | |||
1165 | pkt->hdr.cmd); | 1165 | pkt->hdr.cmd); |
1166 | w->triggered = true; | 1166 | w->triggered = true; |
1167 | if (w->fn) | 1167 | if (w->fn) |
1168 | w->fn(priv, pkt, w->fn_data); | 1168 | w->fn(trans(priv), pkt, w->fn_data); |
1169 | } | 1169 | } |
1170 | spin_unlock(&priv->shrd->notif_wait_lock); | 1170 | spin_unlock(&priv->shrd->notif_wait_lock); |
1171 | 1171 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 466e4ab544f7..d21f535a3b4f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | |||
@@ -610,8 +610,8 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
610 | if (ctx->ht.enabled) { | 610 | if (ctx->ht.enabled) { |
611 | /* if HT40 is used, it should not change | 611 | /* if HT40 is used, it should not change |
612 | * after associated except channel switch */ | 612 | * after associated except channel switch */ |
613 | if (iwl_is_associated_ctx(ctx) && | 613 | if (!ctx->ht.is_40mhz || |
614 | !ctx->ht.is_40mhz) | 614 | !iwl_is_associated_ctx(ctx)) |
615 | iwlagn_config_ht40(conf, ctx); | 615 | iwlagn_config_ht40(conf, ctx); |
616 | } else | 616 | } else |
617 | ctx->ht.is_40mhz = false; | 617 | ctx->ht.is_40mhz = false; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index 626ed701100e..63d948d21c04 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c | |||
@@ -135,8 +135,8 @@ static u16 iwlagn_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) | |||
135 | u16 size = (u16)sizeof(struct iwl_addsta_cmd); | 135 | u16 size = (u16)sizeof(struct iwl_addsta_cmd); |
136 | struct iwl_addsta_cmd *addsta = (struct iwl_addsta_cmd *)data; | 136 | struct iwl_addsta_cmd *addsta = (struct iwl_addsta_cmd *)data; |
137 | memcpy(addsta, cmd, size); | 137 | memcpy(addsta, cmd, size); |
138 | /* resrved in 5000 */ | 138 | /* resrved in agn */ |
139 | addsta->rate_n_flags = cpu_to_le16(0); | 139 | addsta->legacy_reserved = cpu_to_le16(0); |
140 | return size; | 140 | return size; |
141 | } | 141 | } |
142 | 142 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index a1a95d5f3923..81754cddba73 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c | |||
@@ -91,7 +91,10 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv, | |||
91 | tx_cmd->tid_tspec = qc[0] & 0xf; | 91 | tx_cmd->tid_tspec = qc[0] & 0xf; |
92 | tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK; | 92 | tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK; |
93 | } else { | 93 | } else { |
94 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; | 94 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) |
95 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; | ||
96 | else | ||
97 | tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK; | ||
95 | } | 98 | } |
96 | 99 | ||
97 | iwlagn_tx_cmd_protection(priv, info, fc, &tx_flags); | 100 | iwlagn_tx_cmd_protection(priv, info, fc, &tx_flags); |
@@ -148,7 +151,7 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, | |||
148 | if (ieee80211_is_data(fc)) { | 151 | if (ieee80211_is_data(fc)) { |
149 | tx_cmd->initial_rate_index = 0; | 152 | tx_cmd->initial_rate_index = 0; |
150 | tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK; | 153 | tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK; |
151 | #ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL | 154 | #ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE |
152 | if (priv->tm_fixed_rate) { | 155 | if (priv->tm_fixed_rate) { |
153 | /* | 156 | /* |
154 | * rate overwrite by testmode | 157 | * rate overwrite by testmode |
@@ -161,7 +164,8 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, | |||
161 | } | 164 | } |
162 | #endif | 165 | #endif |
163 | return; | 166 | return; |
164 | } | 167 | } else if (ieee80211_is_back_req(fc)) |
168 | tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK; | ||
165 | 169 | ||
166 | /** | 170 | /** |
167 | * If the current TX rate stored in mac80211 has the MCS bit set, it's | 171 | * If the current TX rate stored in mac80211 has the MCS bit set, it's |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index daf010dad70c..f5fe42dbb3b0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -366,7 +366,7 @@ static void iwl_continuous_event_trace(struct iwl_priv *priv) | |||
366 | u32 num_wraps; /* # times uCode wrapped to top of log */ | 366 | u32 num_wraps; /* # times uCode wrapped to top of log */ |
367 | u32 next_entry; /* index of next entry to be written by uCode */ | 367 | u32 next_entry; /* index of next entry to be written by uCode */ |
368 | 368 | ||
369 | base = priv->device_pointers.error_event_table; | 369 | base = priv->shrd->device_pointers.error_event_table; |
370 | if (iwlagn_hw_valid_rtc_data_addr(base)) { | 370 | if (iwlagn_hw_valid_rtc_data_addr(base)) { |
371 | capacity = iwl_read_targ_mem(bus(priv), base); | 371 | capacity = iwl_read_targ_mem(bus(priv), base); |
372 | num_wraps = iwl_read_targ_mem(bus(priv), | 372 | num_wraps = iwl_read_targ_mem(bus(priv), |
@@ -1036,6 +1036,9 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
1036 | priv->inst_evtlog_size = | 1036 | priv->inst_evtlog_size = |
1037 | priv->cfg->base_params->max_event_log_size; | 1037 | priv->cfg->base_params->max_event_log_size; |
1038 | priv->inst_errlog_ptr = pieces.inst_errlog_ptr; | 1038 | priv->inst_errlog_ptr = pieces.inst_errlog_ptr; |
1039 | #ifndef CONFIG_IWLWIFI_P2P | ||
1040 | ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_PAN; | ||
1041 | #endif | ||
1039 | 1042 | ||
1040 | priv->new_scan_threshold_behaviour = | 1043 | priv->new_scan_threshold_behaviour = |
1041 | !!(ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWSCAN); | 1044 | !!(ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWSCAN); |
@@ -1057,7 +1060,6 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
1057 | priv->sta_key_max_num = STA_KEY_MAX_NUM; | 1060 | priv->sta_key_max_num = STA_KEY_MAX_NUM; |
1058 | priv->shrd->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; | 1061 | priv->shrd->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; |
1059 | } | 1062 | } |
1060 | |||
1061 | /* | 1063 | /* |
1062 | * figure out the offset of chain noise reset and gain commands | 1064 | * figure out the offset of chain noise reset and gain commands |
1063 | * base on the size of standard phy calibration commands table size | 1065 | * base on the size of standard phy calibration commands table size |
@@ -1575,7 +1577,7 @@ static int iwl_init_drv(struct iwl_priv *priv) | |||
1575 | 1577 | ||
1576 | mutex_init(&priv->shrd->mutex); | 1578 | mutex_init(&priv->shrd->mutex); |
1577 | 1579 | ||
1578 | INIT_LIST_HEAD(&priv->calib_results); | 1580 | INIT_LIST_HEAD(&trans(priv)->calib_results); |
1579 | 1581 | ||
1580 | priv->ieee_channels = NULL; | 1582 | priv->ieee_channels = NULL; |
1581 | priv->ieee_rates = NULL; | 1583 | priv->ieee_rates = NULL; |
@@ -1633,7 +1635,6 @@ err: | |||
1633 | 1635 | ||
1634 | static void iwl_uninit_drv(struct iwl_priv *priv) | 1636 | static void iwl_uninit_drv(struct iwl_priv *priv) |
1635 | { | 1637 | { |
1636 | iwl_calib_free_results(priv); | ||
1637 | iwl_free_geos(priv); | 1638 | iwl_free_geos(priv); |
1638 | iwl_free_channel_map(priv); | 1639 | iwl_free_channel_map(priv); |
1639 | if (priv->tx_cmd_pool) | 1640 | if (priv->tx_cmd_pool) |
@@ -1703,8 +1704,14 @@ static void iwl_debug_config(struct iwl_priv *priv) | |||
1703 | "disabled\n"); | 1704 | "disabled\n"); |
1704 | #endif | 1705 | #endif |
1705 | 1706 | ||
1706 | dev_printk(KERN_INFO, bus(priv)->dev, "CONFIG_IWLWIFI_DEVICE_SVTOOL " | 1707 | dev_printk(KERN_INFO, bus(priv)->dev, "CONFIG_IWLWIFI_DEVICE_TESTMODE " |
1707 | #ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL | 1708 | #ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE |
1709 | "enabled\n"); | ||
1710 | #else | ||
1711 | "disabled\n"); | ||
1712 | #endif | ||
1713 | dev_printk(KERN_INFO, bus(priv)->dev, "CONFIG_IWLWIFI_P2P " | ||
1714 | #ifdef CONFIG_IWLWIFI_P2P | ||
1708 | "enabled\n"); | 1715 | "enabled\n"); |
1709 | #else | 1716 | #else |
1710 | "disabled\n"); | 1717 | "disabled\n"); |
@@ -1814,11 +1821,11 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, | |||
1814 | goto out_free_eeprom; | 1821 | goto out_free_eeprom; |
1815 | 1822 | ||
1816 | /* extract MAC Address */ | 1823 | /* extract MAC Address */ |
1817 | iwl_eeprom_get_mac(priv, priv->addresses[0].addr); | 1824 | iwl_eeprom_get_mac(priv->shrd, priv->addresses[0].addr); |
1818 | IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->addresses[0].addr); | 1825 | IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->addresses[0].addr); |
1819 | priv->hw->wiphy->addresses = priv->addresses; | 1826 | priv->hw->wiphy->addresses = priv->addresses; |
1820 | priv->hw->wiphy->n_addresses = 1; | 1827 | priv->hw->wiphy->n_addresses = 1; |
1821 | num_mac = iwl_eeprom_query16(priv, EEPROM_NUM_MAC_ADDRESS); | 1828 | num_mac = iwl_eeprom_query16(priv->shrd, EEPROM_NUM_MAC_ADDRESS); |
1822 | if (num_mac > 1) { | 1829 | if (num_mac > 1) { |
1823 | memcpy(priv->addresses[1].addr, priv->addresses[0].addr, | 1830 | memcpy(priv->addresses[1].addr, priv->addresses[0].addr, |
1824 | ETH_ALEN); | 1831 | ETH_ALEN); |
@@ -1883,7 +1890,7 @@ out_destroy_workqueue: | |||
1883 | priv->shrd->workqueue = NULL; | 1890 | priv->shrd->workqueue = NULL; |
1884 | iwl_uninit_drv(priv); | 1891 | iwl_uninit_drv(priv); |
1885 | out_free_eeprom: | 1892 | out_free_eeprom: |
1886 | iwl_eeprom_free(priv); | 1893 | iwl_eeprom_free(priv->shrd); |
1887 | out_free_trans: | 1894 | out_free_trans: |
1888 | iwl_trans_free(trans(priv)); | 1895 | iwl_trans_free(trans(priv)); |
1889 | out_free_traffic_mem: | 1896 | out_free_traffic_mem: |
@@ -1922,7 +1929,7 @@ void __devexit iwl_remove(struct iwl_priv * priv) | |||
1922 | 1929 | ||
1923 | iwl_dealloc_ucode(trans(priv)); | 1930 | iwl_dealloc_ucode(trans(priv)); |
1924 | 1931 | ||
1925 | iwl_eeprom_free(priv); | 1932 | iwl_eeprom_free(priv->shrd); |
1926 | 1933 | ||
1927 | /*netif_stop_queue(dev); */ | 1934 | /*netif_stop_queue(dev); */ |
1928 | flush_workqueue(priv->shrd->workqueue); | 1935 | flush_workqueue(priv->shrd->workqueue); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index f2f10702754d..eb453ea41c41 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h | |||
@@ -117,7 +117,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, | |||
117 | /* lib */ | 117 | /* lib */ |
118 | int iwlagn_send_tx_power(struct iwl_priv *priv); | 118 | int iwlagn_send_tx_power(struct iwl_priv *priv); |
119 | void iwlagn_temperature(struct iwl_priv *priv); | 119 | void iwlagn_temperature(struct iwl_priv *priv); |
120 | u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv); | 120 | u16 iwl_eeprom_calib_version(struct iwl_shared *shrd); |
121 | int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control); | 121 | int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control); |
122 | void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control); | 122 | void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control); |
123 | int iwlagn_send_beacon_cmd(struct iwl_priv *priv); | 123 | int iwlagn_send_beacon_cmd(struct iwl_priv *priv); |
@@ -354,12 +354,12 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags) | |||
354 | 354 | ||
355 | /* eeprom */ | 355 | /* eeprom */ |
356 | void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv); | 356 | void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv); |
357 | void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac); | 357 | void iwl_eeprom_get_mac(const struct iwl_shared *shrd, u8 *mac); |
358 | 358 | ||
359 | extern int iwlagn_init_alive_start(struct iwl_priv *priv); | 359 | extern int iwlagn_init_alive_start(struct iwl_priv *priv); |
360 | extern int iwl_alive_start(struct iwl_priv *priv); | 360 | extern int iwl_alive_start(struct iwl_priv *priv); |
361 | /* svtool */ | 361 | /* svtool */ |
362 | #ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL | 362 | #ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE |
363 | extern int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, | 363 | extern int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, |
364 | int len); | 364 | int len); |
365 | extern int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, | 365 | extern int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index f4eccf583775..265de39d394c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h | |||
@@ -109,10 +109,10 @@ enum { | |||
109 | /* RX, TX, LEDs */ | 109 | /* RX, TX, LEDs */ |
110 | REPLY_TX = 0x1c, | 110 | REPLY_TX = 0x1c, |
111 | REPLY_LEDS_CMD = 0x48, | 111 | REPLY_LEDS_CMD = 0x48, |
112 | REPLY_TX_LINK_QUALITY_CMD = 0x4e, /* for 4965 and up */ | 112 | REPLY_TX_LINK_QUALITY_CMD = 0x4e, |
113 | 113 | ||
114 | /* WiMAX coexistence */ | 114 | /* WiMAX coexistence */ |
115 | COEX_PRIORITY_TABLE_CMD = 0x5a, /* for 5000 series and up */ | 115 | COEX_PRIORITY_TABLE_CMD = 0x5a, |
116 | COEX_MEDIUM_NOTIFICATION = 0x5b, | 116 | COEX_MEDIUM_NOTIFICATION = 0x5b, |
117 | COEX_EVENT_CMD = 0x5c, | 117 | COEX_EVENT_CMD = 0x5c, |
118 | 118 | ||
@@ -466,23 +466,27 @@ struct iwl_error_event_table { | |||
466 | u32 frame_ptr; /* frame pointer */ | 466 | u32 frame_ptr; /* frame pointer */ |
467 | u32 stack_ptr; /* stack pointer */ | 467 | u32 stack_ptr; /* stack pointer */ |
468 | u32 hcmd; /* last host command header */ | 468 | u32 hcmd; /* last host command header */ |
469 | #if 0 | 469 | u32 isr0; /* isr status register LMPM_NIC_ISR0: |
470 | /* no need to read the remainder, we don't use the values */ | 470 | * rxtx_flag */ |
471 | u32 isr0; /* isr status register LMPM_NIC_ISR0: rxtx_flag */ | 471 | u32 isr1; /* isr status register LMPM_NIC_ISR1: |
472 | u32 isr1; /* isr status register LMPM_NIC_ISR1: host_flag */ | 472 | * host_flag */ |
473 | u32 isr2; /* isr status register LMPM_NIC_ISR2: enc_flag */ | 473 | u32 isr2; /* isr status register LMPM_NIC_ISR2: |
474 | u32 isr3; /* isr status register LMPM_NIC_ISR3: time_flag */ | 474 | * enc_flag */ |
475 | u32 isr4; /* isr status register LMPM_NIC_ISR4: wico interrupt */ | 475 | u32 isr3; /* isr status register LMPM_NIC_ISR3: |
476 | * time_flag */ | ||
477 | u32 isr4; /* isr status register LMPM_NIC_ISR4: | ||
478 | * wico interrupt */ | ||
476 | u32 isr_pref; /* isr status register LMPM_NIC_PREF_STAT */ | 479 | u32 isr_pref; /* isr status register LMPM_NIC_PREF_STAT */ |
477 | u32 wait_event; /* wait event() caller address */ | 480 | u32 wait_event; /* wait event() caller address */ |
478 | u32 l2p_control; /* L2pControlField */ | 481 | u32 l2p_control; /* L2pControlField */ |
479 | u32 l2p_duration; /* L2pDurationField */ | 482 | u32 l2p_duration; /* L2pDurationField */ |
480 | u32 l2p_mhvalid; /* L2pMhValidBits */ | 483 | u32 l2p_mhvalid; /* L2pMhValidBits */ |
481 | u32 l2p_addr_match; /* L2pAddrMatchStat */ | 484 | u32 l2p_addr_match; /* L2pAddrMatchStat */ |
482 | u32 lmpm_pmg_sel; /* indicate which clocks are turned on (LMPM_PMG_SEL) */ | 485 | u32 lmpm_pmg_sel; /* indicate which clocks are turned on |
483 | u32 u_timestamp; /* indicate when the date and time of the compilation */ | 486 | * (LMPM_PMG_SEL) */ |
487 | u32 u_timestamp; /* indicate when the date and time of the | ||
488 | * compilation */ | ||
484 | u32 flow_handler; /* FH read/write pointers, RX credit */ | 489 | u32 flow_handler; /* FH read/write pointers, RX credit */ |
485 | #endif | ||
486 | } __packed; | 490 | } __packed; |
487 | 491 | ||
488 | struct iwl_alive_resp { | 492 | struct iwl_alive_resp { |
@@ -810,7 +814,7 @@ struct iwl_qosparam_cmd { | |||
810 | #define IWLAGN_STATION_COUNT 16 | 814 | #define IWLAGN_STATION_COUNT 16 |
811 | 815 | ||
812 | #define IWL_INVALID_STATION 255 | 816 | #define IWL_INVALID_STATION 255 |
813 | #define IWL_MAX_TID_COUNT 9 | 817 | #define IWL_MAX_TID_COUNT 8 |
814 | 818 | ||
815 | #define STA_FLG_TX_RATE_MSK cpu_to_le32(1 << 2) | 819 | #define STA_FLG_TX_RATE_MSK cpu_to_le32(1 << 2) |
816 | #define STA_FLG_PWR_SAVE_MSK cpu_to_le32(1 << 8) | 820 | #define STA_FLG_PWR_SAVE_MSK cpu_to_le32(1 << 8) |
@@ -931,8 +935,7 @@ struct iwl_addsta_cmd { | |||
931 | * corresponding to bit (e.g. bit 5 controls TID 5). | 935 | * corresponding to bit (e.g. bit 5 controls TID 5). |
932 | * Set modify_mask bit STA_MODIFY_TID_DISABLE_TX to use this field. */ | 936 | * Set modify_mask bit STA_MODIFY_TID_DISABLE_TX to use this field. */ |
933 | __le16 tid_disable_tx; | 937 | __le16 tid_disable_tx; |
934 | 938 | __le16 legacy_reserved; | |
935 | __le16 rate_n_flags; /* 3945 only */ | ||
936 | 939 | ||
937 | /* TID for which to add block-ack support. | 940 | /* TID for which to add block-ack support. |
938 | * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */ | 941 | * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */ |
@@ -1162,8 +1165,7 @@ struct iwl_rx_mpdu_res_start { | |||
1162 | * | 1165 | * |
1163 | * uCode handles retrying Tx when an ACK is expected but not received. | 1166 | * uCode handles retrying Tx when an ACK is expected but not received. |
1164 | * This includes trying lower data rates than the one requested in the Tx | 1167 | * This includes trying lower data rates than the one requested in the Tx |
1165 | * command, as set up by the REPLY_RATE_SCALE (for 3945) or | 1168 | * command, as set up by the REPLY_TX_LINK_QUALITY_CMD (agn). |
1166 | * REPLY_TX_LINK_QUALITY_CMD (agn). | ||
1167 | * | 1169 | * |
1168 | * Driver sets up transmit power for various rates via REPLY_TX_PWR_TABLE_CMD. | 1170 | * Driver sets up transmit power for various rates via REPLY_TX_PWR_TABLE_CMD. |
1169 | * This command must be executed after every RXON command, before Tx can occur. | 1171 | * This command must be executed after every RXON command, before Tx can occur. |
@@ -1175,25 +1177,9 @@ struct iwl_rx_mpdu_res_start { | |||
1175 | * 1: Use RTS/CTS protocol or CTS-to-self if spec allows it | 1177 | * 1: Use RTS/CTS protocol or CTS-to-self if spec allows it |
1176 | * before this frame. if CTS-to-self required check | 1178 | * before this frame. if CTS-to-self required check |
1177 | * RXON_FLG_SELF_CTS_EN status. | 1179 | * RXON_FLG_SELF_CTS_EN status. |
1178 | * unused in 3945/4965, used in 5000 series and after | ||
1179 | */ | 1180 | */ |
1180 | #define TX_CMD_FLG_PROT_REQUIRE_MSK cpu_to_le32(1 << 0) | 1181 | #define TX_CMD_FLG_PROT_REQUIRE_MSK cpu_to_le32(1 << 0) |
1181 | 1182 | ||
1182 | /* | ||
1183 | * 1: Use Request-To-Send protocol before this frame. | ||
1184 | * Mutually exclusive vs. TX_CMD_FLG_CTS_MSK. | ||
1185 | * used in 3945/4965, unused in 5000 series and after | ||
1186 | */ | ||
1187 | #define TX_CMD_FLG_RTS_MSK cpu_to_le32(1 << 1) | ||
1188 | |||
1189 | /* | ||
1190 | * 1: Transmit Clear-To-Send to self before this frame. | ||
1191 | * Driver should set this for AUTH/DEAUTH/ASSOC-REQ/REASSOC mgmnt frames. | ||
1192 | * Mutually exclusive vs. TX_CMD_FLG_RTS_MSK. | ||
1193 | * used in 3945/4965, unused in 5000 series and after | ||
1194 | */ | ||
1195 | #define TX_CMD_FLG_CTS_MSK cpu_to_le32(1 << 2) | ||
1196 | |||
1197 | /* 1: Expect ACK from receiving station | 1183 | /* 1: Expect ACK from receiving station |
1198 | * 0: Don't expect ACK (MAC header's duration field s/b 0) | 1184 | * 0: Don't expect ACK (MAC header's duration field s/b 0) |
1199 | * Set this for unicast frames, but not broadcast/multicast. */ | 1185 | * Set this for unicast frames, but not broadcast/multicast. */ |
@@ -1211,18 +1197,8 @@ struct iwl_rx_mpdu_res_start { | |||
1211 | * Set when Txing a block-ack request frame. Also set TX_CMD_FLG_ACK_MSK. */ | 1197 | * Set when Txing a block-ack request frame. Also set TX_CMD_FLG_ACK_MSK. */ |
1212 | #define TX_CMD_FLG_IMM_BA_RSP_MASK cpu_to_le32(1 << 6) | 1198 | #define TX_CMD_FLG_IMM_BA_RSP_MASK cpu_to_le32(1 << 6) |
1213 | 1199 | ||
1214 | /* | 1200 | /* Tx antenna selection field; reserved (0) for agn devices. */ |
1215 | * 1: Frame requires full Tx-Op protection. | ||
1216 | * Set this if either RTS or CTS Tx Flag gets set. | ||
1217 | * used in 3945/4965, unused in 5000 series and after | ||
1218 | */ | ||
1219 | #define TX_CMD_FLG_FULL_TXOP_PROT_MSK cpu_to_le32(1 << 7) | ||
1220 | |||
1221 | /* Tx antenna selection field; used only for 3945, reserved (0) for agn devices. | ||
1222 | * Set field to "0" to allow 3945 uCode to select antenna (normal usage). */ | ||
1223 | #define TX_CMD_FLG_ANT_SEL_MSK cpu_to_le32(0xf00) | 1201 | #define TX_CMD_FLG_ANT_SEL_MSK cpu_to_le32(0xf00) |
1224 | #define TX_CMD_FLG_ANT_A_MSK cpu_to_le32(1 << 8) | ||
1225 | #define TX_CMD_FLG_ANT_B_MSK cpu_to_le32(1 << 9) | ||
1226 | 1202 | ||
1227 | /* 1: Ignore Bluetooth priority for this frame. | 1203 | /* 1: Ignore Bluetooth priority for this frame. |
1228 | * 0: Delay Tx until Bluetooth device is done (normal usage). */ | 1204 | * 0: Delay Tx until Bluetooth device is done (normal usage). */ |
@@ -1568,7 +1544,6 @@ struct iwl_compressed_ba_resp { | |||
1568 | __le64 bitmap; | 1544 | __le64 bitmap; |
1569 | __le16 scd_flow; | 1545 | __le16 scd_flow; |
1570 | __le16 scd_ssn; | 1546 | __le16 scd_ssn; |
1571 | /* following only for 5000 series and up */ | ||
1572 | u8 txed; /* number of frames sent */ | 1547 | u8 txed; /* number of frames sent */ |
1573 | u8 txed_2_done; /* number of frames acked */ | 1548 | u8 txed_2_done; /* number of frames acked */ |
1574 | } __packed; | 1549 | } __packed; |
@@ -1670,7 +1645,7 @@ struct iwl_link_qual_agg_params { | |||
1670 | /* | 1645 | /* |
1671 | * REPLY_TX_LINK_QUALITY_CMD = 0x4e (command, has simple generic response) | 1646 | * REPLY_TX_LINK_QUALITY_CMD = 0x4e (command, has simple generic response) |
1672 | * | 1647 | * |
1673 | * For agn devices only; 3945 uses REPLY_RATE_SCALE. | 1648 | * For agn devices |
1674 | * | 1649 | * |
1675 | * Each station in the agn device's internal station table has its own table | 1650 | * Each station in the agn device's internal station table has its own table |
1676 | * of 16 | 1651 | * of 16 |
@@ -1919,7 +1894,7 @@ struct iwl_link_quality_cmd { | |||
1919 | /* | 1894 | /* |
1920 | * REPLY_BT_CONFIG = 0x9b (command, has simple generic response) | 1895 | * REPLY_BT_CONFIG = 0x9b (command, has simple generic response) |
1921 | * | 1896 | * |
1922 | * 3945 and agn devices support hardware handshake with Bluetooth device on | 1897 | * agn devices support hardware handshake with Bluetooth device on |
1923 | * same platform. Bluetooth device alerts wireless device when it will Tx; | 1898 | * same platform. Bluetooth device alerts wireless device when it will Tx; |
1924 | * wireless device can delay or kill its own Tx to accommodate. | 1899 | * wireless device can delay or kill its own Tx to accommodate. |
1925 | */ | 1900 | */ |
@@ -2203,8 +2178,8 @@ struct iwl_spectrum_notification { | |||
2203 | 2178 | ||
2204 | struct iwl_powertable_cmd { | 2179 | struct iwl_powertable_cmd { |
2205 | __le16 flags; | 2180 | __le16 flags; |
2206 | u8 keep_alive_seconds; /* 3945 reserved */ | 2181 | u8 keep_alive_seconds; |
2207 | u8 debug_flags; /* 3945 reserved */ | 2182 | u8 debug_flags; |
2208 | __le32 rx_data_timeout; | 2183 | __le32 rx_data_timeout; |
2209 | __le32 tx_data_timeout; | 2184 | __le32 tx_data_timeout; |
2210 | __le32 sleep_interval[IWL_POWER_VEC_SIZE]; | 2185 | __le32 sleep_interval[IWL_POWER_VEC_SIZE]; |
@@ -2325,9 +2300,9 @@ struct iwl_scan_channel { | |||
2325 | /** | 2300 | /** |
2326 | * struct iwl_ssid_ie - directed scan network information element | 2301 | * struct iwl_ssid_ie - directed scan network information element |
2327 | * | 2302 | * |
2328 | * Up to 20 of these may appear in REPLY_SCAN_CMD (Note: Only 4 are in | 2303 | * Up to 20 of these may appear in REPLY_SCAN_CMD, |
2329 | * 3945 SCAN api), selected by "type" bit field in struct iwl_scan_channel; | 2304 | * selected by "type" bit field in struct iwl_scan_channel; |
2330 | * each channel may select different ssids from among the 20 (4) entries. | 2305 | * each channel may select different ssids from among the 20 entries. |
2331 | * SSID IEs get transmitted in reverse order of entry. | 2306 | * SSID IEs get transmitted in reverse order of entry. |
2332 | */ | 2307 | */ |
2333 | struct iwl_ssid_ie { | 2308 | struct iwl_ssid_ie { |
@@ -2336,7 +2311,6 @@ struct iwl_ssid_ie { | |||
2336 | u8 ssid[32]; | 2311 | u8 ssid[32]; |
2337 | } __packed; | 2312 | } __packed; |
2338 | 2313 | ||
2339 | #define PROBE_OPTION_MAX_3945 4 | ||
2340 | #define PROBE_OPTION_MAX 20 | 2314 | #define PROBE_OPTION_MAX 20 |
2341 | #define TX_CMD_LIFE_TIME_INFINITE cpu_to_le32(0xFFFFFFFF) | 2315 | #define TX_CMD_LIFE_TIME_INFINITE cpu_to_le32(0xFFFFFFFF) |
2342 | #define IWL_GOOD_CRC_TH_DISABLED 0 | 2316 | #define IWL_GOOD_CRC_TH_DISABLED 0 |
@@ -2417,8 +2391,6 @@ struct iwl_scan_cmd { | |||
2417 | * channel */ | 2391 | * channel */ |
2418 | __le32 suspend_time; /* pause scan this long (in "extended beacon | 2392 | __le32 suspend_time; /* pause scan this long (in "extended beacon |
2419 | * format") when returning to service chnl: | 2393 | * format") when returning to service chnl: |
2420 | * 3945; 31:24 # beacons, 19:0 additional usec, | ||
2421 | * 4965; 31:22 # beacons, 21:0 additional usec. | ||
2422 | */ | 2394 | */ |
2423 | __le32 flags; /* RXON_FLG_* */ | 2395 | __le32 flags; /* RXON_FLG_* */ |
2424 | __le32 filter_flags; /* RXON_FILTER_* */ | 2396 | __le32 filter_flags; /* RXON_FILTER_* */ |
@@ -2734,7 +2706,7 @@ struct statistics_div { | |||
2734 | 2706 | ||
2735 | struct statistics_general_common { | 2707 | struct statistics_general_common { |
2736 | __le32 temperature; /* radio temperature */ | 2708 | __le32 temperature; /* radio temperature */ |
2737 | __le32 temperature_m; /* for 5000 and up, this is radio voltage */ | 2709 | __le32 temperature_m; /* radio voltage */ |
2738 | struct statistics_dbg dbg; | 2710 | struct statistics_dbg dbg; |
2739 | __le32 sleep_time; | 2711 | __le32 sleep_time; |
2740 | __le32 slots_out; | 2712 | __le32 slots_out; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index ccbcab40e78f..6bf6845e1a51 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c | |||
@@ -416,7 +416,7 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file, | |||
416 | return -ENODATA; | 416 | return -ENODATA; |
417 | } | 417 | } |
418 | 418 | ||
419 | ptr = priv->eeprom; | 419 | ptr = priv->shrd->eeprom; |
420 | if (!ptr) { | 420 | if (!ptr) { |
421 | IWL_ERR(priv, "Invalid EEPROM/OTP memory\n"); | 421 | IWL_ERR(priv, "Invalid EEPROM/OTP memory\n"); |
422 | return -ENOMEM; | 422 | return -ENOMEM; |
@@ -428,7 +428,7 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file, | |||
428 | IWL_ERR(priv, "Can not allocate Buffer\n"); | 428 | IWL_ERR(priv, "Can not allocate Buffer\n"); |
429 | return -ENOMEM; | 429 | return -ENOMEM; |
430 | } | 430 | } |
431 | eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION); | 431 | eeprom_ver = iwl_eeprom_query16(priv->shrd, EEPROM_VERSION); |
432 | pos += scnprintf(buf + pos, buf_size - pos, "NVM Type: %s, " | 432 | pos += scnprintf(buf + pos, buf_size - pos, "NVM Type: %s, " |
433 | "version: 0x%x\n", | 433 | "version: 0x%x\n", |
434 | (trans(priv)->nvm_device_type == NVM_DEVICE_TYPE_OTP) | 434 | (trans(priv)->nvm_device_type == NVM_DEVICE_TYPE_OTP) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 6f6a647d34f6..69ecf6e2e658 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -60,11 +60,10 @@ struct iwl_tx_queue; | |||
60 | 60 | ||
61 | /* Default noise level to report when noise measurement is not available. | 61 | /* Default noise level to report when noise measurement is not available. |
62 | * This may be because we're: | 62 | * This may be because we're: |
63 | * 1) Not associated (4965, no beacon statistics being sent to driver) | 63 | * 1) Not associated no beacon statistics being sent to driver) |
64 | * 2) Scanning (noise measurement does not apply to associated channel) | 64 | * 2) Scanning (noise measurement does not apply to associated channel) |
65 | * 3) Receiving CCK (3945 delivers noise info only for OFDM frames) | ||
66 | * Use default noise value of -127 ... this is below the range of measurable | 65 | * Use default noise value of -127 ... this is below the range of measurable |
67 | * Rx dBm for either 3945 or 4965, so it can indicate "unmeasurable" to user. | 66 | * Rx dBm for all agn devices, so it can indicate "unmeasurable" to user. |
68 | * Also, -127 works better than 0 when averaging frames with/without | 67 | * Also, -127 works better than 0 when averaging frames with/without |
69 | * noise info (e.g. averaging might be done in app); measured dBm values are | 68 | * noise info (e.g. averaging might be done in app); measured dBm values are |
70 | * always negative ... using a negative value as the default keeps all | 69 | * always negative ... using a negative value as the default keeps all |
@@ -441,15 +440,6 @@ enum iwlagn_chain_noise_state { | |||
441 | IWL_CHAIN_NOISE_DONE, | 440 | IWL_CHAIN_NOISE_DONE, |
442 | }; | 441 | }; |
443 | 442 | ||
444 | |||
445 | /* Opaque calibration results */ | ||
446 | struct iwl_calib_result { | ||
447 | struct list_head list; | ||
448 | size_t cmd_len; | ||
449 | struct iwl_calib_hdr hdr; | ||
450 | /* data follows */ | ||
451 | }; | ||
452 | |||
453 | /* Sensitivity calib data */ | 443 | /* Sensitivity calib data */ |
454 | struct iwl_sensitivity_data { | 444 | struct iwl_sensitivity_data { |
455 | u32 auto_corr_ofdm; | 445 | u32 auto_corr_ofdm; |
@@ -751,7 +741,7 @@ enum iwl_scan_type { | |||
751 | IWL_SCAN_ROC, | 741 | IWL_SCAN_ROC, |
752 | }; | 742 | }; |
753 | 743 | ||
754 | #ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL | 744 | #ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE |
755 | struct iwl_testmode_trace { | 745 | struct iwl_testmode_trace { |
756 | u32 buff_size; | 746 | u32 buff_size; |
757 | u32 total_size; | 747 | u32 total_size; |
@@ -831,9 +821,6 @@ struct iwl_priv { | |||
831 | s32 temperature; /* Celsius */ | 821 | s32 temperature; /* Celsius */ |
832 | s32 last_temperature; | 822 | s32 last_temperature; |
833 | 823 | ||
834 | /* init calibration results */ | ||
835 | struct list_head calib_results; | ||
836 | |||
837 | struct iwl_wipan_noa_data __rcu *noa_data; | 824 | struct iwl_wipan_noa_data __rcu *noa_data; |
838 | 825 | ||
839 | /* Scan related variables */ | 826 | /* Scan related variables */ |
@@ -866,11 +853,6 @@ struct iwl_priv { | |||
866 | 853 | ||
867 | __le16 switch_channel; | 854 | __le16 switch_channel; |
868 | 855 | ||
869 | struct { | ||
870 | u32 error_event_table; | ||
871 | u32 log_event_table; | ||
872 | } device_pointers; | ||
873 | |||
874 | u16 active_rate; | 856 | u16 active_rate; |
875 | 857 | ||
876 | u8 start_calib; | 858 | u8 start_calib; |
@@ -904,10 +886,6 @@ struct iwl_priv { | |||
904 | /* Indication if ieee80211_ops->open has been called */ | 886 | /* Indication if ieee80211_ops->open has been called */ |
905 | u8 is_open; | 887 | u8 is_open; |
906 | 888 | ||
907 | /* eeprom -- this is in the card's little endian byte order */ | ||
908 | u8 *eeprom; | ||
909 | struct iwl_eeprom_calib_info *calib_info; | ||
910 | |||
911 | enum nl80211_iftype iw_mode; | 889 | enum nl80211_iftype iw_mode; |
912 | 890 | ||
913 | /* Last Rx'd beacon timestamp */ | 891 | /* Last Rx'd beacon timestamp */ |
@@ -1040,7 +1018,7 @@ struct iwl_priv { | |||
1040 | struct led_classdev led; | 1018 | struct led_classdev led; |
1041 | unsigned long blink_on, blink_off; | 1019 | unsigned long blink_on, blink_off; |
1042 | bool led_registered; | 1020 | bool led_registered; |
1043 | #ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL | 1021 | #ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE |
1044 | struct iwl_testmode_trace testmode_trace; | 1022 | struct iwl_testmode_trace testmode_trace; |
1045 | struct iwl_testmode_sram testmode_sram; | 1023 | struct iwl_testmode_sram testmode_sram; |
1046 | u32 tm_fixed_rate; | 1024 | u32 tm_fixed_rate; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index dcada0827ea4..6fcc7d586b24 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c | |||
@@ -215,11 +215,11 @@ static int iwl_eeprom_verify_signature(struct iwl_trans *trans) | |||
215 | return ret; | 215 | return ret; |
216 | } | 216 | } |
217 | 217 | ||
218 | u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset) | 218 | u16 iwl_eeprom_query16(const struct iwl_shared *shrd, size_t offset) |
219 | { | 219 | { |
220 | if (!priv->eeprom) | 220 | if (!shrd->eeprom) |
221 | return 0; | 221 | return 0; |
222 | return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8); | 222 | return (u16)shrd->eeprom[offset] | ((u16)shrd->eeprom[offset + 1] << 8); |
223 | } | 223 | } |
224 | 224 | ||
225 | int iwl_eeprom_check_version(struct iwl_priv *priv) | 225 | int iwl_eeprom_check_version(struct iwl_priv *priv) |
@@ -227,8 +227,8 @@ int iwl_eeprom_check_version(struct iwl_priv *priv) | |||
227 | u16 eeprom_ver; | 227 | u16 eeprom_ver; |
228 | u16 calib_ver; | 228 | u16 calib_ver; |
229 | 229 | ||
230 | eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION); | 230 | eeprom_ver = iwl_eeprom_query16(priv->shrd, EEPROM_VERSION); |
231 | calib_ver = iwlagn_eeprom_calib_version(priv); | 231 | calib_ver = iwl_eeprom_calib_version(priv->shrd); |
232 | 232 | ||
233 | if (eeprom_ver < priv->cfg->eeprom_ver || | 233 | if (eeprom_ver < priv->cfg->eeprom_ver || |
234 | calib_ver < priv->cfg->eeprom_calib_ver) | 234 | calib_ver < priv->cfg->eeprom_calib_ver) |
@@ -249,11 +249,12 @@ err: | |||
249 | 249 | ||
250 | int iwl_eeprom_check_sku(struct iwl_priv *priv) | 250 | int iwl_eeprom_check_sku(struct iwl_priv *priv) |
251 | { | 251 | { |
252 | struct iwl_shared *shrd = priv->shrd; | ||
252 | u16 radio_cfg; | 253 | u16 radio_cfg; |
253 | 254 | ||
254 | if (!priv->cfg->sku) { | 255 | if (!priv->cfg->sku) { |
255 | /* not using sku overwrite */ | 256 | /* not using sku overwrite */ |
256 | priv->cfg->sku = iwl_eeprom_query16(priv, EEPROM_SKU_CAP); | 257 | priv->cfg->sku = iwl_eeprom_query16(shrd, EEPROM_SKU_CAP); |
257 | if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE && | 258 | if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE && |
258 | !priv->cfg->ht_params) { | 259 | !priv->cfg->ht_params) { |
259 | IWL_ERR(priv, "Invalid 11n configuration\n"); | 260 | IWL_ERR(priv, "Invalid 11n configuration\n"); |
@@ -269,7 +270,7 @@ int iwl_eeprom_check_sku(struct iwl_priv *priv) | |||
269 | 270 | ||
270 | if (!priv->cfg->valid_tx_ant && !priv->cfg->valid_rx_ant) { | 271 | if (!priv->cfg->valid_tx_ant && !priv->cfg->valid_rx_ant) { |
271 | /* not using .cfg overwrite */ | 272 | /* not using .cfg overwrite */ |
272 | radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); | 273 | radio_cfg = iwl_eeprom_query16(shrd, EEPROM_RADIO_CONFIG); |
273 | priv->cfg->valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg); | 274 | priv->cfg->valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg); |
274 | priv->cfg->valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(radio_cfg); | 275 | priv->cfg->valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(radio_cfg); |
275 | if (!priv->cfg->valid_tx_ant || !priv->cfg->valid_rx_ant) { | 276 | if (!priv->cfg->valid_tx_ant || !priv->cfg->valid_rx_ant) { |
@@ -289,9 +290,9 @@ int iwl_eeprom_check_sku(struct iwl_priv *priv) | |||
289 | return 0; | 290 | return 0; |
290 | } | 291 | } |
291 | 292 | ||
292 | void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac) | 293 | void iwl_eeprom_get_mac(const struct iwl_shared *shrd, u8 *mac) |
293 | { | 294 | { |
294 | const u8 *addr = iwl_eeprom_query_addr(priv, | 295 | const u8 *addr = iwl_eeprom_query_addr(shrd, |
295 | EEPROM_MAC_ADDRESS); | 296 | EEPROM_MAC_ADDRESS); |
296 | memcpy(mac, addr, ETH_ALEN); | 297 | memcpy(mac, addr, ETH_ALEN); |
297 | } | 298 | } |
@@ -582,6 +583,7 @@ iwl_eeprom_enh_txp_read_element(struct iwl_priv *priv, | |||
582 | 583 | ||
583 | void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv) | 584 | void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv) |
584 | { | 585 | { |
586 | struct iwl_shared *shrd = priv->shrd; | ||
585 | struct iwl_eeprom_enhanced_txpwr *txp_array, *txp; | 587 | struct iwl_eeprom_enhanced_txpwr *txp_array, *txp; |
586 | int idx, entries; | 588 | int idx, entries; |
587 | __le16 *txp_len; | 589 | __le16 *txp_len; |
@@ -590,10 +592,10 @@ void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv) | |||
590 | BUILD_BUG_ON(sizeof(struct iwl_eeprom_enhanced_txpwr) != 8); | 592 | BUILD_BUG_ON(sizeof(struct iwl_eeprom_enhanced_txpwr) != 8); |
591 | 593 | ||
592 | /* the length is in 16-bit words, but we want entries */ | 594 | /* the length is in 16-bit words, but we want entries */ |
593 | txp_len = (__le16 *) iwl_eeprom_query_addr(priv, EEPROM_TXP_SZ_OFFS); | 595 | txp_len = (__le16 *) iwl_eeprom_query_addr(shrd, EEPROM_TXP_SZ_OFFS); |
594 | entries = le16_to_cpup(txp_len) * 2 / EEPROM_TXP_ENTRY_LEN; | 596 | entries = le16_to_cpup(txp_len) * 2 / EEPROM_TXP_ENTRY_LEN; |
595 | 597 | ||
596 | txp_array = (void *) iwl_eeprom_query_addr(priv, EEPROM_TXP_OFFS); | 598 | txp_array = (void *) iwl_eeprom_query_addr(shrd, EEPROM_TXP_OFFS); |
597 | 599 | ||
598 | for (idx = 0; idx < entries; idx++) { | 600 | for (idx = 0; idx < entries; idx++) { |
599 | txp = &txp_array[idx]; | 601 | txp = &txp_array[idx]; |
@@ -646,12 +648,13 @@ void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv) | |||
646 | /** | 648 | /** |
647 | * iwl_eeprom_init - read EEPROM contents | 649 | * iwl_eeprom_init - read EEPROM contents |
648 | * | 650 | * |
649 | * Load the EEPROM contents from adapter into priv->eeprom | 651 | * Load the EEPROM contents from adapter into shrd->eeprom |
650 | * | 652 | * |
651 | * NOTE: This routine uses the non-debug IO access functions. | 653 | * NOTE: This routine uses the non-debug IO access functions. |
652 | */ | 654 | */ |
653 | int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) | 655 | int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) |
654 | { | 656 | { |
657 | struct iwl_shared *shrd = priv->shrd; | ||
655 | __le16 *e; | 658 | __le16 *e; |
656 | u32 gp = iwl_read32(bus(priv), CSR_EEPROM_GP); | 659 | u32 gp = iwl_read32(bus(priv), CSR_EEPROM_GP); |
657 | int sz; | 660 | int sz; |
@@ -666,12 +669,12 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) | |||
666 | /* allocate eeprom */ | 669 | /* allocate eeprom */ |
667 | sz = priv->cfg->base_params->eeprom_size; | 670 | sz = priv->cfg->base_params->eeprom_size; |
668 | IWL_DEBUG_EEPROM(priv, "NVM size = %d\n", sz); | 671 | IWL_DEBUG_EEPROM(priv, "NVM size = %d\n", sz); |
669 | priv->eeprom = kzalloc(sz, GFP_KERNEL); | 672 | shrd->eeprom = kzalloc(sz, GFP_KERNEL); |
670 | if (!priv->eeprom) { | 673 | if (!shrd->eeprom) { |
671 | ret = -ENOMEM; | 674 | ret = -ENOMEM; |
672 | goto alloc_err; | 675 | goto alloc_err; |
673 | } | 676 | } |
674 | e = (__le16 *)priv->eeprom; | 677 | e = (__le16 *)shrd->eeprom; |
675 | 678 | ||
676 | iwl_apm_init(priv); | 679 | iwl_apm_init(priv); |
677 | 680 | ||
@@ -746,7 +749,7 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) | |||
746 | IWL_DEBUG_EEPROM(priv, "NVM Type: %s, version: 0x%x\n", | 749 | IWL_DEBUG_EEPROM(priv, "NVM Type: %s, version: 0x%x\n", |
747 | (trans(priv)->nvm_device_type == NVM_DEVICE_TYPE_OTP) | 750 | (trans(priv)->nvm_device_type == NVM_DEVICE_TYPE_OTP) |
748 | ? "OTP" : "EEPROM", | 751 | ? "OTP" : "EEPROM", |
749 | iwl_eeprom_query16(priv, EEPROM_VERSION)); | 752 | iwl_eeprom_query16(shrd, EEPROM_VERSION)); |
750 | 753 | ||
751 | ret = 0; | 754 | ret = 0; |
752 | done: | 755 | done: |
@@ -754,17 +757,17 @@ done: | |||
754 | 757 | ||
755 | err: | 758 | err: |
756 | if (ret) | 759 | if (ret) |
757 | iwl_eeprom_free(priv); | 760 | iwl_eeprom_free(priv->shrd); |
758 | /* Reset chip to save power until we load uCode during "up". */ | 761 | /* Reset chip to save power until we load uCode during "up". */ |
759 | iwl_apm_stop(priv); | 762 | iwl_apm_stop(priv); |
760 | alloc_err: | 763 | alloc_err: |
761 | return ret; | 764 | return ret; |
762 | } | 765 | } |
763 | 766 | ||
764 | void iwl_eeprom_free(struct iwl_priv *priv) | 767 | void iwl_eeprom_free(struct iwl_shared *shrd) |
765 | { | 768 | { |
766 | kfree(priv->eeprom); | 769 | kfree(shrd->eeprom); |
767 | priv->eeprom = NULL; | 770 | shrd->eeprom = NULL; |
768 | } | 771 | } |
769 | 772 | ||
770 | static void iwl_init_band_reference(const struct iwl_priv *priv, | 773 | static void iwl_init_band_reference(const struct iwl_priv *priv, |
@@ -772,49 +775,50 @@ static void iwl_init_band_reference(const struct iwl_priv *priv, | |||
772 | const struct iwl_eeprom_channel **eeprom_ch_info, | 775 | const struct iwl_eeprom_channel **eeprom_ch_info, |
773 | const u8 **eeprom_ch_index) | 776 | const u8 **eeprom_ch_index) |
774 | { | 777 | { |
778 | struct iwl_shared *shrd = priv->shrd; | ||
775 | u32 offset = priv->cfg->lib-> | 779 | u32 offset = priv->cfg->lib-> |
776 | eeprom_ops.regulatory_bands[eep_band - 1]; | 780 | eeprom_ops.regulatory_bands[eep_band - 1]; |
777 | switch (eep_band) { | 781 | switch (eep_band) { |
778 | case 1: /* 2.4GHz band */ | 782 | case 1: /* 2.4GHz band */ |
779 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_1); | 783 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_1); |
780 | *eeprom_ch_info = (struct iwl_eeprom_channel *) | 784 | *eeprom_ch_info = (struct iwl_eeprom_channel *) |
781 | iwl_eeprom_query_addr(priv, offset); | 785 | iwl_eeprom_query_addr(shrd, offset); |
782 | *eeprom_ch_index = iwl_eeprom_band_1; | 786 | *eeprom_ch_index = iwl_eeprom_band_1; |
783 | break; | 787 | break; |
784 | case 2: /* 4.9GHz band */ | 788 | case 2: /* 4.9GHz band */ |
785 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_2); | 789 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_2); |
786 | *eeprom_ch_info = (struct iwl_eeprom_channel *) | 790 | *eeprom_ch_info = (struct iwl_eeprom_channel *) |
787 | iwl_eeprom_query_addr(priv, offset); | 791 | iwl_eeprom_query_addr(shrd, offset); |
788 | *eeprom_ch_index = iwl_eeprom_band_2; | 792 | *eeprom_ch_index = iwl_eeprom_band_2; |
789 | break; | 793 | break; |
790 | case 3: /* 5.2GHz band */ | 794 | case 3: /* 5.2GHz band */ |
791 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_3); | 795 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_3); |
792 | *eeprom_ch_info = (struct iwl_eeprom_channel *) | 796 | *eeprom_ch_info = (struct iwl_eeprom_channel *) |
793 | iwl_eeprom_query_addr(priv, offset); | 797 | iwl_eeprom_query_addr(shrd, offset); |
794 | *eeprom_ch_index = iwl_eeprom_band_3; | 798 | *eeprom_ch_index = iwl_eeprom_band_3; |
795 | break; | 799 | break; |
796 | case 4: /* 5.5GHz band */ | 800 | case 4: /* 5.5GHz band */ |
797 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_4); | 801 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_4); |
798 | *eeprom_ch_info = (struct iwl_eeprom_channel *) | 802 | *eeprom_ch_info = (struct iwl_eeprom_channel *) |
799 | iwl_eeprom_query_addr(priv, offset); | 803 | iwl_eeprom_query_addr(shrd, offset); |
800 | *eeprom_ch_index = iwl_eeprom_band_4; | 804 | *eeprom_ch_index = iwl_eeprom_band_4; |
801 | break; | 805 | break; |
802 | case 5: /* 5.7GHz band */ | 806 | case 5: /* 5.7GHz band */ |
803 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_5); | 807 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_5); |
804 | *eeprom_ch_info = (struct iwl_eeprom_channel *) | 808 | *eeprom_ch_info = (struct iwl_eeprom_channel *) |
805 | iwl_eeprom_query_addr(priv, offset); | 809 | iwl_eeprom_query_addr(shrd, offset); |
806 | *eeprom_ch_index = iwl_eeprom_band_5; | 810 | *eeprom_ch_index = iwl_eeprom_band_5; |
807 | break; | 811 | break; |
808 | case 6: /* 2.4GHz ht40 channels */ | 812 | case 6: /* 2.4GHz ht40 channels */ |
809 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_6); | 813 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_6); |
810 | *eeprom_ch_info = (struct iwl_eeprom_channel *) | 814 | *eeprom_ch_info = (struct iwl_eeprom_channel *) |
811 | iwl_eeprom_query_addr(priv, offset); | 815 | iwl_eeprom_query_addr(shrd, offset); |
812 | *eeprom_ch_index = iwl_eeprom_band_6; | 816 | *eeprom_ch_index = iwl_eeprom_band_6; |
813 | break; | 817 | break; |
814 | case 7: /* 5 GHz ht40 channels */ | 818 | case 7: /* 5 GHz ht40 channels */ |
815 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_7); | 819 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_7); |
816 | *eeprom_ch_info = (struct iwl_eeprom_channel *) | 820 | *eeprom_ch_info = (struct iwl_eeprom_channel *) |
817 | iwl_eeprom_query_addr(priv, offset); | 821 | iwl_eeprom_query_addr(shrd, offset); |
818 | *eeprom_ch_index = iwl_eeprom_band_7; | 822 | *eeprom_ch_index = iwl_eeprom_band_7; |
819 | break; | 823 | break; |
820 | default: | 824 | default: |
@@ -1064,7 +1068,7 @@ void iwl_rf_config(struct iwl_priv *priv) | |||
1064 | { | 1068 | { |
1065 | u16 radio_cfg; | 1069 | u16 radio_cfg; |
1066 | 1070 | ||
1067 | radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); | 1071 | radio_cfg = iwl_eeprom_query16(priv->shrd, EEPROM_RADIO_CONFIG); |
1068 | 1072 | ||
1069 | /* write radio config values to register */ | 1073 | /* write radio config values to register */ |
1070 | if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX) { | 1074 | if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX) { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index c94747e7299e..9fa937ec35e3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h | |||
@@ -66,6 +66,7 @@ | |||
66 | #include <net/mac80211.h> | 66 | #include <net/mac80211.h> |
67 | 67 | ||
68 | struct iwl_priv; | 68 | struct iwl_priv; |
69 | struct iwl_shared; | ||
69 | 70 | ||
70 | /* | 71 | /* |
71 | * EEPROM access time values: | 72 | * EEPROM access time values: |
@@ -305,11 +306,11 @@ struct iwl_eeprom_ops { | |||
305 | 306 | ||
306 | 307 | ||
307 | int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev); | 308 | int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev); |
308 | void iwl_eeprom_free(struct iwl_priv *priv); | 309 | void iwl_eeprom_free(struct iwl_shared *shrd); |
309 | int iwl_eeprom_check_version(struct iwl_priv *priv); | 310 | int iwl_eeprom_check_version(struct iwl_priv *priv); |
310 | int iwl_eeprom_check_sku(struct iwl_priv *priv); | 311 | int iwl_eeprom_check_sku(struct iwl_priv *priv); |
311 | const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset); | 312 | const u8 *iwl_eeprom_query_addr(const struct iwl_shared *shrd, size_t offset); |
312 | u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset); | 313 | u16 iwl_eeprom_query16(const struct iwl_shared *shrd, size_t offset); |
313 | int iwl_init_channel_map(struct iwl_priv *priv); | 314 | int iwl_init_channel_map(struct iwl_priv *priv); |
314 | void iwl_free_channel_map(struct iwl_priv *priv); | 315 | void iwl_free_channel_map(struct iwl_priv *priv); |
315 | const struct iwl_channel_info *iwl_get_channel_info( | 316 | const struct iwl_channel_info *iwl_get_channel_info( |
diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c index 55308b88faac..e3944f4e4fd6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c | |||
@@ -427,7 +427,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) | |||
427 | iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_CLR, | 427 | iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_CLR, |
428 | CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); | 428 | CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); |
429 | 429 | ||
430 | base = priv->device_pointers.error_event_table; | 430 | base = priv->shrd->device_pointers.error_event_table; |
431 | if (iwlagn_hw_valid_rtc_data_addr(base)) { | 431 | if (iwlagn_hw_valid_rtc_data_addr(base)) { |
432 | spin_lock_irqsave(&bus(priv)->reg_lock, flags); | 432 | spin_lock_irqsave(&bus(priv)->reg_lock, flags); |
433 | ret = iwl_grab_nic_access_silent(bus(priv)); | 433 | ret = iwl_grab_nic_access_silent(bus(priv)); |
@@ -811,21 +811,9 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, | |||
811 | 811 | ||
812 | /* Configure HT40 channels */ | 812 | /* Configure HT40 channels */ |
813 | ctx->ht.enabled = conf_is_ht(conf); | 813 | ctx->ht.enabled = conf_is_ht(conf); |
814 | if (ctx->ht.enabled) { | 814 | if (ctx->ht.enabled) |
815 | if (conf_is_ht40_minus(conf)) { | 815 | iwlagn_config_ht40(conf, ctx); |
816 | ctx->ht.extension_chan_offset = | 816 | else |
817 | IEEE80211_HT_PARAM_CHA_SEC_BELOW; | ||
818 | ctx->ht.is_40mhz = true; | ||
819 | } else if (conf_is_ht40_plus(conf)) { | ||
820 | ctx->ht.extension_chan_offset = | ||
821 | IEEE80211_HT_PARAM_CHA_SEC_ABOVE; | ||
822 | ctx->ht.is_40mhz = true; | ||
823 | } else { | ||
824 | ctx->ht.extension_chan_offset = | ||
825 | IEEE80211_HT_PARAM_CHA_SEC_NONE; | ||
826 | ctx->ht.is_40mhz = false; | ||
827 | } | ||
828 | } else | ||
829 | ctx->ht.is_40mhz = false; | 817 | ctx->ht.is_40mhz = false; |
830 | 818 | ||
831 | if ((le16_to_cpu(ctx->staging.channel) != ch)) | 819 | if ((le16_to_cpu(ctx->staging.channel) != ch)) |
@@ -1060,6 +1048,9 @@ static int iwlagn_mac_tx_sync(struct ieee80211_hw *hw, | |||
1060 | int ret; | 1048 | int ret; |
1061 | u8 sta_id; | 1049 | u8 sta_id; |
1062 | 1050 | ||
1051 | if (ctx->ctxid != IWL_RXON_CTX_PAN) | ||
1052 | return 0; | ||
1053 | |||
1063 | IWL_DEBUG_MAC80211(priv, "enter\n"); | 1054 | IWL_DEBUG_MAC80211(priv, "enter\n"); |
1064 | mutex_lock(&priv->shrd->mutex); | 1055 | mutex_lock(&priv->shrd->mutex); |
1065 | 1056 | ||
@@ -1109,6 +1100,9 @@ static void iwlagn_mac_finish_tx_sync(struct ieee80211_hw *hw, | |||
1109 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; | 1100 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; |
1110 | struct iwl_rxon_context *ctx = vif_priv->ctx; | 1101 | struct iwl_rxon_context *ctx = vif_priv->ctx; |
1111 | 1102 | ||
1103 | if (ctx->ctxid != IWL_RXON_CTX_PAN) | ||
1104 | return; | ||
1105 | |||
1112 | IWL_DEBUG_MAC80211(priv, "enter\n"); | 1106 | IWL_DEBUG_MAC80211(priv, "enter\n"); |
1113 | mutex_lock(&priv->shrd->mutex); | 1107 | mutex_lock(&priv->shrd->mutex); |
1114 | 1108 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 39aa9cf5b847..29a7284aa3ef 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h | |||
@@ -97,6 +97,7 @@ | |||
97 | struct iwl_cfg; | 97 | struct iwl_cfg; |
98 | struct iwl_bus; | 98 | struct iwl_bus; |
99 | struct iwl_priv; | 99 | struct iwl_priv; |
100 | struct iwl_trans; | ||
100 | struct iwl_sensitivity_ranges; | 101 | struct iwl_sensitivity_ranges; |
101 | struct iwl_trans_ops; | 102 | struct iwl_trans_ops; |
102 | 103 | ||
@@ -294,7 +295,7 @@ enum iwl_ucode_type { | |||
294 | struct iwl_notification_wait { | 295 | struct iwl_notification_wait { |
295 | struct list_head list; | 296 | struct list_head list; |
296 | 297 | ||
297 | void (*fn)(struct iwl_priv *priv, struct iwl_rx_packet *pkt, | 298 | void (*fn)(struct iwl_trans *trans, struct iwl_rx_packet *pkt, |
298 | void *data); | 299 | void *data); |
299 | void *fn_data; | 300 | void *fn_data; |
300 | 301 | ||
@@ -323,6 +324,7 @@ struct iwl_notification_wait { | |||
323 | * @notif_waits: things waiting for notification | 324 | * @notif_waits: things waiting for notification |
324 | * @notif_wait_lock: lock protecting notification | 325 | * @notif_wait_lock: lock protecting notification |
325 | * @notif_waitq: head of notification wait queue | 326 | * @notif_waitq: head of notification wait queue |
327 | * @device_pointers: pointers to ucode event tables | ||
326 | */ | 328 | */ |
327 | struct iwl_shared { | 329 | struct iwl_shared { |
328 | #ifdef CONFIG_IWLWIFI_DEBUG | 330 | #ifdef CONFIG_IWLWIFI_DEBUG |
@@ -351,6 +353,9 @@ struct iwl_shared { | |||
351 | 353 | ||
352 | wait_queue_head_t wait_command_queue; | 354 | wait_queue_head_t wait_command_queue; |
353 | 355 | ||
356 | /* eeprom -- this is in the card's little endian byte order */ | ||
357 | u8 *eeprom; | ||
358 | |||
354 | /* ucode related variables */ | 359 | /* ucode related variables */ |
355 | enum iwl_ucode_type ucode_type; | 360 | enum iwl_ucode_type ucode_type; |
356 | 361 | ||
@@ -358,6 +363,12 @@ struct iwl_shared { | |||
358 | struct list_head notif_waits; | 363 | struct list_head notif_waits; |
359 | spinlock_t notif_wait_lock; | 364 | spinlock_t notif_wait_lock; |
360 | wait_queue_head_t notif_waitq; | 365 | wait_queue_head_t notif_waitq; |
366 | |||
367 | struct { | ||
368 | u32 error_event_table; | ||
369 | u32 log_event_table; | ||
370 | } device_pointers; | ||
371 | |||
361 | }; | 372 | }; |
362 | 373 | ||
363 | /*Whatever _m is (iwl_trans, iwl_priv, iwl_bus, these macros will work */ | 374 | /*Whatever _m is (iwl_trans, iwl_priv, iwl_bus, these macros will work */ |
@@ -507,7 +518,7 @@ void __acquires(wait_entry) | |||
507 | iwl_init_notification_wait(struct iwl_shared *shrd, | 518 | iwl_init_notification_wait(struct iwl_shared *shrd, |
508 | struct iwl_notification_wait *wait_entry, | 519 | struct iwl_notification_wait *wait_entry, |
509 | u8 cmd, | 520 | u8 cmd, |
510 | void (*fn)(struct iwl_priv *priv, | 521 | void (*fn)(struct iwl_trans *trans, |
511 | struct iwl_rx_packet *pkt, | 522 | struct iwl_rx_packet *pkt, |
512 | void *data), | 523 | void *data), |
513 | void *fn_data); | 524 | void *fn_data); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c index ff72dbcfd52d..a874eb7b5f8e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c | |||
@@ -77,6 +77,7 @@ | |||
77 | #include "iwl-agn.h" | 77 | #include "iwl-agn.h" |
78 | #include "iwl-testmode.h" | 78 | #include "iwl-testmode.h" |
79 | #include "iwl-trans.h" | 79 | #include "iwl-trans.h" |
80 | #include "iwl-bus.h" | ||
80 | 81 | ||
81 | /* The TLVs used in the gnl message policy between the kernel module and | 82 | /* The TLVs used in the gnl message policy between the kernel module and |
82 | * user space application. iwl_testmode_gnl_msg_policy is to be carried | 83 | * user space application. iwl_testmode_gnl_msg_policy is to be carried |
@@ -110,6 +111,9 @@ struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = { | |||
110 | [IWL_TM_ATTR_SRAM_ADDR] = { .type = NLA_U32, }, | 111 | [IWL_TM_ATTR_SRAM_ADDR] = { .type = NLA_U32, }, |
111 | [IWL_TM_ATTR_SRAM_SIZE] = { .type = NLA_U32, }, | 112 | [IWL_TM_ATTR_SRAM_SIZE] = { .type = NLA_U32, }, |
112 | [IWL_TM_ATTR_SRAM_DUMP] = { .type = NLA_UNSPEC, }, | 113 | [IWL_TM_ATTR_SRAM_DUMP] = { .type = NLA_UNSPEC, }, |
114 | |||
115 | [IWL_TM_ATTR_FW_VERSION] = { .type = NLA_U32, }, | ||
116 | [IWL_TM_ATTR_DEVICE_ID] = { .type = NLA_U32, }, | ||
113 | }; | 117 | }; |
114 | 118 | ||
115 | /* | 119 | /* |
@@ -416,6 +420,8 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) | |||
416 | struct sk_buff *skb; | 420 | struct sk_buff *skb; |
417 | unsigned char *rsp_data_ptr = NULL; | 421 | unsigned char *rsp_data_ptr = NULL; |
418 | int status = 0, rsp_data_len = 0; | 422 | int status = 0, rsp_data_len = 0; |
423 | char buf[32], *ptr = NULL; | ||
424 | unsigned int num, devid; | ||
419 | 425 | ||
420 | switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { | 426 | switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { |
421 | case IWL_TM_CMD_APP2DEV_GET_DEVICENAME: | 427 | case IWL_TM_CMD_APP2DEV_GET_DEVICENAME: |
@@ -479,7 +485,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) | |||
479 | break; | 485 | break; |
480 | 486 | ||
481 | case IWL_TM_CMD_APP2DEV_GET_EEPROM: | 487 | case IWL_TM_CMD_APP2DEV_GET_EEPROM: |
482 | if (priv->eeprom) { | 488 | if (priv->shrd->eeprom) { |
483 | skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, | 489 | skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, |
484 | priv->cfg->base_params->eeprom_size + 20); | 490 | priv->cfg->base_params->eeprom_size + 20); |
485 | if (!skb) { | 491 | if (!skb) { |
@@ -491,7 +497,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) | |||
491 | IWL_TM_CMD_DEV2APP_EEPROM_RSP); | 497 | IWL_TM_CMD_DEV2APP_EEPROM_RSP); |
492 | NLA_PUT(skb, IWL_TM_ATTR_EEPROM, | 498 | NLA_PUT(skb, IWL_TM_ATTR_EEPROM, |
493 | priv->cfg->base_params->eeprom_size, | 499 | priv->cfg->base_params->eeprom_size, |
494 | priv->eeprom); | 500 | priv->shrd->eeprom); |
495 | status = cfg80211_testmode_reply(skb); | 501 | status = cfg80211_testmode_reply(skb); |
496 | if (status < 0) | 502 | if (status < 0) |
497 | IWL_DEBUG_INFO(priv, | 503 | IWL_DEBUG_INFO(priv, |
@@ -510,6 +516,43 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) | |||
510 | priv->tm_fixed_rate = nla_get_u32(tb[IWL_TM_ATTR_FIXRATE]); | 516 | priv->tm_fixed_rate = nla_get_u32(tb[IWL_TM_ATTR_FIXRATE]); |
511 | break; | 517 | break; |
512 | 518 | ||
519 | case IWL_TM_CMD_APP2DEV_GET_FW_VERSION: | ||
520 | IWL_INFO(priv, "uCode version raw: 0x%x\n", priv->ucode_ver); | ||
521 | |||
522 | skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); | ||
523 | if (!skb) { | ||
524 | IWL_DEBUG_INFO(priv, "Error allocating memory\n"); | ||
525 | return -ENOMEM; | ||
526 | } | ||
527 | NLA_PUT_U32(skb, IWL_TM_ATTR_FW_VERSION, priv->ucode_ver); | ||
528 | status = cfg80211_testmode_reply(skb); | ||
529 | if (status < 0) | ||
530 | IWL_DEBUG_INFO(priv, | ||
531 | "Error sending msg : %d\n", status); | ||
532 | break; | ||
533 | |||
534 | case IWL_TM_CMD_APP2DEV_GET_DEVICE_ID: | ||
535 | bus_get_hw_id(bus(priv), buf, sizeof(buf)); | ||
536 | ptr = buf; | ||
537 | strsep(&ptr, ":"); | ||
538 | sscanf(strsep(&ptr, ":"), "%x", &num); | ||
539 | sscanf(strsep(&ptr, ":"), "%x", &devid); | ||
540 | IWL_INFO(priv, "Device ID = 0x%04x, SubDevice ID= 0x%04x\n", | ||
541 | num, devid); | ||
542 | devid |= (num << 16); | ||
543 | |||
544 | skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); | ||
545 | if (!skb) { | ||
546 | IWL_DEBUG_INFO(priv, "Error allocating memory\n"); | ||
547 | return -ENOMEM; | ||
548 | } | ||
549 | NLA_PUT_U32(skb, IWL_TM_ATTR_DEVICE_ID, devid); | ||
550 | status = cfg80211_testmode_reply(skb); | ||
551 | if (status < 0) | ||
552 | IWL_DEBUG_INFO(priv, | ||
553 | "Error sending msg : %d\n", status); | ||
554 | break; | ||
555 | |||
513 | default: | 556 | default: |
514 | IWL_DEBUG_INFO(priv, "Unknown testmode driver command ID\n"); | 557 | IWL_DEBUG_INFO(priv, "Unknown testmode driver command ID\n"); |
515 | return -ENOSYS; | 558 | return -ENOSYS; |
@@ -842,6 +885,8 @@ int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) | |||
842 | case IWL_TM_CMD_APP2DEV_GET_EEPROM: | 885 | case IWL_TM_CMD_APP2DEV_GET_EEPROM: |
843 | case IWL_TM_CMD_APP2DEV_FIXRATE_REQ: | 886 | case IWL_TM_CMD_APP2DEV_FIXRATE_REQ: |
844 | case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW: | 887 | case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW: |
888 | case IWL_TM_CMD_APP2DEV_GET_FW_VERSION: | ||
889 | case IWL_TM_CMD_APP2DEV_GET_DEVICE_ID: | ||
845 | IWL_DEBUG_INFO(priv, "testmode cmd to driver\n"); | 890 | IWL_DEBUG_INFO(priv, "testmode cmd to driver\n"); |
846 | result = iwl_testmode_driver(hw, tb); | 891 | result = iwl_testmode_driver(hw, tb); |
847 | break; | 892 | break; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.h b/drivers/net/wireless/iwlwifi/iwl-testmode.h index deedd27c5f3d..26138f110340 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.h +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.h | |||
@@ -118,6 +118,8 @@ | |||
118 | * commands from user applicaiton to read data in sram | 118 | * commands from user applicaiton to read data in sram |
119 | * | 119 | * |
120 | * @IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW: load Weak On Wireless LAN uCode image | 120 | * @IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW: load Weak On Wireless LAN uCode image |
121 | * @IWL_TM_CMD_APP2DEV_GET_FW_VERSION: retrieve uCode version | ||
122 | * @IWL_TM_CMD_APP2DEV_GET_DEVICE_ID: retrieve ID information in device | ||
121 | * | 123 | * |
122 | */ | 124 | */ |
123 | enum iwl_tm_cmd_t { | 125 | enum iwl_tm_cmd_t { |
@@ -143,7 +145,9 @@ enum iwl_tm_cmd_t { | |||
143 | IWL_TM_CMD_APP2DEV_READ_SRAM = 20, | 145 | IWL_TM_CMD_APP2DEV_READ_SRAM = 20, |
144 | IWL_TM_CMD_APP2DEV_DUMP_SRAM = 21, | 146 | IWL_TM_CMD_APP2DEV_DUMP_SRAM = 21, |
145 | IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW = 22, | 147 | IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW = 22, |
146 | IWL_TM_CMD_MAX = 23, | 148 | IWL_TM_CMD_APP2DEV_GET_FW_VERSION = 23, |
149 | IWL_TM_CMD_APP2DEV_GET_DEVICE_ID = 24, | ||
150 | IWL_TM_CMD_MAX = 25, | ||
147 | }; | 151 | }; |
148 | 152 | ||
149 | /* | 153 | /* |
@@ -225,6 +229,14 @@ enum iwl_tm_cmd_t { | |||
225 | * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_DUMP_SRAM, | 229 | * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_DUMP_SRAM, |
226 | * IWL_TM_ATTR_SRAM_DUMP for the data in sram | 230 | * IWL_TM_ATTR_SRAM_DUMP for the data in sram |
227 | * | 231 | * |
232 | * @IWL_TM_ATTR_FW_VERSION: | ||
233 | * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_GET_FW_VERSION, | ||
234 | * IWL_TM_ATTR_FW_VERSION for the uCode version | ||
235 | * | ||
236 | * @IWL_TM_ATTR_DEVICE_ID: | ||
237 | * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_GET_DEVICE_ID, | ||
238 | * IWL_TM_ATTR_DEVICE_ID for the device ID information | ||
239 | * | ||
228 | */ | 240 | */ |
229 | enum iwl_tm_attr_t { | 241 | enum iwl_tm_attr_t { |
230 | IWL_TM_ATTR_NOT_APPLICABLE = 0, | 242 | IWL_TM_ATTR_NOT_APPLICABLE = 0, |
@@ -245,7 +257,9 @@ enum iwl_tm_attr_t { | |||
245 | IWL_TM_ATTR_SRAM_ADDR = 15, | 257 | IWL_TM_ATTR_SRAM_ADDR = 15, |
246 | IWL_TM_ATTR_SRAM_SIZE = 16, | 258 | IWL_TM_ATTR_SRAM_SIZE = 16, |
247 | IWL_TM_ATTR_SRAM_DUMP = 17, | 259 | IWL_TM_ATTR_SRAM_DUMP = 17, |
248 | IWL_TM_ATTR_MAX = 18, | 260 | IWL_TM_ATTR_FW_VERSION = 18, |
261 | IWL_TM_ATTR_DEVICE_ID = 19, | ||
262 | IWL_TM_ATTR_MAX = 20, | ||
249 | }; | 263 | }; |
250 | 264 | ||
251 | /* uCode trace buffer */ | 265 | /* uCode trace buffer */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c index becd92173ddd..2ee00e0f39d3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | |||
@@ -594,7 +594,7 @@ static void iwl_dump_nic_error_log(struct iwl_trans *trans) | |||
594 | struct iwl_trans_pcie *trans_pcie = | 594 | struct iwl_trans_pcie *trans_pcie = |
595 | IWL_TRANS_GET_PCIE_TRANS(trans); | 595 | IWL_TRANS_GET_PCIE_TRANS(trans); |
596 | 596 | ||
597 | base = priv->device_pointers.error_event_table; | 597 | base = trans->shrd->device_pointers.error_event_table; |
598 | if (trans->shrd->ucode_type == IWL_UCODE_INIT) { | 598 | if (trans->shrd->ucode_type == IWL_UCODE_INIT) { |
599 | if (!base) | 599 | if (!base) |
600 | base = priv->init_errlog_ptr; | 600 | base = priv->init_errlog_ptr; |
@@ -648,6 +648,21 @@ static void iwl_dump_nic_error_log(struct iwl_trans *trans) | |||
648 | IWL_ERR(trans, "0x%08X | hw version\n", table.hw_ver); | 648 | IWL_ERR(trans, "0x%08X | hw version\n", table.hw_ver); |
649 | IWL_ERR(trans, "0x%08X | board version\n", table.brd_ver); | 649 | IWL_ERR(trans, "0x%08X | board version\n", table.brd_ver); |
650 | IWL_ERR(trans, "0x%08X | hcmd\n", table.hcmd); | 650 | IWL_ERR(trans, "0x%08X | hcmd\n", table.hcmd); |
651 | |||
652 | IWL_ERR(trans, "0x%08X | isr0\n", table.isr0); | ||
653 | IWL_ERR(trans, "0x%08X | isr1\n", table.isr1); | ||
654 | IWL_ERR(trans, "0x%08X | isr2\n", table.isr2); | ||
655 | IWL_ERR(trans, "0x%08X | isr3\n", table.isr3); | ||
656 | IWL_ERR(trans, "0x%08X | isr4\n", table.isr4); | ||
657 | IWL_ERR(trans, "0x%08X | isr_pref\n", table.isr_pref); | ||
658 | IWL_ERR(trans, "0x%08X | wait_event\n", table.wait_event); | ||
659 | IWL_ERR(trans, "0x%08X | l2p_control\n", table.l2p_control); | ||
660 | IWL_ERR(trans, "0x%08X | l2p_duration\n", table.l2p_duration); | ||
661 | IWL_ERR(trans, "0x%08X | l2p_mhvalid\n", table.l2p_mhvalid); | ||
662 | IWL_ERR(trans, "0x%08X | l2p_addr_match\n", table.l2p_addr_match); | ||
663 | IWL_ERR(trans, "0x%08X | lmpm_pmg_sel\n", table.lmpm_pmg_sel); | ||
664 | IWL_ERR(trans, "0x%08X | timestamp\n", table.u_timestamp); | ||
665 | IWL_ERR(trans, "0x%08X | flow_handler\n", table.flow_handler); | ||
651 | } | 666 | } |
652 | 667 | ||
653 | /** | 668 | /** |
@@ -709,7 +724,7 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx, | |||
709 | if (num_events == 0) | 724 | if (num_events == 0) |
710 | return pos; | 725 | return pos; |
711 | 726 | ||
712 | base = priv->device_pointers.log_event_table; | 727 | base = trans->shrd->device_pointers.log_event_table; |
713 | if (trans->shrd->ucode_type == IWL_UCODE_INIT) { | 728 | if (trans->shrd->ucode_type == IWL_UCODE_INIT) { |
714 | if (!base) | 729 | if (!base) |
715 | base = priv->init_evtlog_ptr; | 730 | base = priv->init_evtlog_ptr; |
@@ -823,7 +838,7 @@ int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log, | |||
823 | size_t bufsz = 0; | 838 | size_t bufsz = 0; |
824 | struct iwl_priv *priv = priv(trans); | 839 | struct iwl_priv *priv = priv(trans); |
825 | 840 | ||
826 | base = priv->device_pointers.log_event_table; | 841 | base = trans->shrd->device_pointers.log_event_table; |
827 | if (trans->shrd->ucode_type == IWL_UCODE_INIT) { | 842 | if (trans->shrd->ucode_type == IWL_UCODE_INIT) { |
828 | logsize = priv->init_evtlog_size; | 843 | logsize = priv->init_evtlog_size; |
829 | if (!base) | 844 | if (!base) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 304b2ea0375c..66e1b9fa0b8b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | |||
@@ -1373,6 +1373,7 @@ static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid, | |||
1373 | 1373 | ||
1374 | static void iwl_trans_pcie_free(struct iwl_trans *trans) | 1374 | static void iwl_trans_pcie_free(struct iwl_trans *trans) |
1375 | { | 1375 | { |
1376 | iwl_calib_free_results(trans); | ||
1376 | iwl_trans_pcie_tx_free(trans); | 1377 | iwl_trans_pcie_tx_free(trans); |
1377 | iwl_trans_pcie_rx_free(trans); | 1378 | iwl_trans_pcie_rx_free(trans); |
1378 | free_irq(bus(trans)->irq, trans); | 1379 | free_irq(bus(trans)->irq, trans); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 4a29b8ab998e..f94a6ee5f82f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
@@ -220,6 +220,14 @@ struct fw_img { | |||
220 | struct fw_desc data; /* firmware data image */ | 220 | struct fw_desc data; /* firmware data image */ |
221 | }; | 221 | }; |
222 | 222 | ||
223 | /* Opaque calibration results */ | ||
224 | struct iwl_calib_result { | ||
225 | struct list_head list; | ||
226 | size_t cmd_len; | ||
227 | struct iwl_calib_hdr hdr; | ||
228 | /* data follows */ | ||
229 | }; | ||
230 | |||
223 | /** | 231 | /** |
224 | * struct iwl_trans - transport common data | 232 | * struct iwl_trans - transport common data |
225 | * @ops - pointer to iwl_trans_ops | 233 | * @ops - pointer to iwl_trans_ops |
@@ -229,6 +237,8 @@ struct fw_img { | |||
229 | * @ucode_rt: run time ucode image | 237 | * @ucode_rt: run time ucode image |
230 | * @ucode_init: init ucode image | 238 | * @ucode_init: init ucode image |
231 | * @ucode_wowlan: wake on wireless ucode image (optional) | 239 | * @ucode_wowlan: wake on wireless ucode image (optional) |
240 | * @nvm_device_type: indicates OTP or eeprom | ||
241 | * @calib_results: list head for init calibration results | ||
232 | */ | 242 | */ |
233 | struct iwl_trans { | 243 | struct iwl_trans { |
234 | const struct iwl_trans_ops *ops; | 244 | const struct iwl_trans_ops *ops; |
@@ -243,6 +253,9 @@ struct iwl_trans { | |||
243 | /* eeprom related variables */ | 253 | /* eeprom related variables */ |
244 | int nvm_device_type; | 254 | int nvm_device_type; |
245 | 255 | ||
256 | /* init calibration results */ | ||
257 | struct list_head calib_results; | ||
258 | |||
246 | /* pointer to trans specific struct */ | 259 | /* pointer to trans specific struct */ |
247 | /*Ensure that this pointer will always be aligned to sizeof pointer */ | 260 | /*Ensure that this pointer will always be aligned to sizeof pointer */ |
248 | char trans_specific[0] __attribute__((__aligned__(sizeof(void *)))); | 261 | char trans_specific[0] __attribute__((__aligned__(sizeof(void *)))); |
@@ -379,4 +392,9 @@ int iwl_alloc_fw_desc(struct iwl_bus *bus, struct fw_desc *desc, | |||
379 | const void *data, size_t len); | 392 | const void *data, size_t len); |
380 | void iwl_dealloc_ucode(struct iwl_trans *trans); | 393 | void iwl_dealloc_ucode(struct iwl_trans *trans); |
381 | 394 | ||
395 | int iwl_send_calib_results(struct iwl_trans *trans); | ||
396 | int iwl_calib_set(struct iwl_trans *trans, | ||
397 | const struct iwl_calib_hdr *cmd, int len); | ||
398 | void iwl_calib_free_results(struct iwl_trans *trans); | ||
399 | |||
382 | #endif /* __iwl_trans_h__ */ | 400 | #endif /* __iwl_trans_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/iwl-ucode.c index b365de457b1b..0577212ad3f3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-ucode.c | |||
@@ -217,19 +217,20 @@ static int iwl_set_Xtal_calib(struct iwl_priv *priv) | |||
217 | { | 217 | { |
218 | struct iwl_calib_xtal_freq_cmd cmd; | 218 | struct iwl_calib_xtal_freq_cmd cmd; |
219 | __le16 *xtal_calib = | 219 | __le16 *xtal_calib = |
220 | (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_XTAL); | 220 | (__le16 *)iwl_eeprom_query_addr(priv->shrd, EEPROM_XTAL); |
221 | 221 | ||
222 | iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD); | 222 | iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD); |
223 | cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]); | 223 | cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]); |
224 | cmd.cap_pin2 = le16_to_cpu(xtal_calib[1]); | 224 | cmd.cap_pin2 = le16_to_cpu(xtal_calib[1]); |
225 | return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd)); | 225 | return iwl_calib_set(trans(priv), (void *)&cmd, sizeof(cmd)); |
226 | } | 226 | } |
227 | 227 | ||
228 | static int iwl_set_temperature_offset_calib(struct iwl_priv *priv) | 228 | static int iwl_set_temperature_offset_calib(struct iwl_priv *priv) |
229 | { | 229 | { |
230 | struct iwl_calib_temperature_offset_cmd cmd; | 230 | struct iwl_calib_temperature_offset_cmd cmd; |
231 | __le16 *offset_calib = | 231 | __le16 *offset_calib = |
232 | (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_RAW_TEMPERATURE); | 232 | (__le16 *)iwl_eeprom_query_addr(priv->shrd, |
233 | EEPROM_RAW_TEMPERATURE); | ||
233 | 234 | ||
234 | memset(&cmd, 0, sizeof(cmd)); | 235 | memset(&cmd, 0, sizeof(cmd)); |
235 | iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); | 236 | iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); |
@@ -239,21 +240,22 @@ static int iwl_set_temperature_offset_calib(struct iwl_priv *priv) | |||
239 | 240 | ||
240 | IWL_DEBUG_CALIB(priv, "Radio sensor offset: %d\n", | 241 | IWL_DEBUG_CALIB(priv, "Radio sensor offset: %d\n", |
241 | le16_to_cpu(cmd.radio_sensor_offset)); | 242 | le16_to_cpu(cmd.radio_sensor_offset)); |
242 | return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd)); | 243 | return iwl_calib_set(trans(priv), (void *)&cmd, sizeof(cmd)); |
243 | } | 244 | } |
244 | 245 | ||
245 | static int iwl_set_temperature_offset_calib_v2(struct iwl_priv *priv) | 246 | static int iwl_set_temperature_offset_calib_v2(struct iwl_priv *priv) |
246 | { | 247 | { |
247 | struct iwl_calib_temperature_offset_v2_cmd cmd; | 248 | struct iwl_calib_temperature_offset_v2_cmd cmd; |
248 | __le16 *offset_calib_high = (__le16 *)iwl_eeprom_query_addr(priv, | 249 | __le16 *offset_calib_high = (__le16 *)iwl_eeprom_query_addr(priv->shrd, |
249 | EEPROM_KELVIN_TEMPERATURE); | 250 | EEPROM_KELVIN_TEMPERATURE); |
250 | __le16 *offset_calib_low = | 251 | __le16 *offset_calib_low = |
251 | (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_RAW_TEMPERATURE); | 252 | (__le16 *)iwl_eeprom_query_addr(priv->shrd, |
253 | EEPROM_RAW_TEMPERATURE); | ||
252 | struct iwl_eeprom_calib_hdr *hdr; | 254 | struct iwl_eeprom_calib_hdr *hdr; |
253 | 255 | ||
254 | memset(&cmd, 0, sizeof(cmd)); | 256 | memset(&cmd, 0, sizeof(cmd)); |
255 | iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); | 257 | iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); |
256 | hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv, | 258 | hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv->shrd, |
257 | EEPROM_CALIB_ALL); | 259 | EEPROM_CALIB_ALL); |
258 | memcpy(&cmd.radio_sensor_offset_high, offset_calib_high, | 260 | memcpy(&cmd.radio_sensor_offset_high, offset_calib_high, |
259 | sizeof(*offset_calib_high)); | 261 | sizeof(*offset_calib_high)); |
@@ -274,7 +276,7 @@ static int iwl_set_temperature_offset_calib_v2(struct iwl_priv *priv) | |||
274 | IWL_DEBUG_CALIB(priv, "Voltage Ref: %d\n", | 276 | IWL_DEBUG_CALIB(priv, "Voltage Ref: %d\n", |
275 | le16_to_cpu(cmd.burntVoltageRef)); | 277 | le16_to_cpu(cmd.burntVoltageRef)); |
276 | 278 | ||
277 | return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd)); | 279 | return iwl_calib_set(trans(priv), (void *)&cmd, sizeof(cmd)); |
278 | } | 280 | } |
279 | 281 | ||
280 | static int iwl_send_calib_cfg(struct iwl_trans *trans) | 282 | static int iwl_send_calib_cfg(struct iwl_trans *trans) |
@@ -307,7 +309,7 @@ int iwlagn_rx_calib_result(struct iwl_priv *priv, | |||
307 | /* reduce the size of the length field itself */ | 309 | /* reduce the size of the length field itself */ |
308 | len -= 4; | 310 | len -= 4; |
309 | 311 | ||
310 | if (iwl_calib_set(priv, hdr, len)) | 312 | if (iwl_calib_set(trans(priv), hdr, len)) |
311 | IWL_ERR(priv, "Failed to record calibration data %d\n", | 313 | IWL_ERR(priv, "Failed to record calibration data %d\n", |
312 | hdr->op_code); | 314 | hdr->op_code); |
313 | 315 | ||
@@ -457,7 +459,7 @@ static int iwl_alive_notify(struct iwl_priv *priv) | |||
457 | return ret; | 459 | return ret; |
458 | } | 460 | } |
459 | 461 | ||
460 | return iwl_send_calib_results(priv); | 462 | return iwl_send_calib_results(trans(priv)); |
461 | } | 463 | } |
462 | 464 | ||
463 | 465 | ||
@@ -548,7 +550,7 @@ struct iwlagn_alive_data { | |||
548 | u8 subtype; | 550 | u8 subtype; |
549 | }; | 551 | }; |
550 | 552 | ||
551 | static void iwl_alive_fn(struct iwl_priv *priv, | 553 | static void iwl_alive_fn(struct iwl_trans *trans, |
552 | struct iwl_rx_packet *pkt, | 554 | struct iwl_rx_packet *pkt, |
553 | void *data) | 555 | void *data) |
554 | { | 556 | { |
@@ -557,14 +559,14 @@ static void iwl_alive_fn(struct iwl_priv *priv, | |||
557 | 559 | ||
558 | palive = &pkt->u.alive_frame; | 560 | palive = &pkt->u.alive_frame; |
559 | 561 | ||
560 | IWL_DEBUG_FW(priv, "Alive ucode status 0x%08X revision " | 562 | IWL_DEBUG_FW(trans, "Alive ucode status 0x%08X revision " |
561 | "0x%01X 0x%01X\n", | 563 | "0x%01X 0x%01X\n", |
562 | palive->is_valid, palive->ver_type, | 564 | palive->is_valid, palive->ver_type, |
563 | palive->ver_subtype); | 565 | palive->ver_subtype); |
564 | 566 | ||
565 | priv->device_pointers.error_event_table = | 567 | trans->shrd->device_pointers.error_event_table = |
566 | le32_to_cpu(palive->error_event_table_ptr); | 568 | le32_to_cpu(palive->error_event_table_ptr); |
567 | priv->device_pointers.log_event_table = | 569 | trans->shrd->device_pointers.log_event_table = |
568 | le32_to_cpu(palive->log_event_table_ptr); | 570 | le32_to_cpu(palive->log_event_table_ptr); |
569 | 571 | ||
570 | alive_data->subtype = palive->ver_subtype; | 572 | alive_data->subtype = palive->ver_subtype; |
@@ -575,7 +577,7 @@ static void iwl_alive_fn(struct iwl_priv *priv, | |||
575 | void iwl_init_notification_wait(struct iwl_shared *shrd, | 577 | void iwl_init_notification_wait(struct iwl_shared *shrd, |
576 | struct iwl_notification_wait *wait_entry, | 578 | struct iwl_notification_wait *wait_entry, |
577 | u8 cmd, | 579 | u8 cmd, |
578 | void (*fn)(struct iwl_priv *priv, | 580 | void (*fn)(struct iwl_trans *trans, |
579 | struct iwl_rx_packet *pkt, | 581 | struct iwl_rx_packet *pkt, |
580 | void *data), | 582 | void *data), |
581 | void *fn_data) | 583 | void *fn_data) |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 6cf6d6d25e21..52bcdf40d5bd 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -37,7 +37,8 @@ MODULE_AUTHOR("Jouni Malinen"); | |||
37 | MODULE_DESCRIPTION("Software simulator of 802.11 radio(s) for mac80211"); | 37 | MODULE_DESCRIPTION("Software simulator of 802.11 radio(s) for mac80211"); |
38 | MODULE_LICENSE("GPL"); | 38 | MODULE_LICENSE("GPL"); |
39 | 39 | ||
40 | int wmediumd_pid; | 40 | static u32 wmediumd_pid; |
41 | |||
41 | static int radios = 2; | 42 | static int radios = 2; |
42 | module_param(radios, int, 0444); | 43 | module_param(radios, int, 0444); |
43 | MODULE_PARM_DESC(radios, "Number of simulated radios"); | 44 | MODULE_PARM_DESC(radios, "Number of simulated radios"); |
@@ -665,7 +666,7 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
665 | { | 666 | { |
666 | bool ack; | 667 | bool ack; |
667 | struct ieee80211_tx_info *txi; | 668 | struct ieee80211_tx_info *txi; |
668 | int _pid; | 669 | u32 _pid; |
669 | 670 | ||
670 | mac80211_hwsim_monitor_rx(hw, skb); | 671 | mac80211_hwsim_monitor_rx(hw, skb); |
671 | 672 | ||
@@ -676,7 +677,7 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
676 | } | 677 | } |
677 | 678 | ||
678 | /* wmediumd mode check */ | 679 | /* wmediumd mode check */ |
679 | _pid = wmediumd_pid; | 680 | _pid = ACCESS_ONCE(wmediumd_pid); |
680 | 681 | ||
681 | if (_pid) | 682 | if (_pid) |
682 | return mac80211_hwsim_tx_frame_nl(hw, skb, _pid); | 683 | return mac80211_hwsim_tx_frame_nl(hw, skb, _pid); |
@@ -764,7 +765,7 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, | |||
764 | struct ieee80211_hw *hw = arg; | 765 | struct ieee80211_hw *hw = arg; |
765 | struct sk_buff *skb; | 766 | struct sk_buff *skb; |
766 | struct ieee80211_tx_info *info; | 767 | struct ieee80211_tx_info *info; |
767 | int _pid; | 768 | u32 _pid; |
768 | 769 | ||
769 | hwsim_check_magic(vif); | 770 | hwsim_check_magic(vif); |
770 | 771 | ||
@@ -781,7 +782,7 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, | |||
781 | mac80211_hwsim_monitor_rx(hw, skb); | 782 | mac80211_hwsim_monitor_rx(hw, skb); |
782 | 783 | ||
783 | /* wmediumd mode check */ | 784 | /* wmediumd mode check */ |
784 | _pid = wmediumd_pid; | 785 | _pid = ACCESS_ONCE(wmediumd_pid); |
785 | 786 | ||
786 | if (_pid) | 787 | if (_pid) |
787 | return mac80211_hwsim_tx_frame_nl(hw, skb, _pid); | 788 | return mac80211_hwsim_tx_frame_nl(hw, skb, _pid); |
@@ -1254,7 +1255,7 @@ static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif) | |||
1254 | struct hwsim_vif_priv *vp = (void *)vif->drv_priv; | 1255 | struct hwsim_vif_priv *vp = (void *)vif->drv_priv; |
1255 | struct sk_buff *skb; | 1256 | struct sk_buff *skb; |
1256 | struct ieee80211_pspoll *pspoll; | 1257 | struct ieee80211_pspoll *pspoll; |
1257 | int _pid; | 1258 | u32 _pid; |
1258 | 1259 | ||
1259 | if (!vp->assoc) | 1260 | if (!vp->assoc) |
1260 | return; | 1261 | return; |
@@ -1275,7 +1276,7 @@ static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif) | |||
1275 | memcpy(pspoll->ta, mac, ETH_ALEN); | 1276 | memcpy(pspoll->ta, mac, ETH_ALEN); |
1276 | 1277 | ||
1277 | /* wmediumd mode check */ | 1278 | /* wmediumd mode check */ |
1278 | _pid = wmediumd_pid; | 1279 | _pid = ACCESS_ONCE(wmediumd_pid); |
1279 | 1280 | ||
1280 | if (_pid) | 1281 | if (_pid) |
1281 | return mac80211_hwsim_tx_frame_nl(data->hw, skb, _pid); | 1282 | return mac80211_hwsim_tx_frame_nl(data->hw, skb, _pid); |
@@ -1292,7 +1293,7 @@ static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac, | |||
1292 | struct hwsim_vif_priv *vp = (void *)vif->drv_priv; | 1293 | struct hwsim_vif_priv *vp = (void *)vif->drv_priv; |
1293 | struct sk_buff *skb; | 1294 | struct sk_buff *skb; |
1294 | struct ieee80211_hdr *hdr; | 1295 | struct ieee80211_hdr *hdr; |
1295 | int _pid; | 1296 | u32 _pid; |
1296 | 1297 | ||
1297 | if (!vp->assoc) | 1298 | if (!vp->assoc) |
1298 | return; | 1299 | return; |
@@ -1314,7 +1315,7 @@ static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac, | |||
1314 | memcpy(hdr->addr3, vp->bssid, ETH_ALEN); | 1315 | memcpy(hdr->addr3, vp->bssid, ETH_ALEN); |
1315 | 1316 | ||
1316 | /* wmediumd mode check */ | 1317 | /* wmediumd mode check */ |
1317 | _pid = wmediumd_pid; | 1318 | _pid = ACCESS_ONCE(wmediumd_pid); |
1318 | 1319 | ||
1319 | if (_pid) | 1320 | if (_pid) |
1320 | return mac80211_hwsim_tx_frame_nl(data->hw, skb, _pid); | 1321 | return mac80211_hwsim_tx_frame_nl(data->hw, skb, _pid); |
@@ -1634,8 +1635,6 @@ static int hwsim_init_netlink(void) | |||
1634 | int rc; | 1635 | int rc; |
1635 | printk(KERN_INFO "mac80211_hwsim: initializing netlink\n"); | 1636 | printk(KERN_INFO "mac80211_hwsim: initializing netlink\n"); |
1636 | 1637 | ||
1637 | wmediumd_pid = 0; | ||
1638 | |||
1639 | rc = genl_register_family_with_ops(&hwsim_genl_family, | 1638 | rc = genl_register_family_with_ops(&hwsim_genl_family, |
1640 | hwsim_ops, ARRAY_SIZE(hwsim_ops)); | 1639 | hwsim_ops, ARRAY_SIZE(hwsim_ops)); |
1641 | if (rc) | 1640 | if (rc) |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 0db97cc84cb4..787dbe2aa408 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -751,17 +751,13 @@ mwifiex_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, | |||
751 | { | 751 | { |
752 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | 752 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); |
753 | 753 | ||
754 | if (priv->disconnect) | ||
755 | return -EBUSY; | ||
756 | |||
757 | priv->disconnect = 1; | ||
758 | if (mwifiex_deauthenticate(priv, NULL)) | 754 | if (mwifiex_deauthenticate(priv, NULL)) |
759 | return -EFAULT; | 755 | return -EFAULT; |
760 | 756 | ||
761 | wiphy_dbg(wiphy, "info: successfully disconnected from %pM:" | 757 | wiphy_dbg(wiphy, "info: successfully disconnected from %pM:" |
762 | " reason code %d\n", priv->cfg_bssid, reason_code); | 758 | " reason code %d\n", priv->cfg_bssid, reason_code); |
763 | 759 | ||
764 | queue_work(priv->workqueue, &priv->cfg_workqueue); | 760 | memset(priv->cfg_bssid, 0, ETH_ALEN); |
765 | 761 | ||
766 | return 0; | 762 | return 0; |
767 | } | 763 | } |
@@ -981,27 +977,32 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, | |||
981 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | 977 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); |
982 | int ret = 0; | 978 | int ret = 0; |
983 | 979 | ||
984 | if (priv->assoc_request) | ||
985 | return -EBUSY; | ||
986 | |||
987 | if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { | 980 | if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { |
988 | wiphy_err(wiphy, "received infra assoc request " | 981 | wiphy_err(wiphy, "received infra assoc request " |
989 | "when station is in ibss mode\n"); | 982 | "when station is in ibss mode\n"); |
990 | goto done; | 983 | goto done; |
991 | } | 984 | } |
992 | 985 | ||
993 | priv->assoc_request = -EINPROGRESS; | ||
994 | |||
995 | wiphy_dbg(wiphy, "info: Trying to associate to %s and bssid %pM\n", | 986 | wiphy_dbg(wiphy, "info: Trying to associate to %s and bssid %pM\n", |
996 | (char *) sme->ssid, sme->bssid); | 987 | (char *) sme->ssid, sme->bssid); |
997 | 988 | ||
998 | ret = mwifiex_cfg80211_assoc(priv, sme->ssid_len, sme->ssid, sme->bssid, | 989 | ret = mwifiex_cfg80211_assoc(priv, sme->ssid_len, sme->ssid, sme->bssid, |
999 | priv->bss_mode, sme->channel, sme, 0); | 990 | priv->bss_mode, sme->channel, sme, 0); |
1000 | |||
1001 | priv->assoc_request = 1; | ||
1002 | done: | 991 | done: |
1003 | priv->assoc_result = ret; | 992 | if (!ret) { |
1004 | queue_work(priv->workqueue, &priv->cfg_workqueue); | 993 | cfg80211_connect_result(priv->netdev, priv->cfg_bssid, NULL, 0, |
994 | NULL, 0, WLAN_STATUS_SUCCESS, | ||
995 | GFP_KERNEL); | ||
996 | dev_dbg(priv->adapter->dev, | ||
997 | "info: associated to bssid %pM successfully\n", | ||
998 | priv->cfg_bssid); | ||
999 | } else { | ||
1000 | dev_dbg(priv->adapter->dev, | ||
1001 | "info: association to bssid %pM failed\n", | ||
1002 | priv->cfg_bssid); | ||
1003 | memset(priv->cfg_bssid, 0, ETH_ALEN); | ||
1004 | } | ||
1005 | |||
1005 | return ret; | 1006 | return ret; |
1006 | } | 1007 | } |
1007 | 1008 | ||
@@ -1018,28 +1019,29 @@ mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, | |||
1018 | struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); | 1019 | struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); |
1019 | int ret = 0; | 1020 | int ret = 0; |
1020 | 1021 | ||
1021 | if (priv->ibss_join_request) | ||
1022 | return -EBUSY; | ||
1023 | |||
1024 | if (priv->bss_mode != NL80211_IFTYPE_ADHOC) { | 1022 | if (priv->bss_mode != NL80211_IFTYPE_ADHOC) { |
1025 | wiphy_err(wiphy, "request to join ibss received " | 1023 | wiphy_err(wiphy, "request to join ibss received " |
1026 | "when station is not in ibss mode\n"); | 1024 | "when station is not in ibss mode\n"); |
1027 | goto done; | 1025 | goto done; |
1028 | } | 1026 | } |
1029 | 1027 | ||
1030 | priv->ibss_join_request = -EINPROGRESS; | ||
1031 | |||
1032 | wiphy_dbg(wiphy, "info: trying to join to %s and bssid %pM\n", | 1028 | wiphy_dbg(wiphy, "info: trying to join to %s and bssid %pM\n", |
1033 | (char *) params->ssid, params->bssid); | 1029 | (char *) params->ssid, params->bssid); |
1034 | 1030 | ||
1035 | ret = mwifiex_cfg80211_assoc(priv, params->ssid_len, params->ssid, | 1031 | ret = mwifiex_cfg80211_assoc(priv, params->ssid_len, params->ssid, |
1036 | params->bssid, priv->bss_mode, | 1032 | params->bssid, priv->bss_mode, |
1037 | params->channel, NULL, params->privacy); | 1033 | params->channel, NULL, params->privacy); |
1038 | |||
1039 | priv->ibss_join_request = 1; | ||
1040 | done: | 1034 | done: |
1041 | priv->ibss_join_result = ret; | 1035 | if (!ret) { |
1042 | queue_work(priv->workqueue, &priv->cfg_workqueue); | 1036 | cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, GFP_KERNEL); |
1037 | dev_dbg(priv->adapter->dev, | ||
1038 | "info: joined/created adhoc network with bssid" | ||
1039 | " %pM successfully\n", priv->cfg_bssid); | ||
1040 | } else { | ||
1041 | dev_dbg(priv->adapter->dev, | ||
1042 | "info: failed creating/joining adhoc network\n"); | ||
1043 | } | ||
1044 | |||
1043 | return ret; | 1045 | return ret; |
1044 | } | 1046 | } |
1045 | 1047 | ||
@@ -1054,17 +1056,12 @@ mwifiex_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) | |||
1054 | { | 1056 | { |
1055 | struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); | 1057 | struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); |
1056 | 1058 | ||
1057 | if (priv->disconnect) | ||
1058 | return -EBUSY; | ||
1059 | |||
1060 | priv->disconnect = 1; | ||
1061 | |||
1062 | wiphy_dbg(wiphy, "info: disconnecting from essid %pM\n", | 1059 | wiphy_dbg(wiphy, "info: disconnecting from essid %pM\n", |
1063 | priv->cfg_bssid); | 1060 | priv->cfg_bssid); |
1064 | if (mwifiex_deauthenticate(priv, NULL)) | 1061 | if (mwifiex_deauthenticate(priv, NULL)) |
1065 | return -EFAULT; | 1062 | return -EFAULT; |
1066 | 1063 | ||
1067 | queue_work(priv->workqueue, &priv->cfg_workqueue); | 1064 | memset(priv->cfg_bssid, 0, ETH_ALEN); |
1068 | 1065 | ||
1069 | return 0; | 1066 | return 0; |
1070 | } | 1067 | } |
@@ -1081,15 +1078,42 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, struct net_device *dev, | |||
1081 | struct cfg80211_scan_request *request) | 1078 | struct cfg80211_scan_request *request) |
1082 | { | 1079 | { |
1083 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | 1080 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); |
1081 | int i; | ||
1082 | struct ieee80211_channel *chan; | ||
1084 | 1083 | ||
1085 | wiphy_dbg(wiphy, "info: received scan request on %s\n", dev->name); | 1084 | wiphy_dbg(wiphy, "info: received scan request on %s\n", dev->name); |
1086 | 1085 | ||
1087 | if (priv->scan_request && priv->scan_request != request) | ||
1088 | return -EBUSY; | ||
1089 | |||
1090 | priv->scan_request = request; | 1086 | priv->scan_request = request; |
1091 | 1087 | ||
1092 | queue_work(priv->workqueue, &priv->cfg_workqueue); | 1088 | priv->user_scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), |
1089 | GFP_KERNEL); | ||
1090 | if (!priv->user_scan_cfg) { | ||
1091 | dev_err(priv->adapter->dev, "failed to alloc scan_req\n"); | ||
1092 | return -ENOMEM; | ||
1093 | } | ||
1094 | for (i = 0; i < request->n_ssids; i++) { | ||
1095 | memcpy(priv->user_scan_cfg->ssid_list[i].ssid, | ||
1096 | request->ssids[i].ssid, request->ssids[i].ssid_len); | ||
1097 | priv->user_scan_cfg->ssid_list[i].max_len = | ||
1098 | request->ssids[i].ssid_len; | ||
1099 | } | ||
1100 | for (i = 0; i < request->n_channels; i++) { | ||
1101 | chan = request->channels[i]; | ||
1102 | priv->user_scan_cfg->chan_list[i].chan_number = chan->hw_value; | ||
1103 | priv->user_scan_cfg->chan_list[i].radio_type = chan->band; | ||
1104 | |||
1105 | if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) | ||
1106 | priv->user_scan_cfg->chan_list[i].scan_type = | ||
1107 | MWIFIEX_SCAN_TYPE_PASSIVE; | ||
1108 | else | ||
1109 | priv->user_scan_cfg->chan_list[i].scan_type = | ||
1110 | MWIFIEX_SCAN_TYPE_ACTIVE; | ||
1111 | |||
1112 | priv->user_scan_cfg->chan_list[i].scan_time = 0; | ||
1113 | } | ||
1114 | if (mwifiex_set_user_scan_ioctl(priv, priv->user_scan_cfg)) | ||
1115 | return -EFAULT; | ||
1116 | |||
1093 | return 0; | 1117 | return 0; |
1094 | } | 1118 | } |
1095 | 1119 | ||
@@ -1295,10 +1319,6 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev) | |||
1295 | 1319 | ||
1296 | priv->media_connected = false; | 1320 | priv->media_connected = false; |
1297 | 1321 | ||
1298 | cancel_work_sync(&priv->cfg_workqueue); | ||
1299 | flush_workqueue(priv->workqueue); | ||
1300 | destroy_workqueue(priv->workqueue); | ||
1301 | |||
1302 | priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; | 1322 | priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; |
1303 | 1323 | ||
1304 | return 0; | 1324 | return 0; |
@@ -1376,9 +1396,6 @@ int mwifiex_register_cfg80211(struct mwifiex_private *priv) | |||
1376 | memcpy(wdev->wiphy->perm_addr, priv->curr_addr, ETH_ALEN); | 1396 | memcpy(wdev->wiphy->perm_addr, priv->curr_addr, ETH_ALEN); |
1377 | wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | 1397 | wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; |
1378 | 1398 | ||
1379 | /* We are using custom domains */ | ||
1380 | wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; | ||
1381 | |||
1382 | /* Reserve space for bss band information */ | 1399 | /* Reserve space for bss band information */ |
1383 | wdev->wiphy->bss_priv_size = sizeof(u8); | 1400 | wdev->wiphy->bss_priv_size = sizeof(u8); |
1384 | 1401 | ||
@@ -1407,100 +1424,3 @@ int mwifiex_register_cfg80211(struct mwifiex_private *priv) | |||
1407 | 1424 | ||
1408 | return ret; | 1425 | return ret; |
1409 | } | 1426 | } |
1410 | |||
1411 | /* | ||
1412 | * This function handles the result of different pending network operations. | ||
1413 | * | ||
1414 | * The following operations are handled and CFG802.11 subsystem is | ||
1415 | * notified accordingly - | ||
1416 | * - Scan request completion | ||
1417 | * - Association request completion | ||
1418 | * - IBSS join request completion | ||
1419 | * - Disconnect request completion | ||
1420 | */ | ||
1421 | void | ||
1422 | mwifiex_cfg80211_results(struct work_struct *work) | ||
1423 | { | ||
1424 | struct mwifiex_private *priv = | ||
1425 | container_of(work, struct mwifiex_private, cfg_workqueue); | ||
1426 | struct mwifiex_user_scan_cfg *scan_req; | ||
1427 | int ret = 0, i; | ||
1428 | struct ieee80211_channel *chan; | ||
1429 | |||
1430 | if (priv->scan_request) { | ||
1431 | scan_req = kzalloc(sizeof(struct mwifiex_user_scan_cfg), | ||
1432 | GFP_KERNEL); | ||
1433 | if (!scan_req) { | ||
1434 | dev_err(priv->adapter->dev, "failed to alloc " | ||
1435 | "scan_req\n"); | ||
1436 | return; | ||
1437 | } | ||
1438 | for (i = 0; i < priv->scan_request->n_ssids; i++) { | ||
1439 | memcpy(scan_req->ssid_list[i].ssid, | ||
1440 | priv->scan_request->ssids[i].ssid, | ||
1441 | priv->scan_request->ssids[i].ssid_len); | ||
1442 | scan_req->ssid_list[i].max_len = | ||
1443 | priv->scan_request->ssids[i].ssid_len; | ||
1444 | } | ||
1445 | for (i = 0; i < priv->scan_request->n_channels; i++) { | ||
1446 | chan = priv->scan_request->channels[i]; | ||
1447 | scan_req->chan_list[i].chan_number = chan->hw_value; | ||
1448 | scan_req->chan_list[i].radio_type = chan->band; | ||
1449 | if (chan->flags & IEEE80211_CHAN_DISABLED) | ||
1450 | scan_req->chan_list[i].scan_type = | ||
1451 | MWIFIEX_SCAN_TYPE_PASSIVE; | ||
1452 | else | ||
1453 | scan_req->chan_list[i].scan_type = | ||
1454 | MWIFIEX_SCAN_TYPE_ACTIVE; | ||
1455 | scan_req->chan_list[i].scan_time = 0; | ||
1456 | } | ||
1457 | if (mwifiex_set_user_scan_ioctl(priv, scan_req)) | ||
1458 | ret = -EFAULT; | ||
1459 | priv->scan_result_status = ret; | ||
1460 | dev_dbg(priv->adapter->dev, "info: %s: sending scan results\n", | ||
1461 | __func__); | ||
1462 | cfg80211_scan_done(priv->scan_request, | ||
1463 | (priv->scan_result_status < 0)); | ||
1464 | priv->scan_request = NULL; | ||
1465 | kfree(scan_req); | ||
1466 | } | ||
1467 | |||
1468 | if (priv->assoc_request == 1) { | ||
1469 | if (!priv->assoc_result) { | ||
1470 | cfg80211_connect_result(priv->netdev, priv->cfg_bssid, | ||
1471 | NULL, 0, NULL, 0, | ||
1472 | WLAN_STATUS_SUCCESS, | ||
1473 | GFP_KERNEL); | ||
1474 | dev_dbg(priv->adapter->dev, | ||
1475 | "info: associated to bssid %pM successfully\n", | ||
1476 | priv->cfg_bssid); | ||
1477 | } else { | ||
1478 | dev_dbg(priv->adapter->dev, | ||
1479 | "info: association to bssid %pM failed\n", | ||
1480 | priv->cfg_bssid); | ||
1481 | memset(priv->cfg_bssid, 0, ETH_ALEN); | ||
1482 | } | ||
1483 | priv->assoc_request = 0; | ||
1484 | priv->assoc_result = 0; | ||
1485 | } | ||
1486 | |||
1487 | if (priv->ibss_join_request == 1) { | ||
1488 | if (!priv->ibss_join_result) { | ||
1489 | cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, | ||
1490 | GFP_KERNEL); | ||
1491 | dev_dbg(priv->adapter->dev, | ||
1492 | "info: joined/created adhoc network with bssid" | ||
1493 | " %pM successfully\n", priv->cfg_bssid); | ||
1494 | } else { | ||
1495 | dev_dbg(priv->adapter->dev, | ||
1496 | "info: failed creating/joining adhoc network\n"); | ||
1497 | } | ||
1498 | priv->ibss_join_request = 0; | ||
1499 | priv->ibss_join_result = 0; | ||
1500 | } | ||
1501 | |||
1502 | if (priv->disconnect) { | ||
1503 | memset(priv->cfg_bssid, 0, ETH_ALEN); | ||
1504 | priv->disconnect = 0; | ||
1505 | } | ||
1506 | } | ||
diff --git a/drivers/net/wireless/mwifiex/cfg80211.h b/drivers/net/wireless/mwifiex/cfg80211.h index 8d010f2500c5..76c76c60438b 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.h +++ b/drivers/net/wireless/mwifiex/cfg80211.h | |||
@@ -26,5 +26,4 @@ | |||
26 | 26 | ||
27 | int mwifiex_register_cfg80211(struct mwifiex_private *); | 27 | int mwifiex_register_cfg80211(struct mwifiex_private *); |
28 | 28 | ||
29 | void mwifiex_cfg80211_results(struct work_struct *work); | ||
30 | #endif | 29 | #endif |
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index ac278156d390..6e0a3eaecf70 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c | |||
@@ -939,7 +939,6 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter) | |||
939 | { | 939 | { |
940 | struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL; | 940 | struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL; |
941 | unsigned long cmd_flags; | 941 | unsigned long cmd_flags; |
942 | unsigned long cmd_pending_q_flags; | ||
943 | unsigned long scan_pending_q_flags; | 942 | unsigned long scan_pending_q_flags; |
944 | uint16_t cancel_scan_cmd = false; | 943 | uint16_t cancel_scan_cmd = false; |
945 | 944 | ||
@@ -949,12 +948,9 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter) | |||
949 | cmd_node = adapter->curr_cmd; | 948 | cmd_node = adapter->curr_cmd; |
950 | cmd_node->wait_q_enabled = false; | 949 | cmd_node->wait_q_enabled = false; |
951 | cmd_node->cmd_flag |= CMD_F_CANCELED; | 950 | cmd_node->cmd_flag |= CMD_F_CANCELED; |
952 | spin_lock_irqsave(&adapter->cmd_pending_q_lock, | ||
953 | cmd_pending_q_flags); | ||
954 | list_del(&cmd_node->list); | ||
955 | spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, | ||
956 | cmd_pending_q_flags); | ||
957 | mwifiex_insert_cmd_to_free_q(adapter, cmd_node); | 951 | mwifiex_insert_cmd_to_free_q(adapter, cmd_node); |
952 | mwifiex_complete_cmd(adapter, adapter->curr_cmd); | ||
953 | adapter->curr_cmd = NULL; | ||
958 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); | 954 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); |
959 | } | 955 | } |
960 | 956 | ||
@@ -981,7 +977,6 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter) | |||
981 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); | 977 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); |
982 | } | 978 | } |
983 | adapter->cmd_wait_q.status = -1; | 979 | adapter->cmd_wait_q.status = -1; |
984 | mwifiex_complete_cmd(adapter, adapter->curr_cmd); | ||
985 | } | 980 | } |
986 | 981 | ||
987 | /* | 982 | /* |
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index 26940455255b..244c728ef9dc 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c | |||
@@ -283,6 +283,45 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter) | |||
283 | } | 283 | } |
284 | 284 | ||
285 | /* | 285 | /* |
286 | * This function sets trans_start per tx_queue | ||
287 | */ | ||
288 | void mwifiex_set_trans_start(struct net_device *dev) | ||
289 | { | ||
290 | int i; | ||
291 | |||
292 | for (i = 0; i < dev->num_tx_queues; i++) | ||
293 | netdev_get_tx_queue(dev, i)->trans_start = jiffies; | ||
294 | |||
295 | dev->trans_start = jiffies; | ||
296 | } | ||
297 | |||
298 | /* | ||
299 | * This function wakes up all queues in net_device | ||
300 | */ | ||
301 | void mwifiex_wake_up_net_dev_queue(struct net_device *netdev, | ||
302 | struct mwifiex_adapter *adapter) | ||
303 | { | ||
304 | unsigned long dev_queue_flags; | ||
305 | |||
306 | spin_lock_irqsave(&adapter->queue_lock, dev_queue_flags); | ||
307 | netif_tx_wake_all_queues(netdev); | ||
308 | spin_unlock_irqrestore(&adapter->queue_lock, dev_queue_flags); | ||
309 | } | ||
310 | |||
311 | /* | ||
312 | * This function stops all queues in net_device | ||
313 | */ | ||
314 | void mwifiex_stop_net_dev_queue(struct net_device *netdev, | ||
315 | struct mwifiex_adapter *adapter) | ||
316 | { | ||
317 | unsigned long dev_queue_flags; | ||
318 | |||
319 | spin_lock_irqsave(&adapter->queue_lock, dev_queue_flags); | ||
320 | netif_tx_stop_all_queues(netdev); | ||
321 | spin_unlock_irqrestore(&adapter->queue_lock, dev_queue_flags); | ||
322 | } | ||
323 | |||
324 | /* | ||
286 | * This function releases the lock variables and frees the locks and | 325 | * This function releases the lock variables and frees the locks and |
287 | * associated locks. | 326 | * associated locks. |
288 | */ | 327 | */ |
@@ -359,6 +398,7 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter) | |||
359 | spin_lock_init(&adapter->int_lock); | 398 | spin_lock_init(&adapter->int_lock); |
360 | spin_lock_init(&adapter->main_proc_lock); | 399 | spin_lock_init(&adapter->main_proc_lock); |
361 | spin_lock_init(&adapter->mwifiex_cmd_lock); | 400 | spin_lock_init(&adapter->mwifiex_cmd_lock); |
401 | spin_lock_init(&adapter->queue_lock); | ||
362 | for (i = 0; i < adapter->priv_num; i++) { | 402 | for (i = 0; i < adapter->priv_num; i++) { |
363 | if (adapter->priv[i]) { | 403 | if (adapter->priv[i]) { |
364 | priv = adapter->priv[i]; | 404 | priv = adapter->priv[i]; |
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 67e6db7d672d..84be196188cc 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c | |||
@@ -401,7 +401,7 @@ mwifiex_fill_buffer(struct sk_buff *skb) | |||
401 | static int | 401 | static int |
402 | mwifiex_open(struct net_device *dev) | 402 | mwifiex_open(struct net_device *dev) |
403 | { | 403 | { |
404 | netif_start_queue(dev); | 404 | netif_tx_start_all_queues(dev); |
405 | return 0; | 405 | return 0; |
406 | } | 406 | } |
407 | 407 | ||
@@ -465,8 +465,8 @@ mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
465 | atomic_inc(&priv->adapter->tx_pending); | 465 | atomic_inc(&priv->adapter->tx_pending); |
466 | 466 | ||
467 | if (atomic_read(&priv->adapter->tx_pending) >= MAX_TX_PENDING) { | 467 | if (atomic_read(&priv->adapter->tx_pending) >= MAX_TX_PENDING) { |
468 | netif_stop_queue(priv->netdev); | 468 | mwifiex_set_trans_start(dev); |
469 | dev->trans_start = jiffies; | 469 | mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter); |
470 | } | 470 | } |
471 | 471 | ||
472 | queue_work(priv->adapter->workqueue, &priv->adapter->main_work); | 472 | queue_work(priv->adapter->workqueue, &priv->adapter->main_work); |
@@ -533,7 +533,7 @@ mwifiex_tx_timeout(struct net_device *dev) | |||
533 | 533 | ||
534 | dev_err(priv->adapter->dev, "%lu : Tx timeout, bss_index=%d\n", | 534 | dev_err(priv->adapter->dev, "%lu : Tx timeout, bss_index=%d\n", |
535 | jiffies, priv->bss_index); | 535 | jiffies, priv->bss_index); |
536 | dev->trans_start = jiffies; | 536 | mwifiex_set_trans_start(dev); |
537 | priv->num_tx_timeout++; | 537 | priv->num_tx_timeout++; |
538 | } | 538 | } |
539 | 539 | ||
@@ -586,8 +586,6 @@ void mwifiex_init_priv_params(struct mwifiex_private *priv, | |||
586 | priv->media_connected = false; | 586 | priv->media_connected = false; |
587 | memset(&priv->nick_name, 0, sizeof(priv->nick_name)); | 587 | memset(&priv->nick_name, 0, sizeof(priv->nick_name)); |
588 | priv->num_tx_timeout = 0; | 588 | priv->num_tx_timeout = 0; |
589 | priv->workqueue = create_singlethread_workqueue("cfg80211_wq"); | ||
590 | INIT_WORK(&priv->cfg_workqueue, mwifiex_cfg80211_results); | ||
591 | memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN); | 589 | memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN); |
592 | } | 590 | } |
593 | 591 | ||
@@ -793,7 +791,8 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem) | |||
793 | priv = adapter->priv[i]; | 791 | priv = adapter->priv[i]; |
794 | if (priv && priv->netdev) { | 792 | if (priv && priv->netdev) { |
795 | if (!netif_queue_stopped(priv->netdev)) | 793 | if (!netif_queue_stopped(priv->netdev)) |
796 | netif_stop_queue(priv->netdev); | 794 | mwifiex_stop_net_dev_queue(priv->netdev, |
795 | adapter); | ||
797 | if (netif_carrier_ok(priv->netdev)) | 796 | if (netif_carrier_ok(priv->netdev)) |
798 | netif_carrier_off(priv->netdev); | 797 | netif_carrier_off(priv->netdev); |
799 | } | 798 | } |
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 3861a617c0e1..9207fc64641e 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h | |||
@@ -453,15 +453,8 @@ struct mwifiex_private { | |||
453 | u8 scan_pending_on_block; | 453 | u8 scan_pending_on_block; |
454 | u8 report_scan_result; | 454 | u8 report_scan_result; |
455 | struct cfg80211_scan_request *scan_request; | 455 | struct cfg80211_scan_request *scan_request; |
456 | int scan_result_status; | 456 | struct mwifiex_user_scan_cfg *user_scan_cfg; |
457 | int assoc_request; | ||
458 | u16 assoc_result; | ||
459 | int ibss_join_request; | ||
460 | u16 ibss_join_result; | ||
461 | bool disconnect; | ||
462 | u8 cfg_bssid[6]; | 457 | u8 cfg_bssid[6]; |
463 | struct workqueue_struct *workqueue; | ||
464 | struct work_struct cfg_workqueue; | ||
465 | u8 country_code[IEEE80211_COUNTRY_STRING_LEN]; | 458 | u8 country_code[IEEE80211_COUNTRY_STRING_LEN]; |
466 | struct wps wps; | 459 | struct wps wps; |
467 | u8 scan_block; | 460 | u8 scan_block; |
@@ -655,10 +648,19 @@ struct mwifiex_adapter { | |||
655 | struct mwifiex_wait_queue cmd_wait_q; | 648 | struct mwifiex_wait_queue cmd_wait_q; |
656 | u8 scan_wait_q_woken; | 649 | u8 scan_wait_q_woken; |
657 | struct cmd_ctrl_node *cmd_queued; | 650 | struct cmd_ctrl_node *cmd_queued; |
651 | spinlock_t queue_lock; /* lock for tx queues */ | ||
658 | }; | 652 | }; |
659 | 653 | ||
660 | int mwifiex_init_lock_list(struct mwifiex_adapter *adapter); | 654 | int mwifiex_init_lock_list(struct mwifiex_adapter *adapter); |
661 | 655 | ||
656 | void mwifiex_set_trans_start(struct net_device *dev); | ||
657 | |||
658 | void mwifiex_stop_net_dev_queue(struct net_device *netdev, | ||
659 | struct mwifiex_adapter *adapter); | ||
660 | |||
661 | void mwifiex_wake_up_net_dev_queue(struct net_device *netdev, | ||
662 | struct mwifiex_adapter *adapter); | ||
663 | |||
662 | int mwifiex_init_fw(struct mwifiex_adapter *adapter); | 664 | int mwifiex_init_fw(struct mwifiex_adapter *adapter); |
663 | 665 | ||
664 | int mwifiex_init_fw_complete(struct mwifiex_adapter *adapter); | 666 | int mwifiex_init_fw_complete(struct mwifiex_adapter *adapter); |
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c index a2f32008f9a8..405350940a45 100644 --- a/drivers/net/wireless/mwifiex/pcie.c +++ b/drivers/net/wireless/mwifiex/pcie.c | |||
@@ -386,7 +386,7 @@ static int mwifiex_pcie_create_txbd_ring(struct mwifiex_adapter *adapter) | |||
386 | card->txbd_ring_vbase = kzalloc(card->txbd_ring_size, GFP_KERNEL); | 386 | card->txbd_ring_vbase = kzalloc(card->txbd_ring_size, GFP_KERNEL); |
387 | if (!card->txbd_ring_vbase) { | 387 | if (!card->txbd_ring_vbase) { |
388 | dev_err(adapter->dev, "Unable to allocate buffer for txbd ring.\n"); | 388 | dev_err(adapter->dev, "Unable to allocate buffer for txbd ring.\n"); |
389 | return -1; | 389 | return -ENOMEM; |
390 | } | 390 | } |
391 | card->txbd_ring_pbase = virt_to_phys(card->txbd_ring_vbase); | 391 | card->txbd_ring_pbase = virt_to_phys(card->txbd_ring_vbase); |
392 | 392 | ||
@@ -476,7 +476,7 @@ static int mwifiex_pcie_create_rxbd_ring(struct mwifiex_adapter *adapter) | |||
476 | if (!card->rxbd_ring_vbase) { | 476 | if (!card->rxbd_ring_vbase) { |
477 | dev_err(adapter->dev, "Unable to allocate buffer for " | 477 | dev_err(adapter->dev, "Unable to allocate buffer for " |
478 | "rxbd_ring.\n"); | 478 | "rxbd_ring.\n"); |
479 | return -1; | 479 | return -ENOMEM; |
480 | } | 480 | } |
481 | card->rxbd_ring_pbase = virt_to_phys(card->rxbd_ring_vbase); | 481 | card->rxbd_ring_pbase = virt_to_phys(card->rxbd_ring_vbase); |
482 | 482 | ||
@@ -569,7 +569,7 @@ static int mwifiex_pcie_create_evtbd_ring(struct mwifiex_adapter *adapter) | |||
569 | if (!card->evtbd_ring_vbase) { | 569 | if (!card->evtbd_ring_vbase) { |
570 | dev_err(adapter->dev, "Unable to allocate buffer. " | 570 | dev_err(adapter->dev, "Unable to allocate buffer. " |
571 | "Terminating download\n"); | 571 | "Terminating download\n"); |
572 | return -1; | 572 | return -ENOMEM; |
573 | } | 573 | } |
574 | card->evtbd_ring_pbase = virt_to_phys(card->evtbd_ring_vbase); | 574 | card->evtbd_ring_pbase = virt_to_phys(card->evtbd_ring_vbase); |
575 | 575 | ||
@@ -1231,15 +1231,13 @@ static int mwifiex_pcie_event_complete(struct mwifiex_adapter *adapter, | |||
1231 | if (rdptr >= MWIFIEX_MAX_EVT_BD) { | 1231 | if (rdptr >= MWIFIEX_MAX_EVT_BD) { |
1232 | dev_err(adapter->dev, "event_complete: Invalid rdptr 0x%x\n", | 1232 | dev_err(adapter->dev, "event_complete: Invalid rdptr 0x%x\n", |
1233 | rdptr); | 1233 | rdptr); |
1234 | ret = -EINVAL; | 1234 | return -EINVAL; |
1235 | goto done; | ||
1236 | } | 1235 | } |
1237 | 1236 | ||
1238 | /* Read the event ring write pointer set by firmware */ | 1237 | /* Read the event ring write pointer set by firmware */ |
1239 | if (mwifiex_read_reg(adapter, REG_EVTBD_WRPTR, &wrptr)) { | 1238 | if (mwifiex_read_reg(adapter, REG_EVTBD_WRPTR, &wrptr)) { |
1240 | dev_err(adapter->dev, "event_complete: failed to read REG_EVTBD_WRPTR\n"); | 1239 | dev_err(adapter->dev, "event_complete: failed to read REG_EVTBD_WRPTR\n"); |
1241 | ret = -1; | 1240 | return -1; |
1242 | goto done; | ||
1243 | } | 1241 | } |
1244 | 1242 | ||
1245 | if (!card->evt_buf_list[rdptr]) { | 1243 | if (!card->evt_buf_list[rdptr]) { |
@@ -1268,15 +1266,9 @@ static int mwifiex_pcie_event_complete(struct mwifiex_adapter *adapter, | |||
1268 | /* Write the event ring read pointer in to REG_EVTBD_RDPTR */ | 1266 | /* Write the event ring read pointer in to REG_EVTBD_RDPTR */ |
1269 | if (mwifiex_write_reg(adapter, REG_EVTBD_RDPTR, card->evtbd_rdptr)) { | 1267 | if (mwifiex_write_reg(adapter, REG_EVTBD_RDPTR, card->evtbd_rdptr)) { |
1270 | dev_err(adapter->dev, "event_complete: failed to read REG_EVTBD_RDPTR\n"); | 1268 | dev_err(adapter->dev, "event_complete: failed to read REG_EVTBD_RDPTR\n"); |
1271 | ret = -1; | 1269 | return -1; |
1272 | goto done; | ||
1273 | } | 1270 | } |
1274 | 1271 | ||
1275 | done: | ||
1276 | /* Free the buffer for failure case */ | ||
1277 | if (ret && skb) | ||
1278 | dev_kfree_skb_any(skb); | ||
1279 | |||
1280 | dev_dbg(adapter->dev, "info: Check Events Again\n"); | 1272 | dev_dbg(adapter->dev, "info: Check Events Again\n"); |
1281 | ret = mwifiex_pcie_process_event_ready(adapter); | 1273 | ret = mwifiex_pcie_process_event_ready(adapter); |
1282 | 1274 | ||
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index b8b9d37b01a9..e2e715666bca 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c | |||
@@ -1391,11 +1391,8 @@ int mwifiex_set_user_scan_ioctl(struct mwifiex_private *priv, | |||
1391 | { | 1391 | { |
1392 | int status; | 1392 | int status; |
1393 | 1393 | ||
1394 | priv->adapter->scan_wait_q_woken = false; | ||
1395 | |||
1396 | status = mwifiex_scan_networks(priv, scan_req); | 1394 | status = mwifiex_scan_networks(priv, scan_req); |
1397 | if (!status) | 1395 | queue_work(priv->adapter->workqueue, &priv->adapter->main_work); |
1398 | status = mwifiex_wait_queue_complete(priv->adapter); | ||
1399 | 1396 | ||
1400 | return status; | 1397 | return status; |
1401 | } | 1398 | } |
@@ -1796,6 +1793,14 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, | |||
1796 | up(&priv->async_sem); | 1793 | up(&priv->async_sem); |
1797 | } | 1794 | } |
1798 | 1795 | ||
1796 | if (priv->user_scan_cfg) { | ||
1797 | dev_dbg(priv->adapter->dev, "info: %s: sending scan " | ||
1798 | "results\n", __func__); | ||
1799 | cfg80211_scan_done(priv->scan_request, 0); | ||
1800 | priv->scan_request = NULL; | ||
1801 | kfree(priv->user_scan_cfg); | ||
1802 | priv->user_scan_cfg = NULL; | ||
1803 | } | ||
1799 | } else { | 1804 | } else { |
1800 | /* Get scan command from scan_pending_q and put to | 1805 | /* Get scan command from scan_pending_q and put to |
1801 | cmd_pending_q */ | 1806 | cmd_pending_q */ |
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index 702452b505c3..d39d8457f252 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c | |||
@@ -1087,7 +1087,7 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter, | |||
1087 | (adapter->ioport | 0x1000 | | 1087 | (adapter->ioport | 0x1000 | |
1088 | (card->mpa_rx.ports << 4)) + | 1088 | (card->mpa_rx.ports << 4)) + |
1089 | card->mpa_rx.start_port, 1)) | 1089 | card->mpa_rx.start_port, 1)) |
1090 | return -1; | 1090 | goto error; |
1091 | 1091 | ||
1092 | curr_ptr = card->mpa_rx.buf; | 1092 | curr_ptr = card->mpa_rx.buf; |
1093 | 1093 | ||
@@ -1130,12 +1130,29 @@ rx_curr_single: | |||
1130 | if (mwifiex_sdio_card_to_host(adapter, &pkt_type, | 1130 | if (mwifiex_sdio_card_to_host(adapter, &pkt_type, |
1131 | skb->data, skb->len, | 1131 | skb->data, skb->len, |
1132 | adapter->ioport + port)) | 1132 | adapter->ioport + port)) |
1133 | return -1; | 1133 | goto error; |
1134 | 1134 | ||
1135 | mwifiex_decode_rx_packet(adapter, skb, pkt_type); | 1135 | mwifiex_decode_rx_packet(adapter, skb, pkt_type); |
1136 | } | 1136 | } |
1137 | 1137 | ||
1138 | return 0; | 1138 | return 0; |
1139 | |||
1140 | error: | ||
1141 | if (MP_RX_AGGR_IN_PROGRESS(card)) { | ||
1142 | /* Multiport-aggregation transfer failed - cleanup */ | ||
1143 | for (pind = 0; pind < card->mpa_rx.pkt_cnt; pind++) { | ||
1144 | /* copy pkt to deaggr buf */ | ||
1145 | skb_deaggr = card->mpa_rx.skb_arr[pind]; | ||
1146 | dev_kfree_skb_any(skb_deaggr); | ||
1147 | } | ||
1148 | MP_RX_AGGR_BUF_RESET(card); | ||
1149 | } | ||
1150 | |||
1151 | if (f_do_rx_cur) | ||
1152 | /* Single transfer pending. Free curr buff also */ | ||
1153 | dev_kfree_skb_any(skb); | ||
1154 | |||
1155 | return -1; | ||
1139 | } | 1156 | } |
1140 | 1157 | ||
1141 | /* | 1158 | /* |
@@ -1271,7 +1288,6 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) | |||
1271 | 1288 | ||
1272 | dev_dbg(adapter->dev, | 1289 | dev_dbg(adapter->dev, |
1273 | "info: CFG reg val =%x\n", cr); | 1290 | "info: CFG reg val =%x\n", cr); |
1274 | dev_kfree_skb_any(skb); | ||
1275 | return -1; | 1291 | return -1; |
1276 | } | 1292 | } |
1277 | } | 1293 | } |
diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c index f204810e8338..d7aa21da84d0 100644 --- a/drivers/net/wireless/mwifiex/sta_event.c +++ b/drivers/net/wireless/mwifiex/sta_event.c | |||
@@ -115,18 +115,17 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv) | |||
115 | if (adapter->num_cmd_timeout && adapter->curr_cmd) | 115 | if (adapter->num_cmd_timeout && adapter->curr_cmd) |
116 | return; | 116 | return; |
117 | priv->media_connected = false; | 117 | priv->media_connected = false; |
118 | if (!priv->disconnect) { | 118 | dev_dbg(adapter->dev, "info: successfully disconnected from" |
119 | priv->disconnect = 1; | 119 | " %pM: reason code %d\n", priv->cfg_bssid, |
120 | dev_dbg(adapter->dev, "info: successfully disconnected from" | 120 | WLAN_REASON_DEAUTH_LEAVING); |
121 | " %pM: reason code %d\n", priv->cfg_bssid, | 121 | if (priv->bss_mode == NL80211_IFTYPE_STATION) { |
122 | WLAN_REASON_DEAUTH_LEAVING); | 122 | cfg80211_disconnected(priv->netdev, WLAN_REASON_DEAUTH_LEAVING, |
123 | cfg80211_disconnected(priv->netdev, | 123 | NULL, 0, GFP_KERNEL); |
124 | WLAN_REASON_DEAUTH_LEAVING, NULL, 0, | ||
125 | GFP_KERNEL); | ||
126 | queue_work(priv->workqueue, &priv->cfg_workqueue); | ||
127 | } | 124 | } |
125 | memset(priv->cfg_bssid, 0, ETH_ALEN); | ||
126 | |||
128 | if (!netif_queue_stopped(priv->netdev)) | 127 | if (!netif_queue_stopped(priv->netdev)) |
129 | netif_stop_queue(priv->netdev); | 128 | mwifiex_stop_net_dev_queue(priv->netdev, adapter); |
130 | if (netif_carrier_ok(priv->netdev)) | 129 | if (netif_carrier_ok(priv->netdev)) |
131 | netif_carrier_off(priv->netdev); | 130 | netif_carrier_off(priv->netdev); |
132 | /* Reset wireless stats signal info */ | 131 | /* Reset wireless stats signal info */ |
@@ -201,7 +200,7 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) | |||
201 | if (!netif_carrier_ok(priv->netdev)) | 200 | if (!netif_carrier_ok(priv->netdev)) |
202 | netif_carrier_on(priv->netdev); | 201 | netif_carrier_on(priv->netdev); |
203 | if (netif_queue_stopped(priv->netdev)) | 202 | if (netif_queue_stopped(priv->netdev)) |
204 | netif_wake_queue(priv->netdev); | 203 | mwifiex_wake_up_net_dev_queue(priv->netdev, adapter); |
205 | break; | 204 | break; |
206 | 205 | ||
207 | case EVENT_DEAUTHENTICATED: | 206 | case EVENT_DEAUTHENTICATED: |
@@ -292,7 +291,7 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) | |||
292 | priv->adhoc_is_link_sensed = false; | 291 | priv->adhoc_is_link_sensed = false; |
293 | mwifiex_clean_txrx(priv); | 292 | mwifiex_clean_txrx(priv); |
294 | if (!netif_queue_stopped(priv->netdev)) | 293 | if (!netif_queue_stopped(priv->netdev)) |
295 | netif_stop_queue(priv->netdev); | 294 | mwifiex_stop_net_dev_queue(priv->netdev, adapter); |
296 | if (netif_carrier_ok(priv->netdev)) | 295 | if (netif_carrier_ok(priv->netdev)) |
297 | netif_carrier_off(priv->netdev); | 296 | netif_carrier_off(priv->netdev); |
298 | break; | 297 | break; |
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 4b6f5539657d..6d990c798a20 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c | |||
@@ -234,7 +234,7 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, | |||
234 | "associating...\n"); | 234 | "associating...\n"); |
235 | 235 | ||
236 | if (!netif_queue_stopped(priv->netdev)) | 236 | if (!netif_queue_stopped(priv->netdev)) |
237 | netif_stop_queue(priv->netdev); | 237 | mwifiex_stop_net_dev_queue(priv->netdev, adapter); |
238 | 238 | ||
239 | /* Clear any past association response stored for | 239 | /* Clear any past association response stored for |
240 | * application retrieval */ | 240 | * application retrieval */ |
@@ -265,7 +265,7 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, | |||
265 | ret = mwifiex_check_network_compatibility(priv, bss_desc); | 265 | ret = mwifiex_check_network_compatibility(priv, bss_desc); |
266 | 266 | ||
267 | if (!netif_queue_stopped(priv->netdev)) | 267 | if (!netif_queue_stopped(priv->netdev)) |
268 | netif_stop_queue(priv->netdev); | 268 | mwifiex_stop_net_dev_queue(priv->netdev, adapter); |
269 | 269 | ||
270 | if (!ret) { | 270 | if (!ret) { |
271 | dev_dbg(adapter->dev, "info: network found in scan" | 271 | dev_dbg(adapter->dev, "info: network found in scan" |
diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c index a206f412875f..d9274a1b77ac 100644 --- a/drivers/net/wireless/mwifiex/txrx.c +++ b/drivers/net/wireless/mwifiex/txrx.c | |||
@@ -134,7 +134,7 @@ int mwifiex_write_data_complete(struct mwifiex_adapter *adapter, | |||
134 | if (!priv) | 134 | if (!priv) |
135 | goto done; | 135 | goto done; |
136 | 136 | ||
137 | priv->netdev->trans_start = jiffies; | 137 | mwifiex_set_trans_start(priv->netdev); |
138 | if (!status) { | 138 | if (!status) { |
139 | priv->stats.tx_packets++; | 139 | priv->stats.tx_packets++; |
140 | priv->stats.tx_bytes += skb->len; | 140 | priv->stats.tx_bytes += skb->len; |
@@ -152,7 +152,8 @@ int mwifiex_write_data_complete(struct mwifiex_adapter *adapter, | |||
152 | if ((GET_BSS_ROLE(tpriv) == MWIFIEX_BSS_ROLE_STA) | 152 | if ((GET_BSS_ROLE(tpriv) == MWIFIEX_BSS_ROLE_STA) |
153 | && (tpriv->media_connected)) { | 153 | && (tpriv->media_connected)) { |
154 | if (netif_queue_stopped(tpriv->netdev)) | 154 | if (netif_queue_stopped(tpriv->netdev)) |
155 | netif_wake_queue(tpriv->netdev); | 155 | mwifiex_wake_up_net_dev_queue(tpriv->netdev, |
156 | adapter); | ||
156 | } | 157 | } |
157 | } | 158 | } |
158 | done: | 159 | done: |
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index bf0acff07807..ede3c58e6783 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
@@ -160,7 +160,7 @@ void rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
160 | exit_fail: | 160 | exit_fail: |
161 | rt2x00queue_pause_queue(queue); | 161 | rt2x00queue_pause_queue(queue); |
162 | exit_free_skb: | 162 | exit_free_skb: |
163 | dev_kfree_skb_any(skb); | 163 | ieee80211_free_txskb(hw, skb); |
164 | } | 164 | } |
165 | EXPORT_SYMBOL_GPL(rt2x00mac_tx); | 165 | EXPORT_SYMBOL_GPL(rt2x00mac_tx); |
166 | 166 | ||
diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c index a13ecfce4825..d81a6021a30f 100644 --- a/drivers/net/wireless/rtlwifi/base.c +++ b/drivers/net/wireless/rtlwifi/base.c | |||
@@ -448,12 +448,11 @@ int rtl_init_core(struct ieee80211_hw *hw) | |||
448 | 448 | ||
449 | /* <4> locks */ | 449 | /* <4> locks */ |
450 | mutex_init(&rtlpriv->locks.conf_mutex); | 450 | mutex_init(&rtlpriv->locks.conf_mutex); |
451 | spin_lock_init(&rtlpriv->locks.ips_lock); | 451 | mutex_init(&rtlpriv->locks.ps_mutex); |
452 | spin_lock_init(&rtlpriv->locks.irq_th_lock); | 452 | spin_lock_init(&rtlpriv->locks.irq_th_lock); |
453 | spin_lock_init(&rtlpriv->locks.h2c_lock); | 453 | spin_lock_init(&rtlpriv->locks.h2c_lock); |
454 | spin_lock_init(&rtlpriv->locks.rf_ps_lock); | 454 | spin_lock_init(&rtlpriv->locks.rf_ps_lock); |
455 | spin_lock_init(&rtlpriv->locks.rf_lock); | 455 | spin_lock_init(&rtlpriv->locks.rf_lock); |
456 | spin_lock_init(&rtlpriv->locks.lps_lock); | ||
457 | spin_lock_init(&rtlpriv->locks.waitq_lock); | 456 | spin_lock_init(&rtlpriv->locks.waitq_lock); |
458 | spin_lock_init(&rtlpriv->locks.cck_and_rw_pagea_lock); | 457 | spin_lock_init(&rtlpriv->locks.cck_and_rw_pagea_lock); |
459 | 458 | ||
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 91f0525364ea..0d4d242849b4 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c | |||
@@ -610,7 +610,7 @@ tx_status_ok: | |||
610 | if (((rtlpriv->link_info.num_rx_inperiod + | 610 | if (((rtlpriv->link_info.num_rx_inperiod + |
611 | rtlpriv->link_info.num_tx_inperiod) > 8) || | 611 | rtlpriv->link_info.num_tx_inperiod) > 8) || |
612 | (rtlpriv->link_info.num_rx_inperiod > 2)) { | 612 | (rtlpriv->link_info.num_rx_inperiod > 2)) { |
613 | tasklet_schedule(&rtlpriv->works.ips_leave_tasklet); | 613 | schedule_work(&rtlpriv->works.lps_leave_work); |
614 | } | 614 | } |
615 | } | 615 | } |
616 | 616 | ||
@@ -736,7 +736,7 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) | |||
736 | if (((rtlpriv->link_info.num_rx_inperiod + | 736 | if (((rtlpriv->link_info.num_rx_inperiod + |
737 | rtlpriv->link_info.num_tx_inperiod) > 8) || | 737 | rtlpriv->link_info.num_tx_inperiod) > 8) || |
738 | (rtlpriv->link_info.num_rx_inperiod > 2)) { | 738 | (rtlpriv->link_info.num_rx_inperiod > 2)) { |
739 | tasklet_schedule(&rtlpriv->works.ips_leave_tasklet); | 739 | schedule_work(&rtlpriv->works.lps_leave_work); |
740 | } | 740 | } |
741 | 741 | ||
742 | dev_kfree_skb_any(skb); | 742 | dev_kfree_skb_any(skb); |
@@ -903,11 +903,6 @@ static void _rtl_pci_irq_tasklet(struct ieee80211_hw *hw) | |||
903 | _rtl_pci_tx_chk_waitq(hw); | 903 | _rtl_pci_tx_chk_waitq(hw); |
904 | } | 904 | } |
905 | 905 | ||
906 | static void _rtl_pci_ips_leave_tasklet(struct ieee80211_hw *hw) | ||
907 | { | ||
908 | rtl_lps_leave(hw); | ||
909 | } | ||
910 | |||
911 | static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw) | 906 | static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw) |
912 | { | 907 | { |
913 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 908 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
@@ -945,6 +940,15 @@ static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw) | |||
945 | return; | 940 | return; |
946 | } | 941 | } |
947 | 942 | ||
943 | static void rtl_lps_leave_work_callback(struct work_struct *work) | ||
944 | { | ||
945 | struct rtl_works *rtlworks = | ||
946 | container_of(work, struct rtl_works, lps_leave_work); | ||
947 | struct ieee80211_hw *hw = rtlworks->hw; | ||
948 | |||
949 | rtl_lps_leave(hw); | ||
950 | } | ||
951 | |||
948 | static void _rtl_pci_init_trx_var(struct ieee80211_hw *hw) | 952 | static void _rtl_pci_init_trx_var(struct ieee80211_hw *hw) |
949 | { | 953 | { |
950 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | 954 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); |
@@ -1006,9 +1010,7 @@ static void _rtl_pci_init_struct(struct ieee80211_hw *hw, | |||
1006 | tasklet_init(&rtlpriv->works.irq_prepare_bcn_tasklet, | 1010 | tasklet_init(&rtlpriv->works.irq_prepare_bcn_tasklet, |
1007 | (void (*)(unsigned long))_rtl_pci_prepare_bcn_tasklet, | 1011 | (void (*)(unsigned long))_rtl_pci_prepare_bcn_tasklet, |
1008 | (unsigned long)hw); | 1012 | (unsigned long)hw); |
1009 | tasklet_init(&rtlpriv->works.ips_leave_tasklet, | 1013 | INIT_WORK(&rtlpriv->works.lps_leave_work, rtl_lps_leave_work_callback); |
1010 | (void (*)(unsigned long))_rtl_pci_ips_leave_tasklet, | ||
1011 | (unsigned long)hw); | ||
1012 | } | 1014 | } |
1013 | 1015 | ||
1014 | static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw, | 1016 | static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw, |
@@ -1478,7 +1480,7 @@ static void rtl_pci_deinit(struct ieee80211_hw *hw) | |||
1478 | 1480 | ||
1479 | synchronize_irq(rtlpci->pdev->irq); | 1481 | synchronize_irq(rtlpci->pdev->irq); |
1480 | tasklet_kill(&rtlpriv->works.irq_tasklet); | 1482 | tasklet_kill(&rtlpriv->works.irq_tasklet); |
1481 | tasklet_kill(&rtlpriv->works.ips_leave_tasklet); | 1483 | cancel_work_sync(&rtlpriv->works.lps_leave_work); |
1482 | 1484 | ||
1483 | flush_workqueue(rtlpriv->works.rtl_wq); | 1485 | flush_workqueue(rtlpriv->works.rtl_wq); |
1484 | destroy_workqueue(rtlpriv->works.rtl_wq); | 1486 | destroy_workqueue(rtlpriv->works.rtl_wq); |
@@ -1553,7 +1555,7 @@ static void rtl_pci_stop(struct ieee80211_hw *hw) | |||
1553 | set_hal_stop(rtlhal); | 1555 | set_hal_stop(rtlhal); |
1554 | 1556 | ||
1555 | rtlpriv->cfg->ops->disable_interrupt(hw); | 1557 | rtlpriv->cfg->ops->disable_interrupt(hw); |
1556 | tasklet_kill(&rtlpriv->works.ips_leave_tasklet); | 1558 | cancel_work_sync(&rtlpriv->works.lps_leave_work); |
1557 | 1559 | ||
1558 | spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags); | 1560 | spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags); |
1559 | while (ppsc->rfchange_inprogress) { | 1561 | while (ppsc->rfchange_inprogress) { |
diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c index 55c8e50f45fd..a14a68b24635 100644 --- a/drivers/net/wireless/rtlwifi/ps.c +++ b/drivers/net/wireless/rtlwifi/ps.c | |||
@@ -241,7 +241,7 @@ void rtl_ips_nic_on(struct ieee80211_hw *hw) | |||
241 | if (mac->opmode != NL80211_IFTYPE_STATION) | 241 | if (mac->opmode != NL80211_IFTYPE_STATION) |
242 | return; | 242 | return; |
243 | 243 | ||
244 | spin_lock(&rtlpriv->locks.ips_lock); | 244 | mutex_lock(&rtlpriv->locks.ps_mutex); |
245 | 245 | ||
246 | if (ppsc->inactiveps) { | 246 | if (ppsc->inactiveps) { |
247 | rtstate = ppsc->rfpwr_state; | 247 | rtstate = ppsc->rfpwr_state; |
@@ -257,7 +257,7 @@ void rtl_ips_nic_on(struct ieee80211_hw *hw) | |||
257 | } | 257 | } |
258 | } | 258 | } |
259 | 259 | ||
260 | spin_unlock(&rtlpriv->locks.ips_lock); | 260 | mutex_unlock(&rtlpriv->locks.ps_mutex); |
261 | } | 261 | } |
262 | 262 | ||
263 | /*for FW LPS*/ | 263 | /*for FW LPS*/ |
@@ -395,7 +395,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw) | |||
395 | if (mac->link_state != MAC80211_LINKED) | 395 | if (mac->link_state != MAC80211_LINKED) |
396 | return; | 396 | return; |
397 | 397 | ||
398 | spin_lock_irq(&rtlpriv->locks.lps_lock); | 398 | mutex_lock(&rtlpriv->locks.ps_mutex); |
399 | 399 | ||
400 | /* Idle for a while if we connect to AP a while ago. */ | 400 | /* Idle for a while if we connect to AP a while ago. */ |
401 | if (mac->cnt_after_linked >= 2) { | 401 | if (mac->cnt_after_linked >= 2) { |
@@ -407,7 +407,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw) | |||
407 | } | 407 | } |
408 | } | 408 | } |
409 | 409 | ||
410 | spin_unlock_irq(&rtlpriv->locks.lps_lock); | 410 | mutex_unlock(&rtlpriv->locks.ps_mutex); |
411 | } | 411 | } |
412 | 412 | ||
413 | /*Leave the leisure power save mode.*/ | 413 | /*Leave the leisure power save mode.*/ |
@@ -416,9 +416,8 @@ void rtl_lps_leave(struct ieee80211_hw *hw) | |||
416 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 416 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
417 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | 417 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); |
418 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | 418 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
419 | unsigned long flags; | ||
420 | 419 | ||
421 | spin_lock_irqsave(&rtlpriv->locks.lps_lock, flags); | 420 | mutex_lock(&rtlpriv->locks.ps_mutex); |
422 | 421 | ||
423 | if (ppsc->fwctrl_lps) { | 422 | if (ppsc->fwctrl_lps) { |
424 | if (ppsc->dot11_psmode != EACTIVE) { | 423 | if (ppsc->dot11_psmode != EACTIVE) { |
@@ -439,7 +438,7 @@ void rtl_lps_leave(struct ieee80211_hw *hw) | |||
439 | rtl_lps_set_psmode(hw, EACTIVE); | 438 | rtl_lps_set_psmode(hw, EACTIVE); |
440 | } | 439 | } |
441 | } | 440 | } |
442 | spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flags); | 441 | mutex_unlock(&rtlpriv->locks.ps_mutex); |
443 | } | 442 | } |
444 | 443 | ||
445 | /* For sw LPS*/ | 444 | /* For sw LPS*/ |
@@ -540,9 +539,9 @@ void rtl_swlps_rf_awake(struct ieee80211_hw *hw) | |||
540 | RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); | 539 | RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); |
541 | } | 540 | } |
542 | 541 | ||
543 | spin_lock_irq(&rtlpriv->locks.lps_lock); | 542 | mutex_lock(&rtlpriv->locks.ps_mutex); |
544 | rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS); | 543 | rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS); |
545 | spin_unlock_irq(&rtlpriv->locks.lps_lock); | 544 | mutex_unlock(&rtlpriv->locks.ps_mutex); |
546 | } | 545 | } |
547 | 546 | ||
548 | void rtl_swlps_rfon_wq_callback(void *data) | 547 | void rtl_swlps_rfon_wq_callback(void *data) |
@@ -575,9 +574,9 @@ void rtl_swlps_rf_sleep(struct ieee80211_hw *hw) | |||
575 | if (rtlpriv->link_info.busytraffic) | 574 | if (rtlpriv->link_info.busytraffic) |
576 | return; | 575 | return; |
577 | 576 | ||
578 | spin_lock_irq(&rtlpriv->locks.lps_lock); | 577 | mutex_lock(&rtlpriv->locks.ps_mutex); |
579 | rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS); | 578 | rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS); |
580 | spin_unlock_irq(&rtlpriv->locks.lps_lock); | 579 | mutex_unlock(&rtlpriv->locks.ps_mutex); |
581 | 580 | ||
582 | if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM && | 581 | if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM && |
583 | !RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) { | 582 | !RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) { |
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index f3c132b55d42..085dccdbd1b6 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h | |||
@@ -1544,14 +1544,13 @@ struct rtl_hal_cfg { | |||
1544 | struct rtl_locks { | 1544 | struct rtl_locks { |
1545 | /* mutex */ | 1545 | /* mutex */ |
1546 | struct mutex conf_mutex; | 1546 | struct mutex conf_mutex; |
1547 | struct mutex ps_mutex; | ||
1547 | 1548 | ||
1548 | /*spin lock */ | 1549 | /*spin lock */ |
1549 | spinlock_t ips_lock; | ||
1550 | spinlock_t irq_th_lock; | 1550 | spinlock_t irq_th_lock; |
1551 | spinlock_t h2c_lock; | 1551 | spinlock_t h2c_lock; |
1552 | spinlock_t rf_ps_lock; | 1552 | spinlock_t rf_ps_lock; |
1553 | spinlock_t rf_lock; | 1553 | spinlock_t rf_lock; |
1554 | spinlock_t lps_lock; | ||
1555 | spinlock_t waitq_lock; | 1554 | spinlock_t waitq_lock; |
1556 | 1555 | ||
1557 | /*Dual mac*/ | 1556 | /*Dual mac*/ |
@@ -1576,7 +1575,8 @@ struct rtl_works { | |||
1576 | /* For SW LPS */ | 1575 | /* For SW LPS */ |
1577 | struct delayed_work ps_work; | 1576 | struct delayed_work ps_work; |
1578 | struct delayed_work ps_rfon_wq; | 1577 | struct delayed_work ps_rfon_wq; |
1579 | struct tasklet_struct ips_leave_tasklet; | 1578 | |
1579 | struct work_struct lps_leave_work; | ||
1580 | }; | 1580 | }; |
1581 | 1581 | ||
1582 | struct rtl_debug { | 1582 | struct rtl_debug { |
diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index bde1d862bdd5..7537c401a448 100644 --- a/drivers/net/wireless/wl12xx/acx.c +++ b/drivers/net/wireless/wl12xx/acx.c | |||
@@ -186,32 +186,6 @@ out: | |||
186 | return ret; | 186 | return ret; |
187 | } | 187 | } |
188 | 188 | ||
189 | int wl1271_acx_pd_threshold(struct wl1271 *wl) | ||
190 | { | ||
191 | struct acx_packet_detection *pd; | ||
192 | int ret; | ||
193 | |||
194 | wl1271_debug(DEBUG_ACX, "acx data pd threshold"); | ||
195 | |||
196 | pd = kzalloc(sizeof(*pd), GFP_KERNEL); | ||
197 | if (!pd) { | ||
198 | ret = -ENOMEM; | ||
199 | goto out; | ||
200 | } | ||
201 | |||
202 | pd->threshold = cpu_to_le32(wl->conf.rx.packet_detection_threshold); | ||
203 | |||
204 | ret = wl1271_cmd_configure(wl, ACX_PD_THRESHOLD, pd, sizeof(*pd)); | ||
205 | if (ret < 0) { | ||
206 | wl1271_warning("failed to set pd threshold: %d", ret); | ||
207 | goto out; | ||
208 | } | ||
209 | |||
210 | out: | ||
211 | kfree(pd); | ||
212 | return ret; | ||
213 | } | ||
214 | |||
215 | int wl1271_acx_slot(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 189 | int wl1271_acx_slot(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
216 | enum acx_slot_type slot_time) | 190 | enum acx_slot_type slot_time) |
217 | { | 191 | { |
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h index b2d85bea6378..69892b40c2df 100644 --- a/drivers/net/wireless/wl12xx/acx.h +++ b/drivers/net/wireless/wl12xx/acx.h | |||
@@ -171,13 +171,6 @@ struct acx_rx_msdu_lifetime { | |||
171 | __le32 lifetime; | 171 | __le32 lifetime; |
172 | } __packed; | 172 | } __packed; |
173 | 173 | ||
174 | struct acx_packet_detection { | ||
175 | struct acx_header header; | ||
176 | |||
177 | __le32 threshold; | ||
178 | } __packed; | ||
179 | |||
180 | |||
181 | enum acx_slot_type { | 174 | enum acx_slot_type { |
182 | SLOT_TIME_LONG = 0, | 175 | SLOT_TIME_LONG = 0, |
183 | SLOT_TIME_SHORT = 1, | 176 | SLOT_TIME_SHORT = 1, |
@@ -1238,7 +1231,6 @@ int wl1271_acx_feature_cfg(struct wl1271 *wl, struct wl12xx_vif *wlvif); | |||
1238 | int wl1271_acx_mem_map(struct wl1271 *wl, | 1231 | int wl1271_acx_mem_map(struct wl1271 *wl, |
1239 | struct acx_header *mem_map, size_t len); | 1232 | struct acx_header *mem_map, size_t len); |
1240 | int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl); | 1233 | int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl); |
1241 | int wl1271_acx_pd_threshold(struct wl1271 *wl); | ||
1242 | int wl1271_acx_slot(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 1234 | int wl1271_acx_slot(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
1243 | enum acx_slot_type slot_time); | 1235 | enum acx_slot_type slot_time); |
1244 | int wl1271_acx_group_address_tbl(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 1236 | int wl1271_acx_group_address_tbl(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index 2e14b436101f..15eb3a9c30ca 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c | |||
@@ -317,12 +317,19 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, | |||
317 | { | 317 | { |
318 | struct wl1271 *wl = file->private_data; | 318 | struct wl1271 *wl = file->private_data; |
319 | int res = 0; | 319 | int res = 0; |
320 | char buf[1024]; | 320 | ssize_t ret; |
321 | char *buf; | ||
322 | |||
323 | #define DRIVER_STATE_BUF_LEN 1024 | ||
324 | |||
325 | buf = kmalloc(DRIVER_STATE_BUF_LEN, GFP_KERNEL); | ||
326 | if (!buf) | ||
327 | return -ENOMEM; | ||
321 | 328 | ||
322 | mutex_lock(&wl->mutex); | 329 | mutex_lock(&wl->mutex); |
323 | 330 | ||
324 | #define DRIVER_STATE_PRINT(x, fmt) \ | 331 | #define DRIVER_STATE_PRINT(x, fmt) \ |
325 | (res += scnprintf(buf + res, sizeof(buf) - res,\ | 332 | (res += scnprintf(buf + res, DRIVER_STATE_BUF_LEN - res,\ |
326 | #x " = " fmt "\n", wl->x)) | 333 | #x " = " fmt "\n", wl->x)) |
327 | 334 | ||
328 | #define DRIVER_STATE_PRINT_LONG(x) DRIVER_STATE_PRINT(x, "%ld") | 335 | #define DRIVER_STATE_PRINT_LONG(x) DRIVER_STATE_PRINT(x, "%ld") |
@@ -373,10 +380,13 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, | |||
373 | #undef DRIVER_STATE_PRINT_LHEX | 380 | #undef DRIVER_STATE_PRINT_LHEX |
374 | #undef DRIVER_STATE_PRINT_STR | 381 | #undef DRIVER_STATE_PRINT_STR |
375 | #undef DRIVER_STATE_PRINT | 382 | #undef DRIVER_STATE_PRINT |
383 | #undef DRIVER_STATE_BUF_LEN | ||
376 | 384 | ||
377 | mutex_unlock(&wl->mutex); | 385 | mutex_unlock(&wl->mutex); |
378 | 386 | ||
379 | return simple_read_from_buffer(user_buf, count, ppos, buf, res); | 387 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, res); |
388 | kfree(buf); | ||
389 | return ret; | ||
380 | } | 390 | } |
381 | 391 | ||
382 | static const struct file_operations driver_state_ops = { | 392 | static const struct file_operations driver_state_ops = { |
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index 88891cdfdd4a..ca7ee59e4505 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c | |||
@@ -223,17 +223,6 @@ static int wl12xx_init_rx_config(struct wl1271 *wl) | |||
223 | return 0; | 223 | return 0; |
224 | } | 224 | } |
225 | 225 | ||
226 | int wl1271_init_phy_config(struct wl1271 *wl) | ||
227 | { | ||
228 | int ret; | ||
229 | |||
230 | ret = wl1271_acx_pd_threshold(wl); | ||
231 | if (ret < 0) | ||
232 | return ret; | ||
233 | |||
234 | return 0; | ||
235 | } | ||
236 | |||
237 | static int wl12xx_init_phy_vif_config(struct wl1271 *wl, | 226 | static int wl12xx_init_phy_vif_config(struct wl1271 *wl, |
238 | struct wl12xx_vif *wlvif) | 227 | struct wl12xx_vif *wlvif) |
239 | { | 228 | { |
@@ -328,12 +317,6 @@ static int wl1271_sta_hw_init(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
328 | { | 317 | { |
329 | int ret; | 318 | int ret; |
330 | 319 | ||
331 | if (wl->chip.id != CHIP_ID_1283_PG20) { | ||
332 | ret = wl1271_cmd_ext_radio_parms(wl); | ||
333 | if (ret < 0) | ||
334 | return ret; | ||
335 | } | ||
336 | |||
337 | /* PS config */ | 320 | /* PS config */ |
338 | ret = wl12xx_acx_config_ps(wl, wlvif); | 321 | ret = wl12xx_acx_config_ps(wl, wlvif); |
339 | if (ret < 0) | 322 | if (ret < 0) |
@@ -659,19 +642,24 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
659 | { | 642 | { |
660 | int ret; | 643 | int ret; |
661 | 644 | ||
662 | if (wl->chip.id == CHIP_ID_1283_PG20) | 645 | if (wl->chip.id == CHIP_ID_1283_PG20) { |
663 | ret = wl128x_cmd_general_parms(wl); | 646 | ret = wl128x_cmd_general_parms(wl); |
664 | else | 647 | if (ret < 0) |
665 | ret = wl1271_cmd_general_parms(wl); | 648 | return ret; |
666 | if (ret < 0) | ||
667 | return ret; | ||
668 | |||
669 | if (wl->chip.id == CHIP_ID_1283_PG20) | ||
670 | ret = wl128x_cmd_radio_parms(wl); | 649 | ret = wl128x_cmd_radio_parms(wl); |
671 | else | 650 | if (ret < 0) |
651 | return ret; | ||
652 | } else { | ||
653 | ret = wl1271_cmd_general_parms(wl); | ||
654 | if (ret < 0) | ||
655 | return ret; | ||
672 | ret = wl1271_cmd_radio_parms(wl); | 656 | ret = wl1271_cmd_radio_parms(wl); |
673 | if (ret < 0) | 657 | if (ret < 0) |
674 | return ret; | 658 | return ret; |
659 | ret = wl1271_cmd_ext_radio_parms(wl); | ||
660 | if (ret < 0) | ||
661 | return ret; | ||
662 | } | ||
675 | 663 | ||
676 | /* Chip-specific init */ | 664 | /* Chip-specific init */ |
677 | ret = wl1271_chip_specific_init(wl); | 665 | ret = wl1271_chip_specific_init(wl); |
@@ -707,11 +695,6 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
707 | if (ret < 0) | 695 | if (ret < 0) |
708 | goto out_free_memmap; | 696 | goto out_free_memmap; |
709 | 697 | ||
710 | /* PHY layer config */ | ||
711 | ret = wl1271_init_phy_config(wl); | ||
712 | if (ret < 0) | ||
713 | goto out_free_memmap; | ||
714 | |||
715 | ret = wl1271_acx_dco_itrim_params(wl); | 698 | ret = wl1271_acx_dco_itrim_params(wl); |
716 | if (ret < 0) | 699 | if (ret < 0) |
717 | goto out_free_memmap; | 700 | goto out_free_memmap; |
diff --git a/drivers/net/wireless/wl12xx/init.h b/drivers/net/wireless/wl12xx/init.h index 81140b81f654..2da0f404ef6e 100644 --- a/drivers/net/wireless/wl12xx/init.h +++ b/drivers/net/wireless/wl12xx/init.h | |||
@@ -28,7 +28,6 @@ | |||
28 | 28 | ||
29 | int wl1271_hw_init_power_auth(struct wl1271 *wl); | 29 | int wl1271_hw_init_power_auth(struct wl1271 *wl); |
30 | int wl1271_init_templates_config(struct wl1271 *wl); | 30 | int wl1271_init_templates_config(struct wl1271 *wl); |
31 | int wl1271_init_phy_config(struct wl1271 *wl); | ||
32 | int wl1271_init_pta(struct wl1271 *wl); | 31 | int wl1271_init_pta(struct wl1271 *wl); |
33 | int wl1271_init_energy_detection(struct wl1271 *wl); | 32 | int wl1271_init_energy_detection(struct wl1271 *wl); |
34 | int wl1271_chip_specific_init(struct wl1271 *wl); | 33 | int wl1271_chip_specific_init(struct wl1271 *wl); |
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 2f7bfa86c8cd..c3058419e227 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c | |||
@@ -674,11 +674,6 @@ static int wl1271_plt_init(struct wl1271 *wl) | |||
674 | if (ret < 0) | 674 | if (ret < 0) |
675 | return ret; | 675 | return ret; |
676 | 676 | ||
677 | /* PHY layer config */ | ||
678 | ret = wl1271_init_phy_config(wl); | ||
679 | if (ret < 0) | ||
680 | goto out_free_memmap; | ||
681 | |||
682 | ret = wl12xx_acx_mem_cfg(wl); | 677 | ret = wl12xx_acx_mem_cfg(wl); |
683 | if (ret < 0) | 678 | if (ret < 0) |
684 | goto out_free_memmap; | 679 | goto out_free_memmap; |
@@ -1448,7 +1443,7 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1448 | if (hlid == WL12XX_INVALID_LINK_ID || | 1443 | if (hlid == WL12XX_INVALID_LINK_ID || |
1449 | (wlvif && !test_bit(hlid, wlvif->links_map))) { | 1444 | (wlvif && !test_bit(hlid, wlvif->links_map))) { |
1450 | wl1271_debug(DEBUG_TX, "DROP skb hlid %d q %d", hlid, q); | 1445 | wl1271_debug(DEBUG_TX, "DROP skb hlid %d q %d", hlid, q); |
1451 | dev_kfree_skb(skb); | 1446 | ieee80211_free_txskb(hw, skb); |
1452 | goto out; | 1447 | goto out; |
1453 | } | 1448 | } |
1454 | 1449 | ||
@@ -1585,24 +1580,24 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl, | |||
1585 | 1580 | ||
1586 | ret = wait_for_completion_timeout( | 1581 | ret = wait_for_completion_timeout( |
1587 | &compl, msecs_to_jiffies(WL1271_PS_COMPLETE_TIMEOUT)); | 1582 | &compl, msecs_to_jiffies(WL1271_PS_COMPLETE_TIMEOUT)); |
1583 | |||
1584 | mutex_lock(&wl->mutex); | ||
1588 | if (ret <= 0) { | 1585 | if (ret <= 0) { |
1589 | wl1271_warning("couldn't enter ps mode!"); | 1586 | wl1271_warning("couldn't enter ps mode!"); |
1590 | ret = -EBUSY; | 1587 | ret = -EBUSY; |
1591 | goto out; | 1588 | goto out_cleanup; |
1592 | } | 1589 | } |
1593 | 1590 | ||
1594 | /* take mutex again, and wakeup */ | ||
1595 | mutex_lock(&wl->mutex); | ||
1596 | |||
1597 | ret = wl1271_ps_elp_wakeup(wl); | 1591 | ret = wl1271_ps_elp_wakeup(wl); |
1598 | if (ret < 0) | 1592 | if (ret < 0) |
1599 | goto out_unlock; | 1593 | goto out_cleanup; |
1600 | } | 1594 | } |
1601 | out_sleep: | 1595 | out_sleep: |
1602 | wl1271_ps_elp_sleep(wl); | 1596 | wl1271_ps_elp_sleep(wl); |
1597 | out_cleanup: | ||
1598 | wlvif->ps_compl = NULL; | ||
1603 | out_unlock: | 1599 | out_unlock: |
1604 | mutex_unlock(&wl->mutex); | 1600 | mutex_unlock(&wl->mutex); |
1605 | out: | ||
1606 | return ret; | 1601 | return ret; |
1607 | 1602 | ||
1608 | } | 1603 | } |
diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c index 8c277c0cb372..4fbd2a722ffa 100644 --- a/drivers/net/wireless/wl12xx/rx.c +++ b/drivers/net/wireless/wl12xx/rx.c | |||
@@ -258,8 +258,12 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status) | |||
258 | wl->aggr_buf + pkt_offset, | 258 | wl->aggr_buf + pkt_offset, |
259 | pkt_length, unaligned, | 259 | pkt_length, unaligned, |
260 | &hlid) == 1) { | 260 | &hlid) == 1) { |
261 | WARN_ON(hlid >= WL12XX_MAX_LINKS); | 261 | if (hlid < WL12XX_MAX_LINKS) |
262 | __set_bit(hlid, active_hlids); | 262 | __set_bit(hlid, active_hlids); |
263 | else | ||
264 | WARN(1, | ||
265 | "hlid exceeded WL12XX_MAX_LINKS " | ||
266 | "(%d)\n", hlid); | ||
263 | } | 267 | } |
264 | 268 | ||
265 | wl->rx_counter++; | 269 | wl->rx_counter++; |
diff --git a/drivers/net/wireless/wl12xx/testmode.c b/drivers/net/wireless/wl12xx/testmode.c index 978cf2de713d..25093c0cb0ed 100644 --- a/drivers/net/wireless/wl12xx/testmode.c +++ b/drivers/net/wireless/wl12xx/testmode.c | |||
@@ -38,6 +38,7 @@ enum wl1271_tm_commands { | |||
38 | WL1271_TM_CMD_TEST, | 38 | WL1271_TM_CMD_TEST, |
39 | WL1271_TM_CMD_INTERROGATE, | 39 | WL1271_TM_CMD_INTERROGATE, |
40 | WL1271_TM_CMD_CONFIGURE, | 40 | WL1271_TM_CMD_CONFIGURE, |
41 | WL1271_TM_CMD_NVS_PUSH, /* Not in use. Keep to not break ABI */ | ||
41 | WL1271_TM_CMD_SET_PLT_MODE, | 42 | WL1271_TM_CMD_SET_PLT_MODE, |
42 | WL1271_TM_CMD_RECOVER, | 43 | WL1271_TM_CMD_RECOVER, |
43 | 44 | ||
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 7d727ee6ddf6..4508ccd78328 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c | |||
@@ -740,7 +740,14 @@ void wl1271_tx_work_locked(struct wl1271 *wl) | |||
740 | set_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); | 740 | set_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); |
741 | goto out_ack; | 741 | goto out_ack; |
742 | } else if (ret < 0) { | 742 | } else if (ret < 0) { |
743 | dev_kfree_skb(skb); | 743 | if (wl12xx_is_dummy_packet(wl, skb)) |
744 | /* | ||
745 | * fw still expects dummy packet, | ||
746 | * so re-enqueue it | ||
747 | */ | ||
748 | wl1271_skb_queue_head(wl, wlvif, skb); | ||
749 | else | ||
750 | ieee80211_free_txskb(wl->hw, skb); | ||
744 | goto out_ack; | 751 | goto out_ack; |
745 | } | 752 | } |
746 | buf_offset += ret; | 753 | buf_offset += ret; |
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index f1c911774bfd..d21f71ff6f64 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h | |||
@@ -35,13 +35,6 @@ | |||
35 | #include "conf.h" | 35 | #include "conf.h" |
36 | #include "ini.h" | 36 | #include "ini.h" |
37 | 37 | ||
38 | /* | ||
39 | * FW versions support BA 11n | ||
40 | * versions marks x.x.x.50-60.x | ||
41 | */ | ||
42 | #define WL12XX_BA_SUPPORT_FW_COST_VER2_START 50 | ||
43 | #define WL12XX_BA_SUPPORT_FW_COST_VER2_END 60 | ||
44 | |||
45 | #define WL127X_FW_NAME "ti-connectivity/wl127x-fw-3.bin" | 38 | #define WL127X_FW_NAME "ti-connectivity/wl127x-fw-3.bin" |
46 | #define WL128X_FW_NAME "ti-connectivity/wl128x-fw-3.bin" | 39 | #define WL128X_FW_NAME "ti-connectivity/wl128x-fw-3.bin" |
47 | 40 | ||
diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index dbf214ef7321..b8b6c2abbd4a 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c | |||
@@ -72,6 +72,7 @@ MODULE_DEVICE_TABLE(usb, pn533_table); | |||
72 | #define PN533_CMD_IN_LIST_PASSIVE_TARGET 0x4A | 72 | #define PN533_CMD_IN_LIST_PASSIVE_TARGET 0x4A |
73 | #define PN533_CMD_IN_ATR 0x50 | 73 | #define PN533_CMD_IN_ATR 0x50 |
74 | #define PN533_CMD_IN_RELEASE 0x52 | 74 | #define PN533_CMD_IN_RELEASE 0x52 |
75 | #define PN533_CMD_IN_JUMP_FOR_DEP 0x56 | ||
75 | 76 | ||
76 | #define PN533_CMD_RESPONSE(cmd) (cmd + 1) | 77 | #define PN533_CMD_RESPONSE(cmd) (cmd + 1) |
77 | 78 | ||
@@ -231,6 +232,26 @@ struct pn533_cmd_activate_response { | |||
231 | u8 gt[]; | 232 | u8 gt[]; |
232 | } __packed; | 233 | } __packed; |
233 | 234 | ||
235 | /* PN533_CMD_IN_JUMP_FOR_DEP */ | ||
236 | struct pn533_cmd_jump_dep { | ||
237 | u8 active; | ||
238 | u8 baud; | ||
239 | u8 next; | ||
240 | u8 gt[]; | ||
241 | } __packed; | ||
242 | |||
243 | struct pn533_cmd_jump_dep_response { | ||
244 | u8 status; | ||
245 | u8 tg; | ||
246 | u8 nfcid3t[10]; | ||
247 | u8 didt; | ||
248 | u8 bst; | ||
249 | u8 brt; | ||
250 | u8 to; | ||
251 | u8 ppt; | ||
252 | /* optional */ | ||
253 | u8 gt[]; | ||
254 | } __packed; | ||
234 | 255 | ||
235 | struct pn533 { | 256 | struct pn533 { |
236 | struct usb_device *udev; | 257 | struct usb_device *udev; |
@@ -1121,6 +1142,7 @@ static int pn533_activate_target_nfcdep(struct pn533 *dev) | |||
1121 | { | 1142 | { |
1122 | struct pn533_cmd_activate_param param; | 1143 | struct pn533_cmd_activate_param param; |
1123 | struct pn533_cmd_activate_response *resp; | 1144 | struct pn533_cmd_activate_response *resp; |
1145 | u16 gt_len; | ||
1124 | int rc; | 1146 | int rc; |
1125 | 1147 | ||
1126 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 1148 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); |
@@ -1146,7 +1168,11 @@ static int pn533_activate_target_nfcdep(struct pn533 *dev) | |||
1146 | if (rc != PN533_CMD_RET_SUCCESS) | 1168 | if (rc != PN533_CMD_RET_SUCCESS) |
1147 | return -EIO; | 1169 | return -EIO; |
1148 | 1170 | ||
1149 | return 0; | 1171 | /* ATR_RES general bytes are located at offset 16 */ |
1172 | gt_len = PN533_FRAME_CMD_PARAMS_LEN(dev->in_frame) - 16; | ||
1173 | rc = nfc_set_remote_general_bytes(dev->nfc_dev, resp->gt, gt_len); | ||
1174 | |||
1175 | return rc; | ||
1150 | } | 1176 | } |
1151 | 1177 | ||
1152 | static int pn533_activate_target(struct nfc_dev *nfc_dev, u32 target_idx, | 1178 | static int pn533_activate_target(struct nfc_dev *nfc_dev, u32 target_idx, |
@@ -1239,6 +1265,142 @@ static void pn533_deactivate_target(struct nfc_dev *nfc_dev, u32 target_idx) | |||
1239 | return; | 1265 | return; |
1240 | } | 1266 | } |
1241 | 1267 | ||
1268 | |||
1269 | static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, | ||
1270 | u8 *params, int params_len) | ||
1271 | { | ||
1272 | struct pn533_cmd_jump_dep *cmd; | ||
1273 | struct pn533_cmd_jump_dep_response *resp; | ||
1274 | struct nfc_target nfc_target; | ||
1275 | u8 target_gt_len; | ||
1276 | int rc; | ||
1277 | |||
1278 | if (params_len == -ENOENT) { | ||
1279 | nfc_dev_dbg(&dev->interface->dev, ""); | ||
1280 | return 0; | ||
1281 | } | ||
1282 | |||
1283 | if (params_len < 0) { | ||
1284 | nfc_dev_err(&dev->interface->dev, | ||
1285 | "Error %d when bringing DEP link up", | ||
1286 | params_len); | ||
1287 | return 0; | ||
1288 | } | ||
1289 | |||
1290 | if (dev->tgt_available_prots && | ||
1291 | !(dev->tgt_available_prots & (1 << NFC_PROTO_NFC_DEP))) { | ||
1292 | nfc_dev_err(&dev->interface->dev, | ||
1293 | "The target does not support DEP"); | ||
1294 | return -EINVAL; | ||
1295 | } | ||
1296 | |||
1297 | resp = (struct pn533_cmd_jump_dep_response *) params; | ||
1298 | cmd = (struct pn533_cmd_jump_dep *) arg; | ||
1299 | rc = resp->status & PN533_CMD_RET_MASK; | ||
1300 | if (rc != PN533_CMD_RET_SUCCESS) { | ||
1301 | nfc_dev_err(&dev->interface->dev, | ||
1302 | "Bringing DEP link up failed %d", rc); | ||
1303 | return 0; | ||
1304 | } | ||
1305 | |||
1306 | if (!dev->tgt_available_prots) { | ||
1307 | nfc_dev_dbg(&dev->interface->dev, "Creating new target"); | ||
1308 | |||
1309 | nfc_target.supported_protocols = NFC_PROTO_NFC_DEP_MASK; | ||
1310 | rc = nfc_targets_found(dev->nfc_dev, &nfc_target, 1); | ||
1311 | if (rc) | ||
1312 | return 0; | ||
1313 | |||
1314 | dev->tgt_available_prots = 0; | ||
1315 | } | ||
1316 | |||
1317 | dev->tgt_active_prot = NFC_PROTO_NFC_DEP; | ||
1318 | |||
1319 | /* ATR_RES general bytes are located at offset 17 */ | ||
1320 | target_gt_len = PN533_FRAME_CMD_PARAMS_LEN(dev->in_frame) - 17; | ||
1321 | rc = nfc_set_remote_general_bytes(dev->nfc_dev, | ||
1322 | resp->gt, target_gt_len); | ||
1323 | if (rc == 0) | ||
1324 | rc = nfc_dep_link_is_up(dev->nfc_dev, | ||
1325 | dev->nfc_dev->targets[0].idx, | ||
1326 | !cmd->active, NFC_RF_INITIATOR); | ||
1327 | |||
1328 | return 0; | ||
1329 | } | ||
1330 | |||
1331 | static int pn533_dep_link_up(struct nfc_dev *nfc_dev, int target_idx, | ||
1332 | u8 comm_mode, u8 rf_mode) | ||
1333 | { | ||
1334 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); | ||
1335 | struct pn533_cmd_jump_dep *cmd; | ||
1336 | u8 cmd_len, local_gt_len, *local_gt; | ||
1337 | int rc; | ||
1338 | |||
1339 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | ||
1340 | |||
1341 | if (rf_mode == NFC_RF_TARGET) { | ||
1342 | nfc_dev_err(&dev->interface->dev, "Target mode not supported"); | ||
1343 | return -EOPNOTSUPP; | ||
1344 | } | ||
1345 | |||
1346 | |||
1347 | if (dev->poll_mod_count) { | ||
1348 | nfc_dev_err(&dev->interface->dev, | ||
1349 | "Cannot bring the DEP link up while polling"); | ||
1350 | return -EBUSY; | ||
1351 | } | ||
1352 | |||
1353 | if (dev->tgt_active_prot) { | ||
1354 | nfc_dev_err(&dev->interface->dev, | ||
1355 | "There is already an active target"); | ||
1356 | return -EBUSY; | ||
1357 | } | ||
1358 | |||
1359 | local_gt = nfc_get_local_general_bytes(dev->nfc_dev, &local_gt_len); | ||
1360 | if (local_gt_len > NFC_MAX_GT_LEN) | ||
1361 | return -EINVAL; | ||
1362 | |||
1363 | cmd_len = sizeof(struct pn533_cmd_jump_dep) + local_gt_len; | ||
1364 | cmd = kzalloc(cmd_len, GFP_KERNEL); | ||
1365 | if (cmd == NULL) | ||
1366 | return -ENOMEM; | ||
1367 | |||
1368 | pn533_tx_frame_init(dev->out_frame, PN533_CMD_IN_JUMP_FOR_DEP); | ||
1369 | |||
1370 | cmd->active = !comm_mode; | ||
1371 | cmd->baud = 0; | ||
1372 | if (local_gt != NULL) { | ||
1373 | cmd->next = 4; /* We have some Gi */ | ||
1374 | memcpy(cmd->gt, local_gt, local_gt_len); | ||
1375 | } else { | ||
1376 | cmd->next = 0; | ||
1377 | } | ||
1378 | |||
1379 | memcpy(PN533_FRAME_CMD_PARAMS_PTR(dev->out_frame), cmd, cmd_len); | ||
1380 | dev->out_frame->datalen += cmd_len; | ||
1381 | |||
1382 | pn533_tx_frame_finish(dev->out_frame); | ||
1383 | |||
1384 | rc = pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame, | ||
1385 | dev->in_maxlen, pn533_in_dep_link_up_complete, | ||
1386 | cmd, GFP_KERNEL); | ||
1387 | if (rc) | ||
1388 | goto out; | ||
1389 | |||
1390 | |||
1391 | out: | ||
1392 | kfree(cmd); | ||
1393 | |||
1394 | return rc; | ||
1395 | } | ||
1396 | |||
1397 | static int pn533_dep_link_down(struct nfc_dev *nfc_dev) | ||
1398 | { | ||
1399 | pn533_deactivate_target(nfc_dev, 0); | ||
1400 | |||
1401 | return 0; | ||
1402 | } | ||
1403 | |||
1242 | #define PN533_CMD_DATAEXCH_HEAD_LEN (sizeof(struct pn533_frame) + 3) | 1404 | #define PN533_CMD_DATAEXCH_HEAD_LEN (sizeof(struct pn533_frame) + 3) |
1243 | #define PN533_CMD_DATAEXCH_DATA_MAXLEN 262 | 1405 | #define PN533_CMD_DATAEXCH_DATA_MAXLEN 262 |
1244 | 1406 | ||
@@ -1368,7 +1530,7 @@ static int pn533_data_exchange(struct nfc_dev *nfc_dev, u32 target_idx, | |||
1368 | PN533_CMD_DATAEXCH_DATA_MAXLEN + | 1530 | PN533_CMD_DATAEXCH_DATA_MAXLEN + |
1369 | PN533_FRAME_TAIL_SIZE; | 1531 | PN533_FRAME_TAIL_SIZE; |
1370 | 1532 | ||
1371 | skb_resp = nfc_alloc_skb(skb_resp_len, GFP_KERNEL); | 1533 | skb_resp = nfc_alloc_recv_skb(skb_resp_len, GFP_KERNEL); |
1372 | if (!skb_resp) { | 1534 | if (!skb_resp) { |
1373 | rc = -ENOMEM; | 1535 | rc = -ENOMEM; |
1374 | goto error; | 1536 | goto error; |
@@ -1434,6 +1596,8 @@ static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata, | |||
1434 | struct nfc_ops pn533_nfc_ops = { | 1596 | struct nfc_ops pn533_nfc_ops = { |
1435 | .dev_up = NULL, | 1597 | .dev_up = NULL, |
1436 | .dev_down = NULL, | 1598 | .dev_down = NULL, |
1599 | .dep_link_up = pn533_dep_link_up, | ||
1600 | .dep_link_down = pn533_dep_link_down, | ||
1437 | .start_poll = pn533_start_poll, | 1601 | .start_poll = pn533_start_poll, |
1438 | .stop_poll = pn533_stop_poll, | 1602 | .stop_poll = pn533_stop_poll, |
1439 | .activate_target = pn533_activate_target, | 1603 | .activate_target = pn533_activate_target, |
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c index 34c3bab90b9a..973223f5de8e 100644 --- a/drivers/ssb/pci.c +++ b/drivers/ssb/pci.c | |||
@@ -607,6 +607,29 @@ static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in) | |||
607 | memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24, | 607 | memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24, |
608 | sizeof(out->antenna_gain.ghz5)); | 608 | sizeof(out->antenna_gain.ghz5)); |
609 | 609 | ||
610 | /* Extract FEM info */ | ||
611 | SPEX(fem.ghz2.tssipos, SSB_SPROM8_FEM2G, | ||
612 | SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT); | ||
613 | SPEX(fem.ghz2.extpa_gain, SSB_SPROM8_FEM2G, | ||
614 | SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT); | ||
615 | SPEX(fem.ghz2.pdet_range, SSB_SPROM8_FEM2G, | ||
616 | SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT); | ||
617 | SPEX(fem.ghz2.tr_iso, SSB_SPROM8_FEM2G, | ||
618 | SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT); | ||
619 | SPEX(fem.ghz2.antswlut, SSB_SPROM8_FEM2G, | ||
620 | SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT); | ||
621 | |||
622 | SPEX(fem.ghz5.tssipos, SSB_SPROM8_FEM5G, | ||
623 | SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT); | ||
624 | SPEX(fem.ghz5.extpa_gain, SSB_SPROM8_FEM5G, | ||
625 | SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT); | ||
626 | SPEX(fem.ghz5.pdet_range, SSB_SPROM8_FEM5G, | ||
627 | SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT); | ||
628 | SPEX(fem.ghz5.tr_iso, SSB_SPROM8_FEM5G, | ||
629 | SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT); | ||
630 | SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G, | ||
631 | SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT); | ||
632 | |||
610 | sprom_extract_r458(out, in); | 633 | sprom_extract_r458(out, in); |
611 | 634 | ||
612 | /* TODO - get remaining rev 8 stuff needed */ | 635 | /* TODO - get remaining rev 8 stuff needed */ |
diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h index 4d4b59de9467..f4b8346b1a33 100644 --- a/include/linux/bcma/bcma.h +++ b/include/linux/bcma/bcma.h | |||
@@ -205,61 +205,82 @@ struct bcma_bus { | |||
205 | struct ssb_sprom sprom; | 205 | struct ssb_sprom sprom; |
206 | }; | 206 | }; |
207 | 207 | ||
208 | extern inline u32 bcma_read8(struct bcma_device *core, u16 offset) | 208 | static inline u32 bcma_read8(struct bcma_device *core, u16 offset) |
209 | { | 209 | { |
210 | return core->bus->ops->read8(core, offset); | 210 | return core->bus->ops->read8(core, offset); |
211 | } | 211 | } |
212 | extern inline u32 bcma_read16(struct bcma_device *core, u16 offset) | 212 | static inline u32 bcma_read16(struct bcma_device *core, u16 offset) |
213 | { | 213 | { |
214 | return core->bus->ops->read16(core, offset); | 214 | return core->bus->ops->read16(core, offset); |
215 | } | 215 | } |
216 | extern inline u32 bcma_read32(struct bcma_device *core, u16 offset) | 216 | static inline u32 bcma_read32(struct bcma_device *core, u16 offset) |
217 | { | 217 | { |
218 | return core->bus->ops->read32(core, offset); | 218 | return core->bus->ops->read32(core, offset); |
219 | } | 219 | } |
220 | extern inline | 220 | static inline |
221 | void bcma_write8(struct bcma_device *core, u16 offset, u32 value) | 221 | void bcma_write8(struct bcma_device *core, u16 offset, u32 value) |
222 | { | 222 | { |
223 | core->bus->ops->write8(core, offset, value); | 223 | core->bus->ops->write8(core, offset, value); |
224 | } | 224 | } |
225 | extern inline | 225 | static inline |
226 | void bcma_write16(struct bcma_device *core, u16 offset, u32 value) | 226 | void bcma_write16(struct bcma_device *core, u16 offset, u32 value) |
227 | { | 227 | { |
228 | core->bus->ops->write16(core, offset, value); | 228 | core->bus->ops->write16(core, offset, value); |
229 | } | 229 | } |
230 | extern inline | 230 | static inline |
231 | void bcma_write32(struct bcma_device *core, u16 offset, u32 value) | 231 | void bcma_write32(struct bcma_device *core, u16 offset, u32 value) |
232 | { | 232 | { |
233 | core->bus->ops->write32(core, offset, value); | 233 | core->bus->ops->write32(core, offset, value); |
234 | } | 234 | } |
235 | #ifdef CONFIG_BCMA_BLOCKIO | 235 | #ifdef CONFIG_BCMA_BLOCKIO |
236 | extern inline void bcma_block_read(struct bcma_device *core, void *buffer, | 236 | static inline void bcma_block_read(struct bcma_device *core, void *buffer, |
237 | size_t count, u16 offset, u8 reg_width) | 237 | size_t count, u16 offset, u8 reg_width) |
238 | { | 238 | { |
239 | core->bus->ops->block_read(core, buffer, count, offset, reg_width); | 239 | core->bus->ops->block_read(core, buffer, count, offset, reg_width); |
240 | } | 240 | } |
241 | extern inline void bcma_block_write(struct bcma_device *core, const void *buffer, | 241 | static inline void bcma_block_write(struct bcma_device *core, |
242 | size_t count, u16 offset, u8 reg_width) | 242 | const void *buffer, size_t count, |
243 | u16 offset, u8 reg_width) | ||
243 | { | 244 | { |
244 | core->bus->ops->block_write(core, buffer, count, offset, reg_width); | 245 | core->bus->ops->block_write(core, buffer, count, offset, reg_width); |
245 | } | 246 | } |
246 | #endif | 247 | #endif |
247 | extern inline u32 bcma_aread32(struct bcma_device *core, u16 offset) | 248 | static inline u32 bcma_aread32(struct bcma_device *core, u16 offset) |
248 | { | 249 | { |
249 | return core->bus->ops->aread32(core, offset); | 250 | return core->bus->ops->aread32(core, offset); |
250 | } | 251 | } |
251 | extern inline | 252 | static inline |
252 | void bcma_awrite32(struct bcma_device *core, u16 offset, u32 value) | 253 | void bcma_awrite32(struct bcma_device *core, u16 offset, u32 value) |
253 | { | 254 | { |
254 | core->bus->ops->awrite32(core, offset, value); | 255 | core->bus->ops->awrite32(core, offset, value); |
255 | } | 256 | } |
256 | 257 | ||
257 | #define bcma_mask32(cc, offset, mask) \ | 258 | static inline void bcma_mask32(struct bcma_device *cc, u16 offset, u32 mask) |
258 | bcma_write32(cc, offset, bcma_read32(cc, offset) & (mask)) | 259 | { |
259 | #define bcma_set32(cc, offset, set) \ | 260 | bcma_write32(cc, offset, bcma_read32(cc, offset) & mask); |
260 | bcma_write32(cc, offset, bcma_read32(cc, offset) | (set)) | 261 | } |
261 | #define bcma_maskset32(cc, offset, mask, set) \ | 262 | static inline void bcma_set32(struct bcma_device *cc, u16 offset, u32 set) |
262 | bcma_write32(cc, offset, (bcma_read32(cc, offset) & (mask)) | (set)) | 263 | { |
264 | bcma_write32(cc, offset, bcma_read32(cc, offset) | set); | ||
265 | } | ||
266 | static inline void bcma_maskset32(struct bcma_device *cc, | ||
267 | u16 offset, u32 mask, u32 set) | ||
268 | { | ||
269 | bcma_write32(cc, offset, (bcma_read32(cc, offset) & mask) | set); | ||
270 | } | ||
271 | static inline void bcma_mask16(struct bcma_device *cc, u16 offset, u16 mask) | ||
272 | { | ||
273 | bcma_write16(cc, offset, bcma_read16(cc, offset) & mask); | ||
274 | } | ||
275 | static inline void bcma_set16(struct bcma_device *cc, u16 offset, u16 set) | ||
276 | { | ||
277 | bcma_write16(cc, offset, bcma_read16(cc, offset) | set); | ||
278 | } | ||
279 | static inline void bcma_maskset16(struct bcma_device *cc, | ||
280 | u16 offset, u16 mask, u16 set) | ||
281 | { | ||
282 | bcma_write16(cc, offset, (bcma_read16(cc, offset) & mask) | set); | ||
283 | } | ||
263 | 284 | ||
264 | extern bool bcma_core_is_enabled(struct bcma_device *core); | 285 | extern bool bcma_core_is_enabled(struct bcma_device *core); |
265 | extern void bcma_core_disable(struct bcma_device *core, u32 flags); | 286 | extern void bcma_core_disable(struct bcma_device *core, u32 flags); |
diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h index 1526d965ed06..a33086a7530b 100644 --- a/include/linux/bcma/bcma_driver_chipcommon.h +++ b/include/linux/bcma/bcma_driver_chipcommon.h | |||
@@ -203,6 +203,7 @@ | |||
203 | #define BCMA_CC_PMU_CTL 0x0600 /* PMU control */ | 203 | #define BCMA_CC_PMU_CTL 0x0600 /* PMU control */ |
204 | #define BCMA_CC_PMU_CTL_ILP_DIV 0xFFFF0000 /* ILP div mask */ | 204 | #define BCMA_CC_PMU_CTL_ILP_DIV 0xFFFF0000 /* ILP div mask */ |
205 | #define BCMA_CC_PMU_CTL_ILP_DIV_SHIFT 16 | 205 | #define BCMA_CC_PMU_CTL_ILP_DIV_SHIFT 16 |
206 | #define BCMA_CC_PMU_CTL_PLL_UPD 0x00000400 | ||
206 | #define BCMA_CC_PMU_CTL_NOILPONW 0x00000200 /* No ILP on wait */ | 207 | #define BCMA_CC_PMU_CTL_NOILPONW 0x00000200 /* No ILP on wait */ |
207 | #define BCMA_CC_PMU_CTL_HTREQEN 0x00000100 /* HT req enable */ | 208 | #define BCMA_CC_PMU_CTL_HTREQEN 0x00000100 /* HT req enable */ |
208 | #define BCMA_CC_PMU_CTL_ALPREQEN 0x00000080 /* ALP req enable */ | 209 | #define BCMA_CC_PMU_CTL_ALPREQEN 0x00000080 /* ALP req enable */ |
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 17f2a768e2ad..210e2c325534 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h | |||
@@ -544,6 +544,15 @@ static inline int ieee80211_is_qos_nullfunc(__le16 fc) | |||
544 | cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_NULLFUNC); | 544 | cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_NULLFUNC); |
545 | } | 545 | } |
546 | 546 | ||
547 | /** | ||
548 | * ieee80211_is_first_frag - check if IEEE80211_SCTL_FRAG is not set | ||
549 | * @seq_ctrl: frame sequence control bytes in little-endian byteorder | ||
550 | */ | ||
551 | static inline int ieee80211_is_first_frag(__le16 seq_ctrl) | ||
552 | { | ||
553 | return (seq_ctrl & cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0; | ||
554 | } | ||
555 | |||
547 | struct ieee80211s_hdr { | 556 | struct ieee80211s_hdr { |
548 | u8 flags; | 557 | u8 flags; |
549 | u8 ttl; | 558 | u8 ttl; |
diff --git a/include/linux/nfc.h b/include/linux/nfc.h index 36cb955b05cc..89fee4ab1904 100644 --- a/include/linux/nfc.h +++ b/include/linux/nfc.h | |||
@@ -62,6 +62,8 @@ enum nfc_commands { | |||
62 | NFC_CMD_GET_DEVICE, | 62 | NFC_CMD_GET_DEVICE, |
63 | NFC_CMD_DEV_UP, | 63 | NFC_CMD_DEV_UP, |
64 | NFC_CMD_DEV_DOWN, | 64 | NFC_CMD_DEV_DOWN, |
65 | NFC_CMD_DEP_LINK_UP, | ||
66 | NFC_CMD_DEP_LINK_DOWN, | ||
65 | NFC_CMD_START_POLL, | 67 | NFC_CMD_START_POLL, |
66 | NFC_CMD_STOP_POLL, | 68 | NFC_CMD_STOP_POLL, |
67 | NFC_CMD_GET_TARGET, | 69 | NFC_CMD_GET_TARGET, |
@@ -86,6 +88,8 @@ enum nfc_commands { | |||
86 | * @NFC_ATTR_TARGET_SENS_RES: NFC-A targets extra information such as NFCID | 88 | * @NFC_ATTR_TARGET_SENS_RES: NFC-A targets extra information such as NFCID |
87 | * @NFC_ATTR_TARGET_SEL_RES: NFC-A targets extra information (useful if the | 89 | * @NFC_ATTR_TARGET_SEL_RES: NFC-A targets extra information (useful if the |
88 | * target is not NFC-Forum compliant) | 90 | * target is not NFC-Forum compliant) |
91 | * @NFC_ATTR_COMM_MODE: Passive or active mode | ||
92 | * @NFC_ATTR_RF_MODE: Initiator or target | ||
89 | */ | 93 | */ |
90 | enum nfc_attrs { | 94 | enum nfc_attrs { |
91 | NFC_ATTR_UNSPEC, | 95 | NFC_ATTR_UNSPEC, |
@@ -95,6 +99,8 @@ enum nfc_attrs { | |||
95 | NFC_ATTR_TARGET_INDEX, | 99 | NFC_ATTR_TARGET_INDEX, |
96 | NFC_ATTR_TARGET_SENS_RES, | 100 | NFC_ATTR_TARGET_SENS_RES, |
97 | NFC_ATTR_TARGET_SEL_RES, | 101 | NFC_ATTR_TARGET_SEL_RES, |
102 | NFC_ATTR_COMM_MODE, | ||
103 | NFC_ATTR_RF_MODE, | ||
98 | /* private: internal use only */ | 104 | /* private: internal use only */ |
99 | __NFC_ATTR_AFTER_LAST | 105 | __NFC_ATTR_AFTER_LAST |
100 | }; | 106 | }; |
@@ -111,6 +117,14 @@ enum nfc_attrs { | |||
111 | 117 | ||
112 | #define NFC_PROTO_MAX 6 | 118 | #define NFC_PROTO_MAX 6 |
113 | 119 | ||
120 | /* NFC communication modes */ | ||
121 | #define NFC_COMM_ACTIVE 0 | ||
122 | #define NFC_COMM_PASSIVE 1 | ||
123 | |||
124 | /* NFC RF modes */ | ||
125 | #define NFC_RF_INITIATOR 0 | ||
126 | #define NFC_RF_TARGET 1 | ||
127 | |||
114 | /* NFC protocols masks used in bitsets */ | 128 | /* NFC protocols masks used in bitsets */ |
115 | #define NFC_PROTO_JEWEL_MASK (1 << NFC_PROTO_JEWEL) | 129 | #define NFC_PROTO_JEWEL_MASK (1 << NFC_PROTO_JEWEL) |
116 | #define NFC_PROTO_MIFARE_MASK (1 << NFC_PROTO_MIFARE) | 130 | #define NFC_PROTO_MIFARE_MASK (1 << NFC_PROTO_MIFARE) |
@@ -125,9 +139,22 @@ struct sockaddr_nfc { | |||
125 | __u32 nfc_protocol; | 139 | __u32 nfc_protocol; |
126 | }; | 140 | }; |
127 | 141 | ||
142 | #define NFC_LLCP_MAX_SERVICE_NAME 63 | ||
143 | struct sockaddr_nfc_llcp { | ||
144 | sa_family_t sa_family; | ||
145 | __u32 dev_idx; | ||
146 | __u32 target_idx; | ||
147 | __u32 nfc_protocol; | ||
148 | __u8 dsap; /* Destination SAP, if known */ | ||
149 | __u8 ssap; /* Source SAP to be bound to */ | ||
150 | char service_name[NFC_LLCP_MAX_SERVICE_NAME]; /* Service name URI */; | ||
151 | size_t service_name_len; | ||
152 | }; | ||
153 | |||
128 | /* NFC socket protocols */ | 154 | /* NFC socket protocols */ |
129 | #define NFC_SOCKPROTO_RAW 0 | 155 | #define NFC_SOCKPROTO_RAW 0 |
130 | #define NFC_SOCKPROTO_MAX 1 | 156 | #define NFC_SOCKPROTO_LLCP 1 |
157 | #define NFC_SOCKPROTO_MAX 2 | ||
131 | 158 | ||
132 | #define NFC_HEADER_SIZE 1 | 159 | #define NFC_HEADER_SIZE 1 |
133 | 160 | ||
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index a18760684fc9..f795cb7dccdd 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h | |||
@@ -1536,7 +1536,11 @@ enum nl80211_iftype { | |||
1536 | * @NL80211_STA_FLAG_WME: station is WME/QoS capable | 1536 | * @NL80211_STA_FLAG_WME: station is WME/QoS capable |
1537 | * @NL80211_STA_FLAG_MFP: station uses management frame protection | 1537 | * @NL80211_STA_FLAG_MFP: station uses management frame protection |
1538 | * @NL80211_STA_FLAG_AUTHENTICATED: station is authenticated | 1538 | * @NL80211_STA_FLAG_AUTHENTICATED: station is authenticated |
1539 | * @NL80211_STA_FLAG_TDLS_PEER: station is a TDLS peer | 1539 | * @NL80211_STA_FLAG_TDLS_PEER: station is a TDLS peer -- this flag should |
1540 | * only be used in managed mode (even in the flags mask). Note that the | ||
1541 | * flag can't be changed, it is only valid while adding a station, and | ||
1542 | * attempts to change it will silently be ignored (rather than rejected | ||
1543 | * as errors.) | ||
1540 | * @NL80211_STA_FLAG_MAX: highest station flag number currently defined | 1544 | * @NL80211_STA_FLAG_MAX: highest station flag number currently defined |
1541 | * @__NL80211_STA_FLAG_AFTER_LAST: internal use | 1545 | * @__NL80211_STA_FLAG_AFTER_LAST: internal use |
1542 | */ | 1546 | */ |
diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h index 061e560251b4..dcf35b0f303a 100644 --- a/include/linux/ssb/ssb.h +++ b/include/linux/ssb/ssb.h | |||
@@ -94,6 +94,15 @@ struct ssb_sprom { | |||
94 | } ghz5; /* 5GHz band */ | 94 | } ghz5; /* 5GHz band */ |
95 | } antenna_gain; | 95 | } antenna_gain; |
96 | 96 | ||
97 | struct { | ||
98 | struct { | ||
99 | u8 tssipos, extpa_gain, pdet_range, tr_iso, antswlut; | ||
100 | } ghz2; | ||
101 | struct { | ||
102 | u8 tssipos, extpa_gain, pdet_range, tr_iso, antswlut; | ||
103 | } ghz5; | ||
104 | } fem; | ||
105 | |||
97 | /* TODO - add any parameters needed from rev 2, 3, 4, 5 or 8 SPROMs */ | 106 | /* TODO - add any parameters needed from rev 2, 3, 4, 5 or 8 SPROMs */ |
98 | }; | 107 | }; |
99 | 108 | ||
diff --git a/include/linux/ssb/ssb_regs.h b/include/linux/ssb/ssb_regs.h index 98941203a27f..c814ae6eeb22 100644 --- a/include/linux/ssb/ssb_regs.h +++ b/include/linux/ssb/ssb_regs.h | |||
@@ -432,6 +432,23 @@ | |||
432 | #define SSB_SPROM8_RXPO2G 0x00FF /* 2GHz RX power offset */ | 432 | #define SSB_SPROM8_RXPO2G 0x00FF /* 2GHz RX power offset */ |
433 | #define SSB_SPROM8_RXPO5G 0xFF00 /* 5GHz RX power offset */ | 433 | #define SSB_SPROM8_RXPO5G 0xFF00 /* 5GHz RX power offset */ |
434 | #define SSB_SPROM8_RXPO5G_SHIFT 8 | 434 | #define SSB_SPROM8_RXPO5G_SHIFT 8 |
435 | #define SSB_SPROM8_FEM2G 0x00AE | ||
436 | #define SSB_SPROM8_FEM5G 0x00B0 | ||
437 | #define SSB_SROM8_FEM_TSSIPOS 0x0001 | ||
438 | #define SSB_SROM8_FEM_TSSIPOS_SHIFT 0 | ||
439 | #define SSB_SROM8_FEM_EXTPA_GAIN 0x0006 | ||
440 | #define SSB_SROM8_FEM_EXTPA_GAIN_SHIFT 1 | ||
441 | #define SSB_SROM8_FEM_PDET_RANGE 0x00F8 | ||
442 | #define SSB_SROM8_FEM_PDET_RANGE_SHIFT 3 | ||
443 | #define SSB_SROM8_FEM_TR_ISO 0x0700 | ||
444 | #define SSB_SROM8_FEM_TR_ISO_SHIFT 8 | ||
445 | #define SSB_SROM8_FEM_ANTSWLUT 0xF800 | ||
446 | #define SSB_SROM8_FEM_ANTSWLUT_SHIFT 11 | ||
447 | #define SSB_SPROM8_THERMAL 0x00B2 | ||
448 | #define SSB_SPROM8_MPWR_RAWTS 0x00B4 | ||
449 | #define SSB_SPROM8_TS_SLP_OPT_CORRX 0x00B6 | ||
450 | #define SSB_SPROM8_FOC_HWIQ_IQSWP 0x00B8 | ||
451 | #define SSB_SPROM8_PHYCAL_TEMPDELTA 0x00BA | ||
435 | #define SSB_SPROM8_MAXP_BG 0x00C0 /* Max Power 2GHz in path 1 */ | 452 | #define SSB_SPROM8_MAXP_BG 0x00C0 /* Max Power 2GHz in path 1 */ |
436 | #define SSB_SPROM8_MAXP_BG_MASK 0x00FF /* Mask for Max Power 2GHz */ | 453 | #define SSB_SPROM8_MAXP_BG_MASK 0x00FF /* Mask for Max Power 2GHz */ |
437 | #define SSB_SPROM8_ITSSI_BG 0xFF00 /* Mask for path 1 itssi_bg */ | 454 | #define SSB_SPROM8_ITSSI_BG 0xFF00 /* Mask for path 1 itssi_bg */ |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 3de1c39d03e5..9f85fca0b676 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -1346,7 +1346,12 @@ struct cfg80211_gtk_rekey_data { | |||
1346 | * | 1346 | * |
1347 | * @add_station: Add a new station. | 1347 | * @add_station: Add a new station. |
1348 | * @del_station: Remove a station; @mac may be NULL to remove all stations. | 1348 | * @del_station: Remove a station; @mac may be NULL to remove all stations. |
1349 | * @change_station: Modify a given station. | 1349 | * @change_station: Modify a given station. Note that flags changes are not much |
1350 | * validated in cfg80211, in particular the auth/assoc/authorized flags | ||
1351 | * might come to the driver in invalid combinations -- make sure to check | ||
1352 | * them, also against the existing state! Also, supported_rates changes are | ||
1353 | * not checked in station mode -- drivers need to reject (or ignore) them | ||
1354 | * for anything but TDLS peers. | ||
1350 | * @get_station: get station information for the station identified by @mac | 1355 | * @get_station: get station information for the station identified by @mac |
1351 | * @dump_station: dump station callback -- resume dump at index @idx | 1356 | * @dump_station: dump station callback -- resume dump at index @idx |
1352 | * | 1357 | * |
@@ -1694,7 +1699,9 @@ struct cfg80211_ops { | |||
1694 | * regulatory domain no user regulatory domain can enable these channels | 1699 | * regulatory domain no user regulatory domain can enable these channels |
1695 | * at a later time. This can be used for devices which do not have | 1700 | * at a later time. This can be used for devices which do not have |
1696 | * calibration information guaranteed for frequencies or settings | 1701 | * calibration information guaranteed for frequencies or settings |
1697 | * outside of its regulatory domain. | 1702 | * outside of its regulatory domain. If used in combination with |
1703 | * WIPHY_FLAG_CUSTOM_REGULATORY the inspected country IE power settings | ||
1704 | * will be followed. | ||
1698 | * @WIPHY_FLAG_DISABLE_BEACON_HINTS: enable this if your driver needs to ensure | 1705 | * @WIPHY_FLAG_DISABLE_BEACON_HINTS: enable this if your driver needs to ensure |
1699 | * that passive scan flags and beaconing flags may not be lifted by | 1706 | * that passive scan flags and beaconing flags may not be lifted by |
1700 | * cfg80211 due to regulatory beacon hints. For more information on beacon | 1707 | * cfg80211 due to regulatory beacon hints. For more information on beacon |
@@ -3064,6 +3071,32 @@ void cfg80211_roamed(struct net_device *dev, | |||
3064 | const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp); | 3071 | const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp); |
3065 | 3072 | ||
3066 | /** | 3073 | /** |
3074 | * cfg80211_roamed_bss - notify cfg80211 of roaming | ||
3075 | * | ||
3076 | * @dev: network device | ||
3077 | * @bss: entry of bss to which STA got roamed | ||
3078 | * @req_ie: association request IEs (maybe be %NULL) | ||
3079 | * @req_ie_len: association request IEs length | ||
3080 | * @resp_ie: association response IEs (may be %NULL) | ||
3081 | * @resp_ie_len: assoc response IEs length | ||
3082 | * @gfp: allocation flags | ||
3083 | * | ||
3084 | * This is just a wrapper to notify cfg80211 of roaming event with driver | ||
3085 | * passing bss to avoid a race in timeout of the bss entry. It should be | ||
3086 | * called by the underlying driver whenever it roamed from one AP to another | ||
3087 | * while connected. Drivers which have roaming implemented in firmware | ||
3088 | * may use this function to avoid a race in bss entry timeout where the bss | ||
3089 | * entry of the new AP is seen in the driver, but gets timed out by the time | ||
3090 | * it is accessed in __cfg80211_roamed() due to delay in scheduling | ||
3091 | * rdev->event_work. In case of any failures, the reference is released | ||
3092 | * either in cfg80211_roamed_bss() or in __cfg80211_romed(), Otherwise, | ||
3093 | * it will be released while diconneting from the current bss. | ||
3094 | */ | ||
3095 | void cfg80211_roamed_bss(struct net_device *dev, struct cfg80211_bss *bss, | ||
3096 | const u8 *req_ie, size_t req_ie_len, | ||
3097 | const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp); | ||
3098 | |||
3099 | /** | ||
3067 | * cfg80211_disconnected - notify cfg80211 that connection was dropped | 3100 | * cfg80211_disconnected - notify cfg80211 that connection was dropped |
3068 | * | 3101 | * |
3069 | * @dev: network device | 3102 | * @dev: network device |
diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h index 6a7f602aa841..ccfe757a94ec 100644 --- a/include/net/nfc/nfc.h +++ b/include/net/nfc/nfc.h | |||
@@ -52,6 +52,9 @@ struct nfc_ops { | |||
52 | int (*dev_down)(struct nfc_dev *dev); | 52 | int (*dev_down)(struct nfc_dev *dev); |
53 | int (*start_poll)(struct nfc_dev *dev, u32 protocols); | 53 | int (*start_poll)(struct nfc_dev *dev, u32 protocols); |
54 | void (*stop_poll)(struct nfc_dev *dev); | 54 | void (*stop_poll)(struct nfc_dev *dev); |
55 | int (*dep_link_up)(struct nfc_dev *dev, int target_idx, | ||
56 | u8 comm_mode, u8 rf_mode); | ||
57 | int (*dep_link_down)(struct nfc_dev *dev); | ||
55 | int (*activate_target)(struct nfc_dev *dev, u32 target_idx, | 58 | int (*activate_target)(struct nfc_dev *dev, u32 target_idx, |
56 | u32 protocol); | 59 | u32 protocol); |
57 | void (*deactivate_target)(struct nfc_dev *dev, u32 target_idx); | 60 | void (*deactivate_target)(struct nfc_dev *dev, u32 target_idx); |
@@ -60,6 +63,9 @@ struct nfc_ops { | |||
60 | void *cb_context); | 63 | void *cb_context); |
61 | }; | 64 | }; |
62 | 65 | ||
66 | #define NFC_TARGET_IDX_ANY -1 | ||
67 | #define NFC_MAX_GT_LEN 48 | ||
68 | |||
63 | struct nfc_target { | 69 | struct nfc_target { |
64 | u32 idx; | 70 | u32 idx; |
65 | u32 supported_protocols; | 71 | u32 supported_protocols; |
@@ -83,6 +89,8 @@ struct nfc_dev { | |||
83 | bool dev_up; | 89 | bool dev_up; |
84 | bool polling; | 90 | bool polling; |
85 | bool remote_activated; | 91 | bool remote_activated; |
92 | bool dep_link_up; | ||
93 | u32 dep_rf_mode; | ||
86 | struct nfc_genl_data genl_data; | 94 | struct nfc_genl_data genl_data; |
87 | u32 supported_protocols; | 95 | u32 supported_protocols; |
88 | 96 | ||
@@ -157,9 +165,20 @@ static inline const char *nfc_device_name(struct nfc_dev *dev) | |||
157 | return dev_name(&dev->dev); | 165 | return dev_name(&dev->dev); |
158 | } | 166 | } |
159 | 167 | ||
160 | struct sk_buff *nfc_alloc_skb(unsigned int size, gfp_t gfp); | 168 | struct sk_buff *nfc_alloc_send_skb(struct nfc_dev *dev, struct sock *sk, |
169 | unsigned int flags, unsigned int size, | ||
170 | unsigned int *err); | ||
171 | struct sk_buff *nfc_alloc_recv_skb(unsigned int size, gfp_t gfp); | ||
172 | |||
173 | int nfc_set_remote_general_bytes(struct nfc_dev *dev, | ||
174 | u8 *gt, u8 gt_len); | ||
175 | |||
176 | u8 *nfc_get_local_general_bytes(struct nfc_dev *dev, u8 *gt_len); | ||
161 | 177 | ||
162 | int nfc_targets_found(struct nfc_dev *dev, struct nfc_target *targets, | 178 | int nfc_targets_found(struct nfc_dev *dev, struct nfc_target *targets, |
163 | int ntargets); | 179 | int ntargets); |
164 | 180 | ||
181 | int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx, | ||
182 | u8 comm_mode, u8 rf_mode); | ||
183 | |||
165 | #endif /* __NET_NFC_H */ | 184 | #endif /* __NET_NFC_H */ |
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 7380287f010e..e92f98d32746 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -55,6 +55,8 @@ | |||
55 | * @ampdu_action function will be called with the action | 55 | * @ampdu_action function will be called with the action |
56 | * %IEEE80211_AMPDU_TX_STOP. In this case, the call must not fail, | 56 | * %IEEE80211_AMPDU_TX_STOP. In this case, the call must not fail, |
57 | * and the driver must later call ieee80211_stop_tx_ba_cb_irqsafe(). | 57 | * and the driver must later call ieee80211_stop_tx_ba_cb_irqsafe(). |
58 | * Note that the sta can get destroyed before the BA tear down is | ||
59 | * complete. | ||
58 | */ | 60 | */ |
59 | 61 | ||
60 | static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, | 62 | static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, |
@@ -105,7 +107,7 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, | |||
105 | mgmt->u.action.u.addba_req.start_seq_num = | 107 | mgmt->u.action.u.addba_req.start_seq_num = |
106 | cpu_to_le16(start_seq_num << 4); | 108 | cpu_to_le16(start_seq_num << 4); |
107 | 109 | ||
108 | ieee80211_tx_skb(sdata, skb); | 110 | ieee80211_tx_skb_tid(sdata, skb, tid); |
109 | } | 111 | } |
110 | 112 | ||
111 | void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn) | 113 | void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn) |
@@ -134,7 +136,7 @@ void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn) | |||
134 | bar->start_seq_num = cpu_to_le16(ssn); | 136 | bar->start_seq_num = cpu_to_le16(ssn); |
135 | 137 | ||
136 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 138 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
137 | ieee80211_tx_skb(sdata, skb); | 139 | ieee80211_tx_skb_tid(sdata, skb, tid); |
138 | } | 140 | } |
139 | EXPORT_SYMBOL(ieee80211_send_bar); | 141 | EXPORT_SYMBOL(ieee80211_send_bar); |
140 | 142 | ||
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 393b2a4445b8..66ad9d9af87f 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -746,10 +746,11 @@ static void ieee80211_send_layer2_update(struct sta_info *sta) | |||
746 | netif_rx_ni(skb); | 746 | netif_rx_ni(skb); |
747 | } | 747 | } |
748 | 748 | ||
749 | static void sta_apply_parameters(struct ieee80211_local *local, | 749 | static int sta_apply_parameters(struct ieee80211_local *local, |
750 | struct sta_info *sta, | 750 | struct sta_info *sta, |
751 | struct station_parameters *params) | 751 | struct station_parameters *params) |
752 | { | 752 | { |
753 | int ret = 0; | ||
753 | u32 rates; | 754 | u32 rates; |
754 | int i, j; | 755 | int i, j; |
755 | struct ieee80211_supported_band *sband; | 756 | struct ieee80211_supported_band *sband; |
@@ -761,13 +762,59 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
761 | mask = params->sta_flags_mask; | 762 | mask = params->sta_flags_mask; |
762 | set = params->sta_flags_set; | 763 | set = params->sta_flags_set; |
763 | 764 | ||
765 | /* | ||
766 | * In mesh mode, we can clear AUTHENTICATED flag but must | ||
767 | * also make ASSOCIATED follow appropriately for the driver | ||
768 | * API. See also below, after AUTHORIZED changes. | ||
769 | */ | ||
770 | if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) { | ||
771 | /* cfg80211 should not allow this in non-mesh modes */ | ||
772 | if (WARN_ON(!ieee80211_vif_is_mesh(&sdata->vif))) | ||
773 | return -EINVAL; | ||
774 | |||
775 | if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED) && | ||
776 | !test_sta_flag(sta, WLAN_STA_AUTH)) { | ||
777 | ret = sta_info_move_state_checked(sta, | ||
778 | IEEE80211_STA_AUTH); | ||
779 | if (ret) | ||
780 | return ret; | ||
781 | ret = sta_info_move_state_checked(sta, | ||
782 | IEEE80211_STA_ASSOC); | ||
783 | if (ret) | ||
784 | return ret; | ||
785 | } | ||
786 | } | ||
787 | |||
764 | if (mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) { | 788 | if (mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) { |
765 | if (set & BIT(NL80211_STA_FLAG_AUTHORIZED)) | 789 | if (set & BIT(NL80211_STA_FLAG_AUTHORIZED)) |
766 | set_sta_flag(sta, WLAN_STA_AUTHORIZED); | 790 | ret = sta_info_move_state_checked(sta, |
791 | IEEE80211_STA_AUTHORIZED); | ||
767 | else | 792 | else |
768 | clear_sta_flag(sta, WLAN_STA_AUTHORIZED); | 793 | ret = sta_info_move_state_checked(sta, |
794 | IEEE80211_STA_ASSOC); | ||
795 | if (ret) | ||
796 | return ret; | ||
769 | } | 797 | } |
770 | 798 | ||
799 | if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) { | ||
800 | /* cfg80211 should not allow this in non-mesh modes */ | ||
801 | if (WARN_ON(!ieee80211_vif_is_mesh(&sdata->vif))) | ||
802 | return -EINVAL; | ||
803 | |||
804 | if (!(set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) && | ||
805 | test_sta_flag(sta, WLAN_STA_AUTH)) { | ||
806 | ret = sta_info_move_state_checked(sta, | ||
807 | IEEE80211_STA_AUTH); | ||
808 | if (ret) | ||
809 | return ret; | ||
810 | ret = sta_info_move_state_checked(sta, | ||
811 | IEEE80211_STA_NONE); | ||
812 | if (ret) | ||
813 | return ret; | ||
814 | } | ||
815 | } | ||
816 | |||
817 | |||
771 | if (mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) { | 818 | if (mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) { |
772 | if (set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) | 819 | if (set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) |
773 | set_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE); | 820 | set_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE); |
@@ -792,13 +839,6 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
792 | clear_sta_flag(sta, WLAN_STA_MFP); | 839 | clear_sta_flag(sta, WLAN_STA_MFP); |
793 | } | 840 | } |
794 | 841 | ||
795 | if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) { | ||
796 | if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) | ||
797 | set_sta_flag(sta, WLAN_STA_AUTH); | ||
798 | else | ||
799 | clear_sta_flag(sta, WLAN_STA_AUTH); | ||
800 | } | ||
801 | |||
802 | if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) { | 842 | if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) { |
803 | if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) | 843 | if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) |
804 | set_sta_flag(sta, WLAN_STA_TDLS_PEER); | 844 | set_sta_flag(sta, WLAN_STA_TDLS_PEER); |
@@ -870,6 +910,8 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
870 | } | 910 | } |
871 | #endif | 911 | #endif |
872 | } | 912 | } |
913 | |||
914 | return 0; | ||
873 | } | 915 | } |
874 | 916 | ||
875 | static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | 917 | static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, |
@@ -896,20 +938,18 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
896 | if (is_multicast_ether_addr(mac)) | 938 | if (is_multicast_ether_addr(mac)) |
897 | return -EINVAL; | 939 | return -EINVAL; |
898 | 940 | ||
899 | /* Only TDLS-supporting stations can add TDLS peers */ | ||
900 | if ((params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) && | ||
901 | !((wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) && | ||
902 | sdata->vif.type == NL80211_IFTYPE_STATION)) | ||
903 | return -ENOTSUPP; | ||
904 | |||
905 | sta = sta_info_alloc(sdata, mac, GFP_KERNEL); | 941 | sta = sta_info_alloc(sdata, mac, GFP_KERNEL); |
906 | if (!sta) | 942 | if (!sta) |
907 | return -ENOMEM; | 943 | return -ENOMEM; |
908 | 944 | ||
909 | set_sta_flag(sta, WLAN_STA_AUTH); | 945 | sta_info_move_state(sta, IEEE80211_STA_AUTH); |
910 | set_sta_flag(sta, WLAN_STA_ASSOC); | 946 | sta_info_move_state(sta, IEEE80211_STA_ASSOC); |
911 | 947 | ||
912 | sta_apply_parameters(local, sta, params); | 948 | err = sta_apply_parameters(local, sta, params); |
949 | if (err) { | ||
950 | sta_info_free(local, sta); | ||
951 | return err; | ||
952 | } | ||
913 | 953 | ||
914 | /* | 954 | /* |
915 | * for TDLS, rate control should be initialized only when supported | 955 | * for TDLS, rate control should be initialized only when supported |
@@ -960,19 +1000,19 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
960 | struct sta_info *sta; | 1000 | struct sta_info *sta; |
961 | struct ieee80211_sub_if_data *vlansdata; | 1001 | struct ieee80211_sub_if_data *vlansdata; |
962 | 1002 | ||
963 | rcu_read_lock(); | 1003 | mutex_lock(&local->sta_mtx); |
964 | 1004 | ||
965 | sta = sta_info_get_bss(sdata, mac); | 1005 | sta = sta_info_get_bss(sdata, mac); |
966 | if (!sta) { | 1006 | if (!sta) { |
967 | rcu_read_unlock(); | 1007 | mutex_unlock(&local->sta_mtx); |
968 | return -ENOENT; | 1008 | return -ENOENT; |
969 | } | 1009 | } |
970 | 1010 | ||
971 | /* The TDLS bit cannot be toggled after the STA was added */ | 1011 | /* in station mode, supported rates are only valid with TDLS */ |
972 | if ((params->sta_flags_mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) && | 1012 | if (sdata->vif.type == NL80211_IFTYPE_STATION && |
973 | !!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) != | 1013 | params->supported_rates && |
974 | !!test_sta_flag(sta, WLAN_STA_TDLS_PEER)) { | 1014 | !test_sta_flag(sta, WLAN_STA_TDLS_PEER)) { |
975 | rcu_read_unlock(); | 1015 | mutex_unlock(&local->sta_mtx); |
976 | return -EINVAL; | 1016 | return -EINVAL; |
977 | } | 1017 | } |
978 | 1018 | ||
@@ -981,13 +1021,13 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
981 | 1021 | ||
982 | if (vlansdata->vif.type != NL80211_IFTYPE_AP_VLAN && | 1022 | if (vlansdata->vif.type != NL80211_IFTYPE_AP_VLAN && |
983 | vlansdata->vif.type != NL80211_IFTYPE_AP) { | 1023 | vlansdata->vif.type != NL80211_IFTYPE_AP) { |
984 | rcu_read_unlock(); | 1024 | mutex_unlock(&local->sta_mtx); |
985 | return -EINVAL; | 1025 | return -EINVAL; |
986 | } | 1026 | } |
987 | 1027 | ||
988 | if (params->vlan->ieee80211_ptr->use_4addr) { | 1028 | if (params->vlan->ieee80211_ptr->use_4addr) { |
989 | if (vlansdata->u.vlan.sta) { | 1029 | if (vlansdata->u.vlan.sta) { |
990 | rcu_read_unlock(); | 1030 | mutex_unlock(&local->sta_mtx); |
991 | return -EBUSY; | 1031 | return -EBUSY; |
992 | } | 1032 | } |
993 | 1033 | ||
@@ -1003,7 +1043,7 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
1003 | if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) && params->supported_rates) | 1043 | if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) && params->supported_rates) |
1004 | rate_control_rate_init(sta); | 1044 | rate_control_rate_init(sta); |
1005 | 1045 | ||
1006 | rcu_read_unlock(); | 1046 | mutex_unlock(&local->sta_mtx); |
1007 | 1047 | ||
1008 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | 1048 | if (sdata->vif.type == NL80211_IFTYPE_STATION && |
1009 | params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) | 1049 | params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) |
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 8df28910b8ee..176c08ffb13c 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -321,6 +321,7 @@ static ssize_t ieee80211_if_parse_tkip_mic_test( | |||
321 | __IEEE80211_IF_FILE_W(tkip_mic_test); | 321 | __IEEE80211_IF_FILE_W(tkip_mic_test); |
322 | 322 | ||
323 | /* AP attributes */ | 323 | /* AP attributes */ |
324 | IEEE80211_IF_FILE(num_sta_authorized, u.ap.num_sta_authorized, ATOMIC); | ||
324 | IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC); | 325 | IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC); |
325 | IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC); | 326 | IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC); |
326 | 327 | ||
@@ -458,6 +459,7 @@ static void add_ap_files(struct ieee80211_sub_if_data *sdata) | |||
458 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); | 459 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); |
459 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); | 460 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); |
460 | 461 | ||
462 | DEBUGFS_ADD(num_sta_authorized); | ||
461 | DEBUGFS_ADD(num_sta_ps); | 463 | DEBUGFS_ADD(num_sta_ps); |
462 | DEBUGFS_ADD(dtim_count); | 464 | DEBUGFS_ADD(dtim_count); |
463 | DEBUGFS_ADD(num_buffered_multicast); | 465 | DEBUGFS_ADD(num_buffered_multicast); |
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 0fd9c2a7f242..f25fff7607d8 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -300,7 +300,7 @@ void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, | |||
300 | mgmt->u.action.u.delba.params = cpu_to_le16(params); | 300 | mgmt->u.action.u.delba.params = cpu_to_le16(params); |
301 | mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code); | 301 | mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code); |
302 | 302 | ||
303 | ieee80211_tx_skb(sdata, skb); | 303 | ieee80211_tx_skb_tid(sdata, skb, tid); |
304 | } | 304 | } |
305 | 305 | ||
306 | void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, | 306 | void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 3f830ac159e5..f8a32bf98216 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -275,6 +275,80 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
275 | cbss->tsf); | 275 | cbss->tsf); |
276 | } | 276 | } |
277 | 277 | ||
278 | static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta) | ||
279 | __acquires(RCU) | ||
280 | { | ||
281 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
282 | u8 addr[ETH_ALEN]; | ||
283 | |||
284 | memcpy(addr, sta->sta.addr, ETH_ALEN); | ||
285 | |||
286 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
287 | wiphy_debug(sdata->local->hw.wiphy, | ||
288 | "Adding new IBSS station %pM (dev=%s)\n", | ||
289 | addr, sdata->name); | ||
290 | #endif | ||
291 | |||
292 | sta_info_move_state(sta, IEEE80211_STA_AUTH); | ||
293 | sta_info_move_state(sta, IEEE80211_STA_ASSOC); | ||
294 | sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED); | ||
295 | |||
296 | rate_control_rate_init(sta); | ||
297 | |||
298 | /* If it fails, maybe we raced another insertion? */ | ||
299 | if (sta_info_insert_rcu(sta)) | ||
300 | return sta_info_get(sdata, addr); | ||
301 | return sta; | ||
302 | } | ||
303 | |||
304 | static struct sta_info * | ||
305 | ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | ||
306 | const u8 *bssid, const u8 *addr, | ||
307 | u32 supp_rates) | ||
308 | __acquires(RCU) | ||
309 | { | ||
310 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | ||
311 | struct ieee80211_local *local = sdata->local; | ||
312 | struct sta_info *sta; | ||
313 | int band = local->hw.conf.channel->band; | ||
314 | |||
315 | /* | ||
316 | * XXX: Consider removing the least recently used entry and | ||
317 | * allow new one to be added. | ||
318 | */ | ||
319 | if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) { | ||
320 | if (net_ratelimit()) | ||
321 | printk(KERN_DEBUG "%s: No room for a new IBSS STA entry %pM\n", | ||
322 | sdata->name, addr); | ||
323 | rcu_read_lock(); | ||
324 | return NULL; | ||
325 | } | ||
326 | |||
327 | if (ifibss->state == IEEE80211_IBSS_MLME_SEARCH) { | ||
328 | rcu_read_lock(); | ||
329 | return NULL; | ||
330 | } | ||
331 | |||
332 | if (compare_ether_addr(bssid, sdata->u.ibss.bssid)) { | ||
333 | rcu_read_lock(); | ||
334 | return NULL; | ||
335 | } | ||
336 | |||
337 | sta = sta_info_alloc(sdata, addr, GFP_KERNEL); | ||
338 | if (!sta) { | ||
339 | rcu_read_lock(); | ||
340 | return NULL; | ||
341 | } | ||
342 | |||
343 | sta->last_rx = jiffies; | ||
344 | |||
345 | /* make sure mandatory rates are always added */ | ||
346 | sta->sta.supp_rates[band] = supp_rates | | ||
347 | ieee80211_mandatory_rates(local, band); | ||
348 | |||
349 | return ieee80211_ibss_finish_sta(sta); | ||
350 | } | ||
351 | |||
278 | static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | 352 | static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, |
279 | struct ieee80211_mgmt *mgmt, | 353 | struct ieee80211_mgmt *mgmt, |
280 | size_t len, | 354 | size_t len, |
@@ -334,10 +408,11 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
334 | #endif | 408 | #endif |
335 | rates_updated = true; | 409 | rates_updated = true; |
336 | } | 410 | } |
337 | } else | 411 | } else { |
412 | rcu_read_unlock(); | ||
338 | sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid, | 413 | sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid, |
339 | mgmt->sa, supp_rates, | 414 | mgmt->sa, supp_rates); |
340 | GFP_ATOMIC); | 415 | } |
341 | } | 416 | } |
342 | 417 | ||
343 | if (sta && elems->wmm_info) | 418 | if (sta && elems->wmm_info) |
@@ -464,21 +539,17 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
464 | ieee80211_sta_join_ibss(sdata, bss); | 539 | ieee80211_sta_join_ibss(sdata, bss); |
465 | supp_rates = ieee80211_sta_get_rates(local, elems, band); | 540 | supp_rates = ieee80211_sta_get_rates(local, elems, band); |
466 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, | 541 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, |
467 | supp_rates, GFP_KERNEL); | 542 | supp_rates); |
543 | rcu_read_unlock(); | ||
468 | } | 544 | } |
469 | 545 | ||
470 | put_bss: | 546 | put_bss: |
471 | ieee80211_rx_bss_put(local, bss); | 547 | ieee80211_rx_bss_put(local, bss); |
472 | } | 548 | } |
473 | 549 | ||
474 | /* | 550 | void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata, |
475 | * Add a new IBSS station, will also be called by the RX code when, | 551 | const u8 *bssid, const u8 *addr, |
476 | * in IBSS mode, receiving a frame from a yet-unknown station, hence | 552 | u32 supp_rates) |
477 | * must be callable in atomic context. | ||
478 | */ | ||
479 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | ||
480 | u8 *bssid, u8 *addr, u32 supp_rates, | ||
481 | gfp_t gfp) | ||
482 | { | 553 | { |
483 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 554 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
484 | struct ieee80211_local *local = sdata->local; | 555 | struct ieee80211_local *local = sdata->local; |
@@ -493,37 +564,29 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | |||
493 | if (net_ratelimit()) | 564 | if (net_ratelimit()) |
494 | printk(KERN_DEBUG "%s: No room for a new IBSS STA entry %pM\n", | 565 | printk(KERN_DEBUG "%s: No room for a new IBSS STA entry %pM\n", |
495 | sdata->name, addr); | 566 | sdata->name, addr); |
496 | return NULL; | 567 | return; |
497 | } | 568 | } |
498 | 569 | ||
499 | if (ifibss->state == IEEE80211_IBSS_MLME_SEARCH) | 570 | if (ifibss->state == IEEE80211_IBSS_MLME_SEARCH) |
500 | return NULL; | 571 | return; |
501 | 572 | ||
502 | if (compare_ether_addr(bssid, sdata->u.ibss.bssid)) | 573 | if (compare_ether_addr(bssid, sdata->u.ibss.bssid)) |
503 | return NULL; | 574 | return; |
504 | |||
505 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
506 | wiphy_debug(local->hw.wiphy, "Adding new IBSS station %pM (dev=%s)\n", | ||
507 | addr, sdata->name); | ||
508 | #endif | ||
509 | 575 | ||
510 | sta = sta_info_alloc(sdata, addr, gfp); | 576 | sta = sta_info_alloc(sdata, addr, GFP_ATOMIC); |
511 | if (!sta) | 577 | if (!sta) |
512 | return NULL; | 578 | return; |
513 | 579 | ||
514 | sta->last_rx = jiffies; | 580 | sta->last_rx = jiffies; |
515 | set_sta_flag(sta, WLAN_STA_AUTHORIZED); | ||
516 | 581 | ||
517 | /* make sure mandatory rates are always added */ | 582 | /* make sure mandatory rates are always added */ |
518 | sta->sta.supp_rates[band] = supp_rates | | 583 | sta->sta.supp_rates[band] = supp_rates | |
519 | ieee80211_mandatory_rates(local, band); | 584 | ieee80211_mandatory_rates(local, band); |
520 | 585 | ||
521 | rate_control_rate_init(sta); | 586 | spin_lock(&ifibss->incomplete_lock); |
522 | 587 | list_add(&sta->list, &ifibss->incomplete_stations); | |
523 | /* If it fails, maybe we raced another insertion? */ | 588 | spin_unlock(&ifibss->incomplete_lock); |
524 | if (sta_info_insert(sta)) | 589 | ieee80211_queue_work(&local->hw, &sdata->work); |
525 | return sta_info_get(sdata, addr); | ||
526 | return sta; | ||
527 | } | 590 | } |
528 | 591 | ||
529 | static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata) | 592 | static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata) |
@@ -862,6 +925,7 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
862 | void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata) | 925 | void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata) |
863 | { | 926 | { |
864 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 927 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
928 | struct sta_info *sta; | ||
865 | 929 | ||
866 | mutex_lock(&ifibss->mtx); | 930 | mutex_lock(&ifibss->mtx); |
867 | 931 | ||
@@ -873,6 +937,19 @@ void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata) | |||
873 | if (!ifibss->ssid_len) | 937 | if (!ifibss->ssid_len) |
874 | goto out; | 938 | goto out; |
875 | 939 | ||
940 | spin_lock_bh(&ifibss->incomplete_lock); | ||
941 | while (!list_empty(&ifibss->incomplete_stations)) { | ||
942 | sta = list_first_entry(&ifibss->incomplete_stations, | ||
943 | struct sta_info, list); | ||
944 | list_del(&sta->list); | ||
945 | spin_unlock_bh(&ifibss->incomplete_lock); | ||
946 | |||
947 | ieee80211_ibss_finish_sta(sta); | ||
948 | rcu_read_unlock(); | ||
949 | spin_lock_bh(&ifibss->incomplete_lock); | ||
950 | } | ||
951 | spin_unlock_bh(&ifibss->incomplete_lock); | ||
952 | |||
876 | switch (ifibss->state) { | 953 | switch (ifibss->state) { |
877 | case IEEE80211_IBSS_MLME_SEARCH: | 954 | case IEEE80211_IBSS_MLME_SEARCH: |
878 | ieee80211_sta_find_ibss(sdata); | 955 | ieee80211_sta_find_ibss(sdata); |
@@ -931,6 +1008,8 @@ void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata) | |||
931 | setup_timer(&ifibss->timer, ieee80211_ibss_timer, | 1008 | setup_timer(&ifibss->timer, ieee80211_ibss_timer, |
932 | (unsigned long) sdata); | 1009 | (unsigned long) sdata); |
933 | mutex_init(&ifibss->mtx); | 1010 | mutex_init(&ifibss->mtx); |
1011 | INIT_LIST_HEAD(&ifibss->incomplete_stations); | ||
1012 | spin_lock_init(&ifibss->incomplete_lock); | ||
934 | } | 1013 | } |
935 | 1014 | ||
936 | /* scan finished notification */ | 1015 | /* scan finished notification */ |
@@ -993,8 +1072,11 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
993 | if (params->channel_fixed) { | 1072 | if (params->channel_fixed) { |
994 | sdata->local->oper_channel = params->channel; | 1073 | sdata->local->oper_channel = params->channel; |
995 | if (!ieee80211_set_channel_type(sdata->local, sdata, | 1074 | if (!ieee80211_set_channel_type(sdata->local, sdata, |
996 | params->channel_type)) | 1075 | params->channel_type)) { |
1076 | mutex_unlock(&sdata->u.ibss.mtx); | ||
1077 | kfree_skb(skb); | ||
997 | return -EINVAL; | 1078 | return -EINVAL; |
1079 | } | ||
998 | } | 1080 | } |
999 | 1081 | ||
1000 | if (params->ie) { | 1082 | if (params->ie) { |
@@ -1047,6 +1129,7 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) | |||
1047 | struct cfg80211_bss *cbss; | 1129 | struct cfg80211_bss *cbss; |
1048 | u16 capability; | 1130 | u16 capability; |
1049 | int active_ibss; | 1131 | int active_ibss; |
1132 | struct sta_info *sta; | ||
1050 | 1133 | ||
1051 | mutex_lock(&sdata->u.ibss.mtx); | 1134 | mutex_lock(&sdata->u.ibss.mtx); |
1052 | 1135 | ||
@@ -1075,6 +1158,19 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) | |||
1075 | } | 1158 | } |
1076 | 1159 | ||
1077 | sta_info_flush(sdata->local, sdata); | 1160 | sta_info_flush(sdata->local, sdata); |
1161 | |||
1162 | spin_lock_bh(&ifibss->incomplete_lock); | ||
1163 | while (!list_empty(&ifibss->incomplete_stations)) { | ||
1164 | sta = list_first_entry(&ifibss->incomplete_stations, | ||
1165 | struct sta_info, list); | ||
1166 | list_del(&sta->list); | ||
1167 | spin_unlock_bh(&ifibss->incomplete_lock); | ||
1168 | |||
1169 | sta_info_free(local, sta); | ||
1170 | spin_lock_bh(&ifibss->incomplete_lock); | ||
1171 | } | ||
1172 | spin_unlock_bh(&ifibss->incomplete_lock); | ||
1173 | |||
1078 | netif_carrier_off(sdata->dev); | 1174 | netif_carrier_off(sdata->dev); |
1079 | 1175 | ||
1080 | /* remove beacon */ | 1176 | /* remove beacon */ |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 96fe75410bbe..c3f3e431a573 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -243,6 +243,7 @@ struct ieee80211_if_ap { | |||
243 | u8 tim[sizeof(unsigned long) * BITS_TO_LONGS(IEEE80211_MAX_AID + 1)]; | 243 | u8 tim[sizeof(unsigned long) * BITS_TO_LONGS(IEEE80211_MAX_AID + 1)]; |
244 | struct sk_buff_head ps_bc_buf; | 244 | struct sk_buff_head ps_bc_buf; |
245 | atomic_t num_sta_ps; /* number of stations in PS mode */ | 245 | atomic_t num_sta_ps; /* number of stations in PS mode */ |
246 | atomic_t num_sta_authorized; /* number of authorized stations */ | ||
246 | int dtim_count; | 247 | int dtim_count; |
247 | bool dtim_bc_mc; | 248 | bool dtim_bc_mc; |
248 | }; | 249 | }; |
@@ -481,6 +482,9 @@ struct ieee80211_if_ibss { | |||
481 | struct sk_buff __rcu *presp; | 482 | struct sk_buff __rcu *presp; |
482 | struct sk_buff *skb; | 483 | struct sk_buff *skb; |
483 | 484 | ||
485 | spinlock_t incomplete_lock; | ||
486 | struct list_head incomplete_stations; | ||
487 | |||
484 | enum { | 488 | enum { |
485 | IEEE80211_IBSS_MLME_SEARCH, | 489 | IEEE80211_IBSS_MLME_SEARCH, |
486 | IEEE80211_IBSS_MLME_JOINED, | 490 | IEEE80211_IBSS_MLME_JOINED, |
@@ -851,18 +855,15 @@ struct ieee80211_local { | |||
851 | 855 | ||
852 | /* Station data */ | 856 | /* Station data */ |
853 | /* | 857 | /* |
854 | * The mutex only protects the list and counter, | 858 | * The mutex only protects the list, hash table and |
855 | * reads are done in RCU. | 859 | * counter, reads are done with RCU. |
856 | * Additionally, the lock protects the hash table, | ||
857 | * the pending list and each BSS's TIM bitmap. | ||
858 | */ | 860 | */ |
859 | struct mutex sta_mtx; | 861 | struct mutex sta_mtx; |
860 | spinlock_t sta_lock; | 862 | spinlock_t tim_lock; |
861 | unsigned long num_sta; | 863 | unsigned long num_sta; |
862 | struct list_head sta_list, sta_pending_list; | 864 | struct list_head sta_list; |
863 | struct sta_info __rcu *sta_hash[STA_HASH_SIZE]; | 865 | struct sta_info __rcu *sta_hash[STA_HASH_SIZE]; |
864 | struct timer_list sta_cleanup; | 866 | struct timer_list sta_cleanup; |
865 | struct work_struct sta_finish_work; | ||
866 | int sta_generation; | 867 | int sta_generation; |
867 | 868 | ||
868 | struct sk_buff_head pending[IEEE80211_MAX_QUEUES]; | 869 | struct sk_buff_head pending[IEEE80211_MAX_QUEUES]; |
@@ -1171,9 +1172,8 @@ void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata); | |||
1171 | /* IBSS code */ | 1172 | /* IBSS code */ |
1172 | void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local); | 1173 | void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local); |
1173 | void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata); | 1174 | void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata); |
1174 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | 1175 | void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata, |
1175 | u8 *bssid, u8 *addr, u32 supp_rates, | 1176 | const u8 *bssid, const u8 *addr, u32 supp_rates); |
1176 | gfp_t gfp); | ||
1177 | int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | 1177 | int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, |
1178 | struct cfg80211_ibss_params *params); | 1178 | struct cfg80211_ibss_params *params); |
1179 | int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata); | 1179 | int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata); |
@@ -1349,7 +1349,16 @@ void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int ke | |||
1349 | gfp_t gfp); | 1349 | gfp_t gfp); |
1350 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata); | 1350 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata); |
1351 | void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); | 1351 | void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); |
1352 | void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); | 1352 | |
1353 | void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata, | ||
1354 | struct sk_buff *skb, int tid); | ||
1355 | static void inline ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, | ||
1356 | struct sk_buff *skb) | ||
1357 | { | ||
1358 | /* Send all internal mgmt frames on VO. Accordingly set TID to 7. */ | ||
1359 | ieee80211_tx_skb_tid(sdata, skb, 7); | ||
1360 | } | ||
1361 | |||
1353 | void ieee802_11_parse_elems(u8 *start, size_t len, | 1362 | void ieee802_11_parse_elems(u8 *start, size_t len, |
1354 | struct ieee802_11_elems *elems); | 1363 | struct ieee802_11_elems *elems); |
1355 | u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, | 1364 | u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 3d3bb5e9d8fa..e47768cb8cb3 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -318,8 +318,9 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
318 | goto err_del_interface; | 318 | goto err_del_interface; |
319 | } | 319 | } |
320 | 320 | ||
321 | /* no atomic bitop required since STA is not live yet */ | 321 | sta_info_move_state(sta, IEEE80211_STA_AUTH); |
322 | set_sta_flag(sta, WLAN_STA_AUTHORIZED); | 322 | sta_info_move_state(sta, IEEE80211_STA_ASSOC); |
323 | sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED); | ||
323 | 324 | ||
324 | res = sta_info_insert(sta); | 325 | res = sta_info_insert(sta); |
325 | if (res) { | 326 | if (res) { |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 60198ac664a0..0a0d94ad9b08 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -47,7 +47,7 @@ void ieee80211_configure_filter(struct ieee80211_local *local) | |||
47 | if (atomic_read(&local->iff_allmultis)) | 47 | if (atomic_read(&local->iff_allmultis)) |
48 | new_flags |= FIF_ALLMULTI; | 48 | new_flags |= FIF_ALLMULTI; |
49 | 49 | ||
50 | if (local->monitors || local->scanning) | 50 | if (local->monitors || test_bit(SCAN_SW_SCANNING, &local->scanning)) |
51 | new_flags |= FIF_BCN_PRBRESP_PROMISC; | 51 | new_flags |= FIF_BCN_PRBRESP_PROMISC; |
52 | 52 | ||
53 | if (local->fif_probe_req || local->probe_req_reg) | 53 | if (local->fif_probe_req || local->probe_req_reg) |
@@ -150,8 +150,8 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | |||
150 | changed |= IEEE80211_CONF_CHANGE_SMPS; | 150 | changed |= IEEE80211_CONF_CHANGE_SMPS; |
151 | } | 151 | } |
152 | 152 | ||
153 | if ((local->scanning & SCAN_SW_SCANNING) || | 153 | if (test_bit(SCAN_SW_SCANNING, &local->scanning) || |
154 | (local->scanning & SCAN_HW_SCANNING)) | 154 | test_bit(SCAN_HW_SCANNING, &local->scanning)) |
155 | power = chan->max_power; | 155 | power = chan->max_power; |
156 | else | 156 | else |
157 | power = local->power_constr_level ? | 157 | power = local->power_constr_level ? |
@@ -393,9 +393,6 @@ static int ieee80211_ifa_changed(struct notifier_block *nb, | |||
393 | sdata = IEEE80211_DEV_TO_SUB_IF(ndev); | 393 | sdata = IEEE80211_DEV_TO_SUB_IF(ndev); |
394 | bss_conf = &sdata->vif.bss_conf; | 394 | bss_conf = &sdata->vif.bss_conf; |
395 | 395 | ||
396 | if (!ieee80211_sdata_running(sdata)) | ||
397 | return NOTIFY_DONE; | ||
398 | |||
399 | /* ARP filtering is only supported in managed mode */ | 396 | /* ARP filtering is only supported in managed mode */ |
400 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 397 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
401 | return NOTIFY_DONE; | 398 | return NOTIFY_DONE; |
@@ -424,7 +421,7 @@ static int ieee80211_ifa_changed(struct notifier_block *nb, | |||
424 | } | 421 | } |
425 | bss_conf->arp_addr_cnt = c; | 422 | bss_conf->arp_addr_cnt = c; |
426 | 423 | ||
427 | /* Configure driver only if associated */ | 424 | /* Configure driver only if associated (which also implies it is up) */ |
428 | if (ifmgd->associated) { | 425 | if (ifmgd->associated) { |
429 | bss_conf->arp_filter_enabled = sdata->arp_filter_state; | 426 | bss_conf->arp_filter_enabled = sdata->arp_filter_state; |
430 | ieee80211_bss_info_change_notify(sdata, | 427 | ieee80211_bss_info_change_notify(sdata, |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 7314372b12ba..41ef1b476442 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -96,9 +96,12 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, | |||
96 | if (!sta) | 96 | if (!sta) |
97 | return NULL; | 97 | return NULL; |
98 | 98 | ||
99 | set_sta_flag(sta, WLAN_STA_AUTH); | 99 | sta_info_move_state(sta, IEEE80211_STA_AUTH); |
100 | set_sta_flag(sta, WLAN_STA_AUTHORIZED); | 100 | sta_info_move_state(sta, IEEE80211_STA_ASSOC); |
101 | sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED); | ||
102 | |||
101 | set_sta_flag(sta, WLAN_STA_WME); | 103 | set_sta_flag(sta, WLAN_STA_WME); |
104 | |||
102 | sta->sta.supp_rates[local->hw.conf.channel->band] = rates; | 105 | sta->sta.supp_rates[local->hw.conf.channel->band] = rates; |
103 | if (elems->ht_cap_elem) | 106 | if (elems->ht_cap_elem) |
104 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, | 107 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 09019d135942..a984f1f60ddb 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -819,7 +819,7 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) | |||
819 | } | 819 | } |
820 | 820 | ||
821 | if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && | 821 | if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && |
822 | (!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED))) { | 822 | !(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED)) { |
823 | netif_tx_stop_all_queues(sdata->dev); | 823 | netif_tx_stop_all_queues(sdata->dev); |
824 | 824 | ||
825 | if (drv_tx_frames_pending(local)) | 825 | if (drv_tx_frames_pending(local)) |
@@ -1577,10 +1577,10 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, | |||
1577 | return false; | 1577 | return false; |
1578 | } | 1578 | } |
1579 | 1579 | ||
1580 | set_sta_flag(sta, WLAN_STA_AUTH); | 1580 | sta_info_move_state(sta, IEEE80211_STA_AUTH); |
1581 | set_sta_flag(sta, WLAN_STA_ASSOC); | 1581 | sta_info_move_state(sta, IEEE80211_STA_ASSOC); |
1582 | if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) | 1582 | if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) |
1583 | set_sta_flag(sta, WLAN_STA_AUTHORIZED); | 1583 | sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED); |
1584 | 1584 | ||
1585 | rates = 0; | 1585 | rates = 0; |
1586 | basic_rates = 0; | 1586 | basic_rates = 0; |
@@ -2371,6 +2371,7 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) | |||
2371 | (unsigned long) sdata); | 2371 | (unsigned long) sdata); |
2372 | 2372 | ||
2373 | ifmgd->flags = 0; | 2373 | ifmgd->flags = 0; |
2374 | ifmgd->powersave = sdata->wdev.ps; | ||
2374 | 2375 | ||
2375 | mutex_init(&ifmgd->mtx); | 2376 | mutex_init(&ifmgd->mtx); |
2376 | 2377 | ||
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 7d226417ef46..2be5b7d69ad7 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -2775,8 +2775,8 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx, | |||
2775 | rate_idx = 0; /* TODO: HT rates */ | 2775 | rate_idx = 0; /* TODO: HT rates */ |
2776 | else | 2776 | else |
2777 | rate_idx = status->rate_idx; | 2777 | rate_idx = status->rate_idx; |
2778 | rx->sta = ieee80211_ibss_add_sta(sdata, bssid, | 2778 | ieee80211_ibss_rx_no_sta(sdata, bssid, hdr->addr2, |
2779 | hdr->addr2, BIT(rate_idx), GFP_ATOMIC); | 2779 | BIT(rate_idx)); |
2780 | } | 2780 | } |
2781 | break; | 2781 | break; |
2782 | case NL80211_IFTYPE_MESH_POINT: | 2782 | case NL80211_IFTYPE_MESH_POINT: |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index f98235262006..2db01e9541e7 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -62,14 +62,14 @@ | |||
62 | * freed before they are done using it. | 62 | * freed before they are done using it. |
63 | */ | 63 | */ |
64 | 64 | ||
65 | /* Caller must hold local->sta_lock */ | 65 | /* Caller must hold local->sta_mtx */ |
66 | static int sta_info_hash_del(struct ieee80211_local *local, | 66 | static int sta_info_hash_del(struct ieee80211_local *local, |
67 | struct sta_info *sta) | 67 | struct sta_info *sta) |
68 | { | 68 | { |
69 | struct sta_info *s; | 69 | struct sta_info *s; |
70 | 70 | ||
71 | s = rcu_dereference_protected(local->sta_hash[STA_HASH(sta->sta.addr)], | 71 | s = rcu_dereference_protected(local->sta_hash[STA_HASH(sta->sta.addr)], |
72 | lockdep_is_held(&local->sta_lock)); | 72 | lockdep_is_held(&local->sta_mtx)); |
73 | if (!s) | 73 | if (!s) |
74 | return -ENOENT; | 74 | return -ENOENT; |
75 | if (s == sta) { | 75 | if (s == sta) { |
@@ -81,7 +81,7 @@ static int sta_info_hash_del(struct ieee80211_local *local, | |||
81 | while (rcu_access_pointer(s->hnext) && | 81 | while (rcu_access_pointer(s->hnext) && |
82 | rcu_access_pointer(s->hnext) != sta) | 82 | rcu_access_pointer(s->hnext) != sta) |
83 | s = rcu_dereference_protected(s->hnext, | 83 | s = rcu_dereference_protected(s->hnext, |
84 | lockdep_is_held(&local->sta_lock)); | 84 | lockdep_is_held(&local->sta_mtx)); |
85 | if (rcu_access_pointer(s->hnext)) { | 85 | if (rcu_access_pointer(s->hnext)) { |
86 | RCU_INIT_POINTER(s->hnext, sta->hnext); | 86 | RCU_INIT_POINTER(s->hnext, sta->hnext); |
87 | return 0; | 87 | return 0; |
@@ -98,14 +98,12 @@ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, | |||
98 | struct sta_info *sta; | 98 | struct sta_info *sta; |
99 | 99 | ||
100 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], | 100 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], |
101 | lockdep_is_held(&local->sta_lock) || | ||
102 | lockdep_is_held(&local->sta_mtx)); | 101 | lockdep_is_held(&local->sta_mtx)); |
103 | while (sta) { | 102 | while (sta) { |
104 | if (sta->sdata == sdata && !sta->dummy && | 103 | if (sta->sdata == sdata && !sta->dummy && |
105 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | 104 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) |
106 | break; | 105 | break; |
107 | sta = rcu_dereference_check(sta->hnext, | 106 | sta = rcu_dereference_check(sta->hnext, |
108 | lockdep_is_held(&local->sta_lock) || | ||
109 | lockdep_is_held(&local->sta_mtx)); | 107 | lockdep_is_held(&local->sta_mtx)); |
110 | } | 108 | } |
111 | return sta; | 109 | return sta; |
@@ -119,14 +117,12 @@ struct sta_info *sta_info_get_rx(struct ieee80211_sub_if_data *sdata, | |||
119 | struct sta_info *sta; | 117 | struct sta_info *sta; |
120 | 118 | ||
121 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], | 119 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], |
122 | lockdep_is_held(&local->sta_lock) || | ||
123 | lockdep_is_held(&local->sta_mtx)); | 120 | lockdep_is_held(&local->sta_mtx)); |
124 | while (sta) { | 121 | while (sta) { |
125 | if (sta->sdata == sdata && | 122 | if (sta->sdata == sdata && |
126 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | 123 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) |
127 | break; | 124 | break; |
128 | sta = rcu_dereference_check(sta->hnext, | 125 | sta = rcu_dereference_check(sta->hnext, |
129 | lockdep_is_held(&local->sta_lock) || | ||
130 | lockdep_is_held(&local->sta_mtx)); | 126 | lockdep_is_held(&local->sta_mtx)); |
131 | } | 127 | } |
132 | return sta; | 128 | return sta; |
@@ -143,7 +139,6 @@ struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, | |||
143 | struct sta_info *sta; | 139 | struct sta_info *sta; |
144 | 140 | ||
145 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], | 141 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], |
146 | lockdep_is_held(&local->sta_lock) || | ||
147 | lockdep_is_held(&local->sta_mtx)); | 142 | lockdep_is_held(&local->sta_mtx)); |
148 | while (sta) { | 143 | while (sta) { |
149 | if ((sta->sdata == sdata || | 144 | if ((sta->sdata == sdata || |
@@ -152,7 +147,6 @@ struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, | |||
152 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | 147 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) |
153 | break; | 148 | break; |
154 | sta = rcu_dereference_check(sta->hnext, | 149 | sta = rcu_dereference_check(sta->hnext, |
155 | lockdep_is_held(&local->sta_lock) || | ||
156 | lockdep_is_held(&local->sta_mtx)); | 150 | lockdep_is_held(&local->sta_mtx)); |
157 | } | 151 | } |
158 | return sta; | 152 | return sta; |
@@ -169,7 +163,6 @@ struct sta_info *sta_info_get_bss_rx(struct ieee80211_sub_if_data *sdata, | |||
169 | struct sta_info *sta; | 163 | struct sta_info *sta; |
170 | 164 | ||
171 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], | 165 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], |
172 | lockdep_is_held(&local->sta_lock) || | ||
173 | lockdep_is_held(&local->sta_mtx)); | 166 | lockdep_is_held(&local->sta_mtx)); |
174 | while (sta) { | 167 | while (sta) { |
175 | if ((sta->sdata == sdata || | 168 | if ((sta->sdata == sdata || |
@@ -177,7 +170,6 @@ struct sta_info *sta_info_get_bss_rx(struct ieee80211_sub_if_data *sdata, | |||
177 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | 170 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) |
178 | break; | 171 | break; |
179 | sta = rcu_dereference_check(sta->hnext, | 172 | sta = rcu_dereference_check(sta->hnext, |
180 | lockdep_is_held(&local->sta_lock) || | ||
181 | lockdep_is_held(&local->sta_mtx)); | 173 | lockdep_is_held(&local->sta_mtx)); |
182 | } | 174 | } |
183 | return sta; | 175 | return sta; |
@@ -204,16 +196,17 @@ struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata, | |||
204 | } | 196 | } |
205 | 197 | ||
206 | /** | 198 | /** |
207 | * __sta_info_free - internal STA free helper | 199 | * sta_info_free - free STA |
208 | * | 200 | * |
209 | * @local: pointer to the global information | 201 | * @local: pointer to the global information |
210 | * @sta: STA info to free | 202 | * @sta: STA info to free |
211 | * | 203 | * |
212 | * This function must undo everything done by sta_info_alloc() | 204 | * This function must undo everything done by sta_info_alloc() |
213 | * that may happen before sta_info_insert(). | 205 | * that may happen before sta_info_insert(). It may only be |
206 | * called when sta_info_insert() has not been attempted (and | ||
207 | * if that fails, the station is freed anyway.) | ||
214 | */ | 208 | */ |
215 | static void __sta_info_free(struct ieee80211_local *local, | 209 | void sta_info_free(struct ieee80211_local *local, struct sta_info *sta) |
216 | struct sta_info *sta) | ||
217 | { | 210 | { |
218 | if (sta->rate_ctrl) { | 211 | if (sta->rate_ctrl) { |
219 | rate_control_free_sta(sta); | 212 | rate_control_free_sta(sta); |
@@ -227,10 +220,11 @@ static void __sta_info_free(struct ieee80211_local *local, | |||
227 | kfree(sta); | 220 | kfree(sta); |
228 | } | 221 | } |
229 | 222 | ||
230 | /* Caller must hold local->sta_lock */ | 223 | /* Caller must hold local->sta_mtx */ |
231 | static void sta_info_hash_add(struct ieee80211_local *local, | 224 | static void sta_info_hash_add(struct ieee80211_local *local, |
232 | struct sta_info *sta) | 225 | struct sta_info *sta) |
233 | { | 226 | { |
227 | lockdep_assert_held(&local->sta_mtx); | ||
234 | sta->hnext = local->sta_hash[STA_HASH(sta->sta.addr)]; | 228 | sta->hnext = local->sta_hash[STA_HASH(sta->sta.addr)]; |
235 | RCU_INIT_POINTER(local->sta_hash[STA_HASH(sta->sta.addr)], sta); | 229 | RCU_INIT_POINTER(local->sta_hash[STA_HASH(sta->sta.addr)], sta); |
236 | } | 230 | } |
@@ -280,7 +274,7 @@ static int sta_prepare_rate_control(struct ieee80211_local *local, | |||
280 | } | 274 | } |
281 | 275 | ||
282 | struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | 276 | struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, |
283 | u8 *addr, gfp_t gfp) | 277 | const u8 *addr, gfp_t gfp) |
284 | { | 278 | { |
285 | struct ieee80211_local *local = sdata->local; | 279 | struct ieee80211_local *local = sdata->local; |
286 | struct sta_info *sta; | 280 | struct sta_info *sta; |
@@ -338,98 +332,6 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
338 | return sta; | 332 | return sta; |
339 | } | 333 | } |
340 | 334 | ||
341 | static int sta_info_finish_insert(struct sta_info *sta, | ||
342 | bool async, bool dummy_reinsert) | ||
343 | { | ||
344 | struct ieee80211_local *local = sta->local; | ||
345 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
346 | struct station_info sinfo; | ||
347 | unsigned long flags; | ||
348 | int err = 0; | ||
349 | |||
350 | lockdep_assert_held(&local->sta_mtx); | ||
351 | |||
352 | if (!sta->dummy || dummy_reinsert) { | ||
353 | /* notify driver */ | ||
354 | err = drv_sta_add(local, sdata, &sta->sta); | ||
355 | if (err) { | ||
356 | if (!async) | ||
357 | return err; | ||
358 | printk(KERN_DEBUG "%s: failed to add IBSS STA %pM to " | ||
359 | "driver (%d) - keeping it anyway.\n", | ||
360 | sdata->name, sta->sta.addr, err); | ||
361 | } else { | ||
362 | sta->uploaded = true; | ||
363 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
364 | if (async) | ||
365 | wiphy_debug(local->hw.wiphy, | ||
366 | "Finished adding IBSS STA %pM\n", | ||
367 | sta->sta.addr); | ||
368 | #endif | ||
369 | } | ||
370 | |||
371 | sdata = sta->sdata; | ||
372 | } | ||
373 | |||
374 | if (!dummy_reinsert) { | ||
375 | if (!async) { | ||
376 | local->num_sta++; | ||
377 | local->sta_generation++; | ||
378 | smp_mb(); | ||
379 | |||
380 | /* make the station visible */ | ||
381 | spin_lock_irqsave(&local->sta_lock, flags); | ||
382 | sta_info_hash_add(local, sta); | ||
383 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
384 | } | ||
385 | |||
386 | list_add(&sta->list, &local->sta_list); | ||
387 | } else { | ||
388 | sta->dummy = false; | ||
389 | } | ||
390 | |||
391 | if (!sta->dummy) { | ||
392 | ieee80211_sta_debugfs_add(sta); | ||
393 | rate_control_add_sta_debugfs(sta); | ||
394 | |||
395 | memset(&sinfo, 0, sizeof(sinfo)); | ||
396 | sinfo.filled = 0; | ||
397 | sinfo.generation = local->sta_generation; | ||
398 | cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL); | ||
399 | } | ||
400 | |||
401 | return 0; | ||
402 | } | ||
403 | |||
404 | static void sta_info_finish_pending(struct ieee80211_local *local) | ||
405 | { | ||
406 | struct sta_info *sta; | ||
407 | unsigned long flags; | ||
408 | |||
409 | spin_lock_irqsave(&local->sta_lock, flags); | ||
410 | while (!list_empty(&local->sta_pending_list)) { | ||
411 | sta = list_first_entry(&local->sta_pending_list, | ||
412 | struct sta_info, list); | ||
413 | list_del(&sta->list); | ||
414 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
415 | |||
416 | sta_info_finish_insert(sta, true, false); | ||
417 | |||
418 | spin_lock_irqsave(&local->sta_lock, flags); | ||
419 | } | ||
420 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
421 | } | ||
422 | |||
423 | static void sta_info_finish_work(struct work_struct *work) | ||
424 | { | ||
425 | struct ieee80211_local *local = | ||
426 | container_of(work, struct ieee80211_local, sta_finish_work); | ||
427 | |||
428 | mutex_lock(&local->sta_mtx); | ||
429 | sta_info_finish_pending(local); | ||
430 | mutex_unlock(&local->sta_mtx); | ||
431 | } | ||
432 | |||
433 | static int sta_info_insert_check(struct sta_info *sta) | 335 | static int sta_info_insert_check(struct sta_info *sta) |
434 | { | 336 | { |
435 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 337 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
@@ -449,50 +351,15 @@ static int sta_info_insert_check(struct sta_info *sta) | |||
449 | return 0; | 351 | return 0; |
450 | } | 352 | } |
451 | 353 | ||
452 | static int sta_info_insert_ibss(struct sta_info *sta) __acquires(RCU) | ||
453 | { | ||
454 | struct ieee80211_local *local = sta->local; | ||
455 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
456 | unsigned long flags; | ||
457 | |||
458 | spin_lock_irqsave(&local->sta_lock, flags); | ||
459 | /* check if STA exists already */ | ||
460 | if (sta_info_get_bss_rx(sdata, sta->sta.addr)) { | ||
461 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
462 | rcu_read_lock(); | ||
463 | return -EEXIST; | ||
464 | } | ||
465 | |||
466 | local->num_sta++; | ||
467 | local->sta_generation++; | ||
468 | smp_mb(); | ||
469 | sta_info_hash_add(local, sta); | ||
470 | |||
471 | list_add_tail(&sta->list, &local->sta_pending_list); | ||
472 | |||
473 | rcu_read_lock(); | ||
474 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
475 | |||
476 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
477 | wiphy_debug(local->hw.wiphy, "Added IBSS STA %pM\n", | ||
478 | sta->sta.addr); | ||
479 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | ||
480 | |||
481 | ieee80211_queue_work(&local->hw, &local->sta_finish_work); | ||
482 | |||
483 | return 0; | ||
484 | } | ||
485 | |||
486 | /* | 354 | /* |
487 | * should be called with sta_mtx locked | 355 | * should be called with sta_mtx locked |
488 | * this function replaces the mutex lock | 356 | * this function replaces the mutex lock |
489 | * with a RCU lock | 357 | * with a RCU lock |
490 | */ | 358 | */ |
491 | static int sta_info_insert_non_ibss(struct sta_info *sta) __acquires(RCU) | 359 | static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU) |
492 | { | 360 | { |
493 | struct ieee80211_local *local = sta->local; | 361 | struct ieee80211_local *local = sta->local; |
494 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 362 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
495 | unsigned long flags; | ||
496 | struct sta_info *exist_sta; | 363 | struct sta_info *exist_sta; |
497 | bool dummy_reinsert = false; | 364 | bool dummy_reinsert = false; |
498 | int err = 0; | 365 | int err = 0; |
@@ -500,19 +367,8 @@ static int sta_info_insert_non_ibss(struct sta_info *sta) __acquires(RCU) | |||
500 | lockdep_assert_held(&local->sta_mtx); | 367 | lockdep_assert_held(&local->sta_mtx); |
501 | 368 | ||
502 | /* | 369 | /* |
503 | * On first glance, this will look racy, because the code | ||
504 | * in this function, which inserts a station with sleeping, | ||
505 | * unlocks the sta_lock between checking existence in the | ||
506 | * hash table and inserting into it. | ||
507 | * | ||
508 | * However, it is not racy against itself because it keeps | ||
509 | * the mutex locked. | ||
510 | */ | ||
511 | |||
512 | spin_lock_irqsave(&local->sta_lock, flags); | ||
513 | /* | ||
514 | * check if STA exists already. | 370 | * check if STA exists already. |
515 | * only accept a scenario of a second call to sta_info_insert_non_ibss | 371 | * only accept a scenario of a second call to sta_info_insert_finish |
516 | * with a dummy station entry that was inserted earlier | 372 | * with a dummy station entry that was inserted earlier |
517 | * in that case - assume that the dummy station flag should | 373 | * in that case - assume that the dummy station flag should |
518 | * be removed. | 374 | * be removed. |
@@ -522,20 +378,47 @@ static int sta_info_insert_non_ibss(struct sta_info *sta) __acquires(RCU) | |||
522 | if (exist_sta == sta && sta->dummy) { | 378 | if (exist_sta == sta && sta->dummy) { |
523 | dummy_reinsert = true; | 379 | dummy_reinsert = true; |
524 | } else { | 380 | } else { |
525 | spin_unlock_irqrestore(&local->sta_lock, flags); | 381 | err = -EEXIST; |
526 | mutex_unlock(&local->sta_mtx); | 382 | goto out_err; |
527 | rcu_read_lock(); | ||
528 | return -EEXIST; | ||
529 | } | 383 | } |
530 | } | 384 | } |
531 | 385 | ||
532 | spin_unlock_irqrestore(&local->sta_lock, flags); | 386 | if (!sta->dummy || dummy_reinsert) { |
387 | /* notify driver */ | ||
388 | err = drv_sta_add(local, sdata, &sta->sta); | ||
389 | if (err) { | ||
390 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC) | ||
391 | goto out_err; | ||
392 | printk(KERN_DEBUG "%s: failed to add IBSS STA %pM to " | ||
393 | "driver (%d) - keeping it anyway.\n", | ||
394 | sdata->name, sta->sta.addr, err); | ||
395 | } else | ||
396 | sta->uploaded = true; | ||
397 | } | ||
533 | 398 | ||
534 | err = sta_info_finish_insert(sta, false, dummy_reinsert); | 399 | if (!dummy_reinsert) { |
535 | if (err) { | 400 | local->num_sta++; |
536 | mutex_unlock(&local->sta_mtx); | 401 | local->sta_generation++; |
537 | rcu_read_lock(); | 402 | smp_mb(); |
538 | return err; | 403 | |
404 | /* make the station visible */ | ||
405 | sta_info_hash_add(local, sta); | ||
406 | |||
407 | list_add(&sta->list, &local->sta_list); | ||
408 | } else { | ||
409 | sta->dummy = false; | ||
410 | } | ||
411 | |||
412 | if (!sta->dummy) { | ||
413 | struct station_info sinfo; | ||
414 | |||
415 | ieee80211_sta_debugfs_add(sta); | ||
416 | rate_control_add_sta_debugfs(sta); | ||
417 | |||
418 | memset(&sinfo, 0, sizeof(sinfo)); | ||
419 | sinfo.filled = 0; | ||
420 | sinfo.generation = local->sta_generation; | ||
421 | cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL); | ||
539 | } | 422 | } |
540 | 423 | ||
541 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 424 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
@@ -551,54 +434,35 @@ static int sta_info_insert_non_ibss(struct sta_info *sta) __acquires(RCU) | |||
551 | mesh_accept_plinks_update(sdata); | 434 | mesh_accept_plinks_update(sdata); |
552 | 435 | ||
553 | return 0; | 436 | return 0; |
437 | out_err: | ||
438 | mutex_unlock(&local->sta_mtx); | ||
439 | rcu_read_lock(); | ||
440 | return err; | ||
554 | } | 441 | } |
555 | 442 | ||
556 | int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU) | 443 | int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU) |
557 | { | 444 | { |
558 | struct ieee80211_local *local = sta->local; | 445 | struct ieee80211_local *local = sta->local; |
559 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
560 | int err = 0; | 446 | int err = 0; |
561 | 447 | ||
448 | might_sleep(); | ||
449 | |||
562 | err = sta_info_insert_check(sta); | 450 | err = sta_info_insert_check(sta); |
563 | if (err) { | 451 | if (err) { |
564 | rcu_read_lock(); | 452 | rcu_read_lock(); |
565 | goto out_free; | 453 | goto out_free; |
566 | } | 454 | } |
567 | 455 | ||
568 | /* | ||
569 | * In ad-hoc mode, we sometimes need to insert stations | ||
570 | * from tasklet context from the RX path. To avoid races, | ||
571 | * always do so in that case -- see the comment below. | ||
572 | */ | ||
573 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { | ||
574 | err = sta_info_insert_ibss(sta); | ||
575 | if (err) | ||
576 | goto out_free; | ||
577 | |||
578 | return 0; | ||
579 | } | ||
580 | |||
581 | /* | ||
582 | * It might seem that the function called below is in race against | ||
583 | * the function call above that atomically inserts the station... That, | ||
584 | * however, is not true because the above code can only | ||
585 | * be invoked for IBSS interfaces, and the below code will | ||
586 | * not be -- and the two do not race against each other as | ||
587 | * the hash table also keys off the interface. | ||
588 | */ | ||
589 | |||
590 | might_sleep(); | ||
591 | |||
592 | mutex_lock(&local->sta_mtx); | 456 | mutex_lock(&local->sta_mtx); |
593 | 457 | ||
594 | err = sta_info_insert_non_ibss(sta); | 458 | err = sta_info_insert_finish(sta); |
595 | if (err) | 459 | if (err) |
596 | goto out_free; | 460 | goto out_free; |
597 | 461 | ||
598 | return 0; | 462 | return 0; |
599 | out_free: | 463 | out_free: |
600 | BUG_ON(!err); | 464 | BUG_ON(!err); |
601 | __sta_info_free(local, sta); | 465 | sta_info_free(local, sta); |
602 | return err; | 466 | return err; |
603 | } | 467 | } |
604 | 468 | ||
@@ -625,7 +489,7 @@ int sta_info_reinsert(struct sta_info *sta) | |||
625 | 489 | ||
626 | might_sleep(); | 490 | might_sleep(); |
627 | 491 | ||
628 | err = sta_info_insert_non_ibss(sta); | 492 | err = sta_info_insert_finish(sta); |
629 | rcu_read_unlock(); | 493 | rcu_read_unlock(); |
630 | return err; | 494 | return err; |
631 | } | 495 | } |
@@ -712,7 +576,7 @@ void sta_info_recalc_tim(struct sta_info *sta) | |||
712 | } | 576 | } |
713 | 577 | ||
714 | done: | 578 | done: |
715 | spin_lock_irqsave(&local->sta_lock, flags); | 579 | spin_lock_irqsave(&local->tim_lock, flags); |
716 | 580 | ||
717 | if (indicate_tim) | 581 | if (indicate_tim) |
718 | __bss_tim_set(bss, sta->sta.aid); | 582 | __bss_tim_set(bss, sta->sta.aid); |
@@ -725,7 +589,7 @@ void sta_info_recalc_tim(struct sta_info *sta) | |||
725 | local->tim_in_locked_section = false; | 589 | local->tim_in_locked_section = false; |
726 | } | 590 | } |
727 | 591 | ||
728 | spin_unlock_irqrestore(&local->sta_lock, flags); | 592 | spin_unlock_irqrestore(&local->tim_lock, flags); |
729 | } | 593 | } |
730 | 594 | ||
731 | static bool sta_info_buffer_expired(struct sta_info *sta, struct sk_buff *skb) | 595 | static bool sta_info_buffer_expired(struct sta_info *sta, struct sk_buff *skb) |
@@ -849,8 +713,8 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
849 | { | 713 | { |
850 | struct ieee80211_local *local; | 714 | struct ieee80211_local *local; |
851 | struct ieee80211_sub_if_data *sdata; | 715 | struct ieee80211_sub_if_data *sdata; |
852 | unsigned long flags; | ||
853 | int ret, i, ac; | 716 | int ret, i, ac; |
717 | struct tid_ampdu_tx *tid_tx; | ||
854 | 718 | ||
855 | might_sleep(); | 719 | might_sleep(); |
856 | 720 | ||
@@ -869,15 +733,12 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
869 | set_sta_flag(sta, WLAN_STA_BLOCK_BA); | 733 | set_sta_flag(sta, WLAN_STA_BLOCK_BA); |
870 | ieee80211_sta_tear_down_BA_sessions(sta, true); | 734 | ieee80211_sta_tear_down_BA_sessions(sta, true); |
871 | 735 | ||
872 | spin_lock_irqsave(&local->sta_lock, flags); | ||
873 | ret = sta_info_hash_del(local, sta); | 736 | ret = sta_info_hash_del(local, sta); |
874 | /* this might still be the pending list ... which is fine */ | ||
875 | if (!ret) | ||
876 | list_del(&sta->list); | ||
877 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
878 | if (ret) | 737 | if (ret) |
879 | return ret; | 738 | return ret; |
880 | 739 | ||
740 | list_del(&sta->list); | ||
741 | |||
881 | mutex_lock(&local->key_mtx); | 742 | mutex_lock(&local->key_mtx); |
882 | for (i = 0; i < NUM_DEFAULT_KEYS; i++) | 743 | for (i = 0; i < NUM_DEFAULT_KEYS; i++) |
883 | __ieee80211_key_free(key_mtx_dereference(local, sta->gtk[i])); | 744 | __ieee80211_key_free(key_mtx_dereference(local, sta->gtk[i])); |
@@ -904,6 +765,9 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
904 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 765 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
905 | RCU_INIT_POINTER(sdata->u.vlan.sta, NULL); | 766 | RCU_INIT_POINTER(sdata->u.vlan.sta, NULL); |
906 | 767 | ||
768 | while (sta->sta_state > IEEE80211_STA_NONE) | ||
769 | sta_info_move_state(sta, sta->sta_state - 1); | ||
770 | |||
907 | if (sta->uploaded) { | 771 | if (sta->uploaded) { |
908 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 772 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
909 | sdata = container_of(sdata->bss, | 773 | sdata = container_of(sdata->bss, |
@@ -949,7 +813,31 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
949 | } | 813 | } |
950 | #endif | 814 | #endif |
951 | 815 | ||
952 | __sta_info_free(local, sta); | 816 | /* There could be some memory leaks because of ampdu tx pending queue |
817 | * not being freed before destroying the station info. | ||
818 | * | ||
819 | * Make sure that such queues are purged before freeing the station | ||
820 | * info. | ||
821 | * TODO: We have to somehow postpone the full destruction | ||
822 | * until the aggregation stop completes. Refer | ||
823 | * http://thread.gmane.org/gmane.linux.kernel.wireless.general/81936 | ||
824 | */ | ||
825 | for (i = 0; i < STA_TID_NUM; i++) { | ||
826 | if (!sta->ampdu_mlme.tid_tx[i]) | ||
827 | continue; | ||
828 | tid_tx = sta->ampdu_mlme.tid_tx[i]; | ||
829 | if (skb_queue_len(&tid_tx->pending)) { | ||
830 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
831 | wiphy_debug(local->hw.wiphy, "TX A-MPDU purging %d " | ||
832 | "packets for tid=%d\n", | ||
833 | skb_queue_len(&tid_tx->pending), i); | ||
834 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
835 | __skb_queue_purge(&tid_tx->pending); | ||
836 | } | ||
837 | kfree_rcu(tid_tx, rcu_head); | ||
838 | } | ||
839 | |||
840 | sta_info_free(local, sta); | ||
953 | 841 | ||
954 | return 0; | 842 | return 0; |
955 | } | 843 | } |
@@ -1005,11 +893,9 @@ static void sta_info_cleanup(unsigned long data) | |||
1005 | 893 | ||
1006 | void sta_info_init(struct ieee80211_local *local) | 894 | void sta_info_init(struct ieee80211_local *local) |
1007 | { | 895 | { |
1008 | spin_lock_init(&local->sta_lock); | 896 | spin_lock_init(&local->tim_lock); |
1009 | mutex_init(&local->sta_mtx); | 897 | mutex_init(&local->sta_mtx); |
1010 | INIT_LIST_HEAD(&local->sta_list); | 898 | INIT_LIST_HEAD(&local->sta_list); |
1011 | INIT_LIST_HEAD(&local->sta_pending_list); | ||
1012 | INIT_WORK(&local->sta_finish_work, sta_info_finish_work); | ||
1013 | 899 | ||
1014 | setup_timer(&local->sta_cleanup, sta_info_cleanup, | 900 | setup_timer(&local->sta_cleanup, sta_info_cleanup, |
1015 | (unsigned long)local); | 901 | (unsigned long)local); |
@@ -1038,9 +924,6 @@ int sta_info_flush(struct ieee80211_local *local, | |||
1038 | might_sleep(); | 924 | might_sleep(); |
1039 | 925 | ||
1040 | mutex_lock(&local->sta_mtx); | 926 | mutex_lock(&local->sta_mtx); |
1041 | |||
1042 | sta_info_finish_pending(local); | ||
1043 | |||
1044 | list_for_each_entry_safe(sta, tmp, &local->sta_list, list) { | 927 | list_for_each_entry_safe(sta, tmp, &local->sta_list, list) { |
1045 | if (!sdata || sdata == sta->sdata) | 928 | if (!sdata || sdata == sta->sdata) |
1046 | WARN_ON(__sta_info_destroy(sta)); | 929 | WARN_ON(__sta_info_destroy(sta)); |
@@ -1513,3 +1396,56 @@ void ieee80211_sta_set_buffered(struct ieee80211_sta *pubsta, | |||
1513 | sta_info_recalc_tim(sta); | 1396 | sta_info_recalc_tim(sta); |
1514 | } | 1397 | } |
1515 | EXPORT_SYMBOL(ieee80211_sta_set_buffered); | 1398 | EXPORT_SYMBOL(ieee80211_sta_set_buffered); |
1399 | |||
1400 | int sta_info_move_state_checked(struct sta_info *sta, | ||
1401 | enum ieee80211_sta_state new_state) | ||
1402 | { | ||
1403 | might_sleep(); | ||
1404 | |||
1405 | if (sta->sta_state == new_state) | ||
1406 | return 0; | ||
1407 | |||
1408 | switch (new_state) { | ||
1409 | case IEEE80211_STA_NONE: | ||
1410 | if (sta->sta_state == IEEE80211_STA_AUTH) | ||
1411 | clear_bit(WLAN_STA_AUTH, &sta->_flags); | ||
1412 | else | ||
1413 | return -EINVAL; | ||
1414 | break; | ||
1415 | case IEEE80211_STA_AUTH: | ||
1416 | if (sta->sta_state == IEEE80211_STA_NONE) | ||
1417 | set_bit(WLAN_STA_AUTH, &sta->_flags); | ||
1418 | else if (sta->sta_state == IEEE80211_STA_ASSOC) | ||
1419 | clear_bit(WLAN_STA_ASSOC, &sta->_flags); | ||
1420 | else | ||
1421 | return -EINVAL; | ||
1422 | break; | ||
1423 | case IEEE80211_STA_ASSOC: | ||
1424 | if (sta->sta_state == IEEE80211_STA_AUTH) { | ||
1425 | set_bit(WLAN_STA_ASSOC, &sta->_flags); | ||
1426 | } else if (sta->sta_state == IEEE80211_STA_AUTHORIZED) { | ||
1427 | if (sta->sdata->vif.type == NL80211_IFTYPE_AP) | ||
1428 | atomic_dec(&sta->sdata->u.ap.num_sta_authorized); | ||
1429 | clear_bit(WLAN_STA_AUTHORIZED, &sta->_flags); | ||
1430 | } else | ||
1431 | return -EINVAL; | ||
1432 | break; | ||
1433 | case IEEE80211_STA_AUTHORIZED: | ||
1434 | if (sta->sta_state == IEEE80211_STA_ASSOC) { | ||
1435 | if (sta->sdata->vif.type == NL80211_IFTYPE_AP) | ||
1436 | atomic_inc(&sta->sdata->u.ap.num_sta_authorized); | ||
1437 | set_bit(WLAN_STA_AUTHORIZED, &sta->_flags); | ||
1438 | } else | ||
1439 | return -EINVAL; | ||
1440 | break; | ||
1441 | default: | ||
1442 | WARN(1, "invalid state %d", new_state); | ||
1443 | return -EINVAL; | ||
1444 | } | ||
1445 | |||
1446 | printk(KERN_DEBUG "%s: moving STA %pM to state %d\n", | ||
1447 | sta->sdata->name, sta->sta.addr, new_state); | ||
1448 | sta->sta_state = new_state; | ||
1449 | |||
1450 | return 0; | ||
1451 | } | ||
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 1a14fab4bc9a..15b3bb7d8629 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -73,6 +73,14 @@ enum ieee80211_sta_info_flags { | |||
73 | WLAN_STA_4ADDR_EVENT, | 73 | WLAN_STA_4ADDR_EVENT, |
74 | }; | 74 | }; |
75 | 75 | ||
76 | enum ieee80211_sta_state { | ||
77 | /* NOTE: These need to be ordered correctly! */ | ||
78 | IEEE80211_STA_NONE, | ||
79 | IEEE80211_STA_AUTH, | ||
80 | IEEE80211_STA_ASSOC, | ||
81 | IEEE80211_STA_AUTHORIZED, | ||
82 | }; | ||
83 | |||
76 | #define STA_TID_NUM 16 | 84 | #define STA_TID_NUM 16 |
77 | #define ADDBA_RESP_INTERVAL HZ | 85 | #define ADDBA_RESP_INTERVAL HZ |
78 | #define HT_AGG_MAX_RETRIES 0x3 | 86 | #define HT_AGG_MAX_RETRIES 0x3 |
@@ -262,6 +270,7 @@ struct sta_ampdu_mlme { | |||
262 | * @dummy: indicate a dummy station created for receiving | 270 | * @dummy: indicate a dummy station created for receiving |
263 | * EAP frames before association | 271 | * EAP frames before association |
264 | * @sta: station information we share with the driver | 272 | * @sta: station information we share with the driver |
273 | * @sta_state: duplicates information about station state (for debug) | ||
265 | */ | 274 | */ |
266 | struct sta_info { | 275 | struct sta_info { |
267 | /* General information, mostly static */ | 276 | /* General information, mostly static */ |
@@ -283,6 +292,8 @@ struct sta_info { | |||
283 | 292 | ||
284 | bool uploaded; | 293 | bool uploaded; |
285 | 294 | ||
295 | enum ieee80211_sta_state sta_state; | ||
296 | |||
286 | /* use the accessors defined below */ | 297 | /* use the accessors defined below */ |
287 | unsigned long _flags; | 298 | unsigned long _flags; |
288 | 299 | ||
@@ -371,12 +382,18 @@ static inline enum nl80211_plink_state sta_plink_state(struct sta_info *sta) | |||
371 | static inline void set_sta_flag(struct sta_info *sta, | 382 | static inline void set_sta_flag(struct sta_info *sta, |
372 | enum ieee80211_sta_info_flags flag) | 383 | enum ieee80211_sta_info_flags flag) |
373 | { | 384 | { |
385 | WARN_ON(flag == WLAN_STA_AUTH || | ||
386 | flag == WLAN_STA_ASSOC || | ||
387 | flag == WLAN_STA_AUTHORIZED); | ||
374 | set_bit(flag, &sta->_flags); | 388 | set_bit(flag, &sta->_flags); |
375 | } | 389 | } |
376 | 390 | ||
377 | static inline void clear_sta_flag(struct sta_info *sta, | 391 | static inline void clear_sta_flag(struct sta_info *sta, |
378 | enum ieee80211_sta_info_flags flag) | 392 | enum ieee80211_sta_info_flags flag) |
379 | { | 393 | { |
394 | WARN_ON(flag == WLAN_STA_AUTH || | ||
395 | flag == WLAN_STA_ASSOC || | ||
396 | flag == WLAN_STA_AUTHORIZED); | ||
380 | clear_bit(flag, &sta->_flags); | 397 | clear_bit(flag, &sta->_flags); |
381 | } | 398 | } |
382 | 399 | ||
@@ -389,15 +406,32 @@ static inline int test_sta_flag(struct sta_info *sta, | |||
389 | static inline int test_and_clear_sta_flag(struct sta_info *sta, | 406 | static inline int test_and_clear_sta_flag(struct sta_info *sta, |
390 | enum ieee80211_sta_info_flags flag) | 407 | enum ieee80211_sta_info_flags flag) |
391 | { | 408 | { |
409 | WARN_ON(flag == WLAN_STA_AUTH || | ||
410 | flag == WLAN_STA_ASSOC || | ||
411 | flag == WLAN_STA_AUTHORIZED); | ||
392 | return test_and_clear_bit(flag, &sta->_flags); | 412 | return test_and_clear_bit(flag, &sta->_flags); |
393 | } | 413 | } |
394 | 414 | ||
395 | static inline int test_and_set_sta_flag(struct sta_info *sta, | 415 | static inline int test_and_set_sta_flag(struct sta_info *sta, |
396 | enum ieee80211_sta_info_flags flag) | 416 | enum ieee80211_sta_info_flags flag) |
397 | { | 417 | { |
418 | WARN_ON(flag == WLAN_STA_AUTH || | ||
419 | flag == WLAN_STA_ASSOC || | ||
420 | flag == WLAN_STA_AUTHORIZED); | ||
398 | return test_and_set_bit(flag, &sta->_flags); | 421 | return test_and_set_bit(flag, &sta->_flags); |
399 | } | 422 | } |
400 | 423 | ||
424 | int sta_info_move_state_checked(struct sta_info *sta, | ||
425 | enum ieee80211_sta_state new_state); | ||
426 | |||
427 | static inline void sta_info_move_state(struct sta_info *sta, | ||
428 | enum ieee80211_sta_state new_state) | ||
429 | { | ||
430 | int ret = sta_info_move_state_checked(sta, new_state); | ||
431 | WARN_ON_ONCE(ret); | ||
432 | } | ||
433 | |||
434 | |||
401 | void ieee80211_assign_tid_tx(struct sta_info *sta, int tid, | 435 | void ieee80211_assign_tid_tx(struct sta_info *sta, int tid, |
402 | struct tid_ampdu_tx *tid_tx); | 436 | struct tid_ampdu_tx *tid_tx); |
403 | 437 | ||
@@ -488,7 +522,10 @@ struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata, | |||
488 | * until sta_info_insert(). | 522 | * until sta_info_insert(). |
489 | */ | 523 | */ |
490 | struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | 524 | struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, |
491 | u8 *addr, gfp_t gfp); | 525 | const u8 *addr, gfp_t gfp); |
526 | |||
527 | void sta_info_free(struct ieee80211_local *local, struct sta_info *sta); | ||
528 | |||
492 | /* | 529 | /* |
493 | * Insert STA info into hash table/list, returns zero or a | 530 | * Insert STA info into hash table/list, returns zero or a |
494 | * -EEXIST if (if the same MAC address is already present). | 531 | * -EEXIST if (if the same MAC address is already present). |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 46222ce0e5b1..30c265c98f73 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -340,7 +340,6 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
340 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 340 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
341 | struct ieee80211_local *local = hw_to_local(hw); | 341 | struct ieee80211_local *local = hw_to_local(hw); |
342 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 342 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
343 | u16 frag, type; | ||
344 | __le16 fc; | 343 | __le16 fc; |
345 | struct ieee80211_supported_band *sband; | 344 | struct ieee80211_supported_band *sband; |
346 | struct ieee80211_sub_if_data *sdata; | 345 | struct ieee80211_sub_if_data *sdata; |
@@ -476,12 +475,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
476 | * Fragments are passed to low-level drivers as separate skbs, so these | 475 | * Fragments are passed to low-level drivers as separate skbs, so these |
477 | * are actually fragments, not frames. Update frame counters only for | 476 | * are actually fragments, not frames. Update frame counters only for |
478 | * the first fragment of the frame. */ | 477 | * the first fragment of the frame. */ |
479 | |||
480 | frag = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG; | ||
481 | type = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_FTYPE; | ||
482 | |||
483 | if (info->flags & IEEE80211_TX_STAT_ACK) { | 478 | if (info->flags & IEEE80211_TX_STAT_ACK) { |
484 | if (frag == 0) { | 479 | if (ieee80211_is_first_frag(hdr->seq_ctrl)) { |
485 | local->dot11TransmittedFrameCount++; | 480 | local->dot11TransmittedFrameCount++; |
486 | if (is_multicast_ether_addr(hdr->addr1)) | 481 | if (is_multicast_ether_addr(hdr->addr1)) |
487 | local->dot11MulticastTransmittedFrameCount++; | 482 | local->dot11MulticastTransmittedFrameCount++; |
@@ -496,11 +491,11 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
496 | * with a multicast address in the address 1 field of type Data | 491 | * with a multicast address in the address 1 field of type Data |
497 | * or Management. */ | 492 | * or Management. */ |
498 | if (!is_multicast_ether_addr(hdr->addr1) || | 493 | if (!is_multicast_ether_addr(hdr->addr1) || |
499 | type == IEEE80211_FTYPE_DATA || | 494 | ieee80211_is_data(fc) || |
500 | type == IEEE80211_FTYPE_MGMT) | 495 | ieee80211_is_mgmt(fc)) |
501 | local->dot11TransmittedFragmentCount++; | 496 | local->dot11TransmittedFragmentCount++; |
502 | } else { | 497 | } else { |
503 | if (frag == 0) | 498 | if (ieee80211_is_first_frag(hdr->seq_ctrl)) |
504 | local->dot11FailedCount++; | 499 | local->dot11FailedCount++; |
505 | } | 500 | } |
506 | 501 | ||
@@ -572,7 +567,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
572 | 567 | ||
573 | /* Need to make a copy before skb->cb gets cleared */ | 568 | /* Need to make a copy before skb->cb gets cleared */ |
574 | send_to_cooked = !!(info->flags & IEEE80211_TX_CTL_INJECTED) || | 569 | send_to_cooked = !!(info->flags & IEEE80211_TX_CTL_INJECTED) || |
575 | (type != IEEE80211_FTYPE_DATA); | 570 | !(ieee80211_is_data(fc)); |
576 | 571 | ||
577 | /* | 572 | /* |
578 | * This is a bit racy but we can avoid a lot of work | 573 | * This is a bit racy but we can avoid a lot of work |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index e74652d38245..edcd1c7ab83f 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -295,7 +295,6 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) | |||
295 | 295 | ||
296 | if (likely(tx->flags & IEEE80211_TX_UNICAST)) { | 296 | if (likely(tx->flags & IEEE80211_TX_UNICAST)) { |
297 | if (unlikely(!assoc && | 297 | if (unlikely(!assoc && |
298 | tx->sdata->vif.type != NL80211_IFTYPE_ADHOC && | ||
299 | ieee80211_is_data(hdr->frame_control))) { | 298 | ieee80211_is_data(hdr->frame_control))) { |
300 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 299 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
301 | printk(KERN_DEBUG "%s: dropped data frame to not " | 300 | printk(KERN_DEBUG "%s: dropped data frame to not " |
@@ -305,17 +304,14 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) | |||
305 | I802_DEBUG_INC(tx->local->tx_handlers_drop_not_assoc); | 304 | I802_DEBUG_INC(tx->local->tx_handlers_drop_not_assoc); |
306 | return TX_DROP; | 305 | return TX_DROP; |
307 | } | 306 | } |
308 | } else { | 307 | } else if (unlikely(tx->sdata->vif.type == NL80211_IFTYPE_AP && |
309 | if (unlikely(ieee80211_is_data(hdr->frame_control) && | 308 | ieee80211_is_data(hdr->frame_control) && |
310 | tx->local->num_sta == 0 && | 309 | !atomic_read(&tx->sdata->u.ap.num_sta_authorized))) { |
311 | tx->sdata->vif.type != NL80211_IFTYPE_ADHOC)) { | 310 | /* |
312 | /* | 311 | * No associated STAs - no need to send multicast |
313 | * No associated STAs - no need to send multicast | 312 | * frames. |
314 | * frames. | 313 | */ |
315 | */ | 314 | return TX_DROP; |
316 | return TX_DROP; | ||
317 | } | ||
318 | return TX_CONTINUE; | ||
319 | } | 315 | } |
320 | 316 | ||
321 | return TX_CONTINUE; | 317 | return TX_CONTINUE; |
@@ -2337,9 +2333,9 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2337 | } else { | 2333 | } else { |
2338 | unsigned long flags; | 2334 | unsigned long flags; |
2339 | 2335 | ||
2340 | spin_lock_irqsave(&local->sta_lock, flags); | 2336 | spin_lock_irqsave(&local->tim_lock, flags); |
2341 | ieee80211_beacon_add_tim(ap, skb, beacon); | 2337 | ieee80211_beacon_add_tim(ap, skb, beacon); |
2342 | spin_unlock_irqrestore(&local->sta_lock, flags); | 2338 | spin_unlock_irqrestore(&local->tim_lock, flags); |
2343 | } | 2339 | } |
2344 | 2340 | ||
2345 | if (tim_offset) | 2341 | if (tim_offset) |
@@ -2700,15 +2696,15 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | |||
2700 | } | 2696 | } |
2701 | EXPORT_SYMBOL(ieee80211_get_buffered_bc); | 2697 | EXPORT_SYMBOL(ieee80211_get_buffered_bc); |
2702 | 2698 | ||
2703 | void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) | 2699 | void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata, |
2700 | struct sk_buff *skb, int tid) | ||
2704 | { | 2701 | { |
2705 | skb_set_mac_header(skb, 0); | 2702 | skb_set_mac_header(skb, 0); |
2706 | skb_set_network_header(skb, 0); | 2703 | skb_set_network_header(skb, 0); |
2707 | skb_set_transport_header(skb, 0); | 2704 | skb_set_transport_header(skb, 0); |
2708 | 2705 | ||
2709 | /* Send all internal mgmt frames on VO. Accordingly set TID to 7. */ | 2706 | skb_set_queue_mapping(skb, ieee802_1d_to_ac[tid]); |
2710 | skb_set_queue_mapping(skb, IEEE80211_AC_VO); | 2707 | skb->priority = tid; |
2711 | skb->priority = 7; | ||
2712 | 2708 | ||
2713 | /* | 2709 | /* |
2714 | * The other path calling ieee80211_xmit is from the tasklet, | 2710 | * The other path calling ieee80211_xmit is from the tasklet, |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index ac7ea2949de0..eb1a5f737a9c 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -1234,7 +1234,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1234 | 1234 | ||
1235 | switch (sdata->vif.type) { | 1235 | switch (sdata->vif.type) { |
1236 | case NL80211_IFTYPE_STATION: | 1236 | case NL80211_IFTYPE_STATION: |
1237 | changed |= BSS_CHANGED_ASSOC; | 1237 | changed |= BSS_CHANGED_ASSOC | |
1238 | BSS_CHANGED_ARP_FILTER; | ||
1238 | mutex_lock(&sdata->u.mgd.mtx); | 1239 | mutex_lock(&sdata->u.mgd.mtx); |
1239 | ieee80211_bss_info_change_notify(sdata, changed); | 1240 | ieee80211_bss_info_change_notify(sdata, changed); |
1240 | mutex_unlock(&sdata->u.mgd.mtx); | 1241 | mutex_unlock(&sdata->u.mgd.mtx); |
diff --git a/net/nfc/Kconfig b/net/nfc/Kconfig index 58cddadf8e8e..44c865b86d6f 100644 --- a/net/nfc/Kconfig +++ b/net/nfc/Kconfig | |||
@@ -14,5 +14,6 @@ menuconfig NFC | |||
14 | be called nfc. | 14 | be called nfc. |
15 | 15 | ||
16 | source "net/nfc/nci/Kconfig" | 16 | source "net/nfc/nci/Kconfig" |
17 | source "net/nfc/llcp/Kconfig" | ||
17 | 18 | ||
18 | source "drivers/nfc/Kconfig" | 19 | source "drivers/nfc/Kconfig" |
diff --git a/net/nfc/Makefile b/net/nfc/Makefile index fbb550f2377b..7b4a6dcfa566 100644 --- a/net/nfc/Makefile +++ b/net/nfc/Makefile | |||
@@ -6,3 +6,4 @@ obj-$(CONFIG_NFC) += nfc.o | |||
6 | obj-$(CONFIG_NFC_NCI) += nci/ | 6 | obj-$(CONFIG_NFC_NCI) += nci/ |
7 | 7 | ||
8 | nfc-objs := core.o netlink.o af_nfc.o rawsock.o | 8 | nfc-objs := core.o netlink.o af_nfc.o rawsock.o |
9 | nfc-$(CONFIG_NFC_LLCP) += llcp/llcp.o llcp/commands.o llcp/sock.o | ||
diff --git a/net/nfc/core.c b/net/nfc/core.c index 3ebc6b3aabac..3ddf6e698df0 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c | |||
@@ -21,12 +21,13 @@ | |||
21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 24 | #define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__ |
25 | 25 | ||
26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
27 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | #include <linux/nfc.h> | ||
30 | 31 | ||
31 | #include "nfc.h" | 32 | #include "nfc.h" |
32 | 33 | ||
@@ -180,6 +181,86 @@ error: | |||
180 | return rc; | 181 | return rc; |
181 | } | 182 | } |
182 | 183 | ||
184 | int nfc_dep_link_up(struct nfc_dev *dev, int target_index, | ||
185 | u8 comm_mode, u8 rf_mode) | ||
186 | { | ||
187 | int rc = 0; | ||
188 | |||
189 | pr_debug("dev_name=%s comm:%d rf:%d\n", | ||
190 | dev_name(&dev->dev), comm_mode, rf_mode); | ||
191 | |||
192 | if (!dev->ops->dep_link_up) | ||
193 | return -EOPNOTSUPP; | ||
194 | |||
195 | device_lock(&dev->dev); | ||
196 | |||
197 | if (!device_is_registered(&dev->dev)) { | ||
198 | rc = -ENODEV; | ||
199 | goto error; | ||
200 | } | ||
201 | |||
202 | if (dev->dep_link_up == true) { | ||
203 | rc = -EALREADY; | ||
204 | goto error; | ||
205 | } | ||
206 | |||
207 | rc = dev->ops->dep_link_up(dev, target_index, comm_mode, rf_mode); | ||
208 | |||
209 | error: | ||
210 | device_unlock(&dev->dev); | ||
211 | return rc; | ||
212 | } | ||
213 | |||
214 | int nfc_dep_link_down(struct nfc_dev *dev) | ||
215 | { | ||
216 | int rc = 0; | ||
217 | |||
218 | pr_debug("dev_name=%s\n", dev_name(&dev->dev)); | ||
219 | |||
220 | if (!dev->ops->dep_link_down) | ||
221 | return -EOPNOTSUPP; | ||
222 | |||
223 | device_lock(&dev->dev); | ||
224 | |||
225 | if (!device_is_registered(&dev->dev)) { | ||
226 | rc = -ENODEV; | ||
227 | goto error; | ||
228 | } | ||
229 | |||
230 | if (dev->dep_link_up == false) { | ||
231 | rc = -EALREADY; | ||
232 | goto error; | ||
233 | } | ||
234 | |||
235 | if (dev->dep_rf_mode == NFC_RF_TARGET) { | ||
236 | rc = -EOPNOTSUPP; | ||
237 | goto error; | ||
238 | } | ||
239 | |||
240 | rc = dev->ops->dep_link_down(dev); | ||
241 | if (!rc) { | ||
242 | dev->dep_link_up = false; | ||
243 | nfc_llcp_mac_is_down(dev); | ||
244 | nfc_genl_dep_link_down_event(dev); | ||
245 | } | ||
246 | |||
247 | error: | ||
248 | device_unlock(&dev->dev); | ||
249 | return rc; | ||
250 | } | ||
251 | |||
252 | int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx, | ||
253 | u8 comm_mode, u8 rf_mode) | ||
254 | { | ||
255 | dev->dep_link_up = true; | ||
256 | dev->dep_rf_mode = rf_mode; | ||
257 | |||
258 | nfc_llcp_mac_is_up(dev, target_idx, comm_mode, rf_mode); | ||
259 | |||
260 | return nfc_genl_dep_link_up_event(dev, target_idx, comm_mode, rf_mode); | ||
261 | } | ||
262 | EXPORT_SYMBOL(nfc_dep_link_is_up); | ||
263 | |||
183 | /** | 264 | /** |
184 | * nfc_activate_target - prepare the target for data exchange | 265 | * nfc_activate_target - prepare the target for data exchange |
185 | * | 266 | * |
@@ -274,13 +355,54 @@ error: | |||
274 | return rc; | 355 | return rc; |
275 | } | 356 | } |
276 | 357 | ||
358 | int nfc_set_remote_general_bytes(struct nfc_dev *dev, u8 *gb, u8 gb_len) | ||
359 | { | ||
360 | pr_debug("dev_name=%s gb_len=%d\n", | ||
361 | dev_name(&dev->dev), gb_len); | ||
362 | |||
363 | if (gb_len > NFC_MAX_GT_LEN) | ||
364 | return -EINVAL; | ||
365 | |||
366 | return nfc_llcp_set_remote_gb(dev, gb, gb_len); | ||
367 | } | ||
368 | EXPORT_SYMBOL(nfc_set_remote_general_bytes); | ||
369 | |||
370 | u8 *nfc_get_local_general_bytes(struct nfc_dev *dev, u8 *gt_len) | ||
371 | { | ||
372 | return nfc_llcp_general_bytes(dev, gt_len); | ||
373 | } | ||
374 | EXPORT_SYMBOL(nfc_get_local_general_bytes); | ||
375 | |||
277 | /** | 376 | /** |
278 | * nfc_alloc_skb - allocate a skb for data exchange responses | 377 | * nfc_alloc_send_skb - allocate a skb for data exchange responses |
279 | * | 378 | * |
280 | * @size: size to allocate | 379 | * @size: size to allocate |
281 | * @gfp: gfp flags | 380 | * @gfp: gfp flags |
282 | */ | 381 | */ |
283 | struct sk_buff *nfc_alloc_skb(unsigned int size, gfp_t gfp) | 382 | struct sk_buff *nfc_alloc_send_skb(struct nfc_dev *dev, struct sock *sk, |
383 | unsigned int flags, unsigned int size, | ||
384 | unsigned int *err) | ||
385 | { | ||
386 | struct sk_buff *skb; | ||
387 | unsigned int total_size; | ||
388 | |||
389 | total_size = size + | ||
390 | dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE; | ||
391 | |||
392 | skb = sock_alloc_send_skb(sk, total_size, flags & MSG_DONTWAIT, err); | ||
393 | if (skb) | ||
394 | skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE); | ||
395 | |||
396 | return skb; | ||
397 | } | ||
398 | |||
399 | /** | ||
400 | * nfc_alloc_recv_skb - allocate a skb for data exchange responses | ||
401 | * | ||
402 | * @size: size to allocate | ||
403 | * @gfp: gfp flags | ||
404 | */ | ||
405 | struct sk_buff *nfc_alloc_recv_skb(unsigned int size, gfp_t gfp) | ||
284 | { | 406 | { |
285 | struct sk_buff *skb; | 407 | struct sk_buff *skb; |
286 | unsigned int total_size; | 408 | unsigned int total_size; |
@@ -293,7 +415,7 @@ struct sk_buff *nfc_alloc_skb(unsigned int size, gfp_t gfp) | |||
293 | 415 | ||
294 | return skb; | 416 | return skb; |
295 | } | 417 | } |
296 | EXPORT_SYMBOL(nfc_alloc_skb); | 418 | EXPORT_SYMBOL(nfc_alloc_recv_skb); |
297 | 419 | ||
298 | /** | 420 | /** |
299 | * nfc_targets_found - inform that targets were found | 421 | * nfc_targets_found - inform that targets were found |
@@ -441,6 +563,10 @@ int nfc_register_device(struct nfc_dev *dev) | |||
441 | if (rc < 0) | 563 | if (rc < 0) |
442 | return rc; | 564 | return rc; |
443 | 565 | ||
566 | rc = nfc_llcp_register_device(dev); | ||
567 | if (rc) | ||
568 | pr_err("Could not register llcp device\n"); | ||
569 | |||
444 | rc = nfc_genl_device_added(dev); | 570 | rc = nfc_genl_device_added(dev); |
445 | if (rc) | 571 | if (rc) |
446 | pr_debug("The userspace won't be notified that the device %s was added\n", | 572 | pr_debug("The userspace won't be notified that the device %s was added\n", |
@@ -472,6 +598,8 @@ void nfc_unregister_device(struct nfc_dev *dev) | |||
472 | 598 | ||
473 | mutex_unlock(&nfc_devlist_mutex); | 599 | mutex_unlock(&nfc_devlist_mutex); |
474 | 600 | ||
601 | nfc_llcp_unregister_device(dev); | ||
602 | |||
475 | rc = nfc_genl_device_removed(dev); | 603 | rc = nfc_genl_device_removed(dev); |
476 | if (rc) | 604 | if (rc) |
477 | pr_debug("The userspace won't be notified that the device %s was removed\n", | 605 | pr_debug("The userspace won't be notified that the device %s was removed\n", |
@@ -501,6 +629,10 @@ static int __init nfc_init(void) | |||
501 | if (rc) | 629 | if (rc) |
502 | goto err_rawsock; | 630 | goto err_rawsock; |
503 | 631 | ||
632 | rc = nfc_llcp_init(); | ||
633 | if (rc) | ||
634 | goto err_llcp_sock; | ||
635 | |||
504 | rc = af_nfc_init(); | 636 | rc = af_nfc_init(); |
505 | if (rc) | 637 | if (rc) |
506 | goto err_af_nfc; | 638 | goto err_af_nfc; |
@@ -508,6 +640,8 @@ static int __init nfc_init(void) | |||
508 | return 0; | 640 | return 0; |
509 | 641 | ||
510 | err_af_nfc: | 642 | err_af_nfc: |
643 | nfc_llcp_exit(); | ||
644 | err_llcp_sock: | ||
511 | rawsock_exit(); | 645 | rawsock_exit(); |
512 | err_rawsock: | 646 | err_rawsock: |
513 | nfc_genl_exit(); | 647 | nfc_genl_exit(); |
@@ -519,6 +653,7 @@ err_genl: | |||
519 | static void __exit nfc_exit(void) | 653 | static void __exit nfc_exit(void) |
520 | { | 654 | { |
521 | af_nfc_exit(); | 655 | af_nfc_exit(); |
656 | nfc_llcp_exit(); | ||
522 | rawsock_exit(); | 657 | rawsock_exit(); |
523 | nfc_genl_exit(); | 658 | nfc_genl_exit(); |
524 | class_unregister(&nfc_class); | 659 | class_unregister(&nfc_class); |
diff --git a/net/nfc/llcp/Kconfig b/net/nfc/llcp/Kconfig new file mode 100644 index 000000000000..fbf5e8150908 --- /dev/null +++ b/net/nfc/llcp/Kconfig | |||
@@ -0,0 +1,7 @@ | |||
1 | config NFC_LLCP | ||
2 | depends on NFC && EXPERIMENTAL | ||
3 | bool "NFC LLCP support (EXPERIMENTAL)" | ||
4 | default n | ||
5 | help | ||
6 | Say Y here if you want to build support for a kernel NFC LLCP | ||
7 | implementation. \ No newline at end of file | ||
diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c new file mode 100644 index 000000000000..151f2ef429c4 --- /dev/null +++ b/net/nfc/llcp/commands.c | |||
@@ -0,0 +1,399 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Intel Corporation. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the | ||
16 | * Free Software Foundation, Inc., | ||
17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
18 | */ | ||
19 | |||
20 | #define pr_fmt(fmt) "llcp: %s: " fmt, __func__ | ||
21 | |||
22 | #include <linux/init.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/nfc.h> | ||
26 | |||
27 | #include <net/nfc/nfc.h> | ||
28 | |||
29 | #include "../nfc.h" | ||
30 | #include "llcp.h" | ||
31 | |||
32 | static u8 llcp_tlv_length[LLCP_TLV_MAX] = { | ||
33 | 0, | ||
34 | 1, /* VERSION */ | ||
35 | 2, /* MIUX */ | ||
36 | 2, /* WKS */ | ||
37 | 1, /* LTO */ | ||
38 | 1, /* RW */ | ||
39 | 0, /* SN */ | ||
40 | 1, /* OPT */ | ||
41 | 0, /* SDREQ */ | ||
42 | 2, /* SDRES */ | ||
43 | |||
44 | }; | ||
45 | |||
46 | static u8 llcp_tlv8(u8 *tlv, u8 type) | ||
47 | { | ||
48 | if (tlv[0] != type || tlv[1] != llcp_tlv_length[tlv[0]]) | ||
49 | return 0; | ||
50 | |||
51 | return tlv[2]; | ||
52 | } | ||
53 | |||
54 | static u8 llcp_tlv16(u8 *tlv, u8 type) | ||
55 | { | ||
56 | if (tlv[0] != type || tlv[1] != llcp_tlv_length[tlv[0]]) | ||
57 | return 0; | ||
58 | |||
59 | return be16_to_cpu(*((__be16 *)(tlv + 2))); | ||
60 | } | ||
61 | |||
62 | |||
63 | static u8 llcp_tlv_version(u8 *tlv) | ||
64 | { | ||
65 | return llcp_tlv8(tlv, LLCP_TLV_VERSION); | ||
66 | } | ||
67 | |||
68 | static u16 llcp_tlv_miux(u8 *tlv) | ||
69 | { | ||
70 | return llcp_tlv16(tlv, LLCP_TLV_MIUX) & 0x7f; | ||
71 | } | ||
72 | |||
73 | static u16 llcp_tlv_wks(u8 *tlv) | ||
74 | { | ||
75 | return llcp_tlv16(tlv, LLCP_TLV_WKS); | ||
76 | } | ||
77 | |||
78 | static u16 llcp_tlv_lto(u8 *tlv) | ||
79 | { | ||
80 | return llcp_tlv8(tlv, LLCP_TLV_LTO); | ||
81 | } | ||
82 | |||
83 | static u8 llcp_tlv_opt(u8 *tlv) | ||
84 | { | ||
85 | return llcp_tlv8(tlv, LLCP_TLV_OPT); | ||
86 | } | ||
87 | |||
88 | static u8 llcp_tlv_rw(u8 *tlv) | ||
89 | { | ||
90 | return llcp_tlv8(tlv, LLCP_TLV_RW) & 0xf; | ||
91 | } | ||
92 | |||
93 | u8 *nfc_llcp_build_tlv(u8 type, u8 *value, u8 value_length, u8 *tlv_length) | ||
94 | { | ||
95 | u8 *tlv, length; | ||
96 | |||
97 | pr_debug("type %d\n", type); | ||
98 | |||
99 | if (type >= LLCP_TLV_MAX) | ||
100 | return NULL; | ||
101 | |||
102 | length = llcp_tlv_length[type]; | ||
103 | if (length == 0 && value_length == 0) | ||
104 | return NULL; | ||
105 | else | ||
106 | length = value_length; | ||
107 | |||
108 | *tlv_length = 2 + length; | ||
109 | tlv = kzalloc(2 + length, GFP_KERNEL); | ||
110 | if (tlv == NULL) | ||
111 | return tlv; | ||
112 | |||
113 | tlv[0] = type; | ||
114 | tlv[1] = length; | ||
115 | memcpy(tlv + 2, value, length); | ||
116 | |||
117 | return tlv; | ||
118 | } | ||
119 | |||
120 | int nfc_llcp_parse_tlv(struct nfc_llcp_local *local, | ||
121 | u8 *tlv_array, u16 tlv_array_len) | ||
122 | { | ||
123 | u8 *tlv = tlv_array, type, length, offset = 0; | ||
124 | |||
125 | pr_debug("TLV array length %d\n", tlv_array_len); | ||
126 | |||
127 | if (local == NULL) | ||
128 | return -ENODEV; | ||
129 | |||
130 | while (offset < tlv_array_len) { | ||
131 | type = tlv[0]; | ||
132 | length = tlv[1]; | ||
133 | |||
134 | pr_debug("type 0x%x length %d\n", type, length); | ||
135 | |||
136 | switch (type) { | ||
137 | case LLCP_TLV_VERSION: | ||
138 | local->remote_version = llcp_tlv_version(tlv); | ||
139 | break; | ||
140 | case LLCP_TLV_MIUX: | ||
141 | local->remote_miu = llcp_tlv_miux(tlv) + 128; | ||
142 | break; | ||
143 | case LLCP_TLV_WKS: | ||
144 | local->remote_wks = llcp_tlv_wks(tlv); | ||
145 | break; | ||
146 | case LLCP_TLV_LTO: | ||
147 | local->remote_lto = llcp_tlv_lto(tlv) * 10; | ||
148 | break; | ||
149 | case LLCP_TLV_OPT: | ||
150 | local->remote_opt = llcp_tlv_opt(tlv); | ||
151 | break; | ||
152 | case LLCP_TLV_RW: | ||
153 | local->remote_rw = llcp_tlv_rw(tlv); | ||
154 | break; | ||
155 | default: | ||
156 | pr_err("Invalid gt tlv value 0x%x\n", type); | ||
157 | break; | ||
158 | } | ||
159 | |||
160 | offset += length + 2; | ||
161 | tlv += length + 2; | ||
162 | } | ||
163 | |||
164 | pr_debug("version 0x%x miu %d lto %d opt 0x%x wks 0x%x rw %d\n", | ||
165 | local->remote_version, local->remote_miu, | ||
166 | local->remote_lto, local->remote_opt, | ||
167 | local->remote_wks, local->remote_rw); | ||
168 | |||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | static struct sk_buff *llcp_add_header(struct sk_buff *pdu, | ||
173 | u8 dsap, u8 ssap, u8 ptype) | ||
174 | { | ||
175 | u8 header[2]; | ||
176 | |||
177 | pr_debug("ptype 0x%x dsap 0x%x ssap 0x%x\n", ptype, dsap, ssap); | ||
178 | |||
179 | header[0] = (u8)((dsap << 2) | (ptype >> 2)); | ||
180 | header[1] = (u8)((ptype << 6) | ssap); | ||
181 | |||
182 | pr_debug("header 0x%x 0x%x\n", header[0], header[1]); | ||
183 | |||
184 | memcpy(skb_put(pdu, LLCP_HEADER_SIZE), header, LLCP_HEADER_SIZE); | ||
185 | |||
186 | return pdu; | ||
187 | } | ||
188 | |||
189 | static struct sk_buff *llcp_add_tlv(struct sk_buff *pdu, u8 *tlv, u8 tlv_length) | ||
190 | { | ||
191 | /* XXX Add an skb length check */ | ||
192 | |||
193 | if (tlv == NULL) | ||
194 | return NULL; | ||
195 | |||
196 | memcpy(skb_put(pdu, tlv_length), tlv, tlv_length); | ||
197 | |||
198 | return pdu; | ||
199 | } | ||
200 | |||
201 | static struct sk_buff *llcp_allocate_pdu(struct nfc_llcp_sock *sock, | ||
202 | u8 cmd, u16 size) | ||
203 | { | ||
204 | struct sk_buff *skb; | ||
205 | int err; | ||
206 | |||
207 | if (sock->ssap == 0) | ||
208 | return NULL; | ||
209 | |||
210 | skb = nfc_alloc_send_skb(sock->dev, &sock->sk, MSG_DONTWAIT, | ||
211 | size + LLCP_HEADER_SIZE, &err); | ||
212 | if (skb == NULL) { | ||
213 | pr_err("Could not allocate PDU\n"); | ||
214 | return NULL; | ||
215 | } | ||
216 | |||
217 | skb = llcp_add_header(skb, sock->dsap, sock->ssap, cmd); | ||
218 | |||
219 | return skb; | ||
220 | } | ||
221 | |||
222 | int nfc_llcp_disconnect(struct nfc_llcp_sock *sock) | ||
223 | { | ||
224 | struct sk_buff *skb; | ||
225 | struct nfc_dev *dev; | ||
226 | struct nfc_llcp_local *local; | ||
227 | u16 size = 0; | ||
228 | |||
229 | pr_debug("Sending DISC\n"); | ||
230 | |||
231 | local = sock->local; | ||
232 | if (local == NULL) | ||
233 | return -ENODEV; | ||
234 | |||
235 | dev = sock->dev; | ||
236 | if (dev == NULL) | ||
237 | return -ENODEV; | ||
238 | |||
239 | size += LLCP_HEADER_SIZE; | ||
240 | size += dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE; | ||
241 | |||
242 | skb = alloc_skb(size, GFP_ATOMIC); | ||
243 | if (skb == NULL) | ||
244 | return -ENOMEM; | ||
245 | |||
246 | skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE); | ||
247 | |||
248 | skb = llcp_add_header(skb, sock->ssap, sock->dsap, LLCP_PDU_DISC); | ||
249 | |||
250 | skb_queue_tail(&local->tx_queue, skb); | ||
251 | |||
252 | return 0; | ||
253 | } | ||
254 | |||
255 | int nfc_llcp_send_symm(struct nfc_dev *dev) | ||
256 | { | ||
257 | struct sk_buff *skb; | ||
258 | struct nfc_llcp_local *local; | ||
259 | u16 size = 0; | ||
260 | |||
261 | pr_debug("Sending SYMM\n"); | ||
262 | |||
263 | local = nfc_llcp_find_local(dev); | ||
264 | if (local == NULL) | ||
265 | return -ENODEV; | ||
266 | |||
267 | size += LLCP_HEADER_SIZE; | ||
268 | size += dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE; | ||
269 | |||
270 | skb = alloc_skb(size, GFP_KERNEL); | ||
271 | if (skb == NULL) | ||
272 | return -ENOMEM; | ||
273 | |||
274 | skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE); | ||
275 | |||
276 | skb = llcp_add_header(skb, 0, 0, LLCP_PDU_SYMM); | ||
277 | |||
278 | return nfc_data_exchange(dev, local->target_idx, skb, | ||
279 | nfc_llcp_recv, local); | ||
280 | } | ||
281 | |||
282 | int nfc_llcp_send_connect(struct nfc_llcp_sock *sock) | ||
283 | { | ||
284 | struct nfc_llcp_local *local; | ||
285 | struct sk_buff *skb; | ||
286 | u8 *service_name_tlv = NULL, service_name_tlv_length; | ||
287 | int err; | ||
288 | u16 size = 0; | ||
289 | |||
290 | pr_debug("Sending CONNECT\n"); | ||
291 | |||
292 | local = sock->local; | ||
293 | if (local == NULL) | ||
294 | return -ENODEV; | ||
295 | |||
296 | if (sock->service_name != NULL) { | ||
297 | service_name_tlv = nfc_llcp_build_tlv(LLCP_TLV_SN, | ||
298 | sock->service_name, | ||
299 | sock->service_name_len, | ||
300 | &service_name_tlv_length); | ||
301 | size += service_name_tlv_length; | ||
302 | } | ||
303 | |||
304 | pr_debug("SKB size %d SN length %zu\n", size, sock->service_name_len); | ||
305 | |||
306 | skb = llcp_allocate_pdu(sock, LLCP_PDU_CONNECT, size); | ||
307 | if (skb == NULL) { | ||
308 | err = -ENOMEM; | ||
309 | goto error_tlv; | ||
310 | } | ||
311 | |||
312 | if (service_name_tlv != NULL) | ||
313 | skb = llcp_add_tlv(skb, service_name_tlv, | ||
314 | service_name_tlv_length); | ||
315 | |||
316 | skb_queue_tail(&local->tx_queue, skb); | ||
317 | |||
318 | return 0; | ||
319 | |||
320 | error_tlv: | ||
321 | pr_err("error %d\n", err); | ||
322 | |||
323 | kfree(service_name_tlv); | ||
324 | |||
325 | return err; | ||
326 | } | ||
327 | |||
328 | int nfc_llcp_send_cc(struct nfc_llcp_sock *sock) | ||
329 | { | ||
330 | struct nfc_llcp_local *local; | ||
331 | struct sk_buff *skb; | ||
332 | |||
333 | pr_debug("Sending CC\n"); | ||
334 | |||
335 | local = sock->local; | ||
336 | if (local == NULL) | ||
337 | return -ENODEV; | ||
338 | |||
339 | skb = llcp_allocate_pdu(sock, LLCP_PDU_CC, 0); | ||
340 | if (skb == NULL) | ||
341 | return -ENOMEM; | ||
342 | |||
343 | skb_queue_tail(&local->tx_queue, skb); | ||
344 | |||
345 | return 0; | ||
346 | } | ||
347 | |||
348 | int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason) | ||
349 | { | ||
350 | struct sk_buff *skb; | ||
351 | struct nfc_dev *dev; | ||
352 | u16 size = 1; /* Reason code */ | ||
353 | |||
354 | pr_debug("Sending DM reason 0x%x\n", reason); | ||
355 | |||
356 | if (local == NULL) | ||
357 | return -ENODEV; | ||
358 | |||
359 | dev = local->dev; | ||
360 | if (dev == NULL) | ||
361 | return -ENODEV; | ||
362 | |||
363 | size += LLCP_HEADER_SIZE; | ||
364 | size += dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE; | ||
365 | |||
366 | skb = alloc_skb(size, GFP_KERNEL); | ||
367 | if (skb == NULL) | ||
368 | return -ENOMEM; | ||
369 | |||
370 | skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE); | ||
371 | |||
372 | skb = llcp_add_header(skb, ssap, dsap, LLCP_PDU_DM); | ||
373 | |||
374 | memcpy(skb_put(skb, 1), &reason, 1); | ||
375 | |||
376 | skb_queue_head(&local->tx_queue, skb); | ||
377 | |||
378 | return 0; | ||
379 | } | ||
380 | |||
381 | int nfc_llcp_send_disconnect(struct nfc_llcp_sock *sock) | ||
382 | { | ||
383 | struct sk_buff *skb; | ||
384 | struct nfc_llcp_local *local; | ||
385 | |||
386 | pr_debug("Send DISC\n"); | ||
387 | |||
388 | local = sock->local; | ||
389 | if (local == NULL) | ||
390 | return -ENODEV; | ||
391 | |||
392 | skb = llcp_allocate_pdu(sock, LLCP_PDU_DISC, 0); | ||
393 | if (skb == NULL) | ||
394 | return -ENOMEM; | ||
395 | |||
396 | skb_queue_head(&local->tx_queue, skb); | ||
397 | |||
398 | return 0; | ||
399 | } | ||
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c new file mode 100644 index 000000000000..67756b23eac5 --- /dev/null +++ b/net/nfc/llcp/llcp.c | |||
@@ -0,0 +1,973 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Intel Corporation. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the | ||
16 | * Free Software Foundation, Inc., | ||
17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
18 | */ | ||
19 | |||
20 | #define pr_fmt(fmt) "llcp: %s: " fmt, __func__ | ||
21 | |||
22 | #include <linux/init.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/list.h> | ||
25 | #include <linux/nfc.h> | ||
26 | |||
27 | #include "../nfc.h" | ||
28 | #include "llcp.h" | ||
29 | |||
30 | static u8 llcp_magic[3] = {0x46, 0x66, 0x6d}; | ||
31 | |||
32 | static struct list_head llcp_devices; | ||
33 | |||
34 | static void nfc_llcp_socket_release(struct nfc_llcp_local *local) | ||
35 | { | ||
36 | struct nfc_llcp_sock *parent, *s, *n; | ||
37 | struct sock *sk, *parent_sk; | ||
38 | int i; | ||
39 | |||
40 | |||
41 | mutex_lock(&local->socket_lock); | ||
42 | |||
43 | for (i = 0; i < LLCP_MAX_SAP; i++) { | ||
44 | parent = local->sockets[i]; | ||
45 | if (parent == NULL) | ||
46 | continue; | ||
47 | |||
48 | /* Release all child sockets */ | ||
49 | list_for_each_entry_safe(s, n, &parent->list, list) { | ||
50 | list_del(&s->list); | ||
51 | sk = &s->sk; | ||
52 | |||
53 | lock_sock(sk); | ||
54 | |||
55 | if (sk->sk_state == LLCP_CONNECTED) | ||
56 | nfc_put_device(s->dev); | ||
57 | |||
58 | sk->sk_state = LLCP_CLOSED; | ||
59 | sock_set_flag(sk, SOCK_DEAD); | ||
60 | |||
61 | release_sock(sk); | ||
62 | } | ||
63 | |||
64 | parent_sk = &parent->sk; | ||
65 | |||
66 | lock_sock(parent_sk); | ||
67 | |||
68 | if (parent_sk->sk_state == LLCP_LISTEN) { | ||
69 | struct nfc_llcp_sock *lsk, *n; | ||
70 | struct sock *accept_sk; | ||
71 | |||
72 | list_for_each_entry_safe(lsk, n, &parent->accept_queue, | ||
73 | accept_queue) { | ||
74 | accept_sk = &lsk->sk; | ||
75 | lock_sock(accept_sk); | ||
76 | |||
77 | nfc_llcp_accept_unlink(accept_sk); | ||
78 | |||
79 | accept_sk->sk_state = LLCP_CLOSED; | ||
80 | sock_set_flag(accept_sk, SOCK_DEAD); | ||
81 | |||
82 | release_sock(accept_sk); | ||
83 | |||
84 | sock_orphan(accept_sk); | ||
85 | } | ||
86 | } | ||
87 | |||
88 | if (parent_sk->sk_state == LLCP_CONNECTED) | ||
89 | nfc_put_device(parent->dev); | ||
90 | |||
91 | parent_sk->sk_state = LLCP_CLOSED; | ||
92 | sock_set_flag(parent_sk, SOCK_DEAD); | ||
93 | |||
94 | release_sock(parent_sk); | ||
95 | } | ||
96 | |||
97 | mutex_unlock(&local->socket_lock); | ||
98 | } | ||
99 | |||
100 | static void nfc_llcp_timeout_work(struct work_struct *work) | ||
101 | { | ||
102 | struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, | ||
103 | timeout_work); | ||
104 | |||
105 | nfc_dep_link_down(local->dev); | ||
106 | } | ||
107 | |||
108 | static void nfc_llcp_symm_timer(unsigned long data) | ||
109 | { | ||
110 | struct nfc_llcp_local *local = (struct nfc_llcp_local *) data; | ||
111 | |||
112 | pr_err("SYMM timeout\n"); | ||
113 | |||
114 | queue_work(local->timeout_wq, &local->timeout_work); | ||
115 | } | ||
116 | |||
117 | struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev) | ||
118 | { | ||
119 | struct nfc_llcp_local *local, *n; | ||
120 | |||
121 | list_for_each_entry_safe(local, n, &llcp_devices, list) | ||
122 | if (local->dev == dev) | ||
123 | return local; | ||
124 | |||
125 | pr_debug("No device found\n"); | ||
126 | |||
127 | return NULL; | ||
128 | } | ||
129 | |||
130 | static char *wks[] = { | ||
131 | NULL, | ||
132 | NULL, /* SDP */ | ||
133 | "urn:nfc:sn:ip", | ||
134 | "urn:nfc:sn:obex", | ||
135 | "urn:nfc:sn:snep", | ||
136 | }; | ||
137 | |||
138 | static int nfc_llcp_wks_sap(char *service_name, size_t service_name_len) | ||
139 | { | ||
140 | int sap, num_wks; | ||
141 | |||
142 | pr_debug("%s\n", service_name); | ||
143 | |||
144 | if (service_name == NULL) | ||
145 | return -EINVAL; | ||
146 | |||
147 | num_wks = ARRAY_SIZE(wks); | ||
148 | |||
149 | for (sap = 0 ; sap < num_wks; sap++) { | ||
150 | if (wks[sap] == NULL) | ||
151 | continue; | ||
152 | |||
153 | if (strncmp(wks[sap], service_name, service_name_len) == 0) | ||
154 | return sap; | ||
155 | } | ||
156 | |||
157 | return -EINVAL; | ||
158 | } | ||
159 | |||
160 | u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local, | ||
161 | struct nfc_llcp_sock *sock) | ||
162 | { | ||
163 | mutex_lock(&local->sdp_lock); | ||
164 | |||
165 | if (sock->service_name != NULL && sock->service_name_len > 0) { | ||
166 | int ssap = nfc_llcp_wks_sap(sock->service_name, | ||
167 | sock->service_name_len); | ||
168 | |||
169 | if (ssap > 0) { | ||
170 | pr_debug("WKS %d\n", ssap); | ||
171 | |||
172 | /* This is a WKS, let's check if it's free */ | ||
173 | if (local->local_wks & BIT(ssap)) { | ||
174 | mutex_unlock(&local->sdp_lock); | ||
175 | |||
176 | return LLCP_SAP_MAX; | ||
177 | } | ||
178 | |||
179 | set_bit(BIT(ssap), &local->local_wks); | ||
180 | mutex_unlock(&local->sdp_lock); | ||
181 | |||
182 | return ssap; | ||
183 | } | ||
184 | |||
185 | /* | ||
186 | * This is not a well known service, | ||
187 | * we should try to find a local SDP free spot | ||
188 | */ | ||
189 | ssap = find_first_zero_bit(&local->local_sdp, LLCP_SDP_NUM_SAP); | ||
190 | if (ssap == LLCP_SDP_NUM_SAP) { | ||
191 | mutex_unlock(&local->sdp_lock); | ||
192 | |||
193 | return LLCP_SAP_MAX; | ||
194 | } | ||
195 | |||
196 | pr_debug("SDP ssap %d\n", LLCP_WKS_NUM_SAP + ssap); | ||
197 | |||
198 | set_bit(BIT(ssap), &local->local_sdp); | ||
199 | mutex_unlock(&local->sdp_lock); | ||
200 | |||
201 | return LLCP_WKS_NUM_SAP + ssap; | ||
202 | |||
203 | } else if (sock->ssap != 0) { | ||
204 | if (sock->ssap < LLCP_WKS_NUM_SAP) { | ||
205 | if (!(local->local_wks & BIT(sock->ssap))) { | ||
206 | set_bit(BIT(sock->ssap), &local->local_wks); | ||
207 | mutex_unlock(&local->sdp_lock); | ||
208 | |||
209 | return sock->ssap; | ||
210 | } | ||
211 | |||
212 | } else if (sock->ssap < LLCP_SDP_NUM_SAP) { | ||
213 | if (!(local->local_sdp & | ||
214 | BIT(sock->ssap - LLCP_WKS_NUM_SAP))) { | ||
215 | set_bit(BIT(sock->ssap - LLCP_WKS_NUM_SAP), | ||
216 | &local->local_sdp); | ||
217 | mutex_unlock(&local->sdp_lock); | ||
218 | |||
219 | return sock->ssap; | ||
220 | } | ||
221 | } | ||
222 | } | ||
223 | |||
224 | mutex_unlock(&local->sdp_lock); | ||
225 | |||
226 | return LLCP_SAP_MAX; | ||
227 | } | ||
228 | |||
229 | u8 nfc_llcp_get_local_ssap(struct nfc_llcp_local *local) | ||
230 | { | ||
231 | u8 local_ssap; | ||
232 | |||
233 | mutex_lock(&local->sdp_lock); | ||
234 | |||
235 | local_ssap = find_first_zero_bit(&local->local_sap, LLCP_LOCAL_NUM_SAP); | ||
236 | if (local_ssap == LLCP_LOCAL_NUM_SAP) { | ||
237 | mutex_unlock(&local->sdp_lock); | ||
238 | return LLCP_SAP_MAX; | ||
239 | } | ||
240 | |||
241 | set_bit(BIT(local_ssap), &local->local_sap); | ||
242 | |||
243 | mutex_unlock(&local->sdp_lock); | ||
244 | |||
245 | return local_ssap + LLCP_LOCAL_SAP_OFFSET; | ||
246 | } | ||
247 | |||
248 | void nfc_llcp_put_ssap(struct nfc_llcp_local *local, u8 ssap) | ||
249 | { | ||
250 | u8 local_ssap; | ||
251 | unsigned long *sdp; | ||
252 | |||
253 | if (ssap < LLCP_WKS_NUM_SAP) { | ||
254 | local_ssap = ssap; | ||
255 | sdp = &local->local_wks; | ||
256 | } else if (ssap < LLCP_LOCAL_NUM_SAP) { | ||
257 | local_ssap = ssap - LLCP_WKS_NUM_SAP; | ||
258 | sdp = &local->local_sdp; | ||
259 | } else if (ssap < LLCP_MAX_SAP) { | ||
260 | local_ssap = ssap - LLCP_LOCAL_NUM_SAP; | ||
261 | sdp = &local->local_sap; | ||
262 | } else { | ||
263 | return; | ||
264 | } | ||
265 | |||
266 | mutex_lock(&local->sdp_lock); | ||
267 | |||
268 | clear_bit(1 << local_ssap, sdp); | ||
269 | |||
270 | mutex_unlock(&local->sdp_lock); | ||
271 | } | ||
272 | |||
273 | u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, u8 *general_bytes_len) | ||
274 | { | ||
275 | struct nfc_llcp_local *local; | ||
276 | |||
277 | local = nfc_llcp_find_local(dev); | ||
278 | if (local == NULL) { | ||
279 | *general_bytes_len = 0; | ||
280 | return NULL; | ||
281 | } | ||
282 | |||
283 | *general_bytes_len = local->gb_len; | ||
284 | |||
285 | return local->gb; | ||
286 | } | ||
287 | |||
288 | static int nfc_llcp_build_gb(struct nfc_llcp_local *local) | ||
289 | { | ||
290 | u8 *gb_cur, *version_tlv, version, version_length; | ||
291 | u8 *lto_tlv, lto, lto_length; | ||
292 | u8 *wks_tlv, wks_length; | ||
293 | u8 gb_len = 0; | ||
294 | |||
295 | version = LLCP_VERSION_11; | ||
296 | version_tlv = nfc_llcp_build_tlv(LLCP_TLV_VERSION, &version, | ||
297 | 1, &version_length); | ||
298 | gb_len += version_length; | ||
299 | |||
300 | /* 1500 ms */ | ||
301 | lto = 150; | ||
302 | lto_tlv = nfc_llcp_build_tlv(LLCP_TLV_VERSION, <o, 1, <o_length); | ||
303 | gb_len += lto_length; | ||
304 | |||
305 | pr_debug("Local wks 0x%lx\n", local->local_wks); | ||
306 | wks_tlv = nfc_llcp_build_tlv(LLCP_TLV_WKS, (u8 *)&local->local_wks, 2, | ||
307 | &wks_length); | ||
308 | gb_len += wks_length; | ||
309 | |||
310 | gb_len += ARRAY_SIZE(llcp_magic); | ||
311 | |||
312 | if (gb_len > NFC_MAX_GT_LEN) { | ||
313 | kfree(version_tlv); | ||
314 | return -EINVAL; | ||
315 | } | ||
316 | |||
317 | gb_cur = local->gb; | ||
318 | |||
319 | memcpy(gb_cur, llcp_magic, ARRAY_SIZE(llcp_magic)); | ||
320 | gb_cur += ARRAY_SIZE(llcp_magic); | ||
321 | |||
322 | memcpy(gb_cur, version_tlv, version_length); | ||
323 | gb_cur += version_length; | ||
324 | |||
325 | memcpy(gb_cur, lto_tlv, lto_length); | ||
326 | gb_cur += lto_length; | ||
327 | |||
328 | memcpy(gb_cur, wks_tlv, wks_length); | ||
329 | gb_cur += wks_length; | ||
330 | |||
331 | kfree(version_tlv); | ||
332 | kfree(lto_tlv); | ||
333 | |||
334 | local->gb_len = gb_len; | ||
335 | |||
336 | return 0; | ||
337 | } | ||
338 | |||
339 | int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len) | ||
340 | { | ||
341 | struct nfc_llcp_local *local = nfc_llcp_find_local(dev); | ||
342 | |||
343 | if (local == NULL) { | ||
344 | pr_err("No LLCP device\n"); | ||
345 | return -ENODEV; | ||
346 | } | ||
347 | |||
348 | memset(local->remote_gb, 0, NFC_MAX_GT_LEN); | ||
349 | memcpy(local->remote_gb, gb, gb_len); | ||
350 | local->remote_gb_len = gb_len; | ||
351 | |||
352 | if (local->remote_gb == NULL || | ||
353 | local->remote_gb_len == 0) | ||
354 | return -ENODEV; | ||
355 | |||
356 | if (memcmp(local->remote_gb, llcp_magic, 3)) { | ||
357 | pr_err("MAC does not support LLCP\n"); | ||
358 | return -EINVAL; | ||
359 | } | ||
360 | |||
361 | return nfc_llcp_parse_tlv(local, | ||
362 | &local->remote_gb[3], local->remote_gb_len - 3); | ||
363 | } | ||
364 | |||
365 | static void nfc_llcp_tx_work(struct work_struct *work) | ||
366 | { | ||
367 | struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, | ||
368 | tx_work); | ||
369 | struct sk_buff *skb; | ||
370 | |||
371 | skb = skb_dequeue(&local->tx_queue); | ||
372 | if (skb != NULL) { | ||
373 | pr_debug("Sending pending skb\n"); | ||
374 | nfc_data_exchange(local->dev, local->target_idx, | ||
375 | skb, nfc_llcp_recv, local); | ||
376 | } else { | ||
377 | nfc_llcp_send_symm(local->dev); | ||
378 | } | ||
379 | |||
380 | mod_timer(&local->link_timer, | ||
381 | jiffies + msecs_to_jiffies(local->remote_lto)); | ||
382 | } | ||
383 | |||
384 | static u8 nfc_llcp_dsap(struct sk_buff *pdu) | ||
385 | { | ||
386 | return (pdu->data[0] & 0xfc) >> 2; | ||
387 | } | ||
388 | |||
389 | static u8 nfc_llcp_ptype(struct sk_buff *pdu) | ||
390 | { | ||
391 | return ((pdu->data[0] & 0x03) << 2) | ((pdu->data[1] & 0xc0) >> 6); | ||
392 | } | ||
393 | |||
394 | static u8 nfc_llcp_ssap(struct sk_buff *pdu) | ||
395 | { | ||
396 | return pdu->data[1] & 0x3f; | ||
397 | } | ||
398 | |||
399 | static u8 nfc_llcp_ns(struct sk_buff *pdu) | ||
400 | { | ||
401 | return pdu->data[2] >> 4; | ||
402 | } | ||
403 | |||
404 | static u8 nfc_llcp_nr(struct sk_buff *pdu) | ||
405 | { | ||
406 | return pdu->data[2] & 0xf; | ||
407 | } | ||
408 | |||
409 | static void nfc_llcp_set_nrns(struct nfc_llcp_sock *sock, struct sk_buff *pdu) | ||
410 | { | ||
411 | pdu->data[2] = (sock->send_n << 4) | ((sock->recv_n - 1) % 16); | ||
412 | sock->send_n = (sock->send_n + 1) % 16; | ||
413 | sock->recv_ack_n = (sock->recv_n - 1) % 16; | ||
414 | } | ||
415 | |||
416 | static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local, | ||
417 | u8 ssap, u8 dsap) | ||
418 | { | ||
419 | struct nfc_llcp_sock *sock, *llcp_sock, *n; | ||
420 | |||
421 | if (ssap == 0 && dsap == 0) | ||
422 | return NULL; | ||
423 | |||
424 | mutex_lock(&local->socket_lock); | ||
425 | sock = local->sockets[ssap]; | ||
426 | if (sock == NULL) { | ||
427 | mutex_unlock(&local->socket_lock); | ||
428 | return NULL; | ||
429 | } | ||
430 | |||
431 | pr_debug("root dsap %d (%d)\n", sock->dsap, dsap); | ||
432 | |||
433 | if (sock->dsap == dsap) { | ||
434 | sock_hold(&sock->sk); | ||
435 | mutex_unlock(&local->socket_lock); | ||
436 | return sock; | ||
437 | } | ||
438 | |||
439 | list_for_each_entry_safe(llcp_sock, n, &sock->list, list) { | ||
440 | pr_debug("llcp_sock %p sk %p dsap %d\n", llcp_sock, | ||
441 | &llcp_sock->sk, llcp_sock->dsap); | ||
442 | if (llcp_sock->dsap == dsap) { | ||
443 | sock_hold(&llcp_sock->sk); | ||
444 | mutex_unlock(&local->socket_lock); | ||
445 | return llcp_sock; | ||
446 | } | ||
447 | } | ||
448 | |||
449 | pr_err("Could not find socket for %d %d\n", ssap, dsap); | ||
450 | |||
451 | mutex_unlock(&local->socket_lock); | ||
452 | |||
453 | return NULL; | ||
454 | } | ||
455 | |||
456 | static void nfc_llcp_sock_put(struct nfc_llcp_sock *sock) | ||
457 | { | ||
458 | sock_put(&sock->sk); | ||
459 | } | ||
460 | |||
461 | static u8 *nfc_llcp_connect_sn(struct sk_buff *skb, size_t *sn_len) | ||
462 | { | ||
463 | u8 *tlv = &skb->data[2], type, length; | ||
464 | size_t tlv_array_len = skb->len - LLCP_HEADER_SIZE, offset = 0; | ||
465 | |||
466 | while (offset < tlv_array_len) { | ||
467 | type = tlv[0]; | ||
468 | length = tlv[1]; | ||
469 | |||
470 | pr_debug("type 0x%x length %d\n", type, length); | ||
471 | |||
472 | if (type == LLCP_TLV_SN) { | ||
473 | *sn_len = length; | ||
474 | return &tlv[2]; | ||
475 | } | ||
476 | |||
477 | offset += length + 2; | ||
478 | tlv += length + 2; | ||
479 | } | ||
480 | |||
481 | return NULL; | ||
482 | } | ||
483 | |||
484 | static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, | ||
485 | struct sk_buff *skb) | ||
486 | { | ||
487 | struct sock *new_sk, *parent; | ||
488 | struct nfc_llcp_sock *sock, *new_sock; | ||
489 | u8 dsap, ssap, bound_sap, reason; | ||
490 | |||
491 | dsap = nfc_llcp_dsap(skb); | ||
492 | ssap = nfc_llcp_ssap(skb); | ||
493 | |||
494 | pr_debug("%d %d\n", dsap, ssap); | ||
495 | |||
496 | nfc_llcp_parse_tlv(local, &skb->data[LLCP_HEADER_SIZE], | ||
497 | skb->len - LLCP_HEADER_SIZE); | ||
498 | |||
499 | if (dsap != LLCP_SAP_SDP) { | ||
500 | bound_sap = dsap; | ||
501 | |||
502 | mutex_lock(&local->socket_lock); | ||
503 | sock = local->sockets[dsap]; | ||
504 | if (sock == NULL) { | ||
505 | mutex_unlock(&local->socket_lock); | ||
506 | reason = LLCP_DM_NOBOUND; | ||
507 | goto fail; | ||
508 | } | ||
509 | |||
510 | sock_hold(&sock->sk); | ||
511 | mutex_unlock(&local->socket_lock); | ||
512 | |||
513 | lock_sock(&sock->sk); | ||
514 | |||
515 | if (sock->dsap == LLCP_SAP_SDP && | ||
516 | sock->sk.sk_state == LLCP_LISTEN) | ||
517 | goto enqueue; | ||
518 | } else { | ||
519 | u8 *sn; | ||
520 | size_t sn_len; | ||
521 | |||
522 | sn = nfc_llcp_connect_sn(skb, &sn_len); | ||
523 | if (sn == NULL) { | ||
524 | reason = LLCP_DM_NOBOUND; | ||
525 | goto fail; | ||
526 | } | ||
527 | |||
528 | pr_debug("Service name length %zu\n", sn_len); | ||
529 | |||
530 | mutex_lock(&local->socket_lock); | ||
531 | for (bound_sap = 0; bound_sap < LLCP_LOCAL_SAP_OFFSET; | ||
532 | bound_sap++) { | ||
533 | sock = local->sockets[bound_sap]; | ||
534 | if (sock == NULL) | ||
535 | continue; | ||
536 | |||
537 | if (sock->service_name == NULL || | ||
538 | sock->service_name_len == 0) | ||
539 | continue; | ||
540 | |||
541 | if (sock->service_name_len != sn_len) | ||
542 | continue; | ||
543 | |||
544 | if (sock->dsap == LLCP_SAP_SDP && | ||
545 | sock->sk.sk_state == LLCP_LISTEN && | ||
546 | !memcmp(sn, sock->service_name, sn_len)) { | ||
547 | pr_debug("Found service name at SAP %d\n", | ||
548 | bound_sap); | ||
549 | sock_hold(&sock->sk); | ||
550 | mutex_unlock(&local->socket_lock); | ||
551 | |||
552 | lock_sock(&sock->sk); | ||
553 | |||
554 | goto enqueue; | ||
555 | } | ||
556 | } | ||
557 | |||
558 | } | ||
559 | |||
560 | mutex_unlock(&local->socket_lock); | ||
561 | |||
562 | reason = LLCP_DM_NOBOUND; | ||
563 | goto fail; | ||
564 | |||
565 | enqueue: | ||
566 | parent = &sock->sk; | ||
567 | |||
568 | if (sk_acceptq_is_full(parent)) { | ||
569 | reason = LLCP_DM_REJ; | ||
570 | release_sock(&sock->sk); | ||
571 | sock_put(&sock->sk); | ||
572 | goto fail; | ||
573 | } | ||
574 | |||
575 | new_sk = nfc_llcp_sock_alloc(NULL, parent->sk_type, | ||
576 | GFP_ATOMIC); | ||
577 | if (new_sk == NULL) { | ||
578 | reason = LLCP_DM_REJ; | ||
579 | release_sock(&sock->sk); | ||
580 | sock_put(&sock->sk); | ||
581 | goto fail; | ||
582 | } | ||
583 | |||
584 | new_sock = nfc_llcp_sock(new_sk); | ||
585 | new_sock->dev = local->dev; | ||
586 | new_sock->local = local; | ||
587 | new_sock->nfc_protocol = sock->nfc_protocol; | ||
588 | new_sock->ssap = bound_sap; | ||
589 | new_sock->dsap = ssap; | ||
590 | new_sock->parent = parent; | ||
591 | |||
592 | pr_debug("new sock %p sk %p\n", new_sock, &new_sock->sk); | ||
593 | |||
594 | list_add_tail(&new_sock->list, &sock->list); | ||
595 | |||
596 | nfc_llcp_accept_enqueue(&sock->sk, new_sk); | ||
597 | |||
598 | nfc_get_device(local->dev->idx); | ||
599 | |||
600 | new_sk->sk_state = LLCP_CONNECTED; | ||
601 | |||
602 | /* Wake the listening processes */ | ||
603 | parent->sk_data_ready(parent, 0); | ||
604 | |||
605 | /* Send CC */ | ||
606 | nfc_llcp_send_cc(new_sock); | ||
607 | |||
608 | release_sock(&sock->sk); | ||
609 | sock_put(&sock->sk); | ||
610 | |||
611 | return; | ||
612 | |||
613 | fail: | ||
614 | /* Send DM */ | ||
615 | nfc_llcp_send_dm(local, dsap, ssap, reason); | ||
616 | |||
617 | return; | ||
618 | |||
619 | } | ||
620 | |||
621 | static void nfc_llcp_recv_hdlc(struct nfc_llcp_local *local, | ||
622 | struct sk_buff *skb) | ||
623 | { | ||
624 | struct nfc_llcp_sock *llcp_sock; | ||
625 | struct sock *sk; | ||
626 | u8 dsap, ssap, ptype, ns, nr; | ||
627 | |||
628 | ptype = nfc_llcp_ptype(skb); | ||
629 | dsap = nfc_llcp_dsap(skb); | ||
630 | ssap = nfc_llcp_ssap(skb); | ||
631 | ns = nfc_llcp_ns(skb); | ||
632 | nr = nfc_llcp_nr(skb); | ||
633 | |||
634 | pr_debug("%d %d R %d S %d\n", dsap, ssap, nr, ns); | ||
635 | |||
636 | llcp_sock = nfc_llcp_sock_get(local, dsap, ssap); | ||
637 | if (llcp_sock == NULL) { | ||
638 | nfc_llcp_send_dm(local, dsap, ssap, LLCP_DM_NOCONN); | ||
639 | return; | ||
640 | } | ||
641 | |||
642 | sk = &llcp_sock->sk; | ||
643 | lock_sock(sk); | ||
644 | if (sk->sk_state == LLCP_CLOSED) { | ||
645 | release_sock(sk); | ||
646 | nfc_llcp_sock_put(llcp_sock); | ||
647 | } | ||
648 | |||
649 | if (ns == llcp_sock->recv_n) | ||
650 | llcp_sock->recv_n = (llcp_sock->recv_n + 1) % 16; | ||
651 | else | ||
652 | pr_err("Received out of sequence I PDU\n"); | ||
653 | |||
654 | /* Pass the payload upstream */ | ||
655 | if (ptype == LLCP_PDU_I) { | ||
656 | pr_debug("I frame, queueing on %p\n", &llcp_sock->sk); | ||
657 | |||
658 | skb_pull(skb, LLCP_HEADER_SIZE + LLCP_SEQUENCE_SIZE); | ||
659 | if (sock_queue_rcv_skb(&llcp_sock->sk, skb)) { | ||
660 | pr_err("receive queue is full\n"); | ||
661 | skb_queue_head(&llcp_sock->tx_backlog_queue, skb); | ||
662 | } | ||
663 | } | ||
664 | |||
665 | /* Remove skbs from the pending queue */ | ||
666 | if (llcp_sock->send_ack_n != nr) { | ||
667 | struct sk_buff *s, *tmp; | ||
668 | |||
669 | llcp_sock->send_ack_n = nr; | ||
670 | |||
671 | skb_queue_walk_safe(&llcp_sock->tx_pending_queue, s, tmp) | ||
672 | if (nfc_llcp_ns(s) <= nr) { | ||
673 | skb_unlink(s, &llcp_sock->tx_pending_queue); | ||
674 | kfree_skb(s); | ||
675 | } | ||
676 | } | ||
677 | |||
678 | /* Queue some I frames for transmission */ | ||
679 | while (llcp_sock->remote_ready && | ||
680 | skb_queue_len(&llcp_sock->tx_pending_queue) <= local->remote_rw) { | ||
681 | struct sk_buff *pdu, *pending_pdu; | ||
682 | |||
683 | pdu = skb_dequeue(&llcp_sock->tx_queue); | ||
684 | if (pdu == NULL) | ||
685 | break; | ||
686 | |||
687 | /* Update N(S)/N(R) */ | ||
688 | nfc_llcp_set_nrns(llcp_sock, pdu); | ||
689 | |||
690 | pending_pdu = skb_clone(pdu, GFP_KERNEL); | ||
691 | |||
692 | skb_queue_tail(&local->tx_queue, pdu); | ||
693 | skb_queue_tail(&llcp_sock->tx_pending_queue, pending_pdu); | ||
694 | } | ||
695 | |||
696 | release_sock(sk); | ||
697 | nfc_llcp_sock_put(llcp_sock); | ||
698 | } | ||
699 | |||
700 | static void nfc_llcp_recv_disc(struct nfc_llcp_local *local, | ||
701 | struct sk_buff *skb) | ||
702 | { | ||
703 | struct nfc_llcp_sock *llcp_sock; | ||
704 | struct sock *sk; | ||
705 | u8 dsap, ssap; | ||
706 | |||
707 | dsap = nfc_llcp_dsap(skb); | ||
708 | ssap = nfc_llcp_ssap(skb); | ||
709 | |||
710 | llcp_sock = nfc_llcp_sock_get(local, dsap, ssap); | ||
711 | if (llcp_sock == NULL) { | ||
712 | nfc_llcp_send_dm(local, dsap, ssap, LLCP_DM_NOCONN); | ||
713 | return; | ||
714 | } | ||
715 | |||
716 | sk = &llcp_sock->sk; | ||
717 | lock_sock(sk); | ||
718 | if (sk->sk_state == LLCP_CLOSED) { | ||
719 | release_sock(sk); | ||
720 | nfc_llcp_sock_put(llcp_sock); | ||
721 | } | ||
722 | |||
723 | |||
724 | if (sk->sk_state == LLCP_CONNECTED) { | ||
725 | nfc_put_device(local->dev); | ||
726 | sk->sk_state = LLCP_CLOSED; | ||
727 | sk->sk_state_change(sk); | ||
728 | } | ||
729 | |||
730 | nfc_llcp_send_dm(local, dsap, ssap, LLCP_DM_DISC); | ||
731 | |||
732 | release_sock(sk); | ||
733 | nfc_llcp_sock_put(llcp_sock); | ||
734 | } | ||
735 | |||
736 | static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, | ||
737 | struct sk_buff *skb) | ||
738 | { | ||
739 | struct nfc_llcp_sock *llcp_sock; | ||
740 | u8 dsap, ssap; | ||
741 | |||
742 | |||
743 | dsap = nfc_llcp_dsap(skb); | ||
744 | ssap = nfc_llcp_ssap(skb); | ||
745 | |||
746 | llcp_sock = nfc_llcp_sock_get(local, dsap, ssap); | ||
747 | |||
748 | if (llcp_sock == NULL) | ||
749 | llcp_sock = nfc_llcp_sock_get(local, dsap, LLCP_SAP_SDP); | ||
750 | |||
751 | if (llcp_sock == NULL) { | ||
752 | pr_err("Invalid CC\n"); | ||
753 | nfc_llcp_send_dm(local, dsap, ssap, LLCP_DM_NOCONN); | ||
754 | |||
755 | return; | ||
756 | } | ||
757 | |||
758 | llcp_sock->dsap = ssap; | ||
759 | |||
760 | nfc_llcp_parse_tlv(local, &skb->data[LLCP_HEADER_SIZE], | ||
761 | skb->len - LLCP_HEADER_SIZE); | ||
762 | |||
763 | nfc_llcp_sock_put(llcp_sock); | ||
764 | } | ||
765 | |||
766 | static void nfc_llcp_rx_work(struct work_struct *work) | ||
767 | { | ||
768 | struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, | ||
769 | rx_work); | ||
770 | u8 dsap, ssap, ptype; | ||
771 | struct sk_buff *skb; | ||
772 | |||
773 | skb = local->rx_pending; | ||
774 | if (skb == NULL) { | ||
775 | pr_debug("No pending SKB\n"); | ||
776 | return; | ||
777 | } | ||
778 | |||
779 | ptype = nfc_llcp_ptype(skb); | ||
780 | dsap = nfc_llcp_dsap(skb); | ||
781 | ssap = nfc_llcp_ssap(skb); | ||
782 | |||
783 | pr_debug("ptype 0x%x dsap 0x%x ssap 0x%x\n", ptype, dsap, ssap); | ||
784 | |||
785 | switch (ptype) { | ||
786 | case LLCP_PDU_SYMM: | ||
787 | pr_debug("SYMM\n"); | ||
788 | break; | ||
789 | |||
790 | case LLCP_PDU_CONNECT: | ||
791 | pr_debug("CONNECT\n"); | ||
792 | nfc_llcp_recv_connect(local, skb); | ||
793 | break; | ||
794 | |||
795 | case LLCP_PDU_DISC: | ||
796 | pr_debug("DISC\n"); | ||
797 | nfc_llcp_recv_disc(local, skb); | ||
798 | break; | ||
799 | |||
800 | case LLCP_PDU_CC: | ||
801 | pr_debug("CC\n"); | ||
802 | nfc_llcp_recv_cc(local, skb); | ||
803 | break; | ||
804 | |||
805 | case LLCP_PDU_I: | ||
806 | case LLCP_PDU_RR: | ||
807 | pr_debug("I frame\n"); | ||
808 | nfc_llcp_recv_hdlc(local, skb); | ||
809 | break; | ||
810 | |||
811 | } | ||
812 | |||
813 | queue_work(local->tx_wq, &local->tx_work); | ||
814 | kfree_skb(local->rx_pending); | ||
815 | local->rx_pending = NULL; | ||
816 | |||
817 | return; | ||
818 | } | ||
819 | |||
820 | void nfc_llcp_recv(void *data, struct sk_buff *skb, int err) | ||
821 | { | ||
822 | struct nfc_llcp_local *local = (struct nfc_llcp_local *) data; | ||
823 | |||
824 | pr_debug("Received an LLCP PDU\n"); | ||
825 | if (err < 0) { | ||
826 | pr_err("err %d", err); | ||
827 | return; | ||
828 | } | ||
829 | |||
830 | local->rx_pending = skb_get(skb); | ||
831 | del_timer(&local->link_timer); | ||
832 | queue_work(local->rx_wq, &local->rx_work); | ||
833 | |||
834 | return; | ||
835 | } | ||
836 | |||
837 | void nfc_llcp_mac_is_down(struct nfc_dev *dev) | ||
838 | { | ||
839 | struct nfc_llcp_local *local; | ||
840 | |||
841 | local = nfc_llcp_find_local(dev); | ||
842 | if (local == NULL) | ||
843 | return; | ||
844 | |||
845 | /* Close and purge all existing sockets */ | ||
846 | nfc_llcp_socket_release(local); | ||
847 | } | ||
848 | |||
849 | void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx, | ||
850 | u8 comm_mode, u8 rf_mode) | ||
851 | { | ||
852 | struct nfc_llcp_local *local; | ||
853 | |||
854 | pr_debug("rf mode %d\n", rf_mode); | ||
855 | |||
856 | local = nfc_llcp_find_local(dev); | ||
857 | if (local == NULL) | ||
858 | return; | ||
859 | |||
860 | local->target_idx = target_idx; | ||
861 | local->comm_mode = comm_mode; | ||
862 | local->rf_mode = rf_mode; | ||
863 | |||
864 | if (rf_mode == NFC_RF_INITIATOR) { | ||
865 | pr_debug("Queueing Tx work\n"); | ||
866 | |||
867 | queue_work(local->tx_wq, &local->tx_work); | ||
868 | } else { | ||
869 | mod_timer(&local->link_timer, | ||
870 | jiffies + msecs_to_jiffies(local->remote_lto)); | ||
871 | } | ||
872 | } | ||
873 | |||
874 | int nfc_llcp_register_device(struct nfc_dev *ndev) | ||
875 | { | ||
876 | struct device *dev = &ndev->dev; | ||
877 | struct nfc_llcp_local *local; | ||
878 | char name[32]; | ||
879 | int err; | ||
880 | |||
881 | local = kzalloc(sizeof(struct nfc_llcp_local), GFP_KERNEL); | ||
882 | if (local == NULL) | ||
883 | return -ENOMEM; | ||
884 | |||
885 | local->dev = ndev; | ||
886 | INIT_LIST_HEAD(&local->list); | ||
887 | mutex_init(&local->sdp_lock); | ||
888 | mutex_init(&local->socket_lock); | ||
889 | init_timer(&local->link_timer); | ||
890 | local->link_timer.data = (unsigned long) local; | ||
891 | local->link_timer.function = nfc_llcp_symm_timer; | ||
892 | |||
893 | skb_queue_head_init(&local->tx_queue); | ||
894 | INIT_WORK(&local->tx_work, nfc_llcp_tx_work); | ||
895 | snprintf(name, sizeof(name), "%s_llcp_tx_wq", dev_name(dev)); | ||
896 | local->tx_wq = alloc_workqueue(name, | ||
897 | WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM, 1); | ||
898 | if (local->tx_wq == NULL) { | ||
899 | err = -ENOMEM; | ||
900 | goto err_local; | ||
901 | } | ||
902 | |||
903 | local->rx_pending = NULL; | ||
904 | INIT_WORK(&local->rx_work, nfc_llcp_rx_work); | ||
905 | snprintf(name, sizeof(name), "%s_llcp_rx_wq", dev_name(dev)); | ||
906 | local->rx_wq = alloc_workqueue(name, | ||
907 | WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM, 1); | ||
908 | if (local->rx_wq == NULL) { | ||
909 | err = -ENOMEM; | ||
910 | goto err_tx_wq; | ||
911 | } | ||
912 | |||
913 | INIT_WORK(&local->timeout_work, nfc_llcp_timeout_work); | ||
914 | snprintf(name, sizeof(name), "%s_llcp_timeout_wq", dev_name(dev)); | ||
915 | local->timeout_wq = alloc_workqueue(name, | ||
916 | WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM, 1); | ||
917 | if (local->timeout_wq == NULL) { | ||
918 | err = -ENOMEM; | ||
919 | goto err_rx_wq; | ||
920 | } | ||
921 | |||
922 | nfc_llcp_build_gb(local); | ||
923 | |||
924 | local->remote_miu = LLCP_DEFAULT_MIU; | ||
925 | local->remote_lto = LLCP_DEFAULT_LTO; | ||
926 | local->remote_rw = LLCP_DEFAULT_RW; | ||
927 | |||
928 | list_add(&llcp_devices, &local->list); | ||
929 | |||
930 | return 0; | ||
931 | |||
932 | err_rx_wq: | ||
933 | destroy_workqueue(local->rx_wq); | ||
934 | |||
935 | err_tx_wq: | ||
936 | destroy_workqueue(local->tx_wq); | ||
937 | |||
938 | err_local: | ||
939 | kfree(local); | ||
940 | |||
941 | return 0; | ||
942 | } | ||
943 | |||
944 | void nfc_llcp_unregister_device(struct nfc_dev *dev) | ||
945 | { | ||
946 | struct nfc_llcp_local *local = nfc_llcp_find_local(dev); | ||
947 | |||
948 | if (local == NULL) { | ||
949 | pr_debug("No such device\n"); | ||
950 | return; | ||
951 | } | ||
952 | |||
953 | list_del(&local->list); | ||
954 | nfc_llcp_socket_release(local); | ||
955 | del_timer_sync(&local->link_timer); | ||
956 | skb_queue_purge(&local->tx_queue); | ||
957 | destroy_workqueue(local->tx_wq); | ||
958 | destroy_workqueue(local->rx_wq); | ||
959 | kfree(local->rx_pending); | ||
960 | kfree(local); | ||
961 | } | ||
962 | |||
963 | int __init nfc_llcp_init(void) | ||
964 | { | ||
965 | INIT_LIST_HEAD(&llcp_devices); | ||
966 | |||
967 | return nfc_llcp_sock_init(); | ||
968 | } | ||
969 | |||
970 | void nfc_llcp_exit(void) | ||
971 | { | ||
972 | nfc_llcp_sock_exit(); | ||
973 | } | ||
diff --git a/net/nfc/llcp/llcp.h b/net/nfc/llcp/llcp.h new file mode 100644 index 000000000000..0ad2e3361584 --- /dev/null +++ b/net/nfc/llcp/llcp.h | |||
@@ -0,0 +1,193 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Intel Corporation. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the | ||
16 | * Free Software Foundation, Inc., | ||
17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
18 | */ | ||
19 | |||
20 | enum llcp_state { | ||
21 | LLCP_CONNECTED = 1, /* wait_for_packet() wants that */ | ||
22 | LLCP_CLOSED, | ||
23 | LLCP_BOUND, | ||
24 | LLCP_LISTEN, | ||
25 | }; | ||
26 | |||
27 | #define LLCP_DEFAULT_LTO 100 | ||
28 | #define LLCP_DEFAULT_RW 1 | ||
29 | #define LLCP_DEFAULT_MIU 128 | ||
30 | |||
31 | #define LLCP_WKS_NUM_SAP 16 | ||
32 | #define LLCP_SDP_NUM_SAP 16 | ||
33 | #define LLCP_LOCAL_NUM_SAP 32 | ||
34 | #define LLCP_LOCAL_SAP_OFFSET (LLCP_WKS_NUM_SAP + LLCP_SDP_NUM_SAP) | ||
35 | #define LLCP_MAX_SAP (LLCP_WKS_NUM_SAP + LLCP_SDP_NUM_SAP + LLCP_LOCAL_NUM_SAP) | ||
36 | |||
37 | struct nfc_llcp_sock; | ||
38 | |||
39 | struct nfc_llcp_local { | ||
40 | struct list_head list; | ||
41 | struct nfc_dev *dev; | ||
42 | |||
43 | struct mutex sdp_lock; | ||
44 | struct mutex socket_lock; | ||
45 | |||
46 | struct timer_list link_timer; | ||
47 | struct sk_buff_head tx_queue; | ||
48 | struct workqueue_struct *tx_wq; | ||
49 | struct work_struct tx_work; | ||
50 | struct workqueue_struct *rx_wq; | ||
51 | struct work_struct rx_work; | ||
52 | struct sk_buff *rx_pending; | ||
53 | struct workqueue_struct *timeout_wq; | ||
54 | struct work_struct timeout_work; | ||
55 | |||
56 | u32 target_idx; | ||
57 | u8 rf_mode; | ||
58 | u8 comm_mode; | ||
59 | unsigned long local_wks; /* Well known services */ | ||
60 | unsigned long local_sdp; /* Local services */ | ||
61 | unsigned long local_sap; /* Local SAPs, not available for discovery */ | ||
62 | |||
63 | /* local */ | ||
64 | u8 gb[NFC_MAX_GT_LEN]; | ||
65 | u8 gb_len; | ||
66 | |||
67 | /* remote */ | ||
68 | u8 remote_gb[NFC_MAX_GT_LEN]; | ||
69 | u8 remote_gb_len; | ||
70 | |||
71 | u8 remote_version; | ||
72 | u16 remote_miu; | ||
73 | u16 remote_lto; | ||
74 | u8 remote_opt; | ||
75 | u16 remote_wks; | ||
76 | u8 remote_rw; | ||
77 | |||
78 | /* sockets array */ | ||
79 | struct nfc_llcp_sock *sockets[LLCP_MAX_SAP]; | ||
80 | }; | ||
81 | |||
82 | struct nfc_llcp_sock { | ||
83 | struct sock sk; | ||
84 | struct list_head list; | ||
85 | struct nfc_dev *dev; | ||
86 | struct nfc_llcp_local *local; | ||
87 | u32 target_idx; | ||
88 | u32 nfc_protocol; | ||
89 | |||
90 | u8 ssap; | ||
91 | u8 dsap; | ||
92 | char *service_name; | ||
93 | size_t service_name_len; | ||
94 | |||
95 | /* Link variables */ | ||
96 | u8 send_n; | ||
97 | u8 send_ack_n; | ||
98 | u8 recv_n; | ||
99 | u8 recv_ack_n; | ||
100 | |||
101 | /* Is the remote peer ready to receive */ | ||
102 | u8 remote_ready; | ||
103 | |||
104 | struct sk_buff_head tx_queue; | ||
105 | struct sk_buff_head tx_pending_queue; | ||
106 | struct sk_buff_head tx_backlog_queue; | ||
107 | |||
108 | struct list_head accept_queue; | ||
109 | struct sock *parent; | ||
110 | }; | ||
111 | |||
112 | #define nfc_llcp_sock(sk) ((struct nfc_llcp_sock *) (sk)) | ||
113 | #define nfc_llcp_dev(sk) (nfc_llcp_sock((sk))->dev) | ||
114 | |||
115 | #define LLCP_HEADER_SIZE 2 | ||
116 | #define LLCP_SEQUENCE_SIZE 1 | ||
117 | |||
118 | /* LLCP versions: 1.1 is 1.0 plus SDP */ | ||
119 | #define LLCP_VERSION_10 0x10 | ||
120 | #define LLCP_VERSION_11 0x11 | ||
121 | |||
122 | /* LLCP PDU types */ | ||
123 | #define LLCP_PDU_SYMM 0x0 | ||
124 | #define LLCP_PDU_PAX 0x1 | ||
125 | #define LLCP_PDU_AGF 0x2 | ||
126 | #define LLCP_PDU_UI 0x3 | ||
127 | #define LLCP_PDU_CONNECT 0x4 | ||
128 | #define LLCP_PDU_DISC 0x5 | ||
129 | #define LLCP_PDU_CC 0x6 | ||
130 | #define LLCP_PDU_DM 0x7 | ||
131 | #define LLCP_PDU_FRMR 0x8 | ||
132 | #define LLCP_PDU_SNL 0x9 | ||
133 | #define LLCP_PDU_I 0xc | ||
134 | #define LLCP_PDU_RR 0xd | ||
135 | #define LLCP_PDU_RNR 0xe | ||
136 | |||
137 | /* Parameters TLV types */ | ||
138 | #define LLCP_TLV_VERSION 0x1 | ||
139 | #define LLCP_TLV_MIUX 0x2 | ||
140 | #define LLCP_TLV_WKS 0x3 | ||
141 | #define LLCP_TLV_LTO 0x4 | ||
142 | #define LLCP_TLV_RW 0x5 | ||
143 | #define LLCP_TLV_SN 0x6 | ||
144 | #define LLCP_TLV_OPT 0x7 | ||
145 | #define LLCP_TLV_SDREQ 0x8 | ||
146 | #define LLCP_TLV_SDRES 0x9 | ||
147 | #define LLCP_TLV_MAX 0xa | ||
148 | |||
149 | /* Well known LLCP SAP */ | ||
150 | #define LLCP_SAP_SDP 0x1 | ||
151 | #define LLCP_SAP_IP 0x2 | ||
152 | #define LLCP_SAP_OBEX 0x3 | ||
153 | #define LLCP_SAP_SNEP 0x4 | ||
154 | #define LLCP_SAP_MAX 0xff | ||
155 | |||
156 | /* Disconnection reason code */ | ||
157 | #define LLCP_DM_DISC 0x00 | ||
158 | #define LLCP_DM_NOCONN 0x01 | ||
159 | #define LLCP_DM_NOBOUND 0x02 | ||
160 | #define LLCP_DM_REJ 0x03 | ||
161 | |||
162 | |||
163 | struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev); | ||
164 | u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local, | ||
165 | struct nfc_llcp_sock *sock); | ||
166 | u8 nfc_llcp_get_local_ssap(struct nfc_llcp_local *local); | ||
167 | void nfc_llcp_put_ssap(struct nfc_llcp_local *local, u8 ssap); | ||
168 | |||
169 | /* Sock API */ | ||
170 | struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp); | ||
171 | void nfc_llcp_sock_free(struct nfc_llcp_sock *sock); | ||
172 | void nfc_llcp_accept_unlink(struct sock *sk); | ||
173 | void nfc_llcp_accept_enqueue(struct sock *parent, struct sock *sk); | ||
174 | struct sock *nfc_llcp_accept_dequeue(struct sock *sk, struct socket *newsock); | ||
175 | |||
176 | /* TLV API */ | ||
177 | int nfc_llcp_parse_tlv(struct nfc_llcp_local *local, | ||
178 | u8 *tlv_array, u16 tlv_array_len); | ||
179 | |||
180 | /* Commands API */ | ||
181 | void nfc_llcp_recv(void *data, struct sk_buff *skb, int err); | ||
182 | u8 *nfc_llcp_build_tlv(u8 type, u8 *value, u8 value_length, u8 *tlv_length); | ||
183 | void nfc_llcp_recv(void *data, struct sk_buff *skb, int err); | ||
184 | int nfc_llcp_disconnect(struct nfc_llcp_sock *sock); | ||
185 | int nfc_llcp_send_symm(struct nfc_dev *dev); | ||
186 | int nfc_llcp_send_connect(struct nfc_llcp_sock *sock); | ||
187 | int nfc_llcp_send_cc(struct nfc_llcp_sock *sock); | ||
188 | int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason); | ||
189 | int nfc_llcp_send_disconnect(struct nfc_llcp_sock *sock); | ||
190 | |||
191 | /* Socket API */ | ||
192 | int __init nfc_llcp_sock_init(void); | ||
193 | void nfc_llcp_sock_exit(void); | ||
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c new file mode 100644 index 000000000000..f738ccd535f1 --- /dev/null +++ b/net/nfc/llcp/sock.c | |||
@@ -0,0 +1,675 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Intel Corporation. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the | ||
16 | * Free Software Foundation, Inc., | ||
17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
18 | */ | ||
19 | |||
20 | #define pr_fmt(fmt) "llcp: %s: " fmt, __func__ | ||
21 | |||
22 | #include <linux/init.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/nfc.h> | ||
26 | |||
27 | #include "../nfc.h" | ||
28 | #include "llcp.h" | ||
29 | |||
30 | static struct proto llcp_sock_proto = { | ||
31 | .name = "NFC_LLCP", | ||
32 | .owner = THIS_MODULE, | ||
33 | .obj_size = sizeof(struct nfc_llcp_sock), | ||
34 | }; | ||
35 | |||
36 | static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) | ||
37 | { | ||
38 | struct sock *sk = sock->sk; | ||
39 | struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); | ||
40 | struct nfc_llcp_local *local; | ||
41 | struct nfc_dev *dev; | ||
42 | struct sockaddr_nfc_llcp llcp_addr; | ||
43 | int len, ret = 0; | ||
44 | |||
45 | pr_debug("sk %p addr %p family %d\n", sk, addr, addr->sa_family); | ||
46 | |||
47 | if (!addr || addr->sa_family != AF_NFC) | ||
48 | return -EINVAL; | ||
49 | |||
50 | memset(&llcp_addr, 0, sizeof(llcp_addr)); | ||
51 | len = min_t(unsigned int, sizeof(llcp_addr), alen); | ||
52 | memcpy(&llcp_addr, addr, len); | ||
53 | |||
54 | /* This is going to be a listening socket, dsap must be 0 */ | ||
55 | if (llcp_addr.dsap != 0) | ||
56 | return -EINVAL; | ||
57 | |||
58 | lock_sock(sk); | ||
59 | |||
60 | if (sk->sk_state != LLCP_CLOSED) { | ||
61 | ret = -EBADFD; | ||
62 | goto error; | ||
63 | } | ||
64 | |||
65 | dev = nfc_get_device(llcp_addr.dev_idx); | ||
66 | if (dev == NULL) { | ||
67 | ret = -ENODEV; | ||
68 | goto error; | ||
69 | } | ||
70 | |||
71 | local = nfc_llcp_find_local(dev); | ||
72 | if (local == NULL) { | ||
73 | ret = -ENODEV; | ||
74 | goto put_dev; | ||
75 | } | ||
76 | |||
77 | llcp_sock->dev = dev; | ||
78 | llcp_sock->local = local; | ||
79 | llcp_sock->nfc_protocol = llcp_addr.nfc_protocol; | ||
80 | llcp_sock->service_name_len = min_t(unsigned int, | ||
81 | llcp_addr.service_name_len, NFC_LLCP_MAX_SERVICE_NAME); | ||
82 | llcp_sock->service_name = kmemdup(llcp_addr.service_name, | ||
83 | llcp_sock->service_name_len, GFP_KERNEL); | ||
84 | |||
85 | llcp_sock->ssap = nfc_llcp_get_sdp_ssap(local, llcp_sock); | ||
86 | if (llcp_sock->ssap == LLCP_MAX_SAP) | ||
87 | goto put_dev; | ||
88 | |||
89 | local->sockets[llcp_sock->ssap] = llcp_sock; | ||
90 | |||
91 | pr_debug("Socket bound to SAP %d\n", llcp_sock->ssap); | ||
92 | |||
93 | sk->sk_state = LLCP_BOUND; | ||
94 | |||
95 | put_dev: | ||
96 | nfc_put_device(dev); | ||
97 | |||
98 | error: | ||
99 | release_sock(sk); | ||
100 | return ret; | ||
101 | } | ||
102 | |||
103 | static int llcp_sock_listen(struct socket *sock, int backlog) | ||
104 | { | ||
105 | struct sock *sk = sock->sk; | ||
106 | int ret = 0; | ||
107 | |||
108 | pr_debug("sk %p backlog %d\n", sk, backlog); | ||
109 | |||
110 | lock_sock(sk); | ||
111 | |||
112 | if ((sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM) | ||
113 | || sk->sk_state != LLCP_BOUND) { | ||
114 | ret = -EBADFD; | ||
115 | goto error; | ||
116 | } | ||
117 | |||
118 | sk->sk_max_ack_backlog = backlog; | ||
119 | sk->sk_ack_backlog = 0; | ||
120 | |||
121 | pr_debug("Socket listening\n"); | ||
122 | sk->sk_state = LLCP_LISTEN; | ||
123 | |||
124 | error: | ||
125 | release_sock(sk); | ||
126 | |||
127 | return ret; | ||
128 | } | ||
129 | |||
130 | void nfc_llcp_accept_unlink(struct sock *sk) | ||
131 | { | ||
132 | struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); | ||
133 | |||
134 | pr_debug("state %d\n", sk->sk_state); | ||
135 | |||
136 | list_del_init(&llcp_sock->accept_queue); | ||
137 | sk_acceptq_removed(llcp_sock->parent); | ||
138 | llcp_sock->parent = NULL; | ||
139 | |||
140 | sock_put(sk); | ||
141 | } | ||
142 | |||
143 | void nfc_llcp_accept_enqueue(struct sock *parent, struct sock *sk) | ||
144 | { | ||
145 | struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); | ||
146 | struct nfc_llcp_sock *llcp_sock_parent = nfc_llcp_sock(parent); | ||
147 | |||
148 | /* Lock will be free from unlink */ | ||
149 | sock_hold(sk); | ||
150 | |||
151 | list_add_tail(&llcp_sock->accept_queue, | ||
152 | &llcp_sock_parent->accept_queue); | ||
153 | llcp_sock->parent = parent; | ||
154 | sk_acceptq_added(parent); | ||
155 | } | ||
156 | |||
157 | struct sock *nfc_llcp_accept_dequeue(struct sock *parent, | ||
158 | struct socket *newsock) | ||
159 | { | ||
160 | struct nfc_llcp_sock *lsk, *n, *llcp_parent; | ||
161 | struct sock *sk; | ||
162 | |||
163 | llcp_parent = nfc_llcp_sock(parent); | ||
164 | |||
165 | list_for_each_entry_safe(lsk, n, &llcp_parent->accept_queue, | ||
166 | accept_queue) { | ||
167 | sk = &lsk->sk; | ||
168 | lock_sock(sk); | ||
169 | |||
170 | if (sk->sk_state == LLCP_CLOSED) { | ||
171 | release_sock(sk); | ||
172 | nfc_llcp_accept_unlink(sk); | ||
173 | continue; | ||
174 | } | ||
175 | |||
176 | if (sk->sk_state == LLCP_CONNECTED || !newsock) { | ||
177 | nfc_llcp_accept_unlink(sk); | ||
178 | if (newsock) | ||
179 | sock_graft(sk, newsock); | ||
180 | |||
181 | release_sock(sk); | ||
182 | |||
183 | pr_debug("Returning sk state %d\n", sk->sk_state); | ||
184 | |||
185 | return sk; | ||
186 | } | ||
187 | |||
188 | release_sock(sk); | ||
189 | } | ||
190 | |||
191 | return NULL; | ||
192 | } | ||
193 | |||
194 | static int llcp_sock_accept(struct socket *sock, struct socket *newsock, | ||
195 | int flags) | ||
196 | { | ||
197 | DECLARE_WAITQUEUE(wait, current); | ||
198 | struct sock *sk = sock->sk, *new_sk; | ||
199 | long timeo; | ||
200 | int ret = 0; | ||
201 | |||
202 | pr_debug("parent %p\n", sk); | ||
203 | |||
204 | lock_sock_nested(sk, SINGLE_DEPTH_NESTING); | ||
205 | |||
206 | if (sk->sk_state != LLCP_LISTEN) { | ||
207 | ret = -EBADFD; | ||
208 | goto error; | ||
209 | } | ||
210 | |||
211 | timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); | ||
212 | |||
213 | /* Wait for an incoming connection. */ | ||
214 | add_wait_queue_exclusive(sk_sleep(sk), &wait); | ||
215 | while (!(new_sk = nfc_llcp_accept_dequeue(sk, newsock))) { | ||
216 | set_current_state(TASK_INTERRUPTIBLE); | ||
217 | |||
218 | if (!timeo) { | ||
219 | ret = -EAGAIN; | ||
220 | break; | ||
221 | } | ||
222 | |||
223 | if (signal_pending(current)) { | ||
224 | ret = sock_intr_errno(timeo); | ||
225 | break; | ||
226 | } | ||
227 | |||
228 | release_sock(sk); | ||
229 | timeo = schedule_timeout(timeo); | ||
230 | lock_sock_nested(sk, SINGLE_DEPTH_NESTING); | ||
231 | } | ||
232 | __set_current_state(TASK_RUNNING); | ||
233 | remove_wait_queue(sk_sleep(sk), &wait); | ||
234 | |||
235 | if (ret) | ||
236 | goto error; | ||
237 | |||
238 | newsock->state = SS_CONNECTED; | ||
239 | |||
240 | pr_debug("new socket %p\n", new_sk); | ||
241 | |||
242 | error: | ||
243 | release_sock(sk); | ||
244 | |||
245 | return ret; | ||
246 | } | ||
247 | |||
248 | static int llcp_sock_getname(struct socket *sock, struct sockaddr *addr, | ||
249 | int *len, int peer) | ||
250 | { | ||
251 | struct sockaddr_nfc_llcp *llcp_addr = (struct sockaddr_nfc_llcp *) addr; | ||
252 | struct sock *sk = sock->sk; | ||
253 | struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); | ||
254 | |||
255 | pr_debug("%p\n", sk); | ||
256 | |||
257 | addr->sa_family = AF_NFC; | ||
258 | *len = sizeof(struct sockaddr_nfc_llcp); | ||
259 | |||
260 | llcp_addr->dev_idx = llcp_sock->dev->idx; | ||
261 | llcp_addr->dsap = llcp_sock->dsap; | ||
262 | llcp_addr->ssap = llcp_sock->ssap; | ||
263 | llcp_addr->service_name_len = llcp_sock->service_name_len; | ||
264 | memcpy(llcp_addr->service_name, llcp_sock->service_name, | ||
265 | llcp_addr->service_name_len); | ||
266 | |||
267 | return 0; | ||
268 | } | ||
269 | |||
270 | static inline unsigned int llcp_accept_poll(struct sock *parent) | ||
271 | { | ||
272 | struct nfc_llcp_sock *llcp_sock, *n, *parent_sock; | ||
273 | struct sock *sk; | ||
274 | |||
275 | parent_sock = nfc_llcp_sock(parent); | ||
276 | |||
277 | list_for_each_entry_safe(llcp_sock, n, &parent_sock->accept_queue, | ||
278 | accept_queue) { | ||
279 | sk = &llcp_sock->sk; | ||
280 | |||
281 | if (sk->sk_state == LLCP_CONNECTED) | ||
282 | return POLLIN | POLLRDNORM; | ||
283 | } | ||
284 | |||
285 | return 0; | ||
286 | } | ||
287 | |||
288 | static unsigned int llcp_sock_poll(struct file *file, struct socket *sock, | ||
289 | poll_table *wait) | ||
290 | { | ||
291 | struct sock *sk = sock->sk; | ||
292 | unsigned int mask = 0; | ||
293 | |||
294 | pr_debug("%p\n", sk); | ||
295 | |||
296 | sock_poll_wait(file, sk_sleep(sk), wait); | ||
297 | |||
298 | if (sk->sk_state == LLCP_LISTEN) | ||
299 | return llcp_accept_poll(sk); | ||
300 | |||
301 | if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue)) | ||
302 | mask |= POLLERR; | ||
303 | |||
304 | if (!skb_queue_empty(&sk->sk_receive_queue)) | ||
305 | mask |= POLLIN; | ||
306 | |||
307 | if (sk->sk_state == LLCP_CLOSED) | ||
308 | mask |= POLLHUP; | ||
309 | |||
310 | return mask; | ||
311 | } | ||
312 | |||
313 | static int llcp_sock_release(struct socket *sock) | ||
314 | { | ||
315 | struct sock *sk = sock->sk; | ||
316 | struct nfc_llcp_local *local; | ||
317 | struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); | ||
318 | |||
319 | if (!sk) | ||
320 | return 0; | ||
321 | |||
322 | pr_debug("%p\n", sk); | ||
323 | |||
324 | local = llcp_sock->local; | ||
325 | if (local == NULL) | ||
326 | return -ENODEV; | ||
327 | |||
328 | mutex_lock(&local->socket_lock); | ||
329 | |||
330 | if (llcp_sock == local->sockets[llcp_sock->ssap]) { | ||
331 | local->sockets[llcp_sock->ssap] = NULL; | ||
332 | } else { | ||
333 | struct nfc_llcp_sock *parent, *s, *n; | ||
334 | |||
335 | parent = local->sockets[llcp_sock->ssap]; | ||
336 | |||
337 | list_for_each_entry_safe(s, n, &parent->list, list) | ||
338 | if (llcp_sock == s) { | ||
339 | list_del(&s->list); | ||
340 | break; | ||
341 | } | ||
342 | |||
343 | } | ||
344 | |||
345 | mutex_unlock(&local->socket_lock); | ||
346 | |||
347 | lock_sock(sk); | ||
348 | |||
349 | /* Send a DISC */ | ||
350 | if (sk->sk_state == LLCP_CONNECTED) | ||
351 | nfc_llcp_disconnect(llcp_sock); | ||
352 | |||
353 | if (sk->sk_state == LLCP_LISTEN) { | ||
354 | struct nfc_llcp_sock *lsk, *n; | ||
355 | struct sock *accept_sk; | ||
356 | |||
357 | list_for_each_entry_safe(lsk, n, &llcp_sock->accept_queue, | ||
358 | accept_queue) { | ||
359 | accept_sk = &lsk->sk; | ||
360 | lock_sock(accept_sk); | ||
361 | |||
362 | nfc_llcp_disconnect(lsk); | ||
363 | nfc_llcp_accept_unlink(accept_sk); | ||
364 | |||
365 | release_sock(accept_sk); | ||
366 | |||
367 | sock_set_flag(sk, SOCK_DEAD); | ||
368 | sock_orphan(accept_sk); | ||
369 | sock_put(accept_sk); | ||
370 | } | ||
371 | } | ||
372 | |||
373 | /* Freeing the SAP */ | ||
374 | if ((sk->sk_state == LLCP_CONNECTED | ||
375 | && llcp_sock->ssap > LLCP_LOCAL_SAP_OFFSET) || | ||
376 | sk->sk_state == LLCP_BOUND || | ||
377 | sk->sk_state == LLCP_LISTEN) | ||
378 | nfc_llcp_put_ssap(llcp_sock->local, llcp_sock->ssap); | ||
379 | |||
380 | sock_set_flag(sk, SOCK_DEAD); | ||
381 | |||
382 | release_sock(sk); | ||
383 | |||
384 | sock_orphan(sk); | ||
385 | sock_put(sk); | ||
386 | |||
387 | return 0; | ||
388 | } | ||
389 | |||
390 | static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, | ||
391 | int len, int flags) | ||
392 | { | ||
393 | struct sock *sk = sock->sk; | ||
394 | struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); | ||
395 | struct sockaddr_nfc_llcp *addr = (struct sockaddr_nfc_llcp *)_addr; | ||
396 | struct nfc_dev *dev; | ||
397 | struct nfc_llcp_local *local; | ||
398 | int ret = 0; | ||
399 | |||
400 | pr_debug("sock %p sk %p flags 0x%x\n", sock, sk, flags); | ||
401 | |||
402 | if (!addr || len < sizeof(struct sockaddr_nfc) || | ||
403 | addr->sa_family != AF_NFC) { | ||
404 | pr_err("Invalid socket\n"); | ||
405 | return -EINVAL; | ||
406 | } | ||
407 | |||
408 | if (addr->service_name_len == 0 && addr->dsap == 0) { | ||
409 | pr_err("Missing service name or dsap\n"); | ||
410 | return -EINVAL; | ||
411 | } | ||
412 | |||
413 | pr_debug("addr dev_idx=%u target_idx=%u protocol=%u\n", addr->dev_idx, | ||
414 | addr->target_idx, addr->nfc_protocol); | ||
415 | |||
416 | lock_sock(sk); | ||
417 | |||
418 | if (sk->sk_state == LLCP_CONNECTED) { | ||
419 | ret = -EISCONN; | ||
420 | goto error; | ||
421 | } | ||
422 | |||
423 | dev = nfc_get_device(addr->dev_idx); | ||
424 | if (dev == NULL) { | ||
425 | ret = -ENODEV; | ||
426 | goto error; | ||
427 | } | ||
428 | |||
429 | local = nfc_llcp_find_local(dev); | ||
430 | if (local == NULL) { | ||
431 | ret = -ENODEV; | ||
432 | goto put_dev; | ||
433 | } | ||
434 | |||
435 | device_lock(&dev->dev); | ||
436 | if (dev->dep_link_up == false) { | ||
437 | ret = -ENOLINK; | ||
438 | device_unlock(&dev->dev); | ||
439 | goto put_dev; | ||
440 | } | ||
441 | device_unlock(&dev->dev); | ||
442 | |||
443 | if (local->rf_mode == NFC_RF_INITIATOR && | ||
444 | addr->target_idx != local->target_idx) { | ||
445 | ret = -ENOLINK; | ||
446 | goto put_dev; | ||
447 | } | ||
448 | |||
449 | llcp_sock->dev = dev; | ||
450 | llcp_sock->local = local; | ||
451 | llcp_sock->ssap = nfc_llcp_get_local_ssap(local); | ||
452 | if (llcp_sock->ssap == LLCP_SAP_MAX) { | ||
453 | ret = -ENOMEM; | ||
454 | goto put_dev; | ||
455 | } | ||
456 | if (addr->service_name_len == 0) | ||
457 | llcp_sock->dsap = addr->dsap; | ||
458 | else | ||
459 | llcp_sock->dsap = LLCP_SAP_SDP; | ||
460 | llcp_sock->nfc_protocol = addr->nfc_protocol; | ||
461 | llcp_sock->service_name_len = min_t(unsigned int, | ||
462 | addr->service_name_len, NFC_LLCP_MAX_SERVICE_NAME); | ||
463 | llcp_sock->service_name = kmemdup(addr->service_name, | ||
464 | llcp_sock->service_name_len, GFP_KERNEL); | ||
465 | |||
466 | local->sockets[llcp_sock->ssap] = llcp_sock; | ||
467 | |||
468 | ret = nfc_llcp_send_connect(llcp_sock); | ||
469 | if (ret) | ||
470 | goto put_dev; | ||
471 | |||
472 | sk->sk_state = LLCP_CONNECTED; | ||
473 | |||
474 | release_sock(sk); | ||
475 | return 0; | ||
476 | |||
477 | put_dev: | ||
478 | nfc_put_device(dev); | ||
479 | |||
480 | error: | ||
481 | release_sock(sk); | ||
482 | return ret; | ||
483 | } | ||
484 | |||
485 | static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock, | ||
486 | struct msghdr *msg, size_t len, int flags) | ||
487 | { | ||
488 | int noblock = flags & MSG_DONTWAIT; | ||
489 | struct sock *sk = sock->sk; | ||
490 | unsigned int copied, rlen; | ||
491 | struct sk_buff *skb, *cskb; | ||
492 | int err = 0; | ||
493 | |||
494 | pr_debug("%p %zu\n", sk, len); | ||
495 | |||
496 | lock_sock(sk); | ||
497 | |||
498 | if (sk->sk_state == LLCP_CLOSED && | ||
499 | skb_queue_empty(&sk->sk_receive_queue)) { | ||
500 | release_sock(sk); | ||
501 | return 0; | ||
502 | } | ||
503 | |||
504 | release_sock(sk); | ||
505 | |||
506 | if (flags & (MSG_OOB)) | ||
507 | return -EOPNOTSUPP; | ||
508 | |||
509 | skb = skb_recv_datagram(sk, flags, noblock, &err); | ||
510 | if (!skb) { | ||
511 | pr_err("Recv datagram failed state %d %d %d", | ||
512 | sk->sk_state, err, sock_error(sk)); | ||
513 | |||
514 | if (sk->sk_shutdown & RCV_SHUTDOWN) | ||
515 | return 0; | ||
516 | |||
517 | return err; | ||
518 | } | ||
519 | |||
520 | rlen = skb->len; /* real length of skb */ | ||
521 | copied = min_t(unsigned int, rlen, len); | ||
522 | |||
523 | cskb = skb; | ||
524 | if (memcpy_toiovec(msg->msg_iov, cskb->data, copied)) { | ||
525 | if (!(flags & MSG_PEEK)) | ||
526 | skb_queue_head(&sk->sk_receive_queue, skb); | ||
527 | return -EFAULT; | ||
528 | } | ||
529 | |||
530 | /* Mark read part of skb as used */ | ||
531 | if (!(flags & MSG_PEEK)) { | ||
532 | |||
533 | /* SOCK_STREAM: re-queue skb if it contains unreceived data */ | ||
534 | if (sk->sk_type == SOCK_STREAM) { | ||
535 | skb_pull(skb, copied); | ||
536 | if (skb->len) { | ||
537 | skb_queue_head(&sk->sk_receive_queue, skb); | ||
538 | goto done; | ||
539 | } | ||
540 | } | ||
541 | |||
542 | kfree_skb(skb); | ||
543 | } | ||
544 | |||
545 | /* XXX Queue backlogged skbs */ | ||
546 | |||
547 | done: | ||
548 | /* SOCK_SEQPACKET: return real length if MSG_TRUNC is set */ | ||
549 | if (sk->sk_type == SOCK_SEQPACKET && (flags & MSG_TRUNC)) | ||
550 | copied = rlen; | ||
551 | |||
552 | return copied; | ||
553 | } | ||
554 | |||
555 | static const struct proto_ops llcp_sock_ops = { | ||
556 | .family = PF_NFC, | ||
557 | .owner = THIS_MODULE, | ||
558 | .bind = llcp_sock_bind, | ||
559 | .connect = llcp_sock_connect, | ||
560 | .release = llcp_sock_release, | ||
561 | .socketpair = sock_no_socketpair, | ||
562 | .accept = llcp_sock_accept, | ||
563 | .getname = llcp_sock_getname, | ||
564 | .poll = llcp_sock_poll, | ||
565 | .ioctl = sock_no_ioctl, | ||
566 | .listen = llcp_sock_listen, | ||
567 | .shutdown = sock_no_shutdown, | ||
568 | .setsockopt = sock_no_setsockopt, | ||
569 | .getsockopt = sock_no_getsockopt, | ||
570 | .sendmsg = sock_no_sendmsg, | ||
571 | .recvmsg = llcp_sock_recvmsg, | ||
572 | .mmap = sock_no_mmap, | ||
573 | }; | ||
574 | |||
575 | static void llcp_sock_destruct(struct sock *sk) | ||
576 | { | ||
577 | struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); | ||
578 | |||
579 | pr_debug("%p\n", sk); | ||
580 | |||
581 | if (sk->sk_state == LLCP_CONNECTED) | ||
582 | nfc_put_device(llcp_sock->dev); | ||
583 | |||
584 | skb_queue_purge(&sk->sk_receive_queue); | ||
585 | |||
586 | nfc_llcp_sock_free(llcp_sock); | ||
587 | |||
588 | if (!sock_flag(sk, SOCK_DEAD)) { | ||
589 | pr_err("Freeing alive NFC LLCP socket %p\n", sk); | ||
590 | return; | ||
591 | } | ||
592 | } | ||
593 | |||
594 | struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp) | ||
595 | { | ||
596 | struct sock *sk; | ||
597 | struct nfc_llcp_sock *llcp_sock; | ||
598 | |||
599 | sk = sk_alloc(&init_net, PF_NFC, gfp, &llcp_sock_proto); | ||
600 | if (!sk) | ||
601 | return NULL; | ||
602 | |||
603 | llcp_sock = nfc_llcp_sock(sk); | ||
604 | |||
605 | sock_init_data(sock, sk); | ||
606 | sk->sk_state = LLCP_CLOSED; | ||
607 | sk->sk_protocol = NFC_SOCKPROTO_LLCP; | ||
608 | sk->sk_type = type; | ||
609 | sk->sk_destruct = llcp_sock_destruct; | ||
610 | |||
611 | llcp_sock->ssap = 0; | ||
612 | llcp_sock->dsap = LLCP_SAP_SDP; | ||
613 | llcp_sock->send_n = llcp_sock->send_ack_n = 0; | ||
614 | llcp_sock->recv_n = llcp_sock->recv_ack_n = 0; | ||
615 | llcp_sock->remote_ready = 1; | ||
616 | skb_queue_head_init(&llcp_sock->tx_queue); | ||
617 | skb_queue_head_init(&llcp_sock->tx_pending_queue); | ||
618 | skb_queue_head_init(&llcp_sock->tx_backlog_queue); | ||
619 | INIT_LIST_HEAD(&llcp_sock->list); | ||
620 | INIT_LIST_HEAD(&llcp_sock->accept_queue); | ||
621 | |||
622 | if (sock != NULL) | ||
623 | sock->state = SS_UNCONNECTED; | ||
624 | |||
625 | return sk; | ||
626 | } | ||
627 | |||
628 | void nfc_llcp_sock_free(struct nfc_llcp_sock *sock) | ||
629 | { | ||
630 | kfree(sock->service_name); | ||
631 | |||
632 | skb_queue_purge(&sock->tx_queue); | ||
633 | skb_queue_purge(&sock->tx_pending_queue); | ||
634 | skb_queue_purge(&sock->tx_backlog_queue); | ||
635 | |||
636 | list_del_init(&sock->accept_queue); | ||
637 | |||
638 | sock->parent = NULL; | ||
639 | } | ||
640 | |||
641 | static int llcp_sock_create(struct net *net, struct socket *sock, | ||
642 | const struct nfc_protocol *nfc_proto) | ||
643 | { | ||
644 | struct sock *sk; | ||
645 | |||
646 | pr_debug("%p\n", sock); | ||
647 | |||
648 | if (sock->type != SOCK_STREAM && sock->type != SOCK_DGRAM) | ||
649 | return -ESOCKTNOSUPPORT; | ||
650 | |||
651 | sock->ops = &llcp_sock_ops; | ||
652 | |||
653 | sk = nfc_llcp_sock_alloc(sock, sock->type, GFP_ATOMIC); | ||
654 | if (sk == NULL) | ||
655 | return -ENOMEM; | ||
656 | |||
657 | return 0; | ||
658 | } | ||
659 | |||
660 | static const struct nfc_protocol llcp_nfc_proto = { | ||
661 | .id = NFC_SOCKPROTO_LLCP, | ||
662 | .proto = &llcp_sock_proto, | ||
663 | .owner = THIS_MODULE, | ||
664 | .create = llcp_sock_create | ||
665 | }; | ||
666 | |||
667 | int __init nfc_llcp_sock_init(void) | ||
668 | { | ||
669 | return nfc_proto_register(&llcp_nfc_proto); | ||
670 | } | ||
671 | |||
672 | void nfc_llcp_sock_exit(void) | ||
673 | { | ||
674 | nfc_proto_unregister(&llcp_nfc_proto); | ||
675 | } | ||
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c index 37de28e97330..2deb4aebf568 100644 --- a/net/nfc/nci/core.c +++ b/net/nfc/nci/core.c | |||
@@ -25,7 +25,7 @@ | |||
25 | * | 25 | * |
26 | */ | 26 | */ |
27 | 27 | ||
28 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 28 | #define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__ |
29 | 29 | ||
30 | #include <linux/types.h> | 30 | #include <linux/types.h> |
31 | #include <linux/workqueue.h> | 31 | #include <linux/workqueue.h> |
@@ -71,7 +71,7 @@ static int __nci_request(struct nci_dev *ndev, | |||
71 | __u32 timeout) | 71 | __u32 timeout) |
72 | { | 72 | { |
73 | int rc = 0; | 73 | int rc = 0; |
74 | unsigned long completion_rc; | 74 | long completion_rc; |
75 | 75 | ||
76 | ndev->req_status = NCI_REQ_PEND; | 76 | ndev->req_status = NCI_REQ_PEND; |
77 | 77 | ||
diff --git a/net/nfc/nci/data.c b/net/nfc/nci/data.c index 1e040feb2f84..e5756b30e602 100644 --- a/net/nfc/nci/data.c +++ b/net/nfc/nci/data.c | |||
@@ -21,7 +21,7 @@ | |||
21 | * | 21 | * |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 24 | #define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__ |
25 | 25 | ||
26 | #include <linux/types.h> | 26 | #include <linux/types.h> |
27 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c index c36bd4a09abb..003846b2c326 100644 --- a/net/nfc/nci/ntf.c +++ b/net/nfc/nci/ntf.c | |||
@@ -25,7 +25,7 @@ | |||
25 | * | 25 | * |
26 | */ | 26 | */ |
27 | 27 | ||
28 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 28 | #define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__ |
29 | 29 | ||
30 | #include <linux/types.h> | 30 | #include <linux/types.h> |
31 | #include <linux/interrupt.h> | 31 | #include <linux/interrupt.h> |
diff --git a/net/nfc/nci/rsp.c b/net/nfc/nci/rsp.c index ca611c52aaaa..3f444c8a66e9 100644 --- a/net/nfc/nci/rsp.c +++ b/net/nfc/nci/rsp.c | |||
@@ -25,7 +25,7 @@ | |||
25 | * | 25 | * |
26 | */ | 26 | */ |
27 | 27 | ||
28 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 28 | #define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__ |
29 | 29 | ||
30 | #include <linux/types.h> | 30 | #include <linux/types.h> |
31 | #include <linux/interrupt.h> | 31 | #include <linux/interrupt.h> |
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index c10e9b8c5ad9..43a1c47756a7 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c | |||
@@ -21,7 +21,7 @@ | |||
21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 24 | #define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__ |
25 | 25 | ||
26 | #include <net/genetlink.h> | 26 | #include <net/genetlink.h> |
27 | #include <linux/nfc.h> | 27 | #include <linux/nfc.h> |
@@ -46,6 +46,8 @@ static const struct nla_policy nfc_genl_policy[NFC_ATTR_MAX + 1] = { | |||
46 | [NFC_ATTR_DEVICE_NAME] = { .type = NLA_STRING, | 46 | [NFC_ATTR_DEVICE_NAME] = { .type = NLA_STRING, |
47 | .len = NFC_DEVICE_NAME_MAXSIZE }, | 47 | .len = NFC_DEVICE_NAME_MAXSIZE }, |
48 | [NFC_ATTR_PROTOCOLS] = { .type = NLA_U32 }, | 48 | [NFC_ATTR_PROTOCOLS] = { .type = NLA_U32 }, |
49 | [NFC_ATTR_COMM_MODE] = { .type = NLA_U8 }, | ||
50 | [NFC_ATTR_RF_MODE] = { .type = NLA_U8 }, | ||
49 | }; | 51 | }; |
50 | 52 | ||
51 | static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target, | 53 | static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target, |
@@ -311,6 +313,75 @@ static int nfc_genl_dump_devices_done(struct netlink_callback *cb) | |||
311 | return 0; | 313 | return 0; |
312 | } | 314 | } |
313 | 315 | ||
316 | int nfc_genl_dep_link_up_event(struct nfc_dev *dev, u32 target_idx, | ||
317 | u8 comm_mode, u8 rf_mode) | ||
318 | { | ||
319 | struct sk_buff *msg; | ||
320 | void *hdr; | ||
321 | |||
322 | pr_debug("DEP link is up\n"); | ||
323 | |||
324 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); | ||
325 | if (!msg) | ||
326 | return -ENOMEM; | ||
327 | |||
328 | hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, | ||
329 | NFC_CMD_DEP_LINK_UP); | ||
330 | if (!hdr) | ||
331 | goto free_msg; | ||
332 | |||
333 | NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx); | ||
334 | if (rf_mode == NFC_RF_INITIATOR) | ||
335 | NLA_PUT_U32(msg, NFC_ATTR_TARGET_INDEX, target_idx); | ||
336 | NLA_PUT_U8(msg, NFC_ATTR_COMM_MODE, comm_mode); | ||
337 | NLA_PUT_U8(msg, NFC_ATTR_RF_MODE, rf_mode); | ||
338 | |||
339 | genlmsg_end(msg, hdr); | ||
340 | |||
341 | dev->dep_link_up = true; | ||
342 | |||
343 | genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_ATOMIC); | ||
344 | |||
345 | return 0; | ||
346 | |||
347 | nla_put_failure: | ||
348 | genlmsg_cancel(msg, hdr); | ||
349 | free_msg: | ||
350 | nlmsg_free(msg); | ||
351 | return -EMSGSIZE; | ||
352 | } | ||
353 | |||
354 | int nfc_genl_dep_link_down_event(struct nfc_dev *dev) | ||
355 | { | ||
356 | struct sk_buff *msg; | ||
357 | void *hdr; | ||
358 | |||
359 | pr_debug("DEP link is down\n"); | ||
360 | |||
361 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); | ||
362 | if (!msg) | ||
363 | return -ENOMEM; | ||
364 | |||
365 | hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, | ||
366 | NFC_CMD_DEP_LINK_DOWN); | ||
367 | if (!hdr) | ||
368 | goto free_msg; | ||
369 | |||
370 | NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx); | ||
371 | |||
372 | genlmsg_end(msg, hdr); | ||
373 | |||
374 | genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_ATOMIC); | ||
375 | |||
376 | return 0; | ||
377 | |||
378 | nla_put_failure: | ||
379 | genlmsg_cancel(msg, hdr); | ||
380 | free_msg: | ||
381 | nlmsg_free(msg); | ||
382 | return -EMSGSIZE; | ||
383 | } | ||
384 | |||
314 | static int nfc_genl_get_device(struct sk_buff *skb, struct genl_info *info) | 385 | static int nfc_genl_get_device(struct sk_buff *skb, struct genl_info *info) |
315 | { | 386 | { |
316 | struct sk_buff *msg; | 387 | struct sk_buff *msg; |
@@ -398,6 +469,8 @@ static int nfc_genl_start_poll(struct sk_buff *skb, struct genl_info *info) | |||
398 | u32 idx; | 469 | u32 idx; |
399 | u32 protocols; | 470 | u32 protocols; |
400 | 471 | ||
472 | pr_debug("Poll start\n"); | ||
473 | |||
401 | if (!info->attrs[NFC_ATTR_DEVICE_INDEX] || | 474 | if (!info->attrs[NFC_ATTR_DEVICE_INDEX] || |
402 | !info->attrs[NFC_ATTR_PROTOCOLS]) | 475 | !info->attrs[NFC_ATTR_PROTOCOLS]) |
403 | return -EINVAL; | 476 | return -EINVAL; |
@@ -452,6 +525,67 @@ out: | |||
452 | return rc; | 525 | return rc; |
453 | } | 526 | } |
454 | 527 | ||
528 | static int nfc_genl_dep_link_up(struct sk_buff *skb, struct genl_info *info) | ||
529 | { | ||
530 | struct nfc_dev *dev; | ||
531 | int rc, tgt_idx; | ||
532 | u32 idx; | ||
533 | u8 comm, rf; | ||
534 | |||
535 | pr_debug("DEP link up\n"); | ||
536 | |||
537 | if (!info->attrs[NFC_ATTR_DEVICE_INDEX] || | ||
538 | !info->attrs[NFC_ATTR_COMM_MODE] || | ||
539 | !info->attrs[NFC_ATTR_RF_MODE]) | ||
540 | return -EINVAL; | ||
541 | |||
542 | idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); | ||
543 | if (!info->attrs[NFC_ATTR_TARGET_INDEX]) | ||
544 | tgt_idx = NFC_TARGET_IDX_ANY; | ||
545 | else | ||
546 | tgt_idx = nla_get_u32(info->attrs[NFC_ATTR_TARGET_INDEX]); | ||
547 | |||
548 | comm = nla_get_u8(info->attrs[NFC_ATTR_COMM_MODE]); | ||
549 | rf = nla_get_u8(info->attrs[NFC_ATTR_RF_MODE]); | ||
550 | |||
551 | if (comm != NFC_COMM_ACTIVE && comm != NFC_COMM_PASSIVE) | ||
552 | return -EINVAL; | ||
553 | |||
554 | if (rf != NFC_RF_INITIATOR && comm != NFC_RF_TARGET) | ||
555 | return -EINVAL; | ||
556 | |||
557 | dev = nfc_get_device(idx); | ||
558 | if (!dev) | ||
559 | return -ENODEV; | ||
560 | |||
561 | rc = nfc_dep_link_up(dev, tgt_idx, comm, rf); | ||
562 | |||
563 | nfc_put_device(dev); | ||
564 | |||
565 | return rc; | ||
566 | } | ||
567 | |||
568 | static int nfc_genl_dep_link_down(struct sk_buff *skb, struct genl_info *info) | ||
569 | { | ||
570 | struct nfc_dev *dev; | ||
571 | int rc; | ||
572 | u32 idx; | ||
573 | |||
574 | if (!info->attrs[NFC_ATTR_DEVICE_INDEX]) | ||
575 | return -EINVAL; | ||
576 | |||
577 | idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); | ||
578 | |||
579 | dev = nfc_get_device(idx); | ||
580 | if (!dev) | ||
581 | return -ENODEV; | ||
582 | |||
583 | rc = nfc_dep_link_down(dev); | ||
584 | |||
585 | nfc_put_device(dev); | ||
586 | return rc; | ||
587 | } | ||
588 | |||
455 | static struct genl_ops nfc_genl_ops[] = { | 589 | static struct genl_ops nfc_genl_ops[] = { |
456 | { | 590 | { |
457 | .cmd = NFC_CMD_GET_DEVICE, | 591 | .cmd = NFC_CMD_GET_DEVICE, |
@@ -481,6 +615,16 @@ static struct genl_ops nfc_genl_ops[] = { | |||
481 | .policy = nfc_genl_policy, | 615 | .policy = nfc_genl_policy, |
482 | }, | 616 | }, |
483 | { | 617 | { |
618 | .cmd = NFC_CMD_DEP_LINK_UP, | ||
619 | .doit = nfc_genl_dep_link_up, | ||
620 | .policy = nfc_genl_policy, | ||
621 | }, | ||
622 | { | ||
623 | .cmd = NFC_CMD_DEP_LINK_DOWN, | ||
624 | .doit = nfc_genl_dep_link_down, | ||
625 | .policy = nfc_genl_policy, | ||
626 | }, | ||
627 | { | ||
484 | .cmd = NFC_CMD_GET_TARGET, | 628 | .cmd = NFC_CMD_GET_TARGET, |
485 | .dumpit = nfc_genl_dump_targets, | 629 | .dumpit = nfc_genl_dump_targets, |
486 | .done = nfc_genl_dump_targets_done, | 630 | .done = nfc_genl_dump_targets_done, |
@@ -504,12 +648,10 @@ static int nfc_genl_rcv_nl_event(struct notifier_block *this, | |||
504 | dev = nfc_device_iter_next(&iter); | 648 | dev = nfc_device_iter_next(&iter); |
505 | 649 | ||
506 | while (dev) { | 650 | while (dev) { |
507 | mutex_lock(&dev->genl_data.genl_data_mutex); | ||
508 | if (dev->genl_data.poll_req_pid == n->pid) { | 651 | if (dev->genl_data.poll_req_pid == n->pid) { |
509 | nfc_stop_poll(dev); | 652 | nfc_stop_poll(dev); |
510 | dev->genl_data.poll_req_pid = 0; | 653 | dev->genl_data.poll_req_pid = 0; |
511 | } | 654 | } |
512 | mutex_unlock(&dev->genl_data.genl_data_mutex); | ||
513 | dev = nfc_device_iter_next(&iter); | 655 | dev = nfc_device_iter_next(&iter); |
514 | } | 656 | } |
515 | 657 | ||
diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h index 67d605015304..2c2c4015c68b 100644 --- a/net/nfc/nfc.h +++ b/net/nfc/nfc.h | |||
@@ -46,6 +46,60 @@ struct nfc_rawsock { | |||
46 | #define to_rawsock_sk(_tx_work) \ | 46 | #define to_rawsock_sk(_tx_work) \ |
47 | ((struct sock *) container_of(_tx_work, struct nfc_rawsock, tx_work)) | 47 | ((struct sock *) container_of(_tx_work, struct nfc_rawsock, tx_work)) |
48 | 48 | ||
49 | #ifdef CONFIG_NFC_LLCP | ||
50 | |||
51 | void nfc_llcp_mac_is_down(struct nfc_dev *dev); | ||
52 | void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx, | ||
53 | u8 comm_mode, u8 rf_mode); | ||
54 | int nfc_llcp_register_device(struct nfc_dev *dev); | ||
55 | void nfc_llcp_unregister_device(struct nfc_dev *dev); | ||
56 | int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len); | ||
57 | u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, u8 *general_bytes_len); | ||
58 | int __init nfc_llcp_init(void); | ||
59 | void nfc_llcp_exit(void); | ||
60 | |||
61 | #else | ||
62 | |||
63 | void nfc_llcp_mac_is_down(struct nfc_dev *dev) | ||
64 | { | ||
65 | } | ||
66 | |||
67 | void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx, | ||
68 | u8 comm_mode, u8 rf_mode) | ||
69 | { | ||
70 | } | ||
71 | |||
72 | static inline int nfc_llcp_register_device(struct nfc_dev *dev) | ||
73 | { | ||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | static inline void nfc_llcp_unregister_device(struct nfc_dev *dev) | ||
78 | { | ||
79 | } | ||
80 | |||
81 | static inline int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len) | ||
82 | { | ||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | static inline u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, u8 *gb_len) | ||
87 | { | ||
88 | *gb_len = 0; | ||
89 | return NULL; | ||
90 | } | ||
91 | |||
92 | static inline int nfc_llcp_init(void) | ||
93 | { | ||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | static inline void nfc_llcp_exit(void) | ||
98 | { | ||
99 | } | ||
100 | |||
101 | #endif | ||
102 | |||
49 | int __init rawsock_init(void); | 103 | int __init rawsock_init(void); |
50 | void rawsock_exit(void); | 104 | void rawsock_exit(void); |
51 | 105 | ||
@@ -68,6 +122,10 @@ int nfc_genl_targets_found(struct nfc_dev *dev); | |||
68 | int nfc_genl_device_added(struct nfc_dev *dev); | 122 | int nfc_genl_device_added(struct nfc_dev *dev); |
69 | int nfc_genl_device_removed(struct nfc_dev *dev); | 123 | int nfc_genl_device_removed(struct nfc_dev *dev); |
70 | 124 | ||
125 | int nfc_genl_dep_link_up_event(struct nfc_dev *dev, u32 target_idx, | ||
126 | u8 comm_mode, u8 rf_mode); | ||
127 | int nfc_genl_dep_link_down_event(struct nfc_dev *dev); | ||
128 | |||
71 | struct nfc_dev *nfc_get_device(unsigned idx); | 129 | struct nfc_dev *nfc_get_device(unsigned idx); |
72 | 130 | ||
73 | static inline void nfc_put_device(struct nfc_dev *dev) | 131 | static inline void nfc_put_device(struct nfc_dev *dev) |
@@ -102,6 +160,11 @@ int nfc_start_poll(struct nfc_dev *dev, u32 protocols); | |||
102 | 160 | ||
103 | int nfc_stop_poll(struct nfc_dev *dev); | 161 | int nfc_stop_poll(struct nfc_dev *dev); |
104 | 162 | ||
163 | int nfc_dep_link_up(struct nfc_dev *dev, int target_idx, | ||
164 | u8 comm_mode, u8 rf_mode); | ||
165 | |||
166 | int nfc_dep_link_down(struct nfc_dev *dev); | ||
167 | |||
105 | int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol); | 168 | int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol); |
106 | 169 | ||
107 | int nfc_deactivate_target(struct nfc_dev *dev, u32 target_idx); | 170 | int nfc_deactivate_target(struct nfc_dev *dev, u32 target_idx); |
diff --git a/net/nfc/rawsock.c b/net/nfc/rawsock.c index 68ecf3fa94e0..2e2f8c6a61fe 100644 --- a/net/nfc/rawsock.c +++ b/net/nfc/rawsock.c | |||
@@ -21,7 +21,7 @@ | |||
21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 24 | #define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__ |
25 | 25 | ||
26 | #include <net/tcp_states.h> | 26 | #include <net/tcp_states.h> |
27 | #include <linux/nfc.h> | 27 | #include <linux/nfc.h> |
@@ -208,13 +208,10 @@ static int rawsock_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
208 | if (sock->state != SS_CONNECTED) | 208 | if (sock->state != SS_CONNECTED) |
209 | return -ENOTCONN; | 209 | return -ENOTCONN; |
210 | 210 | ||
211 | skb = sock_alloc_send_skb(sk, len + dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE, | 211 | skb = nfc_alloc_send_skb(dev, sk, msg->msg_flags, len, &rc); |
212 | msg->msg_flags & MSG_DONTWAIT, &rc); | 212 | if (skb == NULL) |
213 | if (!skb) | ||
214 | return rc; | 213 | return rc; |
215 | 214 | ||
216 | skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE); | ||
217 | |||
218 | rc = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len); | 215 | rc = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len); |
219 | if (rc < 0) { | 216 | if (rc < 0) { |
220 | kfree_skb(skb); | 217 | kfree_skb(skb); |
@@ -313,7 +310,7 @@ static int rawsock_create(struct net *net, struct socket *sock, | |||
313 | 310 | ||
314 | sock->ops = &rawsock_ops; | 311 | sock->ops = &rawsock_ops; |
315 | 312 | ||
316 | sk = sk_alloc(net, PF_NFC, GFP_KERNEL, nfc_proto->proto); | 313 | sk = sk_alloc(net, PF_NFC, GFP_ATOMIC, nfc_proto->proto); |
317 | if (!sk) | 314 | if (!sk) |
318 | return -ENOMEM; | 315 | return -ENOMEM; |
319 | 316 | ||
diff --git a/net/wireless/core.h b/net/wireless/core.h index fb08c28fc90a..43ad9c81efcf 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -249,12 +249,11 @@ struct cfg80211_event { | |||
249 | u16 status; | 249 | u16 status; |
250 | } cr; | 250 | } cr; |
251 | struct { | 251 | struct { |
252 | struct ieee80211_channel *channel; | ||
253 | u8 bssid[ETH_ALEN]; | ||
254 | const u8 *req_ie; | 252 | const u8 *req_ie; |
255 | const u8 *resp_ie; | 253 | const u8 *resp_ie; |
256 | size_t req_ie_len; | 254 | size_t req_ie_len; |
257 | size_t resp_ie_len; | 255 | size_t resp_ie_len; |
256 | struct cfg80211_bss *bss; | ||
258 | } rm; | 257 | } rm; |
259 | struct { | 258 | struct { |
260 | const u8 *ie; | 259 | const u8 *ie; |
@@ -403,8 +402,7 @@ int cfg80211_disconnect(struct cfg80211_registered_device *rdev, | |||
403 | struct net_device *dev, u16 reason, | 402 | struct net_device *dev, u16 reason, |
404 | bool wextev); | 403 | bool wextev); |
405 | void __cfg80211_roamed(struct wireless_dev *wdev, | 404 | void __cfg80211_roamed(struct wireless_dev *wdev, |
406 | struct ieee80211_channel *channel, | 405 | struct cfg80211_bss *bss, |
407 | const u8 *bssid, | ||
408 | const u8 *req_ie, size_t req_ie_len, | 406 | const u8 *req_ie, size_t req_ie_len, |
409 | const u8 *resp_ie, size_t resp_ie_len); | 407 | const u8 *resp_ie, size_t resp_ie_len); |
410 | int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev, | 408 | int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev, |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index ba439664c2e0..b07c4fc4ae22 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -47,22 +47,21 @@ static struct genl_family nl80211_fam = { | |||
47 | }; | 47 | }; |
48 | 48 | ||
49 | /* internal helper: get rdev and dev */ | 49 | /* internal helper: get rdev and dev */ |
50 | static int get_rdev_dev_by_info_ifindex(struct genl_info *info, | 50 | static int get_rdev_dev_by_ifindex(struct net *netns, struct nlattr **attrs, |
51 | struct cfg80211_registered_device **rdev, | 51 | struct cfg80211_registered_device **rdev, |
52 | struct net_device **dev) | 52 | struct net_device **dev) |
53 | { | 53 | { |
54 | struct nlattr **attrs = info->attrs; | ||
55 | int ifindex; | 54 | int ifindex; |
56 | 55 | ||
57 | if (!attrs[NL80211_ATTR_IFINDEX]) | 56 | if (!attrs[NL80211_ATTR_IFINDEX]) |
58 | return -EINVAL; | 57 | return -EINVAL; |
59 | 58 | ||
60 | ifindex = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]); | 59 | ifindex = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]); |
61 | *dev = dev_get_by_index(genl_info_net(info), ifindex); | 60 | *dev = dev_get_by_index(netns, ifindex); |
62 | if (!*dev) | 61 | if (!*dev) |
63 | return -ENODEV; | 62 | return -ENODEV; |
64 | 63 | ||
65 | *rdev = cfg80211_get_dev_from_ifindex(genl_info_net(info), ifindex); | 64 | *rdev = cfg80211_get_dev_from_ifindex(netns, ifindex); |
66 | if (IS_ERR(*rdev)) { | 65 | if (IS_ERR(*rdev)) { |
67 | dev_put(*dev); | 66 | dev_put(*dev); |
68 | return PTR_ERR(*rdev); | 67 | return PTR_ERR(*rdev); |
@@ -2247,6 +2246,7 @@ static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = { | |||
2247 | [NL80211_STA_FLAG_WME] = { .type = NLA_FLAG }, | 2246 | [NL80211_STA_FLAG_WME] = { .type = NLA_FLAG }, |
2248 | [NL80211_STA_FLAG_MFP] = { .type = NLA_FLAG }, | 2247 | [NL80211_STA_FLAG_MFP] = { .type = NLA_FLAG }, |
2249 | [NL80211_STA_FLAG_AUTHENTICATED] = { .type = NLA_FLAG }, | 2248 | [NL80211_STA_FLAG_AUTHENTICATED] = { .type = NLA_FLAG }, |
2249 | [NL80211_STA_FLAG_TDLS_PEER] = { .type = NLA_FLAG }, | ||
2250 | }; | 2250 | }; |
2251 | 2251 | ||
2252 | static int parse_station_flags(struct genl_info *info, | 2252 | static int parse_station_flags(struct genl_info *info, |
@@ -2579,6 +2579,9 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | |||
2579 | params.ht_capa = | 2579 | params.ht_capa = |
2580 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); | 2580 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); |
2581 | 2581 | ||
2582 | if (!rdev->ops->change_station) | ||
2583 | return -EOPNOTSUPP; | ||
2584 | |||
2582 | if (parse_station_flags(info, ¶ms)) | 2585 | if (parse_station_flags(info, ¶ms)) |
2583 | return -EINVAL; | 2586 | return -EINVAL; |
2584 | 2587 | ||
@@ -2590,73 +2593,84 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | |||
2590 | params.plink_state = | 2593 | params.plink_state = |
2591 | nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]); | 2594 | nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]); |
2592 | 2595 | ||
2593 | params.vlan = get_vlan(info, rdev); | ||
2594 | if (IS_ERR(params.vlan)) | ||
2595 | return PTR_ERR(params.vlan); | ||
2596 | |||
2597 | /* validate settings */ | ||
2598 | err = 0; | ||
2599 | |||
2600 | switch (dev->ieee80211_ptr->iftype) { | 2596 | switch (dev->ieee80211_ptr->iftype) { |
2601 | case NL80211_IFTYPE_AP: | 2597 | case NL80211_IFTYPE_AP: |
2602 | case NL80211_IFTYPE_AP_VLAN: | 2598 | case NL80211_IFTYPE_AP_VLAN: |
2603 | case NL80211_IFTYPE_P2P_GO: | 2599 | case NL80211_IFTYPE_P2P_GO: |
2604 | /* disallow mesh-specific things */ | 2600 | /* disallow mesh-specific things */ |
2605 | if (params.plink_action) | 2601 | if (params.plink_action) |
2606 | err = -EINVAL; | 2602 | return -EINVAL; |
2603 | |||
2604 | /* TDLS can't be set, ... */ | ||
2605 | if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) | ||
2606 | return -EINVAL; | ||
2607 | /* | ||
2608 | * ... but don't bother the driver with it. This works around | ||
2609 | * a hostapd/wpa_supplicant issue -- it always includes the | ||
2610 | * TLDS_PEER flag in the mask even for AP mode. | ||
2611 | */ | ||
2612 | params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER); | ||
2613 | |||
2614 | /* accept only the listed bits */ | ||
2615 | if (params.sta_flags_mask & | ||
2616 | ~(BIT(NL80211_STA_FLAG_AUTHORIZED) | | ||
2617 | BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) | | ||
2618 | BIT(NL80211_STA_FLAG_WME) | | ||
2619 | BIT(NL80211_STA_FLAG_MFP))) | ||
2620 | return -EINVAL; | ||
2621 | |||
2622 | /* must be last in here for error handling */ | ||
2623 | params.vlan = get_vlan(info, rdev); | ||
2624 | if (IS_ERR(params.vlan)) | ||
2625 | return PTR_ERR(params.vlan); | ||
2607 | break; | 2626 | break; |
2608 | case NL80211_IFTYPE_P2P_CLIENT: | 2627 | case NL80211_IFTYPE_P2P_CLIENT: |
2609 | case NL80211_IFTYPE_STATION: | 2628 | case NL80211_IFTYPE_STATION: |
2610 | /* disallow things sta doesn't support */ | 2629 | /* disallow things sta doesn't support */ |
2611 | if (params.plink_action) | 2630 | if (params.plink_action) |
2612 | err = -EINVAL; | 2631 | return -EINVAL; |
2613 | if (params.vlan) | ||
2614 | err = -EINVAL; | ||
2615 | if (params.supported_rates && | ||
2616 | !(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) | ||
2617 | err = -EINVAL; | ||
2618 | if (params.ht_capa) | 2632 | if (params.ht_capa) |
2619 | err = -EINVAL; | 2633 | return -EINVAL; |
2620 | if (params.listen_interval >= 0) | 2634 | if (params.listen_interval >= 0) |
2621 | err = -EINVAL; | 2635 | return -EINVAL; |
2622 | if (params.sta_flags_mask & | 2636 | /* |
2623 | ~(BIT(NL80211_STA_FLAG_AUTHORIZED) | | 2637 | * Don't allow userspace to change the TDLS_PEER flag, |
2624 | BIT(NL80211_STA_FLAG_TDLS_PEER))) | 2638 | * but silently ignore attempts to change it since we |
2625 | err = -EINVAL; | 2639 | * don't have state here to verify that it doesn't try |
2626 | /* can't change the TDLS bit */ | 2640 | * to change the flag. |
2627 | if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) && | 2641 | */ |
2628 | (params.sta_flags_mask & BIT(NL80211_STA_FLAG_TDLS_PEER))) | 2642 | params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER); |
2629 | err = -EINVAL; | 2643 | |
2644 | /* reject any changes other than AUTHORIZED */ | ||
2645 | if (params.sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED)) | ||
2646 | return -EINVAL; | ||
2630 | break; | 2647 | break; |
2631 | case NL80211_IFTYPE_MESH_POINT: | 2648 | case NL80211_IFTYPE_MESH_POINT: |
2632 | /* disallow things mesh doesn't support */ | 2649 | /* disallow things mesh doesn't support */ |
2633 | if (params.vlan) | 2650 | if (params.vlan) |
2634 | err = -EINVAL; | 2651 | return -EINVAL; |
2635 | if (params.ht_capa) | 2652 | if (params.ht_capa) |
2636 | err = -EINVAL; | 2653 | return -EINVAL; |
2637 | if (params.listen_interval >= 0) | 2654 | if (params.listen_interval >= 0) |
2638 | err = -EINVAL; | 2655 | return -EINVAL; |
2656 | /* | ||
2657 | * No special handling for TDLS here -- the userspace | ||
2658 | * mesh code doesn't have this bug. | ||
2659 | */ | ||
2639 | if (params.sta_flags_mask & | 2660 | if (params.sta_flags_mask & |
2640 | ~(BIT(NL80211_STA_FLAG_AUTHENTICATED) | | 2661 | ~(BIT(NL80211_STA_FLAG_AUTHENTICATED) | |
2641 | BIT(NL80211_STA_FLAG_MFP) | | 2662 | BIT(NL80211_STA_FLAG_MFP) | |
2642 | BIT(NL80211_STA_FLAG_AUTHORIZED))) | 2663 | BIT(NL80211_STA_FLAG_AUTHORIZED))) |
2643 | err = -EINVAL; | 2664 | return -EINVAL; |
2644 | break; | 2665 | break; |
2645 | default: | 2666 | default: |
2646 | err = -EINVAL; | 2667 | return -EOPNOTSUPP; |
2647 | } | 2668 | } |
2648 | 2669 | ||
2649 | if (err) | 2670 | /* be aware of params.vlan when changing code here */ |
2650 | goto out; | ||
2651 | |||
2652 | if (!rdev->ops->change_station) { | ||
2653 | err = -EOPNOTSUPP; | ||
2654 | goto out; | ||
2655 | } | ||
2656 | 2671 | ||
2657 | err = rdev->ops->change_station(&rdev->wiphy, dev, mac_addr, ¶ms); | 2672 | err = rdev->ops->change_station(&rdev->wiphy, dev, mac_addr, ¶ms); |
2658 | 2673 | ||
2659 | out: | ||
2660 | if (params.vlan) | 2674 | if (params.vlan) |
2661 | dev_put(params.vlan); | 2675 | dev_put(params.vlan); |
2662 | 2676 | ||
@@ -2711,70 +2725,81 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
2711 | params.plink_action = | 2725 | params.plink_action = |
2712 | nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); | 2726 | nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); |
2713 | 2727 | ||
2728 | if (!rdev->ops->add_station) | ||
2729 | return -EOPNOTSUPP; | ||
2730 | |||
2714 | if (parse_station_flags(info, ¶ms)) | 2731 | if (parse_station_flags(info, ¶ms)) |
2715 | return -EINVAL; | 2732 | return -EINVAL; |
2716 | 2733 | ||
2717 | /* parse WME attributes if sta is WME capable */ | 2734 | switch (dev->ieee80211_ptr->iftype) { |
2718 | if ((rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) && | 2735 | case NL80211_IFTYPE_AP: |
2719 | (params.sta_flags_set & BIT(NL80211_STA_FLAG_WME)) && | 2736 | case NL80211_IFTYPE_AP_VLAN: |
2720 | info->attrs[NL80211_ATTR_STA_WME]) { | 2737 | case NL80211_IFTYPE_P2P_GO: |
2721 | struct nlattr *tb[NL80211_STA_WME_MAX + 1]; | 2738 | /* parse WME attributes if sta is WME capable */ |
2722 | struct nlattr *nla; | 2739 | if ((rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) && |
2740 | (params.sta_flags_set & BIT(NL80211_STA_FLAG_WME)) && | ||
2741 | info->attrs[NL80211_ATTR_STA_WME]) { | ||
2742 | struct nlattr *tb[NL80211_STA_WME_MAX + 1]; | ||
2743 | struct nlattr *nla; | ||
2744 | |||
2745 | nla = info->attrs[NL80211_ATTR_STA_WME]; | ||
2746 | err = nla_parse_nested(tb, NL80211_STA_WME_MAX, nla, | ||
2747 | nl80211_sta_wme_policy); | ||
2748 | if (err) | ||
2749 | return err; | ||
2723 | 2750 | ||
2724 | nla = info->attrs[NL80211_ATTR_STA_WME]; | 2751 | if (tb[NL80211_STA_WME_UAPSD_QUEUES]) |
2725 | err = nla_parse_nested(tb, NL80211_STA_WME_MAX, nla, | 2752 | params.uapsd_queues = |
2726 | nl80211_sta_wme_policy); | 2753 | nla_get_u8(tb[NL80211_STA_WME_UAPSD_QUEUES]); |
2727 | if (err) | 2754 | if (params.uapsd_queues & |
2728 | return err; | 2755 | ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK) |
2756 | return -EINVAL; | ||
2729 | 2757 | ||
2730 | if (tb[NL80211_STA_WME_UAPSD_QUEUES]) | 2758 | if (tb[NL80211_STA_WME_MAX_SP]) |
2731 | params.uapsd_queues = | 2759 | params.max_sp = |
2732 | nla_get_u8(tb[NL80211_STA_WME_UAPSD_QUEUES]); | 2760 | nla_get_u8(tb[NL80211_STA_WME_MAX_SP]); |
2733 | if (params.uapsd_queues & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK) | ||
2734 | return -EINVAL; | ||
2735 | 2761 | ||
2736 | if (tb[NL80211_STA_WME_MAX_SP]) | 2762 | if (params.max_sp & |
2737 | params.max_sp = | 2763 | ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK) |
2738 | nla_get_u8(tb[NL80211_STA_WME_MAX_SP]); | 2764 | return -EINVAL; |
2739 | 2765 | ||
2740 | if (params.max_sp & ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK) | 2766 | params.sta_modify_mask |= STATION_PARAM_APPLY_UAPSD; |
2767 | } | ||
2768 | /* TDLS peers cannot be added */ | ||
2769 | if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) | ||
2741 | return -EINVAL; | 2770 | return -EINVAL; |
2771 | /* but don't bother the driver with it */ | ||
2772 | params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER); | ||
2742 | 2773 | ||
2743 | params.sta_modify_mask |= STATION_PARAM_APPLY_UAPSD; | 2774 | /* must be last in here for error handling */ |
2775 | params.vlan = get_vlan(info, rdev); | ||
2776 | if (IS_ERR(params.vlan)) | ||
2777 | return PTR_ERR(params.vlan); | ||
2778 | break; | ||
2779 | case NL80211_IFTYPE_MESH_POINT: | ||
2780 | /* TDLS peers cannot be added */ | ||
2781 | if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) | ||
2782 | return -EINVAL; | ||
2783 | break; | ||
2784 | case NL80211_IFTYPE_STATION: | ||
2785 | /* Only TDLS peers can be added */ | ||
2786 | if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) | ||
2787 | return -EINVAL; | ||
2788 | /* Can only add if TDLS ... */ | ||
2789 | if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS)) | ||
2790 | return -EOPNOTSUPP; | ||
2791 | /* ... with external setup is supported */ | ||
2792 | if (!(rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP)) | ||
2793 | return -EOPNOTSUPP; | ||
2794 | break; | ||
2795 | default: | ||
2796 | return -EOPNOTSUPP; | ||
2744 | } | 2797 | } |
2745 | 2798 | ||
2746 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && | 2799 | /* be aware of params.vlan when changing code here */ |
2747 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && | ||
2748 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT && | ||
2749 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO && | ||
2750 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) | ||
2751 | return -EINVAL; | ||
2752 | |||
2753 | /* | ||
2754 | * Only managed stations can add TDLS peers, and only when the | ||
2755 | * wiphy supports external TDLS setup. | ||
2756 | */ | ||
2757 | if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION && | ||
2758 | !((params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) && | ||
2759 | (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) && | ||
2760 | (rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP))) | ||
2761 | return -EINVAL; | ||
2762 | |||
2763 | params.vlan = get_vlan(info, rdev); | ||
2764 | if (IS_ERR(params.vlan)) | ||
2765 | return PTR_ERR(params.vlan); | ||
2766 | |||
2767 | /* validate settings */ | ||
2768 | err = 0; | ||
2769 | |||
2770 | if (!rdev->ops->add_station) { | ||
2771 | err = -EOPNOTSUPP; | ||
2772 | goto out; | ||
2773 | } | ||
2774 | 2800 | ||
2775 | err = rdev->ops->add_station(&rdev->wiphy, dev, mac_addr, ¶ms); | 2801 | err = rdev->ops->add_station(&rdev->wiphy, dev, mac_addr, ¶ms); |
2776 | 2802 | ||
2777 | out: | ||
2778 | if (params.vlan) | 2803 | if (params.vlan) |
2779 | dev_put(params.vlan); | 2804 | dev_put(params.vlan); |
2780 | return err; | 2805 | return err; |
@@ -4795,7 +4820,7 @@ static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info) | |||
4795 | static int nl80211_testmode_dump(struct sk_buff *skb, | 4820 | static int nl80211_testmode_dump(struct sk_buff *skb, |
4796 | struct netlink_callback *cb) | 4821 | struct netlink_callback *cb) |
4797 | { | 4822 | { |
4798 | struct cfg80211_registered_device *dev; | 4823 | struct cfg80211_registered_device *rdev; |
4799 | int err; | 4824 | int err; |
4800 | long phy_idx; | 4825 | long phy_idx; |
4801 | void *data = NULL; | 4826 | void *data = NULL; |
@@ -4813,9 +4838,21 @@ static int nl80211_testmode_dump(struct sk_buff *skb, | |||
4813 | nl80211_policy); | 4838 | nl80211_policy); |
4814 | if (err) | 4839 | if (err) |
4815 | return err; | 4840 | return err; |
4816 | if (!nl80211_fam.attrbuf[NL80211_ATTR_WIPHY]) | 4841 | if (nl80211_fam.attrbuf[NL80211_ATTR_WIPHY]) { |
4817 | return -EINVAL; | 4842 | phy_idx = nla_get_u32( |
4818 | phy_idx = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_WIPHY]); | 4843 | nl80211_fam.attrbuf[NL80211_ATTR_WIPHY]); |
4844 | } else { | ||
4845 | struct net_device *netdev; | ||
4846 | |||
4847 | err = get_rdev_dev_by_ifindex(sock_net(skb->sk), | ||
4848 | nl80211_fam.attrbuf, | ||
4849 | &rdev, &netdev); | ||
4850 | if (err) | ||
4851 | return err; | ||
4852 | dev_put(netdev); | ||
4853 | phy_idx = rdev->wiphy_idx; | ||
4854 | cfg80211_unlock_rdev(rdev); | ||
4855 | } | ||
4819 | if (nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA]) | 4856 | if (nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA]) |
4820 | cb->args[1] = | 4857 | cb->args[1] = |
4821 | (long)nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA]; | 4858 | (long)nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA]; |
@@ -4827,15 +4864,15 @@ static int nl80211_testmode_dump(struct sk_buff *skb, | |||
4827 | } | 4864 | } |
4828 | 4865 | ||
4829 | mutex_lock(&cfg80211_mutex); | 4866 | mutex_lock(&cfg80211_mutex); |
4830 | dev = cfg80211_rdev_by_wiphy_idx(phy_idx); | 4867 | rdev = cfg80211_rdev_by_wiphy_idx(phy_idx); |
4831 | if (!dev) { | 4868 | if (!rdev) { |
4832 | mutex_unlock(&cfg80211_mutex); | 4869 | mutex_unlock(&cfg80211_mutex); |
4833 | return -ENOENT; | 4870 | return -ENOENT; |
4834 | } | 4871 | } |
4835 | cfg80211_lock_rdev(dev); | 4872 | cfg80211_lock_rdev(rdev); |
4836 | mutex_unlock(&cfg80211_mutex); | 4873 | mutex_unlock(&cfg80211_mutex); |
4837 | 4874 | ||
4838 | if (!dev->ops->testmode_dump) { | 4875 | if (!rdev->ops->testmode_dump) { |
4839 | err = -EOPNOTSUPP; | 4876 | err = -EOPNOTSUPP; |
4840 | goto out_err; | 4877 | goto out_err; |
4841 | } | 4878 | } |
@@ -4846,7 +4883,7 @@ static int nl80211_testmode_dump(struct sk_buff *skb, | |||
4846 | NL80211_CMD_TESTMODE); | 4883 | NL80211_CMD_TESTMODE); |
4847 | struct nlattr *tmdata; | 4884 | struct nlattr *tmdata; |
4848 | 4885 | ||
4849 | if (nla_put_u32(skb, NL80211_ATTR_WIPHY, dev->wiphy_idx) < 0) { | 4886 | if (nla_put_u32(skb, NL80211_ATTR_WIPHY, phy_idx) < 0) { |
4850 | genlmsg_cancel(skb, hdr); | 4887 | genlmsg_cancel(skb, hdr); |
4851 | break; | 4888 | break; |
4852 | } | 4889 | } |
@@ -4856,8 +4893,8 @@ static int nl80211_testmode_dump(struct sk_buff *skb, | |||
4856 | genlmsg_cancel(skb, hdr); | 4893 | genlmsg_cancel(skb, hdr); |
4857 | break; | 4894 | break; |
4858 | } | 4895 | } |
4859 | err = dev->ops->testmode_dump(&dev->wiphy, skb, cb, | 4896 | err = rdev->ops->testmode_dump(&rdev->wiphy, skb, cb, |
4860 | data, data_len); | 4897 | data, data_len); |
4861 | nla_nest_end(skb, tmdata); | 4898 | nla_nest_end(skb, tmdata); |
4862 | 4899 | ||
4863 | if (err == -ENOBUFS || err == -ENOENT) { | 4900 | if (err == -ENOBUFS || err == -ENOENT) { |
@@ -4875,7 +4912,7 @@ static int nl80211_testmode_dump(struct sk_buff *skb, | |||
4875 | /* see above */ | 4912 | /* see above */ |
4876 | cb->args[0] = phy_idx + 1; | 4913 | cb->args[0] = phy_idx + 1; |
4877 | out_err: | 4914 | out_err: |
4878 | cfg80211_unlock_rdev(dev); | 4915 | cfg80211_unlock_rdev(rdev); |
4879 | return err; | 4916 | return err; |
4880 | } | 4917 | } |
4881 | 4918 | ||
@@ -6110,7 +6147,8 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb, | |||
6110 | } | 6147 | } |
6111 | info->user_ptr[0] = rdev; | 6148 | info->user_ptr[0] = rdev; |
6112 | } else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) { | 6149 | } else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) { |
6113 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | 6150 | err = get_rdev_dev_by_ifindex(genl_info_net(info), info->attrs, |
6151 | &rdev, &dev); | ||
6114 | if (err) { | 6152 | if (err) { |
6115 | if (rtnl) | 6153 | if (rtnl) |
6116 | rtnl_unlock(); | 6154 | rtnl_unlock(); |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 70b171a52aea..c45c8b772ddd 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -873,10 +873,22 @@ static void handle_channel(struct wiphy *wiphy, | |||
873 | chan->flags = flags | bw_flags | map_regdom_flags(reg_rule->flags); | 873 | chan->flags = flags | bw_flags | map_regdom_flags(reg_rule->flags); |
874 | chan->max_antenna_gain = min(chan->orig_mag, | 874 | chan->max_antenna_gain = min(chan->orig_mag, |
875 | (int) MBI_TO_DBI(power_rule->max_antenna_gain)); | 875 | (int) MBI_TO_DBI(power_rule->max_antenna_gain)); |
876 | if (chan->orig_mpwr) | 876 | if (chan->orig_mpwr) { |
877 | chan->max_power = min(chan->orig_mpwr, | 877 | /* |
878 | (int) MBM_TO_DBM(power_rule->max_eirp)); | 878 | * Devices that have their own custom regulatory domain |
879 | else | 879 | * but also use WIPHY_FLAG_STRICT_REGULATORY will follow the |
880 | * passed country IE power settings. | ||
881 | */ | ||
882 | if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE && | ||
883 | wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY && | ||
884 | wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) { | ||
885 | chan->max_power = | ||
886 | MBM_TO_DBM(power_rule->max_eirp); | ||
887 | } else { | ||
888 | chan->max_power = min(chan->orig_mpwr, | ||
889 | (int) MBM_TO_DBM(power_rule->max_eirp)); | ||
890 | } | ||
891 | } else | ||
880 | chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp); | 892 | chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp); |
881 | } | 893 | } |
882 | 894 | ||
@@ -1163,9 +1175,21 @@ void regulatory_update(struct wiphy *wiphy, | |||
1163 | static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator) | 1175 | static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator) |
1164 | { | 1176 | { |
1165 | struct cfg80211_registered_device *rdev; | 1177 | struct cfg80211_registered_device *rdev; |
1178 | struct wiphy *wiphy; | ||
1166 | 1179 | ||
1167 | list_for_each_entry(rdev, &cfg80211_rdev_list, list) | 1180 | list_for_each_entry(rdev, &cfg80211_rdev_list, list) { |
1168 | wiphy_update_regulatory(&rdev->wiphy, initiator); | 1181 | wiphy = &rdev->wiphy; |
1182 | wiphy_update_regulatory(wiphy, initiator); | ||
1183 | /* | ||
1184 | * Regulatory updates set by CORE are ignored for custom | ||
1185 | * regulatory cards. Let us notify the changes to the driver, | ||
1186 | * as some drivers used this to restore its orig_* reg domain. | ||
1187 | */ | ||
1188 | if (initiator == NL80211_REGDOM_SET_BY_CORE && | ||
1189 | wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY && | ||
1190 | wiphy->reg_notifier) | ||
1191 | wiphy->reg_notifier(wiphy, last_request); | ||
1192 | } | ||
1169 | } | 1193 | } |
1170 | 1194 | ||
1171 | static void handle_channel_custom(struct wiphy *wiphy, | 1195 | static void handle_channel_custom(struct wiphy *wiphy, |
@@ -1768,6 +1792,26 @@ static void restore_alpha2(char *alpha2, bool reset_user) | |||
1768 | REG_DBG_PRINT("Restoring regulatory settings\n"); | 1792 | REG_DBG_PRINT("Restoring regulatory settings\n"); |
1769 | } | 1793 | } |
1770 | 1794 | ||
1795 | static void restore_custom_reg_settings(struct wiphy *wiphy) | ||
1796 | { | ||
1797 | struct ieee80211_supported_band *sband; | ||
1798 | enum ieee80211_band band; | ||
1799 | struct ieee80211_channel *chan; | ||
1800 | int i; | ||
1801 | |||
1802 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | ||
1803 | sband = wiphy->bands[band]; | ||
1804 | if (!sband) | ||
1805 | continue; | ||
1806 | for (i = 0; i < sband->n_channels; i++) { | ||
1807 | chan = &sband->channels[i]; | ||
1808 | chan->flags = chan->orig_flags; | ||
1809 | chan->max_antenna_gain = chan->orig_mag; | ||
1810 | chan->max_power = chan->orig_mpwr; | ||
1811 | } | ||
1812 | } | ||
1813 | } | ||
1814 | |||
1771 | /* | 1815 | /* |
1772 | * Restoring regulatory settings involves ingoring any | 1816 | * Restoring regulatory settings involves ingoring any |
1773 | * possibly stale country IE information and user regulatory | 1817 | * possibly stale country IE information and user regulatory |
@@ -1789,6 +1833,7 @@ static void restore_regulatory_settings(bool reset_user) | |||
1789 | struct reg_beacon *reg_beacon, *btmp; | 1833 | struct reg_beacon *reg_beacon, *btmp; |
1790 | struct regulatory_request *reg_request, *tmp; | 1834 | struct regulatory_request *reg_request, *tmp; |
1791 | LIST_HEAD(tmp_reg_req_list); | 1835 | LIST_HEAD(tmp_reg_req_list); |
1836 | struct cfg80211_registered_device *rdev; | ||
1792 | 1837 | ||
1793 | mutex_lock(&cfg80211_mutex); | 1838 | mutex_lock(&cfg80211_mutex); |
1794 | mutex_lock(®_mutex); | 1839 | mutex_lock(®_mutex); |
@@ -1837,6 +1882,11 @@ static void restore_regulatory_settings(bool reset_user) | |||
1837 | /* First restore to the basic regulatory settings */ | 1882 | /* First restore to the basic regulatory settings */ |
1838 | cfg80211_regdomain = cfg80211_world_regdom; | 1883 | cfg80211_regdomain = cfg80211_world_regdom; |
1839 | 1884 | ||
1885 | list_for_each_entry(rdev, &cfg80211_rdev_list, list) { | ||
1886 | if (rdev->wiphy.flags & WIPHY_FLAG_CUSTOM_REGULATORY) | ||
1887 | restore_custom_reg_settings(&rdev->wiphy); | ||
1888 | } | ||
1889 | |||
1840 | mutex_unlock(®_mutex); | 1890 | mutex_unlock(®_mutex); |
1841 | mutex_unlock(&cfg80211_mutex); | 1891 | mutex_unlock(&cfg80211_mutex); |
1842 | 1892 | ||
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index f0c900ce2fb9..7b9ecaed96be 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
@@ -553,45 +553,35 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
553 | EXPORT_SYMBOL(cfg80211_connect_result); | 553 | EXPORT_SYMBOL(cfg80211_connect_result); |
554 | 554 | ||
555 | void __cfg80211_roamed(struct wireless_dev *wdev, | 555 | void __cfg80211_roamed(struct wireless_dev *wdev, |
556 | struct ieee80211_channel *channel, | 556 | struct cfg80211_bss *bss, |
557 | const u8 *bssid, | ||
558 | const u8 *req_ie, size_t req_ie_len, | 557 | const u8 *req_ie, size_t req_ie_len, |
559 | const u8 *resp_ie, size_t resp_ie_len) | 558 | const u8 *resp_ie, size_t resp_ie_len) |
560 | { | 559 | { |
561 | struct cfg80211_bss *bss; | ||
562 | #ifdef CONFIG_CFG80211_WEXT | 560 | #ifdef CONFIG_CFG80211_WEXT |
563 | union iwreq_data wrqu; | 561 | union iwreq_data wrqu; |
564 | #endif | 562 | #endif |
565 | |||
566 | ASSERT_WDEV_LOCK(wdev); | 563 | ASSERT_WDEV_LOCK(wdev); |
567 | 564 | ||
568 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION && | 565 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION && |
569 | wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)) | 566 | wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)) |
570 | return; | 567 | goto out; |
571 | 568 | ||
572 | if (wdev->sme_state != CFG80211_SME_CONNECTED) | 569 | if (wdev->sme_state != CFG80211_SME_CONNECTED) |
573 | return; | 570 | goto out; |
574 | 571 | ||
575 | /* internal error -- how did we get to CONNECTED w/o BSS? */ | 572 | /* internal error -- how did we get to CONNECTED w/o BSS? */ |
576 | if (WARN_ON(!wdev->current_bss)) { | 573 | if (WARN_ON(!wdev->current_bss)) { |
577 | return; | 574 | goto out; |
578 | } | 575 | } |
579 | 576 | ||
580 | cfg80211_unhold_bss(wdev->current_bss); | 577 | cfg80211_unhold_bss(wdev->current_bss); |
581 | cfg80211_put_bss(&wdev->current_bss->pub); | 578 | cfg80211_put_bss(&wdev->current_bss->pub); |
582 | wdev->current_bss = NULL; | 579 | wdev->current_bss = NULL; |
583 | 580 | ||
584 | bss = cfg80211_get_bss(wdev->wiphy, channel, bssid, | ||
585 | wdev->ssid, wdev->ssid_len, | ||
586 | WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); | ||
587 | |||
588 | if (WARN_ON(!bss)) | ||
589 | return; | ||
590 | |||
591 | cfg80211_hold_bss(bss_from_pub(bss)); | 581 | cfg80211_hold_bss(bss_from_pub(bss)); |
592 | wdev->current_bss = bss_from_pub(bss); | 582 | wdev->current_bss = bss_from_pub(bss); |
593 | 583 | ||
594 | nl80211_send_roamed(wiphy_to_dev(wdev->wiphy), wdev->netdev, bssid, | 584 | nl80211_send_roamed(wiphy_to_dev(wdev->wiphy), wdev->netdev, bss->bssid, |
595 | req_ie, req_ie_len, resp_ie, resp_ie_len, | 585 | req_ie, req_ie_len, resp_ie, resp_ie_len, |
596 | GFP_KERNEL); | 586 | GFP_KERNEL); |
597 | 587 | ||
@@ -612,11 +602,15 @@ void __cfg80211_roamed(struct wireless_dev *wdev, | |||
612 | 602 | ||
613 | memset(&wrqu, 0, sizeof(wrqu)); | 603 | memset(&wrqu, 0, sizeof(wrqu)); |
614 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | 604 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; |
615 | memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN); | 605 | memcpy(wrqu.ap_addr.sa_data, bss->bssid, ETH_ALEN); |
616 | memcpy(wdev->wext.prev_bssid, bssid, ETH_ALEN); | 606 | memcpy(wdev->wext.prev_bssid, bss->bssid, ETH_ALEN); |
617 | wdev->wext.prev_bssid_valid = true; | 607 | wdev->wext.prev_bssid_valid = true; |
618 | wireless_send_event(wdev->netdev, SIOCGIWAP, &wrqu, NULL); | 608 | wireless_send_event(wdev->netdev, SIOCGIWAP, &wrqu, NULL); |
619 | #endif | 609 | #endif |
610 | |||
611 | return; | ||
612 | out: | ||
613 | cfg80211_put_bss(bss); | ||
620 | } | 614 | } |
621 | 615 | ||
622 | void cfg80211_roamed(struct net_device *dev, | 616 | void cfg80211_roamed(struct net_device *dev, |
@@ -626,32 +620,57 @@ void cfg80211_roamed(struct net_device *dev, | |||
626 | const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp) | 620 | const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp) |
627 | { | 621 | { |
628 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 622 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
623 | struct cfg80211_bss *bss; | ||
624 | |||
625 | CFG80211_DEV_WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTED); | ||
626 | |||
627 | bss = cfg80211_get_bss(wdev->wiphy, channel, bssid, wdev->ssid, | ||
628 | wdev->ssid_len, WLAN_CAPABILITY_ESS, | ||
629 | WLAN_CAPABILITY_ESS); | ||
630 | if (WARN_ON(!bss)) | ||
631 | return; | ||
632 | |||
633 | cfg80211_roamed_bss(dev, bss, req_ie, req_ie_len, resp_ie, | ||
634 | resp_ie_len, gfp); | ||
635 | } | ||
636 | EXPORT_SYMBOL(cfg80211_roamed); | ||
637 | |||
638 | void cfg80211_roamed_bss(struct net_device *dev, | ||
639 | struct cfg80211_bss *bss, const u8 *req_ie, | ||
640 | size_t req_ie_len, const u8 *resp_ie, | ||
641 | size_t resp_ie_len, gfp_t gfp) | ||
642 | { | ||
643 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
629 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | 644 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); |
630 | struct cfg80211_event *ev; | 645 | struct cfg80211_event *ev; |
631 | unsigned long flags; | 646 | unsigned long flags; |
632 | 647 | ||
633 | CFG80211_DEV_WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTED); | 648 | CFG80211_DEV_WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTED); |
634 | 649 | ||
650 | if (WARN_ON(!bss)) | ||
651 | return; | ||
652 | |||
635 | ev = kzalloc(sizeof(*ev) + req_ie_len + resp_ie_len, gfp); | 653 | ev = kzalloc(sizeof(*ev) + req_ie_len + resp_ie_len, gfp); |
636 | if (!ev) | 654 | if (!ev) { |
655 | cfg80211_put_bss(bss); | ||
637 | return; | 656 | return; |
657 | } | ||
638 | 658 | ||
639 | ev->type = EVENT_ROAMED; | 659 | ev->type = EVENT_ROAMED; |
640 | ev->rm.channel = channel; | ||
641 | memcpy(ev->rm.bssid, bssid, ETH_ALEN); | ||
642 | ev->rm.req_ie = ((u8 *)ev) + sizeof(*ev); | 660 | ev->rm.req_ie = ((u8 *)ev) + sizeof(*ev); |
643 | ev->rm.req_ie_len = req_ie_len; | 661 | ev->rm.req_ie_len = req_ie_len; |
644 | memcpy((void *)ev->rm.req_ie, req_ie, req_ie_len); | 662 | memcpy((void *)ev->rm.req_ie, req_ie, req_ie_len); |
645 | ev->rm.resp_ie = ((u8 *)ev) + sizeof(*ev) + req_ie_len; | 663 | ev->rm.resp_ie = ((u8 *)ev) + sizeof(*ev) + req_ie_len; |
646 | ev->rm.resp_ie_len = resp_ie_len; | 664 | ev->rm.resp_ie_len = resp_ie_len; |
647 | memcpy((void *)ev->rm.resp_ie, resp_ie, resp_ie_len); | 665 | memcpy((void *)ev->rm.resp_ie, resp_ie, resp_ie_len); |
666 | ev->rm.bss = bss; | ||
648 | 667 | ||
649 | spin_lock_irqsave(&wdev->event_lock, flags); | 668 | spin_lock_irqsave(&wdev->event_lock, flags); |
650 | list_add_tail(&ev->list, &wdev->event_list); | 669 | list_add_tail(&ev->list, &wdev->event_list); |
651 | spin_unlock_irqrestore(&wdev->event_lock, flags); | 670 | spin_unlock_irqrestore(&wdev->event_lock, flags); |
652 | queue_work(cfg80211_wq, &rdev->event_work); | 671 | queue_work(cfg80211_wq, &rdev->event_work); |
653 | } | 672 | } |
654 | EXPORT_SYMBOL(cfg80211_roamed); | 673 | EXPORT_SYMBOL(cfg80211_roamed_bss); |
655 | 674 | ||
656 | void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, | 675 | void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, |
657 | size_t ie_len, u16 reason, bool from_ap) | 676 | size_t ie_len, u16 reason, bool from_ap) |
diff --git a/net/wireless/util.c b/net/wireless/util.c index 9c601d59b77a..e77df7585004 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -740,9 +740,9 @@ static void cfg80211_process_wdev_events(struct wireless_dev *wdev) | |||
740 | NULL); | 740 | NULL); |
741 | break; | 741 | break; |
742 | case EVENT_ROAMED: | 742 | case EVENT_ROAMED: |
743 | __cfg80211_roamed(wdev, ev->rm.channel, ev->rm.bssid, | 743 | __cfg80211_roamed(wdev, ev->rm.bss, ev->rm.req_ie, |
744 | ev->rm.req_ie, ev->rm.req_ie_len, | 744 | ev->rm.req_ie_len, ev->rm.resp_ie, |
745 | ev->rm.resp_ie, ev->rm.resp_ie_len); | 745 | ev->rm.resp_ie_len); |
746 | break; | 746 | break; |
747 | case EVENT_DISCONNECTED: | 747 | case EVENT_DISCONNECTED: |
748 | __cfg80211_disconnected(wdev->netdev, | 748 | __cfg80211_disconnected(wdev->netdev, |