diff options
author | David S. Miller <davem@davemloft.net> | 2009-03-17 18:04:31 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-03-17 18:04:31 -0400 |
commit | af4330631cd48987755f1a8d324dc318f60cf16b (patch) | |
tree | 3c9233e81b450921326da13a7f8abacb58ab1f5e | |
parent | 2d6a5e9500103680464a723a4564961675652680 (diff) | |
parent | 808ff697b357cee54e214efd27921a9ec6461a94 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
72 files changed, 7713 insertions, 3048 deletions
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 1294175cab20..612fffe100a6 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig | |||
@@ -473,6 +473,15 @@ config MAC80211_HWSIM | |||
473 | To compile this driver as a module, choose M here: the module will be | 473 | To compile this driver as a module, choose M here: the module will be |
474 | called mac80211_hwsim. If unsure, say N. | 474 | called mac80211_hwsim. If unsure, say N. |
475 | 475 | ||
476 | config MWL8K | ||
477 | tristate "Marvell 88W8xxx PCI/PCIe Wireless support" | ||
478 | depends on MAC80211 && PCI && WLAN_80211 && EXPERIMENTAL | ||
479 | ---help--- | ||
480 | This driver supports Marvell TOPDOG 802.11 wireless cards. | ||
481 | |||
482 | To compile this driver as a module, choose M here: the module | ||
483 | will be called mwl8k. If unsure, say N. | ||
484 | |||
476 | source "drivers/net/wireless/p54/Kconfig" | 485 | source "drivers/net/wireless/p54/Kconfig" |
477 | source "drivers/net/wireless/ath5k/Kconfig" | 486 | source "drivers/net/wireless/ath5k/Kconfig" |
478 | source "drivers/net/wireless/ath9k/Kconfig" | 487 | source "drivers/net/wireless/ath9k/Kconfig" |
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index e2574cafe051..d780487c420f 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile | |||
@@ -48,6 +48,8 @@ obj-$(CONFIG_LIBERTAS_THINFIRM) += libertas_tf/ | |||
48 | 48 | ||
49 | obj-$(CONFIG_ADM8211) += adm8211.o | 49 | obj-$(CONFIG_ADM8211) += adm8211.o |
50 | 50 | ||
51 | obj-$(CONFIG_MWL8K) += mwl8k.o | ||
52 | |||
51 | obj-$(CONFIG_IWLWIFI) += iwlwifi/ | 53 | obj-$(CONFIG_IWLWIFI) += iwlwifi/ |
52 | obj-$(CONFIG_RT2X00) += rt2x00/ | 54 | obj-$(CONFIG_RT2X00) += rt2x00/ |
53 | 55 | ||
diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c index 27696c20f4c2..d0593ed9170e 100644 --- a/drivers/net/wireless/airo_cs.c +++ b/drivers/net/wireless/airo_cs.c | |||
@@ -16,8 +16,8 @@ | |||
16 | In addition this module was derived from dummy_cs. | 16 | In addition this module was derived from dummy_cs. |
17 | The initial developer of dummy_cs is David A. Hinds | 17 | The initial developer of dummy_cs is David A. Hinds |
18 | <dahinds@users.sourceforge.net>. Portions created by David A. Hinds | 18 | <dahinds@users.sourceforge.net>. Portions created by David A. Hinds |
19 | are Copyright (C) 1999 David A. Hinds. All Rights Reserved. | 19 | are Copyright (C) 1999 David A. Hinds. All Rights Reserved. |
20 | 20 | ||
21 | ======================================================================*/ | 21 | ======================================================================*/ |
22 | 22 | ||
23 | #ifdef __IN_PCMCIA_PACKAGE__ | 23 | #ifdef __IN_PCMCIA_PACKAGE__ |
@@ -38,7 +38,7 @@ | |||
38 | #include <pcmcia/cisreg.h> | 38 | #include <pcmcia/cisreg.h> |
39 | #include <pcmcia/ds.h> | 39 | #include <pcmcia/ds.h> |
40 | 40 | ||
41 | #include <asm/io.h> | 41 | #include <linux/io.h> |
42 | #include <asm/system.h> | 42 | #include <asm/system.h> |
43 | 43 | ||
44 | #include "airo.h" | 44 | #include "airo.h" |
@@ -54,7 +54,7 @@ | |||
54 | static int pc_debug = PCMCIA_DEBUG; | 54 | static int pc_debug = PCMCIA_DEBUG; |
55 | module_param(pc_debug, int, 0); | 55 | module_param(pc_debug, int, 0); |
56 | static char *version = "$Revision: 1.2 $"; | 56 | static char *version = "$Revision: 1.2 $"; |
57 | #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args); | 57 | #define DEBUG(n, args...) if (pc_debug > (n)) printk(KERN_DEBUG args); |
58 | #else | 58 | #else |
59 | #define DEBUG(n, args...) | 59 | #define DEBUG(n, args...) |
60 | #endif | 60 | #endif |
@@ -62,9 +62,9 @@ static char *version = "$Revision: 1.2 $"; | |||
62 | /*====================================================================*/ | 62 | /*====================================================================*/ |
63 | 63 | ||
64 | MODULE_AUTHOR("Benjamin Reed"); | 64 | MODULE_AUTHOR("Benjamin Reed"); |
65 | MODULE_DESCRIPTION("Support for Cisco/Aironet 802.11 wireless ethernet \ | 65 | MODULE_DESCRIPTION("Support for Cisco/Aironet 802.11 wireless ethernet " |
66 | cards. This is the module that links the PCMCIA card \ | 66 | "cards. This is the module that links the PCMCIA card " |
67 | with the airo module."); | 67 | "with the airo module."); |
68 | MODULE_LICENSE("Dual BSD/GPL"); | 68 | MODULE_LICENSE("Dual BSD/GPL"); |
69 | MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340 PCMCIA cards"); | 69 | MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340 PCMCIA cards"); |
70 | 70 | ||
@@ -76,7 +76,7 @@ MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340 PCMCIA cards"); | |||
76 | event is received. The config() and release() entry points are | 76 | event is received. The config() and release() entry points are |
77 | used to configure or release a socket, in response to card | 77 | used to configure or release a socket, in response to card |
78 | insertion and ejection events. They are invoked from the airo_cs | 78 | insertion and ejection events. They are invoked from the airo_cs |
79 | event handler. | 79 | event handler. |
80 | */ | 80 | */ |
81 | 81 | ||
82 | static int airo_config(struct pcmcia_device *link); | 82 | static int airo_config(struct pcmcia_device *link); |
@@ -103,8 +103,9 @@ static void airo_detach(struct pcmcia_device *p_dev); | |||
103 | by one struct pcmcia_device structure (defined in ds.h). | 103 | by one struct pcmcia_device structure (defined in ds.h). |
104 | 104 | ||
105 | You may not want to use a linked list for this -- for example, the | 105 | You may not want to use a linked list for this -- for example, the |
106 | memory card driver uses an array of struct pcmcia_device pointers, where minor | 106 | memory card driver uses an array of struct pcmcia_device pointers, |
107 | device numbers are used to derive the corresponding array index. | 107 | where minor device numbers are used to derive the corresponding |
108 | array index. | ||
108 | */ | 109 | */ |
109 | 110 | ||
110 | /* | 111 | /* |
@@ -122,22 +123,22 @@ static void airo_detach(struct pcmcia_device *p_dev); | |||
122 | device IO routines can use a flag like this to throttle IO to a | 123 | device IO routines can use a flag like this to throttle IO to a |
123 | card that is not ready to accept it. | 124 | card that is not ready to accept it. |
124 | */ | 125 | */ |
125 | 126 | ||
126 | typedef struct local_info_t { | 127 | typedef struct local_info_t { |
127 | dev_node_t node; | 128 | dev_node_t node; |
128 | struct net_device *eth_dev; | 129 | struct net_device *eth_dev; |
129 | } local_info_t; | 130 | } local_info_t; |
130 | 131 | ||
131 | /*====================================================================== | 132 | /*====================================================================== |
132 | 133 | ||
133 | airo_attach() creates an "instance" of the driver, allocating | 134 | airo_attach() creates an "instance" of the driver, allocating |
134 | local data structures for one device. The device is registered | 135 | local data structures for one device. The device is registered |
135 | with Card Services. | 136 | with Card Services. |
136 | 137 | ||
137 | The dev_link structure is initialized, but we don't actually | 138 | The dev_link structure is initialized, but we don't actually |
138 | configure the card at this point -- we wait until we receive a | 139 | configure the card at this point -- we wait until we receive a |
139 | card insertion event. | 140 | card insertion event. |
140 | 141 | ||
141 | ======================================================================*/ | 142 | ======================================================================*/ |
142 | 143 | ||
143 | static int airo_probe(struct pcmcia_device *p_dev) | 144 | static int airo_probe(struct pcmcia_device *p_dev) |
@@ -150,7 +151,7 @@ static int airo_probe(struct pcmcia_device *p_dev) | |||
150 | p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; | 151 | p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; |
151 | p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; | 152 | p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; |
152 | p_dev->irq.Handler = NULL; | 153 | p_dev->irq.Handler = NULL; |
153 | 154 | ||
154 | /* | 155 | /* |
155 | General socket configuration defaults can go here. In this | 156 | General socket configuration defaults can go here. In this |
156 | client, we assume very little, and rely on the CIS for almost | 157 | client, we assume very little, and rely on the CIS for almost |
@@ -160,7 +161,7 @@ static int airo_probe(struct pcmcia_device *p_dev) | |||
160 | */ | 161 | */ |
161 | p_dev->conf.Attributes = 0; | 162 | p_dev->conf.Attributes = 0; |
162 | p_dev->conf.IntType = INT_MEMORY_AND_IO; | 163 | p_dev->conf.IntType = INT_MEMORY_AND_IO; |
163 | 164 | ||
164 | /* Allocate space for private device-specific data */ | 165 | /* Allocate space for private device-specific data */ |
165 | local = kzalloc(sizeof(local_info_t), GFP_KERNEL); | 166 | local = kzalloc(sizeof(local_info_t), GFP_KERNEL); |
166 | if (!local) { | 167 | if (!local) { |
@@ -173,12 +174,12 @@ static int airo_probe(struct pcmcia_device *p_dev) | |||
173 | } /* airo_attach */ | 174 | } /* airo_attach */ |
174 | 175 | ||
175 | /*====================================================================== | 176 | /*====================================================================== |
176 | 177 | ||
177 | This deletes a driver "instance". The device is de-registered | 178 | This deletes a driver "instance". The device is de-registered |
178 | with Card Services. If it has been released, all local data | 179 | with Card Services. If it has been released, all local data |
179 | structures are freed. Otherwise, the structures will be freed | 180 | structures are freed. Otherwise, the structures will be freed |
180 | when the device is released. | 181 | when the device is released. |
181 | 182 | ||
182 | ======================================================================*/ | 183 | ======================================================================*/ |
183 | 184 | ||
184 | static void airo_detach(struct pcmcia_device *link) | 185 | static void airo_detach(struct pcmcia_device *link) |
@@ -187,20 +188,20 @@ static void airo_detach(struct pcmcia_device *link) | |||
187 | 188 | ||
188 | airo_release(link); | 189 | airo_release(link); |
189 | 190 | ||
190 | if ( ((local_info_t*)link->priv)->eth_dev ) { | 191 | if (((local_info_t *)link->priv)->eth_dev) { |
191 | stop_airo_card( ((local_info_t*)link->priv)->eth_dev, 0 ); | 192 | stop_airo_card(((local_info_t *)link->priv)->eth_dev, 0); |
192 | } | 193 | } |
193 | ((local_info_t*)link->priv)->eth_dev = NULL; | 194 | ((local_info_t *)link->priv)->eth_dev = NULL; |
194 | 195 | ||
195 | kfree(link->priv); | 196 | kfree(link->priv); |
196 | } /* airo_detach */ | 197 | } /* airo_detach */ |
197 | 198 | ||
198 | /*====================================================================== | 199 | /*====================================================================== |
199 | 200 | ||
200 | airo_config() is scheduled to run after a CARD_INSERTION event | 201 | airo_config() is scheduled to run after a CARD_INSERTION event |
201 | is received, to configure the PCMCIA socket, and to make the | 202 | is received, to configure the PCMCIA socket, and to make the |
202 | device available to the system. | 203 | device available to the system. |
203 | 204 | ||
204 | ======================================================================*/ | 205 | ======================================================================*/ |
205 | 206 | ||
206 | #define CS_CHECK(fn, ret) \ | 207 | #define CS_CHECK(fn, ret) \ |
@@ -325,26 +326,28 @@ static int airo_config(struct pcmcia_device *link) | |||
325 | */ | 326 | */ |
326 | if (link->conf.Attributes & CONF_ENABLE_IRQ) | 327 | if (link->conf.Attributes & CONF_ENABLE_IRQ) |
327 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); | 328 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); |
328 | 329 | ||
329 | /* | 330 | /* |
330 | This actually configures the PCMCIA socket -- setting up | 331 | This actually configures the PCMCIA socket -- setting up |
331 | the I/O windows and the interrupt mapping, and putting the | 332 | the I/O windows and the interrupt mapping, and putting the |
332 | card and host interface into "Memory and IO" mode. | 333 | card and host interface into "Memory and IO" mode. |
333 | */ | 334 | */ |
334 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); | 335 | CS_CHECK(RequestConfiguration, |
335 | ((local_info_t*)link->priv)->eth_dev = | 336 | pcmcia_request_configuration(link, &link->conf)); |
336 | init_airo_card( link->irq.AssignedIRQ, | 337 | ((local_info_t *)link->priv)->eth_dev = |
337 | link->io.BasePort1, 1, &handle_to_dev(link) ); | 338 | init_airo_card(link->irq.AssignedIRQ, |
338 | if (!((local_info_t*)link->priv)->eth_dev) goto cs_failed; | 339 | link->io.BasePort1, 1, &handle_to_dev(link)); |
339 | 340 | if (!((local_info_t *)link->priv)->eth_dev) | |
341 | goto cs_failed; | ||
342 | |||
340 | /* | 343 | /* |
341 | At this point, the dev_node_t structure(s) need to be | 344 | At this point, the dev_node_t structure(s) need to be |
342 | initialized and arranged in a linked list at link->dev_node. | 345 | initialized and arranged in a linked list at link->dev_node. |
343 | */ | 346 | */ |
344 | strcpy(dev->node.dev_name, ((local_info_t*)link->priv)->eth_dev->name ); | 347 | strcpy(dev->node.dev_name, ((local_info_t *)link->priv)->eth_dev->name); |
345 | dev->node.major = dev->node.minor = 0; | 348 | dev->node.major = dev->node.minor = 0; |
346 | link->dev_node = &dev->node; | 349 | link->dev_node = &dev->node; |
347 | 350 | ||
348 | /* Finally, report what we've done */ | 351 | /* Finally, report what we've done */ |
349 | printk(KERN_INFO "%s: index 0x%02x: ", | 352 | printk(KERN_INFO "%s: index 0x%02x: ", |
350 | dev->node.dev_name, link->conf.ConfigIndex); | 353 | dev->node.dev_name, link->conf.ConfigIndex); |
@@ -374,11 +377,11 @@ static int airo_config(struct pcmcia_device *link) | |||
374 | } /* airo_config */ | 377 | } /* airo_config */ |
375 | 378 | ||
376 | /*====================================================================== | 379 | /*====================================================================== |
377 | 380 | ||
378 | After a card is removed, airo_release() will unregister the | 381 | After a card is removed, airo_release() will unregister the |
379 | device, and release the PCMCIA configuration. If the device is | 382 | device, and release the PCMCIA configuration. If the device is |
380 | still open, this will be postponed until it is closed. | 383 | still open, this will be postponed until it is closed. |
381 | 384 | ||
382 | ======================================================================*/ | 385 | ======================================================================*/ |
383 | 386 | ||
384 | static void airo_release(struct pcmcia_device *link) | 387 | static void airo_release(struct pcmcia_device *link) |
@@ -475,7 +478,7 @@ static void airo_cs_cleanup(void) | |||
475 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | 478 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
476 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | 479 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
477 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 480 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
478 | POSSIBILITY OF SUCH DAMAGE. | 481 | POSSIBILITY OF SUCH DAMAGE. |
479 | */ | 482 | */ |
480 | 483 | ||
481 | module_init(airo_cs_init); | 484 | module_init(airo_cs_init); |
diff --git a/drivers/net/wireless/ath5k/Makefile b/drivers/net/wireless/ath5k/Makefile index 719cfaef7085..84a74c5248e5 100644 --- a/drivers/net/wireless/ath5k/Makefile +++ b/drivers/net/wireless/ath5k/Makefile | |||
@@ -10,5 +10,6 @@ ath5k-y += phy.o | |||
10 | ath5k-y += reset.o | 10 | ath5k-y += reset.o |
11 | ath5k-y += attach.o | 11 | ath5k-y += attach.o |
12 | ath5k-y += base.o | 12 | ath5k-y += base.o |
13 | ath5k-y += led.o | ||
13 | ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o | 14 | ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o |
14 | obj-$(CONFIG_ATH5K) += ath5k.o | 15 | obj-$(CONFIG_ATH5K) += ath5k.o |
diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h index b9af2b84c05f..0dc2c7321c8b 100644 --- a/drivers/net/wireless/ath5k/ath5k.h +++ b/drivers/net/wireless/ath5k/ath5k.h | |||
@@ -1129,6 +1129,12 @@ struct ath5k_hw { | |||
1129 | extern struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version); | 1129 | extern struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version); |
1130 | extern void ath5k_hw_detach(struct ath5k_hw *ah); | 1130 | extern void ath5k_hw_detach(struct ath5k_hw *ah); |
1131 | 1131 | ||
1132 | /* LED functions */ | ||
1133 | extern int ath5k_init_leds(struct ath5k_softc *sc); | ||
1134 | extern void ath5k_led_enable(struct ath5k_softc *sc); | ||
1135 | extern void ath5k_led_off(struct ath5k_softc *sc); | ||
1136 | extern void ath5k_unregister_leds(struct ath5k_softc *sc); | ||
1137 | |||
1132 | /* Reset Functions */ | 1138 | /* Reset Functions */ |
1133 | extern int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial); | 1139 | extern int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial); |
1134 | extern int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, struct ieee80211_channel *channel, bool change_channel); | 1140 | extern int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, struct ieee80211_channel *channel, bool change_channel); |
diff --git a/drivers/net/wireless/ath5k/attach.c b/drivers/net/wireless/ath5k/attach.c index 05bc5cb44e88..656cb9dc833b 100644 --- a/drivers/net/wireless/ath5k/attach.c +++ b/drivers/net/wireless/ath5k/attach.c | |||
@@ -34,14 +34,14 @@ | |||
34 | static int ath5k_hw_post(struct ath5k_hw *ah) | 34 | static int ath5k_hw_post(struct ath5k_hw *ah) |
35 | { | 35 | { |
36 | 36 | ||
37 | int i, c; | 37 | static const u32 static_pattern[4] = { |
38 | u16 cur_reg; | ||
39 | u16 regs[2] = {AR5K_STA_ID0, AR5K_PHY(8)}; | ||
40 | u32 var_pattern; | ||
41 | u32 static_pattern[4] = { | ||
42 | 0x55555555, 0xaaaaaaaa, | 38 | 0x55555555, 0xaaaaaaaa, |
43 | 0x66666666, 0x99999999 | 39 | 0x66666666, 0x99999999 |
44 | }; | 40 | }; |
41 | static const u16 regs[2] = { AR5K_STA_ID0, AR5K_PHY(8) }; | ||
42 | int i, c; | ||
43 | u16 cur_reg; | ||
44 | u32 var_pattern; | ||
45 | u32 init_val; | 45 | u32 init_val; |
46 | u32 cur_val; | 46 | u32 cur_val; |
47 | 47 | ||
@@ -106,7 +106,6 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) | |||
106 | { | 106 | { |
107 | struct ath5k_hw *ah; | 107 | struct ath5k_hw *ah; |
108 | struct pci_dev *pdev = sc->pdev; | 108 | struct pci_dev *pdev = sc->pdev; |
109 | u8 mac[ETH_ALEN] = {}; | ||
110 | int ret; | 109 | int ret; |
111 | u32 srev; | 110 | u32 srev; |
112 | 111 | ||
@@ -312,7 +311,7 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) | |||
312 | } | 311 | } |
313 | 312 | ||
314 | /* MAC address is cleared until add_interface */ | 313 | /* MAC address is cleared until add_interface */ |
315 | ath5k_hw_set_lladdr(ah, mac); | 314 | ath5k_hw_set_lladdr(ah, (u8[ETH_ALEN]){}); |
316 | 315 | ||
317 | /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */ | 316 | /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */ |
318 | memset(ah->ah_bssid, 0xff, ETH_ALEN); | 317 | memset(ah->ah_bssid, 0xff, ETH_ALEN); |
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index f7c424dcac66..cad3ccf61b00 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c | |||
@@ -79,7 +79,7 @@ MODULE_VERSION("0.6.0 (EXPERIMENTAL)"); | |||
79 | 79 | ||
80 | 80 | ||
81 | /* Known PCI ids */ | 81 | /* Known PCI ids */ |
82 | static struct pci_device_id ath5k_pci_id_table[] __devinitdata = { | 82 | static const struct pci_device_id ath5k_pci_id_table[] = { |
83 | { PCI_VDEVICE(ATHEROS, 0x0207), .driver_data = AR5K_AR5210 }, /* 5210 early */ | 83 | { PCI_VDEVICE(ATHEROS, 0x0207), .driver_data = AR5K_AR5210 }, /* 5210 early */ |
84 | { PCI_VDEVICE(ATHEROS, 0x0007), .driver_data = AR5K_AR5210 }, /* 5210 */ | 84 | { PCI_VDEVICE(ATHEROS, 0x0007), .driver_data = AR5K_AR5210 }, /* 5210 */ |
85 | { PCI_VDEVICE(ATHEROS, 0x0011), .driver_data = AR5K_AR5211 }, /* 5311 - this is on AHB bus !*/ | 85 | { PCI_VDEVICE(ATHEROS, 0x0011), .driver_data = AR5K_AR5211 }, /* 5311 - this is on AHB bus !*/ |
@@ -103,7 +103,7 @@ static struct pci_device_id ath5k_pci_id_table[] __devinitdata = { | |||
103 | MODULE_DEVICE_TABLE(pci, ath5k_pci_id_table); | 103 | MODULE_DEVICE_TABLE(pci, ath5k_pci_id_table); |
104 | 104 | ||
105 | /* Known SREVs */ | 105 | /* Known SREVs */ |
106 | static struct ath5k_srev_name srev_names[] = { | 106 | static const struct ath5k_srev_name srev_names[] = { |
107 | { "5210", AR5K_VERSION_MAC, AR5K_SREV_AR5210 }, | 107 | { "5210", AR5K_VERSION_MAC, AR5K_SREV_AR5210 }, |
108 | { "5311", AR5K_VERSION_MAC, AR5K_SREV_AR5311 }, | 108 | { "5311", AR5K_VERSION_MAC, AR5K_SREV_AR5311 }, |
109 | { "5311A", AR5K_VERSION_MAC, AR5K_SREV_AR5311A }, | 109 | { "5311A", AR5K_VERSION_MAC, AR5K_SREV_AR5311A }, |
@@ -142,7 +142,7 @@ static struct ath5k_srev_name srev_names[] = { | |||
142 | { "xxxxx", AR5K_VERSION_RAD, AR5K_SREV_UNKNOWN }, | 142 | { "xxxxx", AR5K_VERSION_RAD, AR5K_SREV_UNKNOWN }, |
143 | }; | 143 | }; |
144 | 144 | ||
145 | static struct ieee80211_rate ath5k_rates[] = { | 145 | static const struct ieee80211_rate ath5k_rates[] = { |
146 | { .bitrate = 10, | 146 | { .bitrate = 10, |
147 | .hw_value = ATH5K_RATE_CODE_1M, }, | 147 | .hw_value = ATH5K_RATE_CODE_1M, }, |
148 | { .bitrate = 20, | 148 | { .bitrate = 20, |
@@ -248,7 +248,7 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw, | |||
248 | struct ieee80211_bss_conf *bss_conf, | 248 | struct ieee80211_bss_conf *bss_conf, |
249 | u32 changes); | 249 | u32 changes); |
250 | 250 | ||
251 | static struct ieee80211_ops ath5k_hw_ops = { | 251 | static const struct ieee80211_ops ath5k_hw_ops = { |
252 | .tx = ath5k_tx, | 252 | .tx = ath5k_tx, |
253 | .start = ath5k_start, | 253 | .start = ath5k_start, |
254 | .stop = ath5k_stop, | 254 | .stop = ath5k_stop, |
@@ -370,11 +370,6 @@ static irqreturn_t ath5k_intr(int irq, void *dev_id); | |||
370 | static void ath5k_tasklet_reset(unsigned long data); | 370 | static void ath5k_tasklet_reset(unsigned long data); |
371 | 371 | ||
372 | static void ath5k_calibrate(unsigned long data); | 372 | static void ath5k_calibrate(unsigned long data); |
373 | /* LED functions */ | ||
374 | static int ath5k_init_leds(struct ath5k_softc *sc); | ||
375 | static void ath5k_led_enable(struct ath5k_softc *sc); | ||
376 | static void ath5k_led_off(struct ath5k_softc *sc); | ||
377 | static void ath5k_unregister_leds(struct ath5k_softc *sc); | ||
378 | 373 | ||
379 | /* | 374 | /* |
380 | * Module init/exit functions | 375 | * Module init/exit functions |
@@ -2530,141 +2525,6 @@ ath5k_calibrate(unsigned long data) | |||
2530 | } | 2525 | } |
2531 | 2526 | ||
2532 | 2527 | ||
2533 | |||
2534 | /***************\ | ||
2535 | * LED functions * | ||
2536 | \***************/ | ||
2537 | |||
2538 | static void | ||
2539 | ath5k_led_enable(struct ath5k_softc *sc) | ||
2540 | { | ||
2541 | if (test_bit(ATH_STAT_LEDSOFT, sc->status)) { | ||
2542 | ath5k_hw_set_gpio_output(sc->ah, sc->led_pin); | ||
2543 | ath5k_led_off(sc); | ||
2544 | } | ||
2545 | } | ||
2546 | |||
2547 | static void | ||
2548 | ath5k_led_on(struct ath5k_softc *sc) | ||
2549 | { | ||
2550 | if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) | ||
2551 | return; | ||
2552 | ath5k_hw_set_gpio(sc->ah, sc->led_pin, sc->led_on); | ||
2553 | } | ||
2554 | |||
2555 | static void | ||
2556 | ath5k_led_off(struct ath5k_softc *sc) | ||
2557 | { | ||
2558 | if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) | ||
2559 | return; | ||
2560 | ath5k_hw_set_gpio(sc->ah, sc->led_pin, !sc->led_on); | ||
2561 | } | ||
2562 | |||
2563 | static void | ||
2564 | ath5k_led_brightness_set(struct led_classdev *led_dev, | ||
2565 | enum led_brightness brightness) | ||
2566 | { | ||
2567 | struct ath5k_led *led = container_of(led_dev, struct ath5k_led, | ||
2568 | led_dev); | ||
2569 | |||
2570 | if (brightness == LED_OFF) | ||
2571 | ath5k_led_off(led->sc); | ||
2572 | else | ||
2573 | ath5k_led_on(led->sc); | ||
2574 | } | ||
2575 | |||
2576 | static int | ||
2577 | ath5k_register_led(struct ath5k_softc *sc, struct ath5k_led *led, | ||
2578 | const char *name, char *trigger) | ||
2579 | { | ||
2580 | int err; | ||
2581 | |||
2582 | led->sc = sc; | ||
2583 | strncpy(led->name, name, sizeof(led->name)); | ||
2584 | led->led_dev.name = led->name; | ||
2585 | led->led_dev.default_trigger = trigger; | ||
2586 | led->led_dev.brightness_set = ath5k_led_brightness_set; | ||
2587 | |||
2588 | err = led_classdev_register(&sc->pdev->dev, &led->led_dev); | ||
2589 | if (err) { | ||
2590 | ATH5K_WARN(sc, "could not register LED %s\n", name); | ||
2591 | led->sc = NULL; | ||
2592 | } | ||
2593 | return err; | ||
2594 | } | ||
2595 | |||
2596 | static void | ||
2597 | ath5k_unregister_led(struct ath5k_led *led) | ||
2598 | { | ||
2599 | if (!led->sc) | ||
2600 | return; | ||
2601 | led_classdev_unregister(&led->led_dev); | ||
2602 | ath5k_led_off(led->sc); | ||
2603 | led->sc = NULL; | ||
2604 | } | ||
2605 | |||
2606 | static void | ||
2607 | ath5k_unregister_leds(struct ath5k_softc *sc) | ||
2608 | { | ||
2609 | ath5k_unregister_led(&sc->rx_led); | ||
2610 | ath5k_unregister_led(&sc->tx_led); | ||
2611 | } | ||
2612 | |||
2613 | |||
2614 | static int | ||
2615 | ath5k_init_leds(struct ath5k_softc *sc) | ||
2616 | { | ||
2617 | int ret = 0; | ||
2618 | struct ieee80211_hw *hw = sc->hw; | ||
2619 | struct pci_dev *pdev = sc->pdev; | ||
2620 | char name[ATH5K_LED_MAX_NAME_LEN + 1]; | ||
2621 | |||
2622 | /* | ||
2623 | * Auto-enable soft led processing for IBM cards and for | ||
2624 | * 5211 minipci cards. | ||
2625 | */ | ||
2626 | if (pdev->device == PCI_DEVICE_ID_ATHEROS_AR5212_IBM || | ||
2627 | pdev->device == PCI_DEVICE_ID_ATHEROS_AR5211) { | ||
2628 | __set_bit(ATH_STAT_LEDSOFT, sc->status); | ||
2629 | sc->led_pin = 0; | ||
2630 | sc->led_on = 0; /* active low */ | ||
2631 | } | ||
2632 | /* Enable softled on PIN1 on HP Compaq nc6xx, nc4000 & nx5000 laptops */ | ||
2633 | if (pdev->subsystem_vendor == PCI_VENDOR_ID_COMPAQ) { | ||
2634 | __set_bit(ATH_STAT_LEDSOFT, sc->status); | ||
2635 | sc->led_pin = 1; | ||
2636 | sc->led_on = 1; /* active high */ | ||
2637 | } | ||
2638 | /* | ||
2639 | * Pin 3 on Foxconn chips used in Acer Aspire One (0x105b:e008) and | ||
2640 | * in emachines notebooks with AMBIT subsystem. | ||
2641 | */ | ||
2642 | if (pdev->subsystem_vendor == PCI_VENDOR_ID_FOXCONN || | ||
2643 | pdev->subsystem_vendor == PCI_VENDOR_ID_AMBIT) { | ||
2644 | __set_bit(ATH_STAT_LEDSOFT, sc->status); | ||
2645 | sc->led_pin = 3; | ||
2646 | sc->led_on = 0; /* active low */ | ||
2647 | } | ||
2648 | |||
2649 | if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) | ||
2650 | goto out; | ||
2651 | |||
2652 | ath5k_led_enable(sc); | ||
2653 | |||
2654 | snprintf(name, sizeof(name), "ath5k-%s::rx", wiphy_name(hw->wiphy)); | ||
2655 | ret = ath5k_register_led(sc, &sc->rx_led, name, | ||
2656 | ieee80211_get_rx_led_name(hw)); | ||
2657 | if (ret) | ||
2658 | goto out; | ||
2659 | |||
2660 | snprintf(name, sizeof(name), "ath5k-%s::tx", wiphy_name(hw->wiphy)); | ||
2661 | ret = ath5k_register_led(sc, &sc->tx_led, name, | ||
2662 | ieee80211_get_tx_led_name(hw)); | ||
2663 | out: | ||
2664 | return ret; | ||
2665 | } | ||
2666 | |||
2667 | |||
2668 | /********************\ | 2528 | /********************\ |
2669 | * Mac80211 functions * | 2529 | * Mac80211 functions * |
2670 | \********************/ | 2530 | \********************/ |
diff --git a/drivers/net/wireless/ath5k/debug.c b/drivers/net/wireless/ath5k/debug.c index 413ed689cd5f..9770bb3d40f9 100644 --- a/drivers/net/wireless/ath5k/debug.c +++ b/drivers/net/wireless/ath5k/debug.c | |||
@@ -82,14 +82,14 @@ static int ath5k_debugfs_open(struct inode *inode, struct file *file) | |||
82 | /* debugfs: registers */ | 82 | /* debugfs: registers */ |
83 | 83 | ||
84 | struct reg { | 84 | struct reg { |
85 | char *name; | 85 | const char *name; |
86 | int addr; | 86 | int addr; |
87 | }; | 87 | }; |
88 | 88 | ||
89 | #define REG_STRUCT_INIT(r) { #r, r } | 89 | #define REG_STRUCT_INIT(r) { #r, r } |
90 | 90 | ||
91 | /* just a few random registers, might want to add more */ | 91 | /* just a few random registers, might want to add more */ |
92 | static struct reg regs[] = { | 92 | static const struct reg regs[] = { |
93 | REG_STRUCT_INIT(AR5K_CR), | 93 | REG_STRUCT_INIT(AR5K_CR), |
94 | REG_STRUCT_INIT(AR5K_RXDP), | 94 | REG_STRUCT_INIT(AR5K_RXDP), |
95 | REG_STRUCT_INIT(AR5K_CFG), | 95 | REG_STRUCT_INIT(AR5K_CFG), |
@@ -142,7 +142,7 @@ static struct reg regs[] = { | |||
142 | 142 | ||
143 | static void *reg_start(struct seq_file *seq, loff_t *pos) | 143 | static void *reg_start(struct seq_file *seq, loff_t *pos) |
144 | { | 144 | { |
145 | return *pos < ARRAY_SIZE(regs) ? ®s[*pos] : NULL; | 145 | return *pos < ARRAY_SIZE(regs) ? (void *)®s[*pos] : NULL; |
146 | } | 146 | } |
147 | 147 | ||
148 | static void reg_stop(struct seq_file *seq, void *p) | 148 | static void reg_stop(struct seq_file *seq, void *p) |
@@ -153,7 +153,7 @@ static void reg_stop(struct seq_file *seq, void *p) | |||
153 | static void *reg_next(struct seq_file *seq, void *p, loff_t *pos) | 153 | static void *reg_next(struct seq_file *seq, void *p, loff_t *pos) |
154 | { | 154 | { |
155 | ++*pos; | 155 | ++*pos; |
156 | return *pos < ARRAY_SIZE(regs) ? ®s[*pos] : NULL; | 156 | return *pos < ARRAY_SIZE(regs) ? (void *)®s[*pos] : NULL; |
157 | } | 157 | } |
158 | 158 | ||
159 | static int reg_show(struct seq_file *seq, void *p) | 159 | static int reg_show(struct seq_file *seq, void *p) |
@@ -290,7 +290,7 @@ static const struct file_operations fops_reset = { | |||
290 | 290 | ||
291 | /* debugfs: debug level */ | 291 | /* debugfs: debug level */ |
292 | 292 | ||
293 | static struct { | 293 | static const struct { |
294 | enum ath5k_debug_level level; | 294 | enum ath5k_debug_level level; |
295 | const char *name; | 295 | const char *name; |
296 | const char *desc; | 296 | const char *desc; |
diff --git a/drivers/net/wireless/ath5k/eeprom.c b/drivers/net/wireless/ath5k/eeprom.c index a54ee7e4967b..ac45ca47ca87 100644 --- a/drivers/net/wireless/ath5k/eeprom.c +++ b/drivers/net/wireless/ath5k/eeprom.c | |||
@@ -1418,14 +1418,11 @@ ath5k_eeprom_init(struct ath5k_hw *ah) | |||
1418 | */ | 1418 | */ |
1419 | int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) | 1419 | int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) |
1420 | { | 1420 | { |
1421 | u8 mac_d[ETH_ALEN]; | 1421 | u8 mac_d[ETH_ALEN] = {}; |
1422 | u32 total, offset; | 1422 | u32 total, offset; |
1423 | u16 data; | 1423 | u16 data; |
1424 | int octet, ret; | 1424 | int octet, ret; |
1425 | 1425 | ||
1426 | memset(mac, 0, ETH_ALEN); | ||
1427 | memset(mac_d, 0, ETH_ALEN); | ||
1428 | |||
1429 | ret = ath5k_hw_eeprom_read(ah, 0x20, &data); | 1426 | ret = ath5k_hw_eeprom_read(ah, 0x20, &data); |
1430 | if (ret) | 1427 | if (ret) |
1431 | return ret; | 1428 | return ret; |
@@ -1441,11 +1438,11 @@ int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) | |||
1441 | octet += 2; | 1438 | octet += 2; |
1442 | } | 1439 | } |
1443 | 1440 | ||
1444 | memcpy(mac, mac_d, ETH_ALEN); | ||
1445 | |||
1446 | if (!total || total == 3 * 0xffff) | 1441 | if (!total || total == 3 * 0xffff) |
1447 | return -EINVAL; | 1442 | return -EINVAL; |
1448 | 1443 | ||
1444 | memcpy(mac, mac_d, ETH_ALEN); | ||
1445 | |||
1449 | return 0; | 1446 | return 0; |
1450 | } | 1447 | } |
1451 | 1448 | ||
diff --git a/drivers/net/wireless/ath5k/led.c b/drivers/net/wireless/ath5k/led.c new file mode 100644 index 000000000000..0686e12738b3 --- /dev/null +++ b/drivers/net/wireless/ath5k/led.c | |||
@@ -0,0 +1,174 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting | ||
3 | * Copyright (c) 2004-2005 Atheros Communications, Inc. | ||
4 | * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com> | ||
5 | * Copyright (c) 2009 Bob Copeland <me@bobcopeland.com> | ||
6 | * | ||
7 | * All rights reserved. | ||
8 | * | ||
9 | * Redistribution and use in source and binary forms, with or without | ||
10 | * modification, are permitted provided that the following conditions | ||
11 | * are met: | ||
12 | * 1. Redistributions of source code must retain the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer, | ||
14 | * without modification. | ||
15 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
16 | * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any | ||
17 | * redistribution must be conditioned upon including a substantially | ||
18 | * similar Disclaimer requirement for further binary redistribution. | ||
19 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
20 | * of any contributors may be used to endorse or promote products derived | ||
21 | * from this software without specific prior written permission. | ||
22 | * | ||
23 | * Alternatively, this software may be distributed under the terms of the | ||
24 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
25 | * Software Foundation. | ||
26 | * | ||
27 | * NO WARRANTY | ||
28 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
29 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
30 | * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY | ||
31 | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL | ||
32 | * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, | ||
33 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
34 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
35 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER | ||
36 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
37 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||
38 | * THE POSSIBILITY OF SUCH DAMAGES. | ||
39 | * | ||
40 | */ | ||
41 | |||
42 | #include <linux/pci.h> | ||
43 | #include "ath5k.h" | ||
44 | #include "base.h" | ||
45 | |||
46 | #define ATH_SDEVICE(subv,subd) \ | ||
47 | .vendor = PCI_ANY_ID, .device = PCI_ANY_ID, \ | ||
48 | .subvendor = (subv), .subdevice = (subd) | ||
49 | |||
50 | #define ATH_LED(pin,polarity) .driver_data = (((pin) << 8) | (polarity)) | ||
51 | #define ATH_PIN(data) ((data) >> 8) | ||
52 | #define ATH_POLARITY(data) ((data) & 0xff) | ||
53 | |||
54 | /* Devices we match on for LED config info (typically laptops) */ | ||
55 | static const struct pci_device_id ath5k_led_devices[] = { | ||
56 | /* IBM-specific AR5212 */ | ||
57 | { PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5212_IBM), ATH_LED(0, 0) }, | ||
58 | /* AR5211 */ | ||
59 | { PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5211), ATH_LED(0, 0) }, | ||
60 | /* HP Compaq nc6xx, nc4000, nx6000 */ | ||
61 | { ATH_SDEVICE(PCI_VENDOR_ID_COMPAQ, PCI_ANY_ID), ATH_LED(1, 1) }, | ||
62 | /* Acer Aspire One A150 (maximlevitsky@gmail.com) */ | ||
63 | { ATH_SDEVICE(PCI_VENDOR_ID_FOXCONN, 0xe008), ATH_LED(3, 0) }, | ||
64 | /* Acer Ferrari 5000 (russ.dill@gmail.com) */ | ||
65 | { ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, 0x0422), ATH_LED(1, 1) }, | ||
66 | /* E-machines E510 (tuliom@gmail.com) */ | ||
67 | { ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, 0x0428), ATH_LED(3, 0) }, | ||
68 | { } | ||
69 | }; | ||
70 | |||
71 | void ath5k_led_enable(struct ath5k_softc *sc) | ||
72 | { | ||
73 | if (test_bit(ATH_STAT_LEDSOFT, sc->status)) { | ||
74 | ath5k_hw_set_gpio_output(sc->ah, sc->led_pin); | ||
75 | ath5k_led_off(sc); | ||
76 | } | ||
77 | } | ||
78 | |||
79 | void ath5k_led_on(struct ath5k_softc *sc) | ||
80 | { | ||
81 | if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) | ||
82 | return; | ||
83 | ath5k_hw_set_gpio(sc->ah, sc->led_pin, sc->led_on); | ||
84 | } | ||
85 | |||
86 | void ath5k_led_off(struct ath5k_softc *sc) | ||
87 | { | ||
88 | if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) | ||
89 | return; | ||
90 | ath5k_hw_set_gpio(sc->ah, sc->led_pin, !sc->led_on); | ||
91 | } | ||
92 | |||
93 | static void | ||
94 | ath5k_led_brightness_set(struct led_classdev *led_dev, | ||
95 | enum led_brightness brightness) | ||
96 | { | ||
97 | struct ath5k_led *led = container_of(led_dev, struct ath5k_led, | ||
98 | led_dev); | ||
99 | |||
100 | if (brightness == LED_OFF) | ||
101 | ath5k_led_off(led->sc); | ||
102 | else | ||
103 | ath5k_led_on(led->sc); | ||
104 | } | ||
105 | |||
106 | static int | ||
107 | ath5k_register_led(struct ath5k_softc *sc, struct ath5k_led *led, | ||
108 | const char *name, char *trigger) | ||
109 | { | ||
110 | int err; | ||
111 | |||
112 | led->sc = sc; | ||
113 | strncpy(led->name, name, sizeof(led->name)); | ||
114 | led->led_dev.name = led->name; | ||
115 | led->led_dev.default_trigger = trigger; | ||
116 | led->led_dev.brightness_set = ath5k_led_brightness_set; | ||
117 | |||
118 | err = led_classdev_register(&sc->pdev->dev, &led->led_dev); | ||
119 | if (err) { | ||
120 | ATH5K_WARN(sc, "could not register LED %s\n", name); | ||
121 | led->sc = NULL; | ||
122 | } | ||
123 | return err; | ||
124 | } | ||
125 | |||
126 | static void | ||
127 | ath5k_unregister_led(struct ath5k_led *led) | ||
128 | { | ||
129 | if (!led->sc) | ||
130 | return; | ||
131 | led_classdev_unregister(&led->led_dev); | ||
132 | ath5k_led_off(led->sc); | ||
133 | led->sc = NULL; | ||
134 | } | ||
135 | |||
136 | void ath5k_unregister_leds(struct ath5k_softc *sc) | ||
137 | { | ||
138 | ath5k_unregister_led(&sc->rx_led); | ||
139 | ath5k_unregister_led(&sc->tx_led); | ||
140 | } | ||
141 | |||
142 | int ath5k_init_leds(struct ath5k_softc *sc) | ||
143 | { | ||
144 | int ret = 0; | ||
145 | struct ieee80211_hw *hw = sc->hw; | ||
146 | struct pci_dev *pdev = sc->pdev; | ||
147 | char name[ATH5K_LED_MAX_NAME_LEN + 1]; | ||
148 | const struct pci_device_id *match; | ||
149 | |||
150 | match = pci_match_id(&ath5k_led_devices[0], pdev); | ||
151 | if (match) { | ||
152 | __set_bit(ATH_STAT_LEDSOFT, sc->status); | ||
153 | sc->led_pin = ATH_PIN(match->driver_data); | ||
154 | sc->led_on = ATH_POLARITY(match->driver_data); | ||
155 | } | ||
156 | |||
157 | if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) | ||
158 | goto out; | ||
159 | |||
160 | ath5k_led_enable(sc); | ||
161 | |||
162 | snprintf(name, sizeof(name), "ath5k-%s::rx", wiphy_name(hw->wiphy)); | ||
163 | ret = ath5k_register_led(sc, &sc->rx_led, name, | ||
164 | ieee80211_get_rx_led_name(hw)); | ||
165 | if (ret) | ||
166 | goto out; | ||
167 | |||
168 | snprintf(name, sizeof(name), "ath5k-%s::tx", wiphy_name(hw->wiphy)); | ||
169 | ret = ath5k_register_led(sc, &sc->tx_led, name, | ||
170 | ieee80211_get_tx_led_name(hw)); | ||
171 | out: | ||
172 | return ret; | ||
173 | } | ||
174 | |||
diff --git a/drivers/net/wireless/ath5k/reset.c b/drivers/net/wireless/ath5k/reset.c index 1531ccd35066..685dc213edae 100644 --- a/drivers/net/wireless/ath5k/reset.c +++ b/drivers/net/wireless/ath5k/reset.c | |||
@@ -102,7 +102,7 @@ static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah, | |||
102 | * index into rates for control rates, we can set it up like this because | 102 | * index into rates for control rates, we can set it up like this because |
103 | * this is only used for AR5212 and we know it supports G mode | 103 | * this is only used for AR5212 and we know it supports G mode |
104 | */ | 104 | */ |
105 | static int control_rates[] = | 105 | static const unsigned int control_rates[] = |
106 | { 0, 1, 1, 1, 4, 4, 6, 6, 8, 8, 8, 8 }; | 106 | { 0, 1, 1, 1, 4, 4, 6, 6, 8, 8, 8, 8 }; |
107 | 107 | ||
108 | /** | 108 | /** |
diff --git a/drivers/net/wireless/ath9k/ahb.c b/drivers/net/wireless/ath9k/ahb.c index bc562bd88890..00cc7bb01f2e 100644 --- a/drivers/net/wireless/ath9k/ahb.c +++ b/drivers/net/wireless/ath9k/ahb.c | |||
@@ -60,6 +60,7 @@ static struct ath_bus_ops ath_ahb_bus_ops = { | |||
60 | static int ath_ahb_probe(struct platform_device *pdev) | 60 | static int ath_ahb_probe(struct platform_device *pdev) |
61 | { | 61 | { |
62 | void __iomem *mem; | 62 | void __iomem *mem; |
63 | struct ath_wiphy *aphy; | ||
63 | struct ath_softc *sc; | 64 | struct ath_softc *sc; |
64 | struct ieee80211_hw *hw; | 65 | struct ieee80211_hw *hw; |
65 | struct resource *res; | 66 | struct resource *res; |
diff --git a/drivers/net/wireless/ath9k/calib.c b/drivers/net/wireless/ath9k/calib.c index 1c074c059b5c..c9446fb6b153 100644 --- a/drivers/net/wireless/ath9k/calib.c +++ b/drivers/net/wireless/ath9k/calib.c | |||
@@ -745,43 +745,6 @@ static void ath9k_olc_temp_compensation(struct ath_hw *ah) | |||
745 | } | 745 | } |
746 | } | 746 | } |
747 | 747 | ||
748 | bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, | ||
749 | u8 rxchainmask, bool longcal, | ||
750 | bool *isCalDone) | ||
751 | { | ||
752 | struct hal_cal_list *currCal = ah->cal_list_curr; | ||
753 | |||
754 | *isCalDone = true; | ||
755 | |||
756 | if (currCal && | ||
757 | (currCal->calState == CAL_RUNNING || | ||
758 | currCal->calState == CAL_WAITING)) { | ||
759 | ath9k_hw_per_calibration(ah, chan, rxchainmask, currCal, | ||
760 | isCalDone); | ||
761 | if (*isCalDone) { | ||
762 | ah->cal_list_curr = currCal = currCal->calNext; | ||
763 | |||
764 | if (currCal->calState == CAL_WAITING) { | ||
765 | *isCalDone = false; | ||
766 | ath9k_hw_reset_calibration(ah, currCal); | ||
767 | } | ||
768 | } | ||
769 | } | ||
770 | |||
771 | if (longcal) { | ||
772 | if (OLC_FOR_AR9280_20_LATER) | ||
773 | ath9k_olc_temp_compensation(ah); | ||
774 | ath9k_hw_getnf(ah, chan); | ||
775 | ath9k_hw_loadnf(ah, ah->curchan); | ||
776 | ath9k_hw_start_nfcal(ah); | ||
777 | |||
778 | if (chan->channelFlags & CHANNEL_CW_INT) | ||
779 | chan->channelFlags &= ~CHANNEL_CW_INT; | ||
780 | } | ||
781 | |||
782 | return true; | ||
783 | } | ||
784 | |||
785 | static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah) | 748 | static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah) |
786 | { | 749 | { |
787 | 750 | ||
@@ -877,22 +840,104 @@ static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah) | |||
877 | 840 | ||
878 | } | 841 | } |
879 | 842 | ||
843 | bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, | ||
844 | u8 rxchainmask, bool longcal, | ||
845 | bool *isCalDone) | ||
846 | { | ||
847 | struct hal_cal_list *currCal = ah->cal_list_curr; | ||
848 | |||
849 | *isCalDone = true; | ||
850 | |||
851 | if (currCal && | ||
852 | (currCal->calState == CAL_RUNNING || | ||
853 | currCal->calState == CAL_WAITING)) { | ||
854 | ath9k_hw_per_calibration(ah, chan, rxchainmask, currCal, | ||
855 | isCalDone); | ||
856 | if (*isCalDone) { | ||
857 | ah->cal_list_curr = currCal = currCal->calNext; | ||
858 | |||
859 | if (currCal->calState == CAL_WAITING) { | ||
860 | *isCalDone = false; | ||
861 | ath9k_hw_reset_calibration(ah, currCal); | ||
862 | } | ||
863 | } | ||
864 | } | ||
865 | |||
866 | if (longcal) { | ||
867 | if (AR_SREV_9285(ah) && AR_SREV_9285_11_OR_LATER(ah)) | ||
868 | ath9k_hw_9285_pa_cal(ah); | ||
869 | |||
870 | if (OLC_FOR_AR9280_20_LATER) | ||
871 | ath9k_olc_temp_compensation(ah); | ||
872 | ath9k_hw_getnf(ah, chan); | ||
873 | ath9k_hw_loadnf(ah, ah->curchan); | ||
874 | ath9k_hw_start_nfcal(ah); | ||
875 | |||
876 | if (chan->channelFlags & CHANNEL_CW_INT) | ||
877 | chan->channelFlags &= ~CHANNEL_CW_INT; | ||
878 | } | ||
879 | |||
880 | return true; | ||
881 | } | ||
882 | |||
883 | static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan) | ||
884 | { | ||
885 | REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); | ||
886 | if (chan->channelFlags & CHANNEL_HT20) { | ||
887 | REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); | ||
888 | REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); | ||
889 | REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, | ||
890 | AR_PHY_AGC_CONTROL_FLTR_CAL); | ||
891 | REG_CLR_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE); | ||
892 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); | ||
893 | if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, | ||
894 | AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) { | ||
895 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "offset " | ||
896 | "calibration failed to complete in " | ||
897 | "1ms; noisy ??\n"); | ||
898 | return false; | ||
899 | } | ||
900 | REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); | ||
901 | REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); | ||
902 | REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); | ||
903 | } | ||
904 | REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); | ||
905 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); | ||
906 | REG_SET_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE); | ||
907 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); | ||
908 | if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, | ||
909 | 0, AH_WAIT_TIMEOUT)) { | ||
910 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "offset calibration " | ||
911 | "failed to complete in 1ms; noisy ??\n"); | ||
912 | return false; | ||
913 | } | ||
914 | |||
915 | REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); | ||
916 | REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); | ||
917 | REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); | ||
918 | |||
919 | return true; | ||
920 | } | ||
921 | |||
880 | bool ath9k_hw_init_cal(struct ath_hw *ah, | 922 | bool ath9k_hw_init_cal(struct ath_hw *ah, |
881 | struct ath9k_channel *chan) | 923 | struct ath9k_channel *chan) |
882 | { | 924 | { |
883 | if (AR_SREV_9280_10_OR_LATER(ah)) { | 925 | if (AR_SREV_9285(ah) && AR_SREV_9285_12_OR_LATER(ah)) { |
926 | if (!ar9285_clc(ah, chan)) | ||
927 | return false; | ||
928 | } else if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
884 | REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); | 929 | REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); |
885 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); | 930 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); |
886 | REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); | 931 | REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); |
887 | 932 | ||
888 | /* Kick off the cal */ | 933 | /* Kick off the cal */ |
889 | REG_WRITE(ah, AR_PHY_AGC_CONTROL, | 934 | REG_WRITE(ah, AR_PHY_AGC_CONTROL, |
890 | REG_READ(ah, AR_PHY_AGC_CONTROL) | | 935 | REG_READ(ah, AR_PHY_AGC_CONTROL) | |
891 | AR_PHY_AGC_CONTROL_CAL); | 936 | AR_PHY_AGC_CONTROL_CAL); |
892 | 937 | ||
893 | if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, | 938 | if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, |
894 | AR_PHY_AGC_CONTROL_CAL, 0, | 939 | AR_PHY_AGC_CONTROL_CAL, 0, |
895 | AH_WAIT_TIMEOUT)) { | 940 | AH_WAIT_TIMEOUT)) { |
896 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 941 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, |
897 | "offset calibration failed to complete in 1ms; " | 942 | "offset calibration failed to complete in 1ms; " |
898 | "noisy environment?\n"); | 943 | "noisy environment?\n"); |
@@ -906,11 +951,11 @@ bool ath9k_hw_init_cal(struct ath_hw *ah, | |||
906 | 951 | ||
907 | /* Calibrate the AGC */ | 952 | /* Calibrate the AGC */ |
908 | REG_WRITE(ah, AR_PHY_AGC_CONTROL, | 953 | REG_WRITE(ah, AR_PHY_AGC_CONTROL, |
909 | REG_READ(ah, AR_PHY_AGC_CONTROL) | | 954 | REG_READ(ah, AR_PHY_AGC_CONTROL) | |
910 | AR_PHY_AGC_CONTROL_CAL); | 955 | AR_PHY_AGC_CONTROL_CAL); |
911 | 956 | ||
912 | if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, | 957 | if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, |
913 | 0, AH_WAIT_TIMEOUT)) { | 958 | 0, AH_WAIT_TIMEOUT)) { |
914 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 959 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, |
915 | "offset calibration failed to complete in 1ms; " | 960 | "offset calibration failed to complete in 1ms; " |
916 | "noisy environment?\n"); | 961 | "noisy environment?\n"); |
@@ -928,8 +973,8 @@ bool ath9k_hw_init_cal(struct ath_hw *ah, | |||
928 | 973 | ||
929 | /* Do NF Calibration */ | 974 | /* Do NF Calibration */ |
930 | REG_WRITE(ah, AR_PHY_AGC_CONTROL, | 975 | REG_WRITE(ah, AR_PHY_AGC_CONTROL, |
931 | REG_READ(ah, AR_PHY_AGC_CONTROL) | | 976 | REG_READ(ah, AR_PHY_AGC_CONTROL) | |
932 | AR_PHY_AGC_CONTROL_NF); | 977 | AR_PHY_AGC_CONTROL_NF); |
933 | 978 | ||
934 | ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; | 979 | ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; |
935 | 980 | ||
@@ -938,19 +983,19 @@ bool ath9k_hw_init_cal(struct ath_hw *ah, | |||
938 | INIT_CAL(&ah->adcgain_caldata); | 983 | INIT_CAL(&ah->adcgain_caldata); |
939 | INSERT_CAL(ah, &ah->adcgain_caldata); | 984 | INSERT_CAL(ah, &ah->adcgain_caldata); |
940 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 985 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, |
941 | "enabling ADC Gain Calibration.\n"); | 986 | "enabling ADC Gain Calibration.\n"); |
942 | } | 987 | } |
943 | if (ath9k_hw_iscal_supported(ah, ADC_DC_CAL)) { | 988 | if (ath9k_hw_iscal_supported(ah, ADC_DC_CAL)) { |
944 | INIT_CAL(&ah->adcdc_caldata); | 989 | INIT_CAL(&ah->adcdc_caldata); |
945 | INSERT_CAL(ah, &ah->adcdc_caldata); | 990 | INSERT_CAL(ah, &ah->adcdc_caldata); |
946 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 991 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, |
947 | "enabling ADC DC Calibration.\n"); | 992 | "enabling ADC DC Calibration.\n"); |
948 | } | 993 | } |
949 | if (ath9k_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) { | 994 | if (ath9k_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) { |
950 | INIT_CAL(&ah->iq_caldata); | 995 | INIT_CAL(&ah->iq_caldata); |
951 | INSERT_CAL(ah, &ah->iq_caldata); | 996 | INSERT_CAL(ah, &ah->iq_caldata); |
952 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 997 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, |
953 | "enabling IQ Calibration.\n"); | 998 | "enabling IQ Calibration.\n"); |
954 | } | 999 | } |
955 | 1000 | ||
956 | ah->cal_list_curr = ah->cal_list; | 1001 | ah->cal_list_curr = ah->cal_list; |
diff --git a/drivers/net/wireless/ath9k/debug.c b/drivers/net/wireless/ath9k/debug.c index 8d91422106d9..82573cadb1ab 100644 --- a/drivers/net/wireless/ath9k/debug.c +++ b/drivers/net/wireless/ath9k/debug.c | |||
@@ -14,11 +14,15 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <asm/unaligned.h> | ||
18 | |||
17 | #include "ath9k.h" | 19 | #include "ath9k.h" |
18 | 20 | ||
19 | static unsigned int ath9k_debug = DBG_DEFAULT; | 21 | static unsigned int ath9k_debug = DBG_DEFAULT; |
20 | module_param_named(debug, ath9k_debug, uint, 0); | 22 | module_param_named(debug, ath9k_debug, uint, 0); |
21 | 23 | ||
24 | static struct dentry *ath9k_debugfs_root; | ||
25 | |||
22 | void DPRINTF(struct ath_softc *sc, int dbg_mask, const char *fmt, ...) | 26 | void DPRINTF(struct ath_softc *sc, int dbg_mask, const char *fmt, ...) |
23 | { | 27 | { |
24 | if (!sc) | 28 | if (!sc) |
@@ -318,6 +322,9 @@ static ssize_t read_file_rcstat(struct file *file, char __user *user_buf, | |||
318 | { | 322 | { |
319 | struct ath_softc *sc = file->private_data; | 323 | struct ath_softc *sc = file->private_data; |
320 | 324 | ||
325 | if (sc->cur_rate_table == NULL) | ||
326 | return 0; | ||
327 | |||
321 | if (conf_is_ht(&sc->hw->conf)) | 328 | if (conf_is_ht(&sc->hw->conf)) |
322 | return ath_read_file_stat_11n_rc(file, user_buf, count, ppos); | 329 | return ath_read_file_stat_11n_rc(file, user_buf, count, ppos); |
323 | else | 330 | else |
@@ -491,12 +498,8 @@ int ath9k_init_debug(struct ath_softc *sc) | |||
491 | { | 498 | { |
492 | sc->debug.debug_mask = ath9k_debug; | 499 | sc->debug.debug_mask = ath9k_debug; |
493 | 500 | ||
494 | sc->debug.debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL); | ||
495 | if (!sc->debug.debugfs_root) | ||
496 | goto err; | ||
497 | |||
498 | sc->debug.debugfs_phy = debugfs_create_dir(wiphy_name(sc->hw->wiphy), | 501 | sc->debug.debugfs_phy = debugfs_create_dir(wiphy_name(sc->hw->wiphy), |
499 | sc->debug.debugfs_root); | 502 | ath9k_debugfs_root); |
500 | if (!sc->debug.debugfs_phy) | 503 | if (!sc->debug.debugfs_phy) |
501 | goto err; | 504 | goto err; |
502 | 505 | ||
@@ -538,5 +541,19 @@ void ath9k_exit_debug(struct ath_softc *sc) | |||
538 | debugfs_remove(sc->debug.debugfs_interrupt); | 541 | debugfs_remove(sc->debug.debugfs_interrupt); |
539 | debugfs_remove(sc->debug.debugfs_dma); | 542 | debugfs_remove(sc->debug.debugfs_dma); |
540 | debugfs_remove(sc->debug.debugfs_phy); | 543 | debugfs_remove(sc->debug.debugfs_phy); |
541 | debugfs_remove(sc->debug.debugfs_root); | 544 | } |
545 | |||
546 | int ath9k_debug_create_root(void) | ||
547 | { | ||
548 | ath9k_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL); | ||
549 | if (!ath9k_debugfs_root) | ||
550 | return -ENOENT; | ||
551 | |||
552 | return 0; | ||
553 | } | ||
554 | |||
555 | void ath9k_debug_remove_root(void) | ||
556 | { | ||
557 | debugfs_remove(ath9k_debugfs_root); | ||
558 | ath9k_debugfs_root = NULL; | ||
542 | } | 559 | } |
diff --git a/drivers/net/wireless/ath9k/debug.h b/drivers/net/wireless/ath9k/debug.h index 2a33d74fdbee..065268b8568f 100644 --- a/drivers/net/wireless/ath9k/debug.h +++ b/drivers/net/wireless/ath9k/debug.h | |||
@@ -102,7 +102,6 @@ struct ath_stats { | |||
102 | 102 | ||
103 | struct ath9k_debug { | 103 | struct ath9k_debug { |
104 | int debug_mask; | 104 | int debug_mask; |
105 | struct dentry *debugfs_root; | ||
106 | struct dentry *debugfs_phy; | 105 | struct dentry *debugfs_phy; |
107 | struct dentry *debugfs_dma; | 106 | struct dentry *debugfs_dma; |
108 | struct dentry *debugfs_interrupt; | 107 | struct dentry *debugfs_interrupt; |
@@ -114,6 +113,8 @@ struct ath9k_debug { | |||
114 | void DPRINTF(struct ath_softc *sc, int dbg_mask, const char *fmt, ...); | 113 | void DPRINTF(struct ath_softc *sc, int dbg_mask, const char *fmt, ...); |
115 | int ath9k_init_debug(struct ath_softc *sc); | 114 | int ath9k_init_debug(struct ath_softc *sc); |
116 | void ath9k_exit_debug(struct ath_softc *sc); | 115 | void ath9k_exit_debug(struct ath_softc *sc); |
116 | int ath9k_debug_create_root(void); | ||
117 | void ath9k_debug_remove_root(void); | ||
117 | void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); | 118 | void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); |
118 | void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb); | 119 | void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb); |
119 | void ath_debug_stat_retries(struct ath_softc *sc, int rix, | 120 | void ath_debug_stat_retries(struct ath_softc *sc, int rix, |
@@ -135,6 +136,15 @@ static inline void ath9k_exit_debug(struct ath_softc *sc) | |||
135 | { | 136 | { |
136 | } | 137 | } |
137 | 138 | ||
139 | static inline int ath9k_debug_create_root(void) | ||
140 | { | ||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | static inline void ath9k_debug_remove_root(void) | ||
145 | { | ||
146 | } | ||
147 | |||
138 | static inline void ath_debug_stat_interrupt(struct ath_softc *sc, | 148 | static inline void ath_debug_stat_interrupt(struct ath_softc *sc, |
139 | enum ath9k_int status) | 149 | enum ath9k_int status) |
140 | { | 150 | { |
diff --git a/drivers/net/wireless/ath9k/eeprom.c b/drivers/net/wireless/ath9k/eeprom.c index f935341bc5c4..183c949bcca1 100644 --- a/drivers/net/wireless/ath9k/eeprom.c +++ b/drivers/net/wireless/ath9k/eeprom.c | |||
@@ -640,7 +640,7 @@ static void ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hw *ah, | |||
640 | pPdGainBoundaries[i] = | 640 | pPdGainBoundaries[i] = |
641 | min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]); | 641 | min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]); |
642 | 642 | ||
643 | if ((i == 0) && !AR_SREV_5416_V20_OR_LATER(ah)) { | 643 | if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) { |
644 | minDelta = pPdGainBoundaries[0] - 23; | 644 | minDelta = pPdGainBoundaries[0] - 23; |
645 | pPdGainBoundaries[0] = 23; | 645 | pPdGainBoundaries[0] = 23; |
646 | } else { | 646 | } else { |
@@ -679,7 +679,7 @@ static void ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hw *ah, | |||
679 | vpdTableI[i][sizeCurrVpdTable - 2]); | 679 | vpdTableI[i][sizeCurrVpdTable - 2]); |
680 | vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); | 680 | vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); |
681 | 681 | ||
682 | if (tgtIndex > maxIndex) { | 682 | if (tgtIndex >= maxIndex) { |
683 | while ((ss <= tgtIndex) && | 683 | while ((ss <= tgtIndex) && |
684 | (k < (AR5416_NUM_PDADC_VALUES - 1))) { | 684 | (k < (AR5416_NUM_PDADC_VALUES - 1))) { |
685 | tmpVal = (int16_t) TMP_VAL_VPD_TABLE; | 685 | tmpVal = (int16_t) TMP_VAL_VPD_TABLE; |
@@ -713,11 +713,11 @@ static bool ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, | |||
713 | u8 *pCalBChans = NULL; | 713 | u8 *pCalBChans = NULL; |
714 | u16 pdGainOverlap_t2; | 714 | u16 pdGainOverlap_t2; |
715 | static u8 pdadcValues[AR5416_NUM_PDADC_VALUES]; | 715 | static u8 pdadcValues[AR5416_NUM_PDADC_VALUES]; |
716 | u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK]; | 716 | u16 gainBoundaries[AR5416_EEP4K_PD_GAINS_IN_MASK]; |
717 | u16 numPiers, i, j; | 717 | u16 numPiers, i, j; |
718 | int16_t tMinCalPower; | 718 | int16_t tMinCalPower; |
719 | u16 numXpdGain, xpdMask; | 719 | u16 numXpdGain, xpdMask; |
720 | u16 xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 }; | 720 | u16 xpdGainValues[AR5416_EEP4K_NUM_PD_GAINS] = { 0, 0 }; |
721 | u32 reg32, regOffset, regChainOffset; | 721 | u32 reg32, regOffset, regChainOffset; |
722 | 722 | ||
723 | xpdMask = pEepData->modalHeader.xpdGain; | 723 | xpdMask = pEepData->modalHeader.xpdGain; |
@@ -732,16 +732,16 @@ static bool ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, | |||
732 | } | 732 | } |
733 | 733 | ||
734 | pCalBChans = pEepData->calFreqPier2G; | 734 | pCalBChans = pEepData->calFreqPier2G; |
735 | numPiers = AR5416_NUM_2G_CAL_PIERS; | 735 | numPiers = AR5416_EEP4K_NUM_2G_CAL_PIERS; |
736 | 736 | ||
737 | numXpdGain = 0; | 737 | numXpdGain = 0; |
738 | 738 | ||
739 | for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) { | 739 | for (i = 1; i <= AR5416_EEP4K_PD_GAINS_IN_MASK; i++) { |
740 | if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) { | 740 | if ((xpdMask >> (AR5416_EEP4K_PD_GAINS_IN_MASK - i)) & 1) { |
741 | if (numXpdGain >= AR5416_NUM_PD_GAINS) | 741 | if (numXpdGain >= AR5416_EEP4K_NUM_PD_GAINS) |
742 | break; | 742 | break; |
743 | xpdGainValues[numXpdGain] = | 743 | xpdGainValues[numXpdGain] = |
744 | (u16)(AR5416_PD_GAINS_IN_MASK - i); | 744 | (u16)(AR5416_EEP4K_PD_GAINS_IN_MASK - i); |
745 | numXpdGain++; | 745 | numXpdGain++; |
746 | } | 746 | } |
747 | } | 747 | } |
@@ -754,8 +754,8 @@ static bool ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, | |||
754 | xpdGainValues[1]); | 754 | xpdGainValues[1]); |
755 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, 0); | 755 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, 0); |
756 | 756 | ||
757 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { | 757 | for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) { |
758 | if (AR_SREV_5416_V20_OR_LATER(ah) && | 758 | if (AR_SREV_5416_20_OR_LATER(ah) && |
759 | (ah->rxchainmask == 5 || ah->txchainmask == 5) && | 759 | (ah->rxchainmask == 5 || ah->txchainmask == 5) && |
760 | (i != 0)) { | 760 | (i != 0)) { |
761 | regChainOffset = (i == 1) ? 0x2000 : 0x1000; | 761 | regChainOffset = (i == 1) ? 0x2000 : 0x1000; |
@@ -771,7 +771,7 @@ static bool ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, | |||
771 | &tMinCalPower, gainBoundaries, | 771 | &tMinCalPower, gainBoundaries, |
772 | pdadcValues, numXpdGain); | 772 | pdadcValues, numXpdGain); |
773 | 773 | ||
774 | if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) { | 774 | if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) { |
775 | REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset, | 775 | REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset, |
776 | SM(pdGainOverlap_t2, | 776 | SM(pdGainOverlap_t2, |
777 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | 777 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
@@ -1707,7 +1707,7 @@ static bool ath9k_hw_def_set_board_values(struct ath_hw *ah, | |||
1707 | break; | 1707 | break; |
1708 | } | 1708 | } |
1709 | 1709 | ||
1710 | if (AR_SREV_5416_V20_OR_LATER(ah) && | 1710 | if (AR_SREV_5416_20_OR_LATER(ah) && |
1711 | (ah->rxchainmask == 5 || ah->txchainmask == 5) | 1711 | (ah->rxchainmask == 5 || ah->txchainmask == 5) |
1712 | && (i != 0)) | 1712 | && (i != 0)) |
1713 | regChainOffset = (i == 1) ? 0x2000 : 0x1000; | 1713 | regChainOffset = (i == 1) ? 0x2000 : 0x1000; |
@@ -1728,7 +1728,7 @@ static bool ath9k_hw_def_set_board_values(struct ath_hw *ah, | |||
1728 | SM(pModal->iqCalQCh[i], | 1728 | SM(pModal->iqCalQCh[i], |
1729 | AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); | 1729 | AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); |
1730 | 1730 | ||
1731 | if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) { | 1731 | if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) { |
1732 | if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) { | 1732 | if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) { |
1733 | txRxAttenLocal = pModal->txRxAttenCh[i]; | 1733 | txRxAttenLocal = pModal->txRxAttenCh[i]; |
1734 | if (AR_SREV_9280_10_OR_LATER(ah)) { | 1734 | if (AR_SREV_9280_10_OR_LATER(ah)) { |
@@ -2094,7 +2094,7 @@ static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hw *ah, | |||
2094 | pPdGainBoundaries[i] = | 2094 | pPdGainBoundaries[i] = |
2095 | min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]); | 2095 | min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]); |
2096 | 2096 | ||
2097 | if ((i == 0) && !AR_SREV_5416_V20_OR_LATER(ah)) { | 2097 | if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) { |
2098 | minDelta = pPdGainBoundaries[0] - 23; | 2098 | minDelta = pPdGainBoundaries[0] - 23; |
2099 | pPdGainBoundaries[0] = 23; | 2099 | pPdGainBoundaries[0] = 23; |
2100 | } else { | 2100 | } else { |
@@ -2228,7 +2228,7 @@ static bool ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, | |||
2228 | xpdGainValues[2]); | 2228 | xpdGainValues[2]); |
2229 | 2229 | ||
2230 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { | 2230 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { |
2231 | if (AR_SREV_5416_V20_OR_LATER(ah) && | 2231 | if (AR_SREV_5416_20_OR_LATER(ah) && |
2232 | (ah->rxchainmask == 5 || ah->txchainmask == 5) && | 2232 | (ah->rxchainmask == 5 || ah->txchainmask == 5) && |
2233 | (i != 0)) { | 2233 | (i != 0)) { |
2234 | regChainOffset = (i == 1) ? 0x2000 : 0x1000; | 2234 | regChainOffset = (i == 1) ? 0x2000 : 0x1000; |
@@ -2262,7 +2262,7 @@ static bool ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, | |||
2262 | numXpdGain); | 2262 | numXpdGain); |
2263 | } | 2263 | } |
2264 | 2264 | ||
2265 | if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) { | 2265 | if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) { |
2266 | if (OLC_FOR_AR9280_20_LATER) { | 2266 | if (OLC_FOR_AR9280_20_LATER) { |
2267 | REG_WRITE(ah, | 2267 | REG_WRITE(ah, |
2268 | AR_PHY_TPCRG5 + regChainOffset, | 2268 | AR_PHY_TPCRG5 + regChainOffset, |
diff --git a/drivers/net/wireless/ath9k/eeprom.h b/drivers/net/wireless/ath9k/eeprom.h index 6296e3eff10b..d6f6108f63c7 100644 --- a/drivers/net/wireless/ath9k/eeprom.h +++ b/drivers/net/wireless/ath9k/eeprom.h | |||
@@ -261,7 +261,7 @@ struct base_eep_header_4k { | |||
261 | u16 deviceCap; | 261 | u16 deviceCap; |
262 | u32 binBuildNumber; | 262 | u32 binBuildNumber; |
263 | u8 deviceType; | 263 | u8 deviceType; |
264 | u8 futureBase[1]; | 264 | u8 txGainType; |
265 | } __packed; | 265 | } __packed; |
266 | 266 | ||
267 | 267 | ||
diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index 60e55d8c510b..d494e98ba971 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c | |||
@@ -682,22 +682,16 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, | |||
682 | ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL; | 682 | ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL; |
683 | } | 683 | } |
684 | 684 | ||
685 | if (AR_SREV_9160(ah)) { | 685 | ah->ani_function = ATH9K_ANI_ALL; |
686 | ah->config.enable_ani = 1; | 686 | if (AR_SREV_9280_10_OR_LATER(ah)) |
687 | ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL | | 687 | ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL; |
688 | ATH9K_ANI_FIRSTEP_LEVEL); | ||
689 | } else { | ||
690 | ah->ani_function = ATH9K_ANI_ALL; | ||
691 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
692 | ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL; | ||
693 | } | ||
694 | } | ||
695 | 688 | ||
696 | DPRINTF(sc, ATH_DBG_RESET, | 689 | DPRINTF(sc, ATH_DBG_RESET, |
697 | "This Mac Chip Rev 0x%02x.%x is \n", | 690 | "This Mac Chip Rev 0x%02x.%x is \n", |
698 | ah->hw_version.macVersion, ah->hw_version.macRev); | 691 | ah->hw_version.macVersion, ah->hw_version.macRev); |
699 | 692 | ||
700 | if (AR_SREV_9285_12_OR_LATER(ah)) { | 693 | if (AR_SREV_9285_12_OR_LATER(ah)) { |
694 | |||
701 | INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2, | 695 | INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2, |
702 | ARRAY_SIZE(ar9285Modes_9285_1_2), 6); | 696 | ARRAY_SIZE(ar9285Modes_9285_1_2), 6); |
703 | INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285_1_2, | 697 | INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285_1_2, |
@@ -837,6 +831,22 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, | |||
837 | if (ecode != 0) | 831 | if (ecode != 0) |
838 | goto bad; | 832 | goto bad; |
839 | 833 | ||
834 | if (AR_SREV_9285_12_OR_LATER(ah)) { | ||
835 | u32 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE); | ||
836 | |||
837 | /* txgain table */ | ||
838 | if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) { | ||
839 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
840 | ar9285Modes_high_power_tx_gain_9285_1_2, | ||
841 | ARRAY_SIZE(ar9285Modes_high_power_tx_gain_9285_1_2), 6); | ||
842 | } else { | ||
843 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
844 | ar9285Modes_original_tx_gain_9285_1_2, | ||
845 | ARRAY_SIZE(ar9285Modes_original_tx_gain_9285_1_2), 6); | ||
846 | } | ||
847 | |||
848 | } | ||
849 | |||
840 | /* rxgain table */ | 850 | /* rxgain table */ |
841 | if (AR_SREV_9280_20(ah)) | 851 | if (AR_SREV_9280_20(ah)) |
842 | ath9k_hw_init_rxgain_ini(ah); | 852 | ath9k_hw_init_rxgain_ini(ah); |
@@ -1173,7 +1183,7 @@ static void ath9k_hw_override_ini(struct ath_hw *ah, | |||
1173 | REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); | 1183 | REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); |
1174 | 1184 | ||
1175 | 1185 | ||
1176 | if (!AR_SREV_5416_V20_OR_LATER(ah) || | 1186 | if (!AR_SREV_5416_20_OR_LATER(ah) || |
1177 | AR_SREV_9280_10_OR_LATER(ah)) | 1187 | AR_SREV_9280_10_OR_LATER(ah)) |
1178 | return; | 1188 | return; |
1179 | 1189 | ||
@@ -1275,7 +1285,7 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, | |||
1275 | REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO); | 1285 | REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO); |
1276 | ah->eep_ops->set_addac(ah, chan); | 1286 | ah->eep_ops->set_addac(ah, chan); |
1277 | 1287 | ||
1278 | if (AR_SREV_5416_V22_OR_LATER(ah)) { | 1288 | if (AR_SREV_5416_22_OR_LATER(ah)) { |
1279 | REG_WRITE_ARRAY(&ah->iniAddac, 1, regWrites); | 1289 | REG_WRITE_ARRAY(&ah->iniAddac, 1, regWrites); |
1280 | } else { | 1290 | } else { |
1281 | struct ar5416IniArray temp; | 1291 | struct ar5416IniArray temp; |
@@ -1313,7 +1323,8 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, | |||
1313 | if (AR_SREV_9280(ah)) | 1323 | if (AR_SREV_9280(ah)) |
1314 | REG_WRITE_ARRAY(&ah->iniModesRxGain, modesIndex, regWrites); | 1324 | REG_WRITE_ARRAY(&ah->iniModesRxGain, modesIndex, regWrites); |
1315 | 1325 | ||
1316 | if (AR_SREV_9280(ah)) | 1326 | if (AR_SREV_9280(ah) || (AR_SREV_9285(ah) && |
1327 | AR_SREV_9285_12_OR_LATER(ah))) | ||
1317 | REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites); | 1328 | REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites); |
1318 | 1329 | ||
1319 | for (i = 0; i < ah->iniCommon.ia_rows; i++) { | 1330 | for (i = 0; i < ah->iniCommon.ia_rows; i++) { |
diff --git a/drivers/net/wireless/ath9k/initvals.h b/drivers/net/wireless/ath9k/initvals.h index d49236368a1c..1d60c3706f1c 100644 --- a/drivers/net/wireless/ath9k/initvals.h +++ b/drivers/net/wireless/ath9k/initvals.h | |||
@@ -14,7 +14,7 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | static const u32 ar5416Modes_9100[][6] = { | 17 | static const u32 ar5416Modes[][6] = { |
18 | { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, | 18 | { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, |
19 | { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, | 19 | { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, |
20 | { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, | 20 | { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, |
@@ -78,7 +78,7 @@ static const u32 ar5416Modes_9100[][6] = { | |||
78 | { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | 78 | { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, |
79 | }; | 79 | }; |
80 | 80 | ||
81 | static const u32 ar5416Common_9100[][2] = { | 81 | static const u32 ar5416Common[][2] = { |
82 | { 0x0000000c, 0x00000000 }, | 82 | { 0x0000000c, 0x00000000 }, |
83 | { 0x00000030, 0x00020015 }, | 83 | { 0x00000030, 0x00020015 }, |
84 | { 0x00000034, 0x00000005 }, | 84 | { 0x00000034, 0x00000005 }, |
@@ -456,12 +456,12 @@ static const u32 ar5416Common_9100[][2] = { | |||
456 | { 0x0000a3e0, 0x000001ce }, | 456 | { 0x0000a3e0, 0x000001ce }, |
457 | }; | 457 | }; |
458 | 458 | ||
459 | static const u32 ar5416Bank0_9100[][2] = { | 459 | static const u32 ar5416Bank0[][2] = { |
460 | { 0x000098b0, 0x1e5795e5 }, | 460 | { 0x000098b0, 0x1e5795e5 }, |
461 | { 0x000098e0, 0x02008020 }, | 461 | { 0x000098e0, 0x02008020 }, |
462 | }; | 462 | }; |
463 | 463 | ||
464 | static const u32 ar5416BB_RfGain_9100[][3] = { | 464 | static const u32 ar5416BB_RfGain[][3] = { |
465 | { 0x00009a00, 0x00000000, 0x00000000 }, | 465 | { 0x00009a00, 0x00000000, 0x00000000 }, |
466 | { 0x00009a04, 0x00000040, 0x00000040 }, | 466 | { 0x00009a04, 0x00000040, 0x00000040 }, |
467 | { 0x00009a08, 0x00000080, 0x00000080 }, | 467 | { 0x00009a08, 0x00000080, 0x00000080 }, |
@@ -528,21 +528,21 @@ static const u32 ar5416BB_RfGain_9100[][3] = { | |||
528 | { 0x00009afc, 0x000000f9, 0x000000f9 }, | 528 | { 0x00009afc, 0x000000f9, 0x000000f9 }, |
529 | }; | 529 | }; |
530 | 530 | ||
531 | static const u32 ar5416Bank1_9100[][2] = { | 531 | static const u32 ar5416Bank1[][2] = { |
532 | { 0x000098b0, 0x02108421 }, | 532 | { 0x000098b0, 0x02108421 }, |
533 | { 0x000098ec, 0x00000008 }, | 533 | { 0x000098ec, 0x00000008 }, |
534 | }; | 534 | }; |
535 | 535 | ||
536 | static const u32 ar5416Bank2_9100[][2] = { | 536 | static const u32 ar5416Bank2[][2] = { |
537 | { 0x000098b0, 0x0e73ff17 }, | 537 | { 0x000098b0, 0x0e73ff17 }, |
538 | { 0x000098e0, 0x00000420 }, | 538 | { 0x000098e0, 0x00000420 }, |
539 | }; | 539 | }; |
540 | 540 | ||
541 | static const u32 ar5416Bank3_9100[][3] = { | 541 | static const u32 ar5416Bank3[][3] = { |
542 | { 0x000098f0, 0x01400018, 0x01c00018 }, | 542 | { 0x000098f0, 0x01400018, 0x01c00018 }, |
543 | }; | 543 | }; |
544 | 544 | ||
545 | static const u32 ar5416Bank6_9100[][3] = { | 545 | static const u32 ar5416Bank6[][3] = { |
546 | 546 | ||
547 | { 0x0000989c, 0x00000000, 0x00000000 }, | 547 | { 0x0000989c, 0x00000000, 0x00000000 }, |
548 | { 0x0000989c, 0x00000000, 0x00000000 }, | 548 | { 0x0000989c, 0x00000000, 0x00000000 }, |
@@ -579,7 +579,7 @@ static const u32 ar5416Bank6_9100[][3] = { | |||
579 | { 0x000098d0, 0x0000000f, 0x0010000f }, | 579 | { 0x000098d0, 0x0000000f, 0x0010000f }, |
580 | }; | 580 | }; |
581 | 581 | ||
582 | static const u32 ar5416Bank6TPC_9100[][3] = { | 582 | static const u32 ar5416Bank6TPC[][3] = { |
583 | { 0x0000989c, 0x00000000, 0x00000000 }, | 583 | { 0x0000989c, 0x00000000, 0x00000000 }, |
584 | { 0x0000989c, 0x00000000, 0x00000000 }, | 584 | { 0x0000989c, 0x00000000, 0x00000000 }, |
585 | { 0x0000989c, 0x00000000, 0x00000000 }, | 585 | { 0x0000989c, 0x00000000, 0x00000000 }, |
@@ -615,13 +615,13 @@ static const u32 ar5416Bank6TPC_9100[][3] = { | |||
615 | { 0x000098d0, 0x0000000f, 0x0010000f }, | 615 | { 0x000098d0, 0x0000000f, 0x0010000f }, |
616 | }; | 616 | }; |
617 | 617 | ||
618 | static const u32 ar5416Bank7_9100[][2] = { | 618 | static const u32 ar5416Bank7[][2] = { |
619 | { 0x0000989c, 0x00000500 }, | 619 | { 0x0000989c, 0x00000500 }, |
620 | { 0x0000989c, 0x00000800 }, | 620 | { 0x0000989c, 0x00000800 }, |
621 | { 0x000098cc, 0x0000000e }, | 621 | { 0x000098cc, 0x0000000e }, |
622 | }; | 622 | }; |
623 | 623 | ||
624 | static const u32 ar5416Addac_9100[][2] = { | 624 | static const u32 ar5416Addac[][2] = { |
625 | {0x0000989c, 0x00000000 }, | 625 | {0x0000989c, 0x00000000 }, |
626 | {0x0000989c, 0x00000003 }, | 626 | {0x0000989c, 0x00000003 }, |
627 | {0x0000989c, 0x00000000 }, | 627 | {0x0000989c, 0x00000000 }, |
@@ -661,7 +661,7 @@ static const u32 ar5416Addac_9100[][2] = { | |||
661 | {0x000098cc, 0x00000000 }, | 661 | {0x000098cc, 0x00000000 }, |
662 | }; | 662 | }; |
663 | 663 | ||
664 | static const u32 ar5416Modes[][6] = { | 664 | static const u32 ar5416Modes_9100[][6] = { |
665 | { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, | 665 | { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, |
666 | { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, | 666 | { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, |
667 | { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, | 667 | { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, |
@@ -735,7 +735,7 @@ static const u32 ar5416Modes[][6] = { | |||
735 | { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | 735 | { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, |
736 | }; | 736 | }; |
737 | 737 | ||
738 | static const u32 ar5416Common[][2] = { | 738 | static const u32 ar5416Common_9100[][2] = { |
739 | { 0x0000000c, 0x00000000 }, | 739 | { 0x0000000c, 0x00000000 }, |
740 | { 0x00000030, 0x00020015 }, | 740 | { 0x00000030, 0x00020015 }, |
741 | { 0x00000034, 0x00000005 }, | 741 | { 0x00000034, 0x00000005 }, |
@@ -1109,12 +1109,12 @@ static const u32 ar5416Common[][2] = { | |||
1109 | { 0x0000a3e0, 0x000001ce }, | 1109 | { 0x0000a3e0, 0x000001ce }, |
1110 | }; | 1110 | }; |
1111 | 1111 | ||
1112 | static const u32 ar5416Bank0[][2] = { | 1112 | static const u32 ar5416Bank0_9100[][2] = { |
1113 | { 0x000098b0, 0x1e5795e5 }, | 1113 | { 0x000098b0, 0x1e5795e5 }, |
1114 | { 0x000098e0, 0x02008020 }, | 1114 | { 0x000098e0, 0x02008020 }, |
1115 | }; | 1115 | }; |
1116 | 1116 | ||
1117 | static const u32 ar5416BB_RfGain[][3] = { | 1117 | static const u32 ar5416BB_RfGain_9100[][3] = { |
1118 | { 0x00009a00, 0x00000000, 0x00000000 }, | 1118 | { 0x00009a00, 0x00000000, 0x00000000 }, |
1119 | { 0x00009a04, 0x00000040, 0x00000040 }, | 1119 | { 0x00009a04, 0x00000040, 0x00000040 }, |
1120 | { 0x00009a08, 0x00000080, 0x00000080 }, | 1120 | { 0x00009a08, 0x00000080, 0x00000080 }, |
@@ -1181,21 +1181,21 @@ static const u32 ar5416BB_RfGain[][3] = { | |||
1181 | { 0x00009afc, 0x000000f9, 0x000000f9 }, | 1181 | { 0x00009afc, 0x000000f9, 0x000000f9 }, |
1182 | }; | 1182 | }; |
1183 | 1183 | ||
1184 | static const u32 ar5416Bank1[][2] = { | 1184 | static const u32 ar5416Bank1_9100[][2] = { |
1185 | { 0x000098b0, 0x02108421}, | 1185 | { 0x000098b0, 0x02108421}, |
1186 | { 0x000098ec, 0x00000008}, | 1186 | { 0x000098ec, 0x00000008}, |
1187 | }; | 1187 | }; |
1188 | 1188 | ||
1189 | static const u32 ar5416Bank2[][2] = { | 1189 | static const u32 ar5416Bank2_9100[][2] = { |
1190 | { 0x000098b0, 0x0e73ff17}, | 1190 | { 0x000098b0, 0x0e73ff17}, |
1191 | { 0x000098e0, 0x00000420}, | 1191 | { 0x000098e0, 0x00000420}, |
1192 | }; | 1192 | }; |
1193 | 1193 | ||
1194 | static const u32 ar5416Bank3[][3] = { | 1194 | static const u32 ar5416Bank3_9100[][3] = { |
1195 | { 0x000098f0, 0x01400018, 0x01c00018 }, | 1195 | { 0x000098f0, 0x01400018, 0x01c00018 }, |
1196 | }; | 1196 | }; |
1197 | 1197 | ||
1198 | static const u32 ar5416Bank6[][3] = { | 1198 | static const u32 ar5416Bank6_9100[][3] = { |
1199 | 1199 | ||
1200 | { 0x0000989c, 0x00000000, 0x00000000 }, | 1200 | { 0x0000989c, 0x00000000, 0x00000000 }, |
1201 | { 0x0000989c, 0x00000000, 0x00000000 }, | 1201 | { 0x0000989c, 0x00000000, 0x00000000 }, |
@@ -1233,7 +1233,7 @@ static const u32 ar5416Bank6[][3] = { | |||
1233 | }; | 1233 | }; |
1234 | 1234 | ||
1235 | 1235 | ||
1236 | static const u32 ar5416Bank6TPC[][3] = { | 1236 | static const u32 ar5416Bank6TPC_9100[][3] = { |
1237 | 1237 | ||
1238 | { 0x0000989c, 0x00000000, 0x00000000 }, | 1238 | { 0x0000989c, 0x00000000, 0x00000000 }, |
1239 | { 0x0000989c, 0x00000000, 0x00000000 }, | 1239 | { 0x0000989c, 0x00000000, 0x00000000 }, |
@@ -1270,13 +1270,13 @@ static const u32 ar5416Bank6TPC[][3] = { | |||
1270 | { 0x000098d0, 0x0000000f, 0x0010000f }, | 1270 | { 0x000098d0, 0x0000000f, 0x0010000f }, |
1271 | }; | 1271 | }; |
1272 | 1272 | ||
1273 | static const u32 ar5416Bank7[][2] = { | 1273 | static const u32 ar5416Bank7_9100[][2] = { |
1274 | { 0x0000989c, 0x00000500 }, | 1274 | { 0x0000989c, 0x00000500 }, |
1275 | { 0x0000989c, 0x00000800 }, | 1275 | { 0x0000989c, 0x00000800 }, |
1276 | { 0x000098cc, 0x0000000e }, | 1276 | { 0x000098cc, 0x0000000e }, |
1277 | }; | 1277 | }; |
1278 | 1278 | ||
1279 | static const u32 ar5416Addac[][2] = { | 1279 | static const u32 ar5416Addac_9100[][2] = { |
1280 | {0x0000989c, 0x00000000 }, | 1280 | {0x0000989c, 0x00000000 }, |
1281 | {0x0000989c, 0x00000000 }, | 1281 | {0x0000989c, 0x00000000 }, |
1282 | {0x0000989c, 0x00000000 }, | 1282 | {0x0000989c, 0x00000000 }, |
@@ -4121,6 +4121,7 @@ static const u_int32_t ar9285PciePhy_clkreq_off_L1_9285[][2] = { | |||
4121 | {0x00004044, 0x00000000 }, | 4121 | {0x00004044, 0x00000000 }, |
4122 | }; | 4122 | }; |
4123 | 4123 | ||
4124 | /* AR9285 v1_2 PCI Register Writes. Created: 03/04/09 */ | ||
4124 | static const u_int32_t ar9285Modes_9285_1_2[][6] = { | 4125 | static const u_int32_t ar9285Modes_9285_1_2[][6] = { |
4125 | { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, | 4126 | { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, |
4126 | { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, | 4127 | { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, |
@@ -4155,7 +4156,7 @@ static const u_int32_t ar9285Modes_9285_1_2[][6] = { | |||
4155 | { 0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 }, | 4156 | { 0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 }, |
4156 | { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, | 4157 | { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, |
4157 | { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, | 4158 | { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, |
4158 | { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 }, | 4159 | { 0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329 }, |
4159 | { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, | 4160 | { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, |
4160 | { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, | 4161 | { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, |
4161 | { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | 4162 | { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, |
@@ -4421,25 +4422,6 @@ static const u_int32_t ar9285Modes_9285_1_2[][6] = { | |||
4421 | { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, | 4422 | { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, |
4422 | { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, | 4423 | { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, |
4423 | { 0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000, 0x0004a000 }, | 4424 | { 0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000, 0x0004a000 }, |
4424 | { 0x0000a274, 0x0a81c652, 0x0a81c652, 0x0a820652, 0x0a820652, 0x0a82a652 }, | ||
4425 | { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | ||
4426 | { 0x0000a304, 0x00000000, 0x00000000, 0x00007201, 0x00007201, 0x00000000 }, | ||
4427 | { 0x0000a308, 0x00000000, 0x00000000, 0x00010408, 0x00010408, 0x00000000 }, | ||
4428 | { 0x0000a30c, 0x00000000, 0x00000000, 0x0001860a, 0x0001860a, 0x00000000 }, | ||
4429 | { 0x0000a310, 0x00000000, 0x00000000, 0x00020818, 0x00020818, 0x00000000 }, | ||
4430 | { 0x0000a314, 0x00000000, 0x00000000, 0x00024858, 0x00024858, 0x00000000 }, | ||
4431 | { 0x0000a318, 0x00000000, 0x00000000, 0x00026859, 0x00026859, 0x00000000 }, | ||
4432 | { 0x0000a31c, 0x00000000, 0x00000000, 0x0002985b, 0x0002985b, 0x00000000 }, | ||
4433 | { 0x0000a320, 0x00000000, 0x00000000, 0x0002b89a, 0x0002b89a, 0x00000000 }, | ||
4434 | { 0x0000a324, 0x00000000, 0x00000000, 0x0002d89b, 0x0002d89b, 0x00000000 }, | ||
4435 | { 0x0000a328, 0x00000000, 0x00000000, 0x0002f89c, 0x0002f89c, 0x00000000 }, | ||
4436 | { 0x0000a32c, 0x00000000, 0x00000000, 0x0003189d, 0x0003189d, 0x00000000 }, | ||
4437 | { 0x0000a330, 0x00000000, 0x00000000, 0x0003389e, 0x0003389e, 0x00000000 }, | ||
4438 | { 0x0000a334, 0x00000000, 0x00000000, 0x000368de, 0x000368de, 0x00000000 }, | ||
4439 | { 0x0000a338, 0x00000000, 0x00000000, 0x0003891e, 0x0003891e, 0x00000000 }, | ||
4440 | { 0x0000a33c, 0x00000000, 0x00000000, 0x0003a95e, 0x0003a95e, 0x00000000 }, | ||
4441 | { 0x0000a340, 0x00000000, 0x00000000, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
4442 | { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
4443 | { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, | 4425 | { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, |
4444 | }; | 4426 | }; |
4445 | 4427 | ||
@@ -4569,7 +4551,7 @@ static const u_int32_t ar9285Common_9285_1_2[][2] = { | |||
4569 | { 0x00008110, 0x00000168 }, | 4551 | { 0x00008110, 0x00000168 }, |
4570 | { 0x00008118, 0x000100aa }, | 4552 | { 0x00008118, 0x000100aa }, |
4571 | { 0x0000811c, 0x00003210 }, | 4553 | { 0x0000811c, 0x00003210 }, |
4572 | { 0x00008120, 0x08f04800 }, | 4554 | { 0x00008120, 0x08f04810 }, |
4573 | { 0x00008124, 0x00000000 }, | 4555 | { 0x00008124, 0x00000000 }, |
4574 | { 0x00008128, 0x00000000 }, | 4556 | { 0x00008128, 0x00000000 }, |
4575 | { 0x0000812c, 0x00000000 }, | 4557 | { 0x0000812c, 0x00000000 }, |
@@ -4585,7 +4567,7 @@ static const u_int32_t ar9285Common_9285_1_2[][2] = { | |||
4585 | { 0x00008178, 0x00000100 }, | 4567 | { 0x00008178, 0x00000100 }, |
4586 | { 0x0000817c, 0x00000000 }, | 4568 | { 0x0000817c, 0x00000000 }, |
4587 | { 0x000081c0, 0x00000000 }, | 4569 | { 0x000081c0, 0x00000000 }, |
4588 | { 0x000081d0, 0x00003210 }, | 4570 | { 0x000081d0, 0x0000320a }, |
4589 | { 0x000081ec, 0x00000000 }, | 4571 | { 0x000081ec, 0x00000000 }, |
4590 | { 0x000081f0, 0x00000000 }, | 4572 | { 0x000081f0, 0x00000000 }, |
4591 | { 0x000081f4, 0x00000000 }, | 4573 | { 0x000081f4, 0x00000000 }, |
@@ -4709,8 +4691,6 @@ static const u_int32_t ar9285Common_9285_1_2[][2] = { | |||
4709 | { 0x0000a268, 0x00000000 }, | 4691 | { 0x0000a268, 0x00000000 }, |
4710 | { 0x0000a26c, 0x0ebae9e6 }, | 4692 | { 0x0000a26c, 0x0ebae9e6 }, |
4711 | { 0x0000d270, 0x0d820820 }, | 4693 | { 0x0000d270, 0x0d820820 }, |
4712 | { 0x0000a278, 0x318c6318 }, | ||
4713 | { 0x0000a27c, 0x050c0318 }, | ||
4714 | { 0x0000d35c, 0x07ffffef }, | 4694 | { 0x0000d35c, 0x07ffffef }, |
4715 | { 0x0000d360, 0x0fffffe7 }, | 4695 | { 0x0000d360, 0x0fffffe7 }, |
4716 | { 0x0000d364, 0x17ffffe5 }, | 4696 | { 0x0000d364, 0x17ffffe5 }, |
@@ -4725,8 +4705,6 @@ static const u_int32_t ar9285Common_9285_1_2[][2] = { | |||
4725 | { 0x0000a388, 0x0c000000 }, | 4705 | { 0x0000a388, 0x0c000000 }, |
4726 | { 0x0000a38c, 0x20202020 }, | 4706 | { 0x0000a38c, 0x20202020 }, |
4727 | { 0x0000a390, 0x20202020 }, | 4707 | { 0x0000a390, 0x20202020 }, |
4728 | { 0x0000a394, 0x318c6318 }, | ||
4729 | { 0x0000a398, 0x00000318 }, | ||
4730 | { 0x0000a39c, 0x00000001 }, | 4708 | { 0x0000a39c, 0x00000001 }, |
4731 | { 0x0000a3a0, 0x00000000 }, | 4709 | { 0x0000a3a0, 0x00000000 }, |
4732 | { 0x0000a3a4, 0x00000000 }, | 4710 | { 0x0000a3a4, 0x00000000 }, |
@@ -4741,8 +4719,6 @@ static const u_int32_t ar9285Common_9285_1_2[][2] = { | |||
4741 | { 0x0000a3cc, 0x20202020 }, | 4719 | { 0x0000a3cc, 0x20202020 }, |
4742 | { 0x0000a3d0, 0x20202020 }, | 4720 | { 0x0000a3d0, 0x20202020 }, |
4743 | { 0x0000a3d4, 0x20202020 }, | 4721 | { 0x0000a3d4, 0x20202020 }, |
4744 | { 0x0000a3dc, 0x318c6318 }, | ||
4745 | { 0x0000a3e0, 0x00000318 }, | ||
4746 | { 0x0000a3e4, 0x00000000 }, | 4722 | { 0x0000a3e4, 0x00000000 }, |
4747 | { 0x0000a3e8, 0x18c43433 }, | 4723 | { 0x0000a3e8, 0x18c43433 }, |
4748 | { 0x0000a3ec, 0x00f70081 }, | 4724 | { 0x0000a3ec, 0x00f70081 }, |
@@ -4753,13 +4729,11 @@ static const u_int32_t ar9285Common_9285_1_2[][2] = { | |||
4753 | { 0x00007810, 0x71c0d388 }, | 4729 | { 0x00007810, 0x71c0d388 }, |
4754 | { 0x00007814, 0x924934a8 }, | 4730 | { 0x00007814, 0x924934a8 }, |
4755 | { 0x0000781c, 0x00000000 }, | 4731 | { 0x0000781c, 0x00000000 }, |
4756 | { 0x00007820, 0x00000c04 }, | ||
4757 | { 0x00007824, 0x00d86fff }, | 4732 | { 0x00007824, 0x00d86fff }, |
4758 | { 0x00007828, 0x26d2491b }, | 4733 | { 0x00007828, 0x26d2491b }, |
4759 | { 0x0000782c, 0x6e36d97b }, | 4734 | { 0x0000782c, 0x6e36d97b }, |
4760 | { 0x00007830, 0xedb6d96e }, | 4735 | { 0x00007830, 0xedb6d96e }, |
4761 | { 0x00007834, 0x71400087 }, | 4736 | { 0x00007834, 0x71400087 }, |
4762 | { 0x00007838, 0xfac68801 }, | ||
4763 | { 0x0000783c, 0x0001fffe }, | 4737 | { 0x0000783c, 0x0001fffe }, |
4764 | { 0x00007840, 0xffeb1a20 }, | 4738 | { 0x00007840, 0xffeb1a20 }, |
4765 | { 0x00007844, 0x000c0db6 }, | 4739 | { 0x00007844, 0x000c0db6 }, |
@@ -4772,10 +4746,81 @@ static const u_int32_t ar9285Common_9285_1_2[][2] = { | |||
4772 | { 0x00007860, 0x21084210 }, | 4746 | { 0x00007860, 0x21084210 }, |
4773 | { 0x00007864, 0xf7d7ffde }, | 4747 | { 0x00007864, 0xf7d7ffde }, |
4774 | { 0x00007868, 0xc2034080 }, | 4748 | { 0x00007868, 0xc2034080 }, |
4775 | { 0x0000786c, 0x48609eb4 }, | ||
4776 | { 0x00007870, 0x10142c00 }, | 4749 | { 0x00007870, 0x10142c00 }, |
4777 | }; | 4750 | }; |
4778 | 4751 | ||
4752 | static const u_int32_t ar9285Modes_high_power_tx_gain_9285_1_2[][6] = { | ||
4753 | /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ | ||
4754 | { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | ||
4755 | { 0x0000a304, 0x00000000, 0x00000000, 0x00005200, 0x00005200, 0x00000000 }, | ||
4756 | { 0x0000a308, 0x00000000, 0x00000000, 0x00007201, 0x00007201, 0x00000000 }, | ||
4757 | { 0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240, 0x00000000 }, | ||
4758 | { 0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241, 0x00000000 }, | ||
4759 | { 0x0000a314, 0x00000000, 0x00000000, 0x0000f440, 0x0000f440, 0x00000000 }, | ||
4760 | { 0x0000a318, 0x00000000, 0x00000000, 0x00014640, 0x00014640, 0x00000000 }, | ||
4761 | { 0x0000a31c, 0x00000000, 0x00000000, 0x00018680, 0x00018680, 0x00000000 }, | ||
4762 | { 0x0000a320, 0x00000000, 0x00000000, 0x00019841, 0x00019841, 0x00000000 }, | ||
4763 | { 0x0000a324, 0x00000000, 0x00000000, 0x0001ca40, 0x0001ca40, 0x00000000 }, | ||
4764 | { 0x0000a328, 0x00000000, 0x00000000, 0x0001fa80, 0x0001fa80, 0x00000000 }, | ||
4765 | { 0x0000a32c, 0x00000000, 0x00000000, 0x00023ac0, 0x00023ac0, 0x00000000 }, | ||
4766 | { 0x0000a330, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40, 0x00000000 }, | ||
4767 | { 0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82, 0x00000000 }, | ||
4768 | { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, | ||
4769 | { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, | ||
4770 | { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
4771 | { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
4772 | { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
4773 | { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
4774 | { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
4775 | { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
4776 | { 0x00007838, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803 }, | ||
4777 | { 0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe }, | ||
4778 | { 0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00 }, | ||
4779 | { 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a21a652, 0x0a21a652, 0x0a22a652 }, | ||
4780 | { 0x0000a278, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce }, | ||
4781 | { 0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce }, | ||
4782 | { 0x0000a394, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce }, | ||
4783 | { 0x0000a398, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce }, | ||
4784 | { 0x0000a3dc, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce }, | ||
4785 | { 0x0000a3e0, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce }, | ||
4786 | }; | ||
4787 | |||
4788 | static const u_int32_t ar9285Modes_original_tx_gain_9285_1_2[][6] = { | ||
4789 | /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ | ||
4790 | { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | ||
4791 | { 0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000 }, | ||
4792 | { 0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000 }, | ||
4793 | { 0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000 }, | ||
4794 | { 0x0000a310, 0x00000000, 0x00000000, 0x00022618, 0x00022618, 0x00000000 }, | ||
4795 | { 0x0000a314, 0x00000000, 0x00000000, 0x0002a6c9, 0x0002a6c9, 0x00000000 }, | ||
4796 | { 0x0000a318, 0x00000000, 0x00000000, 0x00031710, 0x00031710, 0x00000000 }, | ||
4797 | { 0x0000a31c, 0x00000000, 0x00000000, 0x00035718, 0x00035718, 0x00000000 }, | ||
4798 | { 0x0000a320, 0x00000000, 0x00000000, 0x00038758, 0x00038758, 0x00000000 }, | ||
4799 | { 0x0000a324, 0x00000000, 0x00000000, 0x0003c75a, 0x0003c75a, 0x00000000 }, | ||
4800 | { 0x0000a328, 0x00000000, 0x00000000, 0x0004075c, 0x0004075c, 0x00000000 }, | ||
4801 | { 0x0000a32c, 0x00000000, 0x00000000, 0x0004475e, 0x0004475e, 0x00000000 }, | ||
4802 | { 0x0000a330, 0x00000000, 0x00000000, 0x0004679f, 0x0004679f, 0x00000000 }, | ||
4803 | { 0x0000a334, 0x00000000, 0x00000000, 0x000487df, 0x000487df, 0x00000000 }, | ||
4804 | { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, | ||
4805 | { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, | ||
4806 | { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
4807 | { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
4808 | { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
4809 | { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
4810 | { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
4811 | { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
4812 | { 0x00007838, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801 }, | ||
4813 | { 0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4 }, | ||
4814 | { 0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04 }, | ||
4815 | { 0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652, 0x0a22a652 }, | ||
4816 | { 0x0000a278, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, | ||
4817 | { 0x0000a27c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c }, | ||
4818 | { 0x0000a394, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, | ||
4819 | { 0x0000a398, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c }, | ||
4820 | { 0x0000a3dc, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, | ||
4821 | { 0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c }, | ||
4822 | }; | ||
4823 | |||
4779 | static const u_int32_t ar9285PciePhy_clkreq_always_on_L1_9285_1_2[][2] = { | 4824 | static const u_int32_t ar9285PciePhy_clkreq_always_on_L1_9285_1_2[][2] = { |
4780 | {0x00004040, 0x9248fd00 }, | 4825 | {0x00004040, 0x9248fd00 }, |
4781 | {0x00004040, 0x24924924 }, | 4826 | {0x00004040, 0x24924924 }, |
diff --git a/drivers/net/wireless/ath9k/mac.h b/drivers/net/wireless/ath9k/mac.h index 37e3948ddc25..a75f65dae1d7 100644 --- a/drivers/net/wireless/ath9k/mac.h +++ b/drivers/net/wireless/ath9k/mac.h | |||
@@ -17,7 +17,7 @@ | |||
17 | #ifndef MAC_H | 17 | #ifndef MAC_H |
18 | #define MAC_H | 18 | #define MAC_H |
19 | 19 | ||
20 | #define RXSTATUS_RATE(ah, ads) (AR_SREV_5416_V20_OR_LATER(ah) ? \ | 20 | #define RXSTATUS_RATE(ah, ads) (AR_SREV_5416_20_OR_LATER(ah) ? \ |
21 | MS(ads->ds_rxstatus0, AR_RxRate) : \ | 21 | MS(ads->ds_rxstatus0, AR_RxRate) : \ |
22 | (ads->ds_rxstatus3 >> 2) & 0xFF) | 22 | (ads->ds_rxstatus3 >> 2) & 0xFF) |
23 | 23 | ||
diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index a9715f5b0af6..8db75f6de53e 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c | |||
@@ -1084,12 +1084,6 @@ fail: | |||
1084 | ath_deinit_leds(sc); | 1084 | ath_deinit_leds(sc); |
1085 | } | 1085 | } |
1086 | 1086 | ||
1087 | #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) | ||
1088 | |||
1089 | /*******************/ | ||
1090 | /* Rfkill */ | ||
1091 | /*******************/ | ||
1092 | |||
1093 | void ath_radio_enable(struct ath_softc *sc) | 1087 | void ath_radio_enable(struct ath_softc *sc) |
1094 | { | 1088 | { |
1095 | struct ath_hw *ah = sc->sc_ah; | 1089 | struct ath_hw *ah = sc->sc_ah; |
@@ -1166,6 +1160,12 @@ void ath_radio_disable(struct ath_softc *sc) | |||
1166 | ath9k_ps_restore(sc); | 1160 | ath9k_ps_restore(sc); |
1167 | } | 1161 | } |
1168 | 1162 | ||
1163 | #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) | ||
1164 | |||
1165 | /*******************/ | ||
1166 | /* Rfkill */ | ||
1167 | /*******************/ | ||
1168 | |||
1169 | static bool ath_is_rfkill_set(struct ath_softc *sc) | 1169 | static bool ath_is_rfkill_set(struct ath_softc *sc) |
1170 | { | 1170 | { |
1171 | struct ath_hw *ah = sc->sc_ah; | 1171 | struct ath_hw *ah = sc->sc_ah; |
@@ -1583,7 +1583,8 @@ void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
1583 | IEEE80211_HW_SIGNAL_DBM | | 1583 | IEEE80211_HW_SIGNAL_DBM | |
1584 | IEEE80211_HW_AMPDU_AGGREGATION | | 1584 | IEEE80211_HW_AMPDU_AGGREGATION | |
1585 | IEEE80211_HW_SUPPORTS_PS | | 1585 | IEEE80211_HW_SUPPORTS_PS | |
1586 | IEEE80211_HW_PS_NULLFUNC_STACK; | 1586 | IEEE80211_HW_PS_NULLFUNC_STACK | |
1587 | IEEE80211_HW_SPECTRUM_MGMT; | ||
1587 | 1588 | ||
1588 | if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || modparam_nohwcrypt) | 1589 | if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || modparam_nohwcrypt) |
1589 | hw->flags |= IEEE80211_HW_MFP_CAPABLE; | 1590 | hw->flags |= IEEE80211_HW_MFP_CAPABLE; |
@@ -1671,7 +1672,7 @@ int ath_attach(u16 devid, struct ath_softc *sc) | |||
1671 | } | 1672 | } |
1672 | wiphy_apply_custom_regulatory(hw->wiphy, regd); | 1673 | wiphy_apply_custom_regulatory(hw->wiphy, regd); |
1673 | ath9k_reg_apply_radar_flags(hw->wiphy); | 1674 | ath9k_reg_apply_radar_flags(hw->wiphy); |
1674 | ath9k_reg_apply_world_flags(hw->wiphy, REGDOM_SET_BY_INIT); | 1675 | ath9k_reg_apply_world_flags(hw->wiphy, NL80211_REGDOM_SET_BY_DRIVER); |
1675 | 1676 | ||
1676 | INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work); | 1677 | INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work); |
1677 | INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work); | 1678 | INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work); |
@@ -1774,6 +1775,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, | |||
1774 | DPRINTF(sc, ATH_DBG_CONFIG, "%s DMA: %u buffers %u desc/buf\n", | 1775 | DPRINTF(sc, ATH_DBG_CONFIG, "%s DMA: %u buffers %u desc/buf\n", |
1775 | name, nbuf, ndesc); | 1776 | name, nbuf, ndesc); |
1776 | 1777 | ||
1778 | INIT_LIST_HEAD(head); | ||
1777 | /* ath_desc must be a multiple of DWORDs */ | 1779 | /* ath_desc must be a multiple of DWORDs */ |
1778 | if ((sizeof(struct ath_desc) % 4) != 0) { | 1780 | if ((sizeof(struct ath_desc) % 4) != 0) { |
1779 | DPRINTF(sc, ATH_DBG_FATAL, "ath_desc not DWORD aligned\n"); | 1781 | DPRINTF(sc, ATH_DBG_FATAL, "ath_desc not DWORD aligned\n"); |
@@ -1805,7 +1807,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, | |||
1805 | 1807 | ||
1806 | /* allocate descriptors */ | 1808 | /* allocate descriptors */ |
1807 | dd->dd_desc = dma_alloc_coherent(sc->dev, dd->dd_desc_len, | 1809 | dd->dd_desc = dma_alloc_coherent(sc->dev, dd->dd_desc_len, |
1808 | &dd->dd_desc_paddr, GFP_ATOMIC); | 1810 | &dd->dd_desc_paddr, GFP_KERNEL); |
1809 | if (dd->dd_desc == NULL) { | 1811 | if (dd->dd_desc == NULL) { |
1810 | error = -ENOMEM; | 1812 | error = -ENOMEM; |
1811 | goto fail; | 1813 | goto fail; |
@@ -1817,15 +1819,13 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, | |||
1817 | 1819 | ||
1818 | /* allocate buffers */ | 1820 | /* allocate buffers */ |
1819 | bsize = sizeof(struct ath_buf) * nbuf; | 1821 | bsize = sizeof(struct ath_buf) * nbuf; |
1820 | bf = kmalloc(bsize, GFP_KERNEL); | 1822 | bf = kzalloc(bsize, GFP_KERNEL); |
1821 | if (bf == NULL) { | 1823 | if (bf == NULL) { |
1822 | error = -ENOMEM; | 1824 | error = -ENOMEM; |
1823 | goto fail2; | 1825 | goto fail2; |
1824 | } | 1826 | } |
1825 | memset(bf, 0, bsize); | ||
1826 | dd->dd_bufptr = bf; | 1827 | dd->dd_bufptr = bf; |
1827 | 1828 | ||
1828 | INIT_LIST_HEAD(head); | ||
1829 | for (i = 0; i < nbuf; i++, bf++, ds += ndesc) { | 1829 | for (i = 0; i < nbuf; i++, bf++, ds += ndesc) { |
1830 | bf->bf_desc = ds; | 1830 | bf->bf_desc = ds; |
1831 | bf->bf_daddr = DS2PHYS(dd, ds); | 1831 | bf->bf_daddr = DS2PHYS(dd, ds); |
@@ -2859,12 +2859,20 @@ static int __init ath9k_init(void) | |||
2859 | goto err_out; | 2859 | goto err_out; |
2860 | } | 2860 | } |
2861 | 2861 | ||
2862 | error = ath9k_debug_create_root(); | ||
2863 | if (error) { | ||
2864 | printk(KERN_ERR | ||
2865 | "ath9k: Unable to create debugfs root: %d\n", | ||
2866 | error); | ||
2867 | goto err_rate_unregister; | ||
2868 | } | ||
2869 | |||
2862 | error = ath_pci_init(); | 2870 | error = ath_pci_init(); |
2863 | if (error < 0) { | 2871 | if (error < 0) { |
2864 | printk(KERN_ERR | 2872 | printk(KERN_ERR |
2865 | "ath9k: No PCI devices found, driver not installed.\n"); | 2873 | "ath9k: No PCI devices found, driver not installed.\n"); |
2866 | error = -ENODEV; | 2874 | error = -ENODEV; |
2867 | goto err_rate_unregister; | 2875 | goto err_remove_root; |
2868 | } | 2876 | } |
2869 | 2877 | ||
2870 | error = ath_ahb_init(); | 2878 | error = ath_ahb_init(); |
@@ -2878,6 +2886,8 @@ static int __init ath9k_init(void) | |||
2878 | err_pci_exit: | 2886 | err_pci_exit: |
2879 | ath_pci_exit(); | 2887 | ath_pci_exit(); |
2880 | 2888 | ||
2889 | err_remove_root: | ||
2890 | ath9k_debug_remove_root(); | ||
2881 | err_rate_unregister: | 2891 | err_rate_unregister: |
2882 | ath_rate_control_unregister(); | 2892 | ath_rate_control_unregister(); |
2883 | err_out: | 2893 | err_out: |
@@ -2889,6 +2899,7 @@ static void __exit ath9k_exit(void) | |||
2889 | { | 2899 | { |
2890 | ath_ahb_exit(); | 2900 | ath_ahb_exit(); |
2891 | ath_pci_exit(); | 2901 | ath_pci_exit(); |
2902 | ath9k_debug_remove_root(); | ||
2892 | ath_rate_control_unregister(); | 2903 | ath_rate_control_unregister(); |
2893 | printk(KERN_INFO "%s: Driver unloaded\n", dev_info); | 2904 | printk(KERN_INFO "%s: Driver unloaded\n", dev_info); |
2894 | } | 2905 | } |
diff --git a/drivers/net/wireless/ath9k/phy.h b/drivers/net/wireless/ath9k/phy.h index 6222e32c7748..1eac8c707342 100644 --- a/drivers/net/wireless/ath9k/phy.h +++ b/drivers/net/wireless/ath9k/phy.h | |||
@@ -446,6 +446,9 @@ bool ath9k_hw_init_rf(struct ath_hw *ah, | |||
446 | #define AR_PHY_TPCRG1_PD_GAIN_3 0x00300000 | 446 | #define AR_PHY_TPCRG1_PD_GAIN_3 0x00300000 |
447 | #define AR_PHY_TPCRG1_PD_GAIN_3_S 20 | 447 | #define AR_PHY_TPCRG1_PD_GAIN_3_S 20 |
448 | 448 | ||
449 | #define AR_PHY_TPCRG1_PD_CAL_ENABLE 0x00400000 | ||
450 | #define AR_PHY_TPCRG1_PD_CAL_ENABLE_S 22 | ||
451 | |||
449 | #define AR_PHY_TX_PWRCTRL4 0xa264 | 452 | #define AR_PHY_TX_PWRCTRL4 0xa264 |
450 | #define AR_PHY_TX_PWRCTRL_PD_AVG_VALID 0x00000001 | 453 | #define AR_PHY_TX_PWRCTRL_PD_AVG_VALID 0x00000001 |
451 | #define AR_PHY_TX_PWRCTRL_PD_AVG_VALID_S 0 | 454 | #define AR_PHY_TX_PWRCTRL_PD_AVG_VALID_S 0 |
@@ -513,6 +516,7 @@ bool ath9k_hw_init_rf(struct ath_hw *ah, | |||
513 | /* Carrier leak calibration control, do it after AGC calibration */ | 516 | /* Carrier leak calibration control, do it after AGC calibration */ |
514 | #define AR_PHY_CL_CAL_CTL 0xA358 | 517 | #define AR_PHY_CL_CAL_CTL 0xA358 |
515 | #define AR_PHY_CL_CAL_ENABLE 0x00000002 | 518 | #define AR_PHY_CL_CAL_ENABLE 0x00000002 |
519 | #define AR_PHY_PARALLEL_CAL_ENABLE 0x00000001 | ||
516 | 520 | ||
517 | #define AR_PHY_POWER_TX_RATE5 0xA38C | 521 | #define AR_PHY_POWER_TX_RATE5 0xA38C |
518 | #define AR_PHY_POWER_TX_RATE6 0xA390 | 522 | #define AR_PHY_POWER_TX_RATE6 0xA390 |
diff --git a/drivers/net/wireless/ath9k/recv.c b/drivers/net/wireless/ath9k/recv.c index 3df5c7824360..0bba17662a1f 100644 --- a/drivers/net/wireless/ath9k/recv.c +++ b/drivers/net/wireless/ath9k/recv.c | |||
@@ -100,7 +100,7 @@ static u64 ath_extend_tsf(struct ath_softc *sc, u32 rstamp) | |||
100 | return (tsf & ~0x7fff) | rstamp; | 100 | return (tsf & ~0x7fff) | rstamp; |
101 | } | 101 | } |
102 | 102 | ||
103 | static struct sk_buff *ath_rxbuf_alloc(struct ath_softc *sc, u32 len) | 103 | static struct sk_buff *ath_rxbuf_alloc(struct ath_softc *sc, u32 len, gfp_t gfp_mask) |
104 | { | 104 | { |
105 | struct sk_buff *skb; | 105 | struct sk_buff *skb; |
106 | u32 off; | 106 | u32 off; |
@@ -118,7 +118,7 @@ static struct sk_buff *ath_rxbuf_alloc(struct ath_softc *sc, u32 len) | |||
118 | * Unfortunately this means we may get 8 KB here from the | 118 | * Unfortunately this means we may get 8 KB here from the |
119 | * kernel... and that is actually what is observed on some | 119 | * kernel... and that is actually what is observed on some |
120 | * systems :( */ | 120 | * systems :( */ |
121 | skb = dev_alloc_skb(len + sc->cachelsz - 1); | 121 | skb = __dev_alloc_skb(len + sc->cachelsz - 1, gfp_mask); |
122 | if (skb != NULL) { | 122 | if (skb != NULL) { |
123 | off = ((unsigned long) skb->data) % sc->cachelsz; | 123 | off = ((unsigned long) skb->data) % sc->cachelsz; |
124 | if (off != 0) | 124 | if (off != 0) |
@@ -306,7 +306,7 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) | |||
306 | } | 306 | } |
307 | 307 | ||
308 | list_for_each_entry(bf, &sc->rx.rxbuf, list) { | 308 | list_for_each_entry(bf, &sc->rx.rxbuf, list) { |
309 | skb = ath_rxbuf_alloc(sc, sc->rx.bufsize); | 309 | skb = ath_rxbuf_alloc(sc, sc->rx.bufsize, GFP_KERNEL); |
310 | if (skb == NULL) { | 310 | if (skb == NULL) { |
311 | error = -ENOMEM; | 311 | error = -ENOMEM; |
312 | break; | 312 | break; |
@@ -385,14 +385,15 @@ u32 ath_calcrxfilter(struct ath_softc *sc) | |||
385 | if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION) | 385 | if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION) |
386 | rfilt |= ATH9K_RX_FILTER_PROBEREQ; | 386 | rfilt |= ATH9K_RX_FILTER_PROBEREQ; |
387 | 387 | ||
388 | /* Can't set HOSTAP into promiscous mode */ | 388 | /* |
389 | * Set promiscuous mode when FIF_PROMISC_IN_BSS is enabled for station | ||
390 | * mode interface or when in monitor mode. AP mode does not need this | ||
391 | * since it receives all in-BSS frames anyway. | ||
392 | */ | ||
389 | if (((sc->sc_ah->opmode != NL80211_IFTYPE_AP) && | 393 | if (((sc->sc_ah->opmode != NL80211_IFTYPE_AP) && |
390 | (sc->rx.rxfilter & FIF_PROMISC_IN_BSS)) || | 394 | (sc->rx.rxfilter & FIF_PROMISC_IN_BSS)) || |
391 | (sc->sc_ah->opmode == NL80211_IFTYPE_MONITOR)) { | 395 | (sc->sc_ah->opmode == NL80211_IFTYPE_MONITOR)) |
392 | rfilt |= ATH9K_RX_FILTER_PROM; | 396 | rfilt |= ATH9K_RX_FILTER_PROM; |
393 | /* ??? To prevent from sending ACK */ | ||
394 | rfilt &= ~ATH9K_RX_FILTER_UCAST; | ||
395 | } | ||
396 | 397 | ||
397 | if (sc->rx.rxfilter & FIF_CONTROL) | 398 | if (sc->rx.rxfilter & FIF_CONTROL) |
398 | rfilt |= ATH9K_RX_FILTER_CONTROL; | 399 | rfilt |= ATH9K_RX_FILTER_CONTROL; |
@@ -580,7 +581,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
580 | 581 | ||
581 | /* Ensure we always have an skb to requeue once we are done | 582 | /* Ensure we always have an skb to requeue once we are done |
582 | * processing the current buffer's skb */ | 583 | * processing the current buffer's skb */ |
583 | requeue_skb = ath_rxbuf_alloc(sc, sc->rx.bufsize); | 584 | requeue_skb = ath_rxbuf_alloc(sc, sc->rx.bufsize, GFP_ATOMIC); |
584 | 585 | ||
585 | /* If there is no memory we ignore the current RX'd frame, | 586 | /* If there is no memory we ignore the current RX'd frame, |
586 | * tell hardware it can give us a new frame using the old | 587 | * tell hardware it can give us a new frame using the old |
diff --git a/drivers/net/wireless/ath9k/reg.h b/drivers/net/wireless/ath9k/reg.h index 91442da18183..d86e90e38173 100644 --- a/drivers/net/wireless/ath9k/reg.h +++ b/drivers/net/wireless/ath9k/reg.h | |||
@@ -158,14 +158,6 @@ | |||
158 | #define AR_CST_TIMEOUT_LIMIT 0xFFFF0000 | 158 | #define AR_CST_TIMEOUT_LIMIT 0xFFFF0000 |
159 | #define AR_CST_TIMEOUT_LIMIT_S 16 | 159 | #define AR_CST_TIMEOUT_LIMIT_S 16 |
160 | 160 | ||
161 | #define AR_SREV_VERSION_9100 0x014 | ||
162 | |||
163 | #define AR_SREV_9100(ah) ((ah->hw_version.macVersion) == AR_SREV_VERSION_9100) | ||
164 | #define AR_SREV_5416_V20_OR_LATER(_ah) \ | ||
165 | (AR_SREV_9100((_ah)) || AR_SREV_5416_20_OR_LATER(_ah)) | ||
166 | #define AR_SREV_5416_V22_OR_LATER(_ah) \ | ||
167 | (AR_SREV_9100((_ah)) || AR_SREV_5416_22_OR_LATER(_ah)) | ||
168 | |||
169 | #define AR_ISR 0x0080 | 161 | #define AR_ISR 0x0080 |
170 | #define AR_ISR_RXOK 0x00000001 | 162 | #define AR_ISR_RXOK 0x00000001 |
171 | #define AR_ISR_RXDESC 0x00000002 | 163 | #define AR_ISR_RXDESC 0x00000002 |
@@ -734,6 +726,7 @@ | |||
734 | #define AR_SREV_REVISION_5416_10 0 | 726 | #define AR_SREV_REVISION_5416_10 0 |
735 | #define AR_SREV_REVISION_5416_20 1 | 727 | #define AR_SREV_REVISION_5416_20 1 |
736 | #define AR_SREV_REVISION_5416_22 2 | 728 | #define AR_SREV_REVISION_5416_22 2 |
729 | #define AR_SREV_VERSION_9100 0x14 | ||
737 | #define AR_SREV_VERSION_9160 0x40 | 730 | #define AR_SREV_VERSION_9160 0x40 |
738 | #define AR_SREV_REVISION_9160_10 0 | 731 | #define AR_SREV_REVISION_9160_10 0 |
739 | #define AR_SREV_REVISION_9160_11 1 | 732 | #define AR_SREV_REVISION_9160_11 1 |
@@ -746,14 +739,23 @@ | |||
746 | #define AR_SREV_REVISION_9285_11 1 | 739 | #define AR_SREV_REVISION_9285_11 1 |
747 | #define AR_SREV_REVISION_9285_12 2 | 740 | #define AR_SREV_REVISION_9285_12 2 |
748 | 741 | ||
749 | #define AR_SREV_9100_OR_LATER(_ah) \ | 742 | #define AR_SREV_5416(_ah) \ |
750 | (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_5416_PCIE)) | 743 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \ |
744 | ((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE)) | ||
751 | #define AR_SREV_5416_20_OR_LATER(_ah) \ | 745 | #define AR_SREV_5416_20_OR_LATER(_ah) \ |
752 | (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9160) || \ | 746 | (((AR_SREV_5416(_ah)) && \ |
753 | ((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_20)) | 747 | ((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_20)) || \ |
748 | ((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100)) | ||
754 | #define AR_SREV_5416_22_OR_LATER(_ah) \ | 749 | #define AR_SREV_5416_22_OR_LATER(_ah) \ |
755 | (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9160) || \ | 750 | (((AR_SREV_5416(_ah)) && \ |
756 | ((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_22)) | 751 | ((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_22)) || \ |
752 | ((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100)) | ||
753 | |||
754 | #define AR_SREV_9100(ah) \ | ||
755 | ((ah->hw_version.macVersion) == AR_SREV_VERSION_9100) | ||
756 | #define AR_SREV_9100_OR_LATER(_ah) \ | ||
757 | (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100)) | ||
758 | |||
757 | #define AR_SREV_9160(_ah) \ | 759 | #define AR_SREV_9160(_ah) \ |
758 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9160)) | 760 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9160)) |
759 | #define AR_SREV_9160_10_OR_LATER(_ah) \ | 761 | #define AR_SREV_9160_10_OR_LATER(_ah) \ |
@@ -778,14 +780,14 @@ | |||
778 | #define AR_SREV_9285_10_OR_LATER(_ah) \ | 780 | #define AR_SREV_9285_10_OR_LATER(_ah) \ |
779 | (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9285)) | 781 | (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9285)) |
780 | #define AR_SREV_9285_11(_ah) \ | 782 | #define AR_SREV_9285_11(_ah) \ |
781 | (AR_SREV_9280(ah) && \ | 783 | (AR_SREV_9285(ah) && \ |
782 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9285_11)) | 784 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9285_11)) |
783 | #define AR_SREV_9285_11_OR_LATER(_ah) \ | 785 | #define AR_SREV_9285_11_OR_LATER(_ah) \ |
784 | (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9285) || \ | 786 | (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9285) || \ |
785 | (AR_SREV_9285(ah) && ((_ah)->hw_version.macRev >= \ | 787 | (AR_SREV_9285(ah) && ((_ah)->hw_version.macRev >= \ |
786 | AR_SREV_REVISION_9285_11))) | 788 | AR_SREV_REVISION_9285_11))) |
787 | #define AR_SREV_9285_12(_ah) \ | 789 | #define AR_SREV_9285_12(_ah) \ |
788 | (AR_SREV_9280(ah) && \ | 790 | (AR_SREV_9285(ah) && \ |
789 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9285_12)) | 791 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9285_12)) |
790 | #define AR_SREV_9285_12_OR_LATER(_ah) \ | 792 | #define AR_SREV_9285_12_OR_LATER(_ah) \ |
791 | (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9285) || \ | 793 | (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9285) || \ |
diff --git a/drivers/net/wireless/ath9k/regd.c b/drivers/net/wireless/ath9k/regd.c index 639da975bf54..b8f9b6d6bec4 100644 --- a/drivers/net/wireless/ath9k/regd.c +++ b/drivers/net/wireless/ath9k/regd.c | |||
@@ -168,8 +168,9 @@ static bool ath9k_is_radar_freq(u16 center_freq) | |||
168 | * received a beacon on a channel we can enable active scan and | 168 | * received a beacon on a channel we can enable active scan and |
169 | * adhoc (or beaconing). | 169 | * adhoc (or beaconing). |
170 | */ | 170 | */ |
171 | static void ath9k_reg_apply_beaconing_flags(struct wiphy *wiphy, | 171 | static void ath9k_reg_apply_beaconing_flags( |
172 | enum reg_set_by setby) | 172 | struct wiphy *wiphy, |
173 | enum nl80211_reg_initiator initiator) | ||
173 | { | 174 | { |
174 | enum ieee80211_band band; | 175 | enum ieee80211_band band; |
175 | struct ieee80211_supported_band *sband; | 176 | struct ieee80211_supported_band *sband; |
@@ -194,7 +195,7 @@ static void ath9k_reg_apply_beaconing_flags(struct wiphy *wiphy, | |||
194 | (ch->flags & IEEE80211_CHAN_RADAR)) | 195 | (ch->flags & IEEE80211_CHAN_RADAR)) |
195 | continue; | 196 | continue; |
196 | 197 | ||
197 | if (setby == REGDOM_SET_BY_COUNTRY_IE) { | 198 | if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) { |
198 | r = freq_reg_info(wiphy, ch->center_freq, | 199 | r = freq_reg_info(wiphy, ch->center_freq, |
199 | &bandwidth, ®_rule); | 200 | &bandwidth, ®_rule); |
200 | if (r) | 201 | if (r) |
@@ -226,8 +227,9 @@ static void ath9k_reg_apply_beaconing_flags(struct wiphy *wiphy, | |||
226 | } | 227 | } |
227 | 228 | ||
228 | /* Allows active scan scan on Ch 12 and 13 */ | 229 | /* Allows active scan scan on Ch 12 and 13 */ |
229 | static void ath9k_reg_apply_active_scan_flags(struct wiphy *wiphy, | 230 | static void ath9k_reg_apply_active_scan_flags( |
230 | enum reg_set_by setby) | 231 | struct wiphy *wiphy, |
232 | enum nl80211_reg_initiator initiator) | ||
231 | { | 233 | { |
232 | struct ieee80211_supported_band *sband; | 234 | struct ieee80211_supported_band *sband; |
233 | struct ieee80211_channel *ch; | 235 | struct ieee80211_channel *ch; |
@@ -241,7 +243,7 @@ static void ath9k_reg_apply_active_scan_flags(struct wiphy *wiphy, | |||
241 | * If no country IE has been received always enable active scan | 243 | * If no country IE has been received always enable active scan |
242 | * on these channels. This is only done for specific regulatory SKUs | 244 | * on these channels. This is only done for specific regulatory SKUs |
243 | */ | 245 | */ |
244 | if (setby != REGDOM_SET_BY_COUNTRY_IE) { | 246 | if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) { |
245 | ch = &sband->channels[11]; /* CH 12 */ | 247 | ch = &sband->channels[11]; /* CH 12 */ |
246 | if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) | 248 | if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) |
247 | ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; | 249 | ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; |
@@ -308,7 +310,8 @@ void ath9k_reg_apply_radar_flags(struct wiphy *wiphy) | |||
308 | } | 310 | } |
309 | } | 311 | } |
310 | 312 | ||
311 | void ath9k_reg_apply_world_flags(struct wiphy *wiphy, enum reg_set_by setby) | 313 | void ath9k_reg_apply_world_flags(struct wiphy *wiphy, |
314 | enum nl80211_reg_initiator initiator) | ||
312 | { | 315 | { |
313 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); | 316 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); |
314 | struct ath_wiphy *aphy = hw->priv; | 317 | struct ath_wiphy *aphy = hw->priv; |
@@ -320,11 +323,11 @@ void ath9k_reg_apply_world_flags(struct wiphy *wiphy, enum reg_set_by setby) | |||
320 | case 0x63: | 323 | case 0x63: |
321 | case 0x66: | 324 | case 0x66: |
322 | case 0x67: | 325 | case 0x67: |
323 | ath9k_reg_apply_beaconing_flags(wiphy, setby); | 326 | ath9k_reg_apply_beaconing_flags(wiphy, initiator); |
324 | break; | 327 | break; |
325 | case 0x68: | 328 | case 0x68: |
326 | ath9k_reg_apply_beaconing_flags(wiphy, setby); | 329 | ath9k_reg_apply_beaconing_flags(wiphy, initiator); |
327 | ath9k_reg_apply_active_scan_flags(wiphy, setby); | 330 | ath9k_reg_apply_active_scan_flags(wiphy, initiator); |
328 | break; | 331 | break; |
329 | } | 332 | } |
330 | return; | 333 | return; |
@@ -340,12 +343,11 @@ int ath9k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) | |||
340 | ath9k_reg_apply_radar_flags(wiphy); | 343 | ath9k_reg_apply_radar_flags(wiphy); |
341 | 344 | ||
342 | switch (request->initiator) { | 345 | switch (request->initiator) { |
343 | case REGDOM_SET_BY_DRIVER: | 346 | case NL80211_REGDOM_SET_BY_DRIVER: |
344 | case REGDOM_SET_BY_INIT: | 347 | case NL80211_REGDOM_SET_BY_CORE: |
345 | case REGDOM_SET_BY_CORE: | 348 | case NL80211_REGDOM_SET_BY_USER: |
346 | case REGDOM_SET_BY_USER: | ||
347 | break; | 349 | break; |
348 | case REGDOM_SET_BY_COUNTRY_IE: | 350 | case NL80211_REGDOM_SET_BY_COUNTRY_IE: |
349 | if (ath9k_is_world_regd(sc->sc_ah)) | 351 | if (ath9k_is_world_regd(sc->sc_ah)) |
350 | ath9k_reg_apply_world_flags(wiphy, request->initiator); | 352 | ath9k_reg_apply_world_flags(wiphy, request->initiator); |
351 | break; | 353 | break; |
diff --git a/drivers/net/wireless/ath9k/regd.h b/drivers/net/wireless/ath9k/regd.h index d48160d0c0e9..8f885f3bc8df 100644 --- a/drivers/net/wireless/ath9k/regd.h +++ b/drivers/net/wireless/ath9k/regd.h | |||
@@ -236,7 +236,8 @@ enum CountryCode { | |||
236 | bool ath9k_is_world_regd(struct ath_hw *ah); | 236 | bool ath9k_is_world_regd(struct ath_hw *ah); |
237 | const struct ieee80211_regdomain *ath9k_world_regdomain(struct ath_hw *ah); | 237 | const struct ieee80211_regdomain *ath9k_world_regdomain(struct ath_hw *ah); |
238 | const struct ieee80211_regdomain *ath9k_default_world_regdomain(void); | 238 | const struct ieee80211_regdomain *ath9k_default_world_regdomain(void); |
239 | void ath9k_reg_apply_world_flags(struct wiphy *wiphy, enum reg_set_by setby); | 239 | void ath9k_reg_apply_world_flags(struct wiphy *wiphy, |
240 | enum nl80211_reg_initiator initiator); | ||
240 | void ath9k_reg_apply_radar_flags(struct wiphy *wiphy); | 241 | void ath9k_reg_apply_radar_flags(struct wiphy *wiphy); |
241 | int ath9k_regd_init(struct ath_hw *ah); | 242 | int ath9k_regd_init(struct ath_hw *ah); |
242 | bool ath9k_regd_is_eeprom_valid(struct ath_hw *ah); | 243 | bool ath9k_regd_is_eeprom_valid(struct ath_hw *ah); |
diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index a82d2ab7c3a0..e3f376611f85 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c | |||
@@ -55,9 +55,9 @@ static u32 bits_per_symbol[][2] = { | |||
55 | 55 | ||
56 | #define IS_HT_RATE(_rate) ((_rate) & 0x80) | 56 | #define IS_HT_RATE(_rate) ((_rate) & 0x80) |
57 | 57 | ||
58 | static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, | 58 | static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq, |
59 | struct ath_atx_tid *tid, | 59 | struct ath_atx_tid *tid, |
60 | struct list_head *bf_head); | 60 | struct list_head *bf_head); |
61 | static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, | 61 | static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, |
62 | struct list_head *bf_q, | 62 | struct list_head *bf_q, |
63 | int txok, int sendbar); | 63 | int txok, int sendbar); |
@@ -152,7 +152,7 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) | |||
152 | bf = list_first_entry(&tid->buf_q, struct ath_buf, list); | 152 | bf = list_first_entry(&tid->buf_q, struct ath_buf, list); |
153 | ASSERT(!bf_isretried(bf)); | 153 | ASSERT(!bf_isretried(bf)); |
154 | list_move_tail(&bf->list, &bf_head); | 154 | list_move_tail(&bf->list, &bf_head); |
155 | ath_tx_send_normal(sc, txq, tid, &bf_head); | 155 | ath_tx_send_ht_normal(sc, txq, tid, &bf_head); |
156 | } | 156 | } |
157 | 157 | ||
158 | spin_unlock_bh(&txq->axq_lock); | 158 | spin_unlock_bh(&txq->axq_lock); |
@@ -891,7 +891,7 @@ struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb) | |||
891 | spin_lock_bh(&txq->axq_lock); | 891 | spin_lock_bh(&txq->axq_lock); |
892 | 892 | ||
893 | if (txq->axq_depth >= (ATH_TXBUF - 20)) { | 893 | if (txq->axq_depth >= (ATH_TXBUF - 20)) { |
894 | DPRINTF(sc, ATH_DBG_FATAL, | 894 | DPRINTF(sc, ATH_DBG_XMIT, |
895 | "TX queue: %d is full, depth: %d\n", | 895 | "TX queue: %d is full, depth: %d\n", |
896 | qnum, txq->axq_depth); | 896 | qnum, txq->axq_depth); |
897 | ieee80211_stop_queue(sc->hw, skb_get_queue_mapping(skb)); | 897 | ieee80211_stop_queue(sc->hw, skb_get_queue_mapping(skb)); |
@@ -1238,9 +1238,9 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, | |||
1238 | ath_tx_txqaddbuf(sc, txctl->txq, bf_head); | 1238 | ath_tx_txqaddbuf(sc, txctl->txq, bf_head); |
1239 | } | 1239 | } |
1240 | 1240 | ||
1241 | static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, | 1241 | static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq, |
1242 | struct ath_atx_tid *tid, | 1242 | struct ath_atx_tid *tid, |
1243 | struct list_head *bf_head) | 1243 | struct list_head *bf_head) |
1244 | { | 1244 | { |
1245 | struct ath_buf *bf; | 1245 | struct ath_buf *bf; |
1246 | 1246 | ||
@@ -1256,6 +1256,19 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, | |||
1256 | ath_tx_txqaddbuf(sc, txq, bf_head); | 1256 | ath_tx_txqaddbuf(sc, txq, bf_head); |
1257 | } | 1257 | } |
1258 | 1258 | ||
1259 | static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, | ||
1260 | struct list_head *bf_head) | ||
1261 | { | ||
1262 | struct ath_buf *bf; | ||
1263 | |||
1264 | bf = list_first_entry(bf_head, struct ath_buf, list); | ||
1265 | |||
1266 | bf->bf_lastbf = bf; | ||
1267 | bf->bf_nframes = 1; | ||
1268 | ath_buf_set_rate(sc, bf); | ||
1269 | ath_tx_txqaddbuf(sc, txq, bf_head); | ||
1270 | } | ||
1271 | |||
1259 | static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb) | 1272 | static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb) |
1260 | { | 1273 | { |
1261 | struct ieee80211_hdr *hdr; | 1274 | struct ieee80211_hdr *hdr; |
@@ -1522,8 +1535,7 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, | |||
1522 | 1535 | ||
1523 | bf->bf_frmlen = skb->len + FCS_LEN - (hdrlen & 3); | 1536 | bf->bf_frmlen = skb->len + FCS_LEN - (hdrlen & 3); |
1524 | 1537 | ||
1525 | if ((conf_is_ht(&sc->hw->conf) && !is_pae(skb) && | 1538 | if (conf_is_ht(&sc->hw->conf) && !is_pae(skb)) |
1526 | (tx_info->flags & IEEE80211_TX_CTL_AMPDU))) | ||
1527 | bf->bf_state.bf_type |= BUF_HT; | 1539 | bf->bf_state.bf_type |= BUF_HT; |
1528 | 1540 | ||
1529 | bf->bf_flags = setup_tx_flags(sc, skb, txctl->txq); | 1541 | bf->bf_flags = setup_tx_flags(sc, skb, txctl->txq); |
@@ -1560,14 +1572,17 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, | |||
1560 | { | 1572 | { |
1561 | struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; | 1573 | struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; |
1562 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 1574 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
1575 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
1563 | struct ath_node *an = NULL; | 1576 | struct ath_node *an = NULL; |
1564 | struct list_head bf_head; | 1577 | struct list_head bf_head; |
1565 | struct ath_desc *ds; | 1578 | struct ath_desc *ds; |
1566 | struct ath_atx_tid *tid; | 1579 | struct ath_atx_tid *tid; |
1567 | struct ath_hw *ah = sc->sc_ah; | 1580 | struct ath_hw *ah = sc->sc_ah; |
1568 | int frm_type; | 1581 | int frm_type; |
1582 | __le16 fc; | ||
1569 | 1583 | ||
1570 | frm_type = get_hw_packet_type(skb); | 1584 | frm_type = get_hw_packet_type(skb); |
1585 | fc = hdr->frame_control; | ||
1571 | 1586 | ||
1572 | INIT_LIST_HEAD(&bf_head); | 1587 | INIT_LIST_HEAD(&bf_head); |
1573 | list_add_tail(&bf->list, &bf_head); | 1588 | list_add_tail(&bf->list, &bf_head); |
@@ -1592,6 +1607,11 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, | |||
1592 | an = (struct ath_node *)tx_info->control.sta->drv_priv; | 1607 | an = (struct ath_node *)tx_info->control.sta->drv_priv; |
1593 | tid = ATH_AN_2_TID(an, bf->bf_tidno); | 1608 | tid = ATH_AN_2_TID(an, bf->bf_tidno); |
1594 | 1609 | ||
1610 | if (!ieee80211_is_data_qos(fc)) { | ||
1611 | ath_tx_send_normal(sc, txctl->txq, &bf_head); | ||
1612 | goto tx_done; | ||
1613 | } | ||
1614 | |||
1595 | if (ath_aggr_query(sc, an, bf->bf_tidno)) { | 1615 | if (ath_aggr_query(sc, an, bf->bf_tidno)) { |
1596 | /* | 1616 | /* |
1597 | * Try aggregation if it's a unicast data frame | 1617 | * Try aggregation if it's a unicast data frame |
@@ -1603,17 +1623,14 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, | |||
1603 | * Send this frame as regular when ADDBA | 1623 | * Send this frame as regular when ADDBA |
1604 | * exchange is neither complete nor pending. | 1624 | * exchange is neither complete nor pending. |
1605 | */ | 1625 | */ |
1606 | ath_tx_send_normal(sc, txctl->txq, | 1626 | ath_tx_send_ht_normal(sc, txctl->txq, |
1607 | tid, &bf_head); | 1627 | tid, &bf_head); |
1608 | } | 1628 | } |
1609 | } else { | 1629 | } else { |
1610 | bf->bf_lastbf = bf; | 1630 | ath_tx_send_normal(sc, txctl->txq, &bf_head); |
1611 | bf->bf_nframes = 1; | ||
1612 | |||
1613 | ath_buf_set_rate(sc, bf); | ||
1614 | ath_tx_txqaddbuf(sc, txctl->txq, &bf_head); | ||
1615 | } | 1631 | } |
1616 | 1632 | ||
1633 | tx_done: | ||
1617 | spin_unlock_bh(&txctl->txq->axq_lock); | 1634 | spin_unlock_bh(&txctl->txq->axq_lock); |
1618 | } | 1635 | } |
1619 | 1636 | ||
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index 91930a2c3c6b..b06835a621a3 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c | |||
@@ -2,8 +2,8 @@ | |||
2 | 2 | ||
3 | Driver for Atmel at76c502 at76c504 and at76c506 wireless cards. | 3 | Driver for Atmel at76c502 at76c504 and at76c506 wireless cards. |
4 | 4 | ||
5 | Copyright 2000-2001 ATMEL Corporation. | 5 | Copyright 2000-2001 ATMEL Corporation. |
6 | Copyright 2003-2004 Simon Kelley. | 6 | Copyright 2003-2004 Simon Kelley. |
7 | 7 | ||
8 | This code was developed from version 2.1.1 of the Atmel drivers, | 8 | This code was developed from version 2.1.1 of the Atmel drivers, |
9 | released by Atmel corp. under the GPL in December 2002. It also | 9 | released by Atmel corp. under the GPL in December 2002. It also |
@@ -89,15 +89,15 @@ static struct { | |||
89 | const char *fw_file; | 89 | const char *fw_file; |
90 | const char *fw_file_ext; | 90 | const char *fw_file_ext; |
91 | } fw_table[] = { | 91 | } fw_table[] = { |
92 | { ATMEL_FW_TYPE_502, "atmel_at76c502", "bin" }, | 92 | { ATMEL_FW_TYPE_502, "atmel_at76c502", "bin" }, |
93 | { ATMEL_FW_TYPE_502D, "atmel_at76c502d", "bin" }, | 93 | { ATMEL_FW_TYPE_502D, "atmel_at76c502d", "bin" }, |
94 | { ATMEL_FW_TYPE_502E, "atmel_at76c502e", "bin" }, | 94 | { ATMEL_FW_TYPE_502E, "atmel_at76c502e", "bin" }, |
95 | { ATMEL_FW_TYPE_502_3COM, "atmel_at76c502_3com", "bin" }, | 95 | { ATMEL_FW_TYPE_502_3COM, "atmel_at76c502_3com", "bin" }, |
96 | { ATMEL_FW_TYPE_504, "atmel_at76c504", "bin" }, | 96 | { ATMEL_FW_TYPE_504, "atmel_at76c504", "bin" }, |
97 | { ATMEL_FW_TYPE_504_2958, "atmel_at76c504_2958", "bin" }, | 97 | { ATMEL_FW_TYPE_504_2958, "atmel_at76c504_2958", "bin" }, |
98 | { ATMEL_FW_TYPE_504A_2958,"atmel_at76c504a_2958","bin" }, | 98 | { ATMEL_FW_TYPE_504A_2958, "atmel_at76c504a_2958", "bin" }, |
99 | { ATMEL_FW_TYPE_506, "atmel_at76c506", "bin" }, | 99 | { ATMEL_FW_TYPE_506, "atmel_at76c506", "bin" }, |
100 | { ATMEL_FW_TYPE_NONE, NULL, NULL } | 100 | { ATMEL_FW_TYPE_NONE, NULL, NULL } |
101 | }; | 101 | }; |
102 | 102 | ||
103 | #define MAX_SSID_LENGTH 32 | 103 | #define MAX_SSID_LENGTH 32 |
@@ -106,60 +106,60 @@ static struct { | |||
106 | #define MAX_BSS_ENTRIES 64 | 106 | #define MAX_BSS_ENTRIES 64 |
107 | 107 | ||
108 | /* registers */ | 108 | /* registers */ |
109 | #define GCR 0x00 // (SIR0) General Configuration Register | 109 | #define GCR 0x00 /* (SIR0) General Configuration Register */ |
110 | #define BSR 0x02 // (SIR1) Bank Switching Select Register | 110 | #define BSR 0x02 /* (SIR1) Bank Switching Select Register */ |
111 | #define AR 0x04 | 111 | #define AR 0x04 |
112 | #define DR 0x08 | 112 | #define DR 0x08 |
113 | #define MR1 0x12 // Mirror Register 1 | 113 | #define MR1 0x12 /* Mirror Register 1 */ |
114 | #define MR2 0x14 // Mirror Register 2 | 114 | #define MR2 0x14 /* Mirror Register 2 */ |
115 | #define MR3 0x16 // Mirror Register 3 | 115 | #define MR3 0x16 /* Mirror Register 3 */ |
116 | #define MR4 0x18 // Mirror Register 4 | 116 | #define MR4 0x18 /* Mirror Register 4 */ |
117 | 117 | ||
118 | #define GPR1 0x0c | 118 | #define GPR1 0x0c |
119 | #define GPR2 0x0e | 119 | #define GPR2 0x0e |
120 | #define GPR3 0x10 | 120 | #define GPR3 0x10 |
121 | // | 121 | /* |
122 | // Constants for the GCR register. | 122 | * Constants for the GCR register. |
123 | // | 123 | */ |
124 | #define GCR_REMAP 0x0400 // Remap internal SRAM to 0 | 124 | #define GCR_REMAP 0x0400 /* Remap internal SRAM to 0 */ |
125 | #define GCR_SWRES 0x0080 // BIU reset (ARM and PAI are NOT reset) | 125 | #define GCR_SWRES 0x0080 /* BIU reset (ARM and PAI are NOT reset) */ |
126 | #define GCR_CORES 0x0060 // Core Reset (ARM and PAI are reset) | 126 | #define GCR_CORES 0x0060 /* Core Reset (ARM and PAI are reset) */ |
127 | #define GCR_ENINT 0x0002 // Enable Interrupts | 127 | #define GCR_ENINT 0x0002 /* Enable Interrupts */ |
128 | #define GCR_ACKINT 0x0008 // Acknowledge Interrupts | 128 | #define GCR_ACKINT 0x0008 /* Acknowledge Interrupts */ |
129 | 129 | ||
130 | #define BSS_SRAM 0x0200 // AMBA module selection --> SRAM | 130 | #define BSS_SRAM 0x0200 /* AMBA module selection --> SRAM */ |
131 | #define BSS_IRAM 0x0100 // AMBA module selection --> IRAM | 131 | #define BSS_IRAM 0x0100 /* AMBA module selection --> IRAM */ |
132 | // | 132 | /* |
133 | // Constants for the MR registers. | 133 | *Constants for the MR registers. |
134 | // | 134 | */ |
135 | #define MAC_INIT_COMPLETE 0x0001 // MAC init has been completed | 135 | #define MAC_INIT_COMPLETE 0x0001 /* MAC init has been completed */ |
136 | #define MAC_BOOT_COMPLETE 0x0010 // MAC boot has been completed | 136 | #define MAC_BOOT_COMPLETE 0x0010 /* MAC boot has been completed */ |
137 | #define MAC_INIT_OK 0x0002 // MAC boot has been completed | 137 | #define MAC_INIT_OK 0x0002 /* MAC boot has been completed */ |
138 | 138 | ||
139 | #define MIB_MAX_DATA_BYTES 212 | 139 | #define MIB_MAX_DATA_BYTES 212 |
140 | #define MIB_HEADER_SIZE 4 /* first four fields */ | 140 | #define MIB_HEADER_SIZE 4 /* first four fields */ |
141 | 141 | ||
142 | struct get_set_mib { | 142 | struct get_set_mib { |
143 | u8 type; | 143 | u8 type; |
144 | u8 size; | 144 | u8 size; |
145 | u8 index; | 145 | u8 index; |
146 | u8 reserved; | 146 | u8 reserved; |
147 | u8 data[MIB_MAX_DATA_BYTES]; | 147 | u8 data[MIB_MAX_DATA_BYTES]; |
148 | }; | 148 | }; |
149 | 149 | ||
150 | struct rx_desc { | 150 | struct rx_desc { |
151 | u32 Next; | 151 | u32 Next; |
152 | u16 MsduPos; | 152 | u16 MsduPos; |
153 | u16 MsduSize; | 153 | u16 MsduSize; |
154 | 154 | ||
155 | u8 State; | 155 | u8 State; |
156 | u8 Status; | 156 | u8 Status; |
157 | u8 Rate; | 157 | u8 Rate; |
158 | u8 Rssi; | 158 | u8 Rssi; |
159 | u8 LinkQuality; | 159 | u8 LinkQuality; |
160 | u8 PreambleType; | 160 | u8 PreambleType; |
161 | u16 Duration; | 161 | u16 Duration; |
162 | u32 RxTime; | 162 | u32 RxTime; |
163 | }; | 163 | }; |
164 | 164 | ||
165 | #define RX_DESC_FLAG_VALID 0x80 | 165 | #define RX_DESC_FLAG_VALID 0x80 |
@@ -192,7 +192,7 @@ struct tx_desc { | |||
192 | u8 KeyIndex; | 192 | u8 KeyIndex; |
193 | u8 ChiperType; | 193 | u8 ChiperType; |
194 | u8 ChipreLength; | 194 | u8 ChipreLength; |
195 | u8 Reserved1; | 195 | u8 Reserved1; |
196 | 196 | ||
197 | u8 Reserved; | 197 | u8 Reserved; |
198 | u8 PacketType; | 198 | u8 PacketType; |
@@ -212,9 +212,9 @@ struct tx_desc { | |||
212 | #define TX_DESC_PACKET_TYPE_OFFSET 17 | 212 | #define TX_DESC_PACKET_TYPE_OFFSET 17 |
213 | #define TX_DESC_HOST_LENGTH_OFFSET 18 | 213 | #define TX_DESC_HOST_LENGTH_OFFSET 18 |
214 | 214 | ||
215 | /////////////////////////////////////////////////////// | 215 | /* |
216 | // Host-MAC interface | 216 | * Host-MAC interface |
217 | /////////////////////////////////////////////////////// | 217 | */ |
218 | 218 | ||
219 | #define TX_STATUS_SUCCESS 0x00 | 219 | #define TX_STATUS_SUCCESS 0x00 |
220 | 220 | ||
@@ -226,14 +226,14 @@ struct tx_desc { | |||
226 | #define TX_PACKET_TYPE_DATA 0x01 | 226 | #define TX_PACKET_TYPE_DATA 0x01 |
227 | #define TX_PACKET_TYPE_MGMT 0x02 | 227 | #define TX_PACKET_TYPE_MGMT 0x02 |
228 | 228 | ||
229 | #define ISR_EMPTY 0x00 // no bits set in ISR | 229 | #define ISR_EMPTY 0x00 /* no bits set in ISR */ |
230 | #define ISR_TxCOMPLETE 0x01 // packet transmitted | 230 | #define ISR_TxCOMPLETE 0x01 /* packet transmitted */ |
231 | #define ISR_RxCOMPLETE 0x02 // packet received | 231 | #define ISR_RxCOMPLETE 0x02 /* packet received */ |
232 | #define ISR_RxFRAMELOST 0x04 // Rx Frame lost | 232 | #define ISR_RxFRAMELOST 0x04 /* Rx Frame lost */ |
233 | #define ISR_FATAL_ERROR 0x08 // Fatal error | 233 | #define ISR_FATAL_ERROR 0x08 /* Fatal error */ |
234 | #define ISR_COMMAND_COMPLETE 0x10 // command completed | 234 | #define ISR_COMMAND_COMPLETE 0x10 /* command completed */ |
235 | #define ISR_OUT_OF_RANGE 0x20 // command completed | 235 | #define ISR_OUT_OF_RANGE 0x20 /* command completed */ |
236 | #define ISR_IBSS_MERGE 0x40 // (4.1.2.30): IBSS merge | 236 | #define ISR_IBSS_MERGE 0x40 /* (4.1.2.30): IBSS merge */ |
237 | #define ISR_GENERIC_IRQ 0x80 | 237 | #define ISR_GENERIC_IRQ 0x80 |
238 | 238 | ||
239 | #define Local_Mib_Type 0x01 | 239 | #define Local_Mib_Type 0x01 |
@@ -311,22 +311,22 @@ struct tx_desc { | |||
311 | #define MAX_ENCRYPTION_KEYS 4 | 311 | #define MAX_ENCRYPTION_KEYS 4 |
312 | #define MAX_ENCRYPTION_KEY_SIZE 40 | 312 | #define MAX_ENCRYPTION_KEY_SIZE 40 |
313 | 313 | ||
314 | /////////////////////////////////////////////////////////////////////////// | 314 | /* |
315 | // 802.11 related definitions | 315 | * 802.11 related definitions |
316 | /////////////////////////////////////////////////////////////////////////// | 316 | */ |
317 | 317 | ||
318 | // | 318 | /* |
319 | // Regulatory Domains | 319 | * Regulatory Domains |
320 | // | 320 | */ |
321 | 321 | ||
322 | #define REG_DOMAIN_FCC 0x10 //Channels 1-11 USA | 322 | #define REG_DOMAIN_FCC 0x10 /* Channels 1-11 USA */ |
323 | #define REG_DOMAIN_DOC 0x20 //Channel 1-11 Canada | 323 | #define REG_DOMAIN_DOC 0x20 /* Channel 1-11 Canada */ |
324 | #define REG_DOMAIN_ETSI 0x30 //Channel 1-13 Europe (ex Spain/France) | 324 | #define REG_DOMAIN_ETSI 0x30 /* Channel 1-13 Europe (ex Spain/France) */ |
325 | #define REG_DOMAIN_SPAIN 0x31 //Channel 10-11 Spain | 325 | #define REG_DOMAIN_SPAIN 0x31 /* Channel 10-11 Spain */ |
326 | #define REG_DOMAIN_FRANCE 0x32 //Channel 10-13 France | 326 | #define REG_DOMAIN_FRANCE 0x32 /* Channel 10-13 France */ |
327 | #define REG_DOMAIN_MKK 0x40 //Channel 14 Japan | 327 | #define REG_DOMAIN_MKK 0x40 /* Channel 14 Japan */ |
328 | #define REG_DOMAIN_MKK1 0x41 //Channel 1-14 Japan(MKK1) | 328 | #define REG_DOMAIN_MKK1 0x41 /* Channel 1-14 Japan(MKK1) */ |
329 | #define REG_DOMAIN_ISRAEL 0x50 //Channel 3-9 ISRAEL | 329 | #define REG_DOMAIN_ISRAEL 0x50 /* Channel 3-9 ISRAEL */ |
330 | 330 | ||
331 | #define BSS_TYPE_AD_HOC 1 | 331 | #define BSS_TYPE_AD_HOC 1 |
332 | #define BSS_TYPE_INFRASTRUCTURE 2 | 332 | #define BSS_TYPE_INFRASTRUCTURE 2 |
@@ -364,13 +364,13 @@ struct tx_desc { | |||
364 | #define CIPHER_SUITE_CCX 4 | 364 | #define CIPHER_SUITE_CCX 4 |
365 | #define CIPHER_SUITE_WEP_128 5 | 365 | #define CIPHER_SUITE_WEP_128 5 |
366 | 366 | ||
367 | // | 367 | /* |
368 | // IFACE MACROS & definitions | 368 | * IFACE MACROS & definitions |
369 | // | 369 | */ |
370 | // | ||
371 | 370 | ||
372 | // FuncCtrl field: | 371 | /* |
373 | // | 372 | * FuncCtrl field: |
373 | */ | ||
374 | #define FUNC_CTRL_TxENABLE 0x10 | 374 | #define FUNC_CTRL_TxENABLE 0x10 |
375 | #define FUNC_CTRL_RxENABLE 0x20 | 375 | #define FUNC_CTRL_RxENABLE 0x20 |
376 | #define FUNC_CTRL_INIT_COMPLETE 0x01 | 376 | #define FUNC_CTRL_INIT_COMPLETE 0x01 |
@@ -378,48 +378,48 @@ struct tx_desc { | |||
378 | /* A stub firmware image which reads the MAC address from NVRAM on the card. | 378 | /* A stub firmware image which reads the MAC address from NVRAM on the card. |
379 | For copyright information and source see the end of this file. */ | 379 | For copyright information and source see the end of this file. */ |
380 | static u8 mac_reader[] = { | 380 | static u8 mac_reader[] = { |
381 | 0x06,0x00,0x00,0xea,0x04,0x00,0x00,0xea,0x03,0x00,0x00,0xea,0x02,0x00,0x00,0xea, | 381 | 0x06, 0x00, 0x00, 0xea, 0x04, 0x00, 0x00, 0xea, 0x03, 0x00, 0x00, 0xea, 0x02, 0x00, 0x00, 0xea, |
382 | 0x01,0x00,0x00,0xea,0x00,0x00,0x00,0xea,0xff,0xff,0xff,0xea,0xfe,0xff,0xff,0xea, | 382 | 0x01, 0x00, 0x00, 0xea, 0x00, 0x00, 0x00, 0xea, 0xff, 0xff, 0xff, 0xea, 0xfe, 0xff, 0xff, 0xea, |
383 | 0xd3,0x00,0xa0,0xe3,0x00,0xf0,0x21,0xe1,0x0e,0x04,0xa0,0xe3,0x00,0x10,0xa0,0xe3, | 383 | 0xd3, 0x00, 0xa0, 0xe3, 0x00, 0xf0, 0x21, 0xe1, 0x0e, 0x04, 0xa0, 0xe3, 0x00, 0x10, 0xa0, 0xe3, |
384 | 0x81,0x11,0xa0,0xe1,0x00,0x10,0x81,0xe3,0x00,0x10,0x80,0xe5,0x1c,0x10,0x90,0xe5, | 384 | 0x81, 0x11, 0xa0, 0xe1, 0x00, 0x10, 0x81, 0xe3, 0x00, 0x10, 0x80, 0xe5, 0x1c, 0x10, 0x90, 0xe5, |
385 | 0x10,0x10,0xc1,0xe3,0x1c,0x10,0x80,0xe5,0x01,0x10,0xa0,0xe3,0x08,0x10,0x80,0xe5, | 385 | 0x10, 0x10, 0xc1, 0xe3, 0x1c, 0x10, 0x80, 0xe5, 0x01, 0x10, 0xa0, 0xe3, 0x08, 0x10, 0x80, 0xe5, |
386 | 0x02,0x03,0xa0,0xe3,0x00,0x10,0xa0,0xe3,0xb0,0x10,0xc0,0xe1,0xb4,0x10,0xc0,0xe1, | 386 | 0x02, 0x03, 0xa0, 0xe3, 0x00, 0x10, 0xa0, 0xe3, 0xb0, 0x10, 0xc0, 0xe1, 0xb4, 0x10, 0xc0, 0xe1, |
387 | 0xb8,0x10,0xc0,0xe1,0xbc,0x10,0xc0,0xe1,0x56,0xdc,0xa0,0xe3,0x21,0x00,0x00,0xeb, | 387 | 0xb8, 0x10, 0xc0, 0xe1, 0xbc, 0x10, 0xc0, 0xe1, 0x56, 0xdc, 0xa0, 0xe3, 0x21, 0x00, 0x00, 0xeb, |
388 | 0x0a,0x00,0xa0,0xe3,0x1a,0x00,0x00,0xeb,0x10,0x00,0x00,0xeb,0x07,0x00,0x00,0xeb, | 388 | 0x0a, 0x00, 0xa0, 0xe3, 0x1a, 0x00, 0x00, 0xeb, 0x10, 0x00, 0x00, 0xeb, 0x07, 0x00, 0x00, 0xeb, |
389 | 0x02,0x03,0xa0,0xe3,0x02,0x14,0xa0,0xe3,0xb4,0x10,0xc0,0xe1,0x4c,0x10,0x9f,0xe5, | 389 | 0x02, 0x03, 0xa0, 0xe3, 0x02, 0x14, 0xa0, 0xe3, 0xb4, 0x10, 0xc0, 0xe1, 0x4c, 0x10, 0x9f, 0xe5, |
390 | 0xbc,0x10,0xc0,0xe1,0x10,0x10,0xa0,0xe3,0xb8,0x10,0xc0,0xe1,0xfe,0xff,0xff,0xea, | 390 | 0xbc, 0x10, 0xc0, 0xe1, 0x10, 0x10, 0xa0, 0xe3, 0xb8, 0x10, 0xc0, 0xe1, 0xfe, 0xff, 0xff, 0xea, |
391 | 0x00,0x40,0x2d,0xe9,0x00,0x20,0xa0,0xe3,0x02,0x3c,0xa0,0xe3,0x00,0x10,0xa0,0xe3, | 391 | 0x00, 0x40, 0x2d, 0xe9, 0x00, 0x20, 0xa0, 0xe3, 0x02, 0x3c, 0xa0, 0xe3, 0x00, 0x10, 0xa0, 0xe3, |
392 | 0x28,0x00,0x9f,0xe5,0x37,0x00,0x00,0xeb,0x00,0x40,0xbd,0xe8,0x1e,0xff,0x2f,0xe1, | 392 | 0x28, 0x00, 0x9f, 0xe5, 0x37, 0x00, 0x00, 0xeb, 0x00, 0x40, 0xbd, 0xe8, 0x1e, 0xff, 0x2f, 0xe1, |
393 | 0x00,0x40,0x2d,0xe9,0x12,0x2e,0xa0,0xe3,0x06,0x30,0xa0,0xe3,0x00,0x10,0xa0,0xe3, | 393 | 0x00, 0x40, 0x2d, 0xe9, 0x12, 0x2e, 0xa0, 0xe3, 0x06, 0x30, 0xa0, 0xe3, 0x00, 0x10, 0xa0, 0xe3, |
394 | 0x02,0x04,0xa0,0xe3,0x2f,0x00,0x00,0xeb,0x00,0x40,0xbd,0xe8,0x1e,0xff,0x2f,0xe1, | 394 | 0x02, 0x04, 0xa0, 0xe3, 0x2f, 0x00, 0x00, 0xeb, 0x00, 0x40, 0xbd, 0xe8, 0x1e, 0xff, 0x2f, 0xe1, |
395 | 0x00,0x02,0x00,0x02,0x80,0x01,0x90,0xe0,0x01,0x00,0x00,0x0a,0x01,0x00,0x50,0xe2, | 395 | 0x00, 0x02, 0x00, 0x02, 0x80, 0x01, 0x90, 0xe0, 0x01, 0x00, 0x00, 0x0a, 0x01, 0x00, 0x50, 0xe2, |
396 | 0xfc,0xff,0xff,0xea,0x1e,0xff,0x2f,0xe1,0x80,0x10,0xa0,0xe3,0xf3,0x06,0xa0,0xe3, | 396 | 0xfc, 0xff, 0xff, 0xea, 0x1e, 0xff, 0x2f, 0xe1, 0x80, 0x10, 0xa0, 0xe3, 0xf3, 0x06, 0xa0, 0xe3, |
397 | 0x00,0x10,0x80,0xe5,0x00,0x10,0xa0,0xe3,0x00,0x10,0x80,0xe5,0x01,0x10,0xa0,0xe3, | 397 | 0x00, 0x10, 0x80, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x80, 0xe5, 0x01, 0x10, 0xa0, 0xe3, |
398 | 0x04,0x10,0x80,0xe5,0x00,0x10,0x80,0xe5,0x0e,0x34,0xa0,0xe3,0x1c,0x10,0x93,0xe5, | 398 | 0x04, 0x10, 0x80, 0xe5, 0x00, 0x10, 0x80, 0xe5, 0x0e, 0x34, 0xa0, 0xe3, 0x1c, 0x10, 0x93, 0xe5, |
399 | 0x02,0x1a,0x81,0xe3,0x1c,0x10,0x83,0xe5,0x58,0x11,0x9f,0xe5,0x30,0x10,0x80,0xe5, | 399 | 0x02, 0x1a, 0x81, 0xe3, 0x1c, 0x10, 0x83, 0xe5, 0x58, 0x11, 0x9f, 0xe5, 0x30, 0x10, 0x80, 0xe5, |
400 | 0x54,0x11,0x9f,0xe5,0x34,0x10,0x80,0xe5,0x38,0x10,0x80,0xe5,0x3c,0x10,0x80,0xe5, | 400 | 0x54, 0x11, 0x9f, 0xe5, 0x34, 0x10, 0x80, 0xe5, 0x38, 0x10, 0x80, 0xe5, 0x3c, 0x10, 0x80, 0xe5, |
401 | 0x10,0x10,0x90,0xe5,0x08,0x00,0x90,0xe5,0x1e,0xff,0x2f,0xe1,0xf3,0x16,0xa0,0xe3, | 401 | 0x10, 0x10, 0x90, 0xe5, 0x08, 0x00, 0x90, 0xe5, 0x1e, 0xff, 0x2f, 0xe1, 0xf3, 0x16, 0xa0, 0xe3, |
402 | 0x08,0x00,0x91,0xe5,0x05,0x00,0xa0,0xe3,0x0c,0x00,0x81,0xe5,0x10,0x00,0x91,0xe5, | 402 | 0x08, 0x00, 0x91, 0xe5, 0x05, 0x00, 0xa0, 0xe3, 0x0c, 0x00, 0x81, 0xe5, 0x10, 0x00, 0x91, 0xe5, |
403 | 0x02,0x00,0x10,0xe3,0xfc,0xff,0xff,0x0a,0xff,0x00,0xa0,0xe3,0x0c,0x00,0x81,0xe5, | 403 | 0x02, 0x00, 0x10, 0xe3, 0xfc, 0xff, 0xff, 0x0a, 0xff, 0x00, 0xa0, 0xe3, 0x0c, 0x00, 0x81, 0xe5, |
404 | 0x10,0x00,0x91,0xe5,0x02,0x00,0x10,0xe3,0xfc,0xff,0xff,0x0a,0x08,0x00,0x91,0xe5, | 404 | 0x10, 0x00, 0x91, 0xe5, 0x02, 0x00, 0x10, 0xe3, 0xfc, 0xff, 0xff, 0x0a, 0x08, 0x00, 0x91, 0xe5, |
405 | 0x10,0x00,0x91,0xe5,0x01,0x00,0x10,0xe3,0xfc,0xff,0xff,0x0a,0x08,0x00,0x91,0xe5, | 405 | 0x10, 0x00, 0x91, 0xe5, 0x01, 0x00, 0x10, 0xe3, 0xfc, 0xff, 0xff, 0x0a, 0x08, 0x00, 0x91, 0xe5, |
406 | 0xff,0x00,0x00,0xe2,0x1e,0xff,0x2f,0xe1,0x30,0x40,0x2d,0xe9,0x00,0x50,0xa0,0xe1, | 406 | 0xff, 0x00, 0x00, 0xe2, 0x1e, 0xff, 0x2f, 0xe1, 0x30, 0x40, 0x2d, 0xe9, 0x00, 0x50, 0xa0, 0xe1, |
407 | 0x03,0x40,0xa0,0xe1,0xa2,0x02,0xa0,0xe1,0x08,0x00,0x00,0xe2,0x03,0x00,0x80,0xe2, | 407 | 0x03, 0x40, 0xa0, 0xe1, 0xa2, 0x02, 0xa0, 0xe1, 0x08, 0x00, 0x00, 0xe2, 0x03, 0x00, 0x80, 0xe2, |
408 | 0xd8,0x10,0x9f,0xe5,0x00,0x00,0xc1,0xe5,0x01,0x20,0xc1,0xe5,0xe2,0xff,0xff,0xeb, | 408 | 0xd8, 0x10, 0x9f, 0xe5, 0x00, 0x00, 0xc1, 0xe5, 0x01, 0x20, 0xc1, 0xe5, 0xe2, 0xff, 0xff, 0xeb, |
409 | 0x01,0x00,0x10,0xe3,0xfc,0xff,0xff,0x1a,0x14,0x00,0xa0,0xe3,0xc4,0xff,0xff,0xeb, | 409 | 0x01, 0x00, 0x10, 0xe3, 0xfc, 0xff, 0xff, 0x1a, 0x14, 0x00, 0xa0, 0xe3, 0xc4, 0xff, 0xff, 0xeb, |
410 | 0x04,0x20,0xa0,0xe1,0x05,0x10,0xa0,0xe1,0x02,0x00,0xa0,0xe3,0x01,0x00,0x00,0xeb, | 410 | 0x04, 0x20, 0xa0, 0xe1, 0x05, 0x10, 0xa0, 0xe1, 0x02, 0x00, 0xa0, 0xe3, 0x01, 0x00, 0x00, 0xeb, |
411 | 0x30,0x40,0xbd,0xe8,0x1e,0xff,0x2f,0xe1,0x70,0x40,0x2d,0xe9,0xf3,0x46,0xa0,0xe3, | 411 | 0x30, 0x40, 0xbd, 0xe8, 0x1e, 0xff, 0x2f, 0xe1, 0x70, 0x40, 0x2d, 0xe9, 0xf3, 0x46, 0xa0, 0xe3, |
412 | 0x00,0x30,0xa0,0xe3,0x00,0x00,0x50,0xe3,0x08,0x00,0x00,0x9a,0x8c,0x50,0x9f,0xe5, | 412 | 0x00, 0x30, 0xa0, 0xe3, 0x00, 0x00, 0x50, 0xe3, 0x08, 0x00, 0x00, 0x9a, 0x8c, 0x50, 0x9f, 0xe5, |
413 | 0x03,0x60,0xd5,0xe7,0x0c,0x60,0x84,0xe5,0x10,0x60,0x94,0xe5,0x02,0x00,0x16,0xe3, | 413 | 0x03, 0x60, 0xd5, 0xe7, 0x0c, 0x60, 0x84, 0xe5, 0x10, 0x60, 0x94, 0xe5, 0x02, 0x00, 0x16, 0xe3, |
414 | 0xfc,0xff,0xff,0x0a,0x01,0x30,0x83,0xe2,0x00,0x00,0x53,0xe1,0xf7,0xff,0xff,0x3a, | 414 | 0xfc, 0xff, 0xff, 0x0a, 0x01, 0x30, 0x83, 0xe2, 0x00, 0x00, 0x53, 0xe1, 0xf7, 0xff, 0xff, 0x3a, |
415 | 0xff,0x30,0xa0,0xe3,0x0c,0x30,0x84,0xe5,0x08,0x00,0x94,0xe5,0x10,0x00,0x94,0xe5, | 415 | 0xff, 0x30, 0xa0, 0xe3, 0x0c, 0x30, 0x84, 0xe5, 0x08, 0x00, 0x94, 0xe5, 0x10, 0x00, 0x94, 0xe5, |
416 | 0x01,0x00,0x10,0xe3,0xfc,0xff,0xff,0x0a,0x08,0x00,0x94,0xe5,0x00,0x00,0xa0,0xe3, | 416 | 0x01, 0x00, 0x10, 0xe3, 0xfc, 0xff, 0xff, 0x0a, 0x08, 0x00, 0x94, 0xe5, 0x00, 0x00, 0xa0, 0xe3, |
417 | 0x00,0x00,0x52,0xe3,0x0b,0x00,0x00,0x9a,0x10,0x50,0x94,0xe5,0x02,0x00,0x15,0xe3, | 417 | 0x00, 0x00, 0x52, 0xe3, 0x0b, 0x00, 0x00, 0x9a, 0x10, 0x50, 0x94, 0xe5, 0x02, 0x00, 0x15, 0xe3, |
418 | 0xfc,0xff,0xff,0x0a,0x0c,0x30,0x84,0xe5,0x10,0x50,0x94,0xe5,0x01,0x00,0x15,0xe3, | 418 | 0xfc, 0xff, 0xff, 0x0a, 0x0c, 0x30, 0x84, 0xe5, 0x10, 0x50, 0x94, 0xe5, 0x01, 0x00, 0x15, 0xe3, |
419 | 0xfc,0xff,0xff,0x0a,0x08,0x50,0x94,0xe5,0x01,0x50,0xc1,0xe4,0x01,0x00,0x80,0xe2, | 419 | 0xfc, 0xff, 0xff, 0x0a, 0x08, 0x50, 0x94, 0xe5, 0x01, 0x50, 0xc1, 0xe4, 0x01, 0x00, 0x80, 0xe2, |
420 | 0x02,0x00,0x50,0xe1,0xf3,0xff,0xff,0x3a,0xc8,0x00,0xa0,0xe3,0x98,0xff,0xff,0xeb, | 420 | 0x02, 0x00, 0x50, 0xe1, 0xf3, 0xff, 0xff, 0x3a, 0xc8, 0x00, 0xa0, 0xe3, 0x98, 0xff, 0xff, 0xeb, |
421 | 0x70,0x40,0xbd,0xe8,0x1e,0xff,0x2f,0xe1,0x01,0x0c,0x00,0x02,0x01,0x02,0x00,0x02, | 421 | 0x70, 0x40, 0xbd, 0xe8, 0x1e, 0xff, 0x2f, 0xe1, 0x01, 0x0c, 0x00, 0x02, 0x01, 0x02, 0x00, 0x02, |
422 | 0x00,0x01,0x00,0x02 | 422 | 0x00, 0x01, 0x00, 0x02 |
423 | }; | 423 | }; |
424 | 424 | ||
425 | struct atmel_private { | 425 | struct atmel_private { |
@@ -433,7 +433,7 @@ struct atmel_private { | |||
433 | struct net_device *dev; | 433 | struct net_device *dev; |
434 | struct device *sys_dev; | 434 | struct device *sys_dev; |
435 | struct iw_statistics wstats; | 435 | struct iw_statistics wstats; |
436 | spinlock_t irqlock, timerlock; // spinlocks | 436 | spinlock_t irqlock, timerlock; /* spinlocks */ |
437 | enum { BUS_TYPE_PCCARD, BUS_TYPE_PCI } bus_type; | 437 | enum { BUS_TYPE_PCCARD, BUS_TYPE_PCI } bus_type; |
438 | enum { | 438 | enum { |
439 | CARD_TYPE_PARALLEL_FLASH, | 439 | CARD_TYPE_PARALLEL_FLASH, |
@@ -541,7 +541,7 @@ struct atmel_private { | |||
541 | u8 rx_buf[MAX_WIRELESS_BODY]; | 541 | u8 rx_buf[MAX_WIRELESS_BODY]; |
542 | }; | 542 | }; |
543 | 543 | ||
544 | static u8 atmel_basic_rates[4] = {0x82,0x84,0x0b,0x16}; | 544 | static u8 atmel_basic_rates[4] = {0x82, 0x84, 0x0b, 0x16}; |
545 | 545 | ||
546 | static const struct { | 546 | static const struct { |
547 | int reg_domain; | 547 | int reg_domain; |
@@ -1283,17 +1283,17 @@ static struct iw_statistics *atmel_get_wireless_stats(struct net_device *dev) | |||
1283 | 1283 | ||
1284 | static int atmel_change_mtu(struct net_device *dev, int new_mtu) | 1284 | static int atmel_change_mtu(struct net_device *dev, int new_mtu) |
1285 | { | 1285 | { |
1286 | if ((new_mtu < 68) || (new_mtu > 2312)) | 1286 | if ((new_mtu < 68) || (new_mtu > 2312)) |
1287 | return -EINVAL; | 1287 | return -EINVAL; |
1288 | dev->mtu = new_mtu; | 1288 | dev->mtu = new_mtu; |
1289 | return 0; | 1289 | return 0; |
1290 | } | 1290 | } |
1291 | 1291 | ||
1292 | static int atmel_set_mac_address(struct net_device *dev, void *p) | 1292 | static int atmel_set_mac_address(struct net_device *dev, void *p) |
1293 | { | 1293 | { |
1294 | struct sockaddr *addr = p; | 1294 | struct sockaddr *addr = p; |
1295 | 1295 | ||
1296 | memcpy (dev->dev_addr, addr->sa_data, dev->addr_len); | 1296 | memcpy (dev->dev_addr, addr->sa_data, dev->addr_len); |
1297 | return atmel_open(dev); | 1297 | return atmel_open(dev); |
1298 | } | 1298 | } |
1299 | 1299 | ||
@@ -1420,10 +1420,17 @@ static int atmel_proc_output (char *buf, struct atmel_private *priv) | |||
1420 | priv->firmware_id); | 1420 | priv->firmware_id); |
1421 | 1421 | ||
1422 | switch (priv->card_type) { | 1422 | switch (priv->card_type) { |
1423 | case CARD_TYPE_PARALLEL_FLASH: c = "Parallel flash"; break; | 1423 | case CARD_TYPE_PARALLEL_FLASH: |
1424 | case CARD_TYPE_SPI_FLASH: c = "SPI flash\n"; break; | 1424 | c = "Parallel flash"; |
1425 | case CARD_TYPE_EEPROM: c = "EEPROM"; break; | 1425 | break; |
1426 | default: c = "<unknown>"; | 1426 | case CARD_TYPE_SPI_FLASH: |
1427 | c = "SPI flash\n"; | ||
1428 | break; | ||
1429 | case CARD_TYPE_EEPROM: | ||
1430 | c = "EEPROM"; | ||
1431 | break; | ||
1432 | default: | ||
1433 | c = "<unknown>"; | ||
1427 | } | 1434 | } |
1428 | 1435 | ||
1429 | r = "<unknown>"; | 1436 | r = "<unknown>"; |
@@ -1439,16 +1446,33 @@ static int atmel_proc_output (char *buf, struct atmel_private *priv) | |||
1439 | priv->use_wpa ? "Yes" : "No"); | 1446 | priv->use_wpa ? "Yes" : "No"); |
1440 | } | 1447 | } |
1441 | 1448 | ||
1442 | switch(priv->station_state) { | 1449 | switch (priv->station_state) { |
1443 | case STATION_STATE_SCANNING: s = "Scanning"; break; | 1450 | case STATION_STATE_SCANNING: |
1444 | case STATION_STATE_JOINNING: s = "Joining"; break; | 1451 | s = "Scanning"; |
1445 | case STATION_STATE_AUTHENTICATING: s = "Authenticating"; break; | 1452 | break; |
1446 | case STATION_STATE_ASSOCIATING: s = "Associating"; break; | 1453 | case STATION_STATE_JOINNING: |
1447 | case STATION_STATE_READY: s = "Ready"; break; | 1454 | s = "Joining"; |
1448 | case STATION_STATE_REASSOCIATING: s = "Reassociating"; break; | 1455 | break; |
1449 | case STATION_STATE_MGMT_ERROR: s = "Management error"; break; | 1456 | case STATION_STATE_AUTHENTICATING: |
1450 | case STATION_STATE_DOWN: s = "Down"; break; | 1457 | s = "Authenticating"; |
1451 | default: s = "<unknown>"; | 1458 | break; |
1459 | case STATION_STATE_ASSOCIATING: | ||
1460 | s = "Associating"; | ||
1461 | break; | ||
1462 | case STATION_STATE_READY: | ||
1463 | s = "Ready"; | ||
1464 | break; | ||
1465 | case STATION_STATE_REASSOCIATING: | ||
1466 | s = "Reassociating"; | ||
1467 | break; | ||
1468 | case STATION_STATE_MGMT_ERROR: | ||
1469 | s = "Management error"; | ||
1470 | break; | ||
1471 | case STATION_STATE_DOWN: | ||
1472 | s = "Down"; | ||
1473 | break; | ||
1474 | default: | ||
1475 | s = "<unknown>"; | ||
1452 | } | 1476 | } |
1453 | 1477 | ||
1454 | p += sprintf(p, "Current state:\t\t%s\n", s); | 1478 | p += sprintf(p, "Current state:\t\t%s\n", s); |
@@ -1458,14 +1482,17 @@ static int atmel_proc_output (char *buf, struct atmel_private *priv) | |||
1458 | static int atmel_read_proc(char *page, char **start, off_t off, | 1482 | static int atmel_read_proc(char *page, char **start, off_t off, |
1459 | int count, int *eof, void *data) | 1483 | int count, int *eof, void *data) |
1460 | { | 1484 | { |
1461 | struct atmel_private *priv = data; | 1485 | struct atmel_private *priv = data; |
1462 | int len = atmel_proc_output (page, priv); | 1486 | int len = atmel_proc_output (page, priv); |
1463 | if (len <= off+count) *eof = 1; | 1487 | if (len <= off+count) |
1464 | *start = page + off; | 1488 | *eof = 1; |
1465 | len -= off; | 1489 | *start = page + off; |
1466 | if (len>count) len = count; | 1490 | len -= off; |
1467 | if (len<0) len = 0; | 1491 | if (len > count) |
1468 | return len; | 1492 | len = count; |
1493 | if (len < 0) | ||
1494 | len = 0; | ||
1495 | return len; | ||
1469 | } | 1496 | } |
1470 | 1497 | ||
1471 | struct net_device *init_atmel_card(unsigned short irq, unsigned long port, | 1498 | struct net_device *init_atmel_card(unsigned short irq, unsigned long port, |
@@ -1479,11 +1506,11 @@ struct net_device *init_atmel_card(unsigned short irq, unsigned long port, | |||
1479 | int rc; | 1506 | int rc; |
1480 | 1507 | ||
1481 | /* Create the network device object. */ | 1508 | /* Create the network device object. */ |
1482 | dev = alloc_etherdev(sizeof(*priv)); | 1509 | dev = alloc_etherdev(sizeof(*priv)); |
1483 | if (!dev) { | 1510 | if (!dev) { |
1484 | printk(KERN_ERR "atmel: Couldn't alloc_etherdev\n"); | 1511 | printk(KERN_ERR "atmel: Couldn't alloc_etherdev\n"); |
1485 | return NULL; | 1512 | return NULL; |
1486 | } | 1513 | } |
1487 | if (dev_alloc_name(dev, dev->name) < 0) { | 1514 | if (dev_alloc_name(dev, dev->name) < 0) { |
1488 | printk(KERN_ERR "atmel: Couldn't get name!\n"); | 1515 | printk(KERN_ERR "atmel: Couldn't get name!\n"); |
1489 | goto err_out_free; | 1516 | goto err_out_free; |
@@ -1577,7 +1604,7 @@ struct net_device *init_atmel_card(unsigned short irq, unsigned long port, | |||
1577 | if (register_netdev(dev)) | 1604 | if (register_netdev(dev)) |
1578 | goto err_out_res; | 1605 | goto err_out_res; |
1579 | 1606 | ||
1580 | if (!probe_atmel_card(dev)){ | 1607 | if (!probe_atmel_card(dev)) { |
1581 | unregister_netdev(dev); | 1608 | unregister_netdev(dev); |
1582 | goto err_out_res; | 1609 | goto err_out_res; |
1583 | } | 1610 | } |
@@ -1594,7 +1621,7 @@ struct net_device *init_atmel_card(unsigned short irq, unsigned long port, | |||
1594 | return dev; | 1621 | return dev; |
1595 | 1622 | ||
1596 | err_out_res: | 1623 | err_out_res: |
1597 | release_region( dev->base_addr, 32); | 1624 | release_region(dev->base_addr, 32); |
1598 | err_out_irq: | 1625 | err_out_irq: |
1599 | free_irq(dev->irq, dev); | 1626 | free_irq(dev->irq, dev); |
1600 | err_out_free: | 1627 | err_out_free: |
@@ -1632,7 +1659,7 @@ static int atmel_set_essid(struct net_device *dev, | |||
1632 | struct atmel_private *priv = netdev_priv(dev); | 1659 | struct atmel_private *priv = netdev_priv(dev); |
1633 | 1660 | ||
1634 | /* Check if we asked for `any' */ | 1661 | /* Check if we asked for `any' */ |
1635 | if(dwrq->flags == 0) { | 1662 | if (dwrq->flags == 0) { |
1636 | priv->connect_to_any_BSS = 1; | 1663 | priv->connect_to_any_BSS = 1; |
1637 | } else { | 1664 | } else { |
1638 | int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; | 1665 | int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; |
@@ -1768,7 +1795,7 @@ static int atmel_set_encode(struct net_device *dev, | |||
1768 | } | 1795 | } |
1769 | if (dwrq->flags & IW_ENCODE_RESTRICTED) | 1796 | if (dwrq->flags & IW_ENCODE_RESTRICTED) |
1770 | priv->exclude_unencrypted = 1; | 1797 | priv->exclude_unencrypted = 1; |
1771 | if(dwrq->flags & IW_ENCODE_OPEN) | 1798 | if (dwrq->flags & IW_ENCODE_OPEN) |
1772 | priv->exclude_unencrypted = 0; | 1799 | priv->exclude_unencrypted = 0; |
1773 | 1800 | ||
1774 | return -EINPROGRESS; /* Call commit handler */ | 1801 | return -EINPROGRESS; /* Call commit handler */ |
@@ -1797,7 +1824,7 @@ static int atmel_get_encode(struct net_device *dev, | |||
1797 | /* Copy the key to the user buffer */ | 1824 | /* Copy the key to the user buffer */ |
1798 | dwrq->length = priv->wep_key_len[index]; | 1825 | dwrq->length = priv->wep_key_len[index]; |
1799 | if (dwrq->length > 16) { | 1826 | if (dwrq->length > 16) { |
1800 | dwrq->length=0; | 1827 | dwrq->length = 0; |
1801 | } else { | 1828 | } else { |
1802 | memset(extra, 0, 16); | 1829 | memset(extra, 0, 16); |
1803 | memcpy(extra, priv->wep_keys[index], dwrq->length); | 1830 | memcpy(extra, priv->wep_keys[index], dwrq->length); |
@@ -2013,11 +2040,20 @@ static int atmel_set_rate(struct net_device *dev, | |||
2013 | } else { | 2040 | } else { |
2014 | /* Setting by frequency value */ | 2041 | /* Setting by frequency value */ |
2015 | switch (vwrq->value) { | 2042 | switch (vwrq->value) { |
2016 | case 1000000: priv->tx_rate = 0; break; | 2043 | case 1000000: |
2017 | case 2000000: priv->tx_rate = 1; break; | 2044 | priv->tx_rate = 0; |
2018 | case 5500000: priv->tx_rate = 2; break; | 2045 | break; |
2019 | case 11000000: priv->tx_rate = 3; break; | 2046 | case 2000000: |
2020 | default: return -EINVAL; | 2047 | priv->tx_rate = 1; |
2048 | break; | ||
2049 | case 5500000: | ||
2050 | priv->tx_rate = 2; | ||
2051 | break; | ||
2052 | case 11000000: | ||
2053 | priv->tx_rate = 3; | ||
2054 | break; | ||
2055 | default: | ||
2056 | return -EINVAL; | ||
2021 | } | 2057 | } |
2022 | } | 2058 | } |
2023 | } | 2059 | } |
@@ -2062,11 +2098,19 @@ static int atmel_get_rate(struct net_device *dev, | |||
2062 | vwrq->value = 11000000; | 2098 | vwrq->value = 11000000; |
2063 | } else { | 2099 | } else { |
2064 | vwrq->fixed = 1; | 2100 | vwrq->fixed = 1; |
2065 | switch(priv->tx_rate) { | 2101 | switch (priv->tx_rate) { |
2066 | case 0: vwrq->value = 1000000; break; | 2102 | case 0: |
2067 | case 1: vwrq->value = 2000000; break; | 2103 | vwrq->value = 1000000; |
2068 | case 2: vwrq->value = 5500000; break; | 2104 | break; |
2069 | case 3: vwrq->value = 11000000; break; | 2105 | case 1: |
2106 | vwrq->value = 2000000; | ||
2107 | break; | ||
2108 | case 2: | ||
2109 | vwrq->value = 5500000; | ||
2110 | break; | ||
2111 | case 3: | ||
2112 | vwrq->value = 11000000; | ||
2113 | break; | ||
2070 | } | 2114 | } |
2071 | } | 2115 | } |
2072 | return 0; | 2116 | return 0; |
@@ -2576,8 +2620,7 @@ static const struct iw_priv_args atmel_private_args[] = { | |||
2576 | }, | 2620 | }, |
2577 | }; | 2621 | }; |
2578 | 2622 | ||
2579 | static const struct iw_handler_def atmel_handler_def = | 2623 | static const struct iw_handler_def atmel_handler_def = { |
2580 | { | ||
2581 | .num_standard = ARRAY_SIZE(atmel_handler), | 2624 | .num_standard = ARRAY_SIZE(atmel_handler), |
2582 | .num_private = ARRAY_SIZE(atmel_private_handler), | 2625 | .num_private = ARRAY_SIZE(atmel_private_handler), |
2583 | .num_private_args = ARRAY_SIZE(atmel_private_args), | 2626 | .num_private_args = ARRAY_SIZE(atmel_private_args), |
@@ -2834,7 +2877,7 @@ static void send_authentication_request(struct atmel_private *priv, u16 system, | |||
2834 | 2877 | ||
2835 | if (priv->wep_is_on && priv->CurrentAuthentTransactionSeqNum != 1) | 2878 | if (priv->wep_is_on && priv->CurrentAuthentTransactionSeqNum != 1) |
2836 | /* no WEP for authentication frames with TrSeqNo 1 */ | 2879 | /* no WEP for authentication frames with TrSeqNo 1 */ |
2837 | header.frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); | 2880 | header.frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); |
2838 | 2881 | ||
2839 | auth.alg = cpu_to_le16(system); | 2882 | auth.alg = cpu_to_le16(system); |
2840 | 2883 | ||
@@ -2969,7 +3012,7 @@ static void store_bss_info(struct atmel_private *priv, | |||
2969 | if (memcmp(bss, priv->BSSinfo[i].BSSID, 6) == 0) | 3012 | if (memcmp(bss, priv->BSSinfo[i].BSSID, 6) == 0) |
2970 | index = i; | 3013 | index = i; |
2971 | 3014 | ||
2972 | /* If we process a probe and an entry from this BSS exists | 3015 | /* If we process a probe and an entry from this BSS exists |
2973 | we will update the BSS entry with the info from this BSS. | 3016 | we will update the BSS entry with the info from this BSS. |
2974 | If we process a beacon we will only update RSSI */ | 3017 | If we process a beacon we will only update RSSI */ |
2975 | 3018 | ||
@@ -2995,7 +3038,7 @@ static void store_bss_info(struct atmel_private *priv, | |||
2995 | if (capability & WLAN_CAPABILITY_IBSS) | 3038 | if (capability & WLAN_CAPABILITY_IBSS) |
2996 | priv->BSSinfo[index].BSStype = IW_MODE_ADHOC; | 3039 | priv->BSSinfo[index].BSStype = IW_MODE_ADHOC; |
2997 | else if (capability & WLAN_CAPABILITY_ESS) | 3040 | else if (capability & WLAN_CAPABILITY_ESS) |
2998 | priv->BSSinfo[index].BSStype =IW_MODE_INFRA; | 3041 | priv->BSSinfo[index].BSStype = IW_MODE_INFRA; |
2999 | 3042 | ||
3000 | priv->BSSinfo[index].preamble = capability & WLAN_CAPABILITY_SHORT_PREAMBLE ? | 3043 | priv->BSSinfo[index].preamble = capability & WLAN_CAPABILITY_SHORT_PREAMBLE ? |
3001 | SHORT_PREAMBLE : LONG_PREAMBLE; | 3044 | SHORT_PREAMBLE : LONG_PREAMBLE; |
@@ -3042,7 +3085,7 @@ static void authenticate(struct atmel_private *priv, u16 frame_len) | |||
3042 | } | 3085 | } |
3043 | 3086 | ||
3044 | if (should_associate) { | 3087 | if (should_associate) { |
3045 | if(priv->station_was_associated) { | 3088 | if (priv->station_was_associated) { |
3046 | atmel_enter_state(priv, STATION_STATE_REASSOCIATING); | 3089 | atmel_enter_state(priv, STATION_STATE_REASSOCIATING); |
3047 | send_association_request(priv, 1); | 3090 | send_association_request(priv, 1); |
3048 | return; | 3091 | return; |
@@ -3063,8 +3106,8 @@ static void authenticate(struct atmel_private *priv, u16 frame_len) | |||
3063 | priv->exclude_unencrypted = 1; | 3106 | priv->exclude_unencrypted = 1; |
3064 | send_authentication_request(priv, WLAN_AUTH_SHARED_KEY, NULL, 0); | 3107 | send_authentication_request(priv, WLAN_AUTH_SHARED_KEY, NULL, 0); |
3065 | return; | 3108 | return; |
3066 | } else if ( system == WLAN_AUTH_SHARED_KEY | 3109 | } else if (system == WLAN_AUTH_SHARED_KEY |
3067 | && priv->wep_is_on) { | 3110 | && priv->wep_is_on) { |
3068 | priv->CurrentAuthentTransactionSeqNum = 0x001; | 3111 | priv->CurrentAuthentTransactionSeqNum = 0x001; |
3069 | priv->exclude_unencrypted = 0; | 3112 | priv->exclude_unencrypted = 0; |
3070 | send_authentication_request(priv, WLAN_AUTH_OPEN, NULL, 0); | 3113 | send_authentication_request(priv, WLAN_AUTH_OPEN, NULL, 0); |
@@ -3252,11 +3295,11 @@ static void smooth_rssi(struct atmel_private *priv, u8 rssi) | |||
3252 | u8 max_rssi = 42; /* 502-rmfd-revd max by experiment, default for now */ | 3295 | u8 max_rssi = 42; /* 502-rmfd-revd max by experiment, default for now */ |
3253 | 3296 | ||
3254 | switch (priv->firmware_type) { | 3297 | switch (priv->firmware_type) { |
3255 | case ATMEL_FW_TYPE_502E: | 3298 | case ATMEL_FW_TYPE_502E: |
3256 | max_rssi = 63; /* 502-rmfd-reve max by experiment */ | 3299 | max_rssi = 63; /* 502-rmfd-reve max by experiment */ |
3257 | break; | 3300 | break; |
3258 | default: | 3301 | default: |
3259 | break; | 3302 | break; |
3260 | } | 3303 | } |
3261 | 3304 | ||
3262 | rssi = rssi * 100 / max_rssi; | 3305 | rssi = rssi * 100 / max_rssi; |
@@ -3473,8 +3516,7 @@ static void atmel_command_irq(struct atmel_private *priv) | |||
3473 | status == CMD_STATUS_IN_PROGRESS) | 3516 | status == CMD_STATUS_IN_PROGRESS) |
3474 | return; | 3517 | return; |
3475 | 3518 | ||
3476 | switch (command){ | 3519 | switch (command) { |
3477 | |||
3478 | case CMD_Start: | 3520 | case CMD_Start: |
3479 | if (status == CMD_STATUS_COMPLETE) { | 3521 | if (status == CMD_STATUS_COMPLETE) { |
3480 | priv->station_was_associated = priv->station_is_associated; | 3522 | priv->station_was_associated = priv->station_is_associated; |
@@ -3709,7 +3751,7 @@ static int probe_atmel_card(struct net_device *dev) | |||
3709 | 3751 | ||
3710 | if (rc) { | 3752 | if (rc) { |
3711 | if (dev->dev_addr[0] == 0xFF) { | 3753 | if (dev->dev_addr[0] == 0xFF) { |
3712 | u8 default_mac[] = {0x00,0x04, 0x25, 0x00, 0x00, 0x00}; | 3754 | u8 default_mac[] = {0x00, 0x04, 0x25, 0x00, 0x00, 0x00}; |
3713 | printk(KERN_ALERT "%s: *** Invalid MAC address. UPGRADE Firmware ****\n", dev->name); | 3755 | printk(KERN_ALERT "%s: *** Invalid MAC address. UPGRADE Firmware ****\n", dev->name); |
3714 | memcpy(dev->dev_addr, default_mac, 6); | 3756 | memcpy(dev->dev_addr, default_mac, 6); |
3715 | } | 3757 | } |
@@ -3803,7 +3845,7 @@ static void build_wpa_mib(struct atmel_private *priv) | |||
3803 | } else { | 3845 | } else { |
3804 | mib.group_key = i; | 3846 | mib.group_key = i; |
3805 | priv->group_cipher_suite = priv->pairwise_cipher_suite; | 3847 | priv->group_cipher_suite = priv->pairwise_cipher_suite; |
3806 | mib.cipher_default_key_value[i][MAX_ENCRYPTION_KEY_SIZE-1] = 1; | 3848 | mib.cipher_default_key_value[i][MAX_ENCRYPTION_KEY_SIZE-1] = 1; |
3807 | mib.cipher_default_key_value[i][MAX_ENCRYPTION_KEY_SIZE-2] = priv->group_cipher_suite; | 3849 | mib.cipher_default_key_value[i][MAX_ENCRYPTION_KEY_SIZE-2] = priv->group_cipher_suite; |
3808 | } | 3850 | } |
3809 | } | 3851 | } |
@@ -3913,7 +3955,7 @@ static int reset_atmel_card(struct net_device *dev) | |||
3913 | len = fw_entry->size; | 3955 | len = fw_entry->size; |
3914 | } | 3956 | } |
3915 | 3957 | ||
3916 | if (len <= 0x6000) { | 3958 | if (len <= 0x6000) { |
3917 | atmel_write16(priv->dev, BSR, BSS_IRAM); | 3959 | atmel_write16(priv->dev, BSR, BSS_IRAM); |
3918 | atmel_copy_to_card(priv->dev, 0, fw, len); | 3960 | atmel_copy_to_card(priv->dev, 0, fw, len); |
3919 | atmel_set_gcr(priv->dev, GCR_REMAP); | 3961 | atmel_set_gcr(priv->dev, GCR_REMAP); |
@@ -3942,7 +3984,7 @@ static int reset_atmel_card(struct net_device *dev) | |||
3942 | priv->use_wpa = (priv->host_info.major_version == 4); | 3984 | priv->use_wpa = (priv->host_info.major_version == 4); |
3943 | priv->radio_on_broken = (priv->host_info.major_version == 5); | 3985 | priv->radio_on_broken = (priv->host_info.major_version == 5); |
3944 | 3986 | ||
3945 | /* unmask all irq sources */ | 3987 | /* unmask all irq sources */ |
3946 | atmel_wmem8(priv, atmel_hi(priv, IFACE_INT_MASK_OFFSET), 0xff); | 3988 | atmel_wmem8(priv, atmel_hi(priv, IFACE_INT_MASK_OFFSET), 0xff); |
3947 | 3989 | ||
3948 | /* int Tx system and enable Tx */ | 3990 | /* int Tx system and enable Tx */ |
@@ -3975,7 +4017,7 @@ static int reset_atmel_card(struct net_device *dev) | |||
3975 | CMD_STATUS_REJECTED_RADIO_OFF) { | 4017 | CMD_STATUS_REJECTED_RADIO_OFF) { |
3976 | printk(KERN_INFO "%s: cannot turn the radio on.\n", | 4018 | printk(KERN_INFO "%s: cannot turn the radio on.\n", |
3977 | dev->name); | 4019 | dev->name); |
3978 | return -EIO; | 4020 | return -EIO; |
3979 | } | 4021 | } |
3980 | } | 4022 | } |
3981 | 4023 | ||
@@ -3999,8 +4041,7 @@ static int reset_atmel_card(struct net_device *dev) | |||
3999 | else | 4041 | else |
4000 | build_wep_mib(priv); | 4042 | build_wep_mib(priv); |
4001 | 4043 | ||
4002 | if (old_state == STATION_STATE_READY) | 4044 | if (old_state == STATION_STATE_READY) { |
4003 | { | ||
4004 | union iwreq_data wrqu; | 4045 | union iwreq_data wrqu; |
4005 | 4046 | ||
4006 | wrqu.data.length = 0; | 4047 | wrqu.data.length = 0; |
@@ -4277,24 +4318,24 @@ static void atmel_wmem32(struct atmel_private *priv, u16 pos, u32 data) | |||
4277 | .set NVRAM_LENGTH, 0x0200 | 4318 | .set NVRAM_LENGTH, 0x0200 |
4278 | .set MAC_ADDRESS_MIB, SRAM_BASE | 4319 | .set MAC_ADDRESS_MIB, SRAM_BASE |
4279 | .set MAC_ADDRESS_LENGTH, 6 | 4320 | .set MAC_ADDRESS_LENGTH, 6 |
4280 | .set MAC_BOOT_FLAG, 0x10 | 4321 | .set MAC_BOOT_FLAG, 0x10 |
4281 | .set MR1, 0 | 4322 | .set MR1, 0 |
4282 | .set MR2, 4 | 4323 | .set MR2, 4 |
4283 | .set MR3, 8 | 4324 | .set MR3, 8 |
4284 | .set MR4, 0xC | 4325 | .set MR4, 0xC |
4285 | RESET_VECTOR: | 4326 | RESET_VECTOR: |
4286 | b RESET_HANDLER | 4327 | b RESET_HANDLER |
4287 | UNDEF_VECTOR: | 4328 | UNDEF_VECTOR: |
4288 | b HALT1 | 4329 | b HALT1 |
4289 | SWI_VECTOR: | 4330 | SWI_VECTOR: |
4290 | b HALT1 | 4331 | b HALT1 |
4291 | IABORT_VECTOR: | 4332 | IABORT_VECTOR: |
4292 | b HALT1 | 4333 | b HALT1 |
4293 | DABORT_VECTOR: | 4334 | DABORT_VECTOR: |
4294 | RESERVED_VECTOR: | 4335 | RESERVED_VECTOR: |
4295 | b HALT1 | 4336 | b HALT1 |
4296 | IRQ_VECTOR: | 4337 | IRQ_VECTOR: |
4297 | b HALT1 | 4338 | b HALT1 |
4298 | FIQ_VECTOR: | 4339 | FIQ_VECTOR: |
4299 | b HALT1 | 4340 | b HALT1 |
4300 | HALT1: b HALT1 | 4341 | HALT1: b HALT1 |
@@ -4306,7 +4347,7 @@ RESET_HANDLER: | |||
4306 | ldr r0, =SPI_CGEN_BASE | 4347 | ldr r0, =SPI_CGEN_BASE |
4307 | mov r1, #0 | 4348 | mov r1, #0 |
4308 | mov r1, r1, lsl #3 | 4349 | mov r1, r1, lsl #3 |
4309 | orr r1,r1, #0 | 4350 | orr r1, r1, #0 |
4310 | str r1, [r0] | 4351 | str r1, [r0] |
4311 | ldr r1, [r0, #28] | 4352 | ldr r1, [r0, #28] |
4312 | bic r1, r1, #16 | 4353 | bic r1, r1, #16 |
diff --git a/drivers/net/wireless/ipw2x00/ieee80211.h b/drivers/net/wireless/ipw2x00/ieee80211.h index 7515fad00f92..f82435eae49d 100644 --- a/drivers/net/wireless/ipw2x00/ieee80211.h +++ b/drivers/net/wireless/ipw2x00/ieee80211.h | |||
@@ -54,65 +54,12 @@ | |||
54 | #define MIN_FRAG_THRESHOLD 256U | 54 | #define MIN_FRAG_THRESHOLD 256U |
55 | #define MAX_FRAG_THRESHOLD 2346U | 55 | #define MAX_FRAG_THRESHOLD 2346U |
56 | 56 | ||
57 | /* Frame control field constants */ | ||
58 | #define IEEE80211_FCTL_VERS 0x0003 | ||
59 | #define IEEE80211_FCTL_FTYPE 0x000c | ||
60 | #define IEEE80211_FCTL_STYPE 0x00f0 | ||
61 | #define IEEE80211_FCTL_TODS 0x0100 | ||
62 | #define IEEE80211_FCTL_FROMDS 0x0200 | ||
63 | #define IEEE80211_FCTL_MOREFRAGS 0x0400 | ||
64 | #define IEEE80211_FCTL_RETRY 0x0800 | ||
65 | #define IEEE80211_FCTL_PM 0x1000 | ||
66 | #define IEEE80211_FCTL_MOREDATA 0x2000 | ||
67 | #define IEEE80211_FCTL_PROTECTED 0x4000 | ||
68 | #define IEEE80211_FCTL_ORDER 0x8000 | ||
69 | |||
70 | #define IEEE80211_FTYPE_MGMT 0x0000 | ||
71 | #define IEEE80211_FTYPE_CTL 0x0004 | ||
72 | #define IEEE80211_FTYPE_DATA 0x0008 | ||
73 | |||
74 | /* management */ | ||
75 | #define IEEE80211_STYPE_ASSOC_REQ 0x0000 | ||
76 | #define IEEE80211_STYPE_ASSOC_RESP 0x0010 | ||
77 | #define IEEE80211_STYPE_REASSOC_REQ 0x0020 | ||
78 | #define IEEE80211_STYPE_REASSOC_RESP 0x0030 | ||
79 | #define IEEE80211_STYPE_PROBE_REQ 0x0040 | ||
80 | #define IEEE80211_STYPE_PROBE_RESP 0x0050 | ||
81 | #define IEEE80211_STYPE_BEACON 0x0080 | ||
82 | #define IEEE80211_STYPE_ATIM 0x0090 | ||
83 | #define IEEE80211_STYPE_DISASSOC 0x00A0 | ||
84 | #define IEEE80211_STYPE_AUTH 0x00B0 | ||
85 | #define IEEE80211_STYPE_DEAUTH 0x00C0 | ||
86 | #define IEEE80211_STYPE_ACTION 0x00D0 | ||
87 | |||
88 | /* control */ | ||
89 | #define IEEE80211_STYPE_PSPOLL 0x00A0 | ||
90 | #define IEEE80211_STYPE_RTS 0x00B0 | ||
91 | #define IEEE80211_STYPE_CTS 0x00C0 | ||
92 | #define IEEE80211_STYPE_ACK 0x00D0 | ||
93 | #define IEEE80211_STYPE_CFEND 0x00E0 | ||
94 | #define IEEE80211_STYPE_CFENDACK 0x00F0 | ||
95 | |||
96 | /* data */ | ||
97 | #define IEEE80211_STYPE_DATA 0x0000 | ||
98 | #define IEEE80211_STYPE_DATA_CFACK 0x0010 | ||
99 | #define IEEE80211_STYPE_DATA_CFPOLL 0x0020 | ||
100 | #define IEEE80211_STYPE_DATA_CFACKPOLL 0x0030 | ||
101 | #define IEEE80211_STYPE_NULLFUNC 0x0040 | ||
102 | #define IEEE80211_STYPE_CFACK 0x0050 | ||
103 | #define IEEE80211_STYPE_CFPOLL 0x0060 | ||
104 | #define IEEE80211_STYPE_CFACKPOLL 0x0070 | ||
105 | #define IEEE80211_STYPE_QOS_DATA 0x0080 | ||
106 | |||
107 | #define IEEE80211_SCTL_FRAG 0x000F | ||
108 | #define IEEE80211_SCTL_SEQ 0xFFF0 | ||
109 | |||
110 | /* QOS control */ | 57 | /* QOS control */ |
111 | #define IEEE80211_QCTL_TID 0x000F | 58 | #define IEEE80211_QCTL_TID 0x000F |
112 | 59 | ||
113 | /* debug macros */ | 60 | /* debug macros */ |
114 | 61 | ||
115 | #ifdef CONFIG_IEEE80211_DEBUG | 62 | #ifdef CONFIG_LIBIPW_DEBUG |
116 | extern u32 ieee80211_debug_level; | 63 | extern u32 ieee80211_debug_level; |
117 | #define IEEE80211_DEBUG(level, fmt, args...) \ | 64 | #define IEEE80211_DEBUG(level, fmt, args...) \ |
118 | do { if (ieee80211_debug_level & (level)) \ | 65 | do { if (ieee80211_debug_level & (level)) \ |
@@ -128,7 +75,7 @@ static inline bool ieee80211_ratelimit_debug(u32 level) | |||
128 | { | 75 | { |
129 | return false; | 76 | return false; |
130 | } | 77 | } |
131 | #endif /* CONFIG_IEEE80211_DEBUG */ | 78 | #endif /* CONFIG_LIBIPW_DEBUG */ |
132 | 79 | ||
133 | /* | 80 | /* |
134 | * To use the debug system: | 81 | * To use the debug system: |
@@ -152,7 +99,7 @@ static inline bool ieee80211_ratelimit_debug(u32 level) | |||
152 | * you simply need to add your entry to the ieee80211_debug_level array. | 99 | * you simply need to add your entry to the ieee80211_debug_level array. |
153 | * | 100 | * |
154 | * If you do not see debug_level in /proc/net/ieee80211 then you do not have | 101 | * If you do not see debug_level in /proc/net/ieee80211 then you do not have |
155 | * CONFIG_IEEE80211_DEBUG defined in your kernel configuration | 102 | * CONFIG_LIBIPW_DEBUG defined in your kernel configuration |
156 | * | 103 | * |
157 | */ | 104 | */ |
158 | 105 | ||
@@ -217,23 +164,6 @@ struct ieee80211_snap_hdr { | |||
217 | #define WLAN_GET_SEQ_FRAG(seq) ((seq) & IEEE80211_SCTL_FRAG) | 164 | #define WLAN_GET_SEQ_FRAG(seq) ((seq) & IEEE80211_SCTL_FRAG) |
218 | #define WLAN_GET_SEQ_SEQ(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4) | 165 | #define WLAN_GET_SEQ_SEQ(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4) |
219 | 166 | ||
220 | /* Action categories - 802.11h */ | ||
221 | enum ieee80211_actioncategories { | ||
222 | WLAN_ACTION_SPECTRUM_MGMT = 0, | ||
223 | /* Reserved 1-127 */ | ||
224 | /* Error 128-255 */ | ||
225 | }; | ||
226 | |||
227 | /* Action details - 802.11h */ | ||
228 | enum ieee80211_actiondetails { | ||
229 | WLAN_ACTION_CATEGORY_MEASURE_REQUEST = 0, | ||
230 | WLAN_ACTION_CATEGORY_MEASURE_REPORT = 1, | ||
231 | WLAN_ACTION_CATEGORY_TPC_REQUEST = 2, | ||
232 | WLAN_ACTION_CATEGORY_TPC_REPORT = 3, | ||
233 | WLAN_ACTION_CATEGORY_CHANNEL_SWITCH = 4, | ||
234 | /* 5 - 255 Reserved */ | ||
235 | }; | ||
236 | |||
237 | #define IEEE80211_STATMASK_SIGNAL (1<<0) | 167 | #define IEEE80211_STATMASK_SIGNAL (1<<0) |
238 | #define IEEE80211_STATMASK_RSSI (1<<1) | 168 | #define IEEE80211_STATMASK_RSSI (1<<1) |
239 | #define IEEE80211_STATMASK_NOISE (1<<2) | 169 | #define IEEE80211_STATMASK_NOISE (1<<2) |
@@ -411,37 +341,6 @@ Total: 28-2340 bytes | |||
411 | 341 | ||
412 | #define BEACON_PROBE_SSID_ID_POSITION 12 | 342 | #define BEACON_PROBE_SSID_ID_POSITION 12 |
413 | 343 | ||
414 | /* Management Frame Information Element Types */ | ||
415 | enum ieee80211_mfie { | ||
416 | MFIE_TYPE_SSID = 0, | ||
417 | MFIE_TYPE_RATES = 1, | ||
418 | MFIE_TYPE_FH_SET = 2, | ||
419 | MFIE_TYPE_DS_SET = 3, | ||
420 | MFIE_TYPE_CF_SET = 4, | ||
421 | MFIE_TYPE_TIM = 5, | ||
422 | MFIE_TYPE_IBSS_SET = 6, | ||
423 | MFIE_TYPE_COUNTRY = 7, | ||
424 | MFIE_TYPE_HOP_PARAMS = 8, | ||
425 | MFIE_TYPE_HOP_TABLE = 9, | ||
426 | MFIE_TYPE_REQUEST = 10, | ||
427 | MFIE_TYPE_CHALLENGE = 16, | ||
428 | MFIE_TYPE_POWER_CONSTRAINT = 32, | ||
429 | MFIE_TYPE_POWER_CAPABILITY = 33, | ||
430 | MFIE_TYPE_TPC_REQUEST = 34, | ||
431 | MFIE_TYPE_TPC_REPORT = 35, | ||
432 | MFIE_TYPE_SUPP_CHANNELS = 36, | ||
433 | MFIE_TYPE_CSA = 37, | ||
434 | MFIE_TYPE_MEASURE_REQUEST = 38, | ||
435 | MFIE_TYPE_MEASURE_REPORT = 39, | ||
436 | MFIE_TYPE_QUIET = 40, | ||
437 | MFIE_TYPE_IBSS_DFS = 41, | ||
438 | MFIE_TYPE_ERP_INFO = 42, | ||
439 | MFIE_TYPE_RSN = 48, | ||
440 | MFIE_TYPE_RATES_EX = 50, | ||
441 | MFIE_TYPE_GENERIC = 221, | ||
442 | MFIE_TYPE_QOS_PARAMETER = 222, | ||
443 | }; | ||
444 | |||
445 | struct ieee80211_hdr_1addr { | 344 | struct ieee80211_hdr_1addr { |
446 | __le16 frame_ctl; | 345 | __le16 frame_ctl; |
447 | __le16 duration_id; | 346 | __le16 duration_id; |
diff --git a/drivers/net/wireless/ipw2x00/libipw_module.c b/drivers/net/wireless/ipw2x00/libipw_module.c index ec7753446bd3..f4803fc05413 100644 --- a/drivers/net/wireless/ipw2x00/libipw_module.c +++ b/drivers/net/wireless/ipw2x00/libipw_module.c | |||
@@ -221,7 +221,7 @@ void free_ieee80211(struct net_device *dev) | |||
221 | free_netdev(dev); | 221 | free_netdev(dev); |
222 | } | 222 | } |
223 | 223 | ||
224 | #ifdef CONFIG_IEEE80211_DEBUG | 224 | #ifdef CONFIG_LIBIPW_DEBUG |
225 | 225 | ||
226 | static int debug = 0; | 226 | static int debug = 0; |
227 | u32 ieee80211_debug_level = 0; | 227 | u32 ieee80211_debug_level = 0; |
@@ -252,11 +252,11 @@ static int store_debug_level(struct file *file, const char __user * buffer, | |||
252 | 252 | ||
253 | return strnlen(buf, len); | 253 | return strnlen(buf, len); |
254 | } | 254 | } |
255 | #endif /* CONFIG_IEEE80211_DEBUG */ | 255 | #endif /* CONFIG_LIBIPW_DEBUG */ |
256 | 256 | ||
257 | static int __init ieee80211_init(void) | 257 | static int __init ieee80211_init(void) |
258 | { | 258 | { |
259 | #ifdef CONFIG_IEEE80211_DEBUG | 259 | #ifdef CONFIG_LIBIPW_DEBUG |
260 | struct proc_dir_entry *e; | 260 | struct proc_dir_entry *e; |
261 | 261 | ||
262 | ieee80211_debug_level = debug; | 262 | ieee80211_debug_level = debug; |
@@ -276,7 +276,7 @@ static int __init ieee80211_init(void) | |||
276 | e->read_proc = show_debug_level; | 276 | e->read_proc = show_debug_level; |
277 | e->write_proc = store_debug_level; | 277 | e->write_proc = store_debug_level; |
278 | e->data = NULL; | 278 | e->data = NULL; |
279 | #endif /* CONFIG_IEEE80211_DEBUG */ | 279 | #endif /* CONFIG_LIBIPW_DEBUG */ |
280 | 280 | ||
281 | printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n"); | 281 | printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n"); |
282 | printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n"); | 282 | printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n"); |
@@ -286,20 +286,20 @@ static int __init ieee80211_init(void) | |||
286 | 286 | ||
287 | static void __exit ieee80211_exit(void) | 287 | static void __exit ieee80211_exit(void) |
288 | { | 288 | { |
289 | #ifdef CONFIG_IEEE80211_DEBUG | 289 | #ifdef CONFIG_LIBIPW_DEBUG |
290 | if (ieee80211_proc) { | 290 | if (ieee80211_proc) { |
291 | remove_proc_entry("debug_level", ieee80211_proc); | 291 | remove_proc_entry("debug_level", ieee80211_proc); |
292 | remove_proc_entry(DRV_NAME, init_net.proc_net); | 292 | remove_proc_entry(DRV_NAME, init_net.proc_net); |
293 | ieee80211_proc = NULL; | 293 | ieee80211_proc = NULL; |
294 | } | 294 | } |
295 | #endif /* CONFIG_IEEE80211_DEBUG */ | 295 | #endif /* CONFIG_LIBIPW_DEBUG */ |
296 | } | 296 | } |
297 | 297 | ||
298 | #ifdef CONFIG_IEEE80211_DEBUG | 298 | #ifdef CONFIG_LIBIPW_DEBUG |
299 | #include <linux/moduleparam.h> | 299 | #include <linux/moduleparam.h> |
300 | module_param(debug, int, 0444); | 300 | module_param(debug, int, 0444); |
301 | MODULE_PARM_DESC(debug, "debug output mask"); | 301 | MODULE_PARM_DESC(debug, "debug output mask"); |
302 | #endif /* CONFIG_IEEE80211_DEBUG */ | 302 | #endif /* CONFIG_LIBIPW_DEBUG */ |
303 | 303 | ||
304 | module_exit(ieee80211_exit); | 304 | module_exit(ieee80211_exit); |
305 | module_init(ieee80211_init); | 305 | module_init(ieee80211_init); |
diff --git a/drivers/net/wireless/ipw2x00/libipw_rx.c b/drivers/net/wireless/ipw2x00/libipw_rx.c index 8d9e96f9eb28..079007936d8a 100644 --- a/drivers/net/wireless/ipw2x00/libipw_rx.c +++ b/drivers/net/wireless/ipw2x00/libipw_rx.c | |||
@@ -1080,37 +1080,37 @@ static int ieee80211_parse_qos_info_param_IE(struct ieee80211_info_element | |||
1080 | return rc; | 1080 | return rc; |
1081 | } | 1081 | } |
1082 | 1082 | ||
1083 | #ifdef CONFIG_IEEE80211_DEBUG | 1083 | #ifdef CONFIG_LIBIPW_DEBUG |
1084 | #define MFIE_STRING(x) case MFIE_TYPE_ ##x: return #x | 1084 | #define MFIE_STRING(x) case WLAN_EID_ ##x: return #x |
1085 | 1085 | ||
1086 | static const char *get_info_element_string(u16 id) | 1086 | static const char *get_info_element_string(u16 id) |
1087 | { | 1087 | { |
1088 | switch (id) { | 1088 | switch (id) { |
1089 | MFIE_STRING(SSID); | 1089 | MFIE_STRING(SSID); |
1090 | MFIE_STRING(RATES); | 1090 | MFIE_STRING(SUPP_RATES); |
1091 | MFIE_STRING(FH_SET); | 1091 | MFIE_STRING(FH_PARAMS); |
1092 | MFIE_STRING(DS_SET); | 1092 | MFIE_STRING(DS_PARAMS); |
1093 | MFIE_STRING(CF_SET); | 1093 | MFIE_STRING(CF_PARAMS); |
1094 | MFIE_STRING(TIM); | 1094 | MFIE_STRING(TIM); |
1095 | MFIE_STRING(IBSS_SET); | 1095 | MFIE_STRING(IBSS_PARAMS); |
1096 | MFIE_STRING(COUNTRY); | 1096 | MFIE_STRING(COUNTRY); |
1097 | MFIE_STRING(HOP_PARAMS); | 1097 | MFIE_STRING(HP_PARAMS); |
1098 | MFIE_STRING(HOP_TABLE); | 1098 | MFIE_STRING(HP_TABLE); |
1099 | MFIE_STRING(REQUEST); | 1099 | MFIE_STRING(REQUEST); |
1100 | MFIE_STRING(CHALLENGE); | 1100 | MFIE_STRING(CHALLENGE); |
1101 | MFIE_STRING(POWER_CONSTRAINT); | 1101 | MFIE_STRING(PWR_CONSTRAINT); |
1102 | MFIE_STRING(POWER_CAPABILITY); | 1102 | MFIE_STRING(PWR_CAPABILITY); |
1103 | MFIE_STRING(TPC_REQUEST); | 1103 | MFIE_STRING(TPC_REQUEST); |
1104 | MFIE_STRING(TPC_REPORT); | 1104 | MFIE_STRING(TPC_REPORT); |
1105 | MFIE_STRING(SUPP_CHANNELS); | 1105 | MFIE_STRING(SUPPORTED_CHANNELS); |
1106 | MFIE_STRING(CSA); | 1106 | MFIE_STRING(CHANNEL_SWITCH); |
1107 | MFIE_STRING(MEASURE_REQUEST); | 1107 | MFIE_STRING(MEASURE_REQUEST); |
1108 | MFIE_STRING(MEASURE_REPORT); | 1108 | MFIE_STRING(MEASURE_REPORT); |
1109 | MFIE_STRING(QUIET); | 1109 | MFIE_STRING(QUIET); |
1110 | MFIE_STRING(IBSS_DFS); | 1110 | MFIE_STRING(IBSS_DFS); |
1111 | MFIE_STRING(ERP_INFO); | 1111 | MFIE_STRING(ERP_INFO); |
1112 | MFIE_STRING(RSN); | 1112 | MFIE_STRING(RSN); |
1113 | MFIE_STRING(RATES_EX); | 1113 | MFIE_STRING(EXT_SUPP_RATES); |
1114 | MFIE_STRING(GENERIC); | 1114 | MFIE_STRING(GENERIC); |
1115 | MFIE_STRING(QOS_PARAMETER); | 1115 | MFIE_STRING(QOS_PARAMETER); |
1116 | default: | 1116 | default: |
@@ -1125,7 +1125,7 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element | |||
1125 | { | 1125 | { |
1126 | DECLARE_SSID_BUF(ssid); | 1126 | DECLARE_SSID_BUF(ssid); |
1127 | u8 i; | 1127 | u8 i; |
1128 | #ifdef CONFIG_IEEE80211_DEBUG | 1128 | #ifdef CONFIG_LIBIPW_DEBUG |
1129 | char rates_str[64]; | 1129 | char rates_str[64]; |
1130 | char *p; | 1130 | char *p; |
1131 | #endif | 1131 | #endif |
@@ -1145,7 +1145,7 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element | |||
1145 | } | 1145 | } |
1146 | 1146 | ||
1147 | switch (info_element->id) { | 1147 | switch (info_element->id) { |
1148 | case MFIE_TYPE_SSID: | 1148 | case WLAN_EID_SSID: |
1149 | network->ssid_len = min(info_element->len, | 1149 | network->ssid_len = min(info_element->len, |
1150 | (u8) IW_ESSID_MAX_SIZE); | 1150 | (u8) IW_ESSID_MAX_SIZE); |
1151 | memcpy(network->ssid, info_element->data, | 1151 | memcpy(network->ssid, info_element->data, |
@@ -1154,21 +1154,21 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element | |||
1154 | memset(network->ssid + network->ssid_len, 0, | 1154 | memset(network->ssid + network->ssid_len, 0, |
1155 | IW_ESSID_MAX_SIZE - network->ssid_len); | 1155 | IW_ESSID_MAX_SIZE - network->ssid_len); |
1156 | 1156 | ||
1157 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_SSID: '%s' len=%d.\n", | 1157 | IEEE80211_DEBUG_MGMT("WLAN_EID_SSID: '%s' len=%d.\n", |
1158 | print_ssid(ssid, network->ssid, | 1158 | print_ssid(ssid, network->ssid, |
1159 | network->ssid_len), | 1159 | network->ssid_len), |
1160 | network->ssid_len); | 1160 | network->ssid_len); |
1161 | break; | 1161 | break; |
1162 | 1162 | ||
1163 | case MFIE_TYPE_RATES: | 1163 | case WLAN_EID_SUPP_RATES: |
1164 | #ifdef CONFIG_IEEE80211_DEBUG | 1164 | #ifdef CONFIG_LIBIPW_DEBUG |
1165 | p = rates_str; | 1165 | p = rates_str; |
1166 | #endif | 1166 | #endif |
1167 | network->rates_len = min(info_element->len, | 1167 | network->rates_len = min(info_element->len, |
1168 | MAX_RATES_LENGTH); | 1168 | MAX_RATES_LENGTH); |
1169 | for (i = 0; i < network->rates_len; i++) { | 1169 | for (i = 0; i < network->rates_len; i++) { |
1170 | network->rates[i] = info_element->data[i]; | 1170 | network->rates[i] = info_element->data[i]; |
1171 | #ifdef CONFIG_IEEE80211_DEBUG | 1171 | #ifdef CONFIG_LIBIPW_DEBUG |
1172 | p += snprintf(p, sizeof(rates_str) - | 1172 | p += snprintf(p, sizeof(rates_str) - |
1173 | (p - rates_str), "%02X ", | 1173 | (p - rates_str), "%02X ", |
1174 | network->rates[i]); | 1174 | network->rates[i]); |
@@ -1183,19 +1183,19 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element | |||
1183 | } | 1183 | } |
1184 | } | 1184 | } |
1185 | 1185 | ||
1186 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES: '%s' (%d)\n", | 1186 | IEEE80211_DEBUG_MGMT("WLAN_EID_SUPP_RATES: '%s' (%d)\n", |
1187 | rates_str, network->rates_len); | 1187 | rates_str, network->rates_len); |
1188 | break; | 1188 | break; |
1189 | 1189 | ||
1190 | case MFIE_TYPE_RATES_EX: | 1190 | case WLAN_EID_EXT_SUPP_RATES: |
1191 | #ifdef CONFIG_IEEE80211_DEBUG | 1191 | #ifdef CONFIG_LIBIPW_DEBUG |
1192 | p = rates_str; | 1192 | p = rates_str; |
1193 | #endif | 1193 | #endif |
1194 | network->rates_ex_len = min(info_element->len, | 1194 | network->rates_ex_len = min(info_element->len, |
1195 | MAX_RATES_EX_LENGTH); | 1195 | MAX_RATES_EX_LENGTH); |
1196 | for (i = 0; i < network->rates_ex_len; i++) { | 1196 | for (i = 0; i < network->rates_ex_len; i++) { |
1197 | network->rates_ex[i] = info_element->data[i]; | 1197 | network->rates_ex[i] = info_element->data[i]; |
1198 | #ifdef CONFIG_IEEE80211_DEBUG | 1198 | #ifdef CONFIG_LIBIPW_DEBUG |
1199 | p += snprintf(p, sizeof(rates_str) - | 1199 | p += snprintf(p, sizeof(rates_str) - |
1200 | (p - rates_str), "%02X ", | 1200 | (p - rates_str), "%02X ", |
1201 | network->rates[i]); | 1201 | network->rates[i]); |
@@ -1210,49 +1210,49 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element | |||
1210 | } | 1210 | } |
1211 | } | 1211 | } |
1212 | 1212 | ||
1213 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES_EX: '%s' (%d)\n", | 1213 | IEEE80211_DEBUG_MGMT("WLAN_EID_EXT_SUPP_RATES: '%s' (%d)\n", |
1214 | rates_str, network->rates_ex_len); | 1214 | rates_str, network->rates_ex_len); |
1215 | break; | 1215 | break; |
1216 | 1216 | ||
1217 | case MFIE_TYPE_DS_SET: | 1217 | case WLAN_EID_DS_PARAMS: |
1218 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_DS_SET: %d\n", | 1218 | IEEE80211_DEBUG_MGMT("WLAN_EID_DS_PARAMS: %d\n", |
1219 | info_element->data[0]); | 1219 | info_element->data[0]); |
1220 | network->channel = info_element->data[0]; | 1220 | network->channel = info_element->data[0]; |
1221 | break; | 1221 | break; |
1222 | 1222 | ||
1223 | case MFIE_TYPE_FH_SET: | 1223 | case WLAN_EID_FH_PARAMS: |
1224 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_FH_SET: ignored\n"); | 1224 | IEEE80211_DEBUG_MGMT("WLAN_EID_FH_PARAMS: ignored\n"); |
1225 | break; | 1225 | break; |
1226 | 1226 | ||
1227 | case MFIE_TYPE_CF_SET: | 1227 | case WLAN_EID_CF_PARAMS: |
1228 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_CF_SET: ignored\n"); | 1228 | IEEE80211_DEBUG_MGMT("WLAN_EID_CF_PARAMS: ignored\n"); |
1229 | break; | 1229 | break; |
1230 | 1230 | ||
1231 | case MFIE_TYPE_TIM: | 1231 | case WLAN_EID_TIM: |
1232 | network->tim.tim_count = info_element->data[0]; | 1232 | network->tim.tim_count = info_element->data[0]; |
1233 | network->tim.tim_period = info_element->data[1]; | 1233 | network->tim.tim_period = info_element->data[1]; |
1234 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_TIM: partially ignored\n"); | 1234 | IEEE80211_DEBUG_MGMT("WLAN_EID_TIM: partially ignored\n"); |
1235 | break; | 1235 | break; |
1236 | 1236 | ||
1237 | case MFIE_TYPE_ERP_INFO: | 1237 | case WLAN_EID_ERP_INFO: |
1238 | network->erp_value = info_element->data[0]; | 1238 | network->erp_value = info_element->data[0]; |
1239 | network->flags |= NETWORK_HAS_ERP_VALUE; | 1239 | network->flags |= NETWORK_HAS_ERP_VALUE; |
1240 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_ERP_SET: %d\n", | 1240 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_ERP_SET: %d\n", |
1241 | network->erp_value); | 1241 | network->erp_value); |
1242 | break; | 1242 | break; |
1243 | 1243 | ||
1244 | case MFIE_TYPE_IBSS_SET: | 1244 | case WLAN_EID_IBSS_PARAMS: |
1245 | network->atim_window = info_element->data[0]; | 1245 | network->atim_window = info_element->data[0]; |
1246 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_IBSS_SET: %d\n", | 1246 | IEEE80211_DEBUG_MGMT("WLAN_EID_IBSS_PARAMS: %d\n", |
1247 | network->atim_window); | 1247 | network->atim_window); |
1248 | break; | 1248 | break; |
1249 | 1249 | ||
1250 | case MFIE_TYPE_CHALLENGE: | 1250 | case WLAN_EID_CHALLENGE: |
1251 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_CHALLENGE: ignored\n"); | 1251 | IEEE80211_DEBUG_MGMT("WLAN_EID_CHALLENGE: ignored\n"); |
1252 | break; | 1252 | break; |
1253 | 1253 | ||
1254 | case MFIE_TYPE_GENERIC: | 1254 | case WLAN_EID_GENERIC: |
1255 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_GENERIC: %d bytes\n", | 1255 | IEEE80211_DEBUG_MGMT("WLAN_EID_GENERIC: %d bytes\n", |
1256 | info_element->len); | 1256 | info_element->len); |
1257 | if (!ieee80211_parse_qos_info_param_IE(info_element, | 1257 | if (!ieee80211_parse_qos_info_param_IE(info_element, |
1258 | network)) | 1258 | network)) |
@@ -1270,8 +1270,8 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element | |||
1270 | } | 1270 | } |
1271 | break; | 1271 | break; |
1272 | 1272 | ||
1273 | case MFIE_TYPE_RSN: | 1273 | case WLAN_EID_RSN: |
1274 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_RSN: %d bytes\n", | 1274 | IEEE80211_DEBUG_MGMT("WLAN_EID_RSN: %d bytes\n", |
1275 | info_element->len); | 1275 | info_element->len); |
1276 | network->rsn_ie_len = min(info_element->len + 2, | 1276 | network->rsn_ie_len = min(info_element->len + 2, |
1277 | MAX_WPA_IE_LEN); | 1277 | MAX_WPA_IE_LEN); |
@@ -1279,22 +1279,22 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element | |||
1279 | network->rsn_ie_len); | 1279 | network->rsn_ie_len); |
1280 | break; | 1280 | break; |
1281 | 1281 | ||
1282 | case MFIE_TYPE_QOS_PARAMETER: | 1282 | case WLAN_EID_QOS_PARAMETER: |
1283 | printk(KERN_ERR | 1283 | printk(KERN_ERR |
1284 | "QoS Error need to parse QOS_PARAMETER IE\n"); | 1284 | "QoS Error need to parse QOS_PARAMETER IE\n"); |
1285 | break; | 1285 | break; |
1286 | /* 802.11h */ | 1286 | /* 802.11h */ |
1287 | case MFIE_TYPE_POWER_CONSTRAINT: | 1287 | case WLAN_EID_PWR_CONSTRAINT: |
1288 | network->power_constraint = info_element->data[0]; | 1288 | network->power_constraint = info_element->data[0]; |
1289 | network->flags |= NETWORK_HAS_POWER_CONSTRAINT; | 1289 | network->flags |= NETWORK_HAS_POWER_CONSTRAINT; |
1290 | break; | 1290 | break; |
1291 | 1291 | ||
1292 | case MFIE_TYPE_CSA: | 1292 | case WLAN_EID_CHANNEL_SWITCH: |
1293 | network->power_constraint = info_element->data[0]; | 1293 | network->power_constraint = info_element->data[0]; |
1294 | network->flags |= NETWORK_HAS_CSA; | 1294 | network->flags |= NETWORK_HAS_CSA; |
1295 | break; | 1295 | break; |
1296 | 1296 | ||
1297 | case MFIE_TYPE_QUIET: | 1297 | case WLAN_EID_QUIET: |
1298 | network->quiet.count = info_element->data[0]; | 1298 | network->quiet.count = info_element->data[0]; |
1299 | network->quiet.period = info_element->data[1]; | 1299 | network->quiet.period = info_element->data[1]; |
1300 | network->quiet.duration = info_element->data[2]; | 1300 | network->quiet.duration = info_element->data[2]; |
@@ -1302,7 +1302,7 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element | |||
1302 | network->flags |= NETWORK_HAS_QUIET; | 1302 | network->flags |= NETWORK_HAS_QUIET; |
1303 | break; | 1303 | break; |
1304 | 1304 | ||
1305 | case MFIE_TYPE_IBSS_DFS: | 1305 | case WLAN_EID_IBSS_DFS: |
1306 | if (network->ibss_dfs) | 1306 | if (network->ibss_dfs) |
1307 | break; | 1307 | break; |
1308 | network->ibss_dfs = kmemdup(info_element->data, | 1308 | network->ibss_dfs = kmemdup(info_element->data, |
@@ -1313,7 +1313,7 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element | |||
1313 | network->flags |= NETWORK_HAS_IBSS_DFS; | 1313 | network->flags |= NETWORK_HAS_IBSS_DFS; |
1314 | break; | 1314 | break; |
1315 | 1315 | ||
1316 | case MFIE_TYPE_TPC_REPORT: | 1316 | case WLAN_EID_TPC_REPORT: |
1317 | network->tpc_report.transmit_power = | 1317 | network->tpc_report.transmit_power = |
1318 | info_element->data[0]; | 1318 | info_element->data[0]; |
1319 | network->tpc_report.link_margin = info_element->data[1]; | 1319 | network->tpc_report.link_margin = info_element->data[1]; |
@@ -1562,7 +1562,7 @@ static void ieee80211_process_probe_response(struct ieee80211_device | |||
1562 | }; | 1562 | }; |
1563 | struct ieee80211_network *target; | 1563 | struct ieee80211_network *target; |
1564 | struct ieee80211_network *oldest = NULL; | 1564 | struct ieee80211_network *oldest = NULL; |
1565 | #ifdef CONFIG_IEEE80211_DEBUG | 1565 | #ifdef CONFIG_LIBIPW_DEBUG |
1566 | struct ieee80211_info_element *info_element = beacon->info_element; | 1566 | struct ieee80211_info_element *info_element = beacon->info_element; |
1567 | #endif | 1567 | #endif |
1568 | unsigned long flags; | 1568 | unsigned long flags; |
@@ -1640,7 +1640,7 @@ static void ieee80211_process_probe_response(struct ieee80211_device | |||
1640 | list_del(ieee->network_free_list.next); | 1640 | list_del(ieee->network_free_list.next); |
1641 | } | 1641 | } |
1642 | 1642 | ||
1643 | #ifdef CONFIG_IEEE80211_DEBUG | 1643 | #ifdef CONFIG_LIBIPW_DEBUG |
1644 | IEEE80211_DEBUG_SCAN("Adding '%s' (%pM) via %s.\n", | 1644 | IEEE80211_DEBUG_SCAN("Adding '%s' (%pM) via %s.\n", |
1645 | print_ssid(ssid, network.ssid, | 1645 | print_ssid(ssid, network.ssid, |
1646 | network.ssid_len), | 1646 | network.ssid_len), |
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index 6cc5a54d35c5..8304f6406a17 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig | |||
@@ -6,11 +6,9 @@ config IWLWIFI | |||
6 | select MAC80211_LEDS if IWLWIFI_LEDS | 6 | select MAC80211_LEDS if IWLWIFI_LEDS |
7 | select LEDS_CLASS if IWLWIFI_LEDS | 7 | select LEDS_CLASS if IWLWIFI_LEDS |
8 | select RFKILL if IWLWIFI_RFKILL | 8 | select RFKILL if IWLWIFI_RFKILL |
9 | select MAC80211_LEDS if IWL3945_LEDS | ||
10 | select LEDS_CLASS if IWL3945_LEDS | ||
11 | 9 | ||
12 | config IWLWIFI_LEDS | 10 | config IWLWIFI_LEDS |
13 | bool "Enable LED support in iwlagn driver" | 11 | bool "Enable LED support in iwlagn and iwl3945 drivers" |
14 | depends on IWLWIFI | 12 | depends on IWLWIFI |
15 | 13 | ||
16 | config IWLWIFI_RFKILL | 14 | config IWLWIFI_RFKILL |
@@ -87,7 +85,7 @@ config IWL4965 | |||
87 | This option enables support for Intel Wireless WiFi Link 4965AGN | 85 | This option enables support for Intel Wireless WiFi Link 4965AGN |
88 | 86 | ||
89 | config IWL5000 | 87 | config IWL5000 |
90 | bool "Intel Wireless WiFi 5000AGN; Intel WiFi Link 100, 6000, and 6050 Series" | 88 | bool "Intel Wireless WiFi 5000AGN; Intel WiFi Link 1000, 6000, and 6050 Series" |
91 | depends on IWLAGN | 89 | depends on IWLAGN |
92 | ---help--- | 90 | ---help--- |
93 | This option enables support for Intel Wireless WiFi Link 5000AGN Family | 91 | This option enables support for Intel Wireless WiFi Link 5000AGN Family |
@@ -122,9 +120,3 @@ config IWL3945_SPECTRUM_MEASUREMENT | |||
122 | depends on IWL3945 | 120 | depends on IWL3945 |
123 | ---help--- | 121 | ---help--- |
124 | This option will enable spectrum measurement for the iwl3945 driver. | 122 | This option will enable spectrum measurement for the iwl3945 driver. |
125 | |||
126 | config IWL3945_LEDS | ||
127 | bool "Enable LEDS features in iwl3945 driver" | ||
128 | depends on IWL3945 | ||
129 | ---help--- | ||
130 | This option enables LEDS for the iwl3945 driver. | ||
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 48af523ceab7..d79d97ad61a5 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile | |||
@@ -13,10 +13,9 @@ iwlagn-objs := iwl-agn.o iwl-agn-rs.o | |||
13 | iwlagn-$(CONFIG_IWL4965) += iwl-4965.o | 13 | iwlagn-$(CONFIG_IWL4965) += iwl-4965.o |
14 | iwlagn-$(CONFIG_IWL5000) += iwl-5000.o | 14 | iwlagn-$(CONFIG_IWL5000) += iwl-5000.o |
15 | iwlagn-$(CONFIG_IWL5000) += iwl-6000.o | 15 | iwlagn-$(CONFIG_IWL5000) += iwl-6000.o |
16 | iwlagn-$(CONFIG_IWL5000) += iwl-100.o | 16 | iwlagn-$(CONFIG_IWL5000) += iwl-1000.o |
17 | 17 | ||
18 | obj-$(CONFIG_IWL3945) += iwl3945.o | 18 | obj-$(CONFIG_IWL3945) += iwl3945.o |
19 | iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o | 19 | iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o iwl-3945-led.o |
20 | iwl3945-$(CONFIG_IWL3945_LEDS) += iwl-3945-led.o | ||
21 | 20 | ||
22 | 21 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-100.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 11d206abb710..7da52f1cc1d6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-100.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c | |||
@@ -46,20 +46,20 @@ | |||
46 | #include "iwl-5000-hw.h" | 46 | #include "iwl-5000-hw.h" |
47 | 47 | ||
48 | /* Highest firmware API version supported */ | 48 | /* Highest firmware API version supported */ |
49 | #define IWL100_UCODE_API_MAX 2 | 49 | #define IWL1000_UCODE_API_MAX 2 |
50 | 50 | ||
51 | /* Lowest firmware API version supported */ | 51 | /* Lowest firmware API version supported */ |
52 | #define IWL100_UCODE_API_MIN 1 | 52 | #define IWL1000_UCODE_API_MIN 1 |
53 | 53 | ||
54 | #define IWL100_FW_PRE "iwlwifi-100-" | 54 | #define IWL1000_FW_PRE "iwlwifi-1000-" |
55 | #define _IWL100_MODULE_FIRMWARE(api) IWL100_FW_PRE #api ".ucode" | 55 | #define _IWL1000_MODULE_FIRMWARE(api) IWL1000_FW_PRE #api ".ucode" |
56 | #define IWL100_MODULE_FIRMWARE(api) _IWL100_MODULE_FIRMWARE(api) | 56 | #define IWL1000_MODULE_FIRMWARE(api) _IWL1000_MODULE_FIRMWARE(api) |
57 | 57 | ||
58 | struct iwl_cfg iwl100_bgn_cfg = { | 58 | struct iwl_cfg iwl1000_bgn_cfg = { |
59 | .name = "100 Series BGN", | 59 | .name = "1000 Series BGN", |
60 | .fw_name_pre = IWL100_FW_PRE, | 60 | .fw_name_pre = IWL1000_FW_PRE, |
61 | .ucode_api_max = IWL100_UCODE_API_MAX, | 61 | .ucode_api_max = IWL1000_UCODE_API_MAX, |
62 | .ucode_api_min = IWL100_UCODE_API_MIN, | 62 | .ucode_api_min = IWL1000_UCODE_API_MIN, |
63 | .sku = IWL_SKU_G|IWL_SKU_N, | 63 | .sku = IWL_SKU_G|IWL_SKU_N, |
64 | .ops = &iwl5000_ops, | 64 | .ops = &iwl5000_ops, |
65 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 65 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c index a973ac13a1d5..ac22f59be9ef 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c | |||
@@ -24,6 +24,7 @@ | |||
24 | * | 24 | * |
25 | *****************************************************************************/ | 25 | *****************************************************************************/ |
26 | 26 | ||
27 | #ifdef CONFIG_IWLWIFI_LEDS | ||
27 | 28 | ||
28 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
29 | #include <linux/module.h> | 30 | #include <linux/module.h> |
@@ -163,8 +164,8 @@ static int iwl3945_led_associated(struct iwl_priv *priv, int led_id) | |||
163 | static void iwl3945_led_brightness_set(struct led_classdev *led_cdev, | 164 | static void iwl3945_led_brightness_set(struct led_classdev *led_cdev, |
164 | enum led_brightness brightness) | 165 | enum led_brightness brightness) |
165 | { | 166 | { |
166 | struct iwl3945_led *led = container_of(led_cdev, | 167 | struct iwl_led *led = container_of(led_cdev, |
167 | struct iwl3945_led, led_dev); | 168 | struct iwl_led, led_dev); |
168 | struct iwl_priv *priv = led->priv; | 169 | struct iwl_priv *priv = led->priv; |
169 | 170 | ||
170 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 171 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
@@ -202,7 +203,7 @@ static void iwl3945_led_brightness_set(struct led_classdev *led_cdev, | |||
202 | * Register led class with the system | 203 | * Register led class with the system |
203 | */ | 204 | */ |
204 | static int iwl3945_led_register_led(struct iwl_priv *priv, | 205 | static int iwl3945_led_register_led(struct iwl_priv *priv, |
205 | struct iwl3945_led *led, | 206 | struct iwl_led *led, |
206 | enum led_type type, u8 set_led, | 207 | enum led_type type, u8 set_led, |
207 | char *trigger) | 208 | char *trigger) |
208 | { | 209 | { |
@@ -315,66 +316,66 @@ int iwl3945_led_register(struct iwl_priv *priv) | |||
315 | priv->allow_blinking = 0; | 316 | priv->allow_blinking = 0; |
316 | 317 | ||
317 | trigger = ieee80211_get_radio_led_name(priv->hw); | 318 | trigger = ieee80211_get_radio_led_name(priv->hw); |
318 | snprintf(priv->led39[IWL_LED_TRG_RADIO].name, | 319 | snprintf(priv->led[IWL_LED_TRG_RADIO].name, |
319 | sizeof(priv->led39[IWL_LED_TRG_RADIO].name), "iwl-%s::radio", | 320 | sizeof(priv->led[IWL_LED_TRG_RADIO].name), "iwl-%s::radio", |
320 | wiphy_name(priv->hw->wiphy)); | 321 | wiphy_name(priv->hw->wiphy)); |
321 | 322 | ||
322 | priv->led39[IWL_LED_TRG_RADIO].led_on = iwl3945_led_on; | 323 | priv->led[IWL_LED_TRG_RADIO].led_on = iwl3945_led_on; |
323 | priv->led39[IWL_LED_TRG_RADIO].led_off = iwl3945_led_off; | 324 | priv->led[IWL_LED_TRG_RADIO].led_off = iwl3945_led_off; |
324 | priv->led39[IWL_LED_TRG_RADIO].led_pattern = NULL; | 325 | priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL; |
325 | 326 | ||
326 | ret = iwl3945_led_register_led(priv, | 327 | ret = iwl3945_led_register_led(priv, |
327 | &priv->led39[IWL_LED_TRG_RADIO], | 328 | &priv->led[IWL_LED_TRG_RADIO], |
328 | IWL_LED_TRG_RADIO, 1, trigger); | 329 | IWL_LED_TRG_RADIO, 1, trigger); |
329 | 330 | ||
330 | if (ret) | 331 | if (ret) |
331 | goto exit_fail; | 332 | goto exit_fail; |
332 | 333 | ||
333 | trigger = ieee80211_get_assoc_led_name(priv->hw); | 334 | trigger = ieee80211_get_assoc_led_name(priv->hw); |
334 | snprintf(priv->led39[IWL_LED_TRG_ASSOC].name, | 335 | snprintf(priv->led[IWL_LED_TRG_ASSOC].name, |
335 | sizeof(priv->led39[IWL_LED_TRG_ASSOC].name), "iwl-%s::assoc", | 336 | sizeof(priv->led[IWL_LED_TRG_ASSOC].name), "iwl-%s::assoc", |
336 | wiphy_name(priv->hw->wiphy)); | 337 | wiphy_name(priv->hw->wiphy)); |
337 | 338 | ||
338 | ret = iwl3945_led_register_led(priv, | 339 | ret = iwl3945_led_register_led(priv, |
339 | &priv->led39[IWL_LED_TRG_ASSOC], | 340 | &priv->led[IWL_LED_TRG_ASSOC], |
340 | IWL_LED_TRG_ASSOC, 0, trigger); | 341 | IWL_LED_TRG_ASSOC, 0, trigger); |
341 | 342 | ||
342 | /* for assoc always turn led on */ | 343 | /* for assoc always turn led on */ |
343 | priv->led39[IWL_LED_TRG_ASSOC].led_on = iwl3945_led_on; | 344 | priv->led[IWL_LED_TRG_ASSOC].led_on = iwl3945_led_on; |
344 | priv->led39[IWL_LED_TRG_ASSOC].led_off = iwl3945_led_on; | 345 | priv->led[IWL_LED_TRG_ASSOC].led_off = iwl3945_led_on; |
345 | priv->led39[IWL_LED_TRG_ASSOC].led_pattern = NULL; | 346 | priv->led[IWL_LED_TRG_ASSOC].led_pattern = NULL; |
346 | 347 | ||
347 | if (ret) | 348 | if (ret) |
348 | goto exit_fail; | 349 | goto exit_fail; |
349 | 350 | ||
350 | trigger = ieee80211_get_rx_led_name(priv->hw); | 351 | trigger = ieee80211_get_rx_led_name(priv->hw); |
351 | snprintf(priv->led39[IWL_LED_TRG_RX].name, | 352 | snprintf(priv->led[IWL_LED_TRG_RX].name, |
352 | sizeof(priv->led39[IWL_LED_TRG_RX].name), "iwl-%s::RX", | 353 | sizeof(priv->led[IWL_LED_TRG_RX].name), "iwl-%s::RX", |
353 | wiphy_name(priv->hw->wiphy)); | 354 | wiphy_name(priv->hw->wiphy)); |
354 | 355 | ||
355 | ret = iwl3945_led_register_led(priv, | 356 | ret = iwl3945_led_register_led(priv, |
356 | &priv->led39[IWL_LED_TRG_RX], | 357 | &priv->led[IWL_LED_TRG_RX], |
357 | IWL_LED_TRG_RX, 0, trigger); | 358 | IWL_LED_TRG_RX, 0, trigger); |
358 | 359 | ||
359 | priv->led39[IWL_LED_TRG_RX].led_on = iwl3945_led_associated; | 360 | priv->led[IWL_LED_TRG_RX].led_on = iwl3945_led_associated; |
360 | priv->led39[IWL_LED_TRG_RX].led_off = iwl3945_led_associated; | 361 | priv->led[IWL_LED_TRG_RX].led_off = iwl3945_led_associated; |
361 | priv->led39[IWL_LED_TRG_RX].led_pattern = iwl3945_led_pattern; | 362 | priv->led[IWL_LED_TRG_RX].led_pattern = iwl3945_led_pattern; |
362 | 363 | ||
363 | if (ret) | 364 | if (ret) |
364 | goto exit_fail; | 365 | goto exit_fail; |
365 | 366 | ||
366 | trigger = ieee80211_get_tx_led_name(priv->hw); | 367 | trigger = ieee80211_get_tx_led_name(priv->hw); |
367 | snprintf(priv->led39[IWL_LED_TRG_TX].name, | 368 | snprintf(priv->led[IWL_LED_TRG_TX].name, |
368 | sizeof(priv->led39[IWL_LED_TRG_TX].name), "iwl-%s::TX", | 369 | sizeof(priv->led[IWL_LED_TRG_TX].name), "iwl-%s::TX", |
369 | wiphy_name(priv->hw->wiphy)); | 370 | wiphy_name(priv->hw->wiphy)); |
370 | 371 | ||
371 | ret = iwl3945_led_register_led(priv, | 372 | ret = iwl3945_led_register_led(priv, |
372 | &priv->led39[IWL_LED_TRG_TX], | 373 | &priv->led[IWL_LED_TRG_TX], |
373 | IWL_LED_TRG_TX, 0, trigger); | 374 | IWL_LED_TRG_TX, 0, trigger); |
374 | 375 | ||
375 | priv->led39[IWL_LED_TRG_TX].led_on = iwl3945_led_associated; | 376 | priv->led[IWL_LED_TRG_TX].led_on = iwl3945_led_associated; |
376 | priv->led39[IWL_LED_TRG_TX].led_off = iwl3945_led_associated; | 377 | priv->led[IWL_LED_TRG_TX].led_off = iwl3945_led_associated; |
377 | priv->led39[IWL_LED_TRG_TX].led_pattern = iwl3945_led_pattern; | 378 | priv->led[IWL_LED_TRG_TX].led_pattern = iwl3945_led_pattern; |
378 | 379 | ||
379 | if (ret) | 380 | if (ret) |
380 | goto exit_fail; | 381 | goto exit_fail; |
@@ -388,7 +389,7 @@ exit_fail: | |||
388 | 389 | ||
389 | 390 | ||
390 | /* unregister led class */ | 391 | /* unregister led class */ |
391 | static void iwl3945_led_unregister_led(struct iwl3945_led *led, u8 set_led) | 392 | static void iwl3945_led_unregister_led(struct iwl_led *led, u8 set_led) |
392 | { | 393 | { |
393 | if (!led->registered) | 394 | if (!led->registered) |
394 | return; | 395 | return; |
@@ -403,9 +404,10 @@ static void iwl3945_led_unregister_led(struct iwl3945_led *led, u8 set_led) | |||
403 | /* Unregister all led handlers */ | 404 | /* Unregister all led handlers */ |
404 | void iwl3945_led_unregister(struct iwl_priv *priv) | 405 | void iwl3945_led_unregister(struct iwl_priv *priv) |
405 | { | 406 | { |
406 | iwl3945_led_unregister_led(&priv->led39[IWL_LED_TRG_ASSOC], 0); | 407 | iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_ASSOC], 0); |
407 | iwl3945_led_unregister_led(&priv->led39[IWL_LED_TRG_RX], 0); | 408 | iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_RX], 0); |
408 | iwl3945_led_unregister_led(&priv->led39[IWL_LED_TRG_TX], 0); | 409 | iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_TX], 0); |
409 | iwl3945_led_unregister_led(&priv->led39[IWL_LED_TRG_RADIO], 1); | 410 | iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_RADIO], 1); |
410 | } | 411 | } |
411 | 412 | ||
413 | #endif | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.h b/drivers/net/wireless/iwlwifi/iwl-3945-led.h index 88185a6ccd6a..3b65642258ca 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.h | |||
@@ -29,24 +29,10 @@ | |||
29 | 29 | ||
30 | struct iwl_priv; | 30 | struct iwl_priv; |
31 | 31 | ||
32 | #ifdef CONFIG_IWL3945_LEDS | 32 | #ifdef CONFIG_IWLWIFI_LEDS |
33 | 33 | ||
34 | #include "iwl-led.h" | 34 | #include "iwl-led.h" |
35 | 35 | ||
36 | struct iwl3945_led { | ||
37 | struct iwl_priv *priv; | ||
38 | struct led_classdev led_dev; | ||
39 | char name[32]; | ||
40 | |||
41 | int (*led_on) (struct iwl_priv *priv, int led_id); | ||
42 | int (*led_off) (struct iwl_priv *priv, int led_id); | ||
43 | int (*led_pattern) (struct iwl_priv *priv, int led_id, | ||
44 | unsigned int idx); | ||
45 | |||
46 | enum led_type type; | ||
47 | unsigned int registered; | ||
48 | }; | ||
49 | |||
50 | extern int iwl3945_led_register(struct iwl_priv *priv); | 36 | extern int iwl3945_led_register(struct iwl_priv *priv); |
51 | extern void iwl3945_led_unregister(struct iwl_priv *priv); | 37 | extern void iwl3945_led_unregister(struct iwl_priv *priv); |
52 | extern void iwl3945_led_background(struct iwl_priv *priv); | 38 | extern void iwl3945_led_background(struct iwl_priv *priv); |
@@ -55,6 +41,6 @@ extern void iwl3945_led_background(struct iwl_priv *priv); | |||
55 | static inline int iwl3945_led_register(struct iwl_priv *priv) { return 0; } | 41 | static inline int iwl3945_led_register(struct iwl_priv *priv) { return 0; } |
56 | static inline void iwl3945_led_unregister(struct iwl_priv *priv) {} | 42 | static inline void iwl3945_led_unregister(struct iwl_priv *priv) {} |
57 | static inline void iwl3945_led_background(struct iwl_priv *priv) {} | 43 | static inline void iwl3945_led_background(struct iwl_priv *priv) {} |
58 | #endif /* CONFIG_IWL3945_LEDS */ | ||
59 | 44 | ||
45 | #endif /* IWLWIFI_LEDS*/ | ||
60 | #endif /* IWL3945_LEDS_H */ | 46 | #endif /* IWL3945_LEDS_H */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index a2664589c884..f65c308a6714 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c | |||
@@ -127,6 +127,7 @@ static struct iwl3945_tpt_entry iwl3945_tpt_table_g[] = { | |||
127 | #define IWL_RATE_MIN_FAILURE_TH 8 | 127 | #define IWL_RATE_MIN_FAILURE_TH 8 |
128 | #define IWL_RATE_MIN_SUCCESS_TH 8 | 128 | #define IWL_RATE_MIN_SUCCESS_TH 8 |
129 | #define IWL_RATE_DECREASE_TH 1920 | 129 | #define IWL_RATE_DECREASE_TH 1920 |
130 | #define IWL_RATE_RETRY_TH 15 | ||
130 | 131 | ||
131 | static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, enum ieee80211_band band) | 132 | static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, enum ieee80211_band band) |
132 | { | 133 | { |
@@ -298,37 +299,53 @@ static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta, | |||
298 | } | 299 | } |
299 | 300 | ||
300 | spin_lock_irqsave(&rs_sta->lock, flags); | 301 | spin_lock_irqsave(&rs_sta->lock, flags); |
301 | while (retries--) { | ||
302 | 302 | ||
303 | /* If we have filled up the window then subtract one from the | 303 | /* |
304 | * success counter if the high-bit is counting toward | 304 | * Keep track of only the latest 62 tx frame attempts in this rate's |
305 | * success */ | 305 | * history window; anything older isn't really relevant any more. |
306 | if (window->counter == IWL_RATE_MAX_WINDOW) { | 306 | * If we have filled up the sliding window, drop the oldest attempt; |
307 | if (window->data & (1ULL << (IWL_RATE_MAX_WINDOW - 1))) | 307 | * if the oldest attempt (highest bit in bitmap) shows "success", |
308 | * subtract "1" from the success counter (this is the main reason | ||
309 | * we keep these bitmaps!). | ||
310 | * */ | ||
311 | while (retries > 0) { | ||
312 | if (window->counter >= IWL_RATE_MAX_WINDOW) { | ||
313 | |||
314 | /* remove earliest */ | ||
315 | window->counter = IWL_RATE_MAX_WINDOW - 1; | ||
316 | |||
317 | if (window->data & (1ULL << (IWL_RATE_MAX_WINDOW - 1))) { | ||
318 | window->data &= ~(1ULL << (IWL_RATE_MAX_WINDOW - 1)); | ||
308 | window->success_counter--; | 319 | window->success_counter--; |
309 | } else | 320 | } |
310 | window->counter++; | 321 | } |
311 | 322 | ||
312 | /* Slide the window to the left one bit */ | 323 | /* Increment frames-attempted counter */ |
313 | window->data = (window->data << 1); | 324 | window->counter++; |
314 | 325 | ||
315 | /* If this packet was a success then set the low bit high */ | 326 | /* Shift bitmap by one frame (throw away oldest history), |
316 | if (success) { | 327 | * OR in "1", and increment "success" if this |
328 | * frame was successful. */ | ||
329 | window->data <<= 1; | ||
330 | if (success > 0) { | ||
317 | window->success_counter++; | 331 | window->success_counter++; |
318 | window->data |= 1; | 332 | window->data |= 0x1; |
333 | success--; | ||
319 | } | 334 | } |
320 | 335 | ||
321 | /* window->counter can't be 0 -- it is either >0 or | 336 | retries--; |
322 | * IWL_RATE_MAX_WINDOW */ | ||
323 | window->success_ratio = 12800 * window->success_counter / | ||
324 | window->counter; | ||
325 | |||
326 | /* Tag this window as having been updated */ | ||
327 | window->stamp = jiffies; | ||
328 | |||
329 | } | 337 | } |
330 | 338 | ||
339 | /* Calculate current success ratio, avoid divide-by-0! */ | ||
340 | if (window->counter > 0) | ||
341 | window->success_ratio = 128 * (100 * window->success_counter) | ||
342 | / window->counter; | ||
343 | else | ||
344 | window->success_ratio = IWL_INVALID_VALUE; | ||
345 | |||
331 | fail_count = window->counter - window->success_counter; | 346 | fail_count = window->counter - window->success_counter; |
347 | |||
348 | /* Calculate average throughput, if we have enough history. */ | ||
332 | if ((fail_count >= IWL_RATE_MIN_FAILURE_TH) || | 349 | if ((fail_count >= IWL_RATE_MIN_FAILURE_TH) || |
333 | (window->success_counter >= IWL_RATE_MIN_SUCCESS_TH)) | 350 | (window->success_counter >= IWL_RATE_MIN_SUCCESS_TH)) |
334 | window->average_tpt = ((window->success_ratio * | 351 | window->average_tpt = ((window->success_ratio * |
@@ -336,6 +353,9 @@ static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta, | |||
336 | else | 353 | else |
337 | window->average_tpt = IWL_INVALID_VALUE; | 354 | window->average_tpt = IWL_INVALID_VALUE; |
338 | 355 | ||
356 | /* Tag this window as having been updated */ | ||
357 | window->stamp = jiffies; | ||
358 | |||
339 | spin_unlock_irqrestore(&rs_sta->lock, flags); | 359 | spin_unlock_irqrestore(&rs_sta->lock, flags); |
340 | 360 | ||
341 | } | 361 | } |
@@ -468,7 +488,10 @@ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband | |||
468 | 488 | ||
469 | IWL_DEBUG_RATE(priv, "enter\n"); | 489 | IWL_DEBUG_RATE(priv, "enter\n"); |
470 | 490 | ||
471 | retries = info->status.rates[0].count; | 491 | retries = info->status.rates[0].count - 1; |
492 | /* Sanity Check for retries */ | ||
493 | if (retries > IWL_RATE_RETRY_TH) | ||
494 | retries = IWL_RATE_RETRY_TH; | ||
472 | 495 | ||
473 | first_index = sband->bitrates[info->status.rates[0].idx].hw_value; | 496 | first_index = sband->bitrates[info->status.rates[0].idx].hw_value; |
474 | if ((first_index < 0) || (first_index >= IWL_RATE_COUNT_3945)) { | 497 | if ((first_index < 0) || (first_index >= IWL_RATE_COUNT_3945)) { |
@@ -724,7 +747,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, | |||
724 | 747 | ||
725 | fail_count = window->counter - window->success_counter; | 748 | fail_count = window->counter - window->success_counter; |
726 | 749 | ||
727 | if (((fail_count <= IWL_RATE_MIN_FAILURE_TH) && | 750 | if (((fail_count < IWL_RATE_MIN_FAILURE_TH) && |
728 | (window->success_counter < IWL_RATE_MIN_SUCCESS_TH))) { | 751 | (window->success_counter < IWL_RATE_MIN_SUCCESS_TH))) { |
729 | spin_unlock_irqrestore(&rs_sta->lock, flags); | 752 | spin_unlock_irqrestore(&rs_sta->lock, flags); |
730 | 753 | ||
@@ -735,6 +758,9 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, | |||
735 | window->counter, | 758 | window->counter, |
736 | window->success_counter, | 759 | window->success_counter, |
737 | rs_sta->expected_tpt ? "not " : ""); | 760 | rs_sta->expected_tpt ? "not " : ""); |
761 | |||
762 | /* Can't calculate this yet; not enough history */ | ||
763 | window->average_tpt = IWL_INVALID_VALUE; | ||
738 | goto out; | 764 | goto out; |
739 | 765 | ||
740 | } | 766 | } |
@@ -750,6 +776,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, | |||
750 | if ((max_rate_idx != -1) && (max_rate_idx < high)) | 776 | if ((max_rate_idx != -1) && (max_rate_idx < high)) |
751 | high = IWL_RATE_INVALID; | 777 | high = IWL_RATE_INVALID; |
752 | 778 | ||
779 | /* Collect Measured throughputs of adjacent rates */ | ||
753 | if (low != IWL_RATE_INVALID) | 780 | if (low != IWL_RATE_INVALID) |
754 | low_tpt = rs_sta->win[low].average_tpt; | 781 | low_tpt = rs_sta->win[low].average_tpt; |
755 | 782 | ||
@@ -758,24 +785,43 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, | |||
758 | 785 | ||
759 | spin_unlock_irqrestore(&rs_sta->lock, flags); | 786 | spin_unlock_irqrestore(&rs_sta->lock, flags); |
760 | 787 | ||
761 | scale_action = 1; | 788 | scale_action = 0; |
762 | 789 | ||
790 | /* Low success ratio , need to drop the rate */ | ||
763 | if ((window->success_ratio < IWL_RATE_DECREASE_TH) || !current_tpt) { | 791 | if ((window->success_ratio < IWL_RATE_DECREASE_TH) || !current_tpt) { |
764 | IWL_DEBUG_RATE(priv, "decrease rate because of low success_ratio\n"); | 792 | IWL_DEBUG_RATE(priv, "decrease rate because of low success_ratio\n"); |
765 | scale_action = -1; | 793 | scale_action = -1; |
794 | |||
795 | /* No throughput measured yet for adjacent rates, | ||
796 | * try increase */ | ||
766 | } else if ((low_tpt == IWL_INVALID_VALUE) && | 797 | } else if ((low_tpt == IWL_INVALID_VALUE) && |
767 | (high_tpt == IWL_INVALID_VALUE)) | 798 | (high_tpt == IWL_INVALID_VALUE)) { |
768 | scale_action = 1; | 799 | |
769 | else if ((low_tpt != IWL_INVALID_VALUE) && | 800 | if (high != IWL_RATE_INVALID && window->success_counter >= IWL_RATE_INCREASE_TH) |
801 | scale_action = 1; | ||
802 | else if (low != IWL_RATE_INVALID) | ||
803 | scale_action = -1; | ||
804 | |||
805 | /* Both adjacent throughputs are measured, but neither one has | ||
806 | * better throughput; we're using the best rate, don't change | ||
807 | * it! */ | ||
808 | } else if ((low_tpt != IWL_INVALID_VALUE) && | ||
770 | (high_tpt != IWL_INVALID_VALUE) && | 809 | (high_tpt != IWL_INVALID_VALUE) && |
771 | (low_tpt < current_tpt) && (high_tpt < current_tpt)) { | 810 | (low_tpt < current_tpt) && (high_tpt < current_tpt)) { |
811 | |||
772 | IWL_DEBUG_RATE(priv, "No action -- low [%d] & high [%d] < " | 812 | IWL_DEBUG_RATE(priv, "No action -- low [%d] & high [%d] < " |
773 | "current_tpt [%d]\n", | 813 | "current_tpt [%d]\n", |
774 | low_tpt, high_tpt, current_tpt); | 814 | low_tpt, high_tpt, current_tpt); |
775 | scale_action = 0; | 815 | scale_action = 0; |
816 | |||
817 | /* At least one of the rates has better throughput */ | ||
776 | } else { | 818 | } else { |
777 | if (high_tpt != IWL_INVALID_VALUE) { | 819 | if (high_tpt != IWL_INVALID_VALUE) { |
778 | if (high_tpt > current_tpt) | 820 | |
821 | /* High rate has better throughput, Increase | ||
822 | * rate */ | ||
823 | if (high_tpt > current_tpt && | ||
824 | window->success_ratio >= IWL_RATE_INCREASE_TH) | ||
779 | scale_action = 1; | 825 | scale_action = 1; |
780 | else { | 826 | else { |
781 | IWL_DEBUG_RATE(priv, | 827 | IWL_DEBUG_RATE(priv, |
@@ -787,29 +833,31 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, | |||
787 | IWL_DEBUG_RATE(priv, | 833 | IWL_DEBUG_RATE(priv, |
788 | "decrease rate because of low tpt\n"); | 834 | "decrease rate because of low tpt\n"); |
789 | scale_action = -1; | 835 | scale_action = -1; |
790 | } else | 836 | } else if (window->success_counter >= IWL_RATE_INCREASE_TH) { |
837 | /* Lower rate has better | ||
838 | * throughput,decrease rate */ | ||
791 | scale_action = 1; | 839 | scale_action = 1; |
840 | } | ||
792 | } | 841 | } |
793 | } | 842 | } |
794 | 843 | ||
795 | if (scale_action == -1) { | 844 | /* Sanity check; asked for decrease, but success rate or throughput |
796 | if (window->success_ratio > IWL_SUCCESS_DOWN_TH) | 845 | * has been good at old rate. Don't change it. */ |
797 | scale_action = 0; | 846 | if ((scale_action == -1) && (low != IWL_RATE_INVALID) && |
798 | } else if (scale_action == 1) { | 847 | ((window->success_ratio > IWL_RATE_HIGH_TH) || |
799 | if (window->success_ratio < IWL_SUCCESS_UP_TH) { | 848 | (current_tpt > (100 * rs_sta->expected_tpt[low])))) |
800 | IWL_DEBUG_RATE(priv, "No action -- success_ratio [%d] < " | 849 | scale_action = 0; |
801 | "SUCCESS UP\n", window->success_ratio); | ||
802 | scale_action = 0; | ||
803 | } | ||
804 | } | ||
805 | 850 | ||
806 | switch (scale_action) { | 851 | switch (scale_action) { |
807 | case -1: | 852 | case -1: |
853 | |||
854 | /* Decrese rate */ | ||
808 | if (low != IWL_RATE_INVALID) | 855 | if (low != IWL_RATE_INVALID) |
809 | index = low; | 856 | index = low; |
810 | break; | 857 | break; |
811 | 858 | ||
812 | case 1: | 859 | case 1: |
860 | /* Increase rate */ | ||
813 | if (high != IWL_RATE_INVALID) | 861 | if (high != IWL_RATE_INVALID) |
814 | index = high; | 862 | index = high; |
815 | 863 | ||
@@ -817,6 +865,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, | |||
817 | 865 | ||
818 | case 0: | 866 | case 0: |
819 | default: | 867 | default: |
868 | /* No change */ | ||
820 | break; | 869 | break; |
821 | } | 870 | } |
822 | 871 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 0a750534ddf2..ba7e720e73c1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c | |||
@@ -554,7 +554,7 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv, | |||
554 | struct ieee80211_rx_status *stats) | 554 | struct ieee80211_rx_status *stats) |
555 | { | 555 | { |
556 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 556 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; |
557 | #ifdef CONFIG_IWL3945_LEDS | 557 | #ifdef CONFIG_IWLWIFI_LEDS |
558 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); | 558 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); |
559 | #endif | 559 | #endif |
560 | struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); | 560 | struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); |
@@ -583,7 +583,7 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv, | |||
583 | (struct ieee80211_hdr *)rxb->skb->data, | 583 | (struct ieee80211_hdr *)rxb->skb->data, |
584 | le32_to_cpu(rx_end->status), stats); | 584 | le32_to_cpu(rx_end->status), stats); |
585 | 585 | ||
586 | #ifdef CONFIG_IWL3945_LEDS | 586 | #ifdef CONFIG_IWLWIFI_LEDS |
587 | if (ieee80211_is_data(hdr->frame_control)) | 587 | if (ieee80211_is_data(hdr->frame_control)) |
588 | priv->rxtxpackets += len; | 588 | priv->rxtxpackets += len; |
589 | #endif | 589 | #endif |
@@ -741,7 +741,8 @@ int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, | |||
741 | void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) | 741 | void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) |
742 | { | 742 | { |
743 | struct iwl3945_tfd *tfd_tmp = (struct iwl3945_tfd *)txq->tfds; | 743 | struct iwl3945_tfd *tfd_tmp = (struct iwl3945_tfd *)txq->tfds; |
744 | struct iwl3945_tfd *tfd = &tfd_tmp[txq->q.read_ptr]; | 744 | int index = txq->q.read_ptr; |
745 | struct iwl3945_tfd *tfd = &tfd_tmp[index]; | ||
745 | struct pci_dev *dev = priv->pci_dev; | 746 | struct pci_dev *dev = priv->pci_dev; |
746 | int i; | 747 | int i; |
747 | int counter; | 748 | int counter; |
@@ -759,6 +760,13 @@ void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) | |||
759 | return; | 760 | return; |
760 | } | 761 | } |
761 | 762 | ||
763 | /* Unmap tx_cmd */ | ||
764 | if (counter) | ||
765 | pci_unmap_single(dev, | ||
766 | pci_unmap_addr(&txq->cmd[index]->meta, mapping), | ||
767 | pci_unmap_len(&txq->cmd[index]->meta, len), | ||
768 | PCI_DMA_TODEVICE); | ||
769 | |||
762 | /* unmap chunks if any */ | 770 | /* unmap chunks if any */ |
763 | 771 | ||
764 | for (i = 1; i < counter; i++) { | 772 | for (i = 1; i < counter; i++) { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 99da40678878..cab7842a73aa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |||
@@ -801,7 +801,10 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
801 | !(info->flags & IEEE80211_TX_STAT_AMPDU)) | 801 | !(info->flags & IEEE80211_TX_STAT_AMPDU)) |
802 | return; | 802 | return; |
803 | 803 | ||
804 | retries = info->status.rates[0].count - 1; | 804 | if (info->flags & IEEE80211_TX_STAT_AMPDU) |
805 | retries = 0; | ||
806 | else | ||
807 | retries = info->status.rates[0].count - 1; | ||
805 | 808 | ||
806 | if (retries > 15) | 809 | if (retries > 15) |
807 | retries = 15; | 810 | retries = 15; |
@@ -913,7 +916,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
913 | tpt = search_tbl->expected_tpt[rs_index]; | 916 | tpt = search_tbl->expected_tpt[rs_index]; |
914 | else | 917 | else |
915 | tpt = 0; | 918 | tpt = 0; |
916 | if (info->flags & IEEE80211_TX_CTL_AMPDU) | 919 | if (info->flags & IEEE80211_TX_STAT_AMPDU) |
917 | rs_collect_tx_data(search_win, rs_index, tpt, | 920 | rs_collect_tx_data(search_win, rs_index, tpt, |
918 | info->status.ampdu_ack_len, | 921 | info->status.ampdu_ack_len, |
919 | info->status.ampdu_ack_map); | 922 | info->status.ampdu_ack_map); |
@@ -929,7 +932,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
929 | tpt = curr_tbl->expected_tpt[rs_index]; | 932 | tpt = curr_tbl->expected_tpt[rs_index]; |
930 | else | 933 | else |
931 | tpt = 0; | 934 | tpt = 0; |
932 | if (info->flags & IEEE80211_TX_CTL_AMPDU) | 935 | if (info->flags & IEEE80211_TX_STAT_AMPDU) |
933 | rs_collect_tx_data(window, rs_index, tpt, | 936 | rs_collect_tx_data(window, rs_index, tpt, |
934 | info->status.ampdu_ack_len, | 937 | info->status.ampdu_ack_len, |
935 | info->status.ampdu_ack_map); | 938 | info->status.ampdu_ack_map); |
@@ -941,7 +944,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
941 | /* If not searching for new mode, increment success/failed counter | 944 | /* If not searching for new mode, increment success/failed counter |
942 | * ... these help determine when to start searching again */ | 945 | * ... these help determine when to start searching again */ |
943 | if (lq_sta->stay_in_tbl) { | 946 | if (lq_sta->stay_in_tbl) { |
944 | if (info->flags & IEEE80211_TX_CTL_AMPDU) { | 947 | if (info->flags & IEEE80211_TX_STAT_AMPDU) { |
945 | lq_sta->total_success += info->status.ampdu_ack_map; | 948 | lq_sta->total_success += info->status.ampdu_ack_map; |
946 | lq_sta->total_failed += | 949 | lq_sta->total_failed += |
947 | (info->status.ampdu_ack_len - info->status.ampdu_ack_map); | 950 | (info->status.ampdu_ack_len - info->status.ampdu_ack_map); |
@@ -1700,6 +1703,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, | |||
1700 | u16 high_low; | 1703 | u16 high_low; |
1701 | s32 sr; | 1704 | s32 sr; |
1702 | u8 tid = MAX_TID_COUNT; | 1705 | u8 tid = MAX_TID_COUNT; |
1706 | struct iwl_tid_data *tid_data; | ||
1703 | 1707 | ||
1704 | IWL_DEBUG_RATE(priv, "rate scale calculate new rate for skb\n"); | 1708 | IWL_DEBUG_RATE(priv, "rate scale calculate new rate for skb\n"); |
1705 | 1709 | ||
@@ -1896,7 +1900,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, | |||
1896 | if (high != IWL_RATE_INVALID && sr >= IWL_RATE_INCREASE_TH) | 1900 | if (high != IWL_RATE_INVALID && sr >= IWL_RATE_INCREASE_TH) |
1897 | scale_action = 1; | 1901 | scale_action = 1; |
1898 | else if (low != IWL_RATE_INVALID) | 1902 | else if (low != IWL_RATE_INVALID) |
1899 | scale_action = -1; | 1903 | scale_action = 0; |
1900 | } | 1904 | } |
1901 | 1905 | ||
1902 | /* Both adjacent throughputs are measured, but neither one has better | 1906 | /* Both adjacent throughputs are measured, but neither one has better |
@@ -1917,9 +1921,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, | |||
1917 | sr >= IWL_RATE_INCREASE_TH) { | 1921 | sr >= IWL_RATE_INCREASE_TH) { |
1918 | scale_action = 1; | 1922 | scale_action = 1; |
1919 | } else { | 1923 | } else { |
1920 | IWL_DEBUG_RATE(priv, | 1924 | scale_action = 0; |
1921 | "decrease rate because of high tpt\n"); | ||
1922 | scale_action = -1; | ||
1923 | } | 1925 | } |
1924 | 1926 | ||
1925 | /* Lower adjacent rate's throughput is measured */ | 1927 | /* Lower adjacent rate's throughput is measured */ |
@@ -2035,8 +2037,15 @@ lq_update: | |||
2035 | if ((lq_sta->last_tpt > IWL_AGG_TPT_THREHOLD) && | 2037 | if ((lq_sta->last_tpt > IWL_AGG_TPT_THREHOLD) && |
2036 | (lq_sta->tx_agg_tid_en & (1 << tid)) && | 2038 | (lq_sta->tx_agg_tid_en & (1 << tid)) && |
2037 | (tid != MAX_TID_COUNT)) { | 2039 | (tid != MAX_TID_COUNT)) { |
2038 | IWL_DEBUG_RATE(priv, "try to aggregate tid %d\n", tid); | 2040 | tid_data = |
2039 | rs_tl_turn_on_agg(priv, tid, lq_sta, sta); | 2041 | &priv->stations[lq_sta->lq.sta_id].tid[tid]; |
2042 | if (tid_data->agg.state == IWL_AGG_OFF) { | ||
2043 | IWL_DEBUG_RATE(priv, | ||
2044 | "try to aggregate tid %d\n", | ||
2045 | tid); | ||
2046 | rs_tl_turn_on_agg(priv, tid, | ||
2047 | lq_sta, sta); | ||
2048 | } | ||
2040 | } | 2049 | } |
2041 | lq_sta->action_counter = 0; | 2050 | lq_sta->action_counter = 0; |
2042 | rs_set_stay_in_table(priv, 0, lq_sta); | 2051 | rs_set_stay_in_table(priv, 0, lq_sta); |
@@ -2464,18 +2473,25 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, | |||
2464 | u32 *rate_n_flags, int index) | 2473 | u32 *rate_n_flags, int index) |
2465 | { | 2474 | { |
2466 | struct iwl_priv *priv; | 2475 | struct iwl_priv *priv; |
2476 | u8 valid_tx_ant; | ||
2477 | u8 ant_sel_tx; | ||
2467 | 2478 | ||
2468 | priv = lq_sta->drv; | 2479 | priv = lq_sta->drv; |
2480 | valid_tx_ant = priv->hw_params.valid_tx_ant; | ||
2469 | if (lq_sta->dbg_fixed_rate) { | 2481 | if (lq_sta->dbg_fixed_rate) { |
2470 | if (index < 12) { | 2482 | ant_sel_tx = |
2483 | ((lq_sta->dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK) | ||
2484 | >> RATE_MCS_ANT_POS); | ||
2485 | if ((valid_tx_ant & ant_sel_tx) == ant_sel_tx) { | ||
2471 | *rate_n_flags = lq_sta->dbg_fixed_rate; | 2486 | *rate_n_flags = lq_sta->dbg_fixed_rate; |
2487 | IWL_DEBUG_RATE(priv, "Fixed rate ON\n"); | ||
2472 | } else { | 2488 | } else { |
2473 | if (lq_sta->band == IEEE80211_BAND_5GHZ) | 2489 | lq_sta->dbg_fixed_rate = 0; |
2474 | *rate_n_flags = 0x800D; | 2490 | IWL_ERR(priv, |
2475 | else | 2491 | "Invalid antenna selection 0x%X, Valid is 0x%X\n", |
2476 | *rate_n_flags = 0x820A; | 2492 | ant_sel_tx, valid_tx_ant); |
2493 | IWL_DEBUG_RATE(priv, "Fixed rate OFF\n"); | ||
2477 | } | 2494 | } |
2478 | IWL_DEBUG_RATE(priv, "Fixed rate ON\n"); | ||
2479 | } else { | 2495 | } else { |
2480 | IWL_DEBUG_RATE(priv, "Fixed rate OFF\n"); | 2496 | IWL_DEBUG_RATE(priv, "Fixed rate OFF\n"); |
2481 | } | 2497 | } |
@@ -2526,7 +2542,10 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, | |||
2526 | ssize_t ret; | 2542 | ssize_t ret; |
2527 | 2543 | ||
2528 | struct iwl_lq_sta *lq_sta = file->private_data; | 2544 | struct iwl_lq_sta *lq_sta = file->private_data; |
2545 | struct iwl_priv *priv; | ||
2546 | struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); | ||
2529 | 2547 | ||
2548 | priv = lq_sta->drv; | ||
2530 | buff = kmalloc(1024, GFP_KERNEL); | 2549 | buff = kmalloc(1024, GFP_KERNEL); |
2531 | if (!buff) | 2550 | if (!buff) |
2532 | return -ENOMEM; | 2551 | return -ENOMEM; |
@@ -2537,6 +2556,20 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, | |||
2537 | lq_sta->active_legacy_rate); | 2556 | lq_sta->active_legacy_rate); |
2538 | desc += sprintf(buff+desc, "fixed rate 0x%X\n", | 2557 | desc += sprintf(buff+desc, "fixed rate 0x%X\n", |
2539 | lq_sta->dbg_fixed_rate); | 2558 | lq_sta->dbg_fixed_rate); |
2559 | desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n", | ||
2560 | (priv->hw_params.valid_tx_ant & ANT_A) ? "ANT_A," : "", | ||
2561 | (priv->hw_params.valid_tx_ant & ANT_B) ? "ANT_B," : "", | ||
2562 | (priv->hw_params.valid_tx_ant & ANT_C) ? "ANT_C" : ""); | ||
2563 | desc += sprintf(buff+desc, "lq type %s\n", | ||
2564 | (is_legacy(tbl->lq_type)) ? "legacy" : "HT"); | ||
2565 | if (is_Ht(tbl->lq_type)) { | ||
2566 | desc += sprintf(buff+desc, " %s", | ||
2567 | (is_siso(tbl->lq_type)) ? "SISO" : | ||
2568 | ((is_mimo2(tbl->lq_type)) ? "MIMO2" : "MIMO3")); | ||
2569 | desc += sprintf(buff+desc, " %s", | ||
2570 | (tbl->is_fat) ? "40MHz" : "20MHz"); | ||
2571 | desc += sprintf(buff+desc, " %s\n", (tbl->is_SGI) ? "SGI" : ""); | ||
2572 | } | ||
2540 | desc += sprintf(buff+desc, "general:" | 2573 | desc += sprintf(buff+desc, "general:" |
2541 | "flags=0x%X mimo-d=%d s-ant0x%x d-ant=0x%x\n", | 2574 | "flags=0x%X mimo-d=%d s-ant0x%x d-ant=0x%x\n", |
2542 | lq_sta->lq.general_params.flags, | 2575 | lq_sta->lq.general_params.flags, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h index 345806dd8870..ab59acc405d9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h | |||
@@ -231,7 +231,7 @@ enum { | |||
231 | #define IWL_RS_GOOD_RATIO 12800 /* 100% */ | 231 | #define IWL_RS_GOOD_RATIO 12800 /* 100% */ |
232 | #define IWL_RATE_SCALE_SWITCH 10880 /* 85% */ | 232 | #define IWL_RATE_SCALE_SWITCH 10880 /* 85% */ |
233 | #define IWL_RATE_HIGH_TH 10880 /* 85% */ | 233 | #define IWL_RATE_HIGH_TH 10880 /* 85% */ |
234 | #define IWL_RATE_INCREASE_TH 8960 /* 70% */ | 234 | #define IWL_RATE_INCREASE_TH 6400 /* 50% */ |
235 | #define IWL_RATE_DECREASE_TH 1920 /* 15% */ | 235 | #define IWL_RATE_DECREASE_TH 1920 /* 15% */ |
236 | 236 | ||
237 | /* possible actions when in legacy mode */ | 237 | /* possible actions when in legacy mode */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 7902d22da663..0db3bc011ac2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -3359,7 +3359,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
3359 | /* amp init */ | 3359 | /* amp init */ |
3360 | err = priv->cfg->ops->lib->apm_ops.init(priv); | 3360 | err = priv->cfg->ops->lib->apm_ops.init(priv); |
3361 | if (err < 0) { | 3361 | if (err < 0) { |
3362 | IWL_DEBUG_INFO(priv, "Failed to init APMG\n"); | 3362 | IWL_ERR(priv, "Failed to init APMG\n"); |
3363 | goto out_iounmap; | 3363 | goto out_iounmap; |
3364 | } | 3364 | } |
3365 | /***************** | 3365 | /***************** |
@@ -3643,9 +3643,9 @@ static struct pci_device_id iwl_hw_card_ids[] = { | |||
3643 | {IWL_PCI_DEVICE(0x0087, PCI_ANY_ID, iwl6050_2agn_cfg)}, | 3643 | {IWL_PCI_DEVICE(0x0087, PCI_ANY_ID, iwl6050_2agn_cfg)}, |
3644 | {IWL_PCI_DEVICE(0x0088, PCI_ANY_ID, iwl6050_3agn_cfg)}, | 3644 | {IWL_PCI_DEVICE(0x0088, PCI_ANY_ID, iwl6050_3agn_cfg)}, |
3645 | {IWL_PCI_DEVICE(0x0089, PCI_ANY_ID, iwl6050_2agn_cfg)}, | 3645 | {IWL_PCI_DEVICE(0x0089, PCI_ANY_ID, iwl6050_2agn_cfg)}, |
3646 | /* 100 Series WiFi */ | 3646 | /* 1000 Series WiFi */ |
3647 | {IWL_PCI_DEVICE(0x0083, PCI_ANY_ID, iwl100_bgn_cfg)}, | 3647 | {IWL_PCI_DEVICE(0x0083, PCI_ANY_ID, iwl1000_bgn_cfg)}, |
3648 | {IWL_PCI_DEVICE(0x0084, PCI_ANY_ID, iwl100_bgn_cfg)}, | 3648 | {IWL_PCI_DEVICE(0x0084, PCI_ANY_ID, iwl1000_bgn_cfg)}, |
3649 | #endif /* CONFIG_IWL5000 */ | 3649 | #endif /* CONFIG_IWL5000 */ |
3650 | 3650 | ||
3651 | {0} | 3651 | {0} |
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index 5028c781275b..2f1242447b3b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h | |||
@@ -211,7 +211,7 @@ | |||
211 | #define CSR_HW_REV_TYPE_5350 (0x0000030) | 211 | #define CSR_HW_REV_TYPE_5350 (0x0000030) |
212 | #define CSR_HW_REV_TYPE_5100 (0x0000050) | 212 | #define CSR_HW_REV_TYPE_5100 (0x0000050) |
213 | #define CSR_HW_REV_TYPE_5150 (0x0000040) | 213 | #define CSR_HW_REV_TYPE_5150 (0x0000040) |
214 | #define CSR_HW_REV_TYPE_100 (0x0000060) | 214 | #define CSR_HW_REV_TYPE_1000 (0x0000060) |
215 | #define CSR_HW_REV_TYPE_6x00 (0x0000070) | 215 | #define CSR_HW_REV_TYPE_6x00 (0x0000070) |
216 | #define CSR_HW_REV_TYPE_6x50 (0x0000080) | 216 | #define CSR_HW_REV_TYPE_6x50 (0x0000080) |
217 | #define CSR_HW_REV_TYPE_NONE (0x00000F0) | 217 | #define CSR_HW_REV_TYPE_NONE (0x00000F0) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index b3e23abb9117..0baae8022824 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -62,7 +62,7 @@ extern struct iwl_cfg iwl6000_2agn_cfg; | |||
62 | extern struct iwl_cfg iwl6000_3agn_cfg; | 62 | extern struct iwl_cfg iwl6000_3agn_cfg; |
63 | extern struct iwl_cfg iwl6050_2agn_cfg; | 63 | extern struct iwl_cfg iwl6050_2agn_cfg; |
64 | extern struct iwl_cfg iwl6050_3agn_cfg; | 64 | extern struct iwl_cfg iwl6050_3agn_cfg; |
65 | extern struct iwl_cfg iwl100_bgn_cfg; | 65 | extern struct iwl_cfg iwl1000_bgn_cfg; |
66 | 66 | ||
67 | /* shared structures from iwl-5000.c */ | 67 | /* shared structures from iwl-5000.c */ |
68 | extern struct iwl_mod_params iwl50_mod_params; | 68 | extern struct iwl_mod_params iwl50_mod_params; |
@@ -926,19 +926,12 @@ struct iwl_priv { | |||
926 | struct rfkill *rfkill; | 926 | struct rfkill *rfkill; |
927 | #endif | 927 | #endif |
928 | 928 | ||
929 | #if defined(CONFIG_IWLWIFI_LEDS) || defined(CONFIG_IWL3945_LEDS) | 929 | #ifdef CONFIG_IWLWIFI_LEDS |
930 | unsigned long last_blink_time; | 930 | unsigned long last_blink_time; |
931 | u8 last_blink_rate; | 931 | u8 last_blink_rate; |
932 | u8 allow_blinking; | 932 | u8 allow_blinking; |
933 | u64 led_tpt; | 933 | u64 led_tpt; |
934 | #endif | ||
935 | |||
936 | #ifdef CONFIG_IWLWIFI_LEDS | ||
937 | struct iwl_led led[IWL_LED_TRG_MAX]; | 934 | struct iwl_led led[IWL_LED_TRG_MAX]; |
938 | #endif | ||
939 | |||
940 | #ifdef CONFIG_IWL3945_LEDS | ||
941 | struct iwl3945_led led39[IWL_LED_TRG_MAX]; | ||
942 | unsigned int rxtxpackets; | 935 | unsigned int rxtxpackets; |
943 | #endif | 936 | #endif |
944 | u16 active_rate; | 937 | u16 active_rate; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index c7b8e5bb4e42..083ea1ffbe87 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h | |||
@@ -156,6 +156,7 @@ static inline void __iwl_clear_bit(const char *f, u32 l, | |||
156 | static inline int _iwl_grab_nic_access(struct iwl_priv *priv) | 156 | static inline int _iwl_grab_nic_access(struct iwl_priv *priv) |
157 | { | 157 | { |
158 | int ret; | 158 | int ret; |
159 | u32 val; | ||
159 | #ifdef CONFIG_IWLWIFI_DEBUG | 160 | #ifdef CONFIG_IWLWIFI_DEBUG |
160 | if (atomic_read(&priv->restrict_refcnt)) | 161 | if (atomic_read(&priv->restrict_refcnt)) |
161 | return 0; | 162 | return 0; |
@@ -167,7 +168,8 @@ static inline int _iwl_grab_nic_access(struct iwl_priv *priv) | |||
167 | (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | | 168 | (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | |
168 | CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000); | 169 | CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000); |
169 | if (ret < 0) { | 170 | if (ret < 0) { |
170 | IWL_ERR(priv, "MAC is in deep sleep!\n"); | 171 | val = _iwl_read32(priv, CSR_GP_CNTRL); |
172 | IWL_ERR(priv, "MAC is in deep sleep!. CSR_GP_CNTRL = 0x%08X\n", val); | ||
171 | return -EIO; | 173 | return -EIO; |
172 | } | 174 | } |
173 | 175 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.h b/drivers/net/wireless/iwlwifi/iwl-led.h index 140fd8fa4855..ef9b174c37ff 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-led.h | |||
@@ -30,7 +30,7 @@ | |||
30 | 30 | ||
31 | struct iwl_priv; | 31 | struct iwl_priv; |
32 | 32 | ||
33 | #if defined(CONFIG_IWLWIFI_LEDS) || defined(CONFIG_IWL3945_LEDS) | 33 | #ifdef CONFIG_IWLWIFI_LEDS |
34 | #include <linux/leds.h> | 34 | #include <linux/leds.h> |
35 | 35 | ||
36 | #define IWL_LED_SOLID 11 | 36 | #define IWL_LED_SOLID 11 |
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 0ea08d080928..1684490d93c0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c | |||
@@ -472,6 +472,7 @@ EXPORT_SYMBOL(iwl_remove_station); | |||
472 | void iwl_clear_stations_table(struct iwl_priv *priv) | 472 | void iwl_clear_stations_table(struct iwl_priv *priv) |
473 | { | 473 | { |
474 | unsigned long flags; | 474 | unsigned long flags; |
475 | int i; | ||
475 | 476 | ||
476 | spin_lock_irqsave(&priv->sta_lock, flags); | 477 | spin_lock_irqsave(&priv->sta_lock, flags); |
477 | 478 | ||
@@ -486,6 +487,12 @@ void iwl_clear_stations_table(struct iwl_priv *priv) | |||
486 | /* clean ucode key table bit map */ | 487 | /* clean ucode key table bit map */ |
487 | priv->ucode_key_table = 0; | 488 | priv->ucode_key_table = 0; |
488 | 489 | ||
490 | /* keep track of static keys */ | ||
491 | for (i = 0; i < WEP_KEYS_MAX ; i++) { | ||
492 | if (priv->wep_keys[i].key_size) | ||
493 | test_and_set_bit(i, &priv->ucode_key_table); | ||
494 | } | ||
495 | |||
489 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 496 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
490 | } | 497 | } |
491 | EXPORT_SYMBOL(iwl_clear_stations_table); | 498 | EXPORT_SYMBOL(iwl_clear_stations_table); |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index d37679c69a5c..4465320f2735 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -328,6 +328,8 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) | |||
328 | struct iwl3945_rxon_cmd *active_rxon = (void *)&priv->active_rxon; | 328 | struct iwl3945_rxon_cmd *active_rxon = (void *)&priv->active_rxon; |
329 | struct iwl3945_rxon_cmd *staging_rxon = (void *)&priv->staging_rxon; | 329 | struct iwl3945_rxon_cmd *staging_rxon = (void *)&priv->staging_rxon; |
330 | int rc = 0; | 330 | int rc = 0; |
331 | bool new_assoc = | ||
332 | !!(priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK); | ||
331 | 333 | ||
332 | if (!iwl_is_alive(priv)) | 334 | if (!iwl_is_alive(priv)) |
333 | return -1; | 335 | return -1; |
@@ -366,8 +368,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) | |||
366 | * an RXON_ASSOC and the new config wants the associated mask enabled, | 368 | * an RXON_ASSOC and the new config wants the associated mask enabled, |
367 | * we must clear the associated from the active configuration | 369 | * we must clear the associated from the active configuration |
368 | * before we apply the new config */ | 370 | * before we apply the new config */ |
369 | if (iwl_is_associated(priv) && | 371 | if (iwl_is_associated(priv) && new_assoc) { |
370 | (staging_rxon->filter_flags & RXON_FILTER_ASSOC_MSK)) { | ||
371 | IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n"); | 372 | IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n"); |
372 | active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 373 | active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
373 | 374 | ||
@@ -395,8 +396,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) | |||
395 | "* with%s RXON_FILTER_ASSOC_MSK\n" | 396 | "* with%s RXON_FILTER_ASSOC_MSK\n" |
396 | "* channel = %d\n" | 397 | "* channel = %d\n" |
397 | "* bssid = %pM\n", | 398 | "* bssid = %pM\n", |
398 | ((priv->staging_rxon.filter_flags & | 399 | (new_assoc ? "" : "out"), |
399 | RXON_FILTER_ASSOC_MSK) ? "" : "out"), | ||
400 | le16_to_cpu(staging_rxon->channel), | 400 | le16_to_cpu(staging_rxon->channel), |
401 | staging_rxon->bssid_addr); | 401 | staging_rxon->bssid_addr); |
402 | 402 | ||
@@ -542,7 +542,7 @@ static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id) | |||
542 | return 0; | 542 | return 0; |
543 | } | 543 | } |
544 | 544 | ||
545 | int iwl3945_set_dynamic_key(struct iwl_priv *priv, | 545 | static int iwl3945_set_dynamic_key(struct iwl_priv *priv, |
546 | struct ieee80211_key_conf *keyconf, u8 sta_id) | 546 | struct ieee80211_key_conf *keyconf, u8 sta_id) |
547 | { | 547 | { |
548 | int ret = 0; | 548 | int ret = 0; |
@@ -890,7 +890,7 @@ static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv, | |||
890 | tx->timeout.pm_frame_timeout = cpu_to_le16(2); | 890 | tx->timeout.pm_frame_timeout = cpu_to_le16(2); |
891 | } else { | 891 | } else { |
892 | tx->timeout.pm_frame_timeout = 0; | 892 | tx->timeout.pm_frame_timeout = 0; |
893 | #ifdef CONFIG_IWL3945_LEDS | 893 | #ifdef CONFIG_IWLWIFI_LEDS |
894 | priv->rxtxpackets += le16_to_cpu(cmd->cmd.tx.len); | 894 | priv->rxtxpackets += le16_to_cpu(cmd->cmd.tx.len); |
895 | #endif | 895 | #endif |
896 | } | 896 | } |
@@ -1479,85 +1479,6 @@ static void iwl3945_setup_rx_handlers(struct iwl_priv *priv) | |||
1479 | iwl3945_hw_rx_handler_setup(priv); | 1479 | iwl3945_hw_rx_handler_setup(priv); |
1480 | } | 1480 | } |
1481 | 1481 | ||
1482 | /** | ||
1483 | * iwl3945_cmd_queue_reclaim - Reclaim CMD queue entries | ||
1484 | * When FW advances 'R' index, all entries between old and new 'R' index | ||
1485 | * need to be reclaimed. | ||
1486 | */ | ||
1487 | static void iwl3945_cmd_queue_reclaim(struct iwl_priv *priv, | ||
1488 | int txq_id, int index) | ||
1489 | { | ||
1490 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; | ||
1491 | struct iwl_queue *q = &txq->q; | ||
1492 | int nfreed = 0; | ||
1493 | |||
1494 | if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) { | ||
1495 | IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, " | ||
1496 | "is out of range [0-%d] %d %d.\n", txq_id, | ||
1497 | index, q->n_bd, q->write_ptr, q->read_ptr); | ||
1498 | return; | ||
1499 | } | ||
1500 | |||
1501 | for (index = iwl_queue_inc_wrap(index, q->n_bd); q->read_ptr != index; | ||
1502 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { | ||
1503 | if (nfreed > 1) { | ||
1504 | IWL_ERR(priv, "HCMD skipped: index (%d) %d %d\n", index, | ||
1505 | q->write_ptr, q->read_ptr); | ||
1506 | queue_work(priv->workqueue, &priv->restart); | ||
1507 | break; | ||
1508 | } | ||
1509 | nfreed++; | ||
1510 | } | ||
1511 | } | ||
1512 | |||
1513 | |||
1514 | /** | ||
1515 | * iwl3945_tx_cmd_complete - Pull unused buffers off the queue and reclaim them | ||
1516 | * @rxb: Rx buffer to reclaim | ||
1517 | * | ||
1518 | * If an Rx buffer has an async callback associated with it the callback | ||
1519 | * will be executed. The attached skb (if present) will only be freed | ||
1520 | * if the callback returns 1 | ||
1521 | */ | ||
1522 | static void iwl3945_tx_cmd_complete(struct iwl_priv *priv, | ||
1523 | struct iwl_rx_mem_buffer *rxb) | ||
1524 | { | ||
1525 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | ||
1526 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); | ||
1527 | int txq_id = SEQ_TO_QUEUE(sequence); | ||
1528 | int index = SEQ_TO_INDEX(sequence); | ||
1529 | int huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME); | ||
1530 | int cmd_index; | ||
1531 | struct iwl_cmd *cmd; | ||
1532 | |||
1533 | if (WARN(txq_id != IWL_CMD_QUEUE_NUM, | ||
1534 | "wrong command queue %d, sequence 0x%X readp=%d writep=%d\n", | ||
1535 | txq_id, sequence, | ||
1536 | priv->txq[IWL_CMD_QUEUE_NUM].q.read_ptr, | ||
1537 | priv->txq[IWL_CMD_QUEUE_NUM].q.write_ptr)) { | ||
1538 | iwl_print_hex_dump(priv, IWL_DL_INFO , rxb, 32); | ||
1539 | return; | ||
1540 | } | ||
1541 | |||
1542 | cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge); | ||
1543 | cmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index]; | ||
1544 | |||
1545 | /* Input error checking is done when commands are added to queue. */ | ||
1546 | if (cmd->meta.flags & CMD_WANT_SKB) { | ||
1547 | cmd->meta.source->u.skb = rxb->skb; | ||
1548 | rxb->skb = NULL; | ||
1549 | } else if (cmd->meta.u.callback && | ||
1550 | !cmd->meta.u.callback(priv, cmd, rxb->skb)) | ||
1551 | rxb->skb = NULL; | ||
1552 | |||
1553 | iwl3945_cmd_queue_reclaim(priv, txq_id, index); | ||
1554 | |||
1555 | if (!(cmd->meta.flags & CMD_ASYNC)) { | ||
1556 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); | ||
1557 | wake_up_interruptible(&priv->wait_command_queue); | ||
1558 | } | ||
1559 | } | ||
1560 | |||
1561 | /************************** RX-FUNCTIONS ****************************/ | 1482 | /************************** RX-FUNCTIONS ****************************/ |
1562 | /* | 1483 | /* |
1563 | * Rx theory of operation | 1484 | * Rx theory of operation |
@@ -1917,7 +1838,7 @@ static void iwl3945_rx_handle(struct iwl_priv *priv) | |||
1917 | * fire off the (possibly) blocking iwl_send_cmd() | 1838 | * fire off the (possibly) blocking iwl_send_cmd() |
1918 | * as we reclaim the driver command queue */ | 1839 | * as we reclaim the driver command queue */ |
1919 | if (rxb && rxb->skb) | 1840 | if (rxb && rxb->skb) |
1920 | iwl3945_tx_cmd_complete(priv, rxb); | 1841 | iwl_tx_cmd_complete(priv, rxb); |
1921 | else | 1842 | else |
1922 | IWL_WARN(priv, "Claim null rxb?\n"); | 1843 | IWL_WARN(priv, "Claim null rxb?\n"); |
1923 | } | 1844 | } |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index fce49ba061d5..a15078bcad73 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -10,7 +10,6 @@ | |||
10 | /* | 10 | /* |
11 | * TODO: | 11 | * TODO: |
12 | * - IBSS mode simulation (Beacon transmission with competition for "air time") | 12 | * - IBSS mode simulation (Beacon transmission with competition for "air time") |
13 | * - IEEE 802.11a and 802.11n modes | ||
14 | * - RX filtering based on filter configuration (data->rx_filter) | 13 | * - RX filtering based on filter configuration (data->rx_filter) |
15 | */ | 14 | */ |
16 | 15 | ||
@@ -31,6 +30,112 @@ static int radios = 2; | |||
31 | module_param(radios, int, 0444); | 30 | module_param(radios, int, 0444); |
32 | MODULE_PARM_DESC(radios, "Number of simulated radios"); | 31 | MODULE_PARM_DESC(radios, "Number of simulated radios"); |
33 | 32 | ||
33 | /** | ||
34 | * enum hwsim_regtest - the type of regulatory tests we offer | ||
35 | * | ||
36 | * These are the different values you can use for the regtest | ||
37 | * module parameter. This is useful to help test world roaming | ||
38 | * and the driver regulatory_hint() call and combinations of these. | ||
39 | * If you want to do specific alpha2 regulatory domain tests simply | ||
40 | * use the userspace regulatory request as that will be respected as | ||
41 | * well without the need of this module parameter. This is designed | ||
42 | * only for testing the driver regulatory request, world roaming | ||
43 | * and all possible combinations. | ||
44 | * | ||
45 | * @HWSIM_REGTEST_DISABLED: No regulatory tests are performed, | ||
46 | * this is the default value. | ||
47 | * @HWSIM_REGTEST_DRIVER_REG_FOLLOW: Used for testing the driver regulatory | ||
48 | * hint, only one driver regulatory hint will be sent as such the | ||
49 | * secondary radios are expected to follow. | ||
50 | * @HWSIM_REGTEST_DRIVER_REG_ALL: Used for testing the driver regulatory | ||
51 | * request with all radios reporting the same regulatory domain. | ||
52 | * @HWSIM_REGTEST_DIFF_COUNTRY: Used for testing the drivers calling | ||
53 | * different regulatory domains requests. Expected behaviour is for | ||
54 | * an intersection to occur but each device will still use their | ||
55 | * respective regulatory requested domains. Subsequent radios will | ||
56 | * use the resulting intersection. | ||
57 | * @HWSIM_REGTEST_WORLD_ROAM: Used for testing the world roaming. We acomplish | ||
58 | * this by using a custom beacon-capable regulatory domain for the first | ||
59 | * radio. All other device world roam. | ||
60 | * @HWSIM_REGTEST_CUSTOM_WORLD: Used for testing the custom world regulatory | ||
61 | * domain requests. All radios will adhere to this custom world regulatory | ||
62 | * domain. | ||
63 | * @HWSIM_REGTEST_CUSTOM_WORLD_2: Used for testing 2 custom world regulatory | ||
64 | * domain requests. The first radio will adhere to the first custom world | ||
65 | * regulatory domain, the second one to the second custom world regulatory | ||
66 | * domain. All other devices will world roam. | ||
67 | * @HWSIM_REGTEST_STRICT_FOLLOW_: Used for testing strict regulatory domain | ||
68 | * settings, only the first radio will send a regulatory domain request | ||
69 | * and use strict settings. The rest of the radios are expected to follow. | ||
70 | * @HWSIM_REGTEST_STRICT_ALL: Used for testing strict regulatory domain | ||
71 | * settings. All radios will adhere to this. | ||
72 | * @HWSIM_REGTEST_STRICT_AND_DRIVER_REG: Used for testing strict regulatory | ||
73 | * domain settings, combined with secondary driver regulatory domain | ||
74 | * settings. The first radio will get a strict regulatory domain setting | ||
75 | * using the first driver regulatory request and the second radio will use | ||
76 | * non-strict settings using the second driver regulatory request. All | ||
77 | * other devices should follow the intersection created between the | ||
78 | * first two. | ||
79 | * @HWSIM_REGTEST_ALL: Used for testing every possible mix. You will need | ||
80 | * at least 6 radios for a complete test. We will test in this order: | ||
81 | * 1 - driver custom world regulatory domain | ||
82 | * 2 - second custom world regulatory domain | ||
83 | * 3 - first driver regulatory domain request | ||
84 | * 4 - second driver regulatory domain request | ||
85 | * 5 - strict regulatory domain settings using the third driver regulatory | ||
86 | * domain request | ||
87 | * 6 and on - should follow the intersection of the 3rd, 4rth and 5th radio | ||
88 | * regulatory requests. | ||
89 | */ | ||
90 | enum hwsim_regtest { | ||
91 | HWSIM_REGTEST_DISABLED = 0, | ||
92 | HWSIM_REGTEST_DRIVER_REG_FOLLOW = 1, | ||
93 | HWSIM_REGTEST_DRIVER_REG_ALL = 2, | ||
94 | HWSIM_REGTEST_DIFF_COUNTRY = 3, | ||
95 | HWSIM_REGTEST_WORLD_ROAM = 4, | ||
96 | HWSIM_REGTEST_CUSTOM_WORLD = 5, | ||
97 | HWSIM_REGTEST_CUSTOM_WORLD_2 = 6, | ||
98 | HWSIM_REGTEST_STRICT_FOLLOW = 7, | ||
99 | HWSIM_REGTEST_STRICT_ALL = 8, | ||
100 | HWSIM_REGTEST_STRICT_AND_DRIVER_REG = 9, | ||
101 | HWSIM_REGTEST_ALL = 10, | ||
102 | }; | ||
103 | |||
104 | /* Set to one of the HWSIM_REGTEST_* values above */ | ||
105 | static int regtest = HWSIM_REGTEST_DISABLED; | ||
106 | module_param(regtest, int, 0444); | ||
107 | MODULE_PARM_DESC(regtest, "The type of regulatory test we want to run"); | ||
108 | |||
109 | static const char *hwsim_alpha2s[] = { | ||
110 | "FI", | ||
111 | "AL", | ||
112 | "US", | ||
113 | "DE", | ||
114 | "JP", | ||
115 | "AL", | ||
116 | }; | ||
117 | |||
118 | static const struct ieee80211_regdomain hwsim_world_regdom_custom_01 = { | ||
119 | .n_reg_rules = 4, | ||
120 | .alpha2 = "99", | ||
121 | .reg_rules = { | ||
122 | REG_RULE(2412-10, 2462+10, 40, 0, 20, 0), | ||
123 | REG_RULE(2484-10, 2484+10, 40, 0, 20, 0), | ||
124 | REG_RULE(5150-10, 5240+10, 40, 0, 30, 0), | ||
125 | REG_RULE(5745-10, 5825+10, 40, 0, 30, 0), | ||
126 | } | ||
127 | }; | ||
128 | |||
129 | static const struct ieee80211_regdomain hwsim_world_regdom_custom_02 = { | ||
130 | .n_reg_rules = 2, | ||
131 | .alpha2 = "99", | ||
132 | .reg_rules = { | ||
133 | REG_RULE(2412-10, 2462+10, 40, 0, 20, 0), | ||
134 | REG_RULE(5725-10, 5850+10, 40, 0, 30, | ||
135 | NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS), | ||
136 | } | ||
137 | }; | ||
138 | |||
34 | struct hwsim_vif_priv { | 139 | struct hwsim_vif_priv { |
35 | u32 magic; | 140 | u32 magic; |
36 | u8 bssid[ETH_ALEN]; | 141 | u8 bssid[ETH_ALEN]; |
@@ -86,22 +191,65 @@ static struct class *hwsim_class; | |||
86 | 191 | ||
87 | static struct net_device *hwsim_mon; /* global monitor netdev */ | 192 | static struct net_device *hwsim_mon; /* global monitor netdev */ |
88 | 193 | ||
194 | #define CHAN2G(_freq) { \ | ||
195 | .band = IEEE80211_BAND_2GHZ, \ | ||
196 | .center_freq = (_freq), \ | ||
197 | .hw_value = (_freq), \ | ||
198 | .max_power = 20, \ | ||
199 | } | ||
200 | |||
201 | #define CHAN5G(_freq) { \ | ||
202 | .band = IEEE80211_BAND_5GHZ, \ | ||
203 | .center_freq = (_freq), \ | ||
204 | .hw_value = (_freq), \ | ||
205 | .max_power = 20, \ | ||
206 | } | ||
207 | |||
208 | static const struct ieee80211_channel hwsim_channels_2ghz[] = { | ||
209 | CHAN2G(2412), /* Channel 1 */ | ||
210 | CHAN2G(2417), /* Channel 2 */ | ||
211 | CHAN2G(2422), /* Channel 3 */ | ||
212 | CHAN2G(2427), /* Channel 4 */ | ||
213 | CHAN2G(2432), /* Channel 5 */ | ||
214 | CHAN2G(2437), /* Channel 6 */ | ||
215 | CHAN2G(2442), /* Channel 7 */ | ||
216 | CHAN2G(2447), /* Channel 8 */ | ||
217 | CHAN2G(2452), /* Channel 9 */ | ||
218 | CHAN2G(2457), /* Channel 10 */ | ||
219 | CHAN2G(2462), /* Channel 11 */ | ||
220 | CHAN2G(2467), /* Channel 12 */ | ||
221 | CHAN2G(2472), /* Channel 13 */ | ||
222 | CHAN2G(2484), /* Channel 14 */ | ||
223 | }; | ||
89 | 224 | ||
90 | static const struct ieee80211_channel hwsim_channels[] = { | 225 | static const struct ieee80211_channel hwsim_channels_5ghz[] = { |
91 | { .center_freq = 2412 }, | 226 | CHAN5G(5180), /* Channel 36 */ |
92 | { .center_freq = 2417 }, | 227 | CHAN5G(5200), /* Channel 40 */ |
93 | { .center_freq = 2422 }, | 228 | CHAN5G(5220), /* Channel 44 */ |
94 | { .center_freq = 2427 }, | 229 | CHAN5G(5240), /* Channel 48 */ |
95 | { .center_freq = 2432 }, | 230 | |
96 | { .center_freq = 2437 }, | 231 | CHAN5G(5260), /* Channel 52 */ |
97 | { .center_freq = 2442 }, | 232 | CHAN5G(5280), /* Channel 56 */ |
98 | { .center_freq = 2447 }, | 233 | CHAN5G(5300), /* Channel 60 */ |
99 | { .center_freq = 2452 }, | 234 | CHAN5G(5320), /* Channel 64 */ |
100 | { .center_freq = 2457 }, | 235 | |
101 | { .center_freq = 2462 }, | 236 | CHAN5G(5500), /* Channel 100 */ |
102 | { .center_freq = 2467 }, | 237 | CHAN5G(5520), /* Channel 104 */ |
103 | { .center_freq = 2472 }, | 238 | CHAN5G(5540), /* Channel 108 */ |
104 | { .center_freq = 2484 }, | 239 | CHAN5G(5560), /* Channel 112 */ |
240 | CHAN5G(5580), /* Channel 116 */ | ||
241 | CHAN5G(5600), /* Channel 120 */ | ||
242 | CHAN5G(5620), /* Channel 124 */ | ||
243 | CHAN5G(5640), /* Channel 128 */ | ||
244 | CHAN5G(5660), /* Channel 132 */ | ||
245 | CHAN5G(5680), /* Channel 136 */ | ||
246 | CHAN5G(5700), /* Channel 140 */ | ||
247 | |||
248 | CHAN5G(5745), /* Channel 149 */ | ||
249 | CHAN5G(5765), /* Channel 153 */ | ||
250 | CHAN5G(5785), /* Channel 157 */ | ||
251 | CHAN5G(5805), /* Channel 161 */ | ||
252 | CHAN5G(5825), /* Channel 165 */ | ||
105 | }; | 253 | }; |
106 | 254 | ||
107 | static const struct ieee80211_rate hwsim_rates[] = { | 255 | static const struct ieee80211_rate hwsim_rates[] = { |
@@ -126,8 +274,9 @@ struct mac80211_hwsim_data { | |||
126 | struct list_head list; | 274 | struct list_head list; |
127 | struct ieee80211_hw *hw; | 275 | struct ieee80211_hw *hw; |
128 | struct device *dev; | 276 | struct device *dev; |
129 | struct ieee80211_supported_band band; | 277 | struct ieee80211_supported_band bands[2]; |
130 | struct ieee80211_channel channels[ARRAY_SIZE(hwsim_channels)]; | 278 | struct ieee80211_channel channels_2ghz[ARRAY_SIZE(hwsim_channels_2ghz)]; |
279 | struct ieee80211_channel channels_5ghz[ARRAY_SIZE(hwsim_channels_5ghz)]; | ||
131 | struct ieee80211_rate rates[ARRAY_SIZE(hwsim_rates)]; | 280 | struct ieee80211_rate rates[ARRAY_SIZE(hwsim_rates)]; |
132 | 281 | ||
133 | struct ieee80211_channel *channel; | 282 | struct ieee80211_channel *channel; |
@@ -728,6 +877,7 @@ static int __init init_mac80211_hwsim(void) | |||
728 | u8 addr[ETH_ALEN]; | 877 | u8 addr[ETH_ALEN]; |
729 | struct mac80211_hwsim_data *data; | 878 | struct mac80211_hwsim_data *data; |
730 | struct ieee80211_hw *hw; | 879 | struct ieee80211_hw *hw; |
880 | enum ieee80211_band band; | ||
731 | 881 | ||
732 | if (radios < 1 || radios > 100) | 882 | if (radios < 1 || radios > 100) |
733 | return -EINVAL; | 883 | return -EINVAL; |
@@ -785,25 +935,105 @@ static int __init init_mac80211_hwsim(void) | |||
785 | hw->vif_data_size = sizeof(struct hwsim_vif_priv); | 935 | hw->vif_data_size = sizeof(struct hwsim_vif_priv); |
786 | hw->sta_data_size = sizeof(struct hwsim_sta_priv); | 936 | hw->sta_data_size = sizeof(struct hwsim_sta_priv); |
787 | 937 | ||
788 | memcpy(data->channels, hwsim_channels, sizeof(hwsim_channels)); | 938 | memcpy(data->channels_2ghz, hwsim_channels_2ghz, |
939 | sizeof(hwsim_channels_2ghz)); | ||
940 | memcpy(data->channels_5ghz, hwsim_channels_5ghz, | ||
941 | sizeof(hwsim_channels_5ghz)); | ||
789 | memcpy(data->rates, hwsim_rates, sizeof(hwsim_rates)); | 942 | memcpy(data->rates, hwsim_rates, sizeof(hwsim_rates)); |
790 | data->band.channels = data->channels; | 943 | |
791 | data->band.n_channels = ARRAY_SIZE(hwsim_channels); | 944 | for (band = IEEE80211_BAND_2GHZ; band < IEEE80211_NUM_BANDS; band++) { |
792 | data->band.bitrates = data->rates; | 945 | struct ieee80211_supported_band *sband = &data->bands[band]; |
793 | data->band.n_bitrates = ARRAY_SIZE(hwsim_rates); | 946 | switch (band) { |
794 | data->band.ht_cap.ht_supported = true; | 947 | case IEEE80211_BAND_2GHZ: |
795 | data->band.ht_cap.cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | | 948 | sband->channels = data->channels_2ghz; |
796 | IEEE80211_HT_CAP_GRN_FLD | | 949 | sband->n_channels = |
797 | IEEE80211_HT_CAP_SGI_40 | | 950 | ARRAY_SIZE(hwsim_channels_2ghz); |
798 | IEEE80211_HT_CAP_DSSSCCK40; | 951 | break; |
799 | data->band.ht_cap.ampdu_factor = 0x3; | 952 | case IEEE80211_BAND_5GHZ: |
800 | data->band.ht_cap.ampdu_density = 0x6; | 953 | sband->channels = data->channels_5ghz; |
801 | memset(&data->band.ht_cap.mcs, 0, | 954 | sband->n_channels = |
802 | sizeof(data->band.ht_cap.mcs)); | 955 | ARRAY_SIZE(hwsim_channels_5ghz); |
803 | data->band.ht_cap.mcs.rx_mask[0] = 0xff; | 956 | break; |
804 | data->band.ht_cap.mcs.rx_mask[1] = 0xff; | 957 | default: |
805 | data->band.ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; | 958 | break; |
806 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &data->band; | 959 | } |
960 | |||
961 | sband->bitrates = data->rates; | ||
962 | sband->n_bitrates = ARRAY_SIZE(hwsim_rates); | ||
963 | |||
964 | sband->ht_cap.ht_supported = true; | ||
965 | sband->ht_cap.cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | | ||
966 | IEEE80211_HT_CAP_GRN_FLD | | ||
967 | IEEE80211_HT_CAP_SGI_40 | | ||
968 | IEEE80211_HT_CAP_DSSSCCK40; | ||
969 | sband->ht_cap.ampdu_factor = 0x3; | ||
970 | sband->ht_cap.ampdu_density = 0x6; | ||
971 | memset(&sband->ht_cap.mcs, 0, | ||
972 | sizeof(sband->ht_cap.mcs)); | ||
973 | sband->ht_cap.mcs.rx_mask[0] = 0xff; | ||
974 | sband->ht_cap.mcs.rx_mask[1] = 0xff; | ||
975 | sband->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; | ||
976 | |||
977 | hw->wiphy->bands[band] = sband; | ||
978 | } | ||
979 | |||
980 | /* Work to be done prior to ieee80211_register_hw() */ | ||
981 | switch (regtest) { | ||
982 | case HWSIM_REGTEST_DISABLED: | ||
983 | case HWSIM_REGTEST_DRIVER_REG_FOLLOW: | ||
984 | case HWSIM_REGTEST_DRIVER_REG_ALL: | ||
985 | case HWSIM_REGTEST_DIFF_COUNTRY: | ||
986 | /* | ||
987 | * Nothing to be done for driver regulatory domain | ||
988 | * hints prior to ieee80211_register_hw() | ||
989 | */ | ||
990 | break; | ||
991 | case HWSIM_REGTEST_WORLD_ROAM: | ||
992 | if (i == 0) { | ||
993 | hw->wiphy->custom_regulatory = true; | ||
994 | wiphy_apply_custom_regulatory(hw->wiphy, | ||
995 | &hwsim_world_regdom_custom_01); | ||
996 | } | ||
997 | break; | ||
998 | case HWSIM_REGTEST_CUSTOM_WORLD: | ||
999 | hw->wiphy->custom_regulatory = true; | ||
1000 | wiphy_apply_custom_regulatory(hw->wiphy, | ||
1001 | &hwsim_world_regdom_custom_01); | ||
1002 | break; | ||
1003 | case HWSIM_REGTEST_CUSTOM_WORLD_2: | ||
1004 | if (i == 0) { | ||
1005 | hw->wiphy->custom_regulatory = true; | ||
1006 | wiphy_apply_custom_regulatory(hw->wiphy, | ||
1007 | &hwsim_world_regdom_custom_01); | ||
1008 | } else if (i == 1) { | ||
1009 | hw->wiphy->custom_regulatory = true; | ||
1010 | wiphy_apply_custom_regulatory(hw->wiphy, | ||
1011 | &hwsim_world_regdom_custom_02); | ||
1012 | } | ||
1013 | break; | ||
1014 | case HWSIM_REGTEST_STRICT_ALL: | ||
1015 | hw->wiphy->strict_regulatory = true; | ||
1016 | break; | ||
1017 | case HWSIM_REGTEST_STRICT_FOLLOW: | ||
1018 | case HWSIM_REGTEST_STRICT_AND_DRIVER_REG: | ||
1019 | if (i == 0) | ||
1020 | hw->wiphy->strict_regulatory = true; | ||
1021 | break; | ||
1022 | case HWSIM_REGTEST_ALL: | ||
1023 | if (i == 0) { | ||
1024 | hw->wiphy->custom_regulatory = true; | ||
1025 | wiphy_apply_custom_regulatory(hw->wiphy, | ||
1026 | &hwsim_world_regdom_custom_01); | ||
1027 | } else if (i == 1) { | ||
1028 | hw->wiphy->custom_regulatory = true; | ||
1029 | wiphy_apply_custom_regulatory(hw->wiphy, | ||
1030 | &hwsim_world_regdom_custom_02); | ||
1031 | } else if (i == 4) | ||
1032 | hw->wiphy->strict_regulatory = true; | ||
1033 | break; | ||
1034 | default: | ||
1035 | break; | ||
1036 | } | ||
807 | 1037 | ||
808 | err = ieee80211_register_hw(hw); | 1038 | err = ieee80211_register_hw(hw); |
809 | if (err < 0) { | 1039 | if (err < 0) { |
@@ -812,6 +1042,52 @@ static int __init init_mac80211_hwsim(void) | |||
812 | goto failed_hw; | 1042 | goto failed_hw; |
813 | } | 1043 | } |
814 | 1044 | ||
1045 | /* Work to be done after to ieee80211_register_hw() */ | ||
1046 | switch (regtest) { | ||
1047 | case HWSIM_REGTEST_WORLD_ROAM: | ||
1048 | case HWSIM_REGTEST_DISABLED: | ||
1049 | break; | ||
1050 | case HWSIM_REGTEST_DRIVER_REG_FOLLOW: | ||
1051 | if (!i) | ||
1052 | regulatory_hint(hw->wiphy, hwsim_alpha2s[0]); | ||
1053 | break; | ||
1054 | case HWSIM_REGTEST_DRIVER_REG_ALL: | ||
1055 | case HWSIM_REGTEST_STRICT_ALL: | ||
1056 | regulatory_hint(hw->wiphy, hwsim_alpha2s[0]); | ||
1057 | break; | ||
1058 | case HWSIM_REGTEST_DIFF_COUNTRY: | ||
1059 | if (i < ARRAY_SIZE(hwsim_alpha2s)) | ||
1060 | regulatory_hint(hw->wiphy, hwsim_alpha2s[i]); | ||
1061 | break; | ||
1062 | case HWSIM_REGTEST_CUSTOM_WORLD: | ||
1063 | case HWSIM_REGTEST_CUSTOM_WORLD_2: | ||
1064 | /* | ||
1065 | * Nothing to be done for custom world regulatory | ||
1066 | * domains after to ieee80211_register_hw | ||
1067 | */ | ||
1068 | break; | ||
1069 | case HWSIM_REGTEST_STRICT_FOLLOW: | ||
1070 | if (i == 0) | ||
1071 | regulatory_hint(hw->wiphy, hwsim_alpha2s[0]); | ||
1072 | break; | ||
1073 | case HWSIM_REGTEST_STRICT_AND_DRIVER_REG: | ||
1074 | if (i == 0) | ||
1075 | regulatory_hint(hw->wiphy, hwsim_alpha2s[0]); | ||
1076 | else if (i == 1) | ||
1077 | regulatory_hint(hw->wiphy, hwsim_alpha2s[1]); | ||
1078 | break; | ||
1079 | case HWSIM_REGTEST_ALL: | ||
1080 | if (i == 2) | ||
1081 | regulatory_hint(hw->wiphy, hwsim_alpha2s[0]); | ||
1082 | else if (i == 3) | ||
1083 | regulatory_hint(hw->wiphy, hwsim_alpha2s[1]); | ||
1084 | else if (i == 4) | ||
1085 | regulatory_hint(hw->wiphy, hwsim_alpha2s[2]); | ||
1086 | break; | ||
1087 | default: | ||
1088 | break; | ||
1089 | } | ||
1090 | |||
815 | printk(KERN_DEBUG "%s: hwaddr %pM registered\n", | 1091 | printk(KERN_DEBUG "%s: hwaddr %pM registered\n", |
816 | wiphy_name(hw->wiphy), | 1092 | wiphy_name(hw->wiphy), |
817 | hw->wiphy->perm_addr); | 1093 | hw->wiphy->perm_addr); |
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c new file mode 100644 index 000000000000..57a0268d1bae --- /dev/null +++ b/drivers/net/wireless/mwl8k.c | |||
@@ -0,0 +1,3789 @@ | |||
1 | /* | ||
2 | * drivers/net/wireless/mwl8k.c driver for Marvell TOPDOG 802.11 Wireless cards | ||
3 | * | ||
4 | * Copyright (C) 2008 Marvell Semiconductor Inc. | ||
5 | * | ||
6 | * This file is licensed under the terms of the GNU General Public | ||
7 | * License version 2. This program is licensed "as is" without any | ||
8 | * warranty of any kind, whether express or implied. | ||
9 | */ | ||
10 | |||
11 | #include <linux/init.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/spinlock.h> | ||
15 | #include <linux/list.h> | ||
16 | #include <linux/pci.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/completion.h> | ||
19 | #include <linux/etherdevice.h> | ||
20 | #include <net/mac80211.h> | ||
21 | #include <linux/moduleparam.h> | ||
22 | #include <linux/firmware.h> | ||
23 | #include <linux/workqueue.h> | ||
24 | |||
25 | #define MWL8K_DESC "Marvell TOPDOG(R) 802.11 Wireless Network Driver" | ||
26 | #define MWL8K_NAME KBUILD_MODNAME | ||
27 | #define MWL8K_VERSION "0.9.1" | ||
28 | |||
29 | MODULE_DESCRIPTION(MWL8K_DESC); | ||
30 | MODULE_VERSION(MWL8K_VERSION); | ||
31 | MODULE_AUTHOR("Lennert Buytenhek <buytenh@marvell.com>"); | ||
32 | MODULE_LICENSE("GPL"); | ||
33 | |||
34 | static DEFINE_PCI_DEVICE_TABLE(mwl8k_table) = { | ||
35 | { PCI_VDEVICE(MARVELL, 0x2a2b), .driver_data = 8687, }, | ||
36 | { PCI_VDEVICE(MARVELL, 0x2a30), .driver_data = 8687, }, | ||
37 | { } | ||
38 | }; | ||
39 | MODULE_DEVICE_TABLE(pci, mwl8k_table); | ||
40 | |||
41 | #define IEEE80211_ADDR_LEN ETH_ALEN | ||
42 | |||
43 | /* Register definitions */ | ||
44 | #define MWL8K_HIU_GEN_PTR 0x00000c10 | ||
45 | #define MWL8K_MODE_STA 0x0000005a | ||
46 | #define MWL8K_MODE_AP 0x000000a5 | ||
47 | #define MWL8K_HIU_INT_CODE 0x00000c14 | ||
48 | #define MWL8K_FWSTA_READY 0xf0f1f2f4 | ||
49 | #define MWL8K_FWAP_READY 0xf1f2f4a5 | ||
50 | #define MWL8K_INT_CODE_CMD_FINISHED 0x00000005 | ||
51 | #define MWL8K_HIU_SCRATCH 0x00000c40 | ||
52 | |||
53 | /* Host->device communications */ | ||
54 | #define MWL8K_HIU_H2A_INTERRUPT_EVENTS 0x00000c18 | ||
55 | #define MWL8K_HIU_H2A_INTERRUPT_STATUS 0x00000c1c | ||
56 | #define MWL8K_HIU_H2A_INTERRUPT_MASK 0x00000c20 | ||
57 | #define MWL8K_HIU_H2A_INTERRUPT_CLEAR_SEL 0x00000c24 | ||
58 | #define MWL8K_HIU_H2A_INTERRUPT_STATUS_MASK 0x00000c28 | ||
59 | #define MWL8K_H2A_INT_DUMMY (1 << 20) | ||
60 | #define MWL8K_H2A_INT_RESET (1 << 15) | ||
61 | #define MWL8K_H2A_INT_PS (1 << 2) | ||
62 | #define MWL8K_H2A_INT_DOORBELL (1 << 1) | ||
63 | #define MWL8K_H2A_INT_PPA_READY (1 << 0) | ||
64 | |||
65 | /* Device->host communications */ | ||
66 | #define MWL8K_HIU_A2H_INTERRUPT_EVENTS 0x00000c2c | ||
67 | #define MWL8K_HIU_A2H_INTERRUPT_STATUS 0x00000c30 | ||
68 | #define MWL8K_HIU_A2H_INTERRUPT_MASK 0x00000c34 | ||
69 | #define MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL 0x00000c38 | ||
70 | #define MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK 0x00000c3c | ||
71 | #define MWL8K_A2H_INT_DUMMY (1 << 20) | ||
72 | #define MWL8K_A2H_INT_CHNL_SWITCHED (1 << 11) | ||
73 | #define MWL8K_A2H_INT_QUEUE_EMPTY (1 << 10) | ||
74 | #define MWL8K_A2H_INT_RADAR_DETECT (1 << 7) | ||
75 | #define MWL8K_A2H_INT_RADIO_ON (1 << 6) | ||
76 | #define MWL8K_A2H_INT_RADIO_OFF (1 << 5) | ||
77 | #define MWL8K_A2H_INT_MAC_EVENT (1 << 3) | ||
78 | #define MWL8K_A2H_INT_OPC_DONE (1 << 2) | ||
79 | #define MWL8K_A2H_INT_RX_READY (1 << 1) | ||
80 | #define MWL8K_A2H_INT_TX_DONE (1 << 0) | ||
81 | |||
82 | #define MWL8K_A2H_EVENTS (MWL8K_A2H_INT_DUMMY | \ | ||
83 | MWL8K_A2H_INT_CHNL_SWITCHED | \ | ||
84 | MWL8K_A2H_INT_QUEUE_EMPTY | \ | ||
85 | MWL8K_A2H_INT_RADAR_DETECT | \ | ||
86 | MWL8K_A2H_INT_RADIO_ON | \ | ||
87 | MWL8K_A2H_INT_RADIO_OFF | \ | ||
88 | MWL8K_A2H_INT_MAC_EVENT | \ | ||
89 | MWL8K_A2H_INT_OPC_DONE | \ | ||
90 | MWL8K_A2H_INT_RX_READY | \ | ||
91 | MWL8K_A2H_INT_TX_DONE) | ||
92 | |||
93 | /* WME stream classes */ | ||
94 | #define WME_AC_BE 0 /* best effort */ | ||
95 | #define WME_AC_BK 1 /* background */ | ||
96 | #define WME_AC_VI 2 /* video */ | ||
97 | #define WME_AC_VO 3 /* voice */ | ||
98 | |||
99 | #define MWL8K_RX_QUEUES 1 | ||
100 | #define MWL8K_TX_QUEUES 4 | ||
101 | |||
102 | struct mwl8k_rx_queue { | ||
103 | int rx_desc_count; | ||
104 | |||
105 | /* hw receives here */ | ||
106 | int rx_head; | ||
107 | |||
108 | /* refill descs here */ | ||
109 | int rx_tail; | ||
110 | |||
111 | struct mwl8k_rx_desc *rx_desc_area; | ||
112 | dma_addr_t rx_desc_dma; | ||
113 | struct sk_buff **rx_skb; | ||
114 | }; | ||
115 | |||
116 | struct mwl8k_skb { | ||
117 | /* | ||
118 | * The DMA engine requires a modification to the payload. | ||
119 | * If the skbuff is shared/cloned, it needs to be unshared. | ||
120 | * This method is used to ensure the stack always gets back | ||
121 | * the skbuff it sent for transmission. | ||
122 | */ | ||
123 | struct sk_buff *clone; | ||
124 | struct sk_buff *skb; | ||
125 | }; | ||
126 | |||
127 | struct mwl8k_tx_queue { | ||
128 | /* hw transmits here */ | ||
129 | int tx_head; | ||
130 | |||
131 | /* sw appends here */ | ||
132 | int tx_tail; | ||
133 | |||
134 | struct ieee80211_tx_queue_stats tx_stats; | ||
135 | struct mwl8k_tx_desc *tx_desc_area; | ||
136 | dma_addr_t tx_desc_dma; | ||
137 | struct mwl8k_skb *tx_skb; | ||
138 | }; | ||
139 | |||
140 | /* Pointers to the firmware data and meta information about it. */ | ||
141 | struct mwl8k_firmware { | ||
142 | /* Microcode */ | ||
143 | struct firmware *ucode; | ||
144 | |||
145 | /* Boot helper code */ | ||
146 | struct firmware *helper; | ||
147 | }; | ||
148 | |||
149 | struct mwl8k_priv { | ||
150 | void __iomem *regs; | ||
151 | struct ieee80211_hw *hw; | ||
152 | |||
153 | struct pci_dev *pdev; | ||
154 | u8 name[16]; | ||
155 | /* firmware access lock */ | ||
156 | spinlock_t fw_lock; | ||
157 | |||
158 | /* firmware files and meta data */ | ||
159 | struct mwl8k_firmware fw; | ||
160 | u32 part_num; | ||
161 | |||
162 | /* lock held over TX and TX reap */ | ||
163 | spinlock_t tx_lock; | ||
164 | u32 int_mask; | ||
165 | |||
166 | struct ieee80211_vif *vif; | ||
167 | struct list_head vif_list; | ||
168 | |||
169 | struct ieee80211_channel *current_channel; | ||
170 | |||
171 | /* power management status cookie from firmware */ | ||
172 | u32 *cookie; | ||
173 | dma_addr_t cookie_dma; | ||
174 | |||
175 | u16 num_mcaddrs; | ||
176 | u16 region_code; | ||
177 | u8 hw_rev; | ||
178 | __le32 fw_rev; | ||
179 | u32 wep_enabled; | ||
180 | |||
181 | /* | ||
182 | * Running count of TX packets in flight, to avoid | ||
183 | * iterating over the transmit rings each time. | ||
184 | */ | ||
185 | int pending_tx_pkts; | ||
186 | |||
187 | struct mwl8k_rx_queue rxq[MWL8K_RX_QUEUES]; | ||
188 | struct mwl8k_tx_queue txq[MWL8K_TX_QUEUES]; | ||
189 | |||
190 | /* PHY parameters */ | ||
191 | struct ieee80211_supported_band band; | ||
192 | struct ieee80211_channel channels[14]; | ||
193 | struct ieee80211_rate rates[12]; | ||
194 | |||
195 | /* RF preamble: Short, Long or Auto */ | ||
196 | u8 radio_preamble; | ||
197 | u8 radio_state; | ||
198 | |||
199 | /* WMM MODE 1 for enabled; 0 for disabled */ | ||
200 | bool wmm_mode; | ||
201 | |||
202 | /* Set if PHY config is in progress */ | ||
203 | bool inconfig; | ||
204 | |||
205 | /* XXX need to convert this to handle multiple interfaces */ | ||
206 | bool capture_beacon; | ||
207 | u8 capture_bssid[IEEE80211_ADDR_LEN]; | ||
208 | struct sk_buff *beacon_skb; | ||
209 | |||
210 | /* | ||
211 | * This FJ worker has to be global as it is scheduled from the | ||
212 | * RX handler. At this point we don't know which interface it | ||
213 | * belongs to until the list of bssids waiting to complete join | ||
214 | * is checked. | ||
215 | */ | ||
216 | struct work_struct finalize_join_worker; | ||
217 | |||
218 | /* Tasklet to reclaim TX descriptors and buffers after tx */ | ||
219 | struct tasklet_struct tx_reclaim_task; | ||
220 | |||
221 | /* Work thread to serialize configuration requests */ | ||
222 | struct workqueue_struct *config_wq; | ||
223 | struct completion *hostcmd_wait; | ||
224 | struct completion *tx_wait; | ||
225 | }; | ||
226 | |||
227 | /* Per interface specific private data */ | ||
228 | struct mwl8k_vif { | ||
229 | struct list_head node; | ||
230 | |||
231 | /* backpointer to parent config block */ | ||
232 | struct mwl8k_priv *priv; | ||
233 | |||
234 | /* BSS config of AP or IBSS from mac80211*/ | ||
235 | struct ieee80211_bss_conf bss_info; | ||
236 | |||
237 | /* BSSID of AP or IBSS */ | ||
238 | u8 bssid[IEEE80211_ADDR_LEN]; | ||
239 | u8 mac_addr[IEEE80211_ADDR_LEN]; | ||
240 | |||
241 | /* | ||
242 | * Subset of supported legacy rates. | ||
243 | * Intersection of AP and STA supported rates. | ||
244 | */ | ||
245 | struct ieee80211_rate legacy_rates[12]; | ||
246 | |||
247 | /* number of supported legacy rates */ | ||
248 | u8 legacy_nrates; | ||
249 | |||
250 | /* Number of supported MCS rates. Work in progress */ | ||
251 | u8 mcs_nrates; | ||
252 | |||
253 | /* Index into station database.Returned by update_sta_db call */ | ||
254 | u8 peer_id; | ||
255 | |||
256 | /* Non AMPDU sequence number assigned by driver */ | ||
257 | u16 seqno; | ||
258 | |||
259 | /* Note:There is no channel info, | ||
260 | * refer to the master channel info in priv | ||
261 | */ | ||
262 | }; | ||
263 | |||
264 | #define MWL8K_VIF(_vif) (struct mwl8k_vif *)(&((_vif)->drv_priv)) | ||
265 | |||
266 | static const struct ieee80211_channel mwl8k_channels[] = { | ||
267 | { .center_freq = 2412, .hw_value = 1, }, | ||
268 | { .center_freq = 2417, .hw_value = 2, }, | ||
269 | { .center_freq = 2422, .hw_value = 3, }, | ||
270 | { .center_freq = 2427, .hw_value = 4, }, | ||
271 | { .center_freq = 2432, .hw_value = 5, }, | ||
272 | { .center_freq = 2437, .hw_value = 6, }, | ||
273 | { .center_freq = 2442, .hw_value = 7, }, | ||
274 | { .center_freq = 2447, .hw_value = 8, }, | ||
275 | { .center_freq = 2452, .hw_value = 9, }, | ||
276 | { .center_freq = 2457, .hw_value = 10, }, | ||
277 | { .center_freq = 2462, .hw_value = 11, }, | ||
278 | }; | ||
279 | |||
280 | static const struct ieee80211_rate mwl8k_rates[] = { | ||
281 | { .bitrate = 10, .hw_value = 2, }, | ||
282 | { .bitrate = 20, .hw_value = 4, }, | ||
283 | { .bitrate = 55, .hw_value = 11, }, | ||
284 | { .bitrate = 60, .hw_value = 12, }, | ||
285 | { .bitrate = 90, .hw_value = 18, }, | ||
286 | { .bitrate = 110, .hw_value = 22, }, | ||
287 | { .bitrate = 120, .hw_value = 24, }, | ||
288 | { .bitrate = 180, .hw_value = 36, }, | ||
289 | { .bitrate = 240, .hw_value = 48, }, | ||
290 | { .bitrate = 360, .hw_value = 72, }, | ||
291 | { .bitrate = 480, .hw_value = 96, }, | ||
292 | { .bitrate = 540, .hw_value = 108, }, | ||
293 | }; | ||
294 | |||
295 | /* Radio settings */ | ||
296 | #define MWL8K_RADIO_FORCE 0x2 | ||
297 | #define MWL8K_RADIO_ENABLE 0x1 | ||
298 | #define MWL8K_RADIO_DISABLE 0x0 | ||
299 | #define MWL8K_RADIO_AUTO_PREAMBLE 0x0005 | ||
300 | #define MWL8K_RADIO_SHORT_PREAMBLE 0x0003 | ||
301 | #define MWL8K_RADIO_LONG_PREAMBLE 0x0001 | ||
302 | |||
303 | /* WMM */ | ||
304 | #define MWL8K_WMM_ENABLE 1 | ||
305 | #define MWL8K_WMM_DISABLE 0 | ||
306 | |||
307 | #define MWL8K_RADIO_DEFAULT_PREAMBLE MWL8K_RADIO_LONG_PREAMBLE | ||
308 | |||
309 | /* Slot time */ | ||
310 | |||
311 | /* Short Slot: 9us slot time */ | ||
312 | #define MWL8K_SHORT_SLOTTIME 1 | ||
313 | |||
314 | /* Long slot: 20us slot time */ | ||
315 | #define MWL8K_LONG_SLOTTIME 0 | ||
316 | |||
317 | /* Set or get info from Firmware */ | ||
318 | #define MWL8K_CMD_SET 0x0001 | ||
319 | #define MWL8K_CMD_GET 0x0000 | ||
320 | |||
321 | /* Firmware command codes */ | ||
322 | #define MWL8K_CMD_CODE_DNLD 0x0001 | ||
323 | #define MWL8K_CMD_GET_HW_SPEC 0x0003 | ||
324 | #define MWL8K_CMD_MAC_MULTICAST_ADR 0x0010 | ||
325 | #define MWL8K_CMD_GET_STAT 0x0014 | ||
326 | #define MWL8K_CMD_RADIO_CONTROL 0x001C | ||
327 | #define MWL8K_CMD_RF_TX_POWER 0x001E | ||
328 | #define MWL8K_CMD_SET_PRE_SCAN 0x0107 | ||
329 | #define MWL8K_CMD_SET_POST_SCAN 0x0108 | ||
330 | #define MWL8K_CMD_SET_RF_CHANNEL 0x010A | ||
331 | #define MWL8K_CMD_SET_SLOT 0x0114 | ||
332 | #define MWL8K_CMD_MIMO_CONFIG 0x0125 | ||
333 | #define MWL8K_CMD_ENABLE_SNIFFER 0x0150 | ||
334 | #define MWL8K_CMD_SET_WMM_MODE 0x0123 | ||
335 | #define MWL8K_CMD_SET_EDCA_PARAMS 0x0115 | ||
336 | #define MWL8K_CMD_SET_FINALIZE_JOIN 0x0111 | ||
337 | #define MWL8K_CMD_UPDATE_STADB 0x1123 | ||
338 | #define MWL8K_CMD_SET_RATEADAPT_MODE 0x0203 | ||
339 | #define MWL8K_CMD_SET_LINKADAPT_MODE 0x0129 | ||
340 | #define MWL8K_CMD_SET_AID 0x010d | ||
341 | #define MWL8K_CMD_SET_RATE 0x0110 | ||
342 | #define MWL8K_CMD_USE_FIXED_RATE 0x0126 | ||
343 | #define MWL8K_CMD_RTS_THRESHOLD 0x0113 | ||
344 | #define MWL8K_CMD_ENCRYPTION 0x1122 | ||
345 | |||
346 | static const char *mwl8k_cmd_name(u16 cmd, char *buf, int bufsize) | ||
347 | { | ||
348 | #define MWL8K_CMDNAME(x) case MWL8K_CMD_##x: do {\ | ||
349 | snprintf(buf, bufsize, "%s", #x);\ | ||
350 | return buf;\ | ||
351 | } while (0) | ||
352 | switch (cmd & (~0x8000)) { | ||
353 | MWL8K_CMDNAME(CODE_DNLD); | ||
354 | MWL8K_CMDNAME(GET_HW_SPEC); | ||
355 | MWL8K_CMDNAME(MAC_MULTICAST_ADR); | ||
356 | MWL8K_CMDNAME(GET_STAT); | ||
357 | MWL8K_CMDNAME(RADIO_CONTROL); | ||
358 | MWL8K_CMDNAME(RF_TX_POWER); | ||
359 | MWL8K_CMDNAME(SET_PRE_SCAN); | ||
360 | MWL8K_CMDNAME(SET_POST_SCAN); | ||
361 | MWL8K_CMDNAME(SET_RF_CHANNEL); | ||
362 | MWL8K_CMDNAME(SET_SLOT); | ||
363 | MWL8K_CMDNAME(MIMO_CONFIG); | ||
364 | MWL8K_CMDNAME(ENABLE_SNIFFER); | ||
365 | MWL8K_CMDNAME(SET_WMM_MODE); | ||
366 | MWL8K_CMDNAME(SET_EDCA_PARAMS); | ||
367 | MWL8K_CMDNAME(SET_FINALIZE_JOIN); | ||
368 | MWL8K_CMDNAME(UPDATE_STADB); | ||
369 | MWL8K_CMDNAME(SET_RATEADAPT_MODE); | ||
370 | MWL8K_CMDNAME(SET_LINKADAPT_MODE); | ||
371 | MWL8K_CMDNAME(SET_AID); | ||
372 | MWL8K_CMDNAME(SET_RATE); | ||
373 | MWL8K_CMDNAME(USE_FIXED_RATE); | ||
374 | MWL8K_CMDNAME(RTS_THRESHOLD); | ||
375 | MWL8K_CMDNAME(ENCRYPTION); | ||
376 | default: | ||
377 | snprintf(buf, bufsize, "0x%x", cmd); | ||
378 | } | ||
379 | #undef MWL8K_CMDNAME | ||
380 | |||
381 | return buf; | ||
382 | } | ||
383 | |||
384 | /* Hardware and firmware reset */ | ||
385 | static void mwl8k_hw_reset(struct mwl8k_priv *priv) | ||
386 | { | ||
387 | iowrite32(MWL8K_H2A_INT_RESET, | ||
388 | priv->regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); | ||
389 | iowrite32(MWL8K_H2A_INT_RESET, | ||
390 | priv->regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); | ||
391 | msleep(20); | ||
392 | } | ||
393 | |||
394 | /* Release fw image */ | ||
395 | static void mwl8k_release_fw(struct firmware **fw) | ||
396 | { | ||
397 | if (*fw == NULL) | ||
398 | return; | ||
399 | release_firmware(*fw); | ||
400 | *fw = NULL; | ||
401 | } | ||
402 | |||
403 | static void mwl8k_release_firmware(struct mwl8k_priv *priv) | ||
404 | { | ||
405 | mwl8k_release_fw(&priv->fw.ucode); | ||
406 | mwl8k_release_fw(&priv->fw.helper); | ||
407 | } | ||
408 | |||
409 | /* Request fw image */ | ||
410 | static int mwl8k_request_fw(struct mwl8k_priv *priv, | ||
411 | const char *fname, struct firmware **fw) | ||
412 | { | ||
413 | /* release current image */ | ||
414 | if (*fw != NULL) | ||
415 | mwl8k_release_fw(fw); | ||
416 | |||
417 | return request_firmware((const struct firmware **)fw, | ||
418 | fname, &priv->pdev->dev); | ||
419 | } | ||
420 | |||
421 | static int mwl8k_request_firmware(struct mwl8k_priv *priv, u32 part_num) | ||
422 | { | ||
423 | u8 filename[64]; | ||
424 | int rc; | ||
425 | |||
426 | priv->part_num = part_num; | ||
427 | |||
428 | snprintf(filename, sizeof(filename), | ||
429 | "mwl8k/helper_%u.fw", priv->part_num); | ||
430 | |||
431 | rc = mwl8k_request_fw(priv, filename, &priv->fw.helper); | ||
432 | if (rc) { | ||
433 | printk(KERN_ERR | ||
434 | "%s Error requesting helper firmware file %s\n", | ||
435 | pci_name(priv->pdev), filename); | ||
436 | return rc; | ||
437 | } | ||
438 | |||
439 | snprintf(filename, sizeof(filename), | ||
440 | "mwl8k/fmimage_%u.fw", priv->part_num); | ||
441 | |||
442 | rc = mwl8k_request_fw(priv, filename, &priv->fw.ucode); | ||
443 | if (rc) { | ||
444 | printk(KERN_ERR "%s Error requesting firmware file %s\n", | ||
445 | pci_name(priv->pdev), filename); | ||
446 | mwl8k_release_fw(&priv->fw.helper); | ||
447 | return rc; | ||
448 | } | ||
449 | |||
450 | return 0; | ||
451 | } | ||
452 | |||
453 | struct mwl8k_cmd_pkt { | ||
454 | __le16 code; | ||
455 | __le16 length; | ||
456 | __le16 seq_num; | ||
457 | __le16 result; | ||
458 | char payload[0]; | ||
459 | } __attribute__((packed)); | ||
460 | |||
461 | /* | ||
462 | * Firmware loading. | ||
463 | */ | ||
464 | static int | ||
465 | mwl8k_send_fw_load_cmd(struct mwl8k_priv *priv, void *data, int length) | ||
466 | { | ||
467 | void __iomem *regs = priv->regs; | ||
468 | dma_addr_t dma_addr; | ||
469 | int rc; | ||
470 | int loops; | ||
471 | |||
472 | dma_addr = pci_map_single(priv->pdev, data, length, PCI_DMA_TODEVICE); | ||
473 | if (pci_dma_mapping_error(priv->pdev, dma_addr)) | ||
474 | return -ENOMEM; | ||
475 | |||
476 | iowrite32(dma_addr, regs + MWL8K_HIU_GEN_PTR); | ||
477 | iowrite32(0, regs + MWL8K_HIU_INT_CODE); | ||
478 | iowrite32(MWL8K_H2A_INT_DOORBELL, | ||
479 | regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); | ||
480 | iowrite32(MWL8K_H2A_INT_DUMMY, | ||
481 | regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); | ||
482 | |||
483 | rc = -ETIMEDOUT; | ||
484 | loops = 1000; | ||
485 | do { | ||
486 | u32 int_code; | ||
487 | |||
488 | int_code = ioread32(regs + MWL8K_HIU_INT_CODE); | ||
489 | if (int_code == MWL8K_INT_CODE_CMD_FINISHED) { | ||
490 | iowrite32(0, regs + MWL8K_HIU_INT_CODE); | ||
491 | rc = 0; | ||
492 | break; | ||
493 | } | ||
494 | |||
495 | udelay(1); | ||
496 | } while (--loops); | ||
497 | |||
498 | pci_unmap_single(priv->pdev, dma_addr, length, PCI_DMA_TODEVICE); | ||
499 | |||
500 | /* | ||
501 | * Clear 'command done' interrupt bit. | ||
502 | */ | ||
503 | loops = 1000; | ||
504 | do { | ||
505 | u32 status; | ||
506 | |||
507 | status = ioread32(priv->regs + | ||
508 | MWL8K_HIU_A2H_INTERRUPT_STATUS); | ||
509 | if (status & MWL8K_A2H_INT_OPC_DONE) { | ||
510 | iowrite32(~MWL8K_A2H_INT_OPC_DONE, | ||
511 | priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); | ||
512 | ioread32(priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); | ||
513 | break; | ||
514 | } | ||
515 | |||
516 | udelay(1); | ||
517 | } while (--loops); | ||
518 | |||
519 | return rc; | ||
520 | } | ||
521 | |||
522 | static int mwl8k_load_fw_image(struct mwl8k_priv *priv, | ||
523 | const u8 *data, size_t length) | ||
524 | { | ||
525 | struct mwl8k_cmd_pkt *cmd; | ||
526 | int done; | ||
527 | int rc = 0; | ||
528 | |||
529 | cmd = kmalloc(sizeof(*cmd) + 256, GFP_KERNEL); | ||
530 | if (cmd == NULL) | ||
531 | return -ENOMEM; | ||
532 | |||
533 | cmd->code = cpu_to_le16(MWL8K_CMD_CODE_DNLD); | ||
534 | cmd->seq_num = 0; | ||
535 | cmd->result = 0; | ||
536 | |||
537 | done = 0; | ||
538 | while (length) { | ||
539 | int block_size = length > 256 ? 256 : length; | ||
540 | |||
541 | memcpy(cmd->payload, data + done, block_size); | ||
542 | cmd->length = cpu_to_le16(block_size); | ||
543 | |||
544 | rc = mwl8k_send_fw_load_cmd(priv, cmd, | ||
545 | sizeof(*cmd) + block_size); | ||
546 | if (rc) | ||
547 | break; | ||
548 | |||
549 | done += block_size; | ||
550 | length -= block_size; | ||
551 | } | ||
552 | |||
553 | if (!rc) { | ||
554 | cmd->length = 0; | ||
555 | rc = mwl8k_send_fw_load_cmd(priv, cmd, sizeof(*cmd)); | ||
556 | } | ||
557 | |||
558 | kfree(cmd); | ||
559 | |||
560 | return rc; | ||
561 | } | ||
562 | |||
563 | static int mwl8k_feed_fw_image(struct mwl8k_priv *priv, | ||
564 | const u8 *data, size_t length) | ||
565 | { | ||
566 | unsigned char *buffer; | ||
567 | int may_continue, rc = 0; | ||
568 | u32 done, prev_block_size; | ||
569 | |||
570 | buffer = kmalloc(1024, GFP_KERNEL); | ||
571 | if (buffer == NULL) | ||
572 | return -ENOMEM; | ||
573 | |||
574 | done = 0; | ||
575 | prev_block_size = 0; | ||
576 | may_continue = 1000; | ||
577 | while (may_continue > 0) { | ||
578 | u32 block_size; | ||
579 | |||
580 | block_size = ioread32(priv->regs + MWL8K_HIU_SCRATCH); | ||
581 | if (block_size & 1) { | ||
582 | block_size &= ~1; | ||
583 | may_continue--; | ||
584 | } else { | ||
585 | done += prev_block_size; | ||
586 | length -= prev_block_size; | ||
587 | } | ||
588 | |||
589 | if (block_size > 1024 || block_size > length) { | ||
590 | rc = -EOVERFLOW; | ||
591 | break; | ||
592 | } | ||
593 | |||
594 | if (length == 0) { | ||
595 | rc = 0; | ||
596 | break; | ||
597 | } | ||
598 | |||
599 | if (block_size == 0) { | ||
600 | rc = -EPROTO; | ||
601 | may_continue--; | ||
602 | udelay(1); | ||
603 | continue; | ||
604 | } | ||
605 | |||
606 | prev_block_size = block_size; | ||
607 | memcpy(buffer, data + done, block_size); | ||
608 | |||
609 | rc = mwl8k_send_fw_load_cmd(priv, buffer, block_size); | ||
610 | if (rc) | ||
611 | break; | ||
612 | } | ||
613 | |||
614 | if (!rc && length != 0) | ||
615 | rc = -EREMOTEIO; | ||
616 | |||
617 | kfree(buffer); | ||
618 | |||
619 | return rc; | ||
620 | } | ||
621 | |||
622 | static int mwl8k_load_firmware(struct mwl8k_priv *priv) | ||
623 | { | ||
624 | int loops, rc; | ||
625 | |||
626 | const u8 *ucode = priv->fw.ucode->data; | ||
627 | size_t ucode_len = priv->fw.ucode->size; | ||
628 | const u8 *helper = priv->fw.helper->data; | ||
629 | size_t helper_len = priv->fw.helper->size; | ||
630 | |||
631 | if (!memcmp(ucode, "\x01\x00\x00\x00", 4)) { | ||
632 | rc = mwl8k_load_fw_image(priv, helper, helper_len); | ||
633 | if (rc) { | ||
634 | printk(KERN_ERR "%s: unable to load firmware " | ||
635 | "helper image\n", pci_name(priv->pdev)); | ||
636 | return rc; | ||
637 | } | ||
638 | msleep(1); | ||
639 | |||
640 | rc = mwl8k_feed_fw_image(priv, ucode, ucode_len); | ||
641 | } else { | ||
642 | rc = mwl8k_load_fw_image(priv, ucode, ucode_len); | ||
643 | } | ||
644 | |||
645 | if (rc) { | ||
646 | printk(KERN_ERR "%s: unable to load firmware data\n", | ||
647 | pci_name(priv->pdev)); | ||
648 | return rc; | ||
649 | } | ||
650 | |||
651 | iowrite32(MWL8K_MODE_STA, priv->regs + MWL8K_HIU_GEN_PTR); | ||
652 | msleep(1); | ||
653 | |||
654 | loops = 200000; | ||
655 | do { | ||
656 | if (ioread32(priv->regs + MWL8K_HIU_INT_CODE) | ||
657 | == MWL8K_FWSTA_READY) | ||
658 | break; | ||
659 | udelay(1); | ||
660 | } while (--loops); | ||
661 | |||
662 | return loops ? 0 : -ETIMEDOUT; | ||
663 | } | ||
664 | |||
665 | |||
666 | /* | ||
667 | * Defines shared between transmission and reception. | ||
668 | */ | ||
669 | /* HT control fields for firmware */ | ||
670 | struct ewc_ht_info { | ||
671 | __le16 control1; | ||
672 | __le16 control2; | ||
673 | __le16 control3; | ||
674 | } __attribute__((packed)); | ||
675 | |||
676 | /* Firmware Station database operations */ | ||
677 | #define MWL8K_STA_DB_ADD_ENTRY 0 | ||
678 | #define MWL8K_STA_DB_MODIFY_ENTRY 1 | ||
679 | #define MWL8K_STA_DB_DEL_ENTRY 2 | ||
680 | #define MWL8K_STA_DB_FLUSH 3 | ||
681 | |||
682 | /* Peer Entry flags - used to define the type of the peer node */ | ||
683 | #define MWL8K_PEER_TYPE_ACCESSPOINT 2 | ||
684 | #define MWL8K_PEER_TYPE_ADHOC_STATION 4 | ||
685 | |||
686 | #define MWL8K_IEEE_LEGACY_DATA_RATES 12 | ||
687 | #define MWL8K_MCS_BITMAP_SIZE 16 | ||
688 | #define pad_size 16 | ||
689 | |||
690 | struct peer_capability_info { | ||
691 | /* Peer type - AP vs. STA. */ | ||
692 | __u8 peer_type; | ||
693 | |||
694 | /* Basic 802.11 capabilities from assoc resp. */ | ||
695 | __le16 basic_caps; | ||
696 | |||
697 | /* Set if peer supports 802.11n high throughput (HT). */ | ||
698 | __u8 ht_support; | ||
699 | |||
700 | /* Valid if HT is supported. */ | ||
701 | __le16 ht_caps; | ||
702 | __u8 extended_ht_caps; | ||
703 | struct ewc_ht_info ewc_info; | ||
704 | |||
705 | /* Legacy rate table. Intersection of our rates and peer rates. */ | ||
706 | __u8 legacy_rates[MWL8K_IEEE_LEGACY_DATA_RATES]; | ||
707 | |||
708 | /* HT rate table. Intersection of our rates and peer rates. */ | ||
709 | __u8 ht_rates[MWL8K_MCS_BITMAP_SIZE]; | ||
710 | __u8 pad[pad_size]; | ||
711 | |||
712 | /* If set, interoperability mode, no proprietary extensions. */ | ||
713 | __u8 interop; | ||
714 | __u8 pad2; | ||
715 | __u8 station_id; | ||
716 | __le16 amsdu_enabled; | ||
717 | } __attribute__((packed)); | ||
718 | |||
719 | /* Inline functions to manipulate QoS field in data descriptor. */ | ||
720 | static inline u16 mwl8k_qos_setbit_tid(u16 qos, u8 tid) | ||
721 | { | ||
722 | u16 val_mask = 0x000f; | ||
723 | u16 qos_mask = ~val_mask; | ||
724 | |||
725 | /* TID bits 0-3 */ | ||
726 | return (qos & qos_mask) | (tid & val_mask); | ||
727 | } | ||
728 | |||
729 | static inline u16 mwl8k_qos_setbit_eosp(u16 qos) | ||
730 | { | ||
731 | u16 val_mask = 1 << 4; | ||
732 | |||
733 | /* End of Service Period Bit 4 */ | ||
734 | return qos | val_mask; | ||
735 | } | ||
736 | |||
737 | static inline u16 mwl8k_qos_setbit_ack(u16 qos, u8 ack_policy) | ||
738 | { | ||
739 | u16 val_mask = 0x3; | ||
740 | u8 shift = 5; | ||
741 | u16 qos_mask = ~(val_mask << shift); | ||
742 | |||
743 | /* Ack Policy Bit 5-6 */ | ||
744 | return (qos & qos_mask) | ((ack_policy & val_mask) << shift); | ||
745 | } | ||
746 | |||
747 | static inline u16 mwl8k_qos_setbit_amsdu(u16 qos) | ||
748 | { | ||
749 | u16 val_mask = 1 << 7; | ||
750 | |||
751 | /* AMSDU present Bit 7 */ | ||
752 | return qos | val_mask; | ||
753 | } | ||
754 | |||
755 | static inline u16 mwl8k_qos_setbit_qlen(u16 qos, u8 len) | ||
756 | { | ||
757 | u16 val_mask = 0xff; | ||
758 | u8 shift = 8; | ||
759 | u16 qos_mask = ~(val_mask << shift); | ||
760 | |||
761 | /* Queue Length Bits 8-15 */ | ||
762 | return (qos & qos_mask) | ((len & val_mask) << shift); | ||
763 | } | ||
764 | |||
765 | /* DMA header used by firmware and hardware. */ | ||
766 | struct mwl8k_dma_data { | ||
767 | __le16 fwlen; | ||
768 | struct ieee80211_hdr wh; | ||
769 | } __attribute__((packed)); | ||
770 | |||
771 | /* Routines to add/remove DMA header from skb. */ | ||
772 | static inline int mwl8k_remove_dma_header(struct sk_buff *skb) | ||
773 | { | ||
774 | struct mwl8k_dma_data *tr = (struct mwl8k_dma_data *)(skb->data); | ||
775 | void *dst, *src = &tr->wh; | ||
776 | __le16 fc = tr->wh.frame_control; | ||
777 | int hdrlen = ieee80211_hdrlen(fc); | ||
778 | u16 space = sizeof(struct mwl8k_dma_data) - hdrlen; | ||
779 | |||
780 | dst = (void *)tr + space; | ||
781 | if (dst != src) { | ||
782 | memmove(dst, src, hdrlen); | ||
783 | skb_pull(skb, space); | ||
784 | } | ||
785 | |||
786 | return 0; | ||
787 | } | ||
788 | |||
789 | static inline struct sk_buff *mwl8k_add_dma_header(struct sk_buff *skb) | ||
790 | { | ||
791 | struct ieee80211_hdr *wh; | ||
792 | u32 hdrlen, pktlen; | ||
793 | struct mwl8k_dma_data *tr; | ||
794 | |||
795 | wh = (struct ieee80211_hdr *)skb->data; | ||
796 | hdrlen = ieee80211_hdrlen(wh->frame_control); | ||
797 | pktlen = skb->len; | ||
798 | |||
799 | /* | ||
800 | * Copy up/down the 802.11 header; the firmware requires | ||
801 | * we present a 2-byte payload length followed by a | ||
802 | * 4-address header (w/o QoS), followed (optionally) by | ||
803 | * any WEP/ExtIV header (but only filled in for CCMP). | ||
804 | */ | ||
805 | if (hdrlen != sizeof(struct mwl8k_dma_data)) | ||
806 | skb_push(skb, sizeof(struct mwl8k_dma_data) - hdrlen); | ||
807 | |||
808 | tr = (struct mwl8k_dma_data *)skb->data; | ||
809 | if (wh != &tr->wh) | ||
810 | memmove(&tr->wh, wh, hdrlen); | ||
811 | |||
812 | /* Clear addr4 */ | ||
813 | memset(tr->wh.addr4, 0, IEEE80211_ADDR_LEN); | ||
814 | |||
815 | /* | ||
816 | * Firmware length is the length of the fully formed "802.11 | ||
817 | * payload". That is, everything except for the 802.11 header. | ||
818 | * This includes all crypto material including the MIC. | ||
819 | */ | ||
820 | tr->fwlen = cpu_to_le16(pktlen - hdrlen); | ||
821 | |||
822 | return skb; | ||
823 | } | ||
824 | |||
825 | |||
826 | /* | ||
827 | * Packet reception. | ||
828 | */ | ||
829 | #define MWL8K_RX_CTRL_KEY_INDEX_MASK 0x30 | ||
830 | #define MWL8K_RX_CTRL_OWNED_BY_HOST 0x02 | ||
831 | #define MWL8K_RX_CTRL_AMPDU 0x01 | ||
832 | |||
833 | struct mwl8k_rx_desc { | ||
834 | __le16 pkt_len; | ||
835 | __u8 link_quality; | ||
836 | __u8 noise_level; | ||
837 | __le32 pkt_phys_addr; | ||
838 | __le32 next_rx_desc_phys_addr; | ||
839 | __le16 qos_control; | ||
840 | __le16 rate_info; | ||
841 | __le32 pad0[4]; | ||
842 | __u8 rssi; | ||
843 | __u8 channel; | ||
844 | __le16 pad1; | ||
845 | __u8 rx_ctrl; | ||
846 | __u8 rx_status; | ||
847 | __u8 pad2[2]; | ||
848 | } __attribute__((packed)); | ||
849 | |||
850 | #define MWL8K_RX_DESCS 256 | ||
851 | #define MWL8K_RX_MAXSZ 3800 | ||
852 | |||
853 | static int mwl8k_rxq_init(struct ieee80211_hw *hw, int index) | ||
854 | { | ||
855 | struct mwl8k_priv *priv = hw->priv; | ||
856 | struct mwl8k_rx_queue *rxq = priv->rxq + index; | ||
857 | int size; | ||
858 | int i; | ||
859 | |||
860 | rxq->rx_desc_count = 0; | ||
861 | rxq->rx_head = 0; | ||
862 | rxq->rx_tail = 0; | ||
863 | |||
864 | size = MWL8K_RX_DESCS * sizeof(struct mwl8k_rx_desc); | ||
865 | |||
866 | rxq->rx_desc_area = | ||
867 | pci_alloc_consistent(priv->pdev, size, &rxq->rx_desc_dma); | ||
868 | if (rxq->rx_desc_area == NULL) { | ||
869 | printk(KERN_ERR "%s: failed to alloc RX descriptors\n", | ||
870 | priv->name); | ||
871 | return -ENOMEM; | ||
872 | } | ||
873 | memset(rxq->rx_desc_area, 0, size); | ||
874 | |||
875 | rxq->rx_skb = kmalloc(MWL8K_RX_DESCS * | ||
876 | sizeof(*rxq->rx_skb), GFP_KERNEL); | ||
877 | if (rxq->rx_skb == NULL) { | ||
878 | printk(KERN_ERR "%s: failed to alloc RX skbuff list\n", | ||
879 | priv->name); | ||
880 | pci_free_consistent(priv->pdev, size, | ||
881 | rxq->rx_desc_area, rxq->rx_desc_dma); | ||
882 | return -ENOMEM; | ||
883 | } | ||
884 | memset(rxq->rx_skb, 0, MWL8K_RX_DESCS * sizeof(*rxq->rx_skb)); | ||
885 | |||
886 | for (i = 0; i < MWL8K_RX_DESCS; i++) { | ||
887 | struct mwl8k_rx_desc *rx_desc; | ||
888 | int nexti; | ||
889 | |||
890 | rx_desc = rxq->rx_desc_area + i; | ||
891 | nexti = (i + 1) % MWL8K_RX_DESCS; | ||
892 | |||
893 | rx_desc->next_rx_desc_phys_addr = | ||
894 | cpu_to_le32(rxq->rx_desc_dma | ||
895 | + nexti * sizeof(*rx_desc)); | ||
896 | rx_desc->rx_ctrl = | ||
897 | cpu_to_le32(MWL8K_RX_CTRL_OWNED_BY_HOST); | ||
898 | } | ||
899 | |||
900 | return 0; | ||
901 | } | ||
902 | |||
903 | static int rxq_refill(struct ieee80211_hw *hw, int index, int limit) | ||
904 | { | ||
905 | struct mwl8k_priv *priv = hw->priv; | ||
906 | struct mwl8k_rx_queue *rxq = priv->rxq + index; | ||
907 | int refilled; | ||
908 | |||
909 | refilled = 0; | ||
910 | while (rxq->rx_desc_count < MWL8K_RX_DESCS && limit--) { | ||
911 | struct sk_buff *skb; | ||
912 | int rx; | ||
913 | |||
914 | skb = dev_alloc_skb(MWL8K_RX_MAXSZ); | ||
915 | if (skb == NULL) | ||
916 | break; | ||
917 | |||
918 | rxq->rx_desc_count++; | ||
919 | |||
920 | rx = rxq->rx_tail; | ||
921 | rxq->rx_tail = (rx + 1) % MWL8K_RX_DESCS; | ||
922 | |||
923 | rxq->rx_desc_area[rx].pkt_phys_addr = | ||
924 | cpu_to_le32(pci_map_single(priv->pdev, skb->data, | ||
925 | MWL8K_RX_MAXSZ, DMA_FROM_DEVICE)); | ||
926 | |||
927 | rxq->rx_desc_area[rx].pkt_len = cpu_to_le16(MWL8K_RX_MAXSZ); | ||
928 | rxq->rx_skb[rx] = skb; | ||
929 | wmb(); | ||
930 | rxq->rx_desc_area[rx].rx_ctrl = 0; | ||
931 | |||
932 | refilled++; | ||
933 | } | ||
934 | |||
935 | return refilled; | ||
936 | } | ||
937 | |||
938 | /* Must be called only when the card's reception is completely halted */ | ||
939 | static void mwl8k_rxq_deinit(struct ieee80211_hw *hw, int index) | ||
940 | { | ||
941 | struct mwl8k_priv *priv = hw->priv; | ||
942 | struct mwl8k_rx_queue *rxq = priv->rxq + index; | ||
943 | int i; | ||
944 | |||
945 | for (i = 0; i < MWL8K_RX_DESCS; i++) { | ||
946 | if (rxq->rx_skb[i] != NULL) { | ||
947 | unsigned long addr; | ||
948 | |||
949 | addr = le32_to_cpu(rxq->rx_desc_area[i].pkt_phys_addr); | ||
950 | pci_unmap_single(priv->pdev, addr, MWL8K_RX_MAXSZ, | ||
951 | PCI_DMA_FROMDEVICE); | ||
952 | kfree_skb(rxq->rx_skb[i]); | ||
953 | rxq->rx_skb[i] = NULL; | ||
954 | } | ||
955 | } | ||
956 | |||
957 | kfree(rxq->rx_skb); | ||
958 | rxq->rx_skb = NULL; | ||
959 | |||
960 | pci_free_consistent(priv->pdev, | ||
961 | MWL8K_RX_DESCS * sizeof(struct mwl8k_rx_desc), | ||
962 | rxq->rx_desc_area, rxq->rx_desc_dma); | ||
963 | rxq->rx_desc_area = NULL; | ||
964 | } | ||
965 | |||
966 | |||
967 | /* | ||
968 | * Scan a list of BSSIDs to process for finalize join. | ||
969 | * Allows for extension to process multiple BSSIDs. | ||
970 | */ | ||
971 | static inline int | ||
972 | mwl8k_capture_bssid(struct mwl8k_priv *priv, struct ieee80211_hdr *wh) | ||
973 | { | ||
974 | return priv->capture_beacon && | ||
975 | ieee80211_is_beacon(wh->frame_control) && | ||
976 | !compare_ether_addr(wh->addr3, priv->capture_bssid); | ||
977 | } | ||
978 | |||
979 | static inline void mwl8k_save_beacon(struct mwl8k_priv *priv, | ||
980 | struct sk_buff *skb) | ||
981 | { | ||
982 | priv->capture_beacon = false; | ||
983 | memset(priv->capture_bssid, 0, IEEE80211_ADDR_LEN); | ||
984 | |||
985 | /* | ||
986 | * Use GFP_ATOMIC as rxq_process is called from | ||
987 | * the primary interrupt handler, memory allocation call | ||
988 | * must not sleep. | ||
989 | */ | ||
990 | priv->beacon_skb = skb_copy(skb, GFP_ATOMIC); | ||
991 | if (priv->beacon_skb != NULL) | ||
992 | queue_work(priv->config_wq, | ||
993 | &priv->finalize_join_worker); | ||
994 | } | ||
995 | |||
996 | static int rxq_process(struct ieee80211_hw *hw, int index, int limit) | ||
997 | { | ||
998 | struct mwl8k_priv *priv = hw->priv; | ||
999 | struct mwl8k_rx_queue *rxq = priv->rxq + index; | ||
1000 | int processed; | ||
1001 | |||
1002 | processed = 0; | ||
1003 | while (rxq->rx_desc_count && limit--) { | ||
1004 | struct mwl8k_rx_desc *rx_desc; | ||
1005 | struct sk_buff *skb; | ||
1006 | struct ieee80211_rx_status status; | ||
1007 | unsigned long addr; | ||
1008 | struct ieee80211_hdr *wh; | ||
1009 | |||
1010 | rx_desc = rxq->rx_desc_area + rxq->rx_head; | ||
1011 | if (!(rx_desc->rx_ctrl & MWL8K_RX_CTRL_OWNED_BY_HOST)) | ||
1012 | break; | ||
1013 | rmb(); | ||
1014 | |||
1015 | skb = rxq->rx_skb[rxq->rx_head]; | ||
1016 | rxq->rx_skb[rxq->rx_head] = NULL; | ||
1017 | |||
1018 | rxq->rx_head = (rxq->rx_head + 1) % MWL8K_RX_DESCS; | ||
1019 | rxq->rx_desc_count--; | ||
1020 | |||
1021 | addr = le32_to_cpu(rx_desc->pkt_phys_addr); | ||
1022 | pci_unmap_single(priv->pdev, addr, | ||
1023 | MWL8K_RX_MAXSZ, PCI_DMA_FROMDEVICE); | ||
1024 | |||
1025 | skb_put(skb, le16_to_cpu(rx_desc->pkt_len)); | ||
1026 | if (mwl8k_remove_dma_header(skb)) { | ||
1027 | dev_kfree_skb(skb); | ||
1028 | continue; | ||
1029 | } | ||
1030 | |||
1031 | wh = (struct ieee80211_hdr *)skb->data; | ||
1032 | |||
1033 | /* | ||
1034 | * Check for pending join operation. save a copy of | ||
1035 | * the beacon and schedule a tasklet to send finalize | ||
1036 | * join command to the firmware. | ||
1037 | */ | ||
1038 | if (mwl8k_capture_bssid(priv, wh)) | ||
1039 | mwl8k_save_beacon(priv, skb); | ||
1040 | |||
1041 | memset(&status, 0, sizeof(status)); | ||
1042 | status.mactime = 0; | ||
1043 | status.signal = -rx_desc->rssi; | ||
1044 | status.noise = -rx_desc->noise_level; | ||
1045 | status.qual = rx_desc->link_quality; | ||
1046 | status.antenna = 1; | ||
1047 | status.rate_idx = 1; | ||
1048 | status.flag = 0; | ||
1049 | status.band = IEEE80211_BAND_2GHZ; | ||
1050 | status.freq = ieee80211_channel_to_frequency(rx_desc->channel); | ||
1051 | ieee80211_rx_irqsafe(hw, skb, &status); | ||
1052 | |||
1053 | processed++; | ||
1054 | } | ||
1055 | |||
1056 | return processed; | ||
1057 | } | ||
1058 | |||
1059 | |||
1060 | /* | ||
1061 | * Packet transmission. | ||
1062 | */ | ||
1063 | |||
1064 | /* Transmit queue assignment. */ | ||
1065 | enum { | ||
1066 | MWL8K_WME_AC_BK = 0, /* background access */ | ||
1067 | MWL8K_WME_AC_BE = 1, /* best effort access */ | ||
1068 | MWL8K_WME_AC_VI = 2, /* video access */ | ||
1069 | MWL8K_WME_AC_VO = 3, /* voice access */ | ||
1070 | }; | ||
1071 | |||
1072 | /* Transmit packet ACK policy */ | ||
1073 | #define MWL8K_TXD_ACK_POLICY_NORMAL 0 | ||
1074 | #define MWL8K_TXD_ACK_POLICY_NONE 1 | ||
1075 | #define MWL8K_TXD_ACK_POLICY_NO_EXPLICIT 2 | ||
1076 | #define MWL8K_TXD_ACK_POLICY_BLOCKACK 3 | ||
1077 | |||
1078 | #define GET_TXQ(_ac) (\ | ||
1079 | ((_ac) == WME_AC_VO) ? MWL8K_WME_AC_VO : \ | ||
1080 | ((_ac) == WME_AC_VI) ? MWL8K_WME_AC_VI : \ | ||
1081 | ((_ac) == WME_AC_BK) ? MWL8K_WME_AC_BK : \ | ||
1082 | MWL8K_WME_AC_BE) | ||
1083 | |||
1084 | #define MWL8K_TXD_STATUS_IDLE 0x00000000 | ||
1085 | #define MWL8K_TXD_STATUS_USED 0x00000001 | ||
1086 | #define MWL8K_TXD_STATUS_OK 0x00000001 | ||
1087 | #define MWL8K_TXD_STATUS_OK_RETRY 0x00000002 | ||
1088 | #define MWL8K_TXD_STATUS_OK_MORE_RETRY 0x00000004 | ||
1089 | #define MWL8K_TXD_STATUS_MULTICAST_TX 0x00000008 | ||
1090 | #define MWL8K_TXD_STATUS_BROADCAST_TX 0x00000010 | ||
1091 | #define MWL8K_TXD_STATUS_FAILED_LINK_ERROR 0x00000020 | ||
1092 | #define MWL8K_TXD_STATUS_FAILED_EXCEED_LIMIT 0x00000040 | ||
1093 | #define MWL8K_TXD_STATUS_FAILED_AGING 0x00000080 | ||
1094 | #define MWL8K_TXD_STATUS_HOST_CMD 0x40000000 | ||
1095 | #define MWL8K_TXD_STATUS_FW_OWNED 0x80000000 | ||
1096 | #define MWL8K_TXD_SOFTSTALE 0x80 | ||
1097 | #define MWL8K_TXD_SOFTSTALE_MGMT_RETRY 0x01 | ||
1098 | |||
1099 | struct mwl8k_tx_desc { | ||
1100 | __le32 status; | ||
1101 | __u8 data_rate; | ||
1102 | __u8 tx_priority; | ||
1103 | __le16 qos_control; | ||
1104 | __le32 pkt_phys_addr; | ||
1105 | __le16 pkt_len; | ||
1106 | __u8 dest_MAC_addr[IEEE80211_ADDR_LEN]; | ||
1107 | __le32 next_tx_desc_phys_addr; | ||
1108 | __le32 reserved; | ||
1109 | __le16 rate_info; | ||
1110 | __u8 peer_id; | ||
1111 | __u8 tx_frag_cnt; | ||
1112 | } __attribute__((packed)); | ||
1113 | |||
1114 | #define MWL8K_TX_DESCS 128 | ||
1115 | |||
1116 | static int mwl8k_txq_init(struct ieee80211_hw *hw, int index) | ||
1117 | { | ||
1118 | struct mwl8k_priv *priv = hw->priv; | ||
1119 | struct mwl8k_tx_queue *txq = priv->txq + index; | ||
1120 | int size; | ||
1121 | int i; | ||
1122 | |||
1123 | memset(&txq->tx_stats, 0, | ||
1124 | sizeof(struct ieee80211_tx_queue_stats)); | ||
1125 | txq->tx_stats.limit = MWL8K_TX_DESCS; | ||
1126 | txq->tx_head = 0; | ||
1127 | txq->tx_tail = 0; | ||
1128 | |||
1129 | size = MWL8K_TX_DESCS * sizeof(struct mwl8k_tx_desc); | ||
1130 | |||
1131 | txq->tx_desc_area = | ||
1132 | pci_alloc_consistent(priv->pdev, size, &txq->tx_desc_dma); | ||
1133 | if (txq->tx_desc_area == NULL) { | ||
1134 | printk(KERN_ERR "%s: failed to alloc TX descriptors\n", | ||
1135 | priv->name); | ||
1136 | return -ENOMEM; | ||
1137 | } | ||
1138 | memset(txq->tx_desc_area, 0, size); | ||
1139 | |||
1140 | txq->tx_skb = kmalloc(MWL8K_TX_DESCS * sizeof(*txq->tx_skb), | ||
1141 | GFP_KERNEL); | ||
1142 | if (txq->tx_skb == NULL) { | ||
1143 | printk(KERN_ERR "%s: failed to alloc TX skbuff list\n", | ||
1144 | priv->name); | ||
1145 | pci_free_consistent(priv->pdev, size, | ||
1146 | txq->tx_desc_area, txq->tx_desc_dma); | ||
1147 | return -ENOMEM; | ||
1148 | } | ||
1149 | memset(txq->tx_skb, 0, MWL8K_TX_DESCS * sizeof(*txq->tx_skb)); | ||
1150 | |||
1151 | for (i = 0; i < MWL8K_TX_DESCS; i++) { | ||
1152 | struct mwl8k_tx_desc *tx_desc; | ||
1153 | int nexti; | ||
1154 | |||
1155 | tx_desc = txq->tx_desc_area + i; | ||
1156 | nexti = (i + 1) % MWL8K_TX_DESCS; | ||
1157 | |||
1158 | tx_desc->status = 0; | ||
1159 | tx_desc->next_tx_desc_phys_addr = | ||
1160 | cpu_to_le32(txq->tx_desc_dma + | ||
1161 | nexti * sizeof(*tx_desc)); | ||
1162 | } | ||
1163 | |||
1164 | return 0; | ||
1165 | } | ||
1166 | |||
1167 | static inline void mwl8k_tx_start(struct mwl8k_priv *priv) | ||
1168 | { | ||
1169 | iowrite32(MWL8K_H2A_INT_PPA_READY, | ||
1170 | priv->regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); | ||
1171 | iowrite32(MWL8K_H2A_INT_DUMMY, | ||
1172 | priv->regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); | ||
1173 | ioread32(priv->regs + MWL8K_HIU_INT_CODE); | ||
1174 | } | ||
1175 | |||
1176 | static inline int mwl8k_txq_busy(struct mwl8k_priv *priv) | ||
1177 | { | ||
1178 | return priv->pending_tx_pkts; | ||
1179 | } | ||
1180 | |||
1181 | struct mwl8k_txq_info { | ||
1182 | u32 fw_owned; | ||
1183 | u32 drv_owned; | ||
1184 | u32 unused; | ||
1185 | u32 len; | ||
1186 | u32 head; | ||
1187 | u32 tail; | ||
1188 | }; | ||
1189 | |||
1190 | static int mwl8k_scan_tx_ring(struct mwl8k_priv *priv, | ||
1191 | struct mwl8k_txq_info txinfo[], | ||
1192 | u32 num_queues) | ||
1193 | { | ||
1194 | int count, desc, status; | ||
1195 | struct mwl8k_tx_queue *txq; | ||
1196 | struct mwl8k_tx_desc *tx_desc; | ||
1197 | int ndescs = 0; | ||
1198 | |||
1199 | memset(txinfo, 0, num_queues * sizeof(struct mwl8k_txq_info)); | ||
1200 | spin_lock_bh(&priv->tx_lock); | ||
1201 | for (count = 0; count < num_queues; count++) { | ||
1202 | txq = priv->txq + count; | ||
1203 | txinfo[count].len = txq->tx_stats.len; | ||
1204 | txinfo[count].head = txq->tx_head; | ||
1205 | txinfo[count].tail = txq->tx_tail; | ||
1206 | for (desc = 0; desc < MWL8K_TX_DESCS; desc++) { | ||
1207 | tx_desc = txq->tx_desc_area + desc; | ||
1208 | status = le32_to_cpu(tx_desc->status); | ||
1209 | |||
1210 | if (status & MWL8K_TXD_STATUS_FW_OWNED) | ||
1211 | txinfo[count].fw_owned++; | ||
1212 | else | ||
1213 | txinfo[count].drv_owned++; | ||
1214 | |||
1215 | if (tx_desc->pkt_len == 0) | ||
1216 | txinfo[count].unused++; | ||
1217 | } | ||
1218 | } | ||
1219 | spin_unlock_bh(&priv->tx_lock); | ||
1220 | |||
1221 | return ndescs; | ||
1222 | } | ||
1223 | |||
1224 | static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw, u32 delay_ms) | ||
1225 | { | ||
1226 | u32 count = 0; | ||
1227 | unsigned long timeout = 0; | ||
1228 | struct mwl8k_priv *priv = hw->priv; | ||
1229 | DECLARE_COMPLETION_ONSTACK(cmd_wait); | ||
1230 | |||
1231 | might_sleep(); | ||
1232 | |||
1233 | if (priv->tx_wait != NULL) | ||
1234 | printk(KERN_ERR "WARNING Previous TXWaitEmpty instance\n"); | ||
1235 | |||
1236 | spin_lock_bh(&priv->tx_lock); | ||
1237 | count = mwl8k_txq_busy(priv); | ||
1238 | if (count) { | ||
1239 | priv->tx_wait = &cmd_wait; | ||
1240 | if (priv->radio_state) | ||
1241 | mwl8k_tx_start(priv); | ||
1242 | } | ||
1243 | spin_unlock_bh(&priv->tx_lock); | ||
1244 | |||
1245 | if (count) { | ||
1246 | struct mwl8k_txq_info txinfo[4]; | ||
1247 | int index; | ||
1248 | int newcount; | ||
1249 | |||
1250 | timeout = wait_for_completion_timeout(&cmd_wait, | ||
1251 | msecs_to_jiffies(delay_ms)); | ||
1252 | if (timeout) | ||
1253 | return 0; | ||
1254 | |||
1255 | spin_lock_bh(&priv->tx_lock); | ||
1256 | priv->tx_wait = NULL; | ||
1257 | newcount = mwl8k_txq_busy(priv); | ||
1258 | spin_unlock_bh(&priv->tx_lock); | ||
1259 | |||
1260 | printk(KERN_ERR "%s(%u) TIMEDOUT:%ums Pend:%u-->%u\n", | ||
1261 | __func__, __LINE__, delay_ms, count, newcount); | ||
1262 | |||
1263 | mwl8k_scan_tx_ring(priv, txinfo, 4); | ||
1264 | for (index = 0 ; index < 4; index++) | ||
1265 | printk(KERN_ERR | ||
1266 | "TXQ:%u L:%u H:%u T:%u FW:%u DRV:%u U:%u\n", | ||
1267 | index, | ||
1268 | txinfo[index].len, | ||
1269 | txinfo[index].head, | ||
1270 | txinfo[index].tail, | ||
1271 | txinfo[index].fw_owned, | ||
1272 | txinfo[index].drv_owned, | ||
1273 | txinfo[index].unused); | ||
1274 | return -ETIMEDOUT; | ||
1275 | } | ||
1276 | |||
1277 | return 0; | ||
1278 | } | ||
1279 | |||
1280 | #define MWL8K_TXD_OK (MWL8K_TXD_STATUS_OK | \ | ||
1281 | MWL8K_TXD_STATUS_OK_RETRY | \ | ||
1282 | MWL8K_TXD_STATUS_OK_MORE_RETRY) | ||
1283 | #define MWL8K_TXD_SUCCESS(stat) ((stat) & MWL8K_TXD_OK) | ||
1284 | #define MWL8K_TXD_FAIL_RETRY(stat) \ | ||
1285 | ((stat) & (MWL8K_TXD_STATUS_FAILED_EXCEED_LIMIT)) | ||
1286 | |||
1287 | static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force) | ||
1288 | { | ||
1289 | struct mwl8k_priv *priv = hw->priv; | ||
1290 | struct mwl8k_tx_queue *txq = priv->txq + index; | ||
1291 | int wake = 0; | ||
1292 | |||
1293 | while (txq->tx_stats.len > 0) { | ||
1294 | int tx; | ||
1295 | int rc; | ||
1296 | struct mwl8k_tx_desc *tx_desc; | ||
1297 | unsigned long addr; | ||
1298 | size_t size; | ||
1299 | struct sk_buff *skb; | ||
1300 | struct ieee80211_tx_info *info; | ||
1301 | u32 status; | ||
1302 | |||
1303 | rc = 0; | ||
1304 | tx = txq->tx_head; | ||
1305 | tx_desc = txq->tx_desc_area + tx; | ||
1306 | |||
1307 | status = le32_to_cpu(tx_desc->status); | ||
1308 | |||
1309 | if (status & MWL8K_TXD_STATUS_FW_OWNED) { | ||
1310 | if (!force) | ||
1311 | break; | ||
1312 | tx_desc->status &= | ||
1313 | ~cpu_to_le32(MWL8K_TXD_STATUS_FW_OWNED); | ||
1314 | } | ||
1315 | |||
1316 | txq->tx_head = (tx + 1) % MWL8K_TX_DESCS; | ||
1317 | BUG_ON(txq->tx_stats.len == 0); | ||
1318 | txq->tx_stats.len--; | ||
1319 | priv->pending_tx_pkts--; | ||
1320 | |||
1321 | addr = le32_to_cpu(tx_desc->pkt_phys_addr); | ||
1322 | size = (u32)(le16_to_cpu(tx_desc->pkt_len)); | ||
1323 | skb = txq->tx_skb[tx].skb; | ||
1324 | txq->tx_skb[tx].skb = NULL; | ||
1325 | |||
1326 | BUG_ON(skb == NULL); | ||
1327 | pci_unmap_single(priv->pdev, addr, size, PCI_DMA_TODEVICE); | ||
1328 | |||
1329 | rc = mwl8k_remove_dma_header(skb); | ||
1330 | |||
1331 | /* Mark descriptor as unused */ | ||
1332 | tx_desc->pkt_phys_addr = 0; | ||
1333 | tx_desc->pkt_len = 0; | ||
1334 | |||
1335 | if (txq->tx_skb[tx].clone) { | ||
1336 | /* Replace with original skb | ||
1337 | * before returning to stack | ||
1338 | * as buffer has been cloned | ||
1339 | */ | ||
1340 | dev_kfree_skb(skb); | ||
1341 | skb = txq->tx_skb[tx].clone; | ||
1342 | txq->tx_skb[tx].clone = NULL; | ||
1343 | } | ||
1344 | |||
1345 | if (rc) { | ||
1346 | /* Something has gone wrong here. | ||
1347 | * Failed to remove DMA header. | ||
1348 | * Print error message and drop packet. | ||
1349 | */ | ||
1350 | printk(KERN_ERR "%s: Error removing DMA header from " | ||
1351 | "tx skb 0x%p.\n", priv->name, skb); | ||
1352 | |||
1353 | dev_kfree_skb(skb); | ||
1354 | continue; | ||
1355 | } | ||
1356 | |||
1357 | info = IEEE80211_SKB_CB(skb); | ||
1358 | ieee80211_tx_info_clear_status(info); | ||
1359 | |||
1360 | /* Convert firmware status stuff into tx_status */ | ||
1361 | if (MWL8K_TXD_SUCCESS(status)) { | ||
1362 | /* Transmit OK */ | ||
1363 | info->flags |= IEEE80211_TX_STAT_ACK; | ||
1364 | } | ||
1365 | |||
1366 | ieee80211_tx_status_irqsafe(hw, skb); | ||
1367 | |||
1368 | wake = !priv->inconfig && priv->radio_state; | ||
1369 | } | ||
1370 | |||
1371 | if (wake) | ||
1372 | ieee80211_wake_queue(hw, index); | ||
1373 | } | ||
1374 | |||
1375 | /* must be called only when the card's transmit is completely halted */ | ||
1376 | static void mwl8k_txq_deinit(struct ieee80211_hw *hw, int index) | ||
1377 | { | ||
1378 | struct mwl8k_priv *priv = hw->priv; | ||
1379 | struct mwl8k_tx_queue *txq = priv->txq + index; | ||
1380 | |||
1381 | mwl8k_txq_reclaim(hw, index, 1); | ||
1382 | |||
1383 | kfree(txq->tx_skb); | ||
1384 | txq->tx_skb = NULL; | ||
1385 | |||
1386 | pci_free_consistent(priv->pdev, | ||
1387 | MWL8K_TX_DESCS * sizeof(struct mwl8k_tx_desc), | ||
1388 | txq->tx_desc_area, txq->tx_desc_dma); | ||
1389 | txq->tx_desc_area = NULL; | ||
1390 | } | ||
1391 | |||
1392 | static int | ||
1393 | mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) | ||
1394 | { | ||
1395 | struct mwl8k_priv *priv = hw->priv; | ||
1396 | struct ieee80211_tx_info *tx_info; | ||
1397 | struct ieee80211_hdr *wh; | ||
1398 | struct mwl8k_tx_queue *txq; | ||
1399 | struct mwl8k_tx_desc *tx; | ||
1400 | struct mwl8k_dma_data *tr; | ||
1401 | struct mwl8k_vif *mwl8k_vif; | ||
1402 | struct sk_buff *org_skb = skb; | ||
1403 | dma_addr_t dma; | ||
1404 | u16 qos = 0; | ||
1405 | bool qosframe = false, ampduframe = false; | ||
1406 | bool mcframe = false, eapolframe = false; | ||
1407 | bool amsduframe = false; | ||
1408 | __le16 fc; | ||
1409 | |||
1410 | txq = priv->txq + index; | ||
1411 | tx = txq->tx_desc_area + txq->tx_tail; | ||
1412 | |||
1413 | BUG_ON(txq->tx_skb[txq->tx_tail].skb != NULL); | ||
1414 | |||
1415 | /* | ||
1416 | * Append HW DMA header to start of packet. Drop packet if | ||
1417 | * there is not enough space or a failure to unshare/unclone | ||
1418 | * the skb. | ||
1419 | */ | ||
1420 | skb = mwl8k_add_dma_header(skb); | ||
1421 | |||
1422 | if (skb == NULL) { | ||
1423 | printk(KERN_DEBUG "%s: failed to prepend HW DMA " | ||
1424 | "header, dropping TX frame.\n", priv->name); | ||
1425 | dev_kfree_skb(org_skb); | ||
1426 | return NETDEV_TX_OK; | ||
1427 | } | ||
1428 | |||
1429 | tx_info = IEEE80211_SKB_CB(skb); | ||
1430 | mwl8k_vif = MWL8K_VIF(tx_info->control.vif); | ||
1431 | tr = (struct mwl8k_dma_data *)skb->data; | ||
1432 | wh = &tr->wh; | ||
1433 | fc = wh->frame_control; | ||
1434 | qosframe = ieee80211_is_data_qos(fc); | ||
1435 | mcframe = is_multicast_ether_addr(wh->addr1); | ||
1436 | ampduframe = !!(tx_info->flags & IEEE80211_TX_CTL_AMPDU); | ||
1437 | |||
1438 | if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { | ||
1439 | u16 seqno = mwl8k_vif->seqno; | ||
1440 | wh->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); | ||
1441 | wh->seq_ctrl |= cpu_to_le16(seqno << 4); | ||
1442 | mwl8k_vif->seqno = seqno++ % 4096; | ||
1443 | } | ||
1444 | |||
1445 | if (qosframe) | ||
1446 | qos = le16_to_cpu(*((__le16 *)ieee80211_get_qos_ctl(wh))); | ||
1447 | |||
1448 | dma = pci_map_single(priv->pdev, skb->data, | ||
1449 | skb->len, PCI_DMA_TODEVICE); | ||
1450 | |||
1451 | if (pci_dma_mapping_error(priv->pdev, dma)) { | ||
1452 | printk(KERN_DEBUG "%s: failed to dma map skb, " | ||
1453 | "dropping TX frame.\n", priv->name); | ||
1454 | |||
1455 | if (org_skb != NULL) | ||
1456 | dev_kfree_skb(org_skb); | ||
1457 | if (skb != NULL) | ||
1458 | dev_kfree_skb(skb); | ||
1459 | return NETDEV_TX_OK; | ||
1460 | } | ||
1461 | |||
1462 | /* Set desc header, cpu bit order. */ | ||
1463 | tx->status = 0; | ||
1464 | tx->data_rate = 0; | ||
1465 | tx->tx_priority = index; | ||
1466 | tx->qos_control = 0; | ||
1467 | tx->rate_info = 0; | ||
1468 | tx->peer_id = mwl8k_vif->peer_id; | ||
1469 | |||
1470 | amsduframe = !!(qos & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT); | ||
1471 | |||
1472 | /* Setup firmware control bit fields for each frame type. */ | ||
1473 | if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) { | ||
1474 | tx->data_rate = 0; | ||
1475 | qos = mwl8k_qos_setbit_eosp(qos); | ||
1476 | /* Set Queue size to unspecified */ | ||
1477 | qos = mwl8k_qos_setbit_qlen(qos, 0xff); | ||
1478 | } else if (ieee80211_is_data(fc)) { | ||
1479 | tx->data_rate = 1; | ||
1480 | if (mcframe) | ||
1481 | tx->status |= MWL8K_TXD_STATUS_MULTICAST_TX; | ||
1482 | |||
1483 | /* | ||
1484 | * Tell firmware to not send EAPOL pkts in an | ||
1485 | * aggregate. Verify against mac80211 tx path. If | ||
1486 | * stack turns off AMPDU for an EAPOL frame this | ||
1487 | * check will be removed. | ||
1488 | */ | ||
1489 | if (eapolframe) { | ||
1490 | qos = mwl8k_qos_setbit_ack(qos, | ||
1491 | MWL8K_TXD_ACK_POLICY_NORMAL); | ||
1492 | } else { | ||
1493 | /* Send pkt in an aggregate if AMPDU frame. */ | ||
1494 | if (ampduframe) | ||
1495 | qos = mwl8k_qos_setbit_ack(qos, | ||
1496 | MWL8K_TXD_ACK_POLICY_BLOCKACK); | ||
1497 | else | ||
1498 | qos = mwl8k_qos_setbit_ack(qos, | ||
1499 | MWL8K_TXD_ACK_POLICY_NORMAL); | ||
1500 | |||
1501 | if (amsduframe) | ||
1502 | qos = mwl8k_qos_setbit_amsdu(qos); | ||
1503 | } | ||
1504 | } | ||
1505 | |||
1506 | /* Convert to little endian */ | ||
1507 | tx->qos_control = cpu_to_le16(qos); | ||
1508 | tx->status = cpu_to_le32(tx->status); | ||
1509 | tx->pkt_phys_addr = cpu_to_le32(dma); | ||
1510 | tx->pkt_len = cpu_to_le16(skb->len); | ||
1511 | |||
1512 | txq->tx_skb[txq->tx_tail].skb = skb; | ||
1513 | txq->tx_skb[txq->tx_tail].clone = | ||
1514 | skb == org_skb ? NULL : org_skb; | ||
1515 | |||
1516 | spin_lock_bh(&priv->tx_lock); | ||
1517 | |||
1518 | tx->status = cpu_to_le32(MWL8K_TXD_STATUS_OK | | ||
1519 | MWL8K_TXD_STATUS_FW_OWNED); | ||
1520 | wmb(); | ||
1521 | txq->tx_stats.len++; | ||
1522 | priv->pending_tx_pkts++; | ||
1523 | txq->tx_stats.count++; | ||
1524 | txq->tx_tail++; | ||
1525 | |||
1526 | if (txq->tx_tail == MWL8K_TX_DESCS) | ||
1527 | txq->tx_tail = 0; | ||
1528 | if (txq->tx_head == txq->tx_tail) | ||
1529 | ieee80211_stop_queue(hw, index); | ||
1530 | |||
1531 | if (priv->inconfig) { | ||
1532 | /* | ||
1533 | * Silently queue packet when we are in the middle of | ||
1534 | * a config cycle. Notify firmware only if we are | ||
1535 | * waiting for TXQs to empty. If a packet is sent | ||
1536 | * before .config() is complete, perhaps it is better | ||
1537 | * to drop the packet, as the channel is being changed | ||
1538 | * and the packet will end up on the wrong channel. | ||
1539 | */ | ||
1540 | printk(KERN_ERR "%s(): WARNING TX activity while " | ||
1541 | "in config\n", __func__); | ||
1542 | |||
1543 | if (priv->tx_wait != NULL) | ||
1544 | mwl8k_tx_start(priv); | ||
1545 | } else | ||
1546 | mwl8k_tx_start(priv); | ||
1547 | |||
1548 | spin_unlock_bh(&priv->tx_lock); | ||
1549 | |||
1550 | return NETDEV_TX_OK; | ||
1551 | } | ||
1552 | |||
1553 | |||
1554 | /* | ||
1555 | * Command processing. | ||
1556 | */ | ||
1557 | |||
1558 | /* Timeout firmware commands after 2000ms */ | ||
1559 | #define MWL8K_CMD_TIMEOUT_MS 2000 | ||
1560 | |||
1561 | static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd) | ||
1562 | { | ||
1563 | DECLARE_COMPLETION_ONSTACK(cmd_wait); | ||
1564 | struct mwl8k_priv *priv = hw->priv; | ||
1565 | void __iomem *regs = priv->regs; | ||
1566 | dma_addr_t dma_addr; | ||
1567 | unsigned int dma_size; | ||
1568 | int rc; | ||
1569 | u16 __iomem *result; | ||
1570 | unsigned long timeout = 0; | ||
1571 | u8 buf[32]; | ||
1572 | |||
1573 | cmd->result = 0xFFFF; | ||
1574 | dma_size = le16_to_cpu(cmd->length); | ||
1575 | dma_addr = pci_map_single(priv->pdev, cmd, dma_size, | ||
1576 | PCI_DMA_BIDIRECTIONAL); | ||
1577 | if (pci_dma_mapping_error(priv->pdev, dma_addr)) | ||
1578 | return -ENOMEM; | ||
1579 | |||
1580 | if (priv->hostcmd_wait != NULL) | ||
1581 | printk(KERN_ERR "WARNING host command in progress\n"); | ||
1582 | |||
1583 | spin_lock_irq(&priv->fw_lock); | ||
1584 | priv->hostcmd_wait = &cmd_wait; | ||
1585 | iowrite32(dma_addr, regs + MWL8K_HIU_GEN_PTR); | ||
1586 | iowrite32(MWL8K_H2A_INT_DOORBELL, | ||
1587 | regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); | ||
1588 | iowrite32(MWL8K_H2A_INT_DUMMY, | ||
1589 | regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); | ||
1590 | spin_unlock_irq(&priv->fw_lock); | ||
1591 | |||
1592 | timeout = wait_for_completion_timeout(&cmd_wait, | ||
1593 | msecs_to_jiffies(MWL8K_CMD_TIMEOUT_MS)); | ||
1594 | |||
1595 | result = &cmd->result; | ||
1596 | if (!timeout) { | ||
1597 | spin_lock_irq(&priv->fw_lock); | ||
1598 | priv->hostcmd_wait = NULL; | ||
1599 | spin_unlock_irq(&priv->fw_lock); | ||
1600 | printk(KERN_ERR "%s: Command %s timeout after %u ms\n", | ||
1601 | priv->name, | ||
1602 | mwl8k_cmd_name(cmd->code, buf, sizeof(buf)), | ||
1603 | MWL8K_CMD_TIMEOUT_MS); | ||
1604 | rc = -ETIMEDOUT; | ||
1605 | } else { | ||
1606 | rc = *result ? -EINVAL : 0; | ||
1607 | if (rc) | ||
1608 | printk(KERN_ERR "%s: Command %s error 0x%x\n", | ||
1609 | priv->name, | ||
1610 | mwl8k_cmd_name(cmd->code, buf, sizeof(buf)), | ||
1611 | *result); | ||
1612 | } | ||
1613 | |||
1614 | pci_unmap_single(priv->pdev, dma_addr, dma_size, | ||
1615 | PCI_DMA_BIDIRECTIONAL); | ||
1616 | return rc; | ||
1617 | } | ||
1618 | |||
1619 | /* | ||
1620 | * GET_HW_SPEC. | ||
1621 | */ | ||
1622 | struct mwl8k_cmd_get_hw_spec { | ||
1623 | struct mwl8k_cmd_pkt header; | ||
1624 | __u8 hw_rev; | ||
1625 | __u8 host_interface; | ||
1626 | __le16 num_mcaddrs; | ||
1627 | __u8 perm_addr[IEEE80211_ADDR_LEN]; | ||
1628 | __le16 region_code; | ||
1629 | __le32 fw_rev; | ||
1630 | __le32 ps_cookie; | ||
1631 | __le32 caps; | ||
1632 | __u8 mcs_bitmap[16]; | ||
1633 | __le32 rx_queue_ptr; | ||
1634 | __le32 num_tx_queues; | ||
1635 | __le32 tx_queue_ptrs[MWL8K_TX_QUEUES]; | ||
1636 | __le32 caps2; | ||
1637 | __le32 num_tx_desc_per_queue; | ||
1638 | __le32 total_rx_desc; | ||
1639 | } __attribute__((packed)); | ||
1640 | |||
1641 | static int mwl8k_cmd_get_hw_spec(struct ieee80211_hw *hw) | ||
1642 | { | ||
1643 | struct mwl8k_priv *priv = hw->priv; | ||
1644 | struct mwl8k_cmd_get_hw_spec *cmd; | ||
1645 | int rc; | ||
1646 | int i; | ||
1647 | |||
1648 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
1649 | if (cmd == NULL) | ||
1650 | return -ENOMEM; | ||
1651 | |||
1652 | cmd->header.code = cpu_to_le16(MWL8K_CMD_GET_HW_SPEC); | ||
1653 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
1654 | |||
1655 | memset(cmd->perm_addr, 0xff, sizeof(cmd->perm_addr)); | ||
1656 | cmd->ps_cookie = cpu_to_le32(priv->cookie_dma); | ||
1657 | cmd->rx_queue_ptr = cpu_to_le32(priv->rxq[0].rx_desc_dma); | ||
1658 | cmd->num_tx_queues = MWL8K_TX_QUEUES; | ||
1659 | for (i = 0; i < MWL8K_TX_QUEUES; i++) | ||
1660 | cmd->tx_queue_ptrs[i] = cpu_to_le32(priv->txq[i].tx_desc_dma); | ||
1661 | cmd->num_tx_desc_per_queue = MWL8K_TX_DESCS; | ||
1662 | cmd->total_rx_desc = MWL8K_RX_DESCS; | ||
1663 | |||
1664 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
1665 | |||
1666 | if (!rc) { | ||
1667 | SET_IEEE80211_PERM_ADDR(hw, cmd->perm_addr); | ||
1668 | priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs); | ||
1669 | priv->fw_rev = cmd->fw_rev; | ||
1670 | priv->hw_rev = cmd->hw_rev; | ||
1671 | priv->region_code = le16_to_cpu(cmd->region_code); | ||
1672 | } | ||
1673 | |||
1674 | kfree(cmd); | ||
1675 | return rc; | ||
1676 | } | ||
1677 | |||
1678 | /* | ||
1679 | * CMD_MAC_MULTICAST_ADR. | ||
1680 | */ | ||
1681 | struct mwl8k_cmd_mac_multicast_adr { | ||
1682 | struct mwl8k_cmd_pkt header; | ||
1683 | __le16 action; | ||
1684 | __le16 numaddr; | ||
1685 | __u8 addr[1][IEEE80211_ADDR_LEN]; | ||
1686 | }; | ||
1687 | |||
1688 | #define MWL8K_ENABLE_RX_MULTICAST 0x000F | ||
1689 | static int mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw, | ||
1690 | int mc_count, | ||
1691 | struct dev_addr_list *mclist) | ||
1692 | { | ||
1693 | struct mwl8k_cmd_mac_multicast_adr *cmd; | ||
1694 | int index = 0; | ||
1695 | int rc; | ||
1696 | int size = sizeof(*cmd) + ((mc_count - 1) * IEEE80211_ADDR_LEN); | ||
1697 | cmd = kzalloc(size, GFP_KERNEL); | ||
1698 | if (cmd == NULL) | ||
1699 | return -ENOMEM; | ||
1700 | |||
1701 | cmd->header.code = cpu_to_le16(MWL8K_CMD_MAC_MULTICAST_ADR); | ||
1702 | cmd->header.length = cpu_to_le16(size); | ||
1703 | cmd->action = cpu_to_le16(MWL8K_ENABLE_RX_MULTICAST); | ||
1704 | cmd->numaddr = cpu_to_le16(mc_count); | ||
1705 | while ((index < mc_count) && mclist) { | ||
1706 | if (mclist->da_addrlen != IEEE80211_ADDR_LEN) { | ||
1707 | rc = -EINVAL; | ||
1708 | goto mwl8k_cmd_mac_multicast_adr_exit; | ||
1709 | } | ||
1710 | memcpy(cmd->addr[index], mclist->da_addr, IEEE80211_ADDR_LEN); | ||
1711 | index++; | ||
1712 | mclist = mclist->next; | ||
1713 | } | ||
1714 | |||
1715 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
1716 | |||
1717 | mwl8k_cmd_mac_multicast_adr_exit: | ||
1718 | kfree(cmd); | ||
1719 | return rc; | ||
1720 | } | ||
1721 | |||
1722 | /* | ||
1723 | * CMD_802_11_GET_STAT. | ||
1724 | */ | ||
1725 | struct mwl8k_cmd_802_11_get_stat { | ||
1726 | struct mwl8k_cmd_pkt header; | ||
1727 | __le16 action; | ||
1728 | __le32 stats[64]; | ||
1729 | } __attribute__((packed)); | ||
1730 | |||
1731 | #define MWL8K_STAT_ACK_FAILURE 9 | ||
1732 | #define MWL8K_STAT_RTS_FAILURE 12 | ||
1733 | #define MWL8K_STAT_FCS_ERROR 24 | ||
1734 | #define MWL8K_STAT_RTS_SUCCESS 11 | ||
1735 | |||
1736 | static int mwl8k_cmd_802_11_get_stat(struct ieee80211_hw *hw, | ||
1737 | struct ieee80211_low_level_stats *stats) | ||
1738 | { | ||
1739 | struct mwl8k_cmd_802_11_get_stat *cmd; | ||
1740 | int rc; | ||
1741 | |||
1742 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
1743 | if (cmd == NULL) | ||
1744 | return -ENOMEM; | ||
1745 | |||
1746 | cmd->header.code = cpu_to_le16(MWL8K_CMD_GET_STAT); | ||
1747 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
1748 | cmd->action = cpu_to_le16(MWL8K_CMD_GET); | ||
1749 | |||
1750 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
1751 | if (!rc) { | ||
1752 | stats->dot11ACKFailureCount = | ||
1753 | le32_to_cpu(cmd->stats[MWL8K_STAT_ACK_FAILURE]); | ||
1754 | stats->dot11RTSFailureCount = | ||
1755 | le32_to_cpu(cmd->stats[MWL8K_STAT_RTS_FAILURE]); | ||
1756 | stats->dot11FCSErrorCount = | ||
1757 | le32_to_cpu(cmd->stats[MWL8K_STAT_FCS_ERROR]); | ||
1758 | stats->dot11RTSSuccessCount = | ||
1759 | le32_to_cpu(cmd->stats[MWL8K_STAT_RTS_SUCCESS]); | ||
1760 | } | ||
1761 | kfree(cmd); | ||
1762 | |||
1763 | return rc; | ||
1764 | } | ||
1765 | |||
1766 | /* | ||
1767 | * CMD_802_11_RADIO_CONTROL. | ||
1768 | */ | ||
1769 | struct mwl8k_cmd_802_11_radio_control { | ||
1770 | struct mwl8k_cmd_pkt header; | ||
1771 | __le16 action; | ||
1772 | __le16 control; | ||
1773 | __le16 radio_on; | ||
1774 | } __attribute__((packed)); | ||
1775 | |||
1776 | static int mwl8k_cmd_802_11_radio_control(struct ieee80211_hw *hw, int enable) | ||
1777 | { | ||
1778 | struct mwl8k_priv *priv = hw->priv; | ||
1779 | struct mwl8k_cmd_802_11_radio_control *cmd; | ||
1780 | int rc; | ||
1781 | |||
1782 | if (((enable & MWL8K_RADIO_ENABLE) == priv->radio_state) && | ||
1783 | !(enable & MWL8K_RADIO_FORCE)) | ||
1784 | return 0; | ||
1785 | |||
1786 | enable &= MWL8K_RADIO_ENABLE; | ||
1787 | |||
1788 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
1789 | if (cmd == NULL) | ||
1790 | return -ENOMEM; | ||
1791 | |||
1792 | cmd->header.code = cpu_to_le16(MWL8K_CMD_RADIO_CONTROL); | ||
1793 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
1794 | cmd->action = cpu_to_le16(MWL8K_CMD_SET); | ||
1795 | cmd->control = cpu_to_le16(priv->radio_preamble); | ||
1796 | cmd->radio_on = cpu_to_le16(enable ? 0x0001 : 0x0000); | ||
1797 | |||
1798 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
1799 | kfree(cmd); | ||
1800 | |||
1801 | if (!rc) | ||
1802 | priv->radio_state = enable; | ||
1803 | |||
1804 | return rc; | ||
1805 | } | ||
1806 | |||
1807 | static int | ||
1808 | mwl8k_set_radio_preamble(struct ieee80211_hw *hw, bool short_preamble) | ||
1809 | { | ||
1810 | struct mwl8k_priv *priv; | ||
1811 | |||
1812 | if (hw == NULL || hw->priv == NULL) | ||
1813 | return -EINVAL; | ||
1814 | priv = hw->priv; | ||
1815 | |||
1816 | priv->radio_preamble = (short_preamble ? | ||
1817 | MWL8K_RADIO_SHORT_PREAMBLE : | ||
1818 | MWL8K_RADIO_LONG_PREAMBLE); | ||
1819 | |||
1820 | return mwl8k_cmd_802_11_radio_control(hw, | ||
1821 | MWL8K_RADIO_ENABLE | MWL8K_RADIO_FORCE); | ||
1822 | } | ||
1823 | |||
1824 | /* | ||
1825 | * CMD_802_11_RF_TX_POWER. | ||
1826 | */ | ||
1827 | #define MWL8K_TX_POWER_LEVEL_TOTAL 8 | ||
1828 | |||
1829 | struct mwl8k_cmd_802_11_rf_tx_power { | ||
1830 | struct mwl8k_cmd_pkt header; | ||
1831 | __le16 action; | ||
1832 | __le16 support_level; | ||
1833 | __le16 current_level; | ||
1834 | __le16 reserved; | ||
1835 | __le16 power_level_list[MWL8K_TX_POWER_LEVEL_TOTAL]; | ||
1836 | } __attribute__((packed)); | ||
1837 | |||
1838 | static int mwl8k_cmd_802_11_rf_tx_power(struct ieee80211_hw *hw, int dBm) | ||
1839 | { | ||
1840 | struct mwl8k_cmd_802_11_rf_tx_power *cmd; | ||
1841 | int rc; | ||
1842 | |||
1843 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
1844 | if (cmd == NULL) | ||
1845 | return -ENOMEM; | ||
1846 | |||
1847 | cmd->header.code = cpu_to_le16(MWL8K_CMD_RF_TX_POWER); | ||
1848 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
1849 | cmd->action = cpu_to_le16(MWL8K_CMD_SET); | ||
1850 | cmd->support_level = cpu_to_le16(dBm); | ||
1851 | |||
1852 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
1853 | kfree(cmd); | ||
1854 | |||
1855 | return rc; | ||
1856 | } | ||
1857 | |||
1858 | /* | ||
1859 | * CMD_SET_PRE_SCAN. | ||
1860 | */ | ||
1861 | struct mwl8k_cmd_set_pre_scan { | ||
1862 | struct mwl8k_cmd_pkt header; | ||
1863 | } __attribute__((packed)); | ||
1864 | |||
1865 | static int mwl8k_cmd_set_pre_scan(struct ieee80211_hw *hw) | ||
1866 | { | ||
1867 | struct mwl8k_cmd_set_pre_scan *cmd; | ||
1868 | int rc; | ||
1869 | |||
1870 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
1871 | if (cmd == NULL) | ||
1872 | return -ENOMEM; | ||
1873 | |||
1874 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_PRE_SCAN); | ||
1875 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
1876 | |||
1877 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
1878 | kfree(cmd); | ||
1879 | |||
1880 | return rc; | ||
1881 | } | ||
1882 | |||
1883 | /* | ||
1884 | * CMD_SET_POST_SCAN. | ||
1885 | */ | ||
1886 | struct mwl8k_cmd_set_post_scan { | ||
1887 | struct mwl8k_cmd_pkt header; | ||
1888 | __le32 isibss; | ||
1889 | __u8 bssid[IEEE80211_ADDR_LEN]; | ||
1890 | } __attribute__((packed)); | ||
1891 | |||
1892 | static int | ||
1893 | mwl8k_cmd_set_post_scan(struct ieee80211_hw *hw, __u8 mac[IEEE80211_ADDR_LEN]) | ||
1894 | { | ||
1895 | struct mwl8k_cmd_set_post_scan *cmd; | ||
1896 | int rc; | ||
1897 | |||
1898 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
1899 | if (cmd == NULL) | ||
1900 | return -ENOMEM; | ||
1901 | |||
1902 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_POST_SCAN); | ||
1903 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
1904 | cmd->isibss = 0; | ||
1905 | memcpy(cmd->bssid, mac, IEEE80211_ADDR_LEN); | ||
1906 | |||
1907 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
1908 | kfree(cmd); | ||
1909 | |||
1910 | return rc; | ||
1911 | } | ||
1912 | |||
1913 | /* | ||
1914 | * CMD_SET_RF_CHANNEL. | ||
1915 | */ | ||
1916 | struct mwl8k_cmd_set_rf_channel { | ||
1917 | struct mwl8k_cmd_pkt header; | ||
1918 | __le16 action; | ||
1919 | __u8 current_channel; | ||
1920 | __le32 channel_flags; | ||
1921 | } __attribute__((packed)); | ||
1922 | |||
1923 | static int mwl8k_cmd_set_rf_channel(struct ieee80211_hw *hw, | ||
1924 | struct ieee80211_channel *channel) | ||
1925 | { | ||
1926 | struct mwl8k_cmd_set_rf_channel *cmd; | ||
1927 | int rc; | ||
1928 | |||
1929 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
1930 | if (cmd == NULL) | ||
1931 | return -ENOMEM; | ||
1932 | |||
1933 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RF_CHANNEL); | ||
1934 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
1935 | cmd->action = cpu_to_le16(MWL8K_CMD_SET); | ||
1936 | cmd->current_channel = channel->hw_value; | ||
1937 | if (channel->band == IEEE80211_BAND_2GHZ) | ||
1938 | cmd->channel_flags = cpu_to_le32(0x00000081); | ||
1939 | else | ||
1940 | cmd->channel_flags = cpu_to_le32(0x00000000); | ||
1941 | |||
1942 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
1943 | kfree(cmd); | ||
1944 | |||
1945 | return rc; | ||
1946 | } | ||
1947 | |||
1948 | /* | ||
1949 | * CMD_SET_SLOT. | ||
1950 | */ | ||
1951 | struct mwl8k_cmd_set_slot { | ||
1952 | struct mwl8k_cmd_pkt header; | ||
1953 | __le16 action; | ||
1954 | __u8 short_slot; | ||
1955 | } __attribute__((packed)); | ||
1956 | |||
1957 | static int mwl8k_cmd_set_slot(struct ieee80211_hw *hw, int slot_time) | ||
1958 | { | ||
1959 | struct mwl8k_cmd_set_slot *cmd; | ||
1960 | int rc; | ||
1961 | |||
1962 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
1963 | if (cmd == NULL) | ||
1964 | return -ENOMEM; | ||
1965 | |||
1966 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_SLOT); | ||
1967 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
1968 | cmd->action = cpu_to_le16(MWL8K_CMD_SET); | ||
1969 | cmd->short_slot = slot_time == MWL8K_SHORT_SLOTTIME ? 1 : 0; | ||
1970 | |||
1971 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
1972 | kfree(cmd); | ||
1973 | |||
1974 | return rc; | ||
1975 | } | ||
1976 | |||
1977 | /* | ||
1978 | * CMD_MIMO_CONFIG. | ||
1979 | */ | ||
1980 | struct mwl8k_cmd_mimo_config { | ||
1981 | struct mwl8k_cmd_pkt header; | ||
1982 | __le32 action; | ||
1983 | __u8 rx_antenna_map; | ||
1984 | __u8 tx_antenna_map; | ||
1985 | } __attribute__((packed)); | ||
1986 | |||
1987 | static int mwl8k_cmd_mimo_config(struct ieee80211_hw *hw, __u8 rx, __u8 tx) | ||
1988 | { | ||
1989 | struct mwl8k_cmd_mimo_config *cmd; | ||
1990 | int rc; | ||
1991 | |||
1992 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
1993 | if (cmd == NULL) | ||
1994 | return -ENOMEM; | ||
1995 | |||
1996 | cmd->header.code = cpu_to_le16(MWL8K_CMD_MIMO_CONFIG); | ||
1997 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
1998 | cmd->action = cpu_to_le32((u32)MWL8K_CMD_SET); | ||
1999 | cmd->rx_antenna_map = rx; | ||
2000 | cmd->tx_antenna_map = tx; | ||
2001 | |||
2002 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
2003 | kfree(cmd); | ||
2004 | |||
2005 | return rc; | ||
2006 | } | ||
2007 | |||
2008 | /* | ||
2009 | * CMD_ENABLE_SNIFFER. | ||
2010 | */ | ||
2011 | struct mwl8k_cmd_enable_sniffer { | ||
2012 | struct mwl8k_cmd_pkt header; | ||
2013 | __le32 action; | ||
2014 | } __attribute__((packed)); | ||
2015 | |||
2016 | static int mwl8k_enable_sniffer(struct ieee80211_hw *hw, bool enable) | ||
2017 | { | ||
2018 | struct mwl8k_cmd_enable_sniffer *cmd; | ||
2019 | int rc; | ||
2020 | |||
2021 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
2022 | if (cmd == NULL) | ||
2023 | return -ENOMEM; | ||
2024 | |||
2025 | cmd->header.code = cpu_to_le16(MWL8K_CMD_ENABLE_SNIFFER); | ||
2026 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
2027 | cmd->action = enable ? cpu_to_le32((u32)MWL8K_CMD_SET) : 0; | ||
2028 | |||
2029 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
2030 | kfree(cmd); | ||
2031 | |||
2032 | return rc; | ||
2033 | } | ||
2034 | |||
2035 | /* | ||
2036 | * CMD_SET_RATE_ADAPT_MODE. | ||
2037 | */ | ||
2038 | struct mwl8k_cmd_set_rate_adapt_mode { | ||
2039 | struct mwl8k_cmd_pkt header; | ||
2040 | __le16 action; | ||
2041 | __le16 mode; | ||
2042 | } __attribute__((packed)); | ||
2043 | |||
2044 | static int mwl8k_cmd_setrateadaptmode(struct ieee80211_hw *hw, __u16 mode) | ||
2045 | { | ||
2046 | struct mwl8k_cmd_set_rate_adapt_mode *cmd; | ||
2047 | int rc; | ||
2048 | |||
2049 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
2050 | if (cmd == NULL) | ||
2051 | return -ENOMEM; | ||
2052 | |||
2053 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATEADAPT_MODE); | ||
2054 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
2055 | cmd->action = cpu_to_le16(MWL8K_CMD_SET); | ||
2056 | cmd->mode = cpu_to_le16(mode); | ||
2057 | |||
2058 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
2059 | kfree(cmd); | ||
2060 | |||
2061 | return rc; | ||
2062 | } | ||
2063 | |||
2064 | /* | ||
2065 | * CMD_SET_WMM_MODE. | ||
2066 | */ | ||
2067 | struct mwl8k_cmd_set_wmm { | ||
2068 | struct mwl8k_cmd_pkt header; | ||
2069 | __le16 action; | ||
2070 | } __attribute__((packed)); | ||
2071 | |||
2072 | static int mwl8k_set_wmm(struct ieee80211_hw *hw, bool enable) | ||
2073 | { | ||
2074 | struct mwl8k_priv *priv = hw->priv; | ||
2075 | struct mwl8k_cmd_set_wmm *cmd; | ||
2076 | int rc; | ||
2077 | |||
2078 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
2079 | if (cmd == NULL) | ||
2080 | return -ENOMEM; | ||
2081 | |||
2082 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_WMM_MODE); | ||
2083 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
2084 | cmd->action = enable ? cpu_to_le16(MWL8K_CMD_SET) : 0; | ||
2085 | |||
2086 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
2087 | kfree(cmd); | ||
2088 | |||
2089 | if (!rc) | ||
2090 | priv->wmm_mode = enable; | ||
2091 | |||
2092 | return rc; | ||
2093 | } | ||
2094 | |||
2095 | /* | ||
2096 | * CMD_SET_RTS_THRESHOLD. | ||
2097 | */ | ||
2098 | struct mwl8k_cmd_rts_threshold { | ||
2099 | struct mwl8k_cmd_pkt header; | ||
2100 | __le16 action; | ||
2101 | __le16 threshold; | ||
2102 | } __attribute__((packed)); | ||
2103 | |||
2104 | static int mwl8k_rts_threshold(struct ieee80211_hw *hw, | ||
2105 | u16 action, u16 *threshold) | ||
2106 | { | ||
2107 | struct mwl8k_cmd_rts_threshold *cmd; | ||
2108 | int rc; | ||
2109 | |||
2110 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
2111 | if (cmd == NULL) | ||
2112 | return -ENOMEM; | ||
2113 | |||
2114 | cmd->header.code = cpu_to_le16(MWL8K_CMD_RTS_THRESHOLD); | ||
2115 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
2116 | cmd->action = cpu_to_le16(action); | ||
2117 | cmd->threshold = cpu_to_le16(*threshold); | ||
2118 | |||
2119 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
2120 | kfree(cmd); | ||
2121 | |||
2122 | return rc; | ||
2123 | } | ||
2124 | |||
2125 | /* | ||
2126 | * CMD_SET_EDCA_PARAMS. | ||
2127 | */ | ||
2128 | struct mwl8k_cmd_set_edca_params { | ||
2129 | struct mwl8k_cmd_pkt header; | ||
2130 | |||
2131 | /* See MWL8K_SET_EDCA_XXX below */ | ||
2132 | __le16 action; | ||
2133 | |||
2134 | /* TX opportunity in units of 32 us */ | ||
2135 | __le16 txop; | ||
2136 | |||
2137 | /* Log exponent of max contention period: 0...15*/ | ||
2138 | __u8 log_cw_max; | ||
2139 | |||
2140 | /* Log exponent of min contention period: 0...15 */ | ||
2141 | __u8 log_cw_min; | ||
2142 | |||
2143 | /* Adaptive interframe spacing in units of 32us */ | ||
2144 | __u8 aifs; | ||
2145 | |||
2146 | /* TX queue to configure */ | ||
2147 | __u8 txq; | ||
2148 | } __attribute__((packed)); | ||
2149 | |||
2150 | #define MWL8K_GET_EDCA_ALL 0 | ||
2151 | #define MWL8K_SET_EDCA_CW 0x01 | ||
2152 | #define MWL8K_SET_EDCA_TXOP 0x02 | ||
2153 | #define MWL8K_SET_EDCA_AIFS 0x04 | ||
2154 | |||
2155 | #define MWL8K_SET_EDCA_ALL (MWL8K_SET_EDCA_CW | \ | ||
2156 | MWL8K_SET_EDCA_TXOP | \ | ||
2157 | MWL8K_SET_EDCA_AIFS) | ||
2158 | |||
2159 | static int | ||
2160 | mwl8k_set_edca_params(struct ieee80211_hw *hw, __u8 qnum, | ||
2161 | __u16 cw_min, __u16 cw_max, | ||
2162 | __u8 aifs, __u16 txop) | ||
2163 | { | ||
2164 | struct mwl8k_cmd_set_edca_params *cmd; | ||
2165 | u32 log_cw_min, log_cw_max; | ||
2166 | int rc; | ||
2167 | |||
2168 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
2169 | if (cmd == NULL) | ||
2170 | return -ENOMEM; | ||
2171 | |||
2172 | log_cw_min = ilog2(cw_min+1); | ||
2173 | log_cw_max = ilog2(cw_max+1); | ||
2174 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_EDCA_PARAMS); | ||
2175 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
2176 | |||
2177 | cmd->action = cpu_to_le16(MWL8K_SET_EDCA_ALL); | ||
2178 | cmd->txop = cpu_to_le16(txop); | ||
2179 | cmd->log_cw_max = (u8)log_cw_max; | ||
2180 | cmd->log_cw_min = (u8)log_cw_min; | ||
2181 | cmd->aifs = aifs; | ||
2182 | cmd->txq = qnum; | ||
2183 | |||
2184 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
2185 | kfree(cmd); | ||
2186 | |||
2187 | return rc; | ||
2188 | } | ||
2189 | |||
2190 | /* | ||
2191 | * CMD_FINALIZE_JOIN. | ||
2192 | */ | ||
2193 | |||
2194 | /* FJ beacon buffer size is compiled into the firmware. */ | ||
2195 | #define MWL8K_FJ_BEACON_MAXLEN 128 | ||
2196 | |||
2197 | struct mwl8k_cmd_finalize_join { | ||
2198 | struct mwl8k_cmd_pkt header; | ||
2199 | __le32 sleep_interval; /* Number of beacon periods to sleep */ | ||
2200 | __u8 beacon_data[MWL8K_FJ_BEACON_MAXLEN]; | ||
2201 | } __attribute__((packed)); | ||
2202 | |||
2203 | static int mwl8k_finalize_join(struct ieee80211_hw *hw, void *frame, | ||
2204 | __u16 framelen, __u16 dtim) | ||
2205 | { | ||
2206 | struct mwl8k_cmd_finalize_join *cmd; | ||
2207 | struct ieee80211_mgmt *payload = frame; | ||
2208 | u16 hdrlen; | ||
2209 | u32 payload_len; | ||
2210 | int rc; | ||
2211 | |||
2212 | if (frame == NULL) | ||
2213 | return -EINVAL; | ||
2214 | |||
2215 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
2216 | if (cmd == NULL) | ||
2217 | return -ENOMEM; | ||
2218 | |||
2219 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_FINALIZE_JOIN); | ||
2220 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
2221 | |||
2222 | if (dtim) | ||
2223 | cmd->sleep_interval = cpu_to_le32(dtim); | ||
2224 | else | ||
2225 | cmd->sleep_interval = cpu_to_le32(1); | ||
2226 | |||
2227 | hdrlen = ieee80211_hdrlen(payload->frame_control); | ||
2228 | |||
2229 | payload_len = framelen > hdrlen ? framelen - hdrlen : 0; | ||
2230 | |||
2231 | /* XXX TBD Might just have to abort and return an error */ | ||
2232 | if (payload_len > MWL8K_FJ_BEACON_MAXLEN) | ||
2233 | printk(KERN_ERR "%s(): WARNING: Incomplete beacon " | ||
2234 | "sent to firmware. Sz=%u MAX=%u\n", __func__, | ||
2235 | payload_len, MWL8K_FJ_BEACON_MAXLEN); | ||
2236 | |||
2237 | payload_len = payload_len > MWL8K_FJ_BEACON_MAXLEN ? | ||
2238 | MWL8K_FJ_BEACON_MAXLEN : payload_len; | ||
2239 | |||
2240 | if (payload && payload_len) | ||
2241 | memcpy(cmd->beacon_data, &payload->u.beacon, payload_len); | ||
2242 | |||
2243 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
2244 | kfree(cmd); | ||
2245 | return rc; | ||
2246 | } | ||
2247 | |||
2248 | /* | ||
2249 | * CMD_UPDATE_STADB. | ||
2250 | */ | ||
2251 | struct mwl8k_cmd_update_sta_db { | ||
2252 | struct mwl8k_cmd_pkt header; | ||
2253 | |||
2254 | /* See STADB_ACTION_TYPE */ | ||
2255 | __le32 action; | ||
2256 | |||
2257 | /* Peer MAC address */ | ||
2258 | __u8 peer_addr[IEEE80211_ADDR_LEN]; | ||
2259 | |||
2260 | __le32 reserved; | ||
2261 | |||
2262 | /* Peer info - valid during add/update. */ | ||
2263 | struct peer_capability_info peer_info; | ||
2264 | } __attribute__((packed)); | ||
2265 | |||
2266 | static int mwl8k_cmd_update_sta_db(struct ieee80211_hw *hw, | ||
2267 | struct ieee80211_vif *vif, __u32 action) | ||
2268 | { | ||
2269 | struct mwl8k_vif *mv_vif = MWL8K_VIF(vif); | ||
2270 | struct ieee80211_bss_conf *info = &mv_vif->bss_info; | ||
2271 | struct mwl8k_cmd_update_sta_db *cmd; | ||
2272 | struct peer_capability_info *peer_info; | ||
2273 | struct ieee80211_rate *bitrates = mv_vif->legacy_rates; | ||
2274 | DECLARE_MAC_BUF(mac); | ||
2275 | int rc; | ||
2276 | __u8 count, *rates; | ||
2277 | |||
2278 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
2279 | if (cmd == NULL) | ||
2280 | return -ENOMEM; | ||
2281 | |||
2282 | cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_STADB); | ||
2283 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
2284 | |||
2285 | cmd->action = cpu_to_le32(action); | ||
2286 | peer_info = &cmd->peer_info; | ||
2287 | memcpy(cmd->peer_addr, mv_vif->bssid, IEEE80211_ADDR_LEN); | ||
2288 | |||
2289 | switch (action) { | ||
2290 | case MWL8K_STA_DB_ADD_ENTRY: | ||
2291 | case MWL8K_STA_DB_MODIFY_ENTRY: | ||
2292 | /* Build peer_info block */ | ||
2293 | peer_info->peer_type = MWL8K_PEER_TYPE_ACCESSPOINT; | ||
2294 | peer_info->basic_caps = cpu_to_le16(info->assoc_capability); | ||
2295 | peer_info->interop = 1; | ||
2296 | peer_info->amsdu_enabled = 0; | ||
2297 | |||
2298 | rates = peer_info->legacy_rates; | ||
2299 | for (count = 0 ; count < mv_vif->legacy_nrates; count++) | ||
2300 | rates[count] = bitrates[count].hw_value; | ||
2301 | |||
2302 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
2303 | if (rc == 0) | ||
2304 | mv_vif->peer_id = peer_info->station_id; | ||
2305 | |||
2306 | break; | ||
2307 | |||
2308 | case MWL8K_STA_DB_DEL_ENTRY: | ||
2309 | case MWL8K_STA_DB_FLUSH: | ||
2310 | default: | ||
2311 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
2312 | if (rc == 0) | ||
2313 | mv_vif->peer_id = 0; | ||
2314 | break; | ||
2315 | } | ||
2316 | kfree(cmd); | ||
2317 | |||
2318 | return rc; | ||
2319 | } | ||
2320 | |||
2321 | /* | ||
2322 | * CMD_SET_AID. | ||
2323 | */ | ||
2324 | #define IEEE80211_OPMODE_DISABLED 0x00 | ||
2325 | #define IEEE80211_OPMODE_NON_MEMBER_PROT_MODE 0x01 | ||
2326 | #define IEEE80211_OPMODE_ONE_20MHZ_STA_PROT_MODE 0x02 | ||
2327 | #define IEEE80211_OPMODE_HTMIXED_PROT_MODE 0x03 | ||
2328 | |||
2329 | #define MWL8K_RATE_INDEX_MAX_ARRAY 14 | ||
2330 | |||
2331 | #define MWL8K_FRAME_PROT_DISABLED 0x00 | ||
2332 | #define MWL8K_FRAME_PROT_11G 0x07 | ||
2333 | #define MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY 0x02 | ||
2334 | #define MWL8K_FRAME_PROT_11N_HT_ALL 0x06 | ||
2335 | #define MWL8K_FRAME_PROT_MASK 0x07 | ||
2336 | |||
2337 | struct mwl8k_cmd_update_set_aid { | ||
2338 | struct mwl8k_cmd_pkt header; | ||
2339 | __le16 aid; | ||
2340 | |||
2341 | /* AP's MAC address (BSSID) */ | ||
2342 | __u8 bssid[IEEE80211_ADDR_LEN]; | ||
2343 | __le16 protection_mode; | ||
2344 | __u8 supp_rates[MWL8K_RATE_INDEX_MAX_ARRAY]; | ||
2345 | } __attribute__((packed)); | ||
2346 | |||
2347 | static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw, | ||
2348 | struct ieee80211_vif *vif) | ||
2349 | { | ||
2350 | struct mwl8k_vif *mv_vif = MWL8K_VIF(vif); | ||
2351 | struct ieee80211_bss_conf *info = &mv_vif->bss_info; | ||
2352 | struct mwl8k_cmd_update_set_aid *cmd; | ||
2353 | struct ieee80211_rate *bitrates = mv_vif->legacy_rates; | ||
2354 | int count; | ||
2355 | u16 prot_mode; | ||
2356 | int rc; | ||
2357 | |||
2358 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
2359 | if (cmd == NULL) | ||
2360 | return -ENOMEM; | ||
2361 | |||
2362 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_AID); | ||
2363 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
2364 | cmd->aid = cpu_to_le16(info->aid); | ||
2365 | |||
2366 | memcpy(cmd->bssid, mv_vif->bssid, IEEE80211_ADDR_LEN); | ||
2367 | |||
2368 | prot_mode = MWL8K_FRAME_PROT_DISABLED; | ||
2369 | |||
2370 | if (info->use_cts_prot) { | ||
2371 | prot_mode = MWL8K_FRAME_PROT_11G; | ||
2372 | } else { | ||
2373 | switch (info->ht.operation_mode & | ||
2374 | IEEE80211_HT_OP_MODE_PROTECTION) { | ||
2375 | case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ: | ||
2376 | prot_mode = MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY; | ||
2377 | break; | ||
2378 | case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED: | ||
2379 | prot_mode = MWL8K_FRAME_PROT_11N_HT_ALL; | ||
2380 | break; | ||
2381 | default: | ||
2382 | prot_mode = MWL8K_FRAME_PROT_DISABLED; | ||
2383 | break; | ||
2384 | } | ||
2385 | } | ||
2386 | |||
2387 | cmd->protection_mode = cpu_to_le16(prot_mode); | ||
2388 | |||
2389 | for (count = 0; count < mv_vif->legacy_nrates; count++) | ||
2390 | cmd->supp_rates[count] = bitrates[count].hw_value; | ||
2391 | |||
2392 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
2393 | kfree(cmd); | ||
2394 | |||
2395 | return rc; | ||
2396 | } | ||
2397 | |||
2398 | /* | ||
2399 | * CMD_SET_RATE. | ||
2400 | */ | ||
2401 | struct mwl8k_cmd_update_rateset { | ||
2402 | struct mwl8k_cmd_pkt header; | ||
2403 | __u8 legacy_rates[MWL8K_RATE_INDEX_MAX_ARRAY]; | ||
2404 | |||
2405 | /* Bitmap for supported MCS codes. */ | ||
2406 | __u8 mcs_set[MWL8K_IEEE_LEGACY_DATA_RATES]; | ||
2407 | __u8 reserved[MWL8K_IEEE_LEGACY_DATA_RATES]; | ||
2408 | } __attribute__((packed)); | ||
2409 | |||
2410 | static int mwl8k_update_rateset(struct ieee80211_hw *hw, | ||
2411 | struct ieee80211_vif *vif) | ||
2412 | { | ||
2413 | struct mwl8k_vif *mv_vif = MWL8K_VIF(vif); | ||
2414 | struct mwl8k_cmd_update_rateset *cmd; | ||
2415 | struct ieee80211_rate *bitrates = mv_vif->legacy_rates; | ||
2416 | int count; | ||
2417 | int rc; | ||
2418 | |||
2419 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
2420 | if (cmd == NULL) | ||
2421 | return -ENOMEM; | ||
2422 | |||
2423 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATE); | ||
2424 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
2425 | |||
2426 | for (count = 0; count < mv_vif->legacy_nrates; count++) | ||
2427 | cmd->legacy_rates[count] = bitrates[count].hw_value; | ||
2428 | |||
2429 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
2430 | kfree(cmd); | ||
2431 | |||
2432 | return rc; | ||
2433 | } | ||
2434 | |||
2435 | /* | ||
2436 | * CMD_USE_FIXED_RATE. | ||
2437 | */ | ||
2438 | #define MWL8K_RATE_TABLE_SIZE 8 | ||
2439 | #define MWL8K_UCAST_RATE 0 | ||
2440 | #define MWL8K_MCAST_RATE 1 | ||
2441 | #define MWL8K_BCAST_RATE 2 | ||
2442 | |||
2443 | #define MWL8K_USE_FIXED_RATE 0x0001 | ||
2444 | #define MWL8K_USE_AUTO_RATE 0x0002 | ||
2445 | |||
2446 | struct mwl8k_rate_entry { | ||
2447 | /* Set to 1 if HT rate, 0 if legacy. */ | ||
2448 | __le32 is_ht_rate; | ||
2449 | |||
2450 | /* Set to 1 to use retry_count field. */ | ||
2451 | __le32 enable_retry; | ||
2452 | |||
2453 | /* Specified legacy rate or MCS. */ | ||
2454 | __le32 rate; | ||
2455 | |||
2456 | /* Number of allowed retries. */ | ||
2457 | __le32 retry_count; | ||
2458 | } __attribute__((packed)); | ||
2459 | |||
2460 | struct mwl8k_rate_table { | ||
2461 | /* 1 to allow specified rate and below */ | ||
2462 | __le32 allow_rate_drop; | ||
2463 | __le32 num_rates; | ||
2464 | struct mwl8k_rate_entry rate_entry[MWL8K_RATE_TABLE_SIZE]; | ||
2465 | } __attribute__((packed)); | ||
2466 | |||
2467 | struct mwl8k_cmd_use_fixed_rate { | ||
2468 | struct mwl8k_cmd_pkt header; | ||
2469 | __le32 action; | ||
2470 | struct mwl8k_rate_table rate_table; | ||
2471 | |||
2472 | /* Unicast, Broadcast or Multicast */ | ||
2473 | __le32 rate_type; | ||
2474 | __le32 reserved1; | ||
2475 | __le32 reserved2; | ||
2476 | } __attribute__((packed)); | ||
2477 | |||
2478 | static int mwl8k_cmd_use_fixed_rate(struct ieee80211_hw *hw, | ||
2479 | u32 action, u32 rate_type, struct mwl8k_rate_table *rate_table) | ||
2480 | { | ||
2481 | struct mwl8k_cmd_use_fixed_rate *cmd; | ||
2482 | int count; | ||
2483 | int rc; | ||
2484 | |||
2485 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
2486 | if (cmd == NULL) | ||
2487 | return -ENOMEM; | ||
2488 | |||
2489 | cmd->header.code = cpu_to_le16(MWL8K_CMD_USE_FIXED_RATE); | ||
2490 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
2491 | |||
2492 | cmd->action = cpu_to_le32(action); | ||
2493 | cmd->rate_type = cpu_to_le32(rate_type); | ||
2494 | |||
2495 | if (rate_table != NULL) { | ||
2496 | /* Copy over each field manually so | ||
2497 | * that bitflipping can be done | ||
2498 | */ | ||
2499 | cmd->rate_table.allow_rate_drop = | ||
2500 | cpu_to_le32(rate_table->allow_rate_drop); | ||
2501 | cmd->rate_table.num_rates = | ||
2502 | cpu_to_le32(rate_table->num_rates); | ||
2503 | |||
2504 | for (count = 0; count < rate_table->num_rates; count++) { | ||
2505 | struct mwl8k_rate_entry *dst = | ||
2506 | &cmd->rate_table.rate_entry[count]; | ||
2507 | struct mwl8k_rate_entry *src = | ||
2508 | &rate_table->rate_entry[count]; | ||
2509 | |||
2510 | dst->is_ht_rate = cpu_to_le32(src->is_ht_rate); | ||
2511 | dst->enable_retry = cpu_to_le32(src->enable_retry); | ||
2512 | dst->rate = cpu_to_le32(src->rate); | ||
2513 | dst->retry_count = cpu_to_le32(src->retry_count); | ||
2514 | } | ||
2515 | } | ||
2516 | |||
2517 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
2518 | kfree(cmd); | ||
2519 | |||
2520 | return rc; | ||
2521 | } | ||
2522 | |||
2523 | |||
2524 | /* | ||
2525 | * Interrupt handling. | ||
2526 | */ | ||
2527 | static irqreturn_t mwl8k_interrupt(int irq, void *dev_id) | ||
2528 | { | ||
2529 | struct ieee80211_hw *hw = dev_id; | ||
2530 | struct mwl8k_priv *priv = hw->priv; | ||
2531 | u32 status; | ||
2532 | |||
2533 | status = ioread32(priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); | ||
2534 | iowrite32(~status, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); | ||
2535 | |||
2536 | status &= priv->int_mask; | ||
2537 | if (!status) | ||
2538 | return IRQ_NONE; | ||
2539 | |||
2540 | if (status & MWL8K_A2H_INT_TX_DONE) | ||
2541 | tasklet_schedule(&priv->tx_reclaim_task); | ||
2542 | |||
2543 | if (status & MWL8K_A2H_INT_RX_READY) { | ||
2544 | while (rxq_process(hw, 0, 1)) | ||
2545 | rxq_refill(hw, 0, 1); | ||
2546 | } | ||
2547 | |||
2548 | if (status & MWL8K_A2H_INT_OPC_DONE) { | ||
2549 | if (priv->hostcmd_wait != NULL) { | ||
2550 | complete(priv->hostcmd_wait); | ||
2551 | priv->hostcmd_wait = NULL; | ||
2552 | } | ||
2553 | } | ||
2554 | |||
2555 | if (status & MWL8K_A2H_INT_QUEUE_EMPTY) { | ||
2556 | if (!priv->inconfig && | ||
2557 | priv->radio_state && | ||
2558 | mwl8k_txq_busy(priv)) | ||
2559 | mwl8k_tx_start(priv); | ||
2560 | } | ||
2561 | |||
2562 | return IRQ_HANDLED; | ||
2563 | } | ||
2564 | |||
2565 | |||
2566 | /* | ||
2567 | * Core driver operations. | ||
2568 | */ | ||
2569 | static int mwl8k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | ||
2570 | { | ||
2571 | struct mwl8k_priv *priv = hw->priv; | ||
2572 | int index = skb_get_queue_mapping(skb); | ||
2573 | int rc; | ||
2574 | |||
2575 | if (priv->current_channel == NULL) { | ||
2576 | printk(KERN_DEBUG "%s: dropped TX frame since radio " | ||
2577 | "disabled\n", priv->name); | ||
2578 | dev_kfree_skb(skb); | ||
2579 | return NETDEV_TX_OK; | ||
2580 | } | ||
2581 | |||
2582 | rc = mwl8k_txq_xmit(hw, index, skb); | ||
2583 | |||
2584 | return rc; | ||
2585 | } | ||
2586 | |||
2587 | struct mwl8k_work_struct { | ||
2588 | /* Initialized by mwl8k_queue_work(). */ | ||
2589 | struct work_struct wt; | ||
2590 | |||
2591 | /* Required field passed in to mwl8k_queue_work(). */ | ||
2592 | struct ieee80211_hw *hw; | ||
2593 | |||
2594 | /* Required field passed in to mwl8k_queue_work(). */ | ||
2595 | int (*wfunc)(struct work_struct *w); | ||
2596 | |||
2597 | /* Initialized by mwl8k_queue_work(). */ | ||
2598 | struct completion *cmd_wait; | ||
2599 | |||
2600 | /* Result code. */ | ||
2601 | int rc; | ||
2602 | |||
2603 | /* | ||
2604 | * Optional field. Refer to explanation of MWL8K_WQ_XXX_XXX | ||
2605 | * flags for explanation. Defaults to MWL8K_WQ_DEFAULT_OPTIONS. | ||
2606 | */ | ||
2607 | u32 options; | ||
2608 | |||
2609 | /* Optional field. Defaults to MWL8K_CONFIG_TIMEOUT_MS. */ | ||
2610 | unsigned long timeout_ms; | ||
2611 | |||
2612 | /* Optional field. Defaults to MWL8K_WQ_TXWAIT_ATTEMPTS. */ | ||
2613 | u32 txwait_attempts; | ||
2614 | |||
2615 | /* Optional field. Defaults to MWL8K_TXWAIT_MS. */ | ||
2616 | u32 tx_timeout_ms; | ||
2617 | u32 step; | ||
2618 | }; | ||
2619 | |||
2620 | /* Flags controlling behavior of config queue requests */ | ||
2621 | |||
2622 | /* Caller spins while waiting for completion. */ | ||
2623 | #define MWL8K_WQ_SPIN 0x00000001 | ||
2624 | |||
2625 | /* Wait for TX queues to empty before proceeding with configuration. */ | ||
2626 | #define MWL8K_WQ_TX_WAIT_EMPTY 0x00000002 | ||
2627 | |||
2628 | /* Queue request and return immediately. */ | ||
2629 | #define MWL8K_WQ_POST_REQUEST 0x00000004 | ||
2630 | |||
2631 | /* | ||
2632 | * Caller sleeps and waits for task complete notification. | ||
2633 | * Do not use in atomic context. | ||
2634 | */ | ||
2635 | #define MWL8K_WQ_SLEEP 0x00000008 | ||
2636 | |||
2637 | /* Free work struct when task is done. */ | ||
2638 | #define MWL8K_WQ_FREE_WORKSTRUCT 0x00000010 | ||
2639 | |||
2640 | /* | ||
2641 | * Config request is queued and returns to caller imediately. Use | ||
2642 | * this in atomic context. Work struct is freed by mwl8k_queue_work() | ||
2643 | * when this flag is set. | ||
2644 | */ | ||
2645 | #define MWL8K_WQ_QUEUE_ONLY (MWL8K_WQ_POST_REQUEST | \ | ||
2646 | MWL8K_WQ_FREE_WORKSTRUCT) | ||
2647 | |||
2648 | /* Default work queue behavior is to sleep and wait for tx completion. */ | ||
2649 | #define MWL8K_WQ_DEFAULT_OPTIONS (MWL8K_WQ_SLEEP | MWL8K_WQ_TX_WAIT_EMPTY) | ||
2650 | |||
2651 | /* | ||
2652 | * Default config request timeout. Add adjustments to make sure the | ||
2653 | * config thread waits long enough for both tx wait and cmd wait before | ||
2654 | * timing out. | ||
2655 | */ | ||
2656 | |||
2657 | /* Time to wait for all TXQs to drain. TX Doorbell is pressed each time. */ | ||
2658 | #define MWL8K_TXWAIT_TIMEOUT_MS 1000 | ||
2659 | |||
2660 | /* Default number of TX wait attempts. */ | ||
2661 | #define MWL8K_WQ_TXWAIT_ATTEMPTS 4 | ||
2662 | |||
2663 | /* Total time to wait for TXQ to drain. */ | ||
2664 | #define MWL8K_TXWAIT_MS (MWL8K_TXWAIT_TIMEOUT_MS * \ | ||
2665 | MWL8K_WQ_TXWAIT_ATTEMPTS) | ||
2666 | |||
2667 | /* Scheduling slop. */ | ||
2668 | #define MWL8K_OS_SCHEDULE_OVERHEAD_MS 200 | ||
2669 | |||
2670 | #define MWL8K_CONFIG_TIMEOUT_MS (MWL8K_CMD_TIMEOUT_MS + \ | ||
2671 | MWL8K_TXWAIT_MS + \ | ||
2672 | MWL8K_OS_SCHEDULE_OVERHEAD_MS) | ||
2673 | |||
2674 | static void mwl8k_config_thread(struct work_struct *wt) | ||
2675 | { | ||
2676 | struct mwl8k_work_struct *worker = (struct mwl8k_work_struct *)wt; | ||
2677 | struct ieee80211_hw *hw = worker->hw; | ||
2678 | struct mwl8k_priv *priv = hw->priv; | ||
2679 | int rc = 0; | ||
2680 | |||
2681 | spin_lock_irq(&priv->tx_lock); | ||
2682 | priv->inconfig = true; | ||
2683 | spin_unlock_irq(&priv->tx_lock); | ||
2684 | |||
2685 | ieee80211_stop_queues(hw); | ||
2686 | |||
2687 | /* | ||
2688 | * Wait for host queues to drain before doing PHY | ||
2689 | * reconfiguration. This avoids interrupting any in-flight | ||
2690 | * DMA transfers to the hardware. | ||
2691 | */ | ||
2692 | if (worker->options & MWL8K_WQ_TX_WAIT_EMPTY) { | ||
2693 | u32 timeout; | ||
2694 | u32 time_remaining; | ||
2695 | u32 iter; | ||
2696 | u32 tx_wait_attempts = worker->txwait_attempts; | ||
2697 | |||
2698 | time_remaining = worker->tx_timeout_ms; | ||
2699 | if (!tx_wait_attempts) | ||
2700 | tx_wait_attempts = 1; | ||
2701 | |||
2702 | timeout = worker->tx_timeout_ms/tx_wait_attempts; | ||
2703 | if (!timeout) | ||
2704 | timeout = 1; | ||
2705 | |||
2706 | iter = tx_wait_attempts; | ||
2707 | do { | ||
2708 | int wait_time; | ||
2709 | |||
2710 | if (time_remaining > timeout) { | ||
2711 | time_remaining -= timeout; | ||
2712 | wait_time = timeout; | ||
2713 | } else | ||
2714 | wait_time = time_remaining; | ||
2715 | |||
2716 | if (!wait_time) | ||
2717 | wait_time = 1; | ||
2718 | |||
2719 | rc = mwl8k_tx_wait_empty(hw, wait_time); | ||
2720 | if (rc) | ||
2721 | printk(KERN_ERR "%s() txwait timeout=%ums " | ||
2722 | "Retry:%u/%u\n", __func__, timeout, | ||
2723 | tx_wait_attempts - iter + 1, | ||
2724 | tx_wait_attempts); | ||
2725 | |||
2726 | } while (rc && --iter); | ||
2727 | |||
2728 | rc = iter ? 0 : -ETIMEDOUT; | ||
2729 | } | ||
2730 | if (!rc) | ||
2731 | rc = worker->wfunc(wt); | ||
2732 | |||
2733 | spin_lock_irq(&priv->tx_lock); | ||
2734 | priv->inconfig = false; | ||
2735 | if (priv->pending_tx_pkts && priv->radio_state) | ||
2736 | mwl8k_tx_start(priv); | ||
2737 | spin_unlock_irq(&priv->tx_lock); | ||
2738 | ieee80211_wake_queues(hw); | ||
2739 | |||
2740 | worker->rc = rc; | ||
2741 | if (worker->options & MWL8K_WQ_SLEEP) | ||
2742 | complete(worker->cmd_wait); | ||
2743 | |||
2744 | if (worker->options & MWL8K_WQ_FREE_WORKSTRUCT) | ||
2745 | kfree(wt); | ||
2746 | } | ||
2747 | |||
2748 | static int mwl8k_queue_work(struct ieee80211_hw *hw, | ||
2749 | struct mwl8k_work_struct *worker, | ||
2750 | struct workqueue_struct *wqueue, | ||
2751 | int (*wfunc)(struct work_struct *w)) | ||
2752 | { | ||
2753 | unsigned long timeout = 0; | ||
2754 | int rc = 0; | ||
2755 | |||
2756 | DECLARE_COMPLETION_ONSTACK(cmd_wait); | ||
2757 | |||
2758 | if (!worker->timeout_ms) | ||
2759 | worker->timeout_ms = MWL8K_CONFIG_TIMEOUT_MS; | ||
2760 | |||
2761 | if (!worker->options) | ||
2762 | worker->options = MWL8K_WQ_DEFAULT_OPTIONS; | ||
2763 | |||
2764 | if (!worker->txwait_attempts) | ||
2765 | worker->txwait_attempts = MWL8K_WQ_TXWAIT_ATTEMPTS; | ||
2766 | |||
2767 | if (!worker->tx_timeout_ms) | ||
2768 | worker->tx_timeout_ms = MWL8K_TXWAIT_MS; | ||
2769 | |||
2770 | worker->hw = hw; | ||
2771 | worker->cmd_wait = &cmd_wait; | ||
2772 | worker->rc = 1; | ||
2773 | worker->wfunc = wfunc; | ||
2774 | |||
2775 | INIT_WORK(&worker->wt, mwl8k_config_thread); | ||
2776 | queue_work(wqueue, &worker->wt); | ||
2777 | |||
2778 | if (worker->options & MWL8K_WQ_POST_REQUEST) { | ||
2779 | rc = 0; | ||
2780 | } else { | ||
2781 | if (worker->options & MWL8K_WQ_SPIN) { | ||
2782 | timeout = worker->timeout_ms; | ||
2783 | while (timeout && (worker->rc > 0)) { | ||
2784 | mdelay(1); | ||
2785 | timeout--; | ||
2786 | } | ||
2787 | } else if (worker->options & MWL8K_WQ_SLEEP) | ||
2788 | timeout = wait_for_completion_timeout(&cmd_wait, | ||
2789 | msecs_to_jiffies(worker->timeout_ms)); | ||
2790 | |||
2791 | if (timeout) | ||
2792 | rc = worker->rc; | ||
2793 | else { | ||
2794 | cancel_work_sync(&worker->wt); | ||
2795 | rc = -ETIMEDOUT; | ||
2796 | } | ||
2797 | } | ||
2798 | |||
2799 | return rc; | ||
2800 | } | ||
2801 | |||
2802 | struct mwl8k_start_worker { | ||
2803 | struct mwl8k_work_struct header; | ||
2804 | }; | ||
2805 | |||
2806 | static int mwl8k_start_wt(struct work_struct *wt) | ||
2807 | { | ||
2808 | struct mwl8k_start_worker *worker = (struct mwl8k_start_worker *)wt; | ||
2809 | struct ieee80211_hw *hw = worker->header.hw; | ||
2810 | struct mwl8k_priv *priv = hw->priv; | ||
2811 | int rc = 0; | ||
2812 | |||
2813 | if (priv->vif != NULL) { | ||
2814 | rc = -EIO; | ||
2815 | goto mwl8k_start_exit; | ||
2816 | } | ||
2817 | |||
2818 | /* Turn on radio */ | ||
2819 | if (mwl8k_cmd_802_11_radio_control(hw, MWL8K_RADIO_ENABLE)) { | ||
2820 | rc = -EIO; | ||
2821 | goto mwl8k_start_exit; | ||
2822 | } | ||
2823 | |||
2824 | /* Purge TX/RX HW queues */ | ||
2825 | if (mwl8k_cmd_set_pre_scan(hw)) { | ||
2826 | rc = -EIO; | ||
2827 | goto mwl8k_start_exit; | ||
2828 | } | ||
2829 | |||
2830 | if (mwl8k_cmd_set_post_scan(hw, "\x00\x00\x00\x00\x00\x00")) { | ||
2831 | rc = -EIO; | ||
2832 | goto mwl8k_start_exit; | ||
2833 | } | ||
2834 | |||
2835 | /* Enable firmware rate adaptation */ | ||
2836 | if (mwl8k_cmd_setrateadaptmode(hw, 0)) { | ||
2837 | rc = -EIO; | ||
2838 | goto mwl8k_start_exit; | ||
2839 | } | ||
2840 | |||
2841 | /* Disable WMM. WMM gets enabled when stack sends WMM parms */ | ||
2842 | if (mwl8k_set_wmm(hw, MWL8K_WMM_DISABLE)) { | ||
2843 | rc = -EIO; | ||
2844 | goto mwl8k_start_exit; | ||
2845 | } | ||
2846 | |||
2847 | /* Disable sniffer mode */ | ||
2848 | if (mwl8k_enable_sniffer(hw, 0)) | ||
2849 | rc = -EIO; | ||
2850 | |||
2851 | mwl8k_start_exit: | ||
2852 | return rc; | ||
2853 | } | ||
2854 | |||
2855 | static int mwl8k_start(struct ieee80211_hw *hw) | ||
2856 | { | ||
2857 | struct mwl8k_start_worker *worker; | ||
2858 | struct mwl8k_priv *priv = hw->priv; | ||
2859 | int rc; | ||
2860 | |||
2861 | /* Enable tx reclaim tasklet */ | ||
2862 | tasklet_enable(&priv->tx_reclaim_task); | ||
2863 | |||
2864 | rc = request_irq(priv->pdev->irq, &mwl8k_interrupt, | ||
2865 | IRQF_SHARED, MWL8K_NAME, hw); | ||
2866 | if (rc) { | ||
2867 | printk(KERN_ERR "%s: failed to register IRQ handler\n", | ||
2868 | priv->name); | ||
2869 | rc = -EIO; | ||
2870 | goto mwl8k_start_disable_tasklet; | ||
2871 | } | ||
2872 | |||
2873 | /* Enable interrupts */ | ||
2874 | iowrite32(priv->int_mask, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); | ||
2875 | |||
2876 | worker = kzalloc(sizeof(*worker), GFP_KERNEL); | ||
2877 | if (worker == NULL) { | ||
2878 | rc = -ENOMEM; | ||
2879 | goto mwl8k_start_disable_irq; | ||
2880 | } | ||
2881 | |||
2882 | rc = mwl8k_queue_work(hw, &worker->header, | ||
2883 | priv->config_wq, mwl8k_start_wt); | ||
2884 | kfree(worker); | ||
2885 | if (!rc) | ||
2886 | return rc; | ||
2887 | |||
2888 | if (rc == -ETIMEDOUT) | ||
2889 | printk(KERN_ERR "%s() timed out\n", __func__); | ||
2890 | |||
2891 | rc = -EIO; | ||
2892 | |||
2893 | mwl8k_start_disable_irq: | ||
2894 | spin_lock_irq(&priv->tx_lock); | ||
2895 | iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); | ||
2896 | spin_unlock_irq(&priv->tx_lock); | ||
2897 | free_irq(priv->pdev->irq, hw); | ||
2898 | |||
2899 | mwl8k_start_disable_tasklet: | ||
2900 | tasklet_disable(&priv->tx_reclaim_task); | ||
2901 | |||
2902 | return rc; | ||
2903 | } | ||
2904 | |||
2905 | struct mwl8k_stop_worker { | ||
2906 | struct mwl8k_work_struct header; | ||
2907 | }; | ||
2908 | |||
2909 | static int mwl8k_stop_wt(struct work_struct *wt) | ||
2910 | { | ||
2911 | struct mwl8k_stop_worker *worker = (struct mwl8k_stop_worker *)wt; | ||
2912 | struct ieee80211_hw *hw = worker->header.hw; | ||
2913 | int rc; | ||
2914 | |||
2915 | rc = mwl8k_cmd_802_11_radio_control(hw, MWL8K_RADIO_DISABLE); | ||
2916 | |||
2917 | return rc; | ||
2918 | } | ||
2919 | |||
2920 | static void mwl8k_stop(struct ieee80211_hw *hw) | ||
2921 | { | ||
2922 | int rc; | ||
2923 | struct mwl8k_stop_worker *worker; | ||
2924 | struct mwl8k_priv *priv = hw->priv; | ||
2925 | int i; | ||
2926 | |||
2927 | if (priv->vif != NULL) | ||
2928 | return; | ||
2929 | |||
2930 | ieee80211_stop_queues(hw); | ||
2931 | |||
2932 | worker = kzalloc(sizeof(*worker), GFP_KERNEL); | ||
2933 | if (worker == NULL) | ||
2934 | return; | ||
2935 | |||
2936 | rc = mwl8k_queue_work(hw, &worker->header, | ||
2937 | priv->config_wq, mwl8k_stop_wt); | ||
2938 | kfree(worker); | ||
2939 | if (rc == -ETIMEDOUT) | ||
2940 | printk(KERN_ERR "%s() timed out\n", __func__); | ||
2941 | |||
2942 | /* Disable interrupts */ | ||
2943 | spin_lock_irq(&priv->tx_lock); | ||
2944 | iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); | ||
2945 | spin_unlock_irq(&priv->tx_lock); | ||
2946 | free_irq(priv->pdev->irq, hw); | ||
2947 | |||
2948 | /* Stop finalize join worker */ | ||
2949 | cancel_work_sync(&priv->finalize_join_worker); | ||
2950 | if (priv->beacon_skb != NULL) | ||
2951 | dev_kfree_skb(priv->beacon_skb); | ||
2952 | |||
2953 | /* Stop tx reclaim tasklet */ | ||
2954 | tasklet_disable(&priv->tx_reclaim_task); | ||
2955 | |||
2956 | /* Stop config thread */ | ||
2957 | flush_workqueue(priv->config_wq); | ||
2958 | |||
2959 | /* Return all skbs to mac80211 */ | ||
2960 | for (i = 0; i < MWL8K_TX_QUEUES; i++) | ||
2961 | mwl8k_txq_reclaim(hw, i, 1); | ||
2962 | } | ||
2963 | |||
2964 | static int mwl8k_add_interface(struct ieee80211_hw *hw, | ||
2965 | struct ieee80211_if_init_conf *conf) | ||
2966 | { | ||
2967 | struct mwl8k_priv *priv = hw->priv; | ||
2968 | struct mwl8k_vif *mwl8k_vif; | ||
2969 | |||
2970 | /* | ||
2971 | * We only support one active interface at a time. | ||
2972 | */ | ||
2973 | if (priv->vif != NULL) | ||
2974 | return -EBUSY; | ||
2975 | |||
2976 | /* | ||
2977 | * We only support managed interfaces for now. | ||
2978 | */ | ||
2979 | if (conf->type != NL80211_IFTYPE_STATION && | ||
2980 | conf->type != NL80211_IFTYPE_MONITOR) | ||
2981 | return -EINVAL; | ||
2982 | |||
2983 | /* Clean out driver private area */ | ||
2984 | mwl8k_vif = MWL8K_VIF(conf->vif); | ||
2985 | memset(mwl8k_vif, 0, sizeof(*mwl8k_vif)); | ||
2986 | |||
2987 | /* Save the mac address */ | ||
2988 | memcpy(mwl8k_vif->mac_addr, conf->mac_addr, IEEE80211_ADDR_LEN); | ||
2989 | |||
2990 | /* Back pointer to parent config block */ | ||
2991 | mwl8k_vif->priv = priv; | ||
2992 | |||
2993 | /* Setup initial PHY parameters */ | ||
2994 | memcpy(mwl8k_vif->legacy_rates , | ||
2995 | priv->rates, sizeof(mwl8k_vif->legacy_rates)); | ||
2996 | mwl8k_vif->legacy_nrates = ARRAY_SIZE(priv->rates); | ||
2997 | |||
2998 | /* Set Initial sequence number to zero */ | ||
2999 | mwl8k_vif->seqno = 0; | ||
3000 | |||
3001 | priv->vif = conf->vif; | ||
3002 | priv->current_channel = NULL; | ||
3003 | |||
3004 | return 0; | ||
3005 | } | ||
3006 | |||
3007 | static void mwl8k_remove_interface(struct ieee80211_hw *hw, | ||
3008 | struct ieee80211_if_init_conf *conf) | ||
3009 | { | ||
3010 | struct mwl8k_priv *priv = hw->priv; | ||
3011 | |||
3012 | if (priv->vif == NULL) | ||
3013 | return; | ||
3014 | |||
3015 | priv->vif = NULL; | ||
3016 | } | ||
3017 | |||
3018 | struct mwl8k_config_worker { | ||
3019 | struct mwl8k_work_struct header; | ||
3020 | u32 changed; | ||
3021 | }; | ||
3022 | |||
3023 | static int mwl8k_config_wt(struct work_struct *wt) | ||
3024 | { | ||
3025 | struct mwl8k_config_worker *worker = | ||
3026 | (struct mwl8k_config_worker *)wt; | ||
3027 | struct ieee80211_hw *hw = worker->header.hw; | ||
3028 | struct ieee80211_conf *conf = &hw->conf; | ||
3029 | struct mwl8k_priv *priv = hw->priv; | ||
3030 | int rc = 0; | ||
3031 | |||
3032 | if (!conf->radio_enabled) { | ||
3033 | mwl8k_cmd_802_11_radio_control(hw, MWL8K_RADIO_DISABLE); | ||
3034 | priv->current_channel = NULL; | ||
3035 | rc = 0; | ||
3036 | goto mwl8k_config_exit; | ||
3037 | } | ||
3038 | |||
3039 | if (mwl8k_cmd_802_11_radio_control(hw, MWL8K_RADIO_ENABLE)) { | ||
3040 | rc = -EINVAL; | ||
3041 | goto mwl8k_config_exit; | ||
3042 | } | ||
3043 | |||
3044 | priv->current_channel = conf->channel; | ||
3045 | |||
3046 | if (mwl8k_cmd_set_rf_channel(hw, conf->channel)) { | ||
3047 | rc = -EINVAL; | ||
3048 | goto mwl8k_config_exit; | ||
3049 | } | ||
3050 | |||
3051 | if (conf->power_level > 18) | ||
3052 | conf->power_level = 18; | ||
3053 | if (mwl8k_cmd_802_11_rf_tx_power(hw, conf->power_level)) { | ||
3054 | rc = -EINVAL; | ||
3055 | goto mwl8k_config_exit; | ||
3056 | } | ||
3057 | |||
3058 | if (mwl8k_cmd_mimo_config(hw, 0x7, 0x7)) | ||
3059 | rc = -EINVAL; | ||
3060 | |||
3061 | mwl8k_config_exit: | ||
3062 | return rc; | ||
3063 | } | ||
3064 | |||
3065 | static int mwl8k_config(struct ieee80211_hw *hw, u32 changed) | ||
3066 | { | ||
3067 | int rc = 0; | ||
3068 | struct mwl8k_config_worker *worker; | ||
3069 | struct mwl8k_priv *priv = hw->priv; | ||
3070 | |||
3071 | worker = kzalloc(sizeof(*worker), GFP_KERNEL); | ||
3072 | if (worker == NULL) | ||
3073 | return -ENOMEM; | ||
3074 | |||
3075 | worker->changed = changed; | ||
3076 | rc = mwl8k_queue_work(hw, &worker->header, | ||
3077 | priv->config_wq, mwl8k_config_wt); | ||
3078 | if (rc == -ETIMEDOUT) { | ||
3079 | printk(KERN_ERR "%s() timed out.\n", __func__); | ||
3080 | rc = -EINVAL; | ||
3081 | } | ||
3082 | |||
3083 | kfree(worker); | ||
3084 | |||
3085 | /* | ||
3086 | * mac80211 will crash on anything other than -EINVAL on | ||
3087 | * error. Looks like wireless extensions which calls mac80211 | ||
3088 | * may be the actual culprit... | ||
3089 | */ | ||
3090 | return rc ? -EINVAL : 0; | ||
3091 | } | ||
3092 | |||
3093 | static int mwl8k_config_interface(struct ieee80211_hw *hw, | ||
3094 | struct ieee80211_vif *vif, | ||
3095 | struct ieee80211_if_conf *conf) | ||
3096 | { | ||
3097 | struct mwl8k_vif *mv_vif = MWL8K_VIF(vif); | ||
3098 | u32 changed = conf->changed; | ||
3099 | |||
3100 | if (changed & IEEE80211_IFCC_BSSID) | ||
3101 | memcpy(mv_vif->bssid, conf->bssid, IEEE80211_ADDR_LEN); | ||
3102 | |||
3103 | return 0; | ||
3104 | } | ||
3105 | |||
3106 | struct mwl8k_bss_info_changed_worker { | ||
3107 | struct mwl8k_work_struct header; | ||
3108 | struct ieee80211_vif *vif; | ||
3109 | struct ieee80211_bss_conf *info; | ||
3110 | u32 changed; | ||
3111 | }; | ||
3112 | |||
3113 | static int mwl8k_bss_info_changed_wt(struct work_struct *wt) | ||
3114 | { | ||
3115 | struct mwl8k_bss_info_changed_worker *worker = | ||
3116 | (struct mwl8k_bss_info_changed_worker *)wt; | ||
3117 | struct ieee80211_hw *hw = worker->header.hw; | ||
3118 | struct ieee80211_vif *vif = worker->vif; | ||
3119 | struct ieee80211_bss_conf *info = worker->info; | ||
3120 | u32 changed; | ||
3121 | int rc; | ||
3122 | |||
3123 | struct mwl8k_priv *priv = hw->priv; | ||
3124 | struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif); | ||
3125 | |||
3126 | changed = worker->changed; | ||
3127 | priv->capture_beacon = false; | ||
3128 | |||
3129 | if (info->assoc) { | ||
3130 | memcpy(&mwl8k_vif->bss_info, info, | ||
3131 | sizeof(struct ieee80211_bss_conf)); | ||
3132 | |||
3133 | /* Install rates */ | ||
3134 | if (mwl8k_update_rateset(hw, vif)) | ||
3135 | goto mwl8k_bss_info_changed_exit; | ||
3136 | |||
3137 | /* Turn on rate adaptation */ | ||
3138 | if (mwl8k_cmd_use_fixed_rate(hw, MWL8K_USE_AUTO_RATE, | ||
3139 | MWL8K_UCAST_RATE, NULL)) | ||
3140 | goto mwl8k_bss_info_changed_exit; | ||
3141 | |||
3142 | /* Set radio preamble */ | ||
3143 | if (mwl8k_set_radio_preamble(hw, | ||
3144 | info->use_short_preamble)) | ||
3145 | goto mwl8k_bss_info_changed_exit; | ||
3146 | |||
3147 | /* Set slot time */ | ||
3148 | if (mwl8k_cmd_set_slot(hw, info->use_short_slot ? | ||
3149 | MWL8K_SHORT_SLOTTIME : MWL8K_LONG_SLOTTIME)) | ||
3150 | goto mwl8k_bss_info_changed_exit; | ||
3151 | |||
3152 | /* Update peer rate info */ | ||
3153 | if (mwl8k_cmd_update_sta_db(hw, vif, | ||
3154 | MWL8K_STA_DB_MODIFY_ENTRY)) | ||
3155 | goto mwl8k_bss_info_changed_exit; | ||
3156 | |||
3157 | /* Set AID */ | ||
3158 | if (mwl8k_cmd_set_aid(hw, vif)) | ||
3159 | goto mwl8k_bss_info_changed_exit; | ||
3160 | |||
3161 | /* | ||
3162 | * Finalize the join. Tell rx handler to process | ||
3163 | * next beacon from our BSSID. | ||
3164 | */ | ||
3165 | memcpy(priv->capture_bssid, | ||
3166 | mwl8k_vif->bssid, IEEE80211_ADDR_LEN); | ||
3167 | priv->capture_beacon = true; | ||
3168 | } else { | ||
3169 | mwl8k_cmd_update_sta_db(hw, vif, MWL8K_STA_DB_DEL_ENTRY); | ||
3170 | memset(&mwl8k_vif->bss_info, 0, | ||
3171 | sizeof(struct ieee80211_bss_conf)); | ||
3172 | memset(mwl8k_vif->bssid, 0, IEEE80211_ADDR_LEN); | ||
3173 | } | ||
3174 | |||
3175 | mwl8k_bss_info_changed_exit: | ||
3176 | rc = 0; | ||
3177 | return rc; | ||
3178 | } | ||
3179 | |||
3180 | static void mwl8k_bss_info_changed(struct ieee80211_hw *hw, | ||
3181 | struct ieee80211_vif *vif, | ||
3182 | struct ieee80211_bss_conf *info, | ||
3183 | u32 changed) | ||
3184 | { | ||
3185 | struct mwl8k_bss_info_changed_worker *worker; | ||
3186 | struct mwl8k_priv *priv = hw->priv; | ||
3187 | int rc; | ||
3188 | |||
3189 | if ((changed & BSS_CHANGED_ASSOC) == 0) | ||
3190 | return; | ||
3191 | |||
3192 | worker = kzalloc(sizeof(*worker), GFP_KERNEL); | ||
3193 | if (worker == NULL) | ||
3194 | return; | ||
3195 | |||
3196 | worker->vif = vif; | ||
3197 | worker->info = info; | ||
3198 | worker->changed = changed; | ||
3199 | rc = mwl8k_queue_work(hw, &worker->header, | ||
3200 | priv->config_wq, | ||
3201 | mwl8k_bss_info_changed_wt); | ||
3202 | kfree(worker); | ||
3203 | if (rc == -ETIMEDOUT) | ||
3204 | printk(KERN_ERR "%s() timed out\n", __func__); | ||
3205 | } | ||
3206 | |||
3207 | struct mwl8k_configure_filter_worker { | ||
3208 | struct mwl8k_work_struct header; | ||
3209 | unsigned int changed_flags; | ||
3210 | unsigned int *total_flags; | ||
3211 | int mc_count; | ||
3212 | struct dev_addr_list *mclist; | ||
3213 | }; | ||
3214 | |||
3215 | #define MWL8K_SUPPORTED_IF_FLAGS FIF_BCN_PRBRESP_PROMISC | ||
3216 | |||
3217 | static int mwl8k_configure_filter_wt(struct work_struct *wt) | ||
3218 | { | ||
3219 | struct mwl8k_configure_filter_worker *worker = | ||
3220 | (struct mwl8k_configure_filter_worker *)wt; | ||
3221 | |||
3222 | struct ieee80211_hw *hw = worker->header.hw; | ||
3223 | unsigned int changed_flags = worker->changed_flags; | ||
3224 | unsigned int *total_flags = worker->total_flags; | ||
3225 | int mc_count = worker->mc_count; | ||
3226 | struct dev_addr_list *mclist = worker->mclist; | ||
3227 | |||
3228 | struct mwl8k_priv *priv = hw->priv; | ||
3229 | struct mwl8k_vif *mv_vif; | ||
3230 | int rc = 0; | ||
3231 | |||
3232 | if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { | ||
3233 | if (*total_flags & FIF_BCN_PRBRESP_PROMISC) | ||
3234 | rc = mwl8k_cmd_set_pre_scan(hw); | ||
3235 | else { | ||
3236 | mv_vif = MWL8K_VIF(priv->vif); | ||
3237 | rc = mwl8k_cmd_set_post_scan(hw, mv_vif->bssid); | ||
3238 | } | ||
3239 | } | ||
3240 | |||
3241 | if (rc) | ||
3242 | goto mwl8k_configure_filter_exit; | ||
3243 | if (mc_count) { | ||
3244 | mc_count = mc_count < priv->num_mcaddrs ? | ||
3245 | mc_count : priv->num_mcaddrs; | ||
3246 | rc = mwl8k_cmd_mac_multicast_adr(hw, mc_count, mclist); | ||
3247 | if (rc) | ||
3248 | printk(KERN_ERR | ||
3249 | "%s()Error setting multicast addresses\n", | ||
3250 | __func__); | ||
3251 | } | ||
3252 | |||
3253 | mwl8k_configure_filter_exit: | ||
3254 | return rc; | ||
3255 | } | ||
3256 | |||
3257 | static void mwl8k_configure_filter(struct ieee80211_hw *hw, | ||
3258 | unsigned int changed_flags, | ||
3259 | unsigned int *total_flags, | ||
3260 | int mc_count, | ||
3261 | struct dev_addr_list *mclist) | ||
3262 | { | ||
3263 | |||
3264 | struct mwl8k_configure_filter_worker *worker; | ||
3265 | struct mwl8k_priv *priv = hw->priv; | ||
3266 | |||
3267 | /* Clear unsupported feature flags */ | ||
3268 | *total_flags &= MWL8K_SUPPORTED_IF_FLAGS; | ||
3269 | |||
3270 | if (!(changed_flags & MWL8K_SUPPORTED_IF_FLAGS) && !mc_count) | ||
3271 | return; | ||
3272 | |||
3273 | worker = kzalloc(sizeof(*worker), GFP_ATOMIC); | ||
3274 | if (worker == NULL) | ||
3275 | return; | ||
3276 | |||
3277 | worker->header.options = MWL8K_WQ_QUEUE_ONLY | MWL8K_WQ_TX_WAIT_EMPTY; | ||
3278 | worker->changed_flags = changed_flags; | ||
3279 | worker->total_flags = total_flags; | ||
3280 | worker->mc_count = mc_count; | ||
3281 | worker->mclist = mclist; | ||
3282 | |||
3283 | mwl8k_queue_work(hw, &worker->header, priv->config_wq, | ||
3284 | mwl8k_configure_filter_wt); | ||
3285 | } | ||
3286 | |||
3287 | struct mwl8k_set_rts_threshold_worker { | ||
3288 | struct mwl8k_work_struct header; | ||
3289 | u32 value; | ||
3290 | }; | ||
3291 | |||
3292 | static int mwl8k_set_rts_threshold_wt(struct work_struct *wt) | ||
3293 | { | ||
3294 | struct mwl8k_set_rts_threshold_worker *worker = | ||
3295 | (struct mwl8k_set_rts_threshold_worker *)wt; | ||
3296 | |||
3297 | struct ieee80211_hw *hw = worker->header.hw; | ||
3298 | u16 threshold = (u16)(worker->value); | ||
3299 | int rc; | ||
3300 | |||
3301 | rc = mwl8k_rts_threshold(hw, MWL8K_CMD_SET, &threshold); | ||
3302 | |||
3303 | return rc; | ||
3304 | } | ||
3305 | |||
3306 | static int mwl8k_set_rts_threshold(struct ieee80211_hw *hw, u32 value) | ||
3307 | { | ||
3308 | int rc; | ||
3309 | struct mwl8k_set_rts_threshold_worker *worker; | ||
3310 | struct mwl8k_priv *priv = hw->priv; | ||
3311 | |||
3312 | worker = kzalloc(sizeof(*worker), GFP_KERNEL); | ||
3313 | if (worker == NULL) | ||
3314 | return -ENOMEM; | ||
3315 | |||
3316 | worker->value = value; | ||
3317 | |||
3318 | rc = mwl8k_queue_work(hw, &worker->header, | ||
3319 | priv->config_wq, | ||
3320 | mwl8k_set_rts_threshold_wt); | ||
3321 | kfree(worker); | ||
3322 | |||
3323 | if (rc == -ETIMEDOUT) { | ||
3324 | printk(KERN_ERR "%s() timed out\n", __func__); | ||
3325 | rc = -EINVAL; | ||
3326 | } | ||
3327 | |||
3328 | return rc; | ||
3329 | } | ||
3330 | |||
3331 | struct mwl8k_conf_tx_worker { | ||
3332 | struct mwl8k_work_struct header; | ||
3333 | u16 queue; | ||
3334 | const struct ieee80211_tx_queue_params *params; | ||
3335 | }; | ||
3336 | |||
3337 | static int mwl8k_conf_tx_wt(struct work_struct *wt) | ||
3338 | { | ||
3339 | struct mwl8k_conf_tx_worker *worker = | ||
3340 | (struct mwl8k_conf_tx_worker *)wt; | ||
3341 | |||
3342 | struct ieee80211_hw *hw = worker->header.hw; | ||
3343 | u16 queue = worker->queue; | ||
3344 | const struct ieee80211_tx_queue_params *params = worker->params; | ||
3345 | |||
3346 | struct mwl8k_priv *priv = hw->priv; | ||
3347 | int rc = 0; | ||
3348 | |||
3349 | if (priv->wmm_mode == MWL8K_WMM_DISABLE) | ||
3350 | if (mwl8k_set_wmm(hw, MWL8K_WMM_ENABLE)) { | ||
3351 | rc = -EINVAL; | ||
3352 | goto mwl8k_conf_tx_exit; | ||
3353 | } | ||
3354 | |||
3355 | if (mwl8k_set_edca_params(hw, GET_TXQ(queue), params->cw_min, | ||
3356 | params->cw_max, params->aifs, params->txop)) | ||
3357 | rc = -EINVAL; | ||
3358 | mwl8k_conf_tx_exit: | ||
3359 | return rc; | ||
3360 | } | ||
3361 | |||
3362 | static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue, | ||
3363 | const struct ieee80211_tx_queue_params *params) | ||
3364 | { | ||
3365 | int rc; | ||
3366 | struct mwl8k_conf_tx_worker *worker; | ||
3367 | struct mwl8k_priv *priv = hw->priv; | ||
3368 | |||
3369 | worker = kzalloc(sizeof(*worker), GFP_KERNEL); | ||
3370 | if (worker == NULL) | ||
3371 | return -ENOMEM; | ||
3372 | |||
3373 | worker->queue = queue; | ||
3374 | worker->params = params; | ||
3375 | rc = mwl8k_queue_work(hw, &worker->header, | ||
3376 | priv->config_wq, mwl8k_conf_tx_wt); | ||
3377 | kfree(worker); | ||
3378 | if (rc == -ETIMEDOUT) { | ||
3379 | printk(KERN_ERR "%s() timed out\n", __func__); | ||
3380 | rc = -EINVAL; | ||
3381 | } | ||
3382 | return rc; | ||
3383 | } | ||
3384 | |||
3385 | static int mwl8k_get_tx_stats(struct ieee80211_hw *hw, | ||
3386 | struct ieee80211_tx_queue_stats *stats) | ||
3387 | { | ||
3388 | struct mwl8k_priv *priv = hw->priv; | ||
3389 | struct mwl8k_tx_queue *txq; | ||
3390 | int index; | ||
3391 | |||
3392 | spin_lock_bh(&priv->tx_lock); | ||
3393 | for (index = 0; index < MWL8K_TX_QUEUES; index++) { | ||
3394 | txq = priv->txq + index; | ||
3395 | memcpy(&stats[index], &txq->tx_stats, | ||
3396 | sizeof(struct ieee80211_tx_queue_stats)); | ||
3397 | } | ||
3398 | spin_unlock_bh(&priv->tx_lock); | ||
3399 | return 0; | ||
3400 | } | ||
3401 | |||
3402 | struct mwl8k_get_stats_worker { | ||
3403 | struct mwl8k_work_struct header; | ||
3404 | struct ieee80211_low_level_stats *stats; | ||
3405 | }; | ||
3406 | |||
3407 | static int mwl8k_get_stats_wt(struct work_struct *wt) | ||
3408 | { | ||
3409 | struct mwl8k_get_stats_worker *worker = | ||
3410 | (struct mwl8k_get_stats_worker *)wt; | ||
3411 | |||
3412 | return mwl8k_cmd_802_11_get_stat(worker->header.hw, worker->stats); | ||
3413 | } | ||
3414 | |||
3415 | static int mwl8k_get_stats(struct ieee80211_hw *hw, | ||
3416 | struct ieee80211_low_level_stats *stats) | ||
3417 | { | ||
3418 | int rc; | ||
3419 | struct mwl8k_get_stats_worker *worker; | ||
3420 | struct mwl8k_priv *priv = hw->priv; | ||
3421 | |||
3422 | worker = kzalloc(sizeof(*worker), GFP_KERNEL); | ||
3423 | if (worker == NULL) | ||
3424 | return -ENOMEM; | ||
3425 | |||
3426 | worker->stats = stats; | ||
3427 | rc = mwl8k_queue_work(hw, &worker->header, | ||
3428 | priv->config_wq, mwl8k_get_stats_wt); | ||
3429 | |||
3430 | kfree(worker); | ||
3431 | if (rc == -ETIMEDOUT) { | ||
3432 | printk(KERN_ERR "%s() timed out\n", __func__); | ||
3433 | rc = -EINVAL; | ||
3434 | } | ||
3435 | |||
3436 | return rc; | ||
3437 | } | ||
3438 | |||
3439 | static const struct ieee80211_ops mwl8k_ops = { | ||
3440 | .tx = mwl8k_tx, | ||
3441 | .start = mwl8k_start, | ||
3442 | .stop = mwl8k_stop, | ||
3443 | .add_interface = mwl8k_add_interface, | ||
3444 | .remove_interface = mwl8k_remove_interface, | ||
3445 | .config = mwl8k_config, | ||
3446 | .config_interface = mwl8k_config_interface, | ||
3447 | .bss_info_changed = mwl8k_bss_info_changed, | ||
3448 | .configure_filter = mwl8k_configure_filter, | ||
3449 | .set_rts_threshold = mwl8k_set_rts_threshold, | ||
3450 | .conf_tx = mwl8k_conf_tx, | ||
3451 | .get_tx_stats = mwl8k_get_tx_stats, | ||
3452 | .get_stats = mwl8k_get_stats, | ||
3453 | }; | ||
3454 | |||
3455 | static void mwl8k_tx_reclaim_handler(unsigned long data) | ||
3456 | { | ||
3457 | int i; | ||
3458 | struct ieee80211_hw *hw = (struct ieee80211_hw *) data; | ||
3459 | struct mwl8k_priv *priv = hw->priv; | ||
3460 | |||
3461 | spin_lock_bh(&priv->tx_lock); | ||
3462 | for (i = 0; i < MWL8K_TX_QUEUES; i++) | ||
3463 | mwl8k_txq_reclaim(hw, i, 0); | ||
3464 | |||
3465 | if (priv->tx_wait != NULL) { | ||
3466 | int count = mwl8k_txq_busy(priv); | ||
3467 | if (count == 0) { | ||
3468 | complete(priv->tx_wait); | ||
3469 | priv->tx_wait = NULL; | ||
3470 | } | ||
3471 | } | ||
3472 | spin_unlock_bh(&priv->tx_lock); | ||
3473 | } | ||
3474 | |||
3475 | static void mwl8k_finalize_join_worker(struct work_struct *work) | ||
3476 | { | ||
3477 | struct mwl8k_priv *priv = | ||
3478 | container_of(work, struct mwl8k_priv, finalize_join_worker); | ||
3479 | struct sk_buff *skb = priv->beacon_skb; | ||
3480 | u8 dtim = (MWL8K_VIF(priv->vif))->bss_info.dtim_period; | ||
3481 | |||
3482 | mwl8k_finalize_join(priv->hw, skb->data, skb->len, dtim); | ||
3483 | dev_kfree_skb(skb); | ||
3484 | |||
3485 | priv->beacon_skb = NULL; | ||
3486 | } | ||
3487 | |||
3488 | static int __devinit mwl8k_probe(struct pci_dev *pdev, | ||
3489 | const struct pci_device_id *id) | ||
3490 | { | ||
3491 | struct ieee80211_hw *hw; | ||
3492 | struct mwl8k_priv *priv; | ||
3493 | DECLARE_MAC_BUF(mac); | ||
3494 | int rc; | ||
3495 | int i; | ||
3496 | u8 *fw; | ||
3497 | |||
3498 | rc = pci_enable_device(pdev); | ||
3499 | if (rc) { | ||
3500 | printk(KERN_ERR "%s: Cannot enable new PCI device\n", | ||
3501 | MWL8K_NAME); | ||
3502 | return rc; | ||
3503 | } | ||
3504 | |||
3505 | rc = pci_request_regions(pdev, MWL8K_NAME); | ||
3506 | if (rc) { | ||
3507 | printk(KERN_ERR "%s: Cannot obtain PCI resources\n", | ||
3508 | MWL8K_NAME); | ||
3509 | return rc; | ||
3510 | } | ||
3511 | |||
3512 | pci_set_master(pdev); | ||
3513 | |||
3514 | hw = ieee80211_alloc_hw(sizeof(*priv), &mwl8k_ops); | ||
3515 | if (hw == NULL) { | ||
3516 | printk(KERN_ERR "%s: ieee80211 alloc failed\n", MWL8K_NAME); | ||
3517 | rc = -ENOMEM; | ||
3518 | goto err_free_reg; | ||
3519 | } | ||
3520 | |||
3521 | priv = hw->priv; | ||
3522 | priv->hw = hw; | ||
3523 | priv->pdev = pdev; | ||
3524 | priv->hostcmd_wait = NULL; | ||
3525 | priv->tx_wait = NULL; | ||
3526 | priv->inconfig = false; | ||
3527 | priv->wep_enabled = 0; | ||
3528 | priv->wmm_mode = false; | ||
3529 | priv->pending_tx_pkts = 0; | ||
3530 | strncpy(priv->name, MWL8K_NAME, sizeof(priv->name)); | ||
3531 | |||
3532 | spin_lock_init(&priv->fw_lock); | ||
3533 | |||
3534 | SET_IEEE80211_DEV(hw, &pdev->dev); | ||
3535 | pci_set_drvdata(pdev, hw); | ||
3536 | |||
3537 | priv->regs = pci_iomap(pdev, 1, 0x10000); | ||
3538 | if (priv->regs == NULL) { | ||
3539 | printk(KERN_ERR "%s: Cannot map device memory\n", priv->name); | ||
3540 | goto err_iounmap; | ||
3541 | } | ||
3542 | |||
3543 | memcpy(priv->channels, mwl8k_channels, sizeof(mwl8k_channels)); | ||
3544 | priv->band.band = IEEE80211_BAND_2GHZ; | ||
3545 | priv->band.channels = priv->channels; | ||
3546 | priv->band.n_channels = ARRAY_SIZE(mwl8k_channels); | ||
3547 | priv->band.bitrates = priv->rates; | ||
3548 | priv->band.n_bitrates = ARRAY_SIZE(mwl8k_rates); | ||
3549 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; | ||
3550 | |||
3551 | BUILD_BUG_ON(sizeof(priv->rates) != sizeof(mwl8k_rates)); | ||
3552 | memcpy(priv->rates, mwl8k_rates, sizeof(mwl8k_rates)); | ||
3553 | |||
3554 | /* | ||
3555 | * Extra headroom is the size of the required DMA header | ||
3556 | * minus the size of the smallest 802.11 frame (CTS frame). | ||
3557 | */ | ||
3558 | hw->extra_tx_headroom = | ||
3559 | sizeof(struct mwl8k_dma_data) - sizeof(struct ieee80211_cts); | ||
3560 | |||
3561 | hw->channel_change_time = 10; | ||
3562 | |||
3563 | hw->queues = MWL8K_TX_QUEUES; | ||
3564 | |||
3565 | hw->wiphy->interface_modes = | ||
3566 | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_MONITOR); | ||
3567 | |||
3568 | /* Set rssi and noise values to dBm */ | ||
3569 | hw->flags |= (IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM); | ||
3570 | hw->vif_data_size = sizeof(struct mwl8k_vif); | ||
3571 | priv->vif = NULL; | ||
3572 | |||
3573 | /* Set default radio state and preamble */ | ||
3574 | priv->radio_preamble = MWL8K_RADIO_DEFAULT_PREAMBLE; | ||
3575 | priv->radio_state = MWL8K_RADIO_DISABLE; | ||
3576 | |||
3577 | /* Finalize join worker */ | ||
3578 | INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker); | ||
3579 | |||
3580 | /* TX reclaim tasklet */ | ||
3581 | tasklet_init(&priv->tx_reclaim_task, | ||
3582 | mwl8k_tx_reclaim_handler, (unsigned long)hw); | ||
3583 | tasklet_disable(&priv->tx_reclaim_task); | ||
3584 | |||
3585 | /* Config workthread */ | ||
3586 | priv->config_wq = create_singlethread_workqueue("mwl8k_config"); | ||
3587 | if (priv->config_wq == NULL) | ||
3588 | goto err_iounmap; | ||
3589 | |||
3590 | /* Power management cookie */ | ||
3591 | priv->cookie = pci_alloc_consistent(priv->pdev, 4, &priv->cookie_dma); | ||
3592 | if (priv->cookie == NULL) | ||
3593 | goto err_iounmap; | ||
3594 | |||
3595 | rc = mwl8k_rxq_init(hw, 0); | ||
3596 | if (rc) | ||
3597 | goto err_iounmap; | ||
3598 | rxq_refill(hw, 0, INT_MAX); | ||
3599 | |||
3600 | spin_lock_init(&priv->tx_lock); | ||
3601 | |||
3602 | for (i = 0; i < MWL8K_TX_QUEUES; i++) { | ||
3603 | rc = mwl8k_txq_init(hw, i); | ||
3604 | if (rc) | ||
3605 | goto err_free_queues; | ||
3606 | } | ||
3607 | |||
3608 | iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); | ||
3609 | priv->int_mask = 0; | ||
3610 | iowrite32(priv->int_mask, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); | ||
3611 | iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL); | ||
3612 | iowrite32(0xffffffff, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK); | ||
3613 | |||
3614 | rc = request_irq(priv->pdev->irq, &mwl8k_interrupt, | ||
3615 | IRQF_SHARED, MWL8K_NAME, hw); | ||
3616 | if (rc) { | ||
3617 | printk(KERN_ERR "%s: failed to register IRQ handler\n", | ||
3618 | priv->name); | ||
3619 | goto err_free_queues; | ||
3620 | } | ||
3621 | |||
3622 | /* Reset firmware and hardware */ | ||
3623 | mwl8k_hw_reset(priv); | ||
3624 | |||
3625 | /* Ask userland hotplug daemon for the device firmware */ | ||
3626 | rc = mwl8k_request_firmware(priv, (u32)id->driver_data); | ||
3627 | if (rc) { | ||
3628 | printk(KERN_ERR "%s: Firmware files not found\n", priv->name); | ||
3629 | goto err_free_irq; | ||
3630 | } | ||
3631 | |||
3632 | /* Load firmware into hardware */ | ||
3633 | rc = mwl8k_load_firmware(priv); | ||
3634 | if (rc) { | ||
3635 | printk(KERN_ERR "%s: Cannot start firmware\n", priv->name); | ||
3636 | goto err_stop_firmware; | ||
3637 | } | ||
3638 | |||
3639 | /* Reclaim memory once firmware is successfully loaded */ | ||
3640 | mwl8k_release_firmware(priv); | ||
3641 | |||
3642 | /* | ||
3643 | * Temporarily enable interrupts. Initial firmware host | ||
3644 | * commands use interrupts and avoids polling. Disable | ||
3645 | * interrupts when done. | ||
3646 | */ | ||
3647 | priv->int_mask |= MWL8K_A2H_EVENTS; | ||
3648 | |||
3649 | iowrite32(priv->int_mask, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); | ||
3650 | |||
3651 | /* Get config data, mac addrs etc */ | ||
3652 | rc = mwl8k_cmd_get_hw_spec(hw); | ||
3653 | if (rc) { | ||
3654 | printk(KERN_ERR "%s: Cannot initialise firmware\n", priv->name); | ||
3655 | goto err_stop_firmware; | ||
3656 | } | ||
3657 | |||
3658 | /* Turn radio off */ | ||
3659 | rc = mwl8k_cmd_802_11_radio_control(hw, MWL8K_RADIO_DISABLE); | ||
3660 | if (rc) { | ||
3661 | printk(KERN_ERR "%s: Cannot disable\n", priv->name); | ||
3662 | goto err_stop_firmware; | ||
3663 | } | ||
3664 | |||
3665 | /* Disable interrupts */ | ||
3666 | spin_lock_irq(&priv->tx_lock); | ||
3667 | iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); | ||
3668 | spin_unlock_irq(&priv->tx_lock); | ||
3669 | free_irq(priv->pdev->irq, hw); | ||
3670 | |||
3671 | rc = ieee80211_register_hw(hw); | ||
3672 | if (rc) { | ||
3673 | printk(KERN_ERR "%s: Cannot register device\n", priv->name); | ||
3674 | goto err_stop_firmware; | ||
3675 | } | ||
3676 | |||
3677 | fw = (u8 *)&priv->fw_rev; | ||
3678 | printk(KERN_INFO "%s: 88W%u %s\n", priv->name, priv->part_num, | ||
3679 | MWL8K_DESC); | ||
3680 | printk(KERN_INFO "%s: Driver Ver:%s Firmware Ver:%u.%u.%u.%u\n", | ||
3681 | priv->name, MWL8K_VERSION, fw[3], fw[2], fw[1], fw[0]); | ||
3682 | printk(KERN_INFO "%s: MAC Address: %s\n", priv->name, | ||
3683 | print_mac(mac, hw->wiphy->perm_addr)); | ||
3684 | |||
3685 | return 0; | ||
3686 | |||
3687 | err_stop_firmware: | ||
3688 | mwl8k_hw_reset(priv); | ||
3689 | mwl8k_release_firmware(priv); | ||
3690 | |||
3691 | err_free_irq: | ||
3692 | spin_lock_irq(&priv->tx_lock); | ||
3693 | iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); | ||
3694 | spin_unlock_irq(&priv->tx_lock); | ||
3695 | free_irq(priv->pdev->irq, hw); | ||
3696 | |||
3697 | err_free_queues: | ||
3698 | for (i = 0; i < MWL8K_TX_QUEUES; i++) | ||
3699 | mwl8k_txq_deinit(hw, i); | ||
3700 | mwl8k_rxq_deinit(hw, 0); | ||
3701 | |||
3702 | err_iounmap: | ||
3703 | if (priv->cookie != NULL) | ||
3704 | pci_free_consistent(priv->pdev, 4, | ||
3705 | priv->cookie, priv->cookie_dma); | ||
3706 | |||
3707 | if (priv->regs != NULL) | ||
3708 | pci_iounmap(pdev, priv->regs); | ||
3709 | |||
3710 | if (priv->config_wq != NULL) | ||
3711 | destroy_workqueue(priv->config_wq); | ||
3712 | |||
3713 | pci_set_drvdata(pdev, NULL); | ||
3714 | ieee80211_free_hw(hw); | ||
3715 | |||
3716 | err_free_reg: | ||
3717 | pci_release_regions(pdev); | ||
3718 | pci_disable_device(pdev); | ||
3719 | |||
3720 | return rc; | ||
3721 | } | ||
3722 | |||
3723 | static void __devexit mwl8k_remove(struct pci_dev *pdev) | ||
3724 | { | ||
3725 | printk(KERN_ERR "===>%s(%u)\n", __func__, __LINE__); | ||
3726 | } | ||
3727 | |||
3728 | static void __devexit mwl8k_shutdown(struct pci_dev *pdev) | ||
3729 | { | ||
3730 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | ||
3731 | struct mwl8k_priv *priv; | ||
3732 | int i; | ||
3733 | |||
3734 | if (hw == NULL) | ||
3735 | return; | ||
3736 | priv = hw->priv; | ||
3737 | |||
3738 | ieee80211_stop_queues(hw); | ||
3739 | |||
3740 | /* Remove tx reclaim tasklet */ | ||
3741 | tasklet_kill(&priv->tx_reclaim_task); | ||
3742 | |||
3743 | /* Stop config thread */ | ||
3744 | destroy_workqueue(priv->config_wq); | ||
3745 | |||
3746 | /* Stop hardware */ | ||
3747 | mwl8k_hw_reset(priv); | ||
3748 | |||
3749 | /* Return all skbs to mac80211 */ | ||
3750 | for (i = 0; i < MWL8K_TX_QUEUES; i++) | ||
3751 | mwl8k_txq_reclaim(hw, i, 1); | ||
3752 | |||
3753 | ieee80211_unregister_hw(hw); | ||
3754 | |||
3755 | for (i = 0; i < MWL8K_TX_QUEUES; i++) | ||
3756 | mwl8k_txq_deinit(hw, i); | ||
3757 | |||
3758 | mwl8k_rxq_deinit(hw, 0); | ||
3759 | |||
3760 | pci_free_consistent(priv->pdev, 4, | ||
3761 | priv->cookie, priv->cookie_dma); | ||
3762 | |||
3763 | pci_iounmap(pdev, priv->regs); | ||
3764 | pci_set_drvdata(pdev, NULL); | ||
3765 | ieee80211_free_hw(hw); | ||
3766 | pci_release_regions(pdev); | ||
3767 | pci_disable_device(pdev); | ||
3768 | } | ||
3769 | |||
3770 | static struct pci_driver mwl8k_driver = { | ||
3771 | .name = MWL8K_NAME, | ||
3772 | .id_table = mwl8k_table, | ||
3773 | .probe = mwl8k_probe, | ||
3774 | .remove = __devexit_p(mwl8k_remove), | ||
3775 | .shutdown = __devexit_p(mwl8k_shutdown), | ||
3776 | }; | ||
3777 | |||
3778 | static int __init mwl8k_init(void) | ||
3779 | { | ||
3780 | return pci_register_driver(&mwl8k_driver); | ||
3781 | } | ||
3782 | |||
3783 | static void __exit mwl8k_exit(void) | ||
3784 | { | ||
3785 | pci_unregister_driver(&mwl8k_driver); | ||
3786 | } | ||
3787 | |||
3788 | module_init(mwl8k_init); | ||
3789 | module_exit(mwl8k_exit); | ||
diff --git a/drivers/net/wireless/orinoco/fw.c b/drivers/net/wireless/orinoco/fw.c index e7abb45d6753..1084b43e04bc 100644 --- a/drivers/net/wireless/orinoco/fw.c +++ b/drivers/net/wireless/orinoco/fw.c | |||
@@ -70,6 +70,19 @@ static const char *validate_fw(const struct orinoco_fw_header *hdr, size_t len) | |||
70 | return NULL; | 70 | return NULL; |
71 | } | 71 | } |
72 | 72 | ||
73 | #if defined(CONFIG_HERMES_CACHE_FW_ON_INIT) || defined(CONFIG_PM_SLEEP) | ||
74 | static inline const struct firmware * | ||
75 | orinoco_cached_fw_get(struct orinoco_private *priv, bool primary) | ||
76 | { | ||
77 | if (primary) | ||
78 | return priv->cached_pri_fw; | ||
79 | else | ||
80 | return priv->cached_fw; | ||
81 | } | ||
82 | #else | ||
83 | #define orinoco_cached_fw_get(priv, primary) (NULL) | ||
84 | #endif | ||
85 | |||
73 | /* Download either STA or AP firmware into the card. */ | 86 | /* Download either STA or AP firmware into the card. */ |
74 | static int | 87 | static int |
75 | orinoco_dl_firmware(struct orinoco_private *priv, | 88 | orinoco_dl_firmware(struct orinoco_private *priv, |
@@ -107,7 +120,7 @@ orinoco_dl_firmware(struct orinoco_private *priv, | |||
107 | if (err) | 120 | if (err) |
108 | goto free; | 121 | goto free; |
109 | 122 | ||
110 | if (!priv->cached_fw) { | 123 | if (!orinoco_cached_fw_get(priv, false)) { |
111 | err = request_firmware(&fw_entry, firmware, priv->dev); | 124 | err = request_firmware(&fw_entry, firmware, priv->dev); |
112 | 125 | ||
113 | if (err) { | 126 | if (err) { |
@@ -117,7 +130,7 @@ orinoco_dl_firmware(struct orinoco_private *priv, | |||
117 | goto free; | 130 | goto free; |
118 | } | 131 | } |
119 | } else | 132 | } else |
120 | fw_entry = priv->cached_fw; | 133 | fw_entry = orinoco_cached_fw_get(priv, false); |
121 | 134 | ||
122 | hdr = (const struct orinoco_fw_header *) fw_entry->data; | 135 | hdr = (const struct orinoco_fw_header *) fw_entry->data; |
123 | 136 | ||
@@ -170,7 +183,7 @@ orinoco_dl_firmware(struct orinoco_private *priv, | |||
170 | 183 | ||
171 | abort: | 184 | abort: |
172 | /* If we requested the firmware, release it. */ | 185 | /* If we requested the firmware, release it. */ |
173 | if (!priv->cached_fw) | 186 | if (!orinoco_cached_fw_get(priv, false)) |
174 | release_firmware(fw_entry); | 187 | release_firmware(fw_entry); |
175 | 188 | ||
176 | free: | 189 | free: |
@@ -273,20 +286,20 @@ symbol_dl_firmware(struct orinoco_private *priv, | |||
273 | int ret; | 286 | int ret; |
274 | const struct firmware *fw_entry; | 287 | const struct firmware *fw_entry; |
275 | 288 | ||
276 | if (!priv->cached_pri_fw) { | 289 | if (!orinoco_cached_fw_get(priv, true)) { |
277 | if (request_firmware(&fw_entry, fw->pri_fw, priv->dev) != 0) { | 290 | if (request_firmware(&fw_entry, fw->pri_fw, priv->dev) != 0) { |
278 | printk(KERN_ERR "%s: Cannot find firmware: %s\n", | 291 | printk(KERN_ERR "%s: Cannot find firmware: %s\n", |
279 | dev->name, fw->pri_fw); | 292 | dev->name, fw->pri_fw); |
280 | return -ENOENT; | 293 | return -ENOENT; |
281 | } | 294 | } |
282 | } else | 295 | } else |
283 | fw_entry = priv->cached_pri_fw; | 296 | fw_entry = orinoco_cached_fw_get(priv, true); |
284 | 297 | ||
285 | /* Load primary firmware */ | 298 | /* Load primary firmware */ |
286 | ret = symbol_dl_image(priv, fw, fw_entry->data, | 299 | ret = symbol_dl_image(priv, fw, fw_entry->data, |
287 | fw_entry->data + fw_entry->size, 0); | 300 | fw_entry->data + fw_entry->size, 0); |
288 | 301 | ||
289 | if (!priv->cached_pri_fw) | 302 | if (!orinoco_cached_fw_get(priv, true)) |
290 | release_firmware(fw_entry); | 303 | release_firmware(fw_entry); |
291 | if (ret) { | 304 | if (ret) { |
292 | printk(KERN_ERR "%s: Primary firmware download failed\n", | 305 | printk(KERN_ERR "%s: Primary firmware download failed\n", |
@@ -294,19 +307,19 @@ symbol_dl_firmware(struct orinoco_private *priv, | |||
294 | return ret; | 307 | return ret; |
295 | } | 308 | } |
296 | 309 | ||
297 | if (!priv->cached_fw) { | 310 | if (!orinoco_cached_fw_get(priv, false)) { |
298 | if (request_firmware(&fw_entry, fw->sta_fw, priv->dev) != 0) { | 311 | if (request_firmware(&fw_entry, fw->sta_fw, priv->dev) != 0) { |
299 | printk(KERN_ERR "%s: Cannot find firmware: %s\n", | 312 | printk(KERN_ERR "%s: Cannot find firmware: %s\n", |
300 | dev->name, fw->sta_fw); | 313 | dev->name, fw->sta_fw); |
301 | return -ENOENT; | 314 | return -ENOENT; |
302 | } | 315 | } |
303 | } else | 316 | } else |
304 | fw_entry = priv->cached_fw; | 317 | fw_entry = orinoco_cached_fw_get(priv, false); |
305 | 318 | ||
306 | /* Load secondary firmware */ | 319 | /* Load secondary firmware */ |
307 | ret = symbol_dl_image(priv, fw, fw_entry->data, | 320 | ret = symbol_dl_image(priv, fw, fw_entry->data, |
308 | fw_entry->data + fw_entry->size, 1); | 321 | fw_entry->data + fw_entry->size, 1); |
309 | if (!priv->cached_fw) | 322 | if (!orinoco_cached_fw_get(priv, false)) |
310 | release_firmware(fw_entry); | 323 | release_firmware(fw_entry); |
311 | if (ret) { | 324 | if (ret) { |
312 | printk(KERN_ERR "%s: Secondary firmware download failed\n", | 325 | printk(KERN_ERR "%s: Secondary firmware download failed\n", |
@@ -340,9 +353,9 @@ int orinoco_download(struct orinoco_private *priv) | |||
340 | return err; | 353 | return err; |
341 | } | 354 | } |
342 | 355 | ||
356 | #if defined(CONFIG_HERMES_CACHE_FW_ON_INIT) || defined(CONFIG_PM_SLEEP) | ||
343 | void orinoco_cache_fw(struct orinoco_private *priv, int ap) | 357 | void orinoco_cache_fw(struct orinoco_private *priv, int ap) |
344 | { | 358 | { |
345 | #if defined(CONFIG_HERMES_CACHE_FW_ON_INIT) || defined(CONFIG_PM_SLEEP) | ||
346 | const struct firmware *fw_entry = NULL; | 359 | const struct firmware *fw_entry = NULL; |
347 | const char *pri_fw; | 360 | const char *pri_fw; |
348 | const char *fw; | 361 | const char *fw; |
@@ -362,12 +375,10 @@ void orinoco_cache_fw(struct orinoco_private *priv, int ap) | |||
362 | if (request_firmware(&fw_entry, fw, priv->dev) == 0) | 375 | if (request_firmware(&fw_entry, fw, priv->dev) == 0) |
363 | priv->cached_fw = fw_entry; | 376 | priv->cached_fw = fw_entry; |
364 | } | 377 | } |
365 | #endif | ||
366 | } | 378 | } |
367 | 379 | ||
368 | void orinoco_uncache_fw(struct orinoco_private *priv) | 380 | void orinoco_uncache_fw(struct orinoco_private *priv) |
369 | { | 381 | { |
370 | #if defined(CONFIG_HERMES_CACHE_FW_ON_INIT) || defined(CONFIG_PM_SLEEP) | ||
371 | if (priv->cached_pri_fw) | 382 | if (priv->cached_pri_fw) |
372 | release_firmware(priv->cached_pri_fw); | 383 | release_firmware(priv->cached_pri_fw); |
373 | if (priv->cached_fw) | 384 | if (priv->cached_fw) |
@@ -375,5 +386,5 @@ void orinoco_uncache_fw(struct orinoco_private *priv) | |||
375 | 386 | ||
376 | priv->cached_pri_fw = NULL; | 387 | priv->cached_pri_fw = NULL; |
377 | priv->cached_fw = NULL; | 388 | priv->cached_fw = NULL; |
378 | #endif | ||
379 | } | 389 | } |
390 | #endif | ||
diff --git a/drivers/net/wireless/orinoco/fw.h b/drivers/net/wireless/orinoco/fw.h index 2290f0845d59..89fc26d25b06 100644 --- a/drivers/net/wireless/orinoco/fw.h +++ b/drivers/net/wireless/orinoco/fw.h | |||
@@ -10,7 +10,12 @@ struct orinoco_private; | |||
10 | 10 | ||
11 | int orinoco_download(struct orinoco_private *priv); | 11 | int orinoco_download(struct orinoco_private *priv); |
12 | 12 | ||
13 | #if defined(CONFIG_HERMES_CACHE_FW_ON_INIT) || defined(CONFIG_PM_SLEEP) | ||
13 | void orinoco_cache_fw(struct orinoco_private *priv, int ap); | 14 | void orinoco_cache_fw(struct orinoco_private *priv, int ap); |
14 | void orinoco_uncache_fw(struct orinoco_private *priv); | 15 | void orinoco_uncache_fw(struct orinoco_private *priv); |
16 | #else | ||
17 | #define orinoco_cache_fw(priv, ap) do { } while(0) | ||
18 | #define orinoco_uncache_fw(priv) do { } while (0) | ||
19 | #endif | ||
15 | 20 | ||
16 | #endif /* _ORINOCO_FW_H_ */ | 21 | #endif /* _ORINOCO_FW_H_ */ |
diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c index e9b1db77a735..345593c4accb 100644 --- a/drivers/net/wireless/orinoco/main.c +++ b/drivers/net/wireless/orinoco/main.c | |||
@@ -2580,8 +2580,10 @@ struct net_device | |||
2580 | netif_carrier_off(dev); | 2580 | netif_carrier_off(dev); |
2581 | priv->last_linkstatus = 0xffff; | 2581 | priv->last_linkstatus = 0xffff; |
2582 | 2582 | ||
2583 | #if defined(CONFIG_HERMES_CACHE_FW_ON_INIT) || defined(CONFIG_PM_SLEEP) | ||
2583 | priv->cached_pri_fw = NULL; | 2584 | priv->cached_pri_fw = NULL; |
2584 | priv->cached_fw = NULL; | 2585 | priv->cached_fw = NULL; |
2586 | #endif | ||
2585 | 2587 | ||
2586 | /* Register PM notifiers */ | 2588 | /* Register PM notifiers */ |
2587 | orinoco_register_pm_notifier(priv); | 2589 | orinoco_register_pm_notifier(priv); |
diff --git a/drivers/net/wireless/orinoco/orinoco.h b/drivers/net/wireless/orinoco/orinoco.h index f3f94b28ce6d..8e5a72cc297f 100644 --- a/drivers/net/wireless/orinoco/orinoco.h +++ b/drivers/net/wireless/orinoco/orinoco.h | |||
@@ -159,9 +159,11 @@ struct orinoco_private { | |||
159 | unsigned int tkip_cm_active:1; | 159 | unsigned int tkip_cm_active:1; |
160 | unsigned int key_mgmt:3; | 160 | unsigned int key_mgmt:3; |
161 | 161 | ||
162 | #if defined(CONFIG_HERMES_CACHE_FW_ON_INIT) || defined(CONFIG_PM_SLEEP) | ||
162 | /* Cached in memory firmware to use during ->resume. */ | 163 | /* Cached in memory firmware to use during ->resume. */ |
163 | const struct firmware *cached_pri_fw; | 164 | const struct firmware *cached_pri_fw; |
164 | const struct firmware *cached_fw; | 165 | const struct firmware *cached_fw; |
166 | #endif | ||
165 | 167 | ||
166 | struct notifier_block pm_notifier; | 168 | struct notifier_block pm_notifier; |
167 | }; | 169 | }; |
diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h index 94c3acd1fcaf..2dda5fe418b6 100644 --- a/drivers/net/wireless/p54/p54.h +++ b/drivers/net/wireless/p54/p54.h | |||
@@ -14,6 +14,10 @@ | |||
14 | * published by the Free Software Foundation. | 14 | * published by the Free Software Foundation. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #ifdef CONFIG_MAC80211_LEDS | ||
18 | #include <linux/leds.h> | ||
19 | #endif /* CONFIG_MAC80211_LEDS */ | ||
20 | |||
17 | enum p54_control_frame_types { | 21 | enum p54_control_frame_types { |
18 | P54_CONTROL_TYPE_SETUP = 0, | 22 | P54_CONTROL_TYPE_SETUP = 0, |
19 | P54_CONTROL_TYPE_SCAN, | 23 | P54_CONTROL_TYPE_SCAN, |
@@ -112,6 +116,21 @@ enum fw_state { | |||
112 | FW_STATE_RESETTING, | 116 | FW_STATE_RESETTING, |
113 | }; | 117 | }; |
114 | 118 | ||
119 | #ifdef CONFIG_MAC80211_LEDS | ||
120 | |||
121 | #define P54_LED_MAX_NAME_LEN 31 | ||
122 | |||
123 | struct p54_led_dev { | ||
124 | struct ieee80211_hw *hw_dev; | ||
125 | struct led_classdev led_dev; | ||
126 | char name[P54_LED_MAX_NAME_LEN + 1]; | ||
127 | |||
128 | unsigned int index; | ||
129 | unsigned int registered; | ||
130 | }; | ||
131 | |||
132 | #endif /* CONFIG_MAC80211_LEDS */ | ||
133 | |||
115 | struct p54_common { | 134 | struct p54_common { |
116 | struct ieee80211_hw *hw; | 135 | struct ieee80211_hw *hw; |
117 | u32 rx_start; | 136 | u32 rx_start; |
@@ -157,6 +176,12 @@ struct p54_common { | |||
157 | struct completion eeprom_comp; | 176 | struct completion eeprom_comp; |
158 | u8 privacy_caps; | 177 | u8 privacy_caps; |
159 | u8 rx_keycache_size; | 178 | u8 rx_keycache_size; |
179 | /* LED management */ | ||
180 | #ifdef CONFIG_MAC80211_LEDS | ||
181 | struct p54_led_dev assoc_led; | ||
182 | struct p54_led_dev tx_led; | ||
183 | #endif /* CONFIG_MAC80211_LEDS */ | ||
184 | u16 softled_state; /* bit field of glowing LEDs */ | ||
160 | }; | 185 | }; |
161 | 186 | ||
162 | int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb); | 187 | int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb); |
@@ -165,6 +190,7 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw); | |||
165 | int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len); | 190 | int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len); |
166 | int p54_read_eeprom(struct ieee80211_hw *dev); | 191 | int p54_read_eeprom(struct ieee80211_hw *dev); |
167 | struct ieee80211_hw *p54_init_common(size_t priv_data_len); | 192 | struct ieee80211_hw *p54_init_common(size_t priv_data_len); |
193 | int p54_register_common(struct ieee80211_hw *dev, struct device *pdev); | ||
168 | void p54_free_common(struct ieee80211_hw *dev); | 194 | void p54_free_common(struct ieee80211_hw *dev); |
169 | 195 | ||
170 | #endif /* P54_H */ | 196 | #endif /* P54_H */ |
diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 14438a642fdd..0a989834b70d 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c | |||
@@ -21,6 +21,9 @@ | |||
21 | #include <linux/etherdevice.h> | 21 | #include <linux/etherdevice.h> |
22 | 22 | ||
23 | #include <net/mac80211.h> | 23 | #include <net/mac80211.h> |
24 | #ifdef CONFIG_MAC80211_LEDS | ||
25 | #include <linux/leds.h> | ||
26 | #endif /* CONFIG_MAC80211_LEDS */ | ||
24 | 27 | ||
25 | #include "p54.h" | 28 | #include "p54.h" |
26 | #include "p54common.h" | 29 | #include "p54common.h" |
@@ -735,10 +738,7 @@ static int p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
735 | return 0; | 738 | return 0; |
736 | 739 | ||
737 | if (!(hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_IN_FCS_GOOD))) { | 740 | if (!(hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_IN_FCS_GOOD))) { |
738 | if (priv->filter_flags & FIF_FCSFAIL) | 741 | return 0; |
739 | rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; | ||
740 | else | ||
741 | return 0; | ||
742 | } | 742 | } |
743 | 743 | ||
744 | if (hdr->decrypt_status == P54_DECRYPT_OK) | 744 | if (hdr->decrypt_status == P54_DECRYPT_OK) |
@@ -1680,7 +1680,7 @@ static int p54_setup_mac(struct ieee80211_hw *dev) | |||
1680 | mode = P54_FILTER_TYPE_PROMISCUOUS; | 1680 | mode = P54_FILTER_TYPE_PROMISCUOUS; |
1681 | break; | 1681 | break; |
1682 | default: | 1682 | default: |
1683 | mode = P54_FILTER_TYPE_NONE; | 1683 | mode = P54_FILTER_TYPE_HIBERNATE; |
1684 | break; | 1684 | break; |
1685 | } | 1685 | } |
1686 | 1686 | ||
@@ -1693,7 +1693,7 @@ static int p54_setup_mac(struct ieee80211_hw *dev) | |||
1693 | (mode != P54_FILTER_TYPE_PROMISCUOUS)) | 1693 | (mode != P54_FILTER_TYPE_PROMISCUOUS)) |
1694 | mode |= P54_FILTER_TYPE_TRANSPARENT; | 1694 | mode |= P54_FILTER_TYPE_TRANSPARENT; |
1695 | } else | 1695 | } else |
1696 | mode = P54_FILTER_TYPE_RX_DISABLED; | 1696 | mode = P54_FILTER_TYPE_HIBERNATE; |
1697 | 1697 | ||
1698 | setup->mac_mode = cpu_to_le16(mode); | 1698 | setup->mac_mode = cpu_to_le16(mode); |
1699 | memcpy(setup->mac_addr, priv->mac_addr, ETH_ALEN); | 1699 | memcpy(setup->mac_addr, priv->mac_addr, ETH_ALEN); |
@@ -1871,7 +1871,7 @@ static int p54_scan(struct ieee80211_hw *dev, u16 mode, u16 dwell) | |||
1871 | return -EINVAL; | 1871 | return -EINVAL; |
1872 | } | 1872 | } |
1873 | 1873 | ||
1874 | static int p54_set_leds(struct ieee80211_hw *dev, int mode, int link, int act) | 1874 | static int p54_set_leds(struct ieee80211_hw *dev) |
1875 | { | 1875 | { |
1876 | struct p54_common *priv = dev->priv; | 1876 | struct p54_common *priv = dev->priv; |
1877 | struct sk_buff *skb; | 1877 | struct sk_buff *skb; |
@@ -1882,11 +1882,11 @@ static int p54_set_leds(struct ieee80211_hw *dev, int mode, int link, int act) | |||
1882 | if (!skb) | 1882 | if (!skb) |
1883 | return -ENOMEM; | 1883 | return -ENOMEM; |
1884 | 1884 | ||
1885 | led = (struct p54_led *)skb_put(skb, sizeof(*led)); | 1885 | led = (struct p54_led *) skb_put(skb, sizeof(*led)); |
1886 | led->mode = cpu_to_le16(mode); | 1886 | led->flags = cpu_to_le16(0x0003); |
1887 | led->led_permanent = cpu_to_le16(link); | 1887 | led->mask[0] = led->mask[1] = cpu_to_le16(priv->softled_state); |
1888 | led->led_temporary = cpu_to_le16(act); | 1888 | led->delay[0] = cpu_to_le16(1); |
1889 | led->duration = cpu_to_le16(1000); | 1889 | led->delay[1] = cpu_to_le16(0); |
1890 | priv->tx(dev, skb); | 1890 | priv->tx(dev, skb); |
1891 | return 0; | 1891 | return 0; |
1892 | } | 1892 | } |
@@ -2070,6 +2070,9 @@ static int p54_start(struct ieee80211_hw *dev) | |||
2070 | 2070 | ||
2071 | queue_delayed_work(dev->workqueue, &priv->work, 0); | 2071 | queue_delayed_work(dev->workqueue, &priv->work, 0); |
2072 | 2072 | ||
2073 | priv->softled_state = 0; | ||
2074 | err = p54_set_leds(dev); | ||
2075 | |||
2073 | out: | 2076 | out: |
2074 | mutex_unlock(&priv->conf_mutex); | 2077 | mutex_unlock(&priv->conf_mutex); |
2075 | return err; | 2078 | return err; |
@@ -2082,6 +2085,9 @@ static void p54_stop(struct ieee80211_hw *dev) | |||
2082 | 2085 | ||
2083 | mutex_lock(&priv->conf_mutex); | 2086 | mutex_lock(&priv->conf_mutex); |
2084 | priv->mode = NL80211_IFTYPE_UNSPECIFIED; | 2087 | priv->mode = NL80211_IFTYPE_UNSPECIFIED; |
2088 | priv->softled_state = 0; | ||
2089 | p54_set_leds(dev); | ||
2090 | |||
2085 | cancel_delayed_work_sync(&priv->work); | 2091 | cancel_delayed_work_sync(&priv->work); |
2086 | if (priv->cached_beacon) | 2092 | if (priv->cached_beacon) |
2087 | p54_tx_cancel(dev, priv->cached_beacon); | 2093 | p54_tx_cancel(dev, priv->cached_beacon); |
@@ -2119,7 +2125,6 @@ static int p54_add_interface(struct ieee80211_hw *dev, | |||
2119 | 2125 | ||
2120 | memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN); | 2126 | memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN); |
2121 | p54_setup_mac(dev); | 2127 | p54_setup_mac(dev); |
2122 | p54_set_leds(dev, 1, 0, 0); | ||
2123 | mutex_unlock(&priv->conf_mutex); | 2128 | mutex_unlock(&priv->conf_mutex); |
2124 | return 0; | 2129 | return 0; |
2125 | } | 2130 | } |
@@ -2199,8 +2204,6 @@ static int p54_config_interface(struct ieee80211_hw *dev, | |||
2199 | goto out; | 2204 | goto out; |
2200 | } | 2205 | } |
2201 | 2206 | ||
2202 | ret = p54_set_leds(dev, 1, !is_multicast_ether_addr(priv->bssid), 0); | ||
2203 | |||
2204 | out: | 2207 | out: |
2205 | mutex_unlock(&priv->conf_mutex); | 2208 | mutex_unlock(&priv->conf_mutex); |
2206 | return ret; | 2209 | return ret; |
@@ -2214,9 +2217,7 @@ static void p54_configure_filter(struct ieee80211_hw *dev, | |||
2214 | struct p54_common *priv = dev->priv; | 2217 | struct p54_common *priv = dev->priv; |
2215 | 2218 | ||
2216 | *total_flags &= FIF_PROMISC_IN_BSS | | 2219 | *total_flags &= FIF_PROMISC_IN_BSS | |
2217 | FIF_OTHER_BSS | | 2220 | FIF_OTHER_BSS; |
2218 | (*total_flags & FIF_PROMISC_IN_BSS ? | ||
2219 | FIF_FCSFAIL : 0); | ||
2220 | 2221 | ||
2221 | priv->filter_flags = *total_flags; | 2222 | priv->filter_flags = *total_flags; |
2222 | 2223 | ||
@@ -2419,6 +2420,96 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd, | |||
2419 | return 0; | 2420 | return 0; |
2420 | } | 2421 | } |
2421 | 2422 | ||
2423 | #ifdef CONFIG_MAC80211_LEDS | ||
2424 | static void p54_led_brightness_set(struct led_classdev *led_dev, | ||
2425 | enum led_brightness brightness) | ||
2426 | { | ||
2427 | struct p54_led_dev *led = container_of(led_dev, struct p54_led_dev, | ||
2428 | led_dev); | ||
2429 | struct ieee80211_hw *dev = led->hw_dev; | ||
2430 | struct p54_common *priv = dev->priv; | ||
2431 | int err; | ||
2432 | |||
2433 | /* Don't toggle the LED, when the device is down. */ | ||
2434 | if (priv->mode == NL80211_IFTYPE_UNSPECIFIED) | ||
2435 | return ; | ||
2436 | |||
2437 | if (brightness != LED_OFF) | ||
2438 | priv->softled_state |= BIT(led->index); | ||
2439 | else | ||
2440 | priv->softled_state &= ~BIT(led->index); | ||
2441 | |||
2442 | err = p54_set_leds(dev); | ||
2443 | if (err && net_ratelimit()) | ||
2444 | printk(KERN_ERR "%s: failed to update %s LED.\n", | ||
2445 | wiphy_name(dev->wiphy), led_dev->name); | ||
2446 | } | ||
2447 | |||
2448 | static int p54_register_led(struct ieee80211_hw *dev, | ||
2449 | struct p54_led_dev *led, | ||
2450 | unsigned int led_index, | ||
2451 | char *name, char *trigger) | ||
2452 | { | ||
2453 | int err; | ||
2454 | |||
2455 | if (led->registered) | ||
2456 | return -EEXIST; | ||
2457 | |||
2458 | snprintf(led->name, sizeof(led->name), "p54-%s::%s", | ||
2459 | wiphy_name(dev->wiphy), name); | ||
2460 | led->hw_dev = dev; | ||
2461 | led->index = led_index; | ||
2462 | led->led_dev.name = led->name; | ||
2463 | led->led_dev.default_trigger = trigger; | ||
2464 | led->led_dev.brightness_set = p54_led_brightness_set; | ||
2465 | |||
2466 | err = led_classdev_register(wiphy_dev(dev->wiphy), &led->led_dev); | ||
2467 | if (err) | ||
2468 | printk(KERN_ERR "%s: Failed to register %s LED.\n", | ||
2469 | wiphy_name(dev->wiphy), name); | ||
2470 | else | ||
2471 | led->registered = 1; | ||
2472 | |||
2473 | return err; | ||
2474 | } | ||
2475 | |||
2476 | static int p54_init_leds(struct ieee80211_hw *dev) | ||
2477 | { | ||
2478 | struct p54_common *priv = dev->priv; | ||
2479 | int err; | ||
2480 | |||
2481 | /* | ||
2482 | * TODO: | ||
2483 | * Figure out if the EEPROM contains some hints about the number | ||
2484 | * of available/programmable LEDs of the device. | ||
2485 | * But for now, we can assume that we have two programmable LEDs. | ||
2486 | */ | ||
2487 | |||
2488 | err = p54_register_led(dev, &priv->assoc_led, 0, "assoc", | ||
2489 | ieee80211_get_assoc_led_name(dev)); | ||
2490 | if (err) | ||
2491 | return err; | ||
2492 | |||
2493 | err = p54_register_led(dev, &priv->tx_led, 1, "tx", | ||
2494 | ieee80211_get_tx_led_name(dev)); | ||
2495 | if (err) | ||
2496 | return err; | ||
2497 | |||
2498 | err = p54_set_leds(dev); | ||
2499 | return err; | ||
2500 | } | ||
2501 | |||
2502 | static void p54_unregister_leds(struct ieee80211_hw *dev) | ||
2503 | { | ||
2504 | struct p54_common *priv = dev->priv; | ||
2505 | |||
2506 | if (priv->tx_led.registered) | ||
2507 | led_classdev_unregister(&priv->tx_led.led_dev); | ||
2508 | if (priv->assoc_led.registered) | ||
2509 | led_classdev_unregister(&priv->assoc_led.led_dev); | ||
2510 | } | ||
2511 | #endif /* CONFIG_MAC80211_LEDS */ | ||
2512 | |||
2422 | static const struct ieee80211_ops p54_ops = { | 2513 | static const struct ieee80211_ops p54_ops = { |
2423 | .tx = p54_tx, | 2514 | .tx = p54_tx, |
2424 | .start = p54_start, | 2515 | .start = p54_start, |
@@ -2452,6 +2543,8 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) | |||
2452 | priv->basic_rate_mask = 0x15f; | 2543 | priv->basic_rate_mask = 0x15f; |
2453 | skb_queue_head_init(&priv->tx_queue); | 2544 | skb_queue_head_init(&priv->tx_queue); |
2454 | dev->flags = IEEE80211_HW_RX_INCLUDES_FCS | | 2545 | dev->flags = IEEE80211_HW_RX_INCLUDES_FCS | |
2546 | IEEE80211_HW_SUPPORTS_PS | | ||
2547 | IEEE80211_HW_PS_NULLFUNC_STACK | | ||
2455 | IEEE80211_HW_SIGNAL_DBM | | 2548 | IEEE80211_HW_SIGNAL_DBM | |
2456 | IEEE80211_HW_NOISE_DBM; | 2549 | IEEE80211_HW_NOISE_DBM; |
2457 | 2550 | ||
@@ -2489,12 +2582,37 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) | |||
2489 | } | 2582 | } |
2490 | EXPORT_SYMBOL_GPL(p54_init_common); | 2583 | EXPORT_SYMBOL_GPL(p54_init_common); |
2491 | 2584 | ||
2585 | int p54_register_common(struct ieee80211_hw *dev, struct device *pdev) | ||
2586 | { | ||
2587 | int err; | ||
2588 | |||
2589 | err = ieee80211_register_hw(dev); | ||
2590 | if (err) { | ||
2591 | dev_err(pdev, "Cannot register device (%d).\n", err); | ||
2592 | return err; | ||
2593 | } | ||
2594 | |||
2595 | #ifdef CONFIG_MAC80211_LEDS | ||
2596 | err = p54_init_leds(dev); | ||
2597 | if (err) | ||
2598 | return err; | ||
2599 | #endif /* CONFIG_MAC80211_LEDS */ | ||
2600 | |||
2601 | dev_info(pdev, "is registered as '%s'\n", wiphy_name(dev->wiphy)); | ||
2602 | return 0; | ||
2603 | } | ||
2604 | EXPORT_SYMBOL_GPL(p54_register_common); | ||
2605 | |||
2492 | void p54_free_common(struct ieee80211_hw *dev) | 2606 | void p54_free_common(struct ieee80211_hw *dev) |
2493 | { | 2607 | { |
2494 | struct p54_common *priv = dev->priv; | 2608 | struct p54_common *priv = dev->priv; |
2495 | kfree(priv->iq_autocal); | 2609 | kfree(priv->iq_autocal); |
2496 | kfree(priv->output_limit); | 2610 | kfree(priv->output_limit); |
2497 | kfree(priv->curve_data); | 2611 | kfree(priv->curve_data); |
2612 | |||
2613 | #ifdef CONFIG_MAC80211_LEDS | ||
2614 | p54_unregister_leds(dev); | ||
2615 | #endif /* CONFIG_MAC80211_LEDS */ | ||
2498 | } | 2616 | } |
2499 | EXPORT_SYMBOL_GPL(p54_free_common); | 2617 | EXPORT_SYMBOL_GPL(p54_free_common); |
2500 | 2618 | ||
diff --git a/drivers/net/wireless/p54/p54common.h b/drivers/net/wireless/p54/p54common.h index def23b1f49ec..75ead7a150fc 100644 --- a/drivers/net/wireless/p54/p54common.h +++ b/drivers/net/wireless/p54/p54common.h | |||
@@ -515,10 +515,9 @@ struct p54_scan_tail_rate { | |||
515 | } __attribute__ ((packed)); | 515 | } __attribute__ ((packed)); |
516 | 516 | ||
517 | struct p54_led { | 517 | struct p54_led { |
518 | __le16 mode; | 518 | __le16 flags; |
519 | __le16 led_temporary; | 519 | __le16 mask[2]; |
520 | __le16 led_permanent; | 520 | __le16 delay[2]; |
521 | __le16 duration; | ||
522 | } __attribute__ ((packed)); | 521 | } __attribute__ ((packed)); |
523 | 522 | ||
524 | struct p54_edcf { | 523 | struct p54_edcf { |
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index 3f9a6b04ea95..e3569a0a952d 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c | |||
@@ -413,8 +413,7 @@ static int p54p_open(struct ieee80211_hw *dev) | |||
413 | err = request_irq(priv->pdev->irq, &p54p_interrupt, | 413 | err = request_irq(priv->pdev->irq, &p54p_interrupt, |
414 | IRQF_SHARED, "p54pci", dev); | 414 | IRQF_SHARED, "p54pci", dev); |
415 | if (err) { | 415 | if (err) { |
416 | printk(KERN_ERR "%s: failed to register IRQ handler\n", | 416 | dev_err(&priv->pdev->dev, "failed to register IRQ handler\n"); |
417 | wiphy_name(dev->wiphy)); | ||
418 | return err; | 417 | return err; |
419 | } | 418 | } |
420 | 419 | ||
@@ -476,30 +475,26 @@ static int __devinit p54p_probe(struct pci_dev *pdev, | |||
476 | 475 | ||
477 | err = pci_enable_device(pdev); | 476 | err = pci_enable_device(pdev); |
478 | if (err) { | 477 | if (err) { |
479 | printk(KERN_ERR "%s (p54pci): Cannot enable new PCI device\n", | 478 | dev_err(&pdev->dev, "Cannot enable new PCI device\n"); |
480 | pci_name(pdev)); | ||
481 | return err; | 479 | return err; |
482 | } | 480 | } |
483 | 481 | ||
484 | mem_addr = pci_resource_start(pdev, 0); | 482 | mem_addr = pci_resource_start(pdev, 0); |
485 | mem_len = pci_resource_len(pdev, 0); | 483 | mem_len = pci_resource_len(pdev, 0); |
486 | if (mem_len < sizeof(struct p54p_csr)) { | 484 | if (mem_len < sizeof(struct p54p_csr)) { |
487 | printk(KERN_ERR "%s (p54pci): Too short PCI resources\n", | 485 | dev_err(&pdev->dev, "Too short PCI resources\n"); |
488 | pci_name(pdev)); | ||
489 | goto err_disable_dev; | 486 | goto err_disable_dev; |
490 | } | 487 | } |
491 | 488 | ||
492 | err = pci_request_regions(pdev, "p54pci"); | 489 | err = pci_request_regions(pdev, "p54pci"); |
493 | if (err) { | 490 | if (err) { |
494 | printk(KERN_ERR "%s (p54pci): Cannot obtain PCI resources\n", | 491 | dev_err(&pdev->dev, "Cannot obtain PCI resources\n"); |
495 | pci_name(pdev)); | ||
496 | goto err_disable_dev; | 492 | goto err_disable_dev; |
497 | } | 493 | } |
498 | 494 | ||
499 | if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) || | 495 | if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) || |
500 | pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) { | 496 | pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) { |
501 | printk(KERN_ERR "%s (p54pci): No suitable DMA available\n", | 497 | dev_err(&pdev->dev, "No suitable DMA available\n"); |
502 | pci_name(pdev)); | ||
503 | goto err_free_reg; | 498 | goto err_free_reg; |
504 | } | 499 | } |
505 | 500 | ||
@@ -511,8 +506,7 @@ static int __devinit p54p_probe(struct pci_dev *pdev, | |||
511 | 506 | ||
512 | dev = p54_init_common(sizeof(*priv)); | 507 | dev = p54_init_common(sizeof(*priv)); |
513 | if (!dev) { | 508 | if (!dev) { |
514 | printk(KERN_ERR "%s (p54pci): ieee80211 alloc failed\n", | 509 | dev_err(&pdev->dev, "ieee80211 alloc failed\n"); |
515 | pci_name(pdev)); | ||
516 | err = -ENOMEM; | 510 | err = -ENOMEM; |
517 | goto err_free_reg; | 511 | goto err_free_reg; |
518 | } | 512 | } |
@@ -525,17 +519,15 @@ static int __devinit p54p_probe(struct pci_dev *pdev, | |||
525 | 519 | ||
526 | priv->map = ioremap(mem_addr, mem_len); | 520 | priv->map = ioremap(mem_addr, mem_len); |
527 | if (!priv->map) { | 521 | if (!priv->map) { |
528 | printk(KERN_ERR "%s (p54pci): Cannot map device memory\n", | 522 | dev_err(&pdev->dev, "Cannot map device memory\n"); |
529 | pci_name(pdev)); | 523 | err = -ENOMEM; |
530 | err = -EINVAL; // TODO: use a better error code? | ||
531 | goto err_free_dev; | 524 | goto err_free_dev; |
532 | } | 525 | } |
533 | 526 | ||
534 | priv->ring_control = pci_alloc_consistent(pdev, sizeof(*priv->ring_control), | 527 | priv->ring_control = pci_alloc_consistent(pdev, sizeof(*priv->ring_control), |
535 | &priv->ring_control_dma); | 528 | &priv->ring_control_dma); |
536 | if (!priv->ring_control) { | 529 | if (!priv->ring_control) { |
537 | printk(KERN_ERR "%s (p54pci): Cannot allocate rings\n", | 530 | dev_err(&pdev->dev, "Cannot allocate rings\n"); |
538 | pci_name(pdev)); | ||
539 | err = -ENOMEM; | 531 | err = -ENOMEM; |
540 | goto err_iounmap; | 532 | goto err_iounmap; |
541 | } | 533 | } |
@@ -549,8 +541,7 @@ static int __devinit p54p_probe(struct pci_dev *pdev, | |||
549 | err = request_firmware(&priv->firmware, "isl3886pci", | 541 | err = request_firmware(&priv->firmware, "isl3886pci", |
550 | &priv->pdev->dev); | 542 | &priv->pdev->dev); |
551 | if (err) { | 543 | if (err) { |
552 | printk(KERN_ERR "%s (p54pci): cannot find firmware " | 544 | dev_err(&pdev->dev, "Cannot find firmware (isl3886pci)\n"); |
553 | "(isl3886pci)\n", pci_name(priv->pdev)); | ||
554 | err = request_firmware(&priv->firmware, "isl3886", | 545 | err = request_firmware(&priv->firmware, "isl3886", |
555 | &priv->pdev->dev); | 546 | &priv->pdev->dev); |
556 | if (err) | 547 | if (err) |
@@ -565,12 +556,9 @@ static int __devinit p54p_probe(struct pci_dev *pdev, | |||
565 | if (err) | 556 | if (err) |
566 | goto err_free_common; | 557 | goto err_free_common; |
567 | 558 | ||
568 | err = ieee80211_register_hw(dev); | 559 | err = p54_register_common(dev, &pdev->dev); |
569 | if (err) { | 560 | if (err) |
570 | printk(KERN_ERR "%s (p54pci): Cannot register netdevice\n", | ||
571 | pci_name(pdev)); | ||
572 | goto err_free_common; | 561 | goto err_free_common; |
573 | } | ||
574 | 562 | ||
575 | return 0; | 563 | return 0; |
576 | 564 | ||
diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c index 7fde243b3d5d..2b222aaa6f0a 100644 --- a/drivers/net/wireless/p54/p54spi.c +++ b/drivers/net/wireless/p54/p54spi.c | |||
@@ -694,15 +694,10 @@ static int __devinit p54spi_probe(struct spi_device *spi) | |||
694 | if (ret) | 694 | if (ret) |
695 | goto err_free_common; | 695 | goto err_free_common; |
696 | 696 | ||
697 | ret = ieee80211_register_hw(hw); | 697 | ret = p54_register_common(hw, &priv->spi->dev); |
698 | if (ret) { | 698 | if (ret) |
699 | dev_err(&priv->spi->dev, "unable to register " | ||
700 | "mac80211 hw: %d", ret); | ||
701 | goto err_free_common; | 699 | goto err_free_common; |
702 | } | ||
703 | 700 | ||
704 | dev_info(&priv->spi->dev, "device is bound to %s\n", | ||
705 | wiphy_name(hw->wiphy)); | ||
706 | return 0; | 701 | return 0; |
707 | 702 | ||
708 | err_free_common: | 703 | err_free_common: |
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index 9539ddcf379f..da6640afc835 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c | |||
@@ -976,11 +976,9 @@ static int __devinit p54u_probe(struct usb_interface *intf, | |||
976 | if (err) | 976 | if (err) |
977 | goto err_free_dev; | 977 | goto err_free_dev; |
978 | 978 | ||
979 | err = ieee80211_register_hw(dev); | 979 | err = p54_register_common(dev, &udev->dev); |
980 | if (err) { | 980 | if (err) |
981 | dev_err(&udev->dev, "(p54usb) Cannot register netdevice\n"); | ||
982 | goto err_free_dev; | 981 | goto err_free_dev; |
983 | } | ||
984 | 982 | ||
985 | return 0; | 983 | return 0; |
986 | 984 | ||
@@ -1024,6 +1022,7 @@ static struct usb_driver p54u_driver = { | |||
1024 | .disconnect = p54u_disconnect, | 1022 | .disconnect = p54u_disconnect, |
1025 | .pre_reset = p54u_pre_reset, | 1023 | .pre_reset = p54u_pre_reset, |
1026 | .post_reset = p54u_post_reset, | 1024 | .post_reset = p54u_post_reset, |
1025 | .soft_unbind = 1, | ||
1027 | }; | 1026 | }; |
1028 | 1027 | ||
1029 | static int __init p54u_init(void) | 1028 | static int __init p54u_init(void) |
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 99ec7d622518..7370edb4e0ce 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c | |||
@@ -8,7 +8,7 @@ | |||
8 | * Copyright (c) 1998 Corey Thomas (corey@world.std.com) | 8 | * Copyright (c) 1998 Corey Thomas (corey@world.std.com) |
9 | * | 9 | * |
10 | * This driver is free software; you can redistribute it and/or modify | 10 | * This driver is free software; you can redistribute it and/or modify |
11 | * it under the terms of version 2 only of the GNU General Public License as | 11 | * it under the terms of version 2 only of the GNU General Public License as |
12 | * published by the Free Software Foundation. | 12 | * published by the Free Software Foundation. |
13 | * | 13 | * |
14 | * It is distributed in the hope that it will be useful, | 14 | * It is distributed in the hope that it will be useful, |
@@ -27,7 +27,7 @@ | |||
27 | * | 27 | * |
28 | * Daniele Bellucci <bellucda@tiscali.it> - 07/10/2003 | 28 | * Daniele Bellucci <bellucda@tiscali.it> - 07/10/2003 |
29 | * - Audit copy_to_user in ioctl(SIOCGIWESSID) | 29 | * - Audit copy_to_user in ioctl(SIOCGIWESSID) |
30 | * | 30 | * |
31 | =============================================================================*/ | 31 | =============================================================================*/ |
32 | 32 | ||
33 | #include <linux/module.h> | 33 | #include <linux/module.h> |
@@ -65,8 +65,8 @@ | |||
65 | /* Warning : these stuff will slow down the driver... */ | 65 | /* Warning : these stuff will slow down the driver... */ |
66 | #define WIRELESS_SPY /* Enable spying addresses */ | 66 | #define WIRELESS_SPY /* Enable spying addresses */ |
67 | /* Definitions we need for spy */ | 67 | /* Definitions we need for spy */ |
68 | typedef struct iw_statistics iw_stats; | 68 | typedef struct iw_statistics iw_stats; |
69 | typedef u_char mac_addr[ETH_ALEN]; /* Hardware address */ | 69 | typedef u_char mac_addr[ETH_ALEN]; /* Hardware address */ |
70 | 70 | ||
71 | #include "rayctl.h" | 71 | #include "rayctl.h" |
72 | #include "ray_cs.h" | 72 | #include "ray_cs.h" |
@@ -86,7 +86,7 @@ static int ray_debug; | |||
86 | static int pc_debug = PCMCIA_DEBUG; | 86 | static int pc_debug = PCMCIA_DEBUG; |
87 | module_param(pc_debug, int, 0); | 87 | module_param(pc_debug, int, 0); |
88 | /* #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args); */ | 88 | /* #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args); */ |
89 | #define DEBUG(n, args...) if (pc_debug>(n)) printk(args); | 89 | #define DEBUG(n, args...) if (pc_debug > (n)) printk(args); |
90 | #else | 90 | #else |
91 | #define DEBUG(n, args...) | 91 | #define DEBUG(n, args...) |
92 | #endif | 92 | #endif |
@@ -108,12 +108,12 @@ static int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev); | |||
108 | static void set_multicast_list(struct net_device *dev); | 108 | static void set_multicast_list(struct net_device *dev); |
109 | static void ray_update_multi_list(struct net_device *dev, int all); | 109 | static void ray_update_multi_list(struct net_device *dev, int all); |
110 | static int translate_frame(ray_dev_t *local, struct tx_msg __iomem *ptx, | 110 | static int translate_frame(ray_dev_t *local, struct tx_msg __iomem *ptx, |
111 | unsigned char *data, int len); | 111 | unsigned char *data, int len); |
112 | static void ray_build_header(ray_dev_t *local, struct tx_msg __iomem *ptx, UCHAR msg_type, | 112 | static void ray_build_header(ray_dev_t *local, struct tx_msg __iomem *ptx, |
113 | unsigned char *data); | 113 | UCHAR msg_type, unsigned char *data); |
114 | static void untranslate(ray_dev_t *local, struct sk_buff *skb, int len); | 114 | static void untranslate(ray_dev_t *local, struct sk_buff *skb, int len); |
115 | static iw_stats * ray_get_wireless_stats(struct net_device * dev); | 115 | static iw_stats *ray_get_wireless_stats(struct net_device *dev); |
116 | static const struct iw_handler_def ray_handler_def; | 116 | static const struct iw_handler_def ray_handler_def; |
117 | 117 | ||
118 | /***** Prototypes for raylink functions **************************************/ | 118 | /***** Prototypes for raylink functions **************************************/ |
119 | static int asc_to_int(char a); | 119 | static int asc_to_int(char a); |
@@ -124,7 +124,7 @@ static int get_free_ccs(ray_dev_t *local); | |||
124 | static int get_free_tx_ccs(ray_dev_t *local); | 124 | static int get_free_tx_ccs(ray_dev_t *local); |
125 | static void init_startup_params(ray_dev_t *local); | 125 | static void init_startup_params(ray_dev_t *local); |
126 | static int parse_addr(char *in_str, UCHAR *out); | 126 | static int parse_addr(char *in_str, UCHAR *out); |
127 | static int ray_hw_xmit(unsigned char* data, int len, struct net_device* dev, UCHAR type); | 127 | static int ray_hw_xmit(unsigned char *data, int len, struct net_device *dev, UCHAR type); |
128 | static int ray_init(struct net_device *dev); | 128 | static int ray_init(struct net_device *dev); |
129 | static int interrupt_ecf(ray_dev_t *local, int ccs); | 129 | static int interrupt_ecf(ray_dev_t *local, int ccs); |
130 | static void ray_reset(struct net_device *dev); | 130 | static void ray_reset(struct net_device *dev); |
@@ -132,17 +132,17 @@ static void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value, i | |||
132 | static void verify_dl_startup(u_long); | 132 | static void verify_dl_startup(u_long); |
133 | 133 | ||
134 | /* Prototypes for interrpt time functions **********************************/ | 134 | /* Prototypes for interrpt time functions **********************************/ |
135 | static irqreturn_t ray_interrupt (int reg, void *dev_id); | 135 | static irqreturn_t ray_interrupt(int reg, void *dev_id); |
136 | static void clear_interrupt(ray_dev_t *local); | 136 | static void clear_interrupt(ray_dev_t *local); |
137 | static void rx_deauthenticate(ray_dev_t *local, struct rcs __iomem *prcs, | 137 | static void rx_deauthenticate(ray_dev_t *local, struct rcs __iomem *prcs, |
138 | unsigned int pkt_addr, int rx_len); | 138 | unsigned int pkt_addr, int rx_len); |
139 | static int copy_from_rx_buff(ray_dev_t *local, UCHAR *dest, int pkt_addr, int len); | 139 | static int copy_from_rx_buff(ray_dev_t *local, UCHAR *dest, int pkt_addr, int len); |
140 | static void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs __iomem *prcs); | 140 | static void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs __iomem *prcs); |
141 | static void release_frag_chain(ray_dev_t *local, struct rcs __iomem *prcs); | 141 | static void release_frag_chain(ray_dev_t *local, struct rcs __iomem *prcs); |
142 | static void rx_authenticate(ray_dev_t *local, struct rcs __iomem *prcs, | 142 | static void rx_authenticate(ray_dev_t *local, struct rcs __iomem *prcs, |
143 | unsigned int pkt_addr, int rx_len); | 143 | unsigned int pkt_addr, int rx_len); |
144 | static void rx_data(struct net_device *dev, struct rcs __iomem *prcs, unsigned int pkt_addr, | 144 | static void rx_data(struct net_device *dev, struct rcs __iomem *prcs, |
145 | int rx_len); | 145 | unsigned int pkt_addr, int rx_len); |
146 | static void associate(ray_dev_t *local); | 146 | static void associate(ray_dev_t *local); |
147 | 147 | ||
148 | /* Card command functions */ | 148 | /* Card command functions */ |
@@ -219,82 +219,84 @@ module_param(phy_addr, charp, 0); | |||
219 | module_param(ray_mem_speed, int, 0); | 219 | module_param(ray_mem_speed, int, 0); |
220 | 220 | ||
221 | static UCHAR b5_default_startup_parms[] = { | 221 | static UCHAR b5_default_startup_parms[] = { |
222 | 0, 0, /* Adhoc station */ | 222 | 0, 0, /* Adhoc station */ |
223 | 'L','I','N','U','X', 0, 0, 0, /* 32 char ESSID */ | 223 | 'L', 'I', 'N', 'U', 'X', 0, 0, 0, /* 32 char ESSID */ |
224 | 0, 0, 0, 0, 0, 0, 0, 0, | 224 | 0, 0, 0, 0, 0, 0, 0, 0, |
225 | 0, 0, 0, 0, 0, 0, 0, 0, | 225 | 0, 0, 0, 0, 0, 0, 0, 0, |
226 | 0, 0, 0, 0, 0, 0, 0, 0, | 226 | 0, 0, 0, 0, 0, 0, 0, 0, |
227 | 1, 0, /* Active scan, CA Mode */ | 227 | 1, 0, /* Active scan, CA Mode */ |
228 | 0, 0, 0, 0, 0, 0, /* No default MAC addr */ | 228 | 0, 0, 0, 0, 0, 0, /* No default MAC addr */ |
229 | 0x7f, 0xff, /* Frag threshold */ | 229 | 0x7f, 0xff, /* Frag threshold */ |
230 | 0x00, 0x80, /* Hop time 128 Kus*/ | 230 | 0x00, 0x80, /* Hop time 128 Kus */ |
231 | 0x01, 0x00, /* Beacon period 256 Kus */ | 231 | 0x01, 0x00, /* Beacon period 256 Kus */ |
232 | 0x01, 0x07, 0xa3, /* DTIM, retries, ack timeout*/ | 232 | 0x01, 0x07, 0xa3, /* DTIM, retries, ack timeout */ |
233 | 0x1d, 0x82, 0x4e, /* SIFS, DIFS, PIFS */ | 233 | 0x1d, 0x82, 0x4e, /* SIFS, DIFS, PIFS */ |
234 | 0x7f, 0xff, /* RTS threshold */ | 234 | 0x7f, 0xff, /* RTS threshold */ |
235 | 0x04, 0xe2, 0x38, 0xA4, /* scan_dwell, max_scan_dwell */ | 235 | 0x04, 0xe2, 0x38, 0xA4, /* scan_dwell, max_scan_dwell */ |
236 | 0x05, /* assoc resp timeout thresh */ | 236 | 0x05, /* assoc resp timeout thresh */ |
237 | 0x08, 0x02, 0x08, /* adhoc, infra, super cycle max*/ | 237 | 0x08, 0x02, 0x08, /* adhoc, infra, super cycle max */ |
238 | 0, /* Promiscuous mode */ | 238 | 0, /* Promiscuous mode */ |
239 | 0x0c, 0x0bd, /* Unique word */ | 239 | 0x0c, 0x0bd, /* Unique word */ |
240 | 0x32, /* Slot time */ | 240 | 0x32, /* Slot time */ |
241 | 0xff, 0xff, /* roam-low snr, low snr count */ | 241 | 0xff, 0xff, /* roam-low snr, low snr count */ |
242 | 0x05, 0xff, /* Infra, adhoc missed bcn thresh */ | 242 | 0x05, 0xff, /* Infra, adhoc missed bcn thresh */ |
243 | 0x01, 0x0b, 0x4f, /* USA, hop pattern, hop pat length */ | 243 | 0x01, 0x0b, 0x4f, /* USA, hop pattern, hop pat length */ |
244 | /* b4 - b5 differences start here */ | 244 | /* b4 - b5 differences start here */ |
245 | 0x00, 0x3f, /* CW max */ | 245 | 0x00, 0x3f, /* CW max */ |
246 | 0x00, 0x0f, /* CW min */ | 246 | 0x00, 0x0f, /* CW min */ |
247 | 0x04, 0x08, /* Noise gain, limit offset */ | 247 | 0x04, 0x08, /* Noise gain, limit offset */ |
248 | 0x28, 0x28, /* det rssi, med busy offsets */ | 248 | 0x28, 0x28, /* det rssi, med busy offsets */ |
249 | 7, /* det sync thresh */ | 249 | 7, /* det sync thresh */ |
250 | 0, 2, 2, /* test mode, min, max */ | 250 | 0, 2, 2, /* test mode, min, max */ |
251 | 0, /* allow broadcast SSID probe resp */ | 251 | 0, /* allow broadcast SSID probe resp */ |
252 | 0, 0, /* privacy must start, can join */ | 252 | 0, 0, /* privacy must start, can join */ |
253 | 2, 0, 0, 0, 0, 0, 0, 0 /* basic rate set */ | 253 | 2, 0, 0, 0, 0, 0, 0, 0 /* basic rate set */ |
254 | }; | 254 | }; |
255 | 255 | ||
256 | static UCHAR b4_default_startup_parms[] = { | 256 | static UCHAR b4_default_startup_parms[] = { |
257 | 0, 0, /* Adhoc station */ | 257 | 0, 0, /* Adhoc station */ |
258 | 'L','I','N','U','X', 0, 0, 0, /* 32 char ESSID */ | 258 | 'L', 'I', 'N', 'U', 'X', 0, 0, 0, /* 32 char ESSID */ |
259 | 0, 0, 0, 0, 0, 0, 0, 0, | 259 | 0, 0, 0, 0, 0, 0, 0, 0, |
260 | 0, 0, 0, 0, 0, 0, 0, 0, | 260 | 0, 0, 0, 0, 0, 0, 0, 0, |
261 | 0, 0, 0, 0, 0, 0, 0, 0, | 261 | 0, 0, 0, 0, 0, 0, 0, 0, |
262 | 1, 0, /* Active scan, CA Mode */ | 262 | 1, 0, /* Active scan, CA Mode */ |
263 | 0, 0, 0, 0, 0, 0, /* No default MAC addr */ | 263 | 0, 0, 0, 0, 0, 0, /* No default MAC addr */ |
264 | 0x7f, 0xff, /* Frag threshold */ | 264 | 0x7f, 0xff, /* Frag threshold */ |
265 | 0x02, 0x00, /* Hop time */ | 265 | 0x02, 0x00, /* Hop time */ |
266 | 0x00, 0x01, /* Beacon period */ | 266 | 0x00, 0x01, /* Beacon period */ |
267 | 0x01, 0x07, 0xa3, /* DTIM, retries, ack timeout*/ | 267 | 0x01, 0x07, 0xa3, /* DTIM, retries, ack timeout */ |
268 | 0x1d, 0x82, 0xce, /* SIFS, DIFS, PIFS */ | 268 | 0x1d, 0x82, 0xce, /* SIFS, DIFS, PIFS */ |
269 | 0x7f, 0xff, /* RTS threshold */ | 269 | 0x7f, 0xff, /* RTS threshold */ |
270 | 0xfb, 0x1e, 0xc7, 0x5c, /* scan_dwell, max_scan_dwell */ | 270 | 0xfb, 0x1e, 0xc7, 0x5c, /* scan_dwell, max_scan_dwell */ |
271 | 0x05, /* assoc resp timeout thresh */ | 271 | 0x05, /* assoc resp timeout thresh */ |
272 | 0x04, 0x02, 0x4, /* adhoc, infra, super cycle max*/ | 272 | 0x04, 0x02, 0x4, /* adhoc, infra, super cycle max */ |
273 | 0, /* Promiscuous mode */ | 273 | 0, /* Promiscuous mode */ |
274 | 0x0c, 0x0bd, /* Unique word */ | 274 | 0x0c, 0x0bd, /* Unique word */ |
275 | 0x4e, /* Slot time (TBD seems wrong)*/ | 275 | 0x4e, /* Slot time (TBD seems wrong) */ |
276 | 0xff, 0xff, /* roam-low snr, low snr count */ | 276 | 0xff, 0xff, /* roam-low snr, low snr count */ |
277 | 0x05, 0xff, /* Infra, adhoc missed bcn thresh */ | 277 | 0x05, 0xff, /* Infra, adhoc missed bcn thresh */ |
278 | 0x01, 0x0b, 0x4e, /* USA, hop pattern, hop pat length */ | 278 | 0x01, 0x0b, 0x4e, /* USA, hop pattern, hop pat length */ |
279 | /* b4 - b5 differences start here */ | 279 | /* b4 - b5 differences start here */ |
280 | 0x3f, 0x0f, /* CW max, min */ | 280 | 0x3f, 0x0f, /* CW max, min */ |
281 | 0x04, 0x08, /* Noise gain, limit offset */ | 281 | 0x04, 0x08, /* Noise gain, limit offset */ |
282 | 0x28, 0x28, /* det rssi, med busy offsets */ | 282 | 0x28, 0x28, /* det rssi, med busy offsets */ |
283 | 7, /* det sync thresh */ | 283 | 7, /* det sync thresh */ |
284 | 0, 2, 2 /* test mode, min, max*/ | 284 | 0, 2, 2 /* test mode, min, max */ |
285 | }; | 285 | }; |
286 | |||
286 | /*===========================================================================*/ | 287 | /*===========================================================================*/ |
287 | static unsigned char eth2_llc[] = {0xaa, 0xaa, 3, 0, 0, 0}; | 288 | static unsigned char eth2_llc[] = { 0xaa, 0xaa, 3, 0, 0, 0 }; |
288 | 289 | ||
289 | static char hop_pattern_length[] = { 1, | 290 | static char hop_pattern_length[] = { 1, |
290 | USA_HOP_MOD, EUROPE_HOP_MOD, | 291 | USA_HOP_MOD, EUROPE_HOP_MOD, |
291 | JAPAN_HOP_MOD, KOREA_HOP_MOD, | 292 | JAPAN_HOP_MOD, KOREA_HOP_MOD, |
292 | SPAIN_HOP_MOD, FRANCE_HOP_MOD, | 293 | SPAIN_HOP_MOD, FRANCE_HOP_MOD, |
293 | ISRAEL_HOP_MOD, AUSTRALIA_HOP_MOD, | 294 | ISRAEL_HOP_MOD, AUSTRALIA_HOP_MOD, |
294 | JAPAN_TEST_HOP_MOD | 295 | JAPAN_TEST_HOP_MOD |
295 | }; | 296 | }; |
296 | 297 | ||
297 | static char rcsid[] = "Raylink/WebGear wireless LAN - Corey <Thomas corey@world.std.com>"; | 298 | static char rcsid[] = |
299 | "Raylink/WebGear wireless LAN - Corey <Thomas corey@world.std.com>"; | ||
298 | 300 | ||
299 | /*============================================================================= | 301 | /*============================================================================= |
300 | ray_attach() creates an "instance" of the driver, allocating | 302 | ray_attach() creates an "instance" of the driver, allocating |
@@ -306,71 +308,72 @@ static char rcsid[] = "Raylink/WebGear wireless LAN - Corey <Thomas corey@world. | |||
306 | =============================================================================*/ | 308 | =============================================================================*/ |
307 | static int ray_probe(struct pcmcia_device *p_dev) | 309 | static int ray_probe(struct pcmcia_device *p_dev) |
308 | { | 310 | { |
309 | ray_dev_t *local; | 311 | ray_dev_t *local; |
310 | struct net_device *dev; | 312 | struct net_device *dev; |
311 | 313 | ||
312 | DEBUG(1, "ray_attach()\n"); | 314 | DEBUG(1, "ray_attach()\n"); |
313 | 315 | ||
314 | /* Allocate space for private device-specific data */ | 316 | /* Allocate space for private device-specific data */ |
315 | dev = alloc_etherdev(sizeof(ray_dev_t)); | 317 | dev = alloc_etherdev(sizeof(ray_dev_t)); |
316 | if (!dev) | 318 | if (!dev) |
317 | goto fail_alloc_dev; | 319 | goto fail_alloc_dev; |
318 | 320 | ||
319 | local = netdev_priv(dev); | 321 | local = netdev_priv(dev); |
320 | local->finder = p_dev; | 322 | local->finder = p_dev; |
321 | 323 | ||
322 | /* The io structure describes IO port mapping. None used here */ | 324 | /* The io structure describes IO port mapping. None used here */ |
323 | p_dev->io.NumPorts1 = 0; | 325 | p_dev->io.NumPorts1 = 0; |
324 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | 326 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; |
325 | p_dev->io.IOAddrLines = 5; | 327 | p_dev->io.IOAddrLines = 5; |
326 | 328 | ||
327 | /* Interrupt setup. For PCMCIA, driver takes what's given */ | 329 | /* Interrupt setup. For PCMCIA, driver takes what's given */ |
328 | p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; | 330 | p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; |
329 | p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; | 331 | p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; |
330 | p_dev->irq.Handler = &ray_interrupt; | 332 | p_dev->irq.Handler = &ray_interrupt; |
331 | 333 | ||
332 | /* General socket configuration */ | 334 | /* General socket configuration */ |
333 | p_dev->conf.Attributes = CONF_ENABLE_IRQ; | 335 | p_dev->conf.Attributes = CONF_ENABLE_IRQ; |
334 | p_dev->conf.IntType = INT_MEMORY_AND_IO; | 336 | p_dev->conf.IntType = INT_MEMORY_AND_IO; |
335 | p_dev->conf.ConfigIndex = 1; | 337 | p_dev->conf.ConfigIndex = 1; |
336 | 338 | ||
337 | p_dev->priv = dev; | 339 | p_dev->priv = dev; |
338 | p_dev->irq.Instance = dev; | 340 | p_dev->irq.Instance = dev; |
339 | 341 | ||
340 | local->finder = p_dev; | 342 | local->finder = p_dev; |
341 | local->card_status = CARD_INSERTED; | 343 | local->card_status = CARD_INSERTED; |
342 | local->authentication_state = UNAUTHENTICATED; | 344 | local->authentication_state = UNAUTHENTICATED; |
343 | local->num_multi = 0; | 345 | local->num_multi = 0; |
344 | DEBUG(2,"ray_attach p_dev = %p, dev = %p, local = %p, intr = %p\n", | 346 | DEBUG(2, "ray_attach p_dev = %p, dev = %p, local = %p, intr = %p\n", |
345 | p_dev,dev,local,&ray_interrupt); | 347 | p_dev, dev, local, &ray_interrupt); |
346 | 348 | ||
347 | /* Raylink entries in the device structure */ | 349 | /* Raylink entries in the device structure */ |
348 | dev->hard_start_xmit = &ray_dev_start_xmit; | 350 | dev->hard_start_xmit = &ray_dev_start_xmit; |
349 | dev->set_config = &ray_dev_config; | 351 | dev->set_config = &ray_dev_config; |
350 | dev->get_stats = &ray_get_stats; | 352 | dev->get_stats = &ray_get_stats; |
351 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); | 353 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); |
352 | dev->wireless_handlers = &ray_handler_def; | 354 | dev->wireless_handlers = &ray_handler_def; |
353 | #ifdef WIRELESS_SPY | 355 | #ifdef WIRELESS_SPY |
354 | local->wireless_data.spy_data = &local->spy_data; | 356 | local->wireless_data.spy_data = &local->spy_data; |
355 | dev->wireless_data = &local->wireless_data; | 357 | dev->wireless_data = &local->wireless_data; |
356 | #endif /* WIRELESS_SPY */ | 358 | #endif /* WIRELESS_SPY */ |
357 | 359 | ||
358 | dev->set_multicast_list = &set_multicast_list; | 360 | dev->set_multicast_list = &set_multicast_list; |
359 | 361 | ||
360 | DEBUG(2,"ray_cs ray_attach calling ether_setup.)\n"); | 362 | DEBUG(2, "ray_cs ray_attach calling ether_setup.)\n"); |
361 | dev->init = &ray_dev_init; | 363 | dev->init = &ray_dev_init; |
362 | dev->open = &ray_open; | 364 | dev->open = &ray_open; |
363 | dev->stop = &ray_dev_close; | 365 | dev->stop = &ray_dev_close; |
364 | netif_stop_queue(dev); | 366 | netif_stop_queue(dev); |
365 | 367 | ||
366 | init_timer(&local->timer); | 368 | init_timer(&local->timer); |
367 | 369 | ||
368 | this_device = p_dev; | 370 | this_device = p_dev; |
369 | return ray_config(p_dev); | 371 | return ray_config(p_dev); |
370 | 372 | ||
371 | fail_alloc_dev: | 373 | fail_alloc_dev: |
372 | return -ENOMEM; | 374 | return -ENOMEM; |
373 | } /* ray_attach */ | 375 | } /* ray_attach */ |
376 | |||
374 | /*============================================================================= | 377 | /*============================================================================= |
375 | This deletes a driver "instance". The device is de-registered | 378 | This deletes a driver "instance". The device is de-registered |
376 | with Card Services. If it has been released, all local data | 379 | with Card Services. If it has been released, all local data |
@@ -379,25 +382,27 @@ fail_alloc_dev: | |||
379 | =============================================================================*/ | 382 | =============================================================================*/ |
380 | static void ray_detach(struct pcmcia_device *link) | 383 | static void ray_detach(struct pcmcia_device *link) |
381 | { | 384 | { |
382 | struct net_device *dev; | 385 | struct net_device *dev; |
383 | ray_dev_t *local; | 386 | ray_dev_t *local; |
384 | 387 | ||
385 | DEBUG(1, "ray_detach(0x%p)\n", link); | 388 | DEBUG(1, "ray_detach(0x%p)\n", link); |
386 | 389 | ||
387 | this_device = NULL; | 390 | this_device = NULL; |
388 | dev = link->priv; | 391 | dev = link->priv; |
389 | 392 | ||
390 | ray_release(link); | 393 | ray_release(link); |
391 | 394 | ||
392 | local = netdev_priv(dev); | 395 | local = netdev_priv(dev); |
393 | del_timer(&local->timer); | 396 | del_timer(&local->timer); |
394 | 397 | ||
395 | if (link->priv) { | 398 | if (link->priv) { |
396 | if (link->dev_node) unregister_netdev(dev); | 399 | if (link->dev_node) |
397 | free_netdev(dev); | 400 | unregister_netdev(dev); |
398 | } | 401 | free_netdev(dev); |
399 | DEBUG(2,"ray_cs ray_detach ending\n"); | 402 | } |
403 | DEBUG(2, "ray_cs ray_detach ending\n"); | ||
400 | } /* ray_detach */ | 404 | } /* ray_detach */ |
405 | |||
401 | /*============================================================================= | 406 | /*============================================================================= |
402 | ray_config() is run after a CARD_INSERTION event | 407 | ray_config() is run after a CARD_INSERTION event |
403 | is received, to configure the PCMCIA socket, and to make the | 408 | is received, to configure the PCMCIA socket, and to make the |
@@ -408,92 +413,101 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | |||
408 | #define MAX_TUPLE_SIZE 128 | 413 | #define MAX_TUPLE_SIZE 128 |
409 | static int ray_config(struct pcmcia_device *link) | 414 | static int ray_config(struct pcmcia_device *link) |
410 | { | 415 | { |
411 | int last_fn = 0, last_ret = 0; | 416 | int last_fn = 0, last_ret = 0; |
412 | int i; | 417 | int i; |
413 | win_req_t req; | 418 | win_req_t req; |
414 | memreq_t mem; | 419 | memreq_t mem; |
415 | struct net_device *dev = (struct net_device *)link->priv; | 420 | struct net_device *dev = (struct net_device *)link->priv; |
416 | ray_dev_t *local = netdev_priv(dev); | 421 | ray_dev_t *local = netdev_priv(dev); |
417 | 422 | ||
418 | DEBUG(1, "ray_config(0x%p)\n", link); | 423 | DEBUG(1, "ray_config(0x%p)\n", link); |
419 | 424 | ||
420 | /* Determine card type and firmware version */ | 425 | /* Determine card type and firmware version */ |
421 | printk(KERN_INFO "ray_cs Detected: %s%s%s%s\n", | 426 | printk(KERN_INFO "ray_cs Detected: %s%s%s%s\n", |
422 | link->prod_id[0] ? link->prod_id[0] : " ", | 427 | link->prod_id[0] ? link->prod_id[0] : " ", |
423 | link->prod_id[1] ? link->prod_id[1] : " ", | 428 | link->prod_id[1] ? link->prod_id[1] : " ", |
424 | link->prod_id[2] ? link->prod_id[2] : " ", | 429 | link->prod_id[2] ? link->prod_id[2] : " ", |
425 | link->prod_id[3] ? link->prod_id[3] : " "); | 430 | link->prod_id[3] ? link->prod_id[3] : " "); |
426 | 431 | ||
427 | /* Now allocate an interrupt line. Note that this does not | 432 | /* Now allocate an interrupt line. Note that this does not |
428 | actually assign a handler to the interrupt. | 433 | actually assign a handler to the interrupt. |
429 | */ | 434 | */ |
430 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); | 435 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); |
431 | dev->irq = link->irq.AssignedIRQ; | 436 | dev->irq = link->irq.AssignedIRQ; |
432 | 437 | ||
433 | /* This actually configures the PCMCIA socket -- setting up | 438 | /* This actually configures the PCMCIA socket -- setting up |
434 | the I/O windows and the interrupt mapping. | 439 | the I/O windows and the interrupt mapping. |
435 | */ | 440 | */ |
436 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); | 441 | CS_CHECK(RequestConfiguration, |
442 | pcmcia_request_configuration(link, &link->conf)); | ||
437 | 443 | ||
438 | /*** Set up 32k window for shared memory (transmit and control) ************/ | 444 | /*** Set up 32k window for shared memory (transmit and control) ************/ |
439 | req.Attributes = WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT; | 445 | req.Attributes = |
440 | req.Base = 0; | 446 | WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT; |
441 | req.Size = 0x8000; | 447 | req.Base = 0; |
442 | req.AccessSpeed = ray_mem_speed; | 448 | req.Size = 0x8000; |
443 | CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &link->win)); | 449 | req.AccessSpeed = ray_mem_speed; |
444 | mem.CardOffset = 0x0000; mem.Page = 0; | 450 | CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &link->win)); |
445 | CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem)); | 451 | mem.CardOffset = 0x0000; |
446 | local->sram = ioremap(req.Base,req.Size); | 452 | mem.Page = 0; |
453 | CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem)); | ||
454 | local->sram = ioremap(req.Base, req.Size); | ||
447 | 455 | ||
448 | /*** Set up 16k window for shared memory (receive buffer) ***************/ | 456 | /*** Set up 16k window for shared memory (receive buffer) ***************/ |
449 | req.Attributes = WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT; | 457 | req.Attributes = |
450 | req.Base = 0; | 458 | WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT; |
451 | req.Size = 0x4000; | 459 | req.Base = 0; |
452 | req.AccessSpeed = ray_mem_speed; | 460 | req.Size = 0x4000; |
453 | CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &local->rmem_handle)); | 461 | req.AccessSpeed = ray_mem_speed; |
454 | mem.CardOffset = 0x8000; mem.Page = 0; | 462 | CS_CHECK(RequestWindow, |
455 | CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->rmem_handle, &mem)); | 463 | pcmcia_request_window(&link, &req, &local->rmem_handle)); |
456 | local->rmem = ioremap(req.Base,req.Size); | 464 | mem.CardOffset = 0x8000; |
465 | mem.Page = 0; | ||
466 | CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->rmem_handle, &mem)); | ||
467 | local->rmem = ioremap(req.Base, req.Size); | ||
457 | 468 | ||
458 | /*** Set up window for attribute memory ***********************************/ | 469 | /*** Set up window for attribute memory ***********************************/ |
459 | req.Attributes = WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_AM | WIN_ENABLE | WIN_USE_WAIT; | 470 | req.Attributes = |
460 | req.Base = 0; | 471 | WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_AM | WIN_ENABLE | WIN_USE_WAIT; |
461 | req.Size = 0x1000; | 472 | req.Base = 0; |
462 | req.AccessSpeed = ray_mem_speed; | 473 | req.Size = 0x1000; |
463 | CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &local->amem_handle)); | 474 | req.AccessSpeed = ray_mem_speed; |
464 | mem.CardOffset = 0x0000; mem.Page = 0; | 475 | CS_CHECK(RequestWindow, |
465 | CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->amem_handle, &mem)); | 476 | pcmcia_request_window(&link, &req, &local->amem_handle)); |
466 | local->amem = ioremap(req.Base,req.Size); | 477 | mem.CardOffset = 0x0000; |
467 | 478 | mem.Page = 0; | |
468 | DEBUG(3,"ray_config sram=%p\n",local->sram); | 479 | CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->amem_handle, &mem)); |
469 | DEBUG(3,"ray_config rmem=%p\n",local->rmem); | 480 | local->amem = ioremap(req.Base, req.Size); |
470 | DEBUG(3,"ray_config amem=%p\n",local->amem); | 481 | |
471 | if (ray_init(dev) < 0) { | 482 | DEBUG(3, "ray_config sram=%p\n", local->sram); |
472 | ray_release(link); | 483 | DEBUG(3, "ray_config rmem=%p\n", local->rmem); |
473 | return -ENODEV; | 484 | DEBUG(3, "ray_config amem=%p\n", local->amem); |
474 | } | 485 | if (ray_init(dev) < 0) { |
475 | 486 | ray_release(link); | |
476 | SET_NETDEV_DEV(dev, &handle_to_dev(link)); | 487 | return -ENODEV; |
477 | i = register_netdev(dev); | 488 | } |
478 | if (i != 0) { | 489 | |
479 | printk("ray_config register_netdev() failed\n"); | 490 | SET_NETDEV_DEV(dev, &handle_to_dev(link)); |
480 | ray_release(link); | 491 | i = register_netdev(dev); |
481 | return i; | 492 | if (i != 0) { |
482 | } | 493 | printk("ray_config register_netdev() failed\n"); |
483 | 494 | ray_release(link); | |
484 | strcpy(local->node.dev_name, dev->name); | 495 | return i; |
485 | link->dev_node = &local->node; | 496 | } |
486 | 497 | ||
487 | printk(KERN_INFO "%s: RayLink, irq %d, hw_addr %pM\n", | 498 | strcpy(local->node.dev_name, dev->name); |
488 | dev->name, dev->irq, dev->dev_addr); | 499 | link->dev_node = &local->node; |
489 | 500 | ||
490 | return 0; | 501 | printk(KERN_INFO "%s: RayLink, irq %d, hw_addr %pM\n", |
502 | dev->name, dev->irq, dev->dev_addr); | ||
503 | |||
504 | return 0; | ||
491 | 505 | ||
492 | cs_failed: | 506 | cs_failed: |
493 | cs_error(link, last_fn, last_ret); | 507 | cs_error(link, last_fn, last_ret); |
494 | 508 | ||
495 | ray_release(link); | 509 | ray_release(link); |
496 | return -ENODEV; | 510 | return -ENODEV; |
497 | } /* ray_config */ | 511 | } /* ray_config */ |
498 | 512 | ||
499 | static inline struct ccs __iomem *ccs_base(ray_dev_t *dev) | 513 | static inline struct ccs __iomem *ccs_base(ray_dev_t *dev) |
@@ -516,267 +530,278 @@ static inline struct rcs __iomem *rcs_base(ray_dev_t *dev) | |||
516 | /*===========================================================================*/ | 530 | /*===========================================================================*/ |
517 | static int ray_init(struct net_device *dev) | 531 | static int ray_init(struct net_device *dev) |
518 | { | 532 | { |
519 | int i; | 533 | int i; |
520 | UCHAR *p; | 534 | UCHAR *p; |
521 | struct ccs __iomem *pccs; | 535 | struct ccs __iomem *pccs; |
522 | ray_dev_t *local = netdev_priv(dev); | 536 | ray_dev_t *local = netdev_priv(dev); |
523 | struct pcmcia_device *link = local->finder; | 537 | struct pcmcia_device *link = local->finder; |
524 | DEBUG(1, "ray_init(0x%p)\n", dev); | 538 | DEBUG(1, "ray_init(0x%p)\n", dev); |
525 | if (!(pcmcia_dev_present(link))) { | 539 | if (!(pcmcia_dev_present(link))) { |
526 | DEBUG(0,"ray_init - device not present\n"); | 540 | DEBUG(0, "ray_init - device not present\n"); |
527 | return -1; | 541 | return -1; |
528 | } | 542 | } |
529 | 543 | ||
530 | local->net_type = net_type; | 544 | local->net_type = net_type; |
531 | local->sta_type = TYPE_STA; | 545 | local->sta_type = TYPE_STA; |
532 | 546 | ||
533 | /* Copy the startup results to local memory */ | 547 | /* Copy the startup results to local memory */ |
534 | memcpy_fromio(&local->startup_res, local->sram + ECF_TO_HOST_BASE,\ | 548 | memcpy_fromio(&local->startup_res, local->sram + ECF_TO_HOST_BASE, |
535 | sizeof(struct startup_res_6)); | 549 | sizeof(struct startup_res_6)); |
536 | 550 | ||
537 | /* Check Power up test status and get mac address from card */ | 551 | /* Check Power up test status and get mac address from card */ |
538 | if (local->startup_res.startup_word != 0x80) { | 552 | if (local->startup_res.startup_word != 0x80) { |
539 | printk(KERN_INFO "ray_init ERROR card status = %2x\n", | 553 | printk(KERN_INFO "ray_init ERROR card status = %2x\n", |
540 | local->startup_res.startup_word); | 554 | local->startup_res.startup_word); |
541 | local->card_status = CARD_INIT_ERROR; | 555 | local->card_status = CARD_INIT_ERROR; |
542 | return -1; | 556 | return -1; |
543 | } | 557 | } |
544 | 558 | ||
545 | local->fw_ver = local->startup_res.firmware_version[0]; | 559 | local->fw_ver = local->startup_res.firmware_version[0]; |
546 | local->fw_bld = local->startup_res.firmware_version[1]; | 560 | local->fw_bld = local->startup_res.firmware_version[1]; |
547 | local->fw_var = local->startup_res.firmware_version[2]; | 561 | local->fw_var = local->startup_res.firmware_version[2]; |
548 | DEBUG(1,"ray_init firmware version %d.%d \n",local->fw_ver, local->fw_bld); | 562 | DEBUG(1, "ray_init firmware version %d.%d \n", local->fw_ver, |
549 | 563 | local->fw_bld); | |
550 | local->tib_length = 0x20; | 564 | |
551 | if ((local->fw_ver == 5) && (local->fw_bld >= 30)) | 565 | local->tib_length = 0x20; |
552 | local->tib_length = local->startup_res.tib_length; | 566 | if ((local->fw_ver == 5) && (local->fw_bld >= 30)) |
553 | DEBUG(2,"ray_init tib_length = 0x%02x\n", local->tib_length); | 567 | local->tib_length = local->startup_res.tib_length; |
554 | /* Initialize CCS's to buffer free state */ | 568 | DEBUG(2, "ray_init tib_length = 0x%02x\n", local->tib_length); |
555 | pccs = ccs_base(local); | 569 | /* Initialize CCS's to buffer free state */ |
556 | for (i=0; i<NUMBER_OF_CCS; i++) { | 570 | pccs = ccs_base(local); |
557 | writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); | 571 | for (i = 0; i < NUMBER_OF_CCS; i++) { |
558 | } | 572 | writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); |
559 | init_startup_params(local); | 573 | } |
560 | 574 | init_startup_params(local); | |
561 | /* copy mac address to startup parameters */ | 575 | |
562 | if (parse_addr(phy_addr, local->sparm.b4.a_mac_addr)) | 576 | /* copy mac address to startup parameters */ |
563 | { | 577 | if (parse_addr(phy_addr, local->sparm.b4.a_mac_addr)) { |
564 | p = local->sparm.b4.a_mac_addr; | 578 | p = local->sparm.b4.a_mac_addr; |
565 | } | 579 | } else { |
566 | else | 580 | memcpy(&local->sparm.b4.a_mac_addr, |
567 | { | 581 | &local->startup_res.station_addr, ADDRLEN); |
568 | memcpy(&local->sparm.b4.a_mac_addr, | 582 | p = local->sparm.b4.a_mac_addr; |
569 | &local->startup_res.station_addr, ADDRLEN); | 583 | } |
570 | p = local->sparm.b4.a_mac_addr; | 584 | |
571 | } | 585 | clear_interrupt(local); /* Clear any interrupt from the card */ |
572 | 586 | local->card_status = CARD_AWAITING_PARAM; | |
573 | clear_interrupt(local); /* Clear any interrupt from the card */ | 587 | DEBUG(2, "ray_init ending\n"); |
574 | local->card_status = CARD_AWAITING_PARAM; | 588 | return 0; |
575 | DEBUG(2,"ray_init ending\n"); | ||
576 | return 0; | ||
577 | } /* ray_init */ | 589 | } /* ray_init */ |
590 | |||
578 | /*===========================================================================*/ | 591 | /*===========================================================================*/ |
579 | /* Download startup parameters to the card and command it to read them */ | 592 | /* Download startup parameters to the card and command it to read them */ |
580 | static int dl_startup_params(struct net_device *dev) | 593 | static int dl_startup_params(struct net_device *dev) |
581 | { | 594 | { |
582 | int ccsindex; | 595 | int ccsindex; |
583 | ray_dev_t *local = netdev_priv(dev); | 596 | ray_dev_t *local = netdev_priv(dev); |
584 | struct ccs __iomem *pccs; | 597 | struct ccs __iomem *pccs; |
585 | struct pcmcia_device *link = local->finder; | 598 | struct pcmcia_device *link = local->finder; |
586 | 599 | ||
587 | DEBUG(1,"dl_startup_params entered\n"); | 600 | DEBUG(1, "dl_startup_params entered\n"); |
588 | if (!(pcmcia_dev_present(link))) { | 601 | if (!(pcmcia_dev_present(link))) { |
589 | DEBUG(2,"ray_cs dl_startup_params - device not present\n"); | 602 | DEBUG(2, "ray_cs dl_startup_params - device not present\n"); |
590 | return -1; | 603 | return -1; |
591 | } | 604 | } |
592 | 605 | ||
593 | /* Copy parameters to host to ECF area */ | 606 | /* Copy parameters to host to ECF area */ |
594 | if (local->fw_ver == 0x55) | 607 | if (local->fw_ver == 0x55) |
595 | memcpy_toio(local->sram + HOST_TO_ECF_BASE, &local->sparm.b4, | 608 | memcpy_toio(local->sram + HOST_TO_ECF_BASE, &local->sparm.b4, |
596 | sizeof(struct b4_startup_params)); | 609 | sizeof(struct b4_startup_params)); |
597 | else | 610 | else |
598 | memcpy_toio(local->sram + HOST_TO_ECF_BASE, &local->sparm.b5, | 611 | memcpy_toio(local->sram + HOST_TO_ECF_BASE, &local->sparm.b5, |
599 | sizeof(struct b5_startup_params)); | 612 | sizeof(struct b5_startup_params)); |
600 | 613 | ||
601 | 614 | /* Fill in the CCS fields for the ECF */ | |
602 | /* Fill in the CCS fields for the ECF */ | 615 | if ((ccsindex = get_free_ccs(local)) < 0) |
603 | if ((ccsindex = get_free_ccs(local)) < 0) return -1; | 616 | return -1; |
604 | local->dl_param_ccs = ccsindex; | 617 | local->dl_param_ccs = ccsindex; |
605 | pccs = ccs_base(local) + ccsindex; | 618 | pccs = ccs_base(local) + ccsindex; |
606 | writeb(CCS_DOWNLOAD_STARTUP_PARAMS, &pccs->cmd); | 619 | writeb(CCS_DOWNLOAD_STARTUP_PARAMS, &pccs->cmd); |
607 | DEBUG(2,"dl_startup_params start ccsindex = %d\n", local->dl_param_ccs); | 620 | DEBUG(2, "dl_startup_params start ccsindex = %d\n", |
608 | /* Interrupt the firmware to process the command */ | 621 | local->dl_param_ccs); |
609 | if (interrupt_ecf(local, ccsindex)) { | 622 | /* Interrupt the firmware to process the command */ |
610 | printk(KERN_INFO "ray dl_startup_params failed - " | 623 | if (interrupt_ecf(local, ccsindex)) { |
611 | "ECF not ready for intr\n"); | 624 | printk(KERN_INFO "ray dl_startup_params failed - " |
612 | local->card_status = CARD_DL_PARAM_ERROR; | 625 | "ECF not ready for intr\n"); |
613 | writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); | 626 | local->card_status = CARD_DL_PARAM_ERROR; |
614 | return -2; | 627 | writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); |
615 | } | 628 | return -2; |
616 | local->card_status = CARD_DL_PARAM; | 629 | } |
617 | /* Start kernel timer to wait for dl startup to complete. */ | 630 | local->card_status = CARD_DL_PARAM; |
618 | local->timer.expires = jiffies + HZ/2; | 631 | /* Start kernel timer to wait for dl startup to complete. */ |
619 | local->timer.data = (long)local; | 632 | local->timer.expires = jiffies + HZ / 2; |
620 | local->timer.function = &verify_dl_startup; | 633 | local->timer.data = (long)local; |
621 | add_timer(&local->timer); | 634 | local->timer.function = &verify_dl_startup; |
622 | DEBUG(2,"ray_cs dl_startup_params started timer for verify_dl_startup\n"); | 635 | add_timer(&local->timer); |
623 | return 0; | 636 | DEBUG(2, |
637 | "ray_cs dl_startup_params started timer for verify_dl_startup\n"); | ||
638 | return 0; | ||
624 | } /* dl_startup_params */ | 639 | } /* dl_startup_params */ |
640 | |||
625 | /*===========================================================================*/ | 641 | /*===========================================================================*/ |
626 | static void init_startup_params(ray_dev_t *local) | 642 | static void init_startup_params(ray_dev_t *local) |
627 | { | 643 | { |
628 | int i; | 644 | int i; |
629 | 645 | ||
630 | if (country > JAPAN_TEST) country = USA; | 646 | if (country > JAPAN_TEST) |
631 | else | 647 | country = USA; |
632 | if (country < USA) country = USA; | 648 | else if (country < USA) |
633 | /* structure for hop time and beacon period is defined here using | 649 | country = USA; |
634 | * New 802.11D6.1 format. Card firmware is still using old format | 650 | /* structure for hop time and beacon period is defined here using |
635 | * until version 6. | 651 | * New 802.11D6.1 format. Card firmware is still using old format |
636 | * Before After | 652 | * until version 6. |
637 | * a_hop_time ms byte a_hop_time ms byte | 653 | * Before After |
638 | * a_hop_time 2s byte a_hop_time ls byte | 654 | * a_hop_time ms byte a_hop_time ms byte |
639 | * a_hop_time ls byte a_beacon_period ms byte | 655 | * a_hop_time 2s byte a_hop_time ls byte |
640 | * a_beacon_period a_beacon_period ls byte | 656 | * a_hop_time ls byte a_beacon_period ms byte |
641 | * | 657 | * a_beacon_period a_beacon_period ls byte |
642 | * a_hop_time = uS a_hop_time = KuS | 658 | * |
643 | * a_beacon_period = hops a_beacon_period = KuS | 659 | * a_hop_time = uS a_hop_time = KuS |
644 | */ /* 64ms = 010000 */ | 660 | * a_beacon_period = hops a_beacon_period = KuS |
645 | if (local->fw_ver == 0x55) { | 661 | *//* 64ms = 010000 */ |
646 | memcpy((UCHAR *)&local->sparm.b4, b4_default_startup_parms, | 662 | if (local->fw_ver == 0x55) { |
647 | sizeof(struct b4_startup_params)); | 663 | memcpy((UCHAR *) &local->sparm.b4, b4_default_startup_parms, |
648 | /* Translate sane kus input values to old build 4/5 format */ | 664 | sizeof(struct b4_startup_params)); |
649 | /* i = hop time in uS truncated to 3 bytes */ | 665 | /* Translate sane kus input values to old build 4/5 format */ |
650 | i = (hop_dwell * 1024) & 0xffffff; | 666 | /* i = hop time in uS truncated to 3 bytes */ |
651 | local->sparm.b4.a_hop_time[0] = (i >> 16) & 0xff; | 667 | i = (hop_dwell * 1024) & 0xffffff; |
652 | local->sparm.b4.a_hop_time[1] = (i >> 8) & 0xff; | 668 | local->sparm.b4.a_hop_time[0] = (i >> 16) & 0xff; |
653 | local->sparm.b4.a_beacon_period[0] = 0; | 669 | local->sparm.b4.a_hop_time[1] = (i >> 8) & 0xff; |
654 | local->sparm.b4.a_beacon_period[1] = | 670 | local->sparm.b4.a_beacon_period[0] = 0; |
655 | ((beacon_period/hop_dwell) - 1) & 0xff; | 671 | local->sparm.b4.a_beacon_period[1] = |
656 | local->sparm.b4.a_curr_country_code = country; | 672 | ((beacon_period / hop_dwell) - 1) & 0xff; |
657 | local->sparm.b4.a_hop_pattern_length = | 673 | local->sparm.b4.a_curr_country_code = country; |
658 | hop_pattern_length[(int)country] - 1; | 674 | local->sparm.b4.a_hop_pattern_length = |
659 | if (bc) | 675 | hop_pattern_length[(int)country] - 1; |
660 | { | 676 | if (bc) { |
661 | local->sparm.b4.a_ack_timeout = 0x50; | 677 | local->sparm.b4.a_ack_timeout = 0x50; |
662 | local->sparm.b4.a_sifs = 0x3f; | 678 | local->sparm.b4.a_sifs = 0x3f; |
663 | } | 679 | } |
664 | } | 680 | } else { /* Version 5 uses real kus values */ |
665 | else { /* Version 5 uses real kus values */ | 681 | memcpy((UCHAR *) &local->sparm.b5, b5_default_startup_parms, |
666 | memcpy((UCHAR *)&local->sparm.b5, b5_default_startup_parms, | 682 | sizeof(struct b5_startup_params)); |
667 | sizeof(struct b5_startup_params)); | 683 | |
668 | 684 | local->sparm.b5.a_hop_time[0] = (hop_dwell >> 8) & 0xff; | |
669 | local->sparm.b5.a_hop_time[0] = (hop_dwell >> 8) & 0xff; | 685 | local->sparm.b5.a_hop_time[1] = hop_dwell & 0xff; |
670 | local->sparm.b5.a_hop_time[1] = hop_dwell & 0xff; | 686 | local->sparm.b5.a_beacon_period[0] = |
671 | local->sparm.b5.a_beacon_period[0] = (beacon_period >> 8) & 0xff; | 687 | (beacon_period >> 8) & 0xff; |
672 | local->sparm.b5.a_beacon_period[1] = beacon_period & 0xff; | 688 | local->sparm.b5.a_beacon_period[1] = beacon_period & 0xff; |
673 | if (psm) | 689 | if (psm) |
674 | local->sparm.b5.a_power_mgt_state = 1; | 690 | local->sparm.b5.a_power_mgt_state = 1; |
675 | local->sparm.b5.a_curr_country_code = country; | 691 | local->sparm.b5.a_curr_country_code = country; |
676 | local->sparm.b5.a_hop_pattern_length = | 692 | local->sparm.b5.a_hop_pattern_length = |
677 | hop_pattern_length[(int)country]; | 693 | hop_pattern_length[(int)country]; |
678 | } | 694 | } |
679 | 695 | ||
680 | local->sparm.b4.a_network_type = net_type & 0x01; | 696 | local->sparm.b4.a_network_type = net_type & 0x01; |
681 | local->sparm.b4.a_acting_as_ap_status = TYPE_STA; | 697 | local->sparm.b4.a_acting_as_ap_status = TYPE_STA; |
682 | 698 | ||
683 | if (essid != NULL) | 699 | if (essid != NULL) |
684 | strncpy(local->sparm.b4.a_current_ess_id, essid, ESSID_SIZE); | 700 | strncpy(local->sparm.b4.a_current_ess_id, essid, ESSID_SIZE); |
685 | } /* init_startup_params */ | 701 | } /* init_startup_params */ |
702 | |||
686 | /*===========================================================================*/ | 703 | /*===========================================================================*/ |
687 | static void verify_dl_startup(u_long data) | 704 | static void verify_dl_startup(u_long data) |
688 | { | 705 | { |
689 | ray_dev_t *local = (ray_dev_t *)data; | 706 | ray_dev_t *local = (ray_dev_t *) data; |
690 | struct ccs __iomem *pccs = ccs_base(local) + local->dl_param_ccs; | 707 | struct ccs __iomem *pccs = ccs_base(local) + local->dl_param_ccs; |
691 | UCHAR status; | 708 | UCHAR status; |
692 | struct pcmcia_device *link = local->finder; | 709 | struct pcmcia_device *link = local->finder; |
693 | 710 | ||
694 | if (!(pcmcia_dev_present(link))) { | 711 | if (!(pcmcia_dev_present(link))) { |
695 | DEBUG(2,"ray_cs verify_dl_startup - device not present\n"); | 712 | DEBUG(2, "ray_cs verify_dl_startup - device not present\n"); |
696 | return; | 713 | return; |
697 | } | 714 | } |
698 | #ifdef PCMCIA_DEBUG | 715 | #ifdef PCMCIA_DEBUG |
699 | if (pc_debug > 2) { | 716 | if (pc_debug > 2) { |
700 | int i; | 717 | int i; |
701 | printk(KERN_DEBUG "verify_dl_startup parameters sent via ccs %d:\n", | 718 | printk(KERN_DEBUG |
702 | local->dl_param_ccs); | 719 | "verify_dl_startup parameters sent via ccs %d:\n", |
703 | for (i=0; i<sizeof(struct b5_startup_params); i++) { | 720 | local->dl_param_ccs); |
704 | printk(" %2x", (unsigned int) readb(local->sram + HOST_TO_ECF_BASE + i)); | 721 | for (i = 0; i < sizeof(struct b5_startup_params); i++) { |
705 | } | 722 | printk(" %2x", |
706 | printk("\n"); | 723 | (unsigned int)readb(local->sram + |
707 | } | 724 | HOST_TO_ECF_BASE + i)); |
725 | } | ||
726 | printk("\n"); | ||
727 | } | ||
708 | #endif | 728 | #endif |
709 | 729 | ||
710 | status = readb(&pccs->buffer_status); | 730 | status = readb(&pccs->buffer_status); |
711 | if (status!= CCS_BUFFER_FREE) | 731 | if (status != CCS_BUFFER_FREE) { |
712 | { | 732 | printk(KERN_INFO |
713 | printk(KERN_INFO "Download startup params failed. Status = %d\n", | 733 | "Download startup params failed. Status = %d\n", |
714 | status); | 734 | status); |
715 | local->card_status = CARD_DL_PARAM_ERROR; | 735 | local->card_status = CARD_DL_PARAM_ERROR; |
716 | return; | 736 | return; |
717 | } | 737 | } |
718 | if (local->sparm.b4.a_network_type == ADHOC) | 738 | if (local->sparm.b4.a_network_type == ADHOC) |
719 | start_net((u_long)local); | 739 | start_net((u_long) local); |
720 | else | 740 | else |
721 | join_net((u_long)local); | 741 | join_net((u_long) local); |
722 | 742 | ||
723 | return; | 743 | return; |
724 | } /* end verify_dl_startup */ | 744 | } /* end verify_dl_startup */ |
745 | |||
725 | /*===========================================================================*/ | 746 | /*===========================================================================*/ |
726 | /* Command card to start a network */ | 747 | /* Command card to start a network */ |
727 | static void start_net(u_long data) | 748 | static void start_net(u_long data) |
728 | { | 749 | { |
729 | ray_dev_t *local = (ray_dev_t *)data; | 750 | ray_dev_t *local = (ray_dev_t *) data; |
730 | struct ccs __iomem *pccs; | 751 | struct ccs __iomem *pccs; |
731 | int ccsindex; | 752 | int ccsindex; |
732 | struct pcmcia_device *link = local->finder; | 753 | struct pcmcia_device *link = local->finder; |
733 | if (!(pcmcia_dev_present(link))) { | 754 | if (!(pcmcia_dev_present(link))) { |
734 | DEBUG(2,"ray_cs start_net - device not present\n"); | 755 | DEBUG(2, "ray_cs start_net - device not present\n"); |
735 | return; | 756 | return; |
736 | } | 757 | } |
737 | /* Fill in the CCS fields for the ECF */ | 758 | /* Fill in the CCS fields for the ECF */ |
738 | if ((ccsindex = get_free_ccs(local)) < 0) return; | 759 | if ((ccsindex = get_free_ccs(local)) < 0) |
739 | pccs = ccs_base(local) + ccsindex; | 760 | return; |
740 | writeb(CCS_START_NETWORK, &pccs->cmd); | 761 | pccs = ccs_base(local) + ccsindex; |
741 | writeb(0, &pccs->var.start_network.update_param); | 762 | writeb(CCS_START_NETWORK, &pccs->cmd); |
742 | /* Interrupt the firmware to process the command */ | 763 | writeb(0, &pccs->var.start_network.update_param); |
743 | if (interrupt_ecf(local, ccsindex)) { | 764 | /* Interrupt the firmware to process the command */ |
744 | DEBUG(1,"ray start net failed - card not ready for intr\n"); | 765 | if (interrupt_ecf(local, ccsindex)) { |
745 | writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); | 766 | DEBUG(1, "ray start net failed - card not ready for intr\n"); |
746 | return; | 767 | writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); |
747 | } | 768 | return; |
748 | local->card_status = CARD_DOING_ACQ; | 769 | } |
749 | return; | 770 | local->card_status = CARD_DOING_ACQ; |
771 | return; | ||
750 | } /* end start_net */ | 772 | } /* end start_net */ |
773 | |||
751 | /*===========================================================================*/ | 774 | /*===========================================================================*/ |
752 | /* Command card to join a network */ | 775 | /* Command card to join a network */ |
753 | static void join_net(u_long data) | 776 | static void join_net(u_long data) |
754 | { | 777 | { |
755 | ray_dev_t *local = (ray_dev_t *)data; | 778 | ray_dev_t *local = (ray_dev_t *) data; |
756 | 779 | ||
757 | struct ccs __iomem *pccs; | 780 | struct ccs __iomem *pccs; |
758 | int ccsindex; | 781 | int ccsindex; |
759 | struct pcmcia_device *link = local->finder; | 782 | struct pcmcia_device *link = local->finder; |
760 | 783 | ||
761 | if (!(pcmcia_dev_present(link))) { | 784 | if (!(pcmcia_dev_present(link))) { |
762 | DEBUG(2,"ray_cs join_net - device not present\n"); | 785 | DEBUG(2, "ray_cs join_net - device not present\n"); |
763 | return; | 786 | return; |
764 | } | 787 | } |
765 | /* Fill in the CCS fields for the ECF */ | 788 | /* Fill in the CCS fields for the ECF */ |
766 | if ((ccsindex = get_free_ccs(local)) < 0) return; | 789 | if ((ccsindex = get_free_ccs(local)) < 0) |
767 | pccs = ccs_base(local) + ccsindex; | 790 | return; |
768 | writeb(CCS_JOIN_NETWORK, &pccs->cmd); | 791 | pccs = ccs_base(local) + ccsindex; |
769 | writeb(0, &pccs->var.join_network.update_param); | 792 | writeb(CCS_JOIN_NETWORK, &pccs->cmd); |
770 | writeb(0, &pccs->var.join_network.net_initiated); | 793 | writeb(0, &pccs->var.join_network.update_param); |
771 | /* Interrupt the firmware to process the command */ | 794 | writeb(0, &pccs->var.join_network.net_initiated); |
772 | if (interrupt_ecf(local, ccsindex)) { | 795 | /* Interrupt the firmware to process the command */ |
773 | DEBUG(1,"ray join net failed - card not ready for intr\n"); | 796 | if (interrupt_ecf(local, ccsindex)) { |
774 | writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); | 797 | DEBUG(1, "ray join net failed - card not ready for intr\n"); |
775 | return; | 798 | writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); |
776 | } | 799 | return; |
777 | local->card_status = CARD_DOING_ACQ; | 800 | } |
778 | return; | 801 | local->card_status = CARD_DOING_ACQ; |
802 | return; | ||
779 | } | 803 | } |
804 | |||
780 | /*============================================================================ | 805 | /*============================================================================ |
781 | After a card is removed, ray_release() will unregister the net | 806 | After a card is removed, ray_release() will unregister the net |
782 | device, and release the PCMCIA configuration. If the device is | 807 | device, and release the PCMCIA configuration. If the device is |
@@ -784,25 +809,27 @@ static void join_net(u_long data) | |||
784 | =============================================================================*/ | 809 | =============================================================================*/ |
785 | static void ray_release(struct pcmcia_device *link) | 810 | static void ray_release(struct pcmcia_device *link) |
786 | { | 811 | { |
787 | struct net_device *dev = link->priv; | 812 | struct net_device *dev = link->priv; |
788 | ray_dev_t *local = netdev_priv(dev); | 813 | ray_dev_t *local = netdev_priv(dev); |
789 | int i; | 814 | int i; |
790 | 815 | ||
791 | DEBUG(1, "ray_release(0x%p)\n", link); | 816 | DEBUG(1, "ray_release(0x%p)\n", link); |
792 | 817 | ||
793 | del_timer(&local->timer); | 818 | del_timer(&local->timer); |
794 | 819 | ||
795 | iounmap(local->sram); | 820 | iounmap(local->sram); |
796 | iounmap(local->rmem); | 821 | iounmap(local->rmem); |
797 | iounmap(local->amem); | 822 | iounmap(local->amem); |
798 | /* Do bother checking to see if these succeed or not */ | 823 | /* Do bother checking to see if these succeed or not */ |
799 | i = pcmcia_release_window(local->amem_handle); | 824 | i = pcmcia_release_window(local->amem_handle); |
800 | if ( i != 0 ) DEBUG(0,"ReleaseWindow(local->amem) ret = %x\n",i); | 825 | if (i != 0) |
801 | i = pcmcia_release_window(local->rmem_handle); | 826 | DEBUG(0, "ReleaseWindow(local->amem) ret = %x\n", i); |
802 | if ( i != 0 ) DEBUG(0,"ReleaseWindow(local->rmem) ret = %x\n",i); | 827 | i = pcmcia_release_window(local->rmem_handle); |
803 | pcmcia_disable_device(link); | 828 | if (i != 0) |
804 | 829 | DEBUG(0, "ReleaseWindow(local->rmem) ret = %x\n", i); | |
805 | DEBUG(2,"ray_release ending\n"); | 830 | pcmcia_disable_device(link); |
831 | |||
832 | DEBUG(2, "ray_release ending\n"); | ||
806 | } | 833 | } |
807 | 834 | ||
808 | static int ray_suspend(struct pcmcia_device *link) | 835 | static int ray_suspend(struct pcmcia_device *link) |
@@ -831,237 +858,243 @@ static int ray_resume(struct pcmcia_device *link) | |||
831 | static int ray_dev_init(struct net_device *dev) | 858 | static int ray_dev_init(struct net_device *dev) |
832 | { | 859 | { |
833 | #ifdef RAY_IMMEDIATE_INIT | 860 | #ifdef RAY_IMMEDIATE_INIT |
834 | int i; | 861 | int i; |
835 | #endif /* RAY_IMMEDIATE_INIT */ | 862 | #endif /* RAY_IMMEDIATE_INIT */ |
836 | ray_dev_t *local = netdev_priv(dev); | 863 | ray_dev_t *local = netdev_priv(dev); |
837 | struct pcmcia_device *link = local->finder; | 864 | struct pcmcia_device *link = local->finder; |
838 | 865 | ||
839 | DEBUG(1,"ray_dev_init(dev=%p)\n",dev); | 866 | DEBUG(1, "ray_dev_init(dev=%p)\n", dev); |
840 | if (!(pcmcia_dev_present(link))) { | 867 | if (!(pcmcia_dev_present(link))) { |
841 | DEBUG(2,"ray_dev_init - device not present\n"); | 868 | DEBUG(2, "ray_dev_init - device not present\n"); |
842 | return -1; | 869 | return -1; |
843 | } | 870 | } |
844 | #ifdef RAY_IMMEDIATE_INIT | 871 | #ifdef RAY_IMMEDIATE_INIT |
845 | /* Download startup parameters */ | 872 | /* Download startup parameters */ |
846 | if ( (i = dl_startup_params(dev)) < 0) | 873 | if ((i = dl_startup_params(dev)) < 0) { |
847 | { | 874 | printk(KERN_INFO "ray_dev_init dl_startup_params failed - " |
848 | printk(KERN_INFO "ray_dev_init dl_startup_params failed - " | 875 | "returns 0x%x\n", i); |
849 | "returns 0x%x\n",i); | 876 | return -1; |
850 | return -1; | 877 | } |
851 | } | 878 | #else /* RAY_IMMEDIATE_INIT */ |
852 | #else /* RAY_IMMEDIATE_INIT */ | 879 | /* Postpone the card init so that we can still configure the card, |
853 | /* Postpone the card init so that we can still configure the card, | 880 | * for example using the Wireless Extensions. The init will happen |
854 | * for example using the Wireless Extensions. The init will happen | 881 | * in ray_open() - Jean II */ |
855 | * in ray_open() - Jean II */ | 882 | DEBUG(1, |
856 | DEBUG(1,"ray_dev_init: postponing card init to ray_open() ; Status = %d\n", | 883 | "ray_dev_init: postponing card init to ray_open() ; Status = %d\n", |
857 | local->card_status); | 884 | local->card_status); |
858 | #endif /* RAY_IMMEDIATE_INIT */ | 885 | #endif /* RAY_IMMEDIATE_INIT */ |
859 | 886 | ||
860 | /* copy mac and broadcast addresses to linux device */ | 887 | /* copy mac and broadcast addresses to linux device */ |
861 | memcpy(&dev->dev_addr, &local->sparm.b4.a_mac_addr, ADDRLEN); | 888 | memcpy(&dev->dev_addr, &local->sparm.b4.a_mac_addr, ADDRLEN); |
862 | memset(dev->broadcast, 0xff, ETH_ALEN); | 889 | memset(dev->broadcast, 0xff, ETH_ALEN); |
863 | 890 | ||
864 | DEBUG(2,"ray_dev_init ending\n"); | 891 | DEBUG(2, "ray_dev_init ending\n"); |
865 | return 0; | 892 | return 0; |
866 | } | 893 | } |
894 | |||
867 | /*===========================================================================*/ | 895 | /*===========================================================================*/ |
868 | static int ray_dev_config(struct net_device *dev, struct ifmap *map) | 896 | static int ray_dev_config(struct net_device *dev, struct ifmap *map) |
869 | { | 897 | { |
870 | ray_dev_t *local = netdev_priv(dev); | 898 | ray_dev_t *local = netdev_priv(dev); |
871 | struct pcmcia_device *link = local->finder; | 899 | struct pcmcia_device *link = local->finder; |
872 | /* Dummy routine to satisfy device structure */ | 900 | /* Dummy routine to satisfy device structure */ |
873 | DEBUG(1,"ray_dev_config(dev=%p,ifmap=%p)\n",dev,map); | 901 | DEBUG(1, "ray_dev_config(dev=%p,ifmap=%p)\n", dev, map); |
874 | if (!(pcmcia_dev_present(link))) { | 902 | if (!(pcmcia_dev_present(link))) { |
875 | DEBUG(2,"ray_dev_config - device not present\n"); | 903 | DEBUG(2, "ray_dev_config - device not present\n"); |
876 | return -1; | 904 | return -1; |
877 | } | 905 | } |
878 | 906 | ||
879 | return 0; | 907 | return 0; |
880 | } | 908 | } |
909 | |||
881 | /*===========================================================================*/ | 910 | /*===========================================================================*/ |
882 | static int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev) | 911 | static int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev) |
883 | { | 912 | { |
884 | ray_dev_t *local = netdev_priv(dev); | 913 | ray_dev_t *local = netdev_priv(dev); |
885 | struct pcmcia_device *link = local->finder; | 914 | struct pcmcia_device *link = local->finder; |
886 | short length = skb->len; | 915 | short length = skb->len; |
887 | 916 | ||
888 | if (!(pcmcia_dev_present(link))) { | 917 | if (!(pcmcia_dev_present(link))) { |
889 | DEBUG(2,"ray_dev_start_xmit - device not present\n"); | 918 | DEBUG(2, "ray_dev_start_xmit - device not present\n"); |
890 | return -1; | 919 | return -1; |
891 | } | 920 | } |
892 | DEBUG(3,"ray_dev_start_xmit(skb=%p, dev=%p)\n",skb,dev); | 921 | DEBUG(3, "ray_dev_start_xmit(skb=%p, dev=%p)\n", skb, dev); |
893 | if (local->authentication_state == NEED_TO_AUTH) { | 922 | if (local->authentication_state == NEED_TO_AUTH) { |
894 | DEBUG(0,"ray_cs Sending authentication request.\n"); | 923 | DEBUG(0, "ray_cs Sending authentication request.\n"); |
895 | if (!build_auth_frame (local, local->auth_id, OPEN_AUTH_REQUEST)) { | 924 | if (!build_auth_frame(local, local->auth_id, OPEN_AUTH_REQUEST)) { |
896 | local->authentication_state = AUTHENTICATED; | 925 | local->authentication_state = AUTHENTICATED; |
897 | netif_stop_queue(dev); | 926 | netif_stop_queue(dev); |
898 | return 1; | 927 | return 1; |
899 | } | 928 | } |
900 | } | 929 | } |
901 | 930 | ||
902 | if (length < ETH_ZLEN) | 931 | if (length < ETH_ZLEN) { |
903 | { | 932 | if (skb_padto(skb, ETH_ZLEN)) |
904 | if (skb_padto(skb, ETH_ZLEN)) | 933 | return 0; |
905 | return 0; | 934 | length = ETH_ZLEN; |
906 | length = ETH_ZLEN; | 935 | } |
907 | } | 936 | switch (ray_hw_xmit(skb->data, length, dev, DATA_TYPE)) { |
908 | switch (ray_hw_xmit( skb->data, length, dev, DATA_TYPE)) { | 937 | case XMIT_NO_CCS: |
909 | case XMIT_NO_CCS: | 938 | case XMIT_NEED_AUTH: |
910 | case XMIT_NEED_AUTH: | 939 | netif_stop_queue(dev); |
911 | netif_stop_queue(dev); | 940 | return 1; |
912 | return 1; | 941 | case XMIT_NO_INTR: |
913 | case XMIT_NO_INTR: | 942 | case XMIT_MSG_BAD: |
914 | case XMIT_MSG_BAD: | 943 | case XMIT_OK: |
915 | case XMIT_OK: | 944 | default: |
916 | default: | 945 | dev->trans_start = jiffies; |
917 | dev->trans_start = jiffies; | 946 | dev_kfree_skb(skb); |
918 | dev_kfree_skb(skb); | 947 | return 0; |
919 | return 0; | 948 | } |
920 | } | 949 | return 0; |
921 | return 0; | ||
922 | } /* ray_dev_start_xmit */ | 950 | } /* ray_dev_start_xmit */ |
951 | |||
923 | /*===========================================================================*/ | 952 | /*===========================================================================*/ |
924 | static int ray_hw_xmit(unsigned char* data, int len, struct net_device* dev, | 953 | static int ray_hw_xmit(unsigned char *data, int len, struct net_device *dev, |
925 | UCHAR msg_type) | 954 | UCHAR msg_type) |
926 | { | 955 | { |
927 | ray_dev_t *local = netdev_priv(dev); | 956 | ray_dev_t *local = netdev_priv(dev); |
928 | struct ccs __iomem *pccs; | 957 | struct ccs __iomem *pccs; |
929 | int ccsindex; | 958 | int ccsindex; |
930 | int offset; | 959 | int offset; |
931 | struct tx_msg __iomem *ptx; /* Address of xmit buffer in PC space */ | 960 | struct tx_msg __iomem *ptx; /* Address of xmit buffer in PC space */ |
932 | short int addr; /* Address of xmit buffer in card space */ | 961 | short int addr; /* Address of xmit buffer in card space */ |
933 | 962 | ||
934 | DEBUG(3,"ray_hw_xmit(data=%p, len=%d, dev=%p)\n",data,len,dev); | 963 | DEBUG(3, "ray_hw_xmit(data=%p, len=%d, dev=%p)\n", data, len, dev); |
935 | if (len + TX_HEADER_LENGTH > TX_BUF_SIZE) | 964 | if (len + TX_HEADER_LENGTH > TX_BUF_SIZE) { |
936 | { | 965 | printk(KERN_INFO "ray_hw_xmit packet too large: %d bytes\n", |
937 | printk(KERN_INFO "ray_hw_xmit packet too large: %d bytes\n",len); | 966 | len); |
938 | return XMIT_MSG_BAD; | 967 | return XMIT_MSG_BAD; |
939 | } | 968 | } |
940 | switch (ccsindex = get_free_tx_ccs(local)) { | 969 | switch (ccsindex = get_free_tx_ccs(local)) { |
941 | case ECCSBUSY: | 970 | case ECCSBUSY: |
942 | DEBUG(2,"ray_hw_xmit tx_ccs table busy\n"); | 971 | DEBUG(2, "ray_hw_xmit tx_ccs table busy\n"); |
943 | case ECCSFULL: | 972 | case ECCSFULL: |
944 | DEBUG(2,"ray_hw_xmit No free tx ccs\n"); | 973 | DEBUG(2, "ray_hw_xmit No free tx ccs\n"); |
945 | case ECARDGONE: | 974 | case ECARDGONE: |
946 | netif_stop_queue(dev); | 975 | netif_stop_queue(dev); |
947 | return XMIT_NO_CCS; | 976 | return XMIT_NO_CCS; |
948 | default: | 977 | default: |
949 | break; | 978 | break; |
950 | } | 979 | } |
951 | addr = TX_BUF_BASE + (ccsindex << 11); | 980 | addr = TX_BUF_BASE + (ccsindex << 11); |
952 | 981 | ||
953 | if (msg_type == DATA_TYPE) { | 982 | if (msg_type == DATA_TYPE) { |
954 | local->stats.tx_bytes += len; | 983 | local->stats.tx_bytes += len; |
955 | local->stats.tx_packets++; | 984 | local->stats.tx_packets++; |
956 | } | 985 | } |
957 | 986 | ||
958 | ptx = local->sram + addr; | 987 | ptx = local->sram + addr; |
959 | 988 | ||
960 | ray_build_header(local, ptx, msg_type, data); | 989 | ray_build_header(local, ptx, msg_type, data); |
961 | if (translate) { | 990 | if (translate) { |
962 | offset = translate_frame(local, ptx, data, len); | 991 | offset = translate_frame(local, ptx, data, len); |
963 | } | 992 | } else { /* Encapsulate frame */ |
964 | else { /* Encapsulate frame */ | 993 | /* TBD TIB length will move address of ptx->var */ |
965 | /* TBD TIB length will move address of ptx->var */ | 994 | memcpy_toio(&ptx->var, data, len); |
966 | memcpy_toio(&ptx->var, data, len); | 995 | offset = 0; |
967 | offset = 0; | 996 | } |
968 | } | 997 | |
969 | 998 | /* fill in the CCS */ | |
970 | /* fill in the CCS */ | 999 | pccs = ccs_base(local) + ccsindex; |
971 | pccs = ccs_base(local) + ccsindex; | 1000 | len += TX_HEADER_LENGTH + offset; |
972 | len += TX_HEADER_LENGTH + offset; | 1001 | writeb(CCS_TX_REQUEST, &pccs->cmd); |
973 | writeb(CCS_TX_REQUEST, &pccs->cmd); | 1002 | writeb(addr >> 8, &pccs->var.tx_request.tx_data_ptr[0]); |
974 | writeb(addr >> 8, &pccs->var.tx_request.tx_data_ptr[0]); | 1003 | writeb(local->tib_length, &pccs->var.tx_request.tx_data_ptr[1]); |
975 | writeb(local->tib_length, &pccs->var.tx_request.tx_data_ptr[1]); | 1004 | writeb(len >> 8, &pccs->var.tx_request.tx_data_length[0]); |
976 | writeb(len >> 8, &pccs->var.tx_request.tx_data_length[0]); | 1005 | writeb(len & 0xff, &pccs->var.tx_request.tx_data_length[1]); |
977 | writeb(len & 0xff, &pccs->var.tx_request.tx_data_length[1]); | ||
978 | /* TBD still need psm_cam? */ | 1006 | /* TBD still need psm_cam? */ |
979 | writeb(PSM_CAM, &pccs->var.tx_request.pow_sav_mode); | 1007 | writeb(PSM_CAM, &pccs->var.tx_request.pow_sav_mode); |
980 | writeb(local->net_default_tx_rate, &pccs->var.tx_request.tx_rate); | 1008 | writeb(local->net_default_tx_rate, &pccs->var.tx_request.tx_rate); |
981 | writeb(0, &pccs->var.tx_request.antenna); | 1009 | writeb(0, &pccs->var.tx_request.antenna); |
982 | DEBUG(3,"ray_hw_xmit default_tx_rate = 0x%x\n",\ | 1010 | DEBUG(3, "ray_hw_xmit default_tx_rate = 0x%x\n", |
983 | local->net_default_tx_rate); | 1011 | local->net_default_tx_rate); |
984 | 1012 | ||
985 | /* Interrupt the firmware to process the command */ | 1013 | /* Interrupt the firmware to process the command */ |
986 | if (interrupt_ecf(local, ccsindex)) { | 1014 | if (interrupt_ecf(local, ccsindex)) { |
987 | DEBUG(2,"ray_hw_xmit failed - ECF not ready for intr\n"); | 1015 | DEBUG(2, "ray_hw_xmit failed - ECF not ready for intr\n"); |
988 | /* TBD very inefficient to copy packet to buffer, and then not | 1016 | /* TBD very inefficient to copy packet to buffer, and then not |
989 | send it, but the alternative is to queue the messages and that | 1017 | send it, but the alternative is to queue the messages and that |
990 | won't be done for a while. Maybe set tbusy until a CCS is free? | 1018 | won't be done for a while. Maybe set tbusy until a CCS is free? |
991 | */ | 1019 | */ |
992 | writeb(CCS_BUFFER_FREE, &pccs->buffer_status); | 1020 | writeb(CCS_BUFFER_FREE, &pccs->buffer_status); |
993 | return XMIT_NO_INTR; | 1021 | return XMIT_NO_INTR; |
994 | } | 1022 | } |
995 | return XMIT_OK; | 1023 | return XMIT_OK; |
996 | } /* end ray_hw_xmit */ | 1024 | } /* end ray_hw_xmit */ |
1025 | |||
997 | /*===========================================================================*/ | 1026 | /*===========================================================================*/ |
998 | static int translate_frame(ray_dev_t *local, struct tx_msg __iomem *ptx, unsigned char *data, | 1027 | static int translate_frame(ray_dev_t *local, struct tx_msg __iomem *ptx, |
999 | int len) | 1028 | unsigned char *data, int len) |
1000 | { | 1029 | { |
1001 | __be16 proto = ((struct ethhdr *)data)->h_proto; | 1030 | __be16 proto = ((struct ethhdr *)data)->h_proto; |
1002 | if (ntohs(proto) >= 1536) { /* DIX II ethernet frame */ | 1031 | if (ntohs(proto) >= 1536) { /* DIX II ethernet frame */ |
1003 | DEBUG(3,"ray_cs translate_frame DIX II\n"); | 1032 | DEBUG(3, "ray_cs translate_frame DIX II\n"); |
1004 | /* Copy LLC header to card buffer */ | 1033 | /* Copy LLC header to card buffer */ |
1005 | memcpy_toio(&ptx->var, eth2_llc, sizeof(eth2_llc)); | 1034 | memcpy_toio(&ptx->var, eth2_llc, sizeof(eth2_llc)); |
1006 | memcpy_toio( ((void __iomem *)&ptx->var) + sizeof(eth2_llc), (UCHAR *)&proto, 2); | 1035 | memcpy_toio(((void __iomem *)&ptx->var) + sizeof(eth2_llc), |
1007 | if (proto == htons(ETH_P_AARP) || proto == htons(ETH_P_IPX)) { | 1036 | (UCHAR *) &proto, 2); |
1008 | /* This is the selective translation table, only 2 entries */ | 1037 | if (proto == htons(ETH_P_AARP) || proto == htons(ETH_P_IPX)) { |
1009 | writeb(0xf8, &((struct snaphdr_t __iomem *)ptx->var)->org[3]); | 1038 | /* This is the selective translation table, only 2 entries */ |
1010 | } | 1039 | writeb(0xf8, |
1011 | /* Copy body of ethernet packet without ethernet header */ | 1040 | &((struct snaphdr_t __iomem *)ptx->var)->org[3]); |
1012 | memcpy_toio((void __iomem *)&ptx->var + sizeof(struct snaphdr_t), \ | 1041 | } |
1013 | data + ETH_HLEN, len - ETH_HLEN); | 1042 | /* Copy body of ethernet packet without ethernet header */ |
1014 | return (int) sizeof(struct snaphdr_t) - ETH_HLEN; | 1043 | memcpy_toio((void __iomem *)&ptx->var + |
1015 | } | 1044 | sizeof(struct snaphdr_t), data + ETH_HLEN, |
1016 | else { /* already 802 type, and proto is length */ | 1045 | len - ETH_HLEN); |
1017 | DEBUG(3,"ray_cs translate_frame 802\n"); | 1046 | return (int)sizeof(struct snaphdr_t) - ETH_HLEN; |
1018 | if (proto == htons(0xffff)) { /* evil netware IPX 802.3 without LLC */ | 1047 | } else { /* already 802 type, and proto is length */ |
1019 | DEBUG(3,"ray_cs translate_frame evil IPX\n"); | 1048 | DEBUG(3, "ray_cs translate_frame 802\n"); |
1020 | memcpy_toio(&ptx->var, data + ETH_HLEN, len - ETH_HLEN); | 1049 | if (proto == htons(0xffff)) { /* evil netware IPX 802.3 without LLC */ |
1021 | return 0 - ETH_HLEN; | 1050 | DEBUG(3, "ray_cs translate_frame evil IPX\n"); |
1022 | } | 1051 | memcpy_toio(&ptx->var, data + ETH_HLEN, len - ETH_HLEN); |
1023 | memcpy_toio(&ptx->var, data + ETH_HLEN, len - ETH_HLEN); | 1052 | return 0 - ETH_HLEN; |
1024 | return 0 - ETH_HLEN; | 1053 | } |
1025 | } | 1054 | memcpy_toio(&ptx->var, data + ETH_HLEN, len - ETH_HLEN); |
1026 | /* TBD do other frame types */ | 1055 | return 0 - ETH_HLEN; |
1056 | } | ||
1057 | /* TBD do other frame types */ | ||
1027 | } /* end translate_frame */ | 1058 | } /* end translate_frame */ |
1059 | |||
1028 | /*===========================================================================*/ | 1060 | /*===========================================================================*/ |
1029 | static void ray_build_header(ray_dev_t *local, struct tx_msg __iomem *ptx, UCHAR msg_type, | 1061 | static void ray_build_header(ray_dev_t *local, struct tx_msg __iomem *ptx, |
1030 | unsigned char *data) | 1062 | UCHAR msg_type, unsigned char *data) |
1031 | { | 1063 | { |
1032 | writeb(PROTOCOL_VER | msg_type, &ptx->mac.frame_ctl_1); | 1064 | writeb(PROTOCOL_VER | msg_type, &ptx->mac.frame_ctl_1); |
1033 | /*** IEEE 802.11 Address field assignments ************* | 1065 | /*** IEEE 802.11 Address field assignments ************* |
1034 | TODS FROMDS addr_1 addr_2 addr_3 addr_4 | 1066 | TODS FROMDS addr_1 addr_2 addr_3 addr_4 |
1035 | Adhoc 0 0 dest src (terminal) BSSID N/A | 1067 | Adhoc 0 0 dest src (terminal) BSSID N/A |
1036 | AP to Terminal 0 1 dest AP(BSSID) source N/A | 1068 | AP to Terminal 0 1 dest AP(BSSID) source N/A |
1037 | Terminal to AP 1 0 AP(BSSID) src (terminal) dest N/A | 1069 | Terminal to AP 1 0 AP(BSSID) src (terminal) dest N/A |
1038 | AP to AP 1 1 dest AP src AP dest source | 1070 | AP to AP 1 1 dest AP src AP dest source |
1039 | *******************************************************/ | 1071 | *******************************************************/ |
1040 | if (local->net_type == ADHOC) { | 1072 | if (local->net_type == ADHOC) { |
1041 | writeb(0, &ptx->mac.frame_ctl_2); | 1073 | writeb(0, &ptx->mac.frame_ctl_2); |
1042 | memcpy_toio(ptx->mac.addr_1, ((struct ethhdr *)data)->h_dest, 2 * ADDRLEN); | 1074 | memcpy_toio(ptx->mac.addr_1, ((struct ethhdr *)data)->h_dest, |
1043 | memcpy_toio(ptx->mac.addr_3, local->bss_id, ADDRLEN); | 1075 | 2 * ADDRLEN); |
1044 | } | 1076 | memcpy_toio(ptx->mac.addr_3, local->bss_id, ADDRLEN); |
1045 | else /* infrastructure */ | 1077 | } else { /* infrastructure */ |
1046 | { | 1078 | |
1047 | if (local->sparm.b4.a_acting_as_ap_status) | 1079 | if (local->sparm.b4.a_acting_as_ap_status) { |
1048 | { | 1080 | writeb(FC2_FROM_DS, &ptx->mac.frame_ctl_2); |
1049 | writeb(FC2_FROM_DS, &ptx->mac.frame_ctl_2); | 1081 | memcpy_toio(ptx->mac.addr_1, |
1050 | memcpy_toio(ptx->mac.addr_1, ((struct ethhdr *)data)->h_dest, ADDRLEN); | 1082 | ((struct ethhdr *)data)->h_dest, ADDRLEN); |
1051 | memcpy_toio(ptx->mac.addr_2, local->bss_id, 6); | 1083 | memcpy_toio(ptx->mac.addr_2, local->bss_id, 6); |
1052 | memcpy_toio(ptx->mac.addr_3, ((struct ethhdr *)data)->h_source, ADDRLEN); | 1084 | memcpy_toio(ptx->mac.addr_3, |
1053 | } | 1085 | ((struct ethhdr *)data)->h_source, ADDRLEN); |
1054 | else /* Terminal */ | 1086 | } else { /* Terminal */ |
1055 | { | 1087 | |
1056 | writeb(FC2_TO_DS, &ptx->mac.frame_ctl_2); | 1088 | writeb(FC2_TO_DS, &ptx->mac.frame_ctl_2); |
1057 | memcpy_toio(ptx->mac.addr_1, local->bss_id, ADDRLEN); | 1089 | memcpy_toio(ptx->mac.addr_1, local->bss_id, ADDRLEN); |
1058 | memcpy_toio(ptx->mac.addr_2, ((struct ethhdr *)data)->h_source, ADDRLEN); | 1090 | memcpy_toio(ptx->mac.addr_2, |
1059 | memcpy_toio(ptx->mac.addr_3, ((struct ethhdr *)data)->h_dest, ADDRLEN); | 1091 | ((struct ethhdr *)data)->h_source, ADDRLEN); |
1060 | } | 1092 | memcpy_toio(ptx->mac.addr_3, |
1061 | } | 1093 | ((struct ethhdr *)data)->h_dest, ADDRLEN); |
1094 | } | ||
1095 | } | ||
1062 | } /* end encapsulate_frame */ | 1096 | } /* end encapsulate_frame */ |
1063 | 1097 | ||
1064 | |||
1065 | /*===========================================================================*/ | 1098 | /*===========================================================================*/ |
1066 | 1099 | ||
1067 | static void netdev_get_drvinfo(struct net_device *dev, | 1100 | static void netdev_get_drvinfo(struct net_device *dev, |
@@ -1071,7 +1104,7 @@ static void netdev_get_drvinfo(struct net_device *dev, | |||
1071 | } | 1104 | } |
1072 | 1105 | ||
1073 | static const struct ethtool_ops netdev_ethtool_ops = { | 1106 | static const struct ethtool_ops netdev_ethtool_ops = { |
1074 | .get_drvinfo = netdev_get_drvinfo, | 1107 | .get_drvinfo = netdev_get_drvinfo, |
1075 | }; | 1108 | }; |
1076 | 1109 | ||
1077 | /*====================================================================*/ | 1110 | /*====================================================================*/ |
@@ -1081,9 +1114,7 @@ static const struct ethtool_ops netdev_ethtool_ops = { | |||
1081 | * Wireless Handler : get protocol name | 1114 | * Wireless Handler : get protocol name |
1082 | */ | 1115 | */ |
1083 | static int ray_get_name(struct net_device *dev, | 1116 | static int ray_get_name(struct net_device *dev, |
1084 | struct iw_request_info *info, | 1117 | struct iw_request_info *info, char *cwrq, char *extra) |
1085 | char *cwrq, | ||
1086 | char *extra) | ||
1087 | { | 1118 | { |
1088 | strcpy(cwrq, "IEEE 802.11-FH"); | 1119 | strcpy(cwrq, "IEEE 802.11-FH"); |
1089 | return 0; | 1120 | return 0; |
@@ -1095,14 +1126,13 @@ static int ray_get_name(struct net_device *dev, | |||
1095 | */ | 1126 | */ |
1096 | static int ray_set_freq(struct net_device *dev, | 1127 | static int ray_set_freq(struct net_device *dev, |
1097 | struct iw_request_info *info, | 1128 | struct iw_request_info *info, |
1098 | struct iw_freq *fwrq, | 1129 | struct iw_freq *fwrq, char *extra) |
1099 | char *extra) | ||
1100 | { | 1130 | { |
1101 | ray_dev_t *local = netdev_priv(dev); | 1131 | ray_dev_t *local = netdev_priv(dev); |
1102 | int err = -EINPROGRESS; /* Call commit handler */ | 1132 | int err = -EINPROGRESS; /* Call commit handler */ |
1103 | 1133 | ||
1104 | /* Reject if card is already initialised */ | 1134 | /* Reject if card is already initialised */ |
1105 | if(local->card_status != CARD_AWAITING_PARAM) | 1135 | if (local->card_status != CARD_AWAITING_PARAM) |
1106 | return -EBUSY; | 1136 | return -EBUSY; |
1107 | 1137 | ||
1108 | /* Setting by channel number */ | 1138 | /* Setting by channel number */ |
@@ -1113,15 +1143,14 @@ static int ray_set_freq(struct net_device *dev, | |||
1113 | 1143 | ||
1114 | return err; | 1144 | return err; |
1115 | } | 1145 | } |
1116 | 1146 | ||
1117 | /*------------------------------------------------------------------*/ | 1147 | /*------------------------------------------------------------------*/ |
1118 | /* | 1148 | /* |
1119 | * Wireless Handler : get frequency | 1149 | * Wireless Handler : get frequency |
1120 | */ | 1150 | */ |
1121 | static int ray_get_freq(struct net_device *dev, | 1151 | static int ray_get_freq(struct net_device *dev, |
1122 | struct iw_request_info *info, | 1152 | struct iw_request_info *info, |
1123 | struct iw_freq *fwrq, | 1153 | struct iw_freq *fwrq, char *extra) |
1124 | char *extra) | ||
1125 | { | 1154 | { |
1126 | ray_dev_t *local = netdev_priv(dev); | 1155 | ray_dev_t *local = netdev_priv(dev); |
1127 | 1156 | ||
@@ -1136,22 +1165,21 @@ static int ray_get_freq(struct net_device *dev, | |||
1136 | */ | 1165 | */ |
1137 | static int ray_set_essid(struct net_device *dev, | 1166 | static int ray_set_essid(struct net_device *dev, |
1138 | struct iw_request_info *info, | 1167 | struct iw_request_info *info, |
1139 | struct iw_point *dwrq, | 1168 | struct iw_point *dwrq, char *extra) |
1140 | char *extra) | ||
1141 | { | 1169 | { |
1142 | ray_dev_t *local = netdev_priv(dev); | 1170 | ray_dev_t *local = netdev_priv(dev); |
1143 | 1171 | ||
1144 | /* Reject if card is already initialised */ | 1172 | /* Reject if card is already initialised */ |
1145 | if(local->card_status != CARD_AWAITING_PARAM) | 1173 | if (local->card_status != CARD_AWAITING_PARAM) |
1146 | return -EBUSY; | 1174 | return -EBUSY; |
1147 | 1175 | ||
1148 | /* Check if we asked for `any' */ | 1176 | /* Check if we asked for `any' */ |
1149 | if(dwrq->flags == 0) { | 1177 | if (dwrq->flags == 0) { |
1150 | /* Corey : can you do that ? */ | 1178 | /* Corey : can you do that ? */ |
1151 | return -EOPNOTSUPP; | 1179 | return -EOPNOTSUPP; |
1152 | } else { | 1180 | } else { |
1153 | /* Check the size of the string */ | 1181 | /* Check the size of the string */ |
1154 | if(dwrq->length > IW_ESSID_MAX_SIZE) { | 1182 | if (dwrq->length > IW_ESSID_MAX_SIZE) { |
1155 | return -E2BIG; | 1183 | return -E2BIG; |
1156 | } | 1184 | } |
1157 | 1185 | ||
@@ -1160,7 +1188,7 @@ static int ray_set_essid(struct net_device *dev, | |||
1160 | memcpy(local->sparm.b5.a_current_ess_id, extra, dwrq->length); | 1188 | memcpy(local->sparm.b5.a_current_ess_id, extra, dwrq->length); |
1161 | } | 1189 | } |
1162 | 1190 | ||
1163 | return -EINPROGRESS; /* Call commit handler */ | 1191 | return -EINPROGRESS; /* Call commit handler */ |
1164 | } | 1192 | } |
1165 | 1193 | ||
1166 | /*------------------------------------------------------------------*/ | 1194 | /*------------------------------------------------------------------*/ |
@@ -1169,8 +1197,7 @@ static int ray_set_essid(struct net_device *dev, | |||
1169 | */ | 1197 | */ |
1170 | static int ray_get_essid(struct net_device *dev, | 1198 | static int ray_get_essid(struct net_device *dev, |
1171 | struct iw_request_info *info, | 1199 | struct iw_request_info *info, |
1172 | struct iw_point *dwrq, | 1200 | struct iw_point *dwrq, char *extra) |
1173 | char *extra) | ||
1174 | { | 1201 | { |
1175 | ray_dev_t *local = netdev_priv(dev); | 1202 | ray_dev_t *local = netdev_priv(dev); |
1176 | 1203 | ||
@@ -1179,7 +1206,7 @@ static int ray_get_essid(struct net_device *dev, | |||
1179 | 1206 | ||
1180 | /* Push it out ! */ | 1207 | /* Push it out ! */ |
1181 | dwrq->length = strlen(extra); | 1208 | dwrq->length = strlen(extra); |
1182 | dwrq->flags = 1; /* active */ | 1209 | dwrq->flags = 1; /* active */ |
1183 | 1210 | ||
1184 | return 0; | 1211 | return 0; |
1185 | } | 1212 | } |
@@ -1189,9 +1216,8 @@ static int ray_get_essid(struct net_device *dev, | |||
1189 | * Wireless Handler : get AP address | 1216 | * Wireless Handler : get AP address |
1190 | */ | 1217 | */ |
1191 | static int ray_get_wap(struct net_device *dev, | 1218 | static int ray_get_wap(struct net_device *dev, |
1192 | struct iw_request_info *info, | 1219 | struct iw_request_info *info, |
1193 | struct sockaddr *awrq, | 1220 | struct sockaddr *awrq, char *extra) |
1194 | char *extra) | ||
1195 | { | 1221 | { |
1196 | ray_dev_t *local = netdev_priv(dev); | 1222 | ray_dev_t *local = netdev_priv(dev); |
1197 | 1223 | ||
@@ -1207,25 +1233,24 @@ static int ray_get_wap(struct net_device *dev, | |||
1207 | */ | 1233 | */ |
1208 | static int ray_set_rate(struct net_device *dev, | 1234 | static int ray_set_rate(struct net_device *dev, |
1209 | struct iw_request_info *info, | 1235 | struct iw_request_info *info, |
1210 | struct iw_param *vwrq, | 1236 | struct iw_param *vwrq, char *extra) |
1211 | char *extra) | ||
1212 | { | 1237 | { |
1213 | ray_dev_t *local = netdev_priv(dev); | 1238 | ray_dev_t *local = netdev_priv(dev); |
1214 | 1239 | ||
1215 | /* Reject if card is already initialised */ | 1240 | /* Reject if card is already initialised */ |
1216 | if(local->card_status != CARD_AWAITING_PARAM) | 1241 | if (local->card_status != CARD_AWAITING_PARAM) |
1217 | return -EBUSY; | 1242 | return -EBUSY; |
1218 | 1243 | ||
1219 | /* Check if rate is in range */ | 1244 | /* Check if rate is in range */ |
1220 | if((vwrq->value != 1000000) && (vwrq->value != 2000000)) | 1245 | if ((vwrq->value != 1000000) && (vwrq->value != 2000000)) |
1221 | return -EINVAL; | 1246 | return -EINVAL; |
1222 | 1247 | ||
1223 | /* Hack for 1.5 Mb/s instead of 2 Mb/s */ | 1248 | /* Hack for 1.5 Mb/s instead of 2 Mb/s */ |
1224 | if((local->fw_ver == 0x55) && /* Please check */ | 1249 | if ((local->fw_ver == 0x55) && /* Please check */ |
1225 | (vwrq->value == 2000000)) | 1250 | (vwrq->value == 2000000)) |
1226 | local->net_default_tx_rate = 3; | 1251 | local->net_default_tx_rate = 3; |
1227 | else | 1252 | else |
1228 | local->net_default_tx_rate = vwrq->value/500000; | 1253 | local->net_default_tx_rate = vwrq->value / 500000; |
1229 | 1254 | ||
1230 | return 0; | 1255 | return 0; |
1231 | } | 1256 | } |
@@ -1236,16 +1261,15 @@ static int ray_set_rate(struct net_device *dev, | |||
1236 | */ | 1261 | */ |
1237 | static int ray_get_rate(struct net_device *dev, | 1262 | static int ray_get_rate(struct net_device *dev, |
1238 | struct iw_request_info *info, | 1263 | struct iw_request_info *info, |
1239 | struct iw_param *vwrq, | 1264 | struct iw_param *vwrq, char *extra) |
1240 | char *extra) | ||
1241 | { | 1265 | { |
1242 | ray_dev_t *local = netdev_priv(dev); | 1266 | ray_dev_t *local = netdev_priv(dev); |
1243 | 1267 | ||
1244 | if(local->net_default_tx_rate == 3) | 1268 | if (local->net_default_tx_rate == 3) |
1245 | vwrq->value = 2000000; /* Hum... */ | 1269 | vwrq->value = 2000000; /* Hum... */ |
1246 | else | 1270 | else |
1247 | vwrq->value = local->net_default_tx_rate * 500000; | 1271 | vwrq->value = local->net_default_tx_rate * 500000; |
1248 | vwrq->fixed = 0; /* We are in auto mode */ | 1272 | vwrq->fixed = 0; /* We are in auto mode */ |
1249 | 1273 | ||
1250 | return 0; | 1274 | return 0; |
1251 | } | 1275 | } |
@@ -1256,43 +1280,40 @@ static int ray_get_rate(struct net_device *dev, | |||
1256 | */ | 1280 | */ |
1257 | static int ray_set_rts(struct net_device *dev, | 1281 | static int ray_set_rts(struct net_device *dev, |
1258 | struct iw_request_info *info, | 1282 | struct iw_request_info *info, |
1259 | struct iw_param *vwrq, | 1283 | struct iw_param *vwrq, char *extra) |
1260 | char *extra) | ||
1261 | { | 1284 | { |
1262 | ray_dev_t *local = netdev_priv(dev); | 1285 | ray_dev_t *local = netdev_priv(dev); |
1263 | int rthr = vwrq->value; | 1286 | int rthr = vwrq->value; |
1264 | 1287 | ||
1265 | /* Reject if card is already initialised */ | 1288 | /* Reject if card is already initialised */ |
1266 | if(local->card_status != CARD_AWAITING_PARAM) | 1289 | if (local->card_status != CARD_AWAITING_PARAM) |
1267 | return -EBUSY; | 1290 | return -EBUSY; |
1268 | 1291 | ||
1269 | /* if(wrq->u.rts.fixed == 0) we should complain */ | 1292 | /* if(wrq->u.rts.fixed == 0) we should complain */ |
1270 | if(vwrq->disabled) | 1293 | if (vwrq->disabled) |
1271 | rthr = 32767; | 1294 | rthr = 32767; |
1272 | else { | 1295 | else { |
1273 | if((rthr < 0) || (rthr > 2347)) /* What's the max packet size ??? */ | 1296 | if ((rthr < 0) || (rthr > 2347)) /* What's the max packet size ??? */ |
1274 | return -EINVAL; | 1297 | return -EINVAL; |
1275 | } | 1298 | } |
1276 | local->sparm.b5.a_rts_threshold[0] = (rthr >> 8) & 0xFF; | 1299 | local->sparm.b5.a_rts_threshold[0] = (rthr >> 8) & 0xFF; |
1277 | local->sparm.b5.a_rts_threshold[1] = rthr & 0xFF; | 1300 | local->sparm.b5.a_rts_threshold[1] = rthr & 0xFF; |
1278 | 1301 | ||
1279 | return -EINPROGRESS; /* Call commit handler */ | 1302 | return -EINPROGRESS; /* Call commit handler */ |
1280 | } | 1303 | } |
1281 | 1304 | ||
1282 | |||
1283 | /*------------------------------------------------------------------*/ | 1305 | /*------------------------------------------------------------------*/ |
1284 | /* | 1306 | /* |
1285 | * Wireless Handler : get RTS threshold | 1307 | * Wireless Handler : get RTS threshold |
1286 | */ | 1308 | */ |
1287 | static int ray_get_rts(struct net_device *dev, | 1309 | static int ray_get_rts(struct net_device *dev, |
1288 | struct iw_request_info *info, | 1310 | struct iw_request_info *info, |
1289 | struct iw_param *vwrq, | 1311 | struct iw_param *vwrq, char *extra) |
1290 | char *extra) | ||
1291 | { | 1312 | { |
1292 | ray_dev_t *local = netdev_priv(dev); | 1313 | ray_dev_t *local = netdev_priv(dev); |
1293 | 1314 | ||
1294 | vwrq->value = (local->sparm.b5.a_rts_threshold[0] << 8) | 1315 | vwrq->value = (local->sparm.b5.a_rts_threshold[0] << 8) |
1295 | + local->sparm.b5.a_rts_threshold[1]; | 1316 | + local->sparm.b5.a_rts_threshold[1]; |
1296 | vwrq->disabled = (vwrq->value == 32767); | 1317 | vwrq->disabled = (vwrq->value == 32767); |
1297 | vwrq->fixed = 1; | 1318 | vwrq->fixed = 1; |
1298 | 1319 | ||
@@ -1305,27 +1326,26 @@ static int ray_get_rts(struct net_device *dev, | |||
1305 | */ | 1326 | */ |
1306 | static int ray_set_frag(struct net_device *dev, | 1327 | static int ray_set_frag(struct net_device *dev, |
1307 | struct iw_request_info *info, | 1328 | struct iw_request_info *info, |
1308 | struct iw_param *vwrq, | 1329 | struct iw_param *vwrq, char *extra) |
1309 | char *extra) | ||
1310 | { | 1330 | { |
1311 | ray_dev_t *local = netdev_priv(dev); | 1331 | ray_dev_t *local = netdev_priv(dev); |
1312 | int fthr = vwrq->value; | 1332 | int fthr = vwrq->value; |
1313 | 1333 | ||
1314 | /* Reject if card is already initialised */ | 1334 | /* Reject if card is already initialised */ |
1315 | if(local->card_status != CARD_AWAITING_PARAM) | 1335 | if (local->card_status != CARD_AWAITING_PARAM) |
1316 | return -EBUSY; | 1336 | return -EBUSY; |
1317 | 1337 | ||
1318 | /* if(wrq->u.frag.fixed == 0) should complain */ | 1338 | /* if(wrq->u.frag.fixed == 0) should complain */ |
1319 | if(vwrq->disabled) | 1339 | if (vwrq->disabled) |
1320 | fthr = 32767; | 1340 | fthr = 32767; |
1321 | else { | 1341 | else { |
1322 | if((fthr < 256) || (fthr > 2347)) /* To check out ! */ | 1342 | if ((fthr < 256) || (fthr > 2347)) /* To check out ! */ |
1323 | return -EINVAL; | 1343 | return -EINVAL; |
1324 | } | 1344 | } |
1325 | local->sparm.b5.a_frag_threshold[0] = (fthr >> 8) & 0xFF; | 1345 | local->sparm.b5.a_frag_threshold[0] = (fthr >> 8) & 0xFF; |
1326 | local->sparm.b5.a_frag_threshold[1] = fthr & 0xFF; | 1346 | local->sparm.b5.a_frag_threshold[1] = fthr & 0xFF; |
1327 | 1347 | ||
1328 | return -EINPROGRESS; /* Call commit handler */ | 1348 | return -EINPROGRESS; /* Call commit handler */ |
1329 | } | 1349 | } |
1330 | 1350 | ||
1331 | /*------------------------------------------------------------------*/ | 1351 | /*------------------------------------------------------------------*/ |
@@ -1334,13 +1354,12 @@ static int ray_set_frag(struct net_device *dev, | |||
1334 | */ | 1354 | */ |
1335 | static int ray_get_frag(struct net_device *dev, | 1355 | static int ray_get_frag(struct net_device *dev, |
1336 | struct iw_request_info *info, | 1356 | struct iw_request_info *info, |
1337 | struct iw_param *vwrq, | 1357 | struct iw_param *vwrq, char *extra) |
1338 | char *extra) | ||
1339 | { | 1358 | { |
1340 | ray_dev_t *local = netdev_priv(dev); | 1359 | ray_dev_t *local = netdev_priv(dev); |
1341 | 1360 | ||
1342 | vwrq->value = (local->sparm.b5.a_frag_threshold[0] << 8) | 1361 | vwrq->value = (local->sparm.b5.a_frag_threshold[0] << 8) |
1343 | + local->sparm.b5.a_frag_threshold[1]; | 1362 | + local->sparm.b5.a_frag_threshold[1]; |
1344 | vwrq->disabled = (vwrq->value == 32767); | 1363 | vwrq->disabled = (vwrq->value == 32767); |
1345 | vwrq->fixed = 1; | 1364 | vwrq->fixed = 1; |
1346 | 1365 | ||
@@ -1352,23 +1371,20 @@ static int ray_get_frag(struct net_device *dev, | |||
1352 | * Wireless Handler : set Mode of Operation | 1371 | * Wireless Handler : set Mode of Operation |
1353 | */ | 1372 | */ |
1354 | static int ray_set_mode(struct net_device *dev, | 1373 | static int ray_set_mode(struct net_device *dev, |
1355 | struct iw_request_info *info, | 1374 | struct iw_request_info *info, __u32 *uwrq, char *extra) |
1356 | __u32 *uwrq, | ||
1357 | char *extra) | ||
1358 | { | 1375 | { |
1359 | ray_dev_t *local = netdev_priv(dev); | 1376 | ray_dev_t *local = netdev_priv(dev); |
1360 | int err = -EINPROGRESS; /* Call commit handler */ | 1377 | int err = -EINPROGRESS; /* Call commit handler */ |
1361 | char card_mode = 1; | 1378 | char card_mode = 1; |
1362 | 1379 | ||
1363 | /* Reject if card is already initialised */ | 1380 | /* Reject if card is already initialised */ |
1364 | if(local->card_status != CARD_AWAITING_PARAM) | 1381 | if (local->card_status != CARD_AWAITING_PARAM) |
1365 | return -EBUSY; | 1382 | return -EBUSY; |
1366 | 1383 | ||
1367 | switch (*uwrq) | 1384 | switch (*uwrq) { |
1368 | { | ||
1369 | case IW_MODE_ADHOC: | 1385 | case IW_MODE_ADHOC: |
1370 | card_mode = 0; | 1386 | card_mode = 0; |
1371 | // Fall through | 1387 | /* Fall through */ |
1372 | case IW_MODE_INFRA: | 1388 | case IW_MODE_INFRA: |
1373 | local->sparm.b5.a_network_type = card_mode; | 1389 | local->sparm.b5.a_network_type = card_mode; |
1374 | break; | 1390 | break; |
@@ -1384,13 +1400,11 @@ static int ray_set_mode(struct net_device *dev, | |||
1384 | * Wireless Handler : get Mode of Operation | 1400 | * Wireless Handler : get Mode of Operation |
1385 | */ | 1401 | */ |
1386 | static int ray_get_mode(struct net_device *dev, | 1402 | static int ray_get_mode(struct net_device *dev, |
1387 | struct iw_request_info *info, | 1403 | struct iw_request_info *info, __u32 *uwrq, char *extra) |
1388 | __u32 *uwrq, | ||
1389 | char *extra) | ||
1390 | { | 1404 | { |
1391 | ray_dev_t *local = netdev_priv(dev); | 1405 | ray_dev_t *local = netdev_priv(dev); |
1392 | 1406 | ||
1393 | if(local->sparm.b5.a_network_type) | 1407 | if (local->sparm.b5.a_network_type) |
1394 | *uwrq = IW_MODE_INFRA; | 1408 | *uwrq = IW_MODE_INFRA; |
1395 | else | 1409 | else |
1396 | *uwrq = IW_MODE_ADHOC; | 1410 | *uwrq = IW_MODE_ADHOC; |
@@ -1404,12 +1418,11 @@ static int ray_get_mode(struct net_device *dev, | |||
1404 | */ | 1418 | */ |
1405 | static int ray_get_range(struct net_device *dev, | 1419 | static int ray_get_range(struct net_device *dev, |
1406 | struct iw_request_info *info, | 1420 | struct iw_request_info *info, |
1407 | struct iw_point *dwrq, | 1421 | struct iw_point *dwrq, char *extra) |
1408 | char *extra) | ||
1409 | { | 1422 | { |
1410 | struct iw_range *range = (struct iw_range *) extra; | 1423 | struct iw_range *range = (struct iw_range *)extra; |
1411 | 1424 | ||
1412 | memset((char *) range, 0, sizeof(struct iw_range)); | 1425 | memset((char *)range, 0, sizeof(struct iw_range)); |
1413 | 1426 | ||
1414 | /* Set the length (very important for backward compatibility) */ | 1427 | /* Set the length (very important for backward compatibility) */ |
1415 | dwrq->length = sizeof(struct iw_range); | 1428 | dwrq->length = sizeof(struct iw_range); |
@@ -1420,7 +1433,7 @@ static int ray_get_range(struct net_device *dev, | |||
1420 | 1433 | ||
1421 | /* Set information in the range struct */ | 1434 | /* Set information in the range struct */ |
1422 | range->throughput = 1.1 * 1000 * 1000; /* Put the right number here */ | 1435 | range->throughput = 1.1 * 1000 * 1000; /* Put the right number here */ |
1423 | range->num_channels = hop_pattern_length[(int)country]; | 1436 | range->num_channels = hop_pattern_length[(int)country]; |
1424 | range->num_frequency = 0; | 1437 | range->num_frequency = 0; |
1425 | range->max_qual.qual = 0; | 1438 | range->max_qual.qual = 0; |
1426 | range->max_qual.level = 255; /* What's the correct value ? */ | 1439 | range->max_qual.level = 255; /* What's the correct value ? */ |
@@ -1437,8 +1450,7 @@ static int ray_get_range(struct net_device *dev, | |||
1437 | */ | 1450 | */ |
1438 | static int ray_set_framing(struct net_device *dev, | 1451 | static int ray_set_framing(struct net_device *dev, |
1439 | struct iw_request_info *info, | 1452 | struct iw_request_info *info, |
1440 | union iwreq_data *wrqu, | 1453 | union iwreq_data *wrqu, char *extra) |
1441 | char *extra) | ||
1442 | { | 1454 | { |
1443 | translate = *(extra); /* Set framing mode */ | 1455 | translate = *(extra); /* Set framing mode */ |
1444 | 1456 | ||
@@ -1451,8 +1463,7 @@ static int ray_set_framing(struct net_device *dev, | |||
1451 | */ | 1463 | */ |
1452 | static int ray_get_framing(struct net_device *dev, | 1464 | static int ray_get_framing(struct net_device *dev, |
1453 | struct iw_request_info *info, | 1465 | struct iw_request_info *info, |
1454 | union iwreq_data *wrqu, | 1466 | union iwreq_data *wrqu, char *extra) |
1455 | char *extra) | ||
1456 | { | 1467 | { |
1457 | *(extra) = translate; | 1468 | *(extra) = translate; |
1458 | 1469 | ||
@@ -1465,8 +1476,7 @@ static int ray_get_framing(struct net_device *dev, | |||
1465 | */ | 1476 | */ |
1466 | static int ray_get_country(struct net_device *dev, | 1477 | static int ray_get_country(struct net_device *dev, |
1467 | struct iw_request_info *info, | 1478 | struct iw_request_info *info, |
1468 | union iwreq_data *wrqu, | 1479 | union iwreq_data *wrqu, char *extra) |
1469 | char *extra) | ||
1470 | { | 1480 | { |
1471 | *(extra) = country; | 1481 | *(extra) = country; |
1472 | 1482 | ||
@@ -1477,11 +1487,10 @@ static int ray_get_country(struct net_device *dev, | |||
1477 | /* | 1487 | /* |
1478 | * Commit handler : called after a bunch of SET operations | 1488 | * Commit handler : called after a bunch of SET operations |
1479 | */ | 1489 | */ |
1480 | static int ray_commit(struct net_device *dev, | 1490 | static int ray_commit(struct net_device *dev, struct iw_request_info *info, /* NULL */ |
1481 | struct iw_request_info *info, /* NULL */ | 1491 | void *zwrq, /* NULL */ |
1482 | void *zwrq, /* NULL */ | 1492 | char *extra) |
1483 | char *extra) /* NULL */ | 1493 | { /* NULL */ |
1484 | { | ||
1485 | return 0; | 1494 | return 0; |
1486 | } | 1495 | } |
1487 | 1496 | ||
@@ -1489,33 +1498,34 @@ static int ray_commit(struct net_device *dev, | |||
1489 | /* | 1498 | /* |
1490 | * Stats handler : return Wireless Stats | 1499 | * Stats handler : return Wireless Stats |
1491 | */ | 1500 | */ |
1492 | static iw_stats * ray_get_wireless_stats(struct net_device * dev) | 1501 | static iw_stats *ray_get_wireless_stats(struct net_device *dev) |
1493 | { | 1502 | { |
1494 | ray_dev_t * local = netdev_priv(dev); | 1503 | ray_dev_t *local = netdev_priv(dev); |
1495 | struct pcmcia_device *link = local->finder; | 1504 | struct pcmcia_device *link = local->finder; |
1496 | struct status __iomem *p = local->sram + STATUS_BASE; | 1505 | struct status __iomem *p = local->sram + STATUS_BASE; |
1497 | 1506 | ||
1498 | if(local == (ray_dev_t *) NULL) | 1507 | if (local == (ray_dev_t *) NULL) |
1499 | return (iw_stats *) NULL; | 1508 | return (iw_stats *) NULL; |
1500 | 1509 | ||
1501 | local->wstats.status = local->card_status; | 1510 | local->wstats.status = local->card_status; |
1502 | #ifdef WIRELESS_SPY | 1511 | #ifdef WIRELESS_SPY |
1503 | if((local->spy_data.spy_number > 0) && (local->sparm.b5.a_network_type == 0)) | 1512 | if ((local->spy_data.spy_number > 0) |
1504 | { | 1513 | && (local->sparm.b5.a_network_type == 0)) { |
1505 | /* Get it from the first node in spy list */ | 1514 | /* Get it from the first node in spy list */ |
1506 | local->wstats.qual.qual = local->spy_data.spy_stat[0].qual; | 1515 | local->wstats.qual.qual = local->spy_data.spy_stat[0].qual; |
1507 | local->wstats.qual.level = local->spy_data.spy_stat[0].level; | 1516 | local->wstats.qual.level = local->spy_data.spy_stat[0].level; |
1508 | local->wstats.qual.noise = local->spy_data.spy_stat[0].noise; | 1517 | local->wstats.qual.noise = local->spy_data.spy_stat[0].noise; |
1509 | local->wstats.qual.updated = local->spy_data.spy_stat[0].updated; | 1518 | local->wstats.qual.updated = |
1510 | } | 1519 | local->spy_data.spy_stat[0].updated; |
1520 | } | ||
1511 | #endif /* WIRELESS_SPY */ | 1521 | #endif /* WIRELESS_SPY */ |
1512 | 1522 | ||
1513 | if(pcmcia_dev_present(link)) { | 1523 | if (pcmcia_dev_present(link)) { |
1514 | local->wstats.qual.noise = readb(&p->rxnoise); | 1524 | local->wstats.qual.noise = readb(&p->rxnoise); |
1515 | local->wstats.qual.updated |= 4; | 1525 | local->wstats.qual.updated |= 4; |
1516 | } | 1526 | } |
1517 | 1527 | ||
1518 | return &local->wstats; | 1528 | return &local->wstats; |
1519 | } /* end ray_get_wireless_stats */ | 1529 | } /* end ray_get_wireless_stats */ |
1520 | 1530 | ||
1521 | /*------------------------------------------------------------------*/ | 1531 | /*------------------------------------------------------------------*/ |
@@ -1523,1159 +1533,1264 @@ static iw_stats * ray_get_wireless_stats(struct net_device * dev) | |||
1523 | * Structures to export the Wireless Handlers | 1533 | * Structures to export the Wireless Handlers |
1524 | */ | 1534 | */ |
1525 | 1535 | ||
1526 | static const iw_handler ray_handler[] = { | 1536 | static const iw_handler ray_handler[] = { |
1527 | [SIOCSIWCOMMIT-SIOCIWFIRST] = (iw_handler) ray_commit, | 1537 | [SIOCSIWCOMMIT - SIOCIWFIRST] = (iw_handler) ray_commit, |
1528 | [SIOCGIWNAME -SIOCIWFIRST] = (iw_handler) ray_get_name, | 1538 | [SIOCGIWNAME - SIOCIWFIRST] = (iw_handler) ray_get_name, |
1529 | [SIOCSIWFREQ -SIOCIWFIRST] = (iw_handler) ray_set_freq, | 1539 | [SIOCSIWFREQ - SIOCIWFIRST] = (iw_handler) ray_set_freq, |
1530 | [SIOCGIWFREQ -SIOCIWFIRST] = (iw_handler) ray_get_freq, | 1540 | [SIOCGIWFREQ - SIOCIWFIRST] = (iw_handler) ray_get_freq, |
1531 | [SIOCSIWMODE -SIOCIWFIRST] = (iw_handler) ray_set_mode, | 1541 | [SIOCSIWMODE - SIOCIWFIRST] = (iw_handler) ray_set_mode, |
1532 | [SIOCGIWMODE -SIOCIWFIRST] = (iw_handler) ray_get_mode, | 1542 | [SIOCGIWMODE - SIOCIWFIRST] = (iw_handler) ray_get_mode, |
1533 | [SIOCGIWRANGE -SIOCIWFIRST] = (iw_handler) ray_get_range, | 1543 | [SIOCGIWRANGE - SIOCIWFIRST] = (iw_handler) ray_get_range, |
1534 | #ifdef WIRELESS_SPY | 1544 | #ifdef WIRELESS_SPY |
1535 | [SIOCSIWSPY -SIOCIWFIRST] = (iw_handler) iw_handler_set_spy, | 1545 | [SIOCSIWSPY - SIOCIWFIRST] = (iw_handler) iw_handler_set_spy, |
1536 | [SIOCGIWSPY -SIOCIWFIRST] = (iw_handler) iw_handler_get_spy, | 1546 | [SIOCGIWSPY - SIOCIWFIRST] = (iw_handler) iw_handler_get_spy, |
1537 | [SIOCSIWTHRSPY-SIOCIWFIRST] = (iw_handler) iw_handler_set_thrspy, | 1547 | [SIOCSIWTHRSPY - SIOCIWFIRST] = (iw_handler) iw_handler_set_thrspy, |
1538 | [SIOCGIWTHRSPY-SIOCIWFIRST] = (iw_handler) iw_handler_get_thrspy, | 1548 | [SIOCGIWTHRSPY - SIOCIWFIRST] = (iw_handler) iw_handler_get_thrspy, |
1539 | #endif /* WIRELESS_SPY */ | 1549 | #endif /* WIRELESS_SPY */ |
1540 | [SIOCGIWAP -SIOCIWFIRST] = (iw_handler) ray_get_wap, | 1550 | [SIOCGIWAP - SIOCIWFIRST] = (iw_handler) ray_get_wap, |
1541 | [SIOCSIWESSID -SIOCIWFIRST] = (iw_handler) ray_set_essid, | 1551 | [SIOCSIWESSID - SIOCIWFIRST] = (iw_handler) ray_set_essid, |
1542 | [SIOCGIWESSID -SIOCIWFIRST] = (iw_handler) ray_get_essid, | 1552 | [SIOCGIWESSID - SIOCIWFIRST] = (iw_handler) ray_get_essid, |
1543 | [SIOCSIWRATE -SIOCIWFIRST] = (iw_handler) ray_set_rate, | 1553 | [SIOCSIWRATE - SIOCIWFIRST] = (iw_handler) ray_set_rate, |
1544 | [SIOCGIWRATE -SIOCIWFIRST] = (iw_handler) ray_get_rate, | 1554 | [SIOCGIWRATE - SIOCIWFIRST] = (iw_handler) ray_get_rate, |
1545 | [SIOCSIWRTS -SIOCIWFIRST] = (iw_handler) ray_set_rts, | 1555 | [SIOCSIWRTS - SIOCIWFIRST] = (iw_handler) ray_set_rts, |
1546 | [SIOCGIWRTS -SIOCIWFIRST] = (iw_handler) ray_get_rts, | 1556 | [SIOCGIWRTS - SIOCIWFIRST] = (iw_handler) ray_get_rts, |
1547 | [SIOCSIWFRAG -SIOCIWFIRST] = (iw_handler) ray_set_frag, | 1557 | [SIOCSIWFRAG - SIOCIWFIRST] = (iw_handler) ray_set_frag, |
1548 | [SIOCGIWFRAG -SIOCIWFIRST] = (iw_handler) ray_get_frag, | 1558 | [SIOCGIWFRAG - SIOCIWFIRST] = (iw_handler) ray_get_frag, |
1549 | }; | 1559 | }; |
1550 | 1560 | ||
1551 | #define SIOCSIPFRAMING SIOCIWFIRSTPRIV /* Set framing mode */ | 1561 | #define SIOCSIPFRAMING SIOCIWFIRSTPRIV /* Set framing mode */ |
1552 | #define SIOCGIPFRAMING SIOCIWFIRSTPRIV + 1 /* Get framing mode */ | 1562 | #define SIOCGIPFRAMING SIOCIWFIRSTPRIV + 1 /* Get framing mode */ |
1553 | #define SIOCGIPCOUNTRY SIOCIWFIRSTPRIV + 3 /* Get country code */ | 1563 | #define SIOCGIPCOUNTRY SIOCIWFIRSTPRIV + 3 /* Get country code */ |
1554 | 1564 | ||
1555 | static const iw_handler ray_private_handler[] = { | 1565 | static const iw_handler ray_private_handler[] = { |
1556 | [0] = (iw_handler) ray_set_framing, | 1566 | [0] = (iw_handler) ray_set_framing, |
1557 | [1] = (iw_handler) ray_get_framing, | 1567 | [1] = (iw_handler) ray_get_framing, |
1558 | [3] = (iw_handler) ray_get_country, | 1568 | [3] = (iw_handler) ray_get_country, |
1559 | }; | 1569 | }; |
1560 | 1570 | ||
1561 | static const struct iw_priv_args ray_private_args[] = { | 1571 | static const struct iw_priv_args ray_private_args[] = { |
1562 | /* cmd, set_args, get_args, name */ | 1572 | /* cmd, set_args, get_args, name */ |
1563 | { SIOCSIPFRAMING, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "set_framing" }, | 1573 | {SIOCSIPFRAMING, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, |
1564 | { SIOCGIPFRAMING, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "get_framing" }, | 1574 | "set_framing"}, |
1565 | { SIOCGIPCOUNTRY, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "get_country" }, | 1575 | {SIOCGIPFRAMING, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, |
1576 | "get_framing"}, | ||
1577 | {SIOCGIPCOUNTRY, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, | ||
1578 | "get_country"}, | ||
1566 | }; | 1579 | }; |
1567 | 1580 | ||
1568 | static const struct iw_handler_def ray_handler_def = | 1581 | static const struct iw_handler_def ray_handler_def = { |
1569 | { | 1582 | .num_standard = ARRAY_SIZE(ray_handler), |
1570 | .num_standard = ARRAY_SIZE(ray_handler), | 1583 | .num_private = ARRAY_SIZE(ray_private_handler), |
1571 | .num_private = ARRAY_SIZE(ray_private_handler), | ||
1572 | .num_private_args = ARRAY_SIZE(ray_private_args), | 1584 | .num_private_args = ARRAY_SIZE(ray_private_args), |
1573 | .standard = ray_handler, | 1585 | .standard = ray_handler, |
1574 | .private = ray_private_handler, | 1586 | .private = ray_private_handler, |
1575 | .private_args = ray_private_args, | 1587 | .private_args = ray_private_args, |
1576 | .get_wireless_stats = ray_get_wireless_stats, | 1588 | .get_wireless_stats = ray_get_wireless_stats, |
1577 | }; | 1589 | }; |
1578 | 1590 | ||
1579 | /*===========================================================================*/ | 1591 | /*===========================================================================*/ |
1580 | static int ray_open(struct net_device *dev) | 1592 | static int ray_open(struct net_device *dev) |
1581 | { | 1593 | { |
1582 | ray_dev_t *local = netdev_priv(dev); | 1594 | ray_dev_t *local = netdev_priv(dev); |
1583 | struct pcmcia_device *link; | 1595 | struct pcmcia_device *link; |
1584 | link = local->finder; | 1596 | link = local->finder; |
1585 | |||
1586 | DEBUG(1, "ray_open('%s')\n", dev->name); | ||
1587 | 1597 | ||
1588 | if (link->open == 0) | 1598 | DEBUG(1, "ray_open('%s')\n", dev->name); |
1589 | local->num_multi = 0; | ||
1590 | link->open++; | ||
1591 | 1599 | ||
1592 | /* If the card is not started, time to start it ! - Jean II */ | 1600 | if (link->open == 0) |
1593 | if(local->card_status == CARD_AWAITING_PARAM) { | 1601 | local->num_multi = 0; |
1594 | int i; | 1602 | link->open++; |
1595 | 1603 | ||
1596 | DEBUG(1,"ray_open: doing init now !\n"); | 1604 | /* If the card is not started, time to start it ! - Jean II */ |
1605 | if (local->card_status == CARD_AWAITING_PARAM) { | ||
1606 | int i; | ||
1597 | 1607 | ||
1598 | /* Download startup parameters */ | 1608 | DEBUG(1, "ray_open: doing init now !\n"); |
1599 | if ( (i = dl_startup_params(dev)) < 0) | 1609 | |
1600 | { | 1610 | /* Download startup parameters */ |
1601 | printk(KERN_INFO "ray_dev_init dl_startup_params failed - " | 1611 | if ((i = dl_startup_params(dev)) < 0) { |
1602 | "returns 0x%x\n",i); | 1612 | printk(KERN_INFO |
1603 | return -1; | 1613 | "ray_dev_init dl_startup_params failed - " |
1604 | } | 1614 | "returns 0x%x\n", i); |
1605 | } | 1615 | return -1; |
1606 | 1616 | } | |
1607 | if (sniffer) netif_stop_queue(dev); | 1617 | } |
1608 | else netif_start_queue(dev); | 1618 | |
1609 | 1619 | if (sniffer) | |
1610 | DEBUG(2,"ray_open ending\n"); | 1620 | netif_stop_queue(dev); |
1611 | return 0; | 1621 | else |
1622 | netif_start_queue(dev); | ||
1623 | |||
1624 | DEBUG(2, "ray_open ending\n"); | ||
1625 | return 0; | ||
1612 | } /* end ray_open */ | 1626 | } /* end ray_open */ |
1627 | |||
1613 | /*===========================================================================*/ | 1628 | /*===========================================================================*/ |
1614 | static int ray_dev_close(struct net_device *dev) | 1629 | static int ray_dev_close(struct net_device *dev) |
1615 | { | 1630 | { |
1616 | ray_dev_t *local = netdev_priv(dev); | 1631 | ray_dev_t *local = netdev_priv(dev); |
1617 | struct pcmcia_device *link; | 1632 | struct pcmcia_device *link; |
1618 | link = local->finder; | 1633 | link = local->finder; |
1619 | 1634 | ||
1620 | DEBUG(1, "ray_dev_close('%s')\n", dev->name); | 1635 | DEBUG(1, "ray_dev_close('%s')\n", dev->name); |
1621 | 1636 | ||
1622 | link->open--; | 1637 | link->open--; |
1623 | netif_stop_queue(dev); | 1638 | netif_stop_queue(dev); |
1624 | 1639 | ||
1625 | /* In here, we should stop the hardware (stop card from beeing active) | 1640 | /* In here, we should stop the hardware (stop card from beeing active) |
1626 | * and set local->card_status to CARD_AWAITING_PARAM, so that while the | 1641 | * and set local->card_status to CARD_AWAITING_PARAM, so that while the |
1627 | * card is closed we can chage its configuration. | 1642 | * card is closed we can chage its configuration. |
1628 | * Probably also need a COR reset to get sane state - Jean II */ | 1643 | * Probably also need a COR reset to get sane state - Jean II */ |
1629 | 1644 | ||
1630 | return 0; | 1645 | return 0; |
1631 | } /* end ray_dev_close */ | 1646 | } /* end ray_dev_close */ |
1647 | |||
1632 | /*===========================================================================*/ | 1648 | /*===========================================================================*/ |
1633 | static void ray_reset(struct net_device *dev) { | 1649 | static void ray_reset(struct net_device *dev) |
1634 | DEBUG(1,"ray_reset entered\n"); | 1650 | { |
1635 | return; | 1651 | DEBUG(1, "ray_reset entered\n"); |
1652 | return; | ||
1636 | } | 1653 | } |
1654 | |||
1637 | /*===========================================================================*/ | 1655 | /*===========================================================================*/ |
1638 | /* Cause a firmware interrupt if it is ready for one */ | 1656 | /* Cause a firmware interrupt if it is ready for one */ |
1639 | /* Return nonzero if not ready */ | 1657 | /* Return nonzero if not ready */ |
1640 | static int interrupt_ecf(ray_dev_t *local, int ccs) | 1658 | static int interrupt_ecf(ray_dev_t *local, int ccs) |
1641 | { | 1659 | { |
1642 | int i = 50; | 1660 | int i = 50; |
1643 | struct pcmcia_device *link = local->finder; | 1661 | struct pcmcia_device *link = local->finder; |
1644 | 1662 | ||
1645 | if (!(pcmcia_dev_present(link))) { | 1663 | if (!(pcmcia_dev_present(link))) { |
1646 | DEBUG(2,"ray_cs interrupt_ecf - device not present\n"); | 1664 | DEBUG(2, "ray_cs interrupt_ecf - device not present\n"); |
1647 | return -1; | 1665 | return -1; |
1648 | } | 1666 | } |
1649 | DEBUG(2,"interrupt_ecf(local=%p, ccs = 0x%x\n",local,ccs); | 1667 | DEBUG(2, "interrupt_ecf(local=%p, ccs = 0x%x\n", local, ccs); |
1650 | 1668 | ||
1651 | while ( i && | 1669 | while (i && |
1652 | (readb(local->amem + CIS_OFFSET + ECF_INTR_OFFSET) & ECF_INTR_SET)) | 1670 | (readb(local->amem + CIS_OFFSET + ECF_INTR_OFFSET) & |
1653 | i--; | 1671 | ECF_INTR_SET)) |
1654 | if (i == 0) { | 1672 | i--; |
1655 | DEBUG(2,"ray_cs interrupt_ecf card not ready for interrupt\n"); | 1673 | if (i == 0) { |
1656 | return -1; | 1674 | DEBUG(2, "ray_cs interrupt_ecf card not ready for interrupt\n"); |
1657 | } | 1675 | return -1; |
1676 | } | ||
1658 | /* Fill the mailbox, then kick the card */ | 1677 | /* Fill the mailbox, then kick the card */ |
1659 | writeb(ccs, local->sram + SCB_BASE); | 1678 | writeb(ccs, local->sram + SCB_BASE); |
1660 | writeb(ECF_INTR_SET, local->amem + CIS_OFFSET + ECF_INTR_OFFSET); | 1679 | writeb(ECF_INTR_SET, local->amem + CIS_OFFSET + ECF_INTR_OFFSET); |
1661 | return 0; | 1680 | return 0; |
1662 | } /* interrupt_ecf */ | 1681 | } /* interrupt_ecf */ |
1682 | |||
1663 | /*===========================================================================*/ | 1683 | /*===========================================================================*/ |
1664 | /* Get next free transmit CCS */ | 1684 | /* Get next free transmit CCS */ |
1665 | /* Return - index of current tx ccs */ | 1685 | /* Return - index of current tx ccs */ |
1666 | static int get_free_tx_ccs(ray_dev_t *local) | 1686 | static int get_free_tx_ccs(ray_dev_t *local) |
1667 | { | 1687 | { |
1668 | int i; | 1688 | int i; |
1669 | struct ccs __iomem *pccs = ccs_base(local); | 1689 | struct ccs __iomem *pccs = ccs_base(local); |
1670 | struct pcmcia_device *link = local->finder; | 1690 | struct pcmcia_device *link = local->finder; |
1671 | 1691 | ||
1672 | if (!(pcmcia_dev_present(link))) { | 1692 | if (!(pcmcia_dev_present(link))) { |
1673 | DEBUG(2,"ray_cs get_free_tx_ccs - device not present\n"); | 1693 | DEBUG(2, "ray_cs get_free_tx_ccs - device not present\n"); |
1674 | return ECARDGONE; | 1694 | return ECARDGONE; |
1675 | } | 1695 | } |
1676 | 1696 | ||
1677 | if (test_and_set_bit(0,&local->tx_ccs_lock)) { | 1697 | if (test_and_set_bit(0, &local->tx_ccs_lock)) { |
1678 | DEBUG(1,"ray_cs tx_ccs_lock busy\n"); | 1698 | DEBUG(1, "ray_cs tx_ccs_lock busy\n"); |
1679 | return ECCSBUSY; | 1699 | return ECCSBUSY; |
1680 | } | 1700 | } |
1681 | 1701 | ||
1682 | for (i=0; i < NUMBER_OF_TX_CCS; i++) { | 1702 | for (i = 0; i < NUMBER_OF_TX_CCS; i++) { |
1683 | if (readb(&(pccs+i)->buffer_status) == CCS_BUFFER_FREE) { | 1703 | if (readb(&(pccs + i)->buffer_status) == CCS_BUFFER_FREE) { |
1684 | writeb(CCS_BUFFER_BUSY, &(pccs+i)->buffer_status); | 1704 | writeb(CCS_BUFFER_BUSY, &(pccs + i)->buffer_status); |
1685 | writeb(CCS_END_LIST, &(pccs+i)->link); | 1705 | writeb(CCS_END_LIST, &(pccs + i)->link); |
1686 | local->tx_ccs_lock = 0; | 1706 | local->tx_ccs_lock = 0; |
1687 | return i; | 1707 | return i; |
1688 | } | 1708 | } |
1689 | } | 1709 | } |
1690 | local->tx_ccs_lock = 0; | 1710 | local->tx_ccs_lock = 0; |
1691 | DEBUG(2,"ray_cs ERROR no free tx CCS for raylink card\n"); | 1711 | DEBUG(2, "ray_cs ERROR no free tx CCS for raylink card\n"); |
1692 | return ECCSFULL; | 1712 | return ECCSFULL; |
1693 | } /* get_free_tx_ccs */ | 1713 | } /* get_free_tx_ccs */ |
1714 | |||
1694 | /*===========================================================================*/ | 1715 | /*===========================================================================*/ |
1695 | /* Get next free CCS */ | 1716 | /* Get next free CCS */ |
1696 | /* Return - index of current ccs */ | 1717 | /* Return - index of current ccs */ |
1697 | static int get_free_ccs(ray_dev_t *local) | 1718 | static int get_free_ccs(ray_dev_t *local) |
1698 | { | 1719 | { |
1699 | int i; | 1720 | int i; |
1700 | struct ccs __iomem *pccs = ccs_base(local); | 1721 | struct ccs __iomem *pccs = ccs_base(local); |
1701 | struct pcmcia_device *link = local->finder; | 1722 | struct pcmcia_device *link = local->finder; |
1702 | 1723 | ||
1703 | if (!(pcmcia_dev_present(link))) { | 1724 | if (!(pcmcia_dev_present(link))) { |
1704 | DEBUG(2,"ray_cs get_free_ccs - device not present\n"); | 1725 | DEBUG(2, "ray_cs get_free_ccs - device not present\n"); |
1705 | return ECARDGONE; | 1726 | return ECARDGONE; |
1706 | } | 1727 | } |
1707 | if (test_and_set_bit(0,&local->ccs_lock)) { | 1728 | if (test_and_set_bit(0, &local->ccs_lock)) { |
1708 | DEBUG(1,"ray_cs ccs_lock busy\n"); | 1729 | DEBUG(1, "ray_cs ccs_lock busy\n"); |
1709 | return ECCSBUSY; | 1730 | return ECCSBUSY; |
1710 | } | 1731 | } |
1711 | 1732 | ||
1712 | for (i = NUMBER_OF_TX_CCS; i < NUMBER_OF_CCS; i++) { | 1733 | for (i = NUMBER_OF_TX_CCS; i < NUMBER_OF_CCS; i++) { |
1713 | if (readb(&(pccs+i)->buffer_status) == CCS_BUFFER_FREE) { | 1734 | if (readb(&(pccs + i)->buffer_status) == CCS_BUFFER_FREE) { |
1714 | writeb(CCS_BUFFER_BUSY, &(pccs+i)->buffer_status); | 1735 | writeb(CCS_BUFFER_BUSY, &(pccs + i)->buffer_status); |
1715 | writeb(CCS_END_LIST, &(pccs+i)->link); | 1736 | writeb(CCS_END_LIST, &(pccs + i)->link); |
1716 | local->ccs_lock = 0; | 1737 | local->ccs_lock = 0; |
1717 | return i; | 1738 | return i; |
1718 | } | 1739 | } |
1719 | } | 1740 | } |
1720 | local->ccs_lock = 0; | 1741 | local->ccs_lock = 0; |
1721 | DEBUG(1,"ray_cs ERROR no free CCS for raylink card\n"); | 1742 | DEBUG(1, "ray_cs ERROR no free CCS for raylink card\n"); |
1722 | return ECCSFULL; | 1743 | return ECCSFULL; |
1723 | } /* get_free_ccs */ | 1744 | } /* get_free_ccs */ |
1745 | |||
1724 | /*===========================================================================*/ | 1746 | /*===========================================================================*/ |
1725 | static void authenticate_timeout(u_long data) | 1747 | static void authenticate_timeout(u_long data) |
1726 | { | 1748 | { |
1727 | ray_dev_t *local = (ray_dev_t *)data; | 1749 | ray_dev_t *local = (ray_dev_t *) data; |
1728 | del_timer(&local->timer); | 1750 | del_timer(&local->timer); |
1729 | printk(KERN_INFO "ray_cs Authentication with access point failed" | 1751 | printk(KERN_INFO "ray_cs Authentication with access point failed" |
1730 | " - timeout\n"); | 1752 | " - timeout\n"); |
1731 | join_net((u_long)local); | 1753 | join_net((u_long) local); |
1732 | } | 1754 | } |
1755 | |||
1733 | /*===========================================================================*/ | 1756 | /*===========================================================================*/ |
1734 | static int asc_to_int(char a) | 1757 | static int asc_to_int(char a) |
1735 | { | 1758 | { |
1736 | if (a < '0') return -1; | 1759 | if (a < '0') |
1737 | if (a <= '9') return (a - '0'); | 1760 | return -1; |
1738 | if (a < 'A') return -1; | 1761 | if (a <= '9') |
1739 | if (a <= 'F') return (10 + a - 'A'); | 1762 | return (a - '0'); |
1740 | if (a < 'a') return -1; | 1763 | if (a < 'A') |
1741 | if (a <= 'f') return (10 + a - 'a'); | 1764 | return -1; |
1742 | return -1; | 1765 | if (a <= 'F') |
1766 | return (10 + a - 'A'); | ||
1767 | if (a < 'a') | ||
1768 | return -1; | ||
1769 | if (a <= 'f') | ||
1770 | return (10 + a - 'a'); | ||
1771 | return -1; | ||
1743 | } | 1772 | } |
1773 | |||
1744 | /*===========================================================================*/ | 1774 | /*===========================================================================*/ |
1745 | static int parse_addr(char *in_str, UCHAR *out) | 1775 | static int parse_addr(char *in_str, UCHAR *out) |
1746 | { | 1776 | { |
1747 | int len; | 1777 | int len; |
1748 | int i,j,k; | 1778 | int i, j, k; |
1749 | int status; | 1779 | int status; |
1750 | 1780 | ||
1751 | if (in_str == NULL) return 0; | 1781 | if (in_str == NULL) |
1752 | if ((len = strlen(in_str)) < 2) return 0; | 1782 | return 0; |
1753 | memset(out, 0, ADDRLEN); | 1783 | if ((len = strlen(in_str)) < 2) |
1754 | 1784 | return 0; | |
1755 | status = 1; | 1785 | memset(out, 0, ADDRLEN); |
1756 | j = len - 1; | 1786 | |
1757 | if (j > 12) j = 12; | 1787 | status = 1; |
1758 | i = 5; | 1788 | j = len - 1; |
1759 | 1789 | if (j > 12) | |
1760 | while (j > 0) | 1790 | j = 12; |
1761 | { | 1791 | i = 5; |
1762 | if ((k = asc_to_int(in_str[j--])) != -1) out[i] = k; | 1792 | |
1763 | else return 0; | 1793 | while (j > 0) { |
1764 | 1794 | if ((k = asc_to_int(in_str[j--])) != -1) | |
1765 | if (j == 0) break; | 1795 | out[i] = k; |
1766 | if ((k = asc_to_int(in_str[j--])) != -1) out[i] += k << 4; | 1796 | else |
1767 | else return 0; | 1797 | return 0; |
1768 | if (!i--) break; | 1798 | |
1769 | } | 1799 | if (j == 0) |
1770 | return status; | 1800 | break; |
1801 | if ((k = asc_to_int(in_str[j--])) != -1) | ||
1802 | out[i] += k << 4; | ||
1803 | else | ||
1804 | return 0; | ||
1805 | if (!i--) | ||
1806 | break; | ||
1807 | } | ||
1808 | return status; | ||
1771 | } | 1809 | } |
1810 | |||
1772 | /*===========================================================================*/ | 1811 | /*===========================================================================*/ |
1773 | static struct net_device_stats *ray_get_stats(struct net_device *dev) | 1812 | static struct net_device_stats *ray_get_stats(struct net_device *dev) |
1774 | { | 1813 | { |
1775 | ray_dev_t *local = netdev_priv(dev); | 1814 | ray_dev_t *local = netdev_priv(dev); |
1776 | struct pcmcia_device *link = local->finder; | 1815 | struct pcmcia_device *link = local->finder; |
1777 | struct status __iomem *p = local->sram + STATUS_BASE; | 1816 | struct status __iomem *p = local->sram + STATUS_BASE; |
1778 | if (!(pcmcia_dev_present(link))) { | 1817 | if (!(pcmcia_dev_present(link))) { |
1779 | DEBUG(2,"ray_cs net_device_stats - device not present\n"); | 1818 | DEBUG(2, "ray_cs net_device_stats - device not present\n"); |
1780 | return &local->stats; | 1819 | return &local->stats; |
1781 | } | 1820 | } |
1782 | if (readb(&p->mrx_overflow_for_host)) | 1821 | if (readb(&p->mrx_overflow_for_host)) { |
1783 | { | 1822 | local->stats.rx_over_errors += swab16(readw(&p->mrx_overflow)); |
1784 | local->stats.rx_over_errors += swab16(readw(&p->mrx_overflow)); | 1823 | writeb(0, &p->mrx_overflow); |
1785 | writeb(0,&p->mrx_overflow); | 1824 | writeb(0, &p->mrx_overflow_for_host); |
1786 | writeb(0,&p->mrx_overflow_for_host); | 1825 | } |
1787 | } | 1826 | if (readb(&p->mrx_checksum_error_for_host)) { |
1788 | if (readb(&p->mrx_checksum_error_for_host)) | 1827 | local->stats.rx_crc_errors += |
1789 | { | 1828 | swab16(readw(&p->mrx_checksum_error)); |
1790 | local->stats.rx_crc_errors += swab16(readw(&p->mrx_checksum_error)); | 1829 | writeb(0, &p->mrx_checksum_error); |
1791 | writeb(0,&p->mrx_checksum_error); | 1830 | writeb(0, &p->mrx_checksum_error_for_host); |
1792 | writeb(0,&p->mrx_checksum_error_for_host); | 1831 | } |
1793 | } | 1832 | if (readb(&p->rx_hec_error_for_host)) { |
1794 | if (readb(&p->rx_hec_error_for_host)) | 1833 | local->stats.rx_frame_errors += swab16(readw(&p->rx_hec_error)); |
1795 | { | 1834 | writeb(0, &p->rx_hec_error); |
1796 | local->stats.rx_frame_errors += swab16(readw(&p->rx_hec_error)); | 1835 | writeb(0, &p->rx_hec_error_for_host); |
1797 | writeb(0,&p->rx_hec_error); | 1836 | } |
1798 | writeb(0,&p->rx_hec_error_for_host); | 1837 | return &local->stats; |
1799 | } | ||
1800 | return &local->stats; | ||
1801 | } | 1838 | } |
1839 | |||
1802 | /*===========================================================================*/ | 1840 | /*===========================================================================*/ |
1803 | static void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value, int len) | 1841 | static void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value, |
1804 | { | 1842 | int len) |
1805 | ray_dev_t *local = netdev_priv(dev); | 1843 | { |
1806 | struct pcmcia_device *link = local->finder; | 1844 | ray_dev_t *local = netdev_priv(dev); |
1807 | int ccsindex; | 1845 | struct pcmcia_device *link = local->finder; |
1808 | int i; | 1846 | int ccsindex; |
1809 | struct ccs __iomem *pccs; | 1847 | int i; |
1810 | 1848 | struct ccs __iomem *pccs; | |
1811 | if (!(pcmcia_dev_present(link))) { | 1849 | |
1812 | DEBUG(2,"ray_update_parm - device not present\n"); | 1850 | if (!(pcmcia_dev_present(link))) { |
1813 | return; | 1851 | DEBUG(2, "ray_update_parm - device not present\n"); |
1814 | } | 1852 | return; |
1815 | 1853 | } | |
1816 | if ((ccsindex = get_free_ccs(local)) < 0) | 1854 | |
1817 | { | 1855 | if ((ccsindex = get_free_ccs(local)) < 0) { |
1818 | DEBUG(0,"ray_update_parm - No free ccs\n"); | 1856 | DEBUG(0, "ray_update_parm - No free ccs\n"); |
1819 | return; | 1857 | return; |
1820 | } | 1858 | } |
1821 | pccs = ccs_base(local) + ccsindex; | 1859 | pccs = ccs_base(local) + ccsindex; |
1822 | writeb(CCS_UPDATE_PARAMS, &pccs->cmd); | 1860 | writeb(CCS_UPDATE_PARAMS, &pccs->cmd); |
1823 | writeb(objid, &pccs->var.update_param.object_id); | 1861 | writeb(objid, &pccs->var.update_param.object_id); |
1824 | writeb(1, &pccs->var.update_param.number_objects); | 1862 | writeb(1, &pccs->var.update_param.number_objects); |
1825 | writeb(0, &pccs->var.update_param.failure_cause); | 1863 | writeb(0, &pccs->var.update_param.failure_cause); |
1826 | for (i=0; i<len; i++) { | 1864 | for (i = 0; i < len; i++) { |
1827 | writeb(value[i], local->sram + HOST_TO_ECF_BASE); | 1865 | writeb(value[i], local->sram + HOST_TO_ECF_BASE); |
1828 | } | 1866 | } |
1829 | /* Interrupt the firmware to process the command */ | 1867 | /* Interrupt the firmware to process the command */ |
1830 | if (interrupt_ecf(local, ccsindex)) { | 1868 | if (interrupt_ecf(local, ccsindex)) { |
1831 | DEBUG(0,"ray_cs associate failed - ECF not ready for intr\n"); | 1869 | DEBUG(0, "ray_cs associate failed - ECF not ready for intr\n"); |
1832 | writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); | 1870 | writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); |
1833 | } | 1871 | } |
1834 | } | 1872 | } |
1873 | |||
1835 | /*===========================================================================*/ | 1874 | /*===========================================================================*/ |
1836 | static void ray_update_multi_list(struct net_device *dev, int all) | 1875 | static void ray_update_multi_list(struct net_device *dev, int all) |
1837 | { | 1876 | { |
1838 | struct dev_mc_list *dmi, **dmip; | 1877 | struct dev_mc_list *dmi, **dmip; |
1839 | int ccsindex; | 1878 | int ccsindex; |
1840 | struct ccs __iomem *pccs; | 1879 | struct ccs __iomem *pccs; |
1841 | int i = 0; | 1880 | int i = 0; |
1842 | ray_dev_t *local = netdev_priv(dev); | 1881 | ray_dev_t *local = netdev_priv(dev); |
1843 | struct pcmcia_device *link = local->finder; | 1882 | struct pcmcia_device *link = local->finder; |
1844 | void __iomem *p = local->sram + HOST_TO_ECF_BASE; | 1883 | void __iomem *p = local->sram + HOST_TO_ECF_BASE; |
1845 | 1884 | ||
1846 | if (!(pcmcia_dev_present(link))) { | 1885 | if (!(pcmcia_dev_present(link))) { |
1847 | DEBUG(2,"ray_update_multi_list - device not present\n"); | 1886 | DEBUG(2, "ray_update_multi_list - device not present\n"); |
1848 | return; | 1887 | return; |
1849 | } | 1888 | } else |
1850 | else | 1889 | DEBUG(2, "ray_update_multi_list(%p)\n", dev); |
1851 | DEBUG(2,"ray_update_multi_list(%p)\n",dev); | 1890 | if ((ccsindex = get_free_ccs(local)) < 0) { |
1852 | if ((ccsindex = get_free_ccs(local)) < 0) | 1891 | DEBUG(1, "ray_update_multi - No free ccs\n"); |
1853 | { | 1892 | return; |
1854 | DEBUG(1,"ray_update_multi - No free ccs\n"); | 1893 | } |
1855 | return; | 1894 | pccs = ccs_base(local) + ccsindex; |
1856 | } | 1895 | writeb(CCS_UPDATE_MULTICAST_LIST, &pccs->cmd); |
1857 | pccs = ccs_base(local) + ccsindex; | 1896 | |
1858 | writeb(CCS_UPDATE_MULTICAST_LIST, &pccs->cmd); | 1897 | if (all) { |
1859 | 1898 | writeb(0xff, &pccs->var); | |
1860 | if (all) { | 1899 | local->num_multi = 0xff; |
1861 | writeb(0xff, &pccs->var); | 1900 | } else { |
1862 | local->num_multi = 0xff; | 1901 | /* Copy the kernel's list of MC addresses to card */ |
1863 | } | 1902 | for (dmip = &dev->mc_list; (dmi = *dmip) != NULL; |
1864 | else { | 1903 | dmip = &dmi->next) { |
1865 | /* Copy the kernel's list of MC addresses to card */ | 1904 | memcpy_toio(p, dmi->dmi_addr, ETH_ALEN); |
1866 | for (dmip=&dev->mc_list; (dmi=*dmip)!=NULL; dmip=&dmi->next) { | 1905 | DEBUG(1, |
1867 | memcpy_toio(p, dmi->dmi_addr, ETH_ALEN); | 1906 | "ray_update_multi add addr %02x%02x%02x%02x%02x%02x\n", |
1868 | DEBUG(1,"ray_update_multi add addr %02x%02x%02x%02x%02x%02x\n",dmi->dmi_addr[0],dmi->dmi_addr[1],dmi->dmi_addr[2],dmi->dmi_addr[3],dmi->dmi_addr[4],dmi->dmi_addr[5]); | 1907 | dmi->dmi_addr[0], dmi->dmi_addr[1], |
1869 | p += ETH_ALEN; | 1908 | dmi->dmi_addr[2], dmi->dmi_addr[3], |
1870 | i++; | 1909 | dmi->dmi_addr[4], dmi->dmi_addr[5]); |
1871 | } | 1910 | p += ETH_ALEN; |
1872 | if (i > 256/ADDRLEN) i = 256/ADDRLEN; | 1911 | i++; |
1873 | writeb((UCHAR)i, &pccs->var); | 1912 | } |
1874 | DEBUG(1,"ray_cs update_multi %d addresses in list\n", i); | 1913 | if (i > 256 / ADDRLEN) |
1875 | /* Interrupt the firmware to process the command */ | 1914 | i = 256 / ADDRLEN; |
1876 | local->num_multi = i; | 1915 | writeb((UCHAR) i, &pccs->var); |
1877 | } | 1916 | DEBUG(1, "ray_cs update_multi %d addresses in list\n", i); |
1878 | if (interrupt_ecf(local, ccsindex)) { | 1917 | /* Interrupt the firmware to process the command */ |
1879 | DEBUG(1,"ray_cs update_multi failed - ECF not ready for intr\n"); | 1918 | local->num_multi = i; |
1880 | writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); | 1919 | } |
1881 | } | 1920 | if (interrupt_ecf(local, ccsindex)) { |
1921 | DEBUG(1, | ||
1922 | "ray_cs update_multi failed - ECF not ready for intr\n"); | ||
1923 | writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); | ||
1924 | } | ||
1882 | } /* end ray_update_multi_list */ | 1925 | } /* end ray_update_multi_list */ |
1926 | |||
1883 | /*===========================================================================*/ | 1927 | /*===========================================================================*/ |
1884 | static void set_multicast_list(struct net_device *dev) | 1928 | static void set_multicast_list(struct net_device *dev) |
1885 | { | 1929 | { |
1886 | ray_dev_t *local = netdev_priv(dev); | 1930 | ray_dev_t *local = netdev_priv(dev); |
1887 | UCHAR promisc; | 1931 | UCHAR promisc; |
1888 | 1932 | ||
1889 | DEBUG(2,"ray_cs set_multicast_list(%p)\n",dev); | 1933 | DEBUG(2, "ray_cs set_multicast_list(%p)\n", dev); |
1890 | 1934 | ||
1891 | if (dev->flags & IFF_PROMISC) | 1935 | if (dev->flags & IFF_PROMISC) { |
1892 | { | 1936 | if (local->sparm.b5.a_promiscuous_mode == 0) { |
1893 | if (local->sparm.b5.a_promiscuous_mode == 0) { | 1937 | DEBUG(1, "ray_cs set_multicast_list promisc on\n"); |
1894 | DEBUG(1,"ray_cs set_multicast_list promisc on\n"); | 1938 | local->sparm.b5.a_promiscuous_mode = 1; |
1895 | local->sparm.b5.a_promiscuous_mode = 1; | 1939 | promisc = 1; |
1896 | promisc = 1; | 1940 | ray_update_parm(dev, OBJID_promiscuous_mode, |
1897 | ray_update_parm(dev, OBJID_promiscuous_mode, \ | 1941 | &promisc, sizeof(promisc)); |
1898 | &promisc, sizeof(promisc)); | 1942 | } |
1899 | } | 1943 | } else { |
1900 | } | 1944 | if (local->sparm.b5.a_promiscuous_mode == 1) { |
1901 | else { | 1945 | DEBUG(1, "ray_cs set_multicast_list promisc off\n"); |
1902 | if (local->sparm.b5.a_promiscuous_mode == 1) { | 1946 | local->sparm.b5.a_promiscuous_mode = 0; |
1903 | DEBUG(1,"ray_cs set_multicast_list promisc off\n"); | 1947 | promisc = 0; |
1904 | local->sparm.b5.a_promiscuous_mode = 0; | 1948 | ray_update_parm(dev, OBJID_promiscuous_mode, |
1905 | promisc = 0; | 1949 | &promisc, sizeof(promisc)); |
1906 | ray_update_parm(dev, OBJID_promiscuous_mode, \ | 1950 | } |
1907 | &promisc, sizeof(promisc)); | 1951 | } |
1908 | } | 1952 | |
1909 | } | 1953 | if (dev->flags & IFF_ALLMULTI) |
1910 | 1954 | ray_update_multi_list(dev, 1); | |
1911 | if (dev->flags & IFF_ALLMULTI) ray_update_multi_list(dev, 1); | 1955 | else { |
1912 | else | 1956 | if (local->num_multi != dev->mc_count) |
1913 | { | 1957 | ray_update_multi_list(dev, 0); |
1914 | if (local->num_multi != dev->mc_count) ray_update_multi_list(dev, 0); | 1958 | } |
1915 | } | ||
1916 | } /* end set_multicast_list */ | 1959 | } /* end set_multicast_list */ |
1960 | |||
1917 | /*============================================================================= | 1961 | /*============================================================================= |
1918 | * All routines below here are run at interrupt time. | 1962 | * All routines below here are run at interrupt time. |
1919 | =============================================================================*/ | 1963 | =============================================================================*/ |
1920 | static irqreturn_t ray_interrupt(int irq, void *dev_id) | 1964 | static irqreturn_t ray_interrupt(int irq, void *dev_id) |
1921 | { | 1965 | { |
1922 | struct net_device *dev = (struct net_device *)dev_id; | 1966 | struct net_device *dev = (struct net_device *)dev_id; |
1923 | struct pcmcia_device *link; | 1967 | struct pcmcia_device *link; |
1924 | ray_dev_t *local; | 1968 | ray_dev_t *local; |
1925 | struct ccs __iomem *pccs; | 1969 | struct ccs __iomem *pccs; |
1926 | struct rcs __iomem *prcs; | 1970 | struct rcs __iomem *prcs; |
1927 | UCHAR rcsindex; | 1971 | UCHAR rcsindex; |
1928 | UCHAR tmp; | 1972 | UCHAR tmp; |
1929 | UCHAR cmd; | 1973 | UCHAR cmd; |
1930 | UCHAR status; | 1974 | UCHAR status; |
1931 | 1975 | ||
1932 | if (dev == NULL) /* Note that we want interrupts with dev->start == 0 */ | 1976 | if (dev == NULL) /* Note that we want interrupts with dev->start == 0 */ |
1933 | return IRQ_NONE; | 1977 | return IRQ_NONE; |
1934 | 1978 | ||
1935 | DEBUG(4,"ray_cs: interrupt for *dev=%p\n",dev); | 1979 | DEBUG(4, "ray_cs: interrupt for *dev=%p\n", dev); |
1936 | 1980 | ||
1937 | local = netdev_priv(dev); | 1981 | local = netdev_priv(dev); |
1938 | link = (struct pcmcia_device *)local->finder; | 1982 | link = (struct pcmcia_device *)local->finder; |
1939 | if (!pcmcia_dev_present(link)) { | 1983 | if (!pcmcia_dev_present(link)) { |
1940 | DEBUG(2,"ray_cs interrupt from device not present or suspended.\n"); | 1984 | DEBUG(2, |
1941 | return IRQ_NONE; | 1985 | "ray_cs interrupt from device not present or suspended.\n"); |
1942 | } | 1986 | return IRQ_NONE; |
1943 | rcsindex = readb(&((struct scb __iomem *)(local->sram))->rcs_index); | 1987 | } |
1944 | 1988 | rcsindex = readb(&((struct scb __iomem *)(local->sram))->rcs_index); | |
1945 | if (rcsindex >= (NUMBER_OF_CCS + NUMBER_OF_RCS)) | 1989 | |
1946 | { | 1990 | if (rcsindex >= (NUMBER_OF_CCS + NUMBER_OF_RCS)) { |
1947 | DEBUG(1,"ray_cs interrupt bad rcsindex = 0x%x\n",rcsindex); | 1991 | DEBUG(1, "ray_cs interrupt bad rcsindex = 0x%x\n", rcsindex); |
1948 | clear_interrupt(local); | 1992 | clear_interrupt(local); |
1949 | return IRQ_HANDLED; | 1993 | return IRQ_HANDLED; |
1950 | } | 1994 | } |
1951 | if (rcsindex < NUMBER_OF_CCS) /* If it's a returned CCS */ | 1995 | if (rcsindex < NUMBER_OF_CCS) { /* If it's a returned CCS */ |
1952 | { | 1996 | pccs = ccs_base(local) + rcsindex; |
1953 | pccs = ccs_base(local) + rcsindex; | 1997 | cmd = readb(&pccs->cmd); |
1954 | cmd = readb(&pccs->cmd); | 1998 | status = readb(&pccs->buffer_status); |
1955 | status = readb(&pccs->buffer_status); | 1999 | switch (cmd) { |
1956 | switch (cmd) | 2000 | case CCS_DOWNLOAD_STARTUP_PARAMS: /* Happens in firmware someday */ |
1957 | { | 2001 | del_timer(&local->timer); |
1958 | case CCS_DOWNLOAD_STARTUP_PARAMS: /* Happens in firmware someday */ | 2002 | if (status == CCS_COMMAND_COMPLETE) { |
1959 | del_timer(&local->timer); | 2003 | DEBUG(1, |
1960 | if (status == CCS_COMMAND_COMPLETE) { | 2004 | "ray_cs interrupt download_startup_parameters OK\n"); |
1961 | DEBUG(1,"ray_cs interrupt download_startup_parameters OK\n"); | 2005 | } else { |
1962 | } | 2006 | DEBUG(1, |
1963 | else { | 2007 | "ray_cs interrupt download_startup_parameters fail\n"); |
1964 | DEBUG(1,"ray_cs interrupt download_startup_parameters fail\n"); | 2008 | } |
1965 | } | 2009 | break; |
1966 | break; | 2010 | case CCS_UPDATE_PARAMS: |
1967 | case CCS_UPDATE_PARAMS: | 2011 | DEBUG(1, "ray_cs interrupt update params done\n"); |
1968 | DEBUG(1,"ray_cs interrupt update params done\n"); | 2012 | if (status != CCS_COMMAND_COMPLETE) { |
1969 | if (status != CCS_COMMAND_COMPLETE) { | 2013 | tmp = |
1970 | tmp = readb(&pccs->var.update_param.failure_cause); | 2014 | readb(&pccs->var.update_param. |
1971 | DEBUG(0,"ray_cs interrupt update params failed - reason %d\n",tmp); | 2015 | failure_cause); |
1972 | } | 2016 | DEBUG(0, |
1973 | break; | 2017 | "ray_cs interrupt update params failed - reason %d\n", |
1974 | case CCS_REPORT_PARAMS: | 2018 | tmp); |
1975 | DEBUG(1,"ray_cs interrupt report params done\n"); | 2019 | } |
1976 | break; | 2020 | break; |
1977 | case CCS_UPDATE_MULTICAST_LIST: /* Note that this CCS isn't returned */ | 2021 | case CCS_REPORT_PARAMS: |
1978 | DEBUG(1,"ray_cs interrupt CCS Update Multicast List done\n"); | 2022 | DEBUG(1, "ray_cs interrupt report params done\n"); |
1979 | break; | 2023 | break; |
1980 | case CCS_UPDATE_POWER_SAVINGS_MODE: | 2024 | case CCS_UPDATE_MULTICAST_LIST: /* Note that this CCS isn't returned */ |
1981 | DEBUG(1,"ray_cs interrupt update power save mode done\n"); | 2025 | DEBUG(1, |
1982 | break; | 2026 | "ray_cs interrupt CCS Update Multicast List done\n"); |
1983 | case CCS_START_NETWORK: | 2027 | break; |
1984 | case CCS_JOIN_NETWORK: | 2028 | case CCS_UPDATE_POWER_SAVINGS_MODE: |
1985 | if (status == CCS_COMMAND_COMPLETE) { | 2029 | DEBUG(1, |
1986 | if (readb(&pccs->var.start_network.net_initiated) == 1) { | 2030 | "ray_cs interrupt update power save mode done\n"); |
1987 | DEBUG(0,"ray_cs interrupt network \"%s\" started\n",\ | 2031 | break; |
1988 | local->sparm.b4.a_current_ess_id); | 2032 | case CCS_START_NETWORK: |
1989 | } | 2033 | case CCS_JOIN_NETWORK: |
1990 | else { | 2034 | if (status == CCS_COMMAND_COMPLETE) { |
1991 | DEBUG(0,"ray_cs interrupt network \"%s\" joined\n",\ | 2035 | if (readb |
1992 | local->sparm.b4.a_current_ess_id); | 2036 | (&pccs->var.start_network.net_initiated) == |
1993 | } | 2037 | 1) { |
1994 | memcpy_fromio(&local->bss_id,pccs->var.start_network.bssid,ADDRLEN); | 2038 | DEBUG(0, |
1995 | 2039 | "ray_cs interrupt network \"%s\" started\n", | |
1996 | if (local->fw_ver == 0x55) local->net_default_tx_rate = 3; | 2040 | local->sparm.b4.a_current_ess_id); |
1997 | else local->net_default_tx_rate = | 2041 | } else { |
1998 | readb(&pccs->var.start_network.net_default_tx_rate); | 2042 | DEBUG(0, |
1999 | local->encryption = readb(&pccs->var.start_network.encryption); | 2043 | "ray_cs interrupt network \"%s\" joined\n", |
2000 | if (!sniffer && (local->net_type == INFRA) | 2044 | local->sparm.b4.a_current_ess_id); |
2001 | && !(local->sparm.b4.a_acting_as_ap_status)) { | 2045 | } |
2002 | authenticate(local); | 2046 | memcpy_fromio(&local->bss_id, |
2003 | } | 2047 | pccs->var.start_network.bssid, |
2004 | local->card_status = CARD_ACQ_COMPLETE; | 2048 | ADDRLEN); |
2005 | } | 2049 | |
2006 | else { | 2050 | if (local->fw_ver == 0x55) |
2007 | local->card_status = CARD_ACQ_FAILED; | 2051 | local->net_default_tx_rate = 3; |
2008 | 2052 | else | |
2009 | del_timer(&local->timer); | 2053 | local->net_default_tx_rate = |
2010 | local->timer.expires = jiffies + HZ*5; | 2054 | readb(&pccs->var.start_network. |
2011 | local->timer.data = (long)local; | 2055 | net_default_tx_rate); |
2012 | if (status == CCS_START_NETWORK) { | 2056 | local->encryption = |
2013 | DEBUG(0,"ray_cs interrupt network \"%s\" start failed\n",\ | 2057 | readb(&pccs->var.start_network.encryption); |
2014 | local->sparm.b4.a_current_ess_id); | 2058 | if (!sniffer && (local->net_type == INFRA) |
2015 | local->timer.function = &start_net; | 2059 | && !(local->sparm.b4.a_acting_as_ap_status)) { |
2016 | } | 2060 | authenticate(local); |
2017 | else { | 2061 | } |
2018 | DEBUG(0,"ray_cs interrupt network \"%s\" join failed\n",\ | 2062 | local->card_status = CARD_ACQ_COMPLETE; |
2019 | local->sparm.b4.a_current_ess_id); | 2063 | } else { |
2020 | local->timer.function = &join_net; | 2064 | local->card_status = CARD_ACQ_FAILED; |
2021 | } | 2065 | |
2022 | add_timer(&local->timer); | 2066 | del_timer(&local->timer); |
2023 | } | 2067 | local->timer.expires = jiffies + HZ * 5; |
2024 | break; | 2068 | local->timer.data = (long)local; |
2025 | case CCS_START_ASSOCIATION: | 2069 | if (status == CCS_START_NETWORK) { |
2026 | if (status == CCS_COMMAND_COMPLETE) { | 2070 | DEBUG(0, |
2027 | local->card_status = CARD_ASSOC_COMPLETE; | 2071 | "ray_cs interrupt network \"%s\" start failed\n", |
2028 | DEBUG(0,"ray_cs association successful\n"); | 2072 | local->sparm.b4.a_current_ess_id); |
2029 | } | 2073 | local->timer.function = &start_net; |
2030 | else | 2074 | } else { |
2031 | { | 2075 | DEBUG(0, |
2032 | DEBUG(0,"ray_cs association failed,\n"); | 2076 | "ray_cs interrupt network \"%s\" join failed\n", |
2033 | local->card_status = CARD_ASSOC_FAILED; | 2077 | local->sparm.b4.a_current_ess_id); |
2034 | join_net((u_long)local); | 2078 | local->timer.function = &join_net; |
2035 | } | 2079 | } |
2036 | break; | 2080 | add_timer(&local->timer); |
2037 | case CCS_TX_REQUEST: | 2081 | } |
2038 | if (status == CCS_COMMAND_COMPLETE) { | 2082 | break; |
2039 | DEBUG(3,"ray_cs interrupt tx request complete\n"); | 2083 | case CCS_START_ASSOCIATION: |
2040 | } | 2084 | if (status == CCS_COMMAND_COMPLETE) { |
2041 | else { | 2085 | local->card_status = CARD_ASSOC_COMPLETE; |
2042 | DEBUG(1,"ray_cs interrupt tx request failed\n"); | 2086 | DEBUG(0, "ray_cs association successful\n"); |
2043 | } | 2087 | } else { |
2044 | if (!sniffer) netif_start_queue(dev); | 2088 | DEBUG(0, "ray_cs association failed,\n"); |
2045 | netif_wake_queue(dev); | 2089 | local->card_status = CARD_ASSOC_FAILED; |
2046 | break; | 2090 | join_net((u_long) local); |
2047 | case CCS_TEST_MEMORY: | 2091 | } |
2048 | DEBUG(1,"ray_cs interrupt mem test done\n"); | 2092 | break; |
2049 | break; | 2093 | case CCS_TX_REQUEST: |
2050 | case CCS_SHUTDOWN: | 2094 | if (status == CCS_COMMAND_COMPLETE) { |
2051 | DEBUG(1,"ray_cs interrupt Unexpected CCS returned - Shutdown\n"); | 2095 | DEBUG(3, |
2052 | break; | 2096 | "ray_cs interrupt tx request complete\n"); |
2053 | case CCS_DUMP_MEMORY: | 2097 | } else { |
2054 | DEBUG(1,"ray_cs interrupt dump memory done\n"); | 2098 | DEBUG(1, |
2055 | break; | 2099 | "ray_cs interrupt tx request failed\n"); |
2056 | case CCS_START_TIMER: | 2100 | } |
2057 | DEBUG(2,"ray_cs interrupt DING - raylink timer expired\n"); | 2101 | if (!sniffer) |
2058 | break; | 2102 | netif_start_queue(dev); |
2059 | default: | 2103 | netif_wake_queue(dev); |
2060 | DEBUG(1,"ray_cs interrupt Unexpected CCS 0x%x returned 0x%x\n",\ | 2104 | break; |
2061 | rcsindex, cmd); | 2105 | case CCS_TEST_MEMORY: |
2062 | } | 2106 | DEBUG(1, "ray_cs interrupt mem test done\n"); |
2063 | writeb(CCS_BUFFER_FREE, &pccs->buffer_status); | 2107 | break; |
2064 | } | 2108 | case CCS_SHUTDOWN: |
2065 | else /* It's an RCS */ | 2109 | DEBUG(1, |
2066 | { | 2110 | "ray_cs interrupt Unexpected CCS returned - Shutdown\n"); |
2067 | prcs = rcs_base(local) + rcsindex; | 2111 | break; |
2068 | 2112 | case CCS_DUMP_MEMORY: | |
2069 | switch (readb(&prcs->interrupt_id)) | 2113 | DEBUG(1, "ray_cs interrupt dump memory done\n"); |
2070 | { | 2114 | break; |
2071 | case PROCESS_RX_PACKET: | 2115 | case CCS_START_TIMER: |
2072 | ray_rx(dev, local, prcs); | 2116 | DEBUG(2, |
2073 | break; | 2117 | "ray_cs interrupt DING - raylink timer expired\n"); |
2074 | case REJOIN_NET_COMPLETE: | 2118 | break; |
2075 | DEBUG(1,"ray_cs interrupt rejoin net complete\n"); | 2119 | default: |
2076 | local->card_status = CARD_ACQ_COMPLETE; | 2120 | DEBUG(1, |
2077 | /* do we need to clear tx buffers CCS's? */ | 2121 | "ray_cs interrupt Unexpected CCS 0x%x returned 0x%x\n", |
2078 | if (local->sparm.b4.a_network_type == ADHOC) { | 2122 | rcsindex, cmd); |
2079 | if (!sniffer) netif_start_queue(dev); | 2123 | } |
2080 | } | 2124 | writeb(CCS_BUFFER_FREE, &pccs->buffer_status); |
2081 | else { | 2125 | } else { /* It's an RCS */ |
2082 | memcpy_fromio(&local->bss_id, prcs->var.rejoin_net_complete.bssid, ADDRLEN); | 2126 | |
2083 | DEBUG(1,"ray_cs new BSSID = %02x%02x%02x%02x%02x%02x\n",\ | 2127 | prcs = rcs_base(local) + rcsindex; |
2084 | local->bss_id[0], local->bss_id[1], local->bss_id[2],\ | 2128 | |
2085 | local->bss_id[3], local->bss_id[4], local->bss_id[5]); | 2129 | switch (readb(&prcs->interrupt_id)) { |
2086 | if (!sniffer) authenticate(local); | 2130 | case PROCESS_RX_PACKET: |
2087 | } | 2131 | ray_rx(dev, local, prcs); |
2088 | break; | 2132 | break; |
2089 | case ROAMING_INITIATED: | 2133 | case REJOIN_NET_COMPLETE: |
2090 | DEBUG(1,"ray_cs interrupt roaming initiated\n"); | 2134 | DEBUG(1, "ray_cs interrupt rejoin net complete\n"); |
2091 | netif_stop_queue(dev); | 2135 | local->card_status = CARD_ACQ_COMPLETE; |
2092 | local->card_status = CARD_DOING_ACQ; | 2136 | /* do we need to clear tx buffers CCS's? */ |
2093 | break; | 2137 | if (local->sparm.b4.a_network_type == ADHOC) { |
2094 | case JAPAN_CALL_SIGN_RXD: | 2138 | if (!sniffer) |
2095 | DEBUG(1,"ray_cs interrupt japan call sign rx\n"); | 2139 | netif_start_queue(dev); |
2096 | break; | 2140 | } else { |
2097 | default: | 2141 | memcpy_fromio(&local->bss_id, |
2098 | DEBUG(1,"ray_cs Unexpected interrupt for RCS 0x%x cmd = 0x%x\n",\ | 2142 | prcs->var.rejoin_net_complete. |
2099 | rcsindex, (unsigned int) readb(&prcs->interrupt_id)); | 2143 | bssid, ADDRLEN); |
2100 | break; | 2144 | DEBUG(1, |
2101 | } | 2145 | "ray_cs new BSSID = %02x%02x%02x%02x%02x%02x\n", |
2102 | writeb(CCS_BUFFER_FREE, &prcs->buffer_status); | 2146 | local->bss_id[0], local->bss_id[1], |
2103 | } | 2147 | local->bss_id[2], local->bss_id[3], |
2104 | clear_interrupt(local); | 2148 | local->bss_id[4], local->bss_id[5]); |
2105 | return IRQ_HANDLED; | 2149 | if (!sniffer) |
2150 | authenticate(local); | ||
2151 | } | ||
2152 | break; | ||
2153 | case ROAMING_INITIATED: | ||
2154 | DEBUG(1, "ray_cs interrupt roaming initiated\n"); | ||
2155 | netif_stop_queue(dev); | ||
2156 | local->card_status = CARD_DOING_ACQ; | ||
2157 | break; | ||
2158 | case JAPAN_CALL_SIGN_RXD: | ||
2159 | DEBUG(1, "ray_cs interrupt japan call sign rx\n"); | ||
2160 | break; | ||
2161 | default: | ||
2162 | DEBUG(1, | ||
2163 | "ray_cs Unexpected interrupt for RCS 0x%x cmd = 0x%x\n", | ||
2164 | rcsindex, | ||
2165 | (unsigned int)readb(&prcs->interrupt_id)); | ||
2166 | break; | ||
2167 | } | ||
2168 | writeb(CCS_BUFFER_FREE, &prcs->buffer_status); | ||
2169 | } | ||
2170 | clear_interrupt(local); | ||
2171 | return IRQ_HANDLED; | ||
2106 | } /* ray_interrupt */ | 2172 | } /* ray_interrupt */ |
2173 | |||
2107 | /*===========================================================================*/ | 2174 | /*===========================================================================*/ |
2108 | static void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs __iomem *prcs) | 2175 | static void ray_rx(struct net_device *dev, ray_dev_t *local, |
2109 | { | 2176 | struct rcs __iomem *prcs) |
2110 | int rx_len; | 2177 | { |
2111 | unsigned int pkt_addr; | 2178 | int rx_len; |
2112 | void __iomem *pmsg; | 2179 | unsigned int pkt_addr; |
2113 | DEBUG(4,"ray_rx process rx packet\n"); | 2180 | void __iomem *pmsg; |
2114 | 2181 | DEBUG(4, "ray_rx process rx packet\n"); | |
2115 | /* Calculate address of packet within Rx buffer */ | 2182 | |
2116 | pkt_addr = ((readb(&prcs->var.rx_packet.rx_data_ptr[0]) << 8) | 2183 | /* Calculate address of packet within Rx buffer */ |
2117 | + readb(&prcs->var.rx_packet.rx_data_ptr[1])) & RX_BUFF_END; | 2184 | pkt_addr = ((readb(&prcs->var.rx_packet.rx_data_ptr[0]) << 8) |
2118 | /* Length of first packet fragment */ | 2185 | + readb(&prcs->var.rx_packet.rx_data_ptr[1])) & RX_BUFF_END; |
2119 | rx_len = (readb(&prcs->var.rx_packet.rx_data_length[0]) << 8) | 2186 | /* Length of first packet fragment */ |
2120 | + readb(&prcs->var.rx_packet.rx_data_length[1]); | 2187 | rx_len = (readb(&prcs->var.rx_packet.rx_data_length[0]) << 8) |
2121 | 2188 | + readb(&prcs->var.rx_packet.rx_data_length[1]); | |
2122 | local->last_rsl = readb(&prcs->var.rx_packet.rx_sig_lev); | 2189 | |
2123 | pmsg = local->rmem + pkt_addr; | 2190 | local->last_rsl = readb(&prcs->var.rx_packet.rx_sig_lev); |
2124 | switch(readb(pmsg)) | 2191 | pmsg = local->rmem + pkt_addr; |
2125 | { | 2192 | switch (readb(pmsg)) { |
2126 | case DATA_TYPE: | 2193 | case DATA_TYPE: |
2127 | DEBUG(4,"ray_rx data type\n"); | 2194 | DEBUG(4, "ray_rx data type\n"); |
2128 | rx_data(dev, prcs, pkt_addr, rx_len); | 2195 | rx_data(dev, prcs, pkt_addr, rx_len); |
2129 | break; | 2196 | break; |
2130 | case AUTHENTIC_TYPE: | 2197 | case AUTHENTIC_TYPE: |
2131 | DEBUG(4,"ray_rx authentic type\n"); | 2198 | DEBUG(4, "ray_rx authentic type\n"); |
2132 | if (sniffer) rx_data(dev, prcs, pkt_addr, rx_len); | 2199 | if (sniffer) |
2133 | else rx_authenticate(local, prcs, pkt_addr, rx_len); | 2200 | rx_data(dev, prcs, pkt_addr, rx_len); |
2134 | break; | 2201 | else |
2135 | case DEAUTHENTIC_TYPE: | 2202 | rx_authenticate(local, prcs, pkt_addr, rx_len); |
2136 | DEBUG(4,"ray_rx deauth type\n"); | 2203 | break; |
2137 | if (sniffer) rx_data(dev, prcs, pkt_addr, rx_len); | 2204 | case DEAUTHENTIC_TYPE: |
2138 | else rx_deauthenticate(local, prcs, pkt_addr, rx_len); | 2205 | DEBUG(4, "ray_rx deauth type\n"); |
2139 | break; | 2206 | if (sniffer) |
2140 | case NULL_MSG_TYPE: | 2207 | rx_data(dev, prcs, pkt_addr, rx_len); |
2141 | DEBUG(3,"ray_cs rx NULL msg\n"); | 2208 | else |
2142 | break; | 2209 | rx_deauthenticate(local, prcs, pkt_addr, rx_len); |
2143 | case BEACON_TYPE: | 2210 | break; |
2144 | DEBUG(4,"ray_rx beacon type\n"); | 2211 | case NULL_MSG_TYPE: |
2145 | if (sniffer) rx_data(dev, prcs, pkt_addr, rx_len); | 2212 | DEBUG(3, "ray_cs rx NULL msg\n"); |
2146 | 2213 | break; | |
2147 | copy_from_rx_buff(local, (UCHAR *)&local->last_bcn, pkt_addr, | 2214 | case BEACON_TYPE: |
2148 | rx_len < sizeof(struct beacon_rx) ? | 2215 | DEBUG(4, "ray_rx beacon type\n"); |
2149 | rx_len : sizeof(struct beacon_rx)); | 2216 | if (sniffer) |
2150 | 2217 | rx_data(dev, prcs, pkt_addr, rx_len); | |
2151 | local->beacon_rxed = 1; | 2218 | |
2152 | /* Get the statistics so the card counters never overflow */ | 2219 | copy_from_rx_buff(local, (UCHAR *) &local->last_bcn, pkt_addr, |
2153 | ray_get_stats(dev); | 2220 | rx_len < sizeof(struct beacon_rx) ? |
2154 | break; | 2221 | rx_len : sizeof(struct beacon_rx)); |
2155 | default: | 2222 | |
2156 | DEBUG(0,"ray_cs unknown pkt type %2x\n", (unsigned int) readb(pmsg)); | 2223 | local->beacon_rxed = 1; |
2157 | break; | 2224 | /* Get the statistics so the card counters never overflow */ |
2158 | } | 2225 | ray_get_stats(dev); |
2226 | break; | ||
2227 | default: | ||
2228 | DEBUG(0, "ray_cs unknown pkt type %2x\n", | ||
2229 | (unsigned int)readb(pmsg)); | ||
2230 | break; | ||
2231 | } | ||
2159 | 2232 | ||
2160 | } /* end ray_rx */ | 2233 | } /* end ray_rx */ |
2234 | |||
2161 | /*===========================================================================*/ | 2235 | /*===========================================================================*/ |
2162 | static void rx_data(struct net_device *dev, struct rcs __iomem *prcs, unsigned int pkt_addr, | 2236 | static void rx_data(struct net_device *dev, struct rcs __iomem *prcs, |
2163 | int rx_len) | 2237 | unsigned int pkt_addr, int rx_len) |
2164 | { | 2238 | { |
2165 | struct sk_buff *skb = NULL; | 2239 | struct sk_buff *skb = NULL; |
2166 | struct rcs __iomem *prcslink = prcs; | 2240 | struct rcs __iomem *prcslink = prcs; |
2167 | ray_dev_t *local = netdev_priv(dev); | 2241 | ray_dev_t *local = netdev_priv(dev); |
2168 | UCHAR *rx_ptr; | 2242 | UCHAR *rx_ptr; |
2169 | int total_len; | 2243 | int total_len; |
2170 | int tmp; | 2244 | int tmp; |
2171 | #ifdef WIRELESS_SPY | 2245 | #ifdef WIRELESS_SPY |
2172 | int siglev = local->last_rsl; | 2246 | int siglev = local->last_rsl; |
2173 | u_char linksrcaddr[ETH_ALEN]; /* Other end of the wireless link */ | 2247 | u_char linksrcaddr[ETH_ALEN]; /* Other end of the wireless link */ |
2174 | #endif | 2248 | #endif |
2175 | 2249 | ||
2176 | if (!sniffer) { | 2250 | if (!sniffer) { |
2177 | if (translate) { | 2251 | if (translate) { |
2178 | /* TBD length needs fixing for translated header */ | 2252 | /* TBD length needs fixing for translated header */ |
2179 | if (rx_len < (ETH_HLEN + RX_MAC_HEADER_LENGTH) || | 2253 | if (rx_len < (ETH_HLEN + RX_MAC_HEADER_LENGTH) || |
2180 | rx_len > (dev->mtu + RX_MAC_HEADER_LENGTH + ETH_HLEN + FCS_LEN)) | 2254 | rx_len > |
2181 | { | 2255 | (dev->mtu + RX_MAC_HEADER_LENGTH + ETH_HLEN + |
2182 | DEBUG(0,"ray_cs invalid packet length %d received \n",rx_len); | 2256 | FCS_LEN)) { |
2183 | return; | 2257 | DEBUG(0, |
2184 | } | 2258 | "ray_cs invalid packet length %d received \n", |
2185 | } | 2259 | rx_len); |
2186 | else /* encapsulated ethernet */ { | 2260 | return; |
2187 | if (rx_len < (ETH_HLEN + RX_MAC_HEADER_LENGTH) || | 2261 | } |
2188 | rx_len > (dev->mtu + RX_MAC_HEADER_LENGTH + ETH_HLEN + FCS_LEN)) | 2262 | } else { /* encapsulated ethernet */ |
2189 | { | 2263 | |
2190 | DEBUG(0,"ray_cs invalid packet length %d received \n",rx_len); | 2264 | if (rx_len < (ETH_HLEN + RX_MAC_HEADER_LENGTH) || |
2191 | return; | 2265 | rx_len > |
2192 | } | 2266 | (dev->mtu + RX_MAC_HEADER_LENGTH + ETH_HLEN + |
2193 | } | 2267 | FCS_LEN)) { |
2194 | } | 2268 | DEBUG(0, |
2195 | DEBUG(4,"ray_cs rx_data packet\n"); | 2269 | "ray_cs invalid packet length %d received \n", |
2196 | /* If fragmented packet, verify sizes of fragments add up */ | 2270 | rx_len); |
2197 | if (readb(&prcs->var.rx_packet.next_frag_rcs_index) != 0xFF) { | 2271 | return; |
2198 | DEBUG(1,"ray_cs rx'ed fragment\n"); | 2272 | } |
2199 | tmp = (readb(&prcs->var.rx_packet.totalpacketlength[0]) << 8) | 2273 | } |
2200 | + readb(&prcs->var.rx_packet.totalpacketlength[1]); | 2274 | } |
2201 | total_len = tmp; | 2275 | DEBUG(4, "ray_cs rx_data packet\n"); |
2202 | prcslink = prcs; | 2276 | /* If fragmented packet, verify sizes of fragments add up */ |
2203 | do { | 2277 | if (readb(&prcs->var.rx_packet.next_frag_rcs_index) != 0xFF) { |
2204 | tmp -= (readb(&prcslink->var.rx_packet.rx_data_length[0]) << 8) | 2278 | DEBUG(1, "ray_cs rx'ed fragment\n"); |
2205 | + readb(&prcslink->var.rx_packet.rx_data_length[1]); | 2279 | tmp = (readb(&prcs->var.rx_packet.totalpacketlength[0]) << 8) |
2206 | if (readb(&prcslink->var.rx_packet.next_frag_rcs_index) == 0xFF | 2280 | + readb(&prcs->var.rx_packet.totalpacketlength[1]); |
2207 | || tmp < 0) break; | 2281 | total_len = tmp; |
2208 | prcslink = rcs_base(local) | 2282 | prcslink = prcs; |
2209 | + readb(&prcslink->link_field); | 2283 | do { |
2210 | } while (1); | 2284 | tmp -= |
2211 | 2285 | (readb(&prcslink->var.rx_packet.rx_data_length[0]) | |
2212 | if (tmp < 0) | 2286 | << 8) |
2213 | { | 2287 | + readb(&prcslink->var.rx_packet.rx_data_length[1]); |
2214 | DEBUG(0,"ray_cs rx_data fragment lengths don't add up\n"); | 2288 | if (readb(&prcslink->var.rx_packet.next_frag_rcs_index) |
2215 | local->stats.rx_dropped++; | 2289 | == 0xFF || tmp < 0) |
2216 | release_frag_chain(local, prcs); | 2290 | break; |
2217 | return; | 2291 | prcslink = rcs_base(local) |
2218 | } | 2292 | + readb(&prcslink->link_field); |
2219 | } | 2293 | } while (1); |
2220 | else { /* Single unfragmented packet */ | 2294 | |
2221 | total_len = rx_len; | 2295 | if (tmp < 0) { |
2222 | } | 2296 | DEBUG(0, |
2223 | 2297 | "ray_cs rx_data fragment lengths don't add up\n"); | |
2224 | skb = dev_alloc_skb( total_len+5 ); | 2298 | local->stats.rx_dropped++; |
2225 | if (skb == NULL) | 2299 | release_frag_chain(local, prcs); |
2226 | { | 2300 | return; |
2227 | DEBUG(0,"ray_cs rx_data could not allocate skb\n"); | 2301 | } |
2228 | local->stats.rx_dropped++; | 2302 | } else { /* Single unfragmented packet */ |
2229 | if (readb(&prcs->var.rx_packet.next_frag_rcs_index) != 0xFF) | 2303 | total_len = rx_len; |
2230 | release_frag_chain(local, prcs); | 2304 | } |
2231 | return; | 2305 | |
2232 | } | 2306 | skb = dev_alloc_skb(total_len + 5); |
2233 | skb_reserve( skb, 2); /* Align IP on 16 byte (TBD check this)*/ | 2307 | if (skb == NULL) { |
2234 | 2308 | DEBUG(0, "ray_cs rx_data could not allocate skb\n"); | |
2235 | DEBUG(4,"ray_cs rx_data total_len = %x, rx_len = %x\n",total_len,rx_len); | 2309 | local->stats.rx_dropped++; |
2310 | if (readb(&prcs->var.rx_packet.next_frag_rcs_index) != 0xFF) | ||
2311 | release_frag_chain(local, prcs); | ||
2312 | return; | ||
2313 | } | ||
2314 | skb_reserve(skb, 2); /* Align IP on 16 byte (TBD check this) */ | ||
2315 | |||
2316 | DEBUG(4, "ray_cs rx_data total_len = %x, rx_len = %x\n", total_len, | ||
2317 | rx_len); | ||
2236 | 2318 | ||
2237 | /************************/ | 2319 | /************************/ |
2238 | /* Reserve enough room for the whole damn packet. */ | 2320 | /* Reserve enough room for the whole damn packet. */ |
2239 | rx_ptr = skb_put( skb, total_len); | 2321 | rx_ptr = skb_put(skb, total_len); |
2240 | /* Copy the whole packet to sk_buff */ | 2322 | /* Copy the whole packet to sk_buff */ |
2241 | rx_ptr += copy_from_rx_buff(local, rx_ptr, pkt_addr & RX_BUFF_END, rx_len); | 2323 | rx_ptr += |
2242 | /* Get source address */ | 2324 | copy_from_rx_buff(local, rx_ptr, pkt_addr & RX_BUFF_END, rx_len); |
2325 | /* Get source address */ | ||
2243 | #ifdef WIRELESS_SPY | 2326 | #ifdef WIRELESS_SPY |
2244 | skb_copy_from_linear_data_offset(skb, offsetof(struct mac_header, addr_2), | 2327 | skb_copy_from_linear_data_offset(skb, |
2245 | linksrcaddr, ETH_ALEN); | 2328 | offsetof(struct mac_header, addr_2), |
2329 | linksrcaddr, ETH_ALEN); | ||
2246 | #endif | 2330 | #endif |
2247 | /* Now, deal with encapsulation/translation/sniffer */ | 2331 | /* Now, deal with encapsulation/translation/sniffer */ |
2248 | if (!sniffer) { | 2332 | if (!sniffer) { |
2249 | if (!translate) { | 2333 | if (!translate) { |
2250 | /* Encapsulated ethernet, so just lop off 802.11 MAC header */ | 2334 | /* Encapsulated ethernet, so just lop off 802.11 MAC header */ |
2251 | /* TBD reserve skb_reserve( skb, RX_MAC_HEADER_LENGTH); */ | 2335 | /* TBD reserve skb_reserve( skb, RX_MAC_HEADER_LENGTH); */ |
2252 | skb_pull( skb, RX_MAC_HEADER_LENGTH); | 2336 | skb_pull(skb, RX_MAC_HEADER_LENGTH); |
2253 | } | 2337 | } else { |
2254 | else { | 2338 | /* Do translation */ |
2255 | /* Do translation */ | 2339 | untranslate(local, skb, total_len); |
2256 | untranslate(local, skb, total_len); | 2340 | } |
2257 | } | 2341 | } else { /* sniffer mode, so just pass whole packet */ |
2258 | } | 2342 | }; |
2259 | else | ||
2260 | { /* sniffer mode, so just pass whole packet */ }; | ||
2261 | 2343 | ||
2262 | /************************/ | 2344 | /************************/ |
2263 | /* Now pick up the rest of the fragments if any */ | 2345 | /* Now pick up the rest of the fragments if any */ |
2264 | tmp = 17; | 2346 | tmp = 17; |
2265 | if (readb(&prcs->var.rx_packet.next_frag_rcs_index) != 0xFF) { | 2347 | if (readb(&prcs->var.rx_packet.next_frag_rcs_index) != 0xFF) { |
2266 | prcslink = prcs; | 2348 | prcslink = prcs; |
2267 | DEBUG(1,"ray_cs rx_data in fragment loop\n"); | 2349 | DEBUG(1, "ray_cs rx_data in fragment loop\n"); |
2268 | do { | 2350 | do { |
2269 | prcslink = rcs_base(local) | 2351 | prcslink = rcs_base(local) |
2270 | + readb(&prcslink->var.rx_packet.next_frag_rcs_index); | 2352 | + |
2271 | rx_len = (( readb(&prcslink->var.rx_packet.rx_data_length[0]) << 8) | 2353 | readb(&prcslink->var.rx_packet.next_frag_rcs_index); |
2272 | + readb(&prcslink->var.rx_packet.rx_data_length[1])) | 2354 | rx_len = |
2273 | & RX_BUFF_END; | 2355 | ((readb(&prcslink->var.rx_packet.rx_data_length[0]) |
2274 | pkt_addr = (( readb(&prcslink->var.rx_packet.rx_data_ptr[0]) << 8) | 2356 | << 8) |
2275 | + readb(&prcslink->var.rx_packet.rx_data_ptr[1])) | 2357 | + |
2276 | & RX_BUFF_END; | 2358 | readb(&prcslink->var.rx_packet.rx_data_length[1])) |
2277 | 2359 | & RX_BUFF_END; | |
2278 | rx_ptr += copy_from_rx_buff(local, rx_ptr, pkt_addr, rx_len); | 2360 | pkt_addr = |
2279 | 2361 | ((readb(&prcslink->var.rx_packet.rx_data_ptr[0]) << | |
2280 | } while (tmp-- && | 2362 | 8) |
2281 | readb(&prcslink->var.rx_packet.next_frag_rcs_index) != 0xFF); | 2363 | + readb(&prcslink->var.rx_packet.rx_data_ptr[1])) |
2282 | release_frag_chain(local, prcs); | 2364 | & RX_BUFF_END; |
2283 | } | 2365 | |
2284 | 2366 | rx_ptr += | |
2285 | skb->protocol = eth_type_trans(skb,dev); | 2367 | copy_from_rx_buff(local, rx_ptr, pkt_addr, rx_len); |
2286 | netif_rx(skb); | 2368 | |
2287 | local->stats.rx_packets++; | 2369 | } while (tmp-- && |
2288 | local->stats.rx_bytes += total_len; | 2370 | readb(&prcslink->var.rx_packet.next_frag_rcs_index) != |
2289 | 2371 | 0xFF); | |
2290 | /* Gather signal strength per address */ | 2372 | release_frag_chain(local, prcs); |
2373 | } | ||
2374 | |||
2375 | skb->protocol = eth_type_trans(skb, dev); | ||
2376 | netif_rx(skb); | ||
2377 | local->stats.rx_packets++; | ||
2378 | local->stats.rx_bytes += total_len; | ||
2379 | |||
2380 | /* Gather signal strength per address */ | ||
2291 | #ifdef WIRELESS_SPY | 2381 | #ifdef WIRELESS_SPY |
2292 | /* For the Access Point or the node having started the ad-hoc net | 2382 | /* For the Access Point or the node having started the ad-hoc net |
2293 | * note : ad-hoc work only in some specific configurations, but we | 2383 | * note : ad-hoc work only in some specific configurations, but we |
2294 | * kludge in ray_get_wireless_stats... */ | 2384 | * kludge in ray_get_wireless_stats... */ |
2295 | if(!memcmp(linksrcaddr, local->bss_id, ETH_ALEN)) | 2385 | if (!memcmp(linksrcaddr, local->bss_id, ETH_ALEN)) { |
2296 | { | 2386 | /* Update statistics */ |
2297 | /* Update statistics */ | 2387 | /*local->wstats.qual.qual = none ? */ |
2298 | /*local->wstats.qual.qual = none ? */ | 2388 | local->wstats.qual.level = siglev; |
2299 | local->wstats.qual.level = siglev; | 2389 | /*local->wstats.qual.noise = none ? */ |
2300 | /*local->wstats.qual.noise = none ? */ | 2390 | local->wstats.qual.updated = 0x2; |
2301 | local->wstats.qual.updated = 0x2; | 2391 | } |
2302 | } | 2392 | /* Now, update the spy stuff */ |
2303 | /* Now, update the spy stuff */ | 2393 | { |
2304 | { | 2394 | struct iw_quality wstats; |
2305 | struct iw_quality wstats; | 2395 | wstats.level = siglev; |
2306 | wstats.level = siglev; | 2396 | /* wstats.noise = none ? */ |
2307 | /* wstats.noise = none ? */ | 2397 | /* wstats.qual = none ? */ |
2308 | /* wstats.qual = none ? */ | 2398 | wstats.updated = 0x2; |
2309 | wstats.updated = 0x2; | 2399 | /* Update spy records */ |
2310 | /* Update spy records */ | 2400 | wireless_spy_update(dev, linksrcaddr, &wstats); |
2311 | wireless_spy_update(dev, linksrcaddr, &wstats); | 2401 | } |
2312 | } | 2402 | #endif /* WIRELESS_SPY */ |
2313 | #endif /* WIRELESS_SPY */ | ||
2314 | } /* end rx_data */ | 2403 | } /* end rx_data */ |
2404 | |||
2315 | /*===========================================================================*/ | 2405 | /*===========================================================================*/ |
2316 | static void untranslate(ray_dev_t *local, struct sk_buff *skb, int len) | 2406 | static void untranslate(ray_dev_t *local, struct sk_buff *skb, int len) |
2317 | { | 2407 | { |
2318 | snaphdr_t *psnap = (snaphdr_t *)(skb->data + RX_MAC_HEADER_LENGTH); | 2408 | snaphdr_t *psnap = (snaphdr_t *) (skb->data + RX_MAC_HEADER_LENGTH); |
2319 | struct ieee80211_hdr *pmac = (struct ieee80211_hdr *)skb->data; | 2409 | struct ieee80211_hdr *pmac = (struct ieee80211_hdr *)skb->data; |
2320 | __be16 type = *(__be16 *)psnap->ethertype; | 2410 | __be16 type = *(__be16 *) psnap->ethertype; |
2321 | int delta; | 2411 | int delta; |
2322 | struct ethhdr *peth; | 2412 | struct ethhdr *peth; |
2323 | UCHAR srcaddr[ADDRLEN]; | 2413 | UCHAR srcaddr[ADDRLEN]; |
2324 | UCHAR destaddr[ADDRLEN]; | 2414 | UCHAR destaddr[ADDRLEN]; |
2325 | static UCHAR org_bridge[3] = {0, 0, 0xf8}; | 2415 | static UCHAR org_bridge[3] = { 0, 0, 0xf8 }; |
2326 | static UCHAR org_1042[3] = {0, 0, 0}; | 2416 | static UCHAR org_1042[3] = { 0, 0, 0 }; |
2327 | 2417 | ||
2328 | memcpy(destaddr, ieee80211_get_DA(pmac), ADDRLEN); | 2418 | memcpy(destaddr, ieee80211_get_DA(pmac), ADDRLEN); |
2329 | memcpy(srcaddr, ieee80211_get_SA(pmac), ADDRLEN); | 2419 | memcpy(srcaddr, ieee80211_get_SA(pmac), ADDRLEN); |
2330 | 2420 | ||
2331 | #ifdef PCMCIA_DEBUG | 2421 | #ifdef PCMCIA_DEBUG |
2332 | if (pc_debug > 3) { | 2422 | if (pc_debug > 3) { |
2333 | int i; | 2423 | int i; |
2334 | printk(KERN_DEBUG "skb->data before untranslate"); | 2424 | printk(KERN_DEBUG "skb->data before untranslate"); |
2335 | for (i=0;i<64;i++) | 2425 | for (i = 0; i < 64; i++) |
2336 | printk("%02x ",skb->data[i]); | 2426 | printk("%02x ", skb->data[i]); |
2337 | printk("\n" KERN_DEBUG "type = %08x, xsap = %02x%02x%02x, org = %02x02x02x\n", | 2427 | printk("\n" KERN_DEBUG |
2338 | ntohs(type), | 2428 | "type = %08x, xsap = %02x%02x%02x, org = %02x02x02x\n", |
2339 | psnap->dsap, psnap->ssap, psnap->ctrl, | 2429 | ntohs(type), psnap->dsap, psnap->ssap, psnap->ctrl, |
2340 | psnap->org[0], psnap->org[1], psnap->org[2]); | 2430 | psnap->org[0], psnap->org[1], psnap->org[2]); |
2341 | printk(KERN_DEBUG "untranslate skb->data = %p\n",skb->data); | 2431 | printk(KERN_DEBUG "untranslate skb->data = %p\n", skb->data); |
2342 | } | 2432 | } |
2343 | #endif | 2433 | #endif |
2344 | 2434 | ||
2345 | if (psnap->dsap != 0xaa || psnap->ssap != 0xaa || psnap->ctrl != 3) { | 2435 | if (psnap->dsap != 0xaa || psnap->ssap != 0xaa || psnap->ctrl != 3) { |
2346 | /* not a snap type so leave it alone */ | 2436 | /* not a snap type so leave it alone */ |
2347 | DEBUG(3,"ray_cs untranslate NOT SNAP %02x %02x %02x\n", | 2437 | DEBUG(3, "ray_cs untranslate NOT SNAP %02x %02x %02x\n", |
2348 | psnap->dsap, psnap->ssap, psnap->ctrl); | 2438 | psnap->dsap, psnap->ssap, psnap->ctrl); |
2349 | 2439 | ||
2350 | delta = RX_MAC_HEADER_LENGTH - ETH_HLEN; | 2440 | delta = RX_MAC_HEADER_LENGTH - ETH_HLEN; |
2351 | peth = (struct ethhdr *)(skb->data + delta); | 2441 | peth = (struct ethhdr *)(skb->data + delta); |
2352 | peth->h_proto = htons(len - RX_MAC_HEADER_LENGTH); | 2442 | peth->h_proto = htons(len - RX_MAC_HEADER_LENGTH); |
2353 | } | 2443 | } else { /* Its a SNAP */ |
2354 | else { /* Its a SNAP */ | 2444 | if (memcmp(psnap->org, org_bridge, 3) == 0) { |
2355 | if (memcmp(psnap->org, org_bridge, 3) == 0) { /* EtherII and nuke the LLC */ | 2445 | /* EtherII and nuke the LLC */ |
2356 | DEBUG(3,"ray_cs untranslate Bridge encap\n"); | 2446 | DEBUG(3, "ray_cs untranslate Bridge encap\n"); |
2357 | delta = RX_MAC_HEADER_LENGTH | 2447 | delta = RX_MAC_HEADER_LENGTH |
2358 | + sizeof(struct snaphdr_t) - ETH_HLEN; | 2448 | + sizeof(struct snaphdr_t) - ETH_HLEN; |
2359 | peth = (struct ethhdr *)(skb->data + delta); | 2449 | peth = (struct ethhdr *)(skb->data + delta); |
2360 | peth->h_proto = type; | 2450 | peth->h_proto = type; |
2361 | } else if (memcmp(psnap->org, org_1042, 3) == 0) { | 2451 | } else if (memcmp(psnap->org, org_1042, 3) == 0) { |
2362 | switch (ntohs(type)) { | 2452 | switch (ntohs(type)) { |
2363 | case ETH_P_IPX: | 2453 | case ETH_P_IPX: |
2364 | case ETH_P_AARP: | 2454 | case ETH_P_AARP: |
2365 | DEBUG(3,"ray_cs untranslate RFC IPX/AARP\n"); | 2455 | DEBUG(3, "ray_cs untranslate RFC IPX/AARP\n"); |
2366 | delta = RX_MAC_HEADER_LENGTH - ETH_HLEN; | 2456 | delta = RX_MAC_HEADER_LENGTH - ETH_HLEN; |
2367 | peth = (struct ethhdr *)(skb->data + delta); | 2457 | peth = (struct ethhdr *)(skb->data + delta); |
2368 | peth->h_proto = htons(len - RX_MAC_HEADER_LENGTH); | 2458 | peth->h_proto = |
2369 | break; | 2459 | htons(len - RX_MAC_HEADER_LENGTH); |
2370 | default: | 2460 | break; |
2371 | DEBUG(3,"ray_cs untranslate RFC default\n"); | 2461 | default: |
2372 | delta = RX_MAC_HEADER_LENGTH + | 2462 | DEBUG(3, "ray_cs untranslate RFC default\n"); |
2373 | sizeof(struct snaphdr_t) - ETH_HLEN; | 2463 | delta = RX_MAC_HEADER_LENGTH + |
2374 | peth = (struct ethhdr *)(skb->data + delta); | 2464 | sizeof(struct snaphdr_t) - ETH_HLEN; |
2375 | peth->h_proto = type; | 2465 | peth = (struct ethhdr *)(skb->data + delta); |
2376 | break; | 2466 | peth->h_proto = type; |
2377 | } | 2467 | break; |
2378 | } else { | 2468 | } |
2379 | printk("ray_cs untranslate very confused by packet\n"); | 2469 | } else { |
2380 | delta = RX_MAC_HEADER_LENGTH - ETH_HLEN; | 2470 | printk("ray_cs untranslate very confused by packet\n"); |
2381 | peth = (struct ethhdr *)(skb->data + delta); | 2471 | delta = RX_MAC_HEADER_LENGTH - ETH_HLEN; |
2382 | peth->h_proto = type; | 2472 | peth = (struct ethhdr *)(skb->data + delta); |
2473 | peth->h_proto = type; | ||
2474 | } | ||
2383 | } | 2475 | } |
2384 | } | ||
2385 | /* TBD reserve skb_reserve(skb, delta); */ | 2476 | /* TBD reserve skb_reserve(skb, delta); */ |
2386 | skb_pull(skb, delta); | 2477 | skb_pull(skb, delta); |
2387 | DEBUG(3,"untranslate after skb_pull(%d), skb->data = %p\n",delta,skb->data); | 2478 | DEBUG(3, "untranslate after skb_pull(%d), skb->data = %p\n", delta, |
2388 | memcpy(peth->h_dest, destaddr, ADDRLEN); | 2479 | skb->data); |
2389 | memcpy(peth->h_source, srcaddr, ADDRLEN); | 2480 | memcpy(peth->h_dest, destaddr, ADDRLEN); |
2481 | memcpy(peth->h_source, srcaddr, ADDRLEN); | ||
2390 | #ifdef PCMCIA_DEBUG | 2482 | #ifdef PCMCIA_DEBUG |
2391 | if (pc_debug > 3) { | 2483 | if (pc_debug > 3) { |
2392 | int i; | 2484 | int i; |
2393 | printk(KERN_DEBUG "skb->data after untranslate:"); | 2485 | printk(KERN_DEBUG "skb->data after untranslate:"); |
2394 | for (i=0;i<64;i++) | 2486 | for (i = 0; i < 64; i++) |
2395 | printk("%02x ",skb->data[i]); | 2487 | printk("%02x ", skb->data[i]); |
2396 | printk("\n"); | 2488 | printk("\n"); |
2397 | } | 2489 | } |
2398 | #endif | 2490 | #endif |
2399 | } /* end untranslate */ | 2491 | } /* end untranslate */ |
2492 | |||
2400 | /*===========================================================================*/ | 2493 | /*===========================================================================*/ |
2401 | /* Copy data from circular receive buffer to PC memory. | 2494 | /* Copy data from circular receive buffer to PC memory. |
2402 | * dest = destination address in PC memory | 2495 | * dest = destination address in PC memory |
2403 | * pkt_addr = source address in receive buffer | 2496 | * pkt_addr = source address in receive buffer |
2404 | * len = length of packet to copy | 2497 | * len = length of packet to copy |
2405 | */ | 2498 | */ |
2406 | static int copy_from_rx_buff(ray_dev_t *local, UCHAR *dest, int pkt_addr, int length) | 2499 | static int copy_from_rx_buff(ray_dev_t *local, UCHAR *dest, int pkt_addr, |
2407 | { | 2500 | int length) |
2408 | int wrap_bytes = (pkt_addr + length) - (RX_BUFF_END + 1); | 2501 | { |
2409 | if (wrap_bytes <= 0) | 2502 | int wrap_bytes = (pkt_addr + length) - (RX_BUFF_END + 1); |
2410 | { | 2503 | if (wrap_bytes <= 0) { |
2411 | memcpy_fromio(dest,local->rmem + pkt_addr,length); | 2504 | memcpy_fromio(dest, local->rmem + pkt_addr, length); |
2412 | } | 2505 | } else { /* Packet wrapped in circular buffer */ |
2413 | else /* Packet wrapped in circular buffer */ | 2506 | |
2414 | { | 2507 | memcpy_fromio(dest, local->rmem + pkt_addr, |
2415 | memcpy_fromio(dest,local->rmem+pkt_addr,length - wrap_bytes); | 2508 | length - wrap_bytes); |
2416 | memcpy_fromio(dest + length - wrap_bytes, local->rmem, wrap_bytes); | 2509 | memcpy_fromio(dest + length - wrap_bytes, local->rmem, |
2417 | } | 2510 | wrap_bytes); |
2418 | return length; | 2511 | } |
2512 | return length; | ||
2419 | } | 2513 | } |
2514 | |||
2420 | /*===========================================================================*/ | 2515 | /*===========================================================================*/ |
2421 | static void release_frag_chain(ray_dev_t *local, struct rcs __iomem * prcs) | 2516 | static void release_frag_chain(ray_dev_t *local, struct rcs __iomem *prcs) |
2422 | { | 2517 | { |
2423 | struct rcs __iomem *prcslink = prcs; | 2518 | struct rcs __iomem *prcslink = prcs; |
2424 | int tmp = 17; | 2519 | int tmp = 17; |
2425 | unsigned rcsindex = readb(&prcs->var.rx_packet.next_frag_rcs_index); | 2520 | unsigned rcsindex = readb(&prcs->var.rx_packet.next_frag_rcs_index); |
2426 | 2521 | ||
2427 | while (tmp--) { | 2522 | while (tmp--) { |
2428 | writeb(CCS_BUFFER_FREE, &prcslink->buffer_status); | 2523 | writeb(CCS_BUFFER_FREE, &prcslink->buffer_status); |
2429 | if (rcsindex >= (NUMBER_OF_CCS + NUMBER_OF_RCS)) { | 2524 | if (rcsindex >= (NUMBER_OF_CCS + NUMBER_OF_RCS)) { |
2430 | DEBUG(1,"ray_cs interrupt bad rcsindex = 0x%x\n",rcsindex); | 2525 | DEBUG(1, "ray_cs interrupt bad rcsindex = 0x%x\n", |
2431 | break; | 2526 | rcsindex); |
2432 | } | 2527 | break; |
2433 | prcslink = rcs_base(local) + rcsindex; | 2528 | } |
2434 | rcsindex = readb(&prcslink->var.rx_packet.next_frag_rcs_index); | 2529 | prcslink = rcs_base(local) + rcsindex; |
2435 | } | 2530 | rcsindex = readb(&prcslink->var.rx_packet.next_frag_rcs_index); |
2436 | writeb(CCS_BUFFER_FREE, &prcslink->buffer_status); | 2531 | } |
2532 | writeb(CCS_BUFFER_FREE, &prcslink->buffer_status); | ||
2437 | } | 2533 | } |
2534 | |||
2438 | /*===========================================================================*/ | 2535 | /*===========================================================================*/ |
2439 | static void authenticate(ray_dev_t *local) | 2536 | static void authenticate(ray_dev_t *local) |
2440 | { | 2537 | { |
2441 | struct pcmcia_device *link = local->finder; | 2538 | struct pcmcia_device *link = local->finder; |
2442 | DEBUG(0,"ray_cs Starting authentication.\n"); | 2539 | DEBUG(0, "ray_cs Starting authentication.\n"); |
2443 | if (!(pcmcia_dev_present(link))) { | 2540 | if (!(pcmcia_dev_present(link))) { |
2444 | DEBUG(2,"ray_cs authenticate - device not present\n"); | 2541 | DEBUG(2, "ray_cs authenticate - device not present\n"); |
2445 | return; | 2542 | return; |
2446 | } | 2543 | } |
2447 | 2544 | ||
2448 | del_timer(&local->timer); | 2545 | del_timer(&local->timer); |
2449 | if (build_auth_frame(local, local->bss_id, OPEN_AUTH_REQUEST)) { | 2546 | if (build_auth_frame(local, local->bss_id, OPEN_AUTH_REQUEST)) { |
2450 | local->timer.function = &join_net; | 2547 | local->timer.function = &join_net; |
2451 | } | 2548 | } else { |
2452 | else { | 2549 | local->timer.function = &authenticate_timeout; |
2453 | local->timer.function = &authenticate_timeout; | 2550 | } |
2454 | } | 2551 | local->timer.expires = jiffies + HZ * 2; |
2455 | local->timer.expires = jiffies + HZ*2; | 2552 | local->timer.data = (long)local; |
2456 | local->timer.data = (long)local; | 2553 | add_timer(&local->timer); |
2457 | add_timer(&local->timer); | 2554 | local->authentication_state = AWAITING_RESPONSE; |
2458 | local->authentication_state = AWAITING_RESPONSE; | ||
2459 | } /* end authenticate */ | 2555 | } /* end authenticate */ |
2556 | |||
2460 | /*===========================================================================*/ | 2557 | /*===========================================================================*/ |
2461 | static void rx_authenticate(ray_dev_t *local, struct rcs __iomem *prcs, | 2558 | static void rx_authenticate(ray_dev_t *local, struct rcs __iomem *prcs, |
2462 | unsigned int pkt_addr, int rx_len) | 2559 | unsigned int pkt_addr, int rx_len) |
2463 | { | 2560 | { |
2464 | UCHAR buff[256]; | 2561 | UCHAR buff[256]; |
2465 | struct rx_msg *msg = (struct rx_msg *)buff; | 2562 | struct rx_msg *msg = (struct rx_msg *)buff; |
2466 | 2563 | ||
2467 | del_timer(&local->timer); | 2564 | del_timer(&local->timer); |
2468 | 2565 | ||
2469 | copy_from_rx_buff(local, buff, pkt_addr, rx_len & 0xff); | 2566 | copy_from_rx_buff(local, buff, pkt_addr, rx_len & 0xff); |
2470 | /* if we are trying to get authenticated */ | 2567 | /* if we are trying to get authenticated */ |
2471 | if (local->sparm.b4.a_network_type == ADHOC) { | 2568 | if (local->sparm.b4.a_network_type == ADHOC) { |
2472 | DEBUG(1,"ray_cs rx_auth var= %02x %02x %02x %02x %02x %02x\n", msg->var[0],msg->var[1],msg->var[2],msg->var[3],msg->var[4],msg->var[5]); | 2569 | DEBUG(1, "ray_cs rx_auth var= %02x %02x %02x %02x %02x %02x\n", |
2473 | if (msg->var[2] == 1) { | 2570 | msg->var[0], msg->var[1], msg->var[2], msg->var[3], |
2474 | DEBUG(0,"ray_cs Sending authentication response.\n"); | 2571 | msg->var[4], msg->var[5]); |
2475 | if (!build_auth_frame (local, msg->mac.addr_2, OPEN_AUTH_RESPONSE)) { | 2572 | if (msg->var[2] == 1) { |
2476 | local->authentication_state = NEED_TO_AUTH; | 2573 | DEBUG(0, "ray_cs Sending authentication response.\n"); |
2477 | memcpy(local->auth_id, msg->mac.addr_2, ADDRLEN); | 2574 | if (!build_auth_frame |
2478 | } | 2575 | (local, msg->mac.addr_2, OPEN_AUTH_RESPONSE)) { |
2479 | } | 2576 | local->authentication_state = NEED_TO_AUTH; |
2480 | } | 2577 | memcpy(local->auth_id, msg->mac.addr_2, |
2481 | else /* Infrastructure network */ | 2578 | ADDRLEN); |
2482 | { | 2579 | } |
2483 | if (local->authentication_state == AWAITING_RESPONSE) { | 2580 | } |
2484 | /* Verify authentication sequence #2 and success */ | 2581 | } else { /* Infrastructure network */ |
2485 | if (msg->var[2] == 2) { | 2582 | |
2486 | if ((msg->var[3] | msg->var[4]) == 0) { | 2583 | if (local->authentication_state == AWAITING_RESPONSE) { |
2487 | DEBUG(1,"Authentication successful\n"); | 2584 | /* Verify authentication sequence #2 and success */ |
2488 | local->card_status = CARD_AUTH_COMPLETE; | 2585 | if (msg->var[2] == 2) { |
2489 | associate(local); | 2586 | if ((msg->var[3] | msg->var[4]) == 0) { |
2490 | local->authentication_state = AUTHENTICATED; | 2587 | DEBUG(1, "Authentication successful\n"); |
2491 | } | 2588 | local->card_status = CARD_AUTH_COMPLETE; |
2492 | else { | 2589 | associate(local); |
2493 | DEBUG(0,"Authentication refused\n"); | 2590 | local->authentication_state = |
2494 | local->card_status = CARD_AUTH_REFUSED; | 2591 | AUTHENTICATED; |
2495 | join_net((u_long)local); | 2592 | } else { |
2496 | local->authentication_state = UNAUTHENTICATED; | 2593 | DEBUG(0, "Authentication refused\n"); |
2497 | } | 2594 | local->card_status = CARD_AUTH_REFUSED; |
2498 | } | 2595 | join_net((u_long) local); |
2499 | } | 2596 | local->authentication_state = |
2500 | } | 2597 | UNAUTHENTICATED; |
2598 | } | ||
2599 | } | ||
2600 | } | ||
2601 | } | ||
2501 | 2602 | ||
2502 | } /* end rx_authenticate */ | 2603 | } /* end rx_authenticate */ |
2604 | |||
2503 | /*===========================================================================*/ | 2605 | /*===========================================================================*/ |
2504 | static void associate(ray_dev_t *local) | 2606 | static void associate(ray_dev_t *local) |
2505 | { | 2607 | { |
2506 | struct ccs __iomem *pccs; | 2608 | struct ccs __iomem *pccs; |
2507 | struct pcmcia_device *link = local->finder; | 2609 | struct pcmcia_device *link = local->finder; |
2508 | struct net_device *dev = link->priv; | 2610 | struct net_device *dev = link->priv; |
2509 | int ccsindex; | 2611 | int ccsindex; |
2510 | if (!(pcmcia_dev_present(link))) { | 2612 | if (!(pcmcia_dev_present(link))) { |
2511 | DEBUG(2,"ray_cs associate - device not present\n"); | 2613 | DEBUG(2, "ray_cs associate - device not present\n"); |
2512 | return; | 2614 | return; |
2513 | } | 2615 | } |
2514 | /* If no tx buffers available, return*/ | 2616 | /* If no tx buffers available, return */ |
2515 | if ((ccsindex = get_free_ccs(local)) < 0) | 2617 | if ((ccsindex = get_free_ccs(local)) < 0) { |
2516 | { | ||
2517 | /* TBD should never be here but... what if we are? */ | 2618 | /* TBD should never be here but... what if we are? */ |
2518 | DEBUG(1,"ray_cs associate - No free ccs\n"); | 2619 | DEBUG(1, "ray_cs associate - No free ccs\n"); |
2519 | return; | 2620 | return; |
2520 | } | 2621 | } |
2521 | DEBUG(1,"ray_cs Starting association with access point\n"); | 2622 | DEBUG(1, "ray_cs Starting association with access point\n"); |
2522 | pccs = ccs_base(local) + ccsindex; | 2623 | pccs = ccs_base(local) + ccsindex; |
2523 | /* fill in the CCS */ | 2624 | /* fill in the CCS */ |
2524 | writeb(CCS_START_ASSOCIATION, &pccs->cmd); | 2625 | writeb(CCS_START_ASSOCIATION, &pccs->cmd); |
2525 | /* Interrupt the firmware to process the command */ | 2626 | /* Interrupt the firmware to process the command */ |
2526 | if (interrupt_ecf(local, ccsindex)) { | 2627 | if (interrupt_ecf(local, ccsindex)) { |
2527 | DEBUG(1,"ray_cs associate failed - ECF not ready for intr\n"); | 2628 | DEBUG(1, "ray_cs associate failed - ECF not ready for intr\n"); |
2528 | writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); | 2629 | writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); |
2529 | 2630 | ||
2530 | del_timer(&local->timer); | 2631 | del_timer(&local->timer); |
2531 | local->timer.expires = jiffies + HZ*2; | 2632 | local->timer.expires = jiffies + HZ * 2; |
2532 | local->timer.data = (long)local; | 2633 | local->timer.data = (long)local; |
2533 | local->timer.function = &join_net; | 2634 | local->timer.function = &join_net; |
2534 | add_timer(&local->timer); | 2635 | add_timer(&local->timer); |
2535 | local->card_status = CARD_ASSOC_FAILED; | 2636 | local->card_status = CARD_ASSOC_FAILED; |
2536 | return; | 2637 | return; |
2537 | } | 2638 | } |
2538 | if (!sniffer) netif_start_queue(dev); | 2639 | if (!sniffer) |
2640 | netif_start_queue(dev); | ||
2539 | 2641 | ||
2540 | } /* end associate */ | 2642 | } /* end associate */ |
2643 | |||
2541 | /*===========================================================================*/ | 2644 | /*===========================================================================*/ |
2542 | static void rx_deauthenticate(ray_dev_t *local, struct rcs __iomem *prcs, | 2645 | static void rx_deauthenticate(ray_dev_t *local, struct rcs __iomem *prcs, |
2543 | unsigned int pkt_addr, int rx_len) | 2646 | unsigned int pkt_addr, int rx_len) |
2544 | { | 2647 | { |
2545 | /* UCHAR buff[256]; | 2648 | /* UCHAR buff[256]; |
2546 | struct rx_msg *msg = (struct rx_msg *)buff; | 2649 | struct rx_msg *msg = (struct rx_msg *)buff; |
2547 | */ | 2650 | */ |
2548 | DEBUG(0,"Deauthentication frame received\n"); | 2651 | DEBUG(0, "Deauthentication frame received\n"); |
2549 | local->authentication_state = UNAUTHENTICATED; | 2652 | local->authentication_state = UNAUTHENTICATED; |
2550 | /* Need to reauthenticate or rejoin depending on reason code */ | 2653 | /* Need to reauthenticate or rejoin depending on reason code */ |
2551 | /* copy_from_rx_buff(local, buff, pkt_addr, rx_len & 0xff); | 2654 | /* copy_from_rx_buff(local, buff, pkt_addr, rx_len & 0xff); |
2552 | */ | 2655 | */ |
2553 | } | 2656 | } |
2657 | |||
2554 | /*===========================================================================*/ | 2658 | /*===========================================================================*/ |
2555 | static void clear_interrupt(ray_dev_t *local) | 2659 | static void clear_interrupt(ray_dev_t *local) |
2556 | { | 2660 | { |
2557 | writeb(0, local->amem + CIS_OFFSET + HCS_INTR_OFFSET); | 2661 | writeb(0, local->amem + CIS_OFFSET + HCS_INTR_OFFSET); |
2558 | } | 2662 | } |
2663 | |||
2559 | /*===========================================================================*/ | 2664 | /*===========================================================================*/ |
2560 | #ifdef CONFIG_PROC_FS | 2665 | #ifdef CONFIG_PROC_FS |
2561 | #define MAXDATA (PAGE_SIZE - 80) | 2666 | #define MAXDATA (PAGE_SIZE - 80) |
2562 | 2667 | ||
2563 | static char *card_status[] = { | 2668 | static char *card_status[] = { |
2564 | "Card inserted - uninitialized", /* 0 */ | 2669 | "Card inserted - uninitialized", /* 0 */ |
2565 | "Card not downloaded", /* 1 */ | 2670 | "Card not downloaded", /* 1 */ |
2566 | "Waiting for download parameters", /* 2 */ | 2671 | "Waiting for download parameters", /* 2 */ |
2567 | "Card doing acquisition", /* 3 */ | 2672 | "Card doing acquisition", /* 3 */ |
2568 | "Acquisition complete", /* 4 */ | 2673 | "Acquisition complete", /* 4 */ |
2569 | "Authentication complete", /* 5 */ | 2674 | "Authentication complete", /* 5 */ |
2570 | "Association complete", /* 6 */ | 2675 | "Association complete", /* 6 */ |
2571 | "???", "???", "???", "???", /* 7 8 9 10 undefined */ | 2676 | "???", "???", "???", "???", /* 7 8 9 10 undefined */ |
2572 | "Card init error", /* 11 */ | 2677 | "Card init error", /* 11 */ |
2573 | "Download parameters error", /* 12 */ | 2678 | "Download parameters error", /* 12 */ |
2574 | "???", /* 13 */ | 2679 | "???", /* 13 */ |
2575 | "Acquisition failed", /* 14 */ | 2680 | "Acquisition failed", /* 14 */ |
2576 | "Authentication refused", /* 15 */ | 2681 | "Authentication refused", /* 15 */ |
2577 | "Association failed" /* 16 */ | 2682 | "Association failed" /* 16 */ |
2578 | }; | 2683 | }; |
2579 | 2684 | ||
2580 | static char *nettype[] = {"Adhoc", "Infra "}; | 2685 | static char *nettype[] = { "Adhoc", "Infra " }; |
2581 | static char *framing[] = {"Encapsulation", "Translation"} | 2686 | static char *framing[] = { "Encapsulation", "Translation" } |
2687 | |||
2582 | ; | 2688 | ; |
2583 | /*===========================================================================*/ | 2689 | /*===========================================================================*/ |
2584 | static int ray_cs_proc_show(struct seq_file *m, void *v) | 2690 | static int ray_cs_proc_show(struct seq_file *m, void *v) |
2585 | { | 2691 | { |
2586 | /* Print current values which are not available via other means | 2692 | /* Print current values which are not available via other means |
2587 | * eg ifconfig | 2693 | * eg ifconfig |
2588 | */ | 2694 | */ |
2589 | int i; | 2695 | int i; |
2590 | struct pcmcia_device *link; | 2696 | struct pcmcia_device *link; |
2591 | struct net_device *dev; | 2697 | struct net_device *dev; |
2592 | ray_dev_t *local; | 2698 | ray_dev_t *local; |
2593 | UCHAR *p; | 2699 | UCHAR *p; |
2594 | struct freq_hop_element *pfh; | 2700 | struct freq_hop_element *pfh; |
2595 | UCHAR c[33]; | 2701 | UCHAR c[33]; |
2596 | 2702 | ||
2597 | link = this_device; | 2703 | link = this_device; |
2598 | if (!link) | 2704 | if (!link) |
2599 | return 0; | 2705 | return 0; |
2600 | dev = (struct net_device *)link->priv; | 2706 | dev = (struct net_device *)link->priv; |
2601 | if (!dev) | 2707 | if (!dev) |
2602 | return 0; | 2708 | return 0; |
2603 | local = netdev_priv(dev); | 2709 | local = netdev_priv(dev); |
2604 | if (!local) | 2710 | if (!local) |
2605 | return 0; | 2711 | return 0; |
2606 | 2712 | ||
2607 | seq_puts(m, "Raylink Wireless LAN driver status\n"); | 2713 | seq_puts(m, "Raylink Wireless LAN driver status\n"); |
2608 | seq_printf(m, "%s\n", rcsid); | 2714 | seq_printf(m, "%s\n", rcsid); |
2609 | /* build 4 does not report version, and field is 0x55 after memtest */ | 2715 | /* build 4 does not report version, and field is 0x55 after memtest */ |
2610 | seq_puts(m, "Firmware version = "); | 2716 | seq_puts(m, "Firmware version = "); |
2611 | if (local->fw_ver == 0x55) | 2717 | if (local->fw_ver == 0x55) |
2612 | seq_puts(m, "4 - Use dump_cis for more details\n"); | 2718 | seq_puts(m, "4 - Use dump_cis for more details\n"); |
2613 | else | 2719 | else |
2614 | seq_printf(m, "%2d.%02d.%02d\n", | 2720 | seq_printf(m, "%2d.%02d.%02d\n", |
2615 | local->fw_ver, local->fw_bld, local->fw_var); | 2721 | local->fw_ver, local->fw_bld, local->fw_var); |
2616 | 2722 | ||
2617 | for (i=0; i<32; i++) c[i] = local->sparm.b5.a_current_ess_id[i]; | 2723 | for (i = 0; i < 32; i++) |
2618 | c[32] = 0; | 2724 | c[i] = local->sparm.b5.a_current_ess_id[i]; |
2619 | seq_printf(m, "%s network ESSID = \"%s\"\n", | 2725 | c[32] = 0; |
2620 | nettype[local->sparm.b5.a_network_type], c); | 2726 | seq_printf(m, "%s network ESSID = \"%s\"\n", |
2621 | 2727 | nettype[local->sparm.b5.a_network_type], c); | |
2622 | p = local->bss_id; | 2728 | |
2623 | seq_printf(m, "BSSID = %pM\n", p); | 2729 | p = local->bss_id; |
2624 | 2730 | seq_printf(m, "BSSID = %pM\n", p); | |
2625 | seq_printf(m, "Country code = %d\n", | 2731 | |
2626 | local->sparm.b5.a_curr_country_code); | 2732 | seq_printf(m, "Country code = %d\n", |
2627 | 2733 | local->sparm.b5.a_curr_country_code); | |
2628 | i = local->card_status; | 2734 | |
2629 | if (i < 0) i = 10; | 2735 | i = local->card_status; |
2630 | if (i > 16) i = 10; | 2736 | if (i < 0) |
2631 | seq_printf(m, "Card status = %s\n", card_status[i]); | 2737 | i = 10; |
2632 | 2738 | if (i > 16) | |
2633 | seq_printf(m, "Framing mode = %s\n",framing[translate]); | 2739 | i = 10; |
2634 | 2740 | seq_printf(m, "Card status = %s\n", card_status[i]); | |
2635 | seq_printf(m, "Last pkt signal lvl = %d\n", local->last_rsl); | 2741 | |
2636 | 2742 | seq_printf(m, "Framing mode = %s\n", framing[translate]); | |
2637 | if (local->beacon_rxed) { | 2743 | |
2638 | /* Pull some fields out of last beacon received */ | 2744 | seq_printf(m, "Last pkt signal lvl = %d\n", local->last_rsl); |
2639 | seq_printf(m, "Beacon Interval = %d Kus\n", | 2745 | |
2640 | local->last_bcn.beacon_intvl[0] | 2746 | if (local->beacon_rxed) { |
2641 | + 256 * local->last_bcn.beacon_intvl[1]); | 2747 | /* Pull some fields out of last beacon received */ |
2642 | 2748 | seq_printf(m, "Beacon Interval = %d Kus\n", | |
2643 | p = local->last_bcn.elements; | 2749 | local->last_bcn.beacon_intvl[0] |
2644 | if (p[0] == C_ESSID_ELEMENT_ID) p += p[1] + 2; | 2750 | + 256 * local->last_bcn.beacon_intvl[1]); |
2645 | else { | 2751 | |
2646 | seq_printf(m, "Parse beacon failed at essid element id = %d\n",p[0]); | 2752 | p = local->last_bcn.elements; |
2647 | return 0; | 2753 | if (p[0] == C_ESSID_ELEMENT_ID) |
2648 | } | 2754 | p += p[1] + 2; |
2649 | 2755 | else { | |
2650 | if (p[0] == C_SUPPORTED_RATES_ELEMENT_ID) { | 2756 | seq_printf(m, |
2651 | seq_puts(m, "Supported rate codes = "); | 2757 | "Parse beacon failed at essid element id = %d\n", |
2652 | for (i=2; i<p[1] + 2; i++) | 2758 | p[0]); |
2653 | seq_printf(m, "0x%02x ", p[i]); | 2759 | return 0; |
2654 | seq_putc(m, '\n'); | 2760 | } |
2655 | p += p[1] + 2; | 2761 | |
2656 | } | 2762 | if (p[0] == C_SUPPORTED_RATES_ELEMENT_ID) { |
2657 | else { | 2763 | seq_puts(m, "Supported rate codes = "); |
2658 | seq_puts(m, "Parse beacon failed at rates element\n"); | 2764 | for (i = 2; i < p[1] + 2; i++) |
2659 | return 0; | 2765 | seq_printf(m, "0x%02x ", p[i]); |
2660 | } | 2766 | seq_putc(m, '\n'); |
2661 | 2767 | p += p[1] + 2; | |
2662 | if (p[0] == C_FH_PARAM_SET_ELEMENT_ID) { | 2768 | } else { |
2663 | pfh = (struct freq_hop_element *)p; | 2769 | seq_puts(m, "Parse beacon failed at rates element\n"); |
2664 | seq_printf(m, "Hop dwell = %d Kus\n", | 2770 | return 0; |
2665 | pfh->dwell_time[0] + 256 * pfh->dwell_time[1]); | 2771 | } |
2666 | seq_printf(m, "Hop set = %d \n", pfh->hop_set); | 2772 | |
2667 | seq_printf(m, "Hop pattern = %d \n", pfh->hop_pattern); | 2773 | if (p[0] == C_FH_PARAM_SET_ELEMENT_ID) { |
2668 | seq_printf(m, "Hop index = %d \n", pfh->hop_index); | 2774 | pfh = (struct freq_hop_element *)p; |
2669 | p += p[1] + 2; | 2775 | seq_printf(m, "Hop dwell = %d Kus\n", |
2670 | } | 2776 | pfh->dwell_time[0] + |
2671 | else { | 2777 | 256 * pfh->dwell_time[1]); |
2672 | seq_puts(m, "Parse beacon failed at FH param element\n"); | 2778 | seq_printf(m, "Hop set = %d \n", |
2673 | return 0; | 2779 | pfh->hop_set); |
2780 | seq_printf(m, "Hop pattern = %d \n", | ||
2781 | pfh->hop_pattern); | ||
2782 | seq_printf(m, "Hop index = %d \n", | ||
2783 | pfh->hop_index); | ||
2784 | p += p[1] + 2; | ||
2785 | } else { | ||
2786 | seq_puts(m, | ||
2787 | "Parse beacon failed at FH param element\n"); | ||
2788 | return 0; | ||
2789 | } | ||
2790 | } else { | ||
2791 | seq_puts(m, "No beacons received\n"); | ||
2674 | } | 2792 | } |
2675 | } else { | 2793 | return 0; |
2676 | seq_puts(m, "No beacons received\n"); | ||
2677 | } | ||
2678 | return 0; | ||
2679 | } | 2794 | } |
2680 | 2795 | ||
2681 | static int ray_cs_proc_open(struct inode *inode, struct file *file) | 2796 | static int ray_cs_proc_open(struct inode *inode, struct file *file) |
@@ -2684,74 +2799,77 @@ static int ray_cs_proc_open(struct inode *inode, struct file *file) | |||
2684 | } | 2799 | } |
2685 | 2800 | ||
2686 | static const struct file_operations ray_cs_proc_fops = { | 2801 | static const struct file_operations ray_cs_proc_fops = { |
2687 | .owner = THIS_MODULE, | 2802 | .owner = THIS_MODULE, |
2688 | .open = ray_cs_proc_open, | 2803 | .open = ray_cs_proc_open, |
2689 | .read = seq_read, | 2804 | .read = seq_read, |
2690 | .llseek = seq_lseek, | 2805 | .llseek = seq_lseek, |
2691 | .release = single_release, | 2806 | .release = single_release, |
2692 | }; | 2807 | }; |
2693 | #endif | 2808 | #endif |
2694 | /*===========================================================================*/ | 2809 | /*===========================================================================*/ |
2695 | static int build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type) | 2810 | static int build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type) |
2696 | { | 2811 | { |
2697 | int addr; | 2812 | int addr; |
2698 | struct ccs __iomem *pccs; | 2813 | struct ccs __iomem *pccs; |
2699 | struct tx_msg __iomem *ptx; | 2814 | struct tx_msg __iomem *ptx; |
2700 | int ccsindex; | 2815 | int ccsindex; |
2701 | 2816 | ||
2702 | /* If no tx buffers available, return */ | 2817 | /* If no tx buffers available, return */ |
2703 | if ((ccsindex = get_free_tx_ccs(local)) < 0) | 2818 | if ((ccsindex = get_free_tx_ccs(local)) < 0) { |
2704 | { | 2819 | DEBUG(1, "ray_cs send authenticate - No free tx ccs\n"); |
2705 | DEBUG(1,"ray_cs send authenticate - No free tx ccs\n"); | 2820 | return -1; |
2706 | return -1; | 2821 | } |
2707 | } | 2822 | |
2708 | 2823 | pccs = ccs_base(local) + ccsindex; | |
2709 | pccs = ccs_base(local) + ccsindex; | 2824 | |
2710 | 2825 | /* Address in card space */ | |
2711 | /* Address in card space */ | 2826 | addr = TX_BUF_BASE + (ccsindex << 11); |
2712 | addr = TX_BUF_BASE + (ccsindex << 11); | 2827 | /* fill in the CCS */ |
2713 | /* fill in the CCS */ | 2828 | writeb(CCS_TX_REQUEST, &pccs->cmd); |
2714 | writeb(CCS_TX_REQUEST, &pccs->cmd); | 2829 | writeb(addr >> 8, pccs->var.tx_request.tx_data_ptr); |
2715 | writeb(addr >> 8, pccs->var.tx_request.tx_data_ptr); | 2830 | writeb(0x20, pccs->var.tx_request.tx_data_ptr + 1); |
2716 | writeb(0x20, pccs->var.tx_request.tx_data_ptr + 1); | 2831 | writeb(TX_AUTHENTICATE_LENGTH_MSB, pccs->var.tx_request.tx_data_length); |
2717 | writeb(TX_AUTHENTICATE_LENGTH_MSB, pccs->var.tx_request.tx_data_length); | 2832 | writeb(TX_AUTHENTICATE_LENGTH_LSB, |
2718 | writeb(TX_AUTHENTICATE_LENGTH_LSB,pccs->var.tx_request.tx_data_length + 1); | 2833 | pccs->var.tx_request.tx_data_length + 1); |
2719 | writeb(0, &pccs->var.tx_request.pow_sav_mode); | 2834 | writeb(0, &pccs->var.tx_request.pow_sav_mode); |
2720 | 2835 | ||
2721 | ptx = local->sram + addr; | 2836 | ptx = local->sram + addr; |
2722 | /* fill in the mac header */ | 2837 | /* fill in the mac header */ |
2723 | writeb(PROTOCOL_VER | AUTHENTIC_TYPE, &ptx->mac.frame_ctl_1); | 2838 | writeb(PROTOCOL_VER | AUTHENTIC_TYPE, &ptx->mac.frame_ctl_1); |
2724 | writeb(0, &ptx->mac.frame_ctl_2); | 2839 | writeb(0, &ptx->mac.frame_ctl_2); |
2725 | 2840 | ||
2726 | memcpy_toio(ptx->mac.addr_1, dest, ADDRLEN); | 2841 | memcpy_toio(ptx->mac.addr_1, dest, ADDRLEN); |
2727 | memcpy_toio(ptx->mac.addr_2, local->sparm.b4.a_mac_addr, ADDRLEN); | 2842 | memcpy_toio(ptx->mac.addr_2, local->sparm.b4.a_mac_addr, ADDRLEN); |
2728 | memcpy_toio(ptx->mac.addr_3, local->bss_id, ADDRLEN); | 2843 | memcpy_toio(ptx->mac.addr_3, local->bss_id, ADDRLEN); |
2729 | 2844 | ||
2730 | /* Fill in msg body with protocol 00 00, sequence 01 00 ,status 00 00 */ | 2845 | /* Fill in msg body with protocol 00 00, sequence 01 00 ,status 00 00 */ |
2731 | memset_io(ptx->var, 0, 6); | 2846 | memset_io(ptx->var, 0, 6); |
2732 | writeb(auth_type & 0xff, ptx->var + 2); | 2847 | writeb(auth_type & 0xff, ptx->var + 2); |
2733 | 2848 | ||
2734 | /* Interrupt the firmware to process the command */ | 2849 | /* Interrupt the firmware to process the command */ |
2735 | if (interrupt_ecf(local, ccsindex)) { | 2850 | if (interrupt_ecf(local, ccsindex)) { |
2736 | DEBUG(1,"ray_cs send authentication request failed - ECF not ready for intr\n"); | 2851 | DEBUG(1, |
2737 | writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); | 2852 | "ray_cs send authentication request failed - ECF not ready for intr\n"); |
2738 | return -1; | 2853 | writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); |
2739 | } | 2854 | return -1; |
2740 | return 0; | 2855 | } |
2856 | return 0; | ||
2741 | } /* End build_auth_frame */ | 2857 | } /* End build_auth_frame */ |
2742 | 2858 | ||
2743 | /*===========================================================================*/ | 2859 | /*===========================================================================*/ |
2744 | #ifdef CONFIG_PROC_FS | 2860 | #ifdef CONFIG_PROC_FS |
2745 | static void raycs_write(const char *name, write_proc_t *w, void *data) | 2861 | static void raycs_write(const char *name, write_proc_t *w, void *data) |
2746 | { | 2862 | { |
2747 | struct proc_dir_entry * entry = create_proc_entry(name, S_IFREG | S_IWUSR, NULL); | 2863 | struct proc_dir_entry *entry = |
2864 | create_proc_entry(name, S_IFREG | S_IWUSR, NULL); | ||
2748 | if (entry) { | 2865 | if (entry) { |
2749 | entry->write_proc = w; | 2866 | entry->write_proc = w; |
2750 | entry->data = data; | 2867 | entry->data = data; |
2751 | } | 2868 | } |
2752 | } | 2869 | } |
2753 | 2870 | ||
2754 | static int write_essid(struct file *file, const char __user *buffer, unsigned long count, void *data) | 2871 | static int write_essid(struct file *file, const char __user *buffer, |
2872 | unsigned long count, void *data) | ||
2755 | { | 2873 | { |
2756 | static char proc_essid[33]; | 2874 | static char proc_essid[33]; |
2757 | int len = count; | 2875 | int len = count; |
@@ -2765,7 +2883,8 @@ static int write_essid(struct file *file, const char __user *buffer, unsigned lo | |||
2765 | return count; | 2883 | return count; |
2766 | } | 2884 | } |
2767 | 2885 | ||
2768 | static int write_int(struct file *file, const char __user *buffer, unsigned long count, void *data) | 2886 | static int write_int(struct file *file, const char __user *buffer, |
2887 | unsigned long count, void *data) | ||
2769 | { | 2888 | { |
2770 | static char proc_number[10]; | 2889 | static char proc_number[10]; |
2771 | char *p; | 2890 | char *p; |
@@ -2785,7 +2904,7 @@ static int write_int(struct file *file, const char __user *buffer, unsigned long | |||
2785 | unsigned int c = *p - '0'; | 2904 | unsigned int c = *p - '0'; |
2786 | if (c > 9) | 2905 | if (c > 9) |
2787 | return -EINVAL; | 2906 | return -EINVAL; |
2788 | nr = nr*10 + c; | 2907 | nr = nr * 10 + c; |
2789 | p++; | 2908 | p++; |
2790 | } while (--len); | 2909 | } while (--len); |
2791 | *(int *)data = nr; | 2910 | *(int *)data = nr; |
@@ -2797,55 +2916,58 @@ static struct pcmcia_device_id ray_ids[] = { | |||
2797 | PCMCIA_DEVICE_MANF_CARD(0x01a6, 0x0000), | 2916 | PCMCIA_DEVICE_MANF_CARD(0x01a6, 0x0000), |
2798 | PCMCIA_DEVICE_NULL, | 2917 | PCMCIA_DEVICE_NULL, |
2799 | }; | 2918 | }; |
2919 | |||
2800 | MODULE_DEVICE_TABLE(pcmcia, ray_ids); | 2920 | MODULE_DEVICE_TABLE(pcmcia, ray_ids); |
2801 | 2921 | ||
2802 | static struct pcmcia_driver ray_driver = { | 2922 | static struct pcmcia_driver ray_driver = { |
2803 | .owner = THIS_MODULE, | 2923 | .owner = THIS_MODULE, |
2804 | .drv = { | 2924 | .drv = { |
2805 | .name = "ray_cs", | 2925 | .name = "ray_cs", |
2806 | }, | 2926 | }, |
2807 | .probe = ray_probe, | 2927 | .probe = ray_probe, |
2808 | .remove = ray_detach, | 2928 | .remove = ray_detach, |
2809 | .id_table = ray_ids, | 2929 | .id_table = ray_ids, |
2810 | .suspend = ray_suspend, | 2930 | .suspend = ray_suspend, |
2811 | .resume = ray_resume, | 2931 | .resume = ray_resume, |
2812 | }; | 2932 | }; |
2813 | 2933 | ||
2814 | static int __init init_ray_cs(void) | 2934 | static int __init init_ray_cs(void) |
2815 | { | 2935 | { |
2816 | int rc; | 2936 | int rc; |
2817 | 2937 | ||
2818 | DEBUG(1, "%s\n", rcsid); | 2938 | DEBUG(1, "%s\n", rcsid); |
2819 | rc = pcmcia_register_driver(&ray_driver); | 2939 | rc = pcmcia_register_driver(&ray_driver); |
2820 | DEBUG(1, "raylink init_module register_pcmcia_driver returns 0x%x\n",rc); | 2940 | DEBUG(1, "raylink init_module register_pcmcia_driver returns 0x%x\n", |
2941 | rc); | ||
2821 | 2942 | ||
2822 | #ifdef CONFIG_PROC_FS | 2943 | #ifdef CONFIG_PROC_FS |
2823 | proc_mkdir("driver/ray_cs", NULL); | 2944 | proc_mkdir("driver/ray_cs", NULL); |
2824 | 2945 | ||
2825 | proc_create("driver/ray_cs/ray_cs", 0, NULL, &ray_cs_proc_fops); | 2946 | proc_create("driver/ray_cs/ray_cs", 0, NULL, &ray_cs_proc_fops); |
2826 | raycs_write("driver/ray_cs/essid", write_essid, NULL); | 2947 | raycs_write("driver/ray_cs/essid", write_essid, NULL); |
2827 | raycs_write("driver/ray_cs/net_type", write_int, &net_type); | 2948 | raycs_write("driver/ray_cs/net_type", write_int, &net_type); |
2828 | raycs_write("driver/ray_cs/translate", write_int, &translate); | 2949 | raycs_write("driver/ray_cs/translate", write_int, &translate); |
2829 | #endif | 2950 | #endif |
2830 | if (translate != 0) translate = 1; | 2951 | if (translate != 0) |
2831 | return 0; | 2952 | translate = 1; |
2953 | return 0; | ||
2832 | } /* init_ray_cs */ | 2954 | } /* init_ray_cs */ |
2833 | 2955 | ||
2834 | /*===========================================================================*/ | 2956 | /*===========================================================================*/ |
2835 | 2957 | ||
2836 | static void __exit exit_ray_cs(void) | 2958 | static void __exit exit_ray_cs(void) |
2837 | { | 2959 | { |
2838 | DEBUG(0, "ray_cs: cleanup_module\n"); | 2960 | DEBUG(0, "ray_cs: cleanup_module\n"); |
2839 | 2961 | ||
2840 | #ifdef CONFIG_PROC_FS | 2962 | #ifdef CONFIG_PROC_FS |
2841 | remove_proc_entry("driver/ray_cs/ray_cs", NULL); | 2963 | remove_proc_entry("driver/ray_cs/ray_cs", NULL); |
2842 | remove_proc_entry("driver/ray_cs/essid", NULL); | 2964 | remove_proc_entry("driver/ray_cs/essid", NULL); |
2843 | remove_proc_entry("driver/ray_cs/net_type", NULL); | 2965 | remove_proc_entry("driver/ray_cs/net_type", NULL); |
2844 | remove_proc_entry("driver/ray_cs/translate", NULL); | 2966 | remove_proc_entry("driver/ray_cs/translate", NULL); |
2845 | remove_proc_entry("driver/ray_cs", NULL); | 2967 | remove_proc_entry("driver/ray_cs", NULL); |
2846 | #endif | 2968 | #endif |
2847 | 2969 | ||
2848 | pcmcia_unregister_driver(&ray_driver); | 2970 | pcmcia_unregister_driver(&ray_driver); |
2849 | } /* exit_ray_cs */ | 2971 | } /* exit_ray_cs */ |
2850 | 2972 | ||
2851 | module_init(init_ray_cs); | 2973 | module_init(init_ray_cs); |
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index f6e56370ea65..f33aa08dd9b3 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h | |||
@@ -150,6 +150,17 @@ | |||
150 | * @NL80211_CMD_SCAN_ABORTED: scan was aborted, for unspecified reasons, | 150 | * @NL80211_CMD_SCAN_ABORTED: scan was aborted, for unspecified reasons, |
151 | * partial scan results may be available | 151 | * partial scan results may be available |
152 | * | 152 | * |
153 | * @NL80211_CMD_REG_CHANGE: indicates to userspace the regulatory domain | ||
154 | * has been changed and provides details of the request information | ||
155 | * that caused the change such as who initiated the regulatory request | ||
156 | * (%NL80211_ATTR_REG_INITIATOR), the wiphy_idx | ||
157 | * (%NL80211_ATTR_REG_ALPHA2) on which the request was made from if | ||
158 | * the initiator was %NL80211_REGDOM_SET_BY_COUNTRY_IE or | ||
159 | * %NL80211_REGDOM_SET_BY_DRIVER, the type of regulatory domain | ||
160 | * set (%NL80211_ATTR_REG_TYPE), if the type of regulatory domain is | ||
161 | * %NL80211_REG_TYPE_COUNTRY the alpha2 to which we have moved on | ||
162 | * to (%NL80211_ATTR_REG_ALPHA2). | ||
163 | * | ||
153 | * @NL80211_CMD_MAX: highest used command number | 164 | * @NL80211_CMD_MAX: highest used command number |
154 | * @__NL80211_CMD_AFTER_LAST: internal use | 165 | * @__NL80211_CMD_AFTER_LAST: internal use |
155 | */ | 166 | */ |
@@ -204,6 +215,8 @@ enum nl80211_commands { | |||
204 | NL80211_CMD_NEW_SCAN_RESULTS, | 215 | NL80211_CMD_NEW_SCAN_RESULTS, |
205 | NL80211_CMD_SCAN_ABORTED, | 216 | NL80211_CMD_SCAN_ABORTED, |
206 | 217 | ||
218 | NL80211_CMD_REG_CHANGE, | ||
219 | |||
207 | /* add new commands above here */ | 220 | /* add new commands above here */ |
208 | 221 | ||
209 | /* used to define NL80211_CMD_MAX below */ | 222 | /* used to define NL80211_CMD_MAX below */ |
@@ -218,6 +231,8 @@ enum nl80211_commands { | |||
218 | #define NL80211_CMD_SET_BSS NL80211_CMD_SET_BSS | 231 | #define NL80211_CMD_SET_BSS NL80211_CMD_SET_BSS |
219 | #define NL80211_CMD_SET_MGMT_EXTRA_IE NL80211_CMD_SET_MGMT_EXTRA_IE | 232 | #define NL80211_CMD_SET_MGMT_EXTRA_IE NL80211_CMD_SET_MGMT_EXTRA_IE |
220 | 233 | ||
234 | #define NL80211_CMD_REG_CHANGE NL80211_CMD_REG_CHANGE | ||
235 | |||
221 | /** | 236 | /** |
222 | * enum nl80211_attrs - nl80211 netlink attributes | 237 | * enum nl80211_attrs - nl80211 netlink attributes |
223 | * | 238 | * |
@@ -329,6 +344,11 @@ enum nl80211_commands { | |||
329 | * messages carried the same generation number) | 344 | * messages carried the same generation number) |
330 | * @NL80211_ATTR_BSS: scan result BSS | 345 | * @NL80211_ATTR_BSS: scan result BSS |
331 | * | 346 | * |
347 | * @NL80211_ATTR_REG_INITIATOR: indicates who requested the regulatory domain | ||
348 | * currently in effect. This could be any of the %NL80211_REGDOM_SET_BY_* | ||
349 | * @NL80211_ATTR_REG_TYPE: indicates the type of the regulatory domain currently | ||
350 | * set. This can be one of the nl80211_reg_type (%NL80211_REGDOM_TYPE_*) | ||
351 | * | ||
332 | * @NL80211_ATTR_MAX: highest attribute number currently defined | 352 | * @NL80211_ATTR_MAX: highest attribute number currently defined |
333 | * @__NL80211_ATTR_AFTER_LAST: internal use | 353 | * @__NL80211_ATTR_AFTER_LAST: internal use |
334 | */ | 354 | */ |
@@ -403,6 +423,9 @@ enum nl80211_attrs { | |||
403 | NL80211_ATTR_SCAN_GENERATION, | 423 | NL80211_ATTR_SCAN_GENERATION, |
404 | NL80211_ATTR_BSS, | 424 | NL80211_ATTR_BSS, |
405 | 425 | ||
426 | NL80211_ATTR_REG_INITIATOR, | ||
427 | NL80211_ATTR_REG_TYPE, | ||
428 | |||
406 | /* add attributes here, update the policy in nl80211.c */ | 429 | /* add attributes here, update the policy in nl80211.c */ |
407 | 430 | ||
408 | __NL80211_ATTR_AFTER_LAST, | 431 | __NL80211_ATTR_AFTER_LAST, |
@@ -420,6 +443,8 @@ enum nl80211_attrs { | |||
420 | #define NL80211_ATTR_WIPHY_CHANNEL_TYPE NL80211_ATTR_WIPHY_CHANNEL_TYPE | 443 | #define NL80211_ATTR_WIPHY_CHANNEL_TYPE NL80211_ATTR_WIPHY_CHANNEL_TYPE |
421 | #define NL80211_ATTR_MGMT_SUBTYPE NL80211_ATTR_MGMT_SUBTYPE | 444 | #define NL80211_ATTR_MGMT_SUBTYPE NL80211_ATTR_MGMT_SUBTYPE |
422 | #define NL80211_ATTR_IE NL80211_ATTR_IE | 445 | #define NL80211_ATTR_IE NL80211_ATTR_IE |
446 | #define NL80211_ATTR_REG_INITIATOR NL80211_ATTR_REG_INITIATOR | ||
447 | #define NL80211_ATTR_REG_TYPE NL80211_ATTR_REG_TYPE | ||
423 | 448 | ||
424 | #define NL80211_MAX_SUPP_RATES 32 | 449 | #define NL80211_MAX_SUPP_RATES 32 |
425 | #define NL80211_MAX_SUPP_REG_RULES 32 | 450 | #define NL80211_MAX_SUPP_REG_RULES 32 |
@@ -673,6 +698,48 @@ enum nl80211_bitrate_attr { | |||
673 | }; | 698 | }; |
674 | 699 | ||
675 | /** | 700 | /** |
701 | * enum nl80211_initiator - Indicates the initiator of a reg domain request | ||
702 | * @NL80211_REGDOM_SET_BY_CORE: Core queried CRDA for a dynamic world | ||
703 | * regulatory domain. | ||
704 | * @NL80211_REGDOM_SET_BY_USER: User asked the wireless core to set the | ||
705 | * regulatory domain. | ||
706 | * @NL80211_REGDOM_SET_BY_DRIVER: a wireless drivers has hinted to the | ||
707 | * wireless core it thinks its knows the regulatory domain we should be in. | ||
708 | * @NL80211_REGDOM_SET_BY_COUNTRY_IE: the wireless core has received an | ||
709 | * 802.11 country information element with regulatory information it | ||
710 | * thinks we should consider. | ||
711 | */ | ||
712 | enum nl80211_reg_initiator { | ||
713 | NL80211_REGDOM_SET_BY_CORE, | ||
714 | NL80211_REGDOM_SET_BY_USER, | ||
715 | NL80211_REGDOM_SET_BY_DRIVER, | ||
716 | NL80211_REGDOM_SET_BY_COUNTRY_IE, | ||
717 | }; | ||
718 | |||
719 | /** | ||
720 | * enum nl80211_reg_type - specifies the type of regulatory domain | ||
721 | * @NL80211_REGDOM_TYPE_COUNTRY: the regulatory domain set is one that pertains | ||
722 | * to a specific country. When this is set you can count on the | ||
723 | * ISO / IEC 3166 alpha2 country code being valid. | ||
724 | * @NL80211_REGDOM_TYPE_WORLD: the regulatory set domain is the world regulatory | ||
725 | * domain. | ||
726 | * @NL80211_REGDOM_TYPE_CUSTOM_WORLD: the regulatory domain set is a custom | ||
727 | * driver specific world regulatory domain. These do not apply system-wide | ||
728 | * and are only applicable to the individual devices which have requested | ||
729 | * them to be applied. | ||
730 | * @NL80211_REGDOM_TYPE_INTERSECTION: the regulatory domain set is the product | ||
731 | * of an intersection between two regulatory domains -- the previously | ||
732 | * set regulatory domain on the system and the last accepted regulatory | ||
733 | * domain request to be processed. | ||
734 | */ | ||
735 | enum nl80211_reg_type { | ||
736 | NL80211_REGDOM_TYPE_COUNTRY, | ||
737 | NL80211_REGDOM_TYPE_WORLD, | ||
738 | NL80211_REGDOM_TYPE_CUSTOM_WORLD, | ||
739 | NL80211_REGDOM_TYPE_INTERSECTION, | ||
740 | }; | ||
741 | |||
742 | /** | ||
676 | * enum nl80211_reg_rule_attr - regulatory rule attributes | 743 | * enum nl80211_reg_rule_attr - regulatory rule attributes |
677 | * @NL80211_ATTR_REG_RULE_FLAGS: a set of flags which specify additional | 744 | * @NL80211_ATTR_REG_RULE_FLAGS: a set of flags which specify additional |
678 | * considerations for a given frequency range. These are the | 745 | * considerations for a given frequency range. These are the |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 75fa556728ce..50f3fd9ff524 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -349,30 +349,9 @@ struct bss_parameters { | |||
349 | }; | 349 | }; |
350 | 350 | ||
351 | /** | 351 | /** |
352 | * enum reg_set_by - Indicates who is trying to set the regulatory domain | ||
353 | * @REGDOM_SET_BY_INIT: regulatory domain was set by initialization. We will be | ||
354 | * using a static world regulatory domain by default. | ||
355 | * @REGDOM_SET_BY_CORE: Core queried CRDA for a dynamic world regulatory domain. | ||
356 | * @REGDOM_SET_BY_USER: User asked the wireless core to set the | ||
357 | * regulatory domain. | ||
358 | * @REGDOM_SET_BY_DRIVER: a wireless drivers has hinted to the wireless core | ||
359 | * it thinks its knows the regulatory domain we should be in. | ||
360 | * @REGDOM_SET_BY_COUNTRY_IE: the wireless core has received an 802.11 country | ||
361 | * information element with regulatory information it thinks we | ||
362 | * should consider. | ||
363 | */ | ||
364 | enum reg_set_by { | ||
365 | REGDOM_SET_BY_INIT, | ||
366 | REGDOM_SET_BY_CORE, | ||
367 | REGDOM_SET_BY_USER, | ||
368 | REGDOM_SET_BY_DRIVER, | ||
369 | REGDOM_SET_BY_COUNTRY_IE, | ||
370 | }; | ||
371 | |||
372 | /** | ||
373 | * enum environment_cap - Environment parsed from country IE | 352 | * enum environment_cap - Environment parsed from country IE |
374 | * @ENVIRON_ANY: indicates country IE applies to both indoor and | 353 | * @ENVIRON_ANY: indicates country IE applies to both indoor and |
375 | * outdoor operation. | 354 | * outdoor operation. |
376 | * @ENVIRON_INDOOR: indicates country IE applies only to indoor operation | 355 | * @ENVIRON_INDOOR: indicates country IE applies only to indoor operation |
377 | * @ENVIRON_OUTDOOR: indicates country IE applies only to outdoor operation | 356 | * @ENVIRON_OUTDOOR: indicates country IE applies only to outdoor operation |
378 | */ | 357 | */ |
@@ -391,7 +370,7 @@ enum environment_cap { | |||
391 | * and potentially inform users of which devices specifically | 370 | * and potentially inform users of which devices specifically |
392 | * cased the conflicts. | 371 | * cased the conflicts. |
393 | * @initiator: indicates who sent this request, could be any of | 372 | * @initiator: indicates who sent this request, could be any of |
394 | * of those set in reg_set_by, %REGDOM_SET_BY_* | 373 | * of those set in nl80211_reg_initiator (%NL80211_REGDOM_SET_BY_*) |
395 | * @alpha2: the ISO / IEC 3166 alpha2 country code of the requested | 374 | * @alpha2: the ISO / IEC 3166 alpha2 country code of the requested |
396 | * regulatory domain. We have a few special codes: | 375 | * regulatory domain. We have a few special codes: |
397 | * 00 - World regulatory domain | 376 | * 00 - World regulatory domain |
@@ -408,7 +387,7 @@ enum environment_cap { | |||
408 | */ | 387 | */ |
409 | struct regulatory_request { | 388 | struct regulatory_request { |
410 | int wiphy_idx; | 389 | int wiphy_idx; |
411 | enum reg_set_by initiator; | 390 | enum nl80211_reg_initiator initiator; |
412 | char alpha2[2]; | 391 | char alpha2[2]; |
413 | bool intersect; | 392 | bool intersect; |
414 | u32 country_ie_checksum; | 393 | u32 country_ie_checksum; |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index ecbc8e0cb3e7..fbb91f1aebb2 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -972,6 +972,7 @@ int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, | |||
972 | char *ie, size_t len); | 972 | char *ie, size_t len); |
973 | 973 | ||
974 | void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local); | 974 | void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local); |
975 | void ieee80211_scan_failed(struct ieee80211_local *local); | ||
975 | int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, | 976 | int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, |
976 | struct cfg80211_scan_request *req); | 977 | struct cfg80211_scan_request *req); |
977 | struct ieee80211_bss * | 978 | struct ieee80211_bss * |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 2acc416e77e1..f9f27b9cadbe 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -370,6 +370,18 @@ static int ieee80211_stop(struct net_device *dev) | |||
370 | rcu_read_unlock(); | 370 | rcu_read_unlock(); |
371 | 371 | ||
372 | /* | 372 | /* |
373 | * Announce that we are leaving the network, in case we are a | ||
374 | * station interface type. This must be done before removing | ||
375 | * all stations associated with sta_info_flush, otherwise STA | ||
376 | * information will be gone and no announce being done. | ||
377 | */ | ||
378 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
379 | if (sdata->u.mgd.state != IEEE80211_STA_MLME_DISABLED) | ||
380 | ieee80211_sta_deauthenticate(sdata, | ||
381 | WLAN_REASON_DEAUTH_LEAVING); | ||
382 | } | ||
383 | |||
384 | /* | ||
373 | * Remove all stations associated with this interface. | 385 | * Remove all stations associated with this interface. |
374 | * | 386 | * |
375 | * This must be done before calling ops->remove_interface() | 387 | * This must be done before calling ops->remove_interface() |
@@ -454,10 +466,6 @@ static int ieee80211_stop(struct net_device *dev) | |||
454 | netif_addr_unlock_bh(local->mdev); | 466 | netif_addr_unlock_bh(local->mdev); |
455 | break; | 467 | break; |
456 | case NL80211_IFTYPE_STATION: | 468 | case NL80211_IFTYPE_STATION: |
457 | /* Announce that we are leaving the network. */ | ||
458 | if (sdata->u.mgd.state != IEEE80211_STA_MLME_DISABLED) | ||
459 | ieee80211_sta_deauthenticate(sdata, | ||
460 | WLAN_REASON_DEAUTH_LEAVING); | ||
461 | memset(sdata->u.mgd.bssid, 0, ETH_ALEN); | 469 | memset(sdata->u.mgd.bssid, 0, ETH_ALEN); |
462 | del_timer_sync(&sdata->u.mgd.chswitch_timer); | 470 | del_timer_sync(&sdata->u.mgd.chswitch_timer); |
463 | del_timer_sync(&sdata->u.mgd.timer); | 471 | del_timer_sync(&sdata->u.mgd.timer); |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 391445c6b892..841b8450b3de 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -417,9 +417,6 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, | |||
417 | 417 | ||
418 | memset(¶ms, 0, sizeof(params)); | 418 | memset(¶ms, 0, sizeof(params)); |
419 | 419 | ||
420 | if (!local->ops->conf_tx) | ||
421 | return; | ||
422 | |||
423 | local->wmm_acm = 0; | 420 | local->wmm_acm = 0; |
424 | for (; left >= 4; left -= 4, pos += 4) { | 421 | for (; left >= 4; left -= 4, pos += 4) { |
425 | int aci = (pos[0] >> 5) & 0x03; | 422 | int aci = (pos[0] >> 5) & 0x03; |
@@ -427,26 +424,26 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, | |||
427 | int queue; | 424 | int queue; |
428 | 425 | ||
429 | switch (aci) { | 426 | switch (aci) { |
430 | case 1: | 427 | case 1: /* AC_BK */ |
431 | queue = 3; | 428 | queue = 3; |
432 | if (acm) | 429 | if (acm) |
433 | local->wmm_acm |= BIT(0) | BIT(3); | 430 | local->wmm_acm |= BIT(1) | BIT(2); /* BK/- */ |
434 | break; | 431 | break; |
435 | case 2: | 432 | case 2: /* AC_VI */ |
436 | queue = 1; | 433 | queue = 1; |
437 | if (acm) | 434 | if (acm) |
438 | local->wmm_acm |= BIT(4) | BIT(5); | 435 | local->wmm_acm |= BIT(4) | BIT(5); /* CL/VI */ |
439 | break; | 436 | break; |
440 | case 3: | 437 | case 3: /* AC_VO */ |
441 | queue = 0; | 438 | queue = 0; |
442 | if (acm) | 439 | if (acm) |
443 | local->wmm_acm |= BIT(6) | BIT(7); | 440 | local->wmm_acm |= BIT(6) | BIT(7); /* VO/NC */ |
444 | break; | 441 | break; |
445 | case 0: | 442 | case 0: /* AC_BE */ |
446 | default: | 443 | default: |
447 | queue = 2; | 444 | queue = 2; |
448 | if (acm) | 445 | if (acm) |
449 | local->wmm_acm |= BIT(1) | BIT(2); | 446 | local->wmm_acm |= BIT(0) | BIT(3); /* BE/EE */ |
450 | break; | 447 | break; |
451 | } | 448 | } |
452 | 449 | ||
@@ -460,9 +457,8 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, | |||
460 | local->mdev->name, queue, aci, acm, params.aifs, params.cw_min, | 457 | local->mdev->name, queue, aci, acm, params.aifs, params.cw_min, |
461 | params.cw_max, params.txop); | 458 | params.cw_max, params.txop); |
462 | #endif | 459 | #endif |
463 | /* TODO: handle ACM (block TX, fallback to next lowest allowed | 460 | if (local->ops->conf_tx && |
464 | * AC for now) */ | 461 | local->ops->conf_tx(local_to_hw(local), queue, ¶ms)) { |
465 | if (local->ops->conf_tx(local_to_hw(local), queue, ¶ms)) { | ||
466 | printk(KERN_DEBUG "%s: failed to set TX queue " | 462 | printk(KERN_DEBUG "%s: failed to set TX queue " |
467 | "parameters for queue %d\n", local->mdev->name, queue); | 463 | "parameters for queue %d\n", local->mdev->name, queue); |
468 | } | 464 | } |
@@ -1724,7 +1720,10 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata) | |||
1724 | local->int_scan_req.ssids[0].ssid_len = 0; | 1720 | local->int_scan_req.ssids[0].ssid_len = 0; |
1725 | else | 1721 | else |
1726 | local->int_scan_req.ssids[0].ssid_len = ifmgd->ssid_len; | 1722 | local->int_scan_req.ssids[0].ssid_len = ifmgd->ssid_len; |
1727 | ieee80211_start_scan(sdata, &local->int_scan_req); | 1723 | |
1724 | if (ieee80211_start_scan(sdata, &local->int_scan_req)) | ||
1725 | ieee80211_scan_failed(local); | ||
1726 | |||
1728 | ifmgd->state = IEEE80211_STA_MLME_AUTHENTICATE; | 1727 | ifmgd->state = IEEE80211_STA_MLME_AUTHENTICATE; |
1729 | set_bit(IEEE80211_STA_REQ_AUTH, &ifmgd->request); | 1728 | set_bit(IEEE80211_STA_REQ_AUTH, &ifmgd->request); |
1730 | } else { | 1729 | } else { |
@@ -1761,7 +1760,14 @@ static void ieee80211_sta_work(struct work_struct *work) | |||
1761 | ifmgd->state != IEEE80211_STA_MLME_AUTHENTICATE && | 1760 | ifmgd->state != IEEE80211_STA_MLME_AUTHENTICATE && |
1762 | ifmgd->state != IEEE80211_STA_MLME_ASSOCIATE && | 1761 | ifmgd->state != IEEE80211_STA_MLME_ASSOCIATE && |
1763 | test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request)) { | 1762 | test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request)) { |
1764 | ieee80211_start_scan(sdata, local->scan_req); | 1763 | /* |
1764 | * The call to ieee80211_start_scan can fail but ieee80211_request_scan | ||
1765 | * (which queued ieee80211_sta_work) did not return an error. Thus, call | ||
1766 | * ieee80211_scan_failed here if ieee80211_start_scan fails in order to | ||
1767 | * notify the scan requester. | ||
1768 | */ | ||
1769 | if (ieee80211_start_scan(sdata, local->scan_req)) | ||
1770 | ieee80211_scan_failed(local); | ||
1765 | return; | 1771 | return; |
1766 | } | 1772 | } |
1767 | 1773 | ||
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 0e81e1633a66..5030a3c87509 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -202,6 +202,18 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | |||
202 | return RX_QUEUED; | 202 | return RX_QUEUED; |
203 | } | 203 | } |
204 | 204 | ||
205 | void ieee80211_scan_failed(struct ieee80211_local *local) | ||
206 | { | ||
207 | if (WARN_ON(!local->scan_req)) | ||
208 | return; | ||
209 | |||
210 | /* notify cfg80211 about the failed scan */ | ||
211 | if (local->scan_req != &local->int_scan_req) | ||
212 | cfg80211_scan_done(local->scan_req, true); | ||
213 | |||
214 | local->scan_req = NULL; | ||
215 | } | ||
216 | |||
205 | void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | 217 | void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) |
206 | { | 218 | { |
207 | struct ieee80211_local *local = hw_to_local(hw); | 219 | struct ieee80211_local *local = hw_to_local(hw); |
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index 093a4ab7f28b..0b8ad1f4ecdd 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c | |||
@@ -99,10 +99,13 @@ static u16 classify80211(struct ieee80211_local *local, struct sk_buff *skb) | |||
99 | /* in case we are a client verify acm is not set for this ac */ | 99 | /* in case we are a client verify acm is not set for this ac */ |
100 | while (unlikely(local->wmm_acm & BIT(skb->priority))) { | 100 | while (unlikely(local->wmm_acm & BIT(skb->priority))) { |
101 | if (wme_downgrade_ac(skb)) { | 101 | if (wme_downgrade_ac(skb)) { |
102 | /* The old code would drop the packet in this | 102 | /* |
103 | * case. | 103 | * This should not really happen. The AP has marked all |
104 | * lower ACs to require admission control which is not | ||
105 | * a reasonable configuration. Allow the frame to be | ||
106 | * transmitted using AC_BK as a workaround. | ||
104 | */ | 107 | */ |
105 | return 0; | 108 | break; |
106 | } | 109 | } |
107 | } | 110 | } |
108 | 111 | ||
diff --git a/net/wireless/core.c b/net/wireless/core.c index dd7f222919fe..17fe39049740 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -350,7 +350,7 @@ int wiphy_register(struct wiphy *wiphy) | |||
350 | mutex_lock(&cfg80211_mutex); | 350 | mutex_lock(&cfg80211_mutex); |
351 | 351 | ||
352 | /* set up regulatory info */ | 352 | /* set up regulatory info */ |
353 | wiphy_update_regulatory(wiphy, REGDOM_SET_BY_CORE); | 353 | wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE); |
354 | 354 | ||
355 | res = device_add(&drv->wiphy.dev); | 355 | res = device_add(&drv->wiphy.dev); |
356 | if (res) | 356 | if (res) |
@@ -365,6 +365,17 @@ int wiphy_register(struct wiphy *wiphy) | |||
365 | if (IS_ERR(drv->wiphy.debugfsdir)) | 365 | if (IS_ERR(drv->wiphy.debugfsdir)) |
366 | drv->wiphy.debugfsdir = NULL; | 366 | drv->wiphy.debugfsdir = NULL; |
367 | 367 | ||
368 | if (wiphy->custom_regulatory) { | ||
369 | struct regulatory_request request; | ||
370 | |||
371 | request.wiphy_idx = get_wiphy_idx(wiphy); | ||
372 | request.initiator = NL80211_REGDOM_SET_BY_DRIVER; | ||
373 | request.alpha2[0] = '9'; | ||
374 | request.alpha2[1] = '9'; | ||
375 | |||
376 | nl80211_send_reg_change_event(&request); | ||
377 | } | ||
378 | |||
368 | res = 0; | 379 | res = 0; |
369 | out_unlock: | 380 | out_unlock: |
370 | mutex_unlock(&cfg80211_mutex); | 381 | mutex_unlock(&cfg80211_mutex); |
diff --git a/net/wireless/core.h b/net/wireless/core.h index f6c53f5807f4..6acd483a61f8 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -136,7 +136,8 @@ extern int cfg80211_dev_rename(struct cfg80211_registered_device *drv, | |||
136 | char *newname); | 136 | char *newname); |
137 | 137 | ||
138 | void ieee80211_set_bitrate_flags(struct wiphy *wiphy); | 138 | void ieee80211_set_bitrate_flags(struct wiphy *wiphy); |
139 | void wiphy_update_regulatory(struct wiphy *wiphy, enum reg_set_by setby); | 139 | void wiphy_update_regulatory(struct wiphy *wiphy, |
140 | enum nl80211_reg_initiator setby); | ||
140 | 141 | ||
141 | void cfg80211_bss_expire(struct cfg80211_registered_device *dev); | 142 | void cfg80211_bss_expire(struct cfg80211_registered_device *dev); |
142 | void cfg80211_bss_age(struct cfg80211_registered_device *dev, | 143 | void cfg80211_bss_age(struct cfg80211_registered_device *dev, |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 531bb67cf502..8ac3d26014a8 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -2739,6 +2739,9 @@ static struct genl_multicast_group nl80211_config_mcgrp = { | |||
2739 | static struct genl_multicast_group nl80211_scan_mcgrp = { | 2739 | static struct genl_multicast_group nl80211_scan_mcgrp = { |
2740 | .name = "scan", | 2740 | .name = "scan", |
2741 | }; | 2741 | }; |
2742 | static struct genl_multicast_group nl80211_regulatory_mcgrp = { | ||
2743 | .name = "regulatory", | ||
2744 | }; | ||
2742 | 2745 | ||
2743 | /* notification functions */ | 2746 | /* notification functions */ |
2744 | 2747 | ||
@@ -2818,6 +2821,61 @@ void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, | |||
2818 | genlmsg_multicast(msg, 0, nl80211_scan_mcgrp.id, GFP_KERNEL); | 2821 | genlmsg_multicast(msg, 0, nl80211_scan_mcgrp.id, GFP_KERNEL); |
2819 | } | 2822 | } |
2820 | 2823 | ||
2824 | /* | ||
2825 | * This can happen on global regulatory changes or device specific settings | ||
2826 | * based on custom world regulatory domains. | ||
2827 | */ | ||
2828 | void nl80211_send_reg_change_event(struct regulatory_request *request) | ||
2829 | { | ||
2830 | struct sk_buff *msg; | ||
2831 | void *hdr; | ||
2832 | |||
2833 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | ||
2834 | if (!msg) | ||
2835 | return; | ||
2836 | |||
2837 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_REG_CHANGE); | ||
2838 | if (!hdr) { | ||
2839 | nlmsg_free(msg); | ||
2840 | return; | ||
2841 | } | ||
2842 | |||
2843 | /* Userspace can always count this one always being set */ | ||
2844 | NLA_PUT_U8(msg, NL80211_ATTR_REG_INITIATOR, request->initiator); | ||
2845 | |||
2846 | if (request->alpha2[0] == '0' && request->alpha2[1] == '0') | ||
2847 | NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE, | ||
2848 | NL80211_REGDOM_TYPE_WORLD); | ||
2849 | else if (request->alpha2[0] == '9' && request->alpha2[1] == '9') | ||
2850 | NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE, | ||
2851 | NL80211_REGDOM_TYPE_CUSTOM_WORLD); | ||
2852 | else if ((request->alpha2[0] == '9' && request->alpha2[1] == '8') || | ||
2853 | request->intersect) | ||
2854 | NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE, | ||
2855 | NL80211_REGDOM_TYPE_INTERSECTION); | ||
2856 | else { | ||
2857 | NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE, | ||
2858 | NL80211_REGDOM_TYPE_COUNTRY); | ||
2859 | NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, request->alpha2); | ||
2860 | } | ||
2861 | |||
2862 | if (wiphy_idx_valid(request->wiphy_idx)) | ||
2863 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, request->wiphy_idx); | ||
2864 | |||
2865 | if (genlmsg_end(msg, hdr) < 0) { | ||
2866 | nlmsg_free(msg); | ||
2867 | return; | ||
2868 | } | ||
2869 | |||
2870 | genlmsg_multicast(msg, 0, nl80211_regulatory_mcgrp.id, GFP_KERNEL); | ||
2871 | |||
2872 | return; | ||
2873 | |||
2874 | nla_put_failure: | ||
2875 | genlmsg_cancel(msg, hdr); | ||
2876 | nlmsg_free(msg); | ||
2877 | } | ||
2878 | |||
2821 | /* initialisation/exit functions */ | 2879 | /* initialisation/exit functions */ |
2822 | 2880 | ||
2823 | int nl80211_init(void) | 2881 | int nl80211_init(void) |
@@ -2842,6 +2900,10 @@ int nl80211_init(void) | |||
2842 | if (err) | 2900 | if (err) |
2843 | goto err_out; | 2901 | goto err_out; |
2844 | 2902 | ||
2903 | err = genl_register_mc_group(&nl80211_fam, &nl80211_regulatory_mcgrp); | ||
2904 | if (err) | ||
2905 | goto err_out; | ||
2906 | |||
2845 | return 0; | 2907 | return 0; |
2846 | err_out: | 2908 | err_out: |
2847 | genl_unregister_family(&nl80211_fam); | 2909 | genl_unregister_family(&nl80211_fam); |
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index 69787b621365..e65a3c38c52f 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h | |||
@@ -11,6 +11,7 @@ extern void nl80211_send_scan_done(struct cfg80211_registered_device *rdev, | |||
11 | struct net_device *netdev); | 11 | struct net_device *netdev); |
12 | extern void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, | 12 | extern void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, |
13 | struct net_device *netdev); | 13 | struct net_device *netdev); |
14 | extern void nl80211_send_reg_change_event(struct regulatory_request *request); | ||
14 | #else | 15 | #else |
15 | static inline int nl80211_init(void) | 16 | static inline int nl80211_init(void) |
16 | { | 17 | { |
@@ -31,6 +32,10 @@ static inline void nl80211_send_scan_aborted( | |||
31 | struct cfg80211_registered_device *rdev, | 32 | struct cfg80211_registered_device *rdev, |
32 | struct net_device *netdev) | 33 | struct net_device *netdev) |
33 | {} | 34 | {} |
35 | static inline void | ||
36 | nl80211_send_reg_change_event(struct regulatory_request *request) | ||
37 | { | ||
38 | } | ||
34 | #endif /* CONFIG_NL80211 */ | 39 | #endif /* CONFIG_NL80211 */ |
35 | 40 | ||
36 | #endif /* __NET_WIRELESS_NL80211_H */ | 41 | #endif /* __NET_WIRELESS_NL80211_H */ |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 58df98f10990..eb8b8ed16155 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <net/cfg80211.h> | 41 | #include <net/cfg80211.h> |
42 | #include "core.h" | 42 | #include "core.h" |
43 | #include "reg.h" | 43 | #include "reg.h" |
44 | #include "nl80211.h" | ||
44 | 45 | ||
45 | /* Receipt of information from last regulatory request */ | 46 | /* Receipt of information from last regulatory request */ |
46 | static struct regulatory_request *last_request; | 47 | static struct regulatory_request *last_request; |
@@ -86,20 +87,31 @@ struct reg_beacon { | |||
86 | 87 | ||
87 | /* We keep a static world regulatory domain in case of the absence of CRDA */ | 88 | /* We keep a static world regulatory domain in case of the absence of CRDA */ |
88 | static const struct ieee80211_regdomain world_regdom = { | 89 | static const struct ieee80211_regdomain world_regdom = { |
89 | .n_reg_rules = 3, | 90 | .n_reg_rules = 5, |
90 | .alpha2 = "00", | 91 | .alpha2 = "00", |
91 | .reg_rules = { | 92 | .reg_rules = { |
92 | /* IEEE 802.11b/g, channels 1..11 */ | 93 | /* IEEE 802.11b/g, channels 1..11 */ |
93 | REG_RULE(2412-10, 2462+10, 40, 6, 20, 0), | 94 | REG_RULE(2412-10, 2462+10, 40, 6, 20, 0), |
94 | /* IEEE 802.11a, channel 36..48 */ | 95 | /* IEEE 802.11b/g, channels 12..13. No HT40 |
95 | REG_RULE(5180-10, 5240+10, 40, 6, 23, | 96 | * channel fits here. */ |
97 | REG_RULE(2467-10, 2472+10, 20, 6, 20, | ||
96 | NL80211_RRF_PASSIVE_SCAN | | 98 | NL80211_RRF_PASSIVE_SCAN | |
97 | NL80211_RRF_NO_IBSS), | 99 | NL80211_RRF_NO_IBSS), |
100 | /* IEEE 802.11 channel 14 - Only JP enables | ||
101 | * this and for 802.11b only */ | ||
102 | REG_RULE(2484-10, 2484+10, 20, 6, 20, | ||
103 | NL80211_RRF_PASSIVE_SCAN | | ||
104 | NL80211_RRF_NO_IBSS | | ||
105 | NL80211_RRF_NO_OFDM), | ||
106 | /* IEEE 802.11a, channel 36..48 */ | ||
107 | REG_RULE(5180-10, 5240+10, 40, 6, 20, | ||
108 | NL80211_RRF_PASSIVE_SCAN | | ||
109 | NL80211_RRF_NO_IBSS), | ||
98 | 110 | ||
99 | /* NB: 5260 MHz - 5700 MHz requies DFS */ | 111 | /* NB: 5260 MHz - 5700 MHz requies DFS */ |
100 | 112 | ||
101 | /* IEEE 802.11a, channel 149..165 */ | 113 | /* IEEE 802.11a, channel 149..165 */ |
102 | REG_RULE(5745-10, 5825+10, 40, 6, 23, | 114 | REG_RULE(5745-10, 5825+10, 40, 6, 20, |
103 | NL80211_RRF_PASSIVE_SCAN | | 115 | NL80211_RRF_PASSIVE_SCAN | |
104 | NL80211_RRF_NO_IBSS), | 116 | NL80211_RRF_NO_IBSS), |
105 | } | 117 | } |
@@ -846,8 +858,8 @@ static int freq_reg_info_regd(struct wiphy *wiphy, | |||
846 | * Follow the driver's regulatory domain, if present, unless a country | 858 | * Follow the driver's regulatory domain, if present, unless a country |
847 | * IE has been processed or a user wants to help complaince further | 859 | * IE has been processed or a user wants to help complaince further |
848 | */ | 860 | */ |
849 | if (last_request->initiator != REGDOM_SET_BY_COUNTRY_IE && | 861 | if (last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && |
850 | last_request->initiator != REGDOM_SET_BY_USER && | 862 | last_request->initiator != NL80211_REGDOM_SET_BY_USER && |
851 | wiphy->regd) | 863 | wiphy->regd) |
852 | regd = wiphy->regd; | 864 | regd = wiphy->regd; |
853 | 865 | ||
@@ -932,7 +944,8 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, | |||
932 | * http://tinyurl.com/11d-clarification | 944 | * http://tinyurl.com/11d-clarification |
933 | */ | 945 | */ |
934 | if (r == -ERANGE && | 946 | if (r == -ERANGE && |
935 | last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) { | 947 | last_request->initiator == |
948 | NL80211_REGDOM_SET_BY_COUNTRY_IE) { | ||
936 | #ifdef CONFIG_CFG80211_REG_DEBUG | 949 | #ifdef CONFIG_CFG80211_REG_DEBUG |
937 | printk(KERN_DEBUG "cfg80211: Leaving channel %d MHz " | 950 | printk(KERN_DEBUG "cfg80211: Leaving channel %d MHz " |
938 | "intact on %s - no rule found in band on " | 951 | "intact on %s - no rule found in band on " |
@@ -945,7 +958,8 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, | |||
945 | * for the band so we respect its band definitions | 958 | * for the band so we respect its band definitions |
946 | */ | 959 | */ |
947 | #ifdef CONFIG_CFG80211_REG_DEBUG | 960 | #ifdef CONFIG_CFG80211_REG_DEBUG |
948 | if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) | 961 | if (last_request->initiator == |
962 | NL80211_REGDOM_SET_BY_COUNTRY_IE) | ||
949 | printk(KERN_DEBUG "cfg80211: Disabling " | 963 | printk(KERN_DEBUG "cfg80211: Disabling " |
950 | "channel %d MHz on %s due to " | 964 | "channel %d MHz on %s due to " |
951 | "Country IE\n", | 965 | "Country IE\n", |
@@ -959,7 +973,7 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, | |||
959 | 973 | ||
960 | power_rule = ®_rule->power_rule; | 974 | power_rule = ®_rule->power_rule; |
961 | 975 | ||
962 | if (last_request->initiator == REGDOM_SET_BY_DRIVER && | 976 | if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER && |
963 | request_wiphy && request_wiphy == wiphy && | 977 | request_wiphy && request_wiphy == wiphy && |
964 | request_wiphy->strict_regulatory) { | 978 | request_wiphy->strict_regulatory) { |
965 | /* | 979 | /* |
@@ -1000,11 +1014,12 @@ static void handle_band(struct wiphy *wiphy, enum ieee80211_band band) | |||
1000 | handle_channel(wiphy, band, i); | 1014 | handle_channel(wiphy, band, i); |
1001 | } | 1015 | } |
1002 | 1016 | ||
1003 | static bool ignore_reg_update(struct wiphy *wiphy, enum reg_set_by setby) | 1017 | static bool ignore_reg_update(struct wiphy *wiphy, |
1018 | enum nl80211_reg_initiator initiator) | ||
1004 | { | 1019 | { |
1005 | if (!last_request) | 1020 | if (!last_request) |
1006 | return true; | 1021 | return true; |
1007 | if (setby == REGDOM_SET_BY_CORE && | 1022 | if (initiator == NL80211_REGDOM_SET_BY_CORE && |
1008 | wiphy->custom_regulatory) | 1023 | wiphy->custom_regulatory) |
1009 | return true; | 1024 | return true; |
1010 | /* | 1025 | /* |
@@ -1017,12 +1032,12 @@ static bool ignore_reg_update(struct wiphy *wiphy, enum reg_set_by setby) | |||
1017 | return false; | 1032 | return false; |
1018 | } | 1033 | } |
1019 | 1034 | ||
1020 | static void update_all_wiphy_regulatory(enum reg_set_by setby) | 1035 | static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator) |
1021 | { | 1036 | { |
1022 | struct cfg80211_registered_device *drv; | 1037 | struct cfg80211_registered_device *drv; |
1023 | 1038 | ||
1024 | list_for_each_entry(drv, &cfg80211_drv_list, list) | 1039 | list_for_each_entry(drv, &cfg80211_drv_list, list) |
1025 | wiphy_update_regulatory(&drv->wiphy, setby); | 1040 | wiphy_update_regulatory(&drv->wiphy, initiator); |
1026 | } | 1041 | } |
1027 | 1042 | ||
1028 | static void handle_reg_beacon(struct wiphy *wiphy, | 1043 | static void handle_reg_beacon(struct wiphy *wiphy, |
@@ -1113,7 +1128,7 @@ static bool reg_is_world_roaming(struct wiphy *wiphy) | |||
1113 | if (is_world_regdom(cfg80211_regdomain->alpha2) || | 1128 | if (is_world_regdom(cfg80211_regdomain->alpha2) || |
1114 | (wiphy->regd && is_world_regdom(wiphy->regd->alpha2))) | 1129 | (wiphy->regd && is_world_regdom(wiphy->regd->alpha2))) |
1115 | return true; | 1130 | return true; |
1116 | if (last_request->initiator != REGDOM_SET_BY_COUNTRY_IE && | 1131 | if (last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && |
1117 | wiphy->custom_regulatory) | 1132 | wiphy->custom_regulatory) |
1118 | return true; | 1133 | return true; |
1119 | return false; | 1134 | return false; |
@@ -1127,11 +1142,12 @@ static void reg_process_beacons(struct wiphy *wiphy) | |||
1127 | wiphy_update_beacon_reg(wiphy); | 1142 | wiphy_update_beacon_reg(wiphy); |
1128 | } | 1143 | } |
1129 | 1144 | ||
1130 | void wiphy_update_regulatory(struct wiphy *wiphy, enum reg_set_by setby) | 1145 | void wiphy_update_regulatory(struct wiphy *wiphy, |
1146 | enum nl80211_reg_initiator initiator) | ||
1131 | { | 1147 | { |
1132 | enum ieee80211_band band; | 1148 | enum ieee80211_band band; |
1133 | 1149 | ||
1134 | if (ignore_reg_update(wiphy, setby)) | 1150 | if (ignore_reg_update(wiphy, initiator)) |
1135 | goto out; | 1151 | goto out; |
1136 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | 1152 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { |
1137 | if (wiphy->bands[band]) | 1153 | if (wiphy->bands[band]) |
@@ -1244,17 +1260,16 @@ static int ignore_request(struct wiphy *wiphy, | |||
1244 | return 0; | 1260 | return 0; |
1245 | 1261 | ||
1246 | switch (pending_request->initiator) { | 1262 | switch (pending_request->initiator) { |
1247 | case REGDOM_SET_BY_INIT: | 1263 | case NL80211_REGDOM_SET_BY_CORE: |
1248 | return -EINVAL; | 1264 | return -EINVAL; |
1249 | case REGDOM_SET_BY_CORE: | 1265 | case NL80211_REGDOM_SET_BY_COUNTRY_IE: |
1250 | return -EINVAL; | ||
1251 | case REGDOM_SET_BY_COUNTRY_IE: | ||
1252 | 1266 | ||
1253 | last_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx); | 1267 | last_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx); |
1254 | 1268 | ||
1255 | if (unlikely(!is_an_alpha2(pending_request->alpha2))) | 1269 | if (unlikely(!is_an_alpha2(pending_request->alpha2))) |
1256 | return -EINVAL; | 1270 | return -EINVAL; |
1257 | if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) { | 1271 | if (last_request->initiator == |
1272 | NL80211_REGDOM_SET_BY_COUNTRY_IE) { | ||
1258 | if (last_wiphy != wiphy) { | 1273 | if (last_wiphy != wiphy) { |
1259 | /* | 1274 | /* |
1260 | * Two cards with two APs claiming different | 1275 | * Two cards with two APs claiming different |
@@ -1275,8 +1290,8 @@ static int ignore_request(struct wiphy *wiphy, | |||
1275 | return -EALREADY; | 1290 | return -EALREADY; |
1276 | } | 1291 | } |
1277 | return REG_INTERSECT; | 1292 | return REG_INTERSECT; |
1278 | case REGDOM_SET_BY_DRIVER: | 1293 | case NL80211_REGDOM_SET_BY_DRIVER: |
1279 | if (last_request->initiator == REGDOM_SET_BY_CORE) { | 1294 | if (last_request->initiator == NL80211_REGDOM_SET_BY_CORE) { |
1280 | if (is_old_static_regdom(cfg80211_regdomain)) | 1295 | if (is_old_static_regdom(cfg80211_regdomain)) |
1281 | return 0; | 1296 | return 0; |
1282 | if (regdom_changes(pending_request->alpha2)) | 1297 | if (regdom_changes(pending_request->alpha2)) |
@@ -1289,28 +1304,28 @@ static int ignore_request(struct wiphy *wiphy, | |||
1289 | * back in or if you add a new device for which the previously | 1304 | * back in or if you add a new device for which the previously |
1290 | * loaded card also agrees on the regulatory domain. | 1305 | * loaded card also agrees on the regulatory domain. |
1291 | */ | 1306 | */ |
1292 | if (last_request->initiator == REGDOM_SET_BY_DRIVER && | 1307 | if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER && |
1293 | !regdom_changes(pending_request->alpha2)) | 1308 | !regdom_changes(pending_request->alpha2)) |
1294 | return -EALREADY; | 1309 | return -EALREADY; |
1295 | 1310 | ||
1296 | return REG_INTERSECT; | 1311 | return REG_INTERSECT; |
1297 | case REGDOM_SET_BY_USER: | 1312 | case NL80211_REGDOM_SET_BY_USER: |
1298 | if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) | 1313 | if (last_request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) |
1299 | return REG_INTERSECT; | 1314 | return REG_INTERSECT; |
1300 | /* | 1315 | /* |
1301 | * If the user knows better the user should set the regdom | 1316 | * If the user knows better the user should set the regdom |
1302 | * to their country before the IE is picked up | 1317 | * to their country before the IE is picked up |
1303 | */ | 1318 | */ |
1304 | if (last_request->initiator == REGDOM_SET_BY_USER && | 1319 | if (last_request->initiator == NL80211_REGDOM_SET_BY_USER && |
1305 | last_request->intersect) | 1320 | last_request->intersect) |
1306 | return -EOPNOTSUPP; | 1321 | return -EOPNOTSUPP; |
1307 | /* | 1322 | /* |
1308 | * Process user requests only after previous user/driver/core | 1323 | * Process user requests only after previous user/driver/core |
1309 | * requests have been processed | 1324 | * requests have been processed |
1310 | */ | 1325 | */ |
1311 | if (last_request->initiator == REGDOM_SET_BY_CORE || | 1326 | if (last_request->initiator == NL80211_REGDOM_SET_BY_CORE || |
1312 | last_request->initiator == REGDOM_SET_BY_DRIVER || | 1327 | last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER || |
1313 | last_request->initiator == REGDOM_SET_BY_USER) { | 1328 | last_request->initiator == NL80211_REGDOM_SET_BY_USER) { |
1314 | if (regdom_changes(last_request->alpha2)) | 1329 | if (regdom_changes(last_request->alpha2)) |
1315 | return -EAGAIN; | 1330 | return -EAGAIN; |
1316 | } | 1331 | } |
@@ -1350,7 +1365,8 @@ static int __regulatory_hint(struct wiphy *wiphy, | |||
1350 | r = ignore_request(wiphy, pending_request); | 1365 | r = ignore_request(wiphy, pending_request); |
1351 | 1366 | ||
1352 | if (r == REG_INTERSECT) { | 1367 | if (r == REG_INTERSECT) { |
1353 | if (pending_request->initiator == REGDOM_SET_BY_DRIVER) { | 1368 | if (pending_request->initiator == |
1369 | NL80211_REGDOM_SET_BY_DRIVER) { | ||
1354 | r = reg_copy_regd(&wiphy->regd, cfg80211_regdomain); | 1370 | r = reg_copy_regd(&wiphy->regd, cfg80211_regdomain); |
1355 | if (r) { | 1371 | if (r) { |
1356 | kfree(pending_request); | 1372 | kfree(pending_request); |
@@ -1365,7 +1381,8 @@ static int __regulatory_hint(struct wiphy *wiphy, | |||
1365 | * wiphy | 1381 | * wiphy |
1366 | */ | 1382 | */ |
1367 | if (r == -EALREADY && | 1383 | if (r == -EALREADY && |
1368 | pending_request->initiator == REGDOM_SET_BY_DRIVER) { | 1384 | pending_request->initiator == |
1385 | NL80211_REGDOM_SET_BY_DRIVER) { | ||
1369 | r = reg_copy_regd(&wiphy->regd, cfg80211_regdomain); | 1386 | r = reg_copy_regd(&wiphy->regd, cfg80211_regdomain); |
1370 | if (r) { | 1387 | if (r) { |
1371 | kfree(pending_request); | 1388 | kfree(pending_request); |
@@ -1387,8 +1404,16 @@ new_request: | |||
1387 | pending_request = NULL; | 1404 | pending_request = NULL; |
1388 | 1405 | ||
1389 | /* When r == REG_INTERSECT we do need to call CRDA */ | 1406 | /* When r == REG_INTERSECT we do need to call CRDA */ |
1390 | if (r < 0) | 1407 | if (r < 0) { |
1408 | /* | ||
1409 | * Since CRDA will not be called in this case as we already | ||
1410 | * have applied the requested regulatory domain before we just | ||
1411 | * inform userspace we have processed the request | ||
1412 | */ | ||
1413 | if (r == -EALREADY) | ||
1414 | nl80211_send_reg_change_event(last_request); | ||
1391 | return r; | 1415 | return r; |
1416 | } | ||
1392 | 1417 | ||
1393 | /* | 1418 | /* |
1394 | * Note: When CONFIG_WIRELESS_OLD_REGULATORY is enabled | 1419 | * Note: When CONFIG_WIRELESS_OLD_REGULATORY is enabled |
@@ -1416,7 +1441,7 @@ static void reg_process_hint(struct regulatory_request *reg_request) | |||
1416 | if (wiphy_idx_valid(reg_request->wiphy_idx)) | 1441 | if (wiphy_idx_valid(reg_request->wiphy_idx)) |
1417 | wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx); | 1442 | wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx); |
1418 | 1443 | ||
1419 | if (reg_request->initiator == REGDOM_SET_BY_DRIVER && | 1444 | if (reg_request->initiator == NL80211_REGDOM_SET_BY_DRIVER && |
1420 | !wiphy) { | 1445 | !wiphy) { |
1421 | kfree(reg_request); | 1446 | kfree(reg_request); |
1422 | goto out; | 1447 | goto out; |
@@ -1430,7 +1455,7 @@ out: | |||
1430 | mutex_unlock(&cfg80211_mutex); | 1455 | mutex_unlock(&cfg80211_mutex); |
1431 | } | 1456 | } |
1432 | 1457 | ||
1433 | /* Processes regulatory hints, this is all the REGDOM_SET_BY_* */ | 1458 | /* Processes regulatory hints, this is all the NL80211_REGDOM_SET_BY_* */ |
1434 | static void reg_process_pending_hints(void) | 1459 | static void reg_process_pending_hints(void) |
1435 | { | 1460 | { |
1436 | struct regulatory_request *reg_request; | 1461 | struct regulatory_request *reg_request; |
@@ -1514,7 +1539,7 @@ static int regulatory_hint_core(const char *alpha2) | |||
1514 | 1539 | ||
1515 | request->alpha2[0] = alpha2[0]; | 1540 | request->alpha2[0] = alpha2[0]; |
1516 | request->alpha2[1] = alpha2[1]; | 1541 | request->alpha2[1] = alpha2[1]; |
1517 | request->initiator = REGDOM_SET_BY_CORE; | 1542 | request->initiator = NL80211_REGDOM_SET_BY_CORE; |
1518 | 1543 | ||
1519 | queue_regulatory_request(request); | 1544 | queue_regulatory_request(request); |
1520 | 1545 | ||
@@ -1535,7 +1560,7 @@ int regulatory_hint_user(const char *alpha2) | |||
1535 | request->wiphy_idx = WIPHY_IDX_STALE; | 1560 | request->wiphy_idx = WIPHY_IDX_STALE; |
1536 | request->alpha2[0] = alpha2[0]; | 1561 | request->alpha2[0] = alpha2[0]; |
1537 | request->alpha2[1] = alpha2[1]; | 1562 | request->alpha2[1] = alpha2[1]; |
1538 | request->initiator = REGDOM_SET_BY_USER, | 1563 | request->initiator = NL80211_REGDOM_SET_BY_USER, |
1539 | 1564 | ||
1540 | queue_regulatory_request(request); | 1565 | queue_regulatory_request(request); |
1541 | 1566 | ||
@@ -1561,7 +1586,7 @@ int regulatory_hint(struct wiphy *wiphy, const char *alpha2) | |||
1561 | 1586 | ||
1562 | request->alpha2[0] = alpha2[0]; | 1587 | request->alpha2[0] = alpha2[0]; |
1563 | request->alpha2[1] = alpha2[1]; | 1588 | request->alpha2[1] = alpha2[1]; |
1564 | request->initiator = REGDOM_SET_BY_DRIVER; | 1589 | request->initiator = NL80211_REGDOM_SET_BY_DRIVER; |
1565 | 1590 | ||
1566 | queue_regulatory_request(request); | 1591 | queue_regulatory_request(request); |
1567 | 1592 | ||
@@ -1710,7 +1735,7 @@ void regulatory_hint_11d(struct wiphy *wiphy, | |||
1710 | request->wiphy_idx = get_wiphy_idx(wiphy); | 1735 | request->wiphy_idx = get_wiphy_idx(wiphy); |
1711 | request->alpha2[0] = rd->alpha2[0]; | 1736 | request->alpha2[0] = rd->alpha2[0]; |
1712 | request->alpha2[1] = rd->alpha2[1]; | 1737 | request->alpha2[1] = rd->alpha2[1]; |
1713 | request->initiator = REGDOM_SET_BY_COUNTRY_IE; | 1738 | request->initiator = NL80211_REGDOM_SET_BY_COUNTRY_IE; |
1714 | request->country_ie_checksum = checksum; | 1739 | request->country_ie_checksum = checksum; |
1715 | request->country_ie_env = env; | 1740 | request->country_ie_env = env; |
1716 | 1741 | ||
@@ -1818,7 +1843,8 @@ static void print_regdomain(const struct ieee80211_regdomain *rd) | |||
1818 | 1843 | ||
1819 | if (is_intersected_alpha2(rd->alpha2)) { | 1844 | if (is_intersected_alpha2(rd->alpha2)) { |
1820 | 1845 | ||
1821 | if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) { | 1846 | if (last_request->initiator == |
1847 | NL80211_REGDOM_SET_BY_COUNTRY_IE) { | ||
1822 | struct cfg80211_registered_device *drv; | 1848 | struct cfg80211_registered_device *drv; |
1823 | drv = cfg80211_drv_by_wiphy_idx( | 1849 | drv = cfg80211_drv_by_wiphy_idx( |
1824 | last_request->wiphy_idx); | 1850 | last_request->wiphy_idx); |
@@ -1910,7 +1936,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) | |||
1910 | * rd is non static (it means CRDA was present and was used last) | 1936 | * rd is non static (it means CRDA was present and was used last) |
1911 | * and the pending request came in from a country IE | 1937 | * and the pending request came in from a country IE |
1912 | */ | 1938 | */ |
1913 | if (last_request->initiator != REGDOM_SET_BY_COUNTRY_IE) { | 1939 | if (last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) { |
1914 | /* | 1940 | /* |
1915 | * If someone else asked us to change the rd lets only bother | 1941 | * If someone else asked us to change the rd lets only bother |
1916 | * checking if the alpha2 changes if CRDA was already called | 1942 | * checking if the alpha2 changes if CRDA was already called |
@@ -1942,7 +1968,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) | |||
1942 | if (!last_request->intersect) { | 1968 | if (!last_request->intersect) { |
1943 | int r; | 1969 | int r; |
1944 | 1970 | ||
1945 | if (last_request->initiator != REGDOM_SET_BY_DRIVER) { | 1971 | if (last_request->initiator != NL80211_REGDOM_SET_BY_DRIVER) { |
1946 | reset_regdomains(); | 1972 | reset_regdomains(); |
1947 | cfg80211_regdomain = rd; | 1973 | cfg80211_regdomain = rd; |
1948 | return 0; | 1974 | return 0; |
@@ -1966,7 +1992,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) | |||
1966 | 1992 | ||
1967 | /* Intersection requires a bit more work */ | 1993 | /* Intersection requires a bit more work */ |
1968 | 1994 | ||
1969 | if (last_request->initiator != REGDOM_SET_BY_COUNTRY_IE) { | 1995 | if (last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) { |
1970 | 1996 | ||
1971 | intersected_rd = regdom_intersect(rd, cfg80211_regdomain); | 1997 | intersected_rd = regdom_intersect(rd, cfg80211_regdomain); |
1972 | if (!intersected_rd) | 1998 | if (!intersected_rd) |
@@ -1977,7 +2003,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) | |||
1977 | * However if a driver requested this specific regulatory | 2003 | * However if a driver requested this specific regulatory |
1978 | * domain we keep it for its private use | 2004 | * domain we keep it for its private use |
1979 | */ | 2005 | */ |
1980 | if (last_request->initiator == REGDOM_SET_BY_DRIVER) | 2006 | if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER) |
1981 | request_wiphy->regd = rd; | 2007 | request_wiphy->regd = rd; |
1982 | else | 2008 | else |
1983 | kfree(rd); | 2009 | kfree(rd); |
@@ -2067,6 +2093,8 @@ int set_regdom(const struct ieee80211_regdomain *rd) | |||
2067 | 2093 | ||
2068 | print_regdomain(cfg80211_regdomain); | 2094 | print_regdomain(cfg80211_regdomain); |
2069 | 2095 | ||
2096 | nl80211_send_reg_change_event(last_request); | ||
2097 | |||
2070 | return r; | 2098 | return r; |
2071 | } | 2099 | } |
2072 | 2100 | ||