diff options
author | John W. Linville <linville@tuxdriver.com> | 2010-12-16 15:21:33 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-12-16 15:21:33 -0500 |
commit | 5928b91acae97622a6f2e679eb7a9f19bed68e3e (patch) | |
tree | 02d55145d355735b12398ad3eab61a72c78d5c4e /drivers | |
parent | 7d5f01ad536afebde9a1c81d985f8d0eaf2a9ab6 (diff) | |
parent | 248daa084cee4b212ff4408e9c9b05b3bdc0da0d (diff) |
Merge branch 'wl12xx-next' of git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/wl12xx/Kconfig | 10 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/Makefile | 3 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/acx.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/acx.h | 9 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/boot.c | 17 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/boot.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/cmd.c | 69 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/cmd.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/debugfs.c | 192 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/init.c | 13 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/io.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/main.c | 119 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/scan.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/sdio_test.c | 520 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/tx.c | 60 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl12xx.h | 129 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl12xx_80211.h | 17 |
17 files changed, 848 insertions, 324 deletions
diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig index d2adeb1f72b7..0e65bce457d6 100644 --- a/drivers/net/wireless/wl12xx/Kconfig +++ b/drivers/net/wireless/wl12xx/Kconfig | |||
@@ -52,6 +52,16 @@ config WL12XX_SDIO | |||
52 | If you choose to build a module, it'll be called wl12xx_sdio. | 52 | If you choose to build a module, it'll be called wl12xx_sdio. |
53 | Say N if unsure. | 53 | Say N if unsure. |
54 | 54 | ||
55 | config WL12XX_SDIO_TEST | ||
56 | tristate "TI wl12xx SDIO testing support" | ||
57 | depends on WL12XX && MMC | ||
58 | default n | ||
59 | ---help--- | ||
60 | This module adds support for the SDIO bus testing with the | ||
61 | TI wl12xx chipsets. You probably don't want this unless you are | ||
62 | testing a new hardware platform. Select this if you want to test the | ||
63 | SDIO bus which is connected to the wl12xx chip. | ||
64 | |||
55 | config WL12XX_PLATFORM_DATA | 65 | config WL12XX_PLATFORM_DATA |
56 | bool | 66 | bool |
57 | depends on WL12XX_SDIO != n || WL1251_SDIO != n | 67 | depends on WL12XX_SDIO != n || WL1251_SDIO != n |
diff --git a/drivers/net/wireless/wl12xx/Makefile b/drivers/net/wireless/wl12xx/Makefile index 005a758174d9..521c0414e52e 100644 --- a/drivers/net/wireless/wl12xx/Makefile +++ b/drivers/net/wireless/wl12xx/Makefile | |||
@@ -3,11 +3,14 @@ wl12xx-objs = main.o cmd.o io.o event.o tx.o rx.o ps.o acx.o \ | |||
3 | 3 | ||
4 | wl12xx_spi-objs = spi.o | 4 | wl12xx_spi-objs = spi.o |
5 | wl12xx_sdio-objs = sdio.o | 5 | wl12xx_sdio-objs = sdio.o |
6 | wl12xx_sdio_test-objs = sdio_test.o | ||
6 | 7 | ||
7 | wl12xx-$(CONFIG_NL80211_TESTMODE) += testmode.o | 8 | wl12xx-$(CONFIG_NL80211_TESTMODE) += testmode.o |
8 | obj-$(CONFIG_WL12XX) += wl12xx.o | 9 | obj-$(CONFIG_WL12XX) += wl12xx.o |
9 | obj-$(CONFIG_WL12XX_SPI) += wl12xx_spi.o | 10 | obj-$(CONFIG_WL12XX_SPI) += wl12xx_spi.o |
10 | obj-$(CONFIG_WL12XX_SDIO) += wl12xx_sdio.o | 11 | obj-$(CONFIG_WL12XX_SDIO) += wl12xx_sdio.o |
11 | 12 | ||
13 | obj-$(CONFIG_WL12XX_SDIO_TEST) += wl12xx_sdio_test.o | ||
14 | |||
12 | # small builtin driver bit | 15 | # small builtin driver bit |
13 | obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx_platform_data.o | 16 | obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx_platform_data.o |
diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index 7cbaeb6d2a37..cc4068d2b4a8 100644 --- a/drivers/net/wireless/wl12xx/acx.c +++ b/drivers/net/wireless/wl12xx/acx.c | |||
@@ -1041,7 +1041,7 @@ out: | |||
1041 | return ret; | 1041 | return ret; |
1042 | } | 1042 | } |
1043 | 1043 | ||
1044 | int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, __be32 address) | 1044 | int wl1271_acx_arp_ip_filter(struct wl1271 *wl, u8 enable, __be32 address) |
1045 | { | 1045 | { |
1046 | struct wl1271_acx_arp_filter *acx; | 1046 | struct wl1271_acx_arp_filter *acx; |
1047 | int ret; | 1047 | int ret; |
@@ -1057,7 +1057,7 @@ int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, __be32 address) | |||
1057 | acx->version = ACX_IPV4_VERSION; | 1057 | acx->version = ACX_IPV4_VERSION; |
1058 | acx->enable = enable; | 1058 | acx->enable = enable; |
1059 | 1059 | ||
1060 | if (enable == true) | 1060 | if (enable) |
1061 | memcpy(acx->address, &address, ACX_IPV4_ADDR_SIZE); | 1061 | memcpy(acx->address, &address, ACX_IPV4_ADDR_SIZE); |
1062 | 1062 | ||
1063 | ret = wl1271_cmd_configure(wl, ACX_ARP_IP_FILTER, | 1063 | ret = wl1271_cmd_configure(wl, ACX_ARP_IP_FILTER, |
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h index 75a6306ff554..9cbc3f40c8dd 100644 --- a/drivers/net/wireless/wl12xx/acx.h +++ b/drivers/net/wireless/wl12xx/acx.h | |||
@@ -868,10 +868,15 @@ struct wl1271_acx_bet_enable { | |||
868 | #define ACX_IPV4_VERSION 4 | 868 | #define ACX_IPV4_VERSION 4 |
869 | #define ACX_IPV6_VERSION 6 | 869 | #define ACX_IPV6_VERSION 6 |
870 | #define ACX_IPV4_ADDR_SIZE 4 | 870 | #define ACX_IPV4_ADDR_SIZE 4 |
871 | |||
872 | /* bitmap of enabled arp_filter features */ | ||
873 | #define ACX_ARP_FILTER_ARP_FILTERING BIT(0) | ||
874 | #define ACX_ARP_FILTER_AUTO_ARP BIT(1) | ||
875 | |||
871 | struct wl1271_acx_arp_filter { | 876 | struct wl1271_acx_arp_filter { |
872 | struct acx_header header; | 877 | struct acx_header header; |
873 | u8 version; /* ACX_IPV4_VERSION, ACX_IPV6_VERSION */ | 878 | u8 version; /* ACX_IPV4_VERSION, ACX_IPV6_VERSION */ |
874 | u8 enable; /* 1 to enable ARP filtering, 0 to disable */ | 879 | u8 enable; /* bitmap of enabled ARP filtering features */ |
875 | u8 padding[2]; | 880 | u8 padding[2]; |
876 | u8 address[16]; /* The configured device IP address - all ARP | 881 | u8 address[16]; /* The configured device IP address - all ARP |
877 | requests directed to this IP address will pass | 882 | requests directed to this IP address will pass |
@@ -1168,7 +1173,7 @@ int wl1271_acx_init_mem_config(struct wl1271 *wl); | |||
1168 | int wl1271_acx_init_rx_interrupt(struct wl1271 *wl); | 1173 | int wl1271_acx_init_rx_interrupt(struct wl1271 *wl); |
1169 | int wl1271_acx_smart_reflex(struct wl1271 *wl); | 1174 | int wl1271_acx_smart_reflex(struct wl1271 *wl); |
1170 | int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable); | 1175 | int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable); |
1171 | int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, __be32 address); | 1176 | int wl1271_acx_arp_ip_filter(struct wl1271 *wl, u8 enable, __be32 address); |
1172 | int wl1271_acx_pm_config(struct wl1271 *wl); | 1177 | int wl1271_acx_pm_config(struct wl1271 *wl); |
1173 | int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable); | 1178 | int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable); |
1174 | int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid); | 1179 | int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid); |
diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c index 1eafb8175832..4a9f929725fd 100644 --- a/drivers/net/wireless/wl12xx/boot.c +++ b/drivers/net/wireless/wl12xx/boot.c | |||
@@ -467,7 +467,8 @@ static void wl1271_boot_hw_version(struct wl1271 *wl) | |||
467 | wl->hw_pg_ver = (s8)fuse; | 467 | wl->hw_pg_ver = (s8)fuse; |
468 | } | 468 | } |
469 | 469 | ||
470 | int wl1271_boot(struct wl1271 *wl) | 470 | /* uploads NVS and firmware */ |
471 | int wl1271_load_firmware(struct wl1271 *wl) | ||
471 | { | 472 | { |
472 | int ret = 0; | 473 | int ret = 0; |
473 | u32 tmp, clk, pause; | 474 | u32 tmp, clk, pause; |
@@ -572,6 +573,20 @@ int wl1271_boot(struct wl1271 *wl) | |||
572 | if (ret < 0) | 573 | if (ret < 0) |
573 | goto out; | 574 | goto out; |
574 | 575 | ||
576 | out: | ||
577 | return ret; | ||
578 | } | ||
579 | EXPORT_SYMBOL_GPL(wl1271_load_firmware); | ||
580 | |||
581 | int wl1271_boot(struct wl1271 *wl) | ||
582 | { | ||
583 | int ret; | ||
584 | |||
585 | /* upload NVS and firmware */ | ||
586 | ret = wl1271_load_firmware(wl); | ||
587 | if (ret) | ||
588 | return ret; | ||
589 | |||
575 | /* 10.5 start firmware */ | 590 | /* 10.5 start firmware */ |
576 | ret = wl1271_boot_run_firmware(wl); | 591 | ret = wl1271_boot_run_firmware(wl); |
577 | if (ret < 0) | 592 | if (ret < 0) |
diff --git a/drivers/net/wireless/wl12xx/boot.h b/drivers/net/wireless/wl12xx/boot.h index c7d771959f3a..d67dcffa31eb 100644 --- a/drivers/net/wireless/wl12xx/boot.h +++ b/drivers/net/wireless/wl12xx/boot.h | |||
@@ -27,6 +27,7 @@ | |||
27 | #include "wl12xx.h" | 27 | #include "wl12xx.h" |
28 | 28 | ||
29 | int wl1271_boot(struct wl1271 *wl); | 29 | int wl1271_boot(struct wl1271 *wl); |
30 | int wl1271_load_firmware(struct wl1271 *wl); | ||
30 | 31 | ||
31 | #define WL1271_NO_SUBBANDS 8 | 32 | #define WL1271_NO_SUBBANDS 8 |
32 | #define WL1271_NO_POWER_LEVELS 4 | 33 | #define WL1271_NO_POWER_LEVELS 4 |
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index f3d0541aaad6..0106628aa5a2 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c | |||
@@ -611,6 +611,75 @@ out: | |||
611 | return ret; | 611 | return ret; |
612 | } | 612 | } |
613 | 613 | ||
614 | struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, | ||
615 | struct sk_buff *skb) | ||
616 | { | ||
617 | int ret; | ||
618 | |||
619 | if (!skb) | ||
620 | skb = ieee80211_ap_probereq_get(wl->hw, wl->vif); | ||
621 | if (!skb) | ||
622 | goto out; | ||
623 | |||
624 | wl1271_dump(DEBUG_SCAN, "AP PROBE REQ: ", skb->data, skb->len); | ||
625 | |||
626 | if (wl->band == IEEE80211_BAND_2GHZ) | ||
627 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, | ||
628 | skb->data, skb->len, 0, | ||
629 | wl->conf.tx.basic_rate); | ||
630 | else | ||
631 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, | ||
632 | skb->data, skb->len, 0, | ||
633 | wl->conf.tx.basic_rate_5); | ||
634 | |||
635 | if (ret < 0) | ||
636 | wl1271_error("Unable to set ap probe request template."); | ||
637 | |||
638 | out: | ||
639 | return skb; | ||
640 | } | ||
641 | |||
642 | int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, __be32 ip_addr) | ||
643 | { | ||
644 | int ret; | ||
645 | struct wl12xx_arp_rsp_template tmpl; | ||
646 | struct ieee80211_hdr_3addr *hdr; | ||
647 | struct arphdr *arp_hdr; | ||
648 | |||
649 | memset(&tmpl, 0, sizeof(tmpl)); | ||
650 | |||
651 | /* mac80211 header */ | ||
652 | hdr = &tmpl.hdr; | ||
653 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | | ||
654 | IEEE80211_STYPE_DATA | | ||
655 | IEEE80211_FCTL_TODS); | ||
656 | memcpy(hdr->addr1, wl->vif->bss_conf.bssid, ETH_ALEN); | ||
657 | memcpy(hdr->addr2, wl->vif->addr, ETH_ALEN); | ||
658 | memset(hdr->addr3, 0xff, ETH_ALEN); | ||
659 | |||
660 | /* llc layer */ | ||
661 | memcpy(tmpl.llc_hdr, rfc1042_header, sizeof(rfc1042_header)); | ||
662 | tmpl.llc_type = htons(ETH_P_ARP); | ||
663 | |||
664 | /* arp header */ | ||
665 | arp_hdr = &tmpl.arp_hdr; | ||
666 | arp_hdr->ar_hrd = htons(ARPHRD_ETHER); | ||
667 | arp_hdr->ar_pro = htons(ETH_P_IP); | ||
668 | arp_hdr->ar_hln = ETH_ALEN; | ||
669 | arp_hdr->ar_pln = 4; | ||
670 | arp_hdr->ar_op = htons(ARPOP_REPLY); | ||
671 | |||
672 | /* arp payload */ | ||
673 | memcpy(tmpl.sender_hw, wl->vif->addr, ETH_ALEN); | ||
674 | tmpl.sender_ip = ip_addr; | ||
675 | |||
676 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_ARP_RSP, | ||
677 | &tmpl, sizeof(tmpl), 0, | ||
678 | wl->basic_rate); | ||
679 | |||
680 | return ret; | ||
681 | } | ||
682 | |||
614 | int wl1271_build_qos_null_data(struct wl1271 *wl) | 683 | int wl1271_build_qos_null_data(struct wl1271 *wl) |
615 | { | 684 | { |
616 | struct ieee80211_qos_hdr template; | 685 | struct ieee80211_qos_hdr template; |
diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h index 16d1bf814e76..2a1d9db7ceb8 100644 --- a/drivers/net/wireless/wl12xx/cmd.h +++ b/drivers/net/wireless/wl12xx/cmd.h | |||
@@ -49,6 +49,9 @@ int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid); | |||
49 | int wl1271_cmd_build_probe_req(struct wl1271 *wl, | 49 | int wl1271_cmd_build_probe_req(struct wl1271 *wl, |
50 | const u8 *ssid, size_t ssid_len, | 50 | const u8 *ssid, size_t ssid_len, |
51 | const u8 *ie, size_t ie_len, u8 band); | 51 | const u8 *ie, size_t ie_len, u8 band); |
52 | struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, | ||
53 | struct sk_buff *skb); | ||
54 | int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, __be32 ip_addr); | ||
52 | int wl1271_build_qos_null_data(struct wl1271 *wl); | 55 | int wl1271_build_qos_null_data(struct wl1271 *wl); |
53 | int wl1271_cmd_build_klv_null_data(struct wl1271 *wl); | 56 | int wl1271_cmd_build_klv_null_data(struct wl1271 *wl); |
54 | int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id); | 57 | int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id); |
@@ -122,6 +125,7 @@ enum cmd_templ { | |||
122 | CMD_TEMPL_CTS, /* | 125 | CMD_TEMPL_CTS, /* |
123 | * For CTS-to-self (FastCTS) mechanism | 126 | * For CTS-to-self (FastCTS) mechanism |
124 | * for BT/WLAN coexistence (SoftGemini). */ | 127 | * for BT/WLAN coexistence (SoftGemini). */ |
128 | CMD_TEMPL_ARP_RSP, | ||
125 | CMD_TEMPL_MAX = 0xff | 129 | CMD_TEMPL_MAX = 0xff |
126 | }; | 130 | }; |
127 | 131 | ||
diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index dd71b7d2105c..ec6077760157 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c | |||
@@ -66,19 +66,10 @@ static const struct file_operations name## _ops = { \ | |||
66 | }; | 66 | }; |
67 | 67 | ||
68 | #define DEBUGFS_ADD(name, parent) \ | 68 | #define DEBUGFS_ADD(name, parent) \ |
69 | wl->debugfs.name = debugfs_create_file(#name, 0400, parent, \ | 69 | entry = debugfs_create_file(#name, 0400, parent, \ |
70 | wl, &name## _ops); \ | 70 | wl, &name## _ops); \ |
71 | if (IS_ERR(wl->debugfs.name)) { \ | 71 | if (!entry || IS_ERR(entry)) \ |
72 | ret = PTR_ERR(wl->debugfs.name); \ | 72 | goto err; \ |
73 | wl->debugfs.name = NULL; \ | ||
74 | goto out; \ | ||
75 | } | ||
76 | |||
77 | #define DEBUGFS_DEL(name) \ | ||
78 | do { \ | ||
79 | debugfs_remove(wl->debugfs.name); \ | ||
80 | wl->debugfs.name = NULL; \ | ||
81 | } while (0) | ||
82 | 73 | ||
83 | #define DEBUGFS_FWSTATS_FILE(sub, name, fmt) \ | 74 | #define DEBUGFS_FWSTATS_FILE(sub, name, fmt) \ |
84 | static ssize_t sub## _ ##name## _read(struct file *file, \ | 75 | static ssize_t sub## _ ##name## _read(struct file *file, \ |
@@ -100,10 +91,7 @@ static const struct file_operations sub## _ ##name## _ops = { \ | |||
100 | }; | 91 | }; |
101 | 92 | ||
102 | #define DEBUGFS_FWSTATS_ADD(sub, name) \ | 93 | #define DEBUGFS_FWSTATS_ADD(sub, name) \ |
103 | DEBUGFS_ADD(sub## _ ##name, wl->debugfs.fw_statistics) | 94 | DEBUGFS_ADD(sub## _ ##name, stats) |
104 | |||
105 | #define DEBUGFS_FWSTATS_DEL(sub, name) \ | ||
106 | DEBUGFS_DEL(sub## _ ##name) | ||
107 | 95 | ||
108 | static void wl1271_debugfs_update_stats(struct wl1271 *wl) | 96 | static void wl1271_debugfs_update_stats(struct wl1271 *wl) |
109 | { | 97 | { |
@@ -237,7 +225,7 @@ static ssize_t tx_queue_len_read(struct file *file, char __user *userbuf, | |||
237 | char buf[20]; | 225 | char buf[20]; |
238 | int res; | 226 | int res; |
239 | 227 | ||
240 | queue_len = skb_queue_len(&wl->tx_queue); | 228 | queue_len = wl->tx_queue_count; |
241 | 229 | ||
242 | res = scnprintf(buf, sizeof(buf), "%u\n", queue_len); | 230 | res = scnprintf(buf, sizeof(buf), "%u\n", queue_len); |
243 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); | 231 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); |
@@ -305,109 +293,16 @@ static const struct file_operations gpio_power_ops = { | |||
305 | .llseek = default_llseek, | 293 | .llseek = default_llseek, |
306 | }; | 294 | }; |
307 | 295 | ||
308 | static void wl1271_debugfs_delete_files(struct wl1271 *wl) | ||
309 | { | ||
310 | DEBUGFS_FWSTATS_DEL(tx, internal_desc_overflow); | ||
311 | |||
312 | DEBUGFS_FWSTATS_DEL(rx, out_of_mem); | ||
313 | DEBUGFS_FWSTATS_DEL(rx, hdr_overflow); | ||
314 | DEBUGFS_FWSTATS_DEL(rx, hw_stuck); | ||
315 | DEBUGFS_FWSTATS_DEL(rx, dropped); | ||
316 | DEBUGFS_FWSTATS_DEL(rx, fcs_err); | ||
317 | DEBUGFS_FWSTATS_DEL(rx, xfr_hint_trig); | ||
318 | DEBUGFS_FWSTATS_DEL(rx, path_reset); | ||
319 | DEBUGFS_FWSTATS_DEL(rx, reset_counter); | ||
320 | |||
321 | DEBUGFS_FWSTATS_DEL(dma, rx_requested); | ||
322 | DEBUGFS_FWSTATS_DEL(dma, rx_errors); | ||
323 | DEBUGFS_FWSTATS_DEL(dma, tx_requested); | ||
324 | DEBUGFS_FWSTATS_DEL(dma, tx_errors); | ||
325 | |||
326 | DEBUGFS_FWSTATS_DEL(isr, cmd_cmplt); | ||
327 | DEBUGFS_FWSTATS_DEL(isr, fiqs); | ||
328 | DEBUGFS_FWSTATS_DEL(isr, rx_headers); | ||
329 | DEBUGFS_FWSTATS_DEL(isr, rx_mem_overflow); | ||
330 | DEBUGFS_FWSTATS_DEL(isr, rx_rdys); | ||
331 | DEBUGFS_FWSTATS_DEL(isr, irqs); | ||
332 | DEBUGFS_FWSTATS_DEL(isr, tx_procs); | ||
333 | DEBUGFS_FWSTATS_DEL(isr, decrypt_done); | ||
334 | DEBUGFS_FWSTATS_DEL(isr, dma0_done); | ||
335 | DEBUGFS_FWSTATS_DEL(isr, dma1_done); | ||
336 | DEBUGFS_FWSTATS_DEL(isr, tx_exch_complete); | ||
337 | DEBUGFS_FWSTATS_DEL(isr, commands); | ||
338 | DEBUGFS_FWSTATS_DEL(isr, rx_procs); | ||
339 | DEBUGFS_FWSTATS_DEL(isr, hw_pm_mode_changes); | ||
340 | DEBUGFS_FWSTATS_DEL(isr, host_acknowledges); | ||
341 | DEBUGFS_FWSTATS_DEL(isr, pci_pm); | ||
342 | DEBUGFS_FWSTATS_DEL(isr, wakeups); | ||
343 | DEBUGFS_FWSTATS_DEL(isr, low_rssi); | ||
344 | |||
345 | DEBUGFS_FWSTATS_DEL(wep, addr_key_count); | ||
346 | DEBUGFS_FWSTATS_DEL(wep, default_key_count); | ||
347 | /* skipping wep.reserved */ | ||
348 | DEBUGFS_FWSTATS_DEL(wep, key_not_found); | ||
349 | DEBUGFS_FWSTATS_DEL(wep, decrypt_fail); | ||
350 | DEBUGFS_FWSTATS_DEL(wep, packets); | ||
351 | DEBUGFS_FWSTATS_DEL(wep, interrupt); | ||
352 | |||
353 | DEBUGFS_FWSTATS_DEL(pwr, ps_enter); | ||
354 | DEBUGFS_FWSTATS_DEL(pwr, elp_enter); | ||
355 | DEBUGFS_FWSTATS_DEL(pwr, missing_bcns); | ||
356 | DEBUGFS_FWSTATS_DEL(pwr, wake_on_host); | ||
357 | DEBUGFS_FWSTATS_DEL(pwr, wake_on_timer_exp); | ||
358 | DEBUGFS_FWSTATS_DEL(pwr, tx_with_ps); | ||
359 | DEBUGFS_FWSTATS_DEL(pwr, tx_without_ps); | ||
360 | DEBUGFS_FWSTATS_DEL(pwr, rcvd_beacons); | ||
361 | DEBUGFS_FWSTATS_DEL(pwr, power_save_off); | ||
362 | DEBUGFS_FWSTATS_DEL(pwr, enable_ps); | ||
363 | DEBUGFS_FWSTATS_DEL(pwr, disable_ps); | ||
364 | DEBUGFS_FWSTATS_DEL(pwr, fix_tsf_ps); | ||
365 | /* skipping cont_miss_bcns_spread for now */ | ||
366 | DEBUGFS_FWSTATS_DEL(pwr, rcvd_awake_beacons); | ||
367 | |||
368 | DEBUGFS_FWSTATS_DEL(mic, rx_pkts); | ||
369 | DEBUGFS_FWSTATS_DEL(mic, calc_failure); | ||
370 | |||
371 | DEBUGFS_FWSTATS_DEL(aes, encrypt_fail); | ||
372 | DEBUGFS_FWSTATS_DEL(aes, decrypt_fail); | ||
373 | DEBUGFS_FWSTATS_DEL(aes, encrypt_packets); | ||
374 | DEBUGFS_FWSTATS_DEL(aes, decrypt_packets); | ||
375 | DEBUGFS_FWSTATS_DEL(aes, encrypt_interrupt); | ||
376 | DEBUGFS_FWSTATS_DEL(aes, decrypt_interrupt); | ||
377 | |||
378 | DEBUGFS_FWSTATS_DEL(event, heart_beat); | ||
379 | DEBUGFS_FWSTATS_DEL(event, calibration); | ||
380 | DEBUGFS_FWSTATS_DEL(event, rx_mismatch); | ||
381 | DEBUGFS_FWSTATS_DEL(event, rx_mem_empty); | ||
382 | DEBUGFS_FWSTATS_DEL(event, rx_pool); | ||
383 | DEBUGFS_FWSTATS_DEL(event, oom_late); | ||
384 | DEBUGFS_FWSTATS_DEL(event, phy_transmit_error); | ||
385 | DEBUGFS_FWSTATS_DEL(event, tx_stuck); | ||
386 | |||
387 | DEBUGFS_FWSTATS_DEL(ps, pspoll_timeouts); | ||
388 | DEBUGFS_FWSTATS_DEL(ps, upsd_timeouts); | ||
389 | DEBUGFS_FWSTATS_DEL(ps, upsd_max_sptime); | ||
390 | DEBUGFS_FWSTATS_DEL(ps, upsd_max_apturn); | ||
391 | DEBUGFS_FWSTATS_DEL(ps, pspoll_max_apturn); | ||
392 | DEBUGFS_FWSTATS_DEL(ps, pspoll_utilization); | ||
393 | DEBUGFS_FWSTATS_DEL(ps, upsd_utilization); | ||
394 | |||
395 | DEBUGFS_FWSTATS_DEL(rxpipe, rx_prep_beacon_drop); | ||
396 | DEBUGFS_FWSTATS_DEL(rxpipe, descr_host_int_trig_rx_data); | ||
397 | DEBUGFS_FWSTATS_DEL(rxpipe, beacon_buffer_thres_host_int_trig_rx_data); | ||
398 | DEBUGFS_FWSTATS_DEL(rxpipe, missed_beacon_host_int_trig_rx_data); | ||
399 | DEBUGFS_FWSTATS_DEL(rxpipe, tx_xfr_host_int_trig_rx_data); | ||
400 | |||
401 | DEBUGFS_DEL(tx_queue_len); | ||
402 | DEBUGFS_DEL(retry_count); | ||
403 | DEBUGFS_DEL(excessive_retries); | ||
404 | |||
405 | DEBUGFS_DEL(gpio_power); | ||
406 | } | ||
407 | |||
408 | static int wl1271_debugfs_add_files(struct wl1271 *wl) | 296 | static int wl1271_debugfs_add_files(struct wl1271 *wl) |
409 | { | 297 | { |
410 | int ret = 0; | 298 | int ret = 0; |
299 | struct dentry *entry, *stats; | ||
300 | |||
301 | stats = debugfs_create_dir("fw-statistics", wl->rootdir); | ||
302 | if (!stats || IS_ERR(stats)) { | ||
303 | entry = stats; | ||
304 | goto err; | ||
305 | } | ||
411 | 306 | ||
412 | DEBUGFS_FWSTATS_ADD(tx, internal_desc_overflow); | 307 | DEBUGFS_FWSTATS_ADD(tx, internal_desc_overflow); |
413 | 308 | ||
@@ -500,21 +395,33 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl) | |||
500 | DEBUGFS_FWSTATS_ADD(rxpipe, missed_beacon_host_int_trig_rx_data); | 395 | DEBUGFS_FWSTATS_ADD(rxpipe, missed_beacon_host_int_trig_rx_data); |
501 | DEBUGFS_FWSTATS_ADD(rxpipe, tx_xfr_host_int_trig_rx_data); | 396 | DEBUGFS_FWSTATS_ADD(rxpipe, tx_xfr_host_int_trig_rx_data); |
502 | 397 | ||
503 | DEBUGFS_ADD(tx_queue_len, wl->debugfs.rootdir); | 398 | DEBUGFS_ADD(tx_queue_len, wl->rootdir); |
504 | DEBUGFS_ADD(retry_count, wl->debugfs.rootdir); | 399 | DEBUGFS_ADD(retry_count, wl->rootdir); |
505 | DEBUGFS_ADD(excessive_retries, wl->debugfs.rootdir); | 400 | DEBUGFS_ADD(excessive_retries, wl->rootdir); |
506 | 401 | ||
507 | DEBUGFS_ADD(gpio_power, wl->debugfs.rootdir); | 402 | DEBUGFS_ADD(gpio_power, wl->rootdir); |
508 | 403 | ||
509 | out: | 404 | entry = debugfs_create_x32("debug_level", 0600, wl->rootdir, |
510 | if (ret < 0) | 405 | &wl12xx_debug_level); |
511 | wl1271_debugfs_delete_files(wl); | 406 | if (!entry || IS_ERR(entry)) |
407 | goto err; | ||
408 | |||
409 | return 0; | ||
410 | |||
411 | err: | ||
412 | if (IS_ERR(entry)) | ||
413 | ret = PTR_ERR(entry); | ||
414 | else | ||
415 | ret = -ENOMEM; | ||
512 | 416 | ||
513 | return ret; | 417 | return ret; |
514 | } | 418 | } |
515 | 419 | ||
516 | void wl1271_debugfs_reset(struct wl1271 *wl) | 420 | void wl1271_debugfs_reset(struct wl1271 *wl) |
517 | { | 421 | { |
422 | if (!wl->rootdir) | ||
423 | return; | ||
424 | |||
518 | memset(wl->stats.fw_stats, 0, sizeof(*wl->stats.fw_stats)); | 425 | memset(wl->stats.fw_stats, 0, sizeof(*wl->stats.fw_stats)); |
519 | wl->stats.retry_count = 0; | 426 | wl->stats.retry_count = 0; |
520 | wl->stats.excessive_retries = 0; | 427 | wl->stats.excessive_retries = 0; |
@@ -524,23 +431,15 @@ int wl1271_debugfs_init(struct wl1271 *wl) | |||
524 | { | 431 | { |
525 | int ret; | 432 | int ret; |
526 | 433 | ||
527 | wl->debugfs.rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL); | 434 | wl->rootdir = debugfs_create_dir(KBUILD_MODNAME, |
435 | wl->hw->wiphy->debugfsdir); | ||
528 | 436 | ||
529 | if (IS_ERR(wl->debugfs.rootdir)) { | 437 | if (IS_ERR(wl->rootdir)) { |
530 | ret = PTR_ERR(wl->debugfs.rootdir); | 438 | ret = PTR_ERR(wl->rootdir); |
531 | wl->debugfs.rootdir = NULL; | 439 | wl->rootdir = NULL; |
532 | goto err; | 440 | goto err; |
533 | } | 441 | } |
534 | 442 | ||
535 | wl->debugfs.fw_statistics = debugfs_create_dir("fw-statistics", | ||
536 | wl->debugfs.rootdir); | ||
537 | |||
538 | if (IS_ERR(wl->debugfs.fw_statistics)) { | ||
539 | ret = PTR_ERR(wl->debugfs.fw_statistics); | ||
540 | wl->debugfs.fw_statistics = NULL; | ||
541 | goto err_root; | ||
542 | } | ||
543 | |||
544 | wl->stats.fw_stats = kzalloc(sizeof(*wl->stats.fw_stats), | 443 | wl->stats.fw_stats = kzalloc(sizeof(*wl->stats.fw_stats), |
545 | GFP_KERNEL); | 444 | GFP_KERNEL); |
546 | 445 | ||
@@ -563,12 +462,8 @@ err_file: | |||
563 | wl->stats.fw_stats = NULL; | 462 | wl->stats.fw_stats = NULL; |
564 | 463 | ||
565 | err_fw: | 464 | err_fw: |
566 | debugfs_remove(wl->debugfs.fw_statistics); | 465 | debugfs_remove_recursive(wl->rootdir); |
567 | wl->debugfs.fw_statistics = NULL; | 466 | wl->rootdir = NULL; |
568 | |||
569 | err_root: | ||
570 | debugfs_remove(wl->debugfs.rootdir); | ||
571 | wl->debugfs.rootdir = NULL; | ||
572 | 467 | ||
573 | err: | 468 | err: |
574 | return ret; | 469 | return ret; |
@@ -576,15 +471,10 @@ err: | |||
576 | 471 | ||
577 | void wl1271_debugfs_exit(struct wl1271 *wl) | 472 | void wl1271_debugfs_exit(struct wl1271 *wl) |
578 | { | 473 | { |
579 | wl1271_debugfs_delete_files(wl); | ||
580 | |||
581 | kfree(wl->stats.fw_stats); | 474 | kfree(wl->stats.fw_stats); |
582 | wl->stats.fw_stats = NULL; | 475 | wl->stats.fw_stats = NULL; |
583 | 476 | ||
584 | debugfs_remove(wl->debugfs.fw_statistics); | 477 | debugfs_remove_recursive(wl->rootdir); |
585 | wl->debugfs.fw_statistics = NULL; | 478 | wl->rootdir = NULL; |
586 | |||
587 | debugfs_remove(wl->debugfs.rootdir); | ||
588 | wl->debugfs.rootdir = NULL; | ||
589 | 479 | ||
590 | } | 480 | } |
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index 7949d346aadb..785a5304bfc4 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c | |||
@@ -53,18 +53,16 @@ static int wl1271_init_hwenc_config(struct wl1271 *wl) | |||
53 | int wl1271_init_templates_config(struct wl1271 *wl) | 53 | int wl1271_init_templates_config(struct wl1271 *wl) |
54 | { | 54 | { |
55 | int ret, i; | 55 | int ret, i; |
56 | size_t size; | ||
57 | 56 | ||
58 | /* send empty templates for fw memory reservation */ | 57 | /* send empty templates for fw memory reservation */ |
59 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL, | 58 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL, |
60 | sizeof(struct wl12xx_probe_req_template), | 59 | WL1271_CMD_TEMPL_MAX_SIZE, |
61 | 0, WL1271_RATE_AUTOMATIC); | 60 | 0, WL1271_RATE_AUTOMATIC); |
62 | if (ret < 0) | 61 | if (ret < 0) |
63 | return ret; | 62 | return ret; |
64 | 63 | ||
65 | size = sizeof(struct wl12xx_probe_req_template); | ||
66 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, | 64 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, |
67 | NULL, size, 0, | 65 | NULL, WL1271_CMD_TEMPL_MAX_SIZE, 0, |
68 | WL1271_RATE_AUTOMATIC); | 66 | WL1271_RATE_AUTOMATIC); |
69 | if (ret < 0) | 67 | if (ret < 0) |
70 | return ret; | 68 | return ret; |
@@ -102,6 +100,13 @@ int wl1271_init_templates_config(struct wl1271 *wl) | |||
102 | if (ret < 0) | 100 | if (ret < 0) |
103 | return ret; | 101 | return ret; |
104 | 102 | ||
103 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_ARP_RSP, NULL, | ||
104 | sizeof | ||
105 | (struct wl12xx_arp_rsp_template), | ||
106 | 0, WL1271_RATE_AUTOMATIC); | ||
107 | if (ret < 0) | ||
108 | return ret; | ||
109 | |||
105 | for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) { | 110 | for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) { |
106 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, NULL, | 111 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, NULL, |
107 | WL1271_CMD_TEMPL_MAX_SIZE, i, | 112 | WL1271_CMD_TEMPL_MAX_SIZE, i, |
diff --git a/drivers/net/wireless/wl12xx/io.c b/drivers/net/wireless/wl12xx/io.c index 35c2f1aca6ba..d557f73e7c19 100644 --- a/drivers/net/wireless/wl12xx/io.c +++ b/drivers/net/wireless/wl12xx/io.c | |||
@@ -113,6 +113,7 @@ int wl1271_set_partition(struct wl1271 *wl, | |||
113 | 113 | ||
114 | return 0; | 114 | return 0; |
115 | } | 115 | } |
116 | EXPORT_SYMBOL_GPL(wl1271_set_partition); | ||
116 | 117 | ||
117 | void wl1271_io_reset(struct wl1271 *wl) | 118 | void wl1271_io_reset(struct wl1271 *wl) |
118 | { | 119 | { |
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 708ffe304c6d..062247ef3ad2 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c | |||
@@ -336,7 +336,8 @@ out: | |||
336 | } | 336 | } |
337 | 337 | ||
338 | static int wl1271_reg_notify(struct wiphy *wiphy, | 338 | static int wl1271_reg_notify(struct wiphy *wiphy, |
339 | struct regulatory_request *request) { | 339 | struct regulatory_request *request) |
340 | { | ||
340 | struct ieee80211_supported_band *band; | 341 | struct ieee80211_supported_band *band; |
341 | struct ieee80211_channel *ch; | 342 | struct ieee80211_channel *ch; |
342 | int i; | 343 | int i; |
@@ -569,7 +570,7 @@ static void wl1271_irq_work(struct work_struct *work) | |||
569 | 570 | ||
570 | /* Check if any tx blocks were freed */ | 571 | /* Check if any tx blocks were freed */ |
571 | if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags) && | 572 | if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags) && |
572 | !skb_queue_empty(&wl->tx_queue)) { | 573 | wl->tx_queue_count) { |
573 | /* | 574 | /* |
574 | * In order to avoid starvation of the TX path, | 575 | * In order to avoid starvation of the TX path, |
575 | * call the work function directly. | 576 | * call the work function directly. |
@@ -890,6 +891,7 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
890 | struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb); | 891 | struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb); |
891 | struct ieee80211_sta *sta = txinfo->control.sta; | 892 | struct ieee80211_sta *sta = txinfo->control.sta; |
892 | unsigned long flags; | 893 | unsigned long flags; |
894 | int q; | ||
893 | 895 | ||
894 | /* | 896 | /* |
895 | * peek into the rates configured in the STA entry. | 897 | * peek into the rates configured in the STA entry. |
@@ -917,10 +919,12 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
917 | set_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags); | 919 | set_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags); |
918 | } | 920 | } |
919 | #endif | 921 | #endif |
922 | wl->tx_queue_count++; | ||
920 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 923 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
921 | 924 | ||
922 | /* queue the packet */ | 925 | /* queue the packet */ |
923 | skb_queue_tail(&wl->tx_queue, skb); | 926 | q = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); |
927 | skb_queue_tail(&wl->tx_queue[q], skb); | ||
924 | 928 | ||
925 | /* | 929 | /* |
926 | * The chip specific setup must run before the first TX packet - | 930 | * The chip specific setup must run before the first TX packet - |
@@ -934,7 +938,7 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
934 | * The workqueue is slow to process the tx_queue and we need stop | 938 | * The workqueue is slow to process the tx_queue and we need stop |
935 | * the queue here, otherwise the queue will get too long. | 939 | * the queue here, otherwise the queue will get too long. |
936 | */ | 940 | */ |
937 | if (skb_queue_len(&wl->tx_queue) >= WL1271_TX_QUEUE_HIGH_WATERMARK) { | 941 | if (wl->tx_queue_count >= WL1271_TX_QUEUE_HIGH_WATERMARK) { |
938 | wl1271_debug(DEBUG_TX, "op_tx: stopping queues"); | 942 | wl1271_debug(DEBUG_TX, "op_tx: stopping queues"); |
939 | 943 | ||
940 | spin_lock_irqsave(&wl->wl_lock, flags); | 944 | spin_lock_irqsave(&wl->wl_lock, flags); |
@@ -1064,6 +1068,16 @@ power_off: | |||
1064 | strncpy(wiphy->fw_version, wl->chip.fw_ver, | 1068 | strncpy(wiphy->fw_version, wl->chip.fw_ver, |
1065 | sizeof(wiphy->fw_version)); | 1069 | sizeof(wiphy->fw_version)); |
1066 | 1070 | ||
1071 | /* | ||
1072 | * Now we know if 11a is supported (info from the NVS), so disable | ||
1073 | * 11a channels if not supported | ||
1074 | */ | ||
1075 | if (!wl->enable_11a) | ||
1076 | wiphy->bands[IEEE80211_BAND_5GHZ]->n_channels = 0; | ||
1077 | |||
1078 | wl1271_debug(DEBUG_MAC80211, "11a is %ssupported", | ||
1079 | wl->enable_11a ? "" : "not "); | ||
1080 | |||
1067 | out: | 1081 | out: |
1068 | mutex_unlock(&wl->mutex); | 1082 | mutex_unlock(&wl->mutex); |
1069 | 1083 | ||
@@ -1157,10 +1171,16 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | |||
1157 | struct wl1271 *wl = hw->priv; | 1171 | struct wl1271 *wl = hw->priv; |
1158 | 1172 | ||
1159 | mutex_lock(&wl->mutex); | 1173 | mutex_lock(&wl->mutex); |
1160 | WARN_ON(wl->vif != vif); | 1174 | /* |
1161 | __wl1271_op_remove_interface(wl); | 1175 | * wl->vif can be null here if someone shuts down the interface |
1162 | mutex_unlock(&wl->mutex); | 1176 | * just when hardware recovery has been started. |
1177 | */ | ||
1178 | if (wl->vif) { | ||
1179 | WARN_ON(wl->vif != vif); | ||
1180 | __wl1271_op_remove_interface(wl); | ||
1181 | } | ||
1163 | 1182 | ||
1183 | mutex_unlock(&wl->mutex); | ||
1164 | cancel_work_sync(&wl->recovery_work); | 1184 | cancel_work_sync(&wl->recovery_work); |
1165 | } | 1185 | } |
1166 | 1186 | ||
@@ -1801,21 +1821,21 @@ out: | |||
1801 | return ret; | 1821 | return ret; |
1802 | } | 1822 | } |
1803 | 1823 | ||
1804 | static void wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *beacon) | 1824 | static void wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *skb, |
1825 | int offset) | ||
1805 | { | 1826 | { |
1806 | u8 *ptr = beacon->data + | 1827 | u8 *ptr = skb->data + offset; |
1807 | offsetof(struct ieee80211_mgmt, u.beacon.variable); | ||
1808 | 1828 | ||
1809 | /* find the location of the ssid in the beacon */ | 1829 | /* find the location of the ssid in the beacon */ |
1810 | while (ptr < beacon->data + beacon->len) { | 1830 | while (ptr < skb->data + skb->len) { |
1811 | if (ptr[0] == WLAN_EID_SSID) { | 1831 | if (ptr[0] == WLAN_EID_SSID) { |
1812 | wl->ssid_len = ptr[1]; | 1832 | wl->ssid_len = ptr[1]; |
1813 | memcpy(wl->ssid, ptr+2, wl->ssid_len); | 1833 | memcpy(wl->ssid, ptr+2, wl->ssid_len); |
1814 | return; | 1834 | return; |
1815 | } | 1835 | } |
1816 | ptr += ptr[1]; | 1836 | ptr += (ptr[1] + 2); |
1817 | } | 1837 | } |
1818 | wl1271_error("ad-hoc beacon template has no SSID!\n"); | 1838 | wl1271_error("No SSID in IEs!\n"); |
1819 | } | 1839 | } |
1820 | 1840 | ||
1821 | static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | 1841 | static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, |
@@ -1858,8 +1878,11 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1858 | 1878 | ||
1859 | if (beacon) { | 1879 | if (beacon) { |
1860 | struct ieee80211_hdr *hdr; | 1880 | struct ieee80211_hdr *hdr; |
1881 | int ieoffset = offsetof(struct ieee80211_mgmt, | ||
1882 | u.beacon.variable); | ||
1883 | |||
1884 | wl1271_ssid_set(wl, beacon, ieoffset); | ||
1861 | 1885 | ||
1862 | wl1271_ssid_set(wl, beacon); | ||
1863 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, | 1886 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, |
1864 | beacon->data, | 1887 | beacon->data, |
1865 | beacon->len, 0, | 1888 | beacon->len, 0, |
@@ -1939,6 +1962,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1939 | if (changed & BSS_CHANGED_ASSOC) { | 1962 | if (changed & BSS_CHANGED_ASSOC) { |
1940 | if (bss_conf->assoc) { | 1963 | if (bss_conf->assoc) { |
1941 | u32 rates; | 1964 | u32 rates; |
1965 | int ieoffset; | ||
1942 | wl->aid = bss_conf->aid; | 1966 | wl->aid = bss_conf->aid; |
1943 | set_assoc = true; | 1967 | set_assoc = true; |
1944 | 1968 | ||
@@ -1967,13 +1991,13 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1967 | goto out_sleep; | 1991 | goto out_sleep; |
1968 | 1992 | ||
1969 | /* | 1993 | /* |
1970 | * The SSID is intentionally set to NULL here - the | 1994 | * Get a template for hardware connection maintenance |
1971 | * firmware will set the probe request with a | ||
1972 | * broadcast SSID regardless of what we set in the | ||
1973 | * template. | ||
1974 | */ | 1995 | */ |
1975 | ret = wl1271_cmd_build_probe_req(wl, NULL, 0, | 1996 | dev_kfree_skb(wl->probereq); |
1976 | NULL, 0, wl->band); | 1997 | wl->probereq = wl1271_cmd_build_ap_probe_req(wl, NULL); |
1998 | ieoffset = offsetof(struct ieee80211_mgmt, | ||
1999 | u.probe_req.variable); | ||
2000 | wl1271_ssid_set(wl, wl->probereq, ieoffset); | ||
1977 | 2001 | ||
1978 | /* enable the connection monitoring feature */ | 2002 | /* enable the connection monitoring feature */ |
1979 | ret = wl1271_acx_conn_monit_params(wl, true); | 2003 | ret = wl1271_acx_conn_monit_params(wl, true); |
@@ -1996,6 +2020,10 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1996 | clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); | 2020 | clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); |
1997 | wl->aid = 0; | 2021 | wl->aid = 0; |
1998 | 2022 | ||
2023 | /* free probe-request template */ | ||
2024 | dev_kfree_skb(wl->probereq); | ||
2025 | wl->probereq = NULL; | ||
2026 | |||
1999 | /* re-enable dynamic ps - just in case */ | 2027 | /* re-enable dynamic ps - just in case */ |
2000 | ieee80211_enable_dyn_ps(wl->vif); | 2028 | ieee80211_enable_dyn_ps(wl->vif); |
2001 | 2029 | ||
@@ -2085,10 +2113,26 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
2085 | __be32 addr = bss_conf->arp_addr_list[0]; | 2113 | __be32 addr = bss_conf->arp_addr_list[0]; |
2086 | WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS); | 2114 | WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS); |
2087 | 2115 | ||
2088 | if (bss_conf->arp_addr_cnt == 1 && bss_conf->arp_filter_enabled) | 2116 | if (bss_conf->arp_addr_cnt == 1 && |
2089 | ret = wl1271_acx_arp_ip_filter(wl, true, addr); | 2117 | bss_conf->arp_filter_enabled) { |
2090 | else | 2118 | /* |
2091 | ret = wl1271_acx_arp_ip_filter(wl, false, addr); | 2119 | * The template should have been configured only upon |
2120 | * association. however, it seems that the correct ip | ||
2121 | * isn't being set (when sending), so we have to | ||
2122 | * reconfigure the template upon every ip change. | ||
2123 | */ | ||
2124 | ret = wl1271_cmd_build_arp_rsp(wl, addr); | ||
2125 | if (ret < 0) { | ||
2126 | wl1271_warning("build arp rsp failed: %d", ret); | ||
2127 | goto out_sleep; | ||
2128 | } | ||
2129 | |||
2130 | ret = wl1271_acx_arp_ip_filter(wl, | ||
2131 | (ACX_ARP_FILTER_ARP_FILTERING | | ||
2132 | ACX_ARP_FILTER_AUTO_ARP), | ||
2133 | addr); | ||
2134 | } else | ||
2135 | ret = wl1271_acx_arp_ip_filter(wl, 0, addr); | ||
2092 | 2136 | ||
2093 | if (ret < 0) | 2137 | if (ret < 0) |
2094 | goto out_sleep; | 2138 | goto out_sleep; |
@@ -2353,14 +2397,6 @@ static struct ieee80211_rate wl1271_rates_5ghz[] = { | |||
2353 | 2397 | ||
2354 | /* 5 GHz band channels for WL1273 */ | 2398 | /* 5 GHz band channels for WL1273 */ |
2355 | static struct ieee80211_channel wl1271_channels_5ghz[] = { | 2399 | static struct ieee80211_channel wl1271_channels_5ghz[] = { |
2356 | { .hw_value = 183, .center_freq = 4915}, | ||
2357 | { .hw_value = 184, .center_freq = 4920}, | ||
2358 | { .hw_value = 185, .center_freq = 4925}, | ||
2359 | { .hw_value = 187, .center_freq = 4935}, | ||
2360 | { .hw_value = 188, .center_freq = 4940}, | ||
2361 | { .hw_value = 189, .center_freq = 4945}, | ||
2362 | { .hw_value = 192, .center_freq = 4960}, | ||
2363 | { .hw_value = 196, .center_freq = 4980}, | ||
2364 | { .hw_value = 7, .center_freq = 5035}, | 2400 | { .hw_value = 7, .center_freq = 5035}, |
2365 | { .hw_value = 8, .center_freq = 5040}, | 2401 | { .hw_value = 8, .center_freq = 5040}, |
2366 | { .hw_value = 9, .center_freq = 5045}, | 2402 | { .hw_value = 9, .center_freq = 5045}, |
@@ -2581,6 +2617,8 @@ int wl1271_register_hw(struct wl1271 *wl) | |||
2581 | 2617 | ||
2582 | wl->mac80211_registered = true; | 2618 | wl->mac80211_registered = true; |
2583 | 2619 | ||
2620 | wl1271_debugfs_init(wl); | ||
2621 | |||
2584 | register_netdevice_notifier(&wl1271_dev_notifier); | 2622 | register_netdevice_notifier(&wl1271_dev_notifier); |
2585 | 2623 | ||
2586 | wl1271_notice("loaded"); | 2624 | wl1271_notice("loaded"); |
@@ -2631,6 +2669,13 @@ int wl1271_init_ieee80211(struct wl1271 *wl) | |||
2631 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | 2669 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
2632 | BIT(NL80211_IFTYPE_ADHOC); | 2670 | BIT(NL80211_IFTYPE_ADHOC); |
2633 | wl->hw->wiphy->max_scan_ssids = 1; | 2671 | wl->hw->wiphy->max_scan_ssids = 1; |
2672 | /* | ||
2673 | * Maximum length of elements in scanning probe request templates | ||
2674 | * should be the maximum length possible for a template, without | ||
2675 | * the IEEE80211 header of the template | ||
2676 | */ | ||
2677 | wl->hw->wiphy->max_scan_ie_len = WL1271_CMD_TEMPL_MAX_SIZE - | ||
2678 | sizeof(struct ieee80211_header); | ||
2634 | wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1271_band_2ghz; | 2679 | wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1271_band_2ghz; |
2635 | wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz; | 2680 | wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz; |
2636 | 2681 | ||
@@ -2677,7 +2722,8 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
2677 | wl->hw = hw; | 2722 | wl->hw = hw; |
2678 | wl->plat_dev = plat_dev; | 2723 | wl->plat_dev = plat_dev; |
2679 | 2724 | ||
2680 | skb_queue_head_init(&wl->tx_queue); | 2725 | for (i = 0; i < NUM_TX_QUEUES; i++) |
2726 | skb_queue_head_init(&wl->tx_queue[i]); | ||
2681 | 2727 | ||
2682 | INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); | 2728 | INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); |
2683 | INIT_DELAYED_WORK(&wl->pspoll_work, wl1271_pspoll_work); | 2729 | INIT_DELAYED_WORK(&wl->pspoll_work, wl1271_pspoll_work); |
@@ -2715,8 +2761,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
2715 | /* Apply default driver configuration. */ | 2761 | /* Apply default driver configuration. */ |
2716 | wl1271_conf_init(wl); | 2762 | wl1271_conf_init(wl); |
2717 | 2763 | ||
2718 | wl1271_debugfs_init(wl); | ||
2719 | |||
2720 | order = get_order(WL1271_AGGR_BUFFER_SIZE); | 2764 | order = get_order(WL1271_AGGR_BUFFER_SIZE); |
2721 | wl->aggr_buf = (u8 *)__get_free_pages(GFP_KERNEL, order); | 2765 | wl->aggr_buf = (u8 *)__get_free_pages(GFP_KERNEL, order); |
2722 | if (!wl->aggr_buf) { | 2766 | if (!wl->aggr_buf) { |
@@ -2793,6 +2837,11 @@ int wl1271_free_hw(struct wl1271 *wl) | |||
2793 | } | 2837 | } |
2794 | EXPORT_SYMBOL_GPL(wl1271_free_hw); | 2838 | EXPORT_SYMBOL_GPL(wl1271_free_hw); |
2795 | 2839 | ||
2840 | u32 wl12xx_debug_level; | ||
2841 | EXPORT_SYMBOL_GPL(wl12xx_debug_level); | ||
2842 | module_param_named(debug_level, wl12xx_debug_level, uint, DEBUG_NONE); | ||
2843 | MODULE_PARM_DESC(debug_level, "wl12xx debugging level"); | ||
2844 | |||
2796 | MODULE_LICENSE("GPL"); | 2845 | MODULE_LICENSE("GPL"); |
2797 | MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>"); | 2846 | MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>"); |
2798 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); | 2847 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); |
diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c index f3f2c5b011ee..6f897b9d90ca 100644 --- a/drivers/net/wireless/wl12xx/scan.c +++ b/drivers/net/wireless/wl12xx/scan.c | |||
@@ -51,6 +51,10 @@ void wl1271_scan_complete_work(struct work_struct *work) | |||
51 | wl->scan.req = NULL; | 51 | wl->scan.req = NULL; |
52 | ieee80211_scan_completed(wl->hw, false); | 52 | ieee80211_scan_completed(wl->hw, false); |
53 | 53 | ||
54 | /* restore hardware connection monitoring template */ | ||
55 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) | ||
56 | wl1271_cmd_build_ap_probe_req(wl, wl->probereq); | ||
57 | |||
54 | if (wl->scan.failed) { | 58 | if (wl->scan.failed) { |
55 | wl1271_info("Scan completed due to error."); | 59 | wl1271_info("Scan completed due to error."); |
56 | ieee80211_queue_work(wl->hw, &wl->recovery_work); | 60 | ieee80211_queue_work(wl->hw, &wl->recovery_work); |
diff --git a/drivers/net/wireless/wl12xx/sdio_test.c b/drivers/net/wireless/wl12xx/sdio_test.c new file mode 100644 index 000000000000..9fcbd3dd8490 --- /dev/null +++ b/drivers/net/wireless/wl12xx/sdio_test.c | |||
@@ -0,0 +1,520 @@ | |||
1 | /* | ||
2 | * SDIO testing driver for wl12xx | ||
3 | * | ||
4 | * Copyright (C) 2010 Nokia Corporation | ||
5 | * | ||
6 | * Contact: Roger Quadros <roger.quadros@nokia.com> | ||
7 | * | ||
8 | * wl12xx read/write routines taken from the main module | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License | ||
12 | * version 2 as published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
22 | * 02110-1301 USA | ||
23 | * | ||
24 | */ | ||
25 | |||
26 | #include <linux/irq.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/crc7.h> | ||
29 | #include <linux/vmalloc.h> | ||
30 | #include <linux/mmc/sdio_func.h> | ||
31 | #include <linux/mmc/sdio_ids.h> | ||
32 | #include <linux/mmc/card.h> | ||
33 | #include <linux/gpio.h> | ||
34 | #include <linux/wl12xx.h> | ||
35 | #include <linux/kthread.h> | ||
36 | #include <linux/firmware.h> | ||
37 | #include <linux/pm_runtime.h> | ||
38 | |||
39 | #include "wl12xx.h" | ||
40 | #include "io.h" | ||
41 | #include "boot.h" | ||
42 | |||
43 | #ifndef SDIO_VENDOR_ID_TI | ||
44 | #define SDIO_VENDOR_ID_TI 0x0097 | ||
45 | #endif | ||
46 | |||
47 | #ifndef SDIO_DEVICE_ID_TI_WL1271 | ||
48 | #define SDIO_DEVICE_ID_TI_WL1271 0x4076 | ||
49 | #endif | ||
50 | |||
51 | static bool rx, tx; | ||
52 | |||
53 | module_param(rx, bool, S_IRUGO | S_IWUSR); | ||
54 | MODULE_PARM_DESC(rx, "Perform rx test. Default (0). " | ||
55 | "This test continuously reads data from the SDIO device.\n"); | ||
56 | |||
57 | module_param(tx, bool, S_IRUGO | S_IWUSR); | ||
58 | MODULE_PARM_DESC(tx, "Perform tx test. Default (0). " | ||
59 | "This test continuously writes data to the SDIO device.\n"); | ||
60 | |||
61 | struct wl1271_test { | ||
62 | struct wl1271 wl; | ||
63 | struct task_struct *test_task; | ||
64 | }; | ||
65 | |||
66 | static const struct sdio_device_id wl1271_devices[] = { | ||
67 | { SDIO_DEVICE(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271) }, | ||
68 | {} | ||
69 | }; | ||
70 | |||
71 | static inline struct sdio_func *wl_to_func(struct wl1271 *wl) | ||
72 | { | ||
73 | return wl->if_priv; | ||
74 | } | ||
75 | |||
76 | static struct device *wl1271_sdio_wl_to_dev(struct wl1271 *wl) | ||
77 | { | ||
78 | return &(wl_to_func(wl)->dev); | ||
79 | } | ||
80 | |||
81 | static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf, | ||
82 | size_t len, bool fixed) | ||
83 | { | ||
84 | int ret = 0; | ||
85 | struct sdio_func *func = wl_to_func(wl); | ||
86 | |||
87 | if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { | ||
88 | ((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret); | ||
89 | wl1271_debug(DEBUG_SDIO, "sdio read 52 addr 0x%x, byte 0x%02x", | ||
90 | addr, ((u8 *)buf)[0]); | ||
91 | } else { | ||
92 | if (fixed) | ||
93 | ret = sdio_readsb(func, buf, addr, len); | ||
94 | else | ||
95 | ret = sdio_memcpy_fromio(func, buf, addr, len); | ||
96 | |||
97 | wl1271_debug(DEBUG_SDIO, "sdio read 53 addr 0x%x, %zu bytes", | ||
98 | addr, len); | ||
99 | wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len); | ||
100 | } | ||
101 | |||
102 | if (ret) | ||
103 | wl1271_error("sdio read failed (%d)", ret); | ||
104 | } | ||
105 | |||
106 | static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf, | ||
107 | size_t len, bool fixed) | ||
108 | { | ||
109 | int ret = 0; | ||
110 | struct sdio_func *func = wl_to_func(wl); | ||
111 | |||
112 | if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { | ||
113 | sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret); | ||
114 | wl1271_debug(DEBUG_SDIO, "sdio write 52 addr 0x%x, byte 0x%02x", | ||
115 | addr, ((u8 *)buf)[0]); | ||
116 | } else { | ||
117 | wl1271_debug(DEBUG_SDIO, "sdio write 53 addr 0x%x, %zu bytes", | ||
118 | addr, len); | ||
119 | wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len); | ||
120 | |||
121 | if (fixed) | ||
122 | ret = sdio_writesb(func, addr, buf, len); | ||
123 | else | ||
124 | ret = sdio_memcpy_toio(func, addr, buf, len); | ||
125 | } | ||
126 | if (ret) | ||
127 | wl1271_error("sdio write failed (%d)", ret); | ||
128 | |||
129 | } | ||
130 | |||
131 | static int wl1271_sdio_set_power(struct wl1271 *wl, bool enable) | ||
132 | { | ||
133 | struct sdio_func *func = wl_to_func(wl); | ||
134 | int ret; | ||
135 | |||
136 | /* Let the SDIO stack handle wlan_enable control, so we | ||
137 | * keep host claimed while wlan is in use to keep wl1271 | ||
138 | * alive. | ||
139 | */ | ||
140 | if (enable) { | ||
141 | /* Power up the card */ | ||
142 | ret = pm_runtime_get_sync(&func->dev); | ||
143 | if (ret < 0) | ||
144 | goto out; | ||
145 | sdio_claim_host(func); | ||
146 | sdio_enable_func(func); | ||
147 | sdio_release_host(func); | ||
148 | } else { | ||
149 | sdio_claim_host(func); | ||
150 | sdio_disable_func(func); | ||
151 | sdio_release_host(func); | ||
152 | |||
153 | /* Power down the card */ | ||
154 | ret = pm_runtime_put_sync(&func->dev); | ||
155 | } | ||
156 | |||
157 | out: | ||
158 | return ret; | ||
159 | } | ||
160 | |||
161 | static void wl1271_sdio_disable_interrupts(struct wl1271 *wl) | ||
162 | { | ||
163 | } | ||
164 | |||
165 | static void wl1271_sdio_enable_interrupts(struct wl1271 *wl) | ||
166 | { | ||
167 | } | ||
168 | |||
169 | |||
170 | static struct wl1271_if_operations sdio_ops = { | ||
171 | .read = wl1271_sdio_raw_read, | ||
172 | .write = wl1271_sdio_raw_write, | ||
173 | .power = wl1271_sdio_set_power, | ||
174 | .dev = wl1271_sdio_wl_to_dev, | ||
175 | .enable_irq = wl1271_sdio_enable_interrupts, | ||
176 | .disable_irq = wl1271_sdio_disable_interrupts, | ||
177 | }; | ||
178 | |||
179 | static void wl1271_fw_wakeup(struct wl1271 *wl) | ||
180 | { | ||
181 | u32 elp_reg; | ||
182 | |||
183 | elp_reg = ELPCTRL_WAKE_UP; | ||
184 | wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg); | ||
185 | } | ||
186 | |||
187 | static int wl1271_fetch_firmware(struct wl1271 *wl) | ||
188 | { | ||
189 | const struct firmware *fw; | ||
190 | int ret; | ||
191 | |||
192 | ret = request_firmware(&fw, WL1271_FW_NAME, wl1271_wl_to_dev(wl)); | ||
193 | |||
194 | if (ret < 0) { | ||
195 | wl1271_error("could not get firmware: %d", ret); | ||
196 | return ret; | ||
197 | } | ||
198 | |||
199 | if (fw->size % 4) { | ||
200 | wl1271_error("firmware size is not multiple of 32 bits: %zu", | ||
201 | fw->size); | ||
202 | ret = -EILSEQ; | ||
203 | goto out; | ||
204 | } | ||
205 | |||
206 | wl->fw_len = fw->size; | ||
207 | wl->fw = vmalloc(wl->fw_len); | ||
208 | |||
209 | if (!wl->fw) { | ||
210 | wl1271_error("could not allocate memory for the firmware"); | ||
211 | ret = -ENOMEM; | ||
212 | goto out; | ||
213 | } | ||
214 | |||
215 | memcpy(wl->fw, fw->data, wl->fw_len); | ||
216 | |||
217 | ret = 0; | ||
218 | |||
219 | out: | ||
220 | release_firmware(fw); | ||
221 | |||
222 | return ret; | ||
223 | } | ||
224 | |||
225 | static int wl1271_fetch_nvs(struct wl1271 *wl) | ||
226 | { | ||
227 | const struct firmware *fw; | ||
228 | int ret; | ||
229 | |||
230 | ret = request_firmware(&fw, WL1271_NVS_NAME, wl1271_wl_to_dev(wl)); | ||
231 | |||
232 | if (ret < 0) { | ||
233 | wl1271_error("could not get nvs file: %d", ret); | ||
234 | return ret; | ||
235 | } | ||
236 | |||
237 | wl->nvs = kmemdup(fw->data, sizeof(struct wl1271_nvs_file), GFP_KERNEL); | ||
238 | |||
239 | if (!wl->nvs) { | ||
240 | wl1271_error("could not allocate memory for the nvs file"); | ||
241 | ret = -ENOMEM; | ||
242 | goto out; | ||
243 | } | ||
244 | |||
245 | wl->nvs_len = fw->size; | ||
246 | |||
247 | out: | ||
248 | release_firmware(fw); | ||
249 | |||
250 | return ret; | ||
251 | } | ||
252 | |||
253 | static int wl1271_chip_wakeup(struct wl1271 *wl) | ||
254 | { | ||
255 | struct wl1271_partition_set partition; | ||
256 | int ret; | ||
257 | |||
258 | msleep(WL1271_PRE_POWER_ON_SLEEP); | ||
259 | ret = wl1271_power_on(wl); | ||
260 | if (ret) | ||
261 | return ret; | ||
262 | |||
263 | msleep(WL1271_POWER_ON_SLEEP); | ||
264 | |||
265 | /* We don't need a real memory partition here, because we only want | ||
266 | * to use the registers at this point. */ | ||
267 | memset(&partition, 0, sizeof(partition)); | ||
268 | partition.reg.start = REGISTERS_BASE; | ||
269 | partition.reg.size = REGISTERS_DOWN_SIZE; | ||
270 | wl1271_set_partition(wl, &partition); | ||
271 | |||
272 | /* ELP module wake up */ | ||
273 | wl1271_fw_wakeup(wl); | ||
274 | |||
275 | /* whal_FwCtrl_BootSm() */ | ||
276 | |||
277 | /* 0. read chip id from CHIP_ID */ | ||
278 | wl->chip.id = wl1271_read32(wl, CHIP_ID_B); | ||
279 | |||
280 | /* 1. check if chip id is valid */ | ||
281 | |||
282 | switch (wl->chip.id) { | ||
283 | case CHIP_ID_1271_PG10: | ||
284 | wl1271_warning("chip id 0x%x (1271 PG10) support is obsolete", | ||
285 | wl->chip.id); | ||
286 | break; | ||
287 | case CHIP_ID_1271_PG20: | ||
288 | wl1271_notice("chip id 0x%x (1271 PG20)", | ||
289 | wl->chip.id); | ||
290 | break; | ||
291 | default: | ||
292 | wl1271_warning("unsupported chip id: 0x%x", wl->chip.id); | ||
293 | return -ENODEV; | ||
294 | } | ||
295 | |||
296 | return ret; | ||
297 | } | ||
298 | |||
299 | static struct wl1271_partition_set part_down = { | ||
300 | .mem = { | ||
301 | .start = 0x00000000, | ||
302 | .size = 0x000177c0 | ||
303 | }, | ||
304 | .reg = { | ||
305 | .start = REGISTERS_BASE, | ||
306 | .size = 0x00008800 | ||
307 | }, | ||
308 | .mem2 = { | ||
309 | .start = 0x00000000, | ||
310 | .size = 0x00000000 | ||
311 | }, | ||
312 | .mem3 = { | ||
313 | .start = 0x00000000, | ||
314 | .size = 0x00000000 | ||
315 | }, | ||
316 | }; | ||
317 | |||
318 | static int tester(void *data) | ||
319 | { | ||
320 | struct wl1271 *wl = data; | ||
321 | struct sdio_func *func = wl_to_func(wl); | ||
322 | struct device *pdev = &func->dev; | ||
323 | int ret = 0; | ||
324 | bool rx_started = 0; | ||
325 | bool tx_started = 0; | ||
326 | uint8_t *tx_buf, *rx_buf; | ||
327 | int test_size = PAGE_SIZE; | ||
328 | u32 addr = 0; | ||
329 | struct wl1271_partition_set partition; | ||
330 | |||
331 | /* We assume chip is powered up and firmware fetched */ | ||
332 | |||
333 | memcpy(&partition, &part_down, sizeof(partition)); | ||
334 | partition.mem.start = addr; | ||
335 | wl1271_set_partition(wl, &partition); | ||
336 | |||
337 | tx_buf = kmalloc(test_size, GFP_KERNEL); | ||
338 | rx_buf = kmalloc(test_size, GFP_KERNEL); | ||
339 | if (!tx_buf || !rx_buf) { | ||
340 | dev_err(pdev, | ||
341 | "Could not allocate memory. Test will not run.\n"); | ||
342 | ret = -ENOMEM; | ||
343 | goto free; | ||
344 | } | ||
345 | |||
346 | memset(tx_buf, 0x5a, test_size); | ||
347 | |||
348 | /* write something in data area so we can read it back */ | ||
349 | wl1271_write(wl, addr, tx_buf, test_size, false); | ||
350 | |||
351 | while (!kthread_should_stop()) { | ||
352 | if (rx && !rx_started) { | ||
353 | dev_info(pdev, "starting rx test\n"); | ||
354 | rx_started = 1; | ||
355 | } else if (!rx && rx_started) { | ||
356 | dev_info(pdev, "stopping rx test\n"); | ||
357 | rx_started = 0; | ||
358 | } | ||
359 | |||
360 | if (tx && !tx_started) { | ||
361 | dev_info(pdev, "starting tx test\n"); | ||
362 | tx_started = 1; | ||
363 | } else if (!tx && tx_started) { | ||
364 | dev_info(pdev, "stopping tx test\n"); | ||
365 | tx_started = 0; | ||
366 | } | ||
367 | |||
368 | if (rx_started) | ||
369 | wl1271_read(wl, addr, rx_buf, test_size, false); | ||
370 | |||
371 | if (tx_started) | ||
372 | wl1271_write(wl, addr, tx_buf, test_size, false); | ||
373 | |||
374 | if (!rx_started && !tx_started) | ||
375 | msleep(100); | ||
376 | } | ||
377 | |||
378 | free: | ||
379 | kfree(tx_buf); | ||
380 | kfree(rx_buf); | ||
381 | return ret; | ||
382 | } | ||
383 | |||
384 | static int __devinit wl1271_probe(struct sdio_func *func, | ||
385 | const struct sdio_device_id *id) | ||
386 | { | ||
387 | const struct wl12xx_platform_data *wlan_data; | ||
388 | struct wl1271 *wl; | ||
389 | struct wl1271_test *wl_test; | ||
390 | int ret = 0; | ||
391 | |||
392 | /* wl1271 has 2 sdio functions we handle just the wlan part */ | ||
393 | if (func->num != 0x02) | ||
394 | return -ENODEV; | ||
395 | |||
396 | wl_test = kzalloc(sizeof(struct wl1271_test), GFP_KERNEL); | ||
397 | if (!wl_test) { | ||
398 | dev_err(&func->dev, "Could not allocate memory\n"); | ||
399 | return -ENOMEM; | ||
400 | } | ||
401 | |||
402 | wl = &wl_test->wl; | ||
403 | |||
404 | wl->if_priv = func; | ||
405 | wl->if_ops = &sdio_ops; | ||
406 | |||
407 | /* Grab access to FN0 for ELP reg. */ | ||
408 | func->card->quirks |= MMC_QUIRK_LENIENT_FN0; | ||
409 | |||
410 | wlan_data = wl12xx_get_platform_data(); | ||
411 | if (IS_ERR(wlan_data)) { | ||
412 | ret = PTR_ERR(wlan_data); | ||
413 | dev_err(&func->dev, "missing wlan platform data: %d\n", ret); | ||
414 | goto out_free; | ||
415 | } | ||
416 | |||
417 | wl->irq = wlan_data->irq; | ||
418 | wl->ref_clock = wlan_data->board_ref_clock; | ||
419 | |||
420 | sdio_set_drvdata(func, wl_test); | ||
421 | |||
422 | |||
423 | /* power up the device */ | ||
424 | ret = wl1271_chip_wakeup(wl); | ||
425 | if (ret) { | ||
426 | dev_err(&func->dev, "could not wake up chip\n"); | ||
427 | goto out_free; | ||
428 | } | ||
429 | |||
430 | if (wl->fw == NULL) { | ||
431 | ret = wl1271_fetch_firmware(wl); | ||
432 | if (ret < 0) { | ||
433 | dev_err(&func->dev, "firmware fetch error\n"); | ||
434 | goto out_off; | ||
435 | } | ||
436 | } | ||
437 | |||
438 | /* fetch NVS */ | ||
439 | if (wl->nvs == NULL) { | ||
440 | ret = wl1271_fetch_nvs(wl); | ||
441 | if (ret < 0) { | ||
442 | dev_err(&func->dev, "NVS fetch error\n"); | ||
443 | goto out_off; | ||
444 | } | ||
445 | } | ||
446 | |||
447 | ret = wl1271_load_firmware(wl); | ||
448 | if (ret < 0) { | ||
449 | dev_err(&func->dev, "firmware load error: %d\n", ret); | ||
450 | goto out_free; | ||
451 | } | ||
452 | |||
453 | dev_info(&func->dev, "initialized\n"); | ||
454 | |||
455 | /* I/O testing will be done in the tester thread */ | ||
456 | |||
457 | wl_test->test_task = kthread_run(tester, wl, "sdio_tester"); | ||
458 | if (IS_ERR(wl_test->test_task)) { | ||
459 | dev_err(&func->dev, "unable to create kernel thread\n"); | ||
460 | ret = PTR_ERR(wl_test->test_task); | ||
461 | goto out_free; | ||
462 | } | ||
463 | |||
464 | return 0; | ||
465 | |||
466 | out_off: | ||
467 | /* power off the chip */ | ||
468 | wl1271_power_off(wl); | ||
469 | |||
470 | out_free: | ||
471 | kfree(wl_test); | ||
472 | return ret; | ||
473 | } | ||
474 | |||
475 | static void __devexit wl1271_remove(struct sdio_func *func) | ||
476 | { | ||
477 | struct wl1271_test *wl_test = sdio_get_drvdata(func); | ||
478 | |||
479 | /* stop the I/O test thread */ | ||
480 | kthread_stop(wl_test->test_task); | ||
481 | |||
482 | /* power off the chip */ | ||
483 | wl1271_power_off(&wl_test->wl); | ||
484 | |||
485 | vfree(wl_test->wl.fw); | ||
486 | wl_test->wl.fw = NULL; | ||
487 | kfree(wl_test->wl.nvs); | ||
488 | wl_test->wl.nvs = NULL; | ||
489 | |||
490 | kfree(wl_test); | ||
491 | } | ||
492 | |||
493 | static struct sdio_driver wl1271_sdio_driver = { | ||
494 | .name = "wl12xx_sdio_test", | ||
495 | .id_table = wl1271_devices, | ||
496 | .probe = wl1271_probe, | ||
497 | .remove = __devexit_p(wl1271_remove), | ||
498 | }; | ||
499 | |||
500 | static int __init wl1271_init(void) | ||
501 | { | ||
502 | int ret; | ||
503 | |||
504 | ret = sdio_register_driver(&wl1271_sdio_driver); | ||
505 | if (ret < 0) | ||
506 | pr_err("failed to register sdio driver: %d\n", ret); | ||
507 | |||
508 | return ret; | ||
509 | } | ||
510 | module_init(wl1271_init); | ||
511 | |||
512 | static void __exit wl1271_exit(void) | ||
513 | { | ||
514 | sdio_unregister_driver(&wl1271_sdio_driver); | ||
515 | } | ||
516 | module_exit(wl1271_exit); | ||
517 | |||
518 | MODULE_LICENSE("GPL"); | ||
519 | MODULE_AUTHOR("Roger Quadros <roger.quadros@nokia.com>"); | ||
520 | |||
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index d332b3f6d0fa..b44c75cd8c1e 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c | |||
@@ -125,7 +125,6 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, | |||
125 | /* queue (we use same identifiers for tid's and ac's */ | 125 | /* queue (we use same identifiers for tid's and ac's */ |
126 | ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); | 126 | ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); |
127 | desc->tid = ac; | 127 | desc->tid = ac; |
128 | |||
129 | desc->aid = TX_HW_DEFAULT_AID; | 128 | desc->aid = TX_HW_DEFAULT_AID; |
130 | desc->reserved = 0; | 129 | desc->reserved = 0; |
131 | 130 | ||
@@ -228,7 +227,7 @@ static void handle_tx_low_watermark(struct wl1271 *wl) | |||
228 | unsigned long flags; | 227 | unsigned long flags; |
229 | 228 | ||
230 | if (test_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags) && | 229 | if (test_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags) && |
231 | skb_queue_len(&wl->tx_queue) <= WL1271_TX_QUEUE_LOW_WATERMARK) { | 230 | wl->tx_queue_count <= WL1271_TX_QUEUE_LOW_WATERMARK) { |
232 | /* firmware buffer has space, restart queues */ | 231 | /* firmware buffer has space, restart queues */ |
233 | spin_lock_irqsave(&wl->wl_lock, flags); | 232 | spin_lock_irqsave(&wl->wl_lock, flags); |
234 | ieee80211_wake_queues(wl->hw); | 233 | ieee80211_wake_queues(wl->hw); |
@@ -237,6 +236,43 @@ static void handle_tx_low_watermark(struct wl1271 *wl) | |||
237 | } | 236 | } |
238 | } | 237 | } |
239 | 238 | ||
239 | static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl) | ||
240 | { | ||
241 | struct sk_buff *skb = NULL; | ||
242 | unsigned long flags; | ||
243 | |||
244 | skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_VO]); | ||
245 | if (skb) | ||
246 | goto out; | ||
247 | skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_VI]); | ||
248 | if (skb) | ||
249 | goto out; | ||
250 | skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_BE]); | ||
251 | if (skb) | ||
252 | goto out; | ||
253 | skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_BK]); | ||
254 | |||
255 | out: | ||
256 | if (skb) { | ||
257 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
258 | wl->tx_queue_count--; | ||
259 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
260 | } | ||
261 | |||
262 | return skb; | ||
263 | } | ||
264 | |||
265 | static void wl1271_skb_queue_head(struct wl1271 *wl, struct sk_buff *skb) | ||
266 | { | ||
267 | unsigned long flags; | ||
268 | int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); | ||
269 | |||
270 | skb_queue_head(&wl->tx_queue[q], skb); | ||
271 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
272 | wl->tx_queue_count++; | ||
273 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
274 | } | ||
275 | |||
240 | void wl1271_tx_work_locked(struct wl1271 *wl) | 276 | void wl1271_tx_work_locked(struct wl1271 *wl) |
241 | { | 277 | { |
242 | struct sk_buff *skb; | 278 | struct sk_buff *skb; |
@@ -270,7 +306,7 @@ void wl1271_tx_work_locked(struct wl1271 *wl) | |||
270 | wl1271_acx_rate_policies(wl); | 306 | wl1271_acx_rate_policies(wl); |
271 | } | 307 | } |
272 | 308 | ||
273 | while ((skb = skb_dequeue(&wl->tx_queue))) { | 309 | while ((skb = wl1271_skb_dequeue(wl))) { |
274 | if (!woken_up) { | 310 | if (!woken_up) { |
275 | ret = wl1271_ps_elp_wakeup(wl, false); | 311 | ret = wl1271_ps_elp_wakeup(wl, false); |
276 | if (ret < 0) | 312 | if (ret < 0) |
@@ -284,9 +320,9 @@ void wl1271_tx_work_locked(struct wl1271 *wl) | |||
284 | * Aggregation buffer is full. | 320 | * Aggregation buffer is full. |
285 | * Flush buffer and try again. | 321 | * Flush buffer and try again. |
286 | */ | 322 | */ |
287 | skb_queue_head(&wl->tx_queue, skb); | 323 | wl1271_skb_queue_head(wl, skb); |
288 | wl1271_write(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf, | 324 | wl1271_write(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf, |
289 | buf_offset, true); | 325 | buf_offset, true); |
290 | sent_packets = true; | 326 | sent_packets = true; |
291 | buf_offset = 0; | 327 | buf_offset = 0; |
292 | continue; | 328 | continue; |
@@ -295,7 +331,7 @@ void wl1271_tx_work_locked(struct wl1271 *wl) | |||
295 | * Firmware buffer is full. | 331 | * Firmware buffer is full. |
296 | * Queue back last skb, and stop aggregating. | 332 | * Queue back last skb, and stop aggregating. |
297 | */ | 333 | */ |
298 | skb_queue_head(&wl->tx_queue, skb); | 334 | wl1271_skb_queue_head(wl, skb); |
299 | /* No work left, avoid scheduling redundant tx work */ | 335 | /* No work left, avoid scheduling redundant tx work */ |
300 | set_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); | 336 | set_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); |
301 | goto out_ack; | 337 | goto out_ack; |
@@ -440,10 +476,13 @@ void wl1271_tx_reset(struct wl1271 *wl) | |||
440 | struct sk_buff *skb; | 476 | struct sk_buff *skb; |
441 | 477 | ||
442 | /* TX failure */ | 478 | /* TX failure */ |
443 | while ((skb = skb_dequeue(&wl->tx_queue))) { | 479 | for (i = 0; i < NUM_TX_QUEUES; i++) { |
444 | wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb); | 480 | while ((skb = skb_dequeue(&wl->tx_queue[i]))) { |
445 | ieee80211_tx_status(wl->hw, skb); | 481 | wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb); |
482 | ieee80211_tx_status(wl->hw, skb); | ||
483 | } | ||
446 | } | 484 | } |
485 | wl->tx_queue_count = 0; | ||
447 | 486 | ||
448 | /* | 487 | /* |
449 | * Make sure the driver is at a consistent state, in case this | 488 | * Make sure the driver is at a consistent state, in case this |
@@ -472,8 +511,7 @@ void wl1271_tx_flush(struct wl1271 *wl) | |||
472 | mutex_lock(&wl->mutex); | 511 | mutex_lock(&wl->mutex); |
473 | wl1271_debug(DEBUG_TX, "flushing tx buffer: %d", | 512 | wl1271_debug(DEBUG_TX, "flushing tx buffer: %d", |
474 | wl->tx_frames_cnt); | 513 | wl->tx_frames_cnt); |
475 | if ((wl->tx_frames_cnt == 0) && | 514 | if ((wl->tx_frames_cnt == 0) && (wl->tx_queue_count == 0)) { |
476 | skb_queue_empty(&wl->tx_queue)) { | ||
477 | mutex_unlock(&wl->mutex); | 515 | mutex_unlock(&wl->mutex); |
478 | return; | 516 | return; |
479 | } | 517 | } |
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 3c836e6063e6..ce3d31f98c55 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h | |||
@@ -60,31 +60,32 @@ enum { | |||
60 | DEBUG_ALL = ~0, | 60 | DEBUG_ALL = ~0, |
61 | }; | 61 | }; |
62 | 62 | ||
63 | #define DEBUG_LEVEL (DEBUG_NONE) | 63 | extern u32 wl12xx_debug_level; |
64 | 64 | ||
65 | #define DEBUG_DUMP_LIMIT 1024 | 65 | #define DEBUG_DUMP_LIMIT 1024 |
66 | 66 | ||
67 | #define wl1271_error(fmt, arg...) \ | 67 | #define wl1271_error(fmt, arg...) \ |
68 | printk(KERN_ERR DRIVER_PREFIX "ERROR " fmt "\n", ##arg) | 68 | pr_err(DRIVER_PREFIX "ERROR " fmt "\n", ##arg) |
69 | 69 | ||
70 | #define wl1271_warning(fmt, arg...) \ | 70 | #define wl1271_warning(fmt, arg...) \ |
71 | printk(KERN_WARNING DRIVER_PREFIX "WARNING " fmt "\n", ##arg) | 71 | pr_warning(DRIVER_PREFIX "WARNING " fmt "\n", ##arg) |
72 | 72 | ||
73 | #define wl1271_notice(fmt, arg...) \ | 73 | #define wl1271_notice(fmt, arg...) \ |
74 | printk(KERN_INFO DRIVER_PREFIX fmt "\n", ##arg) | 74 | pr_info(DRIVER_PREFIX fmt "\n", ##arg) |
75 | 75 | ||
76 | #define wl1271_info(fmt, arg...) \ | 76 | #define wl1271_info(fmt, arg...) \ |
77 | printk(KERN_DEBUG DRIVER_PREFIX fmt "\n", ##arg) | 77 | pr_info(DRIVER_PREFIX fmt "\n", ##arg) |
78 | 78 | ||
79 | #define wl1271_debug(level, fmt, arg...) \ | 79 | #define wl1271_debug(level, fmt, arg...) \ |
80 | do { \ | 80 | do { \ |
81 | if (level & DEBUG_LEVEL) \ | 81 | if (level & wl12xx_debug_level) \ |
82 | printk(KERN_DEBUG DRIVER_PREFIX fmt "\n", ##arg); \ | 82 | pr_debug(DRIVER_PREFIX fmt "\n", ##arg); \ |
83 | } while (0) | 83 | } while (0) |
84 | 84 | ||
85 | /* TODO: use pr_debug_hex_dump when it will be available */ | ||
85 | #define wl1271_dump(level, prefix, buf, len) \ | 86 | #define wl1271_dump(level, prefix, buf, len) \ |
86 | do { \ | 87 | do { \ |
87 | if (level & DEBUG_LEVEL) \ | 88 | if (level & wl12xx_debug_level) \ |
88 | print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \ | 89 | print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \ |
89 | DUMP_PREFIX_OFFSET, 16, 1, \ | 90 | DUMP_PREFIX_OFFSET, 16, 1, \ |
90 | buf, \ | 91 | buf, \ |
@@ -94,7 +95,7 @@ enum { | |||
94 | 95 | ||
95 | #define wl1271_dump_ascii(level, prefix, buf, len) \ | 96 | #define wl1271_dump_ascii(level, prefix, buf, len) \ |
96 | do { \ | 97 | do { \ |
97 | if (level & DEBUG_LEVEL) \ | 98 | if (level & wl12xx_debug_level) \ |
98 | print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \ | 99 | print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \ |
99 | DUMP_PREFIX_OFFSET, 16, 1, \ | 100 | DUMP_PREFIX_OFFSET, 16, 1, \ |
100 | buf, \ | 101 | buf, \ |
@@ -174,108 +175,6 @@ struct wl1271_stats { | |||
174 | unsigned int excessive_retries; | 175 | unsigned int excessive_retries; |
175 | }; | 176 | }; |
176 | 177 | ||
177 | struct wl1271_debugfs { | ||
178 | struct dentry *rootdir; | ||
179 | struct dentry *fw_statistics; | ||
180 | |||
181 | struct dentry *tx_internal_desc_overflow; | ||
182 | |||
183 | struct dentry *rx_out_of_mem; | ||
184 | struct dentry *rx_hdr_overflow; | ||
185 | struct dentry *rx_hw_stuck; | ||
186 | struct dentry *rx_dropped; | ||
187 | struct dentry *rx_fcs_err; | ||
188 | struct dentry *rx_xfr_hint_trig; | ||
189 | struct dentry *rx_path_reset; | ||
190 | struct dentry *rx_reset_counter; | ||
191 | |||
192 | struct dentry *dma_rx_requested; | ||
193 | struct dentry *dma_rx_errors; | ||
194 | struct dentry *dma_tx_requested; | ||
195 | struct dentry *dma_tx_errors; | ||
196 | |||
197 | struct dentry *isr_cmd_cmplt; | ||
198 | struct dentry *isr_fiqs; | ||
199 | struct dentry *isr_rx_headers; | ||
200 | struct dentry *isr_rx_mem_overflow; | ||
201 | struct dentry *isr_rx_rdys; | ||
202 | struct dentry *isr_irqs; | ||
203 | struct dentry *isr_tx_procs; | ||
204 | struct dentry *isr_decrypt_done; | ||
205 | struct dentry *isr_dma0_done; | ||
206 | struct dentry *isr_dma1_done; | ||
207 | struct dentry *isr_tx_exch_complete; | ||
208 | struct dentry *isr_commands; | ||
209 | struct dentry *isr_rx_procs; | ||
210 | struct dentry *isr_hw_pm_mode_changes; | ||
211 | struct dentry *isr_host_acknowledges; | ||
212 | struct dentry *isr_pci_pm; | ||
213 | struct dentry *isr_wakeups; | ||
214 | struct dentry *isr_low_rssi; | ||
215 | |||
216 | struct dentry *wep_addr_key_count; | ||
217 | struct dentry *wep_default_key_count; | ||
218 | /* skipping wep.reserved */ | ||
219 | struct dentry *wep_key_not_found; | ||
220 | struct dentry *wep_decrypt_fail; | ||
221 | struct dentry *wep_packets; | ||
222 | struct dentry *wep_interrupt; | ||
223 | |||
224 | struct dentry *pwr_ps_enter; | ||
225 | struct dentry *pwr_elp_enter; | ||
226 | struct dentry *pwr_missing_bcns; | ||
227 | struct dentry *pwr_wake_on_host; | ||
228 | struct dentry *pwr_wake_on_timer_exp; | ||
229 | struct dentry *pwr_tx_with_ps; | ||
230 | struct dentry *pwr_tx_without_ps; | ||
231 | struct dentry *pwr_rcvd_beacons; | ||
232 | struct dentry *pwr_power_save_off; | ||
233 | struct dentry *pwr_enable_ps; | ||
234 | struct dentry *pwr_disable_ps; | ||
235 | struct dentry *pwr_fix_tsf_ps; | ||
236 | /* skipping cont_miss_bcns_spread for now */ | ||
237 | struct dentry *pwr_rcvd_awake_beacons; | ||
238 | |||
239 | struct dentry *mic_rx_pkts; | ||
240 | struct dentry *mic_calc_failure; | ||
241 | |||
242 | struct dentry *aes_encrypt_fail; | ||
243 | struct dentry *aes_decrypt_fail; | ||
244 | struct dentry *aes_encrypt_packets; | ||
245 | struct dentry *aes_decrypt_packets; | ||
246 | struct dentry *aes_encrypt_interrupt; | ||
247 | struct dentry *aes_decrypt_interrupt; | ||
248 | |||
249 | struct dentry *event_heart_beat; | ||
250 | struct dentry *event_calibration; | ||
251 | struct dentry *event_rx_mismatch; | ||
252 | struct dentry *event_rx_mem_empty; | ||
253 | struct dentry *event_rx_pool; | ||
254 | struct dentry *event_oom_late; | ||
255 | struct dentry *event_phy_transmit_error; | ||
256 | struct dentry *event_tx_stuck; | ||
257 | |||
258 | struct dentry *ps_pspoll_timeouts; | ||
259 | struct dentry *ps_upsd_timeouts; | ||
260 | struct dentry *ps_upsd_max_sptime; | ||
261 | struct dentry *ps_upsd_max_apturn; | ||
262 | struct dentry *ps_pspoll_max_apturn; | ||
263 | struct dentry *ps_pspoll_utilization; | ||
264 | struct dentry *ps_upsd_utilization; | ||
265 | |||
266 | struct dentry *rxpipe_rx_prep_beacon_drop; | ||
267 | struct dentry *rxpipe_descr_host_int_trig_rx_data; | ||
268 | struct dentry *rxpipe_beacon_buffer_thres_host_int_trig_rx_data; | ||
269 | struct dentry *rxpipe_missed_beacon_host_int_trig_rx_data; | ||
270 | struct dentry *rxpipe_tx_xfr_host_int_trig_rx_data; | ||
271 | |||
272 | struct dentry *tx_queue_len; | ||
273 | |||
274 | struct dentry *retry_count; | ||
275 | struct dentry *excessive_retries; | ||
276 | struct dentry *gpio_power; | ||
277 | }; | ||
278 | |||
279 | #define NUM_TX_QUEUES 4 | 178 | #define NUM_TX_QUEUES 4 |
280 | #define NUM_RX_PKT_DESC 8 | 179 | #define NUM_RX_PKT_DESC 8 |
281 | 180 | ||
@@ -393,7 +292,8 @@ struct wl1271 { | |||
393 | int session_counter; | 292 | int session_counter; |
394 | 293 | ||
395 | /* Frames scheduled for transmission, not handled yet */ | 294 | /* Frames scheduled for transmission, not handled yet */ |
396 | struct sk_buff_head tx_queue; | 295 | struct sk_buff_head tx_queue[NUM_TX_QUEUES]; |
296 | int tx_queue_count; | ||
397 | 297 | ||
398 | struct work_struct tx_work; | 298 | struct work_struct tx_work; |
399 | 299 | ||
@@ -431,6 +331,9 @@ struct wl1271 { | |||
431 | struct wl1271_scan scan; | 331 | struct wl1271_scan scan; |
432 | struct delayed_work scan_complete_work; | 332 | struct delayed_work scan_complete_work; |
433 | 333 | ||
334 | /* probe-req template for the current AP */ | ||
335 | struct sk_buff *probereq; | ||
336 | |||
434 | /* Our association ID */ | 337 | /* Our association ID */ |
435 | u16 aid; | 338 | u16 aid; |
436 | 339 | ||
@@ -475,7 +378,7 @@ struct wl1271 { | |||
475 | int last_rssi_event; | 378 | int last_rssi_event; |
476 | 379 | ||
477 | struct wl1271_stats stats; | 380 | struct wl1271_stats stats; |
478 | struct wl1271_debugfs debugfs; | 381 | struct dentry *rootdir; |
479 | 382 | ||
480 | __le32 buffer_32; | 383 | __le32 buffer_32; |
481 | u32 buffer_cmd; | 384 | u32 buffer_cmd; |
diff --git a/drivers/net/wireless/wl12xx/wl12xx_80211.h b/drivers/net/wireless/wl12xx/wl12xx_80211.h index 184628027213..be21032f4dc1 100644 --- a/drivers/net/wireless/wl12xx/wl12xx_80211.h +++ b/drivers/net/wireless/wl12xx/wl12xx_80211.h | |||
@@ -2,6 +2,7 @@ | |||
2 | #define __WL12XX_80211_H__ | 2 | #define __WL12XX_80211_H__ |
3 | 3 | ||
4 | #include <linux/if_ether.h> /* ETH_ALEN */ | 4 | #include <linux/if_ether.h> /* ETH_ALEN */ |
5 | #include <linux/if_arp.h> | ||
5 | 6 | ||
6 | /* RATES */ | 7 | /* RATES */ |
7 | #define IEEE80211_CCK_RATE_1MB 0x02 | 8 | #define IEEE80211_CCK_RATE_1MB 0x02 |
@@ -133,11 +134,17 @@ struct wl12xx_qos_null_data_template { | |||
133 | __le16 qos_ctl; | 134 | __le16 qos_ctl; |
134 | } __packed; | 135 | } __packed; |
135 | 136 | ||
136 | struct wl12xx_probe_req_template { | 137 | struct wl12xx_arp_rsp_template { |
137 | struct ieee80211_header header; | 138 | struct ieee80211_hdr_3addr hdr; |
138 | struct wl12xx_ie_ssid ssid; | 139 | |
139 | struct wl12xx_ie_rates rates; | 140 | u8 llc_hdr[sizeof(rfc1042_header)]; |
140 | struct wl12xx_ie_rates ext_rates; | 141 | u16 llc_type; |
142 | |||
143 | struct arphdr arp_hdr; | ||
144 | u8 sender_hw[ETH_ALEN]; | ||
145 | u32 sender_ip; | ||
146 | u8 target_hw[ETH_ALEN]; | ||
147 | u32 target_ip; | ||
141 | } __packed; | 148 | } __packed; |
142 | 149 | ||
143 | 150 | ||