diff options
author | David S. Miller <davem@davemloft.net> | 2008-11-21 20:05:11 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-11-21 20:05:11 -0500 |
commit | 6c0bce37ffc8f000a516fadf6dee84579c4c8f9b (patch) | |
tree | 273af34d6f777b1ecb0fce7b2685e868064e6cf9 /drivers/net | |
parent | e243455d345ef62751723671bc2605a2f6032ceb (diff) | |
parent | a1eb5fe319beb9e181aa52c8adf75ad9aab56a89 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'drivers/net')
95 files changed, 5155 insertions, 1398 deletions
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 42afaedbb219..84b49c83ae67 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig | |||
@@ -123,150 +123,6 @@ config PCMCIA_RAYCS | |||
123 | To compile this driver as a module, choose M here: the module will be | 123 | To compile this driver as a module, choose M here: the module will be |
124 | called ray_cs. If unsure, say N. | 124 | called ray_cs. If unsure, say N. |
125 | 125 | ||
126 | config IPW2100 | ||
127 | tristate "Intel PRO/Wireless 2100 Network Connection" | ||
128 | depends on PCI && WLAN_80211 | ||
129 | select WIRELESS_EXT | ||
130 | select FW_LOADER | ||
131 | select IEEE80211 | ||
132 | ---help--- | ||
133 | A driver for the Intel PRO/Wireless 2100 Network | ||
134 | Connection 802.11b wireless network adapter. | ||
135 | |||
136 | See <file:Documentation/networking/README.ipw2100> for information on | ||
137 | the capabilities currently enabled in this driver and for tips | ||
138 | for debugging issues and problems. | ||
139 | |||
140 | In order to use this driver, you will need a firmware image for it. | ||
141 | You can obtain the firmware from | ||
142 | <http://ipw2100.sf.net/>. Once you have the firmware image, you | ||
143 | will need to place it in /lib/firmware. | ||
144 | |||
145 | You will also very likely need the Wireless Tools in order to | ||
146 | configure your card: | ||
147 | |||
148 | <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>. | ||
149 | |||
150 | It is recommended that you compile this driver as a module (M) | ||
151 | rather than built-in (Y). This driver requires firmware at device | ||
152 | initialization time, and when built-in this typically happens | ||
153 | before the filesystem is accessible (hence firmware will be | ||
154 | unavailable and initialization will fail). If you do choose to build | ||
155 | this driver into your kernel image, you can avoid this problem by | ||
156 | including the firmware and a firmware loader in an initramfs. | ||
157 | |||
158 | config IPW2100_MONITOR | ||
159 | bool "Enable promiscuous mode" | ||
160 | depends on IPW2100 | ||
161 | ---help--- | ||
162 | Enables promiscuous/monitor mode support for the ipw2100 driver. | ||
163 | With this feature compiled into the driver, you can switch to | ||
164 | promiscuous mode via the Wireless Tool's Monitor mode. While in this | ||
165 | mode, no packets can be sent. | ||
166 | |||
167 | config IPW2100_DEBUG | ||
168 | bool "Enable full debugging output in IPW2100 module." | ||
169 | depends on IPW2100 | ||
170 | ---help--- | ||
171 | This option will enable debug tracing output for the IPW2100. | ||
172 | |||
173 | This will result in the kernel module being ~60k larger. You can | ||
174 | control which debug output is sent to the kernel log by setting the | ||
175 | value in | ||
176 | |||
177 | /sys/bus/pci/drivers/ipw2100/debug_level | ||
178 | |||
179 | This entry will only exist if this option is enabled. | ||
180 | |||
181 | If you are not trying to debug or develop the IPW2100 driver, you | ||
182 | most likely want to say N here. | ||
183 | |||
184 | config IPW2200 | ||
185 | tristate "Intel PRO/Wireless 2200BG and 2915ABG Network Connection" | ||
186 | depends on PCI && WLAN_80211 | ||
187 | select WIRELESS_EXT | ||
188 | select FW_LOADER | ||
189 | select IEEE80211 | ||
190 | ---help--- | ||
191 | A driver for the Intel PRO/Wireless 2200BG and 2915ABG Network | ||
192 | Connection adapters. | ||
193 | |||
194 | See <file:Documentation/networking/README.ipw2200> for | ||
195 | information on the capabilities currently enabled in this | ||
196 | driver and for tips for debugging issues and problems. | ||
197 | |||
198 | In order to use this driver, you will need a firmware image for it. | ||
199 | You can obtain the firmware from | ||
200 | <http://ipw2200.sf.net/>. See the above referenced README.ipw2200 | ||
201 | for information on where to install the firmware images. | ||
202 | |||
203 | You will also very likely need the Wireless Tools in order to | ||
204 | configure your card: | ||
205 | |||
206 | <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>. | ||
207 | |||
208 | It is recommended that you compile this driver as a module (M) | ||
209 | rather than built-in (Y). This driver requires firmware at device | ||
210 | initialization time, and when built-in this typically happens | ||
211 | before the filesystem is accessible (hence firmware will be | ||
212 | unavailable and initialization will fail). If you do choose to build | ||
213 | this driver into your kernel image, you can avoid this problem by | ||
214 | including the firmware and a firmware loader in an initramfs. | ||
215 | |||
216 | config IPW2200_MONITOR | ||
217 | bool "Enable promiscuous mode" | ||
218 | depends on IPW2200 | ||
219 | ---help--- | ||
220 | Enables promiscuous/monitor mode support for the ipw2200 driver. | ||
221 | With this feature compiled into the driver, you can switch to | ||
222 | promiscuous mode via the Wireless Tool's Monitor mode. While in this | ||
223 | mode, no packets can be sent. | ||
224 | |||
225 | config IPW2200_RADIOTAP | ||
226 | bool "Enable radiotap format 802.11 raw packet support" | ||
227 | depends on IPW2200_MONITOR | ||
228 | |||
229 | config IPW2200_PROMISCUOUS | ||
230 | bool "Enable creation of a RF radiotap promiscuous interface" | ||
231 | depends on IPW2200_MONITOR | ||
232 | select IPW2200_RADIOTAP | ||
233 | ---help--- | ||
234 | Enables the creation of a second interface prefixed 'rtap'. | ||
235 | This second interface will provide every received in radiotap | ||
236 | format. | ||
237 | |||
238 | This is useful for performing wireless network analysis while | ||
239 | maintaining an active association. | ||
240 | |||
241 | Example usage: | ||
242 | |||
243 | % modprobe ipw2200 rtap_iface=1 | ||
244 | % ifconfig rtap0 up | ||
245 | % tethereal -i rtap0 | ||
246 | |||
247 | If you do not specify 'rtap_iface=1' as a module parameter then | ||
248 | the rtap interface will not be created and you will need to turn | ||
249 | it on via sysfs: | ||
250 | |||
251 | % echo 1 > /sys/bus/pci/drivers/ipw2200/*/rtap_iface | ||
252 | |||
253 | config IPW2200_QOS | ||
254 | bool "Enable QoS support" | ||
255 | depends on IPW2200 && EXPERIMENTAL | ||
256 | |||
257 | config IPW2200_DEBUG | ||
258 | bool "Enable full debugging output in IPW2200 module." | ||
259 | depends on IPW2200 | ||
260 | ---help--- | ||
261 | This option will enable low level debug tracing output for IPW2200. | ||
262 | |||
263 | Note, normal debug code is already compiled in. This low level | ||
264 | debug option enables debug on hot paths (e.g Tx, Rx, ISR) and | ||
265 | will result in the kernel module being ~70 larger. Most users | ||
266 | will typically not need this high verbosity debug information. | ||
267 | |||
268 | If you are not sure, say N here. | ||
269 | |||
270 | config LIBERTAS | 126 | config LIBERTAS |
271 | tristate "Marvell 8xxx Libertas WLAN driver support" | 127 | tristate "Marvell 8xxx Libertas WLAN driver support" |
272 | depends on WLAN_80211 | 128 | depends on WLAN_80211 |
@@ -712,6 +568,7 @@ config MAC80211_HWSIM | |||
712 | source "drivers/net/wireless/p54/Kconfig" | 568 | source "drivers/net/wireless/p54/Kconfig" |
713 | source "drivers/net/wireless/ath5k/Kconfig" | 569 | source "drivers/net/wireless/ath5k/Kconfig" |
714 | source "drivers/net/wireless/ath9k/Kconfig" | 570 | source "drivers/net/wireless/ath9k/Kconfig" |
571 | source "drivers/net/wireless/ipw2x00/Kconfig" | ||
715 | source "drivers/net/wireless/iwlwifi/Kconfig" | 572 | source "drivers/net/wireless/iwlwifi/Kconfig" |
716 | source "drivers/net/wireless/hostap/Kconfig" | 573 | source "drivers/net/wireless/hostap/Kconfig" |
717 | source "drivers/net/wireless/b43/Kconfig" | 574 | source "drivers/net/wireless/b43/Kconfig" |
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index 78820840fe21..ac590e1ca8be 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile | |||
@@ -2,9 +2,8 @@ | |||
2 | # Makefile for the Linux Wireless network device drivers. | 2 | # Makefile for the Linux Wireless network device drivers. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_IPW2100) += ipw2100.o | 5 | obj-$(CONFIG_IPW2100) += ipw2x00/ |
6 | 6 | obj-$(CONFIG_IPW2200) += ipw2x00/ | |
7 | obj-$(CONFIG_IPW2200) += ipw2200.o | ||
8 | 7 | ||
9 | obj-$(CONFIG_STRIP) += strip.o | 8 | obj-$(CONFIG_STRIP) += strip.o |
10 | obj-$(CONFIG_ARLAN) += arlan.o | 9 | obj-$(CONFIG_ARLAN) += arlan.o |
@@ -31,6 +30,8 @@ obj-$(CONFIG_HOSTAP) += hostap/ | |||
31 | obj-$(CONFIG_B43) += b43/ | 30 | obj-$(CONFIG_B43) += b43/ |
32 | obj-$(CONFIG_B43LEGACY) += b43legacy/ | 31 | obj-$(CONFIG_B43LEGACY) += b43legacy/ |
33 | obj-$(CONFIG_ZD1211RW) += zd1211rw/ | 32 | obj-$(CONFIG_ZD1211RW) += zd1211rw/ |
33 | obj-$(CONFIG_RTL8180) += rtl818x/ | ||
34 | obj-$(CONFIG_RTL8187) += rtl818x/ | ||
34 | 35 | ||
35 | # 16-bit wireless PCMCIA client drivers | 36 | # 16-bit wireless PCMCIA client drivers |
36 | obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o | 37 | obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o |
@@ -43,12 +44,6 @@ obj-$(CONFIG_LIBERTAS) += libertas/ | |||
43 | 44 | ||
44 | obj-$(CONFIG_LIBERTAS_THINFIRM) += libertas_tf/ | 45 | obj-$(CONFIG_LIBERTAS_THINFIRM) += libertas_tf/ |
45 | 46 | ||
46 | rtl8180-objs := rtl8180_dev.o rtl8180_rtl8225.o rtl8180_sa2400.o rtl8180_max2820.o rtl8180_grf5101.o | ||
47 | rtl8187-objs := rtl8187_dev.o rtl8187_rtl8225.o | ||
48 | |||
49 | obj-$(CONFIG_RTL8180) += rtl8180.o | ||
50 | obj-$(CONFIG_RTL8187) += rtl8187.o | ||
51 | |||
52 | obj-$(CONFIG_ADM8211) += adm8211.o | 47 | obj-$(CONFIG_ADM8211) += adm8211.o |
53 | 48 | ||
54 | obj-$(CONFIG_IWLWIFI) += iwlwifi/ | 49 | obj-$(CONFIG_IWLWIFI) += iwlwifi/ |
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index c7ffcbb9062d..34cd1a4a297f 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c | |||
@@ -2219,9 +2219,9 @@ ath5k_init(struct ath5k_softc *sc, bool is_resume) | |||
2219 | */ | 2219 | */ |
2220 | sc->curchan = sc->hw->conf.channel; | 2220 | sc->curchan = sc->hw->conf.channel; |
2221 | sc->curband = &sc->sbands[sc->curchan->band]; | 2221 | sc->curband = &sc->sbands[sc->curchan->band]; |
2222 | sc->imask = AR5K_INT_RXOK | AR5K_INT_TXOK | AR5K_INT_RXEOL | | 2222 | sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL | |
2223 | AR5K_INT_RXORN | AR5K_INT_FATAL | AR5K_INT_GLOBAL | | 2223 | AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL | |
2224 | AR5K_INT_MIB; | 2224 | AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_MIB; |
2225 | ret = ath5k_reset(sc, false, false); | 2225 | ret = ath5k_reset(sc, false, false); |
2226 | if (ret) | 2226 | if (ret) |
2227 | goto done; | 2227 | goto done; |
@@ -2953,9 +2953,9 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw, | |||
2953 | test_bit(ATH_STAT_PROMISC, sc->status)) | 2953 | test_bit(ATH_STAT_PROMISC, sc->status)) |
2954 | rfilt |= AR5K_RX_FILTER_PROM; | 2954 | rfilt |= AR5K_RX_FILTER_PROM; |
2955 | if (sc->opmode == NL80211_IFTYPE_STATION || | 2955 | if (sc->opmode == NL80211_IFTYPE_STATION || |
2956 | sc->opmode == NL80211_IFTYPE_ADHOC) { | 2956 | sc->opmode == NL80211_IFTYPE_ADHOC || |
2957 | sc->opmode == NL80211_IFTYPE_AP) | ||
2957 | rfilt |= AR5K_RX_FILTER_BEACON; | 2958 | rfilt |= AR5K_RX_FILTER_BEACON; |
2958 | } | ||
2959 | if (sc->opmode == NL80211_IFTYPE_MESH_POINT) | 2959 | if (sc->opmode == NL80211_IFTYPE_MESH_POINT) |
2960 | rfilt |= AR5K_RX_FILTER_CONTROL | AR5K_RX_FILTER_BEACON | | 2960 | rfilt |= AR5K_RX_FILTER_CONTROL | AR5K_RX_FILTER_BEACON | |
2961 | AR5K_RX_FILTER_PROBEREQ | AR5K_RX_FILTER_PROM; | 2961 | AR5K_RX_FILTER_PROBEREQ | AR5K_RX_FILTER_PROM; |
diff --git a/drivers/net/wireless/ath5k/phy.c b/drivers/net/wireless/ath5k/phy.c index 69625bf4d11c..7ba18e09463b 100644 --- a/drivers/net/wireless/ath5k/phy.c +++ b/drivers/net/wireless/ath5k/phy.c | |||
@@ -2196,9 +2196,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, | |||
2196 | return ret; | 2196 | return ret; |
2197 | } | 2197 | } |
2198 | 2198 | ||
2199 | ret = ath5k_hw_noise_floor_calibration(ah, channel->center_freq); | 2199 | ath5k_hw_noise_floor_calibration(ah, channel->center_freq); |
2200 | if (ret) | ||
2201 | return ret; | ||
2202 | 2200 | ||
2203 | /* | 2201 | /* |
2204 | * Re-enable RX/TX and beacons | 2202 | * Re-enable RX/TX and beacons |
diff --git a/drivers/net/wireless/ath5k/reset.c b/drivers/net/wireless/ath5k/reset.c index b51bc030da02..5003263c9ea4 100644 --- a/drivers/net/wireless/ath5k/reset.c +++ b/drivers/net/wireless/ath5k/reset.c | |||
@@ -842,9 +842,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
842 | * | 842 | * |
843 | * XXX: Find an interval that's OK for all cards... | 843 | * XXX: Find an interval that's OK for all cards... |
844 | */ | 844 | */ |
845 | ret = ath5k_hw_noise_floor_calibration(ah, channel->center_freq); | 845 | ath5k_hw_noise_floor_calibration(ah, channel->center_freq); |
846 | if (ret) | ||
847 | return ret; | ||
848 | 846 | ||
849 | /* | 847 | /* |
850 | * Reset queues and start beacon timers at the end of the reset routine | 848 | * Reset queues and start beacon timers at the end of the reset routine |
diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index e05c9ef55e47..ff6457e0cb00 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c | |||
@@ -382,8 +382,9 @@ static const char *ath9k_hw_devname(u16 devid) | |||
382 | { | 382 | { |
383 | switch (devid) { | 383 | switch (devid) { |
384 | case AR5416_DEVID_PCI: | 384 | case AR5416_DEVID_PCI: |
385 | case AR5416_DEVID_PCIE: | ||
386 | return "Atheros 5416"; | 385 | return "Atheros 5416"; |
386 | case AR5416_DEVID_PCIE: | ||
387 | return "Atheros 5418"; | ||
387 | case AR9160_DEVID_PCI: | 388 | case AR9160_DEVID_PCI: |
388 | return "Atheros 9160"; | 389 | return "Atheros 9160"; |
389 | case AR9280_DEVID_PCI: | 390 | case AR9280_DEVID_PCI: |
diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index f830fe1e4adc..fbb2dd2373c8 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c | |||
@@ -18,6 +18,7 @@ | |||
18 | 18 | ||
19 | #include <linux/nl80211.h> | 19 | #include <linux/nl80211.h> |
20 | #include "core.h" | 20 | #include "core.h" |
21 | #include "reg.h" | ||
21 | 22 | ||
22 | #define ATH_PCI_VERSION "0.1" | 23 | #define ATH_PCI_VERSION "0.1" |
23 | 24 | ||
@@ -1519,15 +1520,74 @@ static struct ieee80211_ops ath9k_ops = { | |||
1519 | .set_frag_threshold = ath9k_no_fragmentation, | 1520 | .set_frag_threshold = ath9k_no_fragmentation, |
1520 | }; | 1521 | }; |
1521 | 1522 | ||
1523 | static struct { | ||
1524 | u32 version; | ||
1525 | const char * name; | ||
1526 | } ath_mac_bb_names[] = { | ||
1527 | { AR_SREV_VERSION_5416_PCI, "5416" }, | ||
1528 | { AR_SREV_VERSION_5416_PCIE, "5418" }, | ||
1529 | { AR_SREV_VERSION_9100, "9100" }, | ||
1530 | { AR_SREV_VERSION_9160, "9160" }, | ||
1531 | { AR_SREV_VERSION_9280, "9280" }, | ||
1532 | { AR_SREV_VERSION_9285, "9285" } | ||
1533 | }; | ||
1534 | |||
1535 | static struct { | ||
1536 | u16 version; | ||
1537 | const char * name; | ||
1538 | } ath_rf_names[] = { | ||
1539 | { 0, "5133" }, | ||
1540 | { AR_RAD5133_SREV_MAJOR, "5133" }, | ||
1541 | { AR_RAD5122_SREV_MAJOR, "5122" }, | ||
1542 | { AR_RAD2133_SREV_MAJOR, "2133" }, | ||
1543 | { AR_RAD2122_SREV_MAJOR, "2122" } | ||
1544 | }; | ||
1545 | |||
1546 | /* | ||
1547 | * Return the MAC/BB name. "????" is returned if the MAC/BB is unknown. | ||
1548 | */ | ||
1549 | |||
1550 | static const char * | ||
1551 | ath_mac_bb_name(u32 mac_bb_version) | ||
1552 | { | ||
1553 | int i; | ||
1554 | |||
1555 | for (i=0; i<ARRAY_SIZE(ath_mac_bb_names); i++) { | ||
1556 | if (ath_mac_bb_names[i].version == mac_bb_version) { | ||
1557 | return ath_mac_bb_names[i].name; | ||
1558 | } | ||
1559 | } | ||
1560 | |||
1561 | return "????"; | ||
1562 | } | ||
1563 | |||
1564 | /* | ||
1565 | * Return the RF name. "????" is returned if the RF is unknown. | ||
1566 | */ | ||
1567 | |||
1568 | static const char * | ||
1569 | ath_rf_name(u16 rf_version) | ||
1570 | { | ||
1571 | int i; | ||
1572 | |||
1573 | for (i=0; i<ARRAY_SIZE(ath_rf_names); i++) { | ||
1574 | if (ath_rf_names[i].version == rf_version) { | ||
1575 | return ath_rf_names[i].name; | ||
1576 | } | ||
1577 | } | ||
1578 | |||
1579 | return "????"; | ||
1580 | } | ||
1581 | |||
1522 | static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | 1582 | static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) |
1523 | { | 1583 | { |
1524 | void __iomem *mem; | 1584 | void __iomem *mem; |
1525 | struct ath_softc *sc; | 1585 | struct ath_softc *sc; |
1526 | struct ieee80211_hw *hw; | 1586 | struct ieee80211_hw *hw; |
1527 | const char *athname; | ||
1528 | u8 csz; | 1587 | u8 csz; |
1529 | u32 val; | 1588 | u32 val; |
1530 | int ret = 0; | 1589 | int ret = 0; |
1590 | struct ath_hal *ah; | ||
1531 | 1591 | ||
1532 | if (pci_enable_device(pdev)) | 1592 | if (pci_enable_device(pdev)) |
1533 | return -EIO; | 1593 | return -EIO; |
@@ -1614,11 +1674,15 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1614 | goto bad4; | 1674 | goto bad4; |
1615 | } | 1675 | } |
1616 | 1676 | ||
1617 | athname = ath9k_hw_probe(id->vendor, id->device); | 1677 | ah = sc->sc_ah; |
1618 | 1678 | printk(KERN_INFO | |
1619 | printk(KERN_INFO "%s: %s: mem=0x%lx, irq=%d\n", | 1679 | "%s: Atheros AR%s MAC/BB Rev:%x " |
1680 | "AR%s RF Rev:%x: mem=0x%lx, irq=%d\n", | ||
1620 | wiphy_name(hw->wiphy), | 1681 | wiphy_name(hw->wiphy), |
1621 | athname ? athname : "Atheros ???", | 1682 | ath_mac_bb_name(ah->ah_macVersion), |
1683 | ah->ah_macRev, | ||
1684 | ath_rf_name((ah->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR)), | ||
1685 | ah->ah_phyRev, | ||
1622 | (unsigned long)mem, pdev->irq); | 1686 | (unsigned long)mem, pdev->irq); |
1623 | 1687 | ||
1624 | return 0; | 1688 | return 0; |
diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c index aa6bfd717c20..517992d14808 100644 --- a/drivers/net/wireless/ath9k/rc.c +++ b/drivers/net/wireless/ath9k/rc.c | |||
@@ -1272,8 +1272,7 @@ static void ath_rc_update_ht(struct ath_softc *sc, | |||
1272 | rate_ctrl->state[tx_rate].per = 100; | 1272 | rate_ctrl->state[tx_rate].per = 100; |
1273 | } else { | 1273 | } else { |
1274 | /* xretries == 2 */ | 1274 | /* xretries == 2 */ |
1275 | count = sizeof(nretry_to_per_lookup) / | 1275 | count = ARRAY_SIZE(nretry_to_per_lookup); |
1276 | sizeof(nretry_to_per_lookup[0]); | ||
1277 | if (retries >= count) | 1276 | if (retries >= count) |
1278 | retries = count - 1; | 1277 | retries = count - 1; |
1279 | /* new_PER = 7/8*old_PER + 1/8*(currentPER) */ | 1278 | /* new_PER = 7/8*old_PER + 1/8*(currentPER) */ |
@@ -1291,8 +1290,7 @@ static void ath_rc_update_ht(struct ath_softc *sc, | |||
1291 | } else { /* xretries == 0 */ | 1290 | } else { /* xretries == 0 */ |
1292 | /* Update the PER. */ | 1291 | /* Update the PER. */ |
1293 | /* Make sure it doesn't index out of array's bounds. */ | 1292 | /* Make sure it doesn't index out of array's bounds. */ |
1294 | count = sizeof(nretry_to_per_lookup) / | 1293 | count = ARRAY_SIZE(nretry_to_per_lookup); |
1295 | sizeof(nretry_to_per_lookup[0]); | ||
1296 | if (retries >= count) | 1294 | if (retries >= count) |
1297 | retries = count - 1; | 1295 | retries = count - 1; |
1298 | if (info_priv->n_bad_frames) { | 1296 | if (info_priv->n_bad_frames) { |
diff --git a/drivers/net/wireless/ath9k/recv.c b/drivers/net/wireless/ath9k/recv.c index 2ecb0a010ce2..2d72ac19fada 100644 --- a/drivers/net/wireless/ath9k/recv.c +++ b/drivers/net/wireless/ath9k/recv.c | |||
@@ -296,9 +296,8 @@ u32 ath_calcrxfilter(struct ath_softc *sc) | |||
296 | rfilt &= ~ATH9K_RX_FILTER_UCAST; | 296 | rfilt &= ~ATH9K_RX_FILTER_UCAST; |
297 | } | 297 | } |
298 | 298 | ||
299 | if (((sc->sc_ah->ah_opmode == ATH9K_M_STA) && | 299 | if (sc->sc_ah->ah_opmode == ATH9K_M_STA || |
300 | (sc->rx_filter & FIF_BCN_PRBRESP_PROMISC)) || | 300 | sc->sc_ah->ah_opmode == ATH9K_M_IBSS) |
301 | (sc->sc_ah->ah_opmode == ATH9K_M_IBSS)) | ||
302 | rfilt |= ATH9K_RX_FILTER_BEACON; | 301 | rfilt |= ATH9K_RX_FILTER_BEACON; |
303 | 302 | ||
304 | /* If in HOSTAP mode, want to enable reception of PSPOLL frames | 303 | /* If in HOSTAP mode, want to enable reception of PSPOLL frames |
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index adba89b816d4..eae9b8052658 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c | |||
@@ -46,7 +46,6 @@ static int b43_plcp_get_bitrate_idx_cck(struct b43_plcp_hdr6 *plcp) | |||
46 | case 0x6E: | 46 | case 0x6E: |
47 | return 3; | 47 | return 3; |
48 | } | 48 | } |
49 | B43_WARN_ON(1); | ||
50 | return -1; | 49 | return -1; |
51 | } | 50 | } |
52 | 51 | ||
@@ -73,7 +72,6 @@ static u8 b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool aphy) | |||
73 | case 0xC: | 72 | case 0xC: |
74 | return base + 7; | 73 | return base + 7; |
75 | } | 74 | } |
76 | B43_WARN_ON(1); | ||
77 | return -1; | 75 | return -1; |
78 | } | 76 | } |
79 | 77 | ||
@@ -608,6 +606,8 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) | |||
608 | phytype == B43_PHYTYPE_A); | 606 | phytype == B43_PHYTYPE_A); |
609 | else | 607 | else |
610 | status.rate_idx = b43_plcp_get_bitrate_idx_cck(plcp); | 608 | status.rate_idx = b43_plcp_get_bitrate_idx_cck(plcp); |
609 | if (unlikely(status.rate_idx == -1)) | ||
610 | goto drop; | ||
611 | status.antenna = !!(phystat0 & B43_RX_PHYST0_ANT); | 611 | status.antenna = !!(phystat0 & B43_RX_PHYST0_ANT); |
612 | 612 | ||
613 | /* | 613 | /* |
diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h index c40078e1fff9..97b0e06dfe21 100644 --- a/drivers/net/wireless/b43legacy/b43legacy.h +++ b/drivers/net/wireless/b43legacy/b43legacy.h | |||
@@ -145,6 +145,10 @@ | |||
145 | #define B43legacy_SHM_SH_PRMAXTIME 0x0074 /* Probe Response max time */ | 145 | #define B43legacy_SHM_SH_PRMAXTIME 0x0074 /* Probe Response max time */ |
146 | #define B43legacy_SHM_SH_PRPHYCTL 0x0188 /* Probe Resp PHY TX control */ | 146 | #define B43legacy_SHM_SH_PRPHYCTL 0x0188 /* Probe Resp PHY TX control */ |
147 | /* SHM_SHARED rate tables */ | 147 | /* SHM_SHARED rate tables */ |
148 | #define B43legacy_SHM_SH_OFDMDIRECT 0x0480 /* Pointer to OFDM direct map */ | ||
149 | #define B43legacy_SHM_SH_OFDMBASIC 0x04A0 /* Pointer to OFDM basic rate map */ | ||
150 | #define B43legacy_SHM_SH_CCKDIRECT 0x04C0 /* Pointer to CCK direct map */ | ||
151 | #define B43legacy_SHM_SH_CCKBASIC 0x04E0 /* Pointer to CCK basic rate map */ | ||
148 | /* SHM_SHARED microcode soft registers */ | 152 | /* SHM_SHARED microcode soft registers */ |
149 | #define B43legacy_SHM_SH_UCODEREV 0x0000 /* Microcode revision */ | 153 | #define B43legacy_SHM_SH_UCODEREV 0x0000 /* Microcode revision */ |
150 | #define B43legacy_SHM_SH_UCODEPATCH 0x0002 /* Microcode patchlevel */ | 154 | #define B43legacy_SHM_SH_UCODEPATCH 0x0002 /* Microcode patchlevel */ |
@@ -663,7 +667,6 @@ struct b43legacy_wldev { | |||
663 | bool bad_frames_preempt;/* Use "Bad Frames Preemption". */ | 667 | bool bad_frames_preempt;/* Use "Bad Frames Preemption". */ |
664 | bool dfq_valid; /* Directed frame queue valid (IBSS PS mode, ATIM). */ | 668 | bool dfq_valid; /* Directed frame queue valid (IBSS PS mode, ATIM). */ |
665 | bool short_preamble; /* TRUE if using short preamble. */ | 669 | bool short_preamble; /* TRUE if using short preamble. */ |
666 | bool short_slot; /* TRUE if using short slot timing. */ | ||
667 | bool radio_hw_enable; /* State of radio hardware enable bit. */ | 670 | bool radio_hw_enable; /* State of radio hardware enable bit. */ |
668 | 671 | ||
669 | /* PHY/Radio device. */ | 672 | /* PHY/Radio device. */ |
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 6c8eb4d2519a..c1324e31d2f6 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c | |||
@@ -576,13 +576,11 @@ static void b43legacy_set_slot_time(struct b43legacy_wldev *dev, | |||
576 | static void b43legacy_short_slot_timing_enable(struct b43legacy_wldev *dev) | 576 | static void b43legacy_short_slot_timing_enable(struct b43legacy_wldev *dev) |
577 | { | 577 | { |
578 | b43legacy_set_slot_time(dev, 9); | 578 | b43legacy_set_slot_time(dev, 9); |
579 | dev->short_slot = 1; | ||
580 | } | 579 | } |
581 | 580 | ||
582 | static void b43legacy_short_slot_timing_disable(struct b43legacy_wldev *dev) | 581 | static void b43legacy_short_slot_timing_disable(struct b43legacy_wldev *dev) |
583 | { | 582 | { |
584 | b43legacy_set_slot_time(dev, 20); | 583 | b43legacy_set_slot_time(dev, 20); |
585 | dev->short_slot = 0; | ||
586 | } | 584 | } |
587 | 585 | ||
588 | /* Enable a Generic IRQ. "mask" is the mask of which IRQs to enable. | 586 | /* Enable a Generic IRQ. "mask" is the mask of which IRQs to enable. |
@@ -2608,16 +2606,6 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw, | |||
2608 | if (conf->channel->hw_value != phy->channel) | 2606 | if (conf->channel->hw_value != phy->channel) |
2609 | b43legacy_radio_selectchannel(dev, conf->channel->hw_value, 0); | 2607 | b43legacy_radio_selectchannel(dev, conf->channel->hw_value, 0); |
2610 | 2608 | ||
2611 | /* Enable/Disable ShortSlot timing. */ | ||
2612 | if ((!!(conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME)) | ||
2613 | != dev->short_slot) { | ||
2614 | B43legacy_WARN_ON(phy->type != B43legacy_PHYTYPE_G); | ||
2615 | if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) | ||
2616 | b43legacy_short_slot_timing_enable(dev); | ||
2617 | else | ||
2618 | b43legacy_short_slot_timing_disable(dev); | ||
2619 | } | ||
2620 | |||
2621 | dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_RADIOTAP); | 2609 | dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_RADIOTAP); |
2622 | 2610 | ||
2623 | /* Adjust the desired TX power level. */ | 2611 | /* Adjust the desired TX power level. */ |
@@ -2662,6 +2650,104 @@ out_unlock_mutex: | |||
2662 | return err; | 2650 | return err; |
2663 | } | 2651 | } |
2664 | 2652 | ||
2653 | static void b43legacy_update_basic_rates(struct b43legacy_wldev *dev, u64 brates) | ||
2654 | { | ||
2655 | struct ieee80211_supported_band *sband = | ||
2656 | dev->wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ]; | ||
2657 | struct ieee80211_rate *rate; | ||
2658 | int i; | ||
2659 | u16 basic, direct, offset, basic_offset, rateptr; | ||
2660 | |||
2661 | for (i = 0; i < sband->n_bitrates; i++) { | ||
2662 | rate = &sband->bitrates[i]; | ||
2663 | |||
2664 | if (b43legacy_is_cck_rate(rate->hw_value)) { | ||
2665 | direct = B43legacy_SHM_SH_CCKDIRECT; | ||
2666 | basic = B43legacy_SHM_SH_CCKBASIC; | ||
2667 | offset = b43legacy_plcp_get_ratecode_cck(rate->hw_value); | ||
2668 | offset &= 0xF; | ||
2669 | } else { | ||
2670 | direct = B43legacy_SHM_SH_OFDMDIRECT; | ||
2671 | basic = B43legacy_SHM_SH_OFDMBASIC; | ||
2672 | offset = b43legacy_plcp_get_ratecode_ofdm(rate->hw_value); | ||
2673 | offset &= 0xF; | ||
2674 | } | ||
2675 | |||
2676 | rate = ieee80211_get_response_rate(sband, brates, rate->bitrate); | ||
2677 | |||
2678 | if (b43legacy_is_cck_rate(rate->hw_value)) { | ||
2679 | basic_offset = b43legacy_plcp_get_ratecode_cck(rate->hw_value); | ||
2680 | basic_offset &= 0xF; | ||
2681 | } else { | ||
2682 | basic_offset = b43legacy_plcp_get_ratecode_ofdm(rate->hw_value); | ||
2683 | basic_offset &= 0xF; | ||
2684 | } | ||
2685 | |||
2686 | /* | ||
2687 | * Get the pointer that we need to point to | ||
2688 | * from the direct map | ||
2689 | */ | ||
2690 | rateptr = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, | ||
2691 | direct + 2 * basic_offset); | ||
2692 | /* and write it to the basic map */ | ||
2693 | b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, | ||
2694 | basic + 2 * offset, rateptr); | ||
2695 | } | ||
2696 | } | ||
2697 | |||
2698 | static void b43legacy_op_bss_info_changed(struct ieee80211_hw *hw, | ||
2699 | struct ieee80211_vif *vif, | ||
2700 | struct ieee80211_bss_conf *conf, | ||
2701 | u32 changed) | ||
2702 | { | ||
2703 | struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); | ||
2704 | struct b43legacy_wldev *dev; | ||
2705 | struct b43legacy_phy *phy; | ||
2706 | unsigned long flags; | ||
2707 | u32 savedirqs; | ||
2708 | |||
2709 | mutex_lock(&wl->mutex); | ||
2710 | |||
2711 | dev = wl->current_dev; | ||
2712 | phy = &dev->phy; | ||
2713 | |||
2714 | /* Disable IRQs while reconfiguring the device. | ||
2715 | * This makes it possible to drop the spinlock throughout | ||
2716 | * the reconfiguration process. */ | ||
2717 | spin_lock_irqsave(&wl->irq_lock, flags); | ||
2718 | if (b43legacy_status(dev) < B43legacy_STAT_STARTED) { | ||
2719 | spin_unlock_irqrestore(&wl->irq_lock, flags); | ||
2720 | goto out_unlock_mutex; | ||
2721 | } | ||
2722 | savedirqs = b43legacy_interrupt_disable(dev, B43legacy_IRQ_ALL); | ||
2723 | spin_unlock_irqrestore(&wl->irq_lock, flags); | ||
2724 | b43legacy_synchronize_irq(dev); | ||
2725 | |||
2726 | b43legacy_mac_suspend(dev); | ||
2727 | |||
2728 | if (changed & BSS_CHANGED_BASIC_RATES) | ||
2729 | b43legacy_update_basic_rates(dev, conf->basic_rates); | ||
2730 | |||
2731 | if (changed & BSS_CHANGED_ERP_SLOT) { | ||
2732 | if (conf->use_short_slot) | ||
2733 | b43legacy_short_slot_timing_enable(dev); | ||
2734 | else | ||
2735 | b43legacy_short_slot_timing_disable(dev); | ||
2736 | } | ||
2737 | |||
2738 | b43legacy_mac_enable(dev); | ||
2739 | |||
2740 | spin_lock_irqsave(&wl->irq_lock, flags); | ||
2741 | b43legacy_interrupt_enable(dev, savedirqs); | ||
2742 | /* XXX: why? */ | ||
2743 | mmiowb(); | ||
2744 | spin_unlock_irqrestore(&wl->irq_lock, flags); | ||
2745 | out_unlock_mutex: | ||
2746 | mutex_unlock(&wl->mutex); | ||
2747 | |||
2748 | return; | ||
2749 | } | ||
2750 | |||
2665 | static void b43legacy_op_configure_filter(struct ieee80211_hw *hw, | 2751 | static void b43legacy_op_configure_filter(struct ieee80211_hw *hw, |
2666 | unsigned int changed, | 2752 | unsigned int changed, |
2667 | unsigned int *fflags, | 2753 | unsigned int *fflags, |
@@ -3370,6 +3456,7 @@ static const struct ieee80211_ops b43legacy_hw_ops = { | |||
3370 | .add_interface = b43legacy_op_add_interface, | 3456 | .add_interface = b43legacy_op_add_interface, |
3371 | .remove_interface = b43legacy_op_remove_interface, | 3457 | .remove_interface = b43legacy_op_remove_interface, |
3372 | .config = b43legacy_op_dev_config, | 3458 | .config = b43legacy_op_dev_config, |
3459 | .bss_info_changed = b43legacy_op_bss_info_changed, | ||
3373 | .config_interface = b43legacy_op_config_interface, | 3460 | .config_interface = b43legacy_op_config_interface, |
3374 | .configure_filter = b43legacy_op_configure_filter, | 3461 | .configure_filter = b43legacy_op_configure_filter, |
3375 | .get_stats = b43legacy_op_get_stats, | 3462 | .get_stats = b43legacy_op_get_stats, |
diff --git a/drivers/net/wireless/hostap/Kconfig b/drivers/net/wireless/hostap/Kconfig index 1fef33169fdd..87bbd4db4bad 100644 --- a/drivers/net/wireless/hostap/Kconfig +++ b/drivers/net/wireless/hostap/Kconfig | |||
@@ -2,8 +2,10 @@ config HOSTAP | |||
2 | tristate "IEEE 802.11 for Host AP (Prism2/2.5/3 and WEP/TKIP/CCMP)" | 2 | tristate "IEEE 802.11 for Host AP (Prism2/2.5/3 and WEP/TKIP/CCMP)" |
3 | depends on WLAN_80211 | 3 | depends on WLAN_80211 |
4 | select WIRELESS_EXT | 4 | select WIRELESS_EXT |
5 | select IEEE80211 | 5 | select LIB80211 |
6 | select IEEE80211_CRYPT_WEP | 6 | select LIB80211_CRYPT_WEP |
7 | select LIB80211_CRYPT_TKIP | ||
8 | select LIB80211_CRYPT_CCMP | ||
7 | ---help--- | 9 | ---help--- |
8 | Shared driver code for IEEE 802.11b wireless cards based on | 10 | Shared driver code for IEEE 802.11b wireless cards based on |
9 | Intersil Prism2/2.5/3 chipset. This driver supports so called | 11 | Intersil Prism2/2.5/3 chipset. This driver supports so called |
diff --git a/drivers/net/wireless/hostap/hostap.h b/drivers/net/wireless/hostap/hostap.h index 3a386a636cca..2453deaa3e00 100644 --- a/drivers/net/wireless/hostap/hostap.h +++ b/drivers/net/wireless/hostap/hostap.h | |||
@@ -63,7 +63,7 @@ void ap_control_flush_macs(struct mac_restrictions *mac_restrictions); | |||
63 | int ap_control_kick_mac(struct ap_data *ap, struct net_device *dev, u8 *mac); | 63 | int ap_control_kick_mac(struct ap_data *ap, struct net_device *dev, u8 *mac); |
64 | void ap_control_kickall(struct ap_data *ap); | 64 | void ap_control_kickall(struct ap_data *ap); |
65 | void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent, | 65 | void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent, |
66 | struct ieee80211_crypt_data ***crypt); | 66 | struct lib80211_crypt_data ***crypt); |
67 | int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[], | 67 | int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[], |
68 | struct iw_quality qual[], int buf_size, | 68 | struct iw_quality qual[], int buf_size, |
69 | int aplist); | 69 | int aplist); |
diff --git a/drivers/net/wireless/hostap/hostap_80211.h b/drivers/net/wireless/hostap/hostap_80211.h index 3694b1eba521..3a9474d9a907 100644 --- a/drivers/net/wireless/hostap/hostap_80211.h +++ b/drivers/net/wireless/hostap/hostap_80211.h | |||
@@ -2,7 +2,7 @@ | |||
2 | #define HOSTAP_80211_H | 2 | #define HOSTAP_80211_H |
3 | 3 | ||
4 | #include <linux/types.h> | 4 | #include <linux/types.h> |
5 | #include <net/ieee80211_crypt.h> | 5 | #include <net/ieee80211.h> |
6 | 6 | ||
7 | struct hostap_ieee80211_mgmt { | 7 | struct hostap_ieee80211_mgmt { |
8 | __le16 frame_control; | 8 | __le16 frame_control; |
diff --git a/drivers/net/wireless/hostap/hostap_80211_rx.c b/drivers/net/wireless/hostap/hostap_80211_rx.c index 5f64461aa54e..19b1bf0478bd 100644 --- a/drivers/net/wireless/hostap/hostap_80211_rx.c +++ b/drivers/net/wireless/hostap/hostap_80211_rx.c | |||
@@ -1,5 +1,5 @@ | |||
1 | #include <linux/etherdevice.h> | 1 | #include <linux/etherdevice.h> |
2 | #include <net/ieee80211_crypt.h> | 2 | #include <net/lib80211.h> |
3 | 3 | ||
4 | #include "hostap_80211.h" | 4 | #include "hostap_80211.h" |
5 | #include "hostap.h" | 5 | #include "hostap.h" |
@@ -649,7 +649,7 @@ static int hostap_is_eapol_frame(local_info_t *local, struct sk_buff *skb) | |||
649 | /* Called only as a tasklet (software IRQ) */ | 649 | /* Called only as a tasklet (software IRQ) */ |
650 | static int | 650 | static int |
651 | hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb, | 651 | hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb, |
652 | struct ieee80211_crypt_data *crypt) | 652 | struct lib80211_crypt_data *crypt) |
653 | { | 653 | { |
654 | struct ieee80211_hdr_4addr *hdr; | 654 | struct ieee80211_hdr_4addr *hdr; |
655 | int res, hdrlen; | 655 | int res, hdrlen; |
@@ -687,7 +687,7 @@ hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb, | |||
687 | /* Called only as a tasklet (software IRQ) */ | 687 | /* Called only as a tasklet (software IRQ) */ |
688 | static int | 688 | static int |
689 | hostap_rx_frame_decrypt_msdu(local_info_t *local, struct sk_buff *skb, | 689 | hostap_rx_frame_decrypt_msdu(local_info_t *local, struct sk_buff *skb, |
690 | int keyidx, struct ieee80211_crypt_data *crypt) | 690 | int keyidx, struct lib80211_crypt_data *crypt) |
691 | { | 691 | { |
692 | struct ieee80211_hdr_4addr *hdr; | 692 | struct ieee80211_hdr_4addr *hdr; |
693 | int res, hdrlen; | 693 | int res, hdrlen; |
@@ -733,7 +733,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb, | |||
733 | int from_assoc_ap = 0; | 733 | int from_assoc_ap = 0; |
734 | u8 dst[ETH_ALEN]; | 734 | u8 dst[ETH_ALEN]; |
735 | u8 src[ETH_ALEN]; | 735 | u8 src[ETH_ALEN]; |
736 | struct ieee80211_crypt_data *crypt = NULL; | 736 | struct lib80211_crypt_data *crypt = NULL; |
737 | void *sta = NULL; | 737 | void *sta = NULL; |
738 | int keyidx = 0; | 738 | int keyidx = 0; |
739 | 739 | ||
@@ -785,7 +785,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb, | |||
785 | int idx = 0; | 785 | int idx = 0; |
786 | if (skb->len >= hdrlen + 3) | 786 | if (skb->len >= hdrlen + 3) |
787 | idx = skb->data[hdrlen + 3] >> 6; | 787 | idx = skb->data[hdrlen + 3] >> 6; |
788 | crypt = local->crypt[idx]; | 788 | crypt = local->crypt_info.crypt[idx]; |
789 | sta = NULL; | 789 | sta = NULL; |
790 | 790 | ||
791 | /* Use station specific key to override default keys if the | 791 | /* Use station specific key to override default keys if the |
diff --git a/drivers/net/wireless/hostap/hostap_80211_tx.c b/drivers/net/wireless/hostap/hostap_80211_tx.c index 075247188e64..078a010f39a0 100644 --- a/drivers/net/wireless/hostap/hostap_80211_tx.c +++ b/drivers/net/wireless/hostap/hostap_80211_tx.c | |||
@@ -306,7 +306,7 @@ int hostap_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
306 | 306 | ||
307 | /* Called only from software IRQ */ | 307 | /* Called only from software IRQ */ |
308 | static struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb, | 308 | static struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb, |
309 | struct ieee80211_crypt_data *crypt) | 309 | struct lib80211_crypt_data *crypt) |
310 | { | 310 | { |
311 | struct hostap_interface *iface; | 311 | struct hostap_interface *iface; |
312 | local_info_t *local; | 312 | local_info_t *local; |
@@ -405,7 +405,7 @@ int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
405 | if (local->host_encrypt) { | 405 | if (local->host_encrypt) { |
406 | /* Set crypt to default algorithm and key; will be replaced in | 406 | /* Set crypt to default algorithm and key; will be replaced in |
407 | * AP code if STA has own alg/key */ | 407 | * AP code if STA has own alg/key */ |
408 | tx.crypt = local->crypt[local->tx_keyidx]; | 408 | tx.crypt = local->crypt_info.crypt[local->crypt_info.tx_keyidx]; |
409 | tx.host_encrypt = 1; | 409 | tx.host_encrypt = 1; |
410 | } else { | 410 | } else { |
411 | tx.crypt = NULL; | 411 | tx.crypt = NULL; |
@@ -487,7 +487,9 @@ int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
487 | 487 | ||
488 | if (tx.crypt && (!tx.crypt->ops || !tx.crypt->ops->encrypt_mpdu)) | 488 | if (tx.crypt && (!tx.crypt->ops || !tx.crypt->ops->encrypt_mpdu)) |
489 | tx.crypt = NULL; | 489 | tx.crypt = NULL; |
490 | else if ((tx.crypt || local->crypt[local->tx_keyidx]) && !no_encrypt) { | 490 | else if ((tx.crypt || |
491 | local->crypt_info.crypt[local->crypt_info.tx_keyidx]) && | ||
492 | !no_encrypt) { | ||
491 | /* Add ISWEP flag both for firmware and host based encryption | 493 | /* Add ISWEP flag both for firmware and host based encryption |
492 | */ | 494 | */ |
493 | fc |= IEEE80211_FCTL_PROTECTED; | 495 | fc |= IEEE80211_FCTL_PROTECTED; |
diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c index dec3dbe1bf8f..0903db786d5f 100644 --- a/drivers/net/wireless/hostap/hostap_ap.c +++ b/drivers/net/wireless/hostap/hostap_ap.c | |||
@@ -1206,7 +1206,7 @@ static void prism2_check_tx_rates(struct sta_info *sta) | |||
1206 | 1206 | ||
1207 | static void ap_crypt_init(struct ap_data *ap) | 1207 | static void ap_crypt_init(struct ap_data *ap) |
1208 | { | 1208 | { |
1209 | ap->crypt = ieee80211_get_crypto_ops("WEP"); | 1209 | ap->crypt = lib80211_get_crypto_ops("WEP"); |
1210 | 1210 | ||
1211 | if (ap->crypt) { | 1211 | if (ap->crypt) { |
1212 | if (ap->crypt->init) { | 1212 | if (ap->crypt->init) { |
@@ -1224,7 +1224,7 @@ static void ap_crypt_init(struct ap_data *ap) | |||
1224 | 1224 | ||
1225 | if (ap->crypt == NULL) { | 1225 | if (ap->crypt == NULL) { |
1226 | printk(KERN_WARNING "AP could not initialize WEP: load module " | 1226 | printk(KERN_WARNING "AP could not initialize WEP: load module " |
1227 | "ieee80211_crypt_wep.ko\n"); | 1227 | "lib80211_crypt_wep.ko\n"); |
1228 | } | 1228 | } |
1229 | } | 1229 | } |
1230 | 1230 | ||
@@ -1293,7 +1293,7 @@ static void handle_authen(local_info_t *local, struct sk_buff *skb, | |||
1293 | __le16 *pos; | 1293 | __le16 *pos; |
1294 | u16 resp = WLAN_STATUS_SUCCESS, fc; | 1294 | u16 resp = WLAN_STATUS_SUCCESS, fc; |
1295 | struct sta_info *sta = NULL; | 1295 | struct sta_info *sta = NULL; |
1296 | struct ieee80211_crypt_data *crypt; | 1296 | struct lib80211_crypt_data *crypt; |
1297 | char *txt = ""; | 1297 | char *txt = ""; |
1298 | 1298 | ||
1299 | len = skb->len - IEEE80211_MGMT_HDR_LEN; | 1299 | len = skb->len - IEEE80211_MGMT_HDR_LEN; |
@@ -1319,7 +1319,7 @@ static void handle_authen(local_info_t *local, struct sk_buff *skb, | |||
1319 | int idx = 0; | 1319 | int idx = 0; |
1320 | if (skb->len >= hdrlen + 3) | 1320 | if (skb->len >= hdrlen + 3) |
1321 | idx = skb->data[hdrlen + 3] >> 6; | 1321 | idx = skb->data[hdrlen + 3] >> 6; |
1322 | crypt = local->crypt[idx]; | 1322 | crypt = local->crypt_info.crypt[idx]; |
1323 | } | 1323 | } |
1324 | 1324 | ||
1325 | pos = (__le16 *) (skb->data + IEEE80211_MGMT_HDR_LEN); | 1325 | pos = (__le16 *) (skb->data + IEEE80211_MGMT_HDR_LEN); |
@@ -3065,7 +3065,7 @@ ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev, | |||
3065 | /* Called only as a tasklet (software IRQ) */ | 3065 | /* Called only as a tasklet (software IRQ) */ |
3066 | int hostap_handle_sta_crypto(local_info_t *local, | 3066 | int hostap_handle_sta_crypto(local_info_t *local, |
3067 | struct ieee80211_hdr_4addr *hdr, | 3067 | struct ieee80211_hdr_4addr *hdr, |
3068 | struct ieee80211_crypt_data **crypt, | 3068 | struct lib80211_crypt_data **crypt, |
3069 | void **sta_ptr) | 3069 | void **sta_ptr) |
3070 | { | 3070 | { |
3071 | struct sta_info *sta; | 3071 | struct sta_info *sta; |
@@ -3213,7 +3213,7 @@ void hostap_update_rates(local_info_t *local) | |||
3213 | 3213 | ||
3214 | 3214 | ||
3215 | void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent, | 3215 | void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent, |
3216 | struct ieee80211_crypt_data ***crypt) | 3216 | struct lib80211_crypt_data ***crypt) |
3217 | { | 3217 | { |
3218 | struct sta_info *sta; | 3218 | struct sta_info *sta; |
3219 | 3219 | ||
diff --git a/drivers/net/wireless/hostap/hostap_ap.h b/drivers/net/wireless/hostap/hostap_ap.h index 2fa2452b6b07..d36e4b175336 100644 --- a/drivers/net/wireless/hostap/hostap_ap.h +++ b/drivers/net/wireless/hostap/hostap_ap.h | |||
@@ -74,7 +74,7 @@ struct sta_info { | |||
74 | u32 tx_since_last_failure; | 74 | u32 tx_since_last_failure; |
75 | u32 tx_consecutive_exc; | 75 | u32 tx_consecutive_exc; |
76 | 76 | ||
77 | struct ieee80211_crypt_data *crypt; | 77 | struct lib80211_crypt_data *crypt; |
78 | 78 | ||
79 | int ap; /* whether this station is an AP */ | 79 | int ap; /* whether this station is an AP */ |
80 | 80 | ||
@@ -209,7 +209,7 @@ struct ap_data { | |||
209 | 209 | ||
210 | /* WEP operations for generating challenges to be used with shared key | 210 | /* WEP operations for generating challenges to be used with shared key |
211 | * authentication */ | 211 | * authentication */ |
212 | struct ieee80211_crypto_ops *crypt; | 212 | struct lib80211_crypto_ops *crypt; |
213 | void *crypt_priv; | 213 | void *crypt_priv; |
214 | #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ | 214 | #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ |
215 | }; | 215 | }; |
@@ -229,7 +229,7 @@ typedef enum { | |||
229 | struct hostap_tx_data { | 229 | struct hostap_tx_data { |
230 | struct sk_buff *skb; | 230 | struct sk_buff *skb; |
231 | int host_encrypt; | 231 | int host_encrypt; |
232 | struct ieee80211_crypt_data *crypt; | 232 | struct lib80211_crypt_data *crypt; |
233 | void *sta_ptr; | 233 | void *sta_ptr; |
234 | }; | 234 | }; |
235 | ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx); | 235 | ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx); |
@@ -244,7 +244,7 @@ ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev, | |||
244 | struct hostap_80211_rx_status *rx_stats, | 244 | struct hostap_80211_rx_status *rx_stats, |
245 | int wds); | 245 | int wds); |
246 | int hostap_handle_sta_crypto(local_info_t *local, struct ieee80211_hdr_4addr *hdr, | 246 | int hostap_handle_sta_crypto(local_info_t *local, struct ieee80211_hdr_4addr *hdr, |
247 | struct ieee80211_crypt_data **crypt, | 247 | struct lib80211_crypt_data **crypt, |
248 | void **sta_ptr); | 248 | void **sta_ptr); |
249 | int hostap_is_sta_assoc(struct ap_data *ap, u8 *sta_addr); | 249 | int hostap_is_sta_assoc(struct ap_data *ap, u8 *sta_addr); |
250 | int hostap_is_sta_authorized(struct ap_data *ap, u8 *sta_addr); | 250 | int hostap_is_sta_authorized(struct ap_data *ap, u8 *sta_addr); |
diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c index fd7f7ceeac46..0f27059bbe85 100644 --- a/drivers/net/wireless/hostap/hostap_hw.c +++ b/drivers/net/wireless/hostap/hostap_hw.c | |||
@@ -47,7 +47,7 @@ | |||
47 | #include <linux/wireless.h> | 47 | #include <linux/wireless.h> |
48 | #include <net/iw_handler.h> | 48 | #include <net/iw_handler.h> |
49 | #include <net/ieee80211.h> | 49 | #include <net/ieee80211.h> |
50 | #include <net/ieee80211_crypt.h> | 50 | #include <net/lib80211.h> |
51 | #include <asm/irq.h> | 51 | #include <asm/irq.h> |
52 | 52 | ||
53 | #include "hostap_80211.h" | 53 | #include "hostap_80211.h" |
@@ -2788,45 +2788,6 @@ static void prism2_check_sta_fw_version(local_info_t *local) | |||
2788 | } | 2788 | } |
2789 | 2789 | ||
2790 | 2790 | ||
2791 | static void prism2_crypt_deinit_entries(local_info_t *local, int force) | ||
2792 | { | ||
2793 | struct list_head *ptr, *n; | ||
2794 | struct ieee80211_crypt_data *entry; | ||
2795 | |||
2796 | for (ptr = local->crypt_deinit_list.next, n = ptr->next; | ||
2797 | ptr != &local->crypt_deinit_list; ptr = n, n = ptr->next) { | ||
2798 | entry = list_entry(ptr, struct ieee80211_crypt_data, list); | ||
2799 | |||
2800 | if (atomic_read(&entry->refcnt) != 0 && !force) | ||
2801 | continue; | ||
2802 | |||
2803 | list_del(ptr); | ||
2804 | |||
2805 | if (entry->ops) | ||
2806 | entry->ops->deinit(entry->priv); | ||
2807 | kfree(entry); | ||
2808 | } | ||
2809 | } | ||
2810 | |||
2811 | |||
2812 | static void prism2_crypt_deinit_handler(unsigned long data) | ||
2813 | { | ||
2814 | local_info_t *local = (local_info_t *) data; | ||
2815 | unsigned long flags; | ||
2816 | |||
2817 | spin_lock_irqsave(&local->lock, flags); | ||
2818 | prism2_crypt_deinit_entries(local, 0); | ||
2819 | if (!list_empty(&local->crypt_deinit_list)) { | ||
2820 | printk(KERN_DEBUG "%s: entries remaining in delayed crypt " | ||
2821 | "deletion list\n", local->dev->name); | ||
2822 | local->crypt_deinit_timer.expires = jiffies + HZ; | ||
2823 | add_timer(&local->crypt_deinit_timer); | ||
2824 | } | ||
2825 | spin_unlock_irqrestore(&local->lock, flags); | ||
2826 | |||
2827 | } | ||
2828 | |||
2829 | |||
2830 | static void hostap_passive_scan(unsigned long data) | 2791 | static void hostap_passive_scan(unsigned long data) |
2831 | { | 2792 | { |
2832 | local_info_t *local = (local_info_t *) data; | 2793 | local_info_t *local = (local_info_t *) data; |
@@ -3250,10 +3211,8 @@ while (0) | |||
3250 | 3211 | ||
3251 | INIT_LIST_HEAD(&local->cmd_queue); | 3212 | INIT_LIST_HEAD(&local->cmd_queue); |
3252 | init_waitqueue_head(&local->hostscan_wq); | 3213 | init_waitqueue_head(&local->hostscan_wq); |
3253 | INIT_LIST_HEAD(&local->crypt_deinit_list); | 3214 | |
3254 | init_timer(&local->crypt_deinit_timer); | 3215 | lib80211_crypt_info_init(&local->crypt_info, dev->name, &local->lock); |
3255 | local->crypt_deinit_timer.data = (unsigned long) local; | ||
3256 | local->crypt_deinit_timer.function = prism2_crypt_deinit_handler; | ||
3257 | 3216 | ||
3258 | init_timer(&local->passive_scan_timer); | 3217 | init_timer(&local->passive_scan_timer); |
3259 | local->passive_scan_timer.data = (unsigned long) local; | 3218 | local->passive_scan_timer.data = (unsigned long) local; |
@@ -3354,9 +3313,7 @@ static void prism2_free_local_data(struct net_device *dev) | |||
3354 | 3313 | ||
3355 | flush_scheduled_work(); | 3314 | flush_scheduled_work(); |
3356 | 3315 | ||
3357 | if (timer_pending(&local->crypt_deinit_timer)) | 3316 | lib80211_crypt_info_free(&local->crypt_info); |
3358 | del_timer(&local->crypt_deinit_timer); | ||
3359 | prism2_crypt_deinit_entries(local, 1); | ||
3360 | 3317 | ||
3361 | if (timer_pending(&local->passive_scan_timer)) | 3318 | if (timer_pending(&local->passive_scan_timer)) |
3362 | del_timer(&local->passive_scan_timer); | 3319 | del_timer(&local->passive_scan_timer); |
@@ -3373,16 +3330,6 @@ static void prism2_free_local_data(struct net_device *dev) | |||
3373 | if (local->dev_enabled) | 3330 | if (local->dev_enabled) |
3374 | prism2_callback(local, PRISM2_CALLBACK_DISABLE); | 3331 | prism2_callback(local, PRISM2_CALLBACK_DISABLE); |
3375 | 3332 | ||
3376 | for (i = 0; i < WEP_KEYS; i++) { | ||
3377 | struct ieee80211_crypt_data *crypt = local->crypt[i]; | ||
3378 | if (crypt) { | ||
3379 | if (crypt->ops) | ||
3380 | crypt->ops->deinit(crypt->priv); | ||
3381 | kfree(crypt); | ||
3382 | local->crypt[i] = NULL; | ||
3383 | } | ||
3384 | } | ||
3385 | |||
3386 | if (local->ap != NULL) | 3333 | if (local->ap != NULL) |
3387 | hostap_free_data(local->ap); | 3334 | hostap_free_data(local->ap); |
3388 | 3335 | ||
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c index 2318c5df7a08..c40fdf4c79de 100644 --- a/drivers/net/wireless/hostap/hostap_ioctl.c +++ b/drivers/net/wireless/hostap/hostap_ioctl.c | |||
@@ -2,7 +2,7 @@ | |||
2 | 2 | ||
3 | #include <linux/types.h> | 3 | #include <linux/types.h> |
4 | #include <linux/ethtool.h> | 4 | #include <linux/ethtool.h> |
5 | #include <net/ieee80211_crypt.h> | 5 | #include <net/lib80211.h> |
6 | 6 | ||
7 | #include "hostap_wlan.h" | 7 | #include "hostap_wlan.h" |
8 | #include "hostap.h" | 8 | #include "hostap.h" |
@@ -116,32 +116,6 @@ static int prism2_get_name(struct net_device *dev, | |||
116 | } | 116 | } |
117 | 117 | ||
118 | 118 | ||
119 | static void prism2_crypt_delayed_deinit(local_info_t *local, | ||
120 | struct ieee80211_crypt_data **crypt) | ||
121 | { | ||
122 | struct ieee80211_crypt_data *tmp; | ||
123 | unsigned long flags; | ||
124 | |||
125 | tmp = *crypt; | ||
126 | *crypt = NULL; | ||
127 | |||
128 | if (tmp == NULL) | ||
129 | return; | ||
130 | |||
131 | /* must not run ops->deinit() while there may be pending encrypt or | ||
132 | * decrypt operations. Use a list of delayed deinits to avoid needing | ||
133 | * locking. */ | ||
134 | |||
135 | spin_lock_irqsave(&local->lock, flags); | ||
136 | list_add(&tmp->list, &local->crypt_deinit_list); | ||
137 | if (!timer_pending(&local->crypt_deinit_timer)) { | ||
138 | local->crypt_deinit_timer.expires = jiffies + HZ; | ||
139 | add_timer(&local->crypt_deinit_timer); | ||
140 | } | ||
141 | spin_unlock_irqrestore(&local->lock, flags); | ||
142 | } | ||
143 | |||
144 | |||
145 | static int prism2_ioctl_siwencode(struct net_device *dev, | 119 | static int prism2_ioctl_siwencode(struct net_device *dev, |
146 | struct iw_request_info *info, | 120 | struct iw_request_info *info, |
147 | struct iw_point *erq, char *keybuf) | 121 | struct iw_point *erq, char *keybuf) |
@@ -149,47 +123,47 @@ static int prism2_ioctl_siwencode(struct net_device *dev, | |||
149 | struct hostap_interface *iface; | 123 | struct hostap_interface *iface; |
150 | local_info_t *local; | 124 | local_info_t *local; |
151 | int i; | 125 | int i; |
152 | struct ieee80211_crypt_data **crypt; | 126 | struct lib80211_crypt_data **crypt; |
153 | 127 | ||
154 | iface = netdev_priv(dev); | 128 | iface = netdev_priv(dev); |
155 | local = iface->local; | 129 | local = iface->local; |
156 | 130 | ||
157 | i = erq->flags & IW_ENCODE_INDEX; | 131 | i = erq->flags & IW_ENCODE_INDEX; |
158 | if (i < 1 || i > 4) | 132 | if (i < 1 || i > 4) |
159 | i = local->tx_keyidx; | 133 | i = local->crypt_info.tx_keyidx; |
160 | else | 134 | else |
161 | i--; | 135 | i--; |
162 | if (i < 0 || i >= WEP_KEYS) | 136 | if (i < 0 || i >= WEP_KEYS) |
163 | return -EINVAL; | 137 | return -EINVAL; |
164 | 138 | ||
165 | crypt = &local->crypt[i]; | 139 | crypt = &local->crypt_info.crypt[i]; |
166 | 140 | ||
167 | if (erq->flags & IW_ENCODE_DISABLED) { | 141 | if (erq->flags & IW_ENCODE_DISABLED) { |
168 | if (*crypt) | 142 | if (*crypt) |
169 | prism2_crypt_delayed_deinit(local, crypt); | 143 | lib80211_crypt_delayed_deinit(&local->crypt_info, crypt); |
170 | goto done; | 144 | goto done; |
171 | } | 145 | } |
172 | 146 | ||
173 | if (*crypt != NULL && (*crypt)->ops != NULL && | 147 | if (*crypt != NULL && (*crypt)->ops != NULL && |
174 | strcmp((*crypt)->ops->name, "WEP") != 0) { | 148 | strcmp((*crypt)->ops->name, "WEP") != 0) { |
175 | /* changing to use WEP; deinit previously used algorithm */ | 149 | /* changing to use WEP; deinit previously used algorithm */ |
176 | prism2_crypt_delayed_deinit(local, crypt); | 150 | lib80211_crypt_delayed_deinit(&local->crypt_info, crypt); |
177 | } | 151 | } |
178 | 152 | ||
179 | if (*crypt == NULL) { | 153 | if (*crypt == NULL) { |
180 | struct ieee80211_crypt_data *new_crypt; | 154 | struct lib80211_crypt_data *new_crypt; |
181 | 155 | ||
182 | /* take WEP into use */ | 156 | /* take WEP into use */ |
183 | new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data), | 157 | new_crypt = kzalloc(sizeof(struct lib80211_crypt_data), |
184 | GFP_KERNEL); | 158 | GFP_KERNEL); |
185 | if (new_crypt == NULL) | 159 | if (new_crypt == NULL) |
186 | return -ENOMEM; | 160 | return -ENOMEM; |
187 | new_crypt->ops = ieee80211_get_crypto_ops("WEP"); | 161 | new_crypt->ops = lib80211_get_crypto_ops("WEP"); |
188 | if (!new_crypt->ops) { | 162 | if (!new_crypt->ops) { |
189 | request_module("ieee80211_crypt_wep"); | 163 | request_module("lib80211_crypt_wep"); |
190 | new_crypt->ops = ieee80211_get_crypto_ops("WEP"); | 164 | new_crypt->ops = lib80211_get_crypto_ops("WEP"); |
191 | } | 165 | } |
192 | if (new_crypt->ops) | 166 | if (new_crypt->ops && try_module_get(new_crypt->ops->owner)) |
193 | new_crypt->priv = new_crypt->ops->init(i); | 167 | new_crypt->priv = new_crypt->ops->init(i); |
194 | if (!new_crypt->ops || !new_crypt->priv) { | 168 | if (!new_crypt->ops || !new_crypt->priv) { |
195 | kfree(new_crypt); | 169 | kfree(new_crypt); |
@@ -210,16 +184,16 @@ static int prism2_ioctl_siwencode(struct net_device *dev, | |||
210 | memset(keybuf + erq->length, 0, len - erq->length); | 184 | memset(keybuf + erq->length, 0, len - erq->length); |
211 | (*crypt)->ops->set_key(keybuf, len, NULL, (*crypt)->priv); | 185 | (*crypt)->ops->set_key(keybuf, len, NULL, (*crypt)->priv); |
212 | for (j = 0; j < WEP_KEYS; j++) { | 186 | for (j = 0; j < WEP_KEYS; j++) { |
213 | if (j != i && local->crypt[j]) { | 187 | if (j != i && local->crypt_info.crypt[j]) { |
214 | first = 0; | 188 | first = 0; |
215 | break; | 189 | break; |
216 | } | 190 | } |
217 | } | 191 | } |
218 | if (first) | 192 | if (first) |
219 | local->tx_keyidx = i; | 193 | local->crypt_info.tx_keyidx = i; |
220 | } else { | 194 | } else { |
221 | /* No key data - just set the default TX key index */ | 195 | /* No key data - just set the default TX key index */ |
222 | local->tx_keyidx = i; | 196 | local->crypt_info.tx_keyidx = i; |
223 | } | 197 | } |
224 | 198 | ||
225 | done: | 199 | done: |
@@ -252,20 +226,20 @@ static int prism2_ioctl_giwencode(struct net_device *dev, | |||
252 | local_info_t *local; | 226 | local_info_t *local; |
253 | int i, len; | 227 | int i, len; |
254 | u16 val; | 228 | u16 val; |
255 | struct ieee80211_crypt_data *crypt; | 229 | struct lib80211_crypt_data *crypt; |
256 | 230 | ||
257 | iface = netdev_priv(dev); | 231 | iface = netdev_priv(dev); |
258 | local = iface->local; | 232 | local = iface->local; |
259 | 233 | ||
260 | i = erq->flags & IW_ENCODE_INDEX; | 234 | i = erq->flags & IW_ENCODE_INDEX; |
261 | if (i < 1 || i > 4) | 235 | if (i < 1 || i > 4) |
262 | i = local->tx_keyidx; | 236 | i = local->crypt_info.tx_keyidx; |
263 | else | 237 | else |
264 | i--; | 238 | i--; |
265 | if (i < 0 || i >= WEP_KEYS) | 239 | if (i < 0 || i >= WEP_KEYS) |
266 | return -EINVAL; | 240 | return -EINVAL; |
267 | 241 | ||
268 | crypt = local->crypt[i]; | 242 | crypt = local->crypt_info.crypt[i]; |
269 | erq->flags = i + 1; | 243 | erq->flags = i + 1; |
270 | 244 | ||
271 | if (crypt == NULL || crypt->ops == NULL) { | 245 | if (crypt == NULL || crypt->ops == NULL) { |
@@ -3227,8 +3201,8 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev, | |||
3227 | local_info_t *local = iface->local; | 3201 | local_info_t *local = iface->local; |
3228 | struct iw_encode_ext *ext = (struct iw_encode_ext *) extra; | 3202 | struct iw_encode_ext *ext = (struct iw_encode_ext *) extra; |
3229 | int i, ret = 0; | 3203 | int i, ret = 0; |
3230 | struct ieee80211_crypto_ops *ops; | 3204 | struct lib80211_crypto_ops *ops; |
3231 | struct ieee80211_crypt_data **crypt; | 3205 | struct lib80211_crypt_data **crypt; |
3232 | void *sta_ptr; | 3206 | void *sta_ptr; |
3233 | u8 *addr; | 3207 | u8 *addr; |
3234 | const char *alg, *module; | 3208 | const char *alg, *module; |
@@ -3237,7 +3211,7 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev, | |||
3237 | if (i > WEP_KEYS) | 3211 | if (i > WEP_KEYS) |
3238 | return -EINVAL; | 3212 | return -EINVAL; |
3239 | if (i < 1 || i > WEP_KEYS) | 3213 | if (i < 1 || i > WEP_KEYS) |
3240 | i = local->tx_keyidx; | 3214 | i = local->crypt_info.tx_keyidx; |
3241 | else | 3215 | else |
3242 | i--; | 3216 | i--; |
3243 | if (i < 0 || i >= WEP_KEYS) | 3217 | if (i < 0 || i >= WEP_KEYS) |
@@ -3247,7 +3221,7 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev, | |||
3247 | if (addr[0] == 0xff && addr[1] == 0xff && addr[2] == 0xff && | 3221 | if (addr[0] == 0xff && addr[1] == 0xff && addr[2] == 0xff && |
3248 | addr[3] == 0xff && addr[4] == 0xff && addr[5] == 0xff) { | 3222 | addr[3] == 0xff && addr[4] == 0xff && addr[5] == 0xff) { |
3249 | sta_ptr = NULL; | 3223 | sta_ptr = NULL; |
3250 | crypt = &local->crypt[i]; | 3224 | crypt = &local->crypt_info.crypt[i]; |
3251 | } else { | 3225 | } else { |
3252 | if (i != 0) | 3226 | if (i != 0) |
3253 | return -EINVAL; | 3227 | return -EINVAL; |
@@ -3260,7 +3234,7 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev, | |||
3260 | * is emulated by using default key idx 0. | 3234 | * is emulated by using default key idx 0. |
3261 | */ | 3235 | */ |
3262 | i = 0; | 3236 | i = 0; |
3263 | crypt = &local->crypt[i]; | 3237 | crypt = &local->crypt_info.crypt[i]; |
3264 | } else | 3238 | } else |
3265 | return -EINVAL; | 3239 | return -EINVAL; |
3266 | } | 3240 | } |
@@ -3269,22 +3243,22 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev, | |||
3269 | if ((erq->flags & IW_ENCODE_DISABLED) || | 3243 | if ((erq->flags & IW_ENCODE_DISABLED) || |
3270 | ext->alg == IW_ENCODE_ALG_NONE) { | 3244 | ext->alg == IW_ENCODE_ALG_NONE) { |
3271 | if (*crypt) | 3245 | if (*crypt) |
3272 | prism2_crypt_delayed_deinit(local, crypt); | 3246 | lib80211_crypt_delayed_deinit(&local->crypt_info, crypt); |
3273 | goto done; | 3247 | goto done; |
3274 | } | 3248 | } |
3275 | 3249 | ||
3276 | switch (ext->alg) { | 3250 | switch (ext->alg) { |
3277 | case IW_ENCODE_ALG_WEP: | 3251 | case IW_ENCODE_ALG_WEP: |
3278 | alg = "WEP"; | 3252 | alg = "WEP"; |
3279 | module = "ieee80211_crypt_wep"; | 3253 | module = "lib80211_crypt_wep"; |
3280 | break; | 3254 | break; |
3281 | case IW_ENCODE_ALG_TKIP: | 3255 | case IW_ENCODE_ALG_TKIP: |
3282 | alg = "TKIP"; | 3256 | alg = "TKIP"; |
3283 | module = "ieee80211_crypt_tkip"; | 3257 | module = "lib80211_crypt_tkip"; |
3284 | break; | 3258 | break; |
3285 | case IW_ENCODE_ALG_CCMP: | 3259 | case IW_ENCODE_ALG_CCMP: |
3286 | alg = "CCMP"; | 3260 | alg = "CCMP"; |
3287 | module = "ieee80211_crypt_ccmp"; | 3261 | module = "lib80211_crypt_ccmp"; |
3288 | break; | 3262 | break; |
3289 | default: | 3263 | default: |
3290 | printk(KERN_DEBUG "%s: unsupported algorithm %d\n", | 3264 | printk(KERN_DEBUG "%s: unsupported algorithm %d\n", |
@@ -3293,10 +3267,10 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev, | |||
3293 | goto done; | 3267 | goto done; |
3294 | } | 3268 | } |
3295 | 3269 | ||
3296 | ops = ieee80211_get_crypto_ops(alg); | 3270 | ops = lib80211_get_crypto_ops(alg); |
3297 | if (ops == NULL) { | 3271 | if (ops == NULL) { |
3298 | request_module(module); | 3272 | request_module(module); |
3299 | ops = ieee80211_get_crypto_ops(alg); | 3273 | ops = lib80211_get_crypto_ops(alg); |
3300 | } | 3274 | } |
3301 | if (ops == NULL) { | 3275 | if (ops == NULL) { |
3302 | printk(KERN_DEBUG "%s: unknown crypto alg '%s'\n", | 3276 | printk(KERN_DEBUG "%s: unknown crypto alg '%s'\n", |
@@ -3315,18 +3289,19 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev, | |||
3315 | } | 3289 | } |
3316 | 3290 | ||
3317 | if (*crypt == NULL || (*crypt)->ops != ops) { | 3291 | if (*crypt == NULL || (*crypt)->ops != ops) { |
3318 | struct ieee80211_crypt_data *new_crypt; | 3292 | struct lib80211_crypt_data *new_crypt; |
3319 | 3293 | ||
3320 | prism2_crypt_delayed_deinit(local, crypt); | 3294 | lib80211_crypt_delayed_deinit(&local->crypt_info, crypt); |
3321 | 3295 | ||
3322 | new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data), | 3296 | new_crypt = kzalloc(sizeof(struct lib80211_crypt_data), |
3323 | GFP_KERNEL); | 3297 | GFP_KERNEL); |
3324 | if (new_crypt == NULL) { | 3298 | if (new_crypt == NULL) { |
3325 | ret = -ENOMEM; | 3299 | ret = -ENOMEM; |
3326 | goto done; | 3300 | goto done; |
3327 | } | 3301 | } |
3328 | new_crypt->ops = ops; | 3302 | new_crypt->ops = ops; |
3329 | new_crypt->priv = new_crypt->ops->init(i); | 3303 | if (new_crypt->ops && try_module_get(new_crypt->ops->owner)) |
3304 | new_crypt->priv = new_crypt->ops->init(i); | ||
3330 | if (new_crypt->priv == NULL) { | 3305 | if (new_crypt->priv == NULL) { |
3331 | kfree(new_crypt); | 3306 | kfree(new_crypt); |
3332 | ret = -EINVAL; | 3307 | ret = -EINVAL; |
@@ -3354,20 +3329,20 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev, | |||
3354 | 3329 | ||
3355 | if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { | 3330 | if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { |
3356 | if (!sta_ptr) | 3331 | if (!sta_ptr) |
3357 | local->tx_keyidx = i; | 3332 | local->crypt_info.tx_keyidx = i; |
3358 | } | 3333 | } |
3359 | 3334 | ||
3360 | 3335 | ||
3361 | if (sta_ptr == NULL && ext->key_len > 0) { | 3336 | if (sta_ptr == NULL && ext->key_len > 0) { |
3362 | int first = 1, j; | 3337 | int first = 1, j; |
3363 | for (j = 0; j < WEP_KEYS; j++) { | 3338 | for (j = 0; j < WEP_KEYS; j++) { |
3364 | if (j != i && local->crypt[j]) { | 3339 | if (j != i && local->crypt_info.crypt[j]) { |
3365 | first = 0; | 3340 | first = 0; |
3366 | break; | 3341 | break; |
3367 | } | 3342 | } |
3368 | } | 3343 | } |
3369 | if (first) | 3344 | if (first) |
3370 | local->tx_keyidx = i; | 3345 | local->crypt_info.tx_keyidx = i; |
3371 | } | 3346 | } |
3372 | 3347 | ||
3373 | done: | 3348 | done: |
@@ -3399,7 +3374,7 @@ static int prism2_ioctl_giwencodeext(struct net_device *dev, | |||
3399 | { | 3374 | { |
3400 | struct hostap_interface *iface = netdev_priv(dev); | 3375 | struct hostap_interface *iface = netdev_priv(dev); |
3401 | local_info_t *local = iface->local; | 3376 | local_info_t *local = iface->local; |
3402 | struct ieee80211_crypt_data **crypt; | 3377 | struct lib80211_crypt_data **crypt; |
3403 | void *sta_ptr; | 3378 | void *sta_ptr; |
3404 | int max_key_len, i; | 3379 | int max_key_len, i; |
3405 | struct iw_encode_ext *ext = (struct iw_encode_ext *) extra; | 3380 | struct iw_encode_ext *ext = (struct iw_encode_ext *) extra; |
@@ -3411,7 +3386,7 @@ static int prism2_ioctl_giwencodeext(struct net_device *dev, | |||
3411 | 3386 | ||
3412 | i = erq->flags & IW_ENCODE_INDEX; | 3387 | i = erq->flags & IW_ENCODE_INDEX; |
3413 | if (i < 1 || i > WEP_KEYS) | 3388 | if (i < 1 || i > WEP_KEYS) |
3414 | i = local->tx_keyidx; | 3389 | i = local->crypt_info.tx_keyidx; |
3415 | else | 3390 | else |
3416 | i--; | 3391 | i--; |
3417 | 3392 | ||
@@ -3419,7 +3394,7 @@ static int prism2_ioctl_giwencodeext(struct net_device *dev, | |||
3419 | if (addr[0] == 0xff && addr[1] == 0xff && addr[2] == 0xff && | 3394 | if (addr[0] == 0xff && addr[1] == 0xff && addr[2] == 0xff && |
3420 | addr[3] == 0xff && addr[4] == 0xff && addr[5] == 0xff) { | 3395 | addr[3] == 0xff && addr[4] == 0xff && addr[5] == 0xff) { |
3421 | sta_ptr = NULL; | 3396 | sta_ptr = NULL; |
3422 | crypt = &local->crypt[i]; | 3397 | crypt = &local->crypt_info.crypt[i]; |
3423 | } else { | 3398 | } else { |
3424 | i = 0; | 3399 | i = 0; |
3425 | sta_ptr = ap_crypt_get_ptrs(local->ap, addr, 0, &crypt); | 3400 | sta_ptr = ap_crypt_get_ptrs(local->ap, addr, 0, &crypt); |
@@ -3468,8 +3443,8 @@ static int prism2_ioctl_set_encryption(local_info_t *local, | |||
3468 | int param_len) | 3443 | int param_len) |
3469 | { | 3444 | { |
3470 | int ret = 0; | 3445 | int ret = 0; |
3471 | struct ieee80211_crypto_ops *ops; | 3446 | struct lib80211_crypto_ops *ops; |
3472 | struct ieee80211_crypt_data **crypt; | 3447 | struct lib80211_crypt_data **crypt; |
3473 | void *sta_ptr; | 3448 | void *sta_ptr; |
3474 | 3449 | ||
3475 | param->u.crypt.err = 0; | 3450 | param->u.crypt.err = 0; |
@@ -3486,7 +3461,7 @@ static int prism2_ioctl_set_encryption(local_info_t *local, | |||
3486 | if (param->u.crypt.idx >= WEP_KEYS) | 3461 | if (param->u.crypt.idx >= WEP_KEYS) |
3487 | return -EINVAL; | 3462 | return -EINVAL; |
3488 | sta_ptr = NULL; | 3463 | sta_ptr = NULL; |
3489 | crypt = &local->crypt[param->u.crypt.idx]; | 3464 | crypt = &local->crypt_info.crypt[param->u.crypt.idx]; |
3490 | } else { | 3465 | } else { |
3491 | if (param->u.crypt.idx) | 3466 | if (param->u.crypt.idx) |
3492 | return -EINVAL; | 3467 | return -EINVAL; |
@@ -3503,20 +3478,20 @@ static int prism2_ioctl_set_encryption(local_info_t *local, | |||
3503 | 3478 | ||
3504 | if (strcmp(param->u.crypt.alg, "none") == 0) { | 3479 | if (strcmp(param->u.crypt.alg, "none") == 0) { |
3505 | if (crypt) | 3480 | if (crypt) |
3506 | prism2_crypt_delayed_deinit(local, crypt); | 3481 | lib80211_crypt_delayed_deinit(&local->crypt_info, crypt); |
3507 | goto done; | 3482 | goto done; |
3508 | } | 3483 | } |
3509 | 3484 | ||
3510 | ops = ieee80211_get_crypto_ops(param->u.crypt.alg); | 3485 | ops = lib80211_get_crypto_ops(param->u.crypt.alg); |
3511 | if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) { | 3486 | if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) { |
3512 | request_module("ieee80211_crypt_wep"); | 3487 | request_module("lib80211_crypt_wep"); |
3513 | ops = ieee80211_get_crypto_ops(param->u.crypt.alg); | 3488 | ops = lib80211_get_crypto_ops(param->u.crypt.alg); |
3514 | } else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) { | 3489 | } else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) { |
3515 | request_module("ieee80211_crypt_tkip"); | 3490 | request_module("lib80211_crypt_tkip"); |
3516 | ops = ieee80211_get_crypto_ops(param->u.crypt.alg); | 3491 | ops = lib80211_get_crypto_ops(param->u.crypt.alg); |
3517 | } else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) { | 3492 | } else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) { |
3518 | request_module("ieee80211_crypt_ccmp"); | 3493 | request_module("lib80211_crypt_ccmp"); |
3519 | ops = ieee80211_get_crypto_ops(param->u.crypt.alg); | 3494 | ops = lib80211_get_crypto_ops(param->u.crypt.alg); |
3520 | } | 3495 | } |
3521 | if (ops == NULL) { | 3496 | if (ops == NULL) { |
3522 | printk(KERN_DEBUG "%s: unknown crypto alg '%s'\n", | 3497 | printk(KERN_DEBUG "%s: unknown crypto alg '%s'\n", |
@@ -3531,11 +3506,11 @@ static int prism2_ioctl_set_encryption(local_info_t *local, | |||
3531 | local->host_decrypt = local->host_encrypt = 1; | 3506 | local->host_decrypt = local->host_encrypt = 1; |
3532 | 3507 | ||
3533 | if (*crypt == NULL || (*crypt)->ops != ops) { | 3508 | if (*crypt == NULL || (*crypt)->ops != ops) { |
3534 | struct ieee80211_crypt_data *new_crypt; | 3509 | struct lib80211_crypt_data *new_crypt; |
3535 | 3510 | ||
3536 | prism2_crypt_delayed_deinit(local, crypt); | 3511 | lib80211_crypt_delayed_deinit(&local->crypt_info, crypt); |
3537 | 3512 | ||
3538 | new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data), | 3513 | new_crypt = kzalloc(sizeof(struct lib80211_crypt_data), |
3539 | GFP_KERNEL); | 3514 | GFP_KERNEL); |
3540 | if (new_crypt == NULL) { | 3515 | if (new_crypt == NULL) { |
3541 | ret = -ENOMEM; | 3516 | ret = -ENOMEM; |
@@ -3568,7 +3543,7 @@ static int prism2_ioctl_set_encryption(local_info_t *local, | |||
3568 | 3543 | ||
3569 | if (param->u.crypt.flags & HOSTAP_CRYPT_FLAG_SET_TX_KEY) { | 3544 | if (param->u.crypt.flags & HOSTAP_CRYPT_FLAG_SET_TX_KEY) { |
3570 | if (!sta_ptr) | 3545 | if (!sta_ptr) |
3571 | local->tx_keyidx = param->u.crypt.idx; | 3546 | local->crypt_info.tx_keyidx = param->u.crypt.idx; |
3572 | else if (param->u.crypt.idx) { | 3547 | else if (param->u.crypt.idx) { |
3573 | printk(KERN_DEBUG "%s: TX key idx setting failed\n", | 3548 | printk(KERN_DEBUG "%s: TX key idx setting failed\n", |
3574 | local->dev->name); | 3549 | local->dev->name); |
@@ -3604,7 +3579,7 @@ static int prism2_ioctl_get_encryption(local_info_t *local, | |||
3604 | struct prism2_hostapd_param *param, | 3579 | struct prism2_hostapd_param *param, |
3605 | int param_len) | 3580 | int param_len) |
3606 | { | 3581 | { |
3607 | struct ieee80211_crypt_data **crypt; | 3582 | struct lib80211_crypt_data **crypt; |
3608 | void *sta_ptr; | 3583 | void *sta_ptr; |
3609 | int max_key_len; | 3584 | int max_key_len; |
3610 | 3585 | ||
@@ -3620,8 +3595,8 @@ static int prism2_ioctl_get_encryption(local_info_t *local, | |||
3620 | param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) { | 3595 | param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) { |
3621 | sta_ptr = NULL; | 3596 | sta_ptr = NULL; |
3622 | if (param->u.crypt.idx >= WEP_KEYS) | 3597 | if (param->u.crypt.idx >= WEP_KEYS) |
3623 | param->u.crypt.idx = local->tx_keyidx; | 3598 | param->u.crypt.idx = local->crypt_info.tx_keyidx; |
3624 | crypt = &local->crypt[param->u.crypt.idx]; | 3599 | crypt = &local->crypt_info.crypt[param->u.crypt.idx]; |
3625 | } else { | 3600 | } else { |
3626 | param->u.crypt.idx = 0; | 3601 | param->u.crypt.idx = 0; |
3627 | sta_ptr = ap_crypt_get_ptrs(local->ap, param->sta_addr, 0, | 3602 | sta_ptr = ap_crypt_get_ptrs(local->ap, param->sta_addr, 0, |
diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c index 4c36eb2fafd1..02a312ca8607 100644 --- a/drivers/net/wireless/hostap/hostap_main.c +++ b/drivers/net/wireless/hostap/hostap_main.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #include <net/net_namespace.h> | 27 | #include <net/net_namespace.h> |
28 | #include <net/iw_handler.h> | 28 | #include <net/iw_handler.h> |
29 | #include <net/ieee80211.h> | 29 | #include <net/ieee80211.h> |
30 | #include <net/ieee80211_crypt.h> | 30 | #include <net/lib80211.h> |
31 | #include <asm/uaccess.h> | 31 | #include <asm/uaccess.h> |
32 | 32 | ||
33 | #include "hostap_wlan.h" | 33 | #include "hostap_wlan.h" |
@@ -343,10 +343,11 @@ int hostap_set_encryption(local_info_t *local) | |||
343 | char keybuf[WEP_KEY_LEN + 1]; | 343 | char keybuf[WEP_KEY_LEN + 1]; |
344 | enum { NONE, WEP, OTHER } encrypt_type; | 344 | enum { NONE, WEP, OTHER } encrypt_type; |
345 | 345 | ||
346 | idx = local->tx_keyidx; | 346 | idx = local->crypt_info.tx_keyidx; |
347 | if (local->crypt[idx] == NULL || local->crypt[idx]->ops == NULL) | 347 | if (local->crypt_info.crypt[idx] == NULL || |
348 | local->crypt_info.crypt[idx]->ops == NULL) | ||
348 | encrypt_type = NONE; | 349 | encrypt_type = NONE; |
349 | else if (strcmp(local->crypt[idx]->ops->name, "WEP") == 0) | 350 | else if (strcmp(local->crypt_info.crypt[idx]->ops->name, "WEP") == 0) |
350 | encrypt_type = WEP; | 351 | encrypt_type = WEP; |
351 | else | 352 | else |
352 | encrypt_type = OTHER; | 353 | encrypt_type = OTHER; |
@@ -394,17 +395,17 @@ int hostap_set_encryption(local_info_t *local) | |||
394 | /* 104-bit support seems to require that all the keys are set to the | 395 | /* 104-bit support seems to require that all the keys are set to the |
395 | * same keylen */ | 396 | * same keylen */ |
396 | keylen = 6; /* first 5 octets */ | 397 | keylen = 6; /* first 5 octets */ |
397 | len = local->crypt[idx]->ops->get_key(keybuf, sizeof(keybuf), | 398 | len = local->crypt_info.crypt[idx]->ops->get_key(keybuf, sizeof(keybuf), NULL, |
398 | NULL, local->crypt[idx]->priv); | 399 | local->crypt_info.crypt[idx]->priv); |
399 | if (idx >= 0 && idx < WEP_KEYS && len > 5) | 400 | if (idx >= 0 && idx < WEP_KEYS && len > 5) |
400 | keylen = WEP_KEY_LEN + 1; /* first 13 octets */ | 401 | keylen = WEP_KEY_LEN + 1; /* first 13 octets */ |
401 | 402 | ||
402 | for (i = 0; i < WEP_KEYS; i++) { | 403 | for (i = 0; i < WEP_KEYS; i++) { |
403 | memset(keybuf, 0, sizeof(keybuf)); | 404 | memset(keybuf, 0, sizeof(keybuf)); |
404 | if (local->crypt[i]) { | 405 | if (local->crypt_info.crypt[i]) { |
405 | (void) local->crypt[i]->ops->get_key( | 406 | (void) local->crypt_info.crypt[i]->ops->get_key( |
406 | keybuf, sizeof(keybuf), | 407 | keybuf, sizeof(keybuf), |
407 | NULL, local->crypt[i]->priv); | 408 | NULL, local->crypt_info.crypt[i]->priv); |
408 | } | 409 | } |
409 | if (local->func->set_rid(local->dev, | 410 | if (local->func->set_rid(local->dev, |
410 | HFA384X_RID_CNFDEFAULTKEY0 + i, | 411 | HFA384X_RID_CNFDEFAULTKEY0 + i, |
diff --git a/drivers/net/wireless/hostap/hostap_proc.c b/drivers/net/wireless/hostap/hostap_proc.c index ae7d3caf3dae..005ff25a405f 100644 --- a/drivers/net/wireless/hostap/hostap_proc.c +++ b/drivers/net/wireless/hostap/hostap_proc.c | |||
@@ -2,7 +2,7 @@ | |||
2 | 2 | ||
3 | #include <linux/types.h> | 3 | #include <linux/types.h> |
4 | #include <linux/proc_fs.h> | 4 | #include <linux/proc_fs.h> |
5 | #include <net/ieee80211_crypt.h> | 5 | #include <net/lib80211.h> |
6 | 6 | ||
7 | #include "hostap_wlan.h" | 7 | #include "hostap_wlan.h" |
8 | #include "hostap.h" | 8 | #include "hostap.h" |
@@ -36,9 +36,10 @@ static int prism2_debug_proc_read(char *page, char **start, off_t off, | |||
36 | p += sprintf(p, "dev_enabled=%d\n", local->dev_enabled); | 36 | p += sprintf(p, "dev_enabled=%d\n", local->dev_enabled); |
37 | p += sprintf(p, "sw_tick_stuck=%d\n", local->sw_tick_stuck); | 37 | p += sprintf(p, "sw_tick_stuck=%d\n", local->sw_tick_stuck); |
38 | for (i = 0; i < WEP_KEYS; i++) { | 38 | for (i = 0; i < WEP_KEYS; i++) { |
39 | if (local->crypt[i] && local->crypt[i]->ops) { | 39 | if (local->crypt_info.crypt[i] && |
40 | p += sprintf(p, "crypt[%d]=%s\n", | 40 | local->crypt_info.crypt[i]->ops) { |
41 | i, local->crypt[i]->ops->name); | 41 | p += sprintf(p, "crypt[%d]=%s\n", i, |
42 | local->crypt_info.crypt[i]->ops->name); | ||
42 | } | 43 | } |
43 | } | 44 | } |
44 | p += sprintf(p, "pri_only=%d\n", local->pri_only); | 45 | p += sprintf(p, "pri_only=%d\n", local->pri_only); |
@@ -206,12 +207,13 @@ static int prism2_crypt_proc_read(char *page, char **start, off_t off, | |||
206 | return 0; | 207 | return 0; |
207 | } | 208 | } |
208 | 209 | ||
209 | p += sprintf(p, "tx_keyidx=%d\n", local->tx_keyidx); | 210 | p += sprintf(p, "tx_keyidx=%d\n", local->crypt_info.tx_keyidx); |
210 | for (i = 0; i < WEP_KEYS; i++) { | 211 | for (i = 0; i < WEP_KEYS; i++) { |
211 | if (local->crypt[i] && local->crypt[i]->ops && | 212 | if (local->crypt_info.crypt[i] && |
212 | local->crypt[i]->ops->print_stats) { | 213 | local->crypt_info.crypt[i]->ops && |
213 | p = local->crypt[i]->ops->print_stats( | 214 | local->crypt_info.crypt[i]->ops->print_stats) { |
214 | p, local->crypt[i]->priv); | 215 | p = local->crypt_info.crypt[i]->ops->print_stats( |
216 | p, local->crypt_info.crypt[i]->priv); | ||
215 | } | 217 | } |
216 | } | 218 | } |
217 | 219 | ||
diff --git a/drivers/net/wireless/hostap/hostap_wlan.h b/drivers/net/wireless/hostap/hostap_wlan.h index d2c7a56b8b59..4d8d51a353cd 100644 --- a/drivers/net/wireless/hostap/hostap_wlan.h +++ b/drivers/net/wireless/hostap/hostap_wlan.h | |||
@@ -6,6 +6,7 @@ | |||
6 | #include <linux/mutex.h> | 6 | #include <linux/mutex.h> |
7 | #include <net/iw_handler.h> | 7 | #include <net/iw_handler.h> |
8 | #include <net/ieee80211_radiotap.h> | 8 | #include <net/ieee80211_radiotap.h> |
9 | #include <net/lib80211.h> | ||
9 | 10 | ||
10 | #include "hostap_config.h" | 11 | #include "hostap_config.h" |
11 | #include "hostap_common.h" | 12 | #include "hostap_common.h" |
@@ -763,10 +764,7 @@ struct local_info { | |||
763 | 764 | ||
764 | #define WEP_KEYS 4 | 765 | #define WEP_KEYS 4 |
765 | #define WEP_KEY_LEN 13 | 766 | #define WEP_KEY_LEN 13 |
766 | struct ieee80211_crypt_data *crypt[WEP_KEYS]; | 767 | struct lib80211_crypt_info crypt_info; |
767 | int tx_keyidx; /* default TX key index (crypt[tx_keyidx]) */ | ||
768 | struct timer_list crypt_deinit_timer; | ||
769 | struct list_head crypt_deinit_list; | ||
770 | 768 | ||
771 | int open_wep; /* allow unencrypted frames */ | 769 | int open_wep; /* allow unencrypted frames */ |
772 | int host_encrypt; | 770 | int host_encrypt; |
diff --git a/drivers/net/wireless/ipw2x00/Kconfig b/drivers/net/wireless/ipw2x00/Kconfig new file mode 100644 index 000000000000..3d5cc4463d4d --- /dev/null +++ b/drivers/net/wireless/ipw2x00/Kconfig | |||
@@ -0,0 +1,191 @@ | |||
1 | # | ||
2 | # Intel Centrino wireless drivers | ||
3 | # | ||
4 | |||
5 | config IPW2100 | ||
6 | tristate "Intel PRO/Wireless 2100 Network Connection" | ||
7 | depends on PCI && WLAN_80211 | ||
8 | select WIRELESS_EXT | ||
9 | select FW_LOADER | ||
10 | select LIB80211 | ||
11 | select LIBIPW | ||
12 | ---help--- | ||
13 | A driver for the Intel PRO/Wireless 2100 Network | ||
14 | Connection 802.11b wireless network adapter. | ||
15 | |||
16 | See <file:Documentation/networking/README.ipw2100> for information on | ||
17 | the capabilities currently enabled in this driver and for tips | ||
18 | for debugging issues and problems. | ||
19 | |||
20 | In order to use this driver, you will need a firmware image for it. | ||
21 | You can obtain the firmware from | ||
22 | <http://ipw2100.sf.net/>. Once you have the firmware image, you | ||
23 | will need to place it in /lib/firmware. | ||
24 | |||
25 | You will also very likely need the Wireless Tools in order to | ||
26 | configure your card: | ||
27 | |||
28 | <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>. | ||
29 | |||
30 | It is recommended that you compile this driver as a module (M) | ||
31 | rather than built-in (Y). This driver requires firmware at device | ||
32 | initialization time, and when built-in this typically happens | ||
33 | before the filesystem is accessible (hence firmware will be | ||
34 | unavailable and initialization will fail). If you do choose to build | ||
35 | this driver into your kernel image, you can avoid this problem by | ||
36 | including the firmware and a firmware loader in an initramfs. | ||
37 | |||
38 | config IPW2100_MONITOR | ||
39 | bool "Enable promiscuous mode" | ||
40 | depends on IPW2100 | ||
41 | ---help--- | ||
42 | Enables promiscuous/monitor mode support for the ipw2100 driver. | ||
43 | With this feature compiled into the driver, you can switch to | ||
44 | promiscuous mode via the Wireless Tool's Monitor mode. While in this | ||
45 | mode, no packets can be sent. | ||
46 | |||
47 | config IPW2100_DEBUG | ||
48 | bool "Enable full debugging output in IPW2100 module." | ||
49 | depends on IPW2100 | ||
50 | ---help--- | ||
51 | This option will enable debug tracing output for the IPW2100. | ||
52 | |||
53 | This will result in the kernel module being ~60k larger. You can | ||
54 | control which debug output is sent to the kernel log by setting the | ||
55 | value in | ||
56 | |||
57 | /sys/bus/pci/drivers/ipw2100/debug_level | ||
58 | |||
59 | This entry will only exist if this option is enabled. | ||
60 | |||
61 | If you are not trying to debug or develop the IPW2100 driver, you | ||
62 | most likely want to say N here. | ||
63 | |||
64 | config IPW2200 | ||
65 | tristate "Intel PRO/Wireless 2200BG and 2915ABG Network Connection" | ||
66 | depends on PCI && WLAN_80211 | ||
67 | select WIRELESS_EXT | ||
68 | select FW_LOADER | ||
69 | select LIB80211 | ||
70 | select LIBIPW | ||
71 | ---help--- | ||
72 | A driver for the Intel PRO/Wireless 2200BG and 2915ABG Network | ||
73 | Connection adapters. | ||
74 | |||
75 | See <file:Documentation/networking/README.ipw2200> for | ||
76 | information on the capabilities currently enabled in this | ||
77 | driver and for tips for debugging issues and problems. | ||
78 | |||
79 | In order to use this driver, you will need a firmware image for it. | ||
80 | You can obtain the firmware from | ||
81 | <http://ipw2200.sf.net/>. See the above referenced README.ipw2200 | ||
82 | for information on where to install the firmware images. | ||
83 | |||
84 | You will also very likely need the Wireless Tools in order to | ||
85 | configure your card: | ||
86 | |||
87 | <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>. | ||
88 | |||
89 | It is recommended that you compile this driver as a module (M) | ||
90 | rather than built-in (Y). This driver requires firmware at device | ||
91 | initialization time, and when built-in this typically happens | ||
92 | before the filesystem is accessible (hence firmware will be | ||
93 | unavailable and initialization will fail). If you do choose to build | ||
94 | this driver into your kernel image, you can avoid this problem by | ||
95 | including the firmware and a firmware loader in an initramfs. | ||
96 | |||
97 | config IPW2200_MONITOR | ||
98 | bool "Enable promiscuous mode" | ||
99 | depends on IPW2200 | ||
100 | ---help--- | ||
101 | Enables promiscuous/monitor mode support for the ipw2200 driver. | ||
102 | With this feature compiled into the driver, you can switch to | ||
103 | promiscuous mode via the Wireless Tool's Monitor mode. While in this | ||
104 | mode, no packets can be sent. | ||
105 | |||
106 | config IPW2200_RADIOTAP | ||
107 | bool "Enable radiotap format 802.11 raw packet support" | ||
108 | depends on IPW2200_MONITOR | ||
109 | |||
110 | config IPW2200_PROMISCUOUS | ||
111 | bool "Enable creation of a RF radiotap promiscuous interface" | ||
112 | depends on IPW2200_MONITOR | ||
113 | select IPW2200_RADIOTAP | ||
114 | ---help--- | ||
115 | Enables the creation of a second interface prefixed 'rtap'. | ||
116 | This second interface will provide every received in radiotap | ||
117 | format. | ||
118 | |||
119 | This is useful for performing wireless network analysis while | ||
120 | maintaining an active association. | ||
121 | |||
122 | Example usage: | ||
123 | |||
124 | % modprobe ipw2200 rtap_iface=1 | ||
125 | % ifconfig rtap0 up | ||
126 | % tethereal -i rtap0 | ||
127 | |||
128 | If you do not specify 'rtap_iface=1' as a module parameter then | ||
129 | the rtap interface will not be created and you will need to turn | ||
130 | it on via sysfs: | ||
131 | |||
132 | % echo 1 > /sys/bus/pci/drivers/ipw2200/*/rtap_iface | ||
133 | |||
134 | config IPW2200_QOS | ||
135 | bool "Enable QoS support" | ||
136 | depends on IPW2200 && EXPERIMENTAL | ||
137 | |||
138 | config IPW2200_DEBUG | ||
139 | bool "Enable full debugging output in IPW2200 module." | ||
140 | depends on IPW2200 | ||
141 | ---help--- | ||
142 | This option will enable low level debug tracing output for IPW2200. | ||
143 | |||
144 | Note, normal debug code is already compiled in. This low level | ||
145 | debug option enables debug on hot paths (e.g Tx, Rx, ISR) and | ||
146 | will result in the kernel module being ~70 larger. Most users | ||
147 | will typically not need this high verbosity debug information. | ||
148 | |||
149 | If you are not sure, say N here. | ||
150 | |||
151 | config LIBIPW | ||
152 | tristate | ||
153 | select WIRELESS_EXT | ||
154 | select CRYPTO | ||
155 | select CRYPTO_ARC4 | ||
156 | select CRYPTO_ECB | ||
157 | select CRYPTO_AES | ||
158 | select CRYPTO_MICHAEL_MIC | ||
159 | select CRYPTO_ECB | ||
160 | select CRC32 | ||
161 | select LIB80211 | ||
162 | select LIB80211_CRYPT_WEP | ||
163 | select LIB80211_CRYPT_TKIP | ||
164 | select LIB80211_CRYPT_CCMP | ||
165 | ---help--- | ||
166 | This option enables the hardware independent IEEE 802.11 | ||
167 | networking stack. This component is deprecated in favor of the | ||
168 | mac80211 component. | ||
169 | |||
170 | config LIBIPW_DEBUG | ||
171 | bool "Full debugging output for the LIBIPW component" | ||
172 | depends on LIBIPW | ||
173 | ---help--- | ||
174 | This option will enable debug tracing output for the | ||
175 | libipw component. | ||
176 | |||
177 | This will result in the kernel module being ~70k larger. You | ||
178 | can control which debug output is sent to the kernel log by | ||
179 | setting the value in | ||
180 | |||
181 | /proc/net/ieee80211/debug_level | ||
182 | |||
183 | For example: | ||
184 | |||
185 | % echo 0x00000FFO > /proc/net/ieee80211/debug_level | ||
186 | |||
187 | For a list of values you can assign to debug_level, you | ||
188 | can look at the bit mask values in <net/ieee80211.h> | ||
189 | |||
190 | If you are not trying to debug or develop the libipw | ||
191 | component, you most likely want to say N here. | ||
diff --git a/drivers/net/wireless/ipw2x00/Makefile b/drivers/net/wireless/ipw2x00/Makefile new file mode 100644 index 000000000000..aecd2cff462b --- /dev/null +++ b/drivers/net/wireless/ipw2x00/Makefile | |||
@@ -0,0 +1,14 @@ | |||
1 | # | ||
2 | # Makefile for the Intel Centrino wireless drivers | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_IPW2100) += ipw2100.o | ||
6 | obj-$(CONFIG_IPW2200) += ipw2200.o | ||
7 | |||
8 | obj-$(CONFIG_LIBIPW) += libipw.o | ||
9 | libipw-objs := \ | ||
10 | libipw_module.o \ | ||
11 | libipw_tx.o \ | ||
12 | libipw_rx.o \ | ||
13 | libipw_wx.o \ | ||
14 | libipw_geo.o | ||
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 062c9f280304..2d2044d3d1c9 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c | |||
@@ -4010,7 +4010,7 @@ static ssize_t show_internals(struct device *d, struct device_attribute *attr, | |||
4010 | else | 4010 | else |
4011 | len += sprintf(buf + len, "not connected\n"); | 4011 | len += sprintf(buf + len, "not connected\n"); |
4012 | 4012 | ||
4013 | DUMP_VAR(ieee->crypt[priv->ieee->tx_keyidx], "p"); | 4013 | DUMP_VAR(ieee->crypt_info.crypt[priv->ieee->crypt_info.tx_keyidx], "p"); |
4014 | DUMP_VAR(status, "08lx"); | 4014 | DUMP_VAR(status, "08lx"); |
4015 | DUMP_VAR(config, "08lx"); | 4015 | DUMP_VAR(config, "08lx"); |
4016 | DUMP_VAR(capability, "08lx"); | 4016 | DUMP_VAR(capability, "08lx"); |
@@ -5514,7 +5514,7 @@ static int ipw2100_configure_security(struct ipw2100_priv *priv, int batch_mode) | |||
5514 | } | 5514 | } |
5515 | } | 5515 | } |
5516 | 5516 | ||
5517 | ipw2100_set_key_index(priv, priv->ieee->tx_keyidx, 1); | 5517 | ipw2100_set_key_index(priv, priv->ieee->crypt_info.tx_keyidx, 1); |
5518 | } | 5518 | } |
5519 | 5519 | ||
5520 | /* Always enable privacy so the Host can filter WEP packets if | 5520 | /* Always enable privacy so the Host can filter WEP packets if |
@@ -7620,7 +7620,7 @@ static int ipw2100_wx_set_auth(struct net_device *dev, | |||
7620 | struct ipw2100_priv *priv = ieee80211_priv(dev); | 7620 | struct ipw2100_priv *priv = ieee80211_priv(dev); |
7621 | struct ieee80211_device *ieee = priv->ieee; | 7621 | struct ieee80211_device *ieee = priv->ieee; |
7622 | struct iw_param *param = &wrqu->param; | 7622 | struct iw_param *param = &wrqu->param; |
7623 | struct ieee80211_crypt_data *crypt; | 7623 | struct lib80211_crypt_data *crypt; |
7624 | unsigned long flags; | 7624 | unsigned long flags; |
7625 | int ret = 0; | 7625 | int ret = 0; |
7626 | 7626 | ||
@@ -7635,7 +7635,7 @@ static int ipw2100_wx_set_auth(struct net_device *dev, | |||
7635 | break; | 7635 | break; |
7636 | 7636 | ||
7637 | case IW_AUTH_TKIP_COUNTERMEASURES: | 7637 | case IW_AUTH_TKIP_COUNTERMEASURES: |
7638 | crypt = priv->ieee->crypt[priv->ieee->tx_keyidx]; | 7638 | crypt = priv->ieee->crypt_info.crypt[priv->ieee->crypt_info.tx_keyidx]; |
7639 | if (!crypt || !crypt->ops->set_flags || !crypt->ops->get_flags) | 7639 | if (!crypt || !crypt->ops->set_flags || !crypt->ops->get_flags) |
7640 | break; | 7640 | break; |
7641 | 7641 | ||
@@ -7712,7 +7712,7 @@ static int ipw2100_wx_get_auth(struct net_device *dev, | |||
7712 | { | 7712 | { |
7713 | struct ipw2100_priv *priv = ieee80211_priv(dev); | 7713 | struct ipw2100_priv *priv = ieee80211_priv(dev); |
7714 | struct ieee80211_device *ieee = priv->ieee; | 7714 | struct ieee80211_device *ieee = priv->ieee; |
7715 | struct ieee80211_crypt_data *crypt; | 7715 | struct lib80211_crypt_data *crypt; |
7716 | struct iw_param *param = &wrqu->param; | 7716 | struct iw_param *param = &wrqu->param; |
7717 | int ret = 0; | 7717 | int ret = 0; |
7718 | 7718 | ||
@@ -7728,7 +7728,7 @@ static int ipw2100_wx_get_auth(struct net_device *dev, | |||
7728 | break; | 7728 | break; |
7729 | 7729 | ||
7730 | case IW_AUTH_TKIP_COUNTERMEASURES: | 7730 | case IW_AUTH_TKIP_COUNTERMEASURES: |
7731 | crypt = priv->ieee->crypt[priv->ieee->tx_keyidx]; | 7731 | crypt = priv->ieee->crypt_info.crypt[priv->ieee->crypt_info.tx_keyidx]; |
7732 | if (!crypt || !crypt->ops->get_flags) { | 7732 | if (!crypt || !crypt->ops->get_flags) { |
7733 | IPW_DEBUG_WARNING("Can't get TKIP countermeasures: " | 7733 | IPW_DEBUG_WARNING("Can't get TKIP countermeasures: " |
7734 | "crypt not set!\n"); | 7734 | "crypt not set!\n"); |
diff --git a/drivers/net/wireless/ipw2100.h b/drivers/net/wireless/ipw2x00/ipw2100.h index bbf1ddcafba8..bbf1ddcafba8 100644 --- a/drivers/net/wireless/ipw2100.h +++ b/drivers/net/wireless/ipw2x00/ipw2100.h | |||
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 051ae92d8b65..d2a2b7586d08 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c | |||
@@ -6600,7 +6600,7 @@ static int ipw_wx_set_auth(struct net_device *dev, | |||
6600 | struct ipw_priv *priv = ieee80211_priv(dev); | 6600 | struct ipw_priv *priv = ieee80211_priv(dev); |
6601 | struct ieee80211_device *ieee = priv->ieee; | 6601 | struct ieee80211_device *ieee = priv->ieee; |
6602 | struct iw_param *param = &wrqu->param; | 6602 | struct iw_param *param = &wrqu->param; |
6603 | struct ieee80211_crypt_data *crypt; | 6603 | struct lib80211_crypt_data *crypt; |
6604 | unsigned long flags; | 6604 | unsigned long flags; |
6605 | int ret = 0; | 6605 | int ret = 0; |
6606 | 6606 | ||
@@ -6622,7 +6622,7 @@ static int ipw_wx_set_auth(struct net_device *dev, | |||
6622 | break; | 6622 | break; |
6623 | 6623 | ||
6624 | case IW_AUTH_TKIP_COUNTERMEASURES: | 6624 | case IW_AUTH_TKIP_COUNTERMEASURES: |
6625 | crypt = priv->ieee->crypt[priv->ieee->tx_keyidx]; | 6625 | crypt = priv->ieee->crypt_info.crypt[priv->ieee->crypt_info.tx_keyidx]; |
6626 | if (!crypt || !crypt->ops->set_flags || !crypt->ops->get_flags) | 6626 | if (!crypt || !crypt->ops->set_flags || !crypt->ops->get_flags) |
6627 | break; | 6627 | break; |
6628 | 6628 | ||
@@ -6699,7 +6699,7 @@ static int ipw_wx_get_auth(struct net_device *dev, | |||
6699 | { | 6699 | { |
6700 | struct ipw_priv *priv = ieee80211_priv(dev); | 6700 | struct ipw_priv *priv = ieee80211_priv(dev); |
6701 | struct ieee80211_device *ieee = priv->ieee; | 6701 | struct ieee80211_device *ieee = priv->ieee; |
6702 | struct ieee80211_crypt_data *crypt; | 6702 | struct lib80211_crypt_data *crypt; |
6703 | struct iw_param *param = &wrqu->param; | 6703 | struct iw_param *param = &wrqu->param; |
6704 | int ret = 0; | 6704 | int ret = 0; |
6705 | 6705 | ||
@@ -6715,7 +6715,7 @@ static int ipw_wx_get_auth(struct net_device *dev, | |||
6715 | break; | 6715 | break; |
6716 | 6716 | ||
6717 | case IW_AUTH_TKIP_COUNTERMEASURES: | 6717 | case IW_AUTH_TKIP_COUNTERMEASURES: |
6718 | crypt = priv->ieee->crypt[priv->ieee->tx_keyidx]; | 6718 | crypt = priv->ieee->crypt_info.crypt[priv->ieee->crypt_info.tx_keyidx]; |
6719 | if (!crypt || !crypt->ops->get_flags) | 6719 | if (!crypt || !crypt->ops->get_flags) |
6720 | break; | 6720 | break; |
6721 | 6721 | ||
@@ -7575,8 +7575,7 @@ static int ipw_associate(void *data) | |||
7575 | } | 7575 | } |
7576 | 7576 | ||
7577 | if (!(priv->config & CFG_ASSOCIATE) && | 7577 | if (!(priv->config & CFG_ASSOCIATE) && |
7578 | !(priv->config & (CFG_STATIC_ESSID | | 7578 | !(priv->config & (CFG_STATIC_ESSID | CFG_STATIC_BSSID))) { |
7579 | CFG_STATIC_CHANNEL | CFG_STATIC_BSSID))) { | ||
7580 | IPW_DEBUG_ASSOC("Not attempting association (associate=0)\n"); | 7579 | IPW_DEBUG_ASSOC("Not attempting association (associate=0)\n"); |
7581 | return 0; | 7580 | return 0; |
7582 | } | 7581 | } |
@@ -10252,8 +10251,8 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, | |||
10252 | case SEC_LEVEL_1: | 10251 | case SEC_LEVEL_1: |
10253 | tfd->u.data.tfd.tfd_24.mchdr.frame_ctl |= | 10252 | tfd->u.data.tfd.tfd_24.mchdr.frame_ctl |= |
10254 | cpu_to_le16(IEEE80211_FCTL_PROTECTED); | 10253 | cpu_to_le16(IEEE80211_FCTL_PROTECTED); |
10255 | tfd->u.data.key_index = priv->ieee->tx_keyidx; | 10254 | tfd->u.data.key_index = priv->ieee->crypt_info.tx_keyidx; |
10256 | if (priv->ieee->sec.key_sizes[priv->ieee->tx_keyidx] <= | 10255 | if (priv->ieee->sec.key_sizes[priv->ieee->crypt_info.tx_keyidx] <= |
10257 | 40) | 10256 | 40) |
10258 | tfd->u.data.key_index |= DCT_WEP_KEY_64Bit; | 10257 | tfd->u.data.key_index |= DCT_WEP_KEY_64Bit; |
10259 | else | 10258 | else |
diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2x00/ipw2200.h index 0a84d52147bd..0a84d52147bd 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2x00/ipw2200.h | |||
diff --git a/drivers/net/wireless/ipw2x00/libipw_geo.c b/drivers/net/wireless/ipw2x00/libipw_geo.c new file mode 100644 index 000000000000..960ad13f5e9f --- /dev/null +++ b/drivers/net/wireless/ipw2x00/libipw_geo.c | |||
@@ -0,0 +1,195 @@ | |||
1 | /****************************************************************************** | ||
2 | |||
3 | Copyright(c) 2005 Intel Corporation. All rights reserved. | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify it | ||
6 | under the terms of version 2 of the GNU General Public License as | ||
7 | published by the Free Software Foundation. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License along with | ||
15 | this program; if not, write to the Free Software Foundation, Inc., 59 | ||
16 | Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
17 | |||
18 | The full GNU General Public License is included in this distribution in the | ||
19 | file called LICENSE. | ||
20 | |||
21 | Contact Information: | ||
22 | James P. Ketrenos <ipw2100-admin@linux.intel.com> | ||
23 | Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
24 | |||
25 | ******************************************************************************/ | ||
26 | #include <linux/compiler.h> | ||
27 | #include <linux/errno.h> | ||
28 | #include <linux/if_arp.h> | ||
29 | #include <linux/in6.h> | ||
30 | #include <linux/in.h> | ||
31 | #include <linux/ip.h> | ||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/module.h> | ||
34 | #include <linux/netdevice.h> | ||
35 | #include <linux/proc_fs.h> | ||
36 | #include <linux/skbuff.h> | ||
37 | #include <linux/slab.h> | ||
38 | #include <linux/tcp.h> | ||
39 | #include <linux/types.h> | ||
40 | #include <linux/wireless.h> | ||
41 | #include <linux/etherdevice.h> | ||
42 | #include <asm/uaccess.h> | ||
43 | |||
44 | #include <net/ieee80211.h> | ||
45 | |||
46 | int ieee80211_is_valid_channel(struct ieee80211_device *ieee, u8 channel) | ||
47 | { | ||
48 | int i; | ||
49 | |||
50 | /* Driver needs to initialize the geography map before using | ||
51 | * these helper functions */ | ||
52 | if (ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0) | ||
53 | return 0; | ||
54 | |||
55 | if (ieee->freq_band & IEEE80211_24GHZ_BAND) | ||
56 | for (i = 0; i < ieee->geo.bg_channels; i++) | ||
57 | /* NOTE: If G mode is currently supported but | ||
58 | * this is a B only channel, we don't see it | ||
59 | * as valid. */ | ||
60 | if ((ieee->geo.bg[i].channel == channel) && | ||
61 | !(ieee->geo.bg[i].flags & IEEE80211_CH_INVALID) && | ||
62 | (!(ieee->mode & IEEE_G) || | ||
63 | !(ieee->geo.bg[i].flags & IEEE80211_CH_B_ONLY))) | ||
64 | return IEEE80211_24GHZ_BAND; | ||
65 | |||
66 | if (ieee->freq_band & IEEE80211_52GHZ_BAND) | ||
67 | for (i = 0; i < ieee->geo.a_channels; i++) | ||
68 | if ((ieee->geo.a[i].channel == channel) && | ||
69 | !(ieee->geo.a[i].flags & IEEE80211_CH_INVALID)) | ||
70 | return IEEE80211_52GHZ_BAND; | ||
71 | |||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | int ieee80211_channel_to_index(struct ieee80211_device *ieee, u8 channel) | ||
76 | { | ||
77 | int i; | ||
78 | |||
79 | /* Driver needs to initialize the geography map before using | ||
80 | * these helper functions */ | ||
81 | if (ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0) | ||
82 | return -1; | ||
83 | |||
84 | if (ieee->freq_band & IEEE80211_24GHZ_BAND) | ||
85 | for (i = 0; i < ieee->geo.bg_channels; i++) | ||
86 | if (ieee->geo.bg[i].channel == channel) | ||
87 | return i; | ||
88 | |||
89 | if (ieee->freq_band & IEEE80211_52GHZ_BAND) | ||
90 | for (i = 0; i < ieee->geo.a_channels; i++) | ||
91 | if (ieee->geo.a[i].channel == channel) | ||
92 | return i; | ||
93 | |||
94 | return -1; | ||
95 | } | ||
96 | |||
97 | u32 ieee80211_channel_to_freq(struct ieee80211_device * ieee, u8 channel) | ||
98 | { | ||
99 | const struct ieee80211_channel * ch; | ||
100 | |||
101 | /* Driver needs to initialize the geography map before using | ||
102 | * these helper functions */ | ||
103 | if (ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0) | ||
104 | return 0; | ||
105 | |||
106 | ch = ieee80211_get_channel(ieee, channel); | ||
107 | if (!ch->channel) | ||
108 | return 0; | ||
109 | return ch->freq; | ||
110 | } | ||
111 | |||
112 | u8 ieee80211_freq_to_channel(struct ieee80211_device * ieee, u32 freq) | ||
113 | { | ||
114 | int i; | ||
115 | |||
116 | /* Driver needs to initialize the geography map before using | ||
117 | * these helper functions */ | ||
118 | if (ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0) | ||
119 | return 0; | ||
120 | |||
121 | freq /= 100000; | ||
122 | |||
123 | if (ieee->freq_band & IEEE80211_24GHZ_BAND) | ||
124 | for (i = 0; i < ieee->geo.bg_channels; i++) | ||
125 | if (ieee->geo.bg[i].freq == freq) | ||
126 | return ieee->geo.bg[i].channel; | ||
127 | |||
128 | if (ieee->freq_band & IEEE80211_52GHZ_BAND) | ||
129 | for (i = 0; i < ieee->geo.a_channels; i++) | ||
130 | if (ieee->geo.a[i].freq == freq) | ||
131 | return ieee->geo.a[i].channel; | ||
132 | |||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | int ieee80211_set_geo(struct ieee80211_device *ieee, | ||
137 | const struct ieee80211_geo *geo) | ||
138 | { | ||
139 | memcpy(ieee->geo.name, geo->name, 3); | ||
140 | ieee->geo.name[3] = '\0'; | ||
141 | ieee->geo.bg_channels = geo->bg_channels; | ||
142 | ieee->geo.a_channels = geo->a_channels; | ||
143 | memcpy(ieee->geo.bg, geo->bg, geo->bg_channels * | ||
144 | sizeof(struct ieee80211_channel)); | ||
145 | memcpy(ieee->geo.a, geo->a, ieee->geo.a_channels * | ||
146 | sizeof(struct ieee80211_channel)); | ||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | const struct ieee80211_geo *ieee80211_get_geo(struct ieee80211_device *ieee) | ||
151 | { | ||
152 | return &ieee->geo; | ||
153 | } | ||
154 | |||
155 | u8 ieee80211_get_channel_flags(struct ieee80211_device * ieee, u8 channel) | ||
156 | { | ||
157 | int index = ieee80211_channel_to_index(ieee, channel); | ||
158 | |||
159 | if (index == -1) | ||
160 | return IEEE80211_CH_INVALID; | ||
161 | |||
162 | if (channel <= IEEE80211_24GHZ_CHANNELS) | ||
163 | return ieee->geo.bg[index].flags; | ||
164 | |||
165 | return ieee->geo.a[index].flags; | ||
166 | } | ||
167 | |||
168 | static const struct ieee80211_channel bad_channel = { | ||
169 | .channel = 0, | ||
170 | .flags = IEEE80211_CH_INVALID, | ||
171 | .max_power = 0, | ||
172 | }; | ||
173 | |||
174 | const struct ieee80211_channel *ieee80211_get_channel(struct ieee80211_device | ||
175 | *ieee, u8 channel) | ||
176 | { | ||
177 | int index = ieee80211_channel_to_index(ieee, channel); | ||
178 | |||
179 | if (index == -1) | ||
180 | return &bad_channel; | ||
181 | |||
182 | if (channel <= IEEE80211_24GHZ_CHANNELS) | ||
183 | return &ieee->geo.bg[index]; | ||
184 | |||
185 | return &ieee->geo.a[index]; | ||
186 | } | ||
187 | |||
188 | EXPORT_SYMBOL(ieee80211_get_channel); | ||
189 | EXPORT_SYMBOL(ieee80211_get_channel_flags); | ||
190 | EXPORT_SYMBOL(ieee80211_is_valid_channel); | ||
191 | EXPORT_SYMBOL(ieee80211_freq_to_channel); | ||
192 | EXPORT_SYMBOL(ieee80211_channel_to_freq); | ||
193 | EXPORT_SYMBOL(ieee80211_channel_to_index); | ||
194 | EXPORT_SYMBOL(ieee80211_set_geo); | ||
195 | EXPORT_SYMBOL(ieee80211_get_geo); | ||
diff --git a/drivers/net/wireless/ipw2x00/libipw_module.c b/drivers/net/wireless/ipw2x00/libipw_module.c new file mode 100644 index 000000000000..a2f5616d5b09 --- /dev/null +++ b/drivers/net/wireless/ipw2x00/libipw_module.c | |||
@@ -0,0 +1,293 @@ | |||
1 | /******************************************************************************* | ||
2 | |||
3 | Copyright(c) 2004-2005 Intel Corporation. All rights reserved. | ||
4 | |||
5 | Portions of this file are based on the WEP enablement code provided by the | ||
6 | Host AP project hostap-drivers v0.1.3 | ||
7 | Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen | ||
8 | <j@w1.fi> | ||
9 | Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi> | ||
10 | |||
11 | This program is free software; you can redistribute it and/or modify it | ||
12 | under the terms of version 2 of the GNU General Public License as | ||
13 | published by the Free Software Foundation. | ||
14 | |||
15 | This program is distributed in the hope that it will be useful, but WITHOUT | ||
16 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
18 | more details. | ||
19 | |||
20 | You should have received a copy of the GNU General Public License along with | ||
21 | this program; if not, write to the Free Software Foundation, Inc., 59 | ||
22 | Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
23 | |||
24 | The full GNU General Public License is included in this distribution in the | ||
25 | file called LICENSE. | ||
26 | |||
27 | Contact Information: | ||
28 | James P. Ketrenos <ipw2100-admin@linux.intel.com> | ||
29 | Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | |||
31 | *******************************************************************************/ | ||
32 | |||
33 | #include <linux/compiler.h> | ||
34 | #include <linux/errno.h> | ||
35 | #include <linux/if_arp.h> | ||
36 | #include <linux/in6.h> | ||
37 | #include <linux/in.h> | ||
38 | #include <linux/ip.h> | ||
39 | #include <linux/kernel.h> | ||
40 | #include <linux/module.h> | ||
41 | #include <linux/netdevice.h> | ||
42 | #include <linux/proc_fs.h> | ||
43 | #include <linux/skbuff.h> | ||
44 | #include <linux/slab.h> | ||
45 | #include <linux/tcp.h> | ||
46 | #include <linux/types.h> | ||
47 | #include <linux/wireless.h> | ||
48 | #include <linux/etherdevice.h> | ||
49 | #include <asm/uaccess.h> | ||
50 | #include <net/net_namespace.h> | ||
51 | #include <net/arp.h> | ||
52 | |||
53 | #include <net/ieee80211.h> | ||
54 | |||
55 | #define DRV_DESCRIPTION "802.11 data/management/control stack" | ||
56 | #define DRV_NAME "ieee80211" | ||
57 | #define DRV_VERSION IEEE80211_VERSION | ||
58 | #define DRV_COPYRIGHT "Copyright (C) 2004-2005 Intel Corporation <jketreno@linux.intel.com>" | ||
59 | |||
60 | MODULE_VERSION(DRV_VERSION); | ||
61 | MODULE_DESCRIPTION(DRV_DESCRIPTION); | ||
62 | MODULE_AUTHOR(DRV_COPYRIGHT); | ||
63 | MODULE_LICENSE("GPL"); | ||
64 | |||
65 | static int ieee80211_networks_allocate(struct ieee80211_device *ieee) | ||
66 | { | ||
67 | if (ieee->networks) | ||
68 | return 0; | ||
69 | |||
70 | ieee->networks = | ||
71 | kzalloc(MAX_NETWORK_COUNT * sizeof(struct ieee80211_network), | ||
72 | GFP_KERNEL); | ||
73 | if (!ieee->networks) { | ||
74 | printk(KERN_WARNING "%s: Out of memory allocating beacons\n", | ||
75 | ieee->dev->name); | ||
76 | return -ENOMEM; | ||
77 | } | ||
78 | |||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | void ieee80211_network_reset(struct ieee80211_network *network) | ||
83 | { | ||
84 | if (!network) | ||
85 | return; | ||
86 | |||
87 | if (network->ibss_dfs) { | ||
88 | kfree(network->ibss_dfs); | ||
89 | network->ibss_dfs = NULL; | ||
90 | } | ||
91 | } | ||
92 | |||
93 | static inline void ieee80211_networks_free(struct ieee80211_device *ieee) | ||
94 | { | ||
95 | int i; | ||
96 | |||
97 | if (!ieee->networks) | ||
98 | return; | ||
99 | |||
100 | for (i = 0; i < MAX_NETWORK_COUNT; i++) | ||
101 | if (ieee->networks[i].ibss_dfs) | ||
102 | kfree(ieee->networks[i].ibss_dfs); | ||
103 | |||
104 | kfree(ieee->networks); | ||
105 | ieee->networks = NULL; | ||
106 | } | ||
107 | |||
108 | static void ieee80211_networks_initialize(struct ieee80211_device *ieee) | ||
109 | { | ||
110 | int i; | ||
111 | |||
112 | INIT_LIST_HEAD(&ieee->network_free_list); | ||
113 | INIT_LIST_HEAD(&ieee->network_list); | ||
114 | for (i = 0; i < MAX_NETWORK_COUNT; i++) | ||
115 | list_add_tail(&ieee->networks[i].list, | ||
116 | &ieee->network_free_list); | ||
117 | } | ||
118 | |||
119 | static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) | ||
120 | { | ||
121 | if ((new_mtu < 68) || (new_mtu > IEEE80211_DATA_LEN)) | ||
122 | return -EINVAL; | ||
123 | dev->mtu = new_mtu; | ||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | static struct net_device_stats *ieee80211_generic_get_stats( | ||
128 | struct net_device *dev) | ||
129 | { | ||
130 | struct ieee80211_device *ieee = netdev_priv(dev); | ||
131 | return &ieee->stats; | ||
132 | } | ||
133 | |||
134 | struct net_device *alloc_ieee80211(int sizeof_priv) | ||
135 | { | ||
136 | struct ieee80211_device *ieee; | ||
137 | struct net_device *dev; | ||
138 | int err; | ||
139 | |||
140 | IEEE80211_DEBUG_INFO("Initializing...\n"); | ||
141 | |||
142 | dev = alloc_etherdev(sizeof(struct ieee80211_device) + sizeof_priv); | ||
143 | if (!dev) { | ||
144 | IEEE80211_ERROR("Unable to allocate network device.\n"); | ||
145 | goto failed; | ||
146 | } | ||
147 | ieee = netdev_priv(dev); | ||
148 | dev->hard_start_xmit = ieee80211_xmit; | ||
149 | dev->change_mtu = ieee80211_change_mtu; | ||
150 | |||
151 | /* Drivers are free to override this if the generic implementation | ||
152 | * does not meet their needs. */ | ||
153 | dev->get_stats = ieee80211_generic_get_stats; | ||
154 | |||
155 | ieee->dev = dev; | ||
156 | |||
157 | err = ieee80211_networks_allocate(ieee); | ||
158 | if (err) { | ||
159 | IEEE80211_ERROR("Unable to allocate beacon storage: %d\n", err); | ||
160 | goto failed_free_netdev; | ||
161 | } | ||
162 | ieee80211_networks_initialize(ieee); | ||
163 | |||
164 | /* Default fragmentation threshold is maximum payload size */ | ||
165 | ieee->fts = DEFAULT_FTS; | ||
166 | ieee->rts = DEFAULT_FTS; | ||
167 | ieee->scan_age = DEFAULT_MAX_SCAN_AGE; | ||
168 | ieee->open_wep = 1; | ||
169 | |||
170 | /* Default to enabling full open WEP with host based encrypt/decrypt */ | ||
171 | ieee->host_encrypt = 1; | ||
172 | ieee->host_decrypt = 1; | ||
173 | ieee->host_mc_decrypt = 1; | ||
174 | |||
175 | /* Host fragementation in Open mode. Default is enabled. | ||
176 | * Note: host fragmentation is always enabled if host encryption | ||
177 | * is enabled. For cards can do hardware encryption, they must do | ||
178 | * hardware fragmentation as well. So we don't need a variable | ||
179 | * like host_enc_frag. */ | ||
180 | ieee->host_open_frag = 1; | ||
181 | ieee->ieee802_1x = 1; /* Default to supporting 802.1x */ | ||
182 | |||
183 | spin_lock_init(&ieee->lock); | ||
184 | |||
185 | lib80211_crypt_info_init(&ieee->crypt_info, dev->name, &ieee->lock); | ||
186 | |||
187 | ieee->wpa_enabled = 0; | ||
188 | ieee->drop_unencrypted = 0; | ||
189 | ieee->privacy_invoked = 0; | ||
190 | |||
191 | return dev; | ||
192 | |||
193 | failed_free_netdev: | ||
194 | free_netdev(dev); | ||
195 | failed: | ||
196 | return NULL; | ||
197 | } | ||
198 | |||
199 | void free_ieee80211(struct net_device *dev) | ||
200 | { | ||
201 | struct ieee80211_device *ieee = netdev_priv(dev); | ||
202 | |||
203 | lib80211_crypt_info_free(&ieee->crypt_info); | ||
204 | |||
205 | ieee80211_networks_free(ieee); | ||
206 | free_netdev(dev); | ||
207 | } | ||
208 | |||
209 | #ifdef CONFIG_IEEE80211_DEBUG | ||
210 | |||
211 | static int debug = 0; | ||
212 | u32 ieee80211_debug_level = 0; | ||
213 | EXPORT_SYMBOL_GPL(ieee80211_debug_level); | ||
214 | static struct proc_dir_entry *ieee80211_proc = NULL; | ||
215 | |||
216 | static int show_debug_level(char *page, char **start, off_t offset, | ||
217 | int count, int *eof, void *data) | ||
218 | { | ||
219 | return snprintf(page, count, "0x%08X\n", ieee80211_debug_level); | ||
220 | } | ||
221 | |||
222 | static int store_debug_level(struct file *file, const char __user * buffer, | ||
223 | unsigned long count, void *data) | ||
224 | { | ||
225 | char buf[] = "0x00000000\n"; | ||
226 | unsigned long len = min((unsigned long)sizeof(buf) - 1, count); | ||
227 | unsigned long val; | ||
228 | |||
229 | if (copy_from_user(buf, buffer, len)) | ||
230 | return count; | ||
231 | buf[len] = 0; | ||
232 | if (sscanf(buf, "%li", &val) != 1) | ||
233 | printk(KERN_INFO DRV_NAME | ||
234 | ": %s is not in hex or decimal form.\n", buf); | ||
235 | else | ||
236 | ieee80211_debug_level = val; | ||
237 | |||
238 | return strnlen(buf, len); | ||
239 | } | ||
240 | #endif /* CONFIG_IEEE80211_DEBUG */ | ||
241 | |||
242 | static int __init ieee80211_init(void) | ||
243 | { | ||
244 | #ifdef CONFIG_IEEE80211_DEBUG | ||
245 | struct proc_dir_entry *e; | ||
246 | |||
247 | ieee80211_debug_level = debug; | ||
248 | ieee80211_proc = proc_mkdir(DRV_NAME, init_net.proc_net); | ||
249 | if (ieee80211_proc == NULL) { | ||
250 | IEEE80211_ERROR("Unable to create " DRV_NAME | ||
251 | " proc directory\n"); | ||
252 | return -EIO; | ||
253 | } | ||
254 | e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR, | ||
255 | ieee80211_proc); | ||
256 | if (!e) { | ||
257 | remove_proc_entry(DRV_NAME, init_net.proc_net); | ||
258 | ieee80211_proc = NULL; | ||
259 | return -EIO; | ||
260 | } | ||
261 | e->read_proc = show_debug_level; | ||
262 | e->write_proc = store_debug_level; | ||
263 | e->data = NULL; | ||
264 | #endif /* CONFIG_IEEE80211_DEBUG */ | ||
265 | |||
266 | printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n"); | ||
267 | printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n"); | ||
268 | |||
269 | return 0; | ||
270 | } | ||
271 | |||
272 | static void __exit ieee80211_exit(void) | ||
273 | { | ||
274 | #ifdef CONFIG_IEEE80211_DEBUG | ||
275 | if (ieee80211_proc) { | ||
276 | remove_proc_entry("debug_level", ieee80211_proc); | ||
277 | remove_proc_entry(DRV_NAME, init_net.proc_net); | ||
278 | ieee80211_proc = NULL; | ||
279 | } | ||
280 | #endif /* CONFIG_IEEE80211_DEBUG */ | ||
281 | } | ||
282 | |||
283 | #ifdef CONFIG_IEEE80211_DEBUG | ||
284 | #include <linux/moduleparam.h> | ||
285 | module_param(debug, int, 0444); | ||
286 | MODULE_PARM_DESC(debug, "debug output mask"); | ||
287 | #endif /* CONFIG_IEEE80211_DEBUG */ | ||
288 | |||
289 | module_exit(ieee80211_exit); | ||
290 | module_init(ieee80211_init); | ||
291 | |||
292 | EXPORT_SYMBOL(alloc_ieee80211); | ||
293 | EXPORT_SYMBOL(free_ieee80211); | ||
diff --git a/drivers/net/wireless/ipw2x00/libipw_rx.c b/drivers/net/wireless/ipw2x00/libipw_rx.c new file mode 100644 index 000000000000..9c67dfae4320 --- /dev/null +++ b/drivers/net/wireless/ipw2x00/libipw_rx.c | |||
@@ -0,0 +1,1799 @@ | |||
1 | /* | ||
2 | * Original code based Host AP (software wireless LAN access point) driver | ||
3 | * for Intersil Prism2/2.5/3 - hostap.o module, common routines | ||
4 | * | ||
5 | * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen | ||
6 | * <j@w1.fi> | ||
7 | * Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi> | ||
8 | * Copyright (c) 2004-2005, Intel Corporation | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. See README and COPYING for | ||
13 | * more details. | ||
14 | */ | ||
15 | |||
16 | #include <linux/compiler.h> | ||
17 | #include <linux/errno.h> | ||
18 | #include <linux/if_arp.h> | ||
19 | #include <linux/in6.h> | ||
20 | #include <linux/in.h> | ||
21 | #include <linux/ip.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/netdevice.h> | ||
25 | #include <linux/proc_fs.h> | ||
26 | #include <linux/skbuff.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <linux/tcp.h> | ||
29 | #include <linux/types.h> | ||
30 | #include <linux/wireless.h> | ||
31 | #include <linux/etherdevice.h> | ||
32 | #include <asm/uaccess.h> | ||
33 | #include <linux/ctype.h> | ||
34 | |||
35 | #include <net/lib80211.h> | ||
36 | #include <net/ieee80211.h> | ||
37 | |||
38 | static void ieee80211_monitor_rx(struct ieee80211_device *ieee, | ||
39 | struct sk_buff *skb, | ||
40 | struct ieee80211_rx_stats *rx_stats) | ||
41 | { | ||
42 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
43 | u16 fc = le16_to_cpu(hdr->frame_control); | ||
44 | |||
45 | skb->dev = ieee->dev; | ||
46 | skb_reset_mac_header(skb); | ||
47 | skb_pull(skb, ieee80211_get_hdrlen(fc)); | ||
48 | skb->pkt_type = PACKET_OTHERHOST; | ||
49 | skb->protocol = htons(ETH_P_80211_RAW); | ||
50 | memset(skb->cb, 0, sizeof(skb->cb)); | ||
51 | netif_rx(skb); | ||
52 | } | ||
53 | |||
54 | /* Called only as a tasklet (software IRQ) */ | ||
55 | static struct ieee80211_frag_entry *ieee80211_frag_cache_find(struct | ||
56 | ieee80211_device | ||
57 | *ieee, | ||
58 | unsigned int seq, | ||
59 | unsigned int frag, | ||
60 | u8 * src, | ||
61 | u8 * dst) | ||
62 | { | ||
63 | struct ieee80211_frag_entry *entry; | ||
64 | int i; | ||
65 | |||
66 | for (i = 0; i < IEEE80211_FRAG_CACHE_LEN; i++) { | ||
67 | entry = &ieee->frag_cache[i]; | ||
68 | if (entry->skb != NULL && | ||
69 | time_after(jiffies, entry->first_frag_time + 2 * HZ)) { | ||
70 | IEEE80211_DEBUG_FRAG("expiring fragment cache entry " | ||
71 | "seq=%u last_frag=%u\n", | ||
72 | entry->seq, entry->last_frag); | ||
73 | dev_kfree_skb_any(entry->skb); | ||
74 | entry->skb = NULL; | ||
75 | } | ||
76 | |||
77 | if (entry->skb != NULL && entry->seq == seq && | ||
78 | (entry->last_frag + 1 == frag || frag == -1) && | ||
79 | !compare_ether_addr(entry->src_addr, src) && | ||
80 | !compare_ether_addr(entry->dst_addr, dst)) | ||
81 | return entry; | ||
82 | } | ||
83 | |||
84 | return NULL; | ||
85 | } | ||
86 | |||
87 | /* Called only as a tasklet (software IRQ) */ | ||
88 | static struct sk_buff *ieee80211_frag_cache_get(struct ieee80211_device *ieee, | ||
89 | struct ieee80211_hdr_4addr *hdr) | ||
90 | { | ||
91 | struct sk_buff *skb = NULL; | ||
92 | u16 sc; | ||
93 | unsigned int frag, seq; | ||
94 | struct ieee80211_frag_entry *entry; | ||
95 | |||
96 | sc = le16_to_cpu(hdr->seq_ctl); | ||
97 | frag = WLAN_GET_SEQ_FRAG(sc); | ||
98 | seq = WLAN_GET_SEQ_SEQ(sc); | ||
99 | |||
100 | if (frag == 0) { | ||
101 | /* Reserve enough space to fit maximum frame length */ | ||
102 | skb = dev_alloc_skb(ieee->dev->mtu + | ||
103 | sizeof(struct ieee80211_hdr_4addr) + | ||
104 | 8 /* LLC */ + | ||
105 | 2 /* alignment */ + | ||
106 | 8 /* WEP */ + ETH_ALEN /* WDS */ ); | ||
107 | if (skb == NULL) | ||
108 | return NULL; | ||
109 | |||
110 | entry = &ieee->frag_cache[ieee->frag_next_idx]; | ||
111 | ieee->frag_next_idx++; | ||
112 | if (ieee->frag_next_idx >= IEEE80211_FRAG_CACHE_LEN) | ||
113 | ieee->frag_next_idx = 0; | ||
114 | |||
115 | if (entry->skb != NULL) | ||
116 | dev_kfree_skb_any(entry->skb); | ||
117 | |||
118 | entry->first_frag_time = jiffies; | ||
119 | entry->seq = seq; | ||
120 | entry->last_frag = frag; | ||
121 | entry->skb = skb; | ||
122 | memcpy(entry->src_addr, hdr->addr2, ETH_ALEN); | ||
123 | memcpy(entry->dst_addr, hdr->addr1, ETH_ALEN); | ||
124 | } else { | ||
125 | /* received a fragment of a frame for which the head fragment | ||
126 | * should have already been received */ | ||
127 | entry = ieee80211_frag_cache_find(ieee, seq, frag, hdr->addr2, | ||
128 | hdr->addr1); | ||
129 | if (entry != NULL) { | ||
130 | entry->last_frag = frag; | ||
131 | skb = entry->skb; | ||
132 | } | ||
133 | } | ||
134 | |||
135 | return skb; | ||
136 | } | ||
137 | |||
138 | /* Called only as a tasklet (software IRQ) */ | ||
139 | static int ieee80211_frag_cache_invalidate(struct ieee80211_device *ieee, | ||
140 | struct ieee80211_hdr_4addr *hdr) | ||
141 | { | ||
142 | u16 sc; | ||
143 | unsigned int seq; | ||
144 | struct ieee80211_frag_entry *entry; | ||
145 | |||
146 | sc = le16_to_cpu(hdr->seq_ctl); | ||
147 | seq = WLAN_GET_SEQ_SEQ(sc); | ||
148 | |||
149 | entry = ieee80211_frag_cache_find(ieee, seq, -1, hdr->addr2, | ||
150 | hdr->addr1); | ||
151 | |||
152 | if (entry == NULL) { | ||
153 | IEEE80211_DEBUG_FRAG("could not invalidate fragment cache " | ||
154 | "entry (seq=%u)\n", seq); | ||
155 | return -1; | ||
156 | } | ||
157 | |||
158 | entry->skb = NULL; | ||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | #ifdef NOT_YET | ||
163 | /* ieee80211_rx_frame_mgtmt | ||
164 | * | ||
165 | * Responsible for handling management control frames | ||
166 | * | ||
167 | * Called by ieee80211_rx */ | ||
168 | static int | ||
169 | ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb, | ||
170 | struct ieee80211_rx_stats *rx_stats, u16 type, | ||
171 | u16 stype) | ||
172 | { | ||
173 | if (ieee->iw_mode == IW_MODE_MASTER) { | ||
174 | printk(KERN_DEBUG "%s: Master mode not yet suppported.\n", | ||
175 | ieee->dev->name); | ||
176 | return 0; | ||
177 | /* | ||
178 | hostap_update_sta_ps(ieee, (struct hostap_ieee80211_hdr_4addr *) | ||
179 | skb->data);*/ | ||
180 | } | ||
181 | |||
182 | if (ieee->hostapd && type == WLAN_FC_TYPE_MGMT) { | ||
183 | if (stype == WLAN_FC_STYPE_BEACON && | ||
184 | ieee->iw_mode == IW_MODE_MASTER) { | ||
185 | struct sk_buff *skb2; | ||
186 | /* Process beacon frames also in kernel driver to | ||
187 | * update STA(AP) table statistics */ | ||
188 | skb2 = skb_clone(skb, GFP_ATOMIC); | ||
189 | if (skb2) | ||
190 | hostap_rx(skb2->dev, skb2, rx_stats); | ||
191 | } | ||
192 | |||
193 | /* send management frames to the user space daemon for | ||
194 | * processing */ | ||
195 | ieee->apdevstats.rx_packets++; | ||
196 | ieee->apdevstats.rx_bytes += skb->len; | ||
197 | prism2_rx_80211(ieee->apdev, skb, rx_stats, PRISM2_RX_MGMT); | ||
198 | return 0; | ||
199 | } | ||
200 | |||
201 | if (ieee->iw_mode == IW_MODE_MASTER) { | ||
202 | if (type != WLAN_FC_TYPE_MGMT && type != WLAN_FC_TYPE_CTRL) { | ||
203 | printk(KERN_DEBUG "%s: unknown management frame " | ||
204 | "(type=0x%02x, stype=0x%02x) dropped\n", | ||
205 | skb->dev->name, type, stype); | ||
206 | return -1; | ||
207 | } | ||
208 | |||
209 | hostap_rx(skb->dev, skb, rx_stats); | ||
210 | return 0; | ||
211 | } | ||
212 | |||
213 | printk(KERN_DEBUG "%s: hostap_rx_frame_mgmt: management frame " | ||
214 | "received in non-Host AP mode\n", skb->dev->name); | ||
215 | return -1; | ||
216 | } | ||
217 | #endif | ||
218 | |||
219 | /* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */ | ||
220 | /* Ethernet-II snap header (RFC1042 for most EtherTypes) */ | ||
221 | static unsigned char rfc1042_header[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; | ||
222 | |||
223 | /* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */ | ||
224 | static unsigned char bridge_tunnel_header[] = | ||
225 | { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; | ||
226 | /* No encapsulation header if EtherType < 0x600 (=length) */ | ||
227 | |||
228 | /* Called by ieee80211_rx_frame_decrypt */ | ||
229 | static int ieee80211_is_eapol_frame(struct ieee80211_device *ieee, | ||
230 | struct sk_buff *skb) | ||
231 | { | ||
232 | struct net_device *dev = ieee->dev; | ||
233 | u16 fc, ethertype; | ||
234 | struct ieee80211_hdr_3addr *hdr; | ||
235 | u8 *pos; | ||
236 | |||
237 | if (skb->len < 24) | ||
238 | return 0; | ||
239 | |||
240 | hdr = (struct ieee80211_hdr_3addr *)skb->data; | ||
241 | fc = le16_to_cpu(hdr->frame_ctl); | ||
242 | |||
243 | /* check that the frame is unicast frame to us */ | ||
244 | if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == | ||
245 | IEEE80211_FCTL_TODS && | ||
246 | !compare_ether_addr(hdr->addr1, dev->dev_addr) && | ||
247 | !compare_ether_addr(hdr->addr3, dev->dev_addr)) { | ||
248 | /* ToDS frame with own addr BSSID and DA */ | ||
249 | } else if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == | ||
250 | IEEE80211_FCTL_FROMDS && | ||
251 | !compare_ether_addr(hdr->addr1, dev->dev_addr)) { | ||
252 | /* FromDS frame with own addr as DA */ | ||
253 | } else | ||
254 | return 0; | ||
255 | |||
256 | if (skb->len < 24 + 8) | ||
257 | return 0; | ||
258 | |||
259 | /* check for port access entity Ethernet type */ | ||
260 | pos = skb->data + 24; | ||
261 | ethertype = (pos[6] << 8) | pos[7]; | ||
262 | if (ethertype == ETH_P_PAE) | ||
263 | return 1; | ||
264 | |||
265 | return 0; | ||
266 | } | ||
267 | |||
268 | /* Called only as a tasklet (software IRQ), by ieee80211_rx */ | ||
269 | static int | ||
270 | ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb, | ||
271 | struct lib80211_crypt_data *crypt) | ||
272 | { | ||
273 | struct ieee80211_hdr_3addr *hdr; | ||
274 | int res, hdrlen; | ||
275 | |||
276 | if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL) | ||
277 | return 0; | ||
278 | |||
279 | hdr = (struct ieee80211_hdr_3addr *)skb->data; | ||
280 | hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl)); | ||
281 | |||
282 | atomic_inc(&crypt->refcnt); | ||
283 | res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv); | ||
284 | atomic_dec(&crypt->refcnt); | ||
285 | if (res < 0) { | ||
286 | IEEE80211_DEBUG_DROP("decryption failed (SA=%pM) res=%d\n", | ||
287 | hdr->addr2, res); | ||
288 | if (res == -2) | ||
289 | IEEE80211_DEBUG_DROP("Decryption failed ICV " | ||
290 | "mismatch (key %d)\n", | ||
291 | skb->data[hdrlen + 3] >> 6); | ||
292 | ieee->ieee_stats.rx_discards_undecryptable++; | ||
293 | return -1; | ||
294 | } | ||
295 | |||
296 | return res; | ||
297 | } | ||
298 | |||
299 | /* Called only as a tasklet (software IRQ), by ieee80211_rx */ | ||
300 | static int | ||
301 | ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device *ieee, | ||
302 | struct sk_buff *skb, int keyidx, | ||
303 | struct lib80211_crypt_data *crypt) | ||
304 | { | ||
305 | struct ieee80211_hdr_3addr *hdr; | ||
306 | int res, hdrlen; | ||
307 | |||
308 | if (crypt == NULL || crypt->ops->decrypt_msdu == NULL) | ||
309 | return 0; | ||
310 | |||
311 | hdr = (struct ieee80211_hdr_3addr *)skb->data; | ||
312 | hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl)); | ||
313 | |||
314 | atomic_inc(&crypt->refcnt); | ||
315 | res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv); | ||
316 | atomic_dec(&crypt->refcnt); | ||
317 | if (res < 0) { | ||
318 | printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed" | ||
319 | " (SA=%pM keyidx=%d)\n", ieee->dev->name, hdr->addr2, | ||
320 | keyidx); | ||
321 | return -1; | ||
322 | } | ||
323 | |||
324 | return 0; | ||
325 | } | ||
326 | |||
327 | /* All received frames are sent to this function. @skb contains the frame in | ||
328 | * IEEE 802.11 format, i.e., in the format it was sent over air. | ||
329 | * This function is called only as a tasklet (software IRQ). */ | ||
330 | int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, | ||
331 | struct ieee80211_rx_stats *rx_stats) | ||
332 | { | ||
333 | struct net_device *dev = ieee->dev; | ||
334 | struct ieee80211_hdr_4addr *hdr; | ||
335 | size_t hdrlen; | ||
336 | u16 fc, type, stype, sc; | ||
337 | struct net_device_stats *stats; | ||
338 | unsigned int frag; | ||
339 | u8 *payload; | ||
340 | u16 ethertype; | ||
341 | #ifdef NOT_YET | ||
342 | struct net_device *wds = NULL; | ||
343 | struct sk_buff *skb2 = NULL; | ||
344 | struct net_device *wds = NULL; | ||
345 | int frame_authorized = 0; | ||
346 | int from_assoc_ap = 0; | ||
347 | void *sta = NULL; | ||
348 | #endif | ||
349 | u8 dst[ETH_ALEN]; | ||
350 | u8 src[ETH_ALEN]; | ||
351 | struct lib80211_crypt_data *crypt = NULL; | ||
352 | int keyidx = 0; | ||
353 | int can_be_decrypted = 0; | ||
354 | |||
355 | hdr = (struct ieee80211_hdr_4addr *)skb->data; | ||
356 | stats = &ieee->stats; | ||
357 | |||
358 | if (skb->len < 10) { | ||
359 | printk(KERN_INFO "%s: SKB length < 10\n", dev->name); | ||
360 | goto rx_dropped; | ||
361 | } | ||
362 | |||
363 | fc = le16_to_cpu(hdr->frame_ctl); | ||
364 | type = WLAN_FC_GET_TYPE(fc); | ||
365 | stype = WLAN_FC_GET_STYPE(fc); | ||
366 | sc = le16_to_cpu(hdr->seq_ctl); | ||
367 | frag = WLAN_GET_SEQ_FRAG(sc); | ||
368 | hdrlen = ieee80211_get_hdrlen(fc); | ||
369 | |||
370 | if (skb->len < hdrlen) { | ||
371 | printk(KERN_INFO "%s: invalid SKB length %d\n", | ||
372 | dev->name, skb->len); | ||
373 | goto rx_dropped; | ||
374 | } | ||
375 | |||
376 | /* Put this code here so that we avoid duplicating it in all | ||
377 | * Rx paths. - Jean II */ | ||
378 | #ifdef CONFIG_WIRELESS_EXT | ||
379 | #ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */ | ||
380 | /* If spy monitoring on */ | ||
381 | if (ieee->spy_data.spy_number > 0) { | ||
382 | struct iw_quality wstats; | ||
383 | |||
384 | wstats.updated = 0; | ||
385 | if (rx_stats->mask & IEEE80211_STATMASK_RSSI) { | ||
386 | wstats.level = rx_stats->signal; | ||
387 | wstats.updated |= IW_QUAL_LEVEL_UPDATED; | ||
388 | } else | ||
389 | wstats.updated |= IW_QUAL_LEVEL_INVALID; | ||
390 | |||
391 | if (rx_stats->mask & IEEE80211_STATMASK_NOISE) { | ||
392 | wstats.noise = rx_stats->noise; | ||
393 | wstats.updated |= IW_QUAL_NOISE_UPDATED; | ||
394 | } else | ||
395 | wstats.updated |= IW_QUAL_NOISE_INVALID; | ||
396 | |||
397 | if (rx_stats->mask & IEEE80211_STATMASK_SIGNAL) { | ||
398 | wstats.qual = rx_stats->signal; | ||
399 | wstats.updated |= IW_QUAL_QUAL_UPDATED; | ||
400 | } else | ||
401 | wstats.updated |= IW_QUAL_QUAL_INVALID; | ||
402 | |||
403 | /* Update spy records */ | ||
404 | wireless_spy_update(ieee->dev, hdr->addr2, &wstats); | ||
405 | } | ||
406 | #endif /* IW_WIRELESS_SPY */ | ||
407 | #endif /* CONFIG_WIRELESS_EXT */ | ||
408 | |||
409 | #ifdef NOT_YET | ||
410 | hostap_update_rx_stats(local->ap, hdr, rx_stats); | ||
411 | #endif | ||
412 | |||
413 | if (ieee->iw_mode == IW_MODE_MONITOR) { | ||
414 | stats->rx_packets++; | ||
415 | stats->rx_bytes += skb->len; | ||
416 | ieee80211_monitor_rx(ieee, skb, rx_stats); | ||
417 | return 1; | ||
418 | } | ||
419 | |||
420 | can_be_decrypted = (is_multicast_ether_addr(hdr->addr1) || | ||
421 | is_broadcast_ether_addr(hdr->addr2)) ? | ||
422 | ieee->host_mc_decrypt : ieee->host_decrypt; | ||
423 | |||
424 | if (can_be_decrypted) { | ||
425 | if (skb->len >= hdrlen + 3) { | ||
426 | /* Top two-bits of byte 3 are the key index */ | ||
427 | keyidx = skb->data[hdrlen + 3] >> 6; | ||
428 | } | ||
429 | |||
430 | /* ieee->crypt[] is WEP_KEY (4) in length. Given that keyidx | ||
431 | * is only allowed 2-bits of storage, no value of keyidx can | ||
432 | * be provided via above code that would result in keyidx | ||
433 | * being out of range */ | ||
434 | crypt = ieee->crypt_info.crypt[keyidx]; | ||
435 | |||
436 | #ifdef NOT_YET | ||
437 | sta = NULL; | ||
438 | |||
439 | /* Use station specific key to override default keys if the | ||
440 | * receiver address is a unicast address ("individual RA"). If | ||
441 | * bcrx_sta_key parameter is set, station specific key is used | ||
442 | * even with broad/multicast targets (this is against IEEE | ||
443 | * 802.11, but makes it easier to use different keys with | ||
444 | * stations that do not support WEP key mapping). */ | ||
445 | |||
446 | if (!(hdr->addr1[0] & 0x01) || local->bcrx_sta_key) | ||
447 | (void)hostap_handle_sta_crypto(local, hdr, &crypt, | ||
448 | &sta); | ||
449 | #endif | ||
450 | |||
451 | /* allow NULL decrypt to indicate an station specific override | ||
452 | * for default encryption */ | ||
453 | if (crypt && (crypt->ops == NULL || | ||
454 | crypt->ops->decrypt_mpdu == NULL)) | ||
455 | crypt = NULL; | ||
456 | |||
457 | if (!crypt && (fc & IEEE80211_FCTL_PROTECTED)) { | ||
458 | /* This seems to be triggered by some (multicast?) | ||
459 | * frames from other than current BSS, so just drop the | ||
460 | * frames silently instead of filling system log with | ||
461 | * these reports. */ | ||
462 | IEEE80211_DEBUG_DROP("Decryption failed (not set)" | ||
463 | " (SA=%pM)\n", hdr->addr2); | ||
464 | ieee->ieee_stats.rx_discards_undecryptable++; | ||
465 | goto rx_dropped; | ||
466 | } | ||
467 | } | ||
468 | #ifdef NOT_YET | ||
469 | if (type != WLAN_FC_TYPE_DATA) { | ||
470 | if (type == WLAN_FC_TYPE_MGMT && stype == WLAN_FC_STYPE_AUTH && | ||
471 | fc & IEEE80211_FCTL_PROTECTED && ieee->host_decrypt && | ||
472 | (keyidx = hostap_rx_frame_decrypt(ieee, skb, crypt)) < 0) { | ||
473 | printk(KERN_DEBUG "%s: failed to decrypt mgmt::auth " | ||
474 | "from %pM\n", dev->name, hdr->addr2); | ||
475 | /* TODO: could inform hostapd about this so that it | ||
476 | * could send auth failure report */ | ||
477 | goto rx_dropped; | ||
478 | } | ||
479 | |||
480 | if (ieee80211_rx_frame_mgmt(ieee, skb, rx_stats, type, stype)) | ||
481 | goto rx_dropped; | ||
482 | else | ||
483 | goto rx_exit; | ||
484 | } | ||
485 | #endif | ||
486 | /* drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.29) */ | ||
487 | if (sc == ieee->prev_seq_ctl) | ||
488 | goto rx_dropped; | ||
489 | else | ||
490 | ieee->prev_seq_ctl = sc; | ||
491 | |||
492 | /* Data frame - extract src/dst addresses */ | ||
493 | if (skb->len < IEEE80211_3ADDR_LEN) | ||
494 | goto rx_dropped; | ||
495 | |||
496 | switch (fc & (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) { | ||
497 | case IEEE80211_FCTL_FROMDS: | ||
498 | memcpy(dst, hdr->addr1, ETH_ALEN); | ||
499 | memcpy(src, hdr->addr3, ETH_ALEN); | ||
500 | break; | ||
501 | case IEEE80211_FCTL_TODS: | ||
502 | memcpy(dst, hdr->addr3, ETH_ALEN); | ||
503 | memcpy(src, hdr->addr2, ETH_ALEN); | ||
504 | break; | ||
505 | case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS: | ||
506 | if (skb->len < IEEE80211_4ADDR_LEN) | ||
507 | goto rx_dropped; | ||
508 | memcpy(dst, hdr->addr3, ETH_ALEN); | ||
509 | memcpy(src, hdr->addr4, ETH_ALEN); | ||
510 | break; | ||
511 | case 0: | ||
512 | memcpy(dst, hdr->addr1, ETH_ALEN); | ||
513 | memcpy(src, hdr->addr2, ETH_ALEN); | ||
514 | break; | ||
515 | } | ||
516 | |||
517 | #ifdef NOT_YET | ||
518 | if (hostap_rx_frame_wds(ieee, hdr, fc, &wds)) | ||
519 | goto rx_dropped; | ||
520 | if (wds) { | ||
521 | skb->dev = dev = wds; | ||
522 | stats = hostap_get_stats(dev); | ||
523 | } | ||
524 | |||
525 | if (ieee->iw_mode == IW_MODE_MASTER && !wds && | ||
526 | (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == | ||
527 | IEEE80211_FCTL_FROMDS && ieee->stadev | ||
528 | && !compare_ether_addr(hdr->addr2, ieee->assoc_ap_addr)) { | ||
529 | /* Frame from BSSID of the AP for which we are a client */ | ||
530 | skb->dev = dev = ieee->stadev; | ||
531 | stats = hostap_get_stats(dev); | ||
532 | from_assoc_ap = 1; | ||
533 | } | ||
534 | #endif | ||
535 | |||
536 | #ifdef NOT_YET | ||
537 | if ((ieee->iw_mode == IW_MODE_MASTER || | ||
538 | ieee->iw_mode == IW_MODE_REPEAT) && !from_assoc_ap) { | ||
539 | switch (hostap_handle_sta_rx(ieee, dev, skb, rx_stats, | ||
540 | wds != NULL)) { | ||
541 | case AP_RX_CONTINUE_NOT_AUTHORIZED: | ||
542 | frame_authorized = 0; | ||
543 | break; | ||
544 | case AP_RX_CONTINUE: | ||
545 | frame_authorized = 1; | ||
546 | break; | ||
547 | case AP_RX_DROP: | ||
548 | goto rx_dropped; | ||
549 | case AP_RX_EXIT: | ||
550 | goto rx_exit; | ||
551 | } | ||
552 | } | ||
553 | #endif | ||
554 | |||
555 | /* Nullfunc frames may have PS-bit set, so they must be passed to | ||
556 | * hostap_handle_sta_rx() before being dropped here. */ | ||
557 | |||
558 | stype &= ~IEEE80211_STYPE_QOS_DATA; | ||
559 | |||
560 | if (stype != IEEE80211_STYPE_DATA && | ||
561 | stype != IEEE80211_STYPE_DATA_CFACK && | ||
562 | stype != IEEE80211_STYPE_DATA_CFPOLL && | ||
563 | stype != IEEE80211_STYPE_DATA_CFACKPOLL) { | ||
564 | if (stype != IEEE80211_STYPE_NULLFUNC) | ||
565 | IEEE80211_DEBUG_DROP("RX: dropped data frame " | ||
566 | "with no data (type=0x%02x, " | ||
567 | "subtype=0x%02x, len=%d)\n", | ||
568 | type, stype, skb->len); | ||
569 | goto rx_dropped; | ||
570 | } | ||
571 | |||
572 | /* skb: hdr + (possibly fragmented, possibly encrypted) payload */ | ||
573 | |||
574 | if ((fc & IEEE80211_FCTL_PROTECTED) && can_be_decrypted && | ||
575 | (keyidx = ieee80211_rx_frame_decrypt(ieee, skb, crypt)) < 0) | ||
576 | goto rx_dropped; | ||
577 | |||
578 | hdr = (struct ieee80211_hdr_4addr *)skb->data; | ||
579 | |||
580 | /* skb: hdr + (possibly fragmented) plaintext payload */ | ||
581 | // PR: FIXME: hostap has additional conditions in the "if" below: | ||
582 | // ieee->host_decrypt && (fc & IEEE80211_FCTL_PROTECTED) && | ||
583 | if ((frag != 0) || (fc & IEEE80211_FCTL_MOREFRAGS)) { | ||
584 | int flen; | ||
585 | struct sk_buff *frag_skb = ieee80211_frag_cache_get(ieee, hdr); | ||
586 | IEEE80211_DEBUG_FRAG("Rx Fragment received (%u)\n", frag); | ||
587 | |||
588 | if (!frag_skb) { | ||
589 | IEEE80211_DEBUG(IEEE80211_DL_RX | IEEE80211_DL_FRAG, | ||
590 | "Rx cannot get skb from fragment " | ||
591 | "cache (morefrag=%d seq=%u frag=%u)\n", | ||
592 | (fc & IEEE80211_FCTL_MOREFRAGS) != 0, | ||
593 | WLAN_GET_SEQ_SEQ(sc), frag); | ||
594 | goto rx_dropped; | ||
595 | } | ||
596 | |||
597 | flen = skb->len; | ||
598 | if (frag != 0) | ||
599 | flen -= hdrlen; | ||
600 | |||
601 | if (frag_skb->tail + flen > frag_skb->end) { | ||
602 | printk(KERN_WARNING "%s: host decrypted and " | ||
603 | "reassembled frame did not fit skb\n", | ||
604 | dev->name); | ||
605 | ieee80211_frag_cache_invalidate(ieee, hdr); | ||
606 | goto rx_dropped; | ||
607 | } | ||
608 | |||
609 | if (frag == 0) { | ||
610 | /* copy first fragment (including full headers) into | ||
611 | * beginning of the fragment cache skb */ | ||
612 | skb_copy_from_linear_data(skb, skb_put(frag_skb, flen), flen); | ||
613 | } else { | ||
614 | /* append frame payload to the end of the fragment | ||
615 | * cache skb */ | ||
616 | skb_copy_from_linear_data_offset(skb, hdrlen, | ||
617 | skb_put(frag_skb, flen), flen); | ||
618 | } | ||
619 | dev_kfree_skb_any(skb); | ||
620 | skb = NULL; | ||
621 | |||
622 | if (fc & IEEE80211_FCTL_MOREFRAGS) { | ||
623 | /* more fragments expected - leave the skb in fragment | ||
624 | * cache for now; it will be delivered to upper layers | ||
625 | * after all fragments have been received */ | ||
626 | goto rx_exit; | ||
627 | } | ||
628 | |||
629 | /* this was the last fragment and the frame will be | ||
630 | * delivered, so remove skb from fragment cache */ | ||
631 | skb = frag_skb; | ||
632 | hdr = (struct ieee80211_hdr_4addr *)skb->data; | ||
633 | ieee80211_frag_cache_invalidate(ieee, hdr); | ||
634 | } | ||
635 | |||
636 | /* skb: hdr + (possible reassembled) full MSDU payload; possibly still | ||
637 | * encrypted/authenticated */ | ||
638 | if ((fc & IEEE80211_FCTL_PROTECTED) && can_be_decrypted && | ||
639 | ieee80211_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt)) | ||
640 | goto rx_dropped; | ||
641 | |||
642 | hdr = (struct ieee80211_hdr_4addr *)skb->data; | ||
643 | if (crypt && !(fc & IEEE80211_FCTL_PROTECTED) && !ieee->open_wep) { | ||
644 | if ( /*ieee->ieee802_1x && */ | ||
645 | ieee80211_is_eapol_frame(ieee, skb)) { | ||
646 | /* pass unencrypted EAPOL frames even if encryption is | ||
647 | * configured */ | ||
648 | } else { | ||
649 | IEEE80211_DEBUG_DROP("encryption configured, but RX " | ||
650 | "frame not encrypted (SA=%pM)\n", | ||
651 | hdr->addr2); | ||
652 | goto rx_dropped; | ||
653 | } | ||
654 | } | ||
655 | |||
656 | if (crypt && !(fc & IEEE80211_FCTL_PROTECTED) && !ieee->open_wep && | ||
657 | !ieee80211_is_eapol_frame(ieee, skb)) { | ||
658 | IEEE80211_DEBUG_DROP("dropped unencrypted RX data " | ||
659 | "frame from %pM (drop_unencrypted=1)\n", | ||
660 | hdr->addr2); | ||
661 | goto rx_dropped; | ||
662 | } | ||
663 | |||
664 | /* If the frame was decrypted in hardware, we may need to strip off | ||
665 | * any security data (IV, ICV, etc) that was left behind */ | ||
666 | if (!can_be_decrypted && (fc & IEEE80211_FCTL_PROTECTED) && | ||
667 | ieee->host_strip_iv_icv) { | ||
668 | int trimlen = 0; | ||
669 | |||
670 | /* Top two-bits of byte 3 are the key index */ | ||
671 | if (skb->len >= hdrlen + 3) | ||
672 | keyidx = skb->data[hdrlen + 3] >> 6; | ||
673 | |||
674 | /* To strip off any security data which appears before the | ||
675 | * payload, we simply increase hdrlen (as the header gets | ||
676 | * chopped off immediately below). For the security data which | ||
677 | * appears after the payload, we use skb_trim. */ | ||
678 | |||
679 | switch (ieee->sec.encode_alg[keyidx]) { | ||
680 | case SEC_ALG_WEP: | ||
681 | /* 4 byte IV */ | ||
682 | hdrlen += 4; | ||
683 | /* 4 byte ICV */ | ||
684 | trimlen = 4; | ||
685 | break; | ||
686 | case SEC_ALG_TKIP: | ||
687 | /* 4 byte IV, 4 byte ExtIV */ | ||
688 | hdrlen += 8; | ||
689 | /* 8 byte MIC, 4 byte ICV */ | ||
690 | trimlen = 12; | ||
691 | break; | ||
692 | case SEC_ALG_CCMP: | ||
693 | /* 8 byte CCMP header */ | ||
694 | hdrlen += 8; | ||
695 | /* 8 byte MIC */ | ||
696 | trimlen = 8; | ||
697 | break; | ||
698 | } | ||
699 | |||
700 | if (skb->len < trimlen) | ||
701 | goto rx_dropped; | ||
702 | |||
703 | __skb_trim(skb, skb->len - trimlen); | ||
704 | |||
705 | if (skb->len < hdrlen) | ||
706 | goto rx_dropped; | ||
707 | } | ||
708 | |||
709 | /* skb: hdr + (possible reassembled) full plaintext payload */ | ||
710 | |||
711 | payload = skb->data + hdrlen; | ||
712 | ethertype = (payload[6] << 8) | payload[7]; | ||
713 | |||
714 | #ifdef NOT_YET | ||
715 | /* If IEEE 802.1X is used, check whether the port is authorized to send | ||
716 | * the received frame. */ | ||
717 | if (ieee->ieee802_1x && ieee->iw_mode == IW_MODE_MASTER) { | ||
718 | if (ethertype == ETH_P_PAE) { | ||
719 | printk(KERN_DEBUG "%s: RX: IEEE 802.1X frame\n", | ||
720 | dev->name); | ||
721 | if (ieee->hostapd && ieee->apdev) { | ||
722 | /* Send IEEE 802.1X frames to the user | ||
723 | * space daemon for processing */ | ||
724 | prism2_rx_80211(ieee->apdev, skb, rx_stats, | ||
725 | PRISM2_RX_MGMT); | ||
726 | ieee->apdevstats.rx_packets++; | ||
727 | ieee->apdevstats.rx_bytes += skb->len; | ||
728 | goto rx_exit; | ||
729 | } | ||
730 | } else if (!frame_authorized) { | ||
731 | printk(KERN_DEBUG "%s: dropped frame from " | ||
732 | "unauthorized port (IEEE 802.1X): " | ||
733 | "ethertype=0x%04x\n", dev->name, ethertype); | ||
734 | goto rx_dropped; | ||
735 | } | ||
736 | } | ||
737 | #endif | ||
738 | |||
739 | /* convert hdr + possible LLC headers into Ethernet header */ | ||
740 | if (skb->len - hdrlen >= 8 && | ||
741 | ((memcmp(payload, rfc1042_header, SNAP_SIZE) == 0 && | ||
742 | ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) || | ||
743 | memcmp(payload, bridge_tunnel_header, SNAP_SIZE) == 0)) { | ||
744 | /* remove RFC1042 or Bridge-Tunnel encapsulation and | ||
745 | * replace EtherType */ | ||
746 | skb_pull(skb, hdrlen + SNAP_SIZE); | ||
747 | memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN); | ||
748 | memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN); | ||
749 | } else { | ||
750 | __be16 len; | ||
751 | /* Leave Ethernet header part of hdr and full payload */ | ||
752 | skb_pull(skb, hdrlen); | ||
753 | len = htons(skb->len); | ||
754 | memcpy(skb_push(skb, 2), &len, 2); | ||
755 | memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN); | ||
756 | memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN); | ||
757 | } | ||
758 | |||
759 | #ifdef NOT_YET | ||
760 | if (wds && ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == | ||
761 | IEEE80211_FCTL_TODS) && skb->len >= ETH_HLEN + ETH_ALEN) { | ||
762 | /* Non-standard frame: get addr4 from its bogus location after | ||
763 | * the payload */ | ||
764 | skb_copy_to_linear_data_offset(skb, ETH_ALEN, | ||
765 | skb->data + skb->len - ETH_ALEN, | ||
766 | ETH_ALEN); | ||
767 | skb_trim(skb, skb->len - ETH_ALEN); | ||
768 | } | ||
769 | #endif | ||
770 | |||
771 | stats->rx_packets++; | ||
772 | stats->rx_bytes += skb->len; | ||
773 | |||
774 | #ifdef NOT_YET | ||
775 | if (ieee->iw_mode == IW_MODE_MASTER && !wds && ieee->ap->bridge_packets) { | ||
776 | if (dst[0] & 0x01) { | ||
777 | /* copy multicast frame both to the higher layers and | ||
778 | * to the wireless media */ | ||
779 | ieee->ap->bridged_multicast++; | ||
780 | skb2 = skb_clone(skb, GFP_ATOMIC); | ||
781 | if (skb2 == NULL) | ||
782 | printk(KERN_DEBUG "%s: skb_clone failed for " | ||
783 | "multicast frame\n", dev->name); | ||
784 | } else if (hostap_is_sta_assoc(ieee->ap, dst)) { | ||
785 | /* send frame directly to the associated STA using | ||
786 | * wireless media and not passing to higher layers */ | ||
787 | ieee->ap->bridged_unicast++; | ||
788 | skb2 = skb; | ||
789 | skb = NULL; | ||
790 | } | ||
791 | } | ||
792 | |||
793 | if (skb2 != NULL) { | ||
794 | /* send to wireless media */ | ||
795 | skb2->dev = dev; | ||
796 | skb2->protocol = htons(ETH_P_802_3); | ||
797 | skb_reset_mac_header(skb2); | ||
798 | skb_reset_network_header(skb2); | ||
799 | /* skb2->network_header += ETH_HLEN; */ | ||
800 | dev_queue_xmit(skb2); | ||
801 | } | ||
802 | #endif | ||
803 | |||
804 | if (skb) { | ||
805 | skb->protocol = eth_type_trans(skb, dev); | ||
806 | memset(skb->cb, 0, sizeof(skb->cb)); | ||
807 | skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */ | ||
808 | if (netif_rx(skb) == NET_RX_DROP) { | ||
809 | /* netif_rx always succeeds, but it might drop | ||
810 | * the packet. If it drops the packet, we log that | ||
811 | * in our stats. */ | ||
812 | IEEE80211_DEBUG_DROP | ||
813 | ("RX: netif_rx dropped the packet\n"); | ||
814 | stats->rx_dropped++; | ||
815 | } | ||
816 | } | ||
817 | |||
818 | rx_exit: | ||
819 | #ifdef NOT_YET | ||
820 | if (sta) | ||
821 | hostap_handle_sta_release(sta); | ||
822 | #endif | ||
823 | return 1; | ||
824 | |||
825 | rx_dropped: | ||
826 | stats->rx_dropped++; | ||
827 | |||
828 | /* Returning 0 indicates to caller that we have not handled the SKB-- | ||
829 | * so it is still allocated and can be used again by underlying | ||
830 | * hardware as a DMA target */ | ||
831 | return 0; | ||
832 | } | ||
833 | |||
834 | /* Filter out unrelated packets, call ieee80211_rx[_mgt] | ||
835 | * This function takes over the skb, it should not be used again after calling | ||
836 | * this function. */ | ||
837 | void ieee80211_rx_any(struct ieee80211_device *ieee, | ||
838 | struct sk_buff *skb, struct ieee80211_rx_stats *stats) | ||
839 | { | ||
840 | struct ieee80211_hdr_4addr *hdr; | ||
841 | int is_packet_for_us; | ||
842 | u16 fc; | ||
843 | |||
844 | if (ieee->iw_mode == IW_MODE_MONITOR) { | ||
845 | if (!ieee80211_rx(ieee, skb, stats)) | ||
846 | dev_kfree_skb_irq(skb); | ||
847 | return; | ||
848 | } | ||
849 | |||
850 | if (skb->len < sizeof(struct ieee80211_hdr)) | ||
851 | goto drop_free; | ||
852 | |||
853 | hdr = (struct ieee80211_hdr_4addr *)skb->data; | ||
854 | fc = le16_to_cpu(hdr->frame_ctl); | ||
855 | |||
856 | if ((fc & IEEE80211_FCTL_VERS) != 0) | ||
857 | goto drop_free; | ||
858 | |||
859 | switch (fc & IEEE80211_FCTL_FTYPE) { | ||
860 | case IEEE80211_FTYPE_MGMT: | ||
861 | if (skb->len < sizeof(struct ieee80211_hdr_3addr)) | ||
862 | goto drop_free; | ||
863 | ieee80211_rx_mgt(ieee, hdr, stats); | ||
864 | dev_kfree_skb_irq(skb); | ||
865 | return; | ||
866 | case IEEE80211_FTYPE_DATA: | ||
867 | break; | ||
868 | case IEEE80211_FTYPE_CTL: | ||
869 | return; | ||
870 | default: | ||
871 | return; | ||
872 | } | ||
873 | |||
874 | is_packet_for_us = 0; | ||
875 | switch (ieee->iw_mode) { | ||
876 | case IW_MODE_ADHOC: | ||
877 | /* our BSS and not from/to DS */ | ||
878 | if (memcmp(hdr->addr3, ieee->bssid, ETH_ALEN) == 0) | ||
879 | if ((fc & (IEEE80211_FCTL_TODS+IEEE80211_FCTL_FROMDS)) == 0) { | ||
880 | /* promisc: get all */ | ||
881 | if (ieee->dev->flags & IFF_PROMISC) | ||
882 | is_packet_for_us = 1; | ||
883 | /* to us */ | ||
884 | else if (memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN) == 0) | ||
885 | is_packet_for_us = 1; | ||
886 | /* mcast */ | ||
887 | else if (is_multicast_ether_addr(hdr->addr1)) | ||
888 | is_packet_for_us = 1; | ||
889 | } | ||
890 | break; | ||
891 | case IW_MODE_INFRA: | ||
892 | /* our BSS (== from our AP) and from DS */ | ||
893 | if (memcmp(hdr->addr2, ieee->bssid, ETH_ALEN) == 0) | ||
894 | if ((fc & (IEEE80211_FCTL_TODS+IEEE80211_FCTL_FROMDS)) == IEEE80211_FCTL_FROMDS) { | ||
895 | /* promisc: get all */ | ||
896 | if (ieee->dev->flags & IFF_PROMISC) | ||
897 | is_packet_for_us = 1; | ||
898 | /* to us */ | ||
899 | else if (memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN) == 0) | ||
900 | is_packet_for_us = 1; | ||
901 | /* mcast */ | ||
902 | else if (is_multicast_ether_addr(hdr->addr1)) { | ||
903 | /* not our own packet bcasted from AP */ | ||
904 | if (memcmp(hdr->addr3, ieee->dev->dev_addr, ETH_ALEN)) | ||
905 | is_packet_for_us = 1; | ||
906 | } | ||
907 | } | ||
908 | break; | ||
909 | default: | ||
910 | /* ? */ | ||
911 | break; | ||
912 | } | ||
913 | |||
914 | if (is_packet_for_us) | ||
915 | if (!ieee80211_rx(ieee, skb, stats)) | ||
916 | dev_kfree_skb_irq(skb); | ||
917 | return; | ||
918 | |||
919 | drop_free: | ||
920 | dev_kfree_skb_irq(skb); | ||
921 | ieee->stats.rx_dropped++; | ||
922 | return; | ||
923 | } | ||
924 | |||
925 | #define MGMT_FRAME_FIXED_PART_LENGTH 0x24 | ||
926 | |||
927 | static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 }; | ||
928 | |||
929 | /* | ||
930 | * Make ther structure we read from the beacon packet has | ||
931 | * the right values | ||
932 | */ | ||
933 | static int ieee80211_verify_qos_info(struct ieee80211_qos_information_element | ||
934 | *info_element, int sub_type) | ||
935 | { | ||
936 | |||
937 | if (info_element->qui_subtype != sub_type) | ||
938 | return -1; | ||
939 | if (memcmp(info_element->qui, qos_oui, QOS_OUI_LEN)) | ||
940 | return -1; | ||
941 | if (info_element->qui_type != QOS_OUI_TYPE) | ||
942 | return -1; | ||
943 | if (info_element->version != QOS_VERSION_1) | ||
944 | return -1; | ||
945 | |||
946 | return 0; | ||
947 | } | ||
948 | |||
949 | /* | ||
950 | * Parse a QoS parameter element | ||
951 | */ | ||
952 | static int ieee80211_read_qos_param_element(struct ieee80211_qos_parameter_info | ||
953 | *element_param, struct ieee80211_info_element | ||
954 | *info_element) | ||
955 | { | ||
956 | int ret = 0; | ||
957 | u16 size = sizeof(struct ieee80211_qos_parameter_info) - 2; | ||
958 | |||
959 | if ((info_element == NULL) || (element_param == NULL)) | ||
960 | return -1; | ||
961 | |||
962 | if (info_element->id == QOS_ELEMENT_ID && info_element->len == size) { | ||
963 | memcpy(element_param->info_element.qui, info_element->data, | ||
964 | info_element->len); | ||
965 | element_param->info_element.elementID = info_element->id; | ||
966 | element_param->info_element.length = info_element->len; | ||
967 | } else | ||
968 | ret = -1; | ||
969 | if (ret == 0) | ||
970 | ret = ieee80211_verify_qos_info(&element_param->info_element, | ||
971 | QOS_OUI_PARAM_SUB_TYPE); | ||
972 | return ret; | ||
973 | } | ||
974 | |||
975 | /* | ||
976 | * Parse a QoS information element | ||
977 | */ | ||
978 | static int ieee80211_read_qos_info_element(struct | ||
979 | ieee80211_qos_information_element | ||
980 | *element_info, struct ieee80211_info_element | ||
981 | *info_element) | ||
982 | { | ||
983 | int ret = 0; | ||
984 | u16 size = sizeof(struct ieee80211_qos_information_element) - 2; | ||
985 | |||
986 | if (element_info == NULL) | ||
987 | return -1; | ||
988 | if (info_element == NULL) | ||
989 | return -1; | ||
990 | |||
991 | if ((info_element->id == QOS_ELEMENT_ID) && (info_element->len == size)) { | ||
992 | memcpy(element_info->qui, info_element->data, | ||
993 | info_element->len); | ||
994 | element_info->elementID = info_element->id; | ||
995 | element_info->length = info_element->len; | ||
996 | } else | ||
997 | ret = -1; | ||
998 | |||
999 | if (ret == 0) | ||
1000 | ret = ieee80211_verify_qos_info(element_info, | ||
1001 | QOS_OUI_INFO_SUB_TYPE); | ||
1002 | return ret; | ||
1003 | } | ||
1004 | |||
1005 | /* | ||
1006 | * Write QoS parameters from the ac parameters. | ||
1007 | */ | ||
1008 | static int ieee80211_qos_convert_ac_to_parameters(struct | ||
1009 | ieee80211_qos_parameter_info | ||
1010 | *param_elm, struct | ||
1011 | ieee80211_qos_parameters | ||
1012 | *qos_param) | ||
1013 | { | ||
1014 | int rc = 0; | ||
1015 | int i; | ||
1016 | struct ieee80211_qos_ac_parameter *ac_params; | ||
1017 | u32 txop; | ||
1018 | u8 cw_min; | ||
1019 | u8 cw_max; | ||
1020 | |||
1021 | for (i = 0; i < QOS_QUEUE_NUM; i++) { | ||
1022 | ac_params = &(param_elm->ac_params_record[i]); | ||
1023 | |||
1024 | qos_param->aifs[i] = (ac_params->aci_aifsn) & 0x0F; | ||
1025 | qos_param->aifs[i] -= (qos_param->aifs[i] < 2) ? 0 : 2; | ||
1026 | |||
1027 | cw_min = ac_params->ecw_min_max & 0x0F; | ||
1028 | qos_param->cw_min[i] = cpu_to_le16((1 << cw_min) - 1); | ||
1029 | |||
1030 | cw_max = (ac_params->ecw_min_max & 0xF0) >> 4; | ||
1031 | qos_param->cw_max[i] = cpu_to_le16((1 << cw_max) - 1); | ||
1032 | |||
1033 | qos_param->flag[i] = | ||
1034 | (ac_params->aci_aifsn & 0x10) ? 0x01 : 0x00; | ||
1035 | |||
1036 | txop = le16_to_cpu(ac_params->tx_op_limit) * 32; | ||
1037 | qos_param->tx_op_limit[i] = cpu_to_le16(txop); | ||
1038 | } | ||
1039 | return rc; | ||
1040 | } | ||
1041 | |||
1042 | /* | ||
1043 | * we have a generic data element which it may contain QoS information or | ||
1044 | * parameters element. check the information element length to decide | ||
1045 | * which type to read | ||
1046 | */ | ||
1047 | static int ieee80211_parse_qos_info_param_IE(struct ieee80211_info_element | ||
1048 | *info_element, | ||
1049 | struct ieee80211_network *network) | ||
1050 | { | ||
1051 | int rc = 0; | ||
1052 | struct ieee80211_qos_parameters *qos_param = NULL; | ||
1053 | struct ieee80211_qos_information_element qos_info_element; | ||
1054 | |||
1055 | rc = ieee80211_read_qos_info_element(&qos_info_element, info_element); | ||
1056 | |||
1057 | if (rc == 0) { | ||
1058 | network->qos_data.param_count = qos_info_element.ac_info & 0x0F; | ||
1059 | network->flags |= NETWORK_HAS_QOS_INFORMATION; | ||
1060 | } else { | ||
1061 | struct ieee80211_qos_parameter_info param_element; | ||
1062 | |||
1063 | rc = ieee80211_read_qos_param_element(¶m_element, | ||
1064 | info_element); | ||
1065 | if (rc == 0) { | ||
1066 | qos_param = &(network->qos_data.parameters); | ||
1067 | ieee80211_qos_convert_ac_to_parameters(¶m_element, | ||
1068 | qos_param); | ||
1069 | network->flags |= NETWORK_HAS_QOS_PARAMETERS; | ||
1070 | network->qos_data.param_count = | ||
1071 | param_element.info_element.ac_info & 0x0F; | ||
1072 | } | ||
1073 | } | ||
1074 | |||
1075 | if (rc == 0) { | ||
1076 | IEEE80211_DEBUG_QOS("QoS is supported\n"); | ||
1077 | network->qos_data.supported = 1; | ||
1078 | } | ||
1079 | return rc; | ||
1080 | } | ||
1081 | |||
1082 | #ifdef CONFIG_IEEE80211_DEBUG | ||
1083 | #define MFIE_STRING(x) case MFIE_TYPE_ ##x: return #x | ||
1084 | |||
1085 | static const char *get_info_element_string(u16 id) | ||
1086 | { | ||
1087 | switch (id) { | ||
1088 | MFIE_STRING(SSID); | ||
1089 | MFIE_STRING(RATES); | ||
1090 | MFIE_STRING(FH_SET); | ||
1091 | MFIE_STRING(DS_SET); | ||
1092 | MFIE_STRING(CF_SET); | ||
1093 | MFIE_STRING(TIM); | ||
1094 | MFIE_STRING(IBSS_SET); | ||
1095 | MFIE_STRING(COUNTRY); | ||
1096 | MFIE_STRING(HOP_PARAMS); | ||
1097 | MFIE_STRING(HOP_TABLE); | ||
1098 | MFIE_STRING(REQUEST); | ||
1099 | MFIE_STRING(CHALLENGE); | ||
1100 | MFIE_STRING(POWER_CONSTRAINT); | ||
1101 | MFIE_STRING(POWER_CAPABILITY); | ||
1102 | MFIE_STRING(TPC_REQUEST); | ||
1103 | MFIE_STRING(TPC_REPORT); | ||
1104 | MFIE_STRING(SUPP_CHANNELS); | ||
1105 | MFIE_STRING(CSA); | ||
1106 | MFIE_STRING(MEASURE_REQUEST); | ||
1107 | MFIE_STRING(MEASURE_REPORT); | ||
1108 | MFIE_STRING(QUIET); | ||
1109 | MFIE_STRING(IBSS_DFS); | ||
1110 | MFIE_STRING(ERP_INFO); | ||
1111 | MFIE_STRING(RSN); | ||
1112 | MFIE_STRING(RATES_EX); | ||
1113 | MFIE_STRING(GENERIC); | ||
1114 | MFIE_STRING(QOS_PARAMETER); | ||
1115 | default: | ||
1116 | return "UNKNOWN"; | ||
1117 | } | ||
1118 | } | ||
1119 | #endif | ||
1120 | |||
1121 | static int ieee80211_parse_info_param(struct ieee80211_info_element | ||
1122 | *info_element, u16 length, | ||
1123 | struct ieee80211_network *network) | ||
1124 | { | ||
1125 | DECLARE_SSID_BUF(ssid); | ||
1126 | u8 i; | ||
1127 | #ifdef CONFIG_IEEE80211_DEBUG | ||
1128 | char rates_str[64]; | ||
1129 | char *p; | ||
1130 | #endif | ||
1131 | |||
1132 | while (length >= sizeof(*info_element)) { | ||
1133 | if (sizeof(*info_element) + info_element->len > length) { | ||
1134 | IEEE80211_DEBUG_MGMT("Info elem: parse failed: " | ||
1135 | "info_element->len + 2 > left : " | ||
1136 | "info_element->len+2=%zd left=%d, id=%d.\n", | ||
1137 | info_element->len + | ||
1138 | sizeof(*info_element), | ||
1139 | length, info_element->id); | ||
1140 | /* We stop processing but don't return an error here | ||
1141 | * because some misbehaviour APs break this rule. ie. | ||
1142 | * Orinoco AP1000. */ | ||
1143 | break; | ||
1144 | } | ||
1145 | |||
1146 | switch (info_element->id) { | ||
1147 | case MFIE_TYPE_SSID: | ||
1148 | network->ssid_len = min(info_element->len, | ||
1149 | (u8) IW_ESSID_MAX_SIZE); | ||
1150 | memcpy(network->ssid, info_element->data, | ||
1151 | network->ssid_len); | ||
1152 | if (network->ssid_len < IW_ESSID_MAX_SIZE) | ||
1153 | memset(network->ssid + network->ssid_len, 0, | ||
1154 | IW_ESSID_MAX_SIZE - network->ssid_len); | ||
1155 | |||
1156 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_SSID: '%s' len=%d.\n", | ||
1157 | print_ssid(ssid, network->ssid, | ||
1158 | network->ssid_len), | ||
1159 | network->ssid_len); | ||
1160 | break; | ||
1161 | |||
1162 | case MFIE_TYPE_RATES: | ||
1163 | #ifdef CONFIG_IEEE80211_DEBUG | ||
1164 | p = rates_str; | ||
1165 | #endif | ||
1166 | network->rates_len = min(info_element->len, | ||
1167 | MAX_RATES_LENGTH); | ||
1168 | for (i = 0; i < network->rates_len; i++) { | ||
1169 | network->rates[i] = info_element->data[i]; | ||
1170 | #ifdef CONFIG_IEEE80211_DEBUG | ||
1171 | p += snprintf(p, sizeof(rates_str) - | ||
1172 | (p - rates_str), "%02X ", | ||
1173 | network->rates[i]); | ||
1174 | #endif | ||
1175 | if (ieee80211_is_ofdm_rate | ||
1176 | (info_element->data[i])) { | ||
1177 | network->flags |= NETWORK_HAS_OFDM; | ||
1178 | if (info_element->data[i] & | ||
1179 | IEEE80211_BASIC_RATE_MASK) | ||
1180 | network->flags &= | ||
1181 | ~NETWORK_HAS_CCK; | ||
1182 | } | ||
1183 | } | ||
1184 | |||
1185 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES: '%s' (%d)\n", | ||
1186 | rates_str, network->rates_len); | ||
1187 | break; | ||
1188 | |||
1189 | case MFIE_TYPE_RATES_EX: | ||
1190 | #ifdef CONFIG_IEEE80211_DEBUG | ||
1191 | p = rates_str; | ||
1192 | #endif | ||
1193 | network->rates_ex_len = min(info_element->len, | ||
1194 | MAX_RATES_EX_LENGTH); | ||
1195 | for (i = 0; i < network->rates_ex_len; i++) { | ||
1196 | network->rates_ex[i] = info_element->data[i]; | ||
1197 | #ifdef CONFIG_IEEE80211_DEBUG | ||
1198 | p += snprintf(p, sizeof(rates_str) - | ||
1199 | (p - rates_str), "%02X ", | ||
1200 | network->rates[i]); | ||
1201 | #endif | ||
1202 | if (ieee80211_is_ofdm_rate | ||
1203 | (info_element->data[i])) { | ||
1204 | network->flags |= NETWORK_HAS_OFDM; | ||
1205 | if (info_element->data[i] & | ||
1206 | IEEE80211_BASIC_RATE_MASK) | ||
1207 | network->flags &= | ||
1208 | ~NETWORK_HAS_CCK; | ||
1209 | } | ||
1210 | } | ||
1211 | |||
1212 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES_EX: '%s' (%d)\n", | ||
1213 | rates_str, network->rates_ex_len); | ||
1214 | break; | ||
1215 | |||
1216 | case MFIE_TYPE_DS_SET: | ||
1217 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_DS_SET: %d\n", | ||
1218 | info_element->data[0]); | ||
1219 | network->channel = info_element->data[0]; | ||
1220 | break; | ||
1221 | |||
1222 | case MFIE_TYPE_FH_SET: | ||
1223 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_FH_SET: ignored\n"); | ||
1224 | break; | ||
1225 | |||
1226 | case MFIE_TYPE_CF_SET: | ||
1227 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_CF_SET: ignored\n"); | ||
1228 | break; | ||
1229 | |||
1230 | case MFIE_TYPE_TIM: | ||
1231 | network->tim.tim_count = info_element->data[0]; | ||
1232 | network->tim.tim_period = info_element->data[1]; | ||
1233 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_TIM: partially ignored\n"); | ||
1234 | break; | ||
1235 | |||
1236 | case MFIE_TYPE_ERP_INFO: | ||
1237 | network->erp_value = info_element->data[0]; | ||
1238 | network->flags |= NETWORK_HAS_ERP_VALUE; | ||
1239 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_ERP_SET: %d\n", | ||
1240 | network->erp_value); | ||
1241 | break; | ||
1242 | |||
1243 | case MFIE_TYPE_IBSS_SET: | ||
1244 | network->atim_window = info_element->data[0]; | ||
1245 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_IBSS_SET: %d\n", | ||
1246 | network->atim_window); | ||
1247 | break; | ||
1248 | |||
1249 | case MFIE_TYPE_CHALLENGE: | ||
1250 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_CHALLENGE: ignored\n"); | ||
1251 | break; | ||
1252 | |||
1253 | case MFIE_TYPE_GENERIC: | ||
1254 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_GENERIC: %d bytes\n", | ||
1255 | info_element->len); | ||
1256 | if (!ieee80211_parse_qos_info_param_IE(info_element, | ||
1257 | network)) | ||
1258 | break; | ||
1259 | |||
1260 | if (info_element->len >= 4 && | ||
1261 | info_element->data[0] == 0x00 && | ||
1262 | info_element->data[1] == 0x50 && | ||
1263 | info_element->data[2] == 0xf2 && | ||
1264 | info_element->data[3] == 0x01) { | ||
1265 | network->wpa_ie_len = min(info_element->len + 2, | ||
1266 | MAX_WPA_IE_LEN); | ||
1267 | memcpy(network->wpa_ie, info_element, | ||
1268 | network->wpa_ie_len); | ||
1269 | } | ||
1270 | break; | ||
1271 | |||
1272 | case MFIE_TYPE_RSN: | ||
1273 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_RSN: %d bytes\n", | ||
1274 | info_element->len); | ||
1275 | network->rsn_ie_len = min(info_element->len + 2, | ||
1276 | MAX_WPA_IE_LEN); | ||
1277 | memcpy(network->rsn_ie, info_element, | ||
1278 | network->rsn_ie_len); | ||
1279 | break; | ||
1280 | |||
1281 | case MFIE_TYPE_QOS_PARAMETER: | ||
1282 | printk(KERN_ERR | ||
1283 | "QoS Error need to parse QOS_PARAMETER IE\n"); | ||
1284 | break; | ||
1285 | /* 802.11h */ | ||
1286 | case MFIE_TYPE_POWER_CONSTRAINT: | ||
1287 | network->power_constraint = info_element->data[0]; | ||
1288 | network->flags |= NETWORK_HAS_POWER_CONSTRAINT; | ||
1289 | break; | ||
1290 | |||
1291 | case MFIE_TYPE_CSA: | ||
1292 | network->power_constraint = info_element->data[0]; | ||
1293 | network->flags |= NETWORK_HAS_CSA; | ||
1294 | break; | ||
1295 | |||
1296 | case MFIE_TYPE_QUIET: | ||
1297 | network->quiet.count = info_element->data[0]; | ||
1298 | network->quiet.period = info_element->data[1]; | ||
1299 | network->quiet.duration = info_element->data[2]; | ||
1300 | network->quiet.offset = info_element->data[3]; | ||
1301 | network->flags |= NETWORK_HAS_QUIET; | ||
1302 | break; | ||
1303 | |||
1304 | case MFIE_TYPE_IBSS_DFS: | ||
1305 | if (network->ibss_dfs) | ||
1306 | break; | ||
1307 | network->ibss_dfs = kmemdup(info_element->data, | ||
1308 | info_element->len, | ||
1309 | GFP_ATOMIC); | ||
1310 | if (!network->ibss_dfs) | ||
1311 | return 1; | ||
1312 | network->flags |= NETWORK_HAS_IBSS_DFS; | ||
1313 | break; | ||
1314 | |||
1315 | case MFIE_TYPE_TPC_REPORT: | ||
1316 | network->tpc_report.transmit_power = | ||
1317 | info_element->data[0]; | ||
1318 | network->tpc_report.link_margin = info_element->data[1]; | ||
1319 | network->flags |= NETWORK_HAS_TPC_REPORT; | ||
1320 | break; | ||
1321 | |||
1322 | default: | ||
1323 | IEEE80211_DEBUG_MGMT | ||
1324 | ("Unsupported info element: %s (%d)\n", | ||
1325 | get_info_element_string(info_element->id), | ||
1326 | info_element->id); | ||
1327 | break; | ||
1328 | } | ||
1329 | |||
1330 | length -= sizeof(*info_element) + info_element->len; | ||
1331 | info_element = | ||
1332 | (struct ieee80211_info_element *)&info_element-> | ||
1333 | data[info_element->len]; | ||
1334 | } | ||
1335 | |||
1336 | return 0; | ||
1337 | } | ||
1338 | |||
1339 | static int ieee80211_handle_assoc_resp(struct ieee80211_device *ieee, struct ieee80211_assoc_response | ||
1340 | *frame, struct ieee80211_rx_stats *stats) | ||
1341 | { | ||
1342 | struct ieee80211_network network_resp = { | ||
1343 | .ibss_dfs = NULL, | ||
1344 | }; | ||
1345 | struct ieee80211_network *network = &network_resp; | ||
1346 | struct net_device *dev = ieee->dev; | ||
1347 | |||
1348 | network->flags = 0; | ||
1349 | network->qos_data.active = 0; | ||
1350 | network->qos_data.supported = 0; | ||
1351 | network->qos_data.param_count = 0; | ||
1352 | network->qos_data.old_param_count = 0; | ||
1353 | |||
1354 | //network->atim_window = le16_to_cpu(frame->aid) & (0x3FFF); | ||
1355 | network->atim_window = le16_to_cpu(frame->aid); | ||
1356 | network->listen_interval = le16_to_cpu(frame->status); | ||
1357 | memcpy(network->bssid, frame->header.addr3, ETH_ALEN); | ||
1358 | network->capability = le16_to_cpu(frame->capability); | ||
1359 | network->last_scanned = jiffies; | ||
1360 | network->rates_len = network->rates_ex_len = 0; | ||
1361 | network->last_associate = 0; | ||
1362 | network->ssid_len = 0; | ||
1363 | network->erp_value = | ||
1364 | (network->capability & WLAN_CAPABILITY_IBSS) ? 0x3 : 0x0; | ||
1365 | |||
1366 | if (stats->freq == IEEE80211_52GHZ_BAND) { | ||
1367 | /* for A band (No DS info) */ | ||
1368 | network->channel = stats->received_channel; | ||
1369 | } else | ||
1370 | network->flags |= NETWORK_HAS_CCK; | ||
1371 | |||
1372 | network->wpa_ie_len = 0; | ||
1373 | network->rsn_ie_len = 0; | ||
1374 | |||
1375 | if (ieee80211_parse_info_param | ||
1376 | (frame->info_element, stats->len - sizeof(*frame), network)) | ||
1377 | return 1; | ||
1378 | |||
1379 | network->mode = 0; | ||
1380 | if (stats->freq == IEEE80211_52GHZ_BAND) | ||
1381 | network->mode = IEEE_A; | ||
1382 | else { | ||
1383 | if (network->flags & NETWORK_HAS_OFDM) | ||
1384 | network->mode |= IEEE_G; | ||
1385 | if (network->flags & NETWORK_HAS_CCK) | ||
1386 | network->mode |= IEEE_B; | ||
1387 | } | ||
1388 | |||
1389 | memcpy(&network->stats, stats, sizeof(network->stats)); | ||
1390 | |||
1391 | if (ieee->handle_assoc_response != NULL) | ||
1392 | ieee->handle_assoc_response(dev, frame, network); | ||
1393 | |||
1394 | return 0; | ||
1395 | } | ||
1396 | |||
1397 | /***************************************************/ | ||
1398 | |||
1399 | static int ieee80211_network_init(struct ieee80211_device *ieee, struct ieee80211_probe_response | ||
1400 | *beacon, | ||
1401 | struct ieee80211_network *network, | ||
1402 | struct ieee80211_rx_stats *stats) | ||
1403 | { | ||
1404 | DECLARE_SSID_BUF(ssid); | ||
1405 | |||
1406 | network->qos_data.active = 0; | ||
1407 | network->qos_data.supported = 0; | ||
1408 | network->qos_data.param_count = 0; | ||
1409 | network->qos_data.old_param_count = 0; | ||
1410 | |||
1411 | /* Pull out fixed field data */ | ||
1412 | memcpy(network->bssid, beacon->header.addr3, ETH_ALEN); | ||
1413 | network->capability = le16_to_cpu(beacon->capability); | ||
1414 | network->last_scanned = jiffies; | ||
1415 | network->time_stamp[0] = le32_to_cpu(beacon->time_stamp[0]); | ||
1416 | network->time_stamp[1] = le32_to_cpu(beacon->time_stamp[1]); | ||
1417 | network->beacon_interval = le16_to_cpu(beacon->beacon_interval); | ||
1418 | /* Where to pull this? beacon->listen_interval; */ | ||
1419 | network->listen_interval = 0x0A; | ||
1420 | network->rates_len = network->rates_ex_len = 0; | ||
1421 | network->last_associate = 0; | ||
1422 | network->ssid_len = 0; | ||
1423 | network->flags = 0; | ||
1424 | network->atim_window = 0; | ||
1425 | network->erp_value = (network->capability & WLAN_CAPABILITY_IBSS) ? | ||
1426 | 0x3 : 0x0; | ||
1427 | |||
1428 | if (stats->freq == IEEE80211_52GHZ_BAND) { | ||
1429 | /* for A band (No DS info) */ | ||
1430 | network->channel = stats->received_channel; | ||
1431 | } else | ||
1432 | network->flags |= NETWORK_HAS_CCK; | ||
1433 | |||
1434 | network->wpa_ie_len = 0; | ||
1435 | network->rsn_ie_len = 0; | ||
1436 | |||
1437 | if (ieee80211_parse_info_param | ||
1438 | (beacon->info_element, stats->len - sizeof(*beacon), network)) | ||
1439 | return 1; | ||
1440 | |||
1441 | network->mode = 0; | ||
1442 | if (stats->freq == IEEE80211_52GHZ_BAND) | ||
1443 | network->mode = IEEE_A; | ||
1444 | else { | ||
1445 | if (network->flags & NETWORK_HAS_OFDM) | ||
1446 | network->mode |= IEEE_G; | ||
1447 | if (network->flags & NETWORK_HAS_CCK) | ||
1448 | network->mode |= IEEE_B; | ||
1449 | } | ||
1450 | |||
1451 | if (network->mode == 0) { | ||
1452 | IEEE80211_DEBUG_SCAN("Filtered out '%s (%pM)' " | ||
1453 | "network.\n", | ||
1454 | print_ssid(ssid, network->ssid, | ||
1455 | network->ssid_len), | ||
1456 | network->bssid); | ||
1457 | return 1; | ||
1458 | } | ||
1459 | |||
1460 | memcpy(&network->stats, stats, sizeof(network->stats)); | ||
1461 | |||
1462 | return 0; | ||
1463 | } | ||
1464 | |||
1465 | static inline int is_same_network(struct ieee80211_network *src, | ||
1466 | struct ieee80211_network *dst) | ||
1467 | { | ||
1468 | /* A network is only a duplicate if the channel, BSSID, and ESSID | ||
1469 | * all match. We treat all <hidden> with the same BSSID and channel | ||
1470 | * as one network */ | ||
1471 | return ((src->ssid_len == dst->ssid_len) && | ||
1472 | (src->channel == dst->channel) && | ||
1473 | !compare_ether_addr(src->bssid, dst->bssid) && | ||
1474 | !memcmp(src->ssid, dst->ssid, src->ssid_len)); | ||
1475 | } | ||
1476 | |||
1477 | static void update_network(struct ieee80211_network *dst, | ||
1478 | struct ieee80211_network *src) | ||
1479 | { | ||
1480 | int qos_active; | ||
1481 | u8 old_param; | ||
1482 | |||
1483 | ieee80211_network_reset(dst); | ||
1484 | dst->ibss_dfs = src->ibss_dfs; | ||
1485 | |||
1486 | /* We only update the statistics if they were created by receiving | ||
1487 | * the network information on the actual channel the network is on. | ||
1488 | * | ||
1489 | * This keeps beacons received on neighbor channels from bringing | ||
1490 | * down the signal level of an AP. */ | ||
1491 | if (dst->channel == src->stats.received_channel) | ||
1492 | memcpy(&dst->stats, &src->stats, | ||
1493 | sizeof(struct ieee80211_rx_stats)); | ||
1494 | else | ||
1495 | IEEE80211_DEBUG_SCAN("Network %pM info received " | ||
1496 | "off channel (%d vs. %d)\n", src->bssid, | ||
1497 | dst->channel, src->stats.received_channel); | ||
1498 | |||
1499 | dst->capability = src->capability; | ||
1500 | memcpy(dst->rates, src->rates, src->rates_len); | ||
1501 | dst->rates_len = src->rates_len; | ||
1502 | memcpy(dst->rates_ex, src->rates_ex, src->rates_ex_len); | ||
1503 | dst->rates_ex_len = src->rates_ex_len; | ||
1504 | |||
1505 | dst->mode = src->mode; | ||
1506 | dst->flags = src->flags; | ||
1507 | dst->time_stamp[0] = src->time_stamp[0]; | ||
1508 | dst->time_stamp[1] = src->time_stamp[1]; | ||
1509 | |||
1510 | dst->beacon_interval = src->beacon_interval; | ||
1511 | dst->listen_interval = src->listen_interval; | ||
1512 | dst->atim_window = src->atim_window; | ||
1513 | dst->erp_value = src->erp_value; | ||
1514 | dst->tim = src->tim; | ||
1515 | |||
1516 | memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len); | ||
1517 | dst->wpa_ie_len = src->wpa_ie_len; | ||
1518 | memcpy(dst->rsn_ie, src->rsn_ie, src->rsn_ie_len); | ||
1519 | dst->rsn_ie_len = src->rsn_ie_len; | ||
1520 | |||
1521 | dst->last_scanned = jiffies; | ||
1522 | qos_active = src->qos_data.active; | ||
1523 | old_param = dst->qos_data.old_param_count; | ||
1524 | if (dst->flags & NETWORK_HAS_QOS_MASK) | ||
1525 | memcpy(&dst->qos_data, &src->qos_data, | ||
1526 | sizeof(struct ieee80211_qos_data)); | ||
1527 | else { | ||
1528 | dst->qos_data.supported = src->qos_data.supported; | ||
1529 | dst->qos_data.param_count = src->qos_data.param_count; | ||
1530 | } | ||
1531 | |||
1532 | if (dst->qos_data.supported == 1) { | ||
1533 | if (dst->ssid_len) | ||
1534 | IEEE80211_DEBUG_QOS | ||
1535 | ("QoS the network %s is QoS supported\n", | ||
1536 | dst->ssid); | ||
1537 | else | ||
1538 | IEEE80211_DEBUG_QOS | ||
1539 | ("QoS the network is QoS supported\n"); | ||
1540 | } | ||
1541 | dst->qos_data.active = qos_active; | ||
1542 | dst->qos_data.old_param_count = old_param; | ||
1543 | |||
1544 | /* dst->last_associate is not overwritten */ | ||
1545 | } | ||
1546 | |||
1547 | static inline int is_beacon(__le16 fc) | ||
1548 | { | ||
1549 | return (WLAN_FC_GET_STYPE(le16_to_cpu(fc)) == IEEE80211_STYPE_BEACON); | ||
1550 | } | ||
1551 | |||
1552 | static void ieee80211_process_probe_response(struct ieee80211_device | ||
1553 | *ieee, struct | ||
1554 | ieee80211_probe_response | ||
1555 | *beacon, struct ieee80211_rx_stats | ||
1556 | *stats) | ||
1557 | { | ||
1558 | struct net_device *dev = ieee->dev; | ||
1559 | struct ieee80211_network network = { | ||
1560 | .ibss_dfs = NULL, | ||
1561 | }; | ||
1562 | struct ieee80211_network *target; | ||
1563 | struct ieee80211_network *oldest = NULL; | ||
1564 | #ifdef CONFIG_IEEE80211_DEBUG | ||
1565 | struct ieee80211_info_element *info_element = beacon->info_element; | ||
1566 | #endif | ||
1567 | unsigned long flags; | ||
1568 | DECLARE_SSID_BUF(ssid); | ||
1569 | |||
1570 | IEEE80211_DEBUG_SCAN("'%s' (%pM" | ||
1571 | "): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n", | ||
1572 | print_ssid(ssid, info_element->data, info_element->len), | ||
1573 | beacon->header.addr3, | ||
1574 | (beacon->capability & cpu_to_le16(1 << 0xf)) ? '1' : '0', | ||
1575 | (beacon->capability & cpu_to_le16(1 << 0xe)) ? '1' : '0', | ||
1576 | (beacon->capability & cpu_to_le16(1 << 0xd)) ? '1' : '0', | ||
1577 | (beacon->capability & cpu_to_le16(1 << 0xc)) ? '1' : '0', | ||
1578 | (beacon->capability & cpu_to_le16(1 << 0xb)) ? '1' : '0', | ||
1579 | (beacon->capability & cpu_to_le16(1 << 0xa)) ? '1' : '0', | ||
1580 | (beacon->capability & cpu_to_le16(1 << 0x9)) ? '1' : '0', | ||
1581 | (beacon->capability & cpu_to_le16(1 << 0x8)) ? '1' : '0', | ||
1582 | (beacon->capability & cpu_to_le16(1 << 0x7)) ? '1' : '0', | ||
1583 | (beacon->capability & cpu_to_le16(1 << 0x6)) ? '1' : '0', | ||
1584 | (beacon->capability & cpu_to_le16(1 << 0x5)) ? '1' : '0', | ||
1585 | (beacon->capability & cpu_to_le16(1 << 0x4)) ? '1' : '0', | ||
1586 | (beacon->capability & cpu_to_le16(1 << 0x3)) ? '1' : '0', | ||
1587 | (beacon->capability & cpu_to_le16(1 << 0x2)) ? '1' : '0', | ||
1588 | (beacon->capability & cpu_to_le16(1 << 0x1)) ? '1' : '0', | ||
1589 | (beacon->capability & cpu_to_le16(1 << 0x0)) ? '1' : '0'); | ||
1590 | |||
1591 | if (ieee80211_network_init(ieee, beacon, &network, stats)) { | ||
1592 | IEEE80211_DEBUG_SCAN("Dropped '%s' (%pM) via %s.\n", | ||
1593 | print_ssid(ssid, info_element->data, | ||
1594 | info_element->len), | ||
1595 | beacon->header.addr3, | ||
1596 | is_beacon(beacon->header.frame_ctl) ? | ||
1597 | "BEACON" : "PROBE RESPONSE"); | ||
1598 | return; | ||
1599 | } | ||
1600 | |||
1601 | /* The network parsed correctly -- so now we scan our known networks | ||
1602 | * to see if we can find it in our list. | ||
1603 | * | ||
1604 | * NOTE: This search is definitely not optimized. Once its doing | ||
1605 | * the "right thing" we'll optimize it for efficiency if | ||
1606 | * necessary */ | ||
1607 | |||
1608 | /* Search for this entry in the list and update it if it is | ||
1609 | * already there. */ | ||
1610 | |||
1611 | spin_lock_irqsave(&ieee->lock, flags); | ||
1612 | |||
1613 | list_for_each_entry(target, &ieee->network_list, list) { | ||
1614 | if (is_same_network(target, &network)) | ||
1615 | break; | ||
1616 | |||
1617 | if ((oldest == NULL) || | ||
1618 | (target->last_scanned < oldest->last_scanned)) | ||
1619 | oldest = target; | ||
1620 | } | ||
1621 | |||
1622 | /* If we didn't find a match, then get a new network slot to initialize | ||
1623 | * with this beacon's information */ | ||
1624 | if (&target->list == &ieee->network_list) { | ||
1625 | if (list_empty(&ieee->network_free_list)) { | ||
1626 | /* If there are no more slots, expire the oldest */ | ||
1627 | list_del(&oldest->list); | ||
1628 | target = oldest; | ||
1629 | IEEE80211_DEBUG_SCAN("Expired '%s' (%pM) from " | ||
1630 | "network list.\n", | ||
1631 | print_ssid(ssid, target->ssid, | ||
1632 | target->ssid_len), | ||
1633 | target->bssid); | ||
1634 | ieee80211_network_reset(target); | ||
1635 | } else { | ||
1636 | /* Otherwise just pull from the free list */ | ||
1637 | target = list_entry(ieee->network_free_list.next, | ||
1638 | struct ieee80211_network, list); | ||
1639 | list_del(ieee->network_free_list.next); | ||
1640 | } | ||
1641 | |||
1642 | #ifdef CONFIG_IEEE80211_DEBUG | ||
1643 | IEEE80211_DEBUG_SCAN("Adding '%s' (%pM) via %s.\n", | ||
1644 | print_ssid(ssid, network.ssid, | ||
1645 | network.ssid_len), | ||
1646 | network.bssid, | ||
1647 | is_beacon(beacon->header.frame_ctl) ? | ||
1648 | "BEACON" : "PROBE RESPONSE"); | ||
1649 | #endif | ||
1650 | memcpy(target, &network, sizeof(*target)); | ||
1651 | network.ibss_dfs = NULL; | ||
1652 | list_add_tail(&target->list, &ieee->network_list); | ||
1653 | } else { | ||
1654 | IEEE80211_DEBUG_SCAN("Updating '%s' (%pM) via %s.\n", | ||
1655 | print_ssid(ssid, target->ssid, | ||
1656 | target->ssid_len), | ||
1657 | target->bssid, | ||
1658 | is_beacon(beacon->header.frame_ctl) ? | ||
1659 | "BEACON" : "PROBE RESPONSE"); | ||
1660 | update_network(target, &network); | ||
1661 | network.ibss_dfs = NULL; | ||
1662 | } | ||
1663 | |||
1664 | spin_unlock_irqrestore(&ieee->lock, flags); | ||
1665 | |||
1666 | if (is_beacon(beacon->header.frame_ctl)) { | ||
1667 | if (ieee->handle_beacon != NULL) | ||
1668 | ieee->handle_beacon(dev, beacon, target); | ||
1669 | } else { | ||
1670 | if (ieee->handle_probe_response != NULL) | ||
1671 | ieee->handle_probe_response(dev, beacon, target); | ||
1672 | } | ||
1673 | } | ||
1674 | |||
1675 | void ieee80211_rx_mgt(struct ieee80211_device *ieee, | ||
1676 | struct ieee80211_hdr_4addr *header, | ||
1677 | struct ieee80211_rx_stats *stats) | ||
1678 | { | ||
1679 | switch (WLAN_FC_GET_STYPE(le16_to_cpu(header->frame_ctl))) { | ||
1680 | case IEEE80211_STYPE_ASSOC_RESP: | ||
1681 | IEEE80211_DEBUG_MGMT("received ASSOCIATION RESPONSE (%d)\n", | ||
1682 | WLAN_FC_GET_STYPE(le16_to_cpu | ||
1683 | (header->frame_ctl))); | ||
1684 | ieee80211_handle_assoc_resp(ieee, | ||
1685 | (struct ieee80211_assoc_response *) | ||
1686 | header, stats); | ||
1687 | break; | ||
1688 | |||
1689 | case IEEE80211_STYPE_REASSOC_RESP: | ||
1690 | IEEE80211_DEBUG_MGMT("received REASSOCIATION RESPONSE (%d)\n", | ||
1691 | WLAN_FC_GET_STYPE(le16_to_cpu | ||
1692 | (header->frame_ctl))); | ||
1693 | break; | ||
1694 | |||
1695 | case IEEE80211_STYPE_PROBE_REQ: | ||
1696 | IEEE80211_DEBUG_MGMT("received auth (%d)\n", | ||
1697 | WLAN_FC_GET_STYPE(le16_to_cpu | ||
1698 | (header->frame_ctl))); | ||
1699 | |||
1700 | if (ieee->handle_probe_request != NULL) | ||
1701 | ieee->handle_probe_request(ieee->dev, | ||
1702 | (struct | ||
1703 | ieee80211_probe_request *) | ||
1704 | header, stats); | ||
1705 | break; | ||
1706 | |||
1707 | case IEEE80211_STYPE_PROBE_RESP: | ||
1708 | IEEE80211_DEBUG_MGMT("received PROBE RESPONSE (%d)\n", | ||
1709 | WLAN_FC_GET_STYPE(le16_to_cpu | ||
1710 | (header->frame_ctl))); | ||
1711 | IEEE80211_DEBUG_SCAN("Probe response\n"); | ||
1712 | ieee80211_process_probe_response(ieee, | ||
1713 | (struct | ||
1714 | ieee80211_probe_response *) | ||
1715 | header, stats); | ||
1716 | break; | ||
1717 | |||
1718 | case IEEE80211_STYPE_BEACON: | ||
1719 | IEEE80211_DEBUG_MGMT("received BEACON (%d)\n", | ||
1720 | WLAN_FC_GET_STYPE(le16_to_cpu | ||
1721 | (header->frame_ctl))); | ||
1722 | IEEE80211_DEBUG_SCAN("Beacon\n"); | ||
1723 | ieee80211_process_probe_response(ieee, | ||
1724 | (struct | ||
1725 | ieee80211_probe_response *) | ||
1726 | header, stats); | ||
1727 | break; | ||
1728 | case IEEE80211_STYPE_AUTH: | ||
1729 | |||
1730 | IEEE80211_DEBUG_MGMT("received auth (%d)\n", | ||
1731 | WLAN_FC_GET_STYPE(le16_to_cpu | ||
1732 | (header->frame_ctl))); | ||
1733 | |||
1734 | if (ieee->handle_auth != NULL) | ||
1735 | ieee->handle_auth(ieee->dev, | ||
1736 | (struct ieee80211_auth *)header); | ||
1737 | break; | ||
1738 | |||
1739 | case IEEE80211_STYPE_DISASSOC: | ||
1740 | if (ieee->handle_disassoc != NULL) | ||
1741 | ieee->handle_disassoc(ieee->dev, | ||
1742 | (struct ieee80211_disassoc *) | ||
1743 | header); | ||
1744 | break; | ||
1745 | |||
1746 | case IEEE80211_STYPE_ACTION: | ||
1747 | IEEE80211_DEBUG_MGMT("ACTION\n"); | ||
1748 | if (ieee->handle_action) | ||
1749 | ieee->handle_action(ieee->dev, | ||
1750 | (struct ieee80211_action *) | ||
1751 | header, stats); | ||
1752 | break; | ||
1753 | |||
1754 | case IEEE80211_STYPE_REASSOC_REQ: | ||
1755 | IEEE80211_DEBUG_MGMT("received reassoc (%d)\n", | ||
1756 | WLAN_FC_GET_STYPE(le16_to_cpu | ||
1757 | (header->frame_ctl))); | ||
1758 | |||
1759 | IEEE80211_DEBUG_MGMT("%s: IEEE80211_REASSOC_REQ received\n", | ||
1760 | ieee->dev->name); | ||
1761 | if (ieee->handle_reassoc_request != NULL) | ||
1762 | ieee->handle_reassoc_request(ieee->dev, | ||
1763 | (struct ieee80211_reassoc_request *) | ||
1764 | header); | ||
1765 | break; | ||
1766 | |||
1767 | case IEEE80211_STYPE_ASSOC_REQ: | ||
1768 | IEEE80211_DEBUG_MGMT("received assoc (%d)\n", | ||
1769 | WLAN_FC_GET_STYPE(le16_to_cpu | ||
1770 | (header->frame_ctl))); | ||
1771 | |||
1772 | IEEE80211_DEBUG_MGMT("%s: IEEE80211_ASSOC_REQ received\n", | ||
1773 | ieee->dev->name); | ||
1774 | if (ieee->handle_assoc_request != NULL) | ||
1775 | ieee->handle_assoc_request(ieee->dev); | ||
1776 | break; | ||
1777 | |||
1778 | case IEEE80211_STYPE_DEAUTH: | ||
1779 | IEEE80211_DEBUG_MGMT("DEAUTH\n"); | ||
1780 | if (ieee->handle_deauth != NULL) | ||
1781 | ieee->handle_deauth(ieee->dev, | ||
1782 | (struct ieee80211_deauth *) | ||
1783 | header); | ||
1784 | break; | ||
1785 | default: | ||
1786 | IEEE80211_DEBUG_MGMT("received UNKNOWN (%d)\n", | ||
1787 | WLAN_FC_GET_STYPE(le16_to_cpu | ||
1788 | (header->frame_ctl))); | ||
1789 | IEEE80211_DEBUG_MGMT("%s: Unknown management packet: %d\n", | ||
1790 | ieee->dev->name, | ||
1791 | WLAN_FC_GET_STYPE(le16_to_cpu | ||
1792 | (header->frame_ctl))); | ||
1793 | break; | ||
1794 | } | ||
1795 | } | ||
1796 | |||
1797 | EXPORT_SYMBOL_GPL(ieee80211_rx_any); | ||
1798 | EXPORT_SYMBOL(ieee80211_rx_mgt); | ||
1799 | EXPORT_SYMBOL(ieee80211_rx); | ||
diff --git a/drivers/net/wireless/ipw2x00/libipw_tx.c b/drivers/net/wireless/ipw2x00/libipw_tx.c new file mode 100644 index 000000000000..f78f57e8844a --- /dev/null +++ b/drivers/net/wireless/ipw2x00/libipw_tx.c | |||
@@ -0,0 +1,546 @@ | |||
1 | /****************************************************************************** | ||
2 | |||
3 | Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved. | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify it | ||
6 | under the terms of version 2 of the GNU General Public License as | ||
7 | published by the Free Software Foundation. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License along with | ||
15 | this program; if not, write to the Free Software Foundation, Inc., 59 | ||
16 | Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
17 | |||
18 | The full GNU General Public License is included in this distribution in the | ||
19 | file called LICENSE. | ||
20 | |||
21 | Contact Information: | ||
22 | James P. Ketrenos <ipw2100-admin@linux.intel.com> | ||
23 | Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
24 | |||
25 | ******************************************************************************/ | ||
26 | #include <linux/compiler.h> | ||
27 | #include <linux/errno.h> | ||
28 | #include <linux/if_arp.h> | ||
29 | #include <linux/in6.h> | ||
30 | #include <linux/in.h> | ||
31 | #include <linux/ip.h> | ||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/module.h> | ||
34 | #include <linux/netdevice.h> | ||
35 | #include <linux/proc_fs.h> | ||
36 | #include <linux/skbuff.h> | ||
37 | #include <linux/slab.h> | ||
38 | #include <linux/tcp.h> | ||
39 | #include <linux/types.h> | ||
40 | #include <linux/wireless.h> | ||
41 | #include <linux/etherdevice.h> | ||
42 | #include <asm/uaccess.h> | ||
43 | |||
44 | #include <net/ieee80211.h> | ||
45 | |||
46 | /* | ||
47 | |||
48 | 802.11 Data Frame | ||
49 | |||
50 | ,-------------------------------------------------------------------. | ||
51 | Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 | | ||
52 | |------|------|---------|---------|---------|------|---------|------| | ||
53 | Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | Frame | fcs | | ||
54 | | | tion | (BSSID) | | | ence | data | | | ||
55 | `--------------------------------------------------| |------' | ||
56 | Total: 28 non-data bytes `----.----' | ||
57 | | | ||
58 | .- 'Frame data' expands, if WEP enabled, to <----------' | ||
59 | | | ||
60 | V | ||
61 | ,-----------------------. | ||
62 | Bytes | 4 | 0-2296 | 4 | | ||
63 | |-----|-----------|-----| | ||
64 | Desc. | IV | Encrypted | ICV | | ||
65 | | | Packet | | | ||
66 | `-----| |-----' | ||
67 | `-----.-----' | ||
68 | | | ||
69 | .- 'Encrypted Packet' expands to | ||
70 | | | ||
71 | V | ||
72 | ,---------------------------------------------------. | ||
73 | Bytes | 1 | 1 | 1 | 3 | 2 | 0-2304 | | ||
74 | |------|------|---------|----------|------|---------| | ||
75 | Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP | | ||
76 | | DSAP | SSAP | | | | Packet | | ||
77 | | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8| | | | ||
78 | `---------------------------------------------------- | ||
79 | Total: 8 non-data bytes | ||
80 | |||
81 | 802.3 Ethernet Data Frame | ||
82 | |||
83 | ,-----------------------------------------. | ||
84 | Bytes | 6 | 6 | 2 | Variable | 4 | | ||
85 | |-------|-------|------|-----------|------| | ||
86 | Desc. | Dest. | Source| Type | IP Packet | fcs | | ||
87 | | MAC | MAC | | | | | ||
88 | `-----------------------------------------' | ||
89 | Total: 18 non-data bytes | ||
90 | |||
91 | In the event that fragmentation is required, the incoming payload is split into | ||
92 | N parts of size ieee->fts. The first fragment contains the SNAP header and the | ||
93 | remaining packets are just data. | ||
94 | |||
95 | If encryption is enabled, each fragment payload size is reduced by enough space | ||
96 | to add the prefix and postfix (IV and ICV totalling 8 bytes in the case of WEP) | ||
97 | So if you have 1500 bytes of payload with ieee->fts set to 500 without | ||
98 | encryption it will take 3 frames. With WEP it will take 4 frames as the | ||
99 | payload of each frame is reduced to 492 bytes. | ||
100 | |||
101 | * SKB visualization | ||
102 | * | ||
103 | * ,- skb->data | ||
104 | * | | ||
105 | * | ETHERNET HEADER ,-<-- PAYLOAD | ||
106 | * | | 14 bytes from skb->data | ||
107 | * | 2 bytes for Type --> ,T. | (sizeof ethhdr) | ||
108 | * | | | | | ||
109 | * |,-Dest.--. ,--Src.---. | | | | ||
110 | * | 6 bytes| | 6 bytes | | | | | ||
111 | * v | | | | | | | ||
112 | * 0 | v 1 | v | v 2 | ||
113 | * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 | ||
114 | * ^ | ^ | ^ | | ||
115 | * | | | | | | | ||
116 | * | | | | `T' <---- 2 bytes for Type | ||
117 | * | | | | | ||
118 | * | | '---SNAP--' <-------- 6 bytes for SNAP | ||
119 | * | | | ||
120 | * `-IV--' <-------------------- 4 bytes for IV (WEP) | ||
121 | * | ||
122 | * SNAP HEADER | ||
123 | * | ||
124 | */ | ||
125 | |||
126 | static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 }; | ||
127 | static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 }; | ||
128 | |||
129 | static int ieee80211_copy_snap(u8 * data, __be16 h_proto) | ||
130 | { | ||
131 | struct ieee80211_snap_hdr *snap; | ||
132 | u8 *oui; | ||
133 | |||
134 | snap = (struct ieee80211_snap_hdr *)data; | ||
135 | snap->dsap = 0xaa; | ||
136 | snap->ssap = 0xaa; | ||
137 | snap->ctrl = 0x03; | ||
138 | |||
139 | if (h_proto == htons(ETH_P_AARP) || h_proto == htons(ETH_P_IPX)) | ||
140 | oui = P802_1H_OUI; | ||
141 | else | ||
142 | oui = RFC1042_OUI; | ||
143 | snap->oui[0] = oui[0]; | ||
144 | snap->oui[1] = oui[1]; | ||
145 | snap->oui[2] = oui[2]; | ||
146 | |||
147 | memcpy(data + SNAP_SIZE, &h_proto, sizeof(u16)); | ||
148 | |||
149 | return SNAP_SIZE + sizeof(u16); | ||
150 | } | ||
151 | |||
152 | static int ieee80211_encrypt_fragment(struct ieee80211_device *ieee, | ||
153 | struct sk_buff *frag, int hdr_len) | ||
154 | { | ||
155 | struct lib80211_crypt_data *crypt = | ||
156 | ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx]; | ||
157 | int res; | ||
158 | |||
159 | if (crypt == NULL) | ||
160 | return -1; | ||
161 | |||
162 | /* To encrypt, frame format is: | ||
163 | * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */ | ||
164 | atomic_inc(&crypt->refcnt); | ||
165 | res = 0; | ||
166 | if (crypt->ops && crypt->ops->encrypt_mpdu) | ||
167 | res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv); | ||
168 | |||
169 | atomic_dec(&crypt->refcnt); | ||
170 | if (res < 0) { | ||
171 | printk(KERN_INFO "%s: Encryption failed: len=%d.\n", | ||
172 | ieee->dev->name, frag->len); | ||
173 | ieee->ieee_stats.tx_discards++; | ||
174 | return -1; | ||
175 | } | ||
176 | |||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | void ieee80211_txb_free(struct ieee80211_txb *txb) | ||
181 | { | ||
182 | int i; | ||
183 | if (unlikely(!txb)) | ||
184 | return; | ||
185 | for (i = 0; i < txb->nr_frags; i++) | ||
186 | if (txb->fragments[i]) | ||
187 | dev_kfree_skb_any(txb->fragments[i]); | ||
188 | kfree(txb); | ||
189 | } | ||
190 | |||
191 | static struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size, | ||
192 | int headroom, gfp_t gfp_mask) | ||
193 | { | ||
194 | struct ieee80211_txb *txb; | ||
195 | int i; | ||
196 | txb = kmalloc(sizeof(struct ieee80211_txb) + (sizeof(u8 *) * nr_frags), | ||
197 | gfp_mask); | ||
198 | if (!txb) | ||
199 | return NULL; | ||
200 | |||
201 | memset(txb, 0, sizeof(struct ieee80211_txb)); | ||
202 | txb->nr_frags = nr_frags; | ||
203 | txb->frag_size = txb_size; | ||
204 | |||
205 | for (i = 0; i < nr_frags; i++) { | ||
206 | txb->fragments[i] = __dev_alloc_skb(txb_size + headroom, | ||
207 | gfp_mask); | ||
208 | if (unlikely(!txb->fragments[i])) { | ||
209 | i--; | ||
210 | break; | ||
211 | } | ||
212 | skb_reserve(txb->fragments[i], headroom); | ||
213 | } | ||
214 | if (unlikely(i != nr_frags)) { | ||
215 | while (i >= 0) | ||
216 | dev_kfree_skb_any(txb->fragments[i--]); | ||
217 | kfree(txb); | ||
218 | return NULL; | ||
219 | } | ||
220 | return txb; | ||
221 | } | ||
222 | |||
223 | static int ieee80211_classify(struct sk_buff *skb) | ||
224 | { | ||
225 | struct ethhdr *eth; | ||
226 | struct iphdr *ip; | ||
227 | |||
228 | eth = (struct ethhdr *)skb->data; | ||
229 | if (eth->h_proto != htons(ETH_P_IP)) | ||
230 | return 0; | ||
231 | |||
232 | ip = ip_hdr(skb); | ||
233 | switch (ip->tos & 0xfc) { | ||
234 | case 0x20: | ||
235 | return 2; | ||
236 | case 0x40: | ||
237 | return 1; | ||
238 | case 0x60: | ||
239 | return 3; | ||
240 | case 0x80: | ||
241 | return 4; | ||
242 | case 0xa0: | ||
243 | return 5; | ||
244 | case 0xc0: | ||
245 | return 6; | ||
246 | case 0xe0: | ||
247 | return 7; | ||
248 | default: | ||
249 | return 0; | ||
250 | } | ||
251 | } | ||
252 | |||
253 | /* Incoming skb is converted to a txb which consists of | ||
254 | * a block of 802.11 fragment packets (stored as skbs) */ | ||
255 | int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) | ||
256 | { | ||
257 | struct ieee80211_device *ieee = netdev_priv(dev); | ||
258 | struct ieee80211_txb *txb = NULL; | ||
259 | struct ieee80211_hdr_3addrqos *frag_hdr; | ||
260 | int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size, | ||
261 | rts_required; | ||
262 | unsigned long flags; | ||
263 | struct net_device_stats *stats = &ieee->stats; | ||
264 | int encrypt, host_encrypt, host_encrypt_msdu, host_build_iv; | ||
265 | __be16 ether_type; | ||
266 | int bytes, fc, hdr_len; | ||
267 | struct sk_buff *skb_frag; | ||
268 | struct ieee80211_hdr_3addrqos header = {/* Ensure zero initialized */ | ||
269 | .duration_id = 0, | ||
270 | .seq_ctl = 0, | ||
271 | .qos_ctl = 0 | ||
272 | }; | ||
273 | u8 dest[ETH_ALEN], src[ETH_ALEN]; | ||
274 | struct lib80211_crypt_data *crypt; | ||
275 | int priority = skb->priority; | ||
276 | int snapped = 0; | ||
277 | |||
278 | if (ieee->is_queue_full && (*ieee->is_queue_full) (dev, priority)) | ||
279 | return NETDEV_TX_BUSY; | ||
280 | |||
281 | spin_lock_irqsave(&ieee->lock, flags); | ||
282 | |||
283 | /* If there is no driver handler to take the TXB, dont' bother | ||
284 | * creating it... */ | ||
285 | if (!ieee->hard_start_xmit) { | ||
286 | printk(KERN_WARNING "%s: No xmit handler.\n", ieee->dev->name); | ||
287 | goto success; | ||
288 | } | ||
289 | |||
290 | if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) { | ||
291 | printk(KERN_WARNING "%s: skb too small (%d).\n", | ||
292 | ieee->dev->name, skb->len); | ||
293 | goto success; | ||
294 | } | ||
295 | |||
296 | ether_type = ((struct ethhdr *)skb->data)->h_proto; | ||
297 | |||
298 | crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx]; | ||
299 | |||
300 | encrypt = !(ether_type == htons(ETH_P_PAE) && ieee->ieee802_1x) && | ||
301 | ieee->sec.encrypt; | ||
302 | |||
303 | host_encrypt = ieee->host_encrypt && encrypt && crypt; | ||
304 | host_encrypt_msdu = ieee->host_encrypt_msdu && encrypt && crypt; | ||
305 | host_build_iv = ieee->host_build_iv && encrypt && crypt; | ||
306 | |||
307 | if (!encrypt && ieee->ieee802_1x && | ||
308 | ieee->drop_unencrypted && ether_type != htons(ETH_P_PAE)) { | ||
309 | stats->tx_dropped++; | ||
310 | goto success; | ||
311 | } | ||
312 | |||
313 | /* Save source and destination addresses */ | ||
314 | skb_copy_from_linear_data(skb, dest, ETH_ALEN); | ||
315 | skb_copy_from_linear_data_offset(skb, ETH_ALEN, src, ETH_ALEN); | ||
316 | |||
317 | if (host_encrypt || host_build_iv) | ||
318 | fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA | | ||
319 | IEEE80211_FCTL_PROTECTED; | ||
320 | else | ||
321 | fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA; | ||
322 | |||
323 | if (ieee->iw_mode == IW_MODE_INFRA) { | ||
324 | fc |= IEEE80211_FCTL_TODS; | ||
325 | /* To DS: Addr1 = BSSID, Addr2 = SA, Addr3 = DA */ | ||
326 | memcpy(header.addr1, ieee->bssid, ETH_ALEN); | ||
327 | memcpy(header.addr2, src, ETH_ALEN); | ||
328 | memcpy(header.addr3, dest, ETH_ALEN); | ||
329 | } else if (ieee->iw_mode == IW_MODE_ADHOC) { | ||
330 | /* not From/To DS: Addr1 = DA, Addr2 = SA, Addr3 = BSSID */ | ||
331 | memcpy(header.addr1, dest, ETH_ALEN); | ||
332 | memcpy(header.addr2, src, ETH_ALEN); | ||
333 | memcpy(header.addr3, ieee->bssid, ETH_ALEN); | ||
334 | } | ||
335 | hdr_len = IEEE80211_3ADDR_LEN; | ||
336 | |||
337 | if (ieee->is_qos_active && ieee->is_qos_active(dev, skb)) { | ||
338 | fc |= IEEE80211_STYPE_QOS_DATA; | ||
339 | hdr_len += 2; | ||
340 | |||
341 | skb->priority = ieee80211_classify(skb); | ||
342 | header.qos_ctl |= cpu_to_le16(skb->priority & IEEE80211_QCTL_TID); | ||
343 | } | ||
344 | header.frame_ctl = cpu_to_le16(fc); | ||
345 | |||
346 | /* Advance the SKB to the start of the payload */ | ||
347 | skb_pull(skb, sizeof(struct ethhdr)); | ||
348 | |||
349 | /* Determine total amount of storage required for TXB packets */ | ||
350 | bytes = skb->len + SNAP_SIZE + sizeof(u16); | ||
351 | |||
352 | /* Encrypt msdu first on the whole data packet. */ | ||
353 | if ((host_encrypt || host_encrypt_msdu) && | ||
354 | crypt && crypt->ops && crypt->ops->encrypt_msdu) { | ||
355 | int res = 0; | ||
356 | int len = bytes + hdr_len + crypt->ops->extra_msdu_prefix_len + | ||
357 | crypt->ops->extra_msdu_postfix_len; | ||
358 | struct sk_buff *skb_new = dev_alloc_skb(len); | ||
359 | |||
360 | if (unlikely(!skb_new)) | ||
361 | goto failed; | ||
362 | |||
363 | skb_reserve(skb_new, crypt->ops->extra_msdu_prefix_len); | ||
364 | memcpy(skb_put(skb_new, hdr_len), &header, hdr_len); | ||
365 | snapped = 1; | ||
366 | ieee80211_copy_snap(skb_put(skb_new, SNAP_SIZE + sizeof(u16)), | ||
367 | ether_type); | ||
368 | skb_copy_from_linear_data(skb, skb_put(skb_new, skb->len), skb->len); | ||
369 | res = crypt->ops->encrypt_msdu(skb_new, hdr_len, crypt->priv); | ||
370 | if (res < 0) { | ||
371 | IEEE80211_ERROR("msdu encryption failed\n"); | ||
372 | dev_kfree_skb_any(skb_new); | ||
373 | goto failed; | ||
374 | } | ||
375 | dev_kfree_skb_any(skb); | ||
376 | skb = skb_new; | ||
377 | bytes += crypt->ops->extra_msdu_prefix_len + | ||
378 | crypt->ops->extra_msdu_postfix_len; | ||
379 | skb_pull(skb, hdr_len); | ||
380 | } | ||
381 | |||
382 | if (host_encrypt || ieee->host_open_frag) { | ||
383 | /* Determine fragmentation size based on destination (multicast | ||
384 | * and broadcast are not fragmented) */ | ||
385 | if (is_multicast_ether_addr(dest) || | ||
386 | is_broadcast_ether_addr(dest)) | ||
387 | frag_size = MAX_FRAG_THRESHOLD; | ||
388 | else | ||
389 | frag_size = ieee->fts; | ||
390 | |||
391 | /* Determine amount of payload per fragment. Regardless of if | ||
392 | * this stack is providing the full 802.11 header, one will | ||
393 | * eventually be affixed to this fragment -- so we must account | ||
394 | * for it when determining the amount of payload space. */ | ||
395 | bytes_per_frag = frag_size - hdr_len; | ||
396 | if (ieee->config & | ||
397 | (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) | ||
398 | bytes_per_frag -= IEEE80211_FCS_LEN; | ||
399 | |||
400 | /* Each fragment may need to have room for encryptiong | ||
401 | * pre/postfix */ | ||
402 | if (host_encrypt) | ||
403 | bytes_per_frag -= crypt->ops->extra_mpdu_prefix_len + | ||
404 | crypt->ops->extra_mpdu_postfix_len; | ||
405 | |||
406 | /* Number of fragments is the total | ||
407 | * bytes_per_frag / payload_per_fragment */ | ||
408 | nr_frags = bytes / bytes_per_frag; | ||
409 | bytes_last_frag = bytes % bytes_per_frag; | ||
410 | if (bytes_last_frag) | ||
411 | nr_frags++; | ||
412 | else | ||
413 | bytes_last_frag = bytes_per_frag; | ||
414 | } else { | ||
415 | nr_frags = 1; | ||
416 | bytes_per_frag = bytes_last_frag = bytes; | ||
417 | frag_size = bytes + hdr_len; | ||
418 | } | ||
419 | |||
420 | rts_required = (frag_size > ieee->rts | ||
421 | && ieee->config & CFG_IEEE80211_RTS); | ||
422 | if (rts_required) | ||
423 | nr_frags++; | ||
424 | |||
425 | /* When we allocate the TXB we allocate enough space for the reserve | ||
426 | * and full fragment bytes (bytes_per_frag doesn't include prefix, | ||
427 | * postfix, header, FCS, etc.) */ | ||
428 | txb = ieee80211_alloc_txb(nr_frags, frag_size, | ||
429 | ieee->tx_headroom, GFP_ATOMIC); | ||
430 | if (unlikely(!txb)) { | ||
431 | printk(KERN_WARNING "%s: Could not allocate TXB\n", | ||
432 | ieee->dev->name); | ||
433 | goto failed; | ||
434 | } | ||
435 | txb->encrypted = encrypt; | ||
436 | if (host_encrypt) | ||
437 | txb->payload_size = frag_size * (nr_frags - 1) + | ||
438 | bytes_last_frag; | ||
439 | else | ||
440 | txb->payload_size = bytes; | ||
441 | |||
442 | if (rts_required) { | ||
443 | skb_frag = txb->fragments[0]; | ||
444 | frag_hdr = | ||
445 | (struct ieee80211_hdr_3addrqos *)skb_put(skb_frag, hdr_len); | ||
446 | |||
447 | /* | ||
448 | * Set header frame_ctl to the RTS. | ||
449 | */ | ||
450 | header.frame_ctl = | ||
451 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS); | ||
452 | memcpy(frag_hdr, &header, hdr_len); | ||
453 | |||
454 | /* | ||
455 | * Restore header frame_ctl to the original data setting. | ||
456 | */ | ||
457 | header.frame_ctl = cpu_to_le16(fc); | ||
458 | |||
459 | if (ieee->config & | ||
460 | (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) | ||
461 | skb_put(skb_frag, 4); | ||
462 | |||
463 | txb->rts_included = 1; | ||
464 | i = 1; | ||
465 | } else | ||
466 | i = 0; | ||
467 | |||
468 | for (; i < nr_frags; i++) { | ||
469 | skb_frag = txb->fragments[i]; | ||
470 | |||
471 | if (host_encrypt || host_build_iv) | ||
472 | skb_reserve(skb_frag, | ||
473 | crypt->ops->extra_mpdu_prefix_len); | ||
474 | |||
475 | frag_hdr = | ||
476 | (struct ieee80211_hdr_3addrqos *)skb_put(skb_frag, hdr_len); | ||
477 | memcpy(frag_hdr, &header, hdr_len); | ||
478 | |||
479 | /* If this is not the last fragment, then add the MOREFRAGS | ||
480 | * bit to the frame control */ | ||
481 | if (i != nr_frags - 1) { | ||
482 | frag_hdr->frame_ctl = | ||
483 | cpu_to_le16(fc | IEEE80211_FCTL_MOREFRAGS); | ||
484 | bytes = bytes_per_frag; | ||
485 | } else { | ||
486 | /* The last fragment takes the remaining length */ | ||
487 | bytes = bytes_last_frag; | ||
488 | } | ||
489 | |||
490 | if (i == 0 && !snapped) { | ||
491 | ieee80211_copy_snap(skb_put | ||
492 | (skb_frag, SNAP_SIZE + sizeof(u16)), | ||
493 | ether_type); | ||
494 | bytes -= SNAP_SIZE + sizeof(u16); | ||
495 | } | ||
496 | |||
497 | skb_copy_from_linear_data(skb, skb_put(skb_frag, bytes), bytes); | ||
498 | |||
499 | /* Advance the SKB... */ | ||
500 | skb_pull(skb, bytes); | ||
501 | |||
502 | /* Encryption routine will move the header forward in order | ||
503 | * to insert the IV between the header and the payload */ | ||
504 | if (host_encrypt) | ||
505 | ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len); | ||
506 | else if (host_build_iv) { | ||
507 | atomic_inc(&crypt->refcnt); | ||
508 | if (crypt->ops->build_iv) | ||
509 | crypt->ops->build_iv(skb_frag, hdr_len, | ||
510 | ieee->sec.keys[ieee->sec.active_key], | ||
511 | ieee->sec.key_sizes[ieee->sec.active_key], | ||
512 | crypt->priv); | ||
513 | atomic_dec(&crypt->refcnt); | ||
514 | } | ||
515 | |||
516 | if (ieee->config & | ||
517 | (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) | ||
518 | skb_put(skb_frag, 4); | ||
519 | } | ||
520 | |||
521 | success: | ||
522 | spin_unlock_irqrestore(&ieee->lock, flags); | ||
523 | |||
524 | dev_kfree_skb_any(skb); | ||
525 | |||
526 | if (txb) { | ||
527 | int ret = (*ieee->hard_start_xmit) (txb, dev, priority); | ||
528 | if (ret == 0) { | ||
529 | stats->tx_packets++; | ||
530 | stats->tx_bytes += txb->payload_size; | ||
531 | return 0; | ||
532 | } | ||
533 | |||
534 | ieee80211_txb_free(txb); | ||
535 | } | ||
536 | |||
537 | return 0; | ||
538 | |||
539 | failed: | ||
540 | spin_unlock_irqrestore(&ieee->lock, flags); | ||
541 | netif_stop_queue(dev); | ||
542 | stats->tx_errors++; | ||
543 | return 1; | ||
544 | } | ||
545 | |||
546 | EXPORT_SYMBOL(ieee80211_txb_free); | ||
diff --git a/drivers/net/wireless/ipw2x00/libipw_wx.c b/drivers/net/wireless/ipw2x00/libipw_wx.c new file mode 100644 index 000000000000..31ea3abfc327 --- /dev/null +++ b/drivers/net/wireless/ipw2x00/libipw_wx.c | |||
@@ -0,0 +1,760 @@ | |||
1 | /****************************************************************************** | ||
2 | |||
3 | Copyright(c) 2004-2005 Intel Corporation. All rights reserved. | ||
4 | |||
5 | Portions of this file are based on the WEP enablement code provided by the | ||
6 | Host AP project hostap-drivers v0.1.3 | ||
7 | Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen | ||
8 | <j@w1.fi> | ||
9 | Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi> | ||
10 | |||
11 | This program is free software; you can redistribute it and/or modify it | ||
12 | under the terms of version 2 of the GNU General Public License as | ||
13 | published by the Free Software Foundation. | ||
14 | |||
15 | This program is distributed in the hope that it will be useful, but WITHOUT | ||
16 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
18 | more details. | ||
19 | |||
20 | You should have received a copy of the GNU General Public License along with | ||
21 | this program; if not, write to the Free Software Foundation, Inc., 59 | ||
22 | Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
23 | |||
24 | The full GNU General Public License is included in this distribution in the | ||
25 | file called LICENSE. | ||
26 | |||
27 | Contact Information: | ||
28 | James P. Ketrenos <ipw2100-admin@linux.intel.com> | ||
29 | Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | |||
31 | ******************************************************************************/ | ||
32 | |||
33 | #include <linux/kmod.h> | ||
34 | #include <linux/module.h> | ||
35 | #include <linux/jiffies.h> | ||
36 | |||
37 | #include <net/lib80211.h> | ||
38 | #include <net/ieee80211.h> | ||
39 | #include <linux/wireless.h> | ||
40 | |||
41 | static const char *ieee80211_modes[] = { | ||
42 | "?", "a", "b", "ab", "g", "ag", "bg", "abg" | ||
43 | }; | ||
44 | |||
45 | #define MAX_CUSTOM_LEN 64 | ||
46 | static char *ieee80211_translate_scan(struct ieee80211_device *ieee, | ||
47 | char *start, char *stop, | ||
48 | struct ieee80211_network *network, | ||
49 | struct iw_request_info *info) | ||
50 | { | ||
51 | char custom[MAX_CUSTOM_LEN]; | ||
52 | char *p; | ||
53 | struct iw_event iwe; | ||
54 | int i, j; | ||
55 | char *current_val; /* For rates */ | ||
56 | u8 rate; | ||
57 | |||
58 | /* First entry *MUST* be the AP MAC address */ | ||
59 | iwe.cmd = SIOCGIWAP; | ||
60 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; | ||
61 | memcpy(iwe.u.ap_addr.sa_data, network->bssid, ETH_ALEN); | ||
62 | start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN); | ||
63 | |||
64 | /* Remaining entries will be displayed in the order we provide them */ | ||
65 | |||
66 | /* Add the ESSID */ | ||
67 | iwe.cmd = SIOCGIWESSID; | ||
68 | iwe.u.data.flags = 1; | ||
69 | iwe.u.data.length = min(network->ssid_len, (u8) 32); | ||
70 | start = iwe_stream_add_point(info, start, stop, | ||
71 | &iwe, network->ssid); | ||
72 | |||
73 | /* Add the protocol name */ | ||
74 | iwe.cmd = SIOCGIWNAME; | ||
75 | snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11%s", | ||
76 | ieee80211_modes[network->mode]); | ||
77 | start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN); | ||
78 | |||
79 | /* Add mode */ | ||
80 | iwe.cmd = SIOCGIWMODE; | ||
81 | if (network->capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) { | ||
82 | if (network->capability & WLAN_CAPABILITY_ESS) | ||
83 | iwe.u.mode = IW_MODE_MASTER; | ||
84 | else | ||
85 | iwe.u.mode = IW_MODE_ADHOC; | ||
86 | |||
87 | start = iwe_stream_add_event(info, start, stop, | ||
88 | &iwe, IW_EV_UINT_LEN); | ||
89 | } | ||
90 | |||
91 | /* Add channel and frequency */ | ||
92 | /* Note : userspace automatically computes channel using iwrange */ | ||
93 | iwe.cmd = SIOCGIWFREQ; | ||
94 | iwe.u.freq.m = ieee80211_channel_to_freq(ieee, network->channel); | ||
95 | iwe.u.freq.e = 6; | ||
96 | iwe.u.freq.i = 0; | ||
97 | start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN); | ||
98 | |||
99 | /* Add encryption capability */ | ||
100 | iwe.cmd = SIOCGIWENCODE; | ||
101 | if (network->capability & WLAN_CAPABILITY_PRIVACY) | ||
102 | iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; | ||
103 | else | ||
104 | iwe.u.data.flags = IW_ENCODE_DISABLED; | ||
105 | iwe.u.data.length = 0; | ||
106 | start = iwe_stream_add_point(info, start, stop, | ||
107 | &iwe, network->ssid); | ||
108 | |||
109 | /* Add basic and extended rates */ | ||
110 | /* Rate : stuffing multiple values in a single event require a bit | ||
111 | * more of magic - Jean II */ | ||
112 | current_val = start + iwe_stream_lcp_len(info); | ||
113 | iwe.cmd = SIOCGIWRATE; | ||
114 | /* Those two flags are ignored... */ | ||
115 | iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; | ||
116 | |||
117 | for (i = 0, j = 0; i < network->rates_len;) { | ||
118 | if (j < network->rates_ex_len && | ||
119 | ((network->rates_ex[j] & 0x7F) < | ||
120 | (network->rates[i] & 0x7F))) | ||
121 | rate = network->rates_ex[j++] & 0x7F; | ||
122 | else | ||
123 | rate = network->rates[i++] & 0x7F; | ||
124 | /* Bit rate given in 500 kb/s units (+ 0x80) */ | ||
125 | iwe.u.bitrate.value = ((rate & 0x7f) * 500000); | ||
126 | /* Add new value to event */ | ||
127 | current_val = iwe_stream_add_value(info, start, current_val, | ||
128 | stop, &iwe, IW_EV_PARAM_LEN); | ||
129 | } | ||
130 | for (; j < network->rates_ex_len; j++) { | ||
131 | rate = network->rates_ex[j] & 0x7F; | ||
132 | /* Bit rate given in 500 kb/s units (+ 0x80) */ | ||
133 | iwe.u.bitrate.value = ((rate & 0x7f) * 500000); | ||
134 | /* Add new value to event */ | ||
135 | current_val = iwe_stream_add_value(info, start, current_val, | ||
136 | stop, &iwe, IW_EV_PARAM_LEN); | ||
137 | } | ||
138 | /* Check if we added any rate */ | ||
139 | if ((current_val - start) > iwe_stream_lcp_len(info)) | ||
140 | start = current_val; | ||
141 | |||
142 | /* Add quality statistics */ | ||
143 | iwe.cmd = IWEVQUAL; | ||
144 | iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | | ||
145 | IW_QUAL_NOISE_UPDATED; | ||
146 | |||
147 | if (!(network->stats.mask & IEEE80211_STATMASK_RSSI)) { | ||
148 | iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID | | ||
149 | IW_QUAL_LEVEL_INVALID; | ||
150 | iwe.u.qual.qual = 0; | ||
151 | } else { | ||
152 | if (ieee->perfect_rssi == ieee->worst_rssi) | ||
153 | iwe.u.qual.qual = 100; | ||
154 | else | ||
155 | iwe.u.qual.qual = | ||
156 | (100 * | ||
157 | (ieee->perfect_rssi - ieee->worst_rssi) * | ||
158 | (ieee->perfect_rssi - ieee->worst_rssi) - | ||
159 | (ieee->perfect_rssi - network->stats.rssi) * | ||
160 | (15 * (ieee->perfect_rssi - ieee->worst_rssi) + | ||
161 | 62 * (ieee->perfect_rssi - | ||
162 | network->stats.rssi))) / | ||
163 | ((ieee->perfect_rssi - | ||
164 | ieee->worst_rssi) * (ieee->perfect_rssi - | ||
165 | ieee->worst_rssi)); | ||
166 | if (iwe.u.qual.qual > 100) | ||
167 | iwe.u.qual.qual = 100; | ||
168 | else if (iwe.u.qual.qual < 1) | ||
169 | iwe.u.qual.qual = 0; | ||
170 | } | ||
171 | |||
172 | if (!(network->stats.mask & IEEE80211_STATMASK_NOISE)) { | ||
173 | iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID; | ||
174 | iwe.u.qual.noise = 0; | ||
175 | } else { | ||
176 | iwe.u.qual.noise = network->stats.noise; | ||
177 | } | ||
178 | |||
179 | if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL)) { | ||
180 | iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID; | ||
181 | iwe.u.qual.level = 0; | ||
182 | } else { | ||
183 | iwe.u.qual.level = network->stats.signal; | ||
184 | } | ||
185 | |||
186 | start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN); | ||
187 | |||
188 | iwe.cmd = IWEVCUSTOM; | ||
189 | p = custom; | ||
190 | |||
191 | iwe.u.data.length = p - custom; | ||
192 | if (iwe.u.data.length) | ||
193 | start = iwe_stream_add_point(info, start, stop, &iwe, custom); | ||
194 | |||
195 | memset(&iwe, 0, sizeof(iwe)); | ||
196 | if (network->wpa_ie_len) { | ||
197 | char buf[MAX_WPA_IE_LEN]; | ||
198 | memcpy(buf, network->wpa_ie, network->wpa_ie_len); | ||
199 | iwe.cmd = IWEVGENIE; | ||
200 | iwe.u.data.length = network->wpa_ie_len; | ||
201 | start = iwe_stream_add_point(info, start, stop, &iwe, buf); | ||
202 | } | ||
203 | |||
204 | memset(&iwe, 0, sizeof(iwe)); | ||
205 | if (network->rsn_ie_len) { | ||
206 | char buf[MAX_WPA_IE_LEN]; | ||
207 | memcpy(buf, network->rsn_ie, network->rsn_ie_len); | ||
208 | iwe.cmd = IWEVGENIE; | ||
209 | iwe.u.data.length = network->rsn_ie_len; | ||
210 | start = iwe_stream_add_point(info, start, stop, &iwe, buf); | ||
211 | } | ||
212 | |||
213 | /* Add EXTRA: Age to display seconds since last beacon/probe response | ||
214 | * for given network. */ | ||
215 | iwe.cmd = IWEVCUSTOM; | ||
216 | p = custom; | ||
217 | p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), | ||
218 | " Last beacon: %dms ago", | ||
219 | jiffies_to_msecs(jiffies - network->last_scanned)); | ||
220 | iwe.u.data.length = p - custom; | ||
221 | if (iwe.u.data.length) | ||
222 | start = iwe_stream_add_point(info, start, stop, &iwe, custom); | ||
223 | |||
224 | /* Add spectrum management information */ | ||
225 | iwe.cmd = -1; | ||
226 | p = custom; | ||
227 | p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Channel flags: "); | ||
228 | |||
229 | if (ieee80211_get_channel_flags(ieee, network->channel) & | ||
230 | IEEE80211_CH_INVALID) { | ||
231 | iwe.cmd = IWEVCUSTOM; | ||
232 | p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), "INVALID "); | ||
233 | } | ||
234 | |||
235 | if (ieee80211_get_channel_flags(ieee, network->channel) & | ||
236 | IEEE80211_CH_RADAR_DETECT) { | ||
237 | iwe.cmd = IWEVCUSTOM; | ||
238 | p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), "DFS "); | ||
239 | } | ||
240 | |||
241 | if (iwe.cmd == IWEVCUSTOM) { | ||
242 | iwe.u.data.length = p - custom; | ||
243 | start = iwe_stream_add_point(info, start, stop, &iwe, custom); | ||
244 | } | ||
245 | |||
246 | return start; | ||
247 | } | ||
248 | |||
249 | #define SCAN_ITEM_SIZE 128 | ||
250 | |||
251 | int ieee80211_wx_get_scan(struct ieee80211_device *ieee, | ||
252 | struct iw_request_info *info, | ||
253 | union iwreq_data *wrqu, char *extra) | ||
254 | { | ||
255 | struct ieee80211_network *network; | ||
256 | unsigned long flags; | ||
257 | int err = 0; | ||
258 | |||
259 | char *ev = extra; | ||
260 | char *stop = ev + wrqu->data.length; | ||
261 | int i = 0; | ||
262 | DECLARE_SSID_BUF(ssid); | ||
263 | |||
264 | IEEE80211_DEBUG_WX("Getting scan\n"); | ||
265 | |||
266 | spin_lock_irqsave(&ieee->lock, flags); | ||
267 | |||
268 | list_for_each_entry(network, &ieee->network_list, list) { | ||
269 | i++; | ||
270 | if (stop - ev < SCAN_ITEM_SIZE) { | ||
271 | err = -E2BIG; | ||
272 | break; | ||
273 | } | ||
274 | |||
275 | if (ieee->scan_age == 0 || | ||
276 | time_after(network->last_scanned + ieee->scan_age, jiffies)) | ||
277 | ev = ieee80211_translate_scan(ieee, ev, stop, network, | ||
278 | info); | ||
279 | else | ||
280 | IEEE80211_DEBUG_SCAN("Not showing network '%s (" | ||
281 | "%pM)' due to age (%dms).\n", | ||
282 | print_ssid(ssid, network->ssid, | ||
283 | network->ssid_len), | ||
284 | network->bssid, | ||
285 | jiffies_to_msecs(jiffies - | ||
286 | network-> | ||
287 | last_scanned)); | ||
288 | } | ||
289 | |||
290 | spin_unlock_irqrestore(&ieee->lock, flags); | ||
291 | |||
292 | wrqu->data.length = ev - extra; | ||
293 | wrqu->data.flags = 0; | ||
294 | |||
295 | IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i); | ||
296 | |||
297 | return err; | ||
298 | } | ||
299 | |||
300 | int ieee80211_wx_set_encode(struct ieee80211_device *ieee, | ||
301 | struct iw_request_info *info, | ||
302 | union iwreq_data *wrqu, char *keybuf) | ||
303 | { | ||
304 | struct iw_point *erq = &(wrqu->encoding); | ||
305 | struct net_device *dev = ieee->dev; | ||
306 | struct ieee80211_security sec = { | ||
307 | .flags = 0 | ||
308 | }; | ||
309 | int i, key, key_provided, len; | ||
310 | struct lib80211_crypt_data **crypt; | ||
311 | int host_crypto = ieee->host_encrypt || ieee->host_decrypt || ieee->host_build_iv; | ||
312 | DECLARE_SSID_BUF(ssid); | ||
313 | |||
314 | IEEE80211_DEBUG_WX("SET_ENCODE\n"); | ||
315 | |||
316 | key = erq->flags & IW_ENCODE_INDEX; | ||
317 | if (key) { | ||
318 | if (key > WEP_KEYS) | ||
319 | return -EINVAL; | ||
320 | key--; | ||
321 | key_provided = 1; | ||
322 | } else { | ||
323 | key_provided = 0; | ||
324 | key = ieee->crypt_info.tx_keyidx; | ||
325 | } | ||
326 | |||
327 | IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ? | ||
328 | "provided" : "default"); | ||
329 | |||
330 | crypt = &ieee->crypt_info.crypt[key]; | ||
331 | |||
332 | if (erq->flags & IW_ENCODE_DISABLED) { | ||
333 | if (key_provided && *crypt) { | ||
334 | IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n", | ||
335 | key); | ||
336 | lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt); | ||
337 | } else | ||
338 | IEEE80211_DEBUG_WX("Disabling encryption.\n"); | ||
339 | |||
340 | /* Check all the keys to see if any are still configured, | ||
341 | * and if no key index was provided, de-init them all */ | ||
342 | for (i = 0; i < WEP_KEYS; i++) { | ||
343 | if (ieee->crypt_info.crypt[i] != NULL) { | ||
344 | if (key_provided) | ||
345 | break; | ||
346 | lib80211_crypt_delayed_deinit(&ieee->crypt_info, | ||
347 | &ieee->crypt_info.crypt[i]); | ||
348 | } | ||
349 | } | ||
350 | |||
351 | if (i == WEP_KEYS) { | ||
352 | sec.enabled = 0; | ||
353 | sec.encrypt = 0; | ||
354 | sec.level = SEC_LEVEL_0; | ||
355 | sec.flags |= SEC_ENABLED | SEC_LEVEL | SEC_ENCRYPT; | ||
356 | } | ||
357 | |||
358 | goto done; | ||
359 | } | ||
360 | |||
361 | sec.enabled = 1; | ||
362 | sec.encrypt = 1; | ||
363 | sec.flags |= SEC_ENABLED | SEC_ENCRYPT; | ||
364 | |||
365 | if (*crypt != NULL && (*crypt)->ops != NULL && | ||
366 | strcmp((*crypt)->ops->name, "WEP") != 0) { | ||
367 | /* changing to use WEP; deinit previously used algorithm | ||
368 | * on this key */ | ||
369 | lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt); | ||
370 | } | ||
371 | |||
372 | if (*crypt == NULL && host_crypto) { | ||
373 | struct lib80211_crypt_data *new_crypt; | ||
374 | |||
375 | /* take WEP into use */ | ||
376 | new_crypt = kzalloc(sizeof(struct lib80211_crypt_data), | ||
377 | GFP_KERNEL); | ||
378 | if (new_crypt == NULL) | ||
379 | return -ENOMEM; | ||
380 | new_crypt->ops = lib80211_get_crypto_ops("WEP"); | ||
381 | if (!new_crypt->ops) { | ||
382 | request_module("lib80211_crypt_wep"); | ||
383 | new_crypt->ops = lib80211_get_crypto_ops("WEP"); | ||
384 | } | ||
385 | |||
386 | if (new_crypt->ops && try_module_get(new_crypt->ops->owner)) | ||
387 | new_crypt->priv = new_crypt->ops->init(key); | ||
388 | |||
389 | if (!new_crypt->ops || !new_crypt->priv) { | ||
390 | kfree(new_crypt); | ||
391 | new_crypt = NULL; | ||
392 | |||
393 | printk(KERN_WARNING "%s: could not initialize WEP: " | ||
394 | "load module lib80211_crypt_wep\n", dev->name); | ||
395 | return -EOPNOTSUPP; | ||
396 | } | ||
397 | *crypt = new_crypt; | ||
398 | } | ||
399 | |||
400 | /* If a new key was provided, set it up */ | ||
401 | if (erq->length > 0) { | ||
402 | #ifdef CONFIG_IEEE80211_DEBUG | ||
403 | DECLARE_SSID_BUF(ssid); | ||
404 | #endif | ||
405 | |||
406 | len = erq->length <= 5 ? 5 : 13; | ||
407 | memcpy(sec.keys[key], keybuf, erq->length); | ||
408 | if (len > erq->length) | ||
409 | memset(sec.keys[key] + erq->length, 0, | ||
410 | len - erq->length); | ||
411 | IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n", | ||
412 | key, print_ssid(ssid, sec.keys[key], len), | ||
413 | erq->length, len); | ||
414 | sec.key_sizes[key] = len; | ||
415 | if (*crypt) | ||
416 | (*crypt)->ops->set_key(sec.keys[key], len, NULL, | ||
417 | (*crypt)->priv); | ||
418 | sec.flags |= (1 << key); | ||
419 | /* This ensures a key will be activated if no key is | ||
420 | * explicitly set */ | ||
421 | if (key == sec.active_key) | ||
422 | sec.flags |= SEC_ACTIVE_KEY; | ||
423 | |||
424 | } else { | ||
425 | if (host_crypto) { | ||
426 | len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN, | ||
427 | NULL, (*crypt)->priv); | ||
428 | if (len == 0) { | ||
429 | /* Set a default key of all 0 */ | ||
430 | IEEE80211_DEBUG_WX("Setting key %d to all " | ||
431 | "zero.\n", key); | ||
432 | memset(sec.keys[key], 0, 13); | ||
433 | (*crypt)->ops->set_key(sec.keys[key], 13, NULL, | ||
434 | (*crypt)->priv); | ||
435 | sec.key_sizes[key] = 13; | ||
436 | sec.flags |= (1 << key); | ||
437 | } | ||
438 | } | ||
439 | /* No key data - just set the default TX key index */ | ||
440 | if (key_provided) { | ||
441 | IEEE80211_DEBUG_WX("Setting key %d to default Tx " | ||
442 | "key.\n", key); | ||
443 | ieee->crypt_info.tx_keyidx = key; | ||
444 | sec.active_key = key; | ||
445 | sec.flags |= SEC_ACTIVE_KEY; | ||
446 | } | ||
447 | } | ||
448 | if (erq->flags & (IW_ENCODE_OPEN | IW_ENCODE_RESTRICTED)) { | ||
449 | ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED); | ||
450 | sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : | ||
451 | WLAN_AUTH_SHARED_KEY; | ||
452 | sec.flags |= SEC_AUTH_MODE; | ||
453 | IEEE80211_DEBUG_WX("Auth: %s\n", | ||
454 | sec.auth_mode == WLAN_AUTH_OPEN ? | ||
455 | "OPEN" : "SHARED KEY"); | ||
456 | } | ||
457 | |||
458 | /* For now we just support WEP, so only set that security level... | ||
459 | * TODO: When WPA is added this is one place that needs to change */ | ||
460 | sec.flags |= SEC_LEVEL; | ||
461 | sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */ | ||
462 | sec.encode_alg[key] = SEC_ALG_WEP; | ||
463 | |||
464 | done: | ||
465 | if (ieee->set_security) | ||
466 | ieee->set_security(dev, &sec); | ||
467 | |||
468 | /* Do not reset port if card is in Managed mode since resetting will | ||
469 | * generate new IEEE 802.11 authentication which may end up in looping | ||
470 | * with IEEE 802.1X. If your hardware requires a reset after WEP | ||
471 | * configuration (for example... Prism2), implement the reset_port in | ||
472 | * the callbacks structures used to initialize the 802.11 stack. */ | ||
473 | if (ieee->reset_on_keychange && | ||
474 | ieee->iw_mode != IW_MODE_INFRA && | ||
475 | ieee->reset_port && ieee->reset_port(dev)) { | ||
476 | printk(KERN_DEBUG "%s: reset_port failed\n", dev->name); | ||
477 | return -EINVAL; | ||
478 | } | ||
479 | return 0; | ||
480 | } | ||
481 | |||
482 | int ieee80211_wx_get_encode(struct ieee80211_device *ieee, | ||
483 | struct iw_request_info *info, | ||
484 | union iwreq_data *wrqu, char *keybuf) | ||
485 | { | ||
486 | struct iw_point *erq = &(wrqu->encoding); | ||
487 | int len, key; | ||
488 | struct lib80211_crypt_data *crypt; | ||
489 | struct ieee80211_security *sec = &ieee->sec; | ||
490 | |||
491 | IEEE80211_DEBUG_WX("GET_ENCODE\n"); | ||
492 | |||
493 | key = erq->flags & IW_ENCODE_INDEX; | ||
494 | if (key) { | ||
495 | if (key > WEP_KEYS) | ||
496 | return -EINVAL; | ||
497 | key--; | ||
498 | } else | ||
499 | key = ieee->crypt_info.tx_keyidx; | ||
500 | |||
501 | crypt = ieee->crypt_info.crypt[key]; | ||
502 | erq->flags = key + 1; | ||
503 | |||
504 | if (!sec->enabled) { | ||
505 | erq->length = 0; | ||
506 | erq->flags |= IW_ENCODE_DISABLED; | ||
507 | return 0; | ||
508 | } | ||
509 | |||
510 | len = sec->key_sizes[key]; | ||
511 | memcpy(keybuf, sec->keys[key], len); | ||
512 | |||
513 | erq->length = len; | ||
514 | erq->flags |= IW_ENCODE_ENABLED; | ||
515 | |||
516 | if (ieee->open_wep) | ||
517 | erq->flags |= IW_ENCODE_OPEN; | ||
518 | else | ||
519 | erq->flags |= IW_ENCODE_RESTRICTED; | ||
520 | |||
521 | return 0; | ||
522 | } | ||
523 | |||
524 | int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee, | ||
525 | struct iw_request_info *info, | ||
526 | union iwreq_data *wrqu, char *extra) | ||
527 | { | ||
528 | struct net_device *dev = ieee->dev; | ||
529 | struct iw_point *encoding = &wrqu->encoding; | ||
530 | struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; | ||
531 | int i, idx, ret = 0; | ||
532 | int group_key = 0; | ||
533 | const char *alg, *module; | ||
534 | struct lib80211_crypto_ops *ops; | ||
535 | struct lib80211_crypt_data **crypt; | ||
536 | |||
537 | struct ieee80211_security sec = { | ||
538 | .flags = 0, | ||
539 | }; | ||
540 | |||
541 | idx = encoding->flags & IW_ENCODE_INDEX; | ||
542 | if (idx) { | ||
543 | if (idx < 1 || idx > WEP_KEYS) | ||
544 | return -EINVAL; | ||
545 | idx--; | ||
546 | } else | ||
547 | idx = ieee->crypt_info.tx_keyidx; | ||
548 | |||
549 | if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { | ||
550 | crypt = &ieee->crypt_info.crypt[idx]; | ||
551 | group_key = 1; | ||
552 | } else { | ||
553 | /* some Cisco APs use idx>0 for unicast in dynamic WEP */ | ||
554 | if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP) | ||
555 | return -EINVAL; | ||
556 | if (ieee->iw_mode == IW_MODE_INFRA) | ||
557 | crypt = &ieee->crypt_info.crypt[idx]; | ||
558 | else | ||
559 | return -EINVAL; | ||
560 | } | ||
561 | |||
562 | sec.flags |= SEC_ENABLED | SEC_ENCRYPT; | ||
563 | if ((encoding->flags & IW_ENCODE_DISABLED) || | ||
564 | ext->alg == IW_ENCODE_ALG_NONE) { | ||
565 | if (*crypt) | ||
566 | lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt); | ||
567 | |||
568 | for (i = 0; i < WEP_KEYS; i++) | ||
569 | if (ieee->crypt_info.crypt[i] != NULL) | ||
570 | break; | ||
571 | |||
572 | if (i == WEP_KEYS) { | ||
573 | sec.enabled = 0; | ||
574 | sec.encrypt = 0; | ||
575 | sec.level = SEC_LEVEL_0; | ||
576 | sec.flags |= SEC_LEVEL; | ||
577 | } | ||
578 | goto done; | ||
579 | } | ||
580 | |||
581 | sec.enabled = 1; | ||
582 | sec.encrypt = 1; | ||
583 | |||
584 | if (group_key ? !ieee->host_mc_decrypt : | ||
585 | !(ieee->host_encrypt || ieee->host_decrypt || | ||
586 | ieee->host_encrypt_msdu)) | ||
587 | goto skip_host_crypt; | ||
588 | |||
589 | switch (ext->alg) { | ||
590 | case IW_ENCODE_ALG_WEP: | ||
591 | alg = "WEP"; | ||
592 | module = "lib80211_crypt_wep"; | ||
593 | break; | ||
594 | case IW_ENCODE_ALG_TKIP: | ||
595 | alg = "TKIP"; | ||
596 | module = "lib80211_crypt_tkip"; | ||
597 | break; | ||
598 | case IW_ENCODE_ALG_CCMP: | ||
599 | alg = "CCMP"; | ||
600 | module = "lib80211_crypt_ccmp"; | ||
601 | break; | ||
602 | default: | ||
603 | IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n", | ||
604 | dev->name, ext->alg); | ||
605 | ret = -EINVAL; | ||
606 | goto done; | ||
607 | } | ||
608 | |||
609 | ops = lib80211_get_crypto_ops(alg); | ||
610 | if (ops == NULL) { | ||
611 | request_module(module); | ||
612 | ops = lib80211_get_crypto_ops(alg); | ||
613 | } | ||
614 | if (ops == NULL) { | ||
615 | IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n", | ||
616 | dev->name, ext->alg); | ||
617 | ret = -EINVAL; | ||
618 | goto done; | ||
619 | } | ||
620 | |||
621 | if (*crypt == NULL || (*crypt)->ops != ops) { | ||
622 | struct lib80211_crypt_data *new_crypt; | ||
623 | |||
624 | lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt); | ||
625 | |||
626 | new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL); | ||
627 | if (new_crypt == NULL) { | ||
628 | ret = -ENOMEM; | ||
629 | goto done; | ||
630 | } | ||
631 | new_crypt->ops = ops; | ||
632 | if (new_crypt->ops && try_module_get(new_crypt->ops->owner)) | ||
633 | new_crypt->priv = new_crypt->ops->init(idx); | ||
634 | if (new_crypt->priv == NULL) { | ||
635 | kfree(new_crypt); | ||
636 | ret = -EINVAL; | ||
637 | goto done; | ||
638 | } | ||
639 | *crypt = new_crypt; | ||
640 | } | ||
641 | |||
642 | if (ext->key_len > 0 && (*crypt)->ops->set_key && | ||
643 | (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq, | ||
644 | (*crypt)->priv) < 0) { | ||
645 | IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name); | ||
646 | ret = -EINVAL; | ||
647 | goto done; | ||
648 | } | ||
649 | |||
650 | skip_host_crypt: | ||
651 | if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { | ||
652 | ieee->crypt_info.tx_keyidx = idx; | ||
653 | sec.active_key = idx; | ||
654 | sec.flags |= SEC_ACTIVE_KEY; | ||
655 | } | ||
656 | |||
657 | if (ext->alg != IW_ENCODE_ALG_NONE) { | ||
658 | memcpy(sec.keys[idx], ext->key, ext->key_len); | ||
659 | sec.key_sizes[idx] = ext->key_len; | ||
660 | sec.flags |= (1 << idx); | ||
661 | if (ext->alg == IW_ENCODE_ALG_WEP) { | ||
662 | sec.encode_alg[idx] = SEC_ALG_WEP; | ||
663 | sec.flags |= SEC_LEVEL; | ||
664 | sec.level = SEC_LEVEL_1; | ||
665 | } else if (ext->alg == IW_ENCODE_ALG_TKIP) { | ||
666 | sec.encode_alg[idx] = SEC_ALG_TKIP; | ||
667 | sec.flags |= SEC_LEVEL; | ||
668 | sec.level = SEC_LEVEL_2; | ||
669 | } else if (ext->alg == IW_ENCODE_ALG_CCMP) { | ||
670 | sec.encode_alg[idx] = SEC_ALG_CCMP; | ||
671 | sec.flags |= SEC_LEVEL; | ||
672 | sec.level = SEC_LEVEL_3; | ||
673 | } | ||
674 | /* Don't set sec level for group keys. */ | ||
675 | if (group_key) | ||
676 | sec.flags &= ~SEC_LEVEL; | ||
677 | } | ||
678 | done: | ||
679 | if (ieee->set_security) | ||
680 | ieee->set_security(ieee->dev, &sec); | ||
681 | |||
682 | /* | ||
683 | * Do not reset port if card is in Managed mode since resetting will | ||
684 | * generate new IEEE 802.11 authentication which may end up in looping | ||
685 | * with IEEE 802.1X. If your hardware requires a reset after WEP | ||
686 | * configuration (for example... Prism2), implement the reset_port in | ||
687 | * the callbacks structures used to initialize the 802.11 stack. | ||
688 | */ | ||
689 | if (ieee->reset_on_keychange && | ||
690 | ieee->iw_mode != IW_MODE_INFRA && | ||
691 | ieee->reset_port && ieee->reset_port(dev)) { | ||
692 | IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name); | ||
693 | return -EINVAL; | ||
694 | } | ||
695 | |||
696 | return ret; | ||
697 | } | ||
698 | |||
699 | int ieee80211_wx_get_encodeext(struct ieee80211_device *ieee, | ||
700 | struct iw_request_info *info, | ||
701 | union iwreq_data *wrqu, char *extra) | ||
702 | { | ||
703 | struct iw_point *encoding = &wrqu->encoding; | ||
704 | struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; | ||
705 | struct ieee80211_security *sec = &ieee->sec; | ||
706 | int idx, max_key_len; | ||
707 | |||
708 | max_key_len = encoding->length - sizeof(*ext); | ||
709 | if (max_key_len < 0) | ||
710 | return -EINVAL; | ||
711 | |||
712 | idx = encoding->flags & IW_ENCODE_INDEX; | ||
713 | if (idx) { | ||
714 | if (idx < 1 || idx > WEP_KEYS) | ||
715 | return -EINVAL; | ||
716 | idx--; | ||
717 | } else | ||
718 | idx = ieee->crypt_info.tx_keyidx; | ||
719 | |||
720 | if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) && | ||
721 | ext->alg != IW_ENCODE_ALG_WEP) | ||
722 | if (idx != 0 || ieee->iw_mode != IW_MODE_INFRA) | ||
723 | return -EINVAL; | ||
724 | |||
725 | encoding->flags = idx + 1; | ||
726 | memset(ext, 0, sizeof(*ext)); | ||
727 | |||
728 | if (!sec->enabled) { | ||
729 | ext->alg = IW_ENCODE_ALG_NONE; | ||
730 | ext->key_len = 0; | ||
731 | encoding->flags |= IW_ENCODE_DISABLED; | ||
732 | } else { | ||
733 | if (sec->encode_alg[idx] == SEC_ALG_WEP) | ||
734 | ext->alg = IW_ENCODE_ALG_WEP; | ||
735 | else if (sec->encode_alg[idx] == SEC_ALG_TKIP) | ||
736 | ext->alg = IW_ENCODE_ALG_TKIP; | ||
737 | else if (sec->encode_alg[idx] == SEC_ALG_CCMP) | ||
738 | ext->alg = IW_ENCODE_ALG_CCMP; | ||
739 | else | ||
740 | return -EINVAL; | ||
741 | |||
742 | ext->key_len = sec->key_sizes[idx]; | ||
743 | memcpy(ext->key, sec->keys[idx], ext->key_len); | ||
744 | encoding->flags |= IW_ENCODE_ENABLED; | ||
745 | if (ext->key_len && | ||
746 | (ext->alg == IW_ENCODE_ALG_TKIP || | ||
747 | ext->alg == IW_ENCODE_ALG_CCMP)) | ||
748 | ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID; | ||
749 | |||
750 | } | ||
751 | |||
752 | return 0; | ||
753 | } | ||
754 | |||
755 | EXPORT_SYMBOL(ieee80211_wx_set_encodeext); | ||
756 | EXPORT_SYMBOL(ieee80211_wx_get_encodeext); | ||
757 | |||
758 | EXPORT_SYMBOL(ieee80211_wx_get_scan); | ||
759 | EXPORT_SYMBOL(ieee80211_wx_set_encode); | ||
760 | EXPORT_SYMBOL(ieee80211_wx_get_encode); | ||
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 47aa28f6a513..8b45b30e6d5c 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile | |||
@@ -5,6 +5,7 @@ iwlcore-objs += iwl-scan.o | |||
5 | iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o | 5 | iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o |
6 | iwlcore-$(CONFIG_IWLWIFI_LEDS) += iwl-led.o | 6 | iwlcore-$(CONFIG_IWLWIFI_LEDS) += iwl-led.o |
7 | iwlcore-$(CONFIG_IWLWIFI_RFKILL) += iwl-rfkill.o | 7 | iwlcore-$(CONFIG_IWLWIFI_RFKILL) += iwl-rfkill.o |
8 | iwlcore-$(CONFIG_IWLAGN_SPECTRUM_MEASUREMENT) += iwl-spectrum.o | ||
8 | 9 | ||
9 | obj-$(CONFIG_IWLAGN) += iwlagn.o | 10 | obj-$(CONFIG_IWLAGN) += iwlagn.o |
10 | iwlagn-objs := iwl-agn.o iwl-agn-rs.o | 11 | iwlagn-objs := iwl-agn.o iwl-agn-rs.o |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index 9da7c7bea752..fb0fd773960f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h | |||
@@ -819,64 +819,6 @@ enum { | |||
819 | #define IWL49_NUM_QUEUES 16 | 819 | #define IWL49_NUM_QUEUES 16 |
820 | #define IWL49_NUM_AMPDU_QUEUES 8 | 820 | #define IWL49_NUM_AMPDU_QUEUES 8 |
821 | 821 | ||
822 | #define IWL_TX_DMA_MASK (DMA_BIT_MASK(36) & ~0x3) | ||
823 | #define IWL_NUM_OF_TBS 20 | ||
824 | |||
825 | static inline u8 iwl_get_dma_hi_addr(dma_addr_t addr) | ||
826 | { | ||
827 | return (sizeof(addr) > sizeof(u32) ? (addr >> 16) >> 16 : 0) & 0xF; | ||
828 | } | ||
829 | /** | ||
830 | * struct iwl_tfd_tb transmit buffer descriptor within transmit frame descriptor | ||
831 | * | ||
832 | * This structure contains dma address and length of transmission address | ||
833 | * | ||
834 | * @lo: low [31:0] portion of the dma address of TX buffer | ||
835 | * every even is unaligned on 16 bit boundary | ||
836 | * @hi_n_len 0-3 [35:32] portion of dma | ||
837 | * 4-16 length of the tx buffer | ||
838 | */ | ||
839 | struct iwl_tfd_tb { | ||
840 | __le32 lo; | ||
841 | __le16 hi_n_len; | ||
842 | } __attribute__((packed)); | ||
843 | |||
844 | /** | ||
845 | * struct iwl_tfd | ||
846 | * | ||
847 | * Transmit Frame Descriptor (TFD) | ||
848 | * | ||
849 | * @ __reserved1[3] reserved | ||
850 | * @ num_tbs 0-5 number of active tbs | ||
851 | * 6-7 padding (not used) | ||
852 | * @ tbs[20] transmit frame buffer descriptors | ||
853 | * @ __pad padding | ||
854 | * | ||
855 | * Each Tx queue uses a circular buffer of 256 TFDs stored in host DRAM. | ||
856 | * Both driver and device share these circular buffers, each of which must be | ||
857 | * contiguous 256 TFDs x 128 bytes-per-TFD = 32 KBytes | ||
858 | * | ||
859 | * Driver must indicate the physical address of the base of each | ||
860 | * circular buffer via the FH_MEM_CBBC_QUEUE registers. | ||
861 | * | ||
862 | * Each TFD contains pointer/size information for up to 20 data buffers | ||
863 | * in host DRAM. These buffers collectively contain the (one) frame described | ||
864 | * by the TFD. Each buffer must be a single contiguous block of memory within | ||
865 | * itself, but buffers may be scattered in host DRAM. Each buffer has max size | ||
866 | * of (4K - 4). The concatenates all of a TFD's buffers into a single | ||
867 | * Tx frame, up to 8 KBytes in size. | ||
868 | * | ||
869 | * A maximum of 255 (not 256!) TFDs may be on a queue waiting for Tx. | ||
870 | * | ||
871 | * Bit fields in the control dword (val0): | ||
872 | */ | ||
873 | struct iwl_tfd { | ||
874 | u8 __reserved1[3]; | ||
875 | u8 num_tbs; | ||
876 | struct iwl_tfd_tb tbs[IWL_NUM_OF_TBS]; | ||
877 | __le32 __pad; | ||
878 | } __attribute__ ((packed)); | ||
879 | |||
880 | 822 | ||
881 | /** | 823 | /** |
882 | * struct iwl4965_schedq_bc_tbl | 824 | * struct iwl4965_schedq_bc_tbl |
@@ -896,64 +838,9 @@ struct iwl_tfd { | |||
896 | * padding puts each byte count table on a 1024-byte boundary; | 838 | * padding puts each byte count table on a 1024-byte boundary; |
897 | * 4965 assumes tables are separated by 1024 bytes. | 839 | * 4965 assumes tables are separated by 1024 bytes. |
898 | */ | 840 | */ |
899 | struct iwl4965_schedq_bc_tbl { | 841 | struct iwl4965_scd_bc_tbl { |
900 | __le16 tfd_offset[TFD_QUEUE_BC_SIZE]; | 842 | __le16 tfd_offset[TFD_QUEUE_BC_SIZE]; |
901 | u8 pad[1024 - (TFD_QUEUE_BC_SIZE) * sizeof(__le16)]; | 843 | u8 pad[1024 - (TFD_QUEUE_BC_SIZE) * sizeof(__le16)]; |
902 | } __attribute__ ((packed)); | 844 | } __attribute__ ((packed)); |
903 | 845 | ||
904 | 846 | #endif /* !__iwl_4965_hw_h__ */ | |
905 | /** | ||
906 | * struct iwl4965_shared - handshake area for Tx and Rx | ||
907 | * | ||
908 | * For convenience in allocating memory, this structure combines 2 areas of | ||
909 | * DRAM which must be shared between driver and 4965. These do not need to | ||
910 | * be combined, if better allocation would result from keeping them separate: | ||
911 | * | ||
912 | * 1) The Tx byte count tables occupy 1024 bytes each (16 KBytes total for | ||
913 | * 16 queues). Driver uses SCD_DRAM_BASE_ADDR to tell 4965 where to find | ||
914 | * the first of these tables. 4965 assumes tables are 1024 bytes apart. | ||
915 | * | ||
916 | * 2) The Rx status (val0 and val1) occupies only 8 bytes. Driver uses | ||
917 | * FH_RSCSR_CHNL0_STTS_WPTR_REG to tell 4965 where to find this area. | ||
918 | * Driver reads val0 to determine the latest Receive Buffer Descriptor (RBD) | ||
919 | * that has been filled by the 4965. | ||
920 | * | ||
921 | * Bit fields val0: | ||
922 | * 31-12: Not used | ||
923 | * 11- 0: Index of last filled Rx buffer descriptor (4965 writes, driver reads) | ||
924 | * | ||
925 | * Bit fields val1: | ||
926 | * 31- 0: Not used | ||
927 | */ | ||
928 | struct iwl4965_shared { | ||
929 | struct iwl4965_schedq_bc_tbl queues_bc_tbls[IWL49_NUM_QUEUES]; | ||
930 | __le32 rb_closed; | ||
931 | |||
932 | /* __le32 rb_closed_stts_rb_num:12; */ | ||
933 | #define IWL_rb_closed_stts_rb_num_POS 0 | ||
934 | #define IWL_rb_closed_stts_rb_num_LEN 12 | ||
935 | #define IWL_rb_closed_stts_rb_num_SYM rb_closed | ||
936 | /* __le32 rsrv1:4; */ | ||
937 | /* __le32 rb_closed_stts_rx_frame_num:12; */ | ||
938 | #define IWL_rb_closed_stts_rx_frame_num_POS 16 | ||
939 | #define IWL_rb_closed_stts_rx_frame_num_LEN 12 | ||
940 | #define IWL_rb_closed_stts_rx_frame_num_SYM rb_closed | ||
941 | /* __le32 rsrv2:4; */ | ||
942 | |||
943 | __le32 frm_finished; | ||
944 | /* __le32 frame_finished_stts_rb_num:12; */ | ||
945 | #define IWL_frame_finished_stts_rb_num_POS 0 | ||
946 | #define IWL_frame_finished_stts_rb_num_LEN 12 | ||
947 | #define IWL_frame_finished_stts_rb_num_SYM frm_finished | ||
948 | /* __le32 rsrv3:4; */ | ||
949 | /* __le32 frame_finished_stts_rx_frame_num:12; */ | ||
950 | #define IWL_frame_finished_stts_rx_frame_num_POS 16 | ||
951 | #define IWL_frame_finished_stts_rx_frame_num_LEN 12 | ||
952 | #define IWL_frame_finished_stts_rx_frame_num_SYM frm_finished | ||
953 | /* __le32 rsrv4:4; */ | ||
954 | |||
955 | __le32 padding1; /* so that allocation will be aligned to 16B */ | ||
956 | __le32 padding2; | ||
957 | } __attribute__ ((packed)); | ||
958 | |||
959 | #endif /* __iwl4965_4965_hw_h__ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 157cad4e9da0..c43cf2f072cd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -715,8 +715,7 @@ static int iwl4965_alive_notify(struct iwl_priv *priv) | |||
715 | 715 | ||
716 | /* Tel 4965 where to find Tx byte count tables */ | 716 | /* Tel 4965 where to find Tx byte count tables */ |
717 | iwl_write_prph(priv, IWL49_SCD_DRAM_BASE_ADDR, | 717 | iwl_write_prph(priv, IWL49_SCD_DRAM_BASE_ADDR, |
718 | (priv->shared_phys + | 718 | priv->scd_bc_tbls.dma >> 10); |
719 | offsetof(struct iwl4965_shared, queues_bc_tbls)) >> 10); | ||
720 | 719 | ||
721 | /* Disable chain mode for all queues */ | 720 | /* Disable chain mode for all queues */ |
722 | iwl_write_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, 0); | 721 | iwl_write_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, 0); |
@@ -804,6 +803,8 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv) | |||
804 | } | 803 | } |
805 | 804 | ||
806 | priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues; | 805 | priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues; |
806 | priv->hw_params.scd_bc_tbls_size = | ||
807 | IWL49_NUM_QUEUES * sizeof(struct iwl4965_scd_bc_tbl); | ||
807 | priv->hw_params.max_stations = IWL4965_STATION_COUNT; | 808 | priv->hw_params.max_stations = IWL4965_STATION_COUNT; |
808 | priv->hw_params.bcast_sta_id = IWL4965_BROADCAST_ID; | 809 | priv->hw_params.bcast_sta_id = IWL4965_BROADCAST_ID; |
809 | priv->hw_params.max_data_size = IWL49_RTC_DATA_SIZE; | 810 | priv->hw_params.max_data_size = IWL49_RTC_DATA_SIZE; |
@@ -1631,36 +1632,6 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) | |||
1631 | } | 1632 | } |
1632 | #endif | 1633 | #endif |
1633 | 1634 | ||
1634 | static int iwl4965_shared_mem_rx_idx(struct iwl_priv *priv) | ||
1635 | { | ||
1636 | struct iwl4965_shared *s = priv->shared_virt; | ||
1637 | return le32_to_cpu(s->rb_closed) & 0xFFF; | ||
1638 | } | ||
1639 | |||
1640 | static int iwl4965_alloc_shared_mem(struct iwl_priv *priv) | ||
1641 | { | ||
1642 | priv->shared_virt = pci_alloc_consistent(priv->pci_dev, | ||
1643 | sizeof(struct iwl4965_shared), | ||
1644 | &priv->shared_phys); | ||
1645 | if (!priv->shared_virt) | ||
1646 | return -ENOMEM; | ||
1647 | |||
1648 | memset(priv->shared_virt, 0, sizeof(struct iwl4965_shared)); | ||
1649 | |||
1650 | priv->rb_closed_offset = offsetof(struct iwl4965_shared, rb_closed); | ||
1651 | |||
1652 | return 0; | ||
1653 | } | ||
1654 | |||
1655 | static void iwl4965_free_shared_mem(struct iwl_priv *priv) | ||
1656 | { | ||
1657 | if (priv->shared_virt) | ||
1658 | pci_free_consistent(priv->pci_dev, | ||
1659 | sizeof(struct iwl4965_shared), | ||
1660 | priv->shared_virt, | ||
1661 | priv->shared_phys); | ||
1662 | } | ||
1663 | |||
1664 | /** | 1635 | /** |
1665 | * iwl4965_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array | 1636 | * iwl4965_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array |
1666 | */ | 1637 | */ |
@@ -1668,7 +1639,7 @@ static void iwl4965_txq_update_byte_cnt_tbl(struct iwl_priv *priv, | |||
1668 | struct iwl_tx_queue *txq, | 1639 | struct iwl_tx_queue *txq, |
1669 | u16 byte_cnt) | 1640 | u16 byte_cnt) |
1670 | { | 1641 | { |
1671 | struct iwl4965_shared *shared_data = priv->shared_virt; | 1642 | struct iwl4965_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; |
1672 | int txq_id = txq->q.id; | 1643 | int txq_id = txq->q.id; |
1673 | int write_ptr = txq->q.write_ptr; | 1644 | int write_ptr = txq->q.write_ptr; |
1674 | int len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; | 1645 | int len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; |
@@ -1678,11 +1649,11 @@ static void iwl4965_txq_update_byte_cnt_tbl(struct iwl_priv *priv, | |||
1678 | 1649 | ||
1679 | bc_ent = cpu_to_le16(len & 0xFFF); | 1650 | bc_ent = cpu_to_le16(len & 0xFFF); |
1680 | /* Set up byte count within first 256 entries */ | 1651 | /* Set up byte count within first 256 entries */ |
1681 | shared_data->queues_bc_tbls[txq_id].tfd_offset[write_ptr] = bc_ent; | 1652 | scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent; |
1682 | 1653 | ||
1683 | /* If within first 64 entries, duplicate at end */ | 1654 | /* If within first 64 entries, duplicate at end */ |
1684 | if (write_ptr < TFD_QUEUE_SIZE_BC_DUP) | 1655 | if (write_ptr < TFD_QUEUE_SIZE_BC_DUP) |
1685 | shared_data->queues_bc_tbls[txq_id]. | 1656 | scd_bc_tbl[txq_id]. |
1686 | tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent; | 1657 | tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent; |
1687 | } | 1658 | } |
1688 | 1659 | ||
@@ -2304,9 +2275,6 @@ static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { | |||
2304 | 2275 | ||
2305 | static struct iwl_lib_ops iwl4965_lib = { | 2276 | static struct iwl_lib_ops iwl4965_lib = { |
2306 | .set_hw_params = iwl4965_hw_set_hw_params, | 2277 | .set_hw_params = iwl4965_hw_set_hw_params, |
2307 | .alloc_shared_mem = iwl4965_alloc_shared_mem, | ||
2308 | .free_shared_mem = iwl4965_free_shared_mem, | ||
2309 | .shared_mem_rx_idx = iwl4965_shared_mem_rx_idx, | ||
2310 | .txq_update_byte_cnt_tbl = iwl4965_txq_update_byte_cnt_tbl, | 2278 | .txq_update_byte_cnt_tbl = iwl4965_txq_update_byte_cnt_tbl, |
2311 | .txq_set_sched = iwl4965_txq_set_sched, | 2279 | .txq_set_sched = iwl4965_txq_set_sched, |
2312 | .txq_agg_enable = iwl4965_txq_agg_enable, | 2280 | .txq_agg_enable = iwl4965_txq_agg_enable, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h index 12c74048a396..c6595e8b4405 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h | |||
@@ -90,45 +90,10 @@ | |||
90 | * @tfd_offset 0-12 - tx command byte count | 90 | * @tfd_offset 0-12 - tx command byte count |
91 | * 12-16 - station index | 91 | * 12-16 - station index |
92 | */ | 92 | */ |
93 | struct iwl5000_schedq_bc_tbl { | 93 | struct iwl5000_scd_bc_tbl { |
94 | __le16 tfd_offset[TFD_QUEUE_BC_SIZE]; | 94 | __le16 tfd_offset[TFD_QUEUE_BC_SIZE]; |
95 | } __attribute__ ((packed)); | 95 | } __attribute__ ((packed)); |
96 | 96 | ||
97 | /** | ||
98 | * struct iwl5000_shared | ||
99 | * @rb_closed | ||
100 | * address is provided to FH_RSCSR_CHNL0_STTS_WPTR_REG | ||
101 | */ | ||
102 | struct iwl5000_shared { | ||
103 | struct iwl5000_schedq_bc_tbl queues_bc_tbls[IWL50_NUM_QUEUES]; | ||
104 | __le32 rb_closed; | ||
105 | |||
106 | /* __le32 rb_closed_stts_rb_num:12; */ | ||
107 | #define IWL_rb_closed_stts_rb_num_POS 0 | ||
108 | #define IWL_rb_closed_stts_rb_num_LEN 12 | ||
109 | #define IWL_rb_closed_stts_rb_num_SYM rb_closed | ||
110 | /* __le32 rsrv1:4; */ | ||
111 | /* __le32 rb_closed_stts_rx_frame_num:12; */ | ||
112 | #define IWL_rb_closed_stts_rx_frame_num_POS 16 | ||
113 | #define IWL_rb_closed_stts_rx_frame_num_LEN 12 | ||
114 | #define IWL_rb_closed_stts_rx_frame_num_SYM rb_closed | ||
115 | /* __le32 rsrv2:4; */ | ||
116 | |||
117 | __le32 frm_finished; | ||
118 | /* __le32 frame_finished_stts_rb_num:12; */ | ||
119 | #define IWL_frame_finished_stts_rb_num_POS 0 | ||
120 | #define IWL_frame_finished_stts_rb_num_LEN 12 | ||
121 | #define IWL_frame_finished_stts_rb_num_SYM frm_finished | ||
122 | /* __le32 rsrv3:4; */ | ||
123 | /* __le32 frame_finished_stts_rx_frame_num:12; */ | ||
124 | #define IWL_frame_finished_stts_rx_frame_num_POS 16 | ||
125 | #define IWL_frame_finished_stts_rx_frame_num_LEN 12 | ||
126 | #define IWL_frame_finished_stts_rx_frame_num_SYM frm_finished | ||
127 | /* __le32 rsrv4:4; */ | ||
128 | |||
129 | __le32 padding1; /* so that allocation will be aligned to 16B */ | ||
130 | __le32 padding2; | ||
131 | } __attribute__ ((packed)); | ||
132 | 97 | ||
133 | #endif /* __iwl_5000_hw_h__ */ | 98 | #endif /* __iwl_5000_hw_h__ */ |
134 | 99 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 31e62a838ad4..ee3613db3132 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -721,11 +721,9 @@ static int iwl5000_alive_notify(struct iwl_priv *priv) | |||
721 | iwl_write_targ_mem(priv, a, 0); | 721 | iwl_write_targ_mem(priv, a, 0); |
722 | 722 | ||
723 | iwl_write_prph(priv, IWL50_SCD_DRAM_BASE_ADDR, | 723 | iwl_write_prph(priv, IWL50_SCD_DRAM_BASE_ADDR, |
724 | (priv->shared_phys + | 724 | priv->scd_bc_tbls.dma >> 10); |
725 | offsetof(struct iwl5000_shared, queues_bc_tbls)) >> 10); | ||
726 | iwl_write_prph(priv, IWL50_SCD_QUEUECHAIN_SEL, | 725 | iwl_write_prph(priv, IWL50_SCD_QUEUECHAIN_SEL, |
727 | IWL50_SCD_QUEUECHAIN_SEL_ALL( | 726 | IWL50_SCD_QUEUECHAIN_SEL_ALL(priv->hw_params.max_txq_num)); |
728 | priv->hw_params.max_txq_num)); | ||
729 | iwl_write_prph(priv, IWL50_SCD_AGGR_SEL, 0); | 727 | iwl_write_prph(priv, IWL50_SCD_AGGR_SEL, 0); |
730 | 728 | ||
731 | /* initiate the queues */ | 729 | /* initiate the queues */ |
@@ -788,6 +786,8 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) | |||
788 | } | 786 | } |
789 | 787 | ||
790 | priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues; | 788 | priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues; |
789 | priv->hw_params.scd_bc_tbls_size = | ||
790 | IWL50_NUM_QUEUES * sizeof(struct iwl5000_scd_bc_tbl); | ||
791 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; | 791 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; |
792 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; | 792 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; |
793 | priv->hw_params.max_data_size = IWL50_RTC_DATA_SIZE; | 793 | priv->hw_params.max_data_size = IWL50_RTC_DATA_SIZE; |
@@ -853,36 +853,6 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) | |||
853 | return 0; | 853 | return 0; |
854 | } | 854 | } |
855 | 855 | ||
856 | static int iwl5000_alloc_shared_mem(struct iwl_priv *priv) | ||
857 | { | ||
858 | priv->shared_virt = pci_alloc_consistent(priv->pci_dev, | ||
859 | sizeof(struct iwl5000_shared), | ||
860 | &priv->shared_phys); | ||
861 | if (!priv->shared_virt) | ||
862 | return -ENOMEM; | ||
863 | |||
864 | memset(priv->shared_virt, 0, sizeof(struct iwl5000_shared)); | ||
865 | |||
866 | priv->rb_closed_offset = offsetof(struct iwl5000_shared, rb_closed); | ||
867 | |||
868 | return 0; | ||
869 | } | ||
870 | |||
871 | static void iwl5000_free_shared_mem(struct iwl_priv *priv) | ||
872 | { | ||
873 | if (priv->shared_virt) | ||
874 | pci_free_consistent(priv->pci_dev, | ||
875 | sizeof(struct iwl5000_shared), | ||
876 | priv->shared_virt, | ||
877 | priv->shared_phys); | ||
878 | } | ||
879 | |||
880 | static int iwl5000_shared_mem_rx_idx(struct iwl_priv *priv) | ||
881 | { | ||
882 | struct iwl5000_shared *s = priv->shared_virt; | ||
883 | return le32_to_cpu(s->rb_closed) & 0xFFF; | ||
884 | } | ||
885 | |||
886 | /** | 856 | /** |
887 | * iwl5000_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array | 857 | * iwl5000_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array |
888 | */ | 858 | */ |
@@ -890,7 +860,7 @@ static void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv, | |||
890 | struct iwl_tx_queue *txq, | 860 | struct iwl_tx_queue *txq, |
891 | u16 byte_cnt) | 861 | u16 byte_cnt) |
892 | { | 862 | { |
893 | struct iwl5000_shared *shared_data = priv->shared_virt; | 863 | struct iwl5000_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; |
894 | int write_ptr = txq->q.write_ptr; | 864 | int write_ptr = txq->q.write_ptr; |
895 | int txq_id = txq->q.id; | 865 | int txq_id = txq->q.id; |
896 | u8 sec_ctl = 0; | 866 | u8 sec_ctl = 0; |
@@ -919,17 +889,17 @@ static void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv, | |||
919 | 889 | ||
920 | bc_ent = cpu_to_le16((len & 0xFFF) | (sta_id << 12)); | 890 | bc_ent = cpu_to_le16((len & 0xFFF) | (sta_id << 12)); |
921 | 891 | ||
922 | shared_data->queues_bc_tbls[txq_id].tfd_offset[write_ptr] = bc_ent; | 892 | scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent; |
923 | 893 | ||
924 | if (txq->q.write_ptr < TFD_QUEUE_SIZE_BC_DUP) | 894 | if (txq->q.write_ptr < TFD_QUEUE_SIZE_BC_DUP) |
925 | shared_data->queues_bc_tbls[txq_id]. | 895 | scd_bc_tbl[txq_id]. |
926 | tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent; | 896 | tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent; |
927 | } | 897 | } |
928 | 898 | ||
929 | static void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, | 899 | static void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, |
930 | struct iwl_tx_queue *txq) | 900 | struct iwl_tx_queue *txq) |
931 | { | 901 | { |
932 | struct iwl5000_shared *shared_data = priv->shared_virt; | 902 | struct iwl5000_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; |
933 | int txq_id = txq->q.id; | 903 | int txq_id = txq->q.id; |
934 | int read_ptr = txq->q.read_ptr; | 904 | int read_ptr = txq->q.read_ptr; |
935 | u8 sta_id = 0; | 905 | u8 sta_id = 0; |
@@ -941,11 +911,10 @@ static void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, | |||
941 | sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id; | 911 | sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id; |
942 | 912 | ||
943 | bc_ent = cpu_to_le16(1 | (sta_id << 12)); | 913 | bc_ent = cpu_to_le16(1 | (sta_id << 12)); |
944 | shared_data->queues_bc_tbls[txq_id]. | 914 | scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent; |
945 | tfd_offset[read_ptr] = bc_ent; | ||
946 | 915 | ||
947 | if (txq->q.write_ptr < TFD_QUEUE_SIZE_BC_DUP) | 916 | if (txq->q.write_ptr < TFD_QUEUE_SIZE_BC_DUP) |
948 | shared_data->queues_bc_tbls[txq_id]. | 917 | scd_bc_tbl[txq_id]. |
949 | tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent; | 918 | tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent; |
950 | } | 919 | } |
951 | 920 | ||
@@ -1458,9 +1427,6 @@ static struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = { | |||
1458 | 1427 | ||
1459 | static struct iwl_lib_ops iwl5000_lib = { | 1428 | static struct iwl_lib_ops iwl5000_lib = { |
1460 | .set_hw_params = iwl5000_hw_set_hw_params, | 1429 | .set_hw_params = iwl5000_hw_set_hw_params, |
1461 | .alloc_shared_mem = iwl5000_alloc_shared_mem, | ||
1462 | .free_shared_mem = iwl5000_free_shared_mem, | ||
1463 | .shared_mem_rx_idx = iwl5000_shared_mem_rx_idx, | ||
1464 | .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, | 1430 | .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, |
1465 | .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, | 1431 | .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, |
1466 | .txq_set_sched = iwl5000_txq_set_sched, | 1432 | .txq_set_sched = iwl5000_txq_set_sched, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 35cfa1524c35..8fa4f7a2dc1a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -871,138 +871,6 @@ static void iwl_set_rate(struct iwl_priv *priv) | |||
871 | (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; | 871 | (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; |
872 | } | 872 | } |
873 | 873 | ||
874 | #ifdef CONFIG_IWLAGN_SPECTRUM_MEASUREMENT | ||
875 | |||
876 | #include "iwl-spectrum.h" | ||
877 | |||
878 | #define BEACON_TIME_MASK_LOW 0x00FFFFFF | ||
879 | #define BEACON_TIME_MASK_HIGH 0xFF000000 | ||
880 | #define TIME_UNIT 1024 | ||
881 | |||
882 | /* | ||
883 | * extended beacon time format | ||
884 | * time in usec will be changed into a 32-bit value in 8:24 format | ||
885 | * the high 1 byte is the beacon counts | ||
886 | * the lower 3 bytes is the time in usec within one beacon interval | ||
887 | */ | ||
888 | |||
889 | static u32 iwl_usecs_to_beacons(u32 usec, u32 beacon_interval) | ||
890 | { | ||
891 | u32 quot; | ||
892 | u32 rem; | ||
893 | u32 interval = beacon_interval * 1024; | ||
894 | |||
895 | if (!interval || !usec) | ||
896 | return 0; | ||
897 | |||
898 | quot = (usec / interval) & (BEACON_TIME_MASK_HIGH >> 24); | ||
899 | rem = (usec % interval) & BEACON_TIME_MASK_LOW; | ||
900 | |||
901 | return (quot << 24) + rem; | ||
902 | } | ||
903 | |||
904 | /* base is usually what we get from ucode with each received frame, | ||
905 | * the same as HW timer counter counting down | ||
906 | */ | ||
907 | |||
908 | static __le32 iwl_add_beacon_time(u32 base, u32 addon, u32 beacon_interval) | ||
909 | { | ||
910 | u32 base_low = base & BEACON_TIME_MASK_LOW; | ||
911 | u32 addon_low = addon & BEACON_TIME_MASK_LOW; | ||
912 | u32 interval = beacon_interval * TIME_UNIT; | ||
913 | u32 res = (base & BEACON_TIME_MASK_HIGH) + | ||
914 | (addon & BEACON_TIME_MASK_HIGH); | ||
915 | |||
916 | if (base_low > addon_low) | ||
917 | res += base_low - addon_low; | ||
918 | else if (base_low < addon_low) { | ||
919 | res += interval + base_low - addon_low; | ||
920 | res += (1 << 24); | ||
921 | } else | ||
922 | res += (1 << 24); | ||
923 | |||
924 | return cpu_to_le32(res); | ||
925 | } | ||
926 | |||
927 | static int iwl_get_measurement(struct iwl_priv *priv, | ||
928 | struct ieee80211_measurement_params *params, | ||
929 | u8 type) | ||
930 | { | ||
931 | struct iwl4965_spectrum_cmd spectrum; | ||
932 | struct iwl_rx_packet *res; | ||
933 | struct iwl_host_cmd cmd = { | ||
934 | .id = REPLY_SPECTRUM_MEASUREMENT_CMD, | ||
935 | .data = (void *)&spectrum, | ||
936 | .meta.flags = CMD_WANT_SKB, | ||
937 | }; | ||
938 | u32 add_time = le64_to_cpu(params->start_time); | ||
939 | int rc; | ||
940 | int spectrum_resp_status; | ||
941 | int duration = le16_to_cpu(params->duration); | ||
942 | |||
943 | if (iwl_is_associated(priv)) | ||
944 | add_time = | ||
945 | iwl_usecs_to_beacons( | ||
946 | le64_to_cpu(params->start_time) - priv->last_tsf, | ||
947 | le16_to_cpu(priv->rxon_timing.beacon_interval)); | ||
948 | |||
949 | memset(&spectrum, 0, sizeof(spectrum)); | ||
950 | |||
951 | spectrum.channel_count = cpu_to_le16(1); | ||
952 | spectrum.flags = | ||
953 | RXON_FLG_TSF2HOST_MSK | RXON_FLG_ANT_A_MSK | RXON_FLG_DIS_DIV_MSK; | ||
954 | spectrum.filter_flags = MEASUREMENT_FILTER_FLAG; | ||
955 | cmd.len = sizeof(spectrum); | ||
956 | spectrum.len = cpu_to_le16(cmd.len - sizeof(spectrum.len)); | ||
957 | |||
958 | if (iwl_is_associated(priv)) | ||
959 | spectrum.start_time = | ||
960 | iwl_add_beacon_time(priv->last_beacon_time, | ||
961 | add_time, | ||
962 | le16_to_cpu(priv->rxon_timing.beacon_interval)); | ||
963 | else | ||
964 | spectrum.start_time = 0; | ||
965 | |||
966 | spectrum.channels[0].duration = cpu_to_le32(duration * TIME_UNIT); | ||
967 | spectrum.channels[0].channel = params->channel; | ||
968 | spectrum.channels[0].type = type; | ||
969 | if (priv->active_rxon.flags & RXON_FLG_BAND_24G_MSK) | ||
970 | spectrum.flags |= RXON_FLG_BAND_24G_MSK | | ||
971 | RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK; | ||
972 | |||
973 | rc = iwl_send_cmd_sync(priv, &cmd); | ||
974 | if (rc) | ||
975 | return rc; | ||
976 | |||
977 | res = (struct iwl_rx_packet *)cmd.meta.u.skb->data; | ||
978 | if (res->hdr.flags & IWL_CMD_FAILED_MSK) { | ||
979 | IWL_ERROR("Bad return from REPLY_RX_ON_ASSOC command\n"); | ||
980 | rc = -EIO; | ||
981 | } | ||
982 | |||
983 | spectrum_resp_status = le16_to_cpu(res->u.spectrum.status); | ||
984 | switch (spectrum_resp_status) { | ||
985 | case 0: /* Command will be handled */ | ||
986 | if (res->u.spectrum.id != 0xff) { | ||
987 | IWL_DEBUG_INFO | ||
988 | ("Replaced existing measurement: %d\n", | ||
989 | res->u.spectrum.id); | ||
990 | priv->measurement_status &= ~MEASUREMENT_READY; | ||
991 | } | ||
992 | priv->measurement_status |= MEASUREMENT_ACTIVE; | ||
993 | rc = 0; | ||
994 | break; | ||
995 | |||
996 | case 1: /* Command will not be handled */ | ||
997 | rc = -EAGAIN; | ||
998 | break; | ||
999 | } | ||
1000 | |||
1001 | dev_kfree_skb_any(cmd.meta.u.skb); | ||
1002 | |||
1003 | return rc; | ||
1004 | } | ||
1005 | #endif | ||
1006 | 874 | ||
1007 | /****************************************************************************** | 875 | /****************************************************************************** |
1008 | * | 876 | * |
@@ -1072,24 +940,6 @@ static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
1072 | priv->staging_rxon.channel = csa->channel; | 940 | priv->staging_rxon.channel = csa->channel; |
1073 | } | 941 | } |
1074 | 942 | ||
1075 | static void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, | ||
1076 | struct iwl_rx_mem_buffer *rxb) | ||
1077 | { | ||
1078 | #ifdef CONFIG_IWLAGN_SPECTRUM_MEASUREMENT | ||
1079 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | ||
1080 | struct iwl4965_spectrum_notification *report = &(pkt->u.spectrum_notif); | ||
1081 | |||
1082 | if (!report->state) { | ||
1083 | IWL_DEBUG(IWL_DL_11H, | ||
1084 | "Spectrum Measure Notification: Start\n"); | ||
1085 | return; | ||
1086 | } | ||
1087 | |||
1088 | memcpy(&priv->measure_report, report, sizeof(*report)); | ||
1089 | priv->measurement_status |= MEASUREMENT_READY; | ||
1090 | #endif | ||
1091 | } | ||
1092 | |||
1093 | static void iwl_rx_pm_sleep_notif(struct iwl_priv *priv, | 943 | static void iwl_rx_pm_sleep_notif(struct iwl_priv *priv, |
1094 | struct iwl_rx_mem_buffer *rxb) | 944 | struct iwl_rx_mem_buffer *rxb) |
1095 | { | 945 | { |
@@ -1298,8 +1148,6 @@ static void iwl_setup_rx_handlers(struct iwl_priv *priv) | |||
1298 | priv->rx_handlers[REPLY_ALIVE] = iwl_rx_reply_alive; | 1148 | priv->rx_handlers[REPLY_ALIVE] = iwl_rx_reply_alive; |
1299 | priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error; | 1149 | priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error; |
1300 | priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa; | 1150 | priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa; |
1301 | priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] = | ||
1302 | iwl_rx_spectrum_measure_notif; | ||
1303 | priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif; | 1151 | priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif; |
1304 | priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] = | 1152 | priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] = |
1305 | iwl_rx_pm_debug_statistics_notif; | 1153 | iwl_rx_pm_debug_statistics_notif; |
@@ -1313,6 +1161,7 @@ static void iwl_setup_rx_handlers(struct iwl_priv *priv) | |||
1313 | priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl_rx_statistics; | 1161 | priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl_rx_statistics; |
1314 | priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl_rx_statistics; | 1162 | priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl_rx_statistics; |
1315 | 1163 | ||
1164 | iwl_setup_spectrum_handlers(priv); | ||
1316 | iwl_setup_rx_scan_handlers(priv); | 1165 | iwl_setup_rx_scan_handlers(priv); |
1317 | 1166 | ||
1318 | /* status change handler */ | 1167 | /* status change handler */ |
@@ -1359,7 +1208,7 @@ void iwl_rx_handle(struct iwl_priv *priv) | |||
1359 | 1208 | ||
1360 | /* uCode's read index (stored in shared DRAM) indicates the last Rx | 1209 | /* uCode's read index (stored in shared DRAM) indicates the last Rx |
1361 | * buffer that the driver may process (last buffer filled by ucode). */ | 1210 | * buffer that the driver may process (last buffer filled by ucode). */ |
1362 | r = priv->cfg->ops->lib->shared_mem_rx_idx(priv); | 1211 | r = le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF; |
1363 | i = rxq->read; | 1212 | i = rxq->read; |
1364 | 1213 | ||
1365 | /* Rx interrupt, but nothing sent from uCode */ | 1214 | /* Rx interrupt, but nothing sent from uCode */ |
@@ -2002,6 +1851,10 @@ static int iwl_read_ucode(struct iwl_priv *priv) | |||
2002 | return ret; | 1851 | return ret; |
2003 | } | 1852 | } |
2004 | 1853 | ||
1854 | /* temporary */ | ||
1855 | static int iwl_mac_beacon_update(struct ieee80211_hw *hw, | ||
1856 | struct sk_buff *skb); | ||
1857 | |||
2005 | /** | 1858 | /** |
2006 | * iwl_alive_start - called after REPLY_ALIVE notification received | 1859 | * iwl_alive_start - called after REPLY_ALIVE notification received |
2007 | * from protocol/runtime uCode (initialization uCode's | 1860 | * from protocol/runtime uCode (initialization uCode's |
@@ -2084,6 +1937,15 @@ static void iwl_alive_start(struct iwl_priv *priv) | |||
2084 | 1937 | ||
2085 | iwl_power_update_mode(priv, 1); | 1938 | iwl_power_update_mode(priv, 1); |
2086 | 1939 | ||
1940 | /* reassociate for ADHOC mode */ | ||
1941 | if (priv->vif && (priv->iw_mode == NL80211_IFTYPE_ADHOC)) { | ||
1942 | struct sk_buff *beacon = ieee80211_beacon_get(priv->hw, | ||
1943 | priv->vif); | ||
1944 | if (beacon) | ||
1945 | iwl_mac_beacon_update(priv->hw, beacon); | ||
1946 | } | ||
1947 | |||
1948 | |||
2087 | if (test_and_clear_bit(STATUS_MODE_PENDING, &priv->status)) | 1949 | if (test_and_clear_bit(STATUS_MODE_PENDING, &priv->status)) |
2088 | iwl_set_mode(priv, priv->iw_mode); | 1950 | iwl_set_mode(priv, priv->iw_mode); |
2089 | 1951 | ||
@@ -2183,8 +2045,6 @@ static void __iwl_down(struct iwl_priv *priv) | |||
2183 | priv->cfg->ops->lib->apm_ops.stop(priv); | 2045 | priv->cfg->ops->lib->apm_ops.stop(priv); |
2184 | else | 2046 | else |
2185 | priv->cfg->ops->lib->apm_ops.reset(priv); | 2047 | priv->cfg->ops->lib->apm_ops.reset(priv); |
2186 | priv->cfg->ops->lib->free_shared_mem(priv); | ||
2187 | |||
2188 | exit: | 2048 | exit: |
2189 | memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp)); | 2049 | memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp)); |
2190 | 2050 | ||
@@ -2237,12 +2097,6 @@ static int __iwl_up(struct iwl_priv *priv) | |||
2237 | 2097 | ||
2238 | iwl_write32(priv, CSR_INT, 0xFFFFFFFF); | 2098 | iwl_write32(priv, CSR_INT, 0xFFFFFFFF); |
2239 | 2099 | ||
2240 | ret = priv->cfg->ops->lib->alloc_shared_mem(priv); | ||
2241 | if (ret) { | ||
2242 | IWL_ERROR("Unable to allocate shared memory\n"); | ||
2243 | return ret; | ||
2244 | } | ||
2245 | |||
2246 | ret = iwl_hw_nic_init(priv); | 2100 | ret = iwl_hw_nic_init(priv); |
2247 | if (ret) { | 2101 | if (ret) { |
2248 | IWL_ERROR("Unable to init nic\n"); | 2102 | IWL_ERROR("Unable to init nic\n"); |
@@ -2930,8 +2784,6 @@ static void iwl_config_ap(struct iwl_priv *priv) | |||
2930 | * clear sta table, add BCAST sta... */ | 2784 | * clear sta table, add BCAST sta... */ |
2931 | } | 2785 | } |
2932 | 2786 | ||
2933 | /* temporary */ | ||
2934 | static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb); | ||
2935 | 2787 | ||
2936 | static int iwl_mac_config_interface(struct ieee80211_hw *hw, | 2788 | static int iwl_mac_config_interface(struct ieee80211_hw *hw, |
2937 | struct ieee80211_vif *vif, | 2789 | struct ieee80211_vif *vif, |
@@ -2953,7 +2805,9 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, | |||
2953 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); | 2805 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); |
2954 | if (!beacon) | 2806 | if (!beacon) |
2955 | return -ENOMEM; | 2807 | return -ENOMEM; |
2808 | mutex_lock(&priv->mutex); | ||
2956 | rc = iwl_mac_beacon_update(hw, beacon); | 2809 | rc = iwl_mac_beacon_update(hw, beacon); |
2810 | mutex_unlock(&priv->mutex); | ||
2957 | if (rc) | 2811 | if (rc) |
2958 | return rc; | 2812 | return rc; |
2959 | } | 2813 | } |
@@ -3529,18 +3383,15 @@ static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
3529 | unsigned long flags; | 3383 | unsigned long flags; |
3530 | __le64 timestamp; | 3384 | __le64 timestamp; |
3531 | 3385 | ||
3532 | mutex_lock(&priv->mutex); | ||
3533 | IWL_DEBUG_MAC80211("enter\n"); | 3386 | IWL_DEBUG_MAC80211("enter\n"); |
3534 | 3387 | ||
3535 | if (!iwl_is_ready_rf(priv)) { | 3388 | if (!iwl_is_ready_rf(priv)) { |
3536 | IWL_DEBUG_MAC80211("leave - RF not ready\n"); | 3389 | IWL_DEBUG_MAC80211("leave - RF not ready\n"); |
3537 | mutex_unlock(&priv->mutex); | ||
3538 | return -EIO; | 3390 | return -EIO; |
3539 | } | 3391 | } |
3540 | 3392 | ||
3541 | if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { | 3393 | if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { |
3542 | IWL_DEBUG_MAC80211("leave - not IBSS\n"); | 3394 | IWL_DEBUG_MAC80211("leave - not IBSS\n"); |
3543 | mutex_unlock(&priv->mutex); | ||
3544 | return -EIO; | 3395 | return -EIO; |
3545 | } | 3396 | } |
3546 | 3397 | ||
@@ -3562,7 +3413,6 @@ static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
3562 | 3413 | ||
3563 | iwl_post_associate(priv); | 3414 | iwl_post_associate(priv); |
3564 | 3415 | ||
3565 | mutex_unlock(&priv->mutex); | ||
3566 | 3416 | ||
3567 | return 0; | 3417 | return 0; |
3568 | } | 3418 | } |
@@ -3766,79 +3616,6 @@ static ssize_t store_filter_flags(struct device *d, | |||
3766 | static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags, | 3616 | static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags, |
3767 | store_filter_flags); | 3617 | store_filter_flags); |
3768 | 3618 | ||
3769 | #ifdef CONFIG_IWLAGN_SPECTRUM_MEASUREMENT | ||
3770 | |||
3771 | static ssize_t show_measurement(struct device *d, | ||
3772 | struct device_attribute *attr, char *buf) | ||
3773 | { | ||
3774 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3775 | struct iwl4965_spectrum_notification measure_report; | ||
3776 | u32 size = sizeof(measure_report), len = 0, ofs = 0; | ||
3777 | u8 *data = (u8 *)&measure_report; | ||
3778 | unsigned long flags; | ||
3779 | |||
3780 | spin_lock_irqsave(&priv->lock, flags); | ||
3781 | if (!(priv->measurement_status & MEASUREMENT_READY)) { | ||
3782 | spin_unlock_irqrestore(&priv->lock, flags); | ||
3783 | return 0; | ||
3784 | } | ||
3785 | memcpy(&measure_report, &priv->measure_report, size); | ||
3786 | priv->measurement_status = 0; | ||
3787 | spin_unlock_irqrestore(&priv->lock, flags); | ||
3788 | |||
3789 | while (size && (PAGE_SIZE - len)) { | ||
3790 | hex_dump_to_buffer(data + ofs, size, 16, 1, buf + len, | ||
3791 | PAGE_SIZE - len, 1); | ||
3792 | len = strlen(buf); | ||
3793 | if (PAGE_SIZE - len) | ||
3794 | buf[len++] = '\n'; | ||
3795 | |||
3796 | ofs += 16; | ||
3797 | size -= min(size, 16U); | ||
3798 | } | ||
3799 | |||
3800 | return len; | ||
3801 | } | ||
3802 | |||
3803 | static ssize_t store_measurement(struct device *d, | ||
3804 | struct device_attribute *attr, | ||
3805 | const char *buf, size_t count) | ||
3806 | { | ||
3807 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3808 | struct ieee80211_measurement_params params = { | ||
3809 | .channel = le16_to_cpu(priv->active_rxon.channel), | ||
3810 | .start_time = cpu_to_le64(priv->last_tsf), | ||
3811 | .duration = cpu_to_le16(1), | ||
3812 | }; | ||
3813 | u8 type = IWL_MEASURE_BASIC; | ||
3814 | u8 buffer[32]; | ||
3815 | u8 channel; | ||
3816 | |||
3817 | if (count) { | ||
3818 | char *p = buffer; | ||
3819 | strncpy(buffer, buf, min(sizeof(buffer), count)); | ||
3820 | channel = simple_strtoul(p, NULL, 0); | ||
3821 | if (channel) | ||
3822 | params.channel = channel; | ||
3823 | |||
3824 | p = buffer; | ||
3825 | while (*p && *p != ' ') | ||
3826 | p++; | ||
3827 | if (*p) | ||
3828 | type = simple_strtoul(p + 1, NULL, 0); | ||
3829 | } | ||
3830 | |||
3831 | IWL_DEBUG_INFO("Invoking measurement of type %d on " | ||
3832 | "channel %d (for '%s')\n", type, params.channel, buf); | ||
3833 | iwl_get_measurement(priv, ¶ms, type); | ||
3834 | |||
3835 | return count; | ||
3836 | } | ||
3837 | |||
3838 | static DEVICE_ATTR(measurement, S_IRUSR | S_IWUSR, | ||
3839 | show_measurement, store_measurement); | ||
3840 | #endif /* CONFIG_IWLAGN_SPECTRUM_MEASUREMENT */ | ||
3841 | |||
3842 | static ssize_t store_retry_rate(struct device *d, | 3619 | static ssize_t store_retry_rate(struct device *d, |
3843 | struct device_attribute *attr, | 3620 | struct device_attribute *attr, |
3844 | const char *buf, size_t count) | 3621 | const char *buf, size_t count) |
@@ -4091,9 +3868,6 @@ static struct attribute *iwl_sysfs_entries[] = { | |||
4091 | &dev_attr_channels.attr, | 3868 | &dev_attr_channels.attr, |
4092 | &dev_attr_flags.attr, | 3869 | &dev_attr_flags.attr, |
4093 | &dev_attr_filter_flags.attr, | 3870 | &dev_attr_filter_flags.attr, |
4094 | #ifdef CONFIG_IWLAGN_SPECTRUM_MEASUREMENT | ||
4095 | &dev_attr_measurement.attr, | ||
4096 | #endif | ||
4097 | &dev_attr_power_level.attr, | 3871 | &dev_attr_power_level.attr, |
4098 | &dev_attr_retry_rate.attr, | 3872 | &dev_attr_retry_rate.attr, |
4099 | &dev_attr_statistics.attr, | 3873 | &dev_attr_statistics.attr, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 8aade00e165a..1fe83d45443a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h | |||
@@ -213,10 +213,11 @@ struct iwl_cmd_header { | |||
213 | } __attribute__ ((packed)); | 213 | } __attribute__ ((packed)); |
214 | 214 | ||
215 | /** | 215 | /** |
216 | * 4965 rate_n_flags bit fields | 216 | * iwlagn rate_n_flags bit fields |
217 | * | 217 | * |
218 | * rate_n_flags format is used in following 4965 commands: | 218 | * rate_n_flags format is used in following iwlagn commands: |
219 | * REPLY_RX (response only) | 219 | * REPLY_RX (response only) |
220 | * REPLY_RX_MPDU (response only) | ||
220 | * REPLY_TX (both command and response) | 221 | * REPLY_TX (both command and response) |
221 | * REPLY_TX_LINK_QUALITY_CMD | 222 | * REPLY_TX_LINK_QUALITY_CMD |
222 | * | 223 | * |
@@ -230,8 +231,9 @@ struct iwl_cmd_header { | |||
230 | * 6) 54 Mbps | 231 | * 6) 54 Mbps |
231 | * 7) 60 Mbps | 232 | * 7) 60 Mbps |
232 | * | 233 | * |
233 | * 3: 0) Single stream (SISO) | 234 | * 4-3: 0) Single stream (SISO) |
234 | * 1) Dual stream (MIMO) | 235 | * 1) Dual stream (MIMO) |
236 | * 2) Triple stream (MIMO) | ||
235 | * | 237 | * |
236 | * 5: Value of 0x20 in bits 7:0 indicates 6 Mbps FAT duplicate data | 238 | * 5: Value of 0x20 in bits 7:0 indicates 6 Mbps FAT duplicate data |
237 | * | 239 | * |
@@ -252,8 +254,8 @@ struct iwl_cmd_header { | |||
252 | * 110) 11 Mbps | 254 | * 110) 11 Mbps |
253 | */ | 255 | */ |
254 | #define RATE_MCS_CODE_MSK 0x7 | 256 | #define RATE_MCS_CODE_MSK 0x7 |
255 | #define RATE_MCS_MIMO_POS 3 | 257 | #define RATE_MCS_SPATIAL_POS 3 |
256 | #define RATE_MCS_MIMO_MSK 0x8 | 258 | #define RATE_MCS_SPATIAL_MSK 0x18 |
257 | #define RATE_MCS_HT_DUP_POS 5 | 259 | #define RATE_MCS_HT_DUP_POS 5 |
258 | #define RATE_MCS_HT_DUP_MSK 0x20 | 260 | #define RATE_MCS_HT_DUP_MSK 0x20 |
259 | 261 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 8eb02031e797..8bd4d087d4e2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -30,10 +30,9 @@ | |||
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <net/mac80211.h> | 31 | #include <net/mac80211.h> |
32 | 32 | ||
33 | struct iwl_priv; /* FIXME: remove */ | ||
34 | #include "iwl-debug.h" | ||
35 | #include "iwl-eeprom.h" | 33 | #include "iwl-eeprom.h" |
36 | #include "iwl-dev.h" /* FIXME: remove */ | 34 | #include "iwl-dev.h" /* FIXME: remove */ |
35 | #include "iwl-debug.h" | ||
37 | #include "iwl-core.h" | 36 | #include "iwl-core.h" |
38 | #include "iwl-io.h" | 37 | #include "iwl-io.h" |
39 | #include "iwl-rfkill.h" | 38 | #include "iwl-rfkill.h" |
@@ -190,52 +189,6 @@ void iwl_hw_detect(struct iwl_priv *priv) | |||
190 | } | 189 | } |
191 | EXPORT_SYMBOL(iwl_hw_detect); | 190 | EXPORT_SYMBOL(iwl_hw_detect); |
192 | 191 | ||
193 | /* Tell nic where to find the "keep warm" buffer */ | ||
194 | int iwl_kw_init(struct iwl_priv *priv) | ||
195 | { | ||
196 | unsigned long flags; | ||
197 | int ret; | ||
198 | |||
199 | spin_lock_irqsave(&priv->lock, flags); | ||
200 | ret = iwl_grab_nic_access(priv); | ||
201 | if (ret) | ||
202 | goto out; | ||
203 | |||
204 | iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, | ||
205 | priv->kw.dma_addr >> 4); | ||
206 | iwl_release_nic_access(priv); | ||
207 | out: | ||
208 | spin_unlock_irqrestore(&priv->lock, flags); | ||
209 | return ret; | ||
210 | } | ||
211 | |||
212 | int iwl_kw_alloc(struct iwl_priv *priv) | ||
213 | { | ||
214 | struct pci_dev *dev = priv->pci_dev; | ||
215 | struct iwl_kw *kw = &priv->kw; | ||
216 | |||
217 | kw->size = IWL_KW_SIZE; | ||
218 | kw->v_addr = pci_alloc_consistent(dev, kw->size, &kw->dma_addr); | ||
219 | if (!kw->v_addr) | ||
220 | return -ENOMEM; | ||
221 | |||
222 | return 0; | ||
223 | } | ||
224 | |||
225 | /** | ||
226 | * iwl_kw_free - Free the "keep warm" buffer | ||
227 | */ | ||
228 | void iwl_kw_free(struct iwl_priv *priv) | ||
229 | { | ||
230 | struct pci_dev *dev = priv->pci_dev; | ||
231 | struct iwl_kw *kw = &priv->kw; | ||
232 | |||
233 | if (kw->v_addr) { | ||
234 | pci_free_consistent(dev, kw->size, kw->v_addr, kw->dma_addr); | ||
235 | memset(kw, 0, sizeof(*kw)); | ||
236 | } | ||
237 | } | ||
238 | |||
239 | int iwl_hw_nic_init(struct iwl_priv *priv) | 192 | int iwl_hw_nic_init(struct iwl_priv *priv) |
240 | { | 193 | { |
241 | unsigned long flags; | 194 | unsigned long flags; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 10f07f6e1737..ff966b8a0c6d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -102,10 +102,6 @@ struct iwl_hcmd_utils_ops { | |||
102 | struct iwl_lib_ops { | 102 | struct iwl_lib_ops { |
103 | /* set hw dependent parameters */ | 103 | /* set hw dependent parameters */ |
104 | int (*set_hw_params)(struct iwl_priv *priv); | 104 | int (*set_hw_params)(struct iwl_priv *priv); |
105 | /* ucode shared memory */ | ||
106 | int (*alloc_shared_mem)(struct iwl_priv *priv); | ||
107 | void (*free_shared_mem)(struct iwl_priv *priv); | ||
108 | int (*shared_mem_rx_idx)(struct iwl_priv *priv); | ||
109 | /* Handling TX */ | 105 | /* Handling TX */ |
110 | void (*txq_update_byte_cnt_tbl)(struct iwl_priv *priv, | 106 | void (*txq_update_byte_cnt_tbl)(struct iwl_priv *priv, |
111 | struct iwl_tx_queue *txq, | 107 | struct iwl_tx_queue *txq, |
@@ -198,10 +194,6 @@ int iwl_setup_mac(struct iwl_priv *priv); | |||
198 | int iwl_set_hw_params(struct iwl_priv *priv); | 194 | int iwl_set_hw_params(struct iwl_priv *priv); |
199 | int iwl_init_drv(struct iwl_priv *priv); | 195 | int iwl_init_drv(struct iwl_priv *priv); |
200 | void iwl_uninit_drv(struct iwl_priv *priv); | 196 | void iwl_uninit_drv(struct iwl_priv *priv); |
201 | /* "keep warm" functions */ | ||
202 | int iwl_kw_init(struct iwl_priv *priv); | ||
203 | int iwl_kw_alloc(struct iwl_priv *priv); | ||
204 | void iwl_kw_free(struct iwl_priv *priv); | ||
205 | 197 | ||
206 | /***************************************************** | 198 | /***************************************************** |
207 | * RX | 199 | * RX |
@@ -297,6 +289,14 @@ int iwl_send_calib_results(struct iwl_priv *priv); | |||
297 | int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len); | 289 | int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len); |
298 | void iwl_calib_free_results(struct iwl_priv *priv); | 290 | void iwl_calib_free_results(struct iwl_priv *priv); |
299 | 291 | ||
292 | /******************************************************************************* | ||
293 | * Spectrum Measureemtns in iwl-spectrum.c | ||
294 | ******************************************************************************/ | ||
295 | #ifdef CONFIG_IWLAGN_SPECTRUM_MEASUREMENT | ||
296 | void iwl_setup_spectrum_handlers(struct iwl_priv *priv); | ||
297 | #else | ||
298 | static inline void iwl_setup_spectrum_handlers(struct iwl_priv *priv) {} | ||
299 | #endif | ||
300 | /***************************************************** | 300 | /***************************************************** |
301 | * S e n d i n g H o s t C o m m a n d s * | 301 | * S e n d i n g H o s t C o m m a n d s * |
302 | *****************************************************/ | 302 | *****************************************************/ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 84b7772809e3..0e79a6ab4c81 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h | |||
@@ -40,6 +40,13 @@ do { if ((priv->debug_level & (level)) && net_ratelimit()) \ | |||
40 | dev_printk(KERN_ERR, &(priv->hw->wiphy->dev), "%c %s " fmt, \ | 40 | dev_printk(KERN_ERR, &(priv->hw->wiphy->dev), "%c %s " fmt, \ |
41 | in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0) | 41 | in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0) |
42 | 42 | ||
43 | #define iwl_print_hex_dump(priv, level, p, len) \ | ||
44 | do { \ | ||
45 | if (priv->debug_level & level) \ | ||
46 | print_hex_dump(KERN_DEBUG, "iwl data: ", \ | ||
47 | DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \ | ||
48 | } while (0) | ||
49 | |||
43 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 50 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
44 | struct iwl_debugfs { | 51 | struct iwl_debugfs { |
45 | const char *name; | 52 | const char *name; |
@@ -70,6 +77,9 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv); | |||
70 | #else | 77 | #else |
71 | #define IWL_DEBUG(level, fmt, args...) | 78 | #define IWL_DEBUG(level, fmt, args...) |
72 | #define IWL_DEBUG_LIMIT(level, fmt, args...) | 79 | #define IWL_DEBUG_LIMIT(level, fmt, args...) |
80 | static inline void iwl_print_hex_dump(struct iwl_priv *priv, int level, | ||
81 | void *p, u32 len) | ||
82 | {} | ||
73 | #endif /* CONFIG_IWLWIFI_DEBUG */ | 83 | #endif /* CONFIG_IWLWIFI_DEBUG */ |
74 | 84 | ||
75 | 85 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index d509aed5567a..bd3df55e4953 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -301,7 +301,6 @@ struct iwl_host_cmd { | |||
301 | 301 | ||
302 | /** | 302 | /** |
303 | * struct iwl_rx_queue - Rx queue | 303 | * struct iwl_rx_queue - Rx queue |
304 | * @processed: Internal index to last handled Rx packet | ||
305 | * @read: Shared index to newest available Rx buffer | 304 | * @read: Shared index to newest available Rx buffer |
306 | * @write: Shared index to oldest written Rx packet | 305 | * @write: Shared index to oldest written Rx packet |
307 | * @free_count: Number of pre-allocated buffers in rx_free | 306 | * @free_count: Number of pre-allocated buffers in rx_free |
@@ -316,13 +315,14 @@ struct iwl_rx_queue { | |||
316 | dma_addr_t dma_addr; | 315 | dma_addr_t dma_addr; |
317 | struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS]; | 316 | struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS]; |
318 | struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE]; | 317 | struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE]; |
319 | u32 processed; | ||
320 | u32 read; | 318 | u32 read; |
321 | u32 write; | 319 | u32 write; |
322 | u32 free_count; | 320 | u32 free_count; |
323 | struct list_head rx_free; | 321 | struct list_head rx_free; |
324 | struct list_head rx_used; | 322 | struct list_head rx_used; |
325 | int need_update; | 323 | int need_update; |
324 | struct iwl_rb_status *rb_stts; | ||
325 | dma_addr_t rb_stts_dma; | ||
326 | spinlock_t lock; | 326 | spinlock_t lock; |
327 | }; | 327 | }; |
328 | 328 | ||
@@ -507,6 +507,7 @@ struct iwl_sensitivity_ranges { | |||
507 | /** | 507 | /** |
508 | * struct iwl_hw_params | 508 | * struct iwl_hw_params |
509 | * @max_txq_num: Max # Tx queues supported | 509 | * @max_txq_num: Max # Tx queues supported |
510 | * @scd_bc_tbls_size: size of scheduler byte count tables | ||
510 | * @tx/rx_chains_num: Number of TX/RX chains | 511 | * @tx/rx_chains_num: Number of TX/RX chains |
511 | * @valid_tx/rx_ant: usable antennas | 512 | * @valid_tx/rx_ant: usable antennas |
512 | * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2) | 513 | * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2) |
@@ -524,6 +525,7 @@ struct iwl_sensitivity_ranges { | |||
524 | */ | 525 | */ |
525 | struct iwl_hw_params { | 526 | struct iwl_hw_params { |
526 | u16 max_txq_num; | 527 | u16 max_txq_num; |
528 | u16 scd_bc_tbls_size; | ||
527 | u8 tx_chains_num; | 529 | u8 tx_chains_num; |
528 | u8 rx_chains_num; | 530 | u8 rx_chains_num; |
529 | u8 valid_tx_ant; | 531 | u8 valid_tx_ant; |
@@ -605,13 +607,9 @@ static inline u8 get_cmd_index(struct iwl_queue *q, u32 index, int is_huge) | |||
605 | struct iwl_priv; | 607 | struct iwl_priv; |
606 | 608 | ||
607 | 609 | ||
608 | /* Structures, enum, and defines specific to the 4965 */ | 610 | struct iwl_dma_ptr { |
609 | 611 | dma_addr_t dma; | |
610 | #define IWL_KW_SIZE 0x1000 /*4k */ | 612 | void *addr; |
611 | |||
612 | struct iwl_kw { | ||
613 | dma_addr_t dma_addr; | ||
614 | void *v_addr; | ||
615 | size_t size; | 613 | size_t size; |
616 | }; | 614 | }; |
617 | 615 | ||
@@ -907,7 +905,9 @@ struct iwl_priv { | |||
907 | struct iwl_rx_queue rxq; | 905 | struct iwl_rx_queue rxq; |
908 | struct iwl_tx_queue txq[IWL_MAX_NUM_QUEUES]; | 906 | struct iwl_tx_queue txq[IWL_MAX_NUM_QUEUES]; |
909 | unsigned long txq_ctx_active_msk; | 907 | unsigned long txq_ctx_active_msk; |
910 | struct iwl_kw kw; /* keep warm address */ | 908 | struct iwl_dma_ptr kw; /* keep warm address */ |
909 | struct iwl_dma_ptr scd_bc_tbls; | ||
910 | |||
911 | u32 scd_base_addr; /* scheduler sram base address */ | 911 | u32 scd_base_addr; /* scheduler sram base address */ |
912 | 912 | ||
913 | unsigned long status; | 913 | unsigned long status; |
@@ -967,11 +967,7 @@ struct iwl_priv { | |||
967 | struct ieee80211_vif *vif; | 967 | struct ieee80211_vif *vif; |
968 | 968 | ||
969 | struct iwl_hw_params hw_params; | 969 | struct iwl_hw_params hw_params; |
970 | /* driver/uCode shared Tx Byte Counts and Rx status */ | 970 | |
971 | void *shared_virt; | ||
972 | int rb_closed_offset; | ||
973 | /* Physical Pointer to Tx Byte Counts and Rx status */ | ||
974 | dma_addr_t shared_phys; | ||
975 | 971 | ||
976 | /* Current association information needed to configure the | 972 | /* Current association information needed to configure the |
977 | * hardware */ | 973 | * hardware */ |
@@ -1093,23 +1089,6 @@ static inline int is_channel_ibss(const struct iwl_channel_info *ch) | |||
1093 | return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0; | 1089 | return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0; |
1094 | } | 1090 | } |
1095 | 1091 | ||
1096 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1097 | static inline void iwl_print_hex_dump(struct iwl_priv *priv, int level, | ||
1098 | void *p, u32 len) | ||
1099 | { | ||
1100 | if (!(priv->debug_level & level)) | ||
1101 | return; | ||
1102 | |||
1103 | print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1, | ||
1104 | p, len, 1); | ||
1105 | } | ||
1106 | #else | ||
1107 | static inline void iwl_print_hex_dump(struct iwl_priv *priv, int level, | ||
1108 | void *p, u32 len) | ||
1109 | { | ||
1110 | } | ||
1111 | #endif | ||
1112 | |||
1113 | extern const struct iwl_channel_info *iwl_get_channel_info( | 1092 | extern const struct iwl_channel_info *iwl_get_channel_info( |
1114 | const struct iwl_priv *priv, enum ieee80211_band band, u16 channel); | 1093 | const struct iwl_priv *priv, enum ieee80211_band band, u16 channel); |
1115 | 1094 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h index 97e2cf41258d..e46300c28a8f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/iwlwifi/iwl-fh.h | |||
@@ -266,6 +266,8 @@ | |||
266 | #define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_NO_INT_VAL (0x00000000) | 266 | #define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_NO_INT_VAL (0x00000000) |
267 | #define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL (0x00001000) | 267 | #define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL (0x00001000) |
268 | 268 | ||
269 | #define FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME (0x00008000) | ||
270 | |||
269 | 271 | ||
270 | /** | 272 | /** |
271 | * Rx Shared Status Registers (RSSR) | 273 | * Rx Shared Status Registers (RSSR) |
@@ -403,5 +405,86 @@ | |||
403 | #define TFD_QUEUE_SIZE_BC_DUP (64) | 405 | #define TFD_QUEUE_SIZE_BC_DUP (64) |
404 | #define TFD_QUEUE_BC_SIZE (TFD_QUEUE_SIZE_MAX + TFD_QUEUE_SIZE_BC_DUP) | 406 | #define TFD_QUEUE_BC_SIZE (TFD_QUEUE_SIZE_MAX + TFD_QUEUE_SIZE_BC_DUP) |
405 | 407 | ||
408 | /** | ||
409 | * struct iwl_rb_status - reseve buffer status | ||
410 | * host memory mapped FH registers | ||
411 | * @closed_rb_num [0:11] - Indicates the index of the RB which was closed | ||
412 | * @closed_fr_num [0:11] - Indicates the index of the RX Frame which was closed | ||
413 | * @finished_rb_num [0:11] - Indicates the index of the current RB | ||
414 | * in which the last frame was written to | ||
415 | * @finished_fr_num [0:11] - Indicates the index of the RX Frame | ||
416 | * which was transfered | ||
417 | */ | ||
418 | struct iwl_rb_status { | ||
419 | __le16 closed_rb_num; | ||
420 | __le16 closed_fr_num; | ||
421 | __le16 finished_rb_num; | ||
422 | __le16 finished_fr_nam; | ||
423 | } __attribute__ ((packed)); | ||
424 | |||
425 | |||
426 | |||
427 | #define IWL_TX_DMA_MASK DMA_BIT_MASK(36) | ||
428 | |||
429 | #define IWL_NUM_OF_TBS 20 | ||
430 | |||
431 | static inline u8 iwl_get_dma_hi_addr(dma_addr_t addr) | ||
432 | { | ||
433 | return (sizeof(addr) > sizeof(u32) ? (addr >> 16) >> 16 : 0) & 0xF; | ||
434 | } | ||
435 | /** | ||
436 | * struct iwl_tfd_tb transmit buffer descriptor within transmit frame descriptor | ||
437 | * | ||
438 | * This structure contains dma address and length of transmission address | ||
439 | * | ||
440 | * @lo: low [31:0] portion of the dma address of TX buffer | ||
441 | * every even is unaligned on 16 bit boundary | ||
442 | * @hi_n_len 0-3 [35:32] portion of dma | ||
443 | * 4-16 length of the tx buffer | ||
444 | */ | ||
445 | struct iwl_tfd_tb { | ||
446 | __le32 lo; | ||
447 | __le16 hi_n_len; | ||
448 | } __attribute__((packed)); | ||
449 | |||
450 | /** | ||
451 | * struct iwl_tfd | ||
452 | * | ||
453 | * Transmit Frame Descriptor (TFD) | ||
454 | * | ||
455 | * @ __reserved1[3] reserved | ||
456 | * @ num_tbs 0-5 number of active tbs | ||
457 | * 6-7 padding (not used) | ||
458 | * @ tbs[20] transmit frame buffer descriptors | ||
459 | * @ __pad padding | ||
460 | * | ||
461 | * Each Tx queue uses a circular buffer of 256 TFDs stored in host DRAM. | ||
462 | * Both driver and device share these circular buffers, each of which must be | ||
463 | * contiguous 256 TFDs x 128 bytes-per-TFD = 32 KBytes | ||
464 | * | ||
465 | * Driver must indicate the physical address of the base of each | ||
466 | * circular buffer via the FH_MEM_CBBC_QUEUE registers. | ||
467 | * | ||
468 | * Each TFD contains pointer/size information for up to 20 data buffers | ||
469 | * in host DRAM. These buffers collectively contain the (one) frame described | ||
470 | * by the TFD. Each buffer must be a single contiguous block of memory within | ||
471 | * itself, but buffers may be scattered in host DRAM. Each buffer has max size | ||
472 | * of (4K - 4). The concatenates all of a TFD's buffers into a single | ||
473 | * Tx frame, up to 8 KBytes in size. | ||
474 | * | ||
475 | * A maximum of 255 (not 256!) TFDs may be on a queue waiting for Tx. | ||
476 | * | ||
477 | * Bit fields in the control dword (val0): | ||
478 | */ | ||
479 | struct iwl_tfd { | ||
480 | u8 __reserved1[3]; | ||
481 | u8 num_tbs; | ||
482 | struct iwl_tfd_tb tbs[IWL_NUM_OF_TBS]; | ||
483 | __le32 __pad; | ||
484 | } __attribute__ ((packed)); | ||
485 | |||
486 | |||
487 | /* Keep Warm Size */ | ||
488 | #define IWL_KW_SIZE 0x1000 /*4k */ | ||
406 | 489 | ||
407 | #endif /* !__iwl_fh_h__ */ | 490 | #endif /* !__iwl_fh_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 07a5f60e9229..b429daa5a2bc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c | |||
@@ -257,15 +257,11 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force) | |||
257 | struct iwl_power_mgr *setting = &(priv->power_data); | 257 | struct iwl_power_mgr *setting = &(priv->power_data); |
258 | int ret = 0; | 258 | int ret = 0; |
259 | u16 uninitialized_var(final_mode); | 259 | u16 uninitialized_var(final_mode); |
260 | bool update_chains; | ||
260 | 261 | ||
261 | /* Don't update the RX chain when chain noise calibration is running */ | 262 | /* Don't update the RX chain when chain noise calibration is running */ |
262 | if (priv->chain_noise_data.state != IWL_CHAIN_NOISE_DONE && | 263 | update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE || |
263 | priv->chain_noise_data.state != IWL_CHAIN_NOISE_ALIVE) { | 264 | priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE; |
264 | IWL_DEBUG_POWER("Cannot update the power, chain noise " | ||
265 | "calibration running: %d\n", | ||
266 | priv->chain_noise_data.state); | ||
267 | return -EAGAIN; | ||
268 | } | ||
269 | 265 | ||
270 | /* If on battery, set to 3, | 266 | /* If on battery, set to 3, |
271 | * if plugged into AC power, set to CAM ("continuously aware mode"), | 267 | * if plugged into AC power, set to CAM ("continuously aware mode"), |
@@ -313,9 +309,12 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force) | |||
313 | else | 309 | else |
314 | set_bit(STATUS_POWER_PMI, &priv->status); | 310 | set_bit(STATUS_POWER_PMI, &priv->status); |
315 | 311 | ||
316 | if (priv->cfg->ops->lib->update_chain_flags) | 312 | if (priv->cfg->ops->lib->update_chain_flags && update_chains) |
317 | priv->cfg->ops->lib->update_chain_flags(priv); | 313 | priv->cfg->ops->lib->update_chain_flags(priv); |
318 | 314 | else | |
315 | IWL_DEBUG_POWER("Cannot update the power, chain noise " | ||
316 | "calibration running: %d\n", | ||
317 | priv->chain_noise_data.state); | ||
319 | if (!ret) | 318 | if (!ret) |
320 | setting->power_mode = final_mode; | 319 | setting->power_mode = final_mode; |
321 | } | 320 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index b3c35c64d042..876afd4cab9e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c | |||
@@ -218,8 +218,7 @@ int iwl_rx_queue_restock(struct iwl_priv *priv) | |||
218 | 218 | ||
219 | /* If we've added more space for the firmware to place data, tell it. | 219 | /* If we've added more space for the firmware to place data, tell it. |
220 | * Increment device's write pointer in multiples of 8. */ | 220 | * Increment device's write pointer in multiples of 8. */ |
221 | if ((write != (rxq->write & ~0x7)) | 221 | if (write != (rxq->write & ~0x7)) { |
222 | || (abs(rxq->write - rxq->read) > 7)) { | ||
223 | spin_lock_irqsave(&rxq->lock, flags); | 222 | spin_lock_irqsave(&rxq->lock, flags); |
224 | rxq->need_update = 1; | 223 | rxq->need_update = 1; |
225 | spin_unlock_irqrestore(&rxq->lock, flags); | 224 | spin_unlock_irqrestore(&rxq->lock, flags); |
@@ -317,7 +316,10 @@ void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | |||
317 | 316 | ||
318 | pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd, | 317 | pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd, |
319 | rxq->dma_addr); | 318 | rxq->dma_addr); |
319 | pci_free_consistent(priv->pci_dev, sizeof(struct iwl_rb_status), | ||
320 | rxq->rb_stts, rxq->rb_stts_dma); | ||
320 | rxq->bd = NULL; | 321 | rxq->bd = NULL; |
322 | rxq->rb_stts = NULL; | ||
321 | } | 323 | } |
322 | EXPORT_SYMBOL(iwl_rx_queue_free); | 324 | EXPORT_SYMBOL(iwl_rx_queue_free); |
323 | 325 | ||
@@ -334,7 +336,12 @@ int iwl_rx_queue_alloc(struct iwl_priv *priv) | |||
334 | /* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */ | 336 | /* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */ |
335 | rxq->bd = pci_alloc_consistent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr); | 337 | rxq->bd = pci_alloc_consistent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr); |
336 | if (!rxq->bd) | 338 | if (!rxq->bd) |
337 | return -ENOMEM; | 339 | goto err_bd; |
340 | |||
341 | rxq->rb_stts = pci_alloc_consistent(dev, sizeof(struct iwl_rb_status), | ||
342 | &rxq->rb_stts_dma); | ||
343 | if (!rxq->rb_stts) | ||
344 | goto err_rb; | ||
338 | 345 | ||
339 | /* Fill the rx_used queue with _all_ of the Rx buffers */ | 346 | /* Fill the rx_used queue with _all_ of the Rx buffers */ |
340 | for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) | 347 | for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) |
@@ -346,6 +353,12 @@ int iwl_rx_queue_alloc(struct iwl_priv *priv) | |||
346 | rxq->free_count = 0; | 353 | rxq->free_count = 0; |
347 | rxq->need_update = 0; | 354 | rxq->need_update = 0; |
348 | return 0; | 355 | return 0; |
356 | |||
357 | err_rb: | ||
358 | pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd, | ||
359 | rxq->dma_addr); | ||
360 | err_bd: | ||
361 | return -ENOMEM; | ||
349 | } | 362 | } |
350 | EXPORT_SYMBOL(iwl_rx_queue_alloc); | 363 | EXPORT_SYMBOL(iwl_rx_queue_alloc); |
351 | 364 | ||
@@ -412,7 +425,7 @@ int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | |||
412 | 425 | ||
413 | /* Tell device where in DRAM to update its Rx status */ | 426 | /* Tell device where in DRAM to update its Rx status */ |
414 | iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG, | 427 | iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG, |
415 | (priv->shared_phys + priv->rb_closed_offset) >> 4); | 428 | rxq->rb_stts_dma >> 4); |
416 | 429 | ||
417 | /* Enable Rx DMA | 430 | /* Enable Rx DMA |
418 | * FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY is set because of HW bug in | 431 | * FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY is set because of HW bug in |
@@ -426,6 +439,7 @@ int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | |||
426 | FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | | 439 | FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | |
427 | FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY | | 440 | FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY | |
428 | FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | | 441 | FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | |
442 | FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME | | ||
429 | rb_size| | 443 | rb_size| |
430 | (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)| | 444 | (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)| |
431 | (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); | 445 | (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-spectrum.c b/drivers/net/wireless/iwlwifi/iwl-spectrum.c new file mode 100644 index 000000000000..ad319a178a90 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-spectrum.c | |||
@@ -0,0 +1,198 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. | ||
4 | * | ||
5 | * Portions of this file are derived from the ipw3945 project, as well | ||
6 | * as portions of the ieee80211 subsystem header files. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of version 2 of the GNU General Public License as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
15 | * more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along with | ||
18 | * this program; if not, write to the Free Software Foundation, Inc., | ||
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
20 | * | ||
21 | * The full GNU General Public License is included in this distribution in the | ||
22 | * file called LICENSE. | ||
23 | * | ||
24 | * Contact Information: | ||
25 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/pci.h> | ||
34 | #include <linux/delay.h> | ||
35 | #include <linux/skbuff.h> | ||
36 | #include <linux/netdevice.h> | ||
37 | #include <linux/wireless.h> | ||
38 | |||
39 | #include <net/mac80211.h> | ||
40 | |||
41 | #include "iwl-eeprom.h" | ||
42 | #include "iwl-dev.h" | ||
43 | #include "iwl-core.h" | ||
44 | #include "iwl-io.h" | ||
45 | #include "iwl-spectrum.h" | ||
46 | |||
47 | #define BEACON_TIME_MASK_LOW 0x00FFFFFF | ||
48 | #define BEACON_TIME_MASK_HIGH 0xFF000000 | ||
49 | #define TIME_UNIT 1024 | ||
50 | |||
51 | /* | ||
52 | * extended beacon time format | ||
53 | * time in usec will be changed into a 32-bit value in 8:24 format | ||
54 | * the high 1 byte is the beacon counts | ||
55 | * the lower 3 bytes is the time in usec within one beacon interval | ||
56 | */ | ||
57 | |||
58 | /* TOOD: was used in sysfs debug interface need to add to mac */ | ||
59 | #if 0 | ||
60 | static u32 iwl_usecs_to_beacons(u32 usec, u32 beacon_interval) | ||
61 | { | ||
62 | u32 quot; | ||
63 | u32 rem; | ||
64 | u32 interval = beacon_interval * 1024; | ||
65 | |||
66 | if (!interval || !usec) | ||
67 | return 0; | ||
68 | |||
69 | quot = (usec / interval) & (BEACON_TIME_MASK_HIGH >> 24); | ||
70 | rem = (usec % interval) & BEACON_TIME_MASK_LOW; | ||
71 | |||
72 | return (quot << 24) + rem; | ||
73 | } | ||
74 | |||
75 | /* base is usually what we get from ucode with each received frame, | ||
76 | * the same as HW timer counter counting down | ||
77 | */ | ||
78 | |||
79 | static __le32 iwl_add_beacon_time(u32 base, u32 addon, u32 beacon_interval) | ||
80 | { | ||
81 | u32 base_low = base & BEACON_TIME_MASK_LOW; | ||
82 | u32 addon_low = addon & BEACON_TIME_MASK_LOW; | ||
83 | u32 interval = beacon_interval * TIME_UNIT; | ||
84 | u32 res = (base & BEACON_TIME_MASK_HIGH) + | ||
85 | (addon & BEACON_TIME_MASK_HIGH); | ||
86 | |||
87 | if (base_low > addon_low) | ||
88 | res += base_low - addon_low; | ||
89 | else if (base_low < addon_low) { | ||
90 | res += interval + base_low - addon_low; | ||
91 | res += (1 << 24); | ||
92 | } else | ||
93 | res += (1 << 24); | ||
94 | |||
95 | return cpu_to_le32(res); | ||
96 | } | ||
97 | static int iwl_get_measurement(struct iwl_priv *priv, | ||
98 | struct ieee80211_measurement_params *params, | ||
99 | u8 type) | ||
100 | { | ||
101 | struct iwl4965_spectrum_cmd spectrum; | ||
102 | struct iwl_rx_packet *res; | ||
103 | struct iwl_host_cmd cmd = { | ||
104 | .id = REPLY_SPECTRUM_MEASUREMENT_CMD, | ||
105 | .data = (void *)&spectrum, | ||
106 | .meta.flags = CMD_WANT_SKB, | ||
107 | }; | ||
108 | u32 add_time = le64_to_cpu(params->start_time); | ||
109 | int rc; | ||
110 | int spectrum_resp_status; | ||
111 | int duration = le16_to_cpu(params->duration); | ||
112 | |||
113 | if (iwl_is_associated(priv)) | ||
114 | add_time = | ||
115 | iwl_usecs_to_beacons( | ||
116 | le64_to_cpu(params->start_time) - priv->last_tsf, | ||
117 | le16_to_cpu(priv->rxon_timing.beacon_interval)); | ||
118 | |||
119 | memset(&spectrum, 0, sizeof(spectrum)); | ||
120 | |||
121 | spectrum.channel_count = cpu_to_le16(1); | ||
122 | spectrum.flags = | ||
123 | RXON_FLG_TSF2HOST_MSK | RXON_FLG_ANT_A_MSK | RXON_FLG_DIS_DIV_MSK; | ||
124 | spectrum.filter_flags = MEASUREMENT_FILTER_FLAG; | ||
125 | cmd.len = sizeof(spectrum); | ||
126 | spectrum.len = cpu_to_le16(cmd.len - sizeof(spectrum.len)); | ||
127 | |||
128 | if (iwl_is_associated(priv)) | ||
129 | spectrum.start_time = | ||
130 | iwl_add_beacon_time(priv->last_beacon_time, | ||
131 | add_time, | ||
132 | le16_to_cpu(priv->rxon_timing.beacon_interval)); | ||
133 | else | ||
134 | spectrum.start_time = 0; | ||
135 | |||
136 | spectrum.channels[0].duration = cpu_to_le32(duration * TIME_UNIT); | ||
137 | spectrum.channels[0].channel = params->channel; | ||
138 | spectrum.channels[0].type = type; | ||
139 | if (priv->active_rxon.flags & RXON_FLG_BAND_24G_MSK) | ||
140 | spectrum.flags |= RXON_FLG_BAND_24G_MSK | | ||
141 | RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK; | ||
142 | |||
143 | rc = iwl_send_cmd_sync(priv, &cmd); | ||
144 | if (rc) | ||
145 | return rc; | ||
146 | |||
147 | res = (struct iwl_rx_packet *)cmd.meta.u.skb->data; | ||
148 | if (res->hdr.flags & IWL_CMD_FAILED_MSK) { | ||
149 | IWL_ERROR("Bad return from REPLY_RX_ON_ASSOC command\n"); | ||
150 | rc = -EIO; | ||
151 | } | ||
152 | |||
153 | spectrum_resp_status = le16_to_cpu(res->u.spectrum.status); | ||
154 | switch (spectrum_resp_status) { | ||
155 | case 0: /* Command will be handled */ | ||
156 | if (res->u.spectrum.id != 0xff) { | ||
157 | IWL_DEBUG_INFO | ||
158 | ("Replaced existing measurement: %d\n", | ||
159 | res->u.spectrum.id); | ||
160 | priv->measurement_status &= ~MEASUREMENT_READY; | ||
161 | } | ||
162 | priv->measurement_status |= MEASUREMENT_ACTIVE; | ||
163 | rc = 0; | ||
164 | break; | ||
165 | |||
166 | case 1: /* Command will not be handled */ | ||
167 | rc = -EAGAIN; | ||
168 | break; | ||
169 | } | ||
170 | |||
171 | dev_kfree_skb_any(cmd.meta.u.skb); | ||
172 | |||
173 | return rc; | ||
174 | } | ||
175 | #endif | ||
176 | |||
177 | static void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, | ||
178 | struct iwl_rx_mem_buffer *rxb) | ||
179 | { | ||
180 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | ||
181 | struct iwl4965_spectrum_notification *report = &(pkt->u.spectrum_notif); | ||
182 | |||
183 | if (!report->state) { | ||
184 | IWL_DEBUG(IWL_DL_11H, | ||
185 | "Spectrum Measure Notification: Start\n"); | ||
186 | return; | ||
187 | } | ||
188 | |||
189 | memcpy(&priv->measure_report, report, sizeof(*report)); | ||
190 | priv->measurement_status |= MEASUREMENT_READY; | ||
191 | } | ||
192 | |||
193 | void iwl_setup_spectrum_handlers(struct iwl_priv *priv) | ||
194 | { | ||
195 | priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] = | ||
196 | iwl_rx_spectrum_measure_notif; | ||
197 | } | ||
198 | EXPORT_SYMBOL(iwl_setup_spectrum_handlers); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-spectrum.h b/drivers/net/wireless/iwlwifi/iwl-spectrum.h index a40a2174df98..fa990a102515 100644 --- a/drivers/net/wireless/iwlwifi/iwl-spectrum.h +++ b/drivers/net/wireless/iwlwifi/iwl-spectrum.h | |||
@@ -88,4 +88,5 @@ struct ieee80211_measurement_report { | |||
88 | struct ieee80211_basic_report basic[0]; | 88 | struct ieee80211_basic_report basic[0]; |
89 | } u; | 89 | } u; |
90 | } __attribute__ ((packed)); | 90 | } __attribute__ ((packed)); |
91 | |||
91 | #endif | 92 | #endif |
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 7d8b4e2d5094..166f0001e01d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
@@ -56,6 +56,26 @@ static const u16 default_tid_to_tx_fifo[] = { | |||
56 | IWL_TX_FIFO_AC3 | 56 | IWL_TX_FIFO_AC3 |
57 | }; | 57 | }; |
58 | 58 | ||
59 | static inline int iwl_alloc_dma_ptr(struct iwl_priv *priv, | ||
60 | struct iwl_dma_ptr *ptr, size_t size) | ||
61 | { | ||
62 | ptr->addr = pci_alloc_consistent(priv->pci_dev, size, &ptr->dma); | ||
63 | if (!ptr->addr) | ||
64 | return -ENOMEM; | ||
65 | ptr->size = size; | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static inline void iwl_free_dma_ptr(struct iwl_priv *priv, | ||
70 | struct iwl_dma_ptr *ptr) | ||
71 | { | ||
72 | if (unlikely(!ptr->addr)) | ||
73 | return; | ||
74 | |||
75 | pci_free_consistent(priv->pci_dev, ptr->size, ptr->addr, ptr->dma); | ||
76 | memset(ptr, 0, sizeof(*ptr)); | ||
77 | } | ||
78 | |||
59 | static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx) | 79 | static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx) |
60 | { | 80 | { |
61 | struct iwl_tfd_tb *tb = &tfd->tbs[idx]; | 81 | struct iwl_tfd_tb *tb = &tfd->tbs[idx]; |
@@ -517,8 +537,9 @@ void iwl_hw_txq_ctx_free(struct iwl_priv *priv) | |||
517 | else | 537 | else |
518 | iwl_tx_queue_free(priv, txq_id); | 538 | iwl_tx_queue_free(priv, txq_id); |
519 | 539 | ||
520 | /* Keep-warm buffer */ | 540 | iwl_free_dma_ptr(priv, &priv->kw); |
521 | iwl_kw_free(priv); | 541 | |
542 | iwl_free_dma_ptr(priv, &priv->scd_bc_tbls); | ||
522 | } | 543 | } |
523 | EXPORT_SYMBOL(iwl_hw_txq_ctx_free); | 544 | EXPORT_SYMBOL(iwl_hw_txq_ctx_free); |
524 | 545 | ||
@@ -535,13 +556,17 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv) | |||
535 | int txq_id, slots_num; | 556 | int txq_id, slots_num; |
536 | unsigned long flags; | 557 | unsigned long flags; |
537 | 558 | ||
538 | iwl_kw_free(priv); | ||
539 | |||
540 | /* Free all tx/cmd queues and keep-warm buffer */ | 559 | /* Free all tx/cmd queues and keep-warm buffer */ |
541 | iwl_hw_txq_ctx_free(priv); | 560 | iwl_hw_txq_ctx_free(priv); |
542 | 561 | ||
562 | ret = iwl_alloc_dma_ptr(priv, &priv->scd_bc_tbls, | ||
563 | priv->hw_params.scd_bc_tbls_size); | ||
564 | if (ret) { | ||
565 | IWL_ERROR("Scheduler BC Table allocation failed\n"); | ||
566 | goto error_bc_tbls; | ||
567 | } | ||
543 | /* Alloc keep-warm buffer */ | 568 | /* Alloc keep-warm buffer */ |
544 | ret = iwl_kw_alloc(priv); | 569 | ret = iwl_alloc_dma_ptr(priv, &priv->kw, IWL_KW_SIZE); |
545 | if (ret) { | 570 | if (ret) { |
546 | IWL_ERROR("Keep Warm allocation failed\n"); | 571 | IWL_ERROR("Keep Warm allocation failed\n"); |
547 | goto error_kw; | 572 | goto error_kw; |
@@ -556,16 +581,13 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv) | |||
556 | /* Turn off all Tx DMA fifos */ | 581 | /* Turn off all Tx DMA fifos */ |
557 | priv->cfg->ops->lib->txq_set_sched(priv, 0); | 582 | priv->cfg->ops->lib->txq_set_sched(priv, 0); |
558 | 583 | ||
584 | /* Tell NIC where to find the "keep warm" buffer */ | ||
585 | iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); | ||
586 | |||
559 | iwl_release_nic_access(priv); | 587 | iwl_release_nic_access(priv); |
560 | spin_unlock_irqrestore(&priv->lock, flags); | 588 | spin_unlock_irqrestore(&priv->lock, flags); |
561 | 589 | ||
562 | 590 | ||
563 | /* Tell nic where to find the keep-warm buffer */ | ||
564 | ret = iwl_kw_init(priv); | ||
565 | if (ret) { | ||
566 | IWL_ERROR("kw_init failed\n"); | ||
567 | goto error_reset; | ||
568 | } | ||
569 | 591 | ||
570 | /* Alloc and init all Tx queues, including the command queue (#4) */ | 592 | /* Alloc and init all Tx queues, including the command queue (#4) */ |
571 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { | 593 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { |
@@ -584,8 +606,10 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv) | |||
584 | error: | 606 | error: |
585 | iwl_hw_txq_ctx_free(priv); | 607 | iwl_hw_txq_ctx_free(priv); |
586 | error_reset: | 608 | error_reset: |
587 | iwl_kw_free(priv); | 609 | iwl_free_dma_ptr(priv, &priv->kw); |
588 | error_kw: | 610 | error_kw: |
611 | iwl_free_dma_ptr(priv, &priv->scd_bc_tbls); | ||
612 | error_bc_tbls: | ||
589 | return ret; | 613 | return ret; |
590 | } | 614 | } |
591 | 615 | ||
@@ -1236,8 +1260,13 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
1236 | * command queue then there a command routing bug has been introduced | 1260 | * command queue then there a command routing bug has been introduced |
1237 | * in the queue management code. */ | 1261 | * in the queue management code. */ |
1238 | if (WARN(txq_id != IWL_CMD_QUEUE_NUM, | 1262 | if (WARN(txq_id != IWL_CMD_QUEUE_NUM, |
1239 | "wrong command queue %d, command id 0x%X\n", txq_id, pkt->hdr.cmd)) | 1263 | "wrong command queue %d, sequence 0x%X readp=%d writep=%d\n", |
1264 | txq_id, sequence, | ||
1265 | priv->txq[IWL_CMD_QUEUE_NUM].q.read_ptr, | ||
1266 | priv->txq[IWL_CMD_QUEUE_NUM].q.write_ptr)) { | ||
1267 | iwl_print_hex_dump(priv, IWL_DL_INFO , rxb, 32); | ||
1240 | return; | 1268 | return; |
1269 | } | ||
1241 | 1270 | ||
1242 | cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge); | 1271 | cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge); |
1243 | cmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index]; | 1272 | cmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index]; |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index a3ec4d0467a2..3344841b7662 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -1418,9 +1418,16 @@ unsigned int iwl3945_fill_beacon_frame(struct iwl3945_priv *priv, | |||
1418 | return priv->ibss_beacon->len; | 1418 | return priv->ibss_beacon->len; |
1419 | } | 1419 | } |
1420 | 1420 | ||
1421 | static u8 iwl3945_rate_get_lowest_plcp(int rate_mask) | 1421 | static u8 iwl3945_rate_get_lowest_plcp(struct iwl3945_priv *priv) |
1422 | { | 1422 | { |
1423 | u8 i; | 1423 | u8 i; |
1424 | int rate_mask; | ||
1425 | |||
1426 | /* Set rate mask*/ | ||
1427 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) | ||
1428 | rate_mask = priv->active_rate_basic & 0xF; | ||
1429 | else | ||
1430 | rate_mask = priv->active_rate_basic & 0xFF0; | ||
1424 | 1431 | ||
1425 | for (i = IWL_RATE_1M_INDEX; i != IWL_RATE_INVALID; | 1432 | for (i = IWL_RATE_1M_INDEX; i != IWL_RATE_INVALID; |
1426 | i = iwl3945_rates[i].next_ieee) { | 1433 | i = iwl3945_rates[i].next_ieee) { |
@@ -1428,7 +1435,11 @@ static u8 iwl3945_rate_get_lowest_plcp(int rate_mask) | |||
1428 | return iwl3945_rates[i].plcp; | 1435 | return iwl3945_rates[i].plcp; |
1429 | } | 1436 | } |
1430 | 1437 | ||
1431 | return IWL_RATE_INVALID; | 1438 | /* No valid rate was found. Assign the lowest one */ |
1439 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) | ||
1440 | return IWL_RATE_1M_PLCP; | ||
1441 | else | ||
1442 | return IWL_RATE_6M_PLCP; | ||
1432 | } | 1443 | } |
1433 | 1444 | ||
1434 | static int iwl3945_send_beacon_cmd(struct iwl3945_priv *priv) | 1445 | static int iwl3945_send_beacon_cmd(struct iwl3945_priv *priv) |
@@ -1446,16 +1457,7 @@ static int iwl3945_send_beacon_cmd(struct iwl3945_priv *priv) | |||
1446 | return -ENOMEM; | 1457 | return -ENOMEM; |
1447 | } | 1458 | } |
1448 | 1459 | ||
1449 | if (!(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK)) { | 1460 | rate = iwl3945_rate_get_lowest_plcp(priv); |
1450 | rate = iwl3945_rate_get_lowest_plcp(priv->active_rate_basic & | ||
1451 | 0xFF0); | ||
1452 | if (rate == IWL_INVALID_RATE) | ||
1453 | rate = IWL_RATE_6M_PLCP; | ||
1454 | } else { | ||
1455 | rate = iwl3945_rate_get_lowest_plcp(priv->active_rate_basic & 0xF); | ||
1456 | if (rate == IWL_INVALID_RATE) | ||
1457 | rate = IWL_RATE_1M_PLCP; | ||
1458 | } | ||
1459 | 1461 | ||
1460 | frame_size = iwl3945_hw_get_beacon_cmd(priv, frame, rate); | 1462 | frame_size = iwl3945_hw_get_beacon_cmd(priv, frame, rate); |
1461 | 1463 | ||
@@ -4741,7 +4743,7 @@ static void iwl3945_free_channel_map(struct iwl3945_priv *priv) | |||
4741 | #define IWL_PASSIVE_DWELL_BASE (100) | 4743 | #define IWL_PASSIVE_DWELL_BASE (100) |
4742 | #define IWL_CHANNEL_TUNE_TIME 5 | 4744 | #define IWL_CHANNEL_TUNE_TIME 5 |
4743 | 4745 | ||
4744 | #define IWL_SCAN_PROBE_MASK(n) cpu_to_le32((BIT(n) | (BIT(n) - BIT(1)))) | 4746 | #define IWL_SCAN_PROBE_MASK(n) (BIT(n) | (BIT(n) - BIT(1))) |
4745 | 4747 | ||
4746 | static inline u16 iwl3945_get_active_dwell_time(struct iwl3945_priv *priv, | 4748 | static inline u16 iwl3945_get_active_dwell_time(struct iwl3945_priv *priv, |
4747 | enum ieee80211_band band, | 4749 | enum ieee80211_band band, |
@@ -5601,6 +5603,10 @@ static void iwl3945_init_alive_start(struct iwl3945_priv *priv) | |||
5601 | } | 5603 | } |
5602 | 5604 | ||
5603 | 5605 | ||
5606 | /* temporary */ | ||
5607 | static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, | ||
5608 | struct sk_buff *skb); | ||
5609 | |||
5604 | /** | 5610 | /** |
5605 | * iwl3945_alive_start - called after REPLY_ALIVE notification received | 5611 | * iwl3945_alive_start - called after REPLY_ALIVE notification received |
5606 | * from protocol/runtime uCode (initialization uCode's | 5612 | * from protocol/runtime uCode (initialization uCode's |
@@ -5704,6 +5710,14 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv) | |||
5704 | if (priv->error_recovering) | 5710 | if (priv->error_recovering) |
5705 | iwl3945_error_recovery(priv); | 5711 | iwl3945_error_recovery(priv); |
5706 | 5712 | ||
5713 | /* reassociate for ADHOC mode */ | ||
5714 | if (priv->vif && (priv->iw_mode == NL80211_IFTYPE_ADHOC)) { | ||
5715 | struct sk_buff *beacon = ieee80211_beacon_get(priv->hw, | ||
5716 | priv->vif); | ||
5717 | if (beacon) | ||
5718 | iwl3945_mac_beacon_update(priv->hw, beacon); | ||
5719 | } | ||
5720 | |||
5707 | return; | 5721 | return; |
5708 | 5722 | ||
5709 | restart: | 5723 | restart: |
@@ -6710,9 +6724,6 @@ static void iwl3945_config_ap(struct iwl3945_priv *priv) | |||
6710 | * clear sta table, add BCAST sta... */ | 6724 | * clear sta table, add BCAST sta... */ |
6711 | } | 6725 | } |
6712 | 6726 | ||
6713 | /* temporary */ | ||
6714 | static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb); | ||
6715 | |||
6716 | static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, | 6727 | static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, |
6717 | struct ieee80211_vif *vif, | 6728 | struct ieee80211_vif *vif, |
6718 | struct ieee80211_if_conf *conf) | 6729 | struct ieee80211_if_conf *conf) |
@@ -6734,7 +6745,9 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, | |||
6734 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); | 6745 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); |
6735 | if (!beacon) | 6746 | if (!beacon) |
6736 | return -ENOMEM; | 6747 | return -ENOMEM; |
6748 | mutex_lock(&priv->mutex); | ||
6737 | rc = iwl3945_mac_beacon_update(hw, beacon); | 6749 | rc = iwl3945_mac_beacon_update(hw, beacon); |
6750 | mutex_unlock(&priv->mutex); | ||
6738 | if (rc) | 6751 | if (rc) |
6739 | return rc; | 6752 | return rc; |
6740 | } | 6753 | } |
@@ -7188,18 +7201,15 @@ static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk | |||
7188 | struct iwl3945_priv *priv = hw->priv; | 7201 | struct iwl3945_priv *priv = hw->priv; |
7189 | unsigned long flags; | 7202 | unsigned long flags; |
7190 | 7203 | ||
7191 | mutex_lock(&priv->mutex); | ||
7192 | IWL_DEBUG_MAC80211("enter\n"); | 7204 | IWL_DEBUG_MAC80211("enter\n"); |
7193 | 7205 | ||
7194 | if (!iwl3945_is_ready_rf(priv)) { | 7206 | if (!iwl3945_is_ready_rf(priv)) { |
7195 | IWL_DEBUG_MAC80211("leave - RF not ready\n"); | 7207 | IWL_DEBUG_MAC80211("leave - RF not ready\n"); |
7196 | mutex_unlock(&priv->mutex); | ||
7197 | return -EIO; | 7208 | return -EIO; |
7198 | } | 7209 | } |
7199 | 7210 | ||
7200 | if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { | 7211 | if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { |
7201 | IWL_DEBUG_MAC80211("leave - not IBSS\n"); | 7212 | IWL_DEBUG_MAC80211("leave - not IBSS\n"); |
7202 | mutex_unlock(&priv->mutex); | ||
7203 | return -EIO; | 7213 | return -EIO; |
7204 | } | 7214 | } |
7205 | 7215 | ||
@@ -7219,7 +7229,6 @@ static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk | |||
7219 | 7229 | ||
7220 | iwl3945_post_associate(priv); | 7230 | iwl3945_post_associate(priv); |
7221 | 7231 | ||
7222 | mutex_unlock(&priv->mutex); | ||
7223 | 7232 | ||
7224 | return 0; | 7233 | return 0; |
7225 | } | 7234 | } |
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 957fd5a10a8d..639dd02d3d31 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c | |||
@@ -159,7 +159,8 @@ out: | |||
159 | return ret; | 159 | return ret; |
160 | } | 160 | } |
161 | 161 | ||
162 | int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria) | 162 | int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria, |
163 | struct wol_config *p_wol_config) | ||
163 | { | 164 | { |
164 | struct cmd_ds_host_sleep cmd_config; | 165 | struct cmd_ds_host_sleep cmd_config; |
165 | int ret; | 166 | int ret; |
@@ -169,10 +170,21 @@ int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria) | |||
169 | cmd_config.gpio = priv->wol_gpio; | 170 | cmd_config.gpio = priv->wol_gpio; |
170 | cmd_config.gap = priv->wol_gap; | 171 | cmd_config.gap = priv->wol_gap; |
171 | 172 | ||
173 | if (p_wol_config != NULL) | ||
174 | memcpy((uint8_t *)&cmd_config.wol_conf, (uint8_t *)p_wol_config, | ||
175 | sizeof(struct wol_config)); | ||
176 | else | ||
177 | cmd_config.wol_conf.action = CMD_ACT_ACTION_NONE; | ||
178 | |||
172 | ret = lbs_cmd_with_response(priv, CMD_802_11_HOST_SLEEP_CFG, &cmd_config); | 179 | ret = lbs_cmd_with_response(priv, CMD_802_11_HOST_SLEEP_CFG, &cmd_config); |
173 | if (!ret) { | 180 | if (!ret) { |
174 | lbs_deb_cmd("Set WOL criteria to %x\n", criteria); | 181 | if (criteria) { |
175 | priv->wol_criteria = criteria; | 182 | lbs_deb_cmd("Set WOL criteria to %x\n", criteria); |
183 | priv->wol_criteria = criteria; | ||
184 | } else | ||
185 | memcpy((uint8_t *) p_wol_config, | ||
186 | (uint8_t *)&cmd_config.wol_conf, | ||
187 | sizeof(struct wol_config)); | ||
176 | } else { | 188 | } else { |
177 | lbs_pr_info("HOST_SLEEP_CFG failed %d\n", ret); | 189 | lbs_pr_info("HOST_SLEEP_CFG failed %d\n", ret); |
178 | } | 190 | } |
diff --git a/drivers/net/wireless/libertas/cmd.h b/drivers/net/wireless/libertas/cmd.h index 36be4c9703e0..392e578ca095 100644 --- a/drivers/net/wireless/libertas/cmd.h +++ b/drivers/net/wireless/libertas/cmd.h | |||
@@ -56,7 +56,8 @@ int lbs_mesh_config_send(struct lbs_private *priv, | |||
56 | uint16_t action, uint16_t type); | 56 | uint16_t action, uint16_t type); |
57 | int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan); | 57 | int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan); |
58 | 58 | ||
59 | int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria); | 59 | int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria, |
60 | struct wol_config *p_wol_config); | ||
60 | int lbs_suspend(struct lbs_private *priv); | 61 | int lbs_suspend(struct lbs_private *priv); |
61 | void lbs_resume(struct lbs_private *priv); | 62 | void lbs_resume(struct lbs_private *priv); |
62 | 63 | ||
diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h index 2d4666f26808..c364e4c01d1b 100644 --- a/drivers/net/wireless/libertas/defs.h +++ b/drivers/net/wireless/libertas/defs.h | |||
@@ -149,6 +149,18 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in | |||
149 | #define EHS_WAKE_ON_MAC_EVENT 0x0004 | 149 | #define EHS_WAKE_ON_MAC_EVENT 0x0004 |
150 | #define EHS_WAKE_ON_MULTICAST_DATA 0x0008 | 150 | #define EHS_WAKE_ON_MULTICAST_DATA 0x0008 |
151 | #define EHS_REMOVE_WAKEUP 0xFFFFFFFF | 151 | #define EHS_REMOVE_WAKEUP 0xFFFFFFFF |
152 | /* Wake rules for Host_Sleep_CFG command */ | ||
153 | #define WOL_RULE_NET_TYPE_INFRA_OR_IBSS 0x00 | ||
154 | #define WOL_RULE_NET_TYPE_MESH 0x10 | ||
155 | #define WOL_RULE_ADDR_TYPE_BCAST 0x01 | ||
156 | #define WOL_RULE_ADDR_TYPE_MCAST 0x08 | ||
157 | #define WOL_RULE_ADDR_TYPE_UCAST 0x02 | ||
158 | #define WOL_RULE_OP_AND 0x01 | ||
159 | #define WOL_RULE_OP_OR 0x02 | ||
160 | #define WOL_RULE_OP_INVALID 0xFF | ||
161 | #define WOL_RESULT_VALID_CMD 0 | ||
162 | #define WOL_RESULT_NOSPC_ERR 1 | ||
163 | #define WOL_RESULT_EEXIST_ERR 2 | ||
152 | 164 | ||
153 | /** Misc constants */ | 165 | /** Misc constants */ |
154 | /* This section defines 802.11 specific contants */ | 166 | /* This section defines 802.11 specific contants */ |
diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c index 156f471217bb..61d2f50470c8 100644 --- a/drivers/net/wireless/libertas/ethtool.c +++ b/drivers/net/wireless/libertas/ethtool.c | |||
@@ -180,7 +180,7 @@ static int lbs_ethtool_set_wol(struct net_device *dev, | |||
180 | if (wol->wolopts & WAKE_BCAST) criteria |= EHS_WAKE_ON_BROADCAST_DATA; | 180 | if (wol->wolopts & WAKE_BCAST) criteria |= EHS_WAKE_ON_BROADCAST_DATA; |
181 | if (wol->wolopts & WAKE_PHY) criteria |= EHS_WAKE_ON_MAC_EVENT; | 181 | if (wol->wolopts & WAKE_PHY) criteria |= EHS_WAKE_ON_MAC_EVENT; |
182 | 182 | ||
183 | return lbs_host_sleep_cfg(priv, criteria); | 183 | return lbs_host_sleep_cfg(priv, criteria, (struct wol_config *)NULL); |
184 | } | 184 | } |
185 | 185 | ||
186 | struct ethtool_ops lbs_ethtool_ops = { | 186 | struct ethtool_ops lbs_ethtool_ops = { |
diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h index 5004d7679c02..a17b778c172c 100644 --- a/drivers/net/wireless/libertas/host.h +++ b/drivers/net/wireless/libertas/host.h | |||
@@ -220,6 +220,14 @@ enum cmd_fwt_access_opts { | |||
220 | CMD_ACT_FWT_ACCESS_TIME, | 220 | CMD_ACT_FWT_ACCESS_TIME, |
221 | }; | 221 | }; |
222 | 222 | ||
223 | /* Define action or option for CMD_802_11_HOST_SLEEP_CFG */ | ||
224 | enum cmd_wol_cfg_opts { | ||
225 | CMD_ACT_ACTION_NONE = 0, | ||
226 | CMD_ACT_SET_WOL_RULE, | ||
227 | CMD_ACT_GET_WOL_RULE, | ||
228 | CMD_ACT_RESET_WOL_RULE, | ||
229 | }; | ||
230 | |||
223 | /* Define action or option for CMD_MESH_ACCESS */ | 231 | /* Define action or option for CMD_MESH_ACCESS */ |
224 | enum cmd_mesh_access_opts { | 232 | enum cmd_mesh_access_opts { |
225 | CMD_ACT_MESH_GET_TTL = 1, | 233 | CMD_ACT_MESH_GET_TTL = 1, |
diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h index d9f9a12a739e..e173b1b46c23 100644 --- a/drivers/net/wireless/libertas/hostcmd.h +++ b/drivers/net/wireless/libertas/hostcmd.h | |||
@@ -580,13 +580,37 @@ struct MrvlIEtype_keyParamSet { | |||
580 | u8 key[32]; | 580 | u8 key[32]; |
581 | }; | 581 | }; |
582 | 582 | ||
583 | #define MAX_WOL_RULES 16 | ||
584 | |||
585 | struct host_wol_rule { | ||
586 | uint8_t rule_no; | ||
587 | uint8_t rule_ops; | ||
588 | __le16 sig_offset; | ||
589 | __le16 sig_length; | ||
590 | __le16 reserve; | ||
591 | __be32 sig_mask; | ||
592 | __be32 signature; | ||
593 | }; | ||
594 | |||
595 | struct wol_config { | ||
596 | uint8_t action; | ||
597 | uint8_t pattern; | ||
598 | uint8_t no_rules_in_cmd; | ||
599 | uint8_t result; | ||
600 | struct host_wol_rule rule[MAX_WOL_RULES]; | ||
601 | }; | ||
602 | |||
603 | |||
583 | struct cmd_ds_host_sleep { | 604 | struct cmd_ds_host_sleep { |
584 | struct cmd_header hdr; | 605 | struct cmd_header hdr; |
585 | __le32 criteria; | 606 | __le32 criteria; |
586 | uint8_t gpio; | 607 | uint8_t gpio; |
587 | uint8_t gap; | 608 | uint16_t gap; |
609 | struct wol_config wol_conf; | ||
588 | } __attribute__ ((packed)); | 610 | } __attribute__ ((packed)); |
589 | 611 | ||
612 | |||
613 | |||
590 | struct cmd_ds_802_11_key_material { | 614 | struct cmd_ds_802_11_key_material { |
591 | struct cmd_header hdr; | 615 | struct cmd_header hdr; |
592 | 616 | ||
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index cafbccb74143..fcd3fe6abe8c 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c | |||
@@ -178,7 +178,8 @@ static void if_usb_setup_firmware(struct lbs_private *priv) | |||
178 | 178 | ||
179 | priv->wol_gpio = 2; /* Wake via GPIO2... */ | 179 | priv->wol_gpio = 2; /* Wake via GPIO2... */ |
180 | priv->wol_gap = 20; /* ... after 20ms */ | 180 | priv->wol_gap = 20; /* ... after 20ms */ |
181 | lbs_host_sleep_cfg(priv, EHS_WAKE_ON_UNICAST_DATA); | 181 | lbs_host_sleep_cfg(priv, EHS_WAKE_ON_UNICAST_DATA, |
182 | (struct wol_config *) NULL); | ||
182 | 183 | ||
183 | wake_method.hdr.size = cpu_to_le16(sizeof(wake_method)); | 184 | wake_method.hdr.size = cpu_to_le16(sizeof(wake_method)); |
184 | wake_method.action = cpu_to_le16(CMD_ACT_GET); | 185 | wake_method.action = cpu_to_le16(CMD_ACT_GET); |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index b9230da925ee..d8b5cf389405 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -368,7 +368,8 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, | |||
368 | 368 | ||
369 | hwsim_check_magic(vif); | 369 | hwsim_check_magic(vif); |
370 | 370 | ||
371 | if (vif->type != NL80211_IFTYPE_AP) | 371 | if (vif->type != NL80211_IFTYPE_AP && |
372 | vif->type != NL80211_IFTYPE_MESH_POINT) | ||
372 | return; | 373 | return; |
373 | 374 | ||
374 | skb = ieee80211_beacon_get(hw, vif); | 375 | skb = ieee80211_beacon_get(hw, vif); |
@@ -774,7 +775,8 @@ static int __init init_mac80211_hwsim(void) | |||
774 | hw->queues = 4; | 775 | hw->queues = 4; |
775 | hw->wiphy->interface_modes = | 776 | hw->wiphy->interface_modes = |
776 | BIT(NL80211_IFTYPE_STATION) | | 777 | BIT(NL80211_IFTYPE_STATION) | |
777 | BIT(NL80211_IFTYPE_AP); | 778 | BIT(NL80211_IFTYPE_AP) | |
779 | BIT(NL80211_IFTYPE_MESH_POINT); | ||
778 | hw->ampdu_queues = 1; | 780 | hw->ampdu_queues = 1; |
779 | 781 | ||
780 | /* ask mac80211 to reserve space for magic */ | 782 | /* ask mac80211 to reserve space for magic */ |
diff --git a/drivers/net/wireless/orinoco/orinoco.c b/drivers/net/wireless/orinoco/orinoco.c index 072be44b37de..fd9263980d69 100644 --- a/drivers/net/wireless/orinoco/orinoco.c +++ b/drivers/net/wireless/orinoco/orinoco.c | |||
@@ -5444,7 +5444,7 @@ static inline char *orinoco_translate_scan(struct net_device *dev, | |||
5444 | char *current_ev, | 5444 | char *current_ev, |
5445 | char *end_buf, | 5445 | char *end_buf, |
5446 | union hermes_scan_info *bss, | 5446 | union hermes_scan_info *bss, |
5447 | unsigned int last_scanned) | 5447 | unsigned long last_scanned) |
5448 | { | 5448 | { |
5449 | struct orinoco_private *priv = netdev_priv(dev); | 5449 | struct orinoco_private *priv = netdev_priv(dev); |
5450 | u16 capabilities; | 5450 | u16 capabilities; |
@@ -5591,7 +5591,7 @@ static inline char *orinoco_translate_ext_scan(struct net_device *dev, | |||
5591 | char *current_ev, | 5591 | char *current_ev, |
5592 | char *end_buf, | 5592 | char *end_buf, |
5593 | struct agere_ext_scan_info *bss, | 5593 | struct agere_ext_scan_info *bss, |
5594 | unsigned int last_scanned) | 5594 | unsigned long last_scanned) |
5595 | { | 5595 | { |
5596 | u16 capabilities; | 5596 | u16 capabilities; |
5597 | u16 channel; | 5597 | u16 channel; |
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 42bd38ac7a1d..78fca1bcc544 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c | |||
@@ -69,14 +69,14 @@ static void rt2400pci_bbp_write(struct rt2x00_dev *rt2x00dev, | |||
69 | { | 69 | { |
70 | u32 reg; | 70 | u32 reg; |
71 | 71 | ||
72 | mutex_lock(&rt2x00dev->csr_mutex); | ||
73 | |||
72 | /* | 74 | /* |
73 | * Wait until the BBP becomes ready. | 75 | * Wait until the BBP becomes ready. |
74 | */ | 76 | */ |
75 | reg = rt2400pci_bbp_check(rt2x00dev); | 77 | reg = rt2400pci_bbp_check(rt2x00dev); |
76 | if (rt2x00_get_field32(reg, BBPCSR_BUSY)) { | 78 | if (rt2x00_get_field32(reg, BBPCSR_BUSY)) |
77 | ERROR(rt2x00dev, "BBPCSR register busy. Write failed.\n"); | 79 | goto exit_fail; |
78 | return; | ||
79 | } | ||
80 | 80 | ||
81 | /* | 81 | /* |
82 | * Write the data into the BBP. | 82 | * Write the data into the BBP. |
@@ -88,6 +88,15 @@ static void rt2400pci_bbp_write(struct rt2x00_dev *rt2x00dev, | |||
88 | rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 1); | 88 | rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 1); |
89 | 89 | ||
90 | rt2x00pci_register_write(rt2x00dev, BBPCSR, reg); | 90 | rt2x00pci_register_write(rt2x00dev, BBPCSR, reg); |
91 | |||
92 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
93 | |||
94 | return; | ||
95 | |||
96 | exit_fail: | ||
97 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
98 | |||
99 | ERROR(rt2x00dev, "BBPCSR register busy. Write failed.\n"); | ||
91 | } | 100 | } |
92 | 101 | ||
93 | static void rt2400pci_bbp_read(struct rt2x00_dev *rt2x00dev, | 102 | static void rt2400pci_bbp_read(struct rt2x00_dev *rt2x00dev, |
@@ -95,14 +104,14 @@ static void rt2400pci_bbp_read(struct rt2x00_dev *rt2x00dev, | |||
95 | { | 104 | { |
96 | u32 reg; | 105 | u32 reg; |
97 | 106 | ||
107 | mutex_lock(&rt2x00dev->csr_mutex); | ||
108 | |||
98 | /* | 109 | /* |
99 | * Wait until the BBP becomes ready. | 110 | * Wait until the BBP becomes ready. |
100 | */ | 111 | */ |
101 | reg = rt2400pci_bbp_check(rt2x00dev); | 112 | reg = rt2400pci_bbp_check(rt2x00dev); |
102 | if (rt2x00_get_field32(reg, BBPCSR_BUSY)) { | 113 | if (rt2x00_get_field32(reg, BBPCSR_BUSY)) |
103 | ERROR(rt2x00dev, "BBPCSR register busy. Read failed.\n"); | 114 | goto exit_fail; |
104 | return; | ||
105 | } | ||
106 | 115 | ||
107 | /* | 116 | /* |
108 | * Write the request into the BBP. | 117 | * Write the request into the BBP. |
@@ -118,13 +127,20 @@ static void rt2400pci_bbp_read(struct rt2x00_dev *rt2x00dev, | |||
118 | * Wait until the BBP becomes ready. | 127 | * Wait until the BBP becomes ready. |
119 | */ | 128 | */ |
120 | reg = rt2400pci_bbp_check(rt2x00dev); | 129 | reg = rt2400pci_bbp_check(rt2x00dev); |
121 | if (rt2x00_get_field32(reg, BBPCSR_BUSY)) { | 130 | if (rt2x00_get_field32(reg, BBPCSR_BUSY)) |
122 | ERROR(rt2x00dev, "BBPCSR register busy. Read failed.\n"); | 131 | goto exit_fail; |
123 | *value = 0xff; | ||
124 | return; | ||
125 | } | ||
126 | 132 | ||
127 | *value = rt2x00_get_field32(reg, BBPCSR_VALUE); | 133 | *value = rt2x00_get_field32(reg, BBPCSR_VALUE); |
134 | |||
135 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
136 | |||
137 | return; | ||
138 | |||
139 | exit_fail: | ||
140 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
141 | |||
142 | ERROR(rt2x00dev, "BBPCSR register busy. Read failed.\n"); | ||
143 | *value = 0xff; | ||
128 | } | 144 | } |
129 | 145 | ||
130 | static void rt2400pci_rf_write(struct rt2x00_dev *rt2x00dev, | 146 | static void rt2400pci_rf_write(struct rt2x00_dev *rt2x00dev, |
@@ -136,6 +152,8 @@ static void rt2400pci_rf_write(struct rt2x00_dev *rt2x00dev, | |||
136 | if (!word) | 152 | if (!word) |
137 | return; | 153 | return; |
138 | 154 | ||
155 | mutex_lock(&rt2x00dev->csr_mutex); | ||
156 | |||
139 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | 157 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { |
140 | rt2x00pci_register_read(rt2x00dev, RFCSR, ®); | 158 | rt2x00pci_register_read(rt2x00dev, RFCSR, ®); |
141 | if (!rt2x00_get_field32(reg, RFCSR_BUSY)) | 159 | if (!rt2x00_get_field32(reg, RFCSR_BUSY)) |
@@ -143,6 +161,7 @@ static void rt2400pci_rf_write(struct rt2x00_dev *rt2x00dev, | |||
143 | udelay(REGISTER_BUSY_DELAY); | 161 | udelay(REGISTER_BUSY_DELAY); |
144 | } | 162 | } |
145 | 163 | ||
164 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
146 | ERROR(rt2x00dev, "RFCSR register busy. Write failed.\n"); | 165 | ERROR(rt2x00dev, "RFCSR register busy. Write failed.\n"); |
147 | return; | 166 | return; |
148 | 167 | ||
@@ -155,6 +174,8 @@ rf_write: | |||
155 | 174 | ||
156 | rt2x00pci_register_write(rt2x00dev, RFCSR, reg); | 175 | rt2x00pci_register_write(rt2x00dev, RFCSR, reg); |
157 | rt2x00_rf_write(rt2x00dev, word, value); | 176 | rt2x00_rf_write(rt2x00dev, word, value); |
177 | |||
178 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
158 | } | 179 | } |
159 | 180 | ||
160 | static void rt2400pci_eepromregister_read(struct eeprom_93cx6 *eeprom) | 181 | static void rt2400pci_eepromregister_read(struct eeprom_93cx6 *eeprom) |
@@ -322,7 +343,7 @@ static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev, | |||
322 | /* | 343 | /* |
323 | * Enable beacon config | 344 | * Enable beacon config |
324 | */ | 345 | */ |
325 | bcn_preload = PREAMBLE + get_duration(IEEE80211_HEADER, 20); | 346 | bcn_preload = PREAMBLE + GET_DURATION(IEEE80211_HEADER, 20); |
326 | rt2x00pci_register_read(rt2x00dev, BCNCSR1, ®); | 347 | rt2x00pci_register_read(rt2x00dev, BCNCSR1, ®); |
327 | rt2x00_set_field32(®, BCNCSR1_PRELOAD, bcn_preload); | 348 | rt2x00_set_field32(®, BCNCSR1_PRELOAD, bcn_preload); |
328 | rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg); | 349 | rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg); |
@@ -367,25 +388,25 @@ static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev, | |||
367 | rt2x00pci_register_read(rt2x00dev, ARCSR2, ®); | 388 | rt2x00pci_register_read(rt2x00dev, ARCSR2, ®); |
368 | rt2x00_set_field32(®, ARCSR2_SIGNAL, 0x00); | 389 | rt2x00_set_field32(®, ARCSR2_SIGNAL, 0x00); |
369 | rt2x00_set_field32(®, ARCSR2_SERVICE, 0x04); | 390 | rt2x00_set_field32(®, ARCSR2_SERVICE, 0x04); |
370 | rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 10)); | 391 | rt2x00_set_field32(®, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 10)); |
371 | rt2x00pci_register_write(rt2x00dev, ARCSR2, reg); | 392 | rt2x00pci_register_write(rt2x00dev, ARCSR2, reg); |
372 | 393 | ||
373 | rt2x00pci_register_read(rt2x00dev, ARCSR3, ®); | 394 | rt2x00pci_register_read(rt2x00dev, ARCSR3, ®); |
374 | rt2x00_set_field32(®, ARCSR3_SIGNAL, 0x01 | preamble_mask); | 395 | rt2x00_set_field32(®, ARCSR3_SIGNAL, 0x01 | preamble_mask); |
375 | rt2x00_set_field32(®, ARCSR3_SERVICE, 0x04); | 396 | rt2x00_set_field32(®, ARCSR3_SERVICE, 0x04); |
376 | rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 20)); | 397 | rt2x00_set_field32(®, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 20)); |
377 | rt2x00pci_register_write(rt2x00dev, ARCSR3, reg); | 398 | rt2x00pci_register_write(rt2x00dev, ARCSR3, reg); |
378 | 399 | ||
379 | rt2x00pci_register_read(rt2x00dev, ARCSR4, ®); | 400 | rt2x00pci_register_read(rt2x00dev, ARCSR4, ®); |
380 | rt2x00_set_field32(®, ARCSR4_SIGNAL, 0x02 | preamble_mask); | 401 | rt2x00_set_field32(®, ARCSR4_SIGNAL, 0x02 | preamble_mask); |
381 | rt2x00_set_field32(®, ARCSR4_SERVICE, 0x04); | 402 | rt2x00_set_field32(®, ARCSR4_SERVICE, 0x04); |
382 | rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 55)); | 403 | rt2x00_set_field32(®, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 55)); |
383 | rt2x00pci_register_write(rt2x00dev, ARCSR4, reg); | 404 | rt2x00pci_register_write(rt2x00dev, ARCSR4, reg); |
384 | 405 | ||
385 | rt2x00pci_register_read(rt2x00dev, ARCSR5, ®); | 406 | rt2x00pci_register_read(rt2x00dev, ARCSR5, ®); |
386 | rt2x00_set_field32(®, ARCSR5_SIGNAL, 0x03 | preamble_mask); | 407 | rt2x00_set_field32(®, ARCSR5_SIGNAL, 0x03 | preamble_mask); |
387 | rt2x00_set_field32(®, ARCSR5_SERVICE, 0x84); | 408 | rt2x00_set_field32(®, ARCSR5_SERVICE, 0x84); |
388 | rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 110)); | 409 | rt2x00_set_field32(®, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 110)); |
389 | rt2x00pci_register_write(rt2x00dev, ARCSR5, reg); | 410 | rt2x00pci_register_write(rt2x00dev, ARCSR5, reg); |
390 | 411 | ||
391 | rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates); | 412 | rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates); |
@@ -626,36 +647,47 @@ static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev) | |||
626 | /* | 647 | /* |
627 | * Initialization functions. | 648 | * Initialization functions. |
628 | */ | 649 | */ |
629 | static void rt2400pci_init_rxentry(struct rt2x00_dev *rt2x00dev, | 650 | static bool rt2400pci_get_entry_state(struct queue_entry *entry) |
630 | struct queue_entry *entry) | ||
631 | { | 651 | { |
632 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | 652 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; |
633 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | ||
634 | u32 word; | 653 | u32 word; |
635 | 654 | ||
636 | rt2x00_desc_read(entry_priv->desc, 2, &word); | 655 | if (entry->queue->qid == QID_RX) { |
637 | rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH, entry->skb->len); | 656 | rt2x00_desc_read(entry_priv->desc, 0, &word); |
638 | rt2x00_desc_write(entry_priv->desc, 2, word); | ||
639 | 657 | ||
640 | rt2x00_desc_read(entry_priv->desc, 1, &word); | 658 | return rt2x00_get_field32(word, RXD_W0_OWNER_NIC); |
641 | rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma); | 659 | } else { |
642 | rt2x00_desc_write(entry_priv->desc, 1, word); | 660 | rt2x00_desc_read(entry_priv->desc, 0, &word); |
643 | 661 | ||
644 | rt2x00_desc_read(entry_priv->desc, 0, &word); | 662 | return (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) || |
645 | rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1); | 663 | rt2x00_get_field32(word, TXD_W0_VALID)); |
646 | rt2x00_desc_write(entry_priv->desc, 0, word); | 664 | } |
647 | } | 665 | } |
648 | 666 | ||
649 | static void rt2400pci_init_txentry(struct rt2x00_dev *rt2x00dev, | 667 | static void rt2400pci_clear_entry(struct queue_entry *entry) |
650 | struct queue_entry *entry) | ||
651 | { | 668 | { |
652 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | 669 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; |
670 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | ||
653 | u32 word; | 671 | u32 word; |
654 | 672 | ||
655 | rt2x00_desc_read(entry_priv->desc, 0, &word); | 673 | if (entry->queue->qid == QID_RX) { |
656 | rt2x00_set_field32(&word, TXD_W0_VALID, 0); | 674 | rt2x00_desc_read(entry_priv->desc, 2, &word); |
657 | rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0); | 675 | rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH, entry->skb->len); |
658 | rt2x00_desc_write(entry_priv->desc, 0, word); | 676 | rt2x00_desc_write(entry_priv->desc, 2, word); |
677 | |||
678 | rt2x00_desc_read(entry_priv->desc, 1, &word); | ||
679 | rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma); | ||
680 | rt2x00_desc_write(entry_priv->desc, 1, word); | ||
681 | |||
682 | rt2x00_desc_read(entry_priv->desc, 0, &word); | ||
683 | rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1); | ||
684 | rt2x00_desc_write(entry_priv->desc, 0, word); | ||
685 | } else { | ||
686 | rt2x00_desc_read(entry_priv->desc, 0, &word); | ||
687 | rt2x00_set_field32(&word, TXD_W0_VALID, 0); | ||
688 | rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0); | ||
689 | rt2x00_desc_write(entry_priv->desc, 0, word); | ||
690 | } | ||
659 | } | 691 | } |
660 | 692 | ||
661 | static int rt2400pci_init_queues(struct rt2x00_dev *rt2x00dev) | 693 | static int rt2400pci_init_queues(struct rt2x00_dev *rt2x00dev) |
@@ -1570,8 +1602,8 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { | |||
1570 | .probe_hw = rt2400pci_probe_hw, | 1602 | .probe_hw = rt2400pci_probe_hw, |
1571 | .initialize = rt2x00pci_initialize, | 1603 | .initialize = rt2x00pci_initialize, |
1572 | .uninitialize = rt2x00pci_uninitialize, | 1604 | .uninitialize = rt2x00pci_uninitialize, |
1573 | .init_rxentry = rt2400pci_init_rxentry, | 1605 | .get_entry_state = rt2400pci_get_entry_state, |
1574 | .init_txentry = rt2400pci_init_txentry, | 1606 | .clear_entry = rt2400pci_clear_entry, |
1575 | .set_device_state = rt2400pci_set_device_state, | 1607 | .set_device_state = rt2400pci_set_device_state, |
1576 | .rfkill_poll = rt2400pci_rfkill_poll, | 1608 | .rfkill_poll = rt2400pci_rfkill_poll, |
1577 | .link_stats = rt2400pci_link_stats, | 1609 | .link_stats = rt2400pci_link_stats, |
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 928452f30c25..972b5a5c3864 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c | |||
@@ -69,14 +69,14 @@ static void rt2500pci_bbp_write(struct rt2x00_dev *rt2x00dev, | |||
69 | { | 69 | { |
70 | u32 reg; | 70 | u32 reg; |
71 | 71 | ||
72 | mutex_lock(&rt2x00dev->csr_mutex); | ||
73 | |||
72 | /* | 74 | /* |
73 | * Wait until the BBP becomes ready. | 75 | * Wait until the BBP becomes ready. |
74 | */ | 76 | */ |
75 | reg = rt2500pci_bbp_check(rt2x00dev); | 77 | reg = rt2500pci_bbp_check(rt2x00dev); |
76 | if (rt2x00_get_field32(reg, BBPCSR_BUSY)) { | 78 | if (rt2x00_get_field32(reg, BBPCSR_BUSY)) |
77 | ERROR(rt2x00dev, "BBPCSR register busy. Write failed.\n"); | 79 | goto exit_fail; |
78 | return; | ||
79 | } | ||
80 | 80 | ||
81 | /* | 81 | /* |
82 | * Write the data into the BBP. | 82 | * Write the data into the BBP. |
@@ -88,6 +88,15 @@ static void rt2500pci_bbp_write(struct rt2x00_dev *rt2x00dev, | |||
88 | rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 1); | 88 | rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 1); |
89 | 89 | ||
90 | rt2x00pci_register_write(rt2x00dev, BBPCSR, reg); | 90 | rt2x00pci_register_write(rt2x00dev, BBPCSR, reg); |
91 | |||
92 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
93 | |||
94 | return; | ||
95 | |||
96 | exit_fail: | ||
97 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
98 | |||
99 | ERROR(rt2x00dev, "BBPCSR register busy. Write failed.\n"); | ||
91 | } | 100 | } |
92 | 101 | ||
93 | static void rt2500pci_bbp_read(struct rt2x00_dev *rt2x00dev, | 102 | static void rt2500pci_bbp_read(struct rt2x00_dev *rt2x00dev, |
@@ -95,14 +104,14 @@ static void rt2500pci_bbp_read(struct rt2x00_dev *rt2x00dev, | |||
95 | { | 104 | { |
96 | u32 reg; | 105 | u32 reg; |
97 | 106 | ||
107 | mutex_lock(&rt2x00dev->csr_mutex); | ||
108 | |||
98 | /* | 109 | /* |
99 | * Wait until the BBP becomes ready. | 110 | * Wait until the BBP becomes ready. |
100 | */ | 111 | */ |
101 | reg = rt2500pci_bbp_check(rt2x00dev); | 112 | reg = rt2500pci_bbp_check(rt2x00dev); |
102 | if (rt2x00_get_field32(reg, BBPCSR_BUSY)) { | 113 | if (rt2x00_get_field32(reg, BBPCSR_BUSY)) |
103 | ERROR(rt2x00dev, "BBPCSR register busy. Read failed.\n"); | 114 | goto exit_fail; |
104 | return; | ||
105 | } | ||
106 | 115 | ||
107 | /* | 116 | /* |
108 | * Write the request into the BBP. | 117 | * Write the request into the BBP. |
@@ -118,13 +127,20 @@ static void rt2500pci_bbp_read(struct rt2x00_dev *rt2x00dev, | |||
118 | * Wait until the BBP becomes ready. | 127 | * Wait until the BBP becomes ready. |
119 | */ | 128 | */ |
120 | reg = rt2500pci_bbp_check(rt2x00dev); | 129 | reg = rt2500pci_bbp_check(rt2x00dev); |
121 | if (rt2x00_get_field32(reg, BBPCSR_BUSY)) { | 130 | if (rt2x00_get_field32(reg, BBPCSR_BUSY)) |
122 | ERROR(rt2x00dev, "BBPCSR register busy. Read failed.\n"); | 131 | goto exit_fail; |
123 | *value = 0xff; | ||
124 | return; | ||
125 | } | ||
126 | 132 | ||
127 | *value = rt2x00_get_field32(reg, BBPCSR_VALUE); | 133 | *value = rt2x00_get_field32(reg, BBPCSR_VALUE); |
134 | |||
135 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
136 | |||
137 | return; | ||
138 | |||
139 | exit_fail: | ||
140 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
141 | |||
142 | ERROR(rt2x00dev, "BBPCSR register busy. Read failed.\n"); | ||
143 | *value = 0xff; | ||
128 | } | 144 | } |
129 | 145 | ||
130 | static void rt2500pci_rf_write(struct rt2x00_dev *rt2x00dev, | 146 | static void rt2500pci_rf_write(struct rt2x00_dev *rt2x00dev, |
@@ -136,6 +152,8 @@ static void rt2500pci_rf_write(struct rt2x00_dev *rt2x00dev, | |||
136 | if (!word) | 152 | if (!word) |
137 | return; | 153 | return; |
138 | 154 | ||
155 | mutex_lock(&rt2x00dev->csr_mutex); | ||
156 | |||
139 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | 157 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { |
140 | rt2x00pci_register_read(rt2x00dev, RFCSR, ®); | 158 | rt2x00pci_register_read(rt2x00dev, RFCSR, ®); |
141 | if (!rt2x00_get_field32(reg, RFCSR_BUSY)) | 159 | if (!rt2x00_get_field32(reg, RFCSR_BUSY)) |
@@ -143,6 +161,7 @@ static void rt2500pci_rf_write(struct rt2x00_dev *rt2x00dev, | |||
143 | udelay(REGISTER_BUSY_DELAY); | 161 | udelay(REGISTER_BUSY_DELAY); |
144 | } | 162 | } |
145 | 163 | ||
164 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
146 | ERROR(rt2x00dev, "RFCSR register busy. Write failed.\n"); | 165 | ERROR(rt2x00dev, "RFCSR register busy. Write failed.\n"); |
147 | return; | 166 | return; |
148 | 167 | ||
@@ -155,6 +174,8 @@ rf_write: | |||
155 | 174 | ||
156 | rt2x00pci_register_write(rt2x00dev, RFCSR, reg); | 175 | rt2x00pci_register_write(rt2x00dev, RFCSR, reg); |
157 | rt2x00_rf_write(rt2x00dev, word, value); | 176 | rt2x00_rf_write(rt2x00dev, word, value); |
177 | |||
178 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
158 | } | 179 | } |
159 | 180 | ||
160 | static void rt2500pci_eepromregister_read(struct eeprom_93cx6 *eeprom) | 181 | static void rt2500pci_eepromregister_read(struct eeprom_93cx6 *eeprom) |
@@ -327,7 +348,7 @@ static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev, | |||
327 | /* | 348 | /* |
328 | * Enable beacon config | 349 | * Enable beacon config |
329 | */ | 350 | */ |
330 | bcn_preload = PREAMBLE + get_duration(IEEE80211_HEADER, 20); | 351 | bcn_preload = PREAMBLE + GET_DURATION(IEEE80211_HEADER, 20); |
331 | rt2x00pci_register_read(rt2x00dev, BCNCSR1, ®); | 352 | rt2x00pci_register_read(rt2x00dev, BCNCSR1, ®); |
332 | rt2x00_set_field32(®, BCNCSR1_PRELOAD, bcn_preload); | 353 | rt2x00_set_field32(®, BCNCSR1_PRELOAD, bcn_preload); |
333 | rt2x00_set_field32(®, BCNCSR1_BEACON_CWMIN, queue->cw_min); | 354 | rt2x00_set_field32(®, BCNCSR1_BEACON_CWMIN, queue->cw_min); |
@@ -373,25 +394,25 @@ static void rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev, | |||
373 | rt2x00pci_register_read(rt2x00dev, ARCSR2, ®); | 394 | rt2x00pci_register_read(rt2x00dev, ARCSR2, ®); |
374 | rt2x00_set_field32(®, ARCSR2_SIGNAL, 0x00); | 395 | rt2x00_set_field32(®, ARCSR2_SIGNAL, 0x00); |
375 | rt2x00_set_field32(®, ARCSR2_SERVICE, 0x04); | 396 | rt2x00_set_field32(®, ARCSR2_SERVICE, 0x04); |
376 | rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 10)); | 397 | rt2x00_set_field32(®, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 10)); |
377 | rt2x00pci_register_write(rt2x00dev, ARCSR2, reg); | 398 | rt2x00pci_register_write(rt2x00dev, ARCSR2, reg); |
378 | 399 | ||
379 | rt2x00pci_register_read(rt2x00dev, ARCSR3, ®); | 400 | rt2x00pci_register_read(rt2x00dev, ARCSR3, ®); |
380 | rt2x00_set_field32(®, ARCSR3_SIGNAL, 0x01 | preamble_mask); | 401 | rt2x00_set_field32(®, ARCSR3_SIGNAL, 0x01 | preamble_mask); |
381 | rt2x00_set_field32(®, ARCSR3_SERVICE, 0x04); | 402 | rt2x00_set_field32(®, ARCSR3_SERVICE, 0x04); |
382 | rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 20)); | 403 | rt2x00_set_field32(®, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 20)); |
383 | rt2x00pci_register_write(rt2x00dev, ARCSR3, reg); | 404 | rt2x00pci_register_write(rt2x00dev, ARCSR3, reg); |
384 | 405 | ||
385 | rt2x00pci_register_read(rt2x00dev, ARCSR4, ®); | 406 | rt2x00pci_register_read(rt2x00dev, ARCSR4, ®); |
386 | rt2x00_set_field32(®, ARCSR4_SIGNAL, 0x02 | preamble_mask); | 407 | rt2x00_set_field32(®, ARCSR4_SIGNAL, 0x02 | preamble_mask); |
387 | rt2x00_set_field32(®, ARCSR4_SERVICE, 0x04); | 408 | rt2x00_set_field32(®, ARCSR4_SERVICE, 0x04); |
388 | rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 55)); | 409 | rt2x00_set_field32(®, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 55)); |
389 | rt2x00pci_register_write(rt2x00dev, ARCSR4, reg); | 410 | rt2x00pci_register_write(rt2x00dev, ARCSR4, reg); |
390 | 411 | ||
391 | rt2x00pci_register_read(rt2x00dev, ARCSR5, ®); | 412 | rt2x00pci_register_read(rt2x00dev, ARCSR5, ®); |
392 | rt2x00_set_field32(®, ARCSR5_SIGNAL, 0x03 | preamble_mask); | 413 | rt2x00_set_field32(®, ARCSR5_SIGNAL, 0x03 | preamble_mask); |
393 | rt2x00_set_field32(®, ARCSR5_SERVICE, 0x84); | 414 | rt2x00_set_field32(®, ARCSR5_SERVICE, 0x84); |
394 | rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 110)); | 415 | rt2x00_set_field32(®, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 110)); |
395 | rt2x00pci_register_write(rt2x00dev, ARCSR5, reg); | 416 | rt2x00pci_register_write(rt2x00dev, ARCSR5, reg); |
396 | 417 | ||
397 | rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates); | 418 | rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates); |
@@ -722,32 +743,43 @@ dynamic_cca_tune: | |||
722 | /* | 743 | /* |
723 | * Initialization functions. | 744 | * Initialization functions. |
724 | */ | 745 | */ |
725 | static void rt2500pci_init_rxentry(struct rt2x00_dev *rt2x00dev, | 746 | static bool rt2500pci_get_entry_state(struct queue_entry *entry) |
726 | struct queue_entry *entry) | ||
727 | { | 747 | { |
728 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | 748 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; |
729 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | ||
730 | u32 word; | 749 | u32 word; |
731 | 750 | ||
732 | rt2x00_desc_read(entry_priv->desc, 1, &word); | 751 | if (entry->queue->qid == QID_RX) { |
733 | rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma); | 752 | rt2x00_desc_read(entry_priv->desc, 0, &word); |
734 | rt2x00_desc_write(entry_priv->desc, 1, word); | ||
735 | 753 | ||
736 | rt2x00_desc_read(entry_priv->desc, 0, &word); | 754 | return rt2x00_get_field32(word, RXD_W0_OWNER_NIC); |
737 | rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1); | 755 | } else { |
738 | rt2x00_desc_write(entry_priv->desc, 0, word); | 756 | rt2x00_desc_read(entry_priv->desc, 0, &word); |
757 | |||
758 | return (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) || | ||
759 | rt2x00_get_field32(word, TXD_W0_VALID)); | ||
760 | } | ||
739 | } | 761 | } |
740 | 762 | ||
741 | static void rt2500pci_init_txentry(struct rt2x00_dev *rt2x00dev, | 763 | static void rt2500pci_clear_entry(struct queue_entry *entry) |
742 | struct queue_entry *entry) | ||
743 | { | 764 | { |
744 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | 765 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; |
766 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | ||
745 | u32 word; | 767 | u32 word; |
746 | 768 | ||
747 | rt2x00_desc_read(entry_priv->desc, 0, &word); | 769 | if (entry->queue->qid == QID_RX) { |
748 | rt2x00_set_field32(&word, TXD_W0_VALID, 0); | 770 | rt2x00_desc_read(entry_priv->desc, 1, &word); |
749 | rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0); | 771 | rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma); |
750 | rt2x00_desc_write(entry_priv->desc, 0, word); | 772 | rt2x00_desc_write(entry_priv->desc, 1, word); |
773 | |||
774 | rt2x00_desc_read(entry_priv->desc, 0, &word); | ||
775 | rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1); | ||
776 | rt2x00_desc_write(entry_priv->desc, 0, word); | ||
777 | } else { | ||
778 | rt2x00_desc_read(entry_priv->desc, 0, &word); | ||
779 | rt2x00_set_field32(&word, TXD_W0_VALID, 0); | ||
780 | rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0); | ||
781 | rt2x00_desc_write(entry_priv->desc, 0, word); | ||
782 | } | ||
751 | } | 783 | } |
752 | 784 | ||
753 | static int rt2500pci_init_queues(struct rt2x00_dev *rt2x00dev) | 785 | static int rt2500pci_init_queues(struct rt2x00_dev *rt2x00dev) |
@@ -1871,8 +1903,8 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { | |||
1871 | .probe_hw = rt2500pci_probe_hw, | 1903 | .probe_hw = rt2500pci_probe_hw, |
1872 | .initialize = rt2x00pci_initialize, | 1904 | .initialize = rt2x00pci_initialize, |
1873 | .uninitialize = rt2x00pci_uninitialize, | 1905 | .uninitialize = rt2x00pci_uninitialize, |
1874 | .init_rxentry = rt2500pci_init_rxentry, | 1906 | .get_entry_state = rt2500pci_get_entry_state, |
1875 | .init_txentry = rt2500pci_init_txentry, | 1907 | .clear_entry = rt2500pci_clear_entry, |
1876 | .set_device_state = rt2500pci_set_device_state, | 1908 | .set_device_state = rt2500pci_set_device_state, |
1877 | .rfkill_poll = rt2500pci_rfkill_poll, | 1909 | .rfkill_poll = rt2500pci_rfkill_poll, |
1878 | .link_stats = rt2500pci_link_stats, | 1910 | .link_stats = rt2500pci_link_stats, |
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 639d5a2f84e2..e6bae4ae4c47 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c | |||
@@ -47,7 +47,7 @@ | |||
47 | * between each attampt. When the busy bit is still set at that time, | 47 | * between each attampt. When the busy bit is still set at that time, |
48 | * the access attempt is considered to have failed, | 48 | * the access attempt is considered to have failed, |
49 | * and we will print an error. | 49 | * and we will print an error. |
50 | * If the usb_cache_mutex is already held then the _lock variants must | 50 | * If the csr_mutex is already held then the _lock variants must |
51 | * be used instead. | 51 | * be used instead. |
52 | */ | 52 | */ |
53 | static inline void rt2500usb_register_read(struct rt2x00_dev *rt2x00dev, | 53 | static inline void rt2500usb_register_read(struct rt2x00_dev *rt2x00dev, |
@@ -132,7 +132,7 @@ static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev, | |||
132 | { | 132 | { |
133 | u16 reg; | 133 | u16 reg; |
134 | 134 | ||
135 | mutex_lock(&rt2x00dev->usb_cache_mutex); | 135 | mutex_lock(&rt2x00dev->csr_mutex); |
136 | 136 | ||
137 | /* | 137 | /* |
138 | * Wait until the BBP becomes ready. | 138 | * Wait until the BBP becomes ready. |
@@ -151,12 +151,12 @@ static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev, | |||
151 | 151 | ||
152 | rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg); | 152 | rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg); |
153 | 153 | ||
154 | mutex_unlock(&rt2x00dev->usb_cache_mutex); | 154 | mutex_unlock(&rt2x00dev->csr_mutex); |
155 | 155 | ||
156 | return; | 156 | return; |
157 | 157 | ||
158 | exit_fail: | 158 | exit_fail: |
159 | mutex_unlock(&rt2x00dev->usb_cache_mutex); | 159 | mutex_unlock(&rt2x00dev->csr_mutex); |
160 | 160 | ||
161 | ERROR(rt2x00dev, "PHY_CSR8 register busy. Write failed.\n"); | 161 | ERROR(rt2x00dev, "PHY_CSR8 register busy. Write failed.\n"); |
162 | } | 162 | } |
@@ -166,7 +166,7 @@ static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev, | |||
166 | { | 166 | { |
167 | u16 reg; | 167 | u16 reg; |
168 | 168 | ||
169 | mutex_lock(&rt2x00dev->usb_cache_mutex); | 169 | mutex_lock(&rt2x00dev->csr_mutex); |
170 | 170 | ||
171 | /* | 171 | /* |
172 | * Wait until the BBP becomes ready. | 172 | * Wait until the BBP becomes ready. |
@@ -194,12 +194,12 @@ static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev, | |||
194 | rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, ®); | 194 | rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, ®); |
195 | *value = rt2x00_get_field16(reg, PHY_CSR7_DATA); | 195 | *value = rt2x00_get_field16(reg, PHY_CSR7_DATA); |
196 | 196 | ||
197 | mutex_unlock(&rt2x00dev->usb_cache_mutex); | 197 | mutex_unlock(&rt2x00dev->csr_mutex); |
198 | 198 | ||
199 | return; | 199 | return; |
200 | 200 | ||
201 | exit_fail: | 201 | exit_fail: |
202 | mutex_unlock(&rt2x00dev->usb_cache_mutex); | 202 | mutex_unlock(&rt2x00dev->csr_mutex); |
203 | 203 | ||
204 | ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n"); | 204 | ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n"); |
205 | *value = 0xff; | 205 | *value = 0xff; |
@@ -214,7 +214,7 @@ static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev, | |||
214 | if (!word) | 214 | if (!word) |
215 | return; | 215 | return; |
216 | 216 | ||
217 | mutex_lock(&rt2x00dev->usb_cache_mutex); | 217 | mutex_lock(&rt2x00dev->csr_mutex); |
218 | 218 | ||
219 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | 219 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { |
220 | rt2500usb_register_read_lock(rt2x00dev, PHY_CSR10, ®); | 220 | rt2500usb_register_read_lock(rt2x00dev, PHY_CSR10, ®); |
@@ -223,7 +223,7 @@ static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev, | |||
223 | udelay(REGISTER_BUSY_DELAY); | 223 | udelay(REGISTER_BUSY_DELAY); |
224 | } | 224 | } |
225 | 225 | ||
226 | mutex_unlock(&rt2x00dev->usb_cache_mutex); | 226 | mutex_unlock(&rt2x00dev->csr_mutex); |
227 | ERROR(rt2x00dev, "PHY_CSR10 register busy. Write failed.\n"); | 227 | ERROR(rt2x00dev, "PHY_CSR10 register busy. Write failed.\n"); |
228 | return; | 228 | return; |
229 | 229 | ||
@@ -241,7 +241,7 @@ rf_write: | |||
241 | rt2500usb_register_write_lock(rt2x00dev, PHY_CSR10, reg); | 241 | rt2500usb_register_write_lock(rt2x00dev, PHY_CSR10, reg); |
242 | rt2x00_rf_write(rt2x00dev, word, value); | 242 | rt2x00_rf_write(rt2x00dev, word, value); |
243 | 243 | ||
244 | mutex_unlock(&rt2x00dev->usb_cache_mutex); | 244 | mutex_unlock(&rt2x00dev->csr_mutex); |
245 | } | 245 | } |
246 | 246 | ||
247 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS | 247 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS |
@@ -385,7 +385,7 @@ static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev, | |||
385 | /* | 385 | /* |
386 | * Enable beacon config | 386 | * Enable beacon config |
387 | */ | 387 | */ |
388 | bcn_preload = PREAMBLE + get_duration(IEEE80211_HEADER, 20); | 388 | bcn_preload = PREAMBLE + GET_DURATION(IEEE80211_HEADER, 20); |
389 | rt2500usb_register_read(rt2x00dev, TXRX_CSR20, ®); | 389 | rt2500usb_register_read(rt2x00dev, TXRX_CSR20, ®); |
390 | rt2x00_set_field16(®, TXRX_CSR20_OFFSET, bcn_preload >> 6); | 390 | rt2x00_set_field16(®, TXRX_CSR20_OFFSET, bcn_preload >> 6); |
391 | rt2x00_set_field16(®, TXRX_CSR20_BCN_EXPECT_WINDOW, | 391 | rt2x00_set_field16(®, TXRX_CSR20_BCN_EXPECT_WINDOW, |
@@ -1777,8 +1777,7 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { | |||
1777 | .probe_hw = rt2500usb_probe_hw, | 1777 | .probe_hw = rt2500usb_probe_hw, |
1778 | .initialize = rt2x00usb_initialize, | 1778 | .initialize = rt2x00usb_initialize, |
1779 | .uninitialize = rt2x00usb_uninitialize, | 1779 | .uninitialize = rt2x00usb_uninitialize, |
1780 | .init_rxentry = rt2x00usb_init_rxentry, | 1780 | .clear_entry = rt2x00usb_clear_entry, |
1781 | .init_txentry = rt2x00usb_init_txentry, | ||
1782 | .set_device_state = rt2500usb_set_device_state, | 1781 | .set_device_state = rt2500usb_set_device_state, |
1783 | .link_stats = rt2500usb_link_stats, | 1782 | .link_stats = rt2500usb_link_stats, |
1784 | .reset_tuner = rt2500usb_reset_tuner, | 1783 | .reset_tuner = rt2500usb_reset_tuner, |
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index f85eedbbad68..fee61bee1e7e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -92,6 +92,16 @@ | |||
92 | DEBUG_PRINTK(__dev, KERN_DEBUG, "EEPROM recovery", __msg, ##__args) | 92 | DEBUG_PRINTK(__dev, KERN_DEBUG, "EEPROM recovery", __msg, ##__args) |
93 | 93 | ||
94 | /* | 94 | /* |
95 | * Duration calculations | ||
96 | * The rate variable passed is: 100kbs. | ||
97 | * To convert from bytes to bits we multiply size with 8, | ||
98 | * then the size is multiplied with 10 to make the | ||
99 | * real rate -> rate argument correction. | ||
100 | */ | ||
101 | #define GET_DURATION(__size, __rate) (((__size) * 8 * 10) / (__rate)) | ||
102 | #define GET_DURATION_RES(__size, __rate)(((__size) * 8 * 10) % (__rate)) | ||
103 | |||
104 | /* | ||
95 | * Standard timing and size defines. | 105 | * Standard timing and size defines. |
96 | * These values should follow the ieee80211 specifications. | 106 | * These values should follow the ieee80211 specifications. |
97 | */ | 107 | */ |
@@ -109,9 +119,9 @@ | |||
109 | #define DIFS ( PIFS + SLOT_TIME ) | 119 | #define DIFS ( PIFS + SLOT_TIME ) |
110 | #define SHORT_DIFS ( SHORT_PIFS + SHORT_SLOT_TIME ) | 120 | #define SHORT_DIFS ( SHORT_PIFS + SHORT_SLOT_TIME ) |
111 | #define EIFS ( SIFS + DIFS + \ | 121 | #define EIFS ( SIFS + DIFS + \ |
112 | (8 * (IEEE80211_HEADER + ACK_SIZE)) ) | 122 | GET_DURATION(IEEE80211_HEADER + ACK_SIZE, 10) ) |
113 | #define SHORT_EIFS ( SIFS + SHORT_DIFS + \ | 123 | #define SHORT_EIFS ( SIFS + SHORT_DIFS + \ |
114 | (8 * (IEEE80211_HEADER + ACK_SIZE)) ) | 124 | GET_DURATION(IEEE80211_HEADER + ACK_SIZE, 10) ) |
115 | 125 | ||
116 | /* | 126 | /* |
117 | * Chipset identification | 127 | * Chipset identification |
@@ -523,10 +533,8 @@ struct rt2x00lib_ops { | |||
523 | /* | 533 | /* |
524 | * queue initialization handlers | 534 | * queue initialization handlers |
525 | */ | 535 | */ |
526 | void (*init_rxentry) (struct rt2x00_dev *rt2x00dev, | 536 | bool (*get_entry_state) (struct queue_entry *entry); |
527 | struct queue_entry *entry); | 537 | void (*clear_entry) (struct queue_entry *entry); |
528 | void (*init_txentry) (struct rt2x00_dev *rt2x00dev, | ||
529 | struct queue_entry *entry); | ||
530 | 538 | ||
531 | /* | 539 | /* |
532 | * Radio control handlers. | 540 | * Radio control handlers. |
@@ -723,8 +731,7 @@ struct rt2x00_dev { | |||
723 | 731 | ||
724 | /* | 732 | /* |
725 | * This is the default TX/RX antenna setup as indicated | 733 | * This is the default TX/RX antenna setup as indicated |
726 | * by the device's EEPROM. When mac80211 sets its | 734 | * by the device's EEPROM. |
727 | * antenna value to 0 we should be using these values. | ||
728 | */ | 735 | */ |
729 | struct antenna_setup default_ant; | 736 | struct antenna_setup default_ant; |
730 | 737 | ||
@@ -739,16 +746,15 @@ struct rt2x00_dev { | |||
739 | } csr; | 746 | } csr; |
740 | 747 | ||
741 | /* | 748 | /* |
742 | * Mutex to protect register accesses on USB devices. | 749 | * Mutex to protect register accesses. |
743 | * There are 2 reasons this is needed, one is to ensure | 750 | * For PCI and USB devices it protects against concurrent indirect |
744 | * use of the csr_cache (for USB devices) by one thread | 751 | * register access (BBP, RF, MCU) since accessing those |
745 | * isn't corrupted by another thread trying to access it. | 752 | * registers require multiple calls to the CSR registers. |
746 | * The other is that access to BBP and RF registers | 753 | * For USB devices it also protects the csr_cache since that |
747 | * require multiple BUS transactions and if another thread | 754 | * field is used for normal CSR access and it cannot support |
748 | * attempted to access one of those registers at the same | 755 | * multiple callers simultaneously. |
749 | * time one of the writes could silently fail. | ||
750 | */ | 756 | */ |
751 | struct mutex usb_cache_mutex; | 757 | struct mutex csr_mutex; |
752 | 758 | ||
753 | /* | 759 | /* |
754 | * Current packet filter configuration for the device. | 760 | * Current packet filter configuration for the device. |
@@ -923,23 +929,6 @@ static inline u16 rt2x00_check_rev(const struct rt2x00_chip *chipset, | |||
923 | !!(chipset->rev & 0x0000f)); | 929 | !!(chipset->rev & 0x0000f)); |
924 | } | 930 | } |
925 | 931 | ||
926 | /* | ||
927 | * Duration calculations | ||
928 | * The rate variable passed is: 100kbs. | ||
929 | * To convert from bytes to bits we multiply size with 8, | ||
930 | * then the size is multiplied with 10 to make the | ||
931 | * real rate -> rate argument correction. | ||
932 | */ | ||
933 | static inline u16 get_duration(const unsigned int size, const u8 rate) | ||
934 | { | ||
935 | return ((size * 8 * 10) / rate); | ||
936 | } | ||
937 | |||
938 | static inline u16 get_duration_res(const unsigned int size, const u8 rate) | ||
939 | { | ||
940 | return ((size * 8 * 10) % rate); | ||
941 | } | ||
942 | |||
943 | /** | 932 | /** |
944 | * rt2x00queue_map_txskb - Map a skb into DMA for TX purposes. | 933 | * rt2x00queue_map_txskb - Map a skb into DMA for TX purposes. |
945 | * @rt2x00dev: Pointer to &struct rt2x00_dev. | 934 | * @rt2x00dev: Pointer to &struct rt2x00_dev. |
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 3e4eee3ab7d2..7c62ce125b94 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c | |||
@@ -92,8 +92,8 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev, | |||
92 | erp.difs = bss_conf->use_short_slot ? SHORT_DIFS : DIFS; | 92 | erp.difs = bss_conf->use_short_slot ? SHORT_DIFS : DIFS; |
93 | erp.eifs = bss_conf->use_short_slot ? SHORT_EIFS : EIFS; | 93 | erp.eifs = bss_conf->use_short_slot ? SHORT_EIFS : EIFS; |
94 | 94 | ||
95 | erp.ack_timeout = PLCP + erp.difs + get_duration(ACK_SIZE, 10); | 95 | erp.ack_timeout = PLCP + erp.difs + GET_DURATION(ACK_SIZE, 10); |
96 | erp.ack_consume_time = SIFS + PLCP + get_duration(ACK_SIZE, 10); | 96 | erp.ack_consume_time = SIFS + PLCP + GET_DURATION(ACK_SIZE, 10); |
97 | 97 | ||
98 | if (bss_conf->use_short_preamble) { | 98 | if (bss_conf->use_short_preamble) { |
99 | erp.ack_timeout += SHORT_PREAMBLE; | 99 | erp.ack_timeout += SHORT_PREAMBLE; |
@@ -109,15 +109,32 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev, | |||
109 | } | 109 | } |
110 | 110 | ||
111 | void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, | 111 | void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, |
112 | enum antenna rx, enum antenna tx) | 112 | struct antenna_setup *ant) |
113 | { | 113 | { |
114 | struct antenna_setup ant; | 114 | /* |
115 | 115 | * Failsafe: Make sure we are not sending the | |
116 | ant.rx = rx; | 116 | * ANTENNA_SW_DIVERSITY state to the driver. |
117 | ant.tx = tx; | 117 | * If that happes fallback to hardware default, |
118 | * or our own default. | ||
119 | */ | ||
120 | if (ant->rx == ANTENNA_SW_DIVERSITY) { | ||
121 | if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY) | ||
122 | ant->rx = ANTENNA_B; | ||
123 | else | ||
124 | ant->rx = rt2x00dev->default_ant.rx; | ||
125 | } | ||
126 | if (ant->tx == ANTENNA_SW_DIVERSITY) { | ||
127 | if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY) | ||
128 | ant->tx = ANTENNA_B; | ||
129 | else | ||
130 | ant->tx = rt2x00dev->default_ant.tx; | ||
131 | } | ||
118 | 132 | ||
119 | if (rx == rt2x00dev->link.ant.active.rx && | 133 | /* |
120 | tx == rt2x00dev->link.ant.active.tx) | 134 | * Only reconfigure when something has changed. |
135 | */ | ||
136 | if (ant->rx == rt2x00dev->link.ant.active.rx && | ||
137 | ant->tx == rt2x00dev->link.ant.active.tx) | ||
121 | return; | 138 | return; |
122 | 139 | ||
123 | /* | 140 | /* |
@@ -132,12 +149,12 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, | |||
132 | * The latter is required since we need to recalibrate the | 149 | * The latter is required since we need to recalibrate the |
133 | * noise-sensitivity ratio for the new setup. | 150 | * noise-sensitivity ratio for the new setup. |
134 | */ | 151 | */ |
135 | rt2x00dev->ops->lib->config_ant(rt2x00dev, &ant); | 152 | rt2x00dev->ops->lib->config_ant(rt2x00dev, ant); |
136 | 153 | ||
137 | rt2x00lib_reset_link_tuner(rt2x00dev); | 154 | rt2x00lib_reset_link_tuner(rt2x00dev); |
138 | rt2x00_reset_link_ant_rssi(&rt2x00dev->link); | 155 | rt2x00_reset_link_ant_rssi(&rt2x00dev->link); |
139 | 156 | ||
140 | memcpy(&rt2x00dev->link.ant.active, &ant, sizeof(ant)); | 157 | memcpy(&rt2x00dev->link.ant.active, ant, sizeof(*ant)); |
141 | 158 | ||
142 | if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | 159 | if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) |
143 | rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON_LINK); | 160 | rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON_LINK); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 477a944167c4..7fc1d766062b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -101,8 +101,7 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev) | |||
101 | /* | 101 | /* |
102 | * Initialize all data queues. | 102 | * Initialize all data queues. |
103 | */ | 103 | */ |
104 | rt2x00queue_init_rx(rt2x00dev); | 104 | rt2x00queue_init_queues(rt2x00dev); |
105 | rt2x00queue_init_tx(rt2x00dev); | ||
106 | 105 | ||
107 | /* | 106 | /* |
108 | * Enable radio. | 107 | * Enable radio. |
@@ -176,13 +175,14 @@ void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, enum dev_state state) | |||
176 | 175 | ||
177 | static void rt2x00lib_evaluate_antenna_sample(struct rt2x00_dev *rt2x00dev) | 176 | static void rt2x00lib_evaluate_antenna_sample(struct rt2x00_dev *rt2x00dev) |
178 | { | 177 | { |
179 | enum antenna rx = rt2x00dev->link.ant.active.rx; | 178 | struct antenna_setup ant; |
180 | enum antenna tx = rt2x00dev->link.ant.active.tx; | ||
181 | int sample_a = | 179 | int sample_a = |
182 | rt2x00_get_link_ant_rssi_history(&rt2x00dev->link, ANTENNA_A); | 180 | rt2x00_get_link_ant_rssi_history(&rt2x00dev->link, ANTENNA_A); |
183 | int sample_b = | 181 | int sample_b = |
184 | rt2x00_get_link_ant_rssi_history(&rt2x00dev->link, ANTENNA_B); | 182 | rt2x00_get_link_ant_rssi_history(&rt2x00dev->link, ANTENNA_B); |
185 | 183 | ||
184 | memcpy(&ant, &rt2x00dev->link.ant.active, sizeof(ant)); | ||
185 | |||
186 | /* | 186 | /* |
187 | * We are done sampling. Now we should evaluate the results. | 187 | * We are done sampling. Now we should evaluate the results. |
188 | */ | 188 | */ |
@@ -200,21 +200,22 @@ static void rt2x00lib_evaluate_antenna_sample(struct rt2x00_dev *rt2x00dev) | |||
200 | return; | 200 | return; |
201 | 201 | ||
202 | if (rt2x00dev->link.ant.flags & ANTENNA_RX_DIVERSITY) | 202 | if (rt2x00dev->link.ant.flags & ANTENNA_RX_DIVERSITY) |
203 | rx = (sample_a > sample_b) ? ANTENNA_A : ANTENNA_B; | 203 | ant.rx = (sample_a > sample_b) ? ANTENNA_A : ANTENNA_B; |
204 | 204 | ||
205 | if (rt2x00dev->link.ant.flags & ANTENNA_TX_DIVERSITY) | 205 | if (rt2x00dev->link.ant.flags & ANTENNA_TX_DIVERSITY) |
206 | tx = (sample_a > sample_b) ? ANTENNA_A : ANTENNA_B; | 206 | ant.tx = (sample_a > sample_b) ? ANTENNA_A : ANTENNA_B; |
207 | 207 | ||
208 | rt2x00lib_config_antenna(rt2x00dev, rx, tx); | 208 | rt2x00lib_config_antenna(rt2x00dev, &ant); |
209 | } | 209 | } |
210 | 210 | ||
211 | static void rt2x00lib_evaluate_antenna_eval(struct rt2x00_dev *rt2x00dev) | 211 | static void rt2x00lib_evaluate_antenna_eval(struct rt2x00_dev *rt2x00dev) |
212 | { | 212 | { |
213 | enum antenna rx = rt2x00dev->link.ant.active.rx; | 213 | struct antenna_setup ant; |
214 | enum antenna tx = rt2x00dev->link.ant.active.tx; | ||
215 | int rssi_curr = rt2x00_get_link_ant_rssi(&rt2x00dev->link); | 214 | int rssi_curr = rt2x00_get_link_ant_rssi(&rt2x00dev->link); |
216 | int rssi_old = rt2x00_update_ant_rssi(&rt2x00dev->link, rssi_curr); | 215 | int rssi_old = rt2x00_update_ant_rssi(&rt2x00dev->link, rssi_curr); |
217 | 216 | ||
217 | memcpy(&ant, &rt2x00dev->link.ant.active, sizeof(ant)); | ||
218 | |||
218 | /* | 219 | /* |
219 | * Legacy driver indicates that we should swap antenna's | 220 | * Legacy driver indicates that we should swap antenna's |
220 | * when the difference in RSSI is greater that 5. This | 221 | * when the difference in RSSI is greater that 5. This |
@@ -230,12 +231,12 @@ static void rt2x00lib_evaluate_antenna_eval(struct rt2x00_dev *rt2x00dev) | |||
230 | rt2x00dev->link.ant.flags |= ANTENNA_MODE_SAMPLE; | 231 | rt2x00dev->link.ant.flags |= ANTENNA_MODE_SAMPLE; |
231 | 232 | ||
232 | if (rt2x00dev->link.ant.flags & ANTENNA_RX_DIVERSITY) | 233 | if (rt2x00dev->link.ant.flags & ANTENNA_RX_DIVERSITY) |
233 | rx = (rx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A; | 234 | ant.rx = (ant.rx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A; |
234 | 235 | ||
235 | if (rt2x00dev->link.ant.flags & ANTENNA_TX_DIVERSITY) | 236 | if (rt2x00dev->link.ant.flags & ANTENNA_TX_DIVERSITY) |
236 | tx = (tx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A; | 237 | ant.tx = (ant.tx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A; |
237 | 238 | ||
238 | rt2x00lib_config_antenna(rt2x00dev, rx, tx); | 239 | rt2x00lib_config_antenna(rt2x00dev, &ant); |
239 | } | 240 | } |
240 | 241 | ||
241 | static void rt2x00lib_evaluate_antenna(struct rt2x00_dev *rt2x00dev) | 242 | static void rt2x00lib_evaluate_antenna(struct rt2x00_dev *rt2x00dev) |
@@ -574,7 +575,7 @@ void rt2x00lib_txdone(struct queue_entry *entry, | |||
574 | entry->skb = NULL; | 575 | entry->skb = NULL; |
575 | entry->flags = 0; | 576 | entry->flags = 0; |
576 | 577 | ||
577 | rt2x00dev->ops->lib->init_txentry(rt2x00dev, entry); | 578 | rt2x00dev->ops->lib->clear_entry(entry); |
578 | 579 | ||
579 | clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); | 580 | clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); |
580 | rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); | 581 | rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); |
@@ -706,7 +707,7 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, | |||
706 | entry->skb = skb; | 707 | entry->skb = skb; |
707 | entry->flags = 0; | 708 | entry->flags = 0; |
708 | 709 | ||
709 | rt2x00dev->ops->lib->init_rxentry(rt2x00dev, entry); | 710 | rt2x00dev->ops->lib->clear_entry(entry); |
710 | 711 | ||
711 | rt2x00queue_index_inc(entry->queue, Q_INDEX); | 712 | rt2x00queue_index_inc(entry->queue, Q_INDEX); |
712 | } | 713 | } |
@@ -717,31 +718,31 @@ EXPORT_SYMBOL_GPL(rt2x00lib_rxdone); | |||
717 | */ | 718 | */ |
718 | const struct rt2x00_rate rt2x00_supported_rates[12] = { | 719 | const struct rt2x00_rate rt2x00_supported_rates[12] = { |
719 | { | 720 | { |
720 | .flags = DEV_RATE_CCK | DEV_RATE_BASIC, | 721 | .flags = DEV_RATE_CCK, |
721 | .bitrate = 10, | 722 | .bitrate = 10, |
722 | .ratemask = BIT(0), | 723 | .ratemask = BIT(0), |
723 | .plcp = 0x00, | 724 | .plcp = 0x00, |
724 | }, | 725 | }, |
725 | { | 726 | { |
726 | .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE | DEV_RATE_BASIC, | 727 | .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE, |
727 | .bitrate = 20, | 728 | .bitrate = 20, |
728 | .ratemask = BIT(1), | 729 | .ratemask = BIT(1), |
729 | .plcp = 0x01, | 730 | .plcp = 0x01, |
730 | }, | 731 | }, |
731 | { | 732 | { |
732 | .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE | DEV_RATE_BASIC, | 733 | .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE, |
733 | .bitrate = 55, | 734 | .bitrate = 55, |
734 | .ratemask = BIT(2), | 735 | .ratemask = BIT(2), |
735 | .plcp = 0x02, | 736 | .plcp = 0x02, |
736 | }, | 737 | }, |
737 | { | 738 | { |
738 | .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE | DEV_RATE_BASIC, | 739 | .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE, |
739 | .bitrate = 110, | 740 | .bitrate = 110, |
740 | .ratemask = BIT(3), | 741 | .ratemask = BIT(3), |
741 | .plcp = 0x03, | 742 | .plcp = 0x03, |
742 | }, | 743 | }, |
743 | { | 744 | { |
744 | .flags = DEV_RATE_OFDM | DEV_RATE_BASIC, | 745 | .flags = DEV_RATE_OFDM, |
745 | .bitrate = 60, | 746 | .bitrate = 60, |
746 | .ratemask = BIT(4), | 747 | .ratemask = BIT(4), |
747 | .plcp = 0x0b, | 748 | .plcp = 0x0b, |
@@ -753,7 +754,7 @@ const struct rt2x00_rate rt2x00_supported_rates[12] = { | |||
753 | .plcp = 0x0f, | 754 | .plcp = 0x0f, |
754 | }, | 755 | }, |
755 | { | 756 | { |
756 | .flags = DEV_RATE_OFDM | DEV_RATE_BASIC, | 757 | .flags = DEV_RATE_OFDM, |
757 | .bitrate = 120, | 758 | .bitrate = 120, |
758 | .ratemask = BIT(6), | 759 | .ratemask = BIT(6), |
759 | .plcp = 0x0a, | 760 | .plcp = 0x0a, |
@@ -765,7 +766,7 @@ const struct rt2x00_rate rt2x00_supported_rates[12] = { | |||
765 | .plcp = 0x0e, | 766 | .plcp = 0x0e, |
766 | }, | 767 | }, |
767 | { | 768 | { |
768 | .flags = DEV_RATE_OFDM | DEV_RATE_BASIC, | 769 | .flags = DEV_RATE_OFDM, |
769 | .bitrate = 240, | 770 | .bitrate = 240, |
770 | .ratemask = BIT(8), | 771 | .ratemask = BIT(8), |
771 | .plcp = 0x09, | 772 | .plcp = 0x09, |
@@ -1050,6 +1051,8 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) | |||
1050 | { | 1051 | { |
1051 | int retval = -ENOMEM; | 1052 | int retval = -ENOMEM; |
1052 | 1053 | ||
1054 | mutex_init(&rt2x00dev->csr_mutex); | ||
1055 | |||
1053 | /* | 1056 | /* |
1054 | * Make room for rt2x00_intf inside the per-interface | 1057 | * Make room for rt2x00_intf inside the per-interface |
1055 | * structure ieee80211_vif. | 1058 | * structure ieee80211_vif. |
diff --git a/drivers/net/wireless/rt2x00/rt2x00leds.c b/drivers/net/wireless/rt2x00/rt2x00leds.c index b362a1cf3f8d..66c61b1eca5d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00leds.c +++ b/drivers/net/wireless/rt2x00/rt2x00leds.c | |||
@@ -72,49 +72,33 @@ void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev, int rssi) | |||
72 | } | 72 | } |
73 | } | 73 | } |
74 | 74 | ||
75 | void rt2x00led_led_activity(struct rt2x00_dev *rt2x00dev, bool enabled) | 75 | static void rt2x00led_led_simple(struct rt2x00_led *led, bool enabled) |
76 | { | 76 | { |
77 | struct rt2x00_led *led = &rt2x00dev->led_qual; | 77 | unsigned int brightness = enabled ? LED_FULL : LED_OFF; |
78 | unsigned int brightness; | ||
79 | 78 | ||
80 | if ((led->type != LED_TYPE_ACTIVITY) || !(led->flags & LED_REGISTERED)) | 79 | if (!(led->flags & LED_REGISTERED)) |
81 | return; | 80 | return; |
82 | 81 | ||
83 | brightness = enabled ? LED_FULL : LED_OFF; | 82 | led->led_dev.brightness_set(&led->led_dev, brightness); |
84 | if (brightness != led->led_dev.brightness) { | 83 | led->led_dev.brightness = brightness; |
85 | led->led_dev.brightness_set(&led->led_dev, brightness); | ||
86 | led->led_dev.brightness = brightness; | ||
87 | } | ||
88 | } | 84 | } |
89 | 85 | ||
90 | void rt2x00leds_led_assoc(struct rt2x00_dev *rt2x00dev, bool enabled) | 86 | void rt2x00led_led_activity(struct rt2x00_dev *rt2x00dev, bool enabled) |
91 | { | 87 | { |
92 | struct rt2x00_led *led = &rt2x00dev->led_assoc; | 88 | if (rt2x00dev->led_qual.type == LED_TYPE_ACTIVITY) |
93 | unsigned int brightness; | 89 | rt2x00led_led_simple(&rt2x00dev->led_qual, enabled); |
94 | 90 | } | |
95 | if ((led->type != LED_TYPE_ASSOC) || !(led->flags & LED_REGISTERED)) | ||
96 | return; | ||
97 | 91 | ||
98 | brightness = enabled ? LED_FULL : LED_OFF; | 92 | void rt2x00leds_led_assoc(struct rt2x00_dev *rt2x00dev, bool enabled) |
99 | if (brightness != led->led_dev.brightness) { | 93 | { |
100 | led->led_dev.brightness_set(&led->led_dev, brightness); | 94 | if (rt2x00dev->led_assoc.type == LED_TYPE_ASSOC) |
101 | led->led_dev.brightness = brightness; | 95 | rt2x00led_led_simple(&rt2x00dev->led_assoc, enabled); |
102 | } | ||
103 | } | 96 | } |
104 | 97 | ||
105 | void rt2x00leds_led_radio(struct rt2x00_dev *rt2x00dev, bool enabled) | 98 | void rt2x00leds_led_radio(struct rt2x00_dev *rt2x00dev, bool enabled) |
106 | { | 99 | { |
107 | struct rt2x00_led *led = &rt2x00dev->led_radio; | 100 | if (rt2x00dev->led_radio.type == LED_TYPE_ASSOC) |
108 | unsigned int brightness; | 101 | rt2x00led_led_simple(&rt2x00dev->led_radio, enabled); |
109 | |||
110 | if ((led->type != LED_TYPE_RADIO) || !(led->flags & LED_REGISTERED)) | ||
111 | return; | ||
112 | |||
113 | brightness = enabled ? LED_FULL : LED_OFF; | ||
114 | if (brightness != led->led_dev.brightness) { | ||
115 | led->led_dev.brightness_set(&led->led_dev, brightness); | ||
116 | led->led_dev.brightness = brightness; | ||
117 | } | ||
118 | } | 102 | } |
119 | 103 | ||
120 | static int rt2x00leds_register_led(struct rt2x00_dev *rt2x00dev, | 104 | static int rt2x00leds_register_led(struct rt2x00_dev *rt2x00dev, |
@@ -125,6 +109,13 @@ static int rt2x00leds_register_led(struct rt2x00_dev *rt2x00dev, | |||
125 | int retval; | 109 | int retval; |
126 | 110 | ||
127 | led->led_dev.name = name; | 111 | led->led_dev.name = name; |
112 | led->led_dev.brightness = LED_OFF; | ||
113 | |||
114 | /* | ||
115 | * Ensure the LED is off, it might have been enabled | ||
116 | * by the hardware when the device was powered on. | ||
117 | */ | ||
118 | led->led_dev.brightness_set(&led->led_dev, LED_OFF); | ||
128 | 119 | ||
129 | retval = led_classdev_register(device, &led->led_dev); | 120 | retval = led_classdev_register(device, &led->led_dev); |
130 | if (retval) { | 121 | if (retval) { |
@@ -199,7 +190,16 @@ exit_fail: | |||
199 | static void rt2x00leds_unregister_led(struct rt2x00_led *led) | 190 | static void rt2x00leds_unregister_led(struct rt2x00_led *led) |
200 | { | 191 | { |
201 | led_classdev_unregister(&led->led_dev); | 192 | led_classdev_unregister(&led->led_dev); |
202 | led->led_dev.brightness_set(&led->led_dev, LED_OFF); | 193 | |
194 | /* | ||
195 | * This might look weird, but when we are unregistering while | ||
196 | * suspended the led is already off, and since we haven't | ||
197 | * fully resumed yet, access to the device might not be | ||
198 | * possible yet. | ||
199 | */ | ||
200 | if (!(led->led_dev.flags & LED_SUSPENDED)) | ||
201 | led->led_dev.brightness_set(&led->led_dev, LED_OFF); | ||
202 | |||
203 | led->flags &= ~LED_REGISTERED; | 203 | led->flags &= ~LED_REGISTERED; |
204 | } | 204 | } |
205 | 205 | ||
@@ -213,22 +213,40 @@ void rt2x00leds_unregister(struct rt2x00_dev *rt2x00dev) | |||
213 | rt2x00leds_unregister_led(&rt2x00dev->led_radio); | 213 | rt2x00leds_unregister_led(&rt2x00dev->led_radio); |
214 | } | 214 | } |
215 | 215 | ||
216 | static inline void rt2x00leds_suspend_led(struct rt2x00_led *led) | ||
217 | { | ||
218 | led_classdev_suspend(&led->led_dev); | ||
219 | |||
220 | /* This shouldn't be needed, but just to be safe */ | ||
221 | led->led_dev.brightness_set(&led->led_dev, LED_OFF); | ||
222 | led->led_dev.brightness = LED_OFF; | ||
223 | } | ||
224 | |||
216 | void rt2x00leds_suspend(struct rt2x00_dev *rt2x00dev) | 225 | void rt2x00leds_suspend(struct rt2x00_dev *rt2x00dev) |
217 | { | 226 | { |
218 | if (rt2x00dev->led_qual.flags & LED_REGISTERED) | 227 | if (rt2x00dev->led_qual.flags & LED_REGISTERED) |
219 | led_classdev_suspend(&rt2x00dev->led_qual.led_dev); | 228 | rt2x00leds_suspend_led(&rt2x00dev->led_qual); |
220 | if (rt2x00dev->led_assoc.flags & LED_REGISTERED) | 229 | if (rt2x00dev->led_assoc.flags & LED_REGISTERED) |
221 | led_classdev_suspend(&rt2x00dev->led_assoc.led_dev); | 230 | rt2x00leds_suspend_led(&rt2x00dev->led_assoc); |
222 | if (rt2x00dev->led_radio.flags & LED_REGISTERED) | 231 | if (rt2x00dev->led_radio.flags & LED_REGISTERED) |
223 | led_classdev_suspend(&rt2x00dev->led_radio.led_dev); | 232 | rt2x00leds_suspend_led(&rt2x00dev->led_radio); |
233 | } | ||
234 | |||
235 | static inline void rt2x00leds_resume_led(struct rt2x00_led *led) | ||
236 | { | ||
237 | led_classdev_resume(&led->led_dev); | ||
238 | |||
239 | /* Device might have enabled the LEDS during resume */ | ||
240 | led->led_dev.brightness_set(&led->led_dev, LED_OFF); | ||
241 | led->led_dev.brightness = LED_OFF; | ||
224 | } | 242 | } |
225 | 243 | ||
226 | void rt2x00leds_resume(struct rt2x00_dev *rt2x00dev) | 244 | void rt2x00leds_resume(struct rt2x00_dev *rt2x00dev) |
227 | { | 245 | { |
228 | if (rt2x00dev->led_radio.flags & LED_REGISTERED) | 246 | if (rt2x00dev->led_radio.flags & LED_REGISTERED) |
229 | led_classdev_resume(&rt2x00dev->led_radio.led_dev); | 247 | rt2x00leds_resume_led(&rt2x00dev->led_radio); |
230 | if (rt2x00dev->led_assoc.flags & LED_REGISTERED) | 248 | if (rt2x00dev->led_assoc.flags & LED_REGISTERED) |
231 | led_classdev_resume(&rt2x00dev->led_assoc.led_dev); | 249 | rt2x00leds_resume_led(&rt2x00dev->led_assoc); |
232 | if (rt2x00dev->led_qual.flags & LED_REGISTERED) | 250 | if (rt2x00dev->led_qual.flags & LED_REGISTERED) |
233 | led_classdev_resume(&rt2x00dev->led_qual.led_dev); | 251 | rt2x00leds_resume_led(&rt2x00dev->led_qual); |
234 | } | 252 | } |
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 9f214f89ba6d..93997333d46d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h | |||
@@ -43,7 +43,6 @@ struct rt2x00_rate { | |||
43 | #define DEV_RATE_CCK 0x0001 | 43 | #define DEV_RATE_CCK 0x0001 |
44 | #define DEV_RATE_OFDM 0x0002 | 44 | #define DEV_RATE_OFDM 0x0002 |
45 | #define DEV_RATE_SHORT_PREAMBLE 0x0004 | 45 | #define DEV_RATE_SHORT_PREAMBLE 0x0004 |
46 | #define DEV_RATE_BASIC 0x0008 | ||
47 | 46 | ||
48 | unsigned short bitrate; /* In 100kbit/s */ | 47 | unsigned short bitrate; /* In 100kbit/s */ |
49 | unsigned short ratemask; | 48 | unsigned short ratemask; |
@@ -94,7 +93,7 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev, | |||
94 | struct rt2x00_intf *intf, | 93 | struct rt2x00_intf *intf, |
95 | struct ieee80211_bss_conf *conf); | 94 | struct ieee80211_bss_conf *conf); |
96 | void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, | 95 | void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, |
97 | enum antenna rx, enum antenna tx); | 96 | struct antenna_setup *ant); |
98 | void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, | 97 | void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, |
99 | struct ieee80211_conf *conf, | 98 | struct ieee80211_conf *conf, |
100 | const unsigned int changed_flags); | 99 | const unsigned int changed_flags); |
@@ -151,8 +150,16 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, | |||
151 | */ | 150 | */ |
152 | void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index); | 151 | void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index); |
153 | 152 | ||
154 | void rt2x00queue_init_rx(struct rt2x00_dev *rt2x00dev); | 153 | /** |
155 | void rt2x00queue_init_tx(struct rt2x00_dev *rt2x00dev); | 154 | * rt2x00queue_init_queues - Initialize all data queues |
155 | * @rt2x00dev: Pointer to &struct rt2x00_dev. | ||
156 | * | ||
157 | * This function will loop through all available queues to clear all | ||
158 | * index numbers and set the queue entry to the correct initialization | ||
159 | * state. | ||
160 | */ | ||
161 | void rt2x00queue_init_queues(struct rt2x00_dev *rt2x00dev); | ||
162 | |||
156 | int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev); | 163 | int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev); |
157 | void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev); | 164 | void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev); |
158 | int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev); | 165 | int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 8fc2315c5963..48636b0dd895 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
@@ -339,7 +339,6 @@ int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed) | |||
339 | { | 339 | { |
340 | struct rt2x00_dev *rt2x00dev = hw->priv; | 340 | struct rt2x00_dev *rt2x00dev = hw->priv; |
341 | struct ieee80211_conf *conf = &hw->conf; | 341 | struct ieee80211_conf *conf = &hw->conf; |
342 | int radio_on; | ||
343 | int status; | 342 | int status; |
344 | 343 | ||
345 | /* | 344 | /* |
@@ -356,7 +355,6 @@ int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed) | |||
356 | * some configuration parameters (e.g. channel and antenna values) can | 355 | * some configuration parameters (e.g. channel and antenna values) can |
357 | * only be set when the radio is enabled. | 356 | * only be set when the radio is enabled. |
358 | */ | 357 | */ |
359 | radio_on = test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags); | ||
360 | if (conf->radio_enabled) { | 358 | if (conf->radio_enabled) { |
361 | /* For programming the values, we have to turn RX off */ | 359 | /* For programming the values, we have to turn RX off */ |
362 | rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF); | 360 | rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF); |
@@ -372,6 +370,17 @@ int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed) | |||
372 | */ | 370 | */ |
373 | rt2x00lib_config(rt2x00dev, conf, changed); | 371 | rt2x00lib_config(rt2x00dev, conf, changed); |
374 | 372 | ||
373 | /* | ||
374 | * The radio was enabled, configure the antenna to the | ||
375 | * default settings, the link tuner will later start | ||
376 | * continue configuring the antenna based on the software | ||
377 | * diversity. But for non-diversity configurations, we need | ||
378 | * to have configured the correct state now. | ||
379 | */ | ||
380 | if (changed & IEEE80211_CONF_CHANGE_RADIO_ENABLED) | ||
381 | rt2x00lib_config_antenna(rt2x00dev, | ||
382 | &rt2x00dev->default_ant); | ||
383 | |||
375 | /* Turn RX back on */ | 384 | /* Turn RX back on */ |
376 | rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON); | 385 | rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON); |
377 | } else { | 386 | } else { |
@@ -486,7 +495,9 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
486 | struct ieee80211_key_conf *key); | 495 | struct ieee80211_key_conf *key); |
487 | struct rt2x00lib_crypto crypto; | 496 | struct rt2x00lib_crypto crypto; |
488 | 497 | ||
489 | if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) | 498 | if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) |
499 | return 0; | ||
500 | else if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) | ||
490 | return -EOPNOTSUPP; | 501 | return -EOPNOTSUPP; |
491 | else if (key->keylen > 32) | 502 | else if (key->keylen > 32) |
492 | return -ENOSPC; | 503 | return -ENOSPC; |
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 62449da577e5..e33bd0f150c5 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c | |||
@@ -36,20 +36,17 @@ | |||
36 | */ | 36 | */ |
37 | int rt2x00pci_write_tx_data(struct queue_entry *entry) | 37 | int rt2x00pci_write_tx_data(struct queue_entry *entry) |
38 | { | 38 | { |
39 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | ||
39 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | 40 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; |
40 | struct skb_frame_desc *skbdesc; | 41 | struct skb_frame_desc *skbdesc; |
41 | u32 word; | ||
42 | |||
43 | rt2x00_desc_read(entry_priv->desc, 0, &word); | ||
44 | 42 | ||
45 | /* | 43 | /* |
46 | * This should not happen, we already checked the entry | 44 | * This should not happen, we already checked the entry |
47 | * was ours. When the hardware disagrees there has been | 45 | * was ours. When the hardware disagrees there has been |
48 | * a queue corruption! | 46 | * a queue corruption! |
49 | */ | 47 | */ |
50 | if (unlikely(rt2x00_get_field32(word, TXD_ENTRY_OWNER_NIC) || | 48 | if (unlikely(rt2x00dev->ops->lib->get_entry_state(entry))) { |
51 | rt2x00_get_field32(word, TXD_ENTRY_VALID))) { | 49 | ERROR(rt2x00dev, |
52 | ERROR(entry->queue->rt2x00dev, | ||
53 | "Corrupt queue %d, accessing entry which is not ours.\n" | 50 | "Corrupt queue %d, accessing entry which is not ours.\n" |
54 | "Please file bug report to %s.\n", | 51 | "Please file bug report to %s.\n", |
55 | entry->queue->qid, DRV_PROJECT); | 52 | entry->queue->qid, DRV_PROJECT); |
@@ -76,14 +73,12 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) | |||
76 | struct queue_entry *entry; | 73 | struct queue_entry *entry; |
77 | struct queue_entry_priv_pci *entry_priv; | 74 | struct queue_entry_priv_pci *entry_priv; |
78 | struct skb_frame_desc *skbdesc; | 75 | struct skb_frame_desc *skbdesc; |
79 | u32 word; | ||
80 | 76 | ||
81 | while (1) { | 77 | while (1) { |
82 | entry = rt2x00queue_get_entry(queue, Q_INDEX); | 78 | entry = rt2x00queue_get_entry(queue, Q_INDEX); |
83 | entry_priv = entry->priv_data; | 79 | entry_priv = entry->priv_data; |
84 | rt2x00_desc_read(entry_priv->desc, 0, &word); | ||
85 | 80 | ||
86 | if (rt2x00_get_field32(word, RXD_ENTRY_OWNER_NIC)) | 81 | if (rt2x00dev->ops->lib->get_entry_state(entry)) |
87 | break; | 82 | break; |
88 | 83 | ||
89 | /* | 84 | /* |
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h index a83f45f784f2..96a2082a3532 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.h +++ b/drivers/net/wireless/rt2x00/rt2x00pci.h | |||
@@ -44,17 +44,6 @@ | |||
44 | #define REGISTER_BUSY_DELAY 100 | 44 | #define REGISTER_BUSY_DELAY 100 |
45 | 45 | ||
46 | /* | 46 | /* |
47 | * Descriptor availability flags. | ||
48 | * All PCI device descriptors have these 2 flags | ||
49 | * with the exact same definition. | ||
50 | * By storing them here we can use them inside rt2x00pci | ||
51 | * for some simple entry availability checking. | ||
52 | */ | ||
53 | #define TXD_ENTRY_OWNER_NIC FIELD32(0x00000001) | ||
54 | #define TXD_ENTRY_VALID FIELD32(0x00000002) | ||
55 | #define RXD_ENTRY_OWNER_NIC FIELD32(0x00000001) | ||
56 | |||
57 | /* | ||
58 | * Register access. | 47 | * Register access. |
59 | */ | 48 | */ |
60 | static inline void rt2x00pci_register_read(struct rt2x00_dev *rt2x00dev, | 49 | static inline void rt2x00pci_register_read(struct rt2x00_dev *rt2x00dev, |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index e9f4261054bc..d7752dbd2023 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c | |||
@@ -319,8 +319,8 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, | |||
319 | /* | 319 | /* |
320 | * Convert length to microseconds. | 320 | * Convert length to microseconds. |
321 | */ | 321 | */ |
322 | residual = get_duration_res(data_length, hwrate->bitrate); | 322 | residual = GET_DURATION_RES(data_length, hwrate->bitrate); |
323 | duration = get_duration(data_length, hwrate->bitrate); | 323 | duration = GET_DURATION(data_length, hwrate->bitrate); |
324 | 324 | ||
325 | if (residual != 0) { | 325 | if (residual != 0) { |
326 | duration++; | 326 | duration++; |
@@ -589,40 +589,18 @@ static void rt2x00queue_reset(struct data_queue *queue) | |||
589 | spin_unlock_irqrestore(&queue->lock, irqflags); | 589 | spin_unlock_irqrestore(&queue->lock, irqflags); |
590 | } | 590 | } |
591 | 591 | ||
592 | void rt2x00queue_init_rx(struct rt2x00_dev *rt2x00dev) | 592 | void rt2x00queue_init_queues(struct rt2x00_dev *rt2x00dev) |
593 | { | ||
594 | struct data_queue *queue = rt2x00dev->rx; | ||
595 | unsigned int i; | ||
596 | |||
597 | rt2x00queue_reset(queue); | ||
598 | |||
599 | if (!rt2x00dev->ops->lib->init_rxentry) | ||
600 | return; | ||
601 | |||
602 | for (i = 0; i < queue->limit; i++) { | ||
603 | queue->entries[i].flags = 0; | ||
604 | |||
605 | rt2x00dev->ops->lib->init_rxentry(rt2x00dev, | ||
606 | &queue->entries[i]); | ||
607 | } | ||
608 | } | ||
609 | |||
610 | void rt2x00queue_init_tx(struct rt2x00_dev *rt2x00dev) | ||
611 | { | 593 | { |
612 | struct data_queue *queue; | 594 | struct data_queue *queue; |
613 | unsigned int i; | 595 | unsigned int i; |
614 | 596 | ||
615 | txall_queue_for_each(rt2x00dev, queue) { | 597 | queue_for_each(rt2x00dev, queue) { |
616 | rt2x00queue_reset(queue); | 598 | rt2x00queue_reset(queue); |
617 | 599 | ||
618 | if (!rt2x00dev->ops->lib->init_txentry) | ||
619 | continue; | ||
620 | |||
621 | for (i = 0; i < queue->limit; i++) { | 600 | for (i = 0; i < queue->limit; i++) { |
622 | queue->entries[i].flags = 0; | 601 | queue->entries[i].flags = 0; |
623 | 602 | ||
624 | rt2x00dev->ops->lib->init_txentry(rt2x00dev, | 603 | rt2x00dev->ops->lib->clear_entry(&queue->entries[i]); |
625 | &queue->entries[i]); | ||
626 | } | 604 | } |
627 | } | 605 | } |
628 | } | 606 | } |
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index b73a7e0aeed4..c507b0d9409f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c | |||
@@ -79,7 +79,7 @@ int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev, | |||
79 | { | 79 | { |
80 | int status; | 80 | int status; |
81 | 81 | ||
82 | BUG_ON(!mutex_is_locked(&rt2x00dev->usb_cache_mutex)); | 82 | BUG_ON(!mutex_is_locked(&rt2x00dev->csr_mutex)); |
83 | 83 | ||
84 | /* | 84 | /* |
85 | * Check for Cache availability. | 85 | * Check for Cache availability. |
@@ -110,13 +110,13 @@ int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev, | |||
110 | { | 110 | { |
111 | int status; | 111 | int status; |
112 | 112 | ||
113 | mutex_lock(&rt2x00dev->usb_cache_mutex); | 113 | mutex_lock(&rt2x00dev->csr_mutex); |
114 | 114 | ||
115 | status = rt2x00usb_vendor_req_buff_lock(rt2x00dev, request, | 115 | status = rt2x00usb_vendor_req_buff_lock(rt2x00dev, request, |
116 | requesttype, offset, buffer, | 116 | requesttype, offset, buffer, |
117 | buffer_length, timeout); | 117 | buffer_length, timeout); |
118 | 118 | ||
119 | mutex_unlock(&rt2x00dev->usb_cache_mutex); | 119 | mutex_unlock(&rt2x00dev->csr_mutex); |
120 | 120 | ||
121 | return status; | 121 | return status; |
122 | } | 122 | } |
@@ -132,7 +132,7 @@ int rt2x00usb_vendor_request_large_buff(struct rt2x00_dev *rt2x00dev, | |||
132 | unsigned char *tb; | 132 | unsigned char *tb; |
133 | u16 off, len, bsize; | 133 | u16 off, len, bsize; |
134 | 134 | ||
135 | mutex_lock(&rt2x00dev->usb_cache_mutex); | 135 | mutex_lock(&rt2x00dev->csr_mutex); |
136 | 136 | ||
137 | tb = (char *)buffer; | 137 | tb = (char *)buffer; |
138 | off = offset; | 138 | off = offset; |
@@ -148,7 +148,7 @@ int rt2x00usb_vendor_request_large_buff(struct rt2x00_dev *rt2x00dev, | |||
148 | off += bsize; | 148 | off += bsize; |
149 | } | 149 | } |
150 | 150 | ||
151 | mutex_unlock(&rt2x00dev->usb_cache_mutex); | 151 | mutex_unlock(&rt2x00dev->csr_mutex); |
152 | 152 | ||
153 | return status; | 153 | return status; |
154 | } | 154 | } |
@@ -351,28 +351,25 @@ EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio); | |||
351 | /* | 351 | /* |
352 | * Device initialization handlers. | 352 | * Device initialization handlers. |
353 | */ | 353 | */ |
354 | void rt2x00usb_init_rxentry(struct rt2x00_dev *rt2x00dev, | 354 | void rt2x00usb_clear_entry(struct queue_entry *entry) |
355 | struct queue_entry *entry) | ||
356 | { | 355 | { |
357 | struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); | 356 | struct usb_device *usb_dev = |
357 | to_usb_device_intf(entry->queue->rt2x00dev->dev); | ||
358 | struct queue_entry_priv_usb *entry_priv = entry->priv_data; | 358 | struct queue_entry_priv_usb *entry_priv = entry->priv_data; |
359 | 359 | ||
360 | usb_fill_bulk_urb(entry_priv->urb, usb_dev, | 360 | if (entry->queue->qid == QID_RX) { |
361 | usb_rcvbulkpipe(usb_dev, 1), | 361 | usb_fill_bulk_urb(entry_priv->urb, usb_dev, |
362 | entry->skb->data, entry->skb->len, | 362 | usb_rcvbulkpipe(usb_dev, 1), |
363 | rt2x00usb_interrupt_rxdone, entry); | 363 | entry->skb->data, entry->skb->len, |
364 | rt2x00usb_interrupt_rxdone, entry); | ||
364 | 365 | ||
365 | set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); | 366 | set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); |
366 | usb_submit_urb(entry_priv->urb, GFP_ATOMIC); | 367 | usb_submit_urb(entry_priv->urb, GFP_ATOMIC); |
367 | } | 368 | } else { |
368 | EXPORT_SYMBOL_GPL(rt2x00usb_init_rxentry); | 369 | entry->flags = 0; |
369 | 370 | } | |
370 | void rt2x00usb_init_txentry(struct rt2x00_dev *rt2x00dev, | ||
371 | struct queue_entry *entry) | ||
372 | { | ||
373 | entry->flags = 0; | ||
374 | } | 371 | } |
375 | EXPORT_SYMBOL_GPL(rt2x00usb_init_txentry); | 372 | EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry); |
376 | 373 | ||
377 | static int rt2x00usb_alloc_urb(struct rt2x00_dev *rt2x00dev, | 374 | static int rt2x00usb_alloc_urb(struct rt2x00_dev *rt2x00dev, |
378 | struct data_queue *queue) | 375 | struct data_queue *queue) |
@@ -534,7 +531,6 @@ int rt2x00usb_probe(struct usb_interface *usb_intf, | |||
534 | rt2x00dev->dev = &usb_intf->dev; | 531 | rt2x00dev->dev = &usb_intf->dev; |
535 | rt2x00dev->ops = ops; | 532 | rt2x00dev->ops = ops; |
536 | rt2x00dev->hw = hw; | 533 | rt2x00dev->hw = hw; |
537 | mutex_init(&rt2x00dev->usb_cache_mutex); | ||
538 | 534 | ||
539 | rt2x00dev->usb_maxpacket = | 535 | rt2x00dev->usb_maxpacket = |
540 | usb_maxpacket(usb_dev, usb_sndbulkpipe(usb_dev, 1), 1); | 536 | usb_maxpacket(usb_dev, usb_sndbulkpipe(usb_dev, 1), 1); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h index 3b4a67417f95..4104f0e8fa48 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/drivers/net/wireless/rt2x00/rt2x00usb.h | |||
@@ -286,10 +286,7 @@ void rt2x00usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, | |||
286 | /* | 286 | /* |
287 | * Device initialization handlers. | 287 | * Device initialization handlers. |
288 | */ | 288 | */ |
289 | void rt2x00usb_init_rxentry(struct rt2x00_dev *rt2x00dev, | 289 | void rt2x00usb_clear_entry(struct queue_entry *entry); |
290 | struct queue_entry *entry); | ||
291 | void rt2x00usb_init_txentry(struct rt2x00_dev *rt2x00dev, | ||
292 | struct queue_entry *entry); | ||
293 | int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev); | 290 | int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev); |
294 | void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev); | 291 | void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev); |
295 | 292 | ||
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 3f272793412a..89ac34fbadf2 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
@@ -75,14 +75,14 @@ static void rt61pci_bbp_write(struct rt2x00_dev *rt2x00dev, | |||
75 | { | 75 | { |
76 | u32 reg; | 76 | u32 reg; |
77 | 77 | ||
78 | mutex_lock(&rt2x00dev->csr_mutex); | ||
79 | |||
78 | /* | 80 | /* |
79 | * Wait until the BBP becomes ready. | 81 | * Wait until the BBP becomes ready. |
80 | */ | 82 | */ |
81 | reg = rt61pci_bbp_check(rt2x00dev); | 83 | reg = rt61pci_bbp_check(rt2x00dev); |
82 | if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) { | 84 | if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) |
83 | ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n"); | 85 | goto exit_fail; |
84 | return; | ||
85 | } | ||
86 | 86 | ||
87 | /* | 87 | /* |
88 | * Write the data into the BBP. | 88 | * Write the data into the BBP. |
@@ -94,6 +94,14 @@ static void rt61pci_bbp_write(struct rt2x00_dev *rt2x00dev, | |||
94 | rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 0); | 94 | rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 0); |
95 | 95 | ||
96 | rt2x00pci_register_write(rt2x00dev, PHY_CSR3, reg); | 96 | rt2x00pci_register_write(rt2x00dev, PHY_CSR3, reg); |
97 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
98 | |||
99 | return; | ||
100 | |||
101 | exit_fail: | ||
102 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
103 | |||
104 | ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n"); | ||
97 | } | 105 | } |
98 | 106 | ||
99 | static void rt61pci_bbp_read(struct rt2x00_dev *rt2x00dev, | 107 | static void rt61pci_bbp_read(struct rt2x00_dev *rt2x00dev, |
@@ -101,14 +109,14 @@ static void rt61pci_bbp_read(struct rt2x00_dev *rt2x00dev, | |||
101 | { | 109 | { |
102 | u32 reg; | 110 | u32 reg; |
103 | 111 | ||
112 | mutex_lock(&rt2x00dev->csr_mutex); | ||
113 | |||
104 | /* | 114 | /* |
105 | * Wait until the BBP becomes ready. | 115 | * Wait until the BBP becomes ready. |
106 | */ | 116 | */ |
107 | reg = rt61pci_bbp_check(rt2x00dev); | 117 | reg = rt61pci_bbp_check(rt2x00dev); |
108 | if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) { | 118 | if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) |
109 | ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n"); | 119 | goto exit_fail; |
110 | return; | ||
111 | } | ||
112 | 120 | ||
113 | /* | 121 | /* |
114 | * Write the request into the BBP. | 122 | * Write the request into the BBP. |
@@ -124,13 +132,19 @@ static void rt61pci_bbp_read(struct rt2x00_dev *rt2x00dev, | |||
124 | * Wait until the BBP becomes ready. | 132 | * Wait until the BBP becomes ready. |
125 | */ | 133 | */ |
126 | reg = rt61pci_bbp_check(rt2x00dev); | 134 | reg = rt61pci_bbp_check(rt2x00dev); |
127 | if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) { | 135 | if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) |
128 | ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n"); | 136 | goto exit_fail; |
129 | *value = 0xff; | ||
130 | return; | ||
131 | } | ||
132 | 137 | ||
133 | *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE); | 138 | *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE); |
139 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
140 | |||
141 | return; | ||
142 | |||
143 | exit_fail: | ||
144 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
145 | |||
146 | ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n"); | ||
147 | *value = 0xff; | ||
134 | } | 148 | } |
135 | 149 | ||
136 | static void rt61pci_rf_write(struct rt2x00_dev *rt2x00dev, | 150 | static void rt61pci_rf_write(struct rt2x00_dev *rt2x00dev, |
@@ -142,6 +156,8 @@ static void rt61pci_rf_write(struct rt2x00_dev *rt2x00dev, | |||
142 | if (!word) | 156 | if (!word) |
143 | return; | 157 | return; |
144 | 158 | ||
159 | mutex_lock(&rt2x00dev->csr_mutex); | ||
160 | |||
145 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | 161 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { |
146 | rt2x00pci_register_read(rt2x00dev, PHY_CSR4, ®); | 162 | rt2x00pci_register_read(rt2x00dev, PHY_CSR4, ®); |
147 | if (!rt2x00_get_field32(reg, PHY_CSR4_BUSY)) | 163 | if (!rt2x00_get_field32(reg, PHY_CSR4_BUSY)) |
@@ -149,6 +165,7 @@ static void rt61pci_rf_write(struct rt2x00_dev *rt2x00dev, | |||
149 | udelay(REGISTER_BUSY_DELAY); | 165 | udelay(REGISTER_BUSY_DELAY); |
150 | } | 166 | } |
151 | 167 | ||
168 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
152 | ERROR(rt2x00dev, "PHY_CSR4 register busy. Write failed.\n"); | 169 | ERROR(rt2x00dev, "PHY_CSR4 register busy. Write failed.\n"); |
153 | return; | 170 | return; |
154 | 171 | ||
@@ -161,6 +178,8 @@ rf_write: | |||
161 | 178 | ||
162 | rt2x00pci_register_write(rt2x00dev, PHY_CSR4, reg); | 179 | rt2x00pci_register_write(rt2x00dev, PHY_CSR4, reg); |
163 | rt2x00_rf_write(rt2x00dev, word, value); | 180 | rt2x00_rf_write(rt2x00dev, word, value); |
181 | |||
182 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
164 | } | 183 | } |
165 | 184 | ||
166 | #ifdef CONFIG_RT2X00_LIB_LEDS | 185 | #ifdef CONFIG_RT2X00_LIB_LEDS |
@@ -175,14 +194,12 @@ static void rt61pci_mcu_request(struct rt2x00_dev *rt2x00dev, | |||
175 | { | 194 | { |
176 | u32 reg; | 195 | u32 reg; |
177 | 196 | ||
197 | mutex_lock(&rt2x00dev->csr_mutex); | ||
198 | |||
178 | rt2x00pci_register_read(rt2x00dev, H2M_MAILBOX_CSR, ®); | 199 | rt2x00pci_register_read(rt2x00dev, H2M_MAILBOX_CSR, ®); |
179 | 200 | ||
180 | if (rt2x00_get_field32(reg, H2M_MAILBOX_CSR_OWNER)) { | 201 | if (rt2x00_get_field32(reg, H2M_MAILBOX_CSR_OWNER)) |
181 | ERROR(rt2x00dev, "mcu request error. " | 202 | goto exit_fail; |
182 | "Request 0x%02x failed for token 0x%02x.\n", | ||
183 | command, token); | ||
184 | return; | ||
185 | } | ||
186 | 203 | ||
187 | rt2x00_set_field32(®, H2M_MAILBOX_CSR_OWNER, 1); | 204 | rt2x00_set_field32(®, H2M_MAILBOX_CSR_OWNER, 1); |
188 | rt2x00_set_field32(®, H2M_MAILBOX_CSR_CMD_TOKEN, token); | 205 | rt2x00_set_field32(®, H2M_MAILBOX_CSR_CMD_TOKEN, token); |
@@ -194,6 +211,17 @@ static void rt61pci_mcu_request(struct rt2x00_dev *rt2x00dev, | |||
194 | rt2x00_set_field32(®, HOST_CMD_CSR_HOST_COMMAND, command); | 211 | rt2x00_set_field32(®, HOST_CMD_CSR_HOST_COMMAND, command); |
195 | rt2x00_set_field32(®, HOST_CMD_CSR_INTERRUPT_MCU, 1); | 212 | rt2x00_set_field32(®, HOST_CMD_CSR_INTERRUPT_MCU, 1); |
196 | rt2x00pci_register_write(rt2x00dev, HOST_CMD_CSR, reg); | 213 | rt2x00pci_register_write(rt2x00dev, HOST_CMD_CSR, reg); |
214 | |||
215 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
216 | |||
217 | return; | ||
218 | |||
219 | exit_fail: | ||
220 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
221 | |||
222 | ERROR(rt2x00dev, | ||
223 | "mcu request error. Request 0x%02x failed for token 0x%02x.\n", | ||
224 | command, token); | ||
197 | } | 225 | } |
198 | #endif /* CONFIG_RT2X00_LIB_LEDS */ | 226 | #endif /* CONFIG_RT2X00_LIB_LEDS */ |
199 | 227 | ||
@@ -1261,33 +1289,44 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev, const void *data, | |||
1261 | /* | 1289 | /* |
1262 | * Initialization functions. | 1290 | * Initialization functions. |
1263 | */ | 1291 | */ |
1264 | static void rt61pci_init_rxentry(struct rt2x00_dev *rt2x00dev, | 1292 | static bool rt61pci_get_entry_state(struct queue_entry *entry) |
1265 | struct queue_entry *entry) | ||
1266 | { | 1293 | { |
1267 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | 1294 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; |
1268 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | ||
1269 | u32 word; | 1295 | u32 word; |
1270 | 1296 | ||
1271 | rt2x00_desc_read(entry_priv->desc, 5, &word); | 1297 | if (entry->queue->qid == QID_RX) { |
1272 | rt2x00_set_field32(&word, RXD_W5_BUFFER_PHYSICAL_ADDRESS, | 1298 | rt2x00_desc_read(entry_priv->desc, 0, &word); |
1273 | skbdesc->skb_dma); | ||
1274 | rt2x00_desc_write(entry_priv->desc, 5, word); | ||
1275 | 1299 | ||
1276 | rt2x00_desc_read(entry_priv->desc, 0, &word); | 1300 | return rt2x00_get_field32(word, RXD_W0_OWNER_NIC); |
1277 | rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1); | 1301 | } else { |
1278 | rt2x00_desc_write(entry_priv->desc, 0, word); | 1302 | rt2x00_desc_read(entry_priv->desc, 0, &word); |
1303 | |||
1304 | return (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) || | ||
1305 | rt2x00_get_field32(word, TXD_W0_VALID)); | ||
1306 | } | ||
1279 | } | 1307 | } |
1280 | 1308 | ||
1281 | static void rt61pci_init_txentry(struct rt2x00_dev *rt2x00dev, | 1309 | static void rt61pci_clear_entry(struct queue_entry *entry) |
1282 | struct queue_entry *entry) | ||
1283 | { | 1310 | { |
1284 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | 1311 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; |
1312 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | ||
1285 | u32 word; | 1313 | u32 word; |
1286 | 1314 | ||
1287 | rt2x00_desc_read(entry_priv->desc, 0, &word); | 1315 | if (entry->queue->qid == QID_RX) { |
1288 | rt2x00_set_field32(&word, TXD_W0_VALID, 0); | 1316 | rt2x00_desc_read(entry_priv->desc, 5, &word); |
1289 | rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0); | 1317 | rt2x00_set_field32(&word, RXD_W5_BUFFER_PHYSICAL_ADDRESS, |
1290 | rt2x00_desc_write(entry_priv->desc, 0, word); | 1318 | skbdesc->skb_dma); |
1319 | rt2x00_desc_write(entry_priv->desc, 5, word); | ||
1320 | |||
1321 | rt2x00_desc_read(entry_priv->desc, 0, &word); | ||
1322 | rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1); | ||
1323 | rt2x00_desc_write(entry_priv->desc, 0, word); | ||
1324 | } else { | ||
1325 | rt2x00_desc_read(entry_priv->desc, 0, &word); | ||
1326 | rt2x00_set_field32(&word, TXD_W0_VALID, 0); | ||
1327 | rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0); | ||
1328 | rt2x00_desc_write(entry_priv->desc, 0, word); | ||
1329 | } | ||
1291 | } | 1330 | } |
1292 | 1331 | ||
1293 | static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev) | 1332 | static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev) |
@@ -2722,8 +2761,8 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { | |||
2722 | .load_firmware = rt61pci_load_firmware, | 2761 | .load_firmware = rt61pci_load_firmware, |
2723 | .initialize = rt2x00pci_initialize, | 2762 | .initialize = rt2x00pci_initialize, |
2724 | .uninitialize = rt2x00pci_uninitialize, | 2763 | .uninitialize = rt2x00pci_uninitialize, |
2725 | .init_rxentry = rt61pci_init_rxentry, | 2764 | .get_entry_state = rt61pci_get_entry_state, |
2726 | .init_txentry = rt61pci_init_txentry, | 2765 | .clear_entry = rt61pci_clear_entry, |
2727 | .set_device_state = rt61pci_set_device_state, | 2766 | .set_device_state = rt61pci_set_device_state, |
2728 | .rfkill_poll = rt61pci_rfkill_poll, | 2767 | .rfkill_poll = rt61pci_rfkill_poll, |
2729 | .link_stats = rt61pci_link_stats, | 2768 | .link_stats = rt61pci_link_stats, |
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 767e3c98184c..d1a63e0017da 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -55,7 +55,7 @@ MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); | |||
55 | * between each attampt. When the busy bit is still set at that time, | 55 | * between each attampt. When the busy bit is still set at that time, |
56 | * the access attempt is considered to have failed, | 56 | * the access attempt is considered to have failed, |
57 | * and we will print an error. | 57 | * and we will print an error. |
58 | * The _lock versions must be used if you already hold the usb_cache_mutex | 58 | * The _lock versions must be used if you already hold the csr_mutex |
59 | */ | 59 | */ |
60 | static inline void rt73usb_register_read(struct rt2x00_dev *rt2x00dev, | 60 | static inline void rt73usb_register_read(struct rt2x00_dev *rt2x00dev, |
61 | const unsigned int offset, u32 *value) | 61 | const unsigned int offset, u32 *value) |
@@ -135,7 +135,7 @@ static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev, | |||
135 | { | 135 | { |
136 | u32 reg; | 136 | u32 reg; |
137 | 137 | ||
138 | mutex_lock(&rt2x00dev->usb_cache_mutex); | 138 | mutex_lock(&rt2x00dev->csr_mutex); |
139 | 139 | ||
140 | /* | 140 | /* |
141 | * Wait until the BBP becomes ready. | 141 | * Wait until the BBP becomes ready. |
@@ -154,12 +154,12 @@ static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev, | |||
154 | rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 0); | 154 | rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 0); |
155 | 155 | ||
156 | rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg); | 156 | rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg); |
157 | mutex_unlock(&rt2x00dev->usb_cache_mutex); | 157 | mutex_unlock(&rt2x00dev->csr_mutex); |
158 | 158 | ||
159 | return; | 159 | return; |
160 | 160 | ||
161 | exit_fail: | 161 | exit_fail: |
162 | mutex_unlock(&rt2x00dev->usb_cache_mutex); | 162 | mutex_unlock(&rt2x00dev->csr_mutex); |
163 | 163 | ||
164 | ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n"); | 164 | ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n"); |
165 | } | 165 | } |
@@ -169,7 +169,7 @@ static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev, | |||
169 | { | 169 | { |
170 | u32 reg; | 170 | u32 reg; |
171 | 171 | ||
172 | mutex_lock(&rt2x00dev->usb_cache_mutex); | 172 | mutex_lock(&rt2x00dev->csr_mutex); |
173 | 173 | ||
174 | /* | 174 | /* |
175 | * Wait until the BBP becomes ready. | 175 | * Wait until the BBP becomes ready. |
@@ -196,12 +196,12 @@ static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev, | |||
196 | goto exit_fail; | 196 | goto exit_fail; |
197 | 197 | ||
198 | *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE); | 198 | *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE); |
199 | mutex_unlock(&rt2x00dev->usb_cache_mutex); | 199 | mutex_unlock(&rt2x00dev->csr_mutex); |
200 | 200 | ||
201 | return; | 201 | return; |
202 | 202 | ||
203 | exit_fail: | 203 | exit_fail: |
204 | mutex_unlock(&rt2x00dev->usb_cache_mutex); | 204 | mutex_unlock(&rt2x00dev->csr_mutex); |
205 | 205 | ||
206 | ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n"); | 206 | ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n"); |
207 | *value = 0xff; | 207 | *value = 0xff; |
@@ -216,7 +216,7 @@ static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev, | |||
216 | if (!word) | 216 | if (!word) |
217 | return; | 217 | return; |
218 | 218 | ||
219 | mutex_lock(&rt2x00dev->usb_cache_mutex); | 219 | mutex_lock(&rt2x00dev->csr_mutex); |
220 | 220 | ||
221 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | 221 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { |
222 | rt73usb_register_read_lock(rt2x00dev, PHY_CSR4, ®); | 222 | rt73usb_register_read_lock(rt2x00dev, PHY_CSR4, ®); |
@@ -225,7 +225,7 @@ static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev, | |||
225 | udelay(REGISTER_BUSY_DELAY); | 225 | udelay(REGISTER_BUSY_DELAY); |
226 | } | 226 | } |
227 | 227 | ||
228 | mutex_unlock(&rt2x00dev->usb_cache_mutex); | 228 | mutex_unlock(&rt2x00dev->csr_mutex); |
229 | ERROR(rt2x00dev, "PHY_CSR4 register busy. Write failed.\n"); | 229 | ERROR(rt2x00dev, "PHY_CSR4 register busy. Write failed.\n"); |
230 | return; | 230 | return; |
231 | 231 | ||
@@ -245,7 +245,8 @@ rf_write: | |||
245 | 245 | ||
246 | rt73usb_register_write_lock(rt2x00dev, PHY_CSR4, reg); | 246 | rt73usb_register_write_lock(rt2x00dev, PHY_CSR4, reg); |
247 | rt2x00_rf_write(rt2x00dev, word, value); | 247 | rt2x00_rf_write(rt2x00dev, word, value); |
248 | mutex_unlock(&rt2x00dev->usb_cache_mutex); | 248 | |
249 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
249 | } | 250 | } |
250 | 251 | ||
251 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS | 252 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS |
@@ -2313,8 +2314,7 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { | |||
2313 | .load_firmware = rt73usb_load_firmware, | 2314 | .load_firmware = rt73usb_load_firmware, |
2314 | .initialize = rt2x00usb_initialize, | 2315 | .initialize = rt2x00usb_initialize, |
2315 | .uninitialize = rt2x00usb_uninitialize, | 2316 | .uninitialize = rt2x00usb_uninitialize, |
2316 | .init_rxentry = rt2x00usb_init_rxentry, | 2317 | .clear_entry = rt2x00usb_clear_entry, |
2317 | .init_txentry = rt2x00usb_init_txentry, | ||
2318 | .set_device_state = rt73usb_set_device_state, | 2318 | .set_device_state = rt73usb_set_device_state, |
2319 | .link_stats = rt73usb_link_stats, | 2319 | .link_stats = rt73usb_link_stats, |
2320 | .reset_tuner = rt73usb_reset_tuner, | 2320 | .reset_tuner = rt73usb_reset_tuner, |
diff --git a/drivers/net/wireless/rtl818x/Makefile b/drivers/net/wireless/rtl818x/Makefile new file mode 100644 index 000000000000..c113b3e69046 --- /dev/null +++ b/drivers/net/wireless/rtl818x/Makefile | |||
@@ -0,0 +1,7 @@ | |||
1 | rtl8180-objs := rtl8180_dev.o rtl8180_rtl8225.o rtl8180_sa2400.o rtl8180_max2820.o rtl8180_grf5101.o | ||
2 | rtl8187-objs := rtl8187_dev.o rtl8187_rtl8225.o | ||
3 | |||
4 | obj-$(CONFIG_RTL8180) += rtl8180.o | ||
5 | obj-$(CONFIG_RTL8187) += rtl8187.o | ||
6 | |||
7 | |||
diff --git a/drivers/net/wireless/rtl8180.h b/drivers/net/wireless/rtl818x/rtl8180.h index 8721282a8185..8721282a8185 100644 --- a/drivers/net/wireless/rtl8180.h +++ b/drivers/net/wireless/rtl818x/rtl8180.h | |||
diff --git a/drivers/net/wireless/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index 6c226c024dd9..5f887fb137a9 100644 --- a/drivers/net/wireless/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c | |||
@@ -720,6 +720,17 @@ static int rtl8180_config_interface(struct ieee80211_hw *dev, | |||
720 | return 0; | 720 | return 0; |
721 | } | 721 | } |
722 | 722 | ||
723 | static void rtl8180_bss_info_changed(struct ieee80211_hw *dev, | ||
724 | struct ieee80211_vif *vif, | ||
725 | struct ieee80211_bss_conf *info, | ||
726 | u32 changed) | ||
727 | { | ||
728 | struct rtl8180_priv *priv = dev->priv; | ||
729 | |||
730 | if (changed & BSS_CHANGED_ERP_SLOT && priv->rf->conf_erp) | ||
731 | priv->rf->conf_erp(dev, info); | ||
732 | } | ||
733 | |||
723 | static void rtl8180_configure_filter(struct ieee80211_hw *dev, | 734 | static void rtl8180_configure_filter(struct ieee80211_hw *dev, |
724 | unsigned int changed_flags, | 735 | unsigned int changed_flags, |
725 | unsigned int *total_flags, | 736 | unsigned int *total_flags, |
@@ -760,6 +771,7 @@ static const struct ieee80211_ops rtl8180_ops = { | |||
760 | .remove_interface = rtl8180_remove_interface, | 771 | .remove_interface = rtl8180_remove_interface, |
761 | .config = rtl8180_config, | 772 | .config = rtl8180_config, |
762 | .config_interface = rtl8180_config_interface, | 773 | .config_interface = rtl8180_config_interface, |
774 | .bss_info_changed = rtl8180_bss_info_changed, | ||
763 | .configure_filter = rtl8180_configure_filter, | 775 | .configure_filter = rtl8180_configure_filter, |
764 | }; | 776 | }; |
765 | 777 | ||
diff --git a/drivers/net/wireless/rtl8180_grf5101.c b/drivers/net/wireless/rtl818x/rtl8180_grf5101.c index 947ee55f18b2..947ee55f18b2 100644 --- a/drivers/net/wireless/rtl8180_grf5101.c +++ b/drivers/net/wireless/rtl818x/rtl8180_grf5101.c | |||
diff --git a/drivers/net/wireless/rtl8180_grf5101.h b/drivers/net/wireless/rtl818x/rtl8180_grf5101.h index 76647111bcff..76647111bcff 100644 --- a/drivers/net/wireless/rtl8180_grf5101.h +++ b/drivers/net/wireless/rtl818x/rtl8180_grf5101.h | |||
diff --git a/drivers/net/wireless/rtl8180_max2820.c b/drivers/net/wireless/rtl818x/rtl8180_max2820.c index 6c825fd7f3b6..6c825fd7f3b6 100644 --- a/drivers/net/wireless/rtl8180_max2820.c +++ b/drivers/net/wireless/rtl818x/rtl8180_max2820.c | |||
diff --git a/drivers/net/wireless/rtl8180_max2820.h b/drivers/net/wireless/rtl818x/rtl8180_max2820.h index 61cf6d1e7d57..61cf6d1e7d57 100644 --- a/drivers/net/wireless/rtl8180_max2820.h +++ b/drivers/net/wireless/rtl818x/rtl8180_max2820.h | |||
diff --git a/drivers/net/wireless/rtl8180_rtl8225.c b/drivers/net/wireless/rtl818x/rtl8180_rtl8225.c index cd22781728a9..4d2be0d9672b 100644 --- a/drivers/net/wireless/rtl8180_rtl8225.c +++ b/drivers/net/wireless/rtl818x/rtl8180_rtl8225.c | |||
@@ -725,8 +725,14 @@ static void rtl8225_rf_set_channel(struct ieee80211_hw *dev, | |||
725 | 725 | ||
726 | rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]); | 726 | rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]); |
727 | msleep(10); | 727 | msleep(10); |
728 | } | ||
729 | |||
730 | static void rtl8225_rf_conf_erp(struct ieee80211_hw *dev, | ||
731 | struct ieee80211_bss_conf *info) | ||
732 | { | ||
733 | struct rtl8180_priv *priv = dev->priv; | ||
728 | 734 | ||
729 | if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) { | 735 | if (info->use_short_slot) { |
730 | rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9); | 736 | rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9); |
731 | rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22); | 737 | rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22); |
732 | rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14); | 738 | rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14); |
@@ -745,14 +751,16 @@ static const struct rtl818x_rf_ops rtl8225_ops = { | |||
745 | .name = "rtl8225", | 751 | .name = "rtl8225", |
746 | .init = rtl8225_rf_init, | 752 | .init = rtl8225_rf_init, |
747 | .stop = rtl8225_rf_stop, | 753 | .stop = rtl8225_rf_stop, |
748 | .set_chan = rtl8225_rf_set_channel | 754 | .set_chan = rtl8225_rf_set_channel, |
755 | .conf_erp = rtl8225_rf_conf_erp, | ||
749 | }; | 756 | }; |
750 | 757 | ||
751 | static const struct rtl818x_rf_ops rtl8225z2_ops = { | 758 | static const struct rtl818x_rf_ops rtl8225z2_ops = { |
752 | .name = "rtl8225z2", | 759 | .name = "rtl8225z2", |
753 | .init = rtl8225z2_rf_init, | 760 | .init = rtl8225z2_rf_init, |
754 | .stop = rtl8225_rf_stop, | 761 | .stop = rtl8225_rf_stop, |
755 | .set_chan = rtl8225_rf_set_channel | 762 | .set_chan = rtl8225_rf_set_channel, |
763 | .conf_erp = rtl8225_rf_conf_erp, | ||
756 | }; | 764 | }; |
757 | 765 | ||
758 | const struct rtl818x_rf_ops * rtl8180_detect_rf(struct ieee80211_hw *dev) | 766 | const struct rtl818x_rf_ops * rtl8180_detect_rf(struct ieee80211_hw *dev) |
diff --git a/drivers/net/wireless/rtl8180_rtl8225.h b/drivers/net/wireless/rtl818x/rtl8180_rtl8225.h index 310013a2d726..310013a2d726 100644 --- a/drivers/net/wireless/rtl8180_rtl8225.h +++ b/drivers/net/wireless/rtl818x/rtl8180_rtl8225.h | |||
diff --git a/drivers/net/wireless/rtl8180_sa2400.c b/drivers/net/wireless/rtl818x/rtl8180_sa2400.c index cea4e0ccb92d..cea4e0ccb92d 100644 --- a/drivers/net/wireless/rtl8180_sa2400.c +++ b/drivers/net/wireless/rtl818x/rtl8180_sa2400.c | |||
diff --git a/drivers/net/wireless/rtl8180_sa2400.h b/drivers/net/wireless/rtl818x/rtl8180_sa2400.h index a4aaa0d413f1..a4aaa0d413f1 100644 --- a/drivers/net/wireless/rtl8180_sa2400.h +++ b/drivers/net/wireless/rtl818x/rtl8180_sa2400.h | |||
diff --git a/drivers/net/wireless/rtl8187.h b/drivers/net/wireless/rtl818x/rtl8187.h index 33725d0978b3..33725d0978b3 100644 --- a/drivers/net/wireless/rtl8187.h +++ b/drivers/net/wireless/rtl818x/rtl8187.h | |||
diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index e1399d0b55d3..4a9f76f46f77 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c | |||
@@ -7,6 +7,11 @@ | |||
7 | * Based on the r8187 driver, which is: | 7 | * Based on the r8187 driver, which is: |
8 | * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al. | 8 | * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al. |
9 | * | 9 | * |
10 | * The driver was extended to the RTL8187B in 2008 by: | ||
11 | * Herton Ronaldo Krzesinski <herton@mandriva.com.br> | ||
12 | * Hin-Tak Leung <htl10@users.sourceforge.net> | ||
13 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
14 | * | ||
10 | * Magic delays and register offsets below are taken from the original | 15 | * Magic delays and register offsets below are taken from the original |
11 | * r8187 driver sources. Thanks to Realtek for their support! | 16 | * r8187 driver sources. Thanks to Realtek for their support! |
12 | * | 17 | * |
@@ -27,6 +32,9 @@ | |||
27 | 32 | ||
28 | MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>"); | 33 | MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>"); |
29 | MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>"); | 34 | MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>"); |
35 | MODULE_AUTHOR("Herton Ronaldo Krzesinski <herton@mandriva.com.br>"); | ||
36 | MODULE_AUTHOR("Hin-Tak Leung <htl10@users.sourceforge.net>"); | ||
37 | MODULE_AUTHOR("Larry Finger <Larry.Finger@lwfinger.net>"); | ||
30 | MODULE_DESCRIPTION("RTL8187/RTL8187B USB wireless driver"); | 38 | MODULE_DESCRIPTION("RTL8187/RTL8187B USB wireless driver"); |
31 | MODULE_LICENSE("GPL"); | 39 | MODULE_LICENSE("GPL"); |
32 | 40 | ||
diff --git a/drivers/net/wireless/rtl8187_rtl8225.c b/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c index 69030be62b36..69030be62b36 100644 --- a/drivers/net/wireless/rtl8187_rtl8225.c +++ b/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c | |||
diff --git a/drivers/net/wireless/rtl8187_rtl8225.h b/drivers/net/wireless/rtl818x/rtl8187_rtl8225.h index 20c5b6ead0f6..20c5b6ead0f6 100644 --- a/drivers/net/wireless/rtl8187_rtl8225.h +++ b/drivers/net/wireless/rtl818x/rtl8187_rtl8225.h | |||
diff --git a/drivers/net/wireless/rtl818x.h b/drivers/net/wireless/rtl818x/rtl818x.h index 3538b15211b1..34a5555cc19c 100644 --- a/drivers/net/wireless/rtl818x.h +++ b/drivers/net/wireless/rtl818x/rtl818x.h | |||
@@ -191,6 +191,7 @@ struct rtl818x_rf_ops { | |||
191 | void (*init)(struct ieee80211_hw *); | 191 | void (*init)(struct ieee80211_hw *); |
192 | void (*stop)(struct ieee80211_hw *); | 192 | void (*stop)(struct ieee80211_hw *); |
193 | void (*set_chan)(struct ieee80211_hw *, struct ieee80211_conf *); | 193 | void (*set_chan)(struct ieee80211_hw *, struct ieee80211_conf *); |
194 | void (*conf_erp)(struct ieee80211_hw *, struct ieee80211_bss_conf *); | ||
194 | }; | 195 | }; |
195 | 196 | ||
196 | /* Tx/Rx flags are common between RTL818X chips */ | 197 | /* Tx/Rx flags are common between RTL818X chips */ |
diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c index 1134e2fb1890..3404807b3e12 100644 --- a/drivers/net/wireless/zd1201.c +++ b/drivers/net/wireless/zd1201.c | |||
@@ -743,7 +743,7 @@ static int zd1201_join(struct zd1201 *zd, char *essid, int essidlen) | |||
743 | 743 | ||
744 | static int zd1201_net_open(struct net_device *dev) | 744 | static int zd1201_net_open(struct net_device *dev) |
745 | { | 745 | { |
746 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | 746 | struct zd1201 *zd = netdev_priv(dev); |
747 | 747 | ||
748 | /* Start MAC with wildcard if no essid set */ | 748 | /* Start MAC with wildcard if no essid set */ |
749 | if (!zd->mac_enabled) | 749 | if (!zd->mac_enabled) |
@@ -781,7 +781,7 @@ static int zd1201_net_stop(struct net_device *dev) | |||
781 | */ | 781 | */ |
782 | static int zd1201_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | 782 | static int zd1201_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) |
783 | { | 783 | { |
784 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | 784 | struct zd1201 *zd = netdev_priv(dev); |
785 | unsigned char *txbuf = zd->txdata; | 785 | unsigned char *txbuf = zd->txdata; |
786 | int txbuflen, pad = 0, err; | 786 | int txbuflen, pad = 0, err; |
787 | struct urb *urb = zd->tx_urb; | 787 | struct urb *urb = zd->tx_urb; |
@@ -831,7 +831,7 @@ static int zd1201_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
831 | 831 | ||
832 | static void zd1201_tx_timeout(struct net_device *dev) | 832 | static void zd1201_tx_timeout(struct net_device *dev) |
833 | { | 833 | { |
834 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | 834 | struct zd1201 *zd = netdev_priv(dev); |
835 | 835 | ||
836 | if (!zd) | 836 | if (!zd) |
837 | return; | 837 | return; |
@@ -846,7 +846,7 @@ static void zd1201_tx_timeout(struct net_device *dev) | |||
846 | static int zd1201_set_mac_address(struct net_device *dev, void *p) | 846 | static int zd1201_set_mac_address(struct net_device *dev, void *p) |
847 | { | 847 | { |
848 | struct sockaddr *addr = p; | 848 | struct sockaddr *addr = p; |
849 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | 849 | struct zd1201 *zd = netdev_priv(dev); |
850 | int err; | 850 | int err; |
851 | 851 | ||
852 | if (!zd) | 852 | if (!zd) |
@@ -863,21 +863,21 @@ static int zd1201_set_mac_address(struct net_device *dev, void *p) | |||
863 | 863 | ||
864 | static struct net_device_stats *zd1201_get_stats(struct net_device *dev) | 864 | static struct net_device_stats *zd1201_get_stats(struct net_device *dev) |
865 | { | 865 | { |
866 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | 866 | struct zd1201 *zd = netdev_priv(dev); |
867 | 867 | ||
868 | return &zd->stats; | 868 | return &zd->stats; |
869 | } | 869 | } |
870 | 870 | ||
871 | static struct iw_statistics *zd1201_get_wireless_stats(struct net_device *dev) | 871 | static struct iw_statistics *zd1201_get_wireless_stats(struct net_device *dev) |
872 | { | 872 | { |
873 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | 873 | struct zd1201 *zd = netdev_priv(dev); |
874 | 874 | ||
875 | return &zd->iwstats; | 875 | return &zd->iwstats; |
876 | } | 876 | } |
877 | 877 | ||
878 | static void zd1201_set_multicast(struct net_device *dev) | 878 | static void zd1201_set_multicast(struct net_device *dev) |
879 | { | 879 | { |
880 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | 880 | struct zd1201 *zd = netdev_priv(dev); |
881 | struct dev_mc_list *mc = dev->mc_list; | 881 | struct dev_mc_list *mc = dev->mc_list; |
882 | unsigned char reqbuf[ETH_ALEN*ZD1201_MAXMULTI]; | 882 | unsigned char reqbuf[ETH_ALEN*ZD1201_MAXMULTI]; |
883 | int i; | 883 | int i; |
@@ -897,7 +897,7 @@ static void zd1201_set_multicast(struct net_device *dev) | |||
897 | static int zd1201_config_commit(struct net_device *dev, | 897 | static int zd1201_config_commit(struct net_device *dev, |
898 | struct iw_request_info *info, struct iw_point *data, char *essid) | 898 | struct iw_request_info *info, struct iw_point *data, char *essid) |
899 | { | 899 | { |
900 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | 900 | struct zd1201 *zd = netdev_priv(dev); |
901 | 901 | ||
902 | return zd1201_mac_reset(zd); | 902 | return zd1201_mac_reset(zd); |
903 | } | 903 | } |
@@ -912,7 +912,7 @@ static int zd1201_get_name(struct net_device *dev, | |||
912 | static int zd1201_set_freq(struct net_device *dev, | 912 | static int zd1201_set_freq(struct net_device *dev, |
913 | struct iw_request_info *info, struct iw_freq *freq, char *extra) | 913 | struct iw_request_info *info, struct iw_freq *freq, char *extra) |
914 | { | 914 | { |
915 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | 915 | struct zd1201 *zd = netdev_priv(dev); |
916 | short channel = 0; | 916 | short channel = 0; |
917 | int err; | 917 | int err; |
918 | 918 | ||
@@ -937,7 +937,7 @@ static int zd1201_set_freq(struct net_device *dev, | |||
937 | static int zd1201_get_freq(struct net_device *dev, | 937 | static int zd1201_get_freq(struct net_device *dev, |
938 | struct iw_request_info *info, struct iw_freq *freq, char *extra) | 938 | struct iw_request_info *info, struct iw_freq *freq, char *extra) |
939 | { | 939 | { |
940 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | 940 | struct zd1201 *zd = netdev_priv(dev); |
941 | short channel; | 941 | short channel; |
942 | int err; | 942 | int err; |
943 | 943 | ||
@@ -953,7 +953,7 @@ static int zd1201_get_freq(struct net_device *dev, | |||
953 | static int zd1201_set_mode(struct net_device *dev, | 953 | static int zd1201_set_mode(struct net_device *dev, |
954 | struct iw_request_info *info, __u32 *mode, char *extra) | 954 | struct iw_request_info *info, __u32 *mode, char *extra) |
955 | { | 955 | { |
956 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | 956 | struct zd1201 *zd = netdev_priv(dev); |
957 | short porttype, monitor = 0; | 957 | short porttype, monitor = 0; |
958 | unsigned char buffer[IW_ESSID_MAX_SIZE+2]; | 958 | unsigned char buffer[IW_ESSID_MAX_SIZE+2]; |
959 | int err; | 959 | int err; |
@@ -1015,7 +1015,7 @@ static int zd1201_set_mode(struct net_device *dev, | |||
1015 | static int zd1201_get_mode(struct net_device *dev, | 1015 | static int zd1201_get_mode(struct net_device *dev, |
1016 | struct iw_request_info *info, __u32 *mode, char *extra) | 1016 | struct iw_request_info *info, __u32 *mode, char *extra) |
1017 | { | 1017 | { |
1018 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | 1018 | struct zd1201 *zd = netdev_priv(dev); |
1019 | short porttype; | 1019 | short porttype; |
1020 | int err; | 1020 | int err; |
1021 | 1021 | ||
@@ -1091,7 +1091,7 @@ static int zd1201_get_range(struct net_device *dev, | |||
1091 | static int zd1201_get_wap(struct net_device *dev, | 1091 | static int zd1201_get_wap(struct net_device *dev, |
1092 | struct iw_request_info *info, struct sockaddr *ap_addr, char *extra) | 1092 | struct iw_request_info *info, struct sockaddr *ap_addr, char *extra) |
1093 | { | 1093 | { |
1094 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | 1094 | struct zd1201 *zd = netdev_priv(dev); |
1095 | unsigned char buffer[6]; | 1095 | unsigned char buffer[6]; |
1096 | 1096 | ||
1097 | if (!zd1201_getconfig(zd, ZD1201_RID_COMMSQUALITY, buffer, 6)) { | 1097 | if (!zd1201_getconfig(zd, ZD1201_RID_COMMSQUALITY, buffer, 6)) { |
@@ -1119,7 +1119,7 @@ static int zd1201_set_scan(struct net_device *dev, | |||
1119 | static int zd1201_get_scan(struct net_device *dev, | 1119 | static int zd1201_get_scan(struct net_device *dev, |
1120 | struct iw_request_info *info, struct iw_point *srq, char *extra) | 1120 | struct iw_request_info *info, struct iw_point *srq, char *extra) |
1121 | { | 1121 | { |
1122 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | 1122 | struct zd1201 *zd = netdev_priv(dev); |
1123 | int err, i, j, enabled_save; | 1123 | int err, i, j, enabled_save; |
1124 | struct iw_event iwe; | 1124 | struct iw_event iwe; |
1125 | char *cev = extra; | 1125 | char *cev = extra; |
@@ -1211,7 +1211,7 @@ static int zd1201_get_scan(struct net_device *dev, | |||
1211 | static int zd1201_set_essid(struct net_device *dev, | 1211 | static int zd1201_set_essid(struct net_device *dev, |
1212 | struct iw_request_info *info, struct iw_point *data, char *essid) | 1212 | struct iw_request_info *info, struct iw_point *data, char *essid) |
1213 | { | 1213 | { |
1214 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | 1214 | struct zd1201 *zd = netdev_priv(dev); |
1215 | 1215 | ||
1216 | if (data->length > IW_ESSID_MAX_SIZE) | 1216 | if (data->length > IW_ESSID_MAX_SIZE) |
1217 | return -EINVAL; | 1217 | return -EINVAL; |
@@ -1226,7 +1226,7 @@ static int zd1201_set_essid(struct net_device *dev, | |||
1226 | static int zd1201_get_essid(struct net_device *dev, | 1226 | static int zd1201_get_essid(struct net_device *dev, |
1227 | struct iw_request_info *info, struct iw_point *data, char *essid) | 1227 | struct iw_request_info *info, struct iw_point *data, char *essid) |
1228 | { | 1228 | { |
1229 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | 1229 | struct zd1201 *zd = netdev_priv(dev); |
1230 | 1230 | ||
1231 | memcpy(essid, zd->essid, zd->essidlen); | 1231 | memcpy(essid, zd->essid, zd->essidlen); |
1232 | data->flags = 1; | 1232 | data->flags = 1; |
@@ -1247,7 +1247,7 @@ static int zd1201_get_nick(struct net_device *dev, struct iw_request_info *info, | |||
1247 | static int zd1201_set_rate(struct net_device *dev, | 1247 | static int zd1201_set_rate(struct net_device *dev, |
1248 | struct iw_request_info *info, struct iw_param *rrq, char *extra) | 1248 | struct iw_request_info *info, struct iw_param *rrq, char *extra) |
1249 | { | 1249 | { |
1250 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | 1250 | struct zd1201 *zd = netdev_priv(dev); |
1251 | short rate; | 1251 | short rate; |
1252 | int err; | 1252 | int err; |
1253 | 1253 | ||
@@ -1280,7 +1280,7 @@ static int zd1201_set_rate(struct net_device *dev, | |||
1280 | static int zd1201_get_rate(struct net_device *dev, | 1280 | static int zd1201_get_rate(struct net_device *dev, |
1281 | struct iw_request_info *info, struct iw_param *rrq, char *extra) | 1281 | struct iw_request_info *info, struct iw_param *rrq, char *extra) |
1282 | { | 1282 | { |
1283 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | 1283 | struct zd1201 *zd = netdev_priv(dev); |
1284 | short rate; | 1284 | short rate; |
1285 | int err; | 1285 | int err; |
1286 | 1286 | ||
@@ -1313,7 +1313,7 @@ static int zd1201_get_rate(struct net_device *dev, | |||
1313 | static int zd1201_set_rts(struct net_device *dev, struct iw_request_info *info, | 1313 | static int zd1201_set_rts(struct net_device *dev, struct iw_request_info *info, |
1314 | struct iw_param *rts, char *extra) | 1314 | struct iw_param *rts, char *extra) |
1315 | { | 1315 | { |
1316 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | 1316 | struct zd1201 *zd = netdev_priv(dev); |
1317 | int err; | 1317 | int err; |
1318 | short val = rts->value; | 1318 | short val = rts->value; |
1319 | 1319 | ||
@@ -1333,7 +1333,7 @@ static int zd1201_set_rts(struct net_device *dev, struct iw_request_info *info, | |||
1333 | static int zd1201_get_rts(struct net_device *dev, struct iw_request_info *info, | 1333 | static int zd1201_get_rts(struct net_device *dev, struct iw_request_info *info, |
1334 | struct iw_param *rts, char *extra) | 1334 | struct iw_param *rts, char *extra) |
1335 | { | 1335 | { |
1336 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | 1336 | struct zd1201 *zd = netdev_priv(dev); |
1337 | short rtst; | 1337 | short rtst; |
1338 | int err; | 1338 | int err; |
1339 | 1339 | ||
@@ -1350,7 +1350,7 @@ static int zd1201_get_rts(struct net_device *dev, struct iw_request_info *info, | |||
1350 | static int zd1201_set_frag(struct net_device *dev, struct iw_request_info *info, | 1350 | static int zd1201_set_frag(struct net_device *dev, struct iw_request_info *info, |
1351 | struct iw_param *frag, char *extra) | 1351 | struct iw_param *frag, char *extra) |
1352 | { | 1352 | { |
1353 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | 1353 | struct zd1201 *zd = netdev_priv(dev); |
1354 | int err; | 1354 | int err; |
1355 | short val = frag->value; | 1355 | short val = frag->value; |
1356 | 1356 | ||
@@ -1371,7 +1371,7 @@ static int zd1201_set_frag(struct net_device *dev, struct iw_request_info *info, | |||
1371 | static int zd1201_get_frag(struct net_device *dev, struct iw_request_info *info, | 1371 | static int zd1201_get_frag(struct net_device *dev, struct iw_request_info *info, |
1372 | struct iw_param *frag, char *extra) | 1372 | struct iw_param *frag, char *extra) |
1373 | { | 1373 | { |
1374 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | 1374 | struct zd1201 *zd = netdev_priv(dev); |
1375 | short fragt; | 1375 | short fragt; |
1376 | int err; | 1376 | int err; |
1377 | 1377 | ||
@@ -1400,7 +1400,7 @@ static int zd1201_get_retry(struct net_device *dev, | |||
1400 | static int zd1201_set_encode(struct net_device *dev, | 1400 | static int zd1201_set_encode(struct net_device *dev, |
1401 | struct iw_request_info *info, struct iw_point *erq, char *key) | 1401 | struct iw_request_info *info, struct iw_point *erq, char *key) |
1402 | { | 1402 | { |
1403 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | 1403 | struct zd1201 *zd = netdev_priv(dev); |
1404 | short i; | 1404 | short i; |
1405 | int err, rid; | 1405 | int err, rid; |
1406 | 1406 | ||
@@ -1457,7 +1457,7 @@ static int zd1201_set_encode(struct net_device *dev, | |||
1457 | static int zd1201_get_encode(struct net_device *dev, | 1457 | static int zd1201_get_encode(struct net_device *dev, |
1458 | struct iw_request_info *info, struct iw_point *erq, char *key) | 1458 | struct iw_request_info *info, struct iw_point *erq, char *key) |
1459 | { | 1459 | { |
1460 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | 1460 | struct zd1201 *zd = netdev_priv(dev); |
1461 | short i; | 1461 | short i; |
1462 | int err; | 1462 | int err; |
1463 | 1463 | ||
@@ -1490,7 +1490,7 @@ static int zd1201_get_encode(struct net_device *dev, | |||
1490 | static int zd1201_set_power(struct net_device *dev, | 1490 | static int zd1201_set_power(struct net_device *dev, |
1491 | struct iw_request_info *info, struct iw_param *vwrq, char *extra) | 1491 | struct iw_request_info *info, struct iw_param *vwrq, char *extra) |
1492 | { | 1492 | { |
1493 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | 1493 | struct zd1201 *zd = netdev_priv(dev); |
1494 | short enabled, duration, level; | 1494 | short enabled, duration, level; |
1495 | int err; | 1495 | int err; |
1496 | 1496 | ||
@@ -1529,7 +1529,7 @@ out: | |||
1529 | static int zd1201_get_power(struct net_device *dev, | 1529 | static int zd1201_get_power(struct net_device *dev, |
1530 | struct iw_request_info *info, struct iw_param *vwrq, char *extra) | 1530 | struct iw_request_info *info, struct iw_param *vwrq, char *extra) |
1531 | { | 1531 | { |
1532 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | 1532 | struct zd1201 *zd = netdev_priv(dev); |
1533 | short enabled, level, duration; | 1533 | short enabled, level, duration; |
1534 | int err; | 1534 | int err; |
1535 | 1535 | ||
@@ -1616,7 +1616,7 @@ static const iw_handler zd1201_iw_handler[] = | |||
1616 | static int zd1201_set_hostauth(struct net_device *dev, | 1616 | static int zd1201_set_hostauth(struct net_device *dev, |
1617 | struct iw_request_info *info, struct iw_param *rrq, char *extra) | 1617 | struct iw_request_info *info, struct iw_param *rrq, char *extra) |
1618 | { | 1618 | { |
1619 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | 1619 | struct zd1201 *zd = netdev_priv(dev); |
1620 | 1620 | ||
1621 | if (!zd->ap) | 1621 | if (!zd->ap) |
1622 | return -EOPNOTSUPP; | 1622 | return -EOPNOTSUPP; |
@@ -1627,7 +1627,7 @@ static int zd1201_set_hostauth(struct net_device *dev, | |||
1627 | static int zd1201_get_hostauth(struct net_device *dev, | 1627 | static int zd1201_get_hostauth(struct net_device *dev, |
1628 | struct iw_request_info *info, struct iw_param *rrq, char *extra) | 1628 | struct iw_request_info *info, struct iw_param *rrq, char *extra) |
1629 | { | 1629 | { |
1630 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | 1630 | struct zd1201 *zd = netdev_priv(dev); |
1631 | short hostauth; | 1631 | short hostauth; |
1632 | int err; | 1632 | int err; |
1633 | 1633 | ||
@@ -1646,7 +1646,7 @@ static int zd1201_get_hostauth(struct net_device *dev, | |||
1646 | static int zd1201_auth_sta(struct net_device *dev, | 1646 | static int zd1201_auth_sta(struct net_device *dev, |
1647 | struct iw_request_info *info, struct sockaddr *sta, char *extra) | 1647 | struct iw_request_info *info, struct sockaddr *sta, char *extra) |
1648 | { | 1648 | { |
1649 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | 1649 | struct zd1201 *zd = netdev_priv(dev); |
1650 | unsigned char buffer[10]; | 1650 | unsigned char buffer[10]; |
1651 | 1651 | ||
1652 | if (!zd->ap) | 1652 | if (!zd->ap) |
@@ -1662,7 +1662,7 @@ static int zd1201_auth_sta(struct net_device *dev, | |||
1662 | static int zd1201_set_maxassoc(struct net_device *dev, | 1662 | static int zd1201_set_maxassoc(struct net_device *dev, |
1663 | struct iw_request_info *info, struct iw_param *rrq, char *extra) | 1663 | struct iw_request_info *info, struct iw_param *rrq, char *extra) |
1664 | { | 1664 | { |
1665 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | 1665 | struct zd1201 *zd = netdev_priv(dev); |
1666 | int err; | 1666 | int err; |
1667 | 1667 | ||
1668 | if (!zd->ap) | 1668 | if (!zd->ap) |
@@ -1677,7 +1677,7 @@ static int zd1201_set_maxassoc(struct net_device *dev, | |||
1677 | static int zd1201_get_maxassoc(struct net_device *dev, | 1677 | static int zd1201_get_maxassoc(struct net_device *dev, |
1678 | struct iw_request_info *info, struct iw_param *rrq, char *extra) | 1678 | struct iw_request_info *info, struct iw_param *rrq, char *extra) |
1679 | { | 1679 | { |
1680 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | 1680 | struct zd1201 *zd = netdev_priv(dev); |
1681 | short maxassoc; | 1681 | short maxassoc; |
1682 | int err; | 1682 | int err; |
1683 | 1683 | ||
@@ -1729,6 +1729,7 @@ static int zd1201_probe(struct usb_interface *interface, | |||
1729 | const struct usb_device_id *id) | 1729 | const struct usb_device_id *id) |
1730 | { | 1730 | { |
1731 | struct zd1201 *zd; | 1731 | struct zd1201 *zd; |
1732 | struct net_device *dev; | ||
1732 | struct usb_device *usb; | 1733 | struct usb_device *usb; |
1733 | int err; | 1734 | int err; |
1734 | short porttype; | 1735 | short porttype; |
@@ -1736,9 +1737,12 @@ static int zd1201_probe(struct usb_interface *interface, | |||
1736 | 1737 | ||
1737 | usb = interface_to_usbdev(interface); | 1738 | usb = interface_to_usbdev(interface); |
1738 | 1739 | ||
1739 | zd = kzalloc(sizeof(struct zd1201), GFP_KERNEL); | 1740 | dev = alloc_etherdev(sizeof(*zd)); |
1740 | if (!zd) | 1741 | if (!dev) |
1741 | return -ENOMEM; | 1742 | return -ENOMEM; |
1743 | zd = netdev_priv(dev); | ||
1744 | zd->dev = dev; | ||
1745 | |||
1742 | zd->ap = ap; | 1746 | zd->ap = ap; |
1743 | zd->usb = usb; | 1747 | zd->usb = usb; |
1744 | zd->removed = 0; | 1748 | zd->removed = 0; |
@@ -1773,34 +1777,29 @@ static int zd1201_probe(struct usb_interface *interface, | |||
1773 | if (err) | 1777 | if (err) |
1774 | goto err_start; | 1778 | goto err_start; |
1775 | 1779 | ||
1776 | zd->dev = alloc_etherdev(0); | 1780 | dev->open = zd1201_net_open; |
1777 | if (!zd->dev) | 1781 | dev->stop = zd1201_net_stop; |
1778 | goto err_start; | 1782 | dev->get_stats = zd1201_get_stats; |
1779 | 1783 | dev->wireless_handlers = | |
1780 | zd->dev->priv = zd; | ||
1781 | zd->dev->open = zd1201_net_open; | ||
1782 | zd->dev->stop = zd1201_net_stop; | ||
1783 | zd->dev->get_stats = zd1201_get_stats; | ||
1784 | zd->dev->wireless_handlers = | ||
1785 | (struct iw_handler_def *)&zd1201_iw_handlers; | 1784 | (struct iw_handler_def *)&zd1201_iw_handlers; |
1786 | zd->dev->hard_start_xmit = zd1201_hard_start_xmit; | 1785 | dev->hard_start_xmit = zd1201_hard_start_xmit; |
1787 | zd->dev->watchdog_timeo = ZD1201_TX_TIMEOUT; | 1786 | dev->watchdog_timeo = ZD1201_TX_TIMEOUT; |
1788 | zd->dev->tx_timeout = zd1201_tx_timeout; | 1787 | dev->tx_timeout = zd1201_tx_timeout; |
1789 | zd->dev->set_multicast_list = zd1201_set_multicast; | 1788 | dev->set_multicast_list = zd1201_set_multicast; |
1790 | zd->dev->set_mac_address = zd1201_set_mac_address; | 1789 | dev->set_mac_address = zd1201_set_mac_address; |
1791 | strcpy(zd->dev->name, "wlan%d"); | 1790 | strcpy(dev->name, "wlan%d"); |
1792 | 1791 | ||
1793 | err = zd1201_getconfig(zd, ZD1201_RID_CNFOWNMACADDR, | 1792 | err = zd1201_getconfig(zd, ZD1201_RID_CNFOWNMACADDR, |
1794 | zd->dev->dev_addr, zd->dev->addr_len); | 1793 | dev->dev_addr, dev->addr_len); |
1795 | if (err) | 1794 | if (err) |
1796 | goto err_net; | 1795 | goto err_start; |
1797 | 1796 | ||
1798 | /* Set wildcard essid to match zd->essid */ | 1797 | /* Set wildcard essid to match zd->essid */ |
1799 | *(__le16 *)buf = cpu_to_le16(0); | 1798 | *(__le16 *)buf = cpu_to_le16(0); |
1800 | err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID, buf, | 1799 | err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID, buf, |
1801 | IW_ESSID_MAX_SIZE+2, 1); | 1800 | IW_ESSID_MAX_SIZE+2, 1); |
1802 | if (err) | 1801 | if (err) |
1803 | goto err_net; | 1802 | goto err_start; |
1804 | 1803 | ||
1805 | if (zd->ap) | 1804 | if (zd->ap) |
1806 | porttype = ZD1201_PORTTYPE_AP; | 1805 | porttype = ZD1201_PORTTYPE_AP; |
@@ -1808,30 +1807,28 @@ static int zd1201_probe(struct usb_interface *interface, | |||
1808 | porttype = ZD1201_PORTTYPE_BSS; | 1807 | porttype = ZD1201_PORTTYPE_BSS; |
1809 | err = zd1201_setconfig16(zd, ZD1201_RID_CNFPORTTYPE, porttype); | 1808 | err = zd1201_setconfig16(zd, ZD1201_RID_CNFPORTTYPE, porttype); |
1810 | if (err) | 1809 | if (err) |
1811 | goto err_net; | 1810 | goto err_start; |
1812 | 1811 | ||
1813 | SET_NETDEV_DEV(zd->dev, &usb->dev); | 1812 | SET_NETDEV_DEV(dev, &usb->dev); |
1814 | 1813 | ||
1815 | err = register_netdev(zd->dev); | 1814 | err = register_netdev(dev); |
1816 | if (err) | 1815 | if (err) |
1817 | goto err_net; | 1816 | goto err_start; |
1818 | dev_info(&usb->dev, "%s: ZD1201 USB Wireless interface\n", | 1817 | dev_info(&usb->dev, "%s: ZD1201 USB Wireless interface\n", |
1819 | zd->dev->name); | 1818 | dev->name); |
1820 | 1819 | ||
1821 | usb_set_intfdata(interface, zd); | 1820 | usb_set_intfdata(interface, zd); |
1822 | zd1201_enable(zd); /* zd1201 likes to startup enabled, */ | 1821 | zd1201_enable(zd); /* zd1201 likes to startup enabled, */ |
1823 | zd1201_disable(zd); /* interfering with all the wifis in range */ | 1822 | zd1201_disable(zd); /* interfering with all the wifis in range */ |
1824 | return 0; | 1823 | return 0; |
1825 | 1824 | ||
1826 | err_net: | ||
1827 | free_netdev(zd->dev); | ||
1828 | err_start: | 1825 | err_start: |
1829 | /* Leave the device in reset state */ | 1826 | /* Leave the device in reset state */ |
1830 | zd1201_docmd(zd, ZD1201_CMDCODE_INIT, 0, 0, 0); | 1827 | zd1201_docmd(zd, ZD1201_CMDCODE_INIT, 0, 0, 0); |
1831 | err_zd: | 1828 | err_zd: |
1832 | usb_free_urb(zd->tx_urb); | 1829 | usb_free_urb(zd->tx_urb); |
1833 | usb_free_urb(zd->rx_urb); | 1830 | usb_free_urb(zd->rx_urb); |
1834 | kfree(zd); | 1831 | free_netdev(dev); |
1835 | return err; | 1832 | return err; |
1836 | } | 1833 | } |
1837 | 1834 | ||