diff options
235 files changed, 19614 insertions, 8457 deletions
diff --git a/Documentation/ABI/obsolete/sysfs-class-rfkill b/Documentation/ABI/obsolete/sysfs-class-rfkill new file mode 100644 index 000000000000..4201d5b05515 --- /dev/null +++ b/Documentation/ABI/obsolete/sysfs-class-rfkill | |||
@@ -0,0 +1,29 @@ | |||
1 | rfkill - radio frequency (RF) connector kill switch support | ||
2 | |||
3 | For details to this subsystem look at Documentation/rfkill.txt. | ||
4 | |||
5 | What: /sys/class/rfkill/rfkill[0-9]+/state | ||
6 | Date: 09-Jul-2007 | ||
7 | KernelVersion v2.6.22 | ||
8 | Contact: linux-wireless@vger.kernel.org | ||
9 | Description: Current state of the transmitter. | ||
10 | This file is deprecated and sheduled to be removed in 2014, | ||
11 | because its not possible to express the 'soft and hard block' | ||
12 | state of the rfkill driver. | ||
13 | Values: A numeric value. | ||
14 | 0: RFKILL_STATE_SOFT_BLOCKED | ||
15 | transmitter is turned off by software | ||
16 | 1: RFKILL_STATE_UNBLOCKED | ||
17 | transmitter is (potentially) active | ||
18 | 2: RFKILL_STATE_HARD_BLOCKED | ||
19 | transmitter is forced off by something outside of | ||
20 | the driver's control. | ||
21 | |||
22 | What: /sys/class/rfkill/rfkill[0-9]+/claim | ||
23 | Date: 09-Jul-2007 | ||
24 | KernelVersion v2.6.22 | ||
25 | Contact: linux-wireless@vger.kernel.org | ||
26 | Description: This file is deprecated because there no longer is a way to | ||
27 | claim just control over a single rfkill instance. | ||
28 | This file is scheduled to be removed in 2012. | ||
29 | Values: 0: Kernel handles events | ||
diff --git a/Documentation/ABI/stable/sysfs-class-rfkill b/Documentation/ABI/stable/sysfs-class-rfkill new file mode 100644 index 000000000000..097f522c33bb --- /dev/null +++ b/Documentation/ABI/stable/sysfs-class-rfkill | |||
@@ -0,0 +1,67 @@ | |||
1 | rfkill - radio frequency (RF) connector kill switch support | ||
2 | |||
3 | For details to this subsystem look at Documentation/rfkill.txt. | ||
4 | |||
5 | For the deprecated /sys/class/rfkill/*/state and | ||
6 | /sys/class/rfkill/*/claim knobs of this interface look in | ||
7 | Documentation/ABI/obsolete/sysfs-class-rfkill. | ||
8 | |||
9 | What: /sys/class/rfkill | ||
10 | Date: 09-Jul-2007 | ||
11 | KernelVersion: v2.6.22 | ||
12 | Contact: linux-wireless@vger.kernel.org, | ||
13 | Description: The rfkill class subsystem folder. | ||
14 | Each registered rfkill driver is represented by an rfkillX | ||
15 | subfolder (X being an integer > 0). | ||
16 | |||
17 | |||
18 | What: /sys/class/rfkill/rfkill[0-9]+/name | ||
19 | Date: 09-Jul-2007 | ||
20 | KernelVersion v2.6.22 | ||
21 | Contact: linux-wireless@vger.kernel.org | ||
22 | Description: Name assigned by driver to this key (interface or driver name). | ||
23 | Values: arbitrary string. | ||
24 | |||
25 | |||
26 | What: /sys/class/rfkill/rfkill[0-9]+/type | ||
27 | Date: 09-Jul-2007 | ||
28 | KernelVersion v2.6.22 | ||
29 | Contact: linux-wireless@vger.kernel.org | ||
30 | Description: Driver type string ("wlan", "bluetooth", etc). | ||
31 | Values: See include/linux/rfkill.h. | ||
32 | |||
33 | |||
34 | What: /sys/class/rfkill/rfkill[0-9]+/persistent | ||
35 | Date: 09-Jul-2007 | ||
36 | KernelVersion v2.6.22 | ||
37 | Contact: linux-wireless@vger.kernel.org | ||
38 | Description: Whether the soft blocked state is initialised from non-volatile | ||
39 | storage at startup. | ||
40 | Values: A numeric value. | ||
41 | 0: false | ||
42 | 1: true | ||
43 | |||
44 | |||
45 | What: /sys/class/rfkill/rfkill[0-9]+/hard | ||
46 | Date: 12-March-2010 | ||
47 | KernelVersion v2.6.34 | ||
48 | Contact: linux-wireless@vger.kernel.org | ||
49 | Description: Current hardblock state. This file is read only. | ||
50 | Values: A numeric value. | ||
51 | 0: inactive | ||
52 | The transmitter is (potentially) active. | ||
53 | 1: active | ||
54 | The transmitter is forced off by something outside of | ||
55 | the driver's control. | ||
56 | |||
57 | |||
58 | What: /sys/class/rfkill/rfkill[0-9]+/soft | ||
59 | Date: 12-March-2010 | ||
60 | KernelVersion v2.6.34 | ||
61 | Contact: linux-wireless@vger.kernel.org | ||
62 | Description: Current softblock state. This file is read and write. | ||
63 | Values: A numeric value. | ||
64 | 0: inactive | ||
65 | The transmitter is (potentially) active. | ||
66 | 1: active | ||
67 | The transmitter is turned off by software. | ||
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 73ef30dbe612..5f460110c5ee 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt | |||
@@ -543,6 +543,24 @@ Who: Eric Miao <eric.y.miao@gmail.com> | |||
543 | 543 | ||
544 | ---------------------------- | 544 | ---------------------------- |
545 | 545 | ||
546 | What: sysfs-class-rfkill state file | ||
547 | When: Feb 2014 | ||
548 | Files: net/rfkill/core.c | ||
549 | Why: Documented as obsolete since Feb 2010. This file is limited to 3 | ||
550 | states while the rfkill drivers can have 4 states. | ||
551 | Who: anybody or Florian Mickler <florian@mickler.org> | ||
552 | |||
553 | ---------------------------- | ||
554 | |||
555 | What: sysfs-class-rfkill claim file | ||
556 | When: Feb 2012 | ||
557 | Files: net/rfkill/core.c | ||
558 | Why: It is not possible to claim an rfkill driver since 2007. This is | ||
559 | Documented as obsolete since Feb 2010. | ||
560 | Who: anybody or Florian Mickler <florian@mickler.org> | ||
561 | |||
562 | ---------------------------- | ||
563 | |||
546 | What: capifs | 564 | What: capifs |
547 | When: February 2011 | 565 | When: February 2011 |
548 | Files: drivers/isdn/capi/capifs.* | 566 | Files: drivers/isdn/capi/capifs.* |
@@ -550,3 +568,26 @@ Why: udev fully replaces this special file system that only contains CAPI | |||
550 | NCCI TTY device nodes. User space (pppdcapiplugin) works without | 568 | NCCI TTY device nodes. User space (pppdcapiplugin) works without |
551 | noticing the difference. | 569 | noticing the difference. |
552 | Who: Jan Kiszka <jan.kiszka@web.de> | 570 | Who: Jan Kiszka <jan.kiszka@web.de> |
571 | |||
572 | ---------------------------- | ||
573 | |||
574 | What: iwlwifi 50XX module parameters | ||
575 | When: 2.6.40 | ||
576 | Why: The "..50" modules parameters were used to configure 5000 series and | ||
577 | up devices; different set of module parameters also available for 4965 | ||
578 | with same functionalities. Consolidate both set into single place | ||
579 | in drivers/net/wireless/iwlwifi/iwl-agn.c | ||
580 | |||
581 | Who: Wey-Yi Guy <wey-yi.w.guy@intel.com> | ||
582 | |||
583 | ---------------------------- | ||
584 | |||
585 | What: iwl4965 alias support | ||
586 | When: 2.6.40 | ||
587 | Why: Internal alias support has been present in module-init-tools for some | ||
588 | time, the MODULE_ALIAS("iwl4965") boilerplate aliases can be removed | ||
589 | with no impact. | ||
590 | |||
591 | Who: Wey-Yi Guy <wey-yi.w.guy@intel.com> | ||
592 | |||
593 | ---------------------------- | ||
diff --git a/Documentation/rfkill.txt b/Documentation/rfkill.txt index b4860509c319..83668e5dd17f 100644 --- a/Documentation/rfkill.txt +++ b/Documentation/rfkill.txt | |||
@@ -99,37 +99,15 @@ system. Also, it is possible to switch all rfkill drivers (or all drivers of | |||
99 | a specified type) into a state which also updates the default state for | 99 | a specified type) into a state which also updates the default state for |
100 | hotplugged devices. | 100 | hotplugged devices. |
101 | 101 | ||
102 | After an application opens /dev/rfkill, it can read the current state of | 102 | After an application opens /dev/rfkill, it can read the current state of all |
103 | all devices, and afterwards can poll the descriptor for hotplug or state | 103 | devices. Changes can be either obtained by either polling the descriptor for |
104 | change events. | 104 | hotplug or state change events or by listening for uevents emitted by the |
105 | 105 | rfkill core framework. | |
106 | Applications must ignore operations (the "op" field) they do not handle, | 106 | |
107 | this allows the API to be extended in the future. | 107 | Additionally, each rfkill device is registered in sysfs and emits uevents. |
108 | 108 | ||
109 | Additionally, each rfkill device is registered in sysfs and there has the | 109 | rfkill devices issue uevents (with an action of "change"), with the following |
110 | following attributes: | 110 | environment variables set: |
111 | |||
112 | name: Name assigned by driver to this key (interface or driver name). | ||
113 | type: Driver type string ("wlan", "bluetooth", etc). | ||
114 | persistent: Whether the soft blocked state is initialised from | ||
115 | non-volatile storage at startup. | ||
116 | state: Current state of the transmitter | ||
117 | 0: RFKILL_STATE_SOFT_BLOCKED | ||
118 | transmitter is turned off by software | ||
119 | 1: RFKILL_STATE_UNBLOCKED | ||
120 | transmitter is (potentially) active | ||
121 | 2: RFKILL_STATE_HARD_BLOCKED | ||
122 | transmitter is forced off by something outside of | ||
123 | the driver's control. | ||
124 | This file is deprecated because it can only properly show | ||
125 | three of the four possible states, soft-and-hard-blocked is | ||
126 | missing. | ||
127 | claim: 0: Kernel handles events | ||
128 | This file is deprecated because there no longer is a way to | ||
129 | claim just control over a single rfkill instance. | ||
130 | |||
131 | rfkill devices also issue uevents (with an action of "change"), with the | ||
132 | following environment variables set: | ||
133 | 111 | ||
134 | RFKILL_NAME | 112 | RFKILL_NAME |
135 | RFKILL_STATE | 113 | RFKILL_STATE |
@@ -137,3 +115,7 @@ RFKILL_TYPE | |||
137 | 115 | ||
138 | The contents of these variables corresponds to the "name", "state" and | 116 | The contents of these variables corresponds to the "name", "state" and |
139 | "type" sysfs files explained above. | 117 | "type" sysfs files explained above. |
118 | |||
119 | |||
120 | For further details consult Documentation/ABI/stable/dev-rfkill and | ||
121 | Documentation/ABI/stable/sysfs-class-rfkill. | ||
diff --git a/drivers/net/ps3_gelic_wireless.c b/drivers/net/ps3_gelic_wireless.c index 2663b2fdc0bb..f5fc0f78fc21 100644 --- a/drivers/net/ps3_gelic_wireless.c +++ b/drivers/net/ps3_gelic_wireless.c | |||
@@ -2279,26 +2279,25 @@ void gelic_wl_interrupt(struct net_device *netdev, u64 status) | |||
2279 | /* | 2279 | /* |
2280 | * driver helpers | 2280 | * driver helpers |
2281 | */ | 2281 | */ |
2282 | #define IW_IOCTL(n) [(n) - SIOCSIWCOMMIT] | ||
2283 | static const iw_handler gelic_wl_wext_handler[] = | 2282 | static const iw_handler gelic_wl_wext_handler[] = |
2284 | { | 2283 | { |
2285 | IW_IOCTL(SIOCGIWNAME) = gelic_wl_get_name, | 2284 | IW_HANDLER(SIOCGIWNAME, gelic_wl_get_name), |
2286 | IW_IOCTL(SIOCGIWRANGE) = gelic_wl_get_range, | 2285 | IW_HANDLER(SIOCGIWRANGE, gelic_wl_get_range), |
2287 | IW_IOCTL(SIOCSIWSCAN) = gelic_wl_set_scan, | 2286 | IW_HANDLER(SIOCSIWSCAN, gelic_wl_set_scan), |
2288 | IW_IOCTL(SIOCGIWSCAN) = gelic_wl_get_scan, | 2287 | IW_HANDLER(SIOCGIWSCAN, gelic_wl_get_scan), |
2289 | IW_IOCTL(SIOCSIWAUTH) = gelic_wl_set_auth, | 2288 | IW_HANDLER(SIOCSIWAUTH, gelic_wl_set_auth), |
2290 | IW_IOCTL(SIOCGIWAUTH) = gelic_wl_get_auth, | 2289 | IW_HANDLER(SIOCGIWAUTH, gelic_wl_get_auth), |
2291 | IW_IOCTL(SIOCSIWESSID) = gelic_wl_set_essid, | 2290 | IW_HANDLER(SIOCSIWESSID, gelic_wl_set_essid), |
2292 | IW_IOCTL(SIOCGIWESSID) = gelic_wl_get_essid, | 2291 | IW_HANDLER(SIOCGIWESSID, gelic_wl_get_essid), |
2293 | IW_IOCTL(SIOCSIWENCODE) = gelic_wl_set_encode, | 2292 | IW_HANDLER(SIOCSIWENCODE, gelic_wl_set_encode), |
2294 | IW_IOCTL(SIOCGIWENCODE) = gelic_wl_get_encode, | 2293 | IW_HANDLER(SIOCGIWENCODE, gelic_wl_get_encode), |
2295 | IW_IOCTL(SIOCSIWAP) = gelic_wl_set_ap, | 2294 | IW_HANDLER(SIOCSIWAP, gelic_wl_set_ap), |
2296 | IW_IOCTL(SIOCGIWAP) = gelic_wl_get_ap, | 2295 | IW_HANDLER(SIOCGIWAP, gelic_wl_get_ap), |
2297 | IW_IOCTL(SIOCSIWENCODEEXT) = gelic_wl_set_encodeext, | 2296 | IW_HANDLER(SIOCSIWENCODEEXT, gelic_wl_set_encodeext), |
2298 | IW_IOCTL(SIOCGIWENCODEEXT) = gelic_wl_get_encodeext, | 2297 | IW_HANDLER(SIOCGIWENCODEEXT, gelic_wl_get_encodeext), |
2299 | IW_IOCTL(SIOCSIWMODE) = gelic_wl_set_mode, | 2298 | IW_HANDLER(SIOCSIWMODE, gelic_wl_set_mode), |
2300 | IW_IOCTL(SIOCGIWMODE) = gelic_wl_get_mode, | 2299 | IW_HANDLER(SIOCGIWMODE, gelic_wl_get_mode), |
2301 | IW_IOCTL(SIOCGIWNICKN) = gelic_wl_get_nick, | 2300 | IW_HANDLER(SIOCGIWNICKN, gelic_wl_get_nick), |
2302 | }; | 2301 | }; |
2303 | 2302 | ||
2304 | static const struct iw_handler_def gelic_wl_wext_handler_def = { | 2303 | static const struct iw_handler_def gelic_wl_wext_handler_def = { |
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index dc5018a6d9ed..a441aad922c2 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c | |||
@@ -2876,7 +2876,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, | |||
2876 | ai->wep_capable = (cap_rid.softCap & cpu_to_le16(0x02)) ? 1 : 0; | 2876 | ai->wep_capable = (cap_rid.softCap & cpu_to_le16(0x02)) ? 1 : 0; |
2877 | ai->max_wep_idx = (cap_rid.softCap & cpu_to_le16(0x80)) ? 3 : 0; | 2877 | ai->max_wep_idx = (cap_rid.softCap & cpu_to_le16(0x80)) ? 3 : 0; |
2878 | 2878 | ||
2879 | airo_print_info(dev->name, "Firmware version %x.%x.%02x", | 2879 | airo_print_info(dev->name, "Firmware version %x.%x.%02d", |
2880 | ((le16_to_cpu(cap_rid.softVer) >> 8) & 0xF), | 2880 | ((le16_to_cpu(cap_rid.softVer) >> 8) & 0xF), |
2881 | (le16_to_cpu(cap_rid.softVer) & 0xFF), | 2881 | (le16_to_cpu(cap_rid.softVer) & 0xFF), |
2882 | le16_to_cpu(cap_rid.softSubVer)); | 2882 | le16_to_cpu(cap_rid.softSubVer)); |
@@ -3193,19 +3193,26 @@ static void airo_print_status(const char *devname, u16 status) | |||
3193 | { | 3193 | { |
3194 | u8 reason = status & 0xFF; | 3194 | u8 reason = status & 0xFF; |
3195 | 3195 | ||
3196 | switch (status) { | 3196 | switch (status & 0xFF00) { |
3197 | case STAT_NOBEACON: | 3197 | case STAT_NOBEACON: |
3198 | airo_print_dbg(devname, "link lost (missed beacons)"); | 3198 | switch (status) { |
3199 | break; | 3199 | case STAT_NOBEACON: |
3200 | case STAT_MAXRETRIES: | 3200 | airo_print_dbg(devname, "link lost (missed beacons)"); |
3201 | case STAT_MAXARL: | 3201 | break; |
3202 | airo_print_dbg(devname, "link lost (max retries)"); | 3202 | case STAT_MAXRETRIES: |
3203 | break; | 3203 | case STAT_MAXARL: |
3204 | case STAT_FORCELOSS: | 3204 | airo_print_dbg(devname, "link lost (max retries)"); |
3205 | airo_print_dbg(devname, "link lost (local choice)"); | 3205 | break; |
3206 | break; | 3206 | case STAT_FORCELOSS: |
3207 | case STAT_TSFSYNC: | 3207 | airo_print_dbg(devname, "link lost (local choice)"); |
3208 | airo_print_dbg(devname, "link lost (TSF sync lost)"); | 3208 | break; |
3209 | case STAT_TSFSYNC: | ||
3210 | airo_print_dbg(devname, "link lost (TSF sync lost)"); | ||
3211 | break; | ||
3212 | default: | ||
3213 | airo_print_dbg(devname, "unknow status %x\n", status); | ||
3214 | break; | ||
3215 | } | ||
3209 | break; | 3216 | break; |
3210 | case STAT_DEAUTH: | 3217 | case STAT_DEAUTH: |
3211 | airo_print_dbg(devname, "deauthenticated (reason: %d)", reason); | 3218 | airo_print_dbg(devname, "deauthenticated (reason: %d)", reason); |
@@ -3221,7 +3228,11 @@ static void airo_print_status(const char *devname, u16 status) | |||
3221 | airo_print_dbg(devname, "authentication failed (reason: %d)", | 3228 | airo_print_dbg(devname, "authentication failed (reason: %d)", |
3222 | reason); | 3229 | reason); |
3223 | break; | 3230 | break; |
3231 | case STAT_ASSOC: | ||
3232 | case STAT_REASSOC: | ||
3233 | break; | ||
3224 | default: | 3234 | default: |
3235 | airo_print_dbg(devname, "unknow status %x\n", status); | ||
3225 | break; | 3236 | break; |
3226 | } | 3237 | } |
3227 | } | 3238 | } |
diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig index 4e7a7fd695c8..0a75be027afa 100644 --- a/drivers/net/wireless/ath/Kconfig +++ b/drivers/net/wireless/ath/Kconfig | |||
@@ -3,7 +3,7 @@ menuconfig ATH_COMMON | |||
3 | depends on CFG80211 | 3 | depends on CFG80211 |
4 | ---help--- | 4 | ---help--- |
5 | This will enable the support for the Atheros wireless drivers. | 5 | This will enable the support for the Atheros wireless drivers. |
6 | ath5k, ath9k and ar9170 drivers share some common code, this option | 6 | ath5k, ath9k, ath9k_htc and ar9170 drivers share some common code, this option |
7 | enables the common ath.ko module which shares common helpers. | 7 | enables the common ath.ko module which shares common helpers. |
8 | 8 | ||
9 | For more information and documentation on this module you can visit: | 9 | For more information and documentation on this module you can visit: |
diff --git a/drivers/net/wireless/ath/ar9170/cmd.h b/drivers/net/wireless/ath/ar9170/cmd.h index 826c45e6b274..ec8134b4b949 100644 --- a/drivers/net/wireless/ath/ar9170/cmd.h +++ b/drivers/net/wireless/ath/ar9170/cmd.h | |||
@@ -79,7 +79,7 @@ __regwrite_out : \ | |||
79 | if (__nreg) { \ | 79 | if (__nreg) { \ |
80 | if (IS_ACCEPTING_CMD(__ar)) \ | 80 | if (IS_ACCEPTING_CMD(__ar)) \ |
81 | __err = ar->exec_cmd(__ar, AR9170_CMD_WREG, \ | 81 | __err = ar->exec_cmd(__ar, AR9170_CMD_WREG, \ |
82 | 8 * __nreg, \ | 82 | 8 * __nreg, \ |
83 | (u8 *) &__ar->cmdbuf[1], \ | 83 | (u8 *) &__ar->cmdbuf[1], \ |
84 | 0, NULL); \ | 84 | 0, NULL); \ |
85 | __nreg = 0; \ | 85 | __nreg = 0; \ |
diff --git a/drivers/net/wireless/ath/ar9170/eeprom.h b/drivers/net/wireless/ath/ar9170/eeprom.h index d2c8cc83f1dd..6c4663883423 100644 --- a/drivers/net/wireless/ath/ar9170/eeprom.h +++ b/drivers/net/wireless/ath/ar9170/eeprom.h | |||
@@ -127,8 +127,8 @@ struct ar9170_eeprom { | |||
127 | __le16 checksum; | 127 | __le16 checksum; |
128 | __le16 version; | 128 | __le16 version; |
129 | u8 operating_flags; | 129 | u8 operating_flags; |
130 | #define AR9170_OPFLAG_5GHZ 1 | 130 | #define AR9170_OPFLAG_5GHZ 1 |
131 | #define AR9170_OPFLAG_2GHZ 2 | 131 | #define AR9170_OPFLAG_2GHZ 2 |
132 | u8 misc; | 132 | u8 misc; |
133 | __le16 reg_domain[2]; | 133 | __le16 reg_domain[2]; |
134 | u8 mac_address[6]; | 134 | u8 mac_address[6]; |
diff --git a/drivers/net/wireless/ath/ar9170/hw.h b/drivers/net/wireless/ath/ar9170/hw.h index 0a1d4c28e68a..06f1f3c951a4 100644 --- a/drivers/net/wireless/ath/ar9170/hw.h +++ b/drivers/net/wireless/ath/ar9170/hw.h | |||
@@ -425,5 +425,6 @@ enum ar9170_txq { | |||
425 | 425 | ||
426 | #define AR9170_TXQ_DEPTH 32 | 426 | #define AR9170_TXQ_DEPTH 32 |
427 | #define AR9170_TX_MAX_PENDING 128 | 427 | #define AR9170_TX_MAX_PENDING 128 |
428 | #define AR9170_RX_STREAM_MAX_SIZE 65535 | ||
428 | 429 | ||
429 | #endif /* __AR9170_HW_H */ | 430 | #endif /* __AR9170_HW_H */ |
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index f4650fcdebc9..fed6695ec04e 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c | |||
@@ -235,7 +235,7 @@ static void __ar9170_dump_txqueue(struct ar9170 *ar, | |||
235 | wiphy_name(ar->hw->wiphy), skb_queue_len(queue)); | 235 | wiphy_name(ar->hw->wiphy), skb_queue_len(queue)); |
236 | 236 | ||
237 | skb_queue_walk(queue, skb) { | 237 | skb_queue_walk(queue, skb) { |
238 | printk(KERN_DEBUG "index:%d => \n", i++); | 238 | printk(KERN_DEBUG "index:%d =>\n", i++); |
239 | ar9170_print_txheader(ar, skb); | 239 | ar9170_print_txheader(ar, skb); |
240 | } | 240 | } |
241 | if (i != skb_queue_len(queue)) | 241 | if (i != skb_queue_len(queue)) |
@@ -280,7 +280,7 @@ static void ar9170_dump_tx_status_ampdu(struct ar9170 *ar) | |||
280 | unsigned long flags; | 280 | unsigned long flags; |
281 | 281 | ||
282 | spin_lock_irqsave(&ar->tx_status_ampdu.lock, flags); | 282 | spin_lock_irqsave(&ar->tx_status_ampdu.lock, flags); |
283 | printk(KERN_DEBUG "%s: A-MPDU tx_status queue => \n", | 283 | printk(KERN_DEBUG "%s: A-MPDU tx_status queue =>\n", |
284 | wiphy_name(ar->hw->wiphy)); | 284 | wiphy_name(ar->hw->wiphy)); |
285 | __ar9170_dump_txqueue(ar, &ar->tx_status_ampdu); | 285 | __ar9170_dump_txqueue(ar, &ar->tx_status_ampdu); |
286 | spin_unlock_irqrestore(&ar->tx_status_ampdu.lock, flags); | 286 | spin_unlock_irqrestore(&ar->tx_status_ampdu.lock, flags); |
@@ -307,7 +307,7 @@ static void ar9170_recycle_expired(struct ar9170 *ar, | |||
307 | if (time_is_before_jiffies(arinfo->timeout)) { | 307 | if (time_is_before_jiffies(arinfo->timeout)) { |
308 | #ifdef AR9170_QUEUE_DEBUG | 308 | #ifdef AR9170_QUEUE_DEBUG |
309 | printk(KERN_DEBUG "%s: [%ld > %ld] frame expired => " | 309 | printk(KERN_DEBUG "%s: [%ld > %ld] frame expired => " |
310 | "recycle \n", wiphy_name(ar->hw->wiphy), | 310 | "recycle\n", wiphy_name(ar->hw->wiphy), |
311 | jiffies, arinfo->timeout); | 311 | jiffies, arinfo->timeout); |
312 | ar9170_print_txheader(ar, skb); | 312 | ar9170_print_txheader(ar, skb); |
313 | #endif /* AR9170_QUEUE_DEBUG */ | 313 | #endif /* AR9170_QUEUE_DEBUG */ |
@@ -688,7 +688,8 @@ void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len) | |||
688 | 688 | ||
689 | /* firmware debug */ | 689 | /* firmware debug */ |
690 | case 0xca: | 690 | case 0xca: |
691 | printk(KERN_DEBUG "ar9170 FW: %.*s\n", len - 4, (char *)buf + 4); | 691 | printk(KERN_DEBUG "ar9170 FW: %.*s\n", len - 4, |
692 | (char *)buf + 4); | ||
692 | break; | 693 | break; |
693 | case 0xcb: | 694 | case 0xcb: |
694 | len -= 4; | 695 | len -= 4; |
@@ -1727,7 +1728,7 @@ static void ar9170_tx(struct ar9170 *ar) | |||
1727 | printk(KERN_DEBUG "%s: queue %d full\n", | 1728 | printk(KERN_DEBUG "%s: queue %d full\n", |
1728 | wiphy_name(ar->hw->wiphy), i); | 1729 | wiphy_name(ar->hw->wiphy), i); |
1729 | 1730 | ||
1730 | printk(KERN_DEBUG "%s: stuck frames: ===> \n", | 1731 | printk(KERN_DEBUG "%s: stuck frames: ===>\n", |
1731 | wiphy_name(ar->hw->wiphy)); | 1732 | wiphy_name(ar->hw->wiphy)); |
1732 | ar9170_dump_txqueue(ar, &ar->tx_pending[i]); | 1733 | ar9170_dump_txqueue(ar, &ar->tx_pending[i]); |
1733 | ar9170_dump_txqueue(ar, &ar->tx_status[i]); | 1734 | ar9170_dump_txqueue(ar, &ar->tx_status[i]); |
@@ -2515,7 +2516,7 @@ void *ar9170_alloc(size_t priv_size) | |||
2515 | * tends to split the streams into seperate rx descriptors. | 2516 | * tends to split the streams into seperate rx descriptors. |
2516 | */ | 2517 | */ |
2517 | 2518 | ||
2518 | skb = __dev_alloc_skb(AR9170_MAX_RX_BUFFER_SIZE, GFP_KERNEL); | 2519 | skb = __dev_alloc_skb(AR9170_RX_STREAM_MAX_SIZE, GFP_KERNEL); |
2519 | if (!skb) | 2520 | if (!skb) |
2520 | goto err_nomem; | 2521 | goto err_nomem; |
2521 | 2522 | ||
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index 71fc960814f0..1fbf6b1f9a7e 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h | |||
@@ -48,6 +48,12 @@ enum ath_device_state { | |||
48 | ATH_HW_INITIALIZED, | 48 | ATH_HW_INITIALIZED, |
49 | }; | 49 | }; |
50 | 50 | ||
51 | enum ath_bus_type { | ||
52 | ATH_PCI, | ||
53 | ATH_AHB, | ||
54 | ATH_USB, | ||
55 | }; | ||
56 | |||
51 | struct reg_dmn_pair_mapping { | 57 | struct reg_dmn_pair_mapping { |
52 | u16 regDmnEnum; | 58 | u16 regDmnEnum; |
53 | u16 reg_5ghz_ctl; | 59 | u16 reg_5ghz_ctl; |
@@ -73,9 +79,10 @@ struct ath_ops { | |||
73 | struct ath_common; | 79 | struct ath_common; |
74 | 80 | ||
75 | struct ath_bus_ops { | 81 | struct ath_bus_ops { |
76 | void (*read_cachesize)(struct ath_common *common, int *csz); | 82 | enum ath_bus_type ath_bus_type; |
77 | bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data); | 83 | void (*read_cachesize)(struct ath_common *common, int *csz); |
78 | void (*bt_coex_prep)(struct ath_common *common); | 84 | bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data); |
85 | void (*bt_coex_prep)(struct ath_common *common); | ||
79 | }; | 86 | }; |
80 | 87 | ||
81 | struct ath_common { | 88 | struct ath_common { |
diff --git a/drivers/net/wireless/ath/ath5k/Makefile b/drivers/net/wireless/ath/ath5k/Makefile index 090dc6d268a3..cc09595b781a 100644 --- a/drivers/net/wireless/ath/ath5k/Makefile +++ b/drivers/net/wireless/ath/ath5k/Makefile | |||
@@ -12,5 +12,6 @@ ath5k-y += attach.o | |||
12 | ath5k-y += base.o | 12 | ath5k-y += base.o |
13 | ath5k-y += led.o | 13 | ath5k-y += led.o |
14 | ath5k-y += rfkill.o | 14 | ath5k-y += rfkill.o |
15 | ath5k-y += ani.o | ||
15 | ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o | 16 | ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o |
16 | obj-$(CONFIG_ATH5K) += ath5k.o | 17 | obj-$(CONFIG_ATH5K) += ath5k.o |
diff --git a/drivers/net/wireless/ath/ath5k/ani.c b/drivers/net/wireless/ath/ath5k/ani.c new file mode 100644 index 000000000000..584a32859bdb --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/ani.c | |||
@@ -0,0 +1,744 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2010 Bruno Randolf <br1@einfach.org> | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include "ath5k.h" | ||
18 | #include "base.h" | ||
19 | #include "reg.h" | ||
20 | #include "debug.h" | ||
21 | #include "ani.h" | ||
22 | |||
23 | /** | ||
24 | * DOC: Basic ANI Operation | ||
25 | * | ||
26 | * Adaptive Noise Immunity (ANI) controls five noise immunity parameters | ||
27 | * depending on the amount of interference in the environment, increasing | ||
28 | * or reducing sensitivity as necessary. | ||
29 | * | ||
30 | * The parameters are: | ||
31 | * - "noise immunity" | ||
32 | * - "spur immunity" | ||
33 | * - "firstep level" | ||
34 | * - "OFDM weak signal detection" | ||
35 | * - "CCK weak signal detection" | ||
36 | * | ||
37 | * Basically we look at the amount of ODFM and CCK timing errors we get and then | ||
38 | * raise or lower immunity accordingly by setting one or more of these | ||
39 | * parameters. | ||
40 | * Newer chipsets have PHY error counters in hardware which will generate a MIB | ||
41 | * interrupt when they overflow. Older hardware has too enable PHY error frames | ||
42 | * by setting a RX flag and then count every single PHY error. When a specified | ||
43 | * threshold of errors has been reached we will raise immunity. | ||
44 | * Also we regularly check the amount of errors and lower or raise immunity as | ||
45 | * necessary. | ||
46 | */ | ||
47 | |||
48 | |||
49 | /*** ANI parameter control ***/ | ||
50 | |||
51 | /** | ||
52 | * ath5k_ani_set_noise_immunity_level() - Set noise immunity level | ||
53 | * | ||
54 | * @level: level between 0 and @ATH5K_ANI_MAX_NOISE_IMM_LVL | ||
55 | */ | ||
56 | void | ||
57 | ath5k_ani_set_noise_immunity_level(struct ath5k_hw *ah, int level) | ||
58 | { | ||
59 | /* TODO: | ||
60 | * ANI documents suggest the following five levels to use, but the HAL | ||
61 | * and ath9k use only use the last two levels, making this | ||
62 | * essentially an on/off option. There *may* be a reason for this (???), | ||
63 | * so i stick with the HAL version for now... | ||
64 | */ | ||
65 | #if 0 | ||
66 | const s8 hi[] = { -18, -18, -16, -14, -12 }; | ||
67 | const s8 lo[] = { -52, -56, -60, -64, -70 }; | ||
68 | const s8 sz[] = { -34, -41, -48, -55, -62 }; | ||
69 | const s8 fr[] = { -70, -72, -75, -78, -80 }; | ||
70 | #else | ||
71 | const s8 sz[] = { -55, -62 }; | ||
72 | const s8 lo[] = { -64, -70 }; | ||
73 | const s8 hi[] = { -14, -12 }; | ||
74 | const s8 fr[] = { -78, -80 }; | ||
75 | #endif | ||
76 | if (level < 0 || level > ARRAY_SIZE(sz)) { | ||
77 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, | ||
78 | "level out of range %d", level); | ||
79 | return; | ||
80 | } | ||
81 | |||
82 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE, | ||
83 | AR5K_PHY_DESIRED_SIZE_TOT, sz[level]); | ||
84 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_AGCCOARSE, | ||
85 | AR5K_PHY_AGCCOARSE_LO, lo[level]); | ||
86 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_AGCCOARSE, | ||
87 | AR5K_PHY_AGCCOARSE_HI, hi[level]); | ||
88 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SIG, | ||
89 | AR5K_PHY_SIG_FIRPWR, fr[level]); | ||
90 | |||
91 | ah->ah_sc->ani_state.noise_imm_level = level; | ||
92 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "new level %d", level); | ||
93 | } | ||
94 | |||
95 | |||
96 | /** | ||
97 | * ath5k_ani_set_spur_immunity_level() - Set spur immunity level | ||
98 | * | ||
99 | * @level: level between 0 and @max_spur_level (the maximum level is dependent | ||
100 | * on the chip revision). | ||
101 | */ | ||
102 | void | ||
103 | ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level) | ||
104 | { | ||
105 | const int val[] = { 2, 4, 6, 8, 10, 12, 14, 16 }; | ||
106 | |||
107 | if (level < 0 || level > ARRAY_SIZE(val) || | ||
108 | level > ah->ah_sc->ani_state.max_spur_level) { | ||
109 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, | ||
110 | "level out of range %d", level); | ||
111 | return; | ||
112 | } | ||
113 | |||
114 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_OFDM_SELFCORR, | ||
115 | AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1, val[level]); | ||
116 | |||
117 | ah->ah_sc->ani_state.spur_level = level; | ||
118 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "new level %d", level); | ||
119 | } | ||
120 | |||
121 | |||
122 | /** | ||
123 | * ath5k_ani_set_firstep_level() - Set "firstep" level | ||
124 | * | ||
125 | * @level: level between 0 and @ATH5K_ANI_MAX_FIRSTEP_LVL | ||
126 | */ | ||
127 | void | ||
128 | ath5k_ani_set_firstep_level(struct ath5k_hw *ah, int level) | ||
129 | { | ||
130 | const int val[] = { 0, 4, 8 }; | ||
131 | |||
132 | if (level < 0 || level > ARRAY_SIZE(val)) { | ||
133 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, | ||
134 | "level out of range %d", level); | ||
135 | return; | ||
136 | } | ||
137 | |||
138 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SIG, | ||
139 | AR5K_PHY_SIG_FIRSTEP, val[level]); | ||
140 | |||
141 | ah->ah_sc->ani_state.firstep_level = level; | ||
142 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "new level %d", level); | ||
143 | } | ||
144 | |||
145 | |||
146 | /** | ||
147 | * ath5k_ani_set_ofdm_weak_signal_detection() - Control OFDM weak signal | ||
148 | * detection | ||
149 | * | ||
150 | * @on: turn on or off | ||
151 | */ | ||
152 | void | ||
153 | ath5k_ani_set_ofdm_weak_signal_detection(struct ath5k_hw *ah, bool on) | ||
154 | { | ||
155 | const int m1l[] = { 127, 50 }; | ||
156 | const int m2l[] = { 127, 40 }; | ||
157 | const int m1[] = { 127, 0x4d }; | ||
158 | const int m2[] = { 127, 0x40 }; | ||
159 | const int m2cnt[] = { 31, 16 }; | ||
160 | const int m2lcnt[] = { 63, 48 }; | ||
161 | |||
162 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_WEAK_OFDM_LOW_THR, | ||
163 | AR5K_PHY_WEAK_OFDM_LOW_THR_M1, m1l[on]); | ||
164 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_WEAK_OFDM_LOW_THR, | ||
165 | AR5K_PHY_WEAK_OFDM_LOW_THR_M2, m2l[on]); | ||
166 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_WEAK_OFDM_HIGH_THR, | ||
167 | AR5K_PHY_WEAK_OFDM_HIGH_THR_M1, m1[on]); | ||
168 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_WEAK_OFDM_HIGH_THR, | ||
169 | AR5K_PHY_WEAK_OFDM_HIGH_THR_M2, m2[on]); | ||
170 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_WEAK_OFDM_HIGH_THR, | ||
171 | AR5K_PHY_WEAK_OFDM_HIGH_THR_M2_COUNT, m2cnt[on]); | ||
172 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_WEAK_OFDM_LOW_THR, | ||
173 | AR5K_PHY_WEAK_OFDM_LOW_THR_M2_COUNT, m2lcnt[on]); | ||
174 | |||
175 | if (on) | ||
176 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_WEAK_OFDM_LOW_THR, | ||
177 | AR5K_PHY_WEAK_OFDM_LOW_THR_SELFCOR_EN); | ||
178 | else | ||
179 | AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_WEAK_OFDM_LOW_THR, | ||
180 | AR5K_PHY_WEAK_OFDM_LOW_THR_SELFCOR_EN); | ||
181 | |||
182 | ah->ah_sc->ani_state.ofdm_weak_sig = on; | ||
183 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "turned %s", | ||
184 | on ? "on" : "off"); | ||
185 | } | ||
186 | |||
187 | |||
188 | /** | ||
189 | * ath5k_ani_set_cck_weak_signal_detection() - control CCK weak signal detection | ||
190 | * | ||
191 | * @on: turn on or off | ||
192 | */ | ||
193 | void | ||
194 | ath5k_ani_set_cck_weak_signal_detection(struct ath5k_hw *ah, bool on) | ||
195 | { | ||
196 | const int val[] = { 8, 6 }; | ||
197 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_CCK_CROSSCORR, | ||
198 | AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR, val[on]); | ||
199 | ah->ah_sc->ani_state.cck_weak_sig = on; | ||
200 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "turned %s", | ||
201 | on ? "on" : "off"); | ||
202 | } | ||
203 | |||
204 | |||
205 | /*** ANI algorithm ***/ | ||
206 | |||
207 | /** | ||
208 | * ath5k_ani_raise_immunity() - Increase noise immunity | ||
209 | * | ||
210 | * @ofdm_trigger: If this is true we are called because of too many OFDM errors, | ||
211 | * the algorithm will tune more parameters then. | ||
212 | * | ||
213 | * Try to raise noise immunity (=decrease sensitivity) in several steps | ||
214 | * depending on the average RSSI of the beacons we received. | ||
215 | */ | ||
216 | static void | ||
217 | ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as, | ||
218 | bool ofdm_trigger) | ||
219 | { | ||
220 | int rssi = ah->ah_beacon_rssi_avg.avg; | ||
221 | |||
222 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "raise immunity (%s)", | ||
223 | ofdm_trigger ? "ODFM" : "CCK"); | ||
224 | |||
225 | /* first: raise noise immunity */ | ||
226 | if (as->noise_imm_level < ATH5K_ANI_MAX_NOISE_IMM_LVL) { | ||
227 | ath5k_ani_set_noise_immunity_level(ah, as->noise_imm_level + 1); | ||
228 | return; | ||
229 | } | ||
230 | |||
231 | /* only OFDM: raise spur immunity level */ | ||
232 | if (ofdm_trigger && | ||
233 | as->spur_level < ah->ah_sc->ani_state.max_spur_level) { | ||
234 | ath5k_ani_set_spur_immunity_level(ah, as->spur_level + 1); | ||
235 | return; | ||
236 | } | ||
237 | |||
238 | /* AP mode */ | ||
239 | if (ah->ah_sc->opmode == NL80211_IFTYPE_AP) { | ||
240 | if (as->firstep_level < ATH5K_ANI_MAX_FIRSTEP_LVL) | ||
241 | ath5k_ani_set_firstep_level(ah, as->firstep_level + 1); | ||
242 | return; | ||
243 | } | ||
244 | |||
245 | /* STA and IBSS mode */ | ||
246 | |||
247 | /* TODO: for IBSS mode it would be better to keep a beacon RSSI average | ||
248 | * per each neighbour node and use the minimum of these, to make sure we | ||
249 | * don't shut out a remote node by raising immunity too high. */ | ||
250 | |||
251 | if (rssi > ATH5K_ANI_RSSI_THR_HIGH) { | ||
252 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, | ||
253 | "beacon RSSI high"); | ||
254 | /* only OFDM: beacon RSSI is high, we can disable ODFM weak | ||
255 | * signal detection */ | ||
256 | if (ofdm_trigger && as->ofdm_weak_sig == true) { | ||
257 | ath5k_ani_set_ofdm_weak_signal_detection(ah, false); | ||
258 | ath5k_ani_set_spur_immunity_level(ah, 0); | ||
259 | return; | ||
260 | } | ||
261 | /* as a last resort or CCK: raise firstep level */ | ||
262 | if (as->firstep_level < ATH5K_ANI_MAX_FIRSTEP_LVL) { | ||
263 | ath5k_ani_set_firstep_level(ah, as->firstep_level + 1); | ||
264 | return; | ||
265 | } | ||
266 | } else if (rssi > ATH5K_ANI_RSSI_THR_LOW) { | ||
267 | /* beacon RSSI in mid range, we need OFDM weak signal detect, | ||
268 | * but can raise firstep level */ | ||
269 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, | ||
270 | "beacon RSSI mid"); | ||
271 | if (ofdm_trigger && as->ofdm_weak_sig == false) | ||
272 | ath5k_ani_set_ofdm_weak_signal_detection(ah, true); | ||
273 | if (as->firstep_level < ATH5K_ANI_MAX_FIRSTEP_LVL) | ||
274 | ath5k_ani_set_firstep_level(ah, as->firstep_level + 1); | ||
275 | return; | ||
276 | } else if (ah->ah_current_channel->band == IEEE80211_BAND_2GHZ) { | ||
277 | /* beacon RSSI is low. in B/G mode turn of OFDM weak signal | ||
278 | * detect and zero firstep level to maximize CCK sensitivity */ | ||
279 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, | ||
280 | "beacon RSSI low, 2GHz"); | ||
281 | if (ofdm_trigger && as->ofdm_weak_sig == true) | ||
282 | ath5k_ani_set_ofdm_weak_signal_detection(ah, false); | ||
283 | if (as->firstep_level > 0) | ||
284 | ath5k_ani_set_firstep_level(ah, 0); | ||
285 | return; | ||
286 | } | ||
287 | |||
288 | /* TODO: why not?: | ||
289 | if (as->cck_weak_sig == true) { | ||
290 | ath5k_ani_set_cck_weak_signal_detection(ah, false); | ||
291 | } | ||
292 | */ | ||
293 | } | ||
294 | |||
295 | |||
296 | /** | ||
297 | * ath5k_ani_lower_immunity() - Decrease noise immunity | ||
298 | * | ||
299 | * Try to lower noise immunity (=increase sensitivity) in several steps | ||
300 | * depending on the average RSSI of the beacons we received. | ||
301 | */ | ||
302 | static void | ||
303 | ath5k_ani_lower_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as) | ||
304 | { | ||
305 | int rssi = ah->ah_beacon_rssi_avg.avg; | ||
306 | |||
307 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "lower immunity"); | ||
308 | |||
309 | if (ah->ah_sc->opmode == NL80211_IFTYPE_AP) { | ||
310 | /* AP mode */ | ||
311 | if (as->firstep_level > 0) { | ||
312 | ath5k_ani_set_firstep_level(ah, as->firstep_level - 1); | ||
313 | return; | ||
314 | } | ||
315 | } else { | ||
316 | /* STA and IBSS mode (see TODO above) */ | ||
317 | if (rssi > ATH5K_ANI_RSSI_THR_HIGH) { | ||
318 | /* beacon signal is high, leave OFDM weak signal | ||
319 | * detection off or it may oscillate | ||
320 | * TODO: who said it's off??? */ | ||
321 | } else if (rssi > ATH5K_ANI_RSSI_THR_LOW) { | ||
322 | /* beacon RSSI is mid-range: turn on ODFM weak signal | ||
323 | * detection and next, lower firstep level */ | ||
324 | if (as->ofdm_weak_sig == false) { | ||
325 | ath5k_ani_set_ofdm_weak_signal_detection(ah, | ||
326 | true); | ||
327 | return; | ||
328 | } | ||
329 | if (as->firstep_level > 0) { | ||
330 | ath5k_ani_set_firstep_level(ah, | ||
331 | as->firstep_level - 1); | ||
332 | return; | ||
333 | } | ||
334 | } else { | ||
335 | /* beacon signal is low: only reduce firstep level */ | ||
336 | if (as->firstep_level > 0) { | ||
337 | ath5k_ani_set_firstep_level(ah, | ||
338 | as->firstep_level - 1); | ||
339 | return; | ||
340 | } | ||
341 | } | ||
342 | } | ||
343 | |||
344 | /* all modes */ | ||
345 | if (as->spur_level > 0) { | ||
346 | ath5k_ani_set_spur_immunity_level(ah, as->spur_level - 1); | ||
347 | return; | ||
348 | } | ||
349 | |||
350 | /* finally, reduce noise immunity */ | ||
351 | if (as->noise_imm_level > 0) { | ||
352 | ath5k_ani_set_noise_immunity_level(ah, as->noise_imm_level - 1); | ||
353 | return; | ||
354 | } | ||
355 | } | ||
356 | |||
357 | |||
358 | /** | ||
359 | * ath5k_hw_ani_get_listen_time() - Calculate time spent listening | ||
360 | * | ||
361 | * Return an approximation of the time spent "listening" in milliseconds (ms) | ||
362 | * since the last call of this function by deducting the cycles spent | ||
363 | * transmitting and receiving from the total cycle count. | ||
364 | * Save profile count values for debugging/statistics and because we might want | ||
365 | * to use them later. | ||
366 | * | ||
367 | * We assume no one else clears these registers! | ||
368 | */ | ||
369 | static int | ||
370 | ath5k_hw_ani_get_listen_time(struct ath5k_hw *ah, struct ath5k_ani_state *as) | ||
371 | { | ||
372 | int listen; | ||
373 | |||
374 | /* freeze */ | ||
375 | ath5k_hw_reg_write(ah, AR5K_MIBC_FMC, AR5K_MIBC); | ||
376 | /* read */ | ||
377 | as->pfc_cycles = ath5k_hw_reg_read(ah, AR5K_PROFCNT_CYCLE); | ||
378 | as->pfc_busy = ath5k_hw_reg_read(ah, AR5K_PROFCNT_RXCLR); | ||
379 | as->pfc_tx = ath5k_hw_reg_read(ah, AR5K_PROFCNT_TX); | ||
380 | as->pfc_rx = ath5k_hw_reg_read(ah, AR5K_PROFCNT_RX); | ||
381 | /* clear */ | ||
382 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_TX); | ||
383 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RX); | ||
384 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR); | ||
385 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE); | ||
386 | /* un-freeze */ | ||
387 | ath5k_hw_reg_write(ah, 0, AR5K_MIBC); | ||
388 | |||
389 | /* TODO: where does 44000 come from? (11g clock rate?) */ | ||
390 | listen = (as->pfc_cycles - as->pfc_rx - as->pfc_tx) / 44000; | ||
391 | |||
392 | if (as->pfc_cycles == 0 || listen < 0) | ||
393 | return 0; | ||
394 | return listen; | ||
395 | } | ||
396 | |||
397 | |||
398 | /** | ||
399 | * ath5k_ani_save_and_clear_phy_errors() - Clear and save PHY error counters | ||
400 | * | ||
401 | * Clear the PHY error counters as soon as possible, since this might be called | ||
402 | * from a MIB interrupt and we want to make sure we don't get interrupted again. | ||
403 | * Add the count of CCK and OFDM errors to our internal state, so it can be used | ||
404 | * by the algorithm later. | ||
405 | * | ||
406 | * Will be called from interrupt and tasklet context. | ||
407 | * Returns 0 if both counters are zero. | ||
408 | */ | ||
409 | static int | ||
410 | ath5k_ani_save_and_clear_phy_errors(struct ath5k_hw *ah, | ||
411 | struct ath5k_ani_state *as) | ||
412 | { | ||
413 | unsigned int ofdm_err, cck_err; | ||
414 | |||
415 | if (!ah->ah_capabilities.cap_has_phyerr_counters) | ||
416 | return 0; | ||
417 | |||
418 | ofdm_err = ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT1); | ||
419 | cck_err = ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT2); | ||
420 | |||
421 | /* reset counters first, we might be in a hurry (interrupt) */ | ||
422 | ath5k_hw_reg_write(ah, ATH5K_PHYERR_CNT_MAX - ATH5K_ANI_OFDM_TRIG_HIGH, | ||
423 | AR5K_PHYERR_CNT1); | ||
424 | ath5k_hw_reg_write(ah, ATH5K_PHYERR_CNT_MAX - ATH5K_ANI_CCK_TRIG_HIGH, | ||
425 | AR5K_PHYERR_CNT2); | ||
426 | |||
427 | ofdm_err = ATH5K_ANI_OFDM_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX - ofdm_err); | ||
428 | cck_err = ATH5K_ANI_CCK_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX - cck_err); | ||
429 | |||
430 | /* sometimes both can be zero, especially when there is a superfluous | ||
431 | * second interrupt. detect that here and return an error. */ | ||
432 | if (ofdm_err <= 0 && cck_err <= 0) | ||
433 | return 0; | ||
434 | |||
435 | /* avoid negative values should one of the registers overflow */ | ||
436 | if (ofdm_err > 0) { | ||
437 | as->ofdm_errors += ofdm_err; | ||
438 | as->sum_ofdm_errors += ofdm_err; | ||
439 | } | ||
440 | if (cck_err > 0) { | ||
441 | as->cck_errors += cck_err; | ||
442 | as->sum_cck_errors += cck_err; | ||
443 | } | ||
444 | return 1; | ||
445 | } | ||
446 | |||
447 | |||
448 | /** | ||
449 | * ath5k_ani_period_restart() - Restart ANI period | ||
450 | * | ||
451 | * Just reset counters, so they are clear for the next "ani period". | ||
452 | */ | ||
453 | static void | ||
454 | ath5k_ani_period_restart(struct ath5k_hw *ah, struct ath5k_ani_state *as) | ||
455 | { | ||
456 | /* keep last values for debugging */ | ||
457 | as->last_ofdm_errors = as->ofdm_errors; | ||
458 | as->last_cck_errors = as->cck_errors; | ||
459 | as->last_listen = as->listen_time; | ||
460 | |||
461 | as->ofdm_errors = 0; | ||
462 | as->cck_errors = 0; | ||
463 | as->listen_time = 0; | ||
464 | } | ||
465 | |||
466 | |||
467 | /** | ||
468 | * ath5k_ani_calibration() - The main ANI calibration function | ||
469 | * | ||
470 | * We count OFDM and CCK errors relative to the time where we did not send or | ||
471 | * receive ("listen" time) and raise or lower immunity accordingly. | ||
472 | * This is called regularly (every second) from the calibration timer, but also | ||
473 | * when an error threshold has been reached. | ||
474 | * | ||
475 | * In order to synchronize access from different contexts, this should be | ||
476 | * called only indirectly by scheduling the ANI tasklet! | ||
477 | */ | ||
478 | void | ||
479 | ath5k_ani_calibration(struct ath5k_hw *ah) | ||
480 | { | ||
481 | struct ath5k_ani_state *as = &ah->ah_sc->ani_state; | ||
482 | int listen, ofdm_high, ofdm_low, cck_high, cck_low; | ||
483 | |||
484 | if (as->ani_mode != ATH5K_ANI_MODE_AUTO) | ||
485 | return; | ||
486 | |||
487 | /* get listen time since last call and add it to the counter because we | ||
488 | * might not have restarted the "ani period" last time */ | ||
489 | listen = ath5k_hw_ani_get_listen_time(ah, as); | ||
490 | as->listen_time += listen; | ||
491 | |||
492 | ath5k_ani_save_and_clear_phy_errors(ah, as); | ||
493 | |||
494 | ofdm_high = as->listen_time * ATH5K_ANI_OFDM_TRIG_HIGH / 1000; | ||
495 | cck_high = as->listen_time * ATH5K_ANI_CCK_TRIG_HIGH / 1000; | ||
496 | ofdm_low = as->listen_time * ATH5K_ANI_OFDM_TRIG_LOW / 1000; | ||
497 | cck_low = as->listen_time * ATH5K_ANI_CCK_TRIG_LOW / 1000; | ||
498 | |||
499 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, | ||
500 | "listen %d (now %d)", as->listen_time, listen); | ||
501 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, | ||
502 | "check high ofdm %d/%d cck %d/%d", | ||
503 | as->ofdm_errors, ofdm_high, as->cck_errors, cck_high); | ||
504 | |||
505 | if (as->ofdm_errors > ofdm_high || as->cck_errors > cck_high) { | ||
506 | /* too many PHY errors - we have to raise immunity */ | ||
507 | bool ofdm_flag = as->ofdm_errors > ofdm_high ? true : false; | ||
508 | ath5k_ani_raise_immunity(ah, as, ofdm_flag); | ||
509 | ath5k_ani_period_restart(ah, as); | ||
510 | |||
511 | } else if (as->listen_time > 5 * ATH5K_ANI_LISTEN_PERIOD) { | ||
512 | /* If more than 5 (TODO: why 5?) periods have passed and we got | ||
513 | * relatively little errors we can try to lower immunity */ | ||
514 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, | ||
515 | "check low ofdm %d/%d cck %d/%d", | ||
516 | as->ofdm_errors, ofdm_low, as->cck_errors, cck_low); | ||
517 | |||
518 | if (as->ofdm_errors <= ofdm_low && as->cck_errors <= cck_low) | ||
519 | ath5k_ani_lower_immunity(ah, as); | ||
520 | |||
521 | ath5k_ani_period_restart(ah, as); | ||
522 | } | ||
523 | } | ||
524 | |||
525 | |||
526 | /*** INTERRUPT HANDLER ***/ | ||
527 | |||
528 | /** | ||
529 | * ath5k_ani_mib_intr() - Interrupt handler for ANI MIB counters | ||
530 | * | ||
531 | * Just read & reset the registers quickly, so they don't generate more | ||
532 | * interrupts, save the counters and schedule the tasklet to decide whether | ||
533 | * to raise immunity or not. | ||
534 | * | ||
535 | * We just need to handle PHY error counters, ath5k_hw_update_mib_counters() | ||
536 | * should take care of all "normal" MIB interrupts. | ||
537 | */ | ||
538 | void | ||
539 | ath5k_ani_mib_intr(struct ath5k_hw *ah) | ||
540 | { | ||
541 | struct ath5k_ani_state *as = &ah->ah_sc->ani_state; | ||
542 | |||
543 | /* nothing to do here if HW does not have PHY error counters - they | ||
544 | * can't be the reason for the MIB interrupt then */ | ||
545 | if (!ah->ah_capabilities.cap_has_phyerr_counters) | ||
546 | return; | ||
547 | |||
548 | /* not in use but clear anyways */ | ||
549 | ath5k_hw_reg_write(ah, 0, AR5K_OFDM_FIL_CNT); | ||
550 | ath5k_hw_reg_write(ah, 0, AR5K_CCK_FIL_CNT); | ||
551 | |||
552 | if (ah->ah_sc->ani_state.ani_mode != ATH5K_ANI_MODE_AUTO) | ||
553 | return; | ||
554 | |||
555 | /* if one of the errors triggered, we can get a superfluous second | ||
556 | * interrupt, even though we have already reset the register. the | ||
557 | * function detects that so we can return early */ | ||
558 | if (ath5k_ani_save_and_clear_phy_errors(ah, as) == 0) | ||
559 | return; | ||
560 | |||
561 | if (as->ofdm_errors > ATH5K_ANI_OFDM_TRIG_HIGH || | ||
562 | as->cck_errors > ATH5K_ANI_CCK_TRIG_HIGH) | ||
563 | tasklet_schedule(&ah->ah_sc->ani_tasklet); | ||
564 | } | ||
565 | |||
566 | |||
567 | /** | ||
568 | * ath5k_ani_phy_error_report() - Used by older HW to report PHY errors | ||
569 | * | ||
570 | * This is used by hardware without PHY error counters to report PHY errors | ||
571 | * on a frame-by-frame basis, instead of the interrupt. | ||
572 | */ | ||
573 | void | ||
574 | ath5k_ani_phy_error_report(struct ath5k_hw *ah, | ||
575 | enum ath5k_phy_error_code phyerr) | ||
576 | { | ||
577 | struct ath5k_ani_state *as = &ah->ah_sc->ani_state; | ||
578 | |||
579 | if (phyerr == AR5K_RX_PHY_ERROR_OFDM_TIMING) { | ||
580 | as->ofdm_errors++; | ||
581 | if (as->ofdm_errors > ATH5K_ANI_OFDM_TRIG_HIGH) | ||
582 | tasklet_schedule(&ah->ah_sc->ani_tasklet); | ||
583 | } else if (phyerr == AR5K_RX_PHY_ERROR_CCK_TIMING) { | ||
584 | as->cck_errors++; | ||
585 | if (as->cck_errors > ATH5K_ANI_CCK_TRIG_HIGH) | ||
586 | tasklet_schedule(&ah->ah_sc->ani_tasklet); | ||
587 | } | ||
588 | } | ||
589 | |||
590 | |||
591 | /*** INIT ***/ | ||
592 | |||
593 | /** | ||
594 | * ath5k_enable_phy_err_counters() - Enable PHY error counters | ||
595 | * | ||
596 | * Enable PHY error counters for OFDM and CCK timing errors. | ||
597 | */ | ||
598 | static void | ||
599 | ath5k_enable_phy_err_counters(struct ath5k_hw *ah) | ||
600 | { | ||
601 | ath5k_hw_reg_write(ah, ATH5K_PHYERR_CNT_MAX - ATH5K_ANI_OFDM_TRIG_HIGH, | ||
602 | AR5K_PHYERR_CNT1); | ||
603 | ath5k_hw_reg_write(ah, ATH5K_PHYERR_CNT_MAX - ATH5K_ANI_CCK_TRIG_HIGH, | ||
604 | AR5K_PHYERR_CNT2); | ||
605 | ath5k_hw_reg_write(ah, AR5K_PHY_ERR_FIL_OFDM, AR5K_PHYERR_CNT1_MASK); | ||
606 | ath5k_hw_reg_write(ah, AR5K_PHY_ERR_FIL_CCK, AR5K_PHYERR_CNT2_MASK); | ||
607 | |||
608 | /* not in use */ | ||
609 | ath5k_hw_reg_write(ah, 0, AR5K_OFDM_FIL_CNT); | ||
610 | ath5k_hw_reg_write(ah, 0, AR5K_CCK_FIL_CNT); | ||
611 | } | ||
612 | |||
613 | |||
614 | /** | ||
615 | * ath5k_disable_phy_err_counters() - Disable PHY error counters | ||
616 | * | ||
617 | * Disable PHY error counters for OFDM and CCK timing errors. | ||
618 | */ | ||
619 | static void | ||
620 | ath5k_disable_phy_err_counters(struct ath5k_hw *ah) | ||
621 | { | ||
622 | ath5k_hw_reg_write(ah, 0, AR5K_PHYERR_CNT1); | ||
623 | ath5k_hw_reg_write(ah, 0, AR5K_PHYERR_CNT2); | ||
624 | ath5k_hw_reg_write(ah, 0, AR5K_PHYERR_CNT1_MASK); | ||
625 | ath5k_hw_reg_write(ah, 0, AR5K_PHYERR_CNT2_MASK); | ||
626 | |||
627 | /* not in use */ | ||
628 | ath5k_hw_reg_write(ah, 0, AR5K_OFDM_FIL_CNT); | ||
629 | ath5k_hw_reg_write(ah, 0, AR5K_CCK_FIL_CNT); | ||
630 | } | ||
631 | |||
632 | |||
633 | /** | ||
634 | * ath5k_ani_init() - Initialize ANI | ||
635 | * @mode: Which mode to use (auto, manual high, manual low, off) | ||
636 | * | ||
637 | * Initialize ANI according to mode. | ||
638 | */ | ||
639 | void | ||
640 | ath5k_ani_init(struct ath5k_hw *ah, enum ath5k_ani_mode mode) | ||
641 | { | ||
642 | /* ANI is only possible on 5212 and newer */ | ||
643 | if (ah->ah_version < AR5K_AR5212) | ||
644 | return; | ||
645 | |||
646 | /* clear old state information */ | ||
647 | memset(&ah->ah_sc->ani_state, 0, sizeof(ah->ah_sc->ani_state)); | ||
648 | |||
649 | /* older hardware has more spur levels than newer */ | ||
650 | if (ah->ah_mac_srev < AR5K_SREV_AR2414) | ||
651 | ah->ah_sc->ani_state.max_spur_level = 7; | ||
652 | else | ||
653 | ah->ah_sc->ani_state.max_spur_level = 2; | ||
654 | |||
655 | /* initial values for our ani parameters */ | ||
656 | if (mode == ATH5K_ANI_MODE_OFF) { | ||
657 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "ANI off\n"); | ||
658 | } else if (mode == ATH5K_ANI_MODE_MANUAL_LOW) { | ||
659 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, | ||
660 | "ANI manual low -> high sensitivity\n"); | ||
661 | ath5k_ani_set_noise_immunity_level(ah, 0); | ||
662 | ath5k_ani_set_spur_immunity_level(ah, 0); | ||
663 | ath5k_ani_set_firstep_level(ah, 0); | ||
664 | ath5k_ani_set_ofdm_weak_signal_detection(ah, true); | ||
665 | ath5k_ani_set_cck_weak_signal_detection(ah, true); | ||
666 | } else if (mode == ATH5K_ANI_MODE_MANUAL_HIGH) { | ||
667 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, | ||
668 | "ANI manual high -> low sensitivity\n"); | ||
669 | ath5k_ani_set_noise_immunity_level(ah, | ||
670 | ATH5K_ANI_MAX_NOISE_IMM_LVL); | ||
671 | ath5k_ani_set_spur_immunity_level(ah, | ||
672 | ah->ah_sc->ani_state.max_spur_level); | ||
673 | ath5k_ani_set_firstep_level(ah, ATH5K_ANI_MAX_FIRSTEP_LVL); | ||
674 | ath5k_ani_set_ofdm_weak_signal_detection(ah, false); | ||
675 | ath5k_ani_set_cck_weak_signal_detection(ah, false); | ||
676 | } else if (mode == ATH5K_ANI_MODE_AUTO) { | ||
677 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "ANI auto\n"); | ||
678 | ath5k_ani_set_noise_immunity_level(ah, 0); | ||
679 | ath5k_ani_set_spur_immunity_level(ah, 0); | ||
680 | ath5k_ani_set_firstep_level(ah, 0); | ||
681 | ath5k_ani_set_ofdm_weak_signal_detection(ah, true); | ||
682 | ath5k_ani_set_cck_weak_signal_detection(ah, false); | ||
683 | } | ||
684 | |||
685 | /* newer hardware has PHY error counter registers which we can use to | ||
686 | * get OFDM and CCK error counts. older hardware has to set rxfilter and | ||
687 | * report every single PHY error by calling ath5k_ani_phy_error_report() | ||
688 | */ | ||
689 | if (mode == ATH5K_ANI_MODE_AUTO) { | ||
690 | if (ah->ah_capabilities.cap_has_phyerr_counters) | ||
691 | ath5k_enable_phy_err_counters(ah); | ||
692 | else | ||
693 | ath5k_hw_set_rx_filter(ah, ath5k_hw_get_rx_filter(ah) | | ||
694 | AR5K_RX_FILTER_PHYERR); | ||
695 | } else { | ||
696 | if (ah->ah_capabilities.cap_has_phyerr_counters) | ||
697 | ath5k_disable_phy_err_counters(ah); | ||
698 | else | ||
699 | ath5k_hw_set_rx_filter(ah, ath5k_hw_get_rx_filter(ah) & | ||
700 | ~AR5K_RX_FILTER_PHYERR); | ||
701 | } | ||
702 | |||
703 | ah->ah_sc->ani_state.ani_mode = mode; | ||
704 | } | ||
705 | |||
706 | |||
707 | /*** DEBUG ***/ | ||
708 | |||
709 | #ifdef CONFIG_ATH5K_DEBUG | ||
710 | |||
711 | void | ||
712 | ath5k_ani_print_counters(struct ath5k_hw *ah) | ||
713 | { | ||
714 | /* clears too */ | ||
715 | printk(KERN_NOTICE "ACK fail\t%d\n", | ||
716 | ath5k_hw_reg_read(ah, AR5K_ACK_FAIL)); | ||
717 | printk(KERN_NOTICE "RTS fail\t%d\n", | ||
718 | ath5k_hw_reg_read(ah, AR5K_RTS_FAIL)); | ||
719 | printk(KERN_NOTICE "RTS success\t%d\n", | ||
720 | ath5k_hw_reg_read(ah, AR5K_RTS_OK)); | ||
721 | printk(KERN_NOTICE "FCS error\t%d\n", | ||
722 | ath5k_hw_reg_read(ah, AR5K_FCS_FAIL)); | ||
723 | |||
724 | /* no clear */ | ||
725 | printk(KERN_NOTICE "tx\t%d\n", | ||
726 | ath5k_hw_reg_read(ah, AR5K_PROFCNT_TX)); | ||
727 | printk(KERN_NOTICE "rx\t%d\n", | ||
728 | ath5k_hw_reg_read(ah, AR5K_PROFCNT_RX)); | ||
729 | printk(KERN_NOTICE "busy\t%d\n", | ||
730 | ath5k_hw_reg_read(ah, AR5K_PROFCNT_RXCLR)); | ||
731 | printk(KERN_NOTICE "cycles\t%d\n", | ||
732 | ath5k_hw_reg_read(ah, AR5K_PROFCNT_CYCLE)); | ||
733 | |||
734 | printk(KERN_NOTICE "AR5K_PHYERR_CNT1\t%d\n", | ||
735 | ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT1)); | ||
736 | printk(KERN_NOTICE "AR5K_PHYERR_CNT2\t%d\n", | ||
737 | ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT2)); | ||
738 | printk(KERN_NOTICE "AR5K_OFDM_FIL_CNT\t%d\n", | ||
739 | ath5k_hw_reg_read(ah, AR5K_OFDM_FIL_CNT)); | ||
740 | printk(KERN_NOTICE "AR5K_CCK_FIL_CNT\t%d\n", | ||
741 | ath5k_hw_reg_read(ah, AR5K_CCK_FIL_CNT)); | ||
742 | } | ||
743 | |||
744 | #endif | ||
diff --git a/drivers/net/wireless/ath/ath5k/ani.h b/drivers/net/wireless/ath/ath5k/ani.h new file mode 100644 index 000000000000..55cf26d8522c --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/ani.h | |||
@@ -0,0 +1,104 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2010 Bruno Randolf <br1@einfach.org> | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | #ifndef ANI_H | ||
17 | #define ANI_H | ||
18 | |||
19 | /* these thresholds are relative to the ATH5K_ANI_LISTEN_PERIOD */ | ||
20 | #define ATH5K_ANI_LISTEN_PERIOD 100 | ||
21 | #define ATH5K_ANI_OFDM_TRIG_HIGH 500 | ||
22 | #define ATH5K_ANI_OFDM_TRIG_LOW 200 | ||
23 | #define ATH5K_ANI_CCK_TRIG_HIGH 200 | ||
24 | #define ATH5K_ANI_CCK_TRIG_LOW 100 | ||
25 | |||
26 | /* average beacon RSSI thresholds */ | ||
27 | #define ATH5K_ANI_RSSI_THR_HIGH 40 | ||
28 | #define ATH5K_ANI_RSSI_THR_LOW 7 | ||
29 | |||
30 | /* maximum availabe levels */ | ||
31 | #define ATH5K_ANI_MAX_FIRSTEP_LVL 2 | ||
32 | #define ATH5K_ANI_MAX_NOISE_IMM_LVL 1 | ||
33 | |||
34 | |||
35 | /** | ||
36 | * enum ath5k_ani_mode - mode for ANI / noise sensitivity | ||
37 | * | ||
38 | * @ATH5K_ANI_MODE_OFF: Turn ANI off. This can be useful to just stop the ANI | ||
39 | * algorithm after it has been on auto mode. | ||
40 | * ATH5K_ANI_MODE_MANUAL_LOW: Manually set all immunity parameters to low, | ||
41 | * maximizing sensitivity. ANI will not run. | ||
42 | * ATH5K_ANI_MODE_MANUAL_HIGH: Manually set all immunity parameters to high, | ||
43 | * minimizing sensitivity. ANI will not run. | ||
44 | * ATH5K_ANI_MODE_AUTO: Automatically control immunity parameters based on the | ||
45 | * amount of OFDM and CCK frame errors (default). | ||
46 | */ | ||
47 | enum ath5k_ani_mode { | ||
48 | ATH5K_ANI_MODE_OFF = 0, | ||
49 | ATH5K_ANI_MODE_MANUAL_LOW = 1, | ||
50 | ATH5K_ANI_MODE_MANUAL_HIGH = 2, | ||
51 | ATH5K_ANI_MODE_AUTO = 3 | ||
52 | }; | ||
53 | |||
54 | |||
55 | /** | ||
56 | * struct ath5k_ani_state - ANI state and associated counters | ||
57 | * | ||
58 | * @max_spur_level: the maximum spur level is chip dependent | ||
59 | */ | ||
60 | struct ath5k_ani_state { | ||
61 | enum ath5k_ani_mode ani_mode; | ||
62 | |||
63 | /* state */ | ||
64 | int noise_imm_level; | ||
65 | int spur_level; | ||
66 | int firstep_level; | ||
67 | bool ofdm_weak_sig; | ||
68 | bool cck_weak_sig; | ||
69 | |||
70 | int max_spur_level; | ||
71 | |||
72 | /* used by the algorithm */ | ||
73 | unsigned int listen_time; | ||
74 | unsigned int ofdm_errors; | ||
75 | unsigned int cck_errors; | ||
76 | |||
77 | /* debug/statistics only: numbers from last ANI calibration */ | ||
78 | unsigned int pfc_tx; | ||
79 | unsigned int pfc_rx; | ||
80 | unsigned int pfc_busy; | ||
81 | unsigned int pfc_cycles; | ||
82 | unsigned int last_listen; | ||
83 | unsigned int last_ofdm_errors; | ||
84 | unsigned int last_cck_errors; | ||
85 | unsigned int sum_ofdm_errors; | ||
86 | unsigned int sum_cck_errors; | ||
87 | }; | ||
88 | |||
89 | void ath5k_ani_init(struct ath5k_hw *ah, enum ath5k_ani_mode mode); | ||
90 | void ath5k_ani_mib_intr(struct ath5k_hw *ah); | ||
91 | void ath5k_ani_calibration(struct ath5k_hw *ah); | ||
92 | void ath5k_ani_phy_error_report(struct ath5k_hw *ah, | ||
93 | enum ath5k_phy_error_code phyerr); | ||
94 | |||
95 | /* for manual control */ | ||
96 | void ath5k_ani_set_noise_immunity_level(struct ath5k_hw *ah, int level); | ||
97 | void ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level); | ||
98 | void ath5k_ani_set_firstep_level(struct ath5k_hw *ah, int level); | ||
99 | void ath5k_ani_set_ofdm_weak_signal_detection(struct ath5k_hw *ah, bool on); | ||
100 | void ath5k_ani_set_cck_weak_signal_detection(struct ath5k_hw *ah, bool on); | ||
101 | |||
102 | void ath5k_ani_print_counters(struct ath5k_hw *ah); | ||
103 | |||
104 | #endif /* ANI_H */ | ||
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index ac67f02e26d8..2785946f659a 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h | |||
@@ -202,7 +202,8 @@ | |||
202 | #define AR5K_TUNE_MAX_TXPOWER 63 | 202 | #define AR5K_TUNE_MAX_TXPOWER 63 |
203 | #define AR5K_TUNE_DEFAULT_TXPOWER 25 | 203 | #define AR5K_TUNE_DEFAULT_TXPOWER 25 |
204 | #define AR5K_TUNE_TPC_TXPOWER false | 204 | #define AR5K_TUNE_TPC_TXPOWER false |
205 | #define AR5K_TUNE_HWTXTRIES 4 | 205 | #define ATH5K_TUNE_CALIBRATION_INTERVAL_FULL 10000 /* 10 sec */ |
206 | #define ATH5K_TUNE_CALIBRATION_INTERVAL_ANI 1000 /* 1 sec */ | ||
206 | 207 | ||
207 | #define AR5K_INIT_CARR_SENSE_EN 1 | 208 | #define AR5K_INIT_CARR_SENSE_EN 1 |
208 | 209 | ||
@@ -614,28 +615,6 @@ struct ath5k_rx_status { | |||
614 | #define AR5K_BEACON_ENA 0x00800000 /*enable beacon xmit*/ | 615 | #define AR5K_BEACON_ENA 0x00800000 /*enable beacon xmit*/ |
615 | #define AR5K_BEACON_RESET_TSF 0x01000000 /*force a TSF reset*/ | 616 | #define AR5K_BEACON_RESET_TSF 0x01000000 /*force a TSF reset*/ |
616 | 617 | ||
617 | #if 0 | ||
618 | /** | ||
619 | * struct ath5k_beacon_state - Per-station beacon timer state. | ||
620 | * @bs_interval: in TU's, can also include the above flags | ||
621 | * @bs_cfp_max_duration: if non-zero hw is setup to coexist with a | ||
622 | * Point Coordination Function capable AP | ||
623 | */ | ||
624 | struct ath5k_beacon_state { | ||
625 | u32 bs_next_beacon; | ||
626 | u32 bs_next_dtim; | ||
627 | u32 bs_interval; | ||
628 | u8 bs_dtim_period; | ||
629 | u8 bs_cfp_period; | ||
630 | u16 bs_cfp_max_duration; | ||
631 | u16 bs_cfp_du_remain; | ||
632 | u16 bs_tim_offset; | ||
633 | u16 bs_sleep_duration; | ||
634 | u16 bs_bmiss_threshold; | ||
635 | u32 bs_cfp_next; | ||
636 | }; | ||
637 | #endif | ||
638 | |||
639 | 618 | ||
640 | /* | 619 | /* |
641 | * TSF to TU conversion: | 620 | * TSF to TU conversion: |
@@ -822,9 +801,9 @@ struct ath5k_athchan_2ghz { | |||
822 | * @AR5K_INT_TXURN: received when we should increase the TX trigger threshold | 801 | * @AR5K_INT_TXURN: received when we should increase the TX trigger threshold |
823 | * We currently do increments on interrupt by | 802 | * We currently do increments on interrupt by |
824 | * (AR5K_TUNE_MAX_TX_FIFO_THRES - current_trigger_level) / 2 | 803 | * (AR5K_TUNE_MAX_TX_FIFO_THRES - current_trigger_level) / 2 |
825 | * @AR5K_INT_MIB: Indicates the Management Information Base counters should be | 804 | * @AR5K_INT_MIB: Indicates the either Management Information Base counters or |
826 | * checked. We should do this with ath5k_hw_update_mib_counters() but | 805 | * one of the PHY error counters reached the maximum value and should be |
827 | * it seems we should also then do some noise immunity work. | 806 | * read and cleared. |
828 | * @AR5K_INT_RXPHY: RX PHY Error | 807 | * @AR5K_INT_RXPHY: RX PHY Error |
829 | * @AR5K_INT_RXKCM: RX Key cache miss | 808 | * @AR5K_INT_RXKCM: RX Key cache miss |
830 | * @AR5K_INT_SWBA: SoftWare Beacon Alert - indicates its time to send a | 809 | * @AR5K_INT_SWBA: SoftWare Beacon Alert - indicates its time to send a |
@@ -912,10 +891,11 @@ enum ath5k_int { | |||
912 | AR5K_INT_NOCARD = 0xffffffff | 891 | AR5K_INT_NOCARD = 0xffffffff |
913 | }; | 892 | }; |
914 | 893 | ||
915 | /* Software interrupts used for calibration */ | 894 | /* mask which calibration is active at the moment */ |
916 | enum ath5k_software_interrupt { | 895 | enum ath5k_calibration_mask { |
917 | AR5K_SWI_FULL_CALIBRATION = 0x01, | 896 | AR5K_CALIBRATION_FULL = 0x01, |
918 | AR5K_SWI_SHORT_CALIBRATION = 0x02, | 897 | AR5K_CALIBRATION_SHORT = 0x02, |
898 | AR5K_CALIBRATION_ANI = 0x04, | ||
919 | }; | 899 | }; |
920 | 900 | ||
921 | /* | 901 | /* |
@@ -1004,6 +984,8 @@ struct ath5k_capabilities { | |||
1004 | struct { | 984 | struct { |
1005 | u8 q_tx_num; | 985 | u8 q_tx_num; |
1006 | } cap_queues; | 986 | } cap_queues; |
987 | |||
988 | bool cap_has_phyerr_counters; | ||
1007 | }; | 989 | }; |
1008 | 990 | ||
1009 | /* size of noise floor history (keep it a power of two) */ | 991 | /* size of noise floor history (keep it a power of two) */ |
@@ -1014,6 +996,15 @@ struct ath5k_nfcal_hist | |||
1014 | s16 nfval[ATH5K_NF_CAL_HIST_MAX]; /* last few noise floors */ | 996 | s16 nfval[ATH5K_NF_CAL_HIST_MAX]; /* last few noise floors */ |
1015 | }; | 997 | }; |
1016 | 998 | ||
999 | /** | ||
1000 | * struct avg_val - Helper structure for average calculation | ||
1001 | * @avg: contains the actual average value | ||
1002 | * @avg_weight: is used internally during calculation to prevent rounding errors | ||
1003 | */ | ||
1004 | struct ath5k_avg_val { | ||
1005 | int avg; | ||
1006 | int avg_weight; | ||
1007 | }; | ||
1017 | 1008 | ||
1018 | /***************************************\ | 1009 | /***************************************\ |
1019 | HARDWARE ABSTRACTION LAYER STRUCTURE | 1010 | HARDWARE ABSTRACTION LAYER STRUCTURE |
@@ -1028,7 +1019,6 @@ struct ath5k_nfcal_hist | |||
1028 | 1019 | ||
1029 | /* TODO: Clean up and merge with ath5k_softc */ | 1020 | /* TODO: Clean up and merge with ath5k_softc */ |
1030 | struct ath5k_hw { | 1021 | struct ath5k_hw { |
1031 | u32 ah_magic; | ||
1032 | struct ath_common common; | 1022 | struct ath_common common; |
1033 | 1023 | ||
1034 | struct ath5k_softc *ah_sc; | 1024 | struct ath5k_softc *ah_sc; |
@@ -1036,7 +1026,6 @@ struct ath5k_hw { | |||
1036 | 1026 | ||
1037 | enum ath5k_int ah_imr; | 1027 | enum ath5k_int ah_imr; |
1038 | 1028 | ||
1039 | enum nl80211_iftype ah_op_mode; | ||
1040 | struct ieee80211_channel *ah_current_channel; | 1029 | struct ieee80211_channel *ah_current_channel; |
1041 | bool ah_turbo; | 1030 | bool ah_turbo; |
1042 | bool ah_calibration; | 1031 | bool ah_calibration; |
@@ -1049,7 +1038,6 @@ struct ath5k_hw { | |||
1049 | u32 ah_phy; | 1038 | u32 ah_phy; |
1050 | u32 ah_mac_srev; | 1039 | u32 ah_mac_srev; |
1051 | u16 ah_mac_version; | 1040 | u16 ah_mac_version; |
1052 | u16 ah_mac_revision; | ||
1053 | u16 ah_phy_revision; | 1041 | u16 ah_phy_revision; |
1054 | u16 ah_radio_5ghz_revision; | 1042 | u16 ah_radio_5ghz_revision; |
1055 | u16 ah_radio_2ghz_revision; | 1043 | u16 ah_radio_2ghz_revision; |
@@ -1071,8 +1059,6 @@ struct ath5k_hw { | |||
1071 | u8 ah_def_ant; | 1059 | u8 ah_def_ant; |
1072 | bool ah_software_retry; | 1060 | bool ah_software_retry; |
1073 | 1061 | ||
1074 | int ah_gpio_npins; | ||
1075 | |||
1076 | struct ath5k_capabilities ah_capabilities; | 1062 | struct ath5k_capabilities ah_capabilities; |
1077 | 1063 | ||
1078 | struct ath5k_txq_info ah_txq[AR5K_NUM_TX_QUEUES]; | 1064 | struct ath5k_txq_info ah_txq[AR5K_NUM_TX_QUEUES]; |
@@ -1123,17 +1109,18 @@ struct ath5k_hw { | |||
1123 | 1109 | ||
1124 | struct ath5k_nfcal_hist ah_nfcal_hist; | 1110 | struct ath5k_nfcal_hist ah_nfcal_hist; |
1125 | 1111 | ||
1112 | /* average beacon RSSI in our BSS (used by ANI) */ | ||
1113 | struct ath5k_avg_val ah_beacon_rssi_avg; | ||
1114 | |||
1126 | /* noise floor from last periodic calibration */ | 1115 | /* noise floor from last periodic calibration */ |
1127 | s32 ah_noise_floor; | 1116 | s32 ah_noise_floor; |
1128 | 1117 | ||
1129 | /* Calibration timestamp */ | 1118 | /* Calibration timestamp */ |
1130 | unsigned long ah_cal_tstamp; | 1119 | unsigned long ah_cal_next_full; |
1131 | 1120 | unsigned long ah_cal_next_ani; | |
1132 | /* Calibration interval (secs) */ | ||
1133 | u8 ah_cal_intval; | ||
1134 | 1121 | ||
1135 | /* Software interrupt mask */ | 1122 | /* Calibration mask */ |
1136 | u8 ah_swi_mask; | 1123 | u8 ah_cal_mask; |
1137 | 1124 | ||
1138 | /* | 1125 | /* |
1139 | * Function pointers | 1126 | * Function pointers |
@@ -1141,9 +1128,9 @@ struct ath5k_hw { | |||
1141 | int (*ah_setup_rx_desc)(struct ath5k_hw *ah, struct ath5k_desc *desc, | 1128 | int (*ah_setup_rx_desc)(struct ath5k_hw *ah, struct ath5k_desc *desc, |
1142 | u32 size, unsigned int flags); | 1129 | u32 size, unsigned int flags); |
1143 | int (*ah_setup_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, | 1130 | int (*ah_setup_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, |
1144 | unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int, | 1131 | unsigned int, unsigned int, int, enum ath5k_pkt_type, |
1145 | unsigned int, unsigned int, unsigned int, unsigned int, | 1132 | unsigned int, unsigned int, unsigned int, unsigned int, |
1146 | unsigned int, unsigned int, unsigned int); | 1133 | unsigned int, unsigned int, unsigned int, unsigned int); |
1147 | int (*ah_setup_mrr_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, | 1134 | int (*ah_setup_mrr_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, |
1148 | unsigned int, unsigned int, unsigned int, unsigned int, | 1135 | unsigned int, unsigned int, unsigned int, unsigned int, |
1149 | unsigned int, unsigned int); | 1136 | unsigned int, unsigned int); |
@@ -1158,158 +1145,145 @@ struct ath5k_hw { | |||
1158 | */ | 1145 | */ |
1159 | 1146 | ||
1160 | /* Attach/Detach Functions */ | 1147 | /* Attach/Detach Functions */ |
1161 | extern int ath5k_hw_attach(struct ath5k_softc *sc); | 1148 | int ath5k_hw_attach(struct ath5k_softc *sc); |
1162 | extern void ath5k_hw_detach(struct ath5k_hw *ah); | 1149 | void ath5k_hw_detach(struct ath5k_hw *ah); |
1163 | 1150 | ||
1164 | /* LED functions */ | 1151 | /* LED functions */ |
1165 | extern int ath5k_init_leds(struct ath5k_softc *sc); | 1152 | int ath5k_init_leds(struct ath5k_softc *sc); |
1166 | extern void ath5k_led_enable(struct ath5k_softc *sc); | 1153 | void ath5k_led_enable(struct ath5k_softc *sc); |
1167 | extern void ath5k_led_off(struct ath5k_softc *sc); | 1154 | void ath5k_led_off(struct ath5k_softc *sc); |
1168 | extern void ath5k_unregister_leds(struct ath5k_softc *sc); | 1155 | void ath5k_unregister_leds(struct ath5k_softc *sc); |
1169 | 1156 | ||
1170 | /* Reset Functions */ | 1157 | /* Reset Functions */ |
1171 | extern int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial); | 1158 | int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial); |
1172 | extern int ath5k_hw_on_hold(struct ath5k_hw *ah); | 1159 | int ath5k_hw_on_hold(struct ath5k_hw *ah); |
1173 | extern int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, struct ieee80211_channel *channel, bool change_channel); | 1160 | int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, |
1161 | struct ieee80211_channel *channel, bool change_channel); | ||
1162 | int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, | ||
1163 | bool is_set); | ||
1174 | /* Power management functions */ | 1164 | /* Power management functions */ |
1175 | extern int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, bool set_chip, u16 sleep_duration); | ||
1176 | 1165 | ||
1177 | /* DMA Related Functions */ | 1166 | /* DMA Related Functions */ |
1178 | extern void ath5k_hw_start_rx_dma(struct ath5k_hw *ah); | 1167 | void ath5k_hw_start_rx_dma(struct ath5k_hw *ah); |
1179 | extern int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah); | 1168 | int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah); |
1180 | extern u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah); | 1169 | u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah); |
1181 | extern void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr); | 1170 | void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr); |
1182 | extern int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue); | 1171 | int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue); |
1183 | extern int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue); | 1172 | int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue); |
1184 | extern u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue); | 1173 | u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue); |
1185 | extern int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, | 1174 | int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, |
1186 | u32 phys_addr); | 1175 | u32 phys_addr); |
1187 | extern int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase); | 1176 | int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase); |
1188 | /* Interrupt handling */ | 1177 | /* Interrupt handling */ |
1189 | extern bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah); | 1178 | bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah); |
1190 | extern int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask); | 1179 | int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask); |
1191 | extern enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum | 1180 | enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask); |
1192 | ath5k_int new_mask); | 1181 | void ath5k_hw_update_mib_counters(struct ath5k_hw *ah); |
1193 | extern void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, struct ieee80211_low_level_stats *stats); | ||
1194 | 1182 | ||
1195 | /* EEPROM access functions */ | 1183 | /* EEPROM access functions */ |
1196 | extern int ath5k_eeprom_init(struct ath5k_hw *ah); | 1184 | int ath5k_eeprom_init(struct ath5k_hw *ah); |
1197 | extern void ath5k_eeprom_detach(struct ath5k_hw *ah); | 1185 | void ath5k_eeprom_detach(struct ath5k_hw *ah); |
1198 | extern int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac); | 1186 | int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac); |
1199 | extern bool ath5k_eeprom_is_hb63(struct ath5k_hw *ah); | ||
1200 | 1187 | ||
1201 | /* Protocol Control Unit Functions */ | 1188 | /* Protocol Control Unit Functions */ |
1202 | extern int ath5k_hw_set_opmode(struct ath5k_hw *ah); | 1189 | extern int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode); |
1203 | extern void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class); | 1190 | void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class); |
1204 | /* BSSID Functions */ | 1191 | /* BSSID Functions */ |
1205 | extern int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac); | 1192 | int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac); |
1206 | extern void ath5k_hw_set_associd(struct ath5k_hw *ah); | 1193 | void ath5k_hw_set_associd(struct ath5k_hw *ah); |
1207 | extern void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask); | 1194 | void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask); |
1208 | /* Receive start/stop functions */ | 1195 | /* Receive start/stop functions */ |
1209 | extern void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah); | 1196 | void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah); |
1210 | extern void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah); | 1197 | void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah); |
1211 | /* RX Filter functions */ | 1198 | /* RX Filter functions */ |
1212 | extern void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1); | 1199 | void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1); |
1213 | extern int ath5k_hw_set_mcast_filter_idx(struct ath5k_hw *ah, u32 index); | 1200 | u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah); |
1214 | extern int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index); | 1201 | void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter); |
1215 | extern u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah); | ||
1216 | extern void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter); | ||
1217 | /* Beacon control functions */ | 1202 | /* Beacon control functions */ |
1218 | extern u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah); | 1203 | u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah); |
1219 | extern u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah); | 1204 | void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64); |
1220 | extern void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64); | 1205 | void ath5k_hw_reset_tsf(struct ath5k_hw *ah); |
1221 | extern void ath5k_hw_reset_tsf(struct ath5k_hw *ah); | 1206 | void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval); |
1222 | extern void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval); | ||
1223 | #if 0 | ||
1224 | extern int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah, const struct ath5k_beacon_state *state); | ||
1225 | extern void ath5k_hw_reset_beacon(struct ath5k_hw *ah); | ||
1226 | extern int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr); | ||
1227 | #endif | ||
1228 | /* ACK bit rate */ | 1207 | /* ACK bit rate */ |
1229 | void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high); | 1208 | void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high); |
1230 | /* ACK/CTS Timeouts */ | ||
1231 | extern int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout); | ||
1232 | extern unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah); | ||
1233 | extern int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout); | ||
1234 | extern unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah); | ||
1235 | /* Clock rate related functions */ | 1209 | /* Clock rate related functions */ |
1236 | unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec); | 1210 | unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec); |
1237 | unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock); | 1211 | unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock); |
1238 | unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah); | 1212 | unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah); |
1239 | /* Key table (WEP) functions */ | 1213 | /* Key table (WEP) functions */ |
1240 | extern int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry); | 1214 | int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry); |
1241 | extern int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry); | 1215 | int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, |
1242 | extern int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, const struct ieee80211_key_conf *key, const u8 *mac); | 1216 | const struct ieee80211_key_conf *key, const u8 *mac); |
1243 | extern int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac); | 1217 | int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac); |
1244 | 1218 | ||
1245 | /* Queue Control Unit, DFS Control Unit Functions */ | 1219 | /* Queue Control Unit, DFS Control Unit Functions */ |
1246 | extern int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, struct ath5k_txq_info *queue_info); | 1220 | int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, |
1247 | extern int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue, | 1221 | struct ath5k_txq_info *queue_info); |
1248 | const struct ath5k_txq_info *queue_info); | 1222 | int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue, |
1249 | extern int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, | 1223 | const struct ath5k_txq_info *queue_info); |
1250 | enum ath5k_tx_queue queue_type, | 1224 | int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, |
1251 | struct ath5k_txq_info *queue_info); | 1225 | enum ath5k_tx_queue queue_type, |
1252 | extern u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue); | 1226 | struct ath5k_txq_info *queue_info); |
1253 | extern void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue); | 1227 | u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue); |
1254 | extern int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue); | 1228 | void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue); |
1255 | extern unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah); | 1229 | int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue); |
1256 | extern int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time); | 1230 | int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time); |
1257 | 1231 | ||
1258 | /* Hardware Descriptor Functions */ | 1232 | /* Hardware Descriptor Functions */ |
1259 | extern int ath5k_hw_init_desc_functions(struct ath5k_hw *ah); | 1233 | int ath5k_hw_init_desc_functions(struct ath5k_hw *ah); |
1260 | 1234 | ||
1261 | /* GPIO Functions */ | 1235 | /* GPIO Functions */ |
1262 | extern void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state); | 1236 | void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state); |
1263 | extern int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio); | 1237 | int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio); |
1264 | extern int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio); | 1238 | int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio); |
1265 | extern u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio); | 1239 | u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio); |
1266 | extern int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val); | 1240 | int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val); |
1267 | extern void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, u32 interrupt_level); | 1241 | void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, |
1242 | u32 interrupt_level); | ||
1268 | 1243 | ||
1269 | /* rfkill Functions */ | 1244 | /* rfkill Functions */ |
1270 | extern void ath5k_rfkill_hw_start(struct ath5k_hw *ah); | 1245 | void ath5k_rfkill_hw_start(struct ath5k_hw *ah); |
1271 | extern void ath5k_rfkill_hw_stop(struct ath5k_hw *ah); | 1246 | void ath5k_rfkill_hw_stop(struct ath5k_hw *ah); |
1272 | 1247 | ||
1273 | /* Misc functions */ | 1248 | /* Misc functions */ |
1274 | int ath5k_hw_set_capabilities(struct ath5k_hw *ah); | 1249 | int ath5k_hw_set_capabilities(struct ath5k_hw *ah); |
1275 | extern int ath5k_hw_get_capability(struct ath5k_hw *ah, enum ath5k_capability_type cap_type, u32 capability, u32 *result); | 1250 | int ath5k_hw_get_capability(struct ath5k_hw *ah, |
1276 | extern int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, u16 assoc_id); | 1251 | enum ath5k_capability_type cap_type, u32 capability, |
1277 | extern int ath5k_hw_disable_pspoll(struct ath5k_hw *ah); | 1252 | u32 *result); |
1253 | int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, u16 assoc_id); | ||
1254 | int ath5k_hw_disable_pspoll(struct ath5k_hw *ah); | ||
1278 | 1255 | ||
1279 | /* Initial register settings functions */ | 1256 | /* Initial register settings functions */ |
1280 | extern int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel); | 1257 | int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel); |
1281 | 1258 | ||
1282 | /* Initialize RF */ | 1259 | /* Initialize RF */ |
1283 | extern int ath5k_hw_rfregs_init(struct ath5k_hw *ah, | 1260 | int ath5k_hw_rfregs_init(struct ath5k_hw *ah, |
1284 | struct ieee80211_channel *channel, | 1261 | struct ieee80211_channel *channel, |
1285 | unsigned int mode); | 1262 | unsigned int mode); |
1286 | extern int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq); | 1263 | int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq); |
1287 | extern enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah); | 1264 | enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah); |
1288 | extern int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah); | 1265 | int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah); |
1289 | /* PHY/RF channel functions */ | 1266 | /* PHY/RF channel functions */ |
1290 | extern bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags); | 1267 | bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags); |
1291 | extern int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel); | 1268 | int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel); |
1292 | /* PHY calibration */ | 1269 | /* PHY calibration */ |
1293 | void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah); | 1270 | void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah); |
1294 | extern int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, struct ieee80211_channel *channel); | 1271 | int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, |
1295 | extern int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq); | 1272 | struct ieee80211_channel *channel); |
1296 | extern s16 ath5k_hw_get_noise_floor(struct ath5k_hw *ah); | ||
1297 | extern void ath5k_hw_calibration_poll(struct ath5k_hw *ah); | ||
1298 | /* Spur mitigation */ | 1273 | /* Spur mitigation */ |
1299 | bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, | 1274 | bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, |
1300 | struct ieee80211_channel *channel); | 1275 | struct ieee80211_channel *channel); |
1301 | void ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, | 1276 | void ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, |
1302 | struct ieee80211_channel *channel); | 1277 | struct ieee80211_channel *channel); |
1303 | /* Misc PHY functions */ | 1278 | /* Misc PHY functions */ |
1304 | extern u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan); | 1279 | u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan); |
1305 | extern int ath5k_hw_phy_disable(struct ath5k_hw *ah); | 1280 | int ath5k_hw_phy_disable(struct ath5k_hw *ah); |
1306 | /* Antenna control */ | 1281 | /* Antenna control */ |
1307 | extern void ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode); | 1282 | void ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode); |
1308 | extern void ath5k_hw_set_def_antenna(struct ath5k_hw *ah, u8 ant); | ||
1309 | extern unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah); | ||
1310 | /* TX power setup */ | 1283 | /* TX power setup */ |
1311 | extern int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, u8 ee_mode, u8 txpower); | 1284 | int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, |
1312 | extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower); | 1285 | u8 ee_mode, u8 txpower); |
1286 | int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower); | ||
1313 | 1287 | ||
1314 | /* | 1288 | /* |
1315 | * Functions used internaly | 1289 | * Functions used internaly |
@@ -1335,29 +1309,6 @@ static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg) | |||
1335 | iowrite32(val, ah->ah_iobase + reg); | 1309 | iowrite32(val, ah->ah_iobase + reg); |
1336 | } | 1310 | } |
1337 | 1311 | ||
1338 | #if defined(_ATH5K_RESET) || defined(_ATH5K_PHY) | ||
1339 | /* | ||
1340 | * Check if a register write has been completed | ||
1341 | */ | ||
1342 | static int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, | ||
1343 | u32 val, bool is_set) | ||
1344 | { | ||
1345 | int i; | ||
1346 | u32 data; | ||
1347 | |||
1348 | for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) { | ||
1349 | data = ath5k_hw_reg_read(ah, reg); | ||
1350 | if (is_set && (data & flag)) | ||
1351 | break; | ||
1352 | else if ((data & flag) == val) | ||
1353 | break; | ||
1354 | udelay(15); | ||
1355 | } | ||
1356 | |||
1357 | return (i <= 0) ? -EAGAIN : 0; | ||
1358 | } | ||
1359 | #endif | ||
1360 | |||
1361 | static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits) | 1312 | static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits) |
1362 | { | 1313 | { |
1363 | u32 retval = 0, bit, i; | 1314 | u32 retval = 0, bit, i; |
@@ -1370,9 +1321,27 @@ static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits) | |||
1370 | return retval; | 1321 | return retval; |
1371 | } | 1322 | } |
1372 | 1323 | ||
1373 | static inline int ath5k_pad_size(int hdrlen) | 1324 | #define AVG_SAMPLES 8 |
1325 | #define AVG_FACTOR 1000 | ||
1326 | |||
1327 | /** | ||
1328 | * ath5k_moving_average - Exponentially weighted moving average | ||
1329 | * @avg: average structure | ||
1330 | * @val: current value | ||
1331 | * | ||
1332 | * This implementation make use of a struct ath5k_avg_val to prevent rounding | ||
1333 | * errors. | ||
1334 | */ | ||
1335 | static inline struct ath5k_avg_val | ||
1336 | ath5k_moving_average(const struct ath5k_avg_val avg, const int val) | ||
1374 | { | 1337 | { |
1375 | return (hdrlen < 24) ? 0 : hdrlen & 3; | 1338 | struct ath5k_avg_val new; |
1339 | new.avg_weight = avg.avg_weight ? | ||
1340 | (((avg.avg_weight * ((AVG_SAMPLES) - 1)) + | ||
1341 | (val * (AVG_FACTOR))) / (AVG_SAMPLES)) : | ||
1342 | (val * (AVG_FACTOR)); | ||
1343 | new.avg = new.avg_weight / (AVG_FACTOR); | ||
1344 | return new; | ||
1376 | } | 1345 | } |
1377 | 1346 | ||
1378 | #endif | 1347 | #endif |
diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index 42284445b75e..dcf7c30f813f 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c | |||
@@ -113,7 +113,6 @@ int ath5k_hw_attach(struct ath5k_softc *sc) | |||
113 | /* | 113 | /* |
114 | * HW information | 114 | * HW information |
115 | */ | 115 | */ |
116 | ah->ah_op_mode = NL80211_IFTYPE_STATION; | ||
117 | ah->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT; | 116 | ah->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT; |
118 | ah->ah_turbo = false; | 117 | ah->ah_turbo = false; |
119 | ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER; | 118 | ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER; |
@@ -123,6 +122,9 @@ int ath5k_hw_attach(struct ath5k_softc *sc) | |||
123 | ah->ah_cw_min = AR5K_TUNE_CWMIN; | 122 | ah->ah_cw_min = AR5K_TUNE_CWMIN; |
124 | ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY; | 123 | ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY; |
125 | ah->ah_software_retry = false; | 124 | ah->ah_software_retry = false; |
125 | ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT; | ||
126 | ah->ah_noise_floor = -95; /* until first NF calibration is run */ | ||
127 | sc->ani_state.ani_mode = ATH5K_ANI_MODE_AUTO; | ||
126 | 128 | ||
127 | /* | 129 | /* |
128 | * Find the mac version | 130 | * Find the mac version |
@@ -148,7 +150,6 @@ int ath5k_hw_attach(struct ath5k_softc *sc) | |||
148 | /* Get MAC, PHY and RADIO revisions */ | 150 | /* Get MAC, PHY and RADIO revisions */ |
149 | ah->ah_mac_srev = srev; | 151 | ah->ah_mac_srev = srev; |
150 | ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER); | 152 | ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER); |
151 | ah->ah_mac_revision = AR5K_REG_MS(srev, AR5K_SREV_REV); | ||
152 | ah->ah_phy_revision = ath5k_hw_reg_read(ah, AR5K_PHY_CHIP_ID) & | 153 | ah->ah_phy_revision = ath5k_hw_reg_read(ah, AR5K_PHY_CHIP_ID) & |
153 | 0xffffffff; | 154 | 0xffffffff; |
154 | ah->ah_radio_5ghz_revision = ath5k_hw_radio_revision(ah, | 155 | ah->ah_radio_5ghz_revision = ath5k_hw_radio_revision(ah, |
@@ -327,7 +328,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc) | |||
327 | /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */ | 328 | /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */ |
328 | memcpy(common->curbssid, ath_bcast_mac, ETH_ALEN); | 329 | memcpy(common->curbssid, ath_bcast_mac, ETH_ALEN); |
329 | ath5k_hw_set_associd(ah); | 330 | ath5k_hw_set_associd(ah); |
330 | ath5k_hw_set_opmode(ah); | 331 | ath5k_hw_set_opmode(ah, sc->opmode); |
331 | 332 | ||
332 | ath5k_hw_rfgain_opt_init(ah); | 333 | ath5k_hw_rfgain_opt_init(ah); |
333 | 334 | ||
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 8dce0077b023..c085a06f1e05 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -58,8 +58,8 @@ | |||
58 | #include "base.h" | 58 | #include "base.h" |
59 | #include "reg.h" | 59 | #include "reg.h" |
60 | #include "debug.h" | 60 | #include "debug.h" |
61 | #include "ani.h" | ||
61 | 62 | ||
62 | static u8 ath5k_calinterval = 10; /* Calibrate PHY every 10 secs (TODO: Fixme) */ | ||
63 | static int modparam_nohwcrypt; | 63 | static int modparam_nohwcrypt; |
64 | module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); | 64 | module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); |
65 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); | 65 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); |
@@ -198,7 +198,7 @@ static void __devexit ath5k_pci_remove(struct pci_dev *pdev); | |||
198 | static int ath5k_pci_suspend(struct device *dev); | 198 | static int ath5k_pci_suspend(struct device *dev); |
199 | static int ath5k_pci_resume(struct device *dev); | 199 | static int ath5k_pci_resume(struct device *dev); |
200 | 200 | ||
201 | SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume); | 201 | static SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume); |
202 | #define ATH5K_PM_OPS (&ath5k_pm_ops) | 202 | #define ATH5K_PM_OPS (&ath5k_pm_ops) |
203 | #else | 203 | #else |
204 | #define ATH5K_PM_OPS NULL | 204 | #define ATH5K_PM_OPS NULL |
@@ -307,7 +307,7 @@ static int ath5k_rxbuf_setup(struct ath5k_softc *sc, | |||
307 | struct ath5k_buf *bf); | 307 | struct ath5k_buf *bf); |
308 | static int ath5k_txbuf_setup(struct ath5k_softc *sc, | 308 | static int ath5k_txbuf_setup(struct ath5k_softc *sc, |
309 | struct ath5k_buf *bf, | 309 | struct ath5k_buf *bf, |
310 | struct ath5k_txq *txq); | 310 | struct ath5k_txq *txq, int padsize); |
311 | static inline void ath5k_txbuf_free(struct ath5k_softc *sc, | 311 | static inline void ath5k_txbuf_free(struct ath5k_softc *sc, |
312 | struct ath5k_buf *bf) | 312 | struct ath5k_buf *bf) |
313 | { | 313 | { |
@@ -364,6 +364,7 @@ static void ath5k_beacon_send(struct ath5k_softc *sc); | |||
364 | static void ath5k_beacon_config(struct ath5k_softc *sc); | 364 | static void ath5k_beacon_config(struct ath5k_softc *sc); |
365 | static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf); | 365 | static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf); |
366 | static void ath5k_tasklet_beacon(unsigned long data); | 366 | static void ath5k_tasklet_beacon(unsigned long data); |
367 | static void ath5k_tasklet_ani(unsigned long data); | ||
367 | 368 | ||
368 | static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp) | 369 | static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp) |
369 | { | 370 | { |
@@ -829,6 +830,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) | |||
829 | tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc); | 830 | tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc); |
830 | tasklet_init(&sc->calib, ath5k_tasklet_calibrate, (unsigned long)sc); | 831 | tasklet_init(&sc->calib, ath5k_tasklet_calibrate, (unsigned long)sc); |
831 | tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc); | 832 | tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc); |
833 | tasklet_init(&sc->ani_tasklet, ath5k_tasklet_ani, (unsigned long)sc); | ||
832 | 834 | ||
833 | ret = ath5k_eeprom_read_mac(ah, mac); | 835 | ret = ath5k_eeprom_read_mac(ah, mac); |
834 | if (ret) { | 836 | if (ret) { |
@@ -1137,8 +1139,6 @@ ath5k_mode_setup(struct ath5k_softc *sc) | |||
1137 | struct ath5k_hw *ah = sc->ah; | 1139 | struct ath5k_hw *ah = sc->ah; |
1138 | u32 rfilt; | 1140 | u32 rfilt; |
1139 | 1141 | ||
1140 | ah->ah_op_mode = sc->opmode; | ||
1141 | |||
1142 | /* configure rx filter */ | 1142 | /* configure rx filter */ |
1143 | rfilt = sc->filter_flags; | 1143 | rfilt = sc->filter_flags; |
1144 | ath5k_hw_set_rx_filter(ah, rfilt); | 1144 | ath5k_hw_set_rx_filter(ah, rfilt); |
@@ -1147,8 +1147,9 @@ ath5k_mode_setup(struct ath5k_softc *sc) | |||
1147 | ath5k_hw_set_bssid_mask(ah, sc->bssidmask); | 1147 | ath5k_hw_set_bssid_mask(ah, sc->bssidmask); |
1148 | 1148 | ||
1149 | /* configure operational mode */ | 1149 | /* configure operational mode */ |
1150 | ath5k_hw_set_opmode(ah); | 1150 | ath5k_hw_set_opmode(ah, sc->opmode); |
1151 | 1151 | ||
1152 | ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "mode setup opmode %d\n", sc->opmode); | ||
1152 | ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt); | 1153 | ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt); |
1153 | } | 1154 | } |
1154 | 1155 | ||
@@ -1271,7 +1272,7 @@ static enum ath5k_pkt_type get_hw_packet_type(struct sk_buff *skb) | |||
1271 | 1272 | ||
1272 | static int | 1273 | static int |
1273 | ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, | 1274 | ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, |
1274 | struct ath5k_txq *txq) | 1275 | struct ath5k_txq *txq, int padsize) |
1275 | { | 1276 | { |
1276 | struct ath5k_hw *ah = sc->ah; | 1277 | struct ath5k_hw *ah = sc->ah; |
1277 | struct ath5k_desc *ds = bf->desc; | 1278 | struct ath5k_desc *ds = bf->desc; |
@@ -1323,7 +1324,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, | |||
1323 | sc->vif, pktlen, info)); | 1324 | sc->vif, pktlen, info)); |
1324 | } | 1325 | } |
1325 | ret = ah->ah_setup_tx_desc(ah, ds, pktlen, | 1326 | ret = ah->ah_setup_tx_desc(ah, ds, pktlen, |
1326 | ieee80211_get_hdrlen_from_skb(skb), | 1327 | ieee80211_get_hdrlen_from_skb(skb), padsize, |
1327 | get_hw_packet_type(skb), | 1328 | get_hw_packet_type(skb), |
1328 | (sc->power_level * 2), | 1329 | (sc->power_level * 2), |
1329 | hw_rate, | 1330 | hw_rate, |
@@ -1806,6 +1807,86 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb, | |||
1806 | } | 1807 | } |
1807 | 1808 | ||
1808 | static void | 1809 | static void |
1810 | ath5k_update_beacon_rssi(struct ath5k_softc *sc, struct sk_buff *skb, int rssi) | ||
1811 | { | ||
1812 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; | ||
1813 | struct ath5k_hw *ah = sc->ah; | ||
1814 | struct ath_common *common = ath5k_hw_common(ah); | ||
1815 | |||
1816 | /* only beacons from our BSSID */ | ||
1817 | if (!ieee80211_is_beacon(mgmt->frame_control) || | ||
1818 | memcmp(mgmt->bssid, common->curbssid, ETH_ALEN) != 0) | ||
1819 | return; | ||
1820 | |||
1821 | ah->ah_beacon_rssi_avg = ath5k_moving_average(ah->ah_beacon_rssi_avg, | ||
1822 | rssi); | ||
1823 | |||
1824 | /* in IBSS mode we should keep RSSI statistics per neighbour */ | ||
1825 | /* le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS */ | ||
1826 | } | ||
1827 | |||
1828 | /* | ||
1829 | * Compute padding position. skb must contains an IEEE 802.11 frame | ||
1830 | */ | ||
1831 | static int ath5k_common_padpos(struct sk_buff *skb) | ||
1832 | { | ||
1833 | struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data; | ||
1834 | __le16 frame_control = hdr->frame_control; | ||
1835 | int padpos = 24; | ||
1836 | |||
1837 | if (ieee80211_has_a4(frame_control)) { | ||
1838 | padpos += ETH_ALEN; | ||
1839 | } | ||
1840 | if (ieee80211_is_data_qos(frame_control)) { | ||
1841 | padpos += IEEE80211_QOS_CTL_LEN; | ||
1842 | } | ||
1843 | |||
1844 | return padpos; | ||
1845 | } | ||
1846 | |||
1847 | /* | ||
1848 | * This function expects a 802.11 frame and returns the number of | ||
1849 | * bytes added, or -1 if we don't have enought header room. | ||
1850 | */ | ||
1851 | |||
1852 | static int ath5k_add_padding(struct sk_buff *skb) | ||
1853 | { | ||
1854 | int padpos = ath5k_common_padpos(skb); | ||
1855 | int padsize = padpos & 3; | ||
1856 | |||
1857 | if (padsize && skb->len>padpos) { | ||
1858 | |||
1859 | if (skb_headroom(skb) < padsize) | ||
1860 | return -1; | ||
1861 | |||
1862 | skb_push(skb, padsize); | ||
1863 | memmove(skb->data, skb->data+padsize, padpos); | ||
1864 | return padsize; | ||
1865 | } | ||
1866 | |||
1867 | return 0; | ||
1868 | } | ||
1869 | |||
1870 | /* | ||
1871 | * This function expects a 802.11 frame and returns the number of | ||
1872 | * bytes removed | ||
1873 | */ | ||
1874 | |||
1875 | static int ath5k_remove_padding(struct sk_buff *skb) | ||
1876 | { | ||
1877 | int padpos = ath5k_common_padpos(skb); | ||
1878 | int padsize = padpos & 3; | ||
1879 | |||
1880 | if (padsize && skb->len>=padpos+padsize) { | ||
1881 | memmove(skb->data + padsize, skb->data, padpos); | ||
1882 | skb_pull(skb, padsize); | ||
1883 | return padsize; | ||
1884 | } | ||
1885 | |||
1886 | return 0; | ||
1887 | } | ||
1888 | |||
1889 | static void | ||
1809 | ath5k_tasklet_rx(unsigned long data) | 1890 | ath5k_tasklet_rx(unsigned long data) |
1810 | { | 1891 | { |
1811 | struct ieee80211_rx_status *rxs; | 1892 | struct ieee80211_rx_status *rxs; |
@@ -1818,8 +1899,6 @@ ath5k_tasklet_rx(unsigned long data) | |||
1818 | struct ath5k_buf *bf; | 1899 | struct ath5k_buf *bf; |
1819 | struct ath5k_desc *ds; | 1900 | struct ath5k_desc *ds; |
1820 | int ret; | 1901 | int ret; |
1821 | int hdrlen; | ||
1822 | int padsize; | ||
1823 | int rx_flag; | 1902 | int rx_flag; |
1824 | 1903 | ||
1825 | spin_lock(&sc->rxbuflock); | 1904 | spin_lock(&sc->rxbuflock); |
@@ -1844,18 +1923,30 @@ ath5k_tasklet_rx(unsigned long data) | |||
1844 | break; | 1923 | break; |
1845 | else if (unlikely(ret)) { | 1924 | else if (unlikely(ret)) { |
1846 | ATH5K_ERR(sc, "error in processing rx descriptor\n"); | 1925 | ATH5K_ERR(sc, "error in processing rx descriptor\n"); |
1926 | sc->stats.rxerr_proc++; | ||
1847 | spin_unlock(&sc->rxbuflock); | 1927 | spin_unlock(&sc->rxbuflock); |
1848 | return; | 1928 | return; |
1849 | } | 1929 | } |
1850 | 1930 | ||
1931 | sc->stats.rx_all_count++; | ||
1932 | |||
1851 | if (unlikely(rs.rs_more)) { | 1933 | if (unlikely(rs.rs_more)) { |
1852 | ATH5K_WARN(sc, "unsupported jumbo\n"); | 1934 | ATH5K_WARN(sc, "unsupported jumbo\n"); |
1935 | sc->stats.rxerr_jumbo++; | ||
1853 | goto next; | 1936 | goto next; |
1854 | } | 1937 | } |
1855 | 1938 | ||
1856 | if (unlikely(rs.rs_status)) { | 1939 | if (unlikely(rs.rs_status)) { |
1857 | if (rs.rs_status & AR5K_RXERR_PHY) | 1940 | if (rs.rs_status & AR5K_RXERR_CRC) |
1941 | sc->stats.rxerr_crc++; | ||
1942 | if (rs.rs_status & AR5K_RXERR_FIFO) | ||
1943 | sc->stats.rxerr_fifo++; | ||
1944 | if (rs.rs_status & AR5K_RXERR_PHY) { | ||
1945 | sc->stats.rxerr_phy++; | ||
1946 | if (rs.rs_phyerr > 0 && rs.rs_phyerr < 32) | ||
1947 | sc->stats.rxerr_phy_code[rs.rs_phyerr]++; | ||
1858 | goto next; | 1948 | goto next; |
1949 | } | ||
1859 | if (rs.rs_status & AR5K_RXERR_DECRYPT) { | 1950 | if (rs.rs_status & AR5K_RXERR_DECRYPT) { |
1860 | /* | 1951 | /* |
1861 | * Decrypt error. If the error occurred | 1952 | * Decrypt error. If the error occurred |
@@ -1867,12 +1958,14 @@ ath5k_tasklet_rx(unsigned long data) | |||
1867 | * | 1958 | * |
1868 | * XXX do key cache faulting | 1959 | * XXX do key cache faulting |
1869 | */ | 1960 | */ |
1961 | sc->stats.rxerr_decrypt++; | ||
1870 | if (rs.rs_keyix == AR5K_RXKEYIX_INVALID && | 1962 | if (rs.rs_keyix == AR5K_RXKEYIX_INVALID && |
1871 | !(rs.rs_status & AR5K_RXERR_CRC)) | 1963 | !(rs.rs_status & AR5K_RXERR_CRC)) |
1872 | goto accept; | 1964 | goto accept; |
1873 | } | 1965 | } |
1874 | if (rs.rs_status & AR5K_RXERR_MIC) { | 1966 | if (rs.rs_status & AR5K_RXERR_MIC) { |
1875 | rx_flag |= RX_FLAG_MMIC_ERROR; | 1967 | rx_flag |= RX_FLAG_MMIC_ERROR; |
1968 | sc->stats.rxerr_mic++; | ||
1876 | goto accept; | 1969 | goto accept; |
1877 | } | 1970 | } |
1878 | 1971 | ||
@@ -1904,12 +1997,8 @@ accept: | |||
1904 | * bytes and we can optimize this a bit. In addition, we must | 1997 | * bytes and we can optimize this a bit. In addition, we must |
1905 | * not try to remove padding from short control frames that do | 1998 | * not try to remove padding from short control frames that do |
1906 | * not have payload. */ | 1999 | * not have payload. */ |
1907 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 2000 | ath5k_remove_padding(skb); |
1908 | padsize = ath5k_pad_size(hdrlen); | 2001 | |
1909 | if (padsize) { | ||
1910 | memmove(skb->data + padsize, skb->data, hdrlen); | ||
1911 | skb_pull(skb, padsize); | ||
1912 | } | ||
1913 | rxs = IEEE80211_SKB_RXCB(skb); | 2002 | rxs = IEEE80211_SKB_RXCB(skb); |
1914 | 2003 | ||
1915 | /* | 2004 | /* |
@@ -1942,6 +2031,12 @@ accept: | |||
1942 | rxs->signal = rxs->noise + rs.rs_rssi; | 2031 | rxs->signal = rxs->noise + rs.rs_rssi; |
1943 | 2032 | ||
1944 | rxs->antenna = rs.rs_antenna; | 2033 | rxs->antenna = rs.rs_antenna; |
2034 | |||
2035 | if (rs.rs_antenna > 0 && rs.rs_antenna < 5) | ||
2036 | sc->stats.antenna_rx[rs.rs_antenna]++; | ||
2037 | else | ||
2038 | sc->stats.antenna_rx[0]++; /* invalid */ | ||
2039 | |||
1945 | rxs->rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate); | 2040 | rxs->rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate); |
1946 | rxs->flag |= ath5k_rx_decrypted(sc, ds, skb, &rs); | 2041 | rxs->flag |= ath5k_rx_decrypted(sc, ds, skb, &rs); |
1947 | 2042 | ||
@@ -1951,6 +2046,8 @@ accept: | |||
1951 | 2046 | ||
1952 | ath5k_debug_dump_skb(sc, skb, "RX ", 0); | 2047 | ath5k_debug_dump_skb(sc, skb, "RX ", 0); |
1953 | 2048 | ||
2049 | ath5k_update_beacon_rssi(sc, skb, rs.rs_rssi); | ||
2050 | |||
1954 | /* check beacons in IBSS mode */ | 2051 | /* check beacons in IBSS mode */ |
1955 | if (sc->opmode == NL80211_IFTYPE_ADHOC) | 2052 | if (sc->opmode == NL80211_IFTYPE_ADHOC) |
1956 | ath5k_check_ibss_tsf(sc, skb, rxs); | 2053 | ath5k_check_ibss_tsf(sc, skb, rxs); |
@@ -1996,6 +2093,7 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) | |||
1996 | break; | 2093 | break; |
1997 | } | 2094 | } |
1998 | 2095 | ||
2096 | sc->stats.tx_all_count++; | ||
1999 | skb = bf->skb; | 2097 | skb = bf->skb; |
2000 | info = IEEE80211_SKB_CB(skb); | 2098 | info = IEEE80211_SKB_CB(skb); |
2001 | bf->skb = NULL; | 2099 | bf->skb = NULL; |
@@ -2021,14 +2119,31 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) | |||
2021 | info->status.rates[ts.ts_final_idx].count++; | 2119 | info->status.rates[ts.ts_final_idx].count++; |
2022 | 2120 | ||
2023 | if (unlikely(ts.ts_status)) { | 2121 | if (unlikely(ts.ts_status)) { |
2024 | sc->ll_stats.dot11ACKFailureCount++; | 2122 | sc->stats.ack_fail++; |
2025 | if (ts.ts_status & AR5K_TXERR_FILT) | 2123 | if (ts.ts_status & AR5K_TXERR_FILT) { |
2026 | info->flags |= IEEE80211_TX_STAT_TX_FILTERED; | 2124 | info->flags |= IEEE80211_TX_STAT_TX_FILTERED; |
2125 | sc->stats.txerr_filt++; | ||
2126 | } | ||
2127 | if (ts.ts_status & AR5K_TXERR_XRETRY) | ||
2128 | sc->stats.txerr_retry++; | ||
2129 | if (ts.ts_status & AR5K_TXERR_FIFO) | ||
2130 | sc->stats.txerr_fifo++; | ||
2027 | } else { | 2131 | } else { |
2028 | info->flags |= IEEE80211_TX_STAT_ACK; | 2132 | info->flags |= IEEE80211_TX_STAT_ACK; |
2029 | info->status.ack_signal = ts.ts_rssi; | 2133 | info->status.ack_signal = ts.ts_rssi; |
2030 | } | 2134 | } |
2031 | 2135 | ||
2136 | /* | ||
2137 | * Remove MAC header padding before giving the frame | ||
2138 | * back to mac80211. | ||
2139 | */ | ||
2140 | ath5k_remove_padding(skb); | ||
2141 | |||
2142 | if (ts.ts_antenna > 0 && ts.ts_antenna < 5) | ||
2143 | sc->stats.antenna_tx[ts.ts_antenna]++; | ||
2144 | else | ||
2145 | sc->stats.antenna_tx[0]++; /* invalid */ | ||
2146 | |||
2032 | ieee80211_tx_status(sc->hw, skb); | 2147 | ieee80211_tx_status(sc->hw, skb); |
2033 | 2148 | ||
2034 | spin_lock(&sc->txbuflock); | 2149 | spin_lock(&sc->txbuflock); |
@@ -2072,6 +2187,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) | |||
2072 | int ret = 0; | 2187 | int ret = 0; |
2073 | u8 antenna; | 2188 | u8 antenna; |
2074 | u32 flags; | 2189 | u32 flags; |
2190 | const int padsize = 0; | ||
2075 | 2191 | ||
2076 | bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len, | 2192 | bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len, |
2077 | PCI_DMA_TODEVICE); | 2193 | PCI_DMA_TODEVICE); |
@@ -2119,7 +2235,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) | |||
2119 | * from tx power (value is in dB units already) */ | 2235 | * from tx power (value is in dB units already) */ |
2120 | ds->ds_data = bf->skbaddr; | 2236 | ds->ds_data = bf->skbaddr; |
2121 | ret = ah->ah_setup_tx_desc(ah, ds, skb->len, | 2237 | ret = ah->ah_setup_tx_desc(ah, ds, skb->len, |
2122 | ieee80211_get_hdrlen_from_skb(skb), | 2238 | ieee80211_get_hdrlen_from_skb(skb), padsize, |
2123 | AR5K_PKT_TYPE_BEACON, (sc->power_level * 2), | 2239 | AR5K_PKT_TYPE_BEACON, (sc->power_level * 2), |
2124 | ieee80211_get_tx_rate(sc->hw, info)->hw_value, | 2240 | ieee80211_get_tx_rate(sc->hw, info)->hw_value, |
2125 | 1, AR5K_TXKEYIX_INVALID, | 2241 | 1, AR5K_TXKEYIX_INVALID, |
@@ -2406,9 +2522,6 @@ ath5k_init(struct ath5k_softc *sc) | |||
2406 | */ | 2522 | */ |
2407 | ath5k_stop_locked(sc); | 2523 | ath5k_stop_locked(sc); |
2408 | 2524 | ||
2409 | /* Set PHY calibration interval */ | ||
2410 | ah->ah_cal_intval = ath5k_calinterval; | ||
2411 | |||
2412 | /* | 2525 | /* |
2413 | * The basic interface to setting the hardware in a good | 2526 | * The basic interface to setting the hardware in a good |
2414 | * state is ``reset''. On return the hardware is known to | 2527 | * state is ``reset''. On return the hardware is known to |
@@ -2420,7 +2533,8 @@ ath5k_init(struct ath5k_softc *sc) | |||
2420 | sc->curband = &sc->sbands[sc->curchan->band]; | 2533 | sc->curband = &sc->sbands[sc->curchan->band]; |
2421 | sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL | | 2534 | sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL | |
2422 | AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL | | 2535 | AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL | |
2423 | AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_SWI; | 2536 | AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_MIB; |
2537 | |||
2424 | ret = ath5k_reset(sc, NULL); | 2538 | ret = ath5k_reset(sc, NULL); |
2425 | if (ret) | 2539 | if (ret) |
2426 | goto done; | 2540 | goto done; |
@@ -2532,12 +2646,33 @@ ath5k_stop_hw(struct ath5k_softc *sc) | |||
2532 | tasklet_kill(&sc->restq); | 2646 | tasklet_kill(&sc->restq); |
2533 | tasklet_kill(&sc->calib); | 2647 | tasklet_kill(&sc->calib); |
2534 | tasklet_kill(&sc->beacontq); | 2648 | tasklet_kill(&sc->beacontq); |
2649 | tasklet_kill(&sc->ani_tasklet); | ||
2535 | 2650 | ||
2536 | ath5k_rfkill_hw_stop(sc->ah); | 2651 | ath5k_rfkill_hw_stop(sc->ah); |
2537 | 2652 | ||
2538 | return ret; | 2653 | return ret; |
2539 | } | 2654 | } |
2540 | 2655 | ||
2656 | static void | ||
2657 | ath5k_intr_calibration_poll(struct ath5k_hw *ah) | ||
2658 | { | ||
2659 | if (time_is_before_eq_jiffies(ah->ah_cal_next_ani) && | ||
2660 | !(ah->ah_cal_mask & AR5K_CALIBRATION_FULL)) { | ||
2661 | /* run ANI only when full calibration is not active */ | ||
2662 | ah->ah_cal_next_ani = jiffies + | ||
2663 | msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_ANI); | ||
2664 | tasklet_schedule(&ah->ah_sc->ani_tasklet); | ||
2665 | |||
2666 | } else if (time_is_before_eq_jiffies(ah->ah_cal_next_full)) { | ||
2667 | ah->ah_cal_next_full = jiffies + | ||
2668 | msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_FULL); | ||
2669 | tasklet_schedule(&ah->ah_sc->calib); | ||
2670 | } | ||
2671 | /* we could use SWI to generate enough interrupts to meet our | ||
2672 | * calibration interval requirements, if necessary: | ||
2673 | * AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); */ | ||
2674 | } | ||
2675 | |||
2541 | static irqreturn_t | 2676 | static irqreturn_t |
2542 | ath5k_intr(int irq, void *dev_id) | 2677 | ath5k_intr(int irq, void *dev_id) |
2543 | { | 2678 | { |
@@ -2586,15 +2721,10 @@ ath5k_intr(int irq, void *dev_id) | |||
2586 | if (status & AR5K_INT_BMISS) { | 2721 | if (status & AR5K_INT_BMISS) { |
2587 | /* TODO */ | 2722 | /* TODO */ |
2588 | } | 2723 | } |
2589 | if (status & AR5K_INT_SWI) { | ||
2590 | tasklet_schedule(&sc->calib); | ||
2591 | } | ||
2592 | if (status & AR5K_INT_MIB) { | 2724 | if (status & AR5K_INT_MIB) { |
2593 | /* | 2725 | sc->stats.mib_intr++; |
2594 | * These stats are also used for ANI i think | 2726 | ath5k_hw_update_mib_counters(ah); |
2595 | * so how about updating them more often ? | 2727 | ath5k_ani_mib_intr(ah); |
2596 | */ | ||
2597 | ath5k_hw_update_mib_counters(ah, &sc->ll_stats); | ||
2598 | } | 2728 | } |
2599 | if (status & AR5K_INT_GPIO) | 2729 | if (status & AR5K_INT_GPIO) |
2600 | tasklet_schedule(&sc->rf_kill.toggleq); | 2730 | tasklet_schedule(&sc->rf_kill.toggleq); |
@@ -2605,7 +2735,7 @@ ath5k_intr(int irq, void *dev_id) | |||
2605 | if (unlikely(!counter)) | 2735 | if (unlikely(!counter)) |
2606 | ATH5K_WARN(sc, "too many interrupts, giving up for now\n"); | 2736 | ATH5K_WARN(sc, "too many interrupts, giving up for now\n"); |
2607 | 2737 | ||
2608 | ath5k_hw_calibration_poll(ah); | 2738 | ath5k_intr_calibration_poll(ah); |
2609 | 2739 | ||
2610 | return IRQ_HANDLED; | 2740 | return IRQ_HANDLED; |
2611 | } | 2741 | } |
@@ -2629,8 +2759,7 @@ ath5k_tasklet_calibrate(unsigned long data) | |||
2629 | struct ath5k_hw *ah = sc->ah; | 2759 | struct ath5k_hw *ah = sc->ah; |
2630 | 2760 | ||
2631 | /* Only full calibration for now */ | 2761 | /* Only full calibration for now */ |
2632 | if (ah->ah_swi_mask != AR5K_SWI_FULL_CALIBRATION) | 2762 | ah->ah_cal_mask |= AR5K_CALIBRATION_FULL; |
2633 | return; | ||
2634 | 2763 | ||
2635 | /* Stop queues so that calibration | 2764 | /* Stop queues so that calibration |
2636 | * doesn't interfere with tx */ | 2765 | * doesn't interfere with tx */ |
@@ -2653,11 +2782,22 @@ ath5k_tasklet_calibrate(unsigned long data) | |||
2653 | ieee80211_frequency_to_channel( | 2782 | ieee80211_frequency_to_channel( |
2654 | sc->curchan->center_freq)); | 2783 | sc->curchan->center_freq)); |
2655 | 2784 | ||
2656 | ah->ah_swi_mask = 0; | ||
2657 | |||
2658 | /* Wake queues */ | 2785 | /* Wake queues */ |
2659 | ieee80211_wake_queues(sc->hw); | 2786 | ieee80211_wake_queues(sc->hw); |
2660 | 2787 | ||
2788 | ah->ah_cal_mask &= ~AR5K_CALIBRATION_FULL; | ||
2789 | } | ||
2790 | |||
2791 | |||
2792 | static void | ||
2793 | ath5k_tasklet_ani(unsigned long data) | ||
2794 | { | ||
2795 | struct ath5k_softc *sc = (void *)data; | ||
2796 | struct ath5k_hw *ah = sc->ah; | ||
2797 | |||
2798 | ah->ah_cal_mask |= AR5K_CALIBRATION_ANI; | ||
2799 | ath5k_ani_calibration(ah); | ||
2800 | ah->ah_cal_mask &= ~AR5K_CALIBRATION_ANI; | ||
2661 | } | 2801 | } |
2662 | 2802 | ||
2663 | 2803 | ||
@@ -2679,7 +2819,6 @@ static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2679 | struct ath5k_softc *sc = hw->priv; | 2819 | struct ath5k_softc *sc = hw->priv; |
2680 | struct ath5k_buf *bf; | 2820 | struct ath5k_buf *bf; |
2681 | unsigned long flags; | 2821 | unsigned long flags; |
2682 | int hdrlen; | ||
2683 | int padsize; | 2822 | int padsize; |
2684 | 2823 | ||
2685 | ath5k_debug_dump_skb(sc, skb, "TX ", 1); | 2824 | ath5k_debug_dump_skb(sc, skb, "TX ", 1); |
@@ -2691,17 +2830,11 @@ static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2691 | * the hardware expects the header padded to 4 byte boundaries | 2830 | * the hardware expects the header padded to 4 byte boundaries |
2692 | * if this is not the case we add the padding after the header | 2831 | * if this is not the case we add the padding after the header |
2693 | */ | 2832 | */ |
2694 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 2833 | padsize = ath5k_add_padding(skb); |
2695 | padsize = ath5k_pad_size(hdrlen); | 2834 | if (padsize < 0) { |
2696 | if (padsize) { | 2835 | ATH5K_ERR(sc, "tx hdrlen not %%4: not enough" |
2697 | 2836 | " headroom to pad"); | |
2698 | if (skb_headroom(skb) < padsize) { | 2837 | goto drop_packet; |
2699 | ATH5K_ERR(sc, "tx hdrlen not %%4: %d not enough" | ||
2700 | " headroom to pad %d\n", hdrlen, padsize); | ||
2701 | goto drop_packet; | ||
2702 | } | ||
2703 | skb_push(skb, padsize); | ||
2704 | memmove(skb->data, skb->data+padsize, hdrlen); | ||
2705 | } | 2838 | } |
2706 | 2839 | ||
2707 | spin_lock_irqsave(&sc->txbuflock, flags); | 2840 | spin_lock_irqsave(&sc->txbuflock, flags); |
@@ -2720,7 +2853,7 @@ static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2720 | 2853 | ||
2721 | bf->skb = skb; | 2854 | bf->skb = skb; |
2722 | 2855 | ||
2723 | if (ath5k_txbuf_setup(sc, bf, txq)) { | 2856 | if (ath5k_txbuf_setup(sc, bf, txq, padsize)) { |
2724 | bf->skb = NULL; | 2857 | bf->skb = NULL; |
2725 | spin_lock_irqsave(&sc->txbuflock, flags); | 2858 | spin_lock_irqsave(&sc->txbuflock, flags); |
2726 | list_add_tail(&bf->list, &sc->txbuf); | 2859 | list_add_tail(&bf->list, &sc->txbuf); |
@@ -2767,6 +2900,8 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan) | |||
2767 | goto err; | 2900 | goto err; |
2768 | } | 2901 | } |
2769 | 2902 | ||
2903 | ath5k_ani_init(ah, ah->ah_sc->ani_state.ani_mode); | ||
2904 | |||
2770 | /* | 2905 | /* |
2771 | * Change channels and update the h/w rate map if we're switching; | 2906 | * Change channels and update the h/w rate map if we're switching; |
2772 | * e.g. 11a to 11b/g. | 2907 | * e.g. 11a to 11b/g. |
@@ -2835,6 +2970,8 @@ static int ath5k_add_interface(struct ieee80211_hw *hw, | |||
2835 | goto end; | 2970 | goto end; |
2836 | } | 2971 | } |
2837 | 2972 | ||
2973 | ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "add interface mode %d\n", sc->opmode); | ||
2974 | |||
2838 | ath5k_hw_set_lladdr(sc->ah, vif->addr); | 2975 | ath5k_hw_set_lladdr(sc->ah, vif->addr); |
2839 | ath5k_mode_setup(sc); | 2976 | ath5k_mode_setup(sc); |
2840 | 2977 | ||
@@ -2905,7 +3042,7 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed) | |||
2905 | * then we must allow the user to set how many tx antennas we | 3042 | * then we must allow the user to set how many tx antennas we |
2906 | * have available | 3043 | * have available |
2907 | */ | 3044 | */ |
2908 | ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_DEFAULT); | 3045 | ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode); |
2909 | 3046 | ||
2910 | unlock: | 3047 | unlock: |
2911 | mutex_unlock(&sc->lock); | 3048 | mutex_unlock(&sc->lock); |
@@ -3123,12 +3260,14 @@ ath5k_get_stats(struct ieee80211_hw *hw, | |||
3123 | struct ieee80211_low_level_stats *stats) | 3260 | struct ieee80211_low_level_stats *stats) |
3124 | { | 3261 | { |
3125 | struct ath5k_softc *sc = hw->priv; | 3262 | struct ath5k_softc *sc = hw->priv; |
3126 | struct ath5k_hw *ah = sc->ah; | ||
3127 | 3263 | ||
3128 | /* Force update */ | 3264 | /* Force update */ |
3129 | ath5k_hw_update_mib_counters(ah, &sc->ll_stats); | 3265 | ath5k_hw_update_mib_counters(sc->ah); |
3130 | 3266 | ||
3131 | memcpy(stats, &sc->ll_stats, sizeof(sc->ll_stats)); | 3267 | stats->dot11ACKFailureCount = sc->stats.ack_fail; |
3268 | stats->dot11RTSFailureCount = sc->stats.rts_fail; | ||
3269 | stats->dot11RTSSuccessCount = sc->stats.rts_ok; | ||
3270 | stats->dot11FCSErrorCount = sc->stats.fcs_error; | ||
3132 | 3271 | ||
3133 | return 0; | 3272 | return 0; |
3134 | } | 3273 | } |
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h index 7e1a88a5abdb..53a5651c57a2 100644 --- a/drivers/net/wireless/ath/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h | |||
@@ -50,6 +50,7 @@ | |||
50 | 50 | ||
51 | #include "ath5k.h" | 51 | #include "ath5k.h" |
52 | #include "debug.h" | 52 | #include "debug.h" |
53 | #include "ani.h" | ||
53 | 54 | ||
54 | #include "../regd.h" | 55 | #include "../regd.h" |
55 | #include "../ath.h" | 56 | #include "../ath.h" |
@@ -105,6 +106,37 @@ struct ath5k_rfkill { | |||
105 | struct tasklet_struct toggleq; | 106 | struct tasklet_struct toggleq; |
106 | }; | 107 | }; |
107 | 108 | ||
109 | /* statistics */ | ||
110 | struct ath5k_statistics { | ||
111 | /* antenna use */ | ||
112 | unsigned int antenna_rx[5]; /* frames count per antenna RX */ | ||
113 | unsigned int antenna_tx[5]; /* frames count per antenna TX */ | ||
114 | |||
115 | /* frame errors */ | ||
116 | unsigned int rx_all_count; /* all RX frames, including errors */ | ||
117 | unsigned int tx_all_count; /* all TX frames, including errors */ | ||
118 | unsigned int rxerr_crc; | ||
119 | unsigned int rxerr_phy; | ||
120 | unsigned int rxerr_phy_code[32]; | ||
121 | unsigned int rxerr_fifo; | ||
122 | unsigned int rxerr_decrypt; | ||
123 | unsigned int rxerr_mic; | ||
124 | unsigned int rxerr_proc; | ||
125 | unsigned int rxerr_jumbo; | ||
126 | unsigned int txerr_retry; | ||
127 | unsigned int txerr_fifo; | ||
128 | unsigned int txerr_filt; | ||
129 | |||
130 | /* MIB counters */ | ||
131 | unsigned int ack_fail; | ||
132 | unsigned int rts_fail; | ||
133 | unsigned int rts_ok; | ||
134 | unsigned int fcs_error; | ||
135 | unsigned int beacons; | ||
136 | |||
137 | unsigned int mib_intr; | ||
138 | }; | ||
139 | |||
108 | #if CHAN_DEBUG | 140 | #if CHAN_DEBUG |
109 | #define ATH_CHAN_MAX (26+26+26+200+200) | 141 | #define ATH_CHAN_MAX (26+26+26+200+200) |
110 | #else | 142 | #else |
@@ -117,7 +149,6 @@ struct ath5k_softc { | |||
117 | struct pci_dev *pdev; /* for dma mapping */ | 149 | struct pci_dev *pdev; /* for dma mapping */ |
118 | void __iomem *iobase; /* address of the device */ | 150 | void __iomem *iobase; /* address of the device */ |
119 | struct mutex lock; /* dev-level lock */ | 151 | struct mutex lock; /* dev-level lock */ |
120 | struct ieee80211_low_level_stats ll_stats; | ||
121 | struct ieee80211_hw *hw; /* IEEE 802.11 common */ | 152 | struct ieee80211_hw *hw; /* IEEE 802.11 common */ |
122 | struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; | 153 | struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; |
123 | struct ieee80211_channel channels[ATH_CHAN_MAX]; | 154 | struct ieee80211_channel channels[ATH_CHAN_MAX]; |
@@ -191,6 +222,11 @@ struct ath5k_softc { | |||
191 | int power_level; /* Requested tx power in dbm */ | 222 | int power_level; /* Requested tx power in dbm */ |
192 | bool assoc; /* associate state */ | 223 | bool assoc; /* associate state */ |
193 | bool enable_beacon; /* true if beacons are on */ | 224 | bool enable_beacon; /* true if beacons are on */ |
225 | |||
226 | struct ath5k_statistics stats; | ||
227 | |||
228 | struct ath5k_ani_state ani_state; | ||
229 | struct tasklet_struct ani_tasklet; /* ANI calibration */ | ||
194 | }; | 230 | }; |
195 | 231 | ||
196 | #define ath5k_hw_hasbssidmask(_ah) \ | 232 | #define ath5k_hw_hasbssidmask(_ah) \ |
diff --git a/drivers/net/wireless/ath/ath5k/caps.c b/drivers/net/wireless/ath/ath5k/caps.c index 367a6c7d3cc7..74f007126f41 100644 --- a/drivers/net/wireless/ath/ath5k/caps.c +++ b/drivers/net/wireless/ath/ath5k/caps.c | |||
@@ -102,9 +102,6 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah) | |||
102 | } | 102 | } |
103 | } | 103 | } |
104 | 104 | ||
105 | /* GPIO */ | ||
106 | ah->ah_gpio_npins = AR5K_NUM_GPIO; | ||
107 | |||
108 | /* Set number of supported TX queues */ | 105 | /* Set number of supported TX queues */ |
109 | if (ah->ah_version == AR5K_AR5210) | 106 | if (ah->ah_version == AR5K_AR5210) |
110 | ah->ah_capabilities.cap_queues.q_tx_num = | 107 | ah->ah_capabilities.cap_queues.q_tx_num = |
@@ -112,6 +109,12 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah) | |||
112 | else | 109 | else |
113 | ah->ah_capabilities.cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES; | 110 | ah->ah_capabilities.cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES; |
114 | 111 | ||
112 | /* newer hardware has PHY error counters */ | ||
113 | if (ah->ah_mac_srev >= AR5K_SREV_AR5213A) | ||
114 | ah->ah_capabilities.cap_has_phyerr_counters = true; | ||
115 | else | ||
116 | ah->ah_capabilities.cap_has_phyerr_counters = false; | ||
117 | |||
115 | return 0; | 118 | return 0; |
116 | } | 119 | } |
117 | 120 | ||
diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c index 747508c15d34..6fb5c5ffa5b1 100644 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c | |||
@@ -69,6 +69,7 @@ module_param_named(debug, ath5k_debug, uint, 0); | |||
69 | 69 | ||
70 | #include <linux/seq_file.h> | 70 | #include <linux/seq_file.h> |
71 | #include "reg.h" | 71 | #include "reg.h" |
72 | #include "ani.h" | ||
72 | 73 | ||
73 | static struct dentry *ath5k_global_debugfs; | 74 | static struct dentry *ath5k_global_debugfs; |
74 | 75 | ||
@@ -307,6 +308,7 @@ static const struct { | |||
307 | { ATH5K_DEBUG_DUMP_TX, "dumptx", "print transmit skb content" }, | 308 | { ATH5K_DEBUG_DUMP_TX, "dumptx", "print transmit skb content" }, |
308 | { ATH5K_DEBUG_DUMPBANDS, "dumpbands", "dump bands" }, | 309 | { ATH5K_DEBUG_DUMPBANDS, "dumpbands", "dump bands" }, |
309 | { ATH5K_DEBUG_TRACE, "trace", "trace function calls" }, | 310 | { ATH5K_DEBUG_TRACE, "trace", "trace function calls" }, |
311 | { ATH5K_DEBUG_ANI, "ani", "adaptive noise immunity" }, | ||
310 | { ATH5K_DEBUG_ANY, "all", "show all debug levels" }, | 312 | { ATH5K_DEBUG_ANY, "all", "show all debug levels" }, |
311 | }; | 313 | }; |
312 | 314 | ||
@@ -364,6 +366,369 @@ static const struct file_operations fops_debug = { | |||
364 | }; | 366 | }; |
365 | 367 | ||
366 | 368 | ||
369 | /* debugfs: antenna */ | ||
370 | |||
371 | static ssize_t read_file_antenna(struct file *file, char __user *user_buf, | ||
372 | size_t count, loff_t *ppos) | ||
373 | { | ||
374 | struct ath5k_softc *sc = file->private_data; | ||
375 | char buf[700]; | ||
376 | unsigned int len = 0; | ||
377 | unsigned int i; | ||
378 | unsigned int v; | ||
379 | |||
380 | len += snprintf(buf+len, sizeof(buf)-len, "antenna mode\t%d\n", | ||
381 | sc->ah->ah_ant_mode); | ||
382 | len += snprintf(buf+len, sizeof(buf)-len, "default antenna\t%d\n", | ||
383 | sc->ah->ah_def_ant); | ||
384 | len += snprintf(buf+len, sizeof(buf)-len, "tx antenna\t%d\n", | ||
385 | sc->ah->ah_tx_ant); | ||
386 | |||
387 | len += snprintf(buf+len, sizeof(buf)-len, "\nANTENNA\t\tRX\tTX\n"); | ||
388 | for (i = 1; i < ARRAY_SIZE(sc->stats.antenna_rx); i++) { | ||
389 | len += snprintf(buf+len, sizeof(buf)-len, | ||
390 | "[antenna %d]\t%d\t%d\n", | ||
391 | i, sc->stats.antenna_rx[i], sc->stats.antenna_tx[i]); | ||
392 | } | ||
393 | len += snprintf(buf+len, sizeof(buf)-len, "[invalid]\t%d\t%d\n", | ||
394 | sc->stats.antenna_rx[0], sc->stats.antenna_tx[0]); | ||
395 | |||
396 | v = ath5k_hw_reg_read(sc->ah, AR5K_DEFAULT_ANTENNA); | ||
397 | len += snprintf(buf+len, sizeof(buf)-len, | ||
398 | "\nAR5K_DEFAULT_ANTENNA\t0x%08x\n", v); | ||
399 | |||
400 | v = ath5k_hw_reg_read(sc->ah, AR5K_STA_ID1); | ||
401 | len += snprintf(buf+len, sizeof(buf)-len, | ||
402 | "AR5K_STA_ID1_DEFAULT_ANTENNA\t%d\n", | ||
403 | (v & AR5K_STA_ID1_DEFAULT_ANTENNA) != 0); | ||
404 | len += snprintf(buf+len, sizeof(buf)-len, | ||
405 | "AR5K_STA_ID1_DESC_ANTENNA\t%d\n", | ||
406 | (v & AR5K_STA_ID1_DESC_ANTENNA) != 0); | ||
407 | len += snprintf(buf+len, sizeof(buf)-len, | ||
408 | "AR5K_STA_ID1_RTS_DEF_ANTENNA\t%d\n", | ||
409 | (v & AR5K_STA_ID1_RTS_DEF_ANTENNA) != 0); | ||
410 | len += snprintf(buf+len, sizeof(buf)-len, | ||
411 | "AR5K_STA_ID1_SELFGEN_DEF_ANT\t%d\n", | ||
412 | (v & AR5K_STA_ID1_SELFGEN_DEF_ANT) != 0); | ||
413 | |||
414 | v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_AGCCTL); | ||
415 | len += snprintf(buf+len, sizeof(buf)-len, | ||
416 | "\nAR5K_PHY_AGCCTL_OFDM_DIV_DIS\t%d\n", | ||
417 | (v & AR5K_PHY_AGCCTL_OFDM_DIV_DIS) != 0); | ||
418 | |||
419 | v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_RESTART); | ||
420 | len += snprintf(buf+len, sizeof(buf)-len, | ||
421 | "AR5K_PHY_RESTART_DIV_GC\t\t%x\n", | ||
422 | (v & AR5K_PHY_RESTART_DIV_GC) >> AR5K_PHY_RESTART_DIV_GC_S); | ||
423 | |||
424 | v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_FAST_ANT_DIV); | ||
425 | len += snprintf(buf+len, sizeof(buf)-len, | ||
426 | "AR5K_PHY_FAST_ANT_DIV_EN\t%d\n", | ||
427 | (v & AR5K_PHY_FAST_ANT_DIV_EN) != 0); | ||
428 | |||
429 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
430 | } | ||
431 | |||
432 | static ssize_t write_file_antenna(struct file *file, | ||
433 | const char __user *userbuf, | ||
434 | size_t count, loff_t *ppos) | ||
435 | { | ||
436 | struct ath5k_softc *sc = file->private_data; | ||
437 | unsigned int i; | ||
438 | char buf[20]; | ||
439 | |||
440 | if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) | ||
441 | return -EFAULT; | ||
442 | |||
443 | if (strncmp(buf, "diversity", 9) == 0) { | ||
444 | ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_DEFAULT); | ||
445 | printk(KERN_INFO "ath5k debug: enable diversity\n"); | ||
446 | } else if (strncmp(buf, "fixed-a", 7) == 0) { | ||
447 | ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_A); | ||
448 | printk(KERN_INFO "ath5k debugfs: fixed antenna A\n"); | ||
449 | } else if (strncmp(buf, "fixed-b", 7) == 0) { | ||
450 | ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_B); | ||
451 | printk(KERN_INFO "ath5k debug: fixed antenna B\n"); | ||
452 | } else if (strncmp(buf, "clear", 5) == 0) { | ||
453 | for (i = 0; i < ARRAY_SIZE(sc->stats.antenna_rx); i++) { | ||
454 | sc->stats.antenna_rx[i] = 0; | ||
455 | sc->stats.antenna_tx[i] = 0; | ||
456 | } | ||
457 | printk(KERN_INFO "ath5k debug: cleared antenna stats\n"); | ||
458 | } | ||
459 | return count; | ||
460 | } | ||
461 | |||
462 | static const struct file_operations fops_antenna = { | ||
463 | .read = read_file_antenna, | ||
464 | .write = write_file_antenna, | ||
465 | .open = ath5k_debugfs_open, | ||
466 | .owner = THIS_MODULE, | ||
467 | }; | ||
468 | |||
469 | |||
470 | /* debugfs: frameerrors */ | ||
471 | |||
472 | static ssize_t read_file_frameerrors(struct file *file, char __user *user_buf, | ||
473 | size_t count, loff_t *ppos) | ||
474 | { | ||
475 | struct ath5k_softc *sc = file->private_data; | ||
476 | struct ath5k_statistics *st = &sc->stats; | ||
477 | char buf[700]; | ||
478 | unsigned int len = 0; | ||
479 | int i; | ||
480 | |||
481 | len += snprintf(buf+len, sizeof(buf)-len, | ||
482 | "RX\n---------------------\n"); | ||
483 | len += snprintf(buf+len, sizeof(buf)-len, "CRC\t%d\t(%d%%)\n", | ||
484 | st->rxerr_crc, | ||
485 | st->rx_all_count > 0 ? | ||
486 | st->rxerr_crc*100/st->rx_all_count : 0); | ||
487 | len += snprintf(buf+len, sizeof(buf)-len, "PHY\t%d\t(%d%%)\n", | ||
488 | st->rxerr_phy, | ||
489 | st->rx_all_count > 0 ? | ||
490 | st->rxerr_phy*100/st->rx_all_count : 0); | ||
491 | for (i = 0; i < 32; i++) { | ||
492 | if (st->rxerr_phy_code[i]) | ||
493 | len += snprintf(buf+len, sizeof(buf)-len, | ||
494 | " phy_err[%d]\t%d\n", | ||
495 | i, st->rxerr_phy_code[i]); | ||
496 | } | ||
497 | |||
498 | len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%d\t(%d%%)\n", | ||
499 | st->rxerr_fifo, | ||
500 | st->rx_all_count > 0 ? | ||
501 | st->rxerr_fifo*100/st->rx_all_count : 0); | ||
502 | len += snprintf(buf+len, sizeof(buf)-len, "decrypt\t%d\t(%d%%)\n", | ||
503 | st->rxerr_decrypt, | ||
504 | st->rx_all_count > 0 ? | ||
505 | st->rxerr_decrypt*100/st->rx_all_count : 0); | ||
506 | len += snprintf(buf+len, sizeof(buf)-len, "MIC\t%d\t(%d%%)\n", | ||
507 | st->rxerr_mic, | ||
508 | st->rx_all_count > 0 ? | ||
509 | st->rxerr_mic*100/st->rx_all_count : 0); | ||
510 | len += snprintf(buf+len, sizeof(buf)-len, "process\t%d\t(%d%%)\n", | ||
511 | st->rxerr_proc, | ||
512 | st->rx_all_count > 0 ? | ||
513 | st->rxerr_proc*100/st->rx_all_count : 0); | ||
514 | len += snprintf(buf+len, sizeof(buf)-len, "jumbo\t%d\t(%d%%)\n", | ||
515 | st->rxerr_jumbo, | ||
516 | st->rx_all_count > 0 ? | ||
517 | st->rxerr_jumbo*100/st->rx_all_count : 0); | ||
518 | len += snprintf(buf+len, sizeof(buf)-len, "[RX all\t%d]\n", | ||
519 | st->rx_all_count); | ||
520 | |||
521 | len += snprintf(buf+len, sizeof(buf)-len, | ||
522 | "\nTX\n---------------------\n"); | ||
523 | len += snprintf(buf+len, sizeof(buf)-len, "retry\t%d\t(%d%%)\n", | ||
524 | st->txerr_retry, | ||
525 | st->tx_all_count > 0 ? | ||
526 | st->txerr_retry*100/st->tx_all_count : 0); | ||
527 | len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%d\t(%d%%)\n", | ||
528 | st->txerr_fifo, | ||
529 | st->tx_all_count > 0 ? | ||
530 | st->txerr_fifo*100/st->tx_all_count : 0); | ||
531 | len += snprintf(buf+len, sizeof(buf)-len, "filter\t%d\t(%d%%)\n", | ||
532 | st->txerr_filt, | ||
533 | st->tx_all_count > 0 ? | ||
534 | st->txerr_filt*100/st->tx_all_count : 0); | ||
535 | len += snprintf(buf+len, sizeof(buf)-len, "[TX all\t%d]\n", | ||
536 | st->tx_all_count); | ||
537 | |||
538 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
539 | } | ||
540 | |||
541 | static ssize_t write_file_frameerrors(struct file *file, | ||
542 | const char __user *userbuf, | ||
543 | size_t count, loff_t *ppos) | ||
544 | { | ||
545 | struct ath5k_softc *sc = file->private_data; | ||
546 | struct ath5k_statistics *st = &sc->stats; | ||
547 | char buf[20]; | ||
548 | |||
549 | if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) | ||
550 | return -EFAULT; | ||
551 | |||
552 | if (strncmp(buf, "clear", 5) == 0) { | ||
553 | st->rxerr_crc = 0; | ||
554 | st->rxerr_phy = 0; | ||
555 | st->rxerr_fifo = 0; | ||
556 | st->rxerr_decrypt = 0; | ||
557 | st->rxerr_mic = 0; | ||
558 | st->rxerr_proc = 0; | ||
559 | st->rxerr_jumbo = 0; | ||
560 | st->rx_all_count = 0; | ||
561 | st->txerr_retry = 0; | ||
562 | st->txerr_fifo = 0; | ||
563 | st->txerr_filt = 0; | ||
564 | st->tx_all_count = 0; | ||
565 | printk(KERN_INFO "ath5k debug: cleared frameerrors stats\n"); | ||
566 | } | ||
567 | return count; | ||
568 | } | ||
569 | |||
570 | static const struct file_operations fops_frameerrors = { | ||
571 | .read = read_file_frameerrors, | ||
572 | .write = write_file_frameerrors, | ||
573 | .open = ath5k_debugfs_open, | ||
574 | .owner = THIS_MODULE, | ||
575 | }; | ||
576 | |||
577 | |||
578 | /* debugfs: ani */ | ||
579 | |||
580 | static ssize_t read_file_ani(struct file *file, char __user *user_buf, | ||
581 | size_t count, loff_t *ppos) | ||
582 | { | ||
583 | struct ath5k_softc *sc = file->private_data; | ||
584 | struct ath5k_statistics *st = &sc->stats; | ||
585 | struct ath5k_ani_state *as = &sc->ani_state; | ||
586 | |||
587 | char buf[700]; | ||
588 | unsigned int len = 0; | ||
589 | |||
590 | len += snprintf(buf+len, sizeof(buf)-len, | ||
591 | "HW has PHY error counters:\t%s\n", | ||
592 | sc->ah->ah_capabilities.cap_has_phyerr_counters ? | ||
593 | "yes" : "no"); | ||
594 | len += snprintf(buf+len, sizeof(buf)-len, | ||
595 | "HW max spur immunity level:\t%d\n", | ||
596 | as->max_spur_level); | ||
597 | len += snprintf(buf+len, sizeof(buf)-len, | ||
598 | "\nANI state\n--------------------------------------------\n"); | ||
599 | len += snprintf(buf+len, sizeof(buf)-len, "operating mode:\t\t\t"); | ||
600 | switch (as->ani_mode) { | ||
601 | case ATH5K_ANI_MODE_OFF: | ||
602 | len += snprintf(buf+len, sizeof(buf)-len, "OFF\n"); | ||
603 | break; | ||
604 | case ATH5K_ANI_MODE_MANUAL_LOW: | ||
605 | len += snprintf(buf+len, sizeof(buf)-len, | ||
606 | "MANUAL LOW\n"); | ||
607 | break; | ||
608 | case ATH5K_ANI_MODE_MANUAL_HIGH: | ||
609 | len += snprintf(buf+len, sizeof(buf)-len, | ||
610 | "MANUAL HIGH\n"); | ||
611 | break; | ||
612 | case ATH5K_ANI_MODE_AUTO: | ||
613 | len += snprintf(buf+len, sizeof(buf)-len, "AUTO\n"); | ||
614 | break; | ||
615 | default: | ||
616 | len += snprintf(buf+len, sizeof(buf)-len, | ||
617 | "??? (not good)\n"); | ||
618 | break; | ||
619 | } | ||
620 | len += snprintf(buf+len, sizeof(buf)-len, | ||
621 | "noise immunity level:\t\t%d\n", | ||
622 | as->noise_imm_level); | ||
623 | len += snprintf(buf+len, sizeof(buf)-len, | ||
624 | "spur immunity level:\t\t%d\n", | ||
625 | as->spur_level); | ||
626 | len += snprintf(buf+len, sizeof(buf)-len, "firstep level:\t\t\t%d\n", | ||
627 | as->firstep_level); | ||
628 | len += snprintf(buf+len, sizeof(buf)-len, | ||
629 | "OFDM weak signal detection:\t%s\n", | ||
630 | as->ofdm_weak_sig ? "on" : "off"); | ||
631 | len += snprintf(buf+len, sizeof(buf)-len, | ||
632 | "CCK weak signal detection:\t%s\n", | ||
633 | as->cck_weak_sig ? "on" : "off"); | ||
634 | |||
635 | len += snprintf(buf+len, sizeof(buf)-len, | ||
636 | "\nMIB INTERRUPTS:\t\t%u\n", | ||
637 | st->mib_intr); | ||
638 | len += snprintf(buf+len, sizeof(buf)-len, | ||
639 | "beacon RSSI average:\t%d\n", | ||
640 | sc->ah->ah_beacon_rssi_avg.avg); | ||
641 | len += snprintf(buf+len, sizeof(buf)-len, "profcnt tx\t\t%u\t(%d%%)\n", | ||
642 | as->pfc_tx, | ||
643 | as->pfc_cycles > 0 ? | ||
644 | as->pfc_tx*100/as->pfc_cycles : 0); | ||
645 | len += snprintf(buf+len, sizeof(buf)-len, "profcnt rx\t\t%u\t(%d%%)\n", | ||
646 | as->pfc_rx, | ||
647 | as->pfc_cycles > 0 ? | ||
648 | as->pfc_rx*100/as->pfc_cycles : 0); | ||
649 | len += snprintf(buf+len, sizeof(buf)-len, "profcnt busy\t\t%u\t(%d%%)\n", | ||
650 | as->pfc_busy, | ||
651 | as->pfc_cycles > 0 ? | ||
652 | as->pfc_busy*100/as->pfc_cycles : 0); | ||
653 | len += snprintf(buf+len, sizeof(buf)-len, "profcnt cycles\t\t%u\n", | ||
654 | as->pfc_cycles); | ||
655 | len += snprintf(buf+len, sizeof(buf)-len, | ||
656 | "listen time\t\t%d\tlast: %d\n", | ||
657 | as->listen_time, as->last_listen); | ||
658 | len += snprintf(buf+len, sizeof(buf)-len, | ||
659 | "OFDM errors\t\t%u\tlast: %u\tsum: %u\n", | ||
660 | as->ofdm_errors, as->last_ofdm_errors, | ||
661 | as->sum_ofdm_errors); | ||
662 | len += snprintf(buf+len, sizeof(buf)-len, | ||
663 | "CCK errors\t\t%u\tlast: %u\tsum: %u\n", | ||
664 | as->cck_errors, as->last_cck_errors, | ||
665 | as->sum_cck_errors); | ||
666 | len += snprintf(buf+len, sizeof(buf)-len, | ||
667 | "AR5K_PHYERR_CNT1\t%x\t(=%d)\n", | ||
668 | ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT1), | ||
669 | ATH5K_ANI_OFDM_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX - | ||
670 | ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT1))); | ||
671 | len += snprintf(buf+len, sizeof(buf)-len, | ||
672 | "AR5K_PHYERR_CNT2\t%x\t(=%d)\n", | ||
673 | ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT2), | ||
674 | ATH5K_ANI_CCK_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX - | ||
675 | ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT2))); | ||
676 | |||
677 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
678 | } | ||
679 | |||
680 | static ssize_t write_file_ani(struct file *file, | ||
681 | const char __user *userbuf, | ||
682 | size_t count, loff_t *ppos) | ||
683 | { | ||
684 | struct ath5k_softc *sc = file->private_data; | ||
685 | char buf[20]; | ||
686 | |||
687 | if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) | ||
688 | return -EFAULT; | ||
689 | |||
690 | if (strncmp(buf, "sens-low", 8) == 0) { | ||
691 | ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_MANUAL_HIGH); | ||
692 | } else if (strncmp(buf, "sens-high", 9) == 0) { | ||
693 | ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_MANUAL_LOW); | ||
694 | } else if (strncmp(buf, "ani-off", 7) == 0) { | ||
695 | ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_OFF); | ||
696 | } else if (strncmp(buf, "ani-on", 6) == 0) { | ||
697 | ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_AUTO); | ||
698 | } else if (strncmp(buf, "noise-low", 9) == 0) { | ||
699 | ath5k_ani_set_noise_immunity_level(sc->ah, 0); | ||
700 | } else if (strncmp(buf, "noise-high", 10) == 0) { | ||
701 | ath5k_ani_set_noise_immunity_level(sc->ah, | ||
702 | ATH5K_ANI_MAX_NOISE_IMM_LVL); | ||
703 | } else if (strncmp(buf, "spur-low", 8) == 0) { | ||
704 | ath5k_ani_set_spur_immunity_level(sc->ah, 0); | ||
705 | } else if (strncmp(buf, "spur-high", 9) == 0) { | ||
706 | ath5k_ani_set_spur_immunity_level(sc->ah, | ||
707 | sc->ani_state.max_spur_level); | ||
708 | } else if (strncmp(buf, "fir-low", 7) == 0) { | ||
709 | ath5k_ani_set_firstep_level(sc->ah, 0); | ||
710 | } else if (strncmp(buf, "fir-high", 8) == 0) { | ||
711 | ath5k_ani_set_firstep_level(sc->ah, ATH5K_ANI_MAX_FIRSTEP_LVL); | ||
712 | } else if (strncmp(buf, "ofdm-off", 8) == 0) { | ||
713 | ath5k_ani_set_ofdm_weak_signal_detection(sc->ah, false); | ||
714 | } else if (strncmp(buf, "ofdm-on", 7) == 0) { | ||
715 | ath5k_ani_set_ofdm_weak_signal_detection(sc->ah, true); | ||
716 | } else if (strncmp(buf, "cck-off", 7) == 0) { | ||
717 | ath5k_ani_set_cck_weak_signal_detection(sc->ah, false); | ||
718 | } else if (strncmp(buf, "cck-on", 6) == 0) { | ||
719 | ath5k_ani_set_cck_weak_signal_detection(sc->ah, true); | ||
720 | } | ||
721 | return count; | ||
722 | } | ||
723 | |||
724 | static const struct file_operations fops_ani = { | ||
725 | .read = read_file_ani, | ||
726 | .write = write_file_ani, | ||
727 | .open = ath5k_debugfs_open, | ||
728 | .owner = THIS_MODULE, | ||
729 | }; | ||
730 | |||
731 | |||
367 | /* init */ | 732 | /* init */ |
368 | 733 | ||
369 | void | 734 | void |
@@ -393,6 +758,20 @@ ath5k_debug_init_device(struct ath5k_softc *sc) | |||
393 | 758 | ||
394 | sc->debug.debugfs_reset = debugfs_create_file("reset", S_IWUSR, | 759 | sc->debug.debugfs_reset = debugfs_create_file("reset", S_IWUSR, |
395 | sc->debug.debugfs_phydir, sc, &fops_reset); | 760 | sc->debug.debugfs_phydir, sc, &fops_reset); |
761 | |||
762 | sc->debug.debugfs_antenna = debugfs_create_file("antenna", | ||
763 | S_IWUSR | S_IRUSR, | ||
764 | sc->debug.debugfs_phydir, sc, &fops_antenna); | ||
765 | |||
766 | sc->debug.debugfs_frameerrors = debugfs_create_file("frameerrors", | ||
767 | S_IWUSR | S_IRUSR, | ||
768 | sc->debug.debugfs_phydir, sc, | ||
769 | &fops_frameerrors); | ||
770 | |||
771 | sc->debug.debugfs_ani = debugfs_create_file("ani", | ||
772 | S_IWUSR | S_IRUSR, | ||
773 | sc->debug.debugfs_phydir, sc, | ||
774 | &fops_ani); | ||
396 | } | 775 | } |
397 | 776 | ||
398 | void | 777 | void |
@@ -408,6 +787,9 @@ ath5k_debug_finish_device(struct ath5k_softc *sc) | |||
408 | debugfs_remove(sc->debug.debugfs_registers); | 787 | debugfs_remove(sc->debug.debugfs_registers); |
409 | debugfs_remove(sc->debug.debugfs_beacon); | 788 | debugfs_remove(sc->debug.debugfs_beacon); |
410 | debugfs_remove(sc->debug.debugfs_reset); | 789 | debugfs_remove(sc->debug.debugfs_reset); |
790 | debugfs_remove(sc->debug.debugfs_antenna); | ||
791 | debugfs_remove(sc->debug.debugfs_frameerrors); | ||
792 | debugfs_remove(sc->debug.debugfs_ani); | ||
411 | debugfs_remove(sc->debug.debugfs_phydir); | 793 | debugfs_remove(sc->debug.debugfs_phydir); |
412 | } | 794 | } |
413 | 795 | ||
diff --git a/drivers/net/wireless/ath/ath5k/debug.h b/drivers/net/wireless/ath/ath5k/debug.h index 66f69f04e55e..ddd5b3a99e8d 100644 --- a/drivers/net/wireless/ath/ath5k/debug.h +++ b/drivers/net/wireless/ath/ath5k/debug.h | |||
@@ -74,6 +74,9 @@ struct ath5k_dbg_info { | |||
74 | struct dentry *debugfs_registers; | 74 | struct dentry *debugfs_registers; |
75 | struct dentry *debugfs_beacon; | 75 | struct dentry *debugfs_beacon; |
76 | struct dentry *debugfs_reset; | 76 | struct dentry *debugfs_reset; |
77 | struct dentry *debugfs_antenna; | ||
78 | struct dentry *debugfs_frameerrors; | ||
79 | struct dentry *debugfs_ani; | ||
77 | }; | 80 | }; |
78 | 81 | ||
79 | /** | 82 | /** |
@@ -113,6 +116,7 @@ enum ath5k_debug_level { | |||
113 | ATH5K_DEBUG_DUMP_TX = 0x00000200, | 116 | ATH5K_DEBUG_DUMP_TX = 0x00000200, |
114 | ATH5K_DEBUG_DUMPBANDS = 0x00000400, | 117 | ATH5K_DEBUG_DUMPBANDS = 0x00000400, |
115 | ATH5K_DEBUG_TRACE = 0x00001000, | 118 | ATH5K_DEBUG_TRACE = 0x00001000, |
119 | ATH5K_DEBUG_ANI = 0x00002000, | ||
116 | ATH5K_DEBUG_ANY = 0xffffffff | 120 | ATH5K_DEBUG_ANY = 0xffffffff |
117 | }; | 121 | }; |
118 | 122 | ||
diff --git a/drivers/net/wireless/ath/ath5k/desc.c b/drivers/net/wireless/ath/ath5k/desc.c index dc30a2b70a6b..7d7b646ab65a 100644 --- a/drivers/net/wireless/ath/ath5k/desc.c +++ b/drivers/net/wireless/ath/ath5k/desc.c | |||
@@ -35,7 +35,8 @@ | |||
35 | */ | 35 | */ |
36 | static int | 36 | static int |
37 | ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | 37 | ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, |
38 | unsigned int pkt_len, unsigned int hdr_len, enum ath5k_pkt_type type, | 38 | unsigned int pkt_len, unsigned int hdr_len, int padsize, |
39 | enum ath5k_pkt_type type, | ||
39 | unsigned int tx_power, unsigned int tx_rate0, unsigned int tx_tries0, | 40 | unsigned int tx_power, unsigned int tx_rate0, unsigned int tx_tries0, |
40 | unsigned int key_index, unsigned int antenna_mode, unsigned int flags, | 41 | unsigned int key_index, unsigned int antenna_mode, unsigned int flags, |
41 | unsigned int rtscts_rate, unsigned int rtscts_duration) | 42 | unsigned int rtscts_rate, unsigned int rtscts_duration) |
@@ -71,7 +72,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
71 | /* Verify and set frame length */ | 72 | /* Verify and set frame length */ |
72 | 73 | ||
73 | /* remove padding we might have added before */ | 74 | /* remove padding we might have added before */ |
74 | frame_len = pkt_len - ath5k_pad_size(hdr_len) + FCS_LEN; | 75 | frame_len = pkt_len - padsize + FCS_LEN; |
75 | 76 | ||
76 | if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN) | 77 | if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN) |
77 | return -EINVAL; | 78 | return -EINVAL; |
@@ -100,7 +101,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
100 | AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN); | 101 | AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN); |
101 | } | 102 | } |
102 | 103 | ||
103 | /*Diferences between 5210-5211*/ | 104 | /*Differences between 5210-5211*/ |
104 | if (ah->ah_version == AR5K_AR5210) { | 105 | if (ah->ah_version == AR5K_AR5210) { |
105 | switch (type) { | 106 | switch (type) { |
106 | case AR5K_PKT_TYPE_BEACON: | 107 | case AR5K_PKT_TYPE_BEACON: |
@@ -165,6 +166,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
165 | */ | 166 | */ |
166 | static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, | 167 | static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, |
167 | struct ath5k_desc *desc, unsigned int pkt_len, unsigned int hdr_len, | 168 | struct ath5k_desc *desc, unsigned int pkt_len, unsigned int hdr_len, |
169 | int padsize, | ||
168 | enum ath5k_pkt_type type, unsigned int tx_power, unsigned int tx_rate0, | 170 | enum ath5k_pkt_type type, unsigned int tx_power, unsigned int tx_rate0, |
169 | unsigned int tx_tries0, unsigned int key_index, | 171 | unsigned int tx_tries0, unsigned int key_index, |
170 | unsigned int antenna_mode, unsigned int flags, | 172 | unsigned int antenna_mode, unsigned int flags, |
@@ -206,7 +208,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, | |||
206 | /* Verify and set frame length */ | 208 | /* Verify and set frame length */ |
207 | 209 | ||
208 | /* remove padding we might have added before */ | 210 | /* remove padding we might have added before */ |
209 | frame_len = pkt_len - ath5k_pad_size(hdr_len) + FCS_LEN; | 211 | frame_len = pkt_len - padsize + FCS_LEN; |
210 | 212 | ||
211 | if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN) | 213 | if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN) |
212 | return -EINVAL; | 214 | return -EINVAL; |
@@ -229,7 +231,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, | |||
229 | AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT); | 231 | AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT); |
230 | tx_ctl->tx_control_1 |= AR5K_REG_SM(type, | 232 | tx_ctl->tx_control_1 |= AR5K_REG_SM(type, |
231 | AR5K_4W_TX_DESC_CTL1_FRAME_TYPE); | 233 | AR5K_4W_TX_DESC_CTL1_FRAME_TYPE); |
232 | tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES, | 234 | tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0, |
233 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0); | 235 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0); |
234 | tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; | 236 | tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; |
235 | 237 | ||
@@ -643,6 +645,7 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, | |||
643 | rs->rs_status |= AR5K_RXERR_PHY; | 645 | rs->rs_status |= AR5K_RXERR_PHY; |
644 | rs->rs_phyerr |= AR5K_REG_MS(rx_err->rx_error_1, | 646 | rs->rs_phyerr |= AR5K_REG_MS(rx_err->rx_error_1, |
645 | AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE); | 647 | AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE); |
648 | ath5k_ani_phy_error_report(ah, rs->rs_phyerr); | ||
646 | } | 649 | } |
647 | 650 | ||
648 | if (rx_status->rx_status_1 & | 651 | if (rx_status->rx_status_1 & |
@@ -668,12 +671,6 @@ int ath5k_hw_init_desc_functions(struct ath5k_hw *ah) | |||
668 | ah->ah_version != AR5K_AR5212) | 671 | ah->ah_version != AR5K_AR5212) |
669 | return -ENOTSUPP; | 672 | return -ENOTSUPP; |
670 | 673 | ||
671 | /* XXX: What is this magic value and where is it used ? */ | ||
672 | if (ah->ah_version == AR5K_AR5212) | ||
673 | ah->ah_magic = AR5K_EEPROM_MAGIC_5212; | ||
674 | else if (ah->ah_version == AR5K_AR5211) | ||
675 | ah->ah_magic = AR5K_EEPROM_MAGIC_5211; | ||
676 | |||
677 | if (ah->ah_version == AR5K_AR5212) { | 674 | if (ah->ah_version == AR5K_AR5212) { |
678 | ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc; | 675 | ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc; |
679 | ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc; | 676 | ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc; |
diff --git a/drivers/net/wireless/ath/ath5k/desc.h b/drivers/net/wireless/ath/ath5k/desc.h index 56158c804e3e..64538fbe4167 100644 --- a/drivers/net/wireless/ath/ath5k/desc.h +++ b/drivers/net/wireless/ath/ath5k/desc.h | |||
@@ -112,15 +112,32 @@ struct ath5k_hw_rx_error { | |||
112 | #define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE 0x0000ff00 | 112 | #define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE 0x0000ff00 |
113 | #define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE_S 8 | 113 | #define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE_S 8 |
114 | 114 | ||
115 | /* PHY Error codes */ | 115 | /** |
116 | #define AR5K_DESC_RX_PHY_ERROR_NONE 0x00 | 116 | * enum ath5k_phy_error_code - PHY Error codes |
117 | #define AR5K_DESC_RX_PHY_ERROR_TIMING 0x20 | 117 | */ |
118 | #define AR5K_DESC_RX_PHY_ERROR_PARITY 0x40 | 118 | enum ath5k_phy_error_code { |
119 | #define AR5K_DESC_RX_PHY_ERROR_RATE 0x60 | 119 | AR5K_RX_PHY_ERROR_UNDERRUN = 0, /* Transmit underrun */ |
120 | #define AR5K_DESC_RX_PHY_ERROR_LENGTH 0x80 | 120 | AR5K_RX_PHY_ERROR_TIMING = 1, /* Timing error */ |
121 | #define AR5K_DESC_RX_PHY_ERROR_64QAM 0xa0 | 121 | AR5K_RX_PHY_ERROR_PARITY = 2, /* Illegal parity */ |
122 | #define AR5K_DESC_RX_PHY_ERROR_SERVICE 0xc0 | 122 | AR5K_RX_PHY_ERROR_RATE = 3, /* Illegal rate */ |
123 | #define AR5K_DESC_RX_PHY_ERROR_TRANSMITOVR 0xe0 | 123 | AR5K_RX_PHY_ERROR_LENGTH = 4, /* Illegal length */ |
124 | AR5K_RX_PHY_ERROR_RADAR = 5, /* Radar detect */ | ||
125 | AR5K_RX_PHY_ERROR_SERVICE = 6, /* Illegal service */ | ||
126 | AR5K_RX_PHY_ERROR_TOR = 7, /* Transmit override receive */ | ||
127 | /* these are specific to the 5212 */ | ||
128 | AR5K_RX_PHY_ERROR_OFDM_TIMING = 17, | ||
129 | AR5K_RX_PHY_ERROR_OFDM_SIGNAL_PARITY = 18, | ||
130 | AR5K_RX_PHY_ERROR_OFDM_RATE_ILLEGAL = 19, | ||
131 | AR5K_RX_PHY_ERROR_OFDM_LENGTH_ILLEGAL = 20, | ||
132 | AR5K_RX_PHY_ERROR_OFDM_POWER_DROP = 21, | ||
133 | AR5K_RX_PHY_ERROR_OFDM_SERVICE = 22, | ||
134 | AR5K_RX_PHY_ERROR_OFDM_RESTART = 23, | ||
135 | AR5K_RX_PHY_ERROR_CCK_TIMING = 25, | ||
136 | AR5K_RX_PHY_ERROR_CCK_HEADER_CRC = 26, | ||
137 | AR5K_RX_PHY_ERROR_CCK_RATE_ILLEGAL = 27, | ||
138 | AR5K_RX_PHY_ERROR_CCK_SERVICE = 30, | ||
139 | AR5K_RX_PHY_ERROR_CCK_RESTART = 31, | ||
140 | }; | ||
124 | 141 | ||
125 | /* | 142 | /* |
126 | * 5210/5211 hardware 2-word TX control descriptor | 143 | * 5210/5211 hardware 2-word TX control descriptor |
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index 10b52262b232..a3cbfe4fc389 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c | |||
@@ -329,7 +329,8 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset, | |||
329 | ee->ee_x_gain[mode] = (val >> 1) & 0xf; | 329 | ee->ee_x_gain[mode] = (val >> 1) & 0xf; |
330 | ee->ee_xpd[mode] = val & 0x1; | 330 | ee->ee_xpd[mode] = val & 0x1; |
331 | 331 | ||
332 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) | 332 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0 && |
333 | mode != AR5K_EEPROM_MODE_11B) | ||
333 | ee->ee_fixed_bias[mode] = (val >> 13) & 0x1; | 334 | ee->ee_fixed_bias[mode] = (val >> 13) & 0x1; |
334 | 335 | ||
335 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_3) { | 336 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_3) { |
@@ -339,6 +340,7 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset, | |||
339 | if (mode == AR5K_EEPROM_MODE_11A) | 340 | if (mode == AR5K_EEPROM_MODE_11A) |
340 | ee->ee_xr_power[mode] = val & 0x3f; | 341 | ee->ee_xr_power[mode] = val & 0x3f; |
341 | else { | 342 | else { |
343 | /* b_DB_11[bg] and b_OB_11[bg] */ | ||
342 | ee->ee_ob[mode][0] = val & 0x7; | 344 | ee->ee_ob[mode][0] = val & 0x7; |
343 | ee->ee_db[mode][0] = (val >> 3) & 0x7; | 345 | ee->ee_db[mode][0] = (val >> 3) & 0x7; |
344 | } | 346 | } |
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h index 473a483bb9c3..c4a6d5f26af4 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.h +++ b/drivers/net/wireless/ath/ath5k/eeprom.h | |||
@@ -24,9 +24,6 @@ | |||
24 | * SERDES infos are present */ | 24 | * SERDES infos are present */ |
25 | #define AR5K_EEPROM_MAGIC 0x003d /* EEPROM Magic number */ | 25 | #define AR5K_EEPROM_MAGIC 0x003d /* EEPROM Magic number */ |
26 | #define AR5K_EEPROM_MAGIC_VALUE 0x5aa5 /* Default - found on EEPROM */ | 26 | #define AR5K_EEPROM_MAGIC_VALUE 0x5aa5 /* Default - found on EEPROM */ |
27 | #define AR5K_EEPROM_MAGIC_5212 0x0000145c /* 5212 */ | ||
28 | #define AR5K_EEPROM_MAGIC_5211 0x0000145b /* 5211 */ | ||
29 | #define AR5K_EEPROM_MAGIC_5210 0x0000145a /* 5210 */ | ||
30 | 27 | ||
31 | #define AR5K_EEPROM_IS_HB63 0x000b /* Talon detect */ | 28 | #define AR5K_EEPROM_IS_HB63 0x000b /* Talon detect */ |
32 | 29 | ||
@@ -78,9 +75,9 @@ | |||
78 | #define AR5K_EEPROM_HDR_11A(_v) (((_v) >> AR5K_EEPROM_MODE_11A) & 0x1) | 75 | #define AR5K_EEPROM_HDR_11A(_v) (((_v) >> AR5K_EEPROM_MODE_11A) & 0x1) |
79 | #define AR5K_EEPROM_HDR_11B(_v) (((_v) >> AR5K_EEPROM_MODE_11B) & 0x1) | 76 | #define AR5K_EEPROM_HDR_11B(_v) (((_v) >> AR5K_EEPROM_MODE_11B) & 0x1) |
80 | #define AR5K_EEPROM_HDR_11G(_v) (((_v) >> AR5K_EEPROM_MODE_11G) & 0x1) | 77 | #define AR5K_EEPROM_HDR_11G(_v) (((_v) >> AR5K_EEPROM_MODE_11G) & 0x1) |
81 | #define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v) (((_v) >> 3) & 0x1) /* Disable turbo for 2Ghz (?) */ | 78 | #define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v) (((_v) >> 3) & 0x1) /* Disable turbo for 2Ghz */ |
82 | #define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v) (((_v) >> 4) & 0x7f) /* Max turbo power for a/XR mode (eeprom_init) */ | 79 | #define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v) (((_v) >> 4) & 0x7f) /* Max turbo power for < 2W power consumption */ |
83 | #define AR5K_EEPROM_HDR_DEVICE(_v) (((_v) >> 11) & 0x7) | 80 | #define AR5K_EEPROM_HDR_DEVICE(_v) (((_v) >> 11) & 0x7) /* Device type (1 Cardbus, 2 PCI, 3 MiniPCI, 4 AP) */ |
84 | #define AR5K_EEPROM_HDR_RFKILL(_v) (((_v) >> 14) & 0x1) /* Device has RFKill support */ | 81 | #define AR5K_EEPROM_HDR_RFKILL(_v) (((_v) >> 14) & 0x1) /* Device has RFKill support */ |
85 | #define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v) (((_v) >> 15) & 0x1) /* Disable turbo for 5Ghz */ | 82 | #define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v) (((_v) >> 15) & 0x1) /* Disable turbo for 5Ghz */ |
86 | 83 | ||
@@ -101,7 +98,7 @@ | |||
101 | 98 | ||
102 | #define AR5K_EEPROM_MISC1 AR5K_EEPROM_INFO(5) | 99 | #define AR5K_EEPROM_MISC1 AR5K_EEPROM_INFO(5) |
103 | #define AR5K_EEPROM_TARGET_PWRSTART(_v) ((_v) & 0xfff) | 100 | #define AR5K_EEPROM_TARGET_PWRSTART(_v) ((_v) & 0xfff) |
104 | #define AR5K_EEPROM_HAS32KHZCRYSTAL(_v) (((_v) >> 14) & 0x1) | 101 | #define AR5K_EEPROM_HAS32KHZCRYSTAL(_v) (((_v) >> 14) & 0x1) /* has 32KHz crystal for sleep mode */ |
105 | #define AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(_v) (((_v) >> 15) & 0x1) | 102 | #define AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(_v) (((_v) >> 15) & 0x1) |
106 | 103 | ||
107 | #define AR5K_EEPROM_MISC2 AR5K_EEPROM_INFO(6) | 104 | #define AR5K_EEPROM_MISC2 AR5K_EEPROM_INFO(6) |
@@ -114,26 +111,27 @@ | |||
114 | 111 | ||
115 | #define AR5K_EEPROM_MISC4 AR5K_EEPROM_INFO(8) | 112 | #define AR5K_EEPROM_MISC4 AR5K_EEPROM_INFO(8) |
116 | #define AR5K_EEPROM_CAL_DATA_START(_v) (((_v) >> 4) & 0xfff) | 113 | #define AR5K_EEPROM_CAL_DATA_START(_v) (((_v) >> 4) & 0xfff) |
117 | #define AR5K_EEPROM_MASK_R0(_v) (((_v) >> 2) & 0x3) | 114 | #define AR5K_EEPROM_MASK_R0(_v) (((_v) >> 2) & 0x3) /* modes supported by radio 0 (bit 1: G, bit 2: A) */ |
118 | #define AR5K_EEPROM_MASK_R1(_v) ((_v) & 0x3) | 115 | #define AR5K_EEPROM_MASK_R1(_v) ((_v) & 0x3) /* modes supported by radio 1 (bit 1: G, bit 2: A) */ |
119 | 116 | ||
120 | #define AR5K_EEPROM_MISC5 AR5K_EEPROM_INFO(9) | 117 | #define AR5K_EEPROM_MISC5 AR5K_EEPROM_INFO(9) |
121 | #define AR5K_EEPROM_COMP_DIS(_v) ((_v) & 0x1) | 118 | #define AR5K_EEPROM_COMP_DIS(_v) ((_v) & 0x1) /* disable compression */ |
122 | #define AR5K_EEPROM_AES_DIS(_v) (((_v) >> 1) & 0x1) | 119 | #define AR5K_EEPROM_AES_DIS(_v) (((_v) >> 1) & 0x1) /* disable AES */ |
123 | #define AR5K_EEPROM_FF_DIS(_v) (((_v) >> 2) & 0x1) | 120 | #define AR5K_EEPROM_FF_DIS(_v) (((_v) >> 2) & 0x1) /* disable fast frames */ |
124 | #define AR5K_EEPROM_BURST_DIS(_v) (((_v) >> 3) & 0x1) | 121 | #define AR5K_EEPROM_BURST_DIS(_v) (((_v) >> 3) & 0x1) /* disable bursting */ |
125 | #define AR5K_EEPROM_MAX_QCU(_v) (((_v) >> 4) & 0xf) | 122 | #define AR5K_EEPROM_MAX_QCU(_v) (((_v) >> 4) & 0xf) /* max number of QCUs. defaults to 10 */ |
126 | #define AR5K_EEPROM_HEAVY_CLIP_EN(_v) (((_v) >> 8) & 0x1) | 123 | #define AR5K_EEPROM_HEAVY_CLIP_EN(_v) (((_v) >> 8) & 0x1) /* enable heayy clipping */ |
127 | #define AR5K_EEPROM_KEY_CACHE_SIZE(_v) (((_v) >> 12) & 0xf) | 124 | #define AR5K_EEPROM_KEY_CACHE_SIZE(_v) (((_v) >> 12) & 0xf) /* key cache size. defaults to 128 */ |
128 | 125 | ||
129 | #define AR5K_EEPROM_MISC6 AR5K_EEPROM_INFO(10) | 126 | #define AR5K_EEPROM_MISC6 AR5K_EEPROM_INFO(10) |
130 | #define AR5K_EEPROM_TX_CHAIN_DIS ((_v) & 0x8) | 127 | #define AR5K_EEPROM_TX_CHAIN_DIS ((_v) & 0x7) /* MIMO chains disabled for TX bitmask */ |
131 | #define AR5K_EEPROM_RX_CHAIN_DIS (((_v) >> 3) & 0x8) | 128 | #define AR5K_EEPROM_RX_CHAIN_DIS (((_v) >> 3) & 0x7) /* MIMO chains disabled for RX bitmask */ |
132 | #define AR5K_EEPROM_FCC_MID_EN (((_v) >> 6) & 0x1) | 129 | #define AR5K_EEPROM_FCC_MID_EN (((_v) >> 6) & 0x1) /* 5.47-5.7GHz supported */ |
133 | #define AR5K_EEPROM_JAP_U1EVEN_EN (((_v) >> 7) & 0x1) | 130 | #define AR5K_EEPROM_JAP_U1EVEN_EN (((_v) >> 7) & 0x1) /* Japan UNII1 band (5.15-5.25GHz) on even channels (5180, 5200, 5220, 5240) supported */ |
134 | #define AR5K_EEPROM_JAP_U2_EN (((_v) >> 8) & 0x1) | 131 | #define AR5K_EEPROM_JAP_U2_EN (((_v) >> 8) & 0x1) /* Japan UNII2 band (5.25-5.35GHz) supported */ |
135 | #define AR5K_EEPROM_JAP_U1ODD_EN (((_v) >> 9) & 0x1) | 132 | #define AR5K_EEPROM_JAP_MID_EN (((_v) >> 9) & 0x1) /* Japan band from 5.47-5.7GHz supported */ |
136 | #define AR5K_EEPROM_JAP_11A_NEW_EN (((_v) >> 10) & 0x1) | 133 | #define AR5K_EEPROM_JAP_U1ODD_EN (((_v) >> 10) & 0x1) /* Japan UNII2 band (5.15-5.25GHz) on odd channels (5170, 5190, 5210, 5230) supported */ |
134 | #define AR5K_EEPROM_JAP_11A_NEW_EN (((_v) >> 11) & 0x1) /* Japan A mode enabled (using even channels) */ | ||
137 | 135 | ||
138 | /* calibration settings */ | 136 | /* calibration settings */ |
139 | #define AR5K_EEPROM_MODES_11A(_v) AR5K_EEPROM_OFF(_v, 0x00c5, 0x00d4) | 137 | #define AR5K_EEPROM_MODES_11A(_v) AR5K_EEPROM_OFF(_v, 0x00c5, 0x00d4) |
@@ -389,7 +387,49 @@ struct ath5k_edge_power { | |||
389 | bool flag; | 387 | bool flag; |
390 | }; | 388 | }; |
391 | 389 | ||
392 | /* EEPROM calibration data */ | 390 | /** |
391 | * struct ath5k_eeprom_info - EEPROM calibration data | ||
392 | * | ||
393 | * @ee_regdomain: ath/regd.c takes care of COUNTRY_ERD and WORLDWIDE_ROAMING | ||
394 | * flags | ||
395 | * @ee_ant_gain: Antenna gain in 0.5dB steps signed [5211 only?] | ||
396 | * @ee_cck_ofdm_gain_delta: difference in gainF to output the same power for | ||
397 | * OFDM and CCK packets | ||
398 | * @ee_cck_ofdm_power_delta: power difference between OFDM (6Mbps) and CCK | ||
399 | * (11Mbps) rate in G mode. 0.1dB steps | ||
400 | * @ee_scaled_cck_delta: for Japan Channel 14: 0.1dB resolution | ||
401 | * | ||
402 | * @ee_i_cal: Initial I coefficient to correct I/Q mismatch in the receive path | ||
403 | * @ee_q_cal: Initial Q coefficient to correct I/Q mismatch in the receive path | ||
404 | * @ee_fixed_bias: use ee_ob and ee_db settings or use automatic control | ||
405 | * @ee_switch_settling: RX/TX Switch settling time | ||
406 | * @ee_atn_tx_rx: Difference in attenuation between TX and RX in 1dB steps | ||
407 | * @ee_ant_control: Antenna Control Settings | ||
408 | * @ee_ob: Bias current for Output stage of PA | ||
409 | * B/G mode: Index [0] is used for AR2112/5112, otherwise [1] | ||
410 | * A mode: [0] 5.15-5.25 [1] 5.25-5.50 [2] 5.50-5.70 [3] 5.70-5.85 GHz | ||
411 | * @ee_db: Bias current for Output stage of PA. see @ee_ob | ||
412 | * @ee_tx_end2xlna_enable: Time difference from when BB finishes sending a frame | ||
413 | * to when the external LNA is activated | ||
414 | * @ee_tx_end2xpa_disable: Time difference from when BB finishes sending a frame | ||
415 | * to when the external PA switch is deactivated | ||
416 | * @ee_tx_frm2xpa_enable: Time difference from when MAC sends frame to when | ||
417 | * external PA switch is activated | ||
418 | * @ee_thr_62: Clear Channel Assessment (CCA) sensitivity | ||
419 | * (IEEE802.11a section 17.3.10.5 ) | ||
420 | * @ee_xlna_gain: Total gain of the LNA (information only) | ||
421 | * @ee_xpd: Use external (1) or internal power detector | ||
422 | * @ee_x_gain: Gain for external power detector output (differences in EEMAP | ||
423 | * versions!) | ||
424 | * @ee_i_gain: Initial gain value after reset | ||
425 | * @ee_margin_tx_rx: Margin in dB when final attenuation stage should be used | ||
426 | * | ||
427 | * @ee_false_detect: Backoff in Sensitivity (dB) on channels with spur signals | ||
428 | * @ee_noise_floor_thr: Noise floor threshold in 1dB steps | ||
429 | * @ee_adc_desired_size: Desired amplitude for ADC, used by AGC; in 0.5 dB steps | ||
430 | * @ee_pga_desired_size: Desired output of PGA (for BB gain) in 0.5 dB steps | ||
431 | * @ee_pd_gain_overlap: PD ADC curves need to overlap in 0.5dB steps (ee_map>=2) | ||
432 | */ | ||
393 | struct ath5k_eeprom_info { | 433 | struct ath5k_eeprom_info { |
394 | 434 | ||
395 | /* Header information */ | 435 | /* Header information */ |
diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index aefe84f9c04b..710870ea179b 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c | |||
@@ -39,16 +39,16 @@ | |||
39 | * ath5k_hw_set_opmode - Set PCU operating mode | 39 | * ath5k_hw_set_opmode - Set PCU operating mode |
40 | * | 40 | * |
41 | * @ah: The &struct ath5k_hw | 41 | * @ah: The &struct ath5k_hw |
42 | * @op_mode: &enum nl80211_iftype operating mode | ||
42 | * | 43 | * |
43 | * Initialize PCU for the various operating modes (AP/STA etc) | 44 | * Initialize PCU for the various operating modes (AP/STA etc) |
44 | * | ||
45 | * NOTE: ah->ah_op_mode must be set before calling this. | ||
46 | */ | 45 | */ |
47 | int ath5k_hw_set_opmode(struct ath5k_hw *ah) | 46 | int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode) |
48 | { | 47 | { |
49 | struct ath_common *common = ath5k_hw_common(ah); | 48 | struct ath_common *common = ath5k_hw_common(ah); |
50 | u32 pcu_reg, beacon_reg, low_id, high_id; | 49 | u32 pcu_reg, beacon_reg, low_id, high_id; |
51 | 50 | ||
51 | ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_MODE, "mode %d\n", op_mode); | ||
52 | 52 | ||
53 | /* Preserve rest settings */ | 53 | /* Preserve rest settings */ |
54 | pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000; | 54 | pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000; |
@@ -61,7 +61,7 @@ int ath5k_hw_set_opmode(struct ath5k_hw *ah) | |||
61 | 61 | ||
62 | ATH5K_TRACE(ah->ah_sc); | 62 | ATH5K_TRACE(ah->ah_sc); |
63 | 63 | ||
64 | switch (ah->ah_op_mode) { | 64 | switch (op_mode) { |
65 | case NL80211_IFTYPE_ADHOC: | 65 | case NL80211_IFTYPE_ADHOC: |
66 | pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE; | 66 | pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE; |
67 | beacon_reg |= AR5K_BCR_ADHOC; | 67 | beacon_reg |= AR5K_BCR_ADHOC; |
@@ -113,39 +113,26 @@ int ath5k_hw_set_opmode(struct ath5k_hw *ah) | |||
113 | } | 113 | } |
114 | 114 | ||
115 | /** | 115 | /** |
116 | * ath5k_hw_update - Update mib counters (mac layer statistics) | 116 | * ath5k_hw_update - Update MIB counters (mac layer statistics) |
117 | * | 117 | * |
118 | * @ah: The &struct ath5k_hw | 118 | * @ah: The &struct ath5k_hw |
119 | * @stats: The &struct ieee80211_low_level_stats we use to track | ||
120 | * statistics on the driver | ||
121 | * | 119 | * |
122 | * Reads MIB counters from PCU and updates sw statistics. Must be | 120 | * Reads MIB counters from PCU and updates sw statistics. Is called after a |
123 | * called after a MIB interrupt. | 121 | * MIB interrupt, because one of these counters might have reached their maximum |
122 | * and triggered the MIB interrupt, to let us read and clear the counter. | ||
123 | * | ||
124 | * Is called in interrupt context! | ||
124 | */ | 125 | */ |
125 | void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, | 126 | void ath5k_hw_update_mib_counters(struct ath5k_hw *ah) |
126 | struct ieee80211_low_level_stats *stats) | ||
127 | { | 127 | { |
128 | ATH5K_TRACE(ah->ah_sc); | 128 | struct ath5k_statistics *stats = &ah->ah_sc->stats; |
129 | 129 | ||
130 | /* Read-And-Clear */ | 130 | /* Read-And-Clear */ |
131 | stats->dot11ACKFailureCount += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL); | 131 | stats->ack_fail += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL); |
132 | stats->dot11RTSFailureCount += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL); | 132 | stats->rts_fail += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL); |
133 | stats->dot11RTSSuccessCount += ath5k_hw_reg_read(ah, AR5K_RTS_OK); | 133 | stats->rts_ok += ath5k_hw_reg_read(ah, AR5K_RTS_OK); |
134 | stats->dot11FCSErrorCount += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL); | 134 | stats->fcs_error += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL); |
135 | 135 | stats->beacons += ath5k_hw_reg_read(ah, AR5K_BEACON_CNT); | |
136 | /* XXX: Should we use this to track beacon count ? | ||
137 | * -we read it anyway to clear the register */ | ||
138 | ath5k_hw_reg_read(ah, AR5K_BEACON_CNT); | ||
139 | |||
140 | /* Reset profile count registers on 5212*/ | ||
141 | if (ah->ah_version == AR5K_AR5212) { | ||
142 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_TX); | ||
143 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RX); | ||
144 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR); | ||
145 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE); | ||
146 | } | ||
147 | |||
148 | /* TODO: Handle ANI stats */ | ||
149 | } | 136 | } |
150 | 137 | ||
151 | /** | 138 | /** |
@@ -179,25 +166,12 @@ void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high) | |||
179 | \******************/ | 166 | \******************/ |
180 | 167 | ||
181 | /** | 168 | /** |
182 | * ath5k_hw_het_ack_timeout - Get ACK timeout from PCU in usec | ||
183 | * | ||
184 | * @ah: The &struct ath5k_hw | ||
185 | */ | ||
186 | unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah) | ||
187 | { | ||
188 | ATH5K_TRACE(ah->ah_sc); | ||
189 | |||
190 | return ath5k_hw_clocktoh(ah, AR5K_REG_MS(ath5k_hw_reg_read(ah, | ||
191 | AR5K_TIME_OUT), AR5K_TIME_OUT_ACK)); | ||
192 | } | ||
193 | |||
194 | /** | ||
195 | * ath5k_hw_set_ack_timeout - Set ACK timeout on PCU | 169 | * ath5k_hw_set_ack_timeout - Set ACK timeout on PCU |
196 | * | 170 | * |
197 | * @ah: The &struct ath5k_hw | 171 | * @ah: The &struct ath5k_hw |
198 | * @timeout: Timeout in usec | 172 | * @timeout: Timeout in usec |
199 | */ | 173 | */ |
200 | int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) | 174 | static int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) |
201 | { | 175 | { |
202 | ATH5K_TRACE(ah->ah_sc); | 176 | ATH5K_TRACE(ah->ah_sc); |
203 | if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK)) | 177 | if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK)) |
@@ -211,24 +185,12 @@ int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) | |||
211 | } | 185 | } |
212 | 186 | ||
213 | /** | 187 | /** |
214 | * ath5k_hw_get_cts_timeout - Get CTS timeout from PCU in usec | ||
215 | * | ||
216 | * @ah: The &struct ath5k_hw | ||
217 | */ | ||
218 | unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah) | ||
219 | { | ||
220 | ATH5K_TRACE(ah->ah_sc); | ||
221 | return ath5k_hw_clocktoh(ah, AR5K_REG_MS(ath5k_hw_reg_read(ah, | ||
222 | AR5K_TIME_OUT), AR5K_TIME_OUT_CTS)); | ||
223 | } | ||
224 | |||
225 | /** | ||
226 | * ath5k_hw_set_cts_timeout - Set CTS timeout on PCU | 188 | * ath5k_hw_set_cts_timeout - Set CTS timeout on PCU |
227 | * | 189 | * |
228 | * @ah: The &struct ath5k_hw | 190 | * @ah: The &struct ath5k_hw |
229 | * @timeout: Timeout in usec | 191 | * @timeout: Timeout in usec |
230 | */ | 192 | */ |
231 | int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) | 193 | static int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) |
232 | { | 194 | { |
233 | ATH5K_TRACE(ah->ah_sc); | 195 | ATH5K_TRACE(ah->ah_sc); |
234 | if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS)) | 196 | if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS)) |
@@ -290,7 +252,7 @@ unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah) | |||
290 | * | 252 | * |
291 | * @ah: The &struct ath5k_hw | 253 | * @ah: The &struct ath5k_hw |
292 | */ | 254 | */ |
293 | unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah) | 255 | static unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah) |
294 | { | 256 | { |
295 | struct ieee80211_channel *channel = ah->ah_current_channel; | 257 | struct ieee80211_channel *channel = ah->ah_current_channel; |
296 | 258 | ||
@@ -308,7 +270,7 @@ unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah) | |||
308 | * | 270 | * |
309 | * @ah: The &struct ath5k_hw | 271 | * @ah: The &struct ath5k_hw |
310 | */ | 272 | */ |
311 | unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah) | 273 | static unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah) |
312 | { | 274 | { |
313 | struct ieee80211_channel *channel = ah->ah_current_channel; | 275 | struct ieee80211_channel *channel = ah->ah_current_channel; |
314 | 276 | ||
@@ -417,7 +379,6 @@ void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask) | |||
417 | * (ACK etc). | 379 | * (ACK etc). |
418 | * | 380 | * |
419 | * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma | 381 | * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma |
420 | * TODO: Init ANI here | ||
421 | */ | 382 | */ |
422 | void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah) | 383 | void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah) |
423 | { | 384 | { |
@@ -451,42 +412,6 @@ void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1) | |||
451 | ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1); | 412 | ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1); |
452 | } | 413 | } |
453 | 414 | ||
454 | /* | ||
455 | * Set multicast filter by index | ||
456 | */ | ||
457 | int ath5k_hw_set_mcast_filter_idx(struct ath5k_hw *ah, u32 index) | ||
458 | { | ||
459 | |||
460 | ATH5K_TRACE(ah->ah_sc); | ||
461 | if (index >= 64) | ||
462 | return -EINVAL; | ||
463 | else if (index >= 32) | ||
464 | AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER1, | ||
465 | (1 << (index - 32))); | ||
466 | else | ||
467 | AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index)); | ||
468 | |||
469 | return 0; | ||
470 | } | ||
471 | |||
472 | /* | ||
473 | * Clear Multicast filter by index | ||
474 | */ | ||
475 | int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index) | ||
476 | { | ||
477 | |||
478 | ATH5K_TRACE(ah->ah_sc); | ||
479 | if (index >= 64) | ||
480 | return -EINVAL; | ||
481 | else if (index >= 32) | ||
482 | AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER1, | ||
483 | (1 << (index - 32))); | ||
484 | else | ||
485 | AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index)); | ||
486 | |||
487 | return 0; | ||
488 | } | ||
489 | |||
490 | /** | 415 | /** |
491 | * ath5k_hw_get_rx_filter - Get current rx filter | 416 | * ath5k_hw_get_rx_filter - Get current rx filter |
492 | * | 417 | * |
@@ -572,19 +497,6 @@ void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter) | |||
572 | \****************/ | 497 | \****************/ |
573 | 498 | ||
574 | /** | 499 | /** |
575 | * ath5k_hw_get_tsf32 - Get a 32bit TSF | ||
576 | * | ||
577 | * @ah: The &struct ath5k_hw | ||
578 | * | ||
579 | * Returns lower 32 bits of current TSF | ||
580 | */ | ||
581 | u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah) | ||
582 | { | ||
583 | ATH5K_TRACE(ah->ah_sc); | ||
584 | return ath5k_hw_reg_read(ah, AR5K_TSF_L32); | ||
585 | } | ||
586 | |||
587 | /** | ||
588 | * ath5k_hw_get_tsf64 - Get the full 64bit TSF | 500 | * ath5k_hw_get_tsf64 - Get the full 64bit TSF |
589 | * | 501 | * |
590 | * @ah: The &struct ath5k_hw | 502 | * @ah: The &struct ath5k_hw |
@@ -651,7 +563,7 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) | |||
651 | /* | 563 | /* |
652 | * Set the additional timers by mode | 564 | * Set the additional timers by mode |
653 | */ | 565 | */ |
654 | switch (ah->ah_op_mode) { | 566 | switch (ah->ah_sc->opmode) { |
655 | case NL80211_IFTYPE_MONITOR: | 567 | case NL80211_IFTYPE_MONITOR: |
656 | case NL80211_IFTYPE_STATION: | 568 | case NL80211_IFTYPE_STATION: |
657 | /* In STA mode timer1 is used as next wakeup | 569 | /* In STA mode timer1 is used as next wakeup |
@@ -688,8 +600,8 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) | |||
688 | * Set the beacon register and enable all timers. | 600 | * Set the beacon register and enable all timers. |
689 | */ | 601 | */ |
690 | /* When in AP or Mesh Point mode zero timer0 to start TSF */ | 602 | /* When in AP or Mesh Point mode zero timer0 to start TSF */ |
691 | if (ah->ah_op_mode == NL80211_IFTYPE_AP || | 603 | if (ah->ah_sc->opmode == NL80211_IFTYPE_AP || |
692 | ah->ah_op_mode == NL80211_IFTYPE_MESH_POINT) | 604 | ah->ah_sc->opmode == NL80211_IFTYPE_MESH_POINT) |
693 | ath5k_hw_reg_write(ah, 0, AR5K_TIMER0); | 605 | ath5k_hw_reg_write(ah, 0, AR5K_TIMER0); |
694 | 606 | ||
695 | ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0); | 607 | ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0); |
@@ -722,203 +634,6 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) | |||
722 | 634 | ||
723 | } | 635 | } |
724 | 636 | ||
725 | #if 0 | ||
726 | /* | ||
727 | * Set beacon timers | ||
728 | */ | ||
729 | int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah, | ||
730 | const struct ath5k_beacon_state *state) | ||
731 | { | ||
732 | u32 cfp_period, next_cfp, dtim, interval, next_beacon; | ||
733 | |||
734 | /* | ||
735 | * TODO: should be changed through *state | ||
736 | * review struct ath5k_beacon_state struct | ||
737 | * | ||
738 | * XXX: These are used for cfp period bellow, are they | ||
739 | * ok ? Is it O.K. for tsf here to be 0 or should we use | ||
740 | * get_tsf ? | ||
741 | */ | ||
742 | u32 dtim_count = 0; /* XXX */ | ||
743 | u32 cfp_count = 0; /* XXX */ | ||
744 | u32 tsf = 0; /* XXX */ | ||
745 | |||
746 | ATH5K_TRACE(ah->ah_sc); | ||
747 | /* Return on an invalid beacon state */ | ||
748 | if (state->bs_interval < 1) | ||
749 | return -EINVAL; | ||
750 | |||
751 | interval = state->bs_interval; | ||
752 | dtim = state->bs_dtim_period; | ||
753 | |||
754 | /* | ||
755 | * PCF support? | ||
756 | */ | ||
757 | if (state->bs_cfp_period > 0) { | ||
758 | /* | ||
759 | * Enable PCF mode and set the CFP | ||
760 | * (Contention Free Period) and timer registers | ||
761 | */ | ||
762 | cfp_period = state->bs_cfp_period * state->bs_dtim_period * | ||
763 | state->bs_interval; | ||
764 | next_cfp = (cfp_count * state->bs_dtim_period + dtim_count) * | ||
765 | state->bs_interval; | ||
766 | |||
767 | AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, | ||
768 | AR5K_STA_ID1_DEFAULT_ANTENNA | | ||
769 | AR5K_STA_ID1_PCF); | ||
770 | ath5k_hw_reg_write(ah, cfp_period, AR5K_CFP_PERIOD); | ||
771 | ath5k_hw_reg_write(ah, state->bs_cfp_max_duration, | ||
772 | AR5K_CFP_DUR); | ||
773 | ath5k_hw_reg_write(ah, (tsf + (next_cfp == 0 ? cfp_period : | ||
774 | next_cfp)) << 3, AR5K_TIMER2); | ||
775 | } else { | ||
776 | /* Disable PCF mode */ | ||
777 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, | ||
778 | AR5K_STA_ID1_DEFAULT_ANTENNA | | ||
779 | AR5K_STA_ID1_PCF); | ||
780 | } | ||
781 | |||
782 | /* | ||
783 | * Enable the beacon timer register | ||
784 | */ | ||
785 | ath5k_hw_reg_write(ah, state->bs_next_beacon, AR5K_TIMER0); | ||
786 | |||
787 | /* | ||
788 | * Start the beacon timers | ||
789 | */ | ||
790 | ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, AR5K_BEACON) & | ||
791 | ~(AR5K_BEACON_PERIOD | AR5K_BEACON_TIM)) | | ||
792 | AR5K_REG_SM(state->bs_tim_offset ? state->bs_tim_offset + 4 : 0, | ||
793 | AR5K_BEACON_TIM) | AR5K_REG_SM(state->bs_interval, | ||
794 | AR5K_BEACON_PERIOD), AR5K_BEACON); | ||
795 | |||
796 | /* | ||
797 | * Write new beacon miss threshold, if it appears to be valid | ||
798 | * XXX: Figure out right values for min <= bs_bmiss_threshold <= max | ||
799 | * and return if its not in range. We can test this by reading value and | ||
800 | * setting value to a largest value and seeing which values register. | ||
801 | */ | ||
802 | |||
803 | AR5K_REG_WRITE_BITS(ah, AR5K_RSSI_THR, AR5K_RSSI_THR_BMISS, | ||
804 | state->bs_bmiss_threshold); | ||
805 | |||
806 | /* | ||
807 | * Set sleep control register | ||
808 | * XXX: Didn't find this in 5210 code but since this register | ||
809 | * exists also in ar5k's 5210 headers i leave it as common code. | ||
810 | */ | ||
811 | AR5K_REG_WRITE_BITS(ah, AR5K_SLEEP_CTL, AR5K_SLEEP_CTL_SLDUR, | ||
812 | (state->bs_sleep_duration - 3) << 3); | ||
813 | |||
814 | /* | ||
815 | * Set enhanced sleep registers on 5212 | ||
816 | */ | ||
817 | if (ah->ah_version == AR5K_AR5212) { | ||
818 | if (state->bs_sleep_duration > state->bs_interval && | ||
819 | roundup(state->bs_sleep_duration, interval) == | ||
820 | state->bs_sleep_duration) | ||
821 | interval = state->bs_sleep_duration; | ||
822 | |||
823 | if (state->bs_sleep_duration > dtim && (dtim == 0 || | ||
824 | roundup(state->bs_sleep_duration, dtim) == | ||
825 | state->bs_sleep_duration)) | ||
826 | dtim = state->bs_sleep_duration; | ||
827 | |||
828 | if (interval > dtim) | ||
829 | return -EINVAL; | ||
830 | |||
831 | next_beacon = interval == dtim ? state->bs_next_dtim : | ||
832 | state->bs_next_beacon; | ||
833 | |||
834 | ath5k_hw_reg_write(ah, | ||
835 | AR5K_REG_SM((state->bs_next_dtim - 3) << 3, | ||
836 | AR5K_SLEEP0_NEXT_DTIM) | | ||
837 | AR5K_REG_SM(10, AR5K_SLEEP0_CABTO) | | ||
838 | AR5K_SLEEP0_ENH_SLEEP_EN | | ||
839 | AR5K_SLEEP0_ASSUME_DTIM, AR5K_SLEEP0); | ||
840 | |||
841 | ath5k_hw_reg_write(ah, AR5K_REG_SM((next_beacon - 3) << 3, | ||
842 | AR5K_SLEEP1_NEXT_TIM) | | ||
843 | AR5K_REG_SM(10, AR5K_SLEEP1_BEACON_TO), AR5K_SLEEP1); | ||
844 | |||
845 | ath5k_hw_reg_write(ah, | ||
846 | AR5K_REG_SM(interval, AR5K_SLEEP2_TIM_PER) | | ||
847 | AR5K_REG_SM(dtim, AR5K_SLEEP2_DTIM_PER), AR5K_SLEEP2); | ||
848 | } | ||
849 | |||
850 | return 0; | ||
851 | } | ||
852 | |||
853 | /* | ||
854 | * Reset beacon timers | ||
855 | */ | ||
856 | void ath5k_hw_reset_beacon(struct ath5k_hw *ah) | ||
857 | { | ||
858 | ATH5K_TRACE(ah->ah_sc); | ||
859 | /* | ||
860 | * Disable beacon timer | ||
861 | */ | ||
862 | ath5k_hw_reg_write(ah, 0, AR5K_TIMER0); | ||
863 | |||
864 | /* | ||
865 | * Disable some beacon register values | ||
866 | */ | ||
867 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, | ||
868 | AR5K_STA_ID1_DEFAULT_ANTENNA | AR5K_STA_ID1_PCF); | ||
869 | ath5k_hw_reg_write(ah, AR5K_BEACON_PERIOD, AR5K_BEACON); | ||
870 | } | ||
871 | |||
872 | /* | ||
873 | * Wait for beacon queue to finish | ||
874 | */ | ||
875 | int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr) | ||
876 | { | ||
877 | unsigned int i; | ||
878 | int ret; | ||
879 | |||
880 | ATH5K_TRACE(ah->ah_sc); | ||
881 | |||
882 | /* 5210 doesn't have QCU*/ | ||
883 | if (ah->ah_version == AR5K_AR5210) { | ||
884 | /* | ||
885 | * Wait for beaconn queue to finish by checking | ||
886 | * Control Register and Beacon Status Register. | ||
887 | */ | ||
888 | for (i = AR5K_TUNE_BEACON_INTERVAL / 2; i > 0; i--) { | ||
889 | if (!(ath5k_hw_reg_read(ah, AR5K_BSR) & AR5K_BSR_TXQ1F) | ||
890 | || | ||
891 | !(ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_BSR_TXQ1F)) | ||
892 | break; | ||
893 | udelay(10); | ||
894 | } | ||
895 | |||
896 | /* Timeout... */ | ||
897 | if (i <= 0) { | ||
898 | /* | ||
899 | * Re-schedule the beacon queue | ||
900 | */ | ||
901 | ath5k_hw_reg_write(ah, phys_addr, AR5K_NOQCU_TXDP1); | ||
902 | ath5k_hw_reg_write(ah, AR5K_BCR_TQ1V | AR5K_BCR_BDMAE, | ||
903 | AR5K_BCR); | ||
904 | |||
905 | return -EIO; | ||
906 | } | ||
907 | ret = 0; | ||
908 | } else { | ||
909 | /*5211/5212*/ | ||
910 | ret = ath5k_hw_register_timeout(ah, | ||
911 | AR5K_QUEUE_STATUS(AR5K_TX_QUEUE_ID_BEACON), | ||
912 | AR5K_QCU_STS_FRMPENDCNT, 0, false); | ||
913 | |||
914 | if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, AR5K_TX_QUEUE_ID_BEACON)) | ||
915 | return -EIO; | ||
916 | } | ||
917 | |||
918 | return ret; | ||
919 | } | ||
920 | #endif | ||
921 | |||
922 | 637 | ||
923 | /*********************\ | 638 | /*********************\ |
924 | * Key table functions * | 639 | * Key table functions * |
@@ -971,19 +686,6 @@ int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry) | |||
971 | return 0; | 686 | return 0; |
972 | } | 687 | } |
973 | 688 | ||
974 | /* | ||
975 | * Check if a table entry is valid | ||
976 | */ | ||
977 | int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry) | ||
978 | { | ||
979 | ATH5K_TRACE(ah->ah_sc); | ||
980 | AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); | ||
981 | |||
982 | /* Check the validation flag at the end of the entry */ | ||
983 | return ath5k_hw_reg_read(ah, AR5K_KEYTABLE_MAC1(entry)) & | ||
984 | AR5K_KEYTABLE_VALID; | ||
985 | } | ||
986 | |||
987 | static | 689 | static |
988 | int ath5k_keycache_type(const struct ieee80211_key_conf *key) | 690 | int ath5k_keycache_type(const struct ieee80211_key_conf *key) |
989 | { | 691 | { |
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index eff3323efb4b..b6704c93f808 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c | |||
@@ -20,8 +20,6 @@ | |||
20 | * | 20 | * |
21 | */ | 21 | */ |
22 | 22 | ||
23 | #define _ATH5K_PHY | ||
24 | |||
25 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
26 | 24 | ||
27 | #include "ath5k.h" | 25 | #include "ath5k.h" |
@@ -1104,28 +1102,6 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) | |||
1104 | PHY calibration | 1102 | PHY calibration |
1105 | \*****************/ | 1103 | \*****************/ |
1106 | 1104 | ||
1107 | void | ||
1108 | ath5k_hw_calibration_poll(struct ath5k_hw *ah) | ||
1109 | { | ||
1110 | /* Calibration interval in jiffies */ | ||
1111 | unsigned long cal_intval; | ||
1112 | |||
1113 | cal_intval = msecs_to_jiffies(ah->ah_cal_intval * 1000); | ||
1114 | |||
1115 | /* Initialize timestamp if needed */ | ||
1116 | if (!ah->ah_cal_tstamp) | ||
1117 | ah->ah_cal_tstamp = jiffies; | ||
1118 | |||
1119 | /* For now we always do full calibration | ||
1120 | * Mark software interrupt mask and fire software | ||
1121 | * interrupt (bit gets auto-cleared) */ | ||
1122 | if (time_is_before_eq_jiffies(ah->ah_cal_tstamp + cal_intval)) { | ||
1123 | ah->ah_cal_tstamp = jiffies; | ||
1124 | ah->ah_swi_mask = AR5K_SWI_FULL_CALIBRATION; | ||
1125 | AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); | ||
1126 | } | ||
1127 | } | ||
1128 | |||
1129 | static int sign_extend(int val, const int nbits) | 1105 | static int sign_extend(int val, const int nbits) |
1130 | { | 1106 | { |
1131 | int order = BIT(nbits-1); | 1107 | int order = BIT(nbits-1); |
@@ -1190,7 +1166,7 @@ static s16 ath5k_hw_get_median_noise_floor(struct ath5k_hw *ah) | |||
1190 | * The median of the values in the history is then loaded into the | 1166 | * The median of the values in the history is then loaded into the |
1191 | * hardware for its own use for RSSI and CCA measurements. | 1167 | * hardware for its own use for RSSI and CCA measurements. |
1192 | */ | 1168 | */ |
1193 | void ath5k_hw_update_noise_floor(struct ath5k_hw *ah) | 1169 | static void ath5k_hw_update_noise_floor(struct ath5k_hw *ah) |
1194 | { | 1170 | { |
1195 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | 1171 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; |
1196 | u32 val; | 1172 | u32 val; |
@@ -1399,7 +1375,11 @@ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah, | |||
1399 | } | 1375 | } |
1400 | 1376 | ||
1401 | i_coffd = ((i_pwr >> 1) + (q_pwr >> 1)) >> 7; | 1377 | i_coffd = ((i_pwr >> 1) + (q_pwr >> 1)) >> 7; |
1402 | q_coffd = q_pwr >> 7; | 1378 | |
1379 | if (ah->ah_version == AR5K_AR5211) | ||
1380 | q_coffd = q_pwr >> 6; | ||
1381 | else | ||
1382 | q_coffd = q_pwr >> 7; | ||
1403 | 1383 | ||
1404 | /* protect against divide by 0 and loss of sign bits */ | 1384 | /* protect against divide by 0 and loss of sign bits */ |
1405 | if (i_coffd == 0 || q_coffd < 2) | 1385 | if (i_coffd == 0 || q_coffd < 2) |
@@ -1768,7 +1748,7 @@ u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan) | |||
1768 | * Antenna control * | 1748 | * Antenna control * |
1769 | \*****************/ | 1749 | \*****************/ |
1770 | 1750 | ||
1771 | void /*TODO:Boundary check*/ | 1751 | static void /*TODO:Boundary check*/ |
1772 | ath5k_hw_set_def_antenna(struct ath5k_hw *ah, u8 ant) | 1752 | ath5k_hw_set_def_antenna(struct ath5k_hw *ah, u8 ant) |
1773 | { | 1753 | { |
1774 | ATH5K_TRACE(ah->ah_sc); | 1754 | ATH5K_TRACE(ah->ah_sc); |
@@ -1777,16 +1757,6 @@ ath5k_hw_set_def_antenna(struct ath5k_hw *ah, u8 ant) | |||
1777 | ath5k_hw_reg_write(ah, ant & 0x7, AR5K_DEFAULT_ANTENNA); | 1757 | ath5k_hw_reg_write(ah, ant & 0x7, AR5K_DEFAULT_ANTENNA); |
1778 | } | 1758 | } |
1779 | 1759 | ||
1780 | unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah) | ||
1781 | { | ||
1782 | ATH5K_TRACE(ah->ah_sc); | ||
1783 | |||
1784 | if (ah->ah_version != AR5K_AR5210) | ||
1785 | return ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA) & 0x7; | ||
1786 | |||
1787 | return false; /*XXX: What do we return for 5210 ?*/ | ||
1788 | } | ||
1789 | |||
1790 | /* | 1760 | /* |
1791 | * Enable/disable fast rx antenna diversity | 1761 | * Enable/disable fast rx antenna diversity |
1792 | */ | 1762 | */ |
@@ -1930,6 +1900,7 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) | |||
1930 | 1900 | ||
1931 | ah->ah_tx_ant = tx_ant; | 1901 | ah->ah_tx_ant = tx_ant; |
1932 | ah->ah_ant_mode = ant_mode; | 1902 | ah->ah_ant_mode = ant_mode; |
1903 | ah->ah_def_ant = def_ant; | ||
1933 | 1904 | ||
1934 | sta_id1 |= use_def_for_tx ? AR5K_STA_ID1_DEFAULT_ANTENNA : 0; | 1905 | sta_id1 |= use_def_for_tx ? AR5K_STA_ID1_DEFAULT_ANTENNA : 0; |
1935 | sta_id1 |= update_def_on_tx ? AR5K_STA_ID1_DESC_ANTENNA : 0; | 1906 | sta_id1 |= update_def_on_tx ? AR5K_STA_ID1_DESC_ANTENNA : 0; |
@@ -2440,19 +2411,6 @@ ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min, | |||
2440 | pcdac_tmp = pcdac_high_pwr; | 2411 | pcdac_tmp = pcdac_high_pwr; |
2441 | 2412 | ||
2442 | edge_flag = 0x40; | 2413 | edge_flag = 0x40; |
2443 | #if 0 | ||
2444 | /* If both min and max power limits are in lower | ||
2445 | * power curve's range, only use the low power curve. | ||
2446 | * TODO: min/max levels are related to target | ||
2447 | * power values requested from driver/user | ||
2448 | * XXX: Is this really needed ? */ | ||
2449 | if (min_pwr < table_max[1] && | ||
2450 | max_pwr < table_max[1]) { | ||
2451 | edge_flag = 0; | ||
2452 | pcdac_tmp = pcdac_low_pwr; | ||
2453 | max_pwr_idx = (table_max[1] - table_min[1])/2; | ||
2454 | } | ||
2455 | #endif | ||
2456 | } else { | 2414 | } else { |
2457 | pcdac_low_pwr = ah->ah_txpower.tmpL[1]; /* Zeroed */ | 2415 | pcdac_low_pwr = ah->ah_txpower.tmpL[1]; /* Zeroed */ |
2458 | pcdac_high_pwr = ah->ah_txpower.tmpL[0]; | 2416 | pcdac_high_pwr = ah->ah_txpower.tmpL[0]; |
@@ -3143,5 +3101,3 @@ int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower) | |||
3143 | 3101 | ||
3144 | return ath5k_hw_txpower(ah, channel, ee_mode, txpower); | 3102 | return ath5k_hw_txpower(ah, channel, ee_mode, txpower); |
3145 | } | 3103 | } |
3146 | |||
3147 | #undef _ATH5K_PHY | ||
diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c index 9122a8556f45..f5831da33f7b 100644 --- a/drivers/net/wireless/ath/ath5k/qcu.c +++ b/drivers/net/wireless/ath/ath5k/qcu.c | |||
@@ -517,23 +517,6 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | |||
517 | } | 517 | } |
518 | 518 | ||
519 | /* | 519 | /* |
520 | * Get slot time from DCU | ||
521 | */ | ||
522 | unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah) | ||
523 | { | ||
524 | unsigned int slot_time_clock; | ||
525 | |||
526 | ATH5K_TRACE(ah->ah_sc); | ||
527 | |||
528 | if (ah->ah_version == AR5K_AR5210) | ||
529 | slot_time_clock = ath5k_hw_reg_read(ah, AR5K_SLOT_TIME); | ||
530 | else | ||
531 | slot_time_clock = ath5k_hw_reg_read(ah, AR5K_DCU_GBL_IFS_SLOT); | ||
532 | |||
533 | return ath5k_hw_clocktoh(ah, slot_time_clock & 0xffff); | ||
534 | } | ||
535 | |||
536 | /* | ||
537 | * Set slot time on DCU | 520 | * Set slot time on DCU |
538 | */ | 521 | */ |
539 | int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time) | 522 | int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time) |
diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h index 1464f89b249c..45d62e915e4c 100644 --- a/drivers/net/wireless/ath/ath5k/reg.h +++ b/drivers/net/wireless/ath/ath5k/reg.h | |||
@@ -212,10 +212,10 @@ | |||
212 | * MIB control register | 212 | * MIB control register |
213 | */ | 213 | */ |
214 | #define AR5K_MIBC 0x0040 /* Register Address */ | 214 | #define AR5K_MIBC 0x0040 /* Register Address */ |
215 | #define AR5K_MIBC_COW 0x00000001 /* Warn test indicator */ | 215 | #define AR5K_MIBC_COW 0x00000001 /* Counter Overflow Warning */ |
216 | #define AR5K_MIBC_FMC 0x00000002 /* Freeze MIB Counters */ | 216 | #define AR5K_MIBC_FMC 0x00000002 /* Freeze MIB Counters */ |
217 | #define AR5K_MIBC_CMC 0x00000004 /* Clean MIB Counters */ | 217 | #define AR5K_MIBC_CMC 0x00000004 /* Clear MIB Counters */ |
218 | #define AR5K_MIBC_MCS 0x00000008 /* MIB counter strobe */ | 218 | #define AR5K_MIBC_MCS 0x00000008 /* MIB counter strobe, increment all */ |
219 | 219 | ||
220 | /* | 220 | /* |
221 | * Timeout prescale register | 221 | * Timeout prescale register |
@@ -1516,7 +1516,14 @@ | |||
1516 | AR5K_NAV_5210 : AR5K_NAV_5211) | 1516 | AR5K_NAV_5210 : AR5K_NAV_5211) |
1517 | 1517 | ||
1518 | /* | 1518 | /* |
1519 | * RTS success register | 1519 | * MIB counters: |
1520 | * | ||
1521 | * max value is 0xc000, if this is reached we get a MIB interrupt. | ||
1522 | * they can be controlled via AR5K_MIBC and are cleared on read. | ||
1523 | */ | ||
1524 | |||
1525 | /* | ||
1526 | * RTS success (MIB counter) | ||
1520 | */ | 1527 | */ |
1521 | #define AR5K_RTS_OK_5210 0x8090 | 1528 | #define AR5K_RTS_OK_5210 0x8090 |
1522 | #define AR5K_RTS_OK_5211 0x8088 | 1529 | #define AR5K_RTS_OK_5211 0x8088 |
@@ -1524,7 +1531,7 @@ | |||
1524 | AR5K_RTS_OK_5210 : AR5K_RTS_OK_5211) | 1531 | AR5K_RTS_OK_5210 : AR5K_RTS_OK_5211) |
1525 | 1532 | ||
1526 | /* | 1533 | /* |
1527 | * RTS failure register | 1534 | * RTS failure (MIB counter) |
1528 | */ | 1535 | */ |
1529 | #define AR5K_RTS_FAIL_5210 0x8094 | 1536 | #define AR5K_RTS_FAIL_5210 0x8094 |
1530 | #define AR5K_RTS_FAIL_5211 0x808c | 1537 | #define AR5K_RTS_FAIL_5211 0x808c |
@@ -1532,7 +1539,7 @@ | |||
1532 | AR5K_RTS_FAIL_5210 : AR5K_RTS_FAIL_5211) | 1539 | AR5K_RTS_FAIL_5210 : AR5K_RTS_FAIL_5211) |
1533 | 1540 | ||
1534 | /* | 1541 | /* |
1535 | * ACK failure register | 1542 | * ACK failure (MIB counter) |
1536 | */ | 1543 | */ |
1537 | #define AR5K_ACK_FAIL_5210 0x8098 | 1544 | #define AR5K_ACK_FAIL_5210 0x8098 |
1538 | #define AR5K_ACK_FAIL_5211 0x8090 | 1545 | #define AR5K_ACK_FAIL_5211 0x8090 |
@@ -1540,7 +1547,7 @@ | |||
1540 | AR5K_ACK_FAIL_5210 : AR5K_ACK_FAIL_5211) | 1547 | AR5K_ACK_FAIL_5210 : AR5K_ACK_FAIL_5211) |
1541 | 1548 | ||
1542 | /* | 1549 | /* |
1543 | * FCS failure register | 1550 | * FCS failure (MIB counter) |
1544 | */ | 1551 | */ |
1545 | #define AR5K_FCS_FAIL_5210 0x809c | 1552 | #define AR5K_FCS_FAIL_5210 0x809c |
1546 | #define AR5K_FCS_FAIL_5211 0x8094 | 1553 | #define AR5K_FCS_FAIL_5211 0x8094 |
@@ -1667,11 +1674,17 @@ | |||
1667 | 1674 | ||
1668 | /* | 1675 | /* |
1669 | * Profile count registers | 1676 | * Profile count registers |
1677 | * | ||
1678 | * These registers can be cleared and freezed with ATH5K_MIBC, but they do not | ||
1679 | * generate a MIB interrupt. | ||
1680 | * Instead of overflowing, they shift by one bit to the right. All registers | ||
1681 | * shift together, i.e. when one reaches the max, all shift at the same time by | ||
1682 | * one bit to the right. This way we should always get consistent values. | ||
1670 | */ | 1683 | */ |
1671 | #define AR5K_PROFCNT_TX 0x80ec /* Tx count */ | 1684 | #define AR5K_PROFCNT_TX 0x80ec /* Tx count */ |
1672 | #define AR5K_PROFCNT_RX 0x80f0 /* Rx count */ | 1685 | #define AR5K_PROFCNT_RX 0x80f0 /* Rx count */ |
1673 | #define AR5K_PROFCNT_RXCLR 0x80f4 /* Clear Rx count */ | 1686 | #define AR5K_PROFCNT_RXCLR 0x80f4 /* Busy count */ |
1674 | #define AR5K_PROFCNT_CYCLE 0x80f8 /* Cycle count (?) */ | 1687 | #define AR5K_PROFCNT_CYCLE 0x80f8 /* Cycle counter */ |
1675 | 1688 | ||
1676 | /* | 1689 | /* |
1677 | * Quiet period control registers | 1690 | * Quiet period control registers |
@@ -1758,7 +1771,7 @@ | |||
1758 | #define AR5K_CCK_FIL_CNT 0x8128 | 1771 | #define AR5K_CCK_FIL_CNT 0x8128 |
1759 | 1772 | ||
1760 | /* | 1773 | /* |
1761 | * PHY Error Counters (?) | 1774 | * PHY Error Counters (same masks as AR5K_PHY_ERR_FIL) |
1762 | */ | 1775 | */ |
1763 | #define AR5K_PHYERR_CNT1 0x812c | 1776 | #define AR5K_PHYERR_CNT1 0x812c |
1764 | #define AR5K_PHYERR_CNT1_MASK 0x8130 | 1777 | #define AR5K_PHYERR_CNT1_MASK 0x8130 |
@@ -1766,6 +1779,9 @@ | |||
1766 | #define AR5K_PHYERR_CNT2 0x8134 | 1779 | #define AR5K_PHYERR_CNT2 0x8134 |
1767 | #define AR5K_PHYERR_CNT2_MASK 0x8138 | 1780 | #define AR5K_PHYERR_CNT2_MASK 0x8138 |
1768 | 1781 | ||
1782 | /* if the PHY Error Counters reach this maximum, we get MIB interrupts */ | ||
1783 | #define ATH5K_PHYERR_CNT_MAX 0x00c00000 | ||
1784 | |||
1769 | /* | 1785 | /* |
1770 | * TSF Threshold register (?) | 1786 | * TSF Threshold register (?) |
1771 | */ | 1787 | */ |
@@ -1974,7 +1990,7 @@ | |||
1974 | #define AR5K_PHY_SETTLING 0x9844 /* Register Address */ | 1990 | #define AR5K_PHY_SETTLING 0x9844 /* Register Address */ |
1975 | #define AR5K_PHY_SETTLING_AGC 0x0000007f /* AGC settling time */ | 1991 | #define AR5K_PHY_SETTLING_AGC 0x0000007f /* AGC settling time */ |
1976 | #define AR5K_PHY_SETTLING_AGC_S 0 | 1992 | #define AR5K_PHY_SETTLING_AGC_S 0 |
1977 | #define AR5K_PHY_SETTLING_SWITCH 0x00003f80 /* Switch settlig time */ | 1993 | #define AR5K_PHY_SETTLING_SWITCH 0x00003f80 /* Switch settling time */ |
1978 | #define AR5K_PHY_SETTLING_SWITCH_S 7 | 1994 | #define AR5K_PHY_SETTLING_SWITCH_S 7 |
1979 | 1995 | ||
1980 | /* | 1996 | /* |
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index cbf28e379843..44bbbf2a6edd 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c | |||
@@ -19,8 +19,6 @@ | |||
19 | * | 19 | * |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #define _ATH5K_RESET | ||
23 | |||
24 | /*****************************\ | 22 | /*****************************\ |
25 | Reset functions and helpers | 23 | Reset functions and helpers |
26 | \*****************************/ | 24 | \*****************************/ |
@@ -34,6 +32,27 @@ | |||
34 | #include "base.h" | 32 | #include "base.h" |
35 | #include "debug.h" | 33 | #include "debug.h" |
36 | 34 | ||
35 | /* | ||
36 | * Check if a register write has been completed | ||
37 | */ | ||
38 | int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, | ||
39 | bool is_set) | ||
40 | { | ||
41 | int i; | ||
42 | u32 data; | ||
43 | |||
44 | for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) { | ||
45 | data = ath5k_hw_reg_read(ah, reg); | ||
46 | if (is_set && (data & flag)) | ||
47 | break; | ||
48 | else if ((data & flag) == val) | ||
49 | break; | ||
50 | udelay(15); | ||
51 | } | ||
52 | |||
53 | return (i <= 0) ? -EAGAIN : 0; | ||
54 | } | ||
55 | |||
37 | /** | 56 | /** |
38 | * ath5k_hw_write_ofdm_timings - set OFDM timings on AR5212 | 57 | * ath5k_hw_write_ofdm_timings - set OFDM timings on AR5212 |
39 | * | 58 | * |
@@ -221,8 +240,8 @@ static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val) | |||
221 | /* | 240 | /* |
222 | * Sleep control | 241 | * Sleep control |
223 | */ | 242 | */ |
224 | int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, | 243 | static int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, |
225 | bool set_chip, u16 sleep_duration) | 244 | bool set_chip, u16 sleep_duration) |
226 | { | 245 | { |
227 | unsigned int i; | 246 | unsigned int i; |
228 | u32 staid, data; | 247 | u32 staid, data; |
@@ -1017,11 +1036,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1017 | if (ret) | 1036 | if (ret) |
1018 | return ret; | 1037 | return ret; |
1019 | 1038 | ||
1020 | /* | ||
1021 | * Initialize operating mode | ||
1022 | */ | ||
1023 | ah->ah_op_mode = op_mode; | ||
1024 | |||
1025 | /* PHY access enable */ | 1039 | /* PHY access enable */ |
1026 | if (ah->ah_mac_srev >= AR5K_SREV_AR5211) | 1040 | if (ah->ah_mac_srev >= AR5K_SREV_AR5211) |
1027 | ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); | 1041 | ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); |
@@ -1192,7 +1206,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1192 | ath5k_hw_set_associd(ah); | 1206 | ath5k_hw_set_associd(ah); |
1193 | 1207 | ||
1194 | /* Set PCU config */ | 1208 | /* Set PCU config */ |
1195 | ath5k_hw_set_opmode(ah); | 1209 | ath5k_hw_set_opmode(ah, op_mode); |
1196 | 1210 | ||
1197 | /* Clear any pending interrupts | 1211 | /* Clear any pending interrupts |
1198 | * PISR/SISR Not available on 5210 */ | 1212 | * PISR/SISR Not available on 5210 */ |
@@ -1378,7 +1392,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1378 | * external 32KHz crystal when sleeping if one | 1392 | * external 32KHz crystal when sleeping if one |
1379 | * exists */ | 1393 | * exists */ |
1380 | if (ah->ah_version == AR5K_AR5212 && | 1394 | if (ah->ah_version == AR5K_AR5212 && |
1381 | ah->ah_op_mode != NL80211_IFTYPE_AP) | 1395 | op_mode != NL80211_IFTYPE_AP) |
1382 | ath5k_hw_set_sleep_clock(ah, true); | 1396 | ath5k_hw_set_sleep_clock(ah, true); |
1383 | 1397 | ||
1384 | /* | 1398 | /* |
@@ -1388,5 +1402,3 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1388 | ath5k_hw_reset_tsf(ah); | 1402 | ath5k_hw_reset_tsf(ah); |
1389 | return 0; | 1403 | return 0; |
1390 | } | 1404 | } |
1391 | |||
1392 | #undef _ATH5K_RESET | ||
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig index 5774cea23a3b..35f23bdc442f 100644 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig | |||
@@ -32,3 +32,24 @@ config ATH9K_DEBUGFS | |||
32 | 32 | ||
33 | Also required for changing debug message flags at run time. | 33 | Also required for changing debug message flags at run time. |
34 | 34 | ||
35 | config ATH9K_HTC | ||
36 | tristate "Atheros HTC based wireless cards support" | ||
37 | depends on USB && MAC80211 | ||
38 | select ATH9K_HW | ||
39 | select MAC80211_LEDS | ||
40 | select LEDS_CLASS | ||
41 | select NEW_LEDS | ||
42 | select ATH9K_COMMON | ||
43 | ---help--- | ||
44 | Support for Atheros HTC based cards. | ||
45 | Chipsets supported: AR9271 | ||
46 | |||
47 | For more information: http://wireless.kernel.org/en/users/Drivers/ath9k_htc | ||
48 | |||
49 | The built module will be ath9k_htc. | ||
50 | |||
51 | config ATH9K_HTC_DEBUGFS | ||
52 | bool "Atheros ath9k_htc debugging" | ||
53 | depends on ATH9K_HTC && DEBUG_FS | ||
54 | ---help--- | ||
55 | Say Y, if you need access to ath9k_htc's statistics. | ||
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 6b50d5eb9ec3..97133beda269 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile | |||
@@ -28,3 +28,13 @@ obj-$(CONFIG_ATH9K_HW) += ath9k_hw.o | |||
28 | 28 | ||
29 | obj-$(CONFIG_ATH9K_COMMON) += ath9k_common.o | 29 | obj-$(CONFIG_ATH9K_COMMON) += ath9k_common.o |
30 | ath9k_common-y:= common.o | 30 | ath9k_common-y:= common.o |
31 | |||
32 | ath9k_htc-y += htc_hst.o \ | ||
33 | hif_usb.o \ | ||
34 | wmi.o \ | ||
35 | htc_drv_txrx.o \ | ||
36 | htc_drv_main.o \ | ||
37 | htc_drv_beacon.o \ | ||
38 | htc_drv_init.o | ||
39 | |||
40 | obj-$(CONFIG_ATH9K_HTC) += ath9k_htc.o | ||
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index ca4994f13151..85fdd26039c8 100644 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c | |||
@@ -47,6 +47,7 @@ static bool ath_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data) | |||
47 | } | 47 | } |
48 | 48 | ||
49 | static struct ath_bus_ops ath_ahb_bus_ops = { | 49 | static struct ath_bus_ops ath_ahb_bus_ops = { |
50 | .ath_bus_type = ATH_AHB, | ||
50 | .read_cachesize = ath_ahb_read_cachesize, | 51 | .read_cachesize = ath_ahb_read_cachesize, |
51 | .eeprom_read = ath_ahb_eeprom_read, | 52 | .eeprom_read = ath_ahb_eeprom_read, |
52 | }; | 53 | }; |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 83c7ea4c007f..bdcd257ca7a4 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -178,9 +178,6 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd, | |||
178 | #define BAW_WITHIN(_start, _bawsz, _seqno) \ | 178 | #define BAW_WITHIN(_start, _bawsz, _seqno) \ |
179 | ((((_seqno) - (_start)) & 4095) < (_bawsz)) | 179 | ((((_seqno) - (_start)) & 4095) < (_bawsz)) |
180 | 180 | ||
181 | #define ATH_DS_BA_SEQ(_ds) ((_ds)->ds_us.tx.ts_seqnum) | ||
182 | #define ATH_DS_BA_BITMAP(_ds) (&(_ds)->ds_us.tx.ba_low) | ||
183 | #define ATH_DS_TX_BA(_ds) ((_ds)->ds_us.tx.ts_flags & ATH9K_TX_BA) | ||
184 | #define ATH_AN_2_TID(_an, _tidno) (&(_an)->tid[(_tidno)]) | 181 | #define ATH_AN_2_TID(_an, _tidno) (&(_an)->tid[(_tidno)]) |
185 | 182 | ||
186 | #define ATH_TX_COMPLETE_POLL_INT 1000 | 183 | #define ATH_TX_COMPLETE_POLL_INT 1000 |
@@ -483,7 +480,6 @@ struct ath_softc { | |||
483 | bool ps_enabled; | 480 | bool ps_enabled; |
484 | bool ps_idle; | 481 | bool ps_idle; |
485 | unsigned long ps_usecount; | 482 | unsigned long ps_usecount; |
486 | enum ath9k_int imask; | ||
487 | 483 | ||
488 | struct ath_config config; | 484 | struct ath_config config; |
489 | struct ath_rx rx; | 485 | struct ath_rx rx; |
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index b4a31a43a62c..22375a754718 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c | |||
@@ -524,6 +524,7 @@ static void ath9k_beacon_init(struct ath_softc *sc, | |||
524 | static void ath_beacon_config_ap(struct ath_softc *sc, | 524 | static void ath_beacon_config_ap(struct ath_softc *sc, |
525 | struct ath_beacon_config *conf) | 525 | struct ath_beacon_config *conf) |
526 | { | 526 | { |
527 | struct ath_hw *ah = sc->sc_ah; | ||
527 | u32 nexttbtt, intval; | 528 | u32 nexttbtt, intval; |
528 | 529 | ||
529 | /* NB: the beacon interval is kept internally in TU's */ | 530 | /* NB: the beacon interval is kept internally in TU's */ |
@@ -539,15 +540,15 @@ static void ath_beacon_config_ap(struct ath_softc *sc, | |||
539 | * prepare beacon frames. | 540 | * prepare beacon frames. |
540 | */ | 541 | */ |
541 | intval |= ATH9K_BEACON_ENA; | 542 | intval |= ATH9K_BEACON_ENA; |
542 | sc->imask |= ATH9K_INT_SWBA; | 543 | ah->imask |= ATH9K_INT_SWBA; |
543 | ath_beaconq_config(sc); | 544 | ath_beaconq_config(sc); |
544 | 545 | ||
545 | /* Set the computed AP beacon timers */ | 546 | /* Set the computed AP beacon timers */ |
546 | 547 | ||
547 | ath9k_hw_set_interrupts(sc->sc_ah, 0); | 548 | ath9k_hw_set_interrupts(ah, 0); |
548 | ath9k_beacon_init(sc, nexttbtt, intval); | 549 | ath9k_beacon_init(sc, nexttbtt, intval); |
549 | sc->beacon.bmisscnt = 0; | 550 | sc->beacon.bmisscnt = 0; |
550 | ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); | 551 | ath9k_hw_set_interrupts(ah, ah->imask); |
551 | 552 | ||
552 | /* Clear the reset TSF flag, so that subsequent beacon updation | 553 | /* Clear the reset TSF flag, so that subsequent beacon updation |
553 | will not reset the HW TSF. */ | 554 | will not reset the HW TSF. */ |
@@ -566,7 +567,8 @@ static void ath_beacon_config_ap(struct ath_softc *sc, | |||
566 | static void ath_beacon_config_sta(struct ath_softc *sc, | 567 | static void ath_beacon_config_sta(struct ath_softc *sc, |
567 | struct ath_beacon_config *conf) | 568 | struct ath_beacon_config *conf) |
568 | { | 569 | { |
569 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 570 | struct ath_hw *ah = sc->sc_ah; |
571 | struct ath_common *common = ath9k_hw_common(ah); | ||
570 | struct ath9k_beacon_state bs; | 572 | struct ath9k_beacon_state bs; |
571 | int dtimperiod, dtimcount, sleepduration; | 573 | int dtimperiod, dtimcount, sleepduration; |
572 | int cfpperiod, cfpcount; | 574 | int cfpperiod, cfpcount; |
@@ -605,7 +607,7 @@ static void ath_beacon_config_sta(struct ath_softc *sc, | |||
605 | * Pull nexttbtt forward to reflect the current | 607 | * Pull nexttbtt forward to reflect the current |
606 | * TSF and calculate dtim+cfp state for the result. | 608 | * TSF and calculate dtim+cfp state for the result. |
607 | */ | 609 | */ |
608 | tsf = ath9k_hw_gettsf64(sc->sc_ah); | 610 | tsf = ath9k_hw_gettsf64(ah); |
609 | tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE; | 611 | tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE; |
610 | 612 | ||
611 | num_beacons = tsftu / intval + 1; | 613 | num_beacons = tsftu / intval + 1; |
@@ -678,17 +680,18 @@ static void ath_beacon_config_sta(struct ath_softc *sc, | |||
678 | 680 | ||
679 | /* Set the computed STA beacon timers */ | 681 | /* Set the computed STA beacon timers */ |
680 | 682 | ||
681 | ath9k_hw_set_interrupts(sc->sc_ah, 0); | 683 | ath9k_hw_set_interrupts(ah, 0); |
682 | ath9k_hw_set_sta_beacon_timers(sc->sc_ah, &bs); | 684 | ath9k_hw_set_sta_beacon_timers(ah, &bs); |
683 | sc->imask |= ATH9K_INT_BMISS; | 685 | ah->imask |= ATH9K_INT_BMISS; |
684 | ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); | 686 | ath9k_hw_set_interrupts(ah, ah->imask); |
685 | } | 687 | } |
686 | 688 | ||
687 | static void ath_beacon_config_adhoc(struct ath_softc *sc, | 689 | static void ath_beacon_config_adhoc(struct ath_softc *sc, |
688 | struct ath_beacon_config *conf, | 690 | struct ath_beacon_config *conf, |
689 | struct ieee80211_vif *vif) | 691 | struct ieee80211_vif *vif) |
690 | { | 692 | { |
691 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 693 | struct ath_hw *ah = sc->sc_ah; |
694 | struct ath_common *common = ath9k_hw_common(ah); | ||
692 | u64 tsf; | 695 | u64 tsf; |
693 | u32 tsftu, intval, nexttbtt; | 696 | u32 tsftu, intval, nexttbtt; |
694 | 697 | ||
@@ -703,7 +706,7 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, | |||
703 | else if (intval) | 706 | else if (intval) |
704 | nexttbtt = roundup(nexttbtt, intval); | 707 | nexttbtt = roundup(nexttbtt, intval); |
705 | 708 | ||
706 | tsf = ath9k_hw_gettsf64(sc->sc_ah); | 709 | tsf = ath9k_hw_gettsf64(ah); |
707 | tsftu = TSF_TO_TU((u32)(tsf>>32), (u32)tsf) + FUDGE; | 710 | tsftu = TSF_TO_TU((u32)(tsf>>32), (u32)tsf) + FUDGE; |
708 | do { | 711 | do { |
709 | nexttbtt += intval; | 712 | nexttbtt += intval; |
@@ -719,20 +722,20 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, | |||
719 | * self-linked tx descriptor and let the hardware deal with things. | 722 | * self-linked tx descriptor and let the hardware deal with things. |
720 | */ | 723 | */ |
721 | intval |= ATH9K_BEACON_ENA; | 724 | intval |= ATH9K_BEACON_ENA; |
722 | if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) | 725 | if (!(ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) |
723 | sc->imask |= ATH9K_INT_SWBA; | 726 | ah->imask |= ATH9K_INT_SWBA; |
724 | 727 | ||
725 | ath_beaconq_config(sc); | 728 | ath_beaconq_config(sc); |
726 | 729 | ||
727 | /* Set the computed ADHOC beacon timers */ | 730 | /* Set the computed ADHOC beacon timers */ |
728 | 731 | ||
729 | ath9k_hw_set_interrupts(sc->sc_ah, 0); | 732 | ath9k_hw_set_interrupts(ah, 0); |
730 | ath9k_beacon_init(sc, nexttbtt, intval); | 733 | ath9k_beacon_init(sc, nexttbtt, intval); |
731 | sc->beacon.bmisscnt = 0; | 734 | sc->beacon.bmisscnt = 0; |
732 | ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); | 735 | ath9k_hw_set_interrupts(ah, ah->imask); |
733 | 736 | ||
734 | /* FIXME: Handle properly when vif is NULL */ | 737 | /* FIXME: Handle properly when vif is NULL */ |
735 | if (vif && sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL) | 738 | if (vif && ah->caps.hw_caps & ATH9K_HW_CAP_VEOL) |
736 | ath_beacon_start_adhoc(sc, vif); | 739 | ath_beacon_start_adhoc(sc, vif); |
737 | } | 740 | } |
738 | 741 | ||
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 238a5744d8e9..064f5b51dfcd 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c | |||
@@ -18,6 +18,7 @@ | |||
18 | 18 | ||
19 | /* We can tune this as we go by monitoring really low values */ | 19 | /* We can tune this as we go by monitoring really low values */ |
20 | #define ATH9K_NF_TOO_LOW -60 | 20 | #define ATH9K_NF_TOO_LOW -60 |
21 | #define AR9285_CLCAL_REDO_THRESH 1 | ||
21 | 22 | ||
22 | /* AR5416 may return very high value (like -31 dBm), in those cases the nf | 23 | /* AR5416 may return very high value (like -31 dBm), in those cases the nf |
23 | * is incorrect and we should use the static NF value. Later we can try to | 24 | * is incorrect and we should use the static NF value. Later we can try to |
@@ -101,9 +102,13 @@ static void ath9k_hw_do_getnf(struct ath_hw *ah, | |||
101 | nf = 0 - ((nf ^ 0x1ff) + 1); | 102 | nf = 0 - ((nf ^ 0x1ff) + 1); |
102 | ath_print(common, ATH_DBG_CALIBRATE, | 103 | ath_print(common, ATH_DBG_CALIBRATE, |
103 | "NF calibrated [ctl] [chain 0] is %d\n", nf); | 104 | "NF calibrated [ctl] [chain 0] is %d\n", nf); |
105 | |||
106 | if (AR_SREV_9271(ah) && (nf >= -114)) | ||
107 | nf = -116; | ||
108 | |||
104 | nfarray[0] = nf; | 109 | nfarray[0] = nf; |
105 | 110 | ||
106 | if (!AR_SREV_9285(ah)) { | 111 | if (!AR_SREV_9285(ah) && !AR_SREV_9271(ah)) { |
107 | if (AR_SREV_9280_10_OR_LATER(ah)) | 112 | if (AR_SREV_9280_10_OR_LATER(ah)) |
108 | nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), | 113 | nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), |
109 | AR9280_PHY_CH1_MINCCA_PWR); | 114 | AR9280_PHY_CH1_MINCCA_PWR); |
@@ -139,9 +144,13 @@ static void ath9k_hw_do_getnf(struct ath_hw *ah, | |||
139 | nf = 0 - ((nf ^ 0x1ff) + 1); | 144 | nf = 0 - ((nf ^ 0x1ff) + 1); |
140 | ath_print(common, ATH_DBG_CALIBRATE, | 145 | ath_print(common, ATH_DBG_CALIBRATE, |
141 | "NF calibrated [ext] [chain 0] is %d\n", nf); | 146 | "NF calibrated [ext] [chain 0] is %d\n", nf); |
147 | |||
148 | if (AR_SREV_9271(ah) && (nf >= -114)) | ||
149 | nf = -116; | ||
150 | |||
142 | nfarray[3] = nf; | 151 | nfarray[3] = nf; |
143 | 152 | ||
144 | if (!AR_SREV_9285(ah)) { | 153 | if (!AR_SREV_9285(ah) && !AR_SREV_9271(ah)) { |
145 | if (AR_SREV_9280_10_OR_LATER(ah)) | 154 | if (AR_SREV_9280_10_OR_LATER(ah)) |
146 | nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), | 155 | nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), |
147 | AR9280_PHY_CH1_EXT_MINCCA_PWR); | 156 | AR9280_PHY_CH1_EXT_MINCCA_PWR); |
@@ -621,7 +630,7 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
621 | u8 chainmask, rx_chain_status; | 630 | u8 chainmask, rx_chain_status; |
622 | 631 | ||
623 | rx_chain_status = REG_READ(ah, AR_PHY_RX_CHAINMASK); | 632 | rx_chain_status = REG_READ(ah, AR_PHY_RX_CHAINMASK); |
624 | if (AR_SREV_9285(ah)) | 633 | if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) |
625 | chainmask = 0x9; | 634 | chainmask = 0x9; |
626 | else if (AR_SREV_9280(ah) || AR_SREV_9287(ah)) { | 635 | else if (AR_SREV_9280(ah) || AR_SREV_9287(ah)) { |
627 | if ((rx_chain_status & 0x2) || (rx_chain_status & 0x4)) | 636 | if ((rx_chain_status & 0x2) || (rx_chain_status & 0x4)) |
@@ -715,7 +724,7 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah) | |||
715 | 724 | ||
716 | if (AR_SREV_9280(ah)) | 725 | if (AR_SREV_9280(ah)) |
717 | noise_floor = AR_PHY_CCA_MAX_AR9280_GOOD_VALUE; | 726 | noise_floor = AR_PHY_CCA_MAX_AR9280_GOOD_VALUE; |
718 | else if (AR_SREV_9285(ah)) | 727 | else if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) |
719 | noise_floor = AR_PHY_CCA_MAX_AR9285_GOOD_VALUE; | 728 | noise_floor = AR_PHY_CCA_MAX_AR9285_GOOD_VALUE; |
720 | else if (AR_SREV_9287(ah)) | 729 | else if (AR_SREV_9287(ah)) |
721 | noise_floor = AR_PHY_CCA_MAX_AR9287_GOOD_VALUE; | 730 | noise_floor = AR_PHY_CCA_MAX_AR9287_GOOD_VALUE; |
@@ -1051,9 +1060,12 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1051 | /* Do NF cal only at longer intervals */ | 1060 | /* Do NF cal only at longer intervals */ |
1052 | if (longcal) { | 1061 | if (longcal) { |
1053 | /* Do periodic PAOffset Cal */ | 1062 | /* Do periodic PAOffset Cal */ |
1054 | if (AR_SREV_9271(ah)) | 1063 | if (AR_SREV_9271(ah)) { |
1055 | ath9k_hw_9271_pa_cal(ah, false); | 1064 | if (!ah->pacal_info.skipcount) |
1056 | else if (AR_SREV_9285_11_OR_LATER(ah)) { | 1065 | ath9k_hw_9271_pa_cal(ah, false); |
1066 | else | ||
1067 | ah->pacal_info.skipcount--; | ||
1068 | } else if (AR_SREV_9285_11_OR_LATER(ah)) { | ||
1057 | if (!ah->pacal_info.skipcount) | 1069 | if (!ah->pacal_info.skipcount) |
1058 | ath9k_hw_9285_pa_cal(ah, false); | 1070 | ath9k_hw_9285_pa_cal(ah, false); |
1059 | else | 1071 | else |
@@ -1080,7 +1092,7 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1080 | EXPORT_SYMBOL(ath9k_hw_calibrate); | 1092 | EXPORT_SYMBOL(ath9k_hw_calibrate); |
1081 | 1093 | ||
1082 | /* Carrier leakage Calibration fix */ | 1094 | /* Carrier leakage Calibration fix */ |
1083 | static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan) | 1095 | static bool ar9285_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan) |
1084 | { | 1096 | { |
1085 | struct ath_common *common = ath9k_hw_common(ah); | 1097 | struct ath_common *common = ath9k_hw_common(ah); |
1086 | 1098 | ||
@@ -1121,6 +1133,62 @@ static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan) | |||
1121 | return true; | 1133 | return true; |
1122 | } | 1134 | } |
1123 | 1135 | ||
1136 | static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan) | ||
1137 | { | ||
1138 | int i; | ||
1139 | u_int32_t txgain_max; | ||
1140 | u_int32_t clc_gain, gain_mask = 0, clc_num = 0; | ||
1141 | u_int32_t reg_clc_I0, reg_clc_Q0; | ||
1142 | u_int32_t i0_num = 0; | ||
1143 | u_int32_t q0_num = 0; | ||
1144 | u_int32_t total_num = 0; | ||
1145 | u_int32_t reg_rf2g5_org; | ||
1146 | bool retv = true; | ||
1147 | |||
1148 | if (!(ar9285_cl_cal(ah, chan))) | ||
1149 | return false; | ||
1150 | |||
1151 | txgain_max = MS(REG_READ(ah, AR_PHY_TX_PWRCTRL7), | ||
1152 | AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX); | ||
1153 | |||
1154 | for (i = 0; i < (txgain_max+1); i++) { | ||
1155 | clc_gain = (REG_READ(ah, (AR_PHY_TX_GAIN_TBL1+(i<<2))) & | ||
1156 | AR_PHY_TX_GAIN_CLC) >> AR_PHY_TX_GAIN_CLC_S; | ||
1157 | if (!(gain_mask & (1 << clc_gain))) { | ||
1158 | gain_mask |= (1 << clc_gain); | ||
1159 | clc_num++; | ||
1160 | } | ||
1161 | } | ||
1162 | |||
1163 | for (i = 0; i < clc_num; i++) { | ||
1164 | reg_clc_I0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2))) | ||
1165 | & AR_PHY_CLC_I0) >> AR_PHY_CLC_I0_S; | ||
1166 | reg_clc_Q0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2))) | ||
1167 | & AR_PHY_CLC_Q0) >> AR_PHY_CLC_Q0_S; | ||
1168 | if (reg_clc_I0 == 0) | ||
1169 | i0_num++; | ||
1170 | |||
1171 | if (reg_clc_Q0 == 0) | ||
1172 | q0_num++; | ||
1173 | } | ||
1174 | total_num = i0_num + q0_num; | ||
1175 | if (total_num > AR9285_CLCAL_REDO_THRESH) { | ||
1176 | reg_rf2g5_org = REG_READ(ah, AR9285_RF2G5); | ||
1177 | if (AR_SREV_9285E_20(ah)) { | ||
1178 | REG_WRITE(ah, AR9285_RF2G5, | ||
1179 | (reg_rf2g5_org & AR9285_RF2G5_IC50TX) | | ||
1180 | AR9285_RF2G5_IC50TX_XE_SET); | ||
1181 | } else { | ||
1182 | REG_WRITE(ah, AR9285_RF2G5, | ||
1183 | (reg_rf2g5_org & AR9285_RF2G5_IC50TX) | | ||
1184 | AR9285_RF2G5_IC50TX_SET); | ||
1185 | } | ||
1186 | retv = ar9285_cl_cal(ah, chan); | ||
1187 | REG_WRITE(ah, AR9285_RF2G5, reg_rf2g5_org); | ||
1188 | } | ||
1189 | return retv; | ||
1190 | } | ||
1191 | |||
1124 | bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) | 1192 | bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) |
1125 | { | 1193 | { |
1126 | struct ath_common *common = ath9k_hw_common(ah); | 1194 | struct ath_common *common = ath9k_hw_common(ah); |
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index 4d775ae141db..09effdedc8c0 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c | |||
@@ -255,7 +255,8 @@ void ath9k_cmn_rx_skb_postprocess(struct ath_common *common, | |||
255 | 255 | ||
256 | keyix = rx_stats->rs_keyix; | 256 | keyix = rx_stats->rs_keyix; |
257 | 257 | ||
258 | if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error) { | 258 | if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error && |
259 | ieee80211_has_protected(fc)) { | ||
259 | rxs->flag |= RX_FLAG_DECRYPTED; | 260 | rxs->flag |= RX_FLAG_DECRYPTED; |
260 | } else if (ieee80211_has_protected(fc) | 261 | } else if (ieee80211_has_protected(fc) |
261 | && !decrypt_error && skb->len >= hdrlen + 4) { | 262 | && !decrypt_error && skb->len >= hdrlen + 4) { |
@@ -286,6 +287,345 @@ int ath9k_cmn_padpos(__le16 frame_control) | |||
286 | } | 287 | } |
287 | EXPORT_SYMBOL(ath9k_cmn_padpos); | 288 | EXPORT_SYMBOL(ath9k_cmn_padpos); |
288 | 289 | ||
290 | int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb) | ||
291 | { | ||
292 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
293 | |||
294 | if (tx_info->control.hw_key) { | ||
295 | if (tx_info->control.hw_key->alg == ALG_WEP) | ||
296 | return ATH9K_KEY_TYPE_WEP; | ||
297 | else if (tx_info->control.hw_key->alg == ALG_TKIP) | ||
298 | return ATH9K_KEY_TYPE_TKIP; | ||
299 | else if (tx_info->control.hw_key->alg == ALG_CCMP) | ||
300 | return ATH9K_KEY_TYPE_AES; | ||
301 | } | ||
302 | |||
303 | return ATH9K_KEY_TYPE_CLEAR; | ||
304 | } | ||
305 | EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_keytype); | ||
306 | |||
307 | static u32 ath9k_get_extchanmode(struct ieee80211_channel *chan, | ||
308 | enum nl80211_channel_type channel_type) | ||
309 | { | ||
310 | u32 chanmode = 0; | ||
311 | |||
312 | switch (chan->band) { | ||
313 | case IEEE80211_BAND_2GHZ: | ||
314 | switch (channel_type) { | ||
315 | case NL80211_CHAN_NO_HT: | ||
316 | case NL80211_CHAN_HT20: | ||
317 | chanmode = CHANNEL_G_HT20; | ||
318 | break; | ||
319 | case NL80211_CHAN_HT40PLUS: | ||
320 | chanmode = CHANNEL_G_HT40PLUS; | ||
321 | break; | ||
322 | case NL80211_CHAN_HT40MINUS: | ||
323 | chanmode = CHANNEL_G_HT40MINUS; | ||
324 | break; | ||
325 | } | ||
326 | break; | ||
327 | case IEEE80211_BAND_5GHZ: | ||
328 | switch (channel_type) { | ||
329 | case NL80211_CHAN_NO_HT: | ||
330 | case NL80211_CHAN_HT20: | ||
331 | chanmode = CHANNEL_A_HT20; | ||
332 | break; | ||
333 | case NL80211_CHAN_HT40PLUS: | ||
334 | chanmode = CHANNEL_A_HT40PLUS; | ||
335 | break; | ||
336 | case NL80211_CHAN_HT40MINUS: | ||
337 | chanmode = CHANNEL_A_HT40MINUS; | ||
338 | break; | ||
339 | } | ||
340 | break; | ||
341 | default: | ||
342 | break; | ||
343 | } | ||
344 | |||
345 | return chanmode; | ||
346 | } | ||
347 | |||
348 | /* | ||
349 | * Update internal channel flags. | ||
350 | */ | ||
351 | void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw, | ||
352 | struct ath9k_channel *ichan) | ||
353 | { | ||
354 | struct ieee80211_channel *chan = hw->conf.channel; | ||
355 | struct ieee80211_conf *conf = &hw->conf; | ||
356 | |||
357 | ichan->channel = chan->center_freq; | ||
358 | ichan->chan = chan; | ||
359 | |||
360 | if (chan->band == IEEE80211_BAND_2GHZ) { | ||
361 | ichan->chanmode = CHANNEL_G; | ||
362 | ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM | CHANNEL_G; | ||
363 | } else { | ||
364 | ichan->chanmode = CHANNEL_A; | ||
365 | ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM; | ||
366 | } | ||
367 | |||
368 | if (conf_is_ht(conf)) | ||
369 | ichan->chanmode = ath9k_get_extchanmode(chan, | ||
370 | conf->channel_type); | ||
371 | } | ||
372 | EXPORT_SYMBOL(ath9k_cmn_update_ichannel); | ||
373 | |||
374 | /* | ||
375 | * Get the internal channel reference. | ||
376 | */ | ||
377 | struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw, | ||
378 | struct ath_hw *ah) | ||
379 | { | ||
380 | struct ieee80211_channel *curchan = hw->conf.channel; | ||
381 | struct ath9k_channel *channel; | ||
382 | u8 chan_idx; | ||
383 | |||
384 | chan_idx = curchan->hw_value; | ||
385 | channel = &ah->channels[chan_idx]; | ||
386 | ath9k_cmn_update_ichannel(hw, channel); | ||
387 | |||
388 | return channel; | ||
389 | } | ||
390 | EXPORT_SYMBOL(ath9k_cmn_get_curchannel); | ||
391 | |||
392 | static int ath_setkey_tkip(struct ath_common *common, u16 keyix, const u8 *key, | ||
393 | struct ath9k_keyval *hk, const u8 *addr, | ||
394 | bool authenticator) | ||
395 | { | ||
396 | struct ath_hw *ah = common->ah; | ||
397 | const u8 *key_rxmic; | ||
398 | const u8 *key_txmic; | ||
399 | |||
400 | key_txmic = key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY; | ||
401 | key_rxmic = key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY; | ||
402 | |||
403 | if (addr == NULL) { | ||
404 | /* | ||
405 | * Group key installation - only two key cache entries are used | ||
406 | * regardless of splitmic capability since group key is only | ||
407 | * used either for TX or RX. | ||
408 | */ | ||
409 | if (authenticator) { | ||
410 | memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); | ||
411 | memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_mic)); | ||
412 | } else { | ||
413 | memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); | ||
414 | memcpy(hk->kv_txmic, key_rxmic, sizeof(hk->kv_mic)); | ||
415 | } | ||
416 | return ath9k_hw_set_keycache_entry(ah, keyix, hk, addr); | ||
417 | } | ||
418 | if (!common->splitmic) { | ||
419 | /* TX and RX keys share the same key cache entry. */ | ||
420 | memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); | ||
421 | memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic)); | ||
422 | return ath9k_hw_set_keycache_entry(ah, keyix, hk, addr); | ||
423 | } | ||
424 | |||
425 | /* Separate key cache entries for TX and RX */ | ||
426 | |||
427 | /* TX key goes at first index, RX key at +32. */ | ||
428 | memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); | ||
429 | if (!ath9k_hw_set_keycache_entry(ah, keyix, hk, NULL)) { | ||
430 | /* TX MIC entry failed. No need to proceed further */ | ||
431 | ath_print(common, ATH_DBG_FATAL, | ||
432 | "Setting TX MIC Key Failed\n"); | ||
433 | return 0; | ||
434 | } | ||
435 | |||
436 | memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); | ||
437 | /* XXX delete tx key on failure? */ | ||
438 | return ath9k_hw_set_keycache_entry(ah, keyix + 32, hk, addr); | ||
439 | } | ||
440 | |||
441 | static int ath_reserve_key_cache_slot_tkip(struct ath_common *common) | ||
442 | { | ||
443 | int i; | ||
444 | |||
445 | for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) { | ||
446 | if (test_bit(i, common->keymap) || | ||
447 | test_bit(i + 64, common->keymap)) | ||
448 | continue; /* At least one part of TKIP key allocated */ | ||
449 | if (common->splitmic && | ||
450 | (test_bit(i + 32, common->keymap) || | ||
451 | test_bit(i + 64 + 32, common->keymap))) | ||
452 | continue; /* At least one part of TKIP key allocated */ | ||
453 | |||
454 | /* Found a free slot for a TKIP key */ | ||
455 | return i; | ||
456 | } | ||
457 | return -1; | ||
458 | } | ||
459 | |||
460 | static int ath_reserve_key_cache_slot(struct ath_common *common) | ||
461 | { | ||
462 | int i; | ||
463 | |||
464 | /* First, try to find slots that would not be available for TKIP. */ | ||
465 | if (common->splitmic) { | ||
466 | for (i = IEEE80211_WEP_NKID; i < common->keymax / 4; i++) { | ||
467 | if (!test_bit(i, common->keymap) && | ||
468 | (test_bit(i + 32, common->keymap) || | ||
469 | test_bit(i + 64, common->keymap) || | ||
470 | test_bit(i + 64 + 32, common->keymap))) | ||
471 | return i; | ||
472 | if (!test_bit(i + 32, common->keymap) && | ||
473 | (test_bit(i, common->keymap) || | ||
474 | test_bit(i + 64, common->keymap) || | ||
475 | test_bit(i + 64 + 32, common->keymap))) | ||
476 | return i + 32; | ||
477 | if (!test_bit(i + 64, common->keymap) && | ||
478 | (test_bit(i , common->keymap) || | ||
479 | test_bit(i + 32, common->keymap) || | ||
480 | test_bit(i + 64 + 32, common->keymap))) | ||
481 | return i + 64; | ||
482 | if (!test_bit(i + 64 + 32, common->keymap) && | ||
483 | (test_bit(i, common->keymap) || | ||
484 | test_bit(i + 32, common->keymap) || | ||
485 | test_bit(i + 64, common->keymap))) | ||
486 | return i + 64 + 32; | ||
487 | } | ||
488 | } else { | ||
489 | for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) { | ||
490 | if (!test_bit(i, common->keymap) && | ||
491 | test_bit(i + 64, common->keymap)) | ||
492 | return i; | ||
493 | if (test_bit(i, common->keymap) && | ||
494 | !test_bit(i + 64, common->keymap)) | ||
495 | return i + 64; | ||
496 | } | ||
497 | } | ||
498 | |||
499 | /* No partially used TKIP slots, pick any available slot */ | ||
500 | for (i = IEEE80211_WEP_NKID; i < common->keymax; i++) { | ||
501 | /* Do not allow slots that could be needed for TKIP group keys | ||
502 | * to be used. This limitation could be removed if we know that | ||
503 | * TKIP will not be used. */ | ||
504 | if (i >= 64 && i < 64 + IEEE80211_WEP_NKID) | ||
505 | continue; | ||
506 | if (common->splitmic) { | ||
507 | if (i >= 32 && i < 32 + IEEE80211_WEP_NKID) | ||
508 | continue; | ||
509 | if (i >= 64 + 32 && i < 64 + 32 + IEEE80211_WEP_NKID) | ||
510 | continue; | ||
511 | } | ||
512 | |||
513 | if (!test_bit(i, common->keymap)) | ||
514 | return i; /* Found a free slot for a key */ | ||
515 | } | ||
516 | |||
517 | /* No free slot found */ | ||
518 | return -1; | ||
519 | } | ||
520 | |||
521 | /* | ||
522 | * Configure encryption in the HW. | ||
523 | */ | ||
524 | int ath9k_cmn_key_config(struct ath_common *common, | ||
525 | struct ieee80211_vif *vif, | ||
526 | struct ieee80211_sta *sta, | ||
527 | struct ieee80211_key_conf *key) | ||
528 | { | ||
529 | struct ath_hw *ah = common->ah; | ||
530 | struct ath9k_keyval hk; | ||
531 | const u8 *mac = NULL; | ||
532 | int ret = 0; | ||
533 | int idx; | ||
534 | |||
535 | memset(&hk, 0, sizeof(hk)); | ||
536 | |||
537 | switch (key->alg) { | ||
538 | case ALG_WEP: | ||
539 | hk.kv_type = ATH9K_CIPHER_WEP; | ||
540 | break; | ||
541 | case ALG_TKIP: | ||
542 | hk.kv_type = ATH9K_CIPHER_TKIP; | ||
543 | break; | ||
544 | case ALG_CCMP: | ||
545 | hk.kv_type = ATH9K_CIPHER_AES_CCM; | ||
546 | break; | ||
547 | default: | ||
548 | return -EOPNOTSUPP; | ||
549 | } | ||
550 | |||
551 | hk.kv_len = key->keylen; | ||
552 | memcpy(hk.kv_val, key->key, key->keylen); | ||
553 | |||
554 | if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { | ||
555 | /* For now, use the default keys for broadcast keys. This may | ||
556 | * need to change with virtual interfaces. */ | ||
557 | idx = key->keyidx; | ||
558 | } else if (key->keyidx) { | ||
559 | if (WARN_ON(!sta)) | ||
560 | return -EOPNOTSUPP; | ||
561 | mac = sta->addr; | ||
562 | |||
563 | if (vif->type != NL80211_IFTYPE_AP) { | ||
564 | /* Only keyidx 0 should be used with unicast key, but | ||
565 | * allow this for client mode for now. */ | ||
566 | idx = key->keyidx; | ||
567 | } else | ||
568 | return -EIO; | ||
569 | } else { | ||
570 | if (WARN_ON(!sta)) | ||
571 | return -EOPNOTSUPP; | ||
572 | mac = sta->addr; | ||
573 | |||
574 | if (key->alg == ALG_TKIP) | ||
575 | idx = ath_reserve_key_cache_slot_tkip(common); | ||
576 | else | ||
577 | idx = ath_reserve_key_cache_slot(common); | ||
578 | if (idx < 0) | ||
579 | return -ENOSPC; /* no free key cache entries */ | ||
580 | } | ||
581 | |||
582 | if (key->alg == ALG_TKIP) | ||
583 | ret = ath_setkey_tkip(common, idx, key->key, &hk, mac, | ||
584 | vif->type == NL80211_IFTYPE_AP); | ||
585 | else | ||
586 | ret = ath9k_hw_set_keycache_entry(ah, idx, &hk, mac); | ||
587 | |||
588 | if (!ret) | ||
589 | return -EIO; | ||
590 | |||
591 | set_bit(idx, common->keymap); | ||
592 | if (key->alg == ALG_TKIP) { | ||
593 | set_bit(idx + 64, common->keymap); | ||
594 | if (common->splitmic) { | ||
595 | set_bit(idx + 32, common->keymap); | ||
596 | set_bit(idx + 64 + 32, common->keymap); | ||
597 | } | ||
598 | } | ||
599 | |||
600 | return idx; | ||
601 | } | ||
602 | EXPORT_SYMBOL(ath9k_cmn_key_config); | ||
603 | |||
604 | /* | ||
605 | * Delete Key. | ||
606 | */ | ||
607 | void ath9k_cmn_key_delete(struct ath_common *common, | ||
608 | struct ieee80211_key_conf *key) | ||
609 | { | ||
610 | struct ath_hw *ah = common->ah; | ||
611 | |||
612 | ath9k_hw_keyreset(ah, key->hw_key_idx); | ||
613 | if (key->hw_key_idx < IEEE80211_WEP_NKID) | ||
614 | return; | ||
615 | |||
616 | clear_bit(key->hw_key_idx, common->keymap); | ||
617 | if (key->alg != ALG_TKIP) | ||
618 | return; | ||
619 | |||
620 | clear_bit(key->hw_key_idx + 64, common->keymap); | ||
621 | if (common->splitmic) { | ||
622 | ath9k_hw_keyreset(ah, key->hw_key_idx + 32); | ||
623 | clear_bit(key->hw_key_idx + 32, common->keymap); | ||
624 | clear_bit(key->hw_key_idx + 64 + 32, common->keymap); | ||
625 | } | ||
626 | } | ||
627 | EXPORT_SYMBOL(ath9k_cmn_key_delete); | ||
628 | |||
289 | static int __init ath9k_cmn_init(void) | 629 | static int __init ath9k_cmn_init(void) |
290 | { | 630 | { |
291 | return 0; | 631 | return 0; |
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index 042999c2fe9c..72a835d9e97f 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h | |||
@@ -23,6 +23,8 @@ | |||
23 | 23 | ||
24 | /* Common header for Atheros 802.11n base driver cores */ | 24 | /* Common header for Atheros 802.11n base driver cores */ |
25 | 25 | ||
26 | #define IEEE80211_WEP_NKID 4 | ||
27 | |||
26 | #define WME_NUM_TID 16 | 28 | #define WME_NUM_TID 16 |
27 | #define WME_BA_BMP_SIZE 64 | 29 | #define WME_BA_BMP_SIZE 64 |
28 | #define WME_MAX_BA WME_BA_BMP_SIZE | 30 | #define WME_MAX_BA WME_BA_BMP_SIZE |
@@ -125,3 +127,14 @@ void ath9k_cmn_rx_skb_postprocess(struct ath_common *common, | |||
125 | bool decrypt_error); | 127 | bool decrypt_error); |
126 | 128 | ||
127 | int ath9k_cmn_padpos(__le16 frame_control); | 129 | int ath9k_cmn_padpos(__le16 frame_control); |
130 | int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb); | ||
131 | void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw, | ||
132 | struct ath9k_channel *ichan); | ||
133 | struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw, | ||
134 | struct ath_hw *ah); | ||
135 | int ath9k_cmn_key_config(struct ath_common *common, | ||
136 | struct ieee80211_vif *vif, | ||
137 | struct ieee80211_sta *sta, | ||
138 | struct ieee80211_key_conf *key); | ||
139 | void ath9k_cmn_key_delete(struct ath_common *common, | ||
140 | struct ieee80211_key_conf *key); | ||
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 42d2a506845a..c7e895925393 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -556,10 +556,8 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf, | |||
556 | } | 556 | } |
557 | 557 | ||
558 | void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq, | 558 | void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq, |
559 | struct ath_buf *bf) | 559 | struct ath_buf *bf, struct ath_tx_status *ts) |
560 | { | 560 | { |
561 | struct ath_desc *ds = bf->bf_desc; | ||
562 | |||
563 | if (bf_isampdu(bf)) { | 561 | if (bf_isampdu(bf)) { |
564 | if (bf_isxretried(bf)) | 562 | if (bf_isxretried(bf)) |
565 | TX_STAT_INC(txq->axq_qnum, a_xretries); | 563 | TX_STAT_INC(txq->axq_qnum, a_xretries); |
@@ -569,17 +567,17 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq, | |||
569 | TX_STAT_INC(txq->axq_qnum, completed); | 567 | TX_STAT_INC(txq->axq_qnum, completed); |
570 | } | 568 | } |
571 | 569 | ||
572 | if (ds->ds_txstat.ts_status & ATH9K_TXERR_FIFO) | 570 | if (ts->ts_status & ATH9K_TXERR_FIFO) |
573 | TX_STAT_INC(txq->axq_qnum, fifo_underrun); | 571 | TX_STAT_INC(txq->axq_qnum, fifo_underrun); |
574 | if (ds->ds_txstat.ts_status & ATH9K_TXERR_XTXOP) | 572 | if (ts->ts_status & ATH9K_TXERR_XTXOP) |
575 | TX_STAT_INC(txq->axq_qnum, xtxop); | 573 | TX_STAT_INC(txq->axq_qnum, xtxop); |
576 | if (ds->ds_txstat.ts_status & ATH9K_TXERR_TIMER_EXPIRED) | 574 | if (ts->ts_status & ATH9K_TXERR_TIMER_EXPIRED) |
577 | TX_STAT_INC(txq->axq_qnum, timer_exp); | 575 | TX_STAT_INC(txq->axq_qnum, timer_exp); |
578 | if (ds->ds_txstat.ts_flags & ATH9K_TX_DESC_CFG_ERR) | 576 | if (ts->ts_flags & ATH9K_TX_DESC_CFG_ERR) |
579 | TX_STAT_INC(txq->axq_qnum, desc_cfg_err); | 577 | TX_STAT_INC(txq->axq_qnum, desc_cfg_err); |
580 | if (ds->ds_txstat.ts_flags & ATH9K_TX_DATA_UNDERRUN) | 578 | if (ts->ts_flags & ATH9K_TX_DATA_UNDERRUN) |
581 | TX_STAT_INC(txq->axq_qnum, data_underrun); | 579 | TX_STAT_INC(txq->axq_qnum, data_underrun); |
582 | if (ds->ds_txstat.ts_flags & ATH9K_TX_DELIM_UNDERRUN) | 580 | if (ts->ts_flags & ATH9K_TX_DELIM_UNDERRUN) |
583 | TX_STAT_INC(txq->axq_qnum, delim_underrun); | 581 | TX_STAT_INC(txq->axq_qnum, delim_underrun); |
584 | } | 582 | } |
585 | 583 | ||
@@ -662,30 +660,29 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, | |||
662 | #undef PHY_ERR | 660 | #undef PHY_ERR |
663 | } | 661 | } |
664 | 662 | ||
665 | void ath_debug_stat_rx(struct ath_softc *sc, struct ath_buf *bf) | 663 | void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs) |
666 | { | 664 | { |
667 | #define RX_STAT_INC(c) sc->debug.stats.rxstats.c++ | 665 | #define RX_STAT_INC(c) sc->debug.stats.rxstats.c++ |
668 | #define RX_PHY_ERR_INC(c) sc->debug.stats.rxstats.phy_err_stats[c]++ | 666 | #define RX_PHY_ERR_INC(c) sc->debug.stats.rxstats.phy_err_stats[c]++ |
669 | 667 | ||
670 | struct ath_desc *ds = bf->bf_desc; | ||
671 | u32 phyerr; | 668 | u32 phyerr; |
672 | 669 | ||
673 | if (ds->ds_rxstat.rs_status & ATH9K_RXERR_CRC) | 670 | if (rs->rs_status & ATH9K_RXERR_CRC) |
674 | RX_STAT_INC(crc_err); | 671 | RX_STAT_INC(crc_err); |
675 | if (ds->ds_rxstat.rs_status & ATH9K_RXERR_DECRYPT) | 672 | if (rs->rs_status & ATH9K_RXERR_DECRYPT) |
676 | RX_STAT_INC(decrypt_crc_err); | 673 | RX_STAT_INC(decrypt_crc_err); |
677 | if (ds->ds_rxstat.rs_status & ATH9K_RXERR_MIC) | 674 | if (rs->rs_status & ATH9K_RXERR_MIC) |
678 | RX_STAT_INC(mic_err); | 675 | RX_STAT_INC(mic_err); |
679 | if (ds->ds_rxstat.rs_status & ATH9K_RX_DELIM_CRC_PRE) | 676 | if (rs->rs_status & ATH9K_RX_DELIM_CRC_PRE) |
680 | RX_STAT_INC(pre_delim_crc_err); | 677 | RX_STAT_INC(pre_delim_crc_err); |
681 | if (ds->ds_rxstat.rs_status & ATH9K_RX_DELIM_CRC_POST) | 678 | if (rs->rs_status & ATH9K_RX_DELIM_CRC_POST) |
682 | RX_STAT_INC(post_delim_crc_err); | 679 | RX_STAT_INC(post_delim_crc_err); |
683 | if (ds->ds_rxstat.rs_status & ATH9K_RX_DECRYPT_BUSY) | 680 | if (rs->rs_status & ATH9K_RX_DECRYPT_BUSY) |
684 | RX_STAT_INC(decrypt_busy_err); | 681 | RX_STAT_INC(decrypt_busy_err); |
685 | 682 | ||
686 | if (ds->ds_rxstat.rs_status & ATH9K_RXERR_PHY) { | 683 | if (rs->rs_status & ATH9K_RXERR_PHY) { |
687 | RX_STAT_INC(phy_err); | 684 | RX_STAT_INC(phy_err); |
688 | phyerr = ds->ds_rxstat.rs_phyerr & 0x24; | 685 | phyerr = rs->rs_phyerr & 0x24; |
689 | RX_PHY_ERR_INC(phyerr); | 686 | RX_PHY_ERR_INC(phyerr); |
690 | } | 687 | } |
691 | 688 | ||
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 86780e68b31e..b2af9de755e6 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h | |||
@@ -167,8 +167,8 @@ void ath9k_debug_remove_root(void); | |||
167 | void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); | 167 | void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); |
168 | void ath_debug_stat_rc(struct ath_softc *sc, int final_rate); | 168 | void ath_debug_stat_rc(struct ath_softc *sc, int final_rate); |
169 | void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq, | 169 | void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq, |
170 | struct ath_buf *bf); | 170 | struct ath_buf *bf, struct ath_tx_status *ts); |
171 | void ath_debug_stat_rx(struct ath_softc *sc, struct ath_buf *bf); | 171 | void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs); |
172 | void ath_debug_stat_retries(struct ath_softc *sc, int rix, | 172 | void ath_debug_stat_retries(struct ath_softc *sc, int rix, |
173 | int xretries, int retries, u8 per); | 173 | int xretries, int retries, u8 per); |
174 | 174 | ||
@@ -204,12 +204,13 @@ static inline void ath_debug_stat_rc(struct ath_softc *sc, | |||
204 | 204 | ||
205 | static inline void ath_debug_stat_tx(struct ath_softc *sc, | 205 | static inline void ath_debug_stat_tx(struct ath_softc *sc, |
206 | struct ath_txq *txq, | 206 | struct ath_txq *txq, |
207 | struct ath_buf *bf) | 207 | struct ath_buf *bf, |
208 | struct ath_tx_status *ts) | ||
208 | { | 209 | { |
209 | } | 210 | } |
210 | 211 | ||
211 | static inline void ath_debug_stat_rx(struct ath_softc *sc, | 212 | static inline void ath_debug_stat_rx(struct ath_softc *sc, |
212 | struct ath_buf *bf) | 213 | struct ath_rx_status *rs) |
213 | { | 214 | { |
214 | } | 215 | } |
215 | 216 | ||
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index deab8beb0680..1e4578d303dd 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c | |||
@@ -283,22 +283,17 @@ static void ath9k_gen_timer_start(struct ath_hw *ah, | |||
283 | u32 timer_next, | 283 | u32 timer_next, |
284 | u32 timer_period) | 284 | u32 timer_period) |
285 | { | 285 | { |
286 | struct ath_common *common = ath9k_hw_common(ah); | ||
287 | struct ath_softc *sc = (struct ath_softc *) common->priv; | ||
288 | |||
289 | ath9k_hw_gen_timer_start(ah, timer, timer_next, timer_period); | 286 | ath9k_hw_gen_timer_start(ah, timer, timer_next, timer_period); |
290 | 287 | ||
291 | if ((sc->imask & ATH9K_INT_GENTIMER) == 0) { | 288 | if ((ah->imask & ATH9K_INT_GENTIMER) == 0) { |
292 | ath9k_hw_set_interrupts(ah, 0); | 289 | ath9k_hw_set_interrupts(ah, 0); |
293 | sc->imask |= ATH9K_INT_GENTIMER; | 290 | ah->imask |= ATH9K_INT_GENTIMER; |
294 | ath9k_hw_set_interrupts(ah, sc->imask); | 291 | ath9k_hw_set_interrupts(ah, ah->imask); |
295 | } | 292 | } |
296 | } | 293 | } |
297 | 294 | ||
298 | static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer) | 295 | static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer) |
299 | { | 296 | { |
300 | struct ath_common *common = ath9k_hw_common(ah); | ||
301 | struct ath_softc *sc = (struct ath_softc *) common->priv; | ||
302 | struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; | 297 | struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; |
303 | 298 | ||
304 | ath9k_hw_gen_timer_stop(ah, timer); | 299 | ath9k_hw_gen_timer_stop(ah, timer); |
@@ -306,8 +301,8 @@ static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer) | |||
306 | /* if no timer is enabled, turn off interrupt mask */ | 301 | /* if no timer is enabled, turn off interrupt mask */ |
307 | if (timer_table->timer_mask.val == 0) { | 302 | if (timer_table->timer_mask.val == 0) { |
308 | ath9k_hw_set_interrupts(ah, 0); | 303 | ath9k_hw_set_interrupts(ah, 0); |
309 | sc->imask &= ~ATH9K_INT_GENTIMER; | 304 | ah->imask &= ~ATH9K_INT_GENTIMER; |
310 | ath9k_hw_set_interrupts(ah, sc->imask); | 305 | ath9k_hw_set_interrupts(ah, ah->imask); |
311 | } | 306 | } |
312 | } | 307 | } |
313 | 308 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c new file mode 100644 index 000000000000..3afc747ccfbf --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c | |||
@@ -0,0 +1,965 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include "htc.h" | ||
18 | |||
19 | #define ATH9K_FW_USB_DEV(devid, fw) \ | ||
20 | { USB_DEVICE(0x0cf3, devid), .driver_info = (unsigned long) fw } | ||
21 | |||
22 | static struct usb_device_id ath9k_hif_usb_ids[] = { | ||
23 | ATH9K_FW_USB_DEV(0x9271, "ar9271.fw"), | ||
24 | ATH9K_FW_USB_DEV(0x1006, "ar9271.fw"), | ||
25 | { }, | ||
26 | }; | ||
27 | |||
28 | MODULE_DEVICE_TABLE(usb, ath9k_hif_usb_ids); | ||
29 | |||
30 | static int __hif_usb_tx(struct hif_device_usb *hif_dev); | ||
31 | |||
32 | static void hif_usb_regout_cb(struct urb *urb) | ||
33 | { | ||
34 | struct cmd_buf *cmd = (struct cmd_buf *)urb->context; | ||
35 | struct hif_device_usb *hif_dev = cmd->hif_dev; | ||
36 | |||
37 | if (!hif_dev) { | ||
38 | usb_free_urb(urb); | ||
39 | if (cmd) { | ||
40 | if (cmd->skb) | ||
41 | dev_kfree_skb_any(cmd->skb); | ||
42 | kfree(cmd); | ||
43 | } | ||
44 | return; | ||
45 | } | ||
46 | |||
47 | switch (urb->status) { | ||
48 | case 0: | ||
49 | break; | ||
50 | case -ENOENT: | ||
51 | case -ECONNRESET: | ||
52 | break; | ||
53 | case -ENODEV: | ||
54 | case -ESHUTDOWN: | ||
55 | return; | ||
56 | default: | ||
57 | break; | ||
58 | } | ||
59 | |||
60 | if (cmd) { | ||
61 | ath9k_htc_txcompletion_cb(cmd->hif_dev->htc_handle, | ||
62 | cmd->skb, 1); | ||
63 | kfree(cmd); | ||
64 | usb_free_urb(urb); | ||
65 | } | ||
66 | } | ||
67 | |||
68 | static int hif_usb_send_regout(struct hif_device_usb *hif_dev, | ||
69 | struct sk_buff *skb) | ||
70 | { | ||
71 | struct urb *urb; | ||
72 | struct cmd_buf *cmd; | ||
73 | int ret = 0; | ||
74 | |||
75 | urb = usb_alloc_urb(0, GFP_KERNEL); | ||
76 | if (urb == NULL) | ||
77 | return -ENOMEM; | ||
78 | |||
79 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
80 | if (cmd == NULL) { | ||
81 | usb_free_urb(urb); | ||
82 | return -ENOMEM; | ||
83 | } | ||
84 | |||
85 | cmd->skb = skb; | ||
86 | cmd->hif_dev = hif_dev; | ||
87 | |||
88 | usb_fill_int_urb(urb, hif_dev->udev, | ||
89 | usb_sndintpipe(hif_dev->udev, USB_REG_OUT_PIPE), | ||
90 | skb->data, skb->len, | ||
91 | hif_usb_regout_cb, cmd, 1); | ||
92 | |||
93 | ret = usb_submit_urb(urb, GFP_KERNEL); | ||
94 | if (ret) { | ||
95 | usb_free_urb(urb); | ||
96 | kfree(cmd); | ||
97 | } | ||
98 | |||
99 | return ret; | ||
100 | } | ||
101 | |||
102 | static void hif_usb_tx_cb(struct urb *urb) | ||
103 | { | ||
104 | struct tx_buf *tx_buf = (struct tx_buf *) urb->context; | ||
105 | struct hif_device_usb *hif_dev = tx_buf->hif_dev; | ||
106 | struct sk_buff *skb; | ||
107 | bool drop, flush; | ||
108 | |||
109 | if (!hif_dev) | ||
110 | return; | ||
111 | |||
112 | switch (urb->status) { | ||
113 | case 0: | ||
114 | break; | ||
115 | case -ENOENT: | ||
116 | case -ECONNRESET: | ||
117 | break; | ||
118 | case -ENODEV: | ||
119 | case -ESHUTDOWN: | ||
120 | return; | ||
121 | default: | ||
122 | break; | ||
123 | } | ||
124 | |||
125 | if (tx_buf) { | ||
126 | spin_lock(&hif_dev->tx.tx_lock); | ||
127 | drop = !!(hif_dev->tx.flags & HIF_USB_TX_STOP); | ||
128 | flush = !!(hif_dev->tx.flags & HIF_USB_TX_FLUSH); | ||
129 | spin_unlock(&hif_dev->tx.tx_lock); | ||
130 | |||
131 | while ((skb = __skb_dequeue(&tx_buf->skb_queue)) != NULL) { | ||
132 | if (!drop && !flush) { | ||
133 | ath9k_htc_txcompletion_cb(hif_dev->htc_handle, | ||
134 | skb, 1); | ||
135 | TX_STAT_INC(skb_completed); | ||
136 | } else { | ||
137 | dev_kfree_skb_any(skb); | ||
138 | } | ||
139 | } | ||
140 | |||
141 | if (flush) | ||
142 | return; | ||
143 | |||
144 | tx_buf->len = tx_buf->offset = 0; | ||
145 | __skb_queue_head_init(&tx_buf->skb_queue); | ||
146 | |||
147 | spin_lock(&hif_dev->tx.tx_lock); | ||
148 | list_del(&tx_buf->list); | ||
149 | list_add_tail(&tx_buf->list, &hif_dev->tx.tx_buf); | ||
150 | hif_dev->tx.tx_buf_cnt++; | ||
151 | if (!drop) | ||
152 | __hif_usb_tx(hif_dev); /* Check for pending SKBs */ | ||
153 | TX_STAT_INC(buf_completed); | ||
154 | spin_unlock(&hif_dev->tx.tx_lock); | ||
155 | } | ||
156 | } | ||
157 | |||
158 | /* TX lock has to be taken */ | ||
159 | static int __hif_usb_tx(struct hif_device_usb *hif_dev) | ||
160 | { | ||
161 | struct tx_buf *tx_buf = NULL; | ||
162 | struct sk_buff *nskb = NULL; | ||
163 | int ret = 0, i; | ||
164 | u16 *hdr, tx_skb_cnt = 0; | ||
165 | u8 *buf; | ||
166 | |||
167 | if (hif_dev->tx.tx_skb_cnt == 0) | ||
168 | return 0; | ||
169 | |||
170 | /* Check if a free TX buffer is available */ | ||
171 | if (list_empty(&hif_dev->tx.tx_buf)) | ||
172 | return 0; | ||
173 | |||
174 | tx_buf = list_first_entry(&hif_dev->tx.tx_buf, struct tx_buf, list); | ||
175 | list_del(&tx_buf->list); | ||
176 | list_add_tail(&tx_buf->list, &hif_dev->tx.tx_pending); | ||
177 | hif_dev->tx.tx_buf_cnt--; | ||
178 | |||
179 | tx_skb_cnt = min_t(u16, hif_dev->tx.tx_skb_cnt, MAX_TX_AGGR_NUM); | ||
180 | |||
181 | for (i = 0; i < tx_skb_cnt; i++) { | ||
182 | nskb = __skb_dequeue(&hif_dev->tx.tx_skb_queue); | ||
183 | |||
184 | /* Should never be NULL */ | ||
185 | BUG_ON(!nskb); | ||
186 | |||
187 | hif_dev->tx.tx_skb_cnt--; | ||
188 | |||
189 | buf = tx_buf->buf; | ||
190 | buf += tx_buf->offset; | ||
191 | hdr = (u16 *)buf; | ||
192 | *hdr++ = nskb->len; | ||
193 | *hdr++ = ATH_USB_TX_STREAM_MODE_TAG; | ||
194 | buf += 4; | ||
195 | memcpy(buf, nskb->data, nskb->len); | ||
196 | tx_buf->len = nskb->len + 4; | ||
197 | |||
198 | if (i < (tx_skb_cnt - 1)) | ||
199 | tx_buf->offset += (((tx_buf->len - 1) / 4) + 1) * 4; | ||
200 | |||
201 | if (i == (tx_skb_cnt - 1)) | ||
202 | tx_buf->len += tx_buf->offset; | ||
203 | |||
204 | __skb_queue_tail(&tx_buf->skb_queue, nskb); | ||
205 | TX_STAT_INC(skb_queued); | ||
206 | } | ||
207 | |||
208 | usb_fill_bulk_urb(tx_buf->urb, hif_dev->udev, | ||
209 | usb_sndbulkpipe(hif_dev->udev, USB_WLAN_TX_PIPE), | ||
210 | tx_buf->buf, tx_buf->len, | ||
211 | hif_usb_tx_cb, tx_buf); | ||
212 | |||
213 | ret = usb_submit_urb(tx_buf->urb, GFP_ATOMIC); | ||
214 | if (ret) { | ||
215 | tx_buf->len = tx_buf->offset = 0; | ||
216 | __skb_queue_purge(&tx_buf->skb_queue); | ||
217 | __skb_queue_head_init(&tx_buf->skb_queue); | ||
218 | list_move_tail(&tx_buf->list, &hif_dev->tx.tx_buf); | ||
219 | hif_dev->tx.tx_buf_cnt++; | ||
220 | } | ||
221 | |||
222 | if (!ret) | ||
223 | TX_STAT_INC(buf_queued); | ||
224 | |||
225 | return ret; | ||
226 | } | ||
227 | |||
228 | static int hif_usb_send_tx(struct hif_device_usb *hif_dev, struct sk_buff *skb, | ||
229 | struct ath9k_htc_tx_ctl *tx_ctl) | ||
230 | { | ||
231 | unsigned long flags; | ||
232 | |||
233 | spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); | ||
234 | |||
235 | if (hif_dev->tx.flags & HIF_USB_TX_STOP) { | ||
236 | spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); | ||
237 | return -ENODEV; | ||
238 | } | ||
239 | |||
240 | /* Check if the max queue count has been reached */ | ||
241 | if (hif_dev->tx.tx_skb_cnt > MAX_TX_BUF_NUM) { | ||
242 | spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); | ||
243 | return -ENOMEM; | ||
244 | } | ||
245 | |||
246 | __skb_queue_tail(&hif_dev->tx.tx_skb_queue, skb); | ||
247 | hif_dev->tx.tx_skb_cnt++; | ||
248 | |||
249 | /* Send normal frames immediately */ | ||
250 | if (!tx_ctl || (tx_ctl && (tx_ctl->type == ATH9K_HTC_NORMAL))) | ||
251 | __hif_usb_tx(hif_dev); | ||
252 | |||
253 | /* Check if AMPDUs have to be sent immediately */ | ||
254 | if (tx_ctl && (tx_ctl->type == ATH9K_HTC_AMPDU) && | ||
255 | (hif_dev->tx.tx_buf_cnt == MAX_TX_URB_NUM) && | ||
256 | (hif_dev->tx.tx_skb_cnt < 2)) { | ||
257 | __hif_usb_tx(hif_dev); | ||
258 | } | ||
259 | |||
260 | spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); | ||
261 | |||
262 | return 0; | ||
263 | } | ||
264 | |||
265 | static void hif_usb_start(void *hif_handle, u8 pipe_id) | ||
266 | { | ||
267 | struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle; | ||
268 | unsigned long flags; | ||
269 | |||
270 | hif_dev->flags |= HIF_USB_START; | ||
271 | |||
272 | spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); | ||
273 | hif_dev->tx.flags &= ~HIF_USB_TX_STOP; | ||
274 | spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); | ||
275 | } | ||
276 | |||
277 | static void hif_usb_stop(void *hif_handle, u8 pipe_id) | ||
278 | { | ||
279 | struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle; | ||
280 | unsigned long flags; | ||
281 | |||
282 | spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); | ||
283 | __skb_queue_purge(&hif_dev->tx.tx_skb_queue); | ||
284 | hif_dev->tx.tx_skb_cnt = 0; | ||
285 | hif_dev->tx.flags |= HIF_USB_TX_STOP; | ||
286 | spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); | ||
287 | } | ||
288 | |||
289 | static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb, | ||
290 | struct ath9k_htc_tx_ctl *tx_ctl) | ||
291 | { | ||
292 | struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle; | ||
293 | int ret = 0; | ||
294 | |||
295 | switch (pipe_id) { | ||
296 | case USB_WLAN_TX_PIPE: | ||
297 | ret = hif_usb_send_tx(hif_dev, skb, tx_ctl); | ||
298 | break; | ||
299 | case USB_REG_OUT_PIPE: | ||
300 | ret = hif_usb_send_regout(hif_dev, skb); | ||
301 | break; | ||
302 | default: | ||
303 | dev_err(&hif_dev->udev->dev, | ||
304 | "ath9k_htc: Invalid TX pipe: %d\n", pipe_id); | ||
305 | ret = -EINVAL; | ||
306 | break; | ||
307 | } | ||
308 | |||
309 | return ret; | ||
310 | } | ||
311 | |||
312 | static struct ath9k_htc_hif hif_usb = { | ||
313 | .transport = ATH9K_HIF_USB, | ||
314 | .name = "ath9k_hif_usb", | ||
315 | |||
316 | .control_ul_pipe = USB_REG_OUT_PIPE, | ||
317 | .control_dl_pipe = USB_REG_IN_PIPE, | ||
318 | |||
319 | .start = hif_usb_start, | ||
320 | .stop = hif_usb_stop, | ||
321 | .send = hif_usb_send, | ||
322 | }; | ||
323 | |||
324 | static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev, | ||
325 | struct sk_buff *skb) | ||
326 | { | ||
327 | struct sk_buff *nskb, *skb_pool[8]; | ||
328 | int index = 0, i = 0, chk_idx, len = skb->len; | ||
329 | int rx_remain_len = 0, rx_pkt_len = 0; | ||
330 | u16 pkt_len, pkt_tag, pool_index = 0; | ||
331 | u8 *ptr; | ||
332 | |||
333 | rx_remain_len = hif_dev->rx_remain_len; | ||
334 | rx_pkt_len = hif_dev->rx_transfer_len; | ||
335 | |||
336 | if (rx_remain_len != 0) { | ||
337 | struct sk_buff *remain_skb = hif_dev->remain_skb; | ||
338 | |||
339 | if (remain_skb) { | ||
340 | ptr = (u8 *) remain_skb->data; | ||
341 | |||
342 | index = rx_remain_len; | ||
343 | rx_remain_len -= hif_dev->rx_pad_len; | ||
344 | ptr += rx_pkt_len; | ||
345 | |||
346 | memcpy(ptr, skb->data, rx_remain_len); | ||
347 | |||
348 | rx_pkt_len += rx_remain_len; | ||
349 | hif_dev->rx_remain_len = 0; | ||
350 | skb_put(remain_skb, rx_pkt_len); | ||
351 | |||
352 | skb_pool[pool_index++] = remain_skb; | ||
353 | |||
354 | } else { | ||
355 | index = rx_remain_len; | ||
356 | } | ||
357 | } | ||
358 | |||
359 | while (index < len) { | ||
360 | ptr = (u8 *) skb->data; | ||
361 | |||
362 | pkt_len = ptr[index] + (ptr[index+1] << 8); | ||
363 | pkt_tag = ptr[index+2] + (ptr[index+3] << 8); | ||
364 | |||
365 | if (pkt_tag == ATH_USB_RX_STREAM_MODE_TAG) { | ||
366 | u16 pad_len; | ||
367 | |||
368 | pad_len = 4 - (pkt_len & 0x3); | ||
369 | if (pad_len == 4) | ||
370 | pad_len = 0; | ||
371 | |||
372 | chk_idx = index; | ||
373 | index = index + 4 + pkt_len + pad_len; | ||
374 | |||
375 | if (index > MAX_RX_BUF_SIZE) { | ||
376 | hif_dev->rx_remain_len = index - MAX_RX_BUF_SIZE; | ||
377 | hif_dev->rx_transfer_len = | ||
378 | MAX_RX_BUF_SIZE - chk_idx - 4; | ||
379 | hif_dev->rx_pad_len = pad_len; | ||
380 | |||
381 | nskb = __dev_alloc_skb(pkt_len + 32, | ||
382 | GFP_ATOMIC); | ||
383 | if (!nskb) { | ||
384 | dev_err(&hif_dev->udev->dev, | ||
385 | "ath9k_htc: RX memory allocation" | ||
386 | " error\n"); | ||
387 | goto err; | ||
388 | } | ||
389 | skb_reserve(nskb, 32); | ||
390 | RX_STAT_INC(skb_allocated); | ||
391 | |||
392 | memcpy(nskb->data, &(skb->data[chk_idx+4]), | ||
393 | hif_dev->rx_transfer_len); | ||
394 | |||
395 | /* Record the buffer pointer */ | ||
396 | hif_dev->remain_skb = nskb; | ||
397 | } else { | ||
398 | nskb = __dev_alloc_skb(pkt_len + 32, GFP_ATOMIC); | ||
399 | if (!nskb) { | ||
400 | dev_err(&hif_dev->udev->dev, | ||
401 | "ath9k_htc: RX memory allocation" | ||
402 | " error\n"); | ||
403 | goto err; | ||
404 | } | ||
405 | skb_reserve(nskb, 32); | ||
406 | RX_STAT_INC(skb_allocated); | ||
407 | |||
408 | memcpy(nskb->data, &(skb->data[chk_idx+4]), pkt_len); | ||
409 | skb_put(nskb, pkt_len); | ||
410 | skb_pool[pool_index++] = nskb; | ||
411 | } | ||
412 | } else { | ||
413 | RX_STAT_INC(skb_dropped); | ||
414 | return; | ||
415 | } | ||
416 | } | ||
417 | |||
418 | err: | ||
419 | for (i = 0; i < pool_index; i++) { | ||
420 | ath9k_htc_rx_msg(hif_dev->htc_handle, skb_pool[i], | ||
421 | skb_pool[i]->len, USB_WLAN_RX_PIPE); | ||
422 | RX_STAT_INC(skb_completed); | ||
423 | } | ||
424 | } | ||
425 | |||
426 | static void ath9k_hif_usb_rx_cb(struct urb *urb) | ||
427 | { | ||
428 | struct sk_buff *skb = (struct sk_buff *) urb->context; | ||
429 | struct hif_device_usb *hif_dev = (struct hif_device_usb *) | ||
430 | usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); | ||
431 | int ret; | ||
432 | |||
433 | if (!skb) | ||
434 | return; | ||
435 | |||
436 | if (!hif_dev) | ||
437 | goto free; | ||
438 | |||
439 | switch (urb->status) { | ||
440 | case 0: | ||
441 | break; | ||
442 | case -ENOENT: | ||
443 | case -ECONNRESET: | ||
444 | case -ENODEV: | ||
445 | case -ESHUTDOWN: | ||
446 | goto free; | ||
447 | default: | ||
448 | goto resubmit; | ||
449 | } | ||
450 | |||
451 | if (likely(urb->actual_length != 0)) { | ||
452 | skb_put(skb, urb->actual_length); | ||
453 | ath9k_hif_usb_rx_stream(hif_dev, skb); | ||
454 | } | ||
455 | |||
456 | resubmit: | ||
457 | skb_reset_tail_pointer(skb); | ||
458 | skb_trim(skb, 0); | ||
459 | |||
460 | usb_anchor_urb(urb, &hif_dev->rx_submitted); | ||
461 | ret = usb_submit_urb(urb, GFP_ATOMIC); | ||
462 | if (ret) { | ||
463 | usb_unanchor_urb(urb); | ||
464 | goto free; | ||
465 | } | ||
466 | |||
467 | return; | ||
468 | free: | ||
469 | dev_kfree_skb_any(skb); | ||
470 | } | ||
471 | |||
472 | static void ath9k_hif_usb_reg_in_cb(struct urb *urb) | ||
473 | { | ||
474 | struct sk_buff *skb = (struct sk_buff *) urb->context; | ||
475 | struct sk_buff *nskb; | ||
476 | struct hif_device_usb *hif_dev = (struct hif_device_usb *) | ||
477 | usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); | ||
478 | int ret; | ||
479 | |||
480 | if (!skb) | ||
481 | return; | ||
482 | |||
483 | if (!hif_dev) | ||
484 | goto free; | ||
485 | |||
486 | switch (urb->status) { | ||
487 | case 0: | ||
488 | break; | ||
489 | case -ENOENT: | ||
490 | case -ECONNRESET: | ||
491 | case -ENODEV: | ||
492 | case -ESHUTDOWN: | ||
493 | goto free; | ||
494 | default: | ||
495 | goto resubmit; | ||
496 | } | ||
497 | |||
498 | if (likely(urb->actual_length != 0)) { | ||
499 | skb_put(skb, urb->actual_length); | ||
500 | |||
501 | nskb = __dev_alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_ATOMIC); | ||
502 | if (!nskb) | ||
503 | goto resubmit; | ||
504 | |||
505 | usb_fill_int_urb(urb, hif_dev->udev, | ||
506 | usb_rcvintpipe(hif_dev->udev, USB_REG_IN_PIPE), | ||
507 | nskb->data, MAX_REG_IN_BUF_SIZE, | ||
508 | ath9k_hif_usb_reg_in_cb, nskb, 1); | ||
509 | |||
510 | ret = usb_submit_urb(urb, GFP_ATOMIC); | ||
511 | if (ret) { | ||
512 | dev_kfree_skb_any(nskb); | ||
513 | goto free; | ||
514 | } | ||
515 | |||
516 | ath9k_htc_rx_msg(hif_dev->htc_handle, skb, | ||
517 | skb->len, USB_REG_IN_PIPE); | ||
518 | |||
519 | return; | ||
520 | } | ||
521 | |||
522 | resubmit: | ||
523 | skb_reset_tail_pointer(skb); | ||
524 | skb_trim(skb, 0); | ||
525 | |||
526 | ret = usb_submit_urb(urb, GFP_ATOMIC); | ||
527 | if (ret) | ||
528 | goto free; | ||
529 | |||
530 | return; | ||
531 | free: | ||
532 | dev_kfree_skb_any(skb); | ||
533 | urb->context = NULL; | ||
534 | } | ||
535 | |||
536 | static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev) | ||
537 | { | ||
538 | unsigned long flags; | ||
539 | struct tx_buf *tx_buf = NULL, *tx_buf_tmp = NULL; | ||
540 | |||
541 | list_for_each_entry_safe(tx_buf, tx_buf_tmp, &hif_dev->tx.tx_buf, list) { | ||
542 | list_del(&tx_buf->list); | ||
543 | usb_free_urb(tx_buf->urb); | ||
544 | kfree(tx_buf->buf); | ||
545 | kfree(tx_buf); | ||
546 | } | ||
547 | |||
548 | spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); | ||
549 | hif_dev->tx.flags |= HIF_USB_TX_FLUSH; | ||
550 | spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); | ||
551 | |||
552 | list_for_each_entry_safe(tx_buf, tx_buf_tmp, | ||
553 | &hif_dev->tx.tx_pending, list) { | ||
554 | usb_kill_urb(tx_buf->urb); | ||
555 | list_del(&tx_buf->list); | ||
556 | usb_free_urb(tx_buf->urb); | ||
557 | kfree(tx_buf->buf); | ||
558 | kfree(tx_buf); | ||
559 | } | ||
560 | |||
561 | spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); | ||
562 | hif_dev->tx.flags &= ~HIF_USB_TX_FLUSH; | ||
563 | spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); | ||
564 | } | ||
565 | |||
566 | static int ath9k_hif_usb_alloc_tx_urbs(struct hif_device_usb *hif_dev) | ||
567 | { | ||
568 | struct tx_buf *tx_buf; | ||
569 | int i; | ||
570 | |||
571 | INIT_LIST_HEAD(&hif_dev->tx.tx_buf); | ||
572 | INIT_LIST_HEAD(&hif_dev->tx.tx_pending); | ||
573 | spin_lock_init(&hif_dev->tx.tx_lock); | ||
574 | __skb_queue_head_init(&hif_dev->tx.tx_skb_queue); | ||
575 | |||
576 | for (i = 0; i < MAX_TX_URB_NUM; i++) { | ||
577 | tx_buf = kzalloc(sizeof(struct tx_buf), GFP_KERNEL); | ||
578 | if (!tx_buf) | ||
579 | goto err; | ||
580 | |||
581 | tx_buf->buf = kzalloc(MAX_TX_BUF_SIZE, GFP_KERNEL); | ||
582 | if (!tx_buf->buf) | ||
583 | goto err; | ||
584 | |||
585 | tx_buf->urb = usb_alloc_urb(0, GFP_KERNEL); | ||
586 | if (!tx_buf->urb) | ||
587 | goto err; | ||
588 | |||
589 | tx_buf->hif_dev = hif_dev; | ||
590 | __skb_queue_head_init(&tx_buf->skb_queue); | ||
591 | |||
592 | list_add_tail(&tx_buf->list, &hif_dev->tx.tx_buf); | ||
593 | } | ||
594 | |||
595 | hif_dev->tx.tx_buf_cnt = MAX_TX_URB_NUM; | ||
596 | |||
597 | return 0; | ||
598 | err: | ||
599 | ath9k_hif_usb_dealloc_tx_urbs(hif_dev); | ||
600 | return -ENOMEM; | ||
601 | } | ||
602 | |||
603 | static void ath9k_hif_usb_dealloc_rx_urbs(struct hif_device_usb *hif_dev) | ||
604 | { | ||
605 | usb_kill_anchored_urbs(&hif_dev->rx_submitted); | ||
606 | } | ||
607 | |||
608 | static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev) | ||
609 | { | ||
610 | struct urb *urb = NULL; | ||
611 | struct sk_buff *skb = NULL; | ||
612 | int i, ret; | ||
613 | |||
614 | init_usb_anchor(&hif_dev->rx_submitted); | ||
615 | |||
616 | for (i = 0; i < MAX_RX_URB_NUM; i++) { | ||
617 | |||
618 | /* Allocate URB */ | ||
619 | urb = usb_alloc_urb(0, GFP_KERNEL); | ||
620 | if (urb == NULL) { | ||
621 | ret = -ENOMEM; | ||
622 | goto err_urb; | ||
623 | } | ||
624 | |||
625 | /* Allocate buffer */ | ||
626 | skb = __dev_alloc_skb(MAX_RX_BUF_SIZE, GFP_KERNEL); | ||
627 | if (!skb) { | ||
628 | ret = -ENOMEM; | ||
629 | goto err_skb; | ||
630 | } | ||
631 | |||
632 | usb_fill_bulk_urb(urb, hif_dev->udev, | ||
633 | usb_rcvbulkpipe(hif_dev->udev, | ||
634 | USB_WLAN_RX_PIPE), | ||
635 | skb->data, MAX_RX_BUF_SIZE, | ||
636 | ath9k_hif_usb_rx_cb, skb); | ||
637 | |||
638 | /* Anchor URB */ | ||
639 | usb_anchor_urb(urb, &hif_dev->rx_submitted); | ||
640 | |||
641 | /* Submit URB */ | ||
642 | ret = usb_submit_urb(urb, GFP_KERNEL); | ||
643 | if (ret) { | ||
644 | usb_unanchor_urb(urb); | ||
645 | goto err_submit; | ||
646 | } | ||
647 | } | ||
648 | |||
649 | return 0; | ||
650 | |||
651 | err_submit: | ||
652 | dev_kfree_skb_any(skb); | ||
653 | err_skb: | ||
654 | usb_free_urb(urb); | ||
655 | err_urb: | ||
656 | ath9k_hif_usb_dealloc_rx_urbs(hif_dev); | ||
657 | return ret; | ||
658 | } | ||
659 | |||
660 | static void ath9k_hif_usb_dealloc_reg_in_urb(struct hif_device_usb *hif_dev) | ||
661 | { | ||
662 | if (hif_dev->reg_in_urb) { | ||
663 | usb_kill_urb(hif_dev->reg_in_urb); | ||
664 | if (hif_dev->reg_in_urb->context) | ||
665 | dev_kfree_skb_any((void *)hif_dev->reg_in_urb->context); | ||
666 | usb_free_urb(hif_dev->reg_in_urb); | ||
667 | hif_dev->reg_in_urb = NULL; | ||
668 | } | ||
669 | } | ||
670 | |||
671 | static int ath9k_hif_usb_alloc_reg_in_urb(struct hif_device_usb *hif_dev) | ||
672 | { | ||
673 | struct sk_buff *skb; | ||
674 | |||
675 | hif_dev->reg_in_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
676 | if (hif_dev->reg_in_urb == NULL) | ||
677 | return -ENOMEM; | ||
678 | |||
679 | skb = __dev_alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_KERNEL); | ||
680 | if (!skb) | ||
681 | goto err; | ||
682 | |||
683 | usb_fill_int_urb(hif_dev->reg_in_urb, hif_dev->udev, | ||
684 | usb_rcvintpipe(hif_dev->udev, USB_REG_IN_PIPE), | ||
685 | skb->data, MAX_REG_IN_BUF_SIZE, | ||
686 | ath9k_hif_usb_reg_in_cb, skb, 1); | ||
687 | |||
688 | if (usb_submit_urb(hif_dev->reg_in_urb, GFP_KERNEL) != 0) | ||
689 | goto err; | ||
690 | |||
691 | return 0; | ||
692 | |||
693 | err: | ||
694 | ath9k_hif_usb_dealloc_reg_in_urb(hif_dev); | ||
695 | return -ENOMEM; | ||
696 | } | ||
697 | |||
698 | static int ath9k_hif_usb_alloc_urbs(struct hif_device_usb *hif_dev) | ||
699 | { | ||
700 | /* TX */ | ||
701 | if (ath9k_hif_usb_alloc_tx_urbs(hif_dev) < 0) | ||
702 | goto err; | ||
703 | |||
704 | /* RX */ | ||
705 | if (ath9k_hif_usb_alloc_rx_urbs(hif_dev) < 0) | ||
706 | goto err; | ||
707 | |||
708 | /* Register Read/Write */ | ||
709 | if (ath9k_hif_usb_alloc_reg_in_urb(hif_dev) < 0) | ||
710 | goto err; | ||
711 | |||
712 | return 0; | ||
713 | err: | ||
714 | return -ENOMEM; | ||
715 | } | ||
716 | |||
717 | static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev) | ||
718 | { | ||
719 | int transfer, err; | ||
720 | const void *data = hif_dev->firmware->data; | ||
721 | size_t len = hif_dev->firmware->size; | ||
722 | u32 addr = AR9271_FIRMWARE; | ||
723 | u8 *buf = kzalloc(4096, GFP_KERNEL); | ||
724 | |||
725 | if (!buf) | ||
726 | return -ENOMEM; | ||
727 | |||
728 | while (len) { | ||
729 | transfer = min_t(int, len, 4096); | ||
730 | memcpy(buf, data, transfer); | ||
731 | |||
732 | err = usb_control_msg(hif_dev->udev, | ||
733 | usb_sndctrlpipe(hif_dev->udev, 0), | ||
734 | FIRMWARE_DOWNLOAD, 0x40 | USB_DIR_OUT, | ||
735 | addr >> 8, 0, buf, transfer, HZ); | ||
736 | if (err < 0) { | ||
737 | kfree(buf); | ||
738 | return err; | ||
739 | } | ||
740 | |||
741 | len -= transfer; | ||
742 | data += transfer; | ||
743 | addr += transfer; | ||
744 | } | ||
745 | kfree(buf); | ||
746 | |||
747 | /* | ||
748 | * Issue FW download complete command to firmware. | ||
749 | */ | ||
750 | err = usb_control_msg(hif_dev->udev, usb_sndctrlpipe(hif_dev->udev, 0), | ||
751 | FIRMWARE_DOWNLOAD_COMP, | ||
752 | 0x40 | USB_DIR_OUT, | ||
753 | AR9271_FIRMWARE_TEXT >> 8, 0, NULL, 0, HZ); | ||
754 | if (err) | ||
755 | return -EIO; | ||
756 | |||
757 | dev_info(&hif_dev->udev->dev, "ath9k_htc: Transferred FW: %s, size: %ld\n", | ||
758 | "ar9271.fw", (unsigned long) hif_dev->firmware->size); | ||
759 | |||
760 | return 0; | ||
761 | } | ||
762 | |||
763 | static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev, | ||
764 | const char *fw_name) | ||
765 | { | ||
766 | int ret; | ||
767 | |||
768 | /* Request firmware */ | ||
769 | ret = request_firmware(&hif_dev->firmware, fw_name, &hif_dev->udev->dev); | ||
770 | if (ret) { | ||
771 | dev_err(&hif_dev->udev->dev, | ||
772 | "ath9k_htc: Firmware - %s not found\n", fw_name); | ||
773 | goto err_fw_req; | ||
774 | } | ||
775 | |||
776 | /* Download firmware */ | ||
777 | ret = ath9k_hif_usb_download_fw(hif_dev); | ||
778 | if (ret) { | ||
779 | dev_err(&hif_dev->udev->dev, | ||
780 | "ath9k_htc: Firmware - %s download failed\n", fw_name); | ||
781 | goto err_fw_download; | ||
782 | } | ||
783 | |||
784 | /* Alloc URBs */ | ||
785 | ret = ath9k_hif_usb_alloc_urbs(hif_dev); | ||
786 | if (ret) { | ||
787 | dev_err(&hif_dev->udev->dev, | ||
788 | "ath9k_htc: Unable to allocate URBs\n"); | ||
789 | goto err_urb; | ||
790 | } | ||
791 | |||
792 | return 0; | ||
793 | |||
794 | err_urb: | ||
795 | /* Nothing */ | ||
796 | err_fw_download: | ||
797 | release_firmware(hif_dev->firmware); | ||
798 | err_fw_req: | ||
799 | hif_dev->firmware = NULL; | ||
800 | return ret; | ||
801 | } | ||
802 | |||
803 | static void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev) | ||
804 | { | ||
805 | ath9k_hif_usb_dealloc_reg_in_urb(hif_dev); | ||
806 | ath9k_hif_usb_dealloc_tx_urbs(hif_dev); | ||
807 | ath9k_hif_usb_dealloc_rx_urbs(hif_dev); | ||
808 | } | ||
809 | |||
810 | static void ath9k_hif_usb_dev_deinit(struct hif_device_usb *hif_dev) | ||
811 | { | ||
812 | ath9k_hif_usb_dealloc_urbs(hif_dev); | ||
813 | if (hif_dev->firmware) | ||
814 | release_firmware(hif_dev->firmware); | ||
815 | } | ||
816 | |||
817 | static int ath9k_hif_usb_probe(struct usb_interface *interface, | ||
818 | const struct usb_device_id *id) | ||
819 | { | ||
820 | struct usb_device *udev = interface_to_usbdev(interface); | ||
821 | struct hif_device_usb *hif_dev; | ||
822 | const char *fw_name = (const char *) id->driver_info; | ||
823 | int ret = 0; | ||
824 | |||
825 | hif_dev = kzalloc(sizeof(struct hif_device_usb), GFP_KERNEL); | ||
826 | if (!hif_dev) { | ||
827 | ret = -ENOMEM; | ||
828 | goto err_alloc; | ||
829 | } | ||
830 | |||
831 | usb_get_dev(udev); | ||
832 | hif_dev->udev = udev; | ||
833 | hif_dev->interface = interface; | ||
834 | hif_dev->device_id = id->idProduct; | ||
835 | #ifdef CONFIG_PM | ||
836 | udev->reset_resume = 1; | ||
837 | #endif | ||
838 | usb_set_intfdata(interface, hif_dev); | ||
839 | |||
840 | ret = ath9k_hif_usb_dev_init(hif_dev, fw_name); | ||
841 | if (ret) { | ||
842 | ret = -EINVAL; | ||
843 | goto err_hif_init_usb; | ||
844 | } | ||
845 | |||
846 | hif_dev->htc_handle = ath9k_htc_hw_alloc(hif_dev); | ||
847 | if (hif_dev->htc_handle == NULL) { | ||
848 | ret = -ENOMEM; | ||
849 | goto err_htc_hw_alloc; | ||
850 | } | ||
851 | |||
852 | ret = ath9k_htc_hw_init(&hif_usb, hif_dev->htc_handle, hif_dev, | ||
853 | &hif_dev->udev->dev, hif_dev->device_id, | ||
854 | ATH9K_HIF_USB); | ||
855 | if (ret) { | ||
856 | ret = -EINVAL; | ||
857 | goto err_htc_hw_init; | ||
858 | } | ||
859 | |||
860 | dev_info(&hif_dev->udev->dev, "ath9k_htc: USB layer initialized\n"); | ||
861 | |||
862 | return 0; | ||
863 | |||
864 | err_htc_hw_init: | ||
865 | ath9k_htc_hw_free(hif_dev->htc_handle); | ||
866 | err_htc_hw_alloc: | ||
867 | ath9k_hif_usb_dev_deinit(hif_dev); | ||
868 | err_hif_init_usb: | ||
869 | usb_set_intfdata(interface, NULL); | ||
870 | kfree(hif_dev); | ||
871 | usb_put_dev(udev); | ||
872 | err_alloc: | ||
873 | return ret; | ||
874 | } | ||
875 | |||
876 | static void ath9k_hif_usb_disconnect(struct usb_interface *interface) | ||
877 | { | ||
878 | struct usb_device *udev = interface_to_usbdev(interface); | ||
879 | struct hif_device_usb *hif_dev = | ||
880 | (struct hif_device_usb *) usb_get_intfdata(interface); | ||
881 | |||
882 | if (hif_dev) { | ||
883 | ath9k_htc_hw_deinit(hif_dev->htc_handle, true); | ||
884 | ath9k_htc_hw_free(hif_dev->htc_handle); | ||
885 | ath9k_hif_usb_dev_deinit(hif_dev); | ||
886 | usb_set_intfdata(interface, NULL); | ||
887 | } | ||
888 | |||
889 | if (hif_dev->flags & HIF_USB_START) | ||
890 | usb_reset_device(udev); | ||
891 | |||
892 | kfree(hif_dev); | ||
893 | dev_info(&udev->dev, "ath9k_htc: USB layer deinitialized\n"); | ||
894 | usb_put_dev(udev); | ||
895 | } | ||
896 | |||
897 | #ifdef CONFIG_PM | ||
898 | static int ath9k_hif_usb_suspend(struct usb_interface *interface, | ||
899 | pm_message_t message) | ||
900 | { | ||
901 | struct hif_device_usb *hif_dev = | ||
902 | (struct hif_device_usb *) usb_get_intfdata(interface); | ||
903 | |||
904 | ath9k_hif_usb_dealloc_urbs(hif_dev); | ||
905 | |||
906 | return 0; | ||
907 | } | ||
908 | |||
909 | static int ath9k_hif_usb_resume(struct usb_interface *interface) | ||
910 | { | ||
911 | struct hif_device_usb *hif_dev = | ||
912 | (struct hif_device_usb *) usb_get_intfdata(interface); | ||
913 | int ret; | ||
914 | |||
915 | ret = ath9k_hif_usb_alloc_urbs(hif_dev); | ||
916 | if (ret) | ||
917 | return ret; | ||
918 | |||
919 | if (hif_dev->firmware) { | ||
920 | ret = ath9k_hif_usb_download_fw(hif_dev); | ||
921 | if (ret) | ||
922 | goto fail_resume; | ||
923 | } else { | ||
924 | ath9k_hif_usb_dealloc_urbs(hif_dev); | ||
925 | return -EIO; | ||
926 | } | ||
927 | |||
928 | mdelay(100); | ||
929 | |||
930 | ret = ath9k_htc_resume(hif_dev->htc_handle); | ||
931 | |||
932 | if (ret) | ||
933 | goto fail_resume; | ||
934 | |||
935 | return 0; | ||
936 | |||
937 | fail_resume: | ||
938 | ath9k_hif_usb_dealloc_urbs(hif_dev); | ||
939 | |||
940 | return ret; | ||
941 | } | ||
942 | #endif | ||
943 | |||
944 | static struct usb_driver ath9k_hif_usb_driver = { | ||
945 | .name = "ath9k_hif_usb", | ||
946 | .probe = ath9k_hif_usb_probe, | ||
947 | .disconnect = ath9k_hif_usb_disconnect, | ||
948 | #ifdef CONFIG_PM | ||
949 | .suspend = ath9k_hif_usb_suspend, | ||
950 | .resume = ath9k_hif_usb_resume, | ||
951 | .reset_resume = ath9k_hif_usb_resume, | ||
952 | #endif | ||
953 | .id_table = ath9k_hif_usb_ids, | ||
954 | .soft_unbind = 1, | ||
955 | }; | ||
956 | |||
957 | int ath9k_hif_usb_init(void) | ||
958 | { | ||
959 | return usb_register(&ath9k_hif_usb_driver); | ||
960 | } | ||
961 | |||
962 | void ath9k_hif_usb_exit(void) | ||
963 | { | ||
964 | usb_deregister(&ath9k_hif_usb_driver); | ||
965 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h new file mode 100644 index 000000000000..ea9257bdc411 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/hif_usb.h | |||
@@ -0,0 +1,102 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef HTC_USB_H | ||
18 | #define HTC_USB_H | ||
19 | |||
20 | #define AR9271_FIRMWARE 0x501000 | ||
21 | #define AR9271_FIRMWARE_TEXT 0x903000 | ||
22 | |||
23 | #define FIRMWARE_DOWNLOAD 0x30 | ||
24 | #define FIRMWARE_DOWNLOAD_COMP 0x31 | ||
25 | |||
26 | #define ATH_USB_RX_STREAM_MODE_TAG 0x4e00 | ||
27 | #define ATH_USB_TX_STREAM_MODE_TAG 0x697e | ||
28 | |||
29 | /* FIXME: Verify these numbers (with Windows) */ | ||
30 | #define MAX_TX_URB_NUM 8 | ||
31 | #define MAX_TX_BUF_NUM 1024 | ||
32 | #define MAX_TX_BUF_SIZE 32768 | ||
33 | #define MAX_TX_AGGR_NUM 20 | ||
34 | |||
35 | #define MAX_RX_URB_NUM 8 | ||
36 | #define MAX_RX_BUF_SIZE 16384 | ||
37 | |||
38 | #define MAX_REG_OUT_URB_NUM 1 | ||
39 | #define MAX_REG_OUT_BUF_NUM 8 | ||
40 | |||
41 | #define MAX_REG_IN_BUF_SIZE 64 | ||
42 | |||
43 | /* USB Endpoint definition */ | ||
44 | #define USB_WLAN_TX_PIPE 1 | ||
45 | #define USB_WLAN_RX_PIPE 2 | ||
46 | #define USB_REG_IN_PIPE 3 | ||
47 | #define USB_REG_OUT_PIPE 4 | ||
48 | |||
49 | #define HIF_USB_MAX_RXPIPES 2 | ||
50 | #define HIF_USB_MAX_TXPIPES 4 | ||
51 | |||
52 | struct tx_buf { | ||
53 | u8 *buf; | ||
54 | u16 len; | ||
55 | u16 offset; | ||
56 | struct urb *urb; | ||
57 | struct sk_buff_head skb_queue; | ||
58 | struct hif_device_usb *hif_dev; | ||
59 | struct list_head list; | ||
60 | }; | ||
61 | |||
62 | #define HIF_USB_TX_STOP BIT(0) | ||
63 | #define HIF_USB_TX_FLUSH BIT(1) | ||
64 | |||
65 | struct hif_usb_tx { | ||
66 | u8 flags; | ||
67 | u8 tx_buf_cnt; | ||
68 | u16 tx_skb_cnt; | ||
69 | struct sk_buff_head tx_skb_queue; | ||
70 | struct list_head tx_buf; | ||
71 | struct list_head tx_pending; | ||
72 | spinlock_t tx_lock; | ||
73 | }; | ||
74 | |||
75 | struct cmd_buf { | ||
76 | struct sk_buff *skb; | ||
77 | struct hif_device_usb *hif_dev; | ||
78 | }; | ||
79 | |||
80 | #define HIF_USB_START BIT(0) | ||
81 | |||
82 | struct hif_device_usb { | ||
83 | u16 device_id; | ||
84 | struct usb_device *udev; | ||
85 | struct usb_interface *interface; | ||
86 | const struct firmware *firmware; | ||
87 | struct htc_target *htc_handle; | ||
88 | struct hif_usb_tx tx; | ||
89 | struct urb *reg_in_urb; | ||
90 | struct usb_anchor rx_submitted; | ||
91 | struct sk_buff *remain_skb; | ||
92 | int rx_remain_len; | ||
93 | int rx_pkt_len; | ||
94 | int rx_transfer_len; | ||
95 | int rx_pad_len; | ||
96 | u8 flags; /* HIF_USB_* */ | ||
97 | }; | ||
98 | |||
99 | int ath9k_hif_usb_init(void); | ||
100 | void ath9k_hif_usb_exit(void); | ||
101 | |||
102 | #endif /* HTC_USB_H */ | ||
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h new file mode 100644 index 000000000000..78213fc71b09 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/htc.h | |||
@@ -0,0 +1,462 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef HTC_H | ||
18 | #define HTC_H | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | #include <linux/usb.h> | ||
22 | #include <linux/firmware.h> | ||
23 | #include <linux/skbuff.h> | ||
24 | #include <linux/netdevice.h> | ||
25 | #include <linux/leds.h> | ||
26 | #include <net/mac80211.h> | ||
27 | |||
28 | #include "common.h" | ||
29 | #include "htc_hst.h" | ||
30 | #include "hif_usb.h" | ||
31 | #include "wmi.h" | ||
32 | |||
33 | #define ATH_STA_SHORT_CALINTERVAL 1000 /* 1 second */ | ||
34 | #define ATH_ANI_POLLINTERVAL 100 /* 100 ms */ | ||
35 | #define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */ | ||
36 | #define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ | ||
37 | |||
38 | #define ATH_DEFAULT_BMISS_LIMIT 10 | ||
39 | #define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024) | ||
40 | #define TSF_TO_TU(_h, _l) \ | ||
41 | ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10)) | ||
42 | |||
43 | extern struct ieee80211_ops ath9k_htc_ops; | ||
44 | extern int htc_modparam_nohwcrypt; | ||
45 | |||
46 | enum htc_phymode { | ||
47 | HTC_MODE_AUTO = 0, | ||
48 | HTC_MODE_11A = 1, | ||
49 | HTC_MODE_11B = 2, | ||
50 | HTC_MODE_11G = 3, | ||
51 | HTC_MODE_FH = 4, | ||
52 | HTC_MODE_TURBO_A = 5, | ||
53 | HTC_MODE_TURBO_G = 6, | ||
54 | HTC_MODE_11NA = 7, | ||
55 | HTC_MODE_11NG = 8 | ||
56 | }; | ||
57 | |||
58 | enum htc_opmode { | ||
59 | HTC_M_STA = 1, | ||
60 | HTC_M_IBSS = 0, | ||
61 | HTC_M_AHDEMO = 3, | ||
62 | HTC_M_HOSTAP = 6, | ||
63 | HTC_M_MONITOR = 8, | ||
64 | HTC_M_WDS = 2 | ||
65 | }; | ||
66 | |||
67 | #define ATH9K_HTC_HDRSPACE sizeof(struct htc_frame_hdr) | ||
68 | #define ATH9K_HTC_AMPDU 1 | ||
69 | #define ATH9K_HTC_NORMAL 2 | ||
70 | |||
71 | #define ATH9K_HTC_TX_CTSONLY 0x1 | ||
72 | #define ATH9K_HTC_TX_RTSCTS 0x2 | ||
73 | #define ATH9K_HTC_TX_USE_MIN_RATE 0x100 | ||
74 | |||
75 | struct tx_frame_hdr { | ||
76 | u8 data_type; | ||
77 | u8 node_idx; | ||
78 | u8 vif_idx; | ||
79 | u8 tidno; | ||
80 | u32 flags; /* ATH9K_HTC_TX_* */ | ||
81 | u8 key_type; | ||
82 | u8 keyix; | ||
83 | u8 reserved[26]; | ||
84 | } __packed; | ||
85 | |||
86 | struct tx_mgmt_hdr { | ||
87 | u8 node_idx; | ||
88 | u8 vif_idx; | ||
89 | u8 tidno; | ||
90 | u8 flags; | ||
91 | u8 key_type; | ||
92 | u8 keyix; | ||
93 | u16 reserved; | ||
94 | } __packed; | ||
95 | |||
96 | struct tx_beacon_header { | ||
97 | u8 len_changed; | ||
98 | u8 vif_index; | ||
99 | u16 rev; | ||
100 | } __packed; | ||
101 | |||
102 | struct ath9k_htc_target_hw { | ||
103 | u32 flags; | ||
104 | u32 flags_ext; | ||
105 | u32 ampdu_limit; | ||
106 | u8 ampdu_subframes; | ||
107 | u8 tx_chainmask; | ||
108 | u8 tx_chainmask_legacy; | ||
109 | u8 rtscts_ratecode; | ||
110 | u8 protmode; | ||
111 | } __packed; | ||
112 | |||
113 | struct ath9k_htc_cap_target { | ||
114 | u32 flags; | ||
115 | u32 flags_ext; | ||
116 | u32 ampdu_limit; | ||
117 | u8 ampdu_subframes; | ||
118 | u8 tx_chainmask; | ||
119 | u8 tx_chainmask_legacy; | ||
120 | u8 rtscts_ratecode; | ||
121 | u8 protmode; | ||
122 | } __packed; | ||
123 | |||
124 | struct ath9k_htc_target_vif { | ||
125 | u8 index; | ||
126 | u8 des_bssid[ETH_ALEN]; | ||
127 | enum htc_opmode opmode; | ||
128 | u8 myaddr[ETH_ALEN]; | ||
129 | u8 bssid[ETH_ALEN]; | ||
130 | u32 flags; | ||
131 | u32 flags_ext; | ||
132 | u16 ps_sta; | ||
133 | u16 rtsthreshold; | ||
134 | u8 ath_cap; | ||
135 | u8 node; | ||
136 | s8 mcast_rate; | ||
137 | } __packed; | ||
138 | |||
139 | #define ATH_HTC_STA_AUTH 0x0001 | ||
140 | #define ATH_HTC_STA_QOS 0x0002 | ||
141 | #define ATH_HTC_STA_ERP 0x0004 | ||
142 | #define ATH_HTC_STA_HT 0x0008 | ||
143 | |||
144 | /* FIXME: UAPSD variables */ | ||
145 | struct ath9k_htc_target_sta { | ||
146 | u16 associd; | ||
147 | u16 txpower; | ||
148 | u32 ucastkey; | ||
149 | u8 macaddr[ETH_ALEN]; | ||
150 | u8 bssid[ETH_ALEN]; | ||
151 | u8 sta_index; | ||
152 | u8 vif_index; | ||
153 | u8 vif_sta; | ||
154 | u16 flags; /* ATH_HTC_STA_* */ | ||
155 | u16 htcap; | ||
156 | u8 valid; | ||
157 | u16 capinfo; | ||
158 | struct ath9k_htc_target_hw *hw; | ||
159 | struct ath9k_htc_target_vif *vif; | ||
160 | u16 txseqmgmt; | ||
161 | u8 is_vif_sta; | ||
162 | u16 maxampdu; | ||
163 | u16 iv16; | ||
164 | u32 iv32; | ||
165 | } __packed; | ||
166 | |||
167 | struct ath9k_htc_target_aggr { | ||
168 | u8 sta_index; | ||
169 | u8 tidno; | ||
170 | u8 aggr_enable; | ||
171 | u8 padding; | ||
172 | } __packed; | ||
173 | |||
174 | #define ATH_HTC_RATE_MAX 30 | ||
175 | |||
176 | #define WLAN_RC_DS_FLAG 0x01 | ||
177 | #define WLAN_RC_40_FLAG 0x02 | ||
178 | #define WLAN_RC_SGI_FLAG 0x04 | ||
179 | #define WLAN_RC_HT_FLAG 0x08 | ||
180 | |||
181 | struct ath9k_htc_rateset { | ||
182 | u8 rs_nrates; | ||
183 | u8 rs_rates[ATH_HTC_RATE_MAX]; | ||
184 | }; | ||
185 | |||
186 | struct ath9k_htc_rate { | ||
187 | struct ath9k_htc_rateset legacy_rates; | ||
188 | struct ath9k_htc_rateset ht_rates; | ||
189 | } __packed; | ||
190 | |||
191 | struct ath9k_htc_target_rate { | ||
192 | u8 sta_index; | ||
193 | u8 isnew; | ||
194 | u32 capflags; | ||
195 | struct ath9k_htc_rate rates; | ||
196 | }; | ||
197 | |||
198 | struct ath9k_htc_target_stats { | ||
199 | u32 tx_shortretry; | ||
200 | u32 tx_longretry; | ||
201 | u32 tx_xretries; | ||
202 | u32 ht_txunaggr_xretry; | ||
203 | u32 ht_tx_xretries; | ||
204 | } __packed; | ||
205 | |||
206 | struct ath9k_htc_vif { | ||
207 | u8 index; | ||
208 | }; | ||
209 | |||
210 | #define ATH9K_HTC_MAX_STA 8 | ||
211 | #define ATH9K_HTC_MAX_TID 8 | ||
212 | |||
213 | enum tid_aggr_state { | ||
214 | AGGR_STOP = 0, | ||
215 | AGGR_PROGRESS, | ||
216 | AGGR_START, | ||
217 | AGGR_OPERATIONAL | ||
218 | }; | ||
219 | |||
220 | struct ath9k_htc_sta { | ||
221 | u8 index; | ||
222 | enum tid_aggr_state tid_state[ATH9K_HTC_MAX_TID]; | ||
223 | }; | ||
224 | |||
225 | struct ath9k_htc_aggr_work { | ||
226 | u16 tid; | ||
227 | u8 sta_addr[ETH_ALEN]; | ||
228 | struct ieee80211_hw *hw; | ||
229 | struct ieee80211_vif *vif; | ||
230 | enum ieee80211_ampdu_mlme_action action; | ||
231 | struct mutex mutex; | ||
232 | }; | ||
233 | |||
234 | #define ATH9K_HTC_RXBUF 256 | ||
235 | #define HTC_RX_FRAME_HEADER_SIZE 40 | ||
236 | |||
237 | struct ath9k_htc_rxbuf { | ||
238 | bool in_process; | ||
239 | struct sk_buff *skb; | ||
240 | struct ath_htc_rx_status rxstatus; | ||
241 | struct list_head list; | ||
242 | }; | ||
243 | |||
244 | struct ath9k_htc_rx { | ||
245 | int last_rssi; /* FIXME: per-STA */ | ||
246 | struct list_head rxbuf; | ||
247 | spinlock_t rxbuflock; | ||
248 | }; | ||
249 | |||
250 | struct ath9k_htc_tx_ctl { | ||
251 | u8 type; /* ATH9K_HTC_* */ | ||
252 | }; | ||
253 | |||
254 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS | ||
255 | |||
256 | #define TX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c++) | ||
257 | #define RX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.rx_stats.c++) | ||
258 | |||
259 | struct ath_tx_stats { | ||
260 | u32 buf_queued; | ||
261 | u32 buf_completed; | ||
262 | u32 skb_queued; | ||
263 | u32 skb_completed; | ||
264 | }; | ||
265 | |||
266 | struct ath_rx_stats { | ||
267 | u32 skb_allocated; | ||
268 | u32 skb_completed; | ||
269 | u32 skb_dropped; | ||
270 | }; | ||
271 | |||
272 | struct ath9k_debug { | ||
273 | struct dentry *debugfs_phy; | ||
274 | struct dentry *debugfs_tgt_stats; | ||
275 | struct dentry *debugfs_xmit; | ||
276 | struct dentry *debugfs_recv; | ||
277 | struct ath_tx_stats tx_stats; | ||
278 | struct ath_rx_stats rx_stats; | ||
279 | u32 txrate; | ||
280 | }; | ||
281 | |||
282 | #else | ||
283 | |||
284 | #define TX_STAT_INC(c) do { } while (0) | ||
285 | #define RX_STAT_INC(c) do { } while (0) | ||
286 | |||
287 | #endif /* CONFIG_ATH9K_HTC_DEBUGFS */ | ||
288 | |||
289 | #define ATH_LED_PIN_DEF 1 | ||
290 | #define ATH_LED_PIN_9287 8 | ||
291 | #define ATH_LED_PIN_9271 15 | ||
292 | #define ATH_LED_ON_DURATION_IDLE 350 /* in msecs */ | ||
293 | #define ATH_LED_OFF_DURATION_IDLE 250 /* in msecs */ | ||
294 | |||
295 | enum ath_led_type { | ||
296 | ATH_LED_RADIO, | ||
297 | ATH_LED_ASSOC, | ||
298 | ATH_LED_TX, | ||
299 | ATH_LED_RX | ||
300 | }; | ||
301 | |||
302 | struct ath_led { | ||
303 | struct ath9k_htc_priv *priv; | ||
304 | struct led_classdev led_cdev; | ||
305 | enum ath_led_type led_type; | ||
306 | struct delayed_work brightness_work; | ||
307 | char name[32]; | ||
308 | bool registered; | ||
309 | int brightness; | ||
310 | }; | ||
311 | |||
312 | struct htc_beacon_config { | ||
313 | u16 beacon_interval; | ||
314 | u16 listen_interval; | ||
315 | u16 dtim_period; | ||
316 | u16 bmiss_timeout; | ||
317 | u8 dtim_count; | ||
318 | }; | ||
319 | |||
320 | #define OP_INVALID BIT(0) | ||
321 | #define OP_SCANNING BIT(1) | ||
322 | #define OP_FULL_RESET BIT(2) | ||
323 | #define OP_LED_ASSOCIATED BIT(3) | ||
324 | #define OP_LED_ON BIT(4) | ||
325 | #define OP_PREAMBLE_SHORT BIT(5) | ||
326 | #define OP_PROTECT_ENABLE BIT(6) | ||
327 | #define OP_TXAGGR BIT(7) | ||
328 | #define OP_ASSOCIATED BIT(8) | ||
329 | #define OP_ENABLE_BEACON BIT(9) | ||
330 | #define OP_LED_DEINIT BIT(10) | ||
331 | |||
332 | struct ath9k_htc_priv { | ||
333 | struct device *dev; | ||
334 | struct ieee80211_hw *hw; | ||
335 | struct ath_hw *ah; | ||
336 | struct htc_target *htc; | ||
337 | struct wmi *wmi; | ||
338 | |||
339 | enum htc_endpoint_id wmi_cmd_ep; | ||
340 | enum htc_endpoint_id beacon_ep; | ||
341 | enum htc_endpoint_id cab_ep; | ||
342 | enum htc_endpoint_id uapsd_ep; | ||
343 | enum htc_endpoint_id mgmt_ep; | ||
344 | enum htc_endpoint_id data_be_ep; | ||
345 | enum htc_endpoint_id data_bk_ep; | ||
346 | enum htc_endpoint_id data_vi_ep; | ||
347 | enum htc_endpoint_id data_vo_ep; | ||
348 | |||
349 | u16 op_flags; | ||
350 | u16 curtxpow; | ||
351 | u16 txpowlimit; | ||
352 | u16 nvifs; | ||
353 | u16 nstations; | ||
354 | u16 seq_no; | ||
355 | u32 bmiss_cnt; | ||
356 | |||
357 | struct sk_buff *beacon; | ||
358 | spinlock_t beacon_lock; | ||
359 | |||
360 | bool tx_queues_stop; | ||
361 | spinlock_t tx_lock; | ||
362 | |||
363 | struct ieee80211_vif *vif; | ||
364 | struct htc_beacon_config cur_beacon_conf; | ||
365 | unsigned int rxfilter; | ||
366 | struct tasklet_struct wmi_tasklet; | ||
367 | struct tasklet_struct rx_tasklet; | ||
368 | struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; | ||
369 | struct ath9k_htc_rx rx; | ||
370 | struct tasklet_struct tx_tasklet; | ||
371 | struct sk_buff_head tx_queue; | ||
372 | struct ath9k_htc_aggr_work aggr_work; | ||
373 | struct delayed_work ath9k_aggr_work; | ||
374 | struct delayed_work ath9k_ani_work; | ||
375 | struct work_struct ps_work; | ||
376 | |||
377 | struct mutex htc_pm_lock; | ||
378 | unsigned long ps_usecount; | ||
379 | bool ps_enabled; | ||
380 | |||
381 | struct ath_led radio_led; | ||
382 | struct ath_led assoc_led; | ||
383 | struct ath_led tx_led; | ||
384 | struct ath_led rx_led; | ||
385 | struct delayed_work ath9k_led_blink_work; | ||
386 | int led_on_duration; | ||
387 | int led_off_duration; | ||
388 | int led_on_cnt; | ||
389 | int led_off_cnt; | ||
390 | int hwq_map[ATH9K_WME_AC_VO+1]; | ||
391 | |||
392 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS | ||
393 | struct ath9k_debug debug; | ||
394 | #endif | ||
395 | struct ath9k_htc_target_rate tgt_rate; | ||
396 | |||
397 | struct mutex mutex; | ||
398 | }; | ||
399 | |||
400 | static inline void ath_read_cachesize(struct ath_common *common, int *csz) | ||
401 | { | ||
402 | common->bus_ops->read_cachesize(common, csz); | ||
403 | } | ||
404 | |||
405 | void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, | ||
406 | struct ieee80211_vif *vif); | ||
407 | void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending); | ||
408 | void ath9k_htc_beacon_update(struct ath9k_htc_priv *priv, | ||
409 | struct ieee80211_vif *vif); | ||
410 | |||
411 | void ath9k_htc_rxep(void *priv, struct sk_buff *skb, | ||
412 | enum htc_endpoint_id ep_id); | ||
413 | void ath9k_htc_txep(void *priv, struct sk_buff *skb, enum htc_endpoint_id ep_id, | ||
414 | bool txok); | ||
415 | |||
416 | void ath9k_htc_station_work(struct work_struct *work); | ||
417 | void ath9k_htc_aggr_work(struct work_struct *work); | ||
418 | void ath9k_ani_work(struct work_struct *work);; | ||
419 | |||
420 | int ath9k_tx_init(struct ath9k_htc_priv *priv); | ||
421 | void ath9k_tx_tasklet(unsigned long data); | ||
422 | int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb); | ||
423 | void ath9k_tx_cleanup(struct ath9k_htc_priv *priv); | ||
424 | bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, | ||
425 | enum ath9k_tx_queue_subtype qtype); | ||
426 | int get_hw_qnum(u16 queue, int *hwq_map); | ||
427 | int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum, | ||
428 | struct ath9k_tx_queue_info *qinfo); | ||
429 | |||
430 | int ath9k_rx_init(struct ath9k_htc_priv *priv); | ||
431 | void ath9k_rx_cleanup(struct ath9k_htc_priv *priv); | ||
432 | void ath9k_host_rx_init(struct ath9k_htc_priv *priv); | ||
433 | void ath9k_rx_tasklet(unsigned long data); | ||
434 | u32 ath9k_htc_calcrxfilter(struct ath9k_htc_priv *priv); | ||
435 | |||
436 | void ath9k_htc_ps_wakeup(struct ath9k_htc_priv *priv); | ||
437 | void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv); | ||
438 | void ath9k_ps_work(struct work_struct *work); | ||
439 | |||
440 | void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv); | ||
441 | void ath9k_init_leds(struct ath9k_htc_priv *priv); | ||
442 | void ath9k_deinit_leds(struct ath9k_htc_priv *priv); | ||
443 | |||
444 | int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, | ||
445 | u16 devid); | ||
446 | void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug); | ||
447 | #ifdef CONFIG_PM | ||
448 | int ath9k_htc_resume(struct htc_target *htc_handle); | ||
449 | #endif | ||
450 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS | ||
451 | int ath9k_htc_debug_create_root(void); | ||
452 | void ath9k_htc_debug_remove_root(void); | ||
453 | int ath9k_htc_init_debug(struct ath_hw *ah); | ||
454 | void ath9k_htc_exit_debug(struct ath_hw *ah); | ||
455 | #else | ||
456 | static inline int ath9k_htc_debug_create_root(void) { return 0; }; | ||
457 | static inline void ath9k_htc_debug_remove_root(void) {}; | ||
458 | static inline int ath9k_htc_init_debug(struct ath_hw *ah) { return 0; }; | ||
459 | static inline void ath9k_htc_exit_debug(struct ath_hw *ah) {}; | ||
460 | #endif /* CONFIG_ATH9K_HTC_DEBUGFS */ | ||
461 | |||
462 | #endif /* HTC_H */ | ||
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c new file mode 100644 index 000000000000..5e21f4d92ff5 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c | |||
@@ -0,0 +1,277 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include "htc.h" | ||
18 | |||
19 | #define FUDGE 2 | ||
20 | |||
21 | static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv, | ||
22 | struct htc_beacon_config *bss_conf) | ||
23 | { | ||
24 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
25 | struct ath9k_beacon_state bs; | ||
26 | enum ath9k_int imask = 0; | ||
27 | int dtimperiod, dtimcount, sleepduration; | ||
28 | int cfpperiod, cfpcount, bmiss_timeout; | ||
29 | u32 nexttbtt = 0, intval, tsftu, htc_imask = 0; | ||
30 | u64 tsf; | ||
31 | int num_beacons, offset, dtim_dec_count, cfp_dec_count; | ||
32 | int ret; | ||
33 | u8 cmd_rsp; | ||
34 | |||
35 | memset(&bs, 0, sizeof(bs)); | ||
36 | |||
37 | intval = bss_conf->beacon_interval & ATH9K_BEACON_PERIOD; | ||
38 | bmiss_timeout = (ATH_DEFAULT_BMISS_LIMIT * bss_conf->beacon_interval); | ||
39 | |||
40 | /* | ||
41 | * Setup dtim and cfp parameters according to | ||
42 | * last beacon we received (which may be none). | ||
43 | */ | ||
44 | dtimperiod = bss_conf->dtim_period; | ||
45 | if (dtimperiod <= 0) /* NB: 0 if not known */ | ||
46 | dtimperiod = 1; | ||
47 | dtimcount = 1; | ||
48 | if (dtimcount >= dtimperiod) /* NB: sanity check */ | ||
49 | dtimcount = 0; | ||
50 | cfpperiod = 1; /* NB: no PCF support yet */ | ||
51 | cfpcount = 0; | ||
52 | |||
53 | sleepduration = intval; | ||
54 | if (sleepduration <= 0) | ||
55 | sleepduration = intval; | ||
56 | |||
57 | /* | ||
58 | * Pull nexttbtt forward to reflect the current | ||
59 | * TSF and calculate dtim+cfp state for the result. | ||
60 | */ | ||
61 | tsf = ath9k_hw_gettsf64(priv->ah); | ||
62 | tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE; | ||
63 | |||
64 | num_beacons = tsftu / intval + 1; | ||
65 | offset = tsftu % intval; | ||
66 | nexttbtt = tsftu - offset; | ||
67 | if (offset) | ||
68 | nexttbtt += intval; | ||
69 | |||
70 | /* DTIM Beacon every dtimperiod Beacon */ | ||
71 | dtim_dec_count = num_beacons % dtimperiod; | ||
72 | /* CFP every cfpperiod DTIM Beacon */ | ||
73 | cfp_dec_count = (num_beacons / dtimperiod) % cfpperiod; | ||
74 | if (dtim_dec_count) | ||
75 | cfp_dec_count++; | ||
76 | |||
77 | dtimcount -= dtim_dec_count; | ||
78 | if (dtimcount < 0) | ||
79 | dtimcount += dtimperiod; | ||
80 | |||
81 | cfpcount -= cfp_dec_count; | ||
82 | if (cfpcount < 0) | ||
83 | cfpcount += cfpperiod; | ||
84 | |||
85 | bs.bs_intval = intval; | ||
86 | bs.bs_nexttbtt = nexttbtt; | ||
87 | bs.bs_dtimperiod = dtimperiod*intval; | ||
88 | bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount*intval; | ||
89 | bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod; | ||
90 | bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod; | ||
91 | bs.bs_cfpmaxduration = 0; | ||
92 | |||
93 | /* | ||
94 | * Calculate the number of consecutive beacons to miss* before taking | ||
95 | * a BMISS interrupt. The configuration is specified in TU so we only | ||
96 | * need calculate based on the beacon interval. Note that we clamp the | ||
97 | * result to at most 15 beacons. | ||
98 | */ | ||
99 | if (sleepduration > intval) { | ||
100 | bs.bs_bmissthreshold = ATH_DEFAULT_BMISS_LIMIT / 2; | ||
101 | } else { | ||
102 | bs.bs_bmissthreshold = DIV_ROUND_UP(bmiss_timeout, intval); | ||
103 | if (bs.bs_bmissthreshold > 15) | ||
104 | bs.bs_bmissthreshold = 15; | ||
105 | else if (bs.bs_bmissthreshold <= 0) | ||
106 | bs.bs_bmissthreshold = 1; | ||
107 | } | ||
108 | |||
109 | /* | ||
110 | * Calculate sleep duration. The configuration is given in ms. | ||
111 | * We ensure a multiple of the beacon period is used. Also, if the sleep | ||
112 | * duration is greater than the DTIM period then it makes senses | ||
113 | * to make it a multiple of that. | ||
114 | * | ||
115 | * XXX fixed at 100ms | ||
116 | */ | ||
117 | |||
118 | bs.bs_sleepduration = roundup(IEEE80211_MS_TO_TU(100), sleepduration); | ||
119 | if (bs.bs_sleepduration > bs.bs_dtimperiod) | ||
120 | bs.bs_sleepduration = bs.bs_dtimperiod; | ||
121 | |||
122 | /* TSF out of range threshold fixed at 1 second */ | ||
123 | bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD; | ||
124 | |||
125 | ath_print(common, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu); | ||
126 | ath_print(common, ATH_DBG_BEACON, | ||
127 | "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n", | ||
128 | bs.bs_bmissthreshold, bs.bs_sleepduration, | ||
129 | bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext); | ||
130 | |||
131 | /* Set the computed STA beacon timers */ | ||
132 | |||
133 | WMI_CMD(WMI_DISABLE_INTR_CMDID); | ||
134 | ath9k_hw_set_sta_beacon_timers(priv->ah, &bs); | ||
135 | imask |= ATH9K_INT_BMISS; | ||
136 | htc_imask = cpu_to_be32(imask); | ||
137 | WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); | ||
138 | } | ||
139 | |||
140 | static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv, | ||
141 | struct htc_beacon_config *bss_conf) | ||
142 | { | ||
143 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
144 | enum ath9k_int imask = 0; | ||
145 | u32 nexttbtt, intval, htc_imask = 0; | ||
146 | int ret; | ||
147 | u8 cmd_rsp; | ||
148 | |||
149 | intval = bss_conf->beacon_interval & ATH9K_BEACON_PERIOD; | ||
150 | nexttbtt = intval; | ||
151 | intval |= ATH9K_BEACON_ENA; | ||
152 | if (priv->op_flags & OP_ENABLE_BEACON) | ||
153 | imask |= ATH9K_INT_SWBA; | ||
154 | |||
155 | ath_print(common, ATH_DBG_BEACON, | ||
156 | "IBSS Beacon config, intval: %d, imask: 0x%x\n", | ||
157 | bss_conf->beacon_interval, imask); | ||
158 | |||
159 | WMI_CMD(WMI_DISABLE_INTR_CMDID); | ||
160 | ath9k_hw_beaconinit(priv->ah, nexttbtt, intval); | ||
161 | priv->bmiss_cnt = 0; | ||
162 | htc_imask = cpu_to_be32(imask); | ||
163 | WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); | ||
164 | } | ||
165 | |||
166 | void ath9k_htc_beacon_update(struct ath9k_htc_priv *priv, | ||
167 | struct ieee80211_vif *vif) | ||
168 | { | ||
169 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
170 | |||
171 | spin_lock_bh(&priv->beacon_lock); | ||
172 | |||
173 | if (priv->beacon) | ||
174 | dev_kfree_skb_any(priv->beacon); | ||
175 | |||
176 | priv->beacon = ieee80211_beacon_get(priv->hw, vif); | ||
177 | if (!priv->beacon) | ||
178 | ath_print(common, ATH_DBG_BEACON, | ||
179 | "Unable to allocate beacon\n"); | ||
180 | |||
181 | spin_unlock_bh(&priv->beacon_lock); | ||
182 | } | ||
183 | |||
184 | void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending) | ||
185 | { | ||
186 | struct ath9k_htc_vif *avp = (void *)priv->vif->drv_priv; | ||
187 | struct tx_beacon_header beacon_hdr; | ||
188 | struct ath9k_htc_tx_ctl tx_ctl; | ||
189 | struct ieee80211_tx_info *info; | ||
190 | u8 *tx_fhdr; | ||
191 | |||
192 | memset(&beacon_hdr, 0, sizeof(struct tx_beacon_header)); | ||
193 | memset(&tx_ctl, 0, sizeof(struct ath9k_htc_tx_ctl)); | ||
194 | |||
195 | /* FIXME: Handle BMISS */ | ||
196 | if (beacon_pending != 0) { | ||
197 | priv->bmiss_cnt++; | ||
198 | return; | ||
199 | } | ||
200 | |||
201 | spin_lock_bh(&priv->beacon_lock); | ||
202 | |||
203 | if (unlikely(priv->op_flags & OP_SCANNING)) { | ||
204 | spin_unlock_bh(&priv->beacon_lock); | ||
205 | return; | ||
206 | } | ||
207 | |||
208 | if (unlikely(priv->beacon == NULL)) { | ||
209 | spin_unlock_bh(&priv->beacon_lock); | ||
210 | return; | ||
211 | } | ||
212 | |||
213 | /* Free the old SKB first */ | ||
214 | dev_kfree_skb_any(priv->beacon); | ||
215 | |||
216 | /* Get a new beacon */ | ||
217 | priv->beacon = ieee80211_beacon_get(priv->hw, priv->vif); | ||
218 | if (!priv->beacon) { | ||
219 | spin_unlock_bh(&priv->beacon_lock); | ||
220 | return; | ||
221 | } | ||
222 | |||
223 | info = IEEE80211_SKB_CB(priv->beacon); | ||
224 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { | ||
225 | struct ieee80211_hdr *hdr = | ||
226 | (struct ieee80211_hdr *) priv->beacon->data; | ||
227 | priv->seq_no += 0x10; | ||
228 | hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); | ||
229 | hdr->seq_ctrl |= cpu_to_le16(priv->seq_no); | ||
230 | } | ||
231 | |||
232 | tx_ctl.type = ATH9K_HTC_NORMAL; | ||
233 | beacon_hdr.vif_index = avp->index; | ||
234 | tx_fhdr = skb_push(priv->beacon, sizeof(beacon_hdr)); | ||
235 | memcpy(tx_fhdr, (u8 *) &beacon_hdr, sizeof(beacon_hdr)); | ||
236 | |||
237 | htc_send(priv->htc, priv->beacon, priv->beacon_ep, &tx_ctl); | ||
238 | |||
239 | spin_unlock_bh(&priv->beacon_lock); | ||
240 | } | ||
241 | |||
242 | |||
243 | void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, | ||
244 | struct ieee80211_vif *vif) | ||
245 | { | ||
246 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
247 | enum nl80211_iftype iftype; | ||
248 | struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; | ||
249 | |||
250 | if (vif) { | ||
251 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | ||
252 | iftype = vif->type; | ||
253 | cur_conf->beacon_interval = bss_conf->beacon_int; | ||
254 | cur_conf->dtim_period = bss_conf->dtim_period; | ||
255 | cur_conf->listen_interval = 1; | ||
256 | cur_conf->dtim_count = 1; | ||
257 | cur_conf->bmiss_timeout = | ||
258 | ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval; | ||
259 | } else | ||
260 | iftype = priv->ah->opmode; | ||
261 | |||
262 | if (cur_conf->beacon_interval == 0) | ||
263 | cur_conf->beacon_interval = 100; | ||
264 | |||
265 | switch (iftype) { | ||
266 | case NL80211_IFTYPE_STATION: | ||
267 | ath9k_htc_beacon_config_sta(priv, cur_conf); | ||
268 | break; | ||
269 | case NL80211_IFTYPE_ADHOC: | ||
270 | ath9k_htc_beacon_config_adhoc(priv, cur_conf); | ||
271 | break; | ||
272 | default: | ||
273 | ath_print(common, ATH_DBG_CONFIG, | ||
274 | "Unsupported beaconing mode\n"); | ||
275 | return; | ||
276 | } | ||
277 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c new file mode 100644 index 000000000000..aed53573c547 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c | |||
@@ -0,0 +1,723 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include "htc.h" | ||
18 | |||
19 | MODULE_AUTHOR("Atheros Communications"); | ||
20 | MODULE_LICENSE("Dual BSD/GPL"); | ||
21 | MODULE_DESCRIPTION("Atheros driver 802.11n HTC based wireless devices"); | ||
22 | |||
23 | static unsigned int ath9k_debug = ATH_DBG_DEFAULT; | ||
24 | module_param_named(debug, ath9k_debug, uint, 0); | ||
25 | MODULE_PARM_DESC(debug, "Debugging mask"); | ||
26 | |||
27 | int htc_modparam_nohwcrypt; | ||
28 | module_param_named(nohwcrypt, htc_modparam_nohwcrypt, int, 0444); | ||
29 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); | ||
30 | |||
31 | #define CHAN2G(_freq, _idx) { \ | ||
32 | .center_freq = (_freq), \ | ||
33 | .hw_value = (_idx), \ | ||
34 | .max_power = 20, \ | ||
35 | } | ||
36 | |||
37 | static struct ieee80211_channel ath9k_2ghz_channels[] = { | ||
38 | CHAN2G(2412, 0), /* Channel 1 */ | ||
39 | CHAN2G(2417, 1), /* Channel 2 */ | ||
40 | CHAN2G(2422, 2), /* Channel 3 */ | ||
41 | CHAN2G(2427, 3), /* Channel 4 */ | ||
42 | CHAN2G(2432, 4), /* Channel 5 */ | ||
43 | CHAN2G(2437, 5), /* Channel 6 */ | ||
44 | CHAN2G(2442, 6), /* Channel 7 */ | ||
45 | CHAN2G(2447, 7), /* Channel 8 */ | ||
46 | CHAN2G(2452, 8), /* Channel 9 */ | ||
47 | CHAN2G(2457, 9), /* Channel 10 */ | ||
48 | CHAN2G(2462, 10), /* Channel 11 */ | ||
49 | CHAN2G(2467, 11), /* Channel 12 */ | ||
50 | CHAN2G(2472, 12), /* Channel 13 */ | ||
51 | CHAN2G(2484, 13), /* Channel 14 */ | ||
52 | }; | ||
53 | |||
54 | /* Atheros hardware rate code addition for short premble */ | ||
55 | #define SHPCHECK(__hw_rate, __flags) \ | ||
56 | ((__flags & IEEE80211_RATE_SHORT_PREAMBLE) ? (__hw_rate | 0x04) : 0) | ||
57 | |||
58 | #define RATE(_bitrate, _hw_rate, _flags) { \ | ||
59 | .bitrate = (_bitrate), \ | ||
60 | .flags = (_flags), \ | ||
61 | .hw_value = (_hw_rate), \ | ||
62 | .hw_value_short = (SHPCHECK(_hw_rate, _flags)) \ | ||
63 | } | ||
64 | |||
65 | static struct ieee80211_rate ath9k_legacy_rates[] = { | ||
66 | RATE(10, 0x1b, 0), | ||
67 | RATE(20, 0x1a, IEEE80211_RATE_SHORT_PREAMBLE), /* shortp : 0x1e */ | ||
68 | RATE(55, 0x19, IEEE80211_RATE_SHORT_PREAMBLE), /* shortp: 0x1d */ | ||
69 | RATE(110, 0x18, IEEE80211_RATE_SHORT_PREAMBLE), /* short: 0x1c */ | ||
70 | RATE(60, 0x0b, 0), | ||
71 | RATE(90, 0x0f, 0), | ||
72 | RATE(120, 0x0a, 0), | ||
73 | RATE(180, 0x0e, 0), | ||
74 | RATE(240, 0x09, 0), | ||
75 | RATE(360, 0x0d, 0), | ||
76 | RATE(480, 0x08, 0), | ||
77 | RATE(540, 0x0c, 0), | ||
78 | }; | ||
79 | |||
80 | static int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv) | ||
81 | { | ||
82 | int time_left; | ||
83 | |||
84 | /* Firmware can take up to 50ms to get ready, to be safe use 1 second */ | ||
85 | time_left = wait_for_completion_timeout(&priv->htc->target_wait, HZ); | ||
86 | if (!time_left) { | ||
87 | dev_err(priv->dev, "ath9k_htc: Target is unresponsive\n"); | ||
88 | return -ETIMEDOUT; | ||
89 | } | ||
90 | |||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | static void ath9k_deinit_priv(struct ath9k_htc_priv *priv) | ||
95 | { | ||
96 | ath9k_htc_exit_debug(priv->ah); | ||
97 | ath9k_hw_deinit(priv->ah); | ||
98 | tasklet_kill(&priv->wmi_tasklet); | ||
99 | tasklet_kill(&priv->rx_tasklet); | ||
100 | tasklet_kill(&priv->tx_tasklet); | ||
101 | kfree(priv->ah); | ||
102 | priv->ah = NULL; | ||
103 | } | ||
104 | |||
105 | static void ath9k_deinit_device(struct ath9k_htc_priv *priv) | ||
106 | { | ||
107 | struct ieee80211_hw *hw = priv->hw; | ||
108 | |||
109 | wiphy_rfkill_stop_polling(hw->wiphy); | ||
110 | ath9k_deinit_leds(priv); | ||
111 | ieee80211_unregister_hw(hw); | ||
112 | ath9k_rx_cleanup(priv); | ||
113 | ath9k_tx_cleanup(priv); | ||
114 | ath9k_deinit_priv(priv); | ||
115 | } | ||
116 | |||
117 | static inline int ath9k_htc_connect_svc(struct ath9k_htc_priv *priv, | ||
118 | u16 service_id, | ||
119 | void (*tx) (void *, | ||
120 | struct sk_buff *, | ||
121 | enum htc_endpoint_id, | ||
122 | bool txok), | ||
123 | enum htc_endpoint_id *ep_id) | ||
124 | { | ||
125 | struct htc_service_connreq req; | ||
126 | |||
127 | memset(&req, 0, sizeof(struct htc_service_connreq)); | ||
128 | |||
129 | req.service_id = service_id; | ||
130 | req.ep_callbacks.priv = priv; | ||
131 | req.ep_callbacks.rx = ath9k_htc_rxep; | ||
132 | req.ep_callbacks.tx = tx; | ||
133 | |||
134 | return htc_connect_service(priv->htc, &req, ep_id); | ||
135 | } | ||
136 | |||
137 | static int ath9k_init_htc_services(struct ath9k_htc_priv *priv) | ||
138 | { | ||
139 | int ret; | ||
140 | |||
141 | /* WMI CMD*/ | ||
142 | ret = ath9k_wmi_connect(priv->htc, priv->wmi, &priv->wmi_cmd_ep); | ||
143 | if (ret) | ||
144 | goto err; | ||
145 | |||
146 | /* Beacon */ | ||
147 | ret = ath9k_htc_connect_svc(priv, WMI_BEACON_SVC, NULL, | ||
148 | &priv->beacon_ep); | ||
149 | if (ret) | ||
150 | goto err; | ||
151 | |||
152 | /* CAB */ | ||
153 | ret = ath9k_htc_connect_svc(priv, WMI_CAB_SVC, ath9k_htc_txep, | ||
154 | &priv->cab_ep); | ||
155 | if (ret) | ||
156 | goto err; | ||
157 | |||
158 | |||
159 | /* UAPSD */ | ||
160 | ret = ath9k_htc_connect_svc(priv, WMI_UAPSD_SVC, ath9k_htc_txep, | ||
161 | &priv->uapsd_ep); | ||
162 | if (ret) | ||
163 | goto err; | ||
164 | |||
165 | /* MGMT */ | ||
166 | ret = ath9k_htc_connect_svc(priv, WMI_MGMT_SVC, ath9k_htc_txep, | ||
167 | &priv->mgmt_ep); | ||
168 | if (ret) | ||
169 | goto err; | ||
170 | |||
171 | /* DATA BE */ | ||
172 | ret = ath9k_htc_connect_svc(priv, WMI_DATA_BE_SVC, ath9k_htc_txep, | ||
173 | &priv->data_be_ep); | ||
174 | if (ret) | ||
175 | goto err; | ||
176 | |||
177 | /* DATA BK */ | ||
178 | ret = ath9k_htc_connect_svc(priv, WMI_DATA_BK_SVC, ath9k_htc_txep, | ||
179 | &priv->data_bk_ep); | ||
180 | if (ret) | ||
181 | goto err; | ||
182 | |||
183 | /* DATA VI */ | ||
184 | ret = ath9k_htc_connect_svc(priv, WMI_DATA_VI_SVC, ath9k_htc_txep, | ||
185 | &priv->data_vi_ep); | ||
186 | if (ret) | ||
187 | goto err; | ||
188 | |||
189 | /* DATA VO */ | ||
190 | ret = ath9k_htc_connect_svc(priv, WMI_DATA_VO_SVC, ath9k_htc_txep, | ||
191 | &priv->data_vo_ep); | ||
192 | if (ret) | ||
193 | goto err; | ||
194 | |||
195 | ret = htc_init(priv->htc); | ||
196 | if (ret) | ||
197 | goto err; | ||
198 | |||
199 | return 0; | ||
200 | |||
201 | err: | ||
202 | dev_err(priv->dev, "ath9k_htc: Unable to initialize HTC services\n"); | ||
203 | return ret; | ||
204 | } | ||
205 | |||
206 | static int ath9k_reg_notifier(struct wiphy *wiphy, | ||
207 | struct regulatory_request *request) | ||
208 | { | ||
209 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); | ||
210 | struct ath9k_htc_priv *priv = hw->priv; | ||
211 | |||
212 | return ath_reg_notifier_apply(wiphy, request, | ||
213 | ath9k_hw_regulatory(priv->ah)); | ||
214 | } | ||
215 | |||
216 | static unsigned int ath9k_ioread32(void *hw_priv, u32 reg_offset) | ||
217 | { | ||
218 | struct ath_hw *ah = (struct ath_hw *) hw_priv; | ||
219 | struct ath_common *common = ath9k_hw_common(ah); | ||
220 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; | ||
221 | __be32 val, reg = cpu_to_be32(reg_offset); | ||
222 | int r; | ||
223 | |||
224 | r = ath9k_wmi_cmd(priv->wmi, WMI_REG_READ_CMDID, | ||
225 | (u8 *) ®, sizeof(reg), | ||
226 | (u8 *) &val, sizeof(val), | ||
227 | 100); | ||
228 | if (unlikely(r)) { | ||
229 | ath_print(common, ATH_DBG_WMI, | ||
230 | "REGISTER READ FAILED: (0x%04x, %d)\n", | ||
231 | reg_offset, r); | ||
232 | return -EIO; | ||
233 | } | ||
234 | |||
235 | return be32_to_cpu(val); | ||
236 | } | ||
237 | |||
238 | static void ath9k_iowrite32(void *hw_priv, u32 val, u32 reg_offset) | ||
239 | { | ||
240 | struct ath_hw *ah = (struct ath_hw *) hw_priv; | ||
241 | struct ath_common *common = ath9k_hw_common(ah); | ||
242 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; | ||
243 | __be32 buf[2] = { | ||
244 | cpu_to_be32(reg_offset), | ||
245 | cpu_to_be32(val), | ||
246 | }; | ||
247 | int r; | ||
248 | |||
249 | r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID, | ||
250 | (u8 *) &buf, sizeof(buf), | ||
251 | (u8 *) &val, sizeof(val), | ||
252 | 100); | ||
253 | if (unlikely(r)) { | ||
254 | ath_print(common, ATH_DBG_WMI, | ||
255 | "REGISTER WRITE FAILED:(0x%04x, %d)\n", | ||
256 | reg_offset, r); | ||
257 | } | ||
258 | } | ||
259 | |||
260 | static const struct ath_ops ath9k_common_ops = { | ||
261 | .read = ath9k_ioread32, | ||
262 | .write = ath9k_iowrite32, | ||
263 | }; | ||
264 | |||
265 | static void ath_usb_read_cachesize(struct ath_common *common, int *csz) | ||
266 | { | ||
267 | *csz = L1_CACHE_BYTES >> 2; | ||
268 | } | ||
269 | |||
270 | static bool ath_usb_eeprom_read(struct ath_common *common, u32 off, u16 *data) | ||
271 | { | ||
272 | struct ath_hw *ah = (struct ath_hw *) common->ah; | ||
273 | |||
274 | (void)REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S)); | ||
275 | |||
276 | if (!ath9k_hw_wait(ah, | ||
277 | AR_EEPROM_STATUS_DATA, | ||
278 | AR_EEPROM_STATUS_DATA_BUSY | | ||
279 | AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0, | ||
280 | AH_WAIT_TIMEOUT)) | ||
281 | return false; | ||
282 | |||
283 | *data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA), | ||
284 | AR_EEPROM_STATUS_DATA_VAL); | ||
285 | |||
286 | return true; | ||
287 | } | ||
288 | |||
289 | static const struct ath_bus_ops ath9k_usb_bus_ops = { | ||
290 | .ath_bus_type = ATH_USB, | ||
291 | .read_cachesize = ath_usb_read_cachesize, | ||
292 | .eeprom_read = ath_usb_eeprom_read, | ||
293 | }; | ||
294 | |||
295 | static void setup_ht_cap(struct ath9k_htc_priv *priv, | ||
296 | struct ieee80211_sta_ht_cap *ht_info) | ||
297 | { | ||
298 | ht_info->ht_supported = true; | ||
299 | ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | | ||
300 | IEEE80211_HT_CAP_SM_PS | | ||
301 | IEEE80211_HT_CAP_SGI_40 | | ||
302 | IEEE80211_HT_CAP_DSSSCCK40; | ||
303 | |||
304 | ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; | ||
305 | ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; | ||
306 | |||
307 | memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); | ||
308 | ht_info->mcs.rx_mask[0] = 0xff; | ||
309 | ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED; | ||
310 | } | ||
311 | |||
312 | static int ath9k_init_queues(struct ath9k_htc_priv *priv) | ||
313 | { | ||
314 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
315 | int i; | ||
316 | |||
317 | for (i = 0; i < ARRAY_SIZE(priv->hwq_map); i++) | ||
318 | priv->hwq_map[i] = -1; | ||
319 | |||
320 | if (!ath9k_htc_txq_setup(priv, ATH9K_WME_AC_BE)) { | ||
321 | ath_print(common, ATH_DBG_FATAL, | ||
322 | "Unable to setup xmit queue for BE traffic\n"); | ||
323 | goto err; | ||
324 | } | ||
325 | |||
326 | if (!ath9k_htc_txq_setup(priv, ATH9K_WME_AC_BK)) { | ||
327 | ath_print(common, ATH_DBG_FATAL, | ||
328 | "Unable to setup xmit queue for BK traffic\n"); | ||
329 | goto err; | ||
330 | } | ||
331 | if (!ath9k_htc_txq_setup(priv, ATH9K_WME_AC_VI)) { | ||
332 | ath_print(common, ATH_DBG_FATAL, | ||
333 | "Unable to setup xmit queue for VI traffic\n"); | ||
334 | goto err; | ||
335 | } | ||
336 | if (!ath9k_htc_txq_setup(priv, ATH9K_WME_AC_VO)) { | ||
337 | ath_print(common, ATH_DBG_FATAL, | ||
338 | "Unable to setup xmit queue for VO traffic\n"); | ||
339 | goto err; | ||
340 | } | ||
341 | |||
342 | return 0; | ||
343 | |||
344 | err: | ||
345 | return -EINVAL; | ||
346 | } | ||
347 | |||
348 | static void ath9k_init_crypto(struct ath9k_htc_priv *priv) | ||
349 | { | ||
350 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
351 | int i = 0; | ||
352 | |||
353 | /* Get the hardware key cache size. */ | ||
354 | common->keymax = priv->ah->caps.keycache_size; | ||
355 | if (common->keymax > ATH_KEYMAX) { | ||
356 | ath_print(common, ATH_DBG_ANY, | ||
357 | "Warning, using only %u entries in %u key cache\n", | ||
358 | ATH_KEYMAX, common->keymax); | ||
359 | common->keymax = ATH_KEYMAX; | ||
360 | } | ||
361 | |||
362 | /* | ||
363 | * Reset the key cache since some parts do not | ||
364 | * reset the contents on initial power up. | ||
365 | */ | ||
366 | for (i = 0; i < common->keymax; i++) | ||
367 | ath9k_hw_keyreset(priv->ah, (u16) i); | ||
368 | |||
369 | if (ath9k_hw_getcapability(priv->ah, ATH9K_CAP_CIPHER, | ||
370 | ATH9K_CIPHER_TKIP, NULL)) { | ||
371 | /* | ||
372 | * Whether we should enable h/w TKIP MIC. | ||
373 | * XXX: if we don't support WME TKIP MIC, then we wouldn't | ||
374 | * report WMM capable, so it's always safe to turn on | ||
375 | * TKIP MIC in this case. | ||
376 | */ | ||
377 | ath9k_hw_setcapability(priv->ah, ATH9K_CAP_TKIP_MIC, 0, 1, NULL); | ||
378 | } | ||
379 | |||
380 | /* | ||
381 | * Check whether the separate key cache entries | ||
382 | * are required to handle both tx+rx MIC keys. | ||
383 | * With split mic keys the number of stations is limited | ||
384 | * to 27 otherwise 59. | ||
385 | */ | ||
386 | if (ath9k_hw_getcapability(priv->ah, ATH9K_CAP_CIPHER, | ||
387 | ATH9K_CIPHER_TKIP, NULL) | ||
388 | && ath9k_hw_getcapability(priv->ah, ATH9K_CAP_CIPHER, | ||
389 | ATH9K_CIPHER_MIC, NULL) | ||
390 | && ath9k_hw_getcapability(priv->ah, ATH9K_CAP_TKIP_SPLIT, | ||
391 | 0, NULL)) | ||
392 | common->splitmic = 1; | ||
393 | |||
394 | /* turn on mcast key search if possible */ | ||
395 | if (!ath9k_hw_getcapability(priv->ah, ATH9K_CAP_MCAST_KEYSRCH, 0, NULL)) | ||
396 | (void)ath9k_hw_setcapability(priv->ah, ATH9K_CAP_MCAST_KEYSRCH, | ||
397 | 1, 1, NULL); | ||
398 | } | ||
399 | |||
400 | static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv) | ||
401 | { | ||
402 | if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes)) { | ||
403 | priv->sbands[IEEE80211_BAND_2GHZ].channels = | ||
404 | ath9k_2ghz_channels; | ||
405 | priv->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; | ||
406 | priv->sbands[IEEE80211_BAND_2GHZ].n_channels = | ||
407 | ARRAY_SIZE(ath9k_2ghz_channels); | ||
408 | priv->sbands[IEEE80211_BAND_2GHZ].bitrates = ath9k_legacy_rates; | ||
409 | priv->sbands[IEEE80211_BAND_2GHZ].n_bitrates = | ||
410 | ARRAY_SIZE(ath9k_legacy_rates); | ||
411 | } | ||
412 | } | ||
413 | |||
414 | static void ath9k_init_misc(struct ath9k_htc_priv *priv) | ||
415 | { | ||
416 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
417 | |||
418 | common->tx_chainmask = priv->ah->caps.tx_chainmask; | ||
419 | common->rx_chainmask = priv->ah->caps.rx_chainmask; | ||
420 | |||
421 | if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) | ||
422 | memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); | ||
423 | |||
424 | priv->op_flags |= OP_TXAGGR; | ||
425 | priv->ah->opmode = NL80211_IFTYPE_STATION; | ||
426 | } | ||
427 | |||
428 | static int ath9k_init_priv(struct ath9k_htc_priv *priv, u16 devid) | ||
429 | { | ||
430 | struct ath_hw *ah = NULL; | ||
431 | struct ath_common *common; | ||
432 | int ret = 0, csz = 0; | ||
433 | |||
434 | priv->op_flags |= OP_INVALID; | ||
435 | |||
436 | ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL); | ||
437 | if (!ah) | ||
438 | return -ENOMEM; | ||
439 | |||
440 | ah->hw_version.devid = devid; | ||
441 | ah->hw_version.subsysid = 0; /* FIXME */ | ||
442 | priv->ah = ah; | ||
443 | |||
444 | common = ath9k_hw_common(ah); | ||
445 | common->ops = &ath9k_common_ops; | ||
446 | common->bus_ops = &ath9k_usb_bus_ops; | ||
447 | common->ah = ah; | ||
448 | common->hw = priv->hw; | ||
449 | common->priv = priv; | ||
450 | common->debug_mask = ath9k_debug; | ||
451 | |||
452 | spin_lock_init(&priv->wmi->wmi_lock); | ||
453 | spin_lock_init(&priv->beacon_lock); | ||
454 | spin_lock_init(&priv->tx_lock); | ||
455 | mutex_init(&priv->mutex); | ||
456 | mutex_init(&priv->aggr_work.mutex); | ||
457 | mutex_init(&priv->htc_pm_lock); | ||
458 | tasklet_init(&priv->wmi_tasklet, ath9k_wmi_tasklet, | ||
459 | (unsigned long)priv); | ||
460 | tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet, | ||
461 | (unsigned long)priv); | ||
462 | tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet, (unsigned long)priv); | ||
463 | INIT_DELAYED_WORK(&priv->ath9k_aggr_work, ath9k_htc_aggr_work); | ||
464 | INIT_DELAYED_WORK(&priv->ath9k_ani_work, ath9k_ani_work); | ||
465 | INIT_WORK(&priv->ps_work, ath9k_ps_work); | ||
466 | |||
467 | /* | ||
468 | * Cache line size is used to size and align various | ||
469 | * structures used to communicate with the hardware. | ||
470 | */ | ||
471 | ath_read_cachesize(common, &csz); | ||
472 | common->cachelsz = csz << 2; /* convert to bytes */ | ||
473 | |||
474 | ret = ath9k_hw_init(ah); | ||
475 | if (ret) { | ||
476 | ath_print(common, ATH_DBG_FATAL, | ||
477 | "Unable to initialize hardware; " | ||
478 | "initialization status: %d\n", ret); | ||
479 | goto err_hw; | ||
480 | } | ||
481 | |||
482 | ret = ath9k_htc_init_debug(ah); | ||
483 | if (ret) { | ||
484 | ath_print(common, ATH_DBG_FATAL, | ||
485 | "Unable to create debugfs files\n"); | ||
486 | goto err_debug; | ||
487 | } | ||
488 | |||
489 | ret = ath9k_init_queues(priv); | ||
490 | if (ret) | ||
491 | goto err_queues; | ||
492 | |||
493 | ath9k_init_crypto(priv); | ||
494 | ath9k_init_channels_rates(priv); | ||
495 | ath9k_init_misc(priv); | ||
496 | |||
497 | return 0; | ||
498 | |||
499 | err_queues: | ||
500 | ath9k_htc_exit_debug(ah); | ||
501 | err_debug: | ||
502 | ath9k_hw_deinit(ah); | ||
503 | err_hw: | ||
504 | |||
505 | kfree(ah); | ||
506 | priv->ah = NULL; | ||
507 | |||
508 | return ret; | ||
509 | } | ||
510 | |||
511 | static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, | ||
512 | struct ieee80211_hw *hw) | ||
513 | { | ||
514 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
515 | |||
516 | hw->flags = IEEE80211_HW_SIGNAL_DBM | | ||
517 | IEEE80211_HW_AMPDU_AGGREGATION | | ||
518 | IEEE80211_HW_SPECTRUM_MGMT | | ||
519 | IEEE80211_HW_HAS_RATE_CONTROL | | ||
520 | IEEE80211_HW_RX_INCLUDES_FCS | | ||
521 | IEEE80211_HW_SUPPORTS_PS | | ||
522 | IEEE80211_HW_PS_NULLFUNC_STACK; | ||
523 | |||
524 | hw->wiphy->interface_modes = | ||
525 | BIT(NL80211_IFTYPE_STATION) | | ||
526 | BIT(NL80211_IFTYPE_ADHOC); | ||
527 | |||
528 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | ||
529 | |||
530 | hw->queues = 4; | ||
531 | hw->channel_change_time = 5000; | ||
532 | hw->max_listen_interval = 10; | ||
533 | hw->vif_data_size = sizeof(struct ath9k_htc_vif); | ||
534 | hw->sta_data_size = sizeof(struct ath9k_htc_sta); | ||
535 | |||
536 | /* tx_frame_hdr is larger than tx_mgmt_hdr anyway */ | ||
537 | hw->extra_tx_headroom = sizeof(struct tx_frame_hdr) + | ||
538 | sizeof(struct htc_frame_hdr) + 4; | ||
539 | |||
540 | if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes)) | ||
541 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = | ||
542 | &priv->sbands[IEEE80211_BAND_2GHZ]; | ||
543 | |||
544 | if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_HT) { | ||
545 | if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes)) | ||
546 | setup_ht_cap(priv, | ||
547 | &priv->sbands[IEEE80211_BAND_2GHZ].ht_cap); | ||
548 | } | ||
549 | |||
550 | SET_IEEE80211_PERM_ADDR(hw, common->macaddr); | ||
551 | } | ||
552 | |||
553 | static int ath9k_init_device(struct ath9k_htc_priv *priv, u16 devid) | ||
554 | { | ||
555 | struct ieee80211_hw *hw = priv->hw; | ||
556 | struct ath_common *common; | ||
557 | struct ath_hw *ah; | ||
558 | int error = 0; | ||
559 | struct ath_regulatory *reg; | ||
560 | |||
561 | /* Bring up device */ | ||
562 | error = ath9k_init_priv(priv, devid); | ||
563 | if (error != 0) | ||
564 | goto err_init; | ||
565 | |||
566 | ah = priv->ah; | ||
567 | common = ath9k_hw_common(ah); | ||
568 | ath9k_set_hw_capab(priv, hw); | ||
569 | |||
570 | /* Initialize regulatory */ | ||
571 | error = ath_regd_init(&common->regulatory, priv->hw->wiphy, | ||
572 | ath9k_reg_notifier); | ||
573 | if (error) | ||
574 | goto err_regd; | ||
575 | |||
576 | reg = &common->regulatory; | ||
577 | |||
578 | /* Setup TX */ | ||
579 | error = ath9k_tx_init(priv); | ||
580 | if (error != 0) | ||
581 | goto err_tx; | ||
582 | |||
583 | /* Setup RX */ | ||
584 | error = ath9k_rx_init(priv); | ||
585 | if (error != 0) | ||
586 | goto err_rx; | ||
587 | |||
588 | /* Register with mac80211 */ | ||
589 | error = ieee80211_register_hw(hw); | ||
590 | if (error) | ||
591 | goto err_register; | ||
592 | |||
593 | /* Handle world regulatory */ | ||
594 | if (!ath_is_world_regd(reg)) { | ||
595 | error = regulatory_hint(hw->wiphy, reg->alpha2); | ||
596 | if (error) | ||
597 | goto err_world; | ||
598 | } | ||
599 | |||
600 | ath9k_init_leds(priv); | ||
601 | ath9k_start_rfkill_poll(priv); | ||
602 | |||
603 | return 0; | ||
604 | |||
605 | err_world: | ||
606 | ieee80211_unregister_hw(hw); | ||
607 | err_register: | ||
608 | ath9k_rx_cleanup(priv); | ||
609 | err_rx: | ||
610 | ath9k_tx_cleanup(priv); | ||
611 | err_tx: | ||
612 | /* Nothing */ | ||
613 | err_regd: | ||
614 | ath9k_deinit_priv(priv); | ||
615 | err_init: | ||
616 | return error; | ||
617 | } | ||
618 | |||
619 | int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, | ||
620 | u16 devid) | ||
621 | { | ||
622 | struct ieee80211_hw *hw; | ||
623 | struct ath9k_htc_priv *priv; | ||
624 | int ret; | ||
625 | |||
626 | hw = ieee80211_alloc_hw(sizeof(struct ath9k_htc_priv), &ath9k_htc_ops); | ||
627 | if (!hw) | ||
628 | return -ENOMEM; | ||
629 | |||
630 | priv = hw->priv; | ||
631 | priv->hw = hw; | ||
632 | priv->htc = htc_handle; | ||
633 | priv->dev = dev; | ||
634 | htc_handle->drv_priv = priv; | ||
635 | SET_IEEE80211_DEV(hw, priv->dev); | ||
636 | |||
637 | ret = ath9k_htc_wait_for_target(priv); | ||
638 | if (ret) | ||
639 | goto err_free; | ||
640 | |||
641 | priv->wmi = ath9k_init_wmi(priv); | ||
642 | if (!priv->wmi) { | ||
643 | ret = -EINVAL; | ||
644 | goto err_free; | ||
645 | } | ||
646 | |||
647 | ret = ath9k_init_htc_services(priv); | ||
648 | if (ret) | ||
649 | goto err_init; | ||
650 | |||
651 | ret = ath9k_init_device(priv, devid); | ||
652 | if (ret) | ||
653 | goto err_init; | ||
654 | |||
655 | return 0; | ||
656 | |||
657 | err_init: | ||
658 | ath9k_deinit_wmi(priv); | ||
659 | err_free: | ||
660 | ieee80211_free_hw(hw); | ||
661 | return ret; | ||
662 | } | ||
663 | |||
664 | void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug) | ||
665 | { | ||
666 | if (htc_handle->drv_priv) { | ||
667 | ath9k_deinit_device(htc_handle->drv_priv); | ||
668 | ath9k_deinit_wmi(htc_handle->drv_priv); | ||
669 | ieee80211_free_hw(htc_handle->drv_priv->hw); | ||
670 | } | ||
671 | } | ||
672 | |||
673 | #ifdef CONFIG_PM | ||
674 | int ath9k_htc_resume(struct htc_target *htc_handle) | ||
675 | { | ||
676 | int ret; | ||
677 | |||
678 | ret = ath9k_htc_wait_for_target(htc_handle->drv_priv); | ||
679 | if (ret) | ||
680 | return ret; | ||
681 | |||
682 | ret = ath9k_init_htc_services(htc_handle->drv_priv); | ||
683 | return ret; | ||
684 | } | ||
685 | #endif | ||
686 | |||
687 | static int __init ath9k_htc_init(void) | ||
688 | { | ||
689 | int error; | ||
690 | |||
691 | error = ath9k_htc_debug_create_root(); | ||
692 | if (error < 0) { | ||
693 | printk(KERN_ERR | ||
694 | "ath9k_htc: Unable to create debugfs root: %d\n", | ||
695 | error); | ||
696 | goto err_dbg; | ||
697 | } | ||
698 | |||
699 | error = ath9k_hif_usb_init(); | ||
700 | if (error < 0) { | ||
701 | printk(KERN_ERR | ||
702 | "ath9k_htc: No USB devices found," | ||
703 | " driver not installed.\n"); | ||
704 | error = -ENODEV; | ||
705 | goto err_usb; | ||
706 | } | ||
707 | |||
708 | return 0; | ||
709 | |||
710 | err_usb: | ||
711 | ath9k_htc_debug_remove_root(); | ||
712 | err_dbg: | ||
713 | return error; | ||
714 | } | ||
715 | module_init(ath9k_htc_init); | ||
716 | |||
717 | static void __exit ath9k_htc_exit(void) | ||
718 | { | ||
719 | ath9k_hif_usb_exit(); | ||
720 | ath9k_htc_debug_remove_root(); | ||
721 | printk(KERN_INFO "ath9k_htc: Driver unloaded\n"); | ||
722 | } | ||
723 | module_exit(ath9k_htc_exit); | ||
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c new file mode 100644 index 000000000000..eb7722b2cfcc --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | |||
@@ -0,0 +1,1733 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include "htc.h" | ||
18 | |||
19 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS | ||
20 | static struct dentry *ath9k_debugfs_root; | ||
21 | #endif | ||
22 | |||
23 | /*************/ | ||
24 | /* Utilities */ | ||
25 | /*************/ | ||
26 | |||
27 | static void ath_update_txpow(struct ath9k_htc_priv *priv) | ||
28 | { | ||
29 | struct ath_hw *ah = priv->ah; | ||
30 | u32 txpow; | ||
31 | |||
32 | if (priv->curtxpow != priv->txpowlimit) { | ||
33 | ath9k_hw_set_txpowerlimit(ah, priv->txpowlimit); | ||
34 | /* read back in case value is clamped */ | ||
35 | ath9k_hw_getcapability(ah, ATH9K_CAP_TXPOW, 1, &txpow); | ||
36 | priv->curtxpow = txpow; | ||
37 | } | ||
38 | } | ||
39 | |||
40 | /* HACK Alert: Use 11NG for 2.4, use 11NA for 5 */ | ||
41 | static enum htc_phymode ath9k_htc_get_curmode(struct ath9k_htc_priv *priv, | ||
42 | struct ath9k_channel *ichan) | ||
43 | { | ||
44 | enum htc_phymode mode; | ||
45 | |||
46 | mode = HTC_MODE_AUTO; | ||
47 | |||
48 | switch (ichan->chanmode) { | ||
49 | case CHANNEL_G: | ||
50 | case CHANNEL_G_HT20: | ||
51 | case CHANNEL_G_HT40PLUS: | ||
52 | case CHANNEL_G_HT40MINUS: | ||
53 | mode = HTC_MODE_11NG; | ||
54 | break; | ||
55 | case CHANNEL_A: | ||
56 | case CHANNEL_A_HT20: | ||
57 | case CHANNEL_A_HT40PLUS: | ||
58 | case CHANNEL_A_HT40MINUS: | ||
59 | mode = HTC_MODE_11NA; | ||
60 | break; | ||
61 | default: | ||
62 | break; | ||
63 | } | ||
64 | |||
65 | return mode; | ||
66 | } | ||
67 | |||
68 | static bool ath9k_htc_setpower(struct ath9k_htc_priv *priv, | ||
69 | enum ath9k_power_mode mode) | ||
70 | { | ||
71 | bool ret; | ||
72 | |||
73 | mutex_lock(&priv->htc_pm_lock); | ||
74 | ret = ath9k_hw_setpower(priv->ah, mode); | ||
75 | mutex_unlock(&priv->htc_pm_lock); | ||
76 | |||
77 | return ret; | ||
78 | } | ||
79 | |||
80 | void ath9k_htc_ps_wakeup(struct ath9k_htc_priv *priv) | ||
81 | { | ||
82 | mutex_lock(&priv->htc_pm_lock); | ||
83 | if (++priv->ps_usecount != 1) | ||
84 | goto unlock; | ||
85 | ath9k_hw_setpower(priv->ah, ATH9K_PM_AWAKE); | ||
86 | |||
87 | unlock: | ||
88 | mutex_unlock(&priv->htc_pm_lock); | ||
89 | } | ||
90 | |||
91 | void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv) | ||
92 | { | ||
93 | mutex_lock(&priv->htc_pm_lock); | ||
94 | if (--priv->ps_usecount != 0) | ||
95 | goto unlock; | ||
96 | |||
97 | if (priv->ps_enabled) | ||
98 | ath9k_hw_setpower(priv->ah, ATH9K_PM_NETWORK_SLEEP); | ||
99 | unlock: | ||
100 | mutex_unlock(&priv->htc_pm_lock); | ||
101 | } | ||
102 | |||
103 | void ath9k_ps_work(struct work_struct *work) | ||
104 | { | ||
105 | struct ath9k_htc_priv *priv = | ||
106 | container_of(work, struct ath9k_htc_priv, | ||
107 | ps_work); | ||
108 | ath9k_htc_setpower(priv, ATH9K_PM_AWAKE); | ||
109 | |||
110 | /* The chip wakes up after receiving the first beacon | ||
111 | while network sleep is enabled. For the driver to | ||
112 | be in sync with the hw, set the chip to awake and | ||
113 | only then set it to sleep. | ||
114 | */ | ||
115 | ath9k_htc_setpower(priv, ATH9K_PM_NETWORK_SLEEP); | ||
116 | } | ||
117 | |||
118 | static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, | ||
119 | struct ieee80211_hw *hw, | ||
120 | struct ath9k_channel *hchan) | ||
121 | { | ||
122 | struct ath_hw *ah = priv->ah; | ||
123 | struct ath_common *common = ath9k_hw_common(ah); | ||
124 | struct ieee80211_conf *conf = &common->hw->conf; | ||
125 | bool fastcc = true; | ||
126 | struct ieee80211_channel *channel = hw->conf.channel; | ||
127 | enum htc_phymode mode; | ||
128 | u16 htc_mode; | ||
129 | u8 cmd_rsp; | ||
130 | int ret; | ||
131 | |||
132 | if (priv->op_flags & OP_INVALID) | ||
133 | return -EIO; | ||
134 | |||
135 | if (priv->op_flags & OP_FULL_RESET) | ||
136 | fastcc = false; | ||
137 | |||
138 | /* Fiddle around with fastcc later on, for now just use full reset */ | ||
139 | fastcc = false; | ||
140 | ath9k_htc_ps_wakeup(priv); | ||
141 | htc_stop(priv->htc); | ||
142 | WMI_CMD(WMI_DISABLE_INTR_CMDID); | ||
143 | WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); | ||
144 | WMI_CMD(WMI_STOP_RECV_CMDID); | ||
145 | |||
146 | ath_print(common, ATH_DBG_CONFIG, | ||
147 | "(%u MHz) -> (%u MHz), HT: %d, HT40: %d\n", | ||
148 | priv->ah->curchan->channel, | ||
149 | channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf)); | ||
150 | |||
151 | ret = ath9k_hw_reset(ah, hchan, fastcc); | ||
152 | if (ret) { | ||
153 | ath_print(common, ATH_DBG_FATAL, | ||
154 | "Unable to reset channel (%u Mhz) " | ||
155 | "reset status %d\n", channel->center_freq, ret); | ||
156 | ath9k_htc_ps_restore(priv); | ||
157 | goto err; | ||
158 | } | ||
159 | |||
160 | ath_update_txpow(priv); | ||
161 | |||
162 | WMI_CMD(WMI_START_RECV_CMDID); | ||
163 | if (ret) | ||
164 | goto err; | ||
165 | |||
166 | ath9k_host_rx_init(priv); | ||
167 | |||
168 | mode = ath9k_htc_get_curmode(priv, hchan); | ||
169 | htc_mode = cpu_to_be16(mode); | ||
170 | WMI_CMD_BUF(WMI_SET_MODE_CMDID, &htc_mode); | ||
171 | if (ret) | ||
172 | goto err; | ||
173 | |||
174 | WMI_CMD(WMI_ENABLE_INTR_CMDID); | ||
175 | if (ret) | ||
176 | goto err; | ||
177 | |||
178 | htc_start(priv->htc); | ||
179 | |||
180 | priv->op_flags &= ~OP_FULL_RESET; | ||
181 | err: | ||
182 | ath9k_htc_ps_restore(priv); | ||
183 | return ret; | ||
184 | } | ||
185 | |||
186 | static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv) | ||
187 | { | ||
188 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
189 | struct ath9k_htc_target_vif hvif; | ||
190 | int ret = 0; | ||
191 | u8 cmd_rsp; | ||
192 | |||
193 | if (priv->nvifs > 0) | ||
194 | return -ENOBUFS; | ||
195 | |||
196 | memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); | ||
197 | memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN); | ||
198 | |||
199 | hvif.opmode = cpu_to_be32(HTC_M_MONITOR); | ||
200 | priv->ah->opmode = NL80211_IFTYPE_MONITOR; | ||
201 | hvif.index = priv->nvifs; | ||
202 | |||
203 | WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif); | ||
204 | if (ret) | ||
205 | return ret; | ||
206 | |||
207 | priv->nvifs++; | ||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | static int ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv) | ||
212 | { | ||
213 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
214 | struct ath9k_htc_target_vif hvif; | ||
215 | int ret = 0; | ||
216 | u8 cmd_rsp; | ||
217 | |||
218 | memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); | ||
219 | memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN); | ||
220 | hvif.index = 0; /* Should do for now */ | ||
221 | WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); | ||
222 | priv->nvifs--; | ||
223 | |||
224 | return ret; | ||
225 | } | ||
226 | |||
227 | static int ath9k_htc_add_station(struct ath9k_htc_priv *priv, | ||
228 | struct ieee80211_vif *vif, | ||
229 | struct ieee80211_sta *sta) | ||
230 | { | ||
231 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
232 | struct ath9k_htc_target_sta tsta; | ||
233 | struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv; | ||
234 | struct ath9k_htc_sta *ista; | ||
235 | int ret; | ||
236 | u8 cmd_rsp; | ||
237 | |||
238 | if (priv->nstations >= ATH9K_HTC_MAX_STA) | ||
239 | return -ENOBUFS; | ||
240 | |||
241 | memset(&tsta, 0, sizeof(struct ath9k_htc_target_sta)); | ||
242 | |||
243 | if (sta) { | ||
244 | ista = (struct ath9k_htc_sta *) sta->drv_priv; | ||
245 | memcpy(&tsta.macaddr, sta->addr, ETH_ALEN); | ||
246 | memcpy(&tsta.bssid, common->curbssid, ETH_ALEN); | ||
247 | tsta.associd = common->curaid; | ||
248 | tsta.is_vif_sta = 0; | ||
249 | tsta.valid = true; | ||
250 | ista->index = priv->nstations; | ||
251 | } else { | ||
252 | memcpy(&tsta.macaddr, vif->addr, ETH_ALEN); | ||
253 | tsta.is_vif_sta = 1; | ||
254 | } | ||
255 | |||
256 | tsta.sta_index = priv->nstations; | ||
257 | tsta.vif_index = avp->index; | ||
258 | tsta.maxampdu = 0xffff; | ||
259 | if (sta && sta->ht_cap.ht_supported) | ||
260 | tsta.flags = cpu_to_be16(ATH_HTC_STA_HT); | ||
261 | |||
262 | WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta); | ||
263 | if (ret) { | ||
264 | if (sta) | ||
265 | ath_print(common, ATH_DBG_FATAL, | ||
266 | "Unable to add station entry for: %pM\n", sta->addr); | ||
267 | return ret; | ||
268 | } | ||
269 | |||
270 | if (sta) | ||
271 | ath_print(common, ATH_DBG_CONFIG, | ||
272 | "Added a station entry for: %pM (idx: %d)\n", | ||
273 | sta->addr, tsta.sta_index); | ||
274 | |||
275 | priv->nstations++; | ||
276 | return 0; | ||
277 | } | ||
278 | |||
279 | static int ath9k_htc_remove_station(struct ath9k_htc_priv *priv, | ||
280 | struct ieee80211_vif *vif, | ||
281 | struct ieee80211_sta *sta) | ||
282 | { | ||
283 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
284 | struct ath9k_htc_sta *ista; | ||
285 | int ret; | ||
286 | u8 cmd_rsp, sta_idx; | ||
287 | |||
288 | if (sta) { | ||
289 | ista = (struct ath9k_htc_sta *) sta->drv_priv; | ||
290 | sta_idx = ista->index; | ||
291 | } else { | ||
292 | sta_idx = 0; | ||
293 | } | ||
294 | |||
295 | WMI_CMD_BUF(WMI_NODE_REMOVE_CMDID, &sta_idx); | ||
296 | if (ret) { | ||
297 | if (sta) | ||
298 | ath_print(common, ATH_DBG_FATAL, | ||
299 | "Unable to remove station entry for: %pM\n", | ||
300 | sta->addr); | ||
301 | return ret; | ||
302 | } | ||
303 | |||
304 | if (sta) | ||
305 | ath_print(common, ATH_DBG_CONFIG, | ||
306 | "Removed a station entry for: %pM (idx: %d)\n", | ||
307 | sta->addr, sta_idx); | ||
308 | |||
309 | priv->nstations--; | ||
310 | return 0; | ||
311 | } | ||
312 | |||
313 | static int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv) | ||
314 | { | ||
315 | struct ath9k_htc_cap_target tcap; | ||
316 | int ret; | ||
317 | u8 cmd_rsp; | ||
318 | |||
319 | memset(&tcap, 0, sizeof(struct ath9k_htc_cap_target)); | ||
320 | |||
321 | /* FIXME: Values are hardcoded */ | ||
322 | tcap.flags = 0x240c40; | ||
323 | tcap.flags_ext = 0x80601000; | ||
324 | tcap.ampdu_limit = 0xffff0000; | ||
325 | tcap.ampdu_subframes = 20; | ||
326 | tcap.tx_chainmask_legacy = 1; | ||
327 | tcap.protmode = 1; | ||
328 | tcap.tx_chainmask = 1; | ||
329 | |||
330 | WMI_CMD_BUF(WMI_TARGET_IC_UPDATE_CMDID, &tcap); | ||
331 | |||
332 | return ret; | ||
333 | } | ||
334 | |||
335 | static int ath9k_htc_init_rate(struct ath9k_htc_priv *priv, | ||
336 | struct ieee80211_vif *vif, | ||
337 | struct ieee80211_sta *sta) | ||
338 | { | ||
339 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
340 | struct ath9k_htc_sta *ista = (struct ath9k_htc_sta *) sta->drv_priv; | ||
341 | struct ieee80211_supported_band *sband; | ||
342 | struct ath9k_htc_target_rate trate; | ||
343 | u32 caps = 0; | ||
344 | u8 cmd_rsp; | ||
345 | int i, j, ret; | ||
346 | |||
347 | memset(&trate, 0, sizeof(trate)); | ||
348 | |||
349 | /* Only 2GHz is supported */ | ||
350 | sband = priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ]; | ||
351 | |||
352 | for (i = 0, j = 0; i < sband->n_bitrates; i++) { | ||
353 | if (sta->supp_rates[sband->band] & BIT(i)) { | ||
354 | priv->tgt_rate.rates.legacy_rates.rs_rates[j] | ||
355 | = (sband->bitrates[i].bitrate * 2) / 10; | ||
356 | j++; | ||
357 | } | ||
358 | } | ||
359 | priv->tgt_rate.rates.legacy_rates.rs_nrates = j; | ||
360 | |||
361 | if (sta->ht_cap.ht_supported) { | ||
362 | for (i = 0, j = 0; i < 77; i++) { | ||
363 | if (sta->ht_cap.mcs.rx_mask[i/8] & (1<<(i%8))) | ||
364 | priv->tgt_rate.rates.ht_rates.rs_rates[j++] = i; | ||
365 | if (j == ATH_HTC_RATE_MAX) | ||
366 | break; | ||
367 | } | ||
368 | priv->tgt_rate.rates.ht_rates.rs_nrates = j; | ||
369 | |||
370 | caps = WLAN_RC_HT_FLAG; | ||
371 | if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) | ||
372 | caps |= WLAN_RC_40_FLAG; | ||
373 | if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) | ||
374 | caps |= WLAN_RC_SGI_FLAG; | ||
375 | |||
376 | } | ||
377 | |||
378 | priv->tgt_rate.sta_index = ista->index; | ||
379 | priv->tgt_rate.isnew = 1; | ||
380 | trate = priv->tgt_rate; | ||
381 | priv->tgt_rate.capflags = caps; | ||
382 | trate.capflags = cpu_to_be32(caps); | ||
383 | |||
384 | WMI_CMD_BUF(WMI_RC_RATE_UPDATE_CMDID, &trate); | ||
385 | if (ret) { | ||
386 | ath_print(common, ATH_DBG_FATAL, | ||
387 | "Unable to initialize Rate information on target\n"); | ||
388 | return ret; | ||
389 | } | ||
390 | |||
391 | ath_print(common, ATH_DBG_CONFIG, | ||
392 | "Updated target STA: %pM (caps: 0x%x)\n", sta->addr, caps); | ||
393 | return 0; | ||
394 | } | ||
395 | |||
396 | static bool check_rc_update(struct ieee80211_hw *hw, bool *cw40) | ||
397 | { | ||
398 | struct ath9k_htc_priv *priv = hw->priv; | ||
399 | struct ieee80211_conf *conf = &hw->conf; | ||
400 | |||
401 | if (!conf_is_ht(conf)) | ||
402 | return false; | ||
403 | |||
404 | if (!(priv->op_flags & OP_ASSOCIATED) || | ||
405 | (priv->op_flags & OP_SCANNING)) | ||
406 | return false; | ||
407 | |||
408 | if (conf_is_ht40(conf)) { | ||
409 | if (priv->ah->curchan->chanmode & | ||
410 | (CHANNEL_HT40PLUS | CHANNEL_HT40MINUS)) { | ||
411 | return false; | ||
412 | } else { | ||
413 | *cw40 = true; | ||
414 | return true; | ||
415 | } | ||
416 | } else { /* ht20 */ | ||
417 | if (priv->ah->curchan->chanmode & CHANNEL_HT20) | ||
418 | return false; | ||
419 | else | ||
420 | return true; | ||
421 | } | ||
422 | } | ||
423 | |||
424 | static void ath9k_htc_rc_update(struct ath9k_htc_priv *priv, bool is_cw40) | ||
425 | { | ||
426 | struct ath9k_htc_target_rate trate; | ||
427 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
428 | int ret; | ||
429 | u8 cmd_rsp; | ||
430 | |||
431 | memset(&trate, 0, sizeof(trate)); | ||
432 | |||
433 | trate = priv->tgt_rate; | ||
434 | |||
435 | if (is_cw40) | ||
436 | priv->tgt_rate.capflags |= WLAN_RC_40_FLAG; | ||
437 | else | ||
438 | priv->tgt_rate.capflags &= ~WLAN_RC_40_FLAG; | ||
439 | |||
440 | trate.capflags = cpu_to_be32(priv->tgt_rate.capflags); | ||
441 | |||
442 | WMI_CMD_BUF(WMI_RC_RATE_UPDATE_CMDID, &trate); | ||
443 | if (ret) { | ||
444 | ath_print(common, ATH_DBG_FATAL, | ||
445 | "Unable to update Rate information on target\n"); | ||
446 | return; | ||
447 | } | ||
448 | |||
449 | ath_print(common, ATH_DBG_CONFIG, "Rate control updated with " | ||
450 | "caps:0x%x on target\n", priv->tgt_rate.capflags); | ||
451 | } | ||
452 | |||
453 | static int ath9k_htc_aggr_oper(struct ath9k_htc_priv *priv, | ||
454 | struct ieee80211_vif *vif, | ||
455 | u8 *sta_addr, u8 tid, bool oper) | ||
456 | { | ||
457 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
458 | struct ath9k_htc_target_aggr aggr; | ||
459 | struct ieee80211_sta *sta = NULL; | ||
460 | struct ath9k_htc_sta *ista = (struct ath9k_htc_sta *) sta->drv_priv; | ||
461 | int ret = 0; | ||
462 | u8 cmd_rsp; | ||
463 | |||
464 | if (tid > ATH9K_HTC_MAX_TID) | ||
465 | return -EINVAL; | ||
466 | |||
467 | memset(&aggr, 0, sizeof(struct ath9k_htc_target_aggr)); | ||
468 | |||
469 | rcu_read_lock(); | ||
470 | |||
471 | /* Check if we are able to retrieve the station */ | ||
472 | sta = ieee80211_find_sta(vif, sta_addr); | ||
473 | if (!sta) { | ||
474 | rcu_read_unlock(); | ||
475 | return -EINVAL; | ||
476 | } | ||
477 | |||
478 | ista = (struct ath9k_htc_sta *) sta->drv_priv; | ||
479 | |||
480 | if (oper) | ||
481 | ista->tid_state[tid] = AGGR_START; | ||
482 | else | ||
483 | ista->tid_state[tid] = AGGR_STOP; | ||
484 | |||
485 | aggr.sta_index = ista->index; | ||
486 | |||
487 | rcu_read_unlock(); | ||
488 | |||
489 | aggr.tidno = tid; | ||
490 | aggr.aggr_enable = oper; | ||
491 | |||
492 | WMI_CMD_BUF(WMI_TX_AGGR_ENABLE_CMDID, &aggr); | ||
493 | if (ret) | ||
494 | ath_print(common, ATH_DBG_CONFIG, | ||
495 | "Unable to %s TX aggregation for (%pM, %d)\n", | ||
496 | (oper) ? "start" : "stop", sta->addr, tid); | ||
497 | else | ||
498 | ath_print(common, ATH_DBG_CONFIG, | ||
499 | "%s aggregation for (%pM, %d)\n", | ||
500 | (oper) ? "Starting" : "Stopping", sta->addr, tid); | ||
501 | |||
502 | return ret; | ||
503 | } | ||
504 | |||
505 | void ath9k_htc_aggr_work(struct work_struct *work) | ||
506 | { | ||
507 | int ret = 0; | ||
508 | struct ath9k_htc_priv *priv = | ||
509 | container_of(work, struct ath9k_htc_priv, | ||
510 | ath9k_aggr_work.work); | ||
511 | struct ath9k_htc_aggr_work *wk = &priv->aggr_work; | ||
512 | |||
513 | mutex_lock(&wk->mutex); | ||
514 | |||
515 | switch (wk->action) { | ||
516 | case IEEE80211_AMPDU_TX_START: | ||
517 | ret = ath9k_htc_aggr_oper(priv, wk->vif, wk->sta_addr, | ||
518 | wk->tid, true); | ||
519 | if (!ret) | ||
520 | ieee80211_start_tx_ba_cb(wk->vif, wk->sta_addr, | ||
521 | wk->tid); | ||
522 | break; | ||
523 | case IEEE80211_AMPDU_TX_STOP: | ||
524 | ath9k_htc_aggr_oper(priv, wk->vif, wk->sta_addr, | ||
525 | wk->tid, false); | ||
526 | ieee80211_stop_tx_ba_cb(wk->vif, wk->sta_addr, wk->tid); | ||
527 | break; | ||
528 | default: | ||
529 | ath_print(ath9k_hw_common(priv->ah), ATH_DBG_FATAL, | ||
530 | "Unknown AMPDU action\n"); | ||
531 | } | ||
532 | |||
533 | mutex_unlock(&wk->mutex); | ||
534 | } | ||
535 | |||
536 | /*********/ | ||
537 | /* DEBUG */ | ||
538 | /*********/ | ||
539 | |||
540 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS | ||
541 | |||
542 | static int ath9k_debugfs_open(struct inode *inode, struct file *file) | ||
543 | { | ||
544 | file->private_data = inode->i_private; | ||
545 | return 0; | ||
546 | } | ||
547 | |||
548 | static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf, | ||
549 | size_t count, loff_t *ppos) | ||
550 | { | ||
551 | struct ath9k_htc_priv *priv = | ||
552 | (struct ath9k_htc_priv *) file->private_data; | ||
553 | struct ath9k_htc_target_stats cmd_rsp; | ||
554 | char buf[512]; | ||
555 | unsigned int len = 0; | ||
556 | int ret = 0; | ||
557 | |||
558 | memset(&cmd_rsp, 0, sizeof(cmd_rsp)); | ||
559 | |||
560 | WMI_CMD(WMI_TGT_STATS_CMDID); | ||
561 | if (ret) | ||
562 | return -EINVAL; | ||
563 | |||
564 | |||
565 | len += snprintf(buf + len, sizeof(buf) - len, | ||
566 | "%19s : %10u\n", "TX Short Retries", | ||
567 | be32_to_cpu(cmd_rsp.tx_shortretry)); | ||
568 | len += snprintf(buf + len, sizeof(buf) - len, | ||
569 | "%19s : %10u\n", "TX Long Retries", | ||
570 | be32_to_cpu(cmd_rsp.tx_longretry)); | ||
571 | len += snprintf(buf + len, sizeof(buf) - len, | ||
572 | "%19s : %10u\n", "TX Xretries", | ||
573 | be32_to_cpu(cmd_rsp.tx_xretries)); | ||
574 | len += snprintf(buf + len, sizeof(buf) - len, | ||
575 | "%19s : %10u\n", "TX Unaggr. Xretries", | ||
576 | be32_to_cpu(cmd_rsp.ht_txunaggr_xretry)); | ||
577 | len += snprintf(buf + len, sizeof(buf) - len, | ||
578 | "%19s : %10u\n", "TX Xretries (HT)", | ||
579 | be32_to_cpu(cmd_rsp.ht_tx_xretries)); | ||
580 | len += snprintf(buf + len, sizeof(buf) - len, | ||
581 | "%19s : %10u\n", "TX Rate", priv->debug.txrate); | ||
582 | |||
583 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
584 | } | ||
585 | |||
586 | static const struct file_operations fops_tgt_stats = { | ||
587 | .read = read_file_tgt_stats, | ||
588 | .open = ath9k_debugfs_open, | ||
589 | .owner = THIS_MODULE | ||
590 | }; | ||
591 | |||
592 | static ssize_t read_file_xmit(struct file *file, char __user *user_buf, | ||
593 | size_t count, loff_t *ppos) | ||
594 | { | ||
595 | struct ath9k_htc_priv *priv = | ||
596 | (struct ath9k_htc_priv *) file->private_data; | ||
597 | char buf[512]; | ||
598 | unsigned int len = 0; | ||
599 | |||
600 | len += snprintf(buf + len, sizeof(buf) - len, | ||
601 | "%20s : %10u\n", "Buffers queued", | ||
602 | priv->debug.tx_stats.buf_queued); | ||
603 | len += snprintf(buf + len, sizeof(buf) - len, | ||
604 | "%20s : %10u\n", "Buffers completed", | ||
605 | priv->debug.tx_stats.buf_completed); | ||
606 | len += snprintf(buf + len, sizeof(buf) - len, | ||
607 | "%20s : %10u\n", "SKBs queued", | ||
608 | priv->debug.tx_stats.skb_queued); | ||
609 | len += snprintf(buf + len, sizeof(buf) - len, | ||
610 | "%20s : %10u\n", "SKBs completed", | ||
611 | priv->debug.tx_stats.skb_completed); | ||
612 | |||
613 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
614 | } | ||
615 | |||
616 | static const struct file_operations fops_xmit = { | ||
617 | .read = read_file_xmit, | ||
618 | .open = ath9k_debugfs_open, | ||
619 | .owner = THIS_MODULE | ||
620 | }; | ||
621 | |||
622 | static ssize_t read_file_recv(struct file *file, char __user *user_buf, | ||
623 | size_t count, loff_t *ppos) | ||
624 | { | ||
625 | struct ath9k_htc_priv *priv = | ||
626 | (struct ath9k_htc_priv *) file->private_data; | ||
627 | char buf[512]; | ||
628 | unsigned int len = 0; | ||
629 | |||
630 | len += snprintf(buf + len, sizeof(buf) - len, | ||
631 | "%20s : %10u\n", "SKBs allocated", | ||
632 | priv->debug.rx_stats.skb_allocated); | ||
633 | len += snprintf(buf + len, sizeof(buf) - len, | ||
634 | "%20s : %10u\n", "SKBs completed", | ||
635 | priv->debug.rx_stats.skb_completed); | ||
636 | len += snprintf(buf + len, sizeof(buf) - len, | ||
637 | "%20s : %10u\n", "SKBs Dropped", | ||
638 | priv->debug.rx_stats.skb_dropped); | ||
639 | |||
640 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
641 | } | ||
642 | |||
643 | static const struct file_operations fops_recv = { | ||
644 | .read = read_file_recv, | ||
645 | .open = ath9k_debugfs_open, | ||
646 | .owner = THIS_MODULE | ||
647 | }; | ||
648 | |||
649 | int ath9k_htc_init_debug(struct ath_hw *ah) | ||
650 | { | ||
651 | struct ath_common *common = ath9k_hw_common(ah); | ||
652 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; | ||
653 | |||
654 | if (!ath9k_debugfs_root) | ||
655 | return -ENOENT; | ||
656 | |||
657 | priv->debug.debugfs_phy = debugfs_create_dir(wiphy_name(priv->hw->wiphy), | ||
658 | ath9k_debugfs_root); | ||
659 | if (!priv->debug.debugfs_phy) | ||
660 | goto err; | ||
661 | |||
662 | priv->debug.debugfs_tgt_stats = debugfs_create_file("tgt_stats", S_IRUSR, | ||
663 | priv->debug.debugfs_phy, | ||
664 | priv, &fops_tgt_stats); | ||
665 | if (!priv->debug.debugfs_tgt_stats) | ||
666 | goto err; | ||
667 | |||
668 | |||
669 | priv->debug.debugfs_xmit = debugfs_create_file("xmit", S_IRUSR, | ||
670 | priv->debug.debugfs_phy, | ||
671 | priv, &fops_xmit); | ||
672 | if (!priv->debug.debugfs_xmit) | ||
673 | goto err; | ||
674 | |||
675 | priv->debug.debugfs_recv = debugfs_create_file("recv", S_IRUSR, | ||
676 | priv->debug.debugfs_phy, | ||
677 | priv, &fops_recv); | ||
678 | if (!priv->debug.debugfs_recv) | ||
679 | goto err; | ||
680 | |||
681 | return 0; | ||
682 | |||
683 | err: | ||
684 | ath9k_htc_exit_debug(ah); | ||
685 | return -ENOMEM; | ||
686 | } | ||
687 | |||
688 | void ath9k_htc_exit_debug(struct ath_hw *ah) | ||
689 | { | ||
690 | struct ath_common *common = ath9k_hw_common(ah); | ||
691 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; | ||
692 | |||
693 | debugfs_remove(priv->debug.debugfs_recv); | ||
694 | debugfs_remove(priv->debug.debugfs_xmit); | ||
695 | debugfs_remove(priv->debug.debugfs_tgt_stats); | ||
696 | debugfs_remove(priv->debug.debugfs_phy); | ||
697 | } | ||
698 | |||
699 | int ath9k_htc_debug_create_root(void) | ||
700 | { | ||
701 | ath9k_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL); | ||
702 | if (!ath9k_debugfs_root) | ||
703 | return -ENOENT; | ||
704 | |||
705 | return 0; | ||
706 | } | ||
707 | |||
708 | void ath9k_htc_debug_remove_root(void) | ||
709 | { | ||
710 | debugfs_remove(ath9k_debugfs_root); | ||
711 | ath9k_debugfs_root = NULL; | ||
712 | } | ||
713 | |||
714 | #endif /* CONFIG_ATH9K_HTC_DEBUGFS */ | ||
715 | |||
716 | /*******/ | ||
717 | /* ANI */ | ||
718 | /*******/ | ||
719 | |||
720 | static void ath_start_ani(struct ath9k_htc_priv *priv) | ||
721 | { | ||
722 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
723 | unsigned long timestamp = jiffies_to_msecs(jiffies); | ||
724 | |||
725 | common->ani.longcal_timer = timestamp; | ||
726 | common->ani.shortcal_timer = timestamp; | ||
727 | common->ani.checkani_timer = timestamp; | ||
728 | |||
729 | ieee80211_queue_delayed_work(common->hw, &priv->ath9k_ani_work, | ||
730 | msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); | ||
731 | } | ||
732 | |||
733 | void ath9k_ani_work(struct work_struct *work) | ||
734 | { | ||
735 | struct ath9k_htc_priv *priv = | ||
736 | container_of(work, struct ath9k_htc_priv, | ||
737 | ath9k_ani_work.work); | ||
738 | struct ath_hw *ah = priv->ah; | ||
739 | struct ath_common *common = ath9k_hw_common(ah); | ||
740 | bool longcal = false; | ||
741 | bool shortcal = false; | ||
742 | bool aniflag = false; | ||
743 | unsigned int timestamp = jiffies_to_msecs(jiffies); | ||
744 | u32 cal_interval, short_cal_interval; | ||
745 | |||
746 | short_cal_interval = ATH_STA_SHORT_CALINTERVAL; | ||
747 | |||
748 | /* Only calibrate if awake */ | ||
749 | if (ah->power_mode != ATH9K_PM_AWAKE) | ||
750 | goto set_timer; | ||
751 | |||
752 | /* Long calibration runs independently of short calibration. */ | ||
753 | if ((timestamp - common->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) { | ||
754 | longcal = true; | ||
755 | ath_print(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies); | ||
756 | common->ani.longcal_timer = timestamp; | ||
757 | } | ||
758 | |||
759 | /* Short calibration applies only while caldone is false */ | ||
760 | if (!common->ani.caldone) { | ||
761 | if ((timestamp - common->ani.shortcal_timer) >= | ||
762 | short_cal_interval) { | ||
763 | shortcal = true; | ||
764 | ath_print(common, ATH_DBG_ANI, | ||
765 | "shortcal @%lu\n", jiffies); | ||
766 | common->ani.shortcal_timer = timestamp; | ||
767 | common->ani.resetcal_timer = timestamp; | ||
768 | } | ||
769 | } else { | ||
770 | if ((timestamp - common->ani.resetcal_timer) >= | ||
771 | ATH_RESTART_CALINTERVAL) { | ||
772 | common->ani.caldone = ath9k_hw_reset_calvalid(ah); | ||
773 | if (common->ani.caldone) | ||
774 | common->ani.resetcal_timer = timestamp; | ||
775 | } | ||
776 | } | ||
777 | |||
778 | /* Verify whether we must check ANI */ | ||
779 | if ((timestamp - common->ani.checkani_timer) >= ATH_ANI_POLLINTERVAL) { | ||
780 | aniflag = true; | ||
781 | common->ani.checkani_timer = timestamp; | ||
782 | } | ||
783 | |||
784 | /* Skip all processing if there's nothing to do. */ | ||
785 | if (longcal || shortcal || aniflag) { | ||
786 | |||
787 | ath9k_htc_ps_wakeup(priv); | ||
788 | |||
789 | /* Call ANI routine if necessary */ | ||
790 | if (aniflag) | ||
791 | ath9k_hw_ani_monitor(ah, ah->curchan); | ||
792 | |||
793 | /* Perform calibration if necessary */ | ||
794 | if (longcal || shortcal) { | ||
795 | common->ani.caldone = | ||
796 | ath9k_hw_calibrate(ah, ah->curchan, | ||
797 | common->rx_chainmask, | ||
798 | longcal); | ||
799 | |||
800 | if (longcal) | ||
801 | common->ani.noise_floor = | ||
802 | ath9k_hw_getchan_noise(ah, ah->curchan); | ||
803 | |||
804 | ath_print(common, ATH_DBG_ANI, | ||
805 | " calibrate chan %u/%x nf: %d\n", | ||
806 | ah->curchan->channel, | ||
807 | ah->curchan->channelFlags, | ||
808 | common->ani.noise_floor); | ||
809 | } | ||
810 | |||
811 | ath9k_htc_ps_restore(priv); | ||
812 | } | ||
813 | |||
814 | set_timer: | ||
815 | /* | ||
816 | * Set timer interval based on previous results. | ||
817 | * The interval must be the shortest necessary to satisfy ANI, | ||
818 | * short calibration and long calibration. | ||
819 | */ | ||
820 | cal_interval = ATH_LONG_CALINTERVAL; | ||
821 | if (priv->ah->config.enable_ani) | ||
822 | cal_interval = min(cal_interval, (u32)ATH_ANI_POLLINTERVAL); | ||
823 | if (!common->ani.caldone) | ||
824 | cal_interval = min(cal_interval, (u32)short_cal_interval); | ||
825 | |||
826 | ieee80211_queue_delayed_work(common->hw, &priv->ath9k_ani_work, | ||
827 | msecs_to_jiffies(cal_interval)); | ||
828 | } | ||
829 | |||
830 | /*******/ | ||
831 | /* LED */ | ||
832 | /*******/ | ||
833 | |||
834 | static void ath9k_led_blink_work(struct work_struct *work) | ||
835 | { | ||
836 | struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv, | ||
837 | ath9k_led_blink_work.work); | ||
838 | |||
839 | if (!(priv->op_flags & OP_LED_ASSOCIATED)) | ||
840 | return; | ||
841 | |||
842 | if ((priv->led_on_duration == ATH_LED_ON_DURATION_IDLE) || | ||
843 | (priv->led_off_duration == ATH_LED_OFF_DURATION_IDLE)) | ||
844 | ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 0); | ||
845 | else | ||
846 | ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, | ||
847 | (priv->op_flags & OP_LED_ON) ? 1 : 0); | ||
848 | |||
849 | ieee80211_queue_delayed_work(priv->hw, | ||
850 | &priv->ath9k_led_blink_work, | ||
851 | (priv->op_flags & OP_LED_ON) ? | ||
852 | msecs_to_jiffies(priv->led_off_duration) : | ||
853 | msecs_to_jiffies(priv->led_on_duration)); | ||
854 | |||
855 | priv->led_on_duration = priv->led_on_cnt ? | ||
856 | max((ATH_LED_ON_DURATION_IDLE - priv->led_on_cnt), 25) : | ||
857 | ATH_LED_ON_DURATION_IDLE; | ||
858 | priv->led_off_duration = priv->led_off_cnt ? | ||
859 | max((ATH_LED_OFF_DURATION_IDLE - priv->led_off_cnt), 10) : | ||
860 | ATH_LED_OFF_DURATION_IDLE; | ||
861 | priv->led_on_cnt = priv->led_off_cnt = 0; | ||
862 | |||
863 | if (priv->op_flags & OP_LED_ON) | ||
864 | priv->op_flags &= ~OP_LED_ON; | ||
865 | else | ||
866 | priv->op_flags |= OP_LED_ON; | ||
867 | } | ||
868 | |||
869 | static void ath9k_led_brightness_work(struct work_struct *work) | ||
870 | { | ||
871 | struct ath_led *led = container_of(work, struct ath_led, | ||
872 | brightness_work.work); | ||
873 | struct ath9k_htc_priv *priv = led->priv; | ||
874 | |||
875 | switch (led->brightness) { | ||
876 | case LED_OFF: | ||
877 | if (led->led_type == ATH_LED_ASSOC || | ||
878 | led->led_type == ATH_LED_RADIO) { | ||
879 | ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, | ||
880 | (led->led_type == ATH_LED_RADIO)); | ||
881 | priv->op_flags &= ~OP_LED_ASSOCIATED; | ||
882 | if (led->led_type == ATH_LED_RADIO) | ||
883 | priv->op_flags &= ~OP_LED_ON; | ||
884 | } else { | ||
885 | priv->led_off_cnt++; | ||
886 | } | ||
887 | break; | ||
888 | case LED_FULL: | ||
889 | if (led->led_type == ATH_LED_ASSOC) { | ||
890 | priv->op_flags |= OP_LED_ASSOCIATED; | ||
891 | ieee80211_queue_delayed_work(priv->hw, | ||
892 | &priv->ath9k_led_blink_work, 0); | ||
893 | } else if (led->led_type == ATH_LED_RADIO) { | ||
894 | ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 0); | ||
895 | priv->op_flags |= OP_LED_ON; | ||
896 | } else { | ||
897 | priv->led_on_cnt++; | ||
898 | } | ||
899 | break; | ||
900 | default: | ||
901 | break; | ||
902 | } | ||
903 | } | ||
904 | |||
905 | static void ath9k_led_brightness(struct led_classdev *led_cdev, | ||
906 | enum led_brightness brightness) | ||
907 | { | ||
908 | struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev); | ||
909 | struct ath9k_htc_priv *priv = led->priv; | ||
910 | |||
911 | led->brightness = brightness; | ||
912 | if (!(priv->op_flags & OP_LED_DEINIT)) | ||
913 | ieee80211_queue_delayed_work(priv->hw, | ||
914 | &led->brightness_work, 0); | ||
915 | } | ||
916 | |||
917 | static void ath9k_led_stop_brightness(struct ath9k_htc_priv *priv) | ||
918 | { | ||
919 | cancel_delayed_work_sync(&priv->radio_led.brightness_work); | ||
920 | cancel_delayed_work_sync(&priv->assoc_led.brightness_work); | ||
921 | cancel_delayed_work_sync(&priv->tx_led.brightness_work); | ||
922 | cancel_delayed_work_sync(&priv->rx_led.brightness_work); | ||
923 | } | ||
924 | |||
925 | static int ath9k_register_led(struct ath9k_htc_priv *priv, struct ath_led *led, | ||
926 | char *trigger) | ||
927 | { | ||
928 | int ret; | ||
929 | |||
930 | led->priv = priv; | ||
931 | led->led_cdev.name = led->name; | ||
932 | led->led_cdev.default_trigger = trigger; | ||
933 | led->led_cdev.brightness_set = ath9k_led_brightness; | ||
934 | |||
935 | ret = led_classdev_register(wiphy_dev(priv->hw->wiphy), &led->led_cdev); | ||
936 | if (ret) | ||
937 | ath_print(ath9k_hw_common(priv->ah), ATH_DBG_FATAL, | ||
938 | "Failed to register led:%s", led->name); | ||
939 | else | ||
940 | led->registered = 1; | ||
941 | |||
942 | INIT_DELAYED_WORK(&led->brightness_work, ath9k_led_brightness_work); | ||
943 | |||
944 | return ret; | ||
945 | } | ||
946 | |||
947 | static void ath9k_unregister_led(struct ath_led *led) | ||
948 | { | ||
949 | if (led->registered) { | ||
950 | led_classdev_unregister(&led->led_cdev); | ||
951 | led->registered = 0; | ||
952 | } | ||
953 | } | ||
954 | |||
955 | void ath9k_deinit_leds(struct ath9k_htc_priv *priv) | ||
956 | { | ||
957 | priv->op_flags |= OP_LED_DEINIT; | ||
958 | ath9k_unregister_led(&priv->assoc_led); | ||
959 | priv->op_flags &= ~OP_LED_ASSOCIATED; | ||
960 | ath9k_unregister_led(&priv->tx_led); | ||
961 | ath9k_unregister_led(&priv->rx_led); | ||
962 | ath9k_unregister_led(&priv->radio_led); | ||
963 | ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1); | ||
964 | } | ||
965 | |||
966 | void ath9k_init_leds(struct ath9k_htc_priv *priv) | ||
967 | { | ||
968 | char *trigger; | ||
969 | int ret; | ||
970 | |||
971 | if (AR_SREV_9287(priv->ah)) | ||
972 | priv->ah->led_pin = ATH_LED_PIN_9287; | ||
973 | else if (AR_SREV_9271(priv->ah)) | ||
974 | priv->ah->led_pin = ATH_LED_PIN_9271; | ||
975 | else | ||
976 | priv->ah->led_pin = ATH_LED_PIN_DEF; | ||
977 | |||
978 | /* Configure gpio 1 for output */ | ||
979 | ath9k_hw_cfg_output(priv->ah, priv->ah->led_pin, | ||
980 | AR_GPIO_OUTPUT_MUX_AS_OUTPUT); | ||
981 | /* LED off, active low */ | ||
982 | ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1); | ||
983 | |||
984 | INIT_DELAYED_WORK(&priv->ath9k_led_blink_work, ath9k_led_blink_work); | ||
985 | |||
986 | trigger = ieee80211_get_radio_led_name(priv->hw); | ||
987 | snprintf(priv->radio_led.name, sizeof(priv->radio_led.name), | ||
988 | "ath9k-%s::radio", wiphy_name(priv->hw->wiphy)); | ||
989 | ret = ath9k_register_led(priv, &priv->radio_led, trigger); | ||
990 | priv->radio_led.led_type = ATH_LED_RADIO; | ||
991 | if (ret) | ||
992 | goto fail; | ||
993 | |||
994 | trigger = ieee80211_get_assoc_led_name(priv->hw); | ||
995 | snprintf(priv->assoc_led.name, sizeof(priv->assoc_led.name), | ||
996 | "ath9k-%s::assoc", wiphy_name(priv->hw->wiphy)); | ||
997 | ret = ath9k_register_led(priv, &priv->assoc_led, trigger); | ||
998 | priv->assoc_led.led_type = ATH_LED_ASSOC; | ||
999 | if (ret) | ||
1000 | goto fail; | ||
1001 | |||
1002 | trigger = ieee80211_get_tx_led_name(priv->hw); | ||
1003 | snprintf(priv->tx_led.name, sizeof(priv->tx_led.name), | ||
1004 | "ath9k-%s::tx", wiphy_name(priv->hw->wiphy)); | ||
1005 | ret = ath9k_register_led(priv, &priv->tx_led, trigger); | ||
1006 | priv->tx_led.led_type = ATH_LED_TX; | ||
1007 | if (ret) | ||
1008 | goto fail; | ||
1009 | |||
1010 | trigger = ieee80211_get_rx_led_name(priv->hw); | ||
1011 | snprintf(priv->rx_led.name, sizeof(priv->rx_led.name), | ||
1012 | "ath9k-%s::rx", wiphy_name(priv->hw->wiphy)); | ||
1013 | ret = ath9k_register_led(priv, &priv->rx_led, trigger); | ||
1014 | priv->rx_led.led_type = ATH_LED_RX; | ||
1015 | if (ret) | ||
1016 | goto fail; | ||
1017 | |||
1018 | priv->op_flags &= ~OP_LED_DEINIT; | ||
1019 | |||
1020 | return; | ||
1021 | |||
1022 | fail: | ||
1023 | cancel_delayed_work_sync(&priv->ath9k_led_blink_work); | ||
1024 | ath9k_deinit_leds(priv); | ||
1025 | } | ||
1026 | |||
1027 | /*******************/ | ||
1028 | /* Rfkill */ | ||
1029 | /*******************/ | ||
1030 | |||
1031 | static bool ath_is_rfkill_set(struct ath9k_htc_priv *priv) | ||
1032 | { | ||
1033 | return ath9k_hw_gpio_get(priv->ah, priv->ah->rfkill_gpio) == | ||
1034 | priv->ah->rfkill_polarity; | ||
1035 | } | ||
1036 | |||
1037 | static void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw) | ||
1038 | { | ||
1039 | struct ath9k_htc_priv *priv = hw->priv; | ||
1040 | bool blocked = !!ath_is_rfkill_set(priv); | ||
1041 | |||
1042 | wiphy_rfkill_set_hw_state(hw->wiphy, blocked); | ||
1043 | } | ||
1044 | |||
1045 | void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv) | ||
1046 | { | ||
1047 | if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) | ||
1048 | wiphy_rfkill_start_polling(priv->hw->wiphy); | ||
1049 | } | ||
1050 | |||
1051 | /**********************/ | ||
1052 | /* mac80211 Callbacks */ | ||
1053 | /**********************/ | ||
1054 | |||
1055 | static int ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | ||
1056 | { | ||
1057 | struct ieee80211_hdr *hdr; | ||
1058 | struct ath9k_htc_priv *priv = hw->priv; | ||
1059 | int padpos, padsize, ret; | ||
1060 | |||
1061 | hdr = (struct ieee80211_hdr *) skb->data; | ||
1062 | |||
1063 | /* Add the padding after the header if this is not already done */ | ||
1064 | padpos = ath9k_cmn_padpos(hdr->frame_control); | ||
1065 | padsize = padpos & 3; | ||
1066 | if (padsize && skb->len > padpos) { | ||
1067 | if (skb_headroom(skb) < padsize) | ||
1068 | return -1; | ||
1069 | skb_push(skb, padsize); | ||
1070 | memmove(skb->data, skb->data + padsize, padpos); | ||
1071 | } | ||
1072 | |||
1073 | ret = ath9k_htc_tx_start(priv, skb); | ||
1074 | if (ret != 0) { | ||
1075 | if (ret == -ENOMEM) { | ||
1076 | ath_print(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, | ||
1077 | "Stopping TX queues\n"); | ||
1078 | ieee80211_stop_queues(hw); | ||
1079 | spin_lock_bh(&priv->tx_lock); | ||
1080 | priv->tx_queues_stop = true; | ||
1081 | spin_unlock_bh(&priv->tx_lock); | ||
1082 | } else { | ||
1083 | ath_print(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, | ||
1084 | "Tx failed"); | ||
1085 | } | ||
1086 | goto fail_tx; | ||
1087 | } | ||
1088 | |||
1089 | return 0; | ||
1090 | |||
1091 | fail_tx: | ||
1092 | dev_kfree_skb_any(skb); | ||
1093 | return 0; | ||
1094 | } | ||
1095 | |||
1096 | static int ath9k_htc_start(struct ieee80211_hw *hw) | ||
1097 | { | ||
1098 | struct ath9k_htc_priv *priv = hw->priv; | ||
1099 | struct ath_hw *ah = priv->ah; | ||
1100 | struct ath_common *common = ath9k_hw_common(ah); | ||
1101 | struct ieee80211_channel *curchan = hw->conf.channel; | ||
1102 | struct ath9k_channel *init_channel; | ||
1103 | int ret = 0; | ||
1104 | enum htc_phymode mode; | ||
1105 | u16 htc_mode; | ||
1106 | u8 cmd_rsp; | ||
1107 | |||
1108 | ath_print(common, ATH_DBG_CONFIG, | ||
1109 | "Starting driver with initial channel: %d MHz\n", | ||
1110 | curchan->center_freq); | ||
1111 | |||
1112 | mutex_lock(&priv->mutex); | ||
1113 | |||
1114 | /* setup initial channel */ | ||
1115 | init_channel = ath9k_cmn_get_curchannel(hw, ah); | ||
1116 | |||
1117 | /* Reset SERDES registers */ | ||
1118 | ath9k_hw_configpcipowersave(ah, 0, 0); | ||
1119 | |||
1120 | ath9k_hw_htc_resetinit(ah); | ||
1121 | ret = ath9k_hw_reset(ah, init_channel, false); | ||
1122 | if (ret) { | ||
1123 | ath_print(common, ATH_DBG_FATAL, | ||
1124 | "Unable to reset hardware; reset status %d " | ||
1125 | "(freq %u MHz)\n", ret, curchan->center_freq); | ||
1126 | goto mutex_unlock; | ||
1127 | } | ||
1128 | |||
1129 | ath_update_txpow(priv); | ||
1130 | |||
1131 | mode = ath9k_htc_get_curmode(priv, init_channel); | ||
1132 | htc_mode = cpu_to_be16(mode); | ||
1133 | WMI_CMD_BUF(WMI_SET_MODE_CMDID, &htc_mode); | ||
1134 | if (ret) | ||
1135 | goto mutex_unlock; | ||
1136 | |||
1137 | WMI_CMD(WMI_ATH_INIT_CMDID); | ||
1138 | if (ret) | ||
1139 | goto mutex_unlock; | ||
1140 | |||
1141 | WMI_CMD(WMI_START_RECV_CMDID); | ||
1142 | if (ret) | ||
1143 | goto mutex_unlock; | ||
1144 | |||
1145 | ath9k_host_rx_init(priv); | ||
1146 | |||
1147 | priv->op_flags &= ~OP_INVALID; | ||
1148 | htc_start(priv->htc); | ||
1149 | |||
1150 | spin_lock_bh(&priv->tx_lock); | ||
1151 | priv->tx_queues_stop = false; | ||
1152 | spin_unlock_bh(&priv->tx_lock); | ||
1153 | |||
1154 | ieee80211_wake_queues(hw); | ||
1155 | |||
1156 | mutex_unlock: | ||
1157 | mutex_unlock(&priv->mutex); | ||
1158 | return ret; | ||
1159 | } | ||
1160 | |||
1161 | static void ath9k_htc_stop(struct ieee80211_hw *hw) | ||
1162 | { | ||
1163 | struct ath9k_htc_priv *priv = hw->priv; | ||
1164 | struct ath_hw *ah = priv->ah; | ||
1165 | struct ath_common *common = ath9k_hw_common(ah); | ||
1166 | int ret = 0; | ||
1167 | u8 cmd_rsp; | ||
1168 | |||
1169 | mutex_lock(&priv->mutex); | ||
1170 | |||
1171 | if (priv->op_flags & OP_INVALID) { | ||
1172 | ath_print(common, ATH_DBG_ANY, "Device not present\n"); | ||
1173 | mutex_unlock(&priv->mutex); | ||
1174 | return; | ||
1175 | } | ||
1176 | |||
1177 | ath9k_htc_ps_wakeup(priv); | ||
1178 | htc_stop(priv->htc); | ||
1179 | WMI_CMD(WMI_DISABLE_INTR_CMDID); | ||
1180 | WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); | ||
1181 | WMI_CMD(WMI_STOP_RECV_CMDID); | ||
1182 | ath9k_hw_phy_disable(ah); | ||
1183 | ath9k_hw_disable(ah); | ||
1184 | ath9k_hw_configpcipowersave(ah, 1, 1); | ||
1185 | ath9k_htc_ps_restore(priv); | ||
1186 | ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP); | ||
1187 | |||
1188 | cancel_work_sync(&priv->ps_work); | ||
1189 | cancel_delayed_work_sync(&priv->ath9k_ani_work); | ||
1190 | cancel_delayed_work_sync(&priv->ath9k_aggr_work); | ||
1191 | cancel_delayed_work_sync(&priv->ath9k_led_blink_work); | ||
1192 | ath9k_led_stop_brightness(priv); | ||
1193 | skb_queue_purge(&priv->tx_queue); | ||
1194 | |||
1195 | /* Remove monitor interface here */ | ||
1196 | if (ah->opmode == NL80211_IFTYPE_MONITOR) { | ||
1197 | if (ath9k_htc_remove_monitor_interface(priv)) | ||
1198 | ath_print(common, ATH_DBG_FATAL, | ||
1199 | "Unable to remove monitor interface\n"); | ||
1200 | else | ||
1201 | ath_print(common, ATH_DBG_CONFIG, | ||
1202 | "Monitor interface removed\n"); | ||
1203 | } | ||
1204 | |||
1205 | priv->op_flags |= OP_INVALID; | ||
1206 | mutex_unlock(&priv->mutex); | ||
1207 | |||
1208 | ath_print(common, ATH_DBG_CONFIG, "Driver halt\n"); | ||
1209 | } | ||
1210 | |||
1211 | static int ath9k_htc_add_interface(struct ieee80211_hw *hw, | ||
1212 | struct ieee80211_vif *vif) | ||
1213 | { | ||
1214 | struct ath9k_htc_priv *priv = hw->priv; | ||
1215 | struct ath9k_htc_vif *avp = (void *)vif->drv_priv; | ||
1216 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
1217 | struct ath9k_htc_target_vif hvif; | ||
1218 | int ret = 0; | ||
1219 | u8 cmd_rsp; | ||
1220 | |||
1221 | mutex_lock(&priv->mutex); | ||
1222 | |||
1223 | /* Only one interface for now */ | ||
1224 | if (priv->nvifs > 0) { | ||
1225 | ret = -ENOBUFS; | ||
1226 | goto out; | ||
1227 | } | ||
1228 | |||
1229 | ath9k_htc_ps_wakeup(priv); | ||
1230 | memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); | ||
1231 | memcpy(&hvif.myaddr, vif->addr, ETH_ALEN); | ||
1232 | |||
1233 | switch (vif->type) { | ||
1234 | case NL80211_IFTYPE_STATION: | ||
1235 | hvif.opmode = cpu_to_be32(HTC_M_STA); | ||
1236 | break; | ||
1237 | case NL80211_IFTYPE_ADHOC: | ||
1238 | hvif.opmode = cpu_to_be32(HTC_M_IBSS); | ||
1239 | break; | ||
1240 | default: | ||
1241 | ath_print(common, ATH_DBG_FATAL, | ||
1242 | "Interface type %d not yet supported\n", vif->type); | ||
1243 | ret = -EOPNOTSUPP; | ||
1244 | goto out; | ||
1245 | } | ||
1246 | |||
1247 | ath_print(common, ATH_DBG_CONFIG, | ||
1248 | "Attach a VIF of type: %d\n", vif->type); | ||
1249 | |||
1250 | priv->ah->opmode = vif->type; | ||
1251 | |||
1252 | /* Index starts from zero on the target */ | ||
1253 | avp->index = hvif.index = priv->nvifs; | ||
1254 | hvif.rtsthreshold = cpu_to_be16(2304); | ||
1255 | WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif); | ||
1256 | if (ret) | ||
1257 | goto out; | ||
1258 | |||
1259 | priv->nvifs++; | ||
1260 | |||
1261 | /* | ||
1262 | * We need a node in target to tx mgmt frames | ||
1263 | * before association. | ||
1264 | */ | ||
1265 | ret = ath9k_htc_add_station(priv, vif, NULL); | ||
1266 | if (ret) | ||
1267 | goto out; | ||
1268 | |||
1269 | ret = ath9k_htc_update_cap_target(priv); | ||
1270 | if (ret) | ||
1271 | ath_print(common, ATH_DBG_CONFIG, "Failed to update" | ||
1272 | " capability in target \n"); | ||
1273 | |||
1274 | priv->vif = vif; | ||
1275 | out: | ||
1276 | ath9k_htc_ps_restore(priv); | ||
1277 | mutex_unlock(&priv->mutex); | ||
1278 | return ret; | ||
1279 | } | ||
1280 | |||
1281 | static void ath9k_htc_remove_interface(struct ieee80211_hw *hw, | ||
1282 | struct ieee80211_vif *vif) | ||
1283 | { | ||
1284 | struct ath9k_htc_priv *priv = hw->priv; | ||
1285 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
1286 | struct ath9k_htc_vif *avp = (void *)vif->drv_priv; | ||
1287 | struct ath9k_htc_target_vif hvif; | ||
1288 | int ret = 0; | ||
1289 | u8 cmd_rsp; | ||
1290 | |||
1291 | ath_print(common, ATH_DBG_CONFIG, "Detach Interface\n"); | ||
1292 | |||
1293 | mutex_lock(&priv->mutex); | ||
1294 | |||
1295 | memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); | ||
1296 | memcpy(&hvif.myaddr, vif->addr, ETH_ALEN); | ||
1297 | hvif.index = avp->index; | ||
1298 | WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); | ||
1299 | priv->nvifs--; | ||
1300 | |||
1301 | ath9k_htc_remove_station(priv, vif, NULL); | ||
1302 | |||
1303 | if (vif->type == NL80211_IFTYPE_ADHOC) { | ||
1304 | spin_lock_bh(&priv->beacon_lock); | ||
1305 | if (priv->beacon) | ||
1306 | dev_kfree_skb_any(priv->beacon); | ||
1307 | priv->beacon = NULL; | ||
1308 | spin_unlock_bh(&priv->beacon_lock); | ||
1309 | } | ||
1310 | |||
1311 | priv->vif = NULL; | ||
1312 | |||
1313 | mutex_unlock(&priv->mutex); | ||
1314 | } | ||
1315 | |||
1316 | static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) | ||
1317 | { | ||
1318 | struct ath9k_htc_priv *priv = hw->priv; | ||
1319 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
1320 | struct ieee80211_conf *conf = &hw->conf; | ||
1321 | |||
1322 | mutex_lock(&priv->mutex); | ||
1323 | |||
1324 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { | ||
1325 | struct ieee80211_channel *curchan = hw->conf.channel; | ||
1326 | int pos = curchan->hw_value; | ||
1327 | bool is_cw40 = false; | ||
1328 | |||
1329 | ath_print(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n", | ||
1330 | curchan->center_freq); | ||
1331 | |||
1332 | if (check_rc_update(hw, &is_cw40)) | ||
1333 | ath9k_htc_rc_update(priv, is_cw40); | ||
1334 | |||
1335 | ath9k_cmn_update_ichannel(hw, &priv->ah->channels[pos]); | ||
1336 | |||
1337 | if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) { | ||
1338 | ath_print(common, ATH_DBG_FATAL, | ||
1339 | "Unable to set channel\n"); | ||
1340 | mutex_unlock(&priv->mutex); | ||
1341 | return -EINVAL; | ||
1342 | } | ||
1343 | |||
1344 | } | ||
1345 | if (changed & IEEE80211_CONF_CHANGE_PS) { | ||
1346 | if (conf->flags & IEEE80211_CONF_PS) { | ||
1347 | ath9k_htc_setpower(priv, ATH9K_PM_NETWORK_SLEEP); | ||
1348 | priv->ps_enabled = true; | ||
1349 | } else { | ||
1350 | priv->ps_enabled = false; | ||
1351 | cancel_work_sync(&priv->ps_work); | ||
1352 | ath9k_htc_setpower(priv, ATH9K_PM_AWAKE); | ||
1353 | } | ||
1354 | } | ||
1355 | |||
1356 | if (changed & IEEE80211_CONF_CHANGE_MONITOR) { | ||
1357 | if (conf->flags & IEEE80211_CONF_MONITOR) { | ||
1358 | if (ath9k_htc_add_monitor_interface(priv)) | ||
1359 | ath_print(common, ATH_DBG_FATAL, | ||
1360 | "Failed to set monitor mode\n"); | ||
1361 | else | ||
1362 | ath_print(common, ATH_DBG_CONFIG, | ||
1363 | "HW opmode set to Monitor mode\n"); | ||
1364 | } | ||
1365 | } | ||
1366 | |||
1367 | mutex_unlock(&priv->mutex); | ||
1368 | |||
1369 | return 0; | ||
1370 | } | ||
1371 | |||
1372 | #define SUPPORTED_FILTERS \ | ||
1373 | (FIF_PROMISC_IN_BSS | \ | ||
1374 | FIF_ALLMULTI | \ | ||
1375 | FIF_CONTROL | \ | ||
1376 | FIF_PSPOLL | \ | ||
1377 | FIF_OTHER_BSS | \ | ||
1378 | FIF_BCN_PRBRESP_PROMISC | \ | ||
1379 | FIF_FCSFAIL) | ||
1380 | |||
1381 | static void ath9k_htc_configure_filter(struct ieee80211_hw *hw, | ||
1382 | unsigned int changed_flags, | ||
1383 | unsigned int *total_flags, | ||
1384 | u64 multicast) | ||
1385 | { | ||
1386 | struct ath9k_htc_priv *priv = hw->priv; | ||
1387 | u32 rfilt; | ||
1388 | |||
1389 | mutex_lock(&priv->mutex); | ||
1390 | |||
1391 | ath9k_htc_ps_wakeup(priv); | ||
1392 | changed_flags &= SUPPORTED_FILTERS; | ||
1393 | *total_flags &= SUPPORTED_FILTERS; | ||
1394 | |||
1395 | priv->rxfilter = *total_flags; | ||
1396 | rfilt = ath9k_htc_calcrxfilter(priv); | ||
1397 | ath9k_hw_setrxfilter(priv->ah, rfilt); | ||
1398 | |||
1399 | ath_print(ath9k_hw_common(priv->ah), ATH_DBG_CONFIG, | ||
1400 | "Set HW RX filter: 0x%x\n", rfilt); | ||
1401 | |||
1402 | ath9k_htc_ps_restore(priv); | ||
1403 | mutex_unlock(&priv->mutex); | ||
1404 | } | ||
1405 | |||
1406 | static void ath9k_htc_sta_notify(struct ieee80211_hw *hw, | ||
1407 | struct ieee80211_vif *vif, | ||
1408 | enum sta_notify_cmd cmd, | ||
1409 | struct ieee80211_sta *sta) | ||
1410 | { | ||
1411 | struct ath9k_htc_priv *priv = hw->priv; | ||
1412 | int ret; | ||
1413 | |||
1414 | switch (cmd) { | ||
1415 | case STA_NOTIFY_ADD: | ||
1416 | ret = ath9k_htc_add_station(priv, vif, sta); | ||
1417 | if (!ret) | ||
1418 | ath9k_htc_init_rate(priv, vif, sta); | ||
1419 | break; | ||
1420 | case STA_NOTIFY_REMOVE: | ||
1421 | ath9k_htc_remove_station(priv, vif, sta); | ||
1422 | break; | ||
1423 | default: | ||
1424 | break; | ||
1425 | } | ||
1426 | } | ||
1427 | |||
1428 | static int ath9k_htc_conf_tx(struct ieee80211_hw *hw, u16 queue, | ||
1429 | const struct ieee80211_tx_queue_params *params) | ||
1430 | { | ||
1431 | struct ath9k_htc_priv *priv = hw->priv; | ||
1432 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
1433 | struct ath9k_tx_queue_info qi; | ||
1434 | int ret = 0, qnum; | ||
1435 | |||
1436 | if (queue >= WME_NUM_AC) | ||
1437 | return 0; | ||
1438 | |||
1439 | mutex_lock(&priv->mutex); | ||
1440 | |||
1441 | memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); | ||
1442 | |||
1443 | qi.tqi_aifs = params->aifs; | ||
1444 | qi.tqi_cwmin = params->cw_min; | ||
1445 | qi.tqi_cwmax = params->cw_max; | ||
1446 | qi.tqi_burstTime = params->txop; | ||
1447 | |||
1448 | qnum = get_hw_qnum(queue, priv->hwq_map); | ||
1449 | |||
1450 | ath_print(common, ATH_DBG_CONFIG, | ||
1451 | "Configure tx [queue/hwq] [%d/%d], " | ||
1452 | "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n", | ||
1453 | queue, qnum, params->aifs, params->cw_min, | ||
1454 | params->cw_max, params->txop); | ||
1455 | |||
1456 | ret = ath_htc_txq_update(priv, qnum, &qi); | ||
1457 | if (ret) | ||
1458 | ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n"); | ||
1459 | |||
1460 | mutex_unlock(&priv->mutex); | ||
1461 | |||
1462 | return ret; | ||
1463 | } | ||
1464 | |||
1465 | static int ath9k_htc_set_key(struct ieee80211_hw *hw, | ||
1466 | enum set_key_cmd cmd, | ||
1467 | struct ieee80211_vif *vif, | ||
1468 | struct ieee80211_sta *sta, | ||
1469 | struct ieee80211_key_conf *key) | ||
1470 | { | ||
1471 | struct ath9k_htc_priv *priv = hw->priv; | ||
1472 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
1473 | int ret = 0; | ||
1474 | |||
1475 | if (htc_modparam_nohwcrypt) | ||
1476 | return -ENOSPC; | ||
1477 | |||
1478 | mutex_lock(&priv->mutex); | ||
1479 | ath_print(common, ATH_DBG_CONFIG, "Set HW Key\n"); | ||
1480 | ath9k_htc_ps_wakeup(priv); | ||
1481 | |||
1482 | switch (cmd) { | ||
1483 | case SET_KEY: | ||
1484 | ret = ath9k_cmn_key_config(common, vif, sta, key); | ||
1485 | if (ret >= 0) { | ||
1486 | key->hw_key_idx = ret; | ||
1487 | /* push IV and Michael MIC generation to stack */ | ||
1488 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | ||
1489 | if (key->alg == ALG_TKIP) | ||
1490 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; | ||
1491 | if (priv->ah->sw_mgmt_crypto && key->alg == ALG_CCMP) | ||
1492 | key->flags |= IEEE80211_KEY_FLAG_SW_MGMT; | ||
1493 | ret = 0; | ||
1494 | } | ||
1495 | break; | ||
1496 | case DISABLE_KEY: | ||
1497 | ath9k_cmn_key_delete(common, key); | ||
1498 | break; | ||
1499 | default: | ||
1500 | ret = -EINVAL; | ||
1501 | } | ||
1502 | |||
1503 | ath9k_htc_ps_restore(priv); | ||
1504 | mutex_unlock(&priv->mutex); | ||
1505 | |||
1506 | return ret; | ||
1507 | } | ||
1508 | |||
1509 | static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, | ||
1510 | struct ieee80211_vif *vif, | ||
1511 | struct ieee80211_bss_conf *bss_conf, | ||
1512 | u32 changed) | ||
1513 | { | ||
1514 | struct ath9k_htc_priv *priv = hw->priv; | ||
1515 | struct ath_hw *ah = priv->ah; | ||
1516 | struct ath_common *common = ath9k_hw_common(ah); | ||
1517 | |||
1518 | mutex_lock(&priv->mutex); | ||
1519 | ath9k_htc_ps_wakeup(priv); | ||
1520 | |||
1521 | if (changed & BSS_CHANGED_ASSOC) { | ||
1522 | common->curaid = bss_conf->assoc ? | ||
1523 | bss_conf->aid : 0; | ||
1524 | ath_print(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n", | ||
1525 | bss_conf->assoc); | ||
1526 | |||
1527 | if (bss_conf->assoc) { | ||
1528 | priv->op_flags |= OP_ASSOCIATED; | ||
1529 | ath_start_ani(priv); | ||
1530 | } else { | ||
1531 | priv->op_flags &= ~OP_ASSOCIATED; | ||
1532 | cancel_work_sync(&priv->ps_work); | ||
1533 | cancel_delayed_work_sync(&priv->ath9k_ani_work); | ||
1534 | } | ||
1535 | } | ||
1536 | |||
1537 | if (changed & BSS_CHANGED_BSSID) { | ||
1538 | /* Set BSSID */ | ||
1539 | memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); | ||
1540 | ath9k_hw_write_associd(ah); | ||
1541 | |||
1542 | ath_print(common, ATH_DBG_CONFIG, | ||
1543 | "BSSID: %pM aid: 0x%x\n", | ||
1544 | common->curbssid, common->curaid); | ||
1545 | } | ||
1546 | |||
1547 | if ((changed & BSS_CHANGED_BEACON_INT) || | ||
1548 | (changed & BSS_CHANGED_BEACON) || | ||
1549 | ((changed & BSS_CHANGED_BEACON_ENABLED) && | ||
1550 | bss_conf->enable_beacon)) { | ||
1551 | priv->op_flags |= OP_ENABLE_BEACON; | ||
1552 | ath9k_htc_beacon_config(priv, vif); | ||
1553 | } | ||
1554 | |||
1555 | if (changed & BSS_CHANGED_BEACON) | ||
1556 | ath9k_htc_beacon_update(priv, vif); | ||
1557 | |||
1558 | if ((changed & BSS_CHANGED_BEACON_ENABLED) && | ||
1559 | !bss_conf->enable_beacon) { | ||
1560 | priv->op_flags &= ~OP_ENABLE_BEACON; | ||
1561 | ath9k_htc_beacon_config(priv, vif); | ||
1562 | } | ||
1563 | |||
1564 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { | ||
1565 | ath_print(common, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n", | ||
1566 | bss_conf->use_short_preamble); | ||
1567 | if (bss_conf->use_short_preamble) | ||
1568 | priv->op_flags |= OP_PREAMBLE_SHORT; | ||
1569 | else | ||
1570 | priv->op_flags &= ~OP_PREAMBLE_SHORT; | ||
1571 | } | ||
1572 | |||
1573 | if (changed & BSS_CHANGED_ERP_CTS_PROT) { | ||
1574 | ath_print(common, ATH_DBG_CONFIG, "BSS Changed CTS PROT %d\n", | ||
1575 | bss_conf->use_cts_prot); | ||
1576 | if (bss_conf->use_cts_prot && | ||
1577 | hw->conf.channel->band != IEEE80211_BAND_5GHZ) | ||
1578 | priv->op_flags |= OP_PROTECT_ENABLE; | ||
1579 | else | ||
1580 | priv->op_flags &= ~OP_PROTECT_ENABLE; | ||
1581 | } | ||
1582 | |||
1583 | if (changed & BSS_CHANGED_ERP_SLOT) { | ||
1584 | if (bss_conf->use_short_slot) | ||
1585 | ah->slottime = 9; | ||
1586 | else | ||
1587 | ah->slottime = 20; | ||
1588 | |||
1589 | ath9k_hw_init_global_settings(ah); | ||
1590 | } | ||
1591 | |||
1592 | ath9k_htc_ps_restore(priv); | ||
1593 | mutex_unlock(&priv->mutex); | ||
1594 | } | ||
1595 | |||
1596 | static u64 ath9k_htc_get_tsf(struct ieee80211_hw *hw) | ||
1597 | { | ||
1598 | struct ath9k_htc_priv *priv = hw->priv; | ||
1599 | u64 tsf; | ||
1600 | |||
1601 | mutex_lock(&priv->mutex); | ||
1602 | tsf = ath9k_hw_gettsf64(priv->ah); | ||
1603 | mutex_unlock(&priv->mutex); | ||
1604 | |||
1605 | return tsf; | ||
1606 | } | ||
1607 | |||
1608 | static void ath9k_htc_set_tsf(struct ieee80211_hw *hw, u64 tsf) | ||
1609 | { | ||
1610 | struct ath9k_htc_priv *priv = hw->priv; | ||
1611 | |||
1612 | mutex_lock(&priv->mutex); | ||
1613 | ath9k_hw_settsf64(priv->ah, tsf); | ||
1614 | mutex_unlock(&priv->mutex); | ||
1615 | } | ||
1616 | |||
1617 | static void ath9k_htc_reset_tsf(struct ieee80211_hw *hw) | ||
1618 | { | ||
1619 | struct ath9k_htc_priv *priv = hw->priv; | ||
1620 | |||
1621 | ath9k_htc_ps_wakeup(priv); | ||
1622 | mutex_lock(&priv->mutex); | ||
1623 | ath9k_hw_reset_tsf(priv->ah); | ||
1624 | mutex_unlock(&priv->mutex); | ||
1625 | ath9k_htc_ps_restore(priv); | ||
1626 | } | ||
1627 | |||
1628 | static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, | ||
1629 | struct ieee80211_vif *vif, | ||
1630 | enum ieee80211_ampdu_mlme_action action, | ||
1631 | struct ieee80211_sta *sta, | ||
1632 | u16 tid, u16 *ssn) | ||
1633 | { | ||
1634 | struct ath9k_htc_priv *priv = hw->priv; | ||
1635 | struct ath9k_htc_aggr_work *work = &priv->aggr_work; | ||
1636 | struct ath9k_htc_sta *ista; | ||
1637 | |||
1638 | switch (action) { | ||
1639 | case IEEE80211_AMPDU_RX_START: | ||
1640 | break; | ||
1641 | case IEEE80211_AMPDU_RX_STOP: | ||
1642 | break; | ||
1643 | case IEEE80211_AMPDU_TX_START: | ||
1644 | case IEEE80211_AMPDU_TX_STOP: | ||
1645 | if (!(priv->op_flags & OP_TXAGGR)) | ||
1646 | return -ENOTSUPP; | ||
1647 | memcpy(work->sta_addr, sta->addr, ETH_ALEN); | ||
1648 | work->hw = hw; | ||
1649 | work->vif = vif; | ||
1650 | work->action = action; | ||
1651 | work->tid = tid; | ||
1652 | ieee80211_queue_delayed_work(hw, &priv->ath9k_aggr_work, 0); | ||
1653 | break; | ||
1654 | case IEEE80211_AMPDU_TX_OPERATIONAL: | ||
1655 | ista = (struct ath9k_htc_sta *) sta->drv_priv; | ||
1656 | ista->tid_state[tid] = AGGR_OPERATIONAL; | ||
1657 | break; | ||
1658 | default: | ||
1659 | ath_print(ath9k_hw_common(priv->ah), ATH_DBG_FATAL, | ||
1660 | "Unknown AMPDU action\n"); | ||
1661 | } | ||
1662 | |||
1663 | return 0; | ||
1664 | } | ||
1665 | |||
1666 | static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw) | ||
1667 | { | ||
1668 | struct ath9k_htc_priv *priv = hw->priv; | ||
1669 | |||
1670 | mutex_lock(&priv->mutex); | ||
1671 | spin_lock_bh(&priv->beacon_lock); | ||
1672 | priv->op_flags |= OP_SCANNING; | ||
1673 | spin_unlock_bh(&priv->beacon_lock); | ||
1674 | cancel_work_sync(&priv->ps_work); | ||
1675 | cancel_delayed_work_sync(&priv->ath9k_ani_work); | ||
1676 | mutex_unlock(&priv->mutex); | ||
1677 | } | ||
1678 | |||
1679 | static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw) | ||
1680 | { | ||
1681 | struct ath9k_htc_priv *priv = hw->priv; | ||
1682 | |||
1683 | ath9k_htc_ps_wakeup(priv); | ||
1684 | mutex_lock(&priv->mutex); | ||
1685 | spin_lock_bh(&priv->beacon_lock); | ||
1686 | priv->op_flags &= ~OP_SCANNING; | ||
1687 | spin_unlock_bh(&priv->beacon_lock); | ||
1688 | priv->op_flags |= OP_FULL_RESET; | ||
1689 | if (priv->op_flags & OP_ASSOCIATED) | ||
1690 | ath9k_htc_beacon_config(priv, NULL); | ||
1691 | ath_start_ani(priv); | ||
1692 | mutex_unlock(&priv->mutex); | ||
1693 | ath9k_htc_ps_restore(priv); | ||
1694 | } | ||
1695 | |||
1696 | static int ath9k_htc_set_rts_threshold(struct ieee80211_hw *hw, u32 value) | ||
1697 | { | ||
1698 | return 0; | ||
1699 | } | ||
1700 | |||
1701 | static void ath9k_htc_set_coverage_class(struct ieee80211_hw *hw, | ||
1702 | u8 coverage_class) | ||
1703 | { | ||
1704 | struct ath9k_htc_priv *priv = hw->priv; | ||
1705 | |||
1706 | mutex_lock(&priv->mutex); | ||
1707 | priv->ah->coverage_class = coverage_class; | ||
1708 | ath9k_hw_init_global_settings(priv->ah); | ||
1709 | mutex_unlock(&priv->mutex); | ||
1710 | } | ||
1711 | |||
1712 | struct ieee80211_ops ath9k_htc_ops = { | ||
1713 | .tx = ath9k_htc_tx, | ||
1714 | .start = ath9k_htc_start, | ||
1715 | .stop = ath9k_htc_stop, | ||
1716 | .add_interface = ath9k_htc_add_interface, | ||
1717 | .remove_interface = ath9k_htc_remove_interface, | ||
1718 | .config = ath9k_htc_config, | ||
1719 | .configure_filter = ath9k_htc_configure_filter, | ||
1720 | .sta_notify = ath9k_htc_sta_notify, | ||
1721 | .conf_tx = ath9k_htc_conf_tx, | ||
1722 | .bss_info_changed = ath9k_htc_bss_info_changed, | ||
1723 | .set_key = ath9k_htc_set_key, | ||
1724 | .get_tsf = ath9k_htc_get_tsf, | ||
1725 | .set_tsf = ath9k_htc_set_tsf, | ||
1726 | .reset_tsf = ath9k_htc_reset_tsf, | ||
1727 | .ampdu_action = ath9k_htc_ampdu_action, | ||
1728 | .sw_scan_start = ath9k_htc_sw_scan_start, | ||
1729 | .sw_scan_complete = ath9k_htc_sw_scan_complete, | ||
1730 | .set_rts_threshold = ath9k_htc_set_rts_threshold, | ||
1731 | .rfkill_poll = ath9k_htc_rfkill_poll_state, | ||
1732 | .set_coverage_class = ath9k_htc_set_coverage_class, | ||
1733 | }; | ||
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c new file mode 100644 index 000000000000..0a7cb30af5b4 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | |||
@@ -0,0 +1,704 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include "htc.h" | ||
18 | |||
19 | /******/ | ||
20 | /* TX */ | ||
21 | /******/ | ||
22 | |||
23 | int get_hw_qnum(u16 queue, int *hwq_map) | ||
24 | { | ||
25 | switch (queue) { | ||
26 | case 0: | ||
27 | return hwq_map[ATH9K_WME_AC_VO]; | ||
28 | case 1: | ||
29 | return hwq_map[ATH9K_WME_AC_VI]; | ||
30 | case 2: | ||
31 | return hwq_map[ATH9K_WME_AC_BE]; | ||
32 | case 3: | ||
33 | return hwq_map[ATH9K_WME_AC_BK]; | ||
34 | default: | ||
35 | return hwq_map[ATH9K_WME_AC_BE]; | ||
36 | } | ||
37 | } | ||
38 | |||
39 | int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum, | ||
40 | struct ath9k_tx_queue_info *qinfo) | ||
41 | { | ||
42 | struct ath_hw *ah = priv->ah; | ||
43 | int error = 0; | ||
44 | struct ath9k_tx_queue_info qi; | ||
45 | |||
46 | ath9k_hw_get_txq_props(ah, qnum, &qi); | ||
47 | |||
48 | qi.tqi_aifs = qinfo->tqi_aifs; | ||
49 | qi.tqi_cwmin = qinfo->tqi_cwmin / 2; /* XXX */ | ||
50 | qi.tqi_cwmax = qinfo->tqi_cwmax; | ||
51 | qi.tqi_burstTime = qinfo->tqi_burstTime; | ||
52 | qi.tqi_readyTime = qinfo->tqi_readyTime; | ||
53 | |||
54 | if (!ath9k_hw_set_txq_props(ah, qnum, &qi)) { | ||
55 | ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, | ||
56 | "Unable to update hardware queue %u!\n", qnum); | ||
57 | error = -EIO; | ||
58 | } else { | ||
59 | ath9k_hw_resettxqueue(ah, qnum); | ||
60 | } | ||
61 | |||
62 | return error; | ||
63 | } | ||
64 | |||
65 | int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb) | ||
66 | { | ||
67 | struct ieee80211_hdr *hdr; | ||
68 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
69 | struct ieee80211_sta *sta = tx_info->control.sta; | ||
70 | struct ath9k_htc_sta *ista; | ||
71 | struct ath9k_htc_vif *avp; | ||
72 | struct ath9k_htc_tx_ctl tx_ctl; | ||
73 | enum htc_endpoint_id epid; | ||
74 | u16 qnum, hw_qnum; | ||
75 | __le16 fc; | ||
76 | u8 *tx_fhdr; | ||
77 | u8 sta_idx; | ||
78 | |||
79 | hdr = (struct ieee80211_hdr *) skb->data; | ||
80 | fc = hdr->frame_control; | ||
81 | |||
82 | avp = (struct ath9k_htc_vif *) tx_info->control.vif->drv_priv; | ||
83 | if (sta) { | ||
84 | ista = (struct ath9k_htc_sta *) sta->drv_priv; | ||
85 | sta_idx = ista->index; | ||
86 | } else { | ||
87 | sta_idx = 0; | ||
88 | } | ||
89 | |||
90 | memset(&tx_ctl, 0, sizeof(struct ath9k_htc_tx_ctl)); | ||
91 | |||
92 | if (ieee80211_is_data(fc)) { | ||
93 | struct tx_frame_hdr tx_hdr; | ||
94 | u8 *qc; | ||
95 | |||
96 | memset(&tx_hdr, 0, sizeof(struct tx_frame_hdr)); | ||
97 | |||
98 | tx_hdr.node_idx = sta_idx; | ||
99 | tx_hdr.vif_idx = avp->index; | ||
100 | |||
101 | if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { | ||
102 | tx_ctl.type = ATH9K_HTC_AMPDU; | ||
103 | tx_hdr.data_type = ATH9K_HTC_AMPDU; | ||
104 | } else { | ||
105 | tx_ctl.type = ATH9K_HTC_NORMAL; | ||
106 | tx_hdr.data_type = ATH9K_HTC_NORMAL; | ||
107 | } | ||
108 | |||
109 | if (ieee80211_is_data(fc)) { | ||
110 | qc = ieee80211_get_qos_ctl(hdr); | ||
111 | tx_hdr.tidno = qc[0] & IEEE80211_QOS_CTL_TID_MASK; | ||
112 | } | ||
113 | |||
114 | /* Check for RTS protection */ | ||
115 | if (priv->hw->wiphy->rts_threshold != (u32) -1) | ||
116 | if (skb->len > priv->hw->wiphy->rts_threshold) | ||
117 | tx_hdr.flags |= ATH9K_HTC_TX_RTSCTS; | ||
118 | |||
119 | /* CTS-to-self */ | ||
120 | if (!(tx_hdr.flags & ATH9K_HTC_TX_RTSCTS) && | ||
121 | (priv->op_flags & OP_PROTECT_ENABLE)) | ||
122 | tx_hdr.flags |= ATH9K_HTC_TX_CTSONLY; | ||
123 | |||
124 | tx_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb); | ||
125 | if (tx_hdr.key_type == ATH9K_KEY_TYPE_CLEAR) | ||
126 | tx_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID; | ||
127 | else | ||
128 | tx_hdr.keyix = tx_info->control.hw_key->hw_key_idx; | ||
129 | |||
130 | tx_fhdr = skb_push(skb, sizeof(tx_hdr)); | ||
131 | memcpy(tx_fhdr, (u8 *) &tx_hdr, sizeof(tx_hdr)); | ||
132 | |||
133 | qnum = skb_get_queue_mapping(skb); | ||
134 | hw_qnum = get_hw_qnum(qnum, priv->hwq_map); | ||
135 | |||
136 | switch (hw_qnum) { | ||
137 | case 0: | ||
138 | epid = priv->data_be_ep; | ||
139 | break; | ||
140 | case 2: | ||
141 | epid = priv->data_vi_ep; | ||
142 | break; | ||
143 | case 3: | ||
144 | epid = priv->data_vo_ep; | ||
145 | break; | ||
146 | case 1: | ||
147 | default: | ||
148 | epid = priv->data_bk_ep; | ||
149 | break; | ||
150 | } | ||
151 | } else { | ||
152 | struct tx_mgmt_hdr mgmt_hdr; | ||
153 | |||
154 | memset(&mgmt_hdr, 0, sizeof(struct tx_mgmt_hdr)); | ||
155 | |||
156 | tx_ctl.type = ATH9K_HTC_NORMAL; | ||
157 | |||
158 | mgmt_hdr.node_idx = sta_idx; | ||
159 | mgmt_hdr.vif_idx = avp->index; | ||
160 | mgmt_hdr.tidno = 0; | ||
161 | mgmt_hdr.flags = 0; | ||
162 | |||
163 | mgmt_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb); | ||
164 | if (mgmt_hdr.key_type == ATH9K_KEY_TYPE_CLEAR) | ||
165 | mgmt_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID; | ||
166 | else | ||
167 | mgmt_hdr.keyix = tx_info->control.hw_key->hw_key_idx; | ||
168 | |||
169 | tx_fhdr = skb_push(skb, sizeof(mgmt_hdr)); | ||
170 | memcpy(tx_fhdr, (u8 *) &mgmt_hdr, sizeof(mgmt_hdr)); | ||
171 | epid = priv->mgmt_ep; | ||
172 | } | ||
173 | |||
174 | return htc_send(priv->htc, skb, epid, &tx_ctl); | ||
175 | } | ||
176 | |||
177 | void ath9k_tx_tasklet(unsigned long data) | ||
178 | { | ||
179 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; | ||
180 | struct ieee80211_sta *sta; | ||
181 | struct ieee80211_hdr *hdr; | ||
182 | struct ieee80211_tx_info *tx_info; | ||
183 | struct sk_buff *skb = NULL; | ||
184 | __le16 fc; | ||
185 | |||
186 | while ((skb = skb_dequeue(&priv->tx_queue)) != NULL) { | ||
187 | |||
188 | hdr = (struct ieee80211_hdr *) skb->data; | ||
189 | fc = hdr->frame_control; | ||
190 | tx_info = IEEE80211_SKB_CB(skb); | ||
191 | |||
192 | memset(&tx_info->status, 0, sizeof(tx_info->status)); | ||
193 | |||
194 | rcu_read_lock(); | ||
195 | |||
196 | sta = ieee80211_find_sta(priv->vif, hdr->addr1); | ||
197 | if (!sta) { | ||
198 | rcu_read_unlock(); | ||
199 | ieee80211_tx_status(priv->hw, skb); | ||
200 | continue; | ||
201 | } | ||
202 | |||
203 | /* Check if we need to start aggregation */ | ||
204 | |||
205 | if (sta && conf_is_ht(&priv->hw->conf) && | ||
206 | (priv->op_flags & OP_TXAGGR) | ||
207 | && !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { | ||
208 | if (ieee80211_is_data_qos(fc)) { | ||
209 | u8 *qc, tid; | ||
210 | struct ath9k_htc_sta *ista; | ||
211 | |||
212 | qc = ieee80211_get_qos_ctl(hdr); | ||
213 | tid = qc[0] & 0xf; | ||
214 | ista = (struct ath9k_htc_sta *)sta->drv_priv; | ||
215 | |||
216 | if ((tid < ATH9K_HTC_MAX_TID) && | ||
217 | ista->tid_state[tid] == AGGR_STOP) { | ||
218 | ieee80211_start_tx_ba_session(sta, tid); | ||
219 | ista->tid_state[tid] = AGGR_PROGRESS; | ||
220 | } | ||
221 | } | ||
222 | } | ||
223 | |||
224 | rcu_read_unlock(); | ||
225 | |||
226 | /* Send status to mac80211 */ | ||
227 | ieee80211_tx_status(priv->hw, skb); | ||
228 | } | ||
229 | |||
230 | /* Wake TX queues if needed */ | ||
231 | spin_lock_bh(&priv->tx_lock); | ||
232 | if (priv->tx_queues_stop) { | ||
233 | priv->tx_queues_stop = false; | ||
234 | spin_unlock_bh(&priv->tx_lock); | ||
235 | ath_print(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, | ||
236 | "Waking up TX queues\n"); | ||
237 | ieee80211_wake_queues(priv->hw); | ||
238 | return; | ||
239 | } | ||
240 | spin_unlock_bh(&priv->tx_lock); | ||
241 | } | ||
242 | |||
243 | void ath9k_htc_txep(void *drv_priv, struct sk_buff *skb, | ||
244 | enum htc_endpoint_id ep_id, bool txok) | ||
245 | { | ||
246 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) drv_priv; | ||
247 | struct ieee80211_tx_info *tx_info; | ||
248 | |||
249 | if (!skb) | ||
250 | return; | ||
251 | |||
252 | if (ep_id == priv->mgmt_ep) | ||
253 | skb_pull(skb, sizeof(struct tx_mgmt_hdr)); | ||
254 | else | ||
255 | /* TODO: Check for cab/uapsd/data */ | ||
256 | skb_pull(skb, sizeof(struct tx_frame_hdr)); | ||
257 | |||
258 | tx_info = IEEE80211_SKB_CB(skb); | ||
259 | |||
260 | if (txok) | ||
261 | tx_info->flags |= IEEE80211_TX_STAT_ACK; | ||
262 | |||
263 | skb_queue_tail(&priv->tx_queue, skb); | ||
264 | tasklet_schedule(&priv->tx_tasklet); | ||
265 | } | ||
266 | |||
267 | int ath9k_tx_init(struct ath9k_htc_priv *priv) | ||
268 | { | ||
269 | skb_queue_head_init(&priv->tx_queue); | ||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | void ath9k_tx_cleanup(struct ath9k_htc_priv *priv) | ||
274 | { | ||
275 | |||
276 | } | ||
277 | |||
278 | bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, | ||
279 | enum ath9k_tx_queue_subtype subtype) | ||
280 | { | ||
281 | struct ath_hw *ah = priv->ah; | ||
282 | struct ath_common *common = ath9k_hw_common(ah); | ||
283 | struct ath9k_tx_queue_info qi; | ||
284 | int qnum; | ||
285 | |||
286 | memset(&qi, 0, sizeof(qi)); | ||
287 | |||
288 | qi.tqi_subtype = subtype; | ||
289 | qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT; | ||
290 | qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT; | ||
291 | qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT; | ||
292 | qi.tqi_physCompBuf = 0; | ||
293 | qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE | TXQ_FLAG_TXDESCINT_ENABLE; | ||
294 | |||
295 | qnum = ath9k_hw_setuptxqueue(priv->ah, ATH9K_TX_QUEUE_DATA, &qi); | ||
296 | if (qnum == -1) | ||
297 | return false; | ||
298 | |||
299 | if (qnum >= ARRAY_SIZE(priv->hwq_map)) { | ||
300 | ath_print(common, ATH_DBG_FATAL, | ||
301 | "qnum %u out of range, max %u!\n", | ||
302 | qnum, (unsigned int)ARRAY_SIZE(priv->hwq_map)); | ||
303 | ath9k_hw_releasetxqueue(ah, qnum); | ||
304 | return false; | ||
305 | } | ||
306 | |||
307 | priv->hwq_map[subtype] = qnum; | ||
308 | return true; | ||
309 | } | ||
310 | |||
311 | /******/ | ||
312 | /* RX */ | ||
313 | /******/ | ||
314 | |||
315 | /* | ||
316 | * Calculate the RX filter to be set in the HW. | ||
317 | */ | ||
318 | u32 ath9k_htc_calcrxfilter(struct ath9k_htc_priv *priv) | ||
319 | { | ||
320 | #define RX_FILTER_PRESERVE (ATH9K_RX_FILTER_PHYERR | ATH9K_RX_FILTER_PHYRADAR) | ||
321 | |||
322 | struct ath_hw *ah = priv->ah; | ||
323 | u32 rfilt; | ||
324 | |||
325 | rfilt = (ath9k_hw_getrxfilter(ah) & RX_FILTER_PRESERVE) | ||
326 | | ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST | ||
327 | | ATH9K_RX_FILTER_MCAST; | ||
328 | |||
329 | /* If not a STA, enable processing of Probe Requests */ | ||
330 | if (ah->opmode != NL80211_IFTYPE_STATION) | ||
331 | rfilt |= ATH9K_RX_FILTER_PROBEREQ; | ||
332 | |||
333 | /* | ||
334 | * Set promiscuous mode when FIF_PROMISC_IN_BSS is enabled for station | ||
335 | * mode interface or when in monitor mode. AP mode does not need this | ||
336 | * since it receives all in-BSS frames anyway. | ||
337 | */ | ||
338 | if (((ah->opmode != NL80211_IFTYPE_AP) && | ||
339 | (priv->rxfilter & FIF_PROMISC_IN_BSS)) || | ||
340 | (ah->opmode == NL80211_IFTYPE_MONITOR)) | ||
341 | rfilt |= ATH9K_RX_FILTER_PROM; | ||
342 | |||
343 | if (priv->rxfilter & FIF_CONTROL) | ||
344 | rfilt |= ATH9K_RX_FILTER_CONTROL; | ||
345 | |||
346 | if ((ah->opmode == NL80211_IFTYPE_STATION) && | ||
347 | !(priv->rxfilter & FIF_BCN_PRBRESP_PROMISC)) | ||
348 | rfilt |= ATH9K_RX_FILTER_MYBEACON; | ||
349 | else | ||
350 | rfilt |= ATH9K_RX_FILTER_BEACON; | ||
351 | |||
352 | if (conf_is_ht(&priv->hw->conf)) | ||
353 | rfilt |= ATH9K_RX_FILTER_COMP_BAR; | ||
354 | |||
355 | return rfilt; | ||
356 | |||
357 | #undef RX_FILTER_PRESERVE | ||
358 | } | ||
359 | |||
360 | /* | ||
361 | * Recv initialization for opmode change. | ||
362 | */ | ||
363 | static void ath9k_htc_opmode_init(struct ath9k_htc_priv *priv) | ||
364 | { | ||
365 | struct ath_hw *ah = priv->ah; | ||
366 | struct ath_common *common = ath9k_hw_common(ah); | ||
367 | |||
368 | u32 rfilt, mfilt[2]; | ||
369 | |||
370 | /* configure rx filter */ | ||
371 | rfilt = ath9k_htc_calcrxfilter(priv); | ||
372 | ath9k_hw_setrxfilter(ah, rfilt); | ||
373 | |||
374 | /* configure bssid mask */ | ||
375 | if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) | ||
376 | ath_hw_setbssidmask(common); | ||
377 | |||
378 | /* configure operational mode */ | ||
379 | ath9k_hw_setopmode(ah); | ||
380 | |||
381 | /* Handle any link-level address change. */ | ||
382 | ath9k_hw_setmac(ah, common->macaddr); | ||
383 | |||
384 | /* calculate and install multicast filter */ | ||
385 | mfilt[0] = mfilt[1] = ~0; | ||
386 | ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]); | ||
387 | } | ||
388 | |||
389 | void ath9k_host_rx_init(struct ath9k_htc_priv *priv) | ||
390 | { | ||
391 | ath9k_hw_rxena(priv->ah); | ||
392 | ath9k_htc_opmode_init(priv); | ||
393 | ath9k_hw_startpcureceive(priv->ah); | ||
394 | priv->rx.last_rssi = ATH_RSSI_DUMMY_MARKER; | ||
395 | } | ||
396 | |||
397 | static void ath9k_process_rate(struct ieee80211_hw *hw, | ||
398 | struct ieee80211_rx_status *rxs, | ||
399 | u8 rx_rate, u8 rs_flags) | ||
400 | { | ||
401 | struct ieee80211_supported_band *sband; | ||
402 | enum ieee80211_band band; | ||
403 | unsigned int i = 0; | ||
404 | |||
405 | if (rx_rate & 0x80) { | ||
406 | /* HT rate */ | ||
407 | rxs->flag |= RX_FLAG_HT; | ||
408 | if (rs_flags & ATH9K_RX_2040) | ||
409 | rxs->flag |= RX_FLAG_40MHZ; | ||
410 | if (rs_flags & ATH9K_RX_GI) | ||
411 | rxs->flag |= RX_FLAG_SHORT_GI; | ||
412 | rxs->rate_idx = rx_rate & 0x7f; | ||
413 | return; | ||
414 | } | ||
415 | |||
416 | band = hw->conf.channel->band; | ||
417 | sband = hw->wiphy->bands[band]; | ||
418 | |||
419 | for (i = 0; i < sband->n_bitrates; i++) { | ||
420 | if (sband->bitrates[i].hw_value == rx_rate) { | ||
421 | rxs->rate_idx = i; | ||
422 | return; | ||
423 | } | ||
424 | if (sband->bitrates[i].hw_value_short == rx_rate) { | ||
425 | rxs->rate_idx = i; | ||
426 | rxs->flag |= RX_FLAG_SHORTPRE; | ||
427 | return; | ||
428 | } | ||
429 | } | ||
430 | |||
431 | } | ||
432 | |||
433 | static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, | ||
434 | struct ath9k_htc_rxbuf *rxbuf, | ||
435 | struct ieee80211_rx_status *rx_status) | ||
436 | |||
437 | { | ||
438 | struct ieee80211_hdr *hdr; | ||
439 | struct ieee80211_hw *hw = priv->hw; | ||
440 | struct sk_buff *skb = rxbuf->skb; | ||
441 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
442 | int hdrlen, padpos, padsize; | ||
443 | int last_rssi = ATH_RSSI_DUMMY_MARKER; | ||
444 | __le16 fc; | ||
445 | |||
446 | hdr = (struct ieee80211_hdr *)skb->data; | ||
447 | fc = hdr->frame_control; | ||
448 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | ||
449 | |||
450 | padpos = ath9k_cmn_padpos(fc); | ||
451 | |||
452 | padsize = padpos & 3; | ||
453 | if (padsize && skb->len >= padpos+padsize+FCS_LEN) { | ||
454 | memmove(skb->data + padsize, skb->data, padpos); | ||
455 | skb_pull(skb, padsize); | ||
456 | } | ||
457 | |||
458 | memset(rx_status, 0, sizeof(struct ieee80211_rx_status)); | ||
459 | |||
460 | if (rxbuf->rxstatus.rs_status != 0) { | ||
461 | if (rxbuf->rxstatus.rs_status & ATH9K_RXERR_CRC) | ||
462 | rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; | ||
463 | if (rxbuf->rxstatus.rs_status & ATH9K_RXERR_PHY) | ||
464 | goto rx_next; | ||
465 | |||
466 | if (rxbuf->rxstatus.rs_status & ATH9K_RXERR_DECRYPT) { | ||
467 | /* FIXME */ | ||
468 | } else if (rxbuf->rxstatus.rs_status & ATH9K_RXERR_MIC) { | ||
469 | if (ieee80211_is_ctl(fc)) | ||
470 | /* | ||
471 | * Sometimes, we get invalid | ||
472 | * MIC failures on valid control frames. | ||
473 | * Remove these mic errors. | ||
474 | */ | ||
475 | rxbuf->rxstatus.rs_status &= ~ATH9K_RXERR_MIC; | ||
476 | else | ||
477 | rx_status->flag |= RX_FLAG_MMIC_ERROR; | ||
478 | } | ||
479 | |||
480 | /* | ||
481 | * Reject error frames with the exception of | ||
482 | * decryption and MIC failures. For monitor mode, | ||
483 | * we also ignore the CRC error. | ||
484 | */ | ||
485 | if (priv->ah->opmode == NL80211_IFTYPE_MONITOR) { | ||
486 | if (rxbuf->rxstatus.rs_status & | ||
487 | ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC | | ||
488 | ATH9K_RXERR_CRC)) | ||
489 | goto rx_next; | ||
490 | } else { | ||
491 | if (rxbuf->rxstatus.rs_status & | ||
492 | ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) { | ||
493 | goto rx_next; | ||
494 | } | ||
495 | } | ||
496 | } | ||
497 | |||
498 | if (!(rxbuf->rxstatus.rs_status & ATH9K_RXERR_DECRYPT)) { | ||
499 | u8 keyix; | ||
500 | keyix = rxbuf->rxstatus.rs_keyix; | ||
501 | if (keyix != ATH9K_RXKEYIX_INVALID) { | ||
502 | rx_status->flag |= RX_FLAG_DECRYPTED; | ||
503 | } else if (ieee80211_has_protected(fc) && | ||
504 | skb->len >= hdrlen + 4) { | ||
505 | keyix = skb->data[hdrlen + 3] >> 6; | ||
506 | if (test_bit(keyix, common->keymap)) | ||
507 | rx_status->flag |= RX_FLAG_DECRYPTED; | ||
508 | } | ||
509 | } | ||
510 | |||
511 | ath9k_process_rate(hw, rx_status, rxbuf->rxstatus.rs_rate, | ||
512 | rxbuf->rxstatus.rs_flags); | ||
513 | |||
514 | if (priv->op_flags & OP_ASSOCIATED) { | ||
515 | if (rxbuf->rxstatus.rs_rssi != ATH9K_RSSI_BAD && | ||
516 | !rxbuf->rxstatus.rs_moreaggr) | ||
517 | ATH_RSSI_LPF(priv->rx.last_rssi, | ||
518 | rxbuf->rxstatus.rs_rssi); | ||
519 | |||
520 | last_rssi = priv->rx.last_rssi; | ||
521 | |||
522 | if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) | ||
523 | rxbuf->rxstatus.rs_rssi = ATH_EP_RND(last_rssi, | ||
524 | ATH_RSSI_EP_MULTIPLIER); | ||
525 | |||
526 | if (rxbuf->rxstatus.rs_rssi < 0) | ||
527 | rxbuf->rxstatus.rs_rssi = 0; | ||
528 | |||
529 | if (ieee80211_is_beacon(fc)) | ||
530 | priv->ah->stats.avgbrssi = rxbuf->rxstatus.rs_rssi; | ||
531 | } | ||
532 | |||
533 | rx_status->mactime = rxbuf->rxstatus.rs_tstamp; | ||
534 | rx_status->band = hw->conf.channel->band; | ||
535 | rx_status->freq = hw->conf.channel->center_freq; | ||
536 | rx_status->signal = rxbuf->rxstatus.rs_rssi + ATH_DEFAULT_NOISE_FLOOR; | ||
537 | rx_status->antenna = rxbuf->rxstatus.rs_antenna; | ||
538 | rx_status->flag |= RX_FLAG_TSFT; | ||
539 | |||
540 | return true; | ||
541 | |||
542 | rx_next: | ||
543 | return false; | ||
544 | } | ||
545 | |||
546 | /* | ||
547 | * FIXME: Handle FLUSH later on. | ||
548 | */ | ||
549 | void ath9k_rx_tasklet(unsigned long data) | ||
550 | { | ||
551 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; | ||
552 | struct ath9k_htc_rxbuf *rxbuf = NULL, *tmp_buf = NULL; | ||
553 | struct ieee80211_rx_status rx_status; | ||
554 | struct sk_buff *skb; | ||
555 | unsigned long flags; | ||
556 | struct ieee80211_hdr *hdr; | ||
557 | |||
558 | do { | ||
559 | spin_lock_irqsave(&priv->rx.rxbuflock, flags); | ||
560 | list_for_each_entry(tmp_buf, &priv->rx.rxbuf, list) { | ||
561 | if (tmp_buf->in_process) { | ||
562 | rxbuf = tmp_buf; | ||
563 | break; | ||
564 | } | ||
565 | } | ||
566 | |||
567 | if (rxbuf == NULL) { | ||
568 | spin_unlock_irqrestore(&priv->rx.rxbuflock, flags); | ||
569 | break; | ||
570 | } | ||
571 | |||
572 | if (!rxbuf->skb) | ||
573 | goto requeue; | ||
574 | |||
575 | if (!ath9k_rx_prepare(priv, rxbuf, &rx_status)) { | ||
576 | dev_kfree_skb_any(rxbuf->skb); | ||
577 | goto requeue; | ||
578 | } | ||
579 | |||
580 | memcpy(IEEE80211_SKB_RXCB(rxbuf->skb), &rx_status, | ||
581 | sizeof(struct ieee80211_rx_status)); | ||
582 | skb = rxbuf->skb; | ||
583 | hdr = (struct ieee80211_hdr *) skb->data; | ||
584 | |||
585 | if (ieee80211_is_beacon(hdr->frame_control) && priv->ps_enabled) | ||
586 | ieee80211_queue_work(priv->hw, &priv->ps_work); | ||
587 | |||
588 | spin_unlock_irqrestore(&priv->rx.rxbuflock, flags); | ||
589 | |||
590 | ieee80211_rx(priv->hw, skb); | ||
591 | |||
592 | spin_lock_irqsave(&priv->rx.rxbuflock, flags); | ||
593 | requeue: | ||
594 | rxbuf->in_process = false; | ||
595 | rxbuf->skb = NULL; | ||
596 | list_move_tail(&rxbuf->list, &priv->rx.rxbuf); | ||
597 | rxbuf = NULL; | ||
598 | spin_unlock_irqrestore(&priv->rx.rxbuflock, flags); | ||
599 | } while (1); | ||
600 | |||
601 | } | ||
602 | |||
603 | void ath9k_htc_rxep(void *drv_priv, struct sk_buff *skb, | ||
604 | enum htc_endpoint_id ep_id) | ||
605 | { | ||
606 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)drv_priv; | ||
607 | struct ath_hw *ah = priv->ah; | ||
608 | struct ath_common *common = ath9k_hw_common(ah); | ||
609 | struct ath9k_htc_rxbuf *rxbuf = NULL, *tmp_buf = NULL; | ||
610 | struct ath_htc_rx_status *rxstatus; | ||
611 | u32 len = 0; | ||
612 | |||
613 | spin_lock(&priv->rx.rxbuflock); | ||
614 | list_for_each_entry(tmp_buf, &priv->rx.rxbuf, list) { | ||
615 | if (!tmp_buf->in_process) { | ||
616 | rxbuf = tmp_buf; | ||
617 | break; | ||
618 | } | ||
619 | } | ||
620 | spin_unlock(&priv->rx.rxbuflock); | ||
621 | |||
622 | if (rxbuf == NULL) { | ||
623 | ath_print(common, ATH_DBG_ANY, | ||
624 | "No free RX buffer\n"); | ||
625 | goto err; | ||
626 | } | ||
627 | |||
628 | len = skb->len; | ||
629 | if (len <= HTC_RX_FRAME_HEADER_SIZE) { | ||
630 | ath_print(common, ATH_DBG_FATAL, | ||
631 | "Corrupted RX frame, dropping\n"); | ||
632 | goto err; | ||
633 | } | ||
634 | |||
635 | rxstatus = (struct ath_htc_rx_status *)skb->data; | ||
636 | |||
637 | rxstatus->rs_tstamp = be64_to_cpu(rxstatus->rs_tstamp); | ||
638 | rxstatus->rs_datalen = be16_to_cpu(rxstatus->rs_datalen); | ||
639 | rxstatus->evm0 = be32_to_cpu(rxstatus->evm0); | ||
640 | rxstatus->evm1 = be32_to_cpu(rxstatus->evm1); | ||
641 | rxstatus->evm2 = be32_to_cpu(rxstatus->evm2); | ||
642 | |||
643 | if (rxstatus->rs_datalen - (len - HTC_RX_FRAME_HEADER_SIZE) != 0) { | ||
644 | ath_print(common, ATH_DBG_FATAL, | ||
645 | "Corrupted RX data len, dropping " | ||
646 | "(epid: %d, dlen: %d, skblen: %d)\n", | ||
647 | ep_id, rxstatus->rs_datalen, len); | ||
648 | goto err; | ||
649 | } | ||
650 | |||
651 | spin_lock(&priv->rx.rxbuflock); | ||
652 | memcpy(&rxbuf->rxstatus, rxstatus, HTC_RX_FRAME_HEADER_SIZE); | ||
653 | skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE); | ||
654 | rxbuf->skb = skb; | ||
655 | rxbuf->in_process = true; | ||
656 | spin_unlock(&priv->rx.rxbuflock); | ||
657 | |||
658 | tasklet_schedule(&priv->rx_tasklet); | ||
659 | return; | ||
660 | err: | ||
661 | dev_kfree_skb_any(skb); | ||
662 | return; | ||
663 | } | ||
664 | |||
665 | /* FIXME: Locking for cleanup/init */ | ||
666 | |||
667 | void ath9k_rx_cleanup(struct ath9k_htc_priv *priv) | ||
668 | { | ||
669 | struct ath9k_htc_rxbuf *rxbuf, *tbuf; | ||
670 | |||
671 | list_for_each_entry_safe(rxbuf, tbuf, &priv->rx.rxbuf, list) { | ||
672 | list_del(&rxbuf->list); | ||
673 | if (rxbuf->skb) | ||
674 | dev_kfree_skb_any(rxbuf->skb); | ||
675 | kfree(rxbuf); | ||
676 | } | ||
677 | } | ||
678 | |||
679 | int ath9k_rx_init(struct ath9k_htc_priv *priv) | ||
680 | { | ||
681 | struct ath_hw *ah = priv->ah; | ||
682 | struct ath_common *common = ath9k_hw_common(ah); | ||
683 | struct ath9k_htc_rxbuf *rxbuf; | ||
684 | int i = 0; | ||
685 | |||
686 | INIT_LIST_HEAD(&priv->rx.rxbuf); | ||
687 | spin_lock_init(&priv->rx.rxbuflock); | ||
688 | |||
689 | for (i = 0; i < ATH9K_HTC_RXBUF; i++) { | ||
690 | rxbuf = kzalloc(sizeof(struct ath9k_htc_rxbuf), GFP_KERNEL); | ||
691 | if (rxbuf == NULL) { | ||
692 | ath_print(common, ATH_DBG_FATAL, | ||
693 | "Unable to allocate RX buffers\n"); | ||
694 | goto err; | ||
695 | } | ||
696 | list_add_tail(&rxbuf->list, &priv->rx.rxbuf); | ||
697 | } | ||
698 | |||
699 | return 0; | ||
700 | |||
701 | err: | ||
702 | ath9k_rx_cleanup(priv); | ||
703 | return -ENOMEM; | ||
704 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c new file mode 100644 index 000000000000..30f608bfc567 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c | |||
@@ -0,0 +1,463 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include "htc.h" | ||
18 | |||
19 | static int htc_issue_send(struct htc_target *target, struct sk_buff* skb, | ||
20 | u16 len, u8 flags, u8 epid, | ||
21 | struct ath9k_htc_tx_ctl *tx_ctl) | ||
22 | { | ||
23 | struct htc_frame_hdr *hdr; | ||
24 | struct htc_endpoint *endpoint = &target->endpoint[epid]; | ||
25 | int status; | ||
26 | |||
27 | hdr = (struct htc_frame_hdr *) | ||
28 | skb_push(skb, sizeof(struct htc_frame_hdr)); | ||
29 | hdr->endpoint_id = epid; | ||
30 | hdr->flags = flags; | ||
31 | hdr->payload_len = cpu_to_be16(len); | ||
32 | |||
33 | status = target->hif->send(target->hif_dev, endpoint->ul_pipeid, skb, | ||
34 | tx_ctl); | ||
35 | return status; | ||
36 | } | ||
37 | |||
38 | static struct htc_endpoint *get_next_avail_ep(struct htc_endpoint *endpoint) | ||
39 | { | ||
40 | enum htc_endpoint_id avail_epid; | ||
41 | |||
42 | for (avail_epid = ENDPOINT_MAX; avail_epid > ENDPOINT0; avail_epid--) | ||
43 | if (endpoint[avail_epid].service_id == 0) | ||
44 | return &endpoint[avail_epid]; | ||
45 | return NULL; | ||
46 | } | ||
47 | |||
48 | static u8 service_to_ulpipe(u16 service_id) | ||
49 | { | ||
50 | switch (service_id) { | ||
51 | case WMI_CONTROL_SVC: | ||
52 | return 4; | ||
53 | case WMI_BEACON_SVC: | ||
54 | case WMI_CAB_SVC: | ||
55 | case WMI_UAPSD_SVC: | ||
56 | case WMI_MGMT_SVC: | ||
57 | case WMI_DATA_VO_SVC: | ||
58 | case WMI_DATA_VI_SVC: | ||
59 | case WMI_DATA_BE_SVC: | ||
60 | case WMI_DATA_BK_SVC: | ||
61 | return 1; | ||
62 | default: | ||
63 | return 0; | ||
64 | } | ||
65 | } | ||
66 | |||
67 | static u8 service_to_dlpipe(u16 service_id) | ||
68 | { | ||
69 | switch (service_id) { | ||
70 | case WMI_CONTROL_SVC: | ||
71 | return 3; | ||
72 | case WMI_BEACON_SVC: | ||
73 | case WMI_CAB_SVC: | ||
74 | case WMI_UAPSD_SVC: | ||
75 | case WMI_MGMT_SVC: | ||
76 | case WMI_DATA_VO_SVC: | ||
77 | case WMI_DATA_VI_SVC: | ||
78 | case WMI_DATA_BE_SVC: | ||
79 | case WMI_DATA_BK_SVC: | ||
80 | return 2; | ||
81 | default: | ||
82 | return 0; | ||
83 | } | ||
84 | } | ||
85 | |||
86 | static void htc_process_target_rdy(struct htc_target *target, | ||
87 | void *buf) | ||
88 | { | ||
89 | struct htc_endpoint *endpoint; | ||
90 | struct htc_ready_msg *htc_ready_msg = (struct htc_ready_msg *) buf; | ||
91 | |||
92 | target->credits = be16_to_cpu(htc_ready_msg->credits); | ||
93 | target->credit_size = be16_to_cpu(htc_ready_msg->credit_size); | ||
94 | |||
95 | endpoint = &target->endpoint[ENDPOINT0]; | ||
96 | endpoint->service_id = HTC_CTRL_RSVD_SVC; | ||
97 | endpoint->max_msglen = HTC_MAX_CONTROL_MESSAGE_LENGTH; | ||
98 | complete(&target->target_wait); | ||
99 | } | ||
100 | |||
101 | static void htc_process_conn_rsp(struct htc_target *target, | ||
102 | struct htc_frame_hdr *htc_hdr) | ||
103 | { | ||
104 | struct htc_conn_svc_rspmsg *svc_rspmsg; | ||
105 | struct htc_endpoint *endpoint, *tmp_endpoint = NULL; | ||
106 | u16 service_id; | ||
107 | u16 max_msglen; | ||
108 | enum htc_endpoint_id epid, tepid; | ||
109 | |||
110 | svc_rspmsg = (struct htc_conn_svc_rspmsg *) | ||
111 | ((void *) htc_hdr + sizeof(struct htc_frame_hdr)); | ||
112 | |||
113 | if (svc_rspmsg->status == HTC_SERVICE_SUCCESS) { | ||
114 | epid = svc_rspmsg->endpoint_id; | ||
115 | service_id = be16_to_cpu(svc_rspmsg->service_id); | ||
116 | max_msglen = be16_to_cpu(svc_rspmsg->max_msg_len); | ||
117 | endpoint = &target->endpoint[epid]; | ||
118 | |||
119 | for (tepid = ENDPOINT_MAX; tepid > ENDPOINT0; tepid--) { | ||
120 | tmp_endpoint = &target->endpoint[tepid]; | ||
121 | if (tmp_endpoint->service_id == service_id) { | ||
122 | tmp_endpoint->service_id = 0; | ||
123 | break; | ||
124 | } | ||
125 | } | ||
126 | |||
127 | if (!tmp_endpoint) | ||
128 | return; | ||
129 | |||
130 | endpoint->service_id = service_id; | ||
131 | endpoint->max_txqdepth = tmp_endpoint->max_txqdepth; | ||
132 | endpoint->ep_callbacks = tmp_endpoint->ep_callbacks; | ||
133 | endpoint->ul_pipeid = tmp_endpoint->ul_pipeid; | ||
134 | endpoint->dl_pipeid = tmp_endpoint->dl_pipeid; | ||
135 | endpoint->max_msglen = max_msglen; | ||
136 | target->conn_rsp_epid = epid; | ||
137 | complete(&target->cmd_wait); | ||
138 | } else { | ||
139 | target->conn_rsp_epid = ENDPOINT_UNUSED; | ||
140 | } | ||
141 | } | ||
142 | |||
143 | static int htc_config_pipe_credits(struct htc_target *target) | ||
144 | { | ||
145 | struct sk_buff *skb; | ||
146 | struct htc_config_pipe_msg *cp_msg; | ||
147 | int ret, time_left; | ||
148 | |||
149 | skb = dev_alloc_skb(50 + sizeof(struct htc_frame_hdr)); | ||
150 | if (!skb) { | ||
151 | dev_err(target->dev, "failed to allocate send buffer\n"); | ||
152 | return -ENOMEM; | ||
153 | } | ||
154 | skb_reserve(skb, sizeof(struct htc_frame_hdr)); | ||
155 | |||
156 | cp_msg = (struct htc_config_pipe_msg *) | ||
157 | skb_put(skb, sizeof(struct htc_config_pipe_msg)); | ||
158 | |||
159 | cp_msg->message_id = cpu_to_be16(HTC_MSG_CONFIG_PIPE_ID); | ||
160 | cp_msg->pipe_id = USB_WLAN_TX_PIPE; | ||
161 | cp_msg->credits = 28; | ||
162 | |||
163 | target->htc_flags |= HTC_OP_CONFIG_PIPE_CREDITS; | ||
164 | |||
165 | ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL); | ||
166 | if (ret) | ||
167 | goto err; | ||
168 | |||
169 | time_left = wait_for_completion_timeout(&target->cmd_wait, HZ); | ||
170 | if (!time_left) { | ||
171 | dev_err(target->dev, "HTC credit config timeout\n"); | ||
172 | return -ETIMEDOUT; | ||
173 | } | ||
174 | |||
175 | return 0; | ||
176 | err: | ||
177 | dev_kfree_skb(skb); | ||
178 | return -EINVAL; | ||
179 | } | ||
180 | |||
181 | static int htc_setup_complete(struct htc_target *target) | ||
182 | { | ||
183 | struct sk_buff *skb; | ||
184 | struct htc_comp_msg *comp_msg; | ||
185 | int ret = 0, time_left; | ||
186 | |||
187 | skb = dev_alloc_skb(50 + sizeof(struct htc_frame_hdr)); | ||
188 | if (!skb) { | ||
189 | dev_err(target->dev, "failed to allocate send buffer\n"); | ||
190 | return -ENOMEM; | ||
191 | } | ||
192 | skb_reserve(skb, sizeof(struct htc_frame_hdr)); | ||
193 | |||
194 | comp_msg = (struct htc_comp_msg *) | ||
195 | skb_put(skb, sizeof(struct htc_comp_msg)); | ||
196 | comp_msg->msg_id = cpu_to_be16(HTC_MSG_SETUP_COMPLETE_ID); | ||
197 | |||
198 | target->htc_flags |= HTC_OP_START_WAIT; | ||
199 | |||
200 | ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL); | ||
201 | if (ret) | ||
202 | goto err; | ||
203 | |||
204 | time_left = wait_for_completion_timeout(&target->cmd_wait, HZ); | ||
205 | if (!time_left) { | ||
206 | dev_err(target->dev, "HTC start timeout\n"); | ||
207 | return -ETIMEDOUT; | ||
208 | } | ||
209 | |||
210 | return 0; | ||
211 | |||
212 | err: | ||
213 | dev_kfree_skb(skb); | ||
214 | return -EINVAL; | ||
215 | } | ||
216 | |||
217 | /* HTC APIs */ | ||
218 | |||
219 | int htc_init(struct htc_target *target) | ||
220 | { | ||
221 | int ret; | ||
222 | |||
223 | ret = htc_config_pipe_credits(target); | ||
224 | if (ret) | ||
225 | return ret; | ||
226 | |||
227 | return htc_setup_complete(target); | ||
228 | } | ||
229 | |||
230 | int htc_connect_service(struct htc_target *target, | ||
231 | struct htc_service_connreq *service_connreq, | ||
232 | enum htc_endpoint_id *conn_rsp_epid) | ||
233 | { | ||
234 | struct sk_buff *skb; | ||
235 | struct htc_endpoint *endpoint; | ||
236 | struct htc_conn_svc_msg *conn_msg; | ||
237 | int ret, time_left; | ||
238 | |||
239 | /* Find an available endpoint */ | ||
240 | endpoint = get_next_avail_ep(target->endpoint); | ||
241 | if (!endpoint) { | ||
242 | dev_err(target->dev, "Endpoint is not available for" | ||
243 | "service %d\n", service_connreq->service_id); | ||
244 | return -EINVAL; | ||
245 | } | ||
246 | |||
247 | endpoint->service_id = service_connreq->service_id; | ||
248 | endpoint->max_txqdepth = service_connreq->max_send_qdepth; | ||
249 | endpoint->ul_pipeid = service_to_ulpipe(service_connreq->service_id); | ||
250 | endpoint->dl_pipeid = service_to_dlpipe(service_connreq->service_id); | ||
251 | endpoint->ep_callbacks = service_connreq->ep_callbacks; | ||
252 | |||
253 | skb = dev_alloc_skb(sizeof(struct htc_conn_svc_msg) + | ||
254 | sizeof(struct htc_frame_hdr)); | ||
255 | if (!skb) { | ||
256 | dev_err(target->dev, "Failed to allocate buf to send" | ||
257 | "service connect req\n"); | ||
258 | return -ENOMEM; | ||
259 | } | ||
260 | |||
261 | skb_reserve(skb, sizeof(struct htc_frame_hdr)); | ||
262 | |||
263 | conn_msg = (struct htc_conn_svc_msg *) | ||
264 | skb_put(skb, sizeof(struct htc_conn_svc_msg)); | ||
265 | conn_msg->service_id = cpu_to_be16(service_connreq->service_id); | ||
266 | conn_msg->msg_id = cpu_to_be16(HTC_MSG_CONNECT_SERVICE_ID); | ||
267 | conn_msg->con_flags = cpu_to_be16(service_connreq->con_flags); | ||
268 | conn_msg->dl_pipeid = endpoint->dl_pipeid; | ||
269 | conn_msg->ul_pipeid = endpoint->ul_pipeid; | ||
270 | |||
271 | ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL); | ||
272 | if (ret) | ||
273 | goto err; | ||
274 | |||
275 | time_left = wait_for_completion_timeout(&target->cmd_wait, HZ); | ||
276 | if (!time_left) { | ||
277 | dev_err(target->dev, "Service connection timeout for: %d\n", | ||
278 | service_connreq->service_id); | ||
279 | return -ETIMEDOUT; | ||
280 | } | ||
281 | |||
282 | *conn_rsp_epid = target->conn_rsp_epid; | ||
283 | return 0; | ||
284 | err: | ||
285 | dev_kfree_skb(skb); | ||
286 | return ret; | ||
287 | } | ||
288 | |||
289 | int htc_send(struct htc_target *target, struct sk_buff *skb, | ||
290 | enum htc_endpoint_id epid, struct ath9k_htc_tx_ctl *tx_ctl) | ||
291 | { | ||
292 | return htc_issue_send(target, skb, skb->len, 0, epid, tx_ctl); | ||
293 | } | ||
294 | |||
295 | void htc_stop(struct htc_target *target) | ||
296 | { | ||
297 | enum htc_endpoint_id epid; | ||
298 | struct htc_endpoint *endpoint; | ||
299 | |||
300 | for (epid = ENDPOINT0; epid <= ENDPOINT_MAX; epid++) { | ||
301 | endpoint = &target->endpoint[epid]; | ||
302 | if (endpoint->service_id != 0) | ||
303 | target->hif->stop(target->hif_dev, endpoint->ul_pipeid); | ||
304 | } | ||
305 | } | ||
306 | |||
307 | void htc_start(struct htc_target *target) | ||
308 | { | ||
309 | enum htc_endpoint_id epid; | ||
310 | struct htc_endpoint *endpoint; | ||
311 | |||
312 | for (epid = ENDPOINT0; epid <= ENDPOINT_MAX; epid++) { | ||
313 | endpoint = &target->endpoint[epid]; | ||
314 | if (endpoint->service_id != 0) | ||
315 | target->hif->start(target->hif_dev, | ||
316 | endpoint->ul_pipeid); | ||
317 | } | ||
318 | } | ||
319 | |||
320 | void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle, | ||
321 | struct sk_buff *skb, bool txok) | ||
322 | { | ||
323 | struct htc_endpoint *endpoint; | ||
324 | struct htc_frame_hdr *htc_hdr; | ||
325 | |||
326 | if (htc_handle->htc_flags & HTC_OP_CONFIG_PIPE_CREDITS) { | ||
327 | complete(&htc_handle->cmd_wait); | ||
328 | htc_handle->htc_flags &= ~HTC_OP_CONFIG_PIPE_CREDITS; | ||
329 | } | ||
330 | |||
331 | if (htc_handle->htc_flags & HTC_OP_START_WAIT) { | ||
332 | complete(&htc_handle->cmd_wait); | ||
333 | htc_handle->htc_flags &= ~HTC_OP_START_WAIT; | ||
334 | } | ||
335 | |||
336 | if (skb) { | ||
337 | htc_hdr = (struct htc_frame_hdr *) skb->data; | ||
338 | endpoint = &htc_handle->endpoint[htc_hdr->endpoint_id]; | ||
339 | skb_pull(skb, sizeof(struct htc_frame_hdr)); | ||
340 | |||
341 | if (endpoint->ep_callbacks.tx) { | ||
342 | endpoint->ep_callbacks.tx(htc_handle->drv_priv, skb, | ||
343 | htc_hdr->endpoint_id, txok); | ||
344 | } | ||
345 | } | ||
346 | } | ||
347 | |||
348 | /* | ||
349 | * HTC Messages are handled directly here and the obtained SKB | ||
350 | * is freed. | ||
351 | * | ||
352 | * Sevice messages (Data, WMI) passed to the corresponding | ||
353 | * endpoint RX handlers, which have to free the SKB. | ||
354 | */ | ||
355 | void ath9k_htc_rx_msg(struct htc_target *htc_handle, | ||
356 | struct sk_buff *skb, u32 len, u8 pipe_id) | ||
357 | { | ||
358 | struct htc_frame_hdr *htc_hdr; | ||
359 | enum htc_endpoint_id epid; | ||
360 | struct htc_endpoint *endpoint; | ||
361 | u16 *msg_id; | ||
362 | |||
363 | if (!htc_handle || !skb) | ||
364 | return; | ||
365 | |||
366 | htc_hdr = (struct htc_frame_hdr *) skb->data; | ||
367 | epid = htc_hdr->endpoint_id; | ||
368 | |||
369 | if (epid >= ENDPOINT_MAX) { | ||
370 | dev_kfree_skb_any(skb); | ||
371 | return; | ||
372 | } | ||
373 | |||
374 | if (epid == ENDPOINT0) { | ||
375 | |||
376 | /* Handle trailer */ | ||
377 | if (htc_hdr->flags & HTC_FLAGS_RECV_TRAILER) { | ||
378 | if (be32_to_cpu(*(u32 *) skb->data) == 0x00C60000) | ||
379 | /* Move past the Watchdog pattern */ | ||
380 | htc_hdr = (struct htc_frame_hdr *)(skb->data + 4); | ||
381 | } | ||
382 | |||
383 | /* Get the message ID */ | ||
384 | msg_id = (u16 *) ((void *) htc_hdr + | ||
385 | sizeof(struct htc_frame_hdr)); | ||
386 | |||
387 | /* Now process HTC messages */ | ||
388 | switch (be16_to_cpu(*msg_id)) { | ||
389 | case HTC_MSG_READY_ID: | ||
390 | htc_process_target_rdy(htc_handle, htc_hdr); | ||
391 | break; | ||
392 | case HTC_MSG_CONNECT_SERVICE_RESPONSE_ID: | ||
393 | htc_process_conn_rsp(htc_handle, htc_hdr); | ||
394 | break; | ||
395 | default: | ||
396 | break; | ||
397 | } | ||
398 | |||
399 | dev_kfree_skb_any(skb); | ||
400 | |||
401 | } else { | ||
402 | if (htc_hdr->flags & HTC_FLAGS_RECV_TRAILER) | ||
403 | skb_trim(skb, len - htc_hdr->control[0]); | ||
404 | |||
405 | skb_pull(skb, sizeof(struct htc_frame_hdr)); | ||
406 | |||
407 | endpoint = &htc_handle->endpoint[epid]; | ||
408 | if (endpoint->ep_callbacks.rx) | ||
409 | endpoint->ep_callbacks.rx(endpoint->ep_callbacks.priv, | ||
410 | skb, epid); | ||
411 | } | ||
412 | } | ||
413 | |||
414 | struct htc_target *ath9k_htc_hw_alloc(void *hif_handle) | ||
415 | { | ||
416 | struct htc_target *target; | ||
417 | |||
418 | target = kzalloc(sizeof(struct htc_target), GFP_KERNEL); | ||
419 | if (!target) | ||
420 | printk(KERN_ERR "Unable to allocate memory for" | ||
421 | "target device\n"); | ||
422 | |||
423 | return target; | ||
424 | } | ||
425 | |||
426 | void ath9k_htc_hw_free(struct htc_target *htc) | ||
427 | { | ||
428 | kfree(htc); | ||
429 | } | ||
430 | |||
431 | int ath9k_htc_hw_init(struct ath9k_htc_hif *hif, struct htc_target *target, | ||
432 | void *hif_handle, struct device *dev, u16 devid, | ||
433 | enum ath9k_hif_transports transport) | ||
434 | { | ||
435 | struct htc_endpoint *endpoint; | ||
436 | int err = 0; | ||
437 | |||
438 | init_completion(&target->target_wait); | ||
439 | init_completion(&target->cmd_wait); | ||
440 | |||
441 | target->hif = hif; | ||
442 | target->hif_dev = hif_handle; | ||
443 | target->dev = dev; | ||
444 | |||
445 | /* Assign control endpoint pipe IDs */ | ||
446 | endpoint = &target->endpoint[ENDPOINT0]; | ||
447 | endpoint->ul_pipeid = hif->control_ul_pipe; | ||
448 | endpoint->dl_pipeid = hif->control_dl_pipe; | ||
449 | |||
450 | err = ath9k_htc_probe_device(target, dev, devid); | ||
451 | if (err) { | ||
452 | printk(KERN_ERR "Failed to initialize the device\n"); | ||
453 | return -ENODEV; | ||
454 | } | ||
455 | |||
456 | return 0; | ||
457 | } | ||
458 | |||
459 | void ath9k_htc_hw_deinit(struct htc_target *target, bool hot_unplug) | ||
460 | { | ||
461 | if (target) | ||
462 | ath9k_htc_disconnect_device(target, hot_unplug); | ||
463 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.h b/drivers/net/wireless/ath/ath9k/htc_hst.h new file mode 100644 index 000000000000..cd7048ffd239 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/htc_hst.h | |||
@@ -0,0 +1,246 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef HTC_HST_H | ||
18 | #define HTC_HST_H | ||
19 | |||
20 | struct ath9k_htc_priv; | ||
21 | struct htc_target; | ||
22 | struct ath9k_htc_tx_ctl; | ||
23 | |||
24 | enum ath9k_hif_transports { | ||
25 | ATH9K_HIF_USB, | ||
26 | }; | ||
27 | |||
28 | struct ath9k_htc_hif { | ||
29 | struct list_head list; | ||
30 | const enum ath9k_hif_transports transport; | ||
31 | const char *name; | ||
32 | |||
33 | u8 control_dl_pipe; | ||
34 | u8 control_ul_pipe; | ||
35 | |||
36 | void (*start) (void *hif_handle, u8 pipe); | ||
37 | void (*stop) (void *hif_handle, u8 pipe); | ||
38 | int (*send) (void *hif_handle, u8 pipe, struct sk_buff *buf, | ||
39 | struct ath9k_htc_tx_ctl *tx_ctl); | ||
40 | }; | ||
41 | |||
42 | enum htc_endpoint_id { | ||
43 | ENDPOINT_UNUSED = -1, | ||
44 | ENDPOINT0 = 0, | ||
45 | ENDPOINT1 = 1, | ||
46 | ENDPOINT2 = 2, | ||
47 | ENDPOINT3 = 3, | ||
48 | ENDPOINT4 = 4, | ||
49 | ENDPOINT5 = 5, | ||
50 | ENDPOINT6 = 6, | ||
51 | ENDPOINT7 = 7, | ||
52 | ENDPOINT8 = 8, | ||
53 | ENDPOINT_MAX = 22 | ||
54 | }; | ||
55 | |||
56 | /* Htc frame hdr flags */ | ||
57 | #define HTC_FLAGS_RECV_TRAILER (1 << 1) | ||
58 | |||
59 | struct htc_frame_hdr { | ||
60 | u8 endpoint_id; | ||
61 | u8 flags; | ||
62 | u16 payload_len; | ||
63 | u8 control[4]; | ||
64 | } __packed; | ||
65 | |||
66 | struct htc_ready_msg { | ||
67 | u16 message_id; | ||
68 | u16 credits; | ||
69 | u16 credit_size; | ||
70 | u8 max_endpoints; | ||
71 | u8 pad; | ||
72 | } __packed; | ||
73 | |||
74 | struct htc_config_pipe_msg { | ||
75 | u16 message_id; | ||
76 | u8 pipe_id; | ||
77 | u8 credits; | ||
78 | } __packed; | ||
79 | |||
80 | struct htc_packet { | ||
81 | void *pktcontext; | ||
82 | u8 *buf; | ||
83 | u8 *buf_payload; | ||
84 | u32 buflen; | ||
85 | u32 payload_len; | ||
86 | |||
87 | int endpoint; | ||
88 | int status; | ||
89 | |||
90 | void *context; | ||
91 | u32 reserved; | ||
92 | }; | ||
93 | |||
94 | struct htc_ep_callbacks { | ||
95 | void *priv; | ||
96 | void (*tx) (void *, struct sk_buff *, enum htc_endpoint_id, bool txok); | ||
97 | void (*rx) (void *, struct sk_buff *, enum htc_endpoint_id); | ||
98 | }; | ||
99 | |||
100 | #define HTC_TX_QUEUE_SIZE 256 | ||
101 | |||
102 | struct htc_txq { | ||
103 | struct sk_buff *buf[HTC_TX_QUEUE_SIZE]; | ||
104 | u32 txqdepth; | ||
105 | u16 txbuf_cnt; | ||
106 | u16 txq_head; | ||
107 | u16 txq_tail; | ||
108 | }; | ||
109 | |||
110 | struct htc_endpoint { | ||
111 | u16 service_id; | ||
112 | |||
113 | struct htc_ep_callbacks ep_callbacks; | ||
114 | struct htc_txq htc_txq; | ||
115 | u32 max_txqdepth; | ||
116 | int max_msglen; | ||
117 | |||
118 | u8 ul_pipeid; | ||
119 | u8 dl_pipeid; | ||
120 | }; | ||
121 | |||
122 | #define HTC_MAX_CONTROL_MESSAGE_LENGTH 255 | ||
123 | #define HTC_CONTROL_BUFFER_SIZE \ | ||
124 | (HTC_MAX_CONTROL_MESSAGE_LENGTH + sizeof(struct htc_frame_hdr)) | ||
125 | |||
126 | #define NUM_CONTROL_BUFFERS 8 | ||
127 | #define HST_ENDPOINT_MAX 8 | ||
128 | |||
129 | struct htc_control_buf { | ||
130 | struct htc_packet htc_pkt; | ||
131 | u8 buf[HTC_CONTROL_BUFFER_SIZE]; | ||
132 | }; | ||
133 | |||
134 | #define HTC_OP_START_WAIT BIT(0) | ||
135 | #define HTC_OP_CONFIG_PIPE_CREDITS BIT(1) | ||
136 | |||
137 | struct htc_target { | ||
138 | void *hif_dev; | ||
139 | struct ath9k_htc_priv *drv_priv; | ||
140 | struct device *dev; | ||
141 | struct ath9k_htc_hif *hif; | ||
142 | struct htc_endpoint endpoint[HST_ENDPOINT_MAX]; | ||
143 | struct completion target_wait; | ||
144 | struct completion cmd_wait; | ||
145 | struct list_head list; | ||
146 | enum htc_endpoint_id conn_rsp_epid; | ||
147 | u16 credits; | ||
148 | u16 credit_size; | ||
149 | u8 htc_flags; | ||
150 | }; | ||
151 | |||
152 | enum htc_msg_id { | ||
153 | HTC_MSG_READY_ID = 1, | ||
154 | HTC_MSG_CONNECT_SERVICE_ID, | ||
155 | HTC_MSG_CONNECT_SERVICE_RESPONSE_ID, | ||
156 | HTC_MSG_SETUP_COMPLETE_ID, | ||
157 | HTC_MSG_CONFIG_PIPE_ID, | ||
158 | HTC_MSG_CONFIG_PIPE_RESPONSE_ID, | ||
159 | }; | ||
160 | |||
161 | struct htc_service_connreq { | ||
162 | u16 service_id; | ||
163 | u16 con_flags; | ||
164 | u32 max_send_qdepth; | ||
165 | struct htc_ep_callbacks ep_callbacks; | ||
166 | }; | ||
167 | |||
168 | /* Current service IDs */ | ||
169 | |||
170 | enum htc_service_group_ids{ | ||
171 | RSVD_SERVICE_GROUP = 0, | ||
172 | WMI_SERVICE_GROUP = 1, | ||
173 | |||
174 | HTC_SERVICE_GROUP_LAST = 255 | ||
175 | }; | ||
176 | |||
177 | #define MAKE_SERVICE_ID(group, index) \ | ||
178 | (int)(((int)group << 8) | (int)(index)) | ||
179 | |||
180 | /* NOTE: service ID of 0x0000 is reserved and should never be used */ | ||
181 | #define HTC_CTRL_RSVD_SVC MAKE_SERVICE_ID(RSVD_SERVICE_GROUP, 1) | ||
182 | #define HTC_LOOPBACK_RSVD_SVC MAKE_SERVICE_ID(RSVD_SERVICE_GROUP, 2) | ||
183 | |||
184 | #define WMI_CONTROL_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 0) | ||
185 | #define WMI_BEACON_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 1) | ||
186 | #define WMI_CAB_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 2) | ||
187 | #define WMI_UAPSD_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 3) | ||
188 | #define WMI_MGMT_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 4) | ||
189 | #define WMI_DATA_VO_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 5) | ||
190 | #define WMI_DATA_VI_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 6) | ||
191 | #define WMI_DATA_BE_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 7) | ||
192 | #define WMI_DATA_BK_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 8) | ||
193 | |||
194 | struct htc_conn_svc_msg { | ||
195 | u16 msg_id; | ||
196 | u16 service_id; | ||
197 | u16 con_flags; | ||
198 | u8 dl_pipeid; | ||
199 | u8 ul_pipeid; | ||
200 | u8 svc_meta_len; | ||
201 | u8 pad; | ||
202 | } __packed; | ||
203 | |||
204 | /* connect response status codes */ | ||
205 | #define HTC_SERVICE_SUCCESS 0 | ||
206 | #define HTC_SERVICE_NOT_FOUND 1 | ||
207 | #define HTC_SERVICE_FAILED 2 | ||
208 | #define HTC_SERVICE_NO_RESOURCES 3 | ||
209 | #define HTC_SERVICE_NO_MORE_EP 4 | ||
210 | |||
211 | struct htc_conn_svc_rspmsg { | ||
212 | u16 msg_id; | ||
213 | u16 service_id; | ||
214 | u8 status; | ||
215 | u8 endpoint_id; | ||
216 | u16 max_msg_len; | ||
217 | u8 svc_meta_len; | ||
218 | u8 pad; | ||
219 | } __packed; | ||
220 | |||
221 | struct htc_comp_msg { | ||
222 | u16 msg_id; | ||
223 | } __packed; | ||
224 | |||
225 | int htc_init(struct htc_target *target); | ||
226 | int htc_connect_service(struct htc_target *target, | ||
227 | struct htc_service_connreq *service_connreq, | ||
228 | enum htc_endpoint_id *conn_rsp_eid); | ||
229 | int htc_send(struct htc_target *target, struct sk_buff *skb, | ||
230 | enum htc_endpoint_id eid, struct ath9k_htc_tx_ctl *tx_ctl); | ||
231 | void htc_stop(struct htc_target *target); | ||
232 | void htc_start(struct htc_target *target); | ||
233 | |||
234 | void ath9k_htc_rx_msg(struct htc_target *htc_handle, | ||
235 | struct sk_buff *skb, u32 len, u8 pipe_id); | ||
236 | void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle, | ||
237 | struct sk_buff *skb, bool txok); | ||
238 | |||
239 | struct htc_target *ath9k_htc_hw_alloc(void *hif_handle); | ||
240 | void ath9k_htc_hw_free(struct htc_target *htc); | ||
241 | int ath9k_htc_hw_init(struct ath9k_htc_hif *hif, struct htc_target *target, | ||
242 | void *hif_handle, struct device *dev, u16 devid, | ||
243 | enum ath9k_hif_transports transport); | ||
244 | void ath9k_htc_hw_deinit(struct htc_target *target, bool hot_unplug); | ||
245 | |||
246 | #endif /* HTC_HST_H */ | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 2e767cf22f1e..88f8bfdbded4 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -499,8 +499,10 @@ static int ath9k_hw_post_init(struct ath_hw *ah) | |||
499 | { | 499 | { |
500 | int ecode; | 500 | int ecode; |
501 | 501 | ||
502 | if (!ath9k_hw_chip_test(ah)) | 502 | if (!AR_SREV_9271(ah)) { |
503 | return -ENODEV; | 503 | if (!ath9k_hw_chip_test(ah)) |
504 | return -ENODEV; | ||
505 | } | ||
504 | 506 | ||
505 | ecode = ath9k_hw_rf_claim(ah); | 507 | ecode = ath9k_hw_rf_claim(ah); |
506 | if (ecode != 0) | 508 | if (ecode != 0) |
@@ -545,7 +547,6 @@ static bool ath9k_hw_devid_supported(u16 devid) | |||
545 | case AR9285_DEVID_PCIE: | 547 | case AR9285_DEVID_PCIE: |
546 | case AR5416_DEVID_AR9287_PCI: | 548 | case AR5416_DEVID_AR9287_PCI: |
547 | case AR5416_DEVID_AR9287_PCIE: | 549 | case AR5416_DEVID_AR9287_PCIE: |
548 | case AR9271_USB: | ||
549 | case AR2427_DEVID_PCIE: | 550 | case AR2427_DEVID_PCIE: |
550 | return true; | 551 | return true; |
551 | default: | 552 | default: |
@@ -603,9 +604,23 @@ static void ath9k_hw_init_mode_regs(struct ath_hw *ah) | |||
603 | ARRAY_SIZE(ar9271Modes_9271), 6); | 604 | ARRAY_SIZE(ar9271Modes_9271), 6); |
604 | INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271, | 605 | INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271, |
605 | ARRAY_SIZE(ar9271Common_9271), 2); | 606 | ARRAY_SIZE(ar9271Common_9271), 2); |
607 | INIT_INI_ARRAY(&ah->iniCommon_normal_cck_fir_coeff_9271, | ||
608 | ar9271Common_normal_cck_fir_coeff_9271, | ||
609 | ARRAY_SIZE(ar9271Common_normal_cck_fir_coeff_9271), 2); | ||
610 | INIT_INI_ARRAY(&ah->iniCommon_japan_2484_cck_fir_coeff_9271, | ||
611 | ar9271Common_japan_2484_cck_fir_coeff_9271, | ||
612 | ARRAY_SIZE(ar9271Common_japan_2484_cck_fir_coeff_9271), 2); | ||
606 | INIT_INI_ARRAY(&ah->iniModes_9271_1_0_only, | 613 | INIT_INI_ARRAY(&ah->iniModes_9271_1_0_only, |
607 | ar9271Modes_9271_1_0_only, | 614 | ar9271Modes_9271_1_0_only, |
608 | ARRAY_SIZE(ar9271Modes_9271_1_0_only), 6); | 615 | ARRAY_SIZE(ar9271Modes_9271_1_0_only), 6); |
616 | INIT_INI_ARRAY(&ah->iniModes_9271_ANI_reg, ar9271Modes_9271_ANI_reg, | ||
617 | ARRAY_SIZE(ar9271Modes_9271_ANI_reg), 6); | ||
618 | INIT_INI_ARRAY(&ah->iniModes_high_power_tx_gain_9271, | ||
619 | ar9271Modes_high_power_tx_gain_9271, | ||
620 | ARRAY_SIZE(ar9271Modes_high_power_tx_gain_9271), 6); | ||
621 | INIT_INI_ARRAY(&ah->iniModes_normal_power_tx_gain_9271, | ||
622 | ar9271Modes_normal_power_tx_gain_9271, | ||
623 | ARRAY_SIZE(ar9271Modes_normal_power_tx_gain_9271), 6); | ||
609 | return; | 624 | return; |
610 | } | 625 | } |
611 | 626 | ||
@@ -800,15 +815,30 @@ static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah) | |||
800 | 815 | ||
801 | /* txgain table */ | 816 | /* txgain table */ |
802 | if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) { | 817 | if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) { |
803 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 818 | if (AR_SREV_9285E_20(ah)) { |
804 | ar9285Modes_high_power_tx_gain_9285_1_2, | 819 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
805 | ARRAY_SIZE(ar9285Modes_high_power_tx_gain_9285_1_2), 6); | 820 | ar9285Modes_XE2_0_high_power, |
821 | ARRAY_SIZE( | ||
822 | ar9285Modes_XE2_0_high_power), 6); | ||
823 | } else { | ||
824 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
825 | ar9285Modes_high_power_tx_gain_9285_1_2, | ||
826 | ARRAY_SIZE( | ||
827 | ar9285Modes_high_power_tx_gain_9285_1_2), 6); | ||
828 | } | ||
806 | } else { | 829 | } else { |
807 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 830 | if (AR_SREV_9285E_20(ah)) { |
808 | ar9285Modes_original_tx_gain_9285_1_2, | 831 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
809 | ARRAY_SIZE(ar9285Modes_original_tx_gain_9285_1_2), 6); | 832 | ar9285Modes_XE2_0_normal_power, |
833 | ARRAY_SIZE( | ||
834 | ar9285Modes_XE2_0_normal_power), 6); | ||
835 | } else { | ||
836 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
837 | ar9285Modes_original_tx_gain_9285_1_2, | ||
838 | ARRAY_SIZE( | ||
839 | ar9285Modes_original_tx_gain_9285_1_2), 6); | ||
840 | } | ||
810 | } | 841 | } |
811 | |||
812 | } | 842 | } |
813 | } | 843 | } |
814 | 844 | ||
@@ -839,11 +869,13 @@ int ath9k_hw_init(struct ath_hw *ah) | |||
839 | struct ath_common *common = ath9k_hw_common(ah); | 869 | struct ath_common *common = ath9k_hw_common(ah); |
840 | int r = 0; | 870 | int r = 0; |
841 | 871 | ||
842 | if (!ath9k_hw_devid_supported(ah->hw_version.devid)) { | 872 | if (common->bus_ops->ath_bus_type != ATH_USB) { |
843 | ath_print(common, ATH_DBG_FATAL, | 873 | if (!ath9k_hw_devid_supported(ah->hw_version.devid)) { |
844 | "Unsupported device ID: 0x%0x\n", | 874 | ath_print(common, ATH_DBG_FATAL, |
845 | ah->hw_version.devid); | 875 | "Unsupported device ID: 0x%0x\n", |
846 | return -EOPNOTSUPP; | 876 | ah->hw_version.devid); |
877 | return -EOPNOTSUPP; | ||
878 | } | ||
847 | } | 879 | } |
848 | 880 | ||
849 | ath9k_hw_init_defaults(ah); | 881 | ath9k_hw_init_defaults(ah); |
@@ -990,22 +1022,6 @@ static void ath9k_hw_init_qos(struct ath_hw *ah) | |||
990 | REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF); | 1022 | REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF); |
991 | } | 1023 | } |
992 | 1024 | ||
993 | static void ath9k_hw_change_target_baud(struct ath_hw *ah, u32 freq, u32 baud) | ||
994 | { | ||
995 | u32 lcr; | ||
996 | u32 baud_divider = freq * 1000 * 1000 / 16 / baud; | ||
997 | |||
998 | lcr = REG_READ(ah , 0x5100c); | ||
999 | lcr |= 0x80; | ||
1000 | |||
1001 | REG_WRITE(ah, 0x5100c, lcr); | ||
1002 | REG_WRITE(ah, 0x51004, (baud_divider >> 8)); | ||
1003 | REG_WRITE(ah, 0x51000, (baud_divider & 0xff)); | ||
1004 | |||
1005 | lcr &= ~0x80; | ||
1006 | REG_WRITE(ah, 0x5100c, lcr); | ||
1007 | } | ||
1008 | |||
1009 | static void ath9k_hw_init_pll(struct ath_hw *ah, | 1025 | static void ath9k_hw_init_pll(struct ath_hw *ah, |
1010 | struct ath9k_channel *chan) | 1026 | struct ath9k_channel *chan) |
1011 | { | 1027 | { |
@@ -1071,22 +1087,8 @@ static void ath9k_hw_init_pll(struct ath_hw *ah, | |||
1071 | 1087 | ||
1072 | /* Switch the core clock for ar9271 to 117Mhz */ | 1088 | /* Switch the core clock for ar9271 to 117Mhz */ |
1073 | if (AR_SREV_9271(ah)) { | 1089 | if (AR_SREV_9271(ah)) { |
1074 | if ((pll == 0x142c) || (pll == 0x2850) ) { | 1090 | udelay(500); |
1075 | udelay(500); | 1091 | REG_WRITE(ah, 0x50040, 0x304); |
1076 | /* set CLKOBS to output AHB clock */ | ||
1077 | REG_WRITE(ah, 0x7020, 0xe); | ||
1078 | /* | ||
1079 | * 0x304: 117Mhz, ahb_ratio: 1x1 | ||
1080 | * 0x306: 40Mhz, ahb_ratio: 1x1 | ||
1081 | */ | ||
1082 | REG_WRITE(ah, 0x50040, 0x304); | ||
1083 | /* | ||
1084 | * makes adjustments for the baud dividor to keep the | ||
1085 | * targetted baud rate based on the used core clock. | ||
1086 | */ | ||
1087 | ath9k_hw_change_target_baud(ah, AR9271_CORE_CLOCK, | ||
1088 | AR9271_TARGET_BAUD_RATE); | ||
1089 | } | ||
1090 | } | 1092 | } |
1091 | 1093 | ||
1092 | udelay(RTC_PLL_SETTLE_DELAY); | 1094 | udelay(RTC_PLL_SETTLE_DELAY); |
@@ -1134,24 +1136,25 @@ static void ath9k_hw_init_chain_masks(struct ath_hw *ah) | |||
1134 | static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, | 1136 | static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, |
1135 | enum nl80211_iftype opmode) | 1137 | enum nl80211_iftype opmode) |
1136 | { | 1138 | { |
1137 | ah->mask_reg = AR_IMR_TXERR | | 1139 | u32 imr_reg = AR_IMR_TXERR | |
1138 | AR_IMR_TXURN | | 1140 | AR_IMR_TXURN | |
1139 | AR_IMR_RXERR | | 1141 | AR_IMR_RXERR | |
1140 | AR_IMR_RXORN | | 1142 | AR_IMR_RXORN | |
1141 | AR_IMR_BCNMISC; | 1143 | AR_IMR_BCNMISC; |
1142 | 1144 | ||
1143 | if (ah->config.rx_intr_mitigation) | 1145 | if (ah->config.rx_intr_mitigation) |
1144 | ah->mask_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR; | 1146 | imr_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR; |
1145 | else | 1147 | else |
1146 | ah->mask_reg |= AR_IMR_RXOK; | 1148 | imr_reg |= AR_IMR_RXOK; |
1147 | 1149 | ||
1148 | ah->mask_reg |= AR_IMR_TXOK; | 1150 | imr_reg |= AR_IMR_TXOK; |
1149 | 1151 | ||
1150 | if (opmode == NL80211_IFTYPE_AP) | 1152 | if (opmode == NL80211_IFTYPE_AP) |
1151 | ah->mask_reg |= AR_IMR_MIB; | 1153 | imr_reg |= AR_IMR_MIB; |
1152 | 1154 | ||
1153 | REG_WRITE(ah, AR_IMR, ah->mask_reg); | 1155 | REG_WRITE(ah, AR_IMR, imr_reg); |
1154 | REG_WRITE(ah, AR_IMR_S2, REG_READ(ah, AR_IMR_S2) | AR_IMR_S2_GTT); | 1156 | ah->imrs2_reg |= AR_IMR_S2_GTT; |
1157 | REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg); | ||
1155 | 1158 | ||
1156 | if (!AR_SREV_9100(ah)) { | 1159 | if (!AR_SREV_9100(ah)) { |
1157 | REG_WRITE(ah, AR_INTR_SYNC_CAUSE, 0xFFFFFFFF); | 1160 | REG_WRITE(ah, AR_INTR_SYNC_CAUSE, 0xFFFFFFFF); |
@@ -1240,7 +1243,7 @@ void ath9k_hw_deinit(struct ath_hw *ah) | |||
1240 | { | 1243 | { |
1241 | struct ath_common *common = ath9k_hw_common(ah); | 1244 | struct ath_common *common = ath9k_hw_common(ah); |
1242 | 1245 | ||
1243 | if (common->state <= ATH_HW_INITIALIZED) | 1246 | if (common->state < ATH_HW_INITIALIZED) |
1244 | goto free_hw; | 1247 | goto free_hw; |
1245 | 1248 | ||
1246 | if (!AR_SREV_9100(ah)) | 1249 | if (!AR_SREV_9100(ah)) |
@@ -1251,8 +1254,6 @@ void ath9k_hw_deinit(struct ath_hw *ah) | |||
1251 | free_hw: | 1254 | free_hw: |
1252 | if (!AR_SREV_9280_10_OR_LATER(ah)) | 1255 | if (!AR_SREV_9280_10_OR_LATER(ah)) |
1253 | ath9k_hw_rf_free_ext_banks(ah); | 1256 | ath9k_hw_rf_free_ext_banks(ah); |
1254 | kfree(ah); | ||
1255 | ah = NULL; | ||
1256 | } | 1257 | } |
1257 | EXPORT_SYMBOL(ath9k_hw_deinit); | 1258 | EXPORT_SYMBOL(ath9k_hw_deinit); |
1258 | 1259 | ||
@@ -1265,26 +1266,6 @@ static void ath9k_hw_override_ini(struct ath_hw *ah, | |||
1265 | { | 1266 | { |
1266 | u32 val; | 1267 | u32 val; |
1267 | 1268 | ||
1268 | if (AR_SREV_9271(ah)) { | ||
1269 | /* | ||
1270 | * Enable spectral scan to solution for issues with stuck | ||
1271 | * beacons on AR9271 1.0. The beacon stuck issue is not seeon on | ||
1272 | * AR9271 1.1 | ||
1273 | */ | ||
1274 | if (AR_SREV_9271_10(ah)) { | ||
1275 | val = REG_READ(ah, AR_PHY_SPECTRAL_SCAN) | | ||
1276 | AR_PHY_SPECTRAL_SCAN_ENABLE; | ||
1277 | REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val); | ||
1278 | } | ||
1279 | else if (AR_SREV_9271_11(ah)) | ||
1280 | /* | ||
1281 | * change AR_PHY_RF_CTL3 setting to fix MAC issue | ||
1282 | * present on AR9271 1.1 | ||
1283 | */ | ||
1284 | REG_WRITE(ah, AR_PHY_RF_CTL3, 0x3a020001); | ||
1285 | return; | ||
1286 | } | ||
1287 | |||
1288 | /* | 1269 | /* |
1289 | * Set the RX_ABORT and RX_DIS and clear if off only after | 1270 | * Set the RX_ABORT and RX_DIS and clear if off only after |
1290 | * RXE is set for MAC. This prevents frames with corrupted | 1271 | * RXE is set for MAC. This prevents frames with corrupted |
@@ -1293,8 +1274,10 @@ static void ath9k_hw_override_ini(struct ath_hw *ah, | |||
1293 | REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); | 1274 | REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); |
1294 | 1275 | ||
1295 | if (AR_SREV_9280_10_OR_LATER(ah)) { | 1276 | if (AR_SREV_9280_10_OR_LATER(ah)) { |
1296 | val = REG_READ(ah, AR_PCU_MISC_MODE2) & | 1277 | val = REG_READ(ah, AR_PCU_MISC_MODE2); |
1297 | (~AR_PCU_MISC_MODE2_HWWAR1); | 1278 | |
1279 | if (!AR_SREV_9271(ah)) | ||
1280 | val &= ~AR_PCU_MISC_MODE2_HWWAR1; | ||
1298 | 1281 | ||
1299 | if (AR_SREV_9287_10_OR_LATER(ah)) | 1282 | if (AR_SREV_9287_10_OR_LATER(ah)) |
1300 | val = val & (~AR_PCU_MISC_MODE2_HWWAR2); | 1283 | val = val & (~AR_PCU_MISC_MODE2_HWWAR2); |
@@ -1438,7 +1421,10 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, | |||
1438 | return -EINVAL; | 1421 | return -EINVAL; |
1439 | } | 1422 | } |
1440 | 1423 | ||
1424 | /* Set correct baseband to analog shift setting to access analog chips */ | ||
1441 | REG_WRITE(ah, AR_PHY(0), 0x00000007); | 1425 | REG_WRITE(ah, AR_PHY(0), 0x00000007); |
1426 | |||
1427 | /* Write ADDAC shifts */ | ||
1442 | REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO); | 1428 | REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO); |
1443 | ah->eep_ops->set_addac(ah, chan); | 1429 | ah->eep_ops->set_addac(ah, chan); |
1444 | 1430 | ||
@@ -1450,9 +1436,11 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, | |||
1450 | sizeof(u32) * ah->iniAddac.ia_rows * | 1436 | sizeof(u32) * ah->iniAddac.ia_rows * |
1451 | ah->iniAddac.ia_columns; | 1437 | ah->iniAddac.ia_columns; |
1452 | 1438 | ||
1439 | /* For AR5416 2.0/2.1 */ | ||
1453 | memcpy(ah->addac5416_21, | 1440 | memcpy(ah->addac5416_21, |
1454 | ah->iniAddac.ia_array, addacSize); | 1441 | ah->iniAddac.ia_array, addacSize); |
1455 | 1442 | ||
1443 | /* override CLKDRV value at [row, column] = [31, 1] */ | ||
1456 | (ah->addac5416_21)[31 * ah->iniAddac.ia_columns + 1] = 0; | 1444 | (ah->addac5416_21)[31 * ah->iniAddac.ia_columns + 1] = 0; |
1457 | 1445 | ||
1458 | temp.ia_array = ah->addac5416_21; | 1446 | temp.ia_array = ah->addac5416_21; |
@@ -1484,6 +1472,11 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, | |||
1484 | AR_SREV_9287_10_OR_LATER(ah)) | 1472 | AR_SREV_9287_10_OR_LATER(ah)) |
1485 | REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites); | 1473 | REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites); |
1486 | 1474 | ||
1475 | if (AR_SREV_9271_10(ah)) | ||
1476 | REG_WRITE_ARRAY(&ah->iniModes_9271_1_0_only, | ||
1477 | modesIndex, regWrites); | ||
1478 | |||
1479 | /* Write common array parameters */ | ||
1487 | for (i = 0; i < ah->iniCommon.ia_rows; i++) { | 1480 | for (i = 0; i < ah->iniCommon.ia_rows; i++) { |
1488 | u32 reg = INI_RA(&ah->iniCommon, i, 0); | 1481 | u32 reg = INI_RA(&ah->iniCommon, i, 0); |
1489 | u32 val = INI_RA(&ah->iniCommon, i, 1); | 1482 | u32 val = INI_RA(&ah->iniCommon, i, 1); |
@@ -1498,11 +1491,16 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, | |||
1498 | DO_DELAY(regWrites); | 1491 | DO_DELAY(regWrites); |
1499 | } | 1492 | } |
1500 | 1493 | ||
1501 | ath9k_hw_write_regs(ah, freqIndex, regWrites); | 1494 | if (AR_SREV_9271(ah)) { |
1495 | if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) == 1) | ||
1496 | REG_WRITE_ARRAY(&ah->iniModes_high_power_tx_gain_9271, | ||
1497 | modesIndex, regWrites); | ||
1498 | else | ||
1499 | REG_WRITE_ARRAY(&ah->iniModes_normal_power_tx_gain_9271, | ||
1500 | modesIndex, regWrites); | ||
1501 | } | ||
1502 | 1502 | ||
1503 | if (AR_SREV_9271_10(ah)) | 1503 | ath9k_hw_write_regs(ah, freqIndex, regWrites); |
1504 | REG_WRITE_ARRAY(&ah->iniModes_9271_1_0_only, | ||
1505 | modesIndex, regWrites); | ||
1506 | 1504 | ||
1507 | if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan)) { | 1505 | if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan)) { |
1508 | REG_WRITE_ARRAY(&ah->iniModesAdditional, modesIndex, | 1506 | REG_WRITE_ARRAY(&ah->iniModesAdditional, modesIndex, |
@@ -1516,6 +1514,7 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, | |||
1516 | if (OLC_FOR_AR9280_20_LATER) | 1514 | if (OLC_FOR_AR9280_20_LATER) |
1517 | ath9k_olc_init(ah); | 1515 | ath9k_olc_init(ah); |
1518 | 1516 | ||
1517 | /* Set TX power */ | ||
1519 | ah->eep_ops->set_txpower(ah, chan, | 1518 | ah->eep_ops->set_txpower(ah, chan, |
1520 | ath9k_regd_get_ctl(regulatory, chan), | 1519 | ath9k_regd_get_ctl(regulatory, chan), |
1521 | channel->max_antenna_gain * 2, | 1520 | channel->max_antenna_gain * 2, |
@@ -1523,6 +1522,7 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, | |||
1523 | min((u32) MAX_RATE_POWER, | 1522 | min((u32) MAX_RATE_POWER, |
1524 | (u32) regulatory->power_limit)); | 1523 | (u32) regulatory->power_limit)); |
1525 | 1524 | ||
1525 | /* Write analog registers */ | ||
1526 | if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) { | 1526 | if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) { |
1527 | ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, | 1527 | ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, |
1528 | "ar5416SetRfRegs failed\n"); | 1528 | "ar5416SetRfRegs failed\n"); |
@@ -1965,6 +1965,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1965 | 1965 | ||
1966 | ath9k_hw_mark_phy_inactive(ah); | 1966 | ath9k_hw_mark_phy_inactive(ah); |
1967 | 1967 | ||
1968 | /* Only required on the first reset */ | ||
1968 | if (AR_SREV_9271(ah) && ah->htc_reset_init) { | 1969 | if (AR_SREV_9271(ah) && ah->htc_reset_init) { |
1969 | REG_WRITE(ah, | 1970 | REG_WRITE(ah, |
1970 | AR9271_RESET_POWER_DOWN_CONTROL, | 1971 | AR9271_RESET_POWER_DOWN_CONTROL, |
@@ -1977,6 +1978,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1977 | return -EINVAL; | 1978 | return -EINVAL; |
1978 | } | 1979 | } |
1979 | 1980 | ||
1981 | /* Only required on the first reset */ | ||
1980 | if (AR_SREV_9271(ah) && ah->htc_reset_init) { | 1982 | if (AR_SREV_9271(ah) && ah->htc_reset_init) { |
1981 | ah->htc_reset_init = false; | 1983 | ah->htc_reset_init = false; |
1982 | REG_WRITE(ah, | 1984 | REG_WRITE(ah, |
@@ -2437,7 +2439,7 @@ static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip) | |||
2437 | if (!AR_SREV_9100(ah)) | 2439 | if (!AR_SREV_9100(ah)) |
2438 | REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF); | 2440 | REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF); |
2439 | 2441 | ||
2440 | if(!AR_SREV_5416(ah)) | 2442 | if (!AR_SREV_5416(ah) && !AR_SREV_9271(ah)) |
2441 | REG_CLR_BIT(ah, (AR_RTC_RESET), | 2443 | REG_CLR_BIT(ah, (AR_RTC_RESET), |
2442 | AR_RTC_RESET_EN); | 2444 | AR_RTC_RESET_EN); |
2443 | } | 2445 | } |
@@ -2853,7 +2855,7 @@ EXPORT_SYMBOL(ath9k_hw_getisr); | |||
2853 | 2855 | ||
2854 | enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) | 2856 | enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) |
2855 | { | 2857 | { |
2856 | u32 omask = ah->mask_reg; | 2858 | enum ath9k_int omask = ah->imask; |
2857 | u32 mask, mask2; | 2859 | u32 mask, mask2; |
2858 | struct ath9k_hw_capabilities *pCap = &ah->caps; | 2860 | struct ath9k_hw_capabilities *pCap = &ah->caps; |
2859 | struct ath_common *common = ath9k_hw_common(ah); | 2861 | struct ath_common *common = ath9k_hw_common(ah); |
@@ -2920,15 +2922,11 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) | |||
2920 | 2922 | ||
2921 | ath_print(common, ATH_DBG_INTERRUPT, "new IMR 0x%x\n", mask); | 2923 | ath_print(common, ATH_DBG_INTERRUPT, "new IMR 0x%x\n", mask); |
2922 | REG_WRITE(ah, AR_IMR, mask); | 2924 | REG_WRITE(ah, AR_IMR, mask); |
2923 | mask = REG_READ(ah, AR_IMR_S2) & ~(AR_IMR_S2_TIM | | 2925 | ah->imrs2_reg &= ~(AR_IMR_S2_TIM | AR_IMR_S2_DTIM | AR_IMR_S2_DTIMSYNC | |
2924 | AR_IMR_S2_DTIM | | 2926 | AR_IMR_S2_CABEND | AR_IMR_S2_CABTO | |
2925 | AR_IMR_S2_DTIMSYNC | | 2927 | AR_IMR_S2_TSFOOR | AR_IMR_S2_GTT | AR_IMR_S2_CST); |
2926 | AR_IMR_S2_CABEND | | 2928 | ah->imrs2_reg |= mask2; |
2927 | AR_IMR_S2_CABTO | | 2929 | REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg); |
2928 | AR_IMR_S2_TSFOOR | | ||
2929 | AR_IMR_S2_GTT | AR_IMR_S2_CST); | ||
2930 | REG_WRITE(ah, AR_IMR_S2, mask | mask2); | ||
2931 | ah->mask_reg = ints; | ||
2932 | 2930 | ||
2933 | if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { | 2931 | if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { |
2934 | if (ints & ATH9K_INT_TIM_TIMER) | 2932 | if (ints & ATH9K_INT_TIM_TIMER) |
@@ -3218,7 +3216,9 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
3218 | else | 3216 | else |
3219 | pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD; | 3217 | pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD; |
3220 | 3218 | ||
3221 | if (AR_SREV_9285_10_OR_LATER(ah)) | 3219 | if (AR_SREV_9271(ah)) |
3220 | pCap->num_gpio_pins = AR9271_NUM_GPIO; | ||
3221 | else if (AR_SREV_9285_10_OR_LATER(ah)) | ||
3222 | pCap->num_gpio_pins = AR9285_NUM_GPIO; | 3222 | pCap->num_gpio_pins = AR9285_NUM_GPIO; |
3223 | else if (AR_SREV_9280_10_OR_LATER(ah)) | 3223 | else if (AR_SREV_9280_10_OR_LATER(ah)) |
3224 | pCap->num_gpio_pins = AR928X_NUM_GPIO; | 3224 | pCap->num_gpio_pins = AR928X_NUM_GPIO; |
@@ -3245,8 +3245,10 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
3245 | pCap->hw_caps |= ATH9K_HW_CAP_RFSILENT; | 3245 | pCap->hw_caps |= ATH9K_HW_CAP_RFSILENT; |
3246 | } | 3246 | } |
3247 | #endif | 3247 | #endif |
3248 | 3248 | if (AR_SREV_9271(ah)) | |
3249 | pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP; | 3249 | pCap->hw_caps |= ATH9K_HW_CAP_AUTOSLEEP; |
3250 | else | ||
3251 | pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP; | ||
3250 | 3252 | ||
3251 | if (AR_SREV_9280(ah) || AR_SREV_9285(ah)) | 3253 | if (AR_SREV_9280(ah) || AR_SREV_9285(ah)) |
3252 | pCap->hw_caps &= ~ATH9K_HW_CAP_4KB_SPLITTRANS; | 3254 | pCap->hw_caps &= ~ATH9K_HW_CAP_4KB_SPLITTRANS; |
@@ -3454,7 +3456,9 @@ u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio) | |||
3454 | if (gpio >= ah->caps.num_gpio_pins) | 3456 | if (gpio >= ah->caps.num_gpio_pins) |
3455 | return 0xffffffff; | 3457 | return 0xffffffff; |
3456 | 3458 | ||
3457 | if (AR_SREV_9287_10_OR_LATER(ah)) | 3459 | if (AR_SREV_9271(ah)) |
3460 | return MS_REG_READ(AR9271, gpio) != 0; | ||
3461 | else if (AR_SREV_9287_10_OR_LATER(ah)) | ||
3458 | return MS_REG_READ(AR9287, gpio) != 0; | 3462 | return MS_REG_READ(AR9287, gpio) != 0; |
3459 | else if (AR_SREV_9285_10_OR_LATER(ah)) | 3463 | else if (AR_SREV_9285_10_OR_LATER(ah)) |
3460 | return MS_REG_READ(AR9285, gpio) != 0; | 3464 | return MS_REG_READ(AR9285, gpio) != 0; |
@@ -3483,6 +3487,9 @@ EXPORT_SYMBOL(ath9k_hw_cfg_output); | |||
3483 | 3487 | ||
3484 | void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val) | 3488 | void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val) |
3485 | { | 3489 | { |
3490 | if (AR_SREV_9271(ah)) | ||
3491 | val = ~val; | ||
3492 | |||
3486 | REG_RMW(ah, AR_GPIO_IN_OUT, ((val & 1) << gpio), | 3493 | REG_RMW(ah, AR_GPIO_IN_OUT, ((val & 1) << gpio), |
3487 | AR_GPIO_BIT(gpio)); | 3494 | AR_GPIO_BIT(gpio)); |
3488 | } | 3495 | } |
@@ -3867,6 +3874,16 @@ void ath_gen_timer_isr(struct ath_hw *ah) | |||
3867 | } | 3874 | } |
3868 | EXPORT_SYMBOL(ath_gen_timer_isr); | 3875 | EXPORT_SYMBOL(ath_gen_timer_isr); |
3869 | 3876 | ||
3877 | /********/ | ||
3878 | /* HTC */ | ||
3879 | /********/ | ||
3880 | |||
3881 | void ath9k_hw_htc_resetinit(struct ath_hw *ah) | ||
3882 | { | ||
3883 | ah->htc_reset_init = true; | ||
3884 | } | ||
3885 | EXPORT_SYMBOL(ath9k_hw_htc_resetinit); | ||
3886 | |||
3870 | static struct { | 3887 | static struct { |
3871 | u32 version; | 3888 | u32 version; |
3872 | const char * name; | 3889 | const char * name; |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index dbbf7ca5f97d..b02a97c72c64 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -44,8 +44,6 @@ | |||
44 | 44 | ||
45 | #define AR5416_AR9100_DEVID 0x000b | 45 | #define AR5416_AR9100_DEVID 0x000b |
46 | 46 | ||
47 | #define AR9271_USB 0x9271 | ||
48 | |||
49 | #define AR_SUBVENDOR_ID_NOG 0x0e11 | 47 | #define AR_SUBVENDOR_ID_NOG 0x0e11 |
50 | #define AR_SUBVENDOR_ID_NEW_A 0x7065 | 48 | #define AR_SUBVENDOR_ID_NEW_A 0x7065 |
51 | #define AR5416_MAGIC 0x19641014 | 49 | #define AR5416_MAGIC 0x19641014 |
@@ -478,7 +476,8 @@ struct ath_hw { | |||
478 | struct ath9k_tx_queue_info txq[ATH9K_NUM_TX_QUEUES]; | 476 | struct ath9k_tx_queue_info txq[ATH9K_NUM_TX_QUEUES]; |
479 | 477 | ||
480 | int16_t curchan_rad_index; | 478 | int16_t curchan_rad_index; |
481 | u32 mask_reg; | 479 | enum ath9k_int imask; |
480 | u32 imrs2_reg; | ||
482 | u32 txok_interrupt_mask; | 481 | u32 txok_interrupt_mask; |
483 | u32 txerr_interrupt_mask; | 482 | u32 txerr_interrupt_mask; |
484 | u32 txdesc_interrupt_mask; | 483 | u32 txdesc_interrupt_mask; |
@@ -598,6 +597,11 @@ struct ath_hw { | |||
598 | struct ar5416IniArray iniModes_9271_1_0_only; | 597 | struct ar5416IniArray iniModes_9271_1_0_only; |
599 | struct ar5416IniArray iniCckfirNormal; | 598 | struct ar5416IniArray iniCckfirNormal; |
600 | struct ar5416IniArray iniCckfirJapan2484; | 599 | struct ar5416IniArray iniCckfirJapan2484; |
600 | struct ar5416IniArray iniCommon_normal_cck_fir_coeff_9271; | ||
601 | struct ar5416IniArray iniCommon_japan_2484_cck_fir_coeff_9271; | ||
602 | struct ar5416IniArray iniModes_9271_ANI_reg; | ||
603 | struct ar5416IniArray iniModes_high_power_tx_gain_9271; | ||
604 | struct ar5416IniArray iniModes_normal_power_tx_gain_9271; | ||
601 | 605 | ||
602 | u32 intr_gen_timer_trigger; | 606 | u32 intr_gen_timer_trigger; |
603 | u32 intr_gen_timer_thresh; | 607 | u32 intr_gen_timer_thresh; |
@@ -701,6 +705,9 @@ u32 ath9k_hw_gettsf32(struct ath_hw *ah); | |||
701 | 705 | ||
702 | void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len); | 706 | void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len); |
703 | 707 | ||
708 | /* HTC */ | ||
709 | void ath9k_hw_htc_resetinit(struct ath_hw *ah); | ||
710 | |||
704 | #define ATH_PCIE_CAP_LINK_CTRL 0x70 | 711 | #define ATH_PCIE_CAP_LINK_CTRL 0x70 |
705 | #define ATH_PCIE_CAP_LINK_L0S 1 | 712 | #define ATH_PCIE_CAP_LINK_L0S 1 |
706 | #define ATH_PCIE_CAP_LINK_L1 2 | 713 | #define ATH_PCIE_CAP_LINK_L1 2 |
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 623c2f884987..6063f5463708 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -758,6 +758,9 @@ static void ath9k_deinit_softc(struct ath_softc *sc) | |||
758 | 758 | ||
759 | tasklet_kill(&sc->intr_tq); | 759 | tasklet_kill(&sc->intr_tq); |
760 | tasklet_kill(&sc->bcon_tasklet); | 760 | tasklet_kill(&sc->bcon_tasklet); |
761 | |||
762 | kfree(sc->sc_ah); | ||
763 | sc->sc_ah = NULL; | ||
761 | } | 764 | } |
762 | 765 | ||
763 | void ath9k_deinit_device(struct ath_softc *sc) | 766 | void ath9k_deinit_device(struct ath_softc *sc) |
diff --git a/drivers/net/wireless/ath/ath9k/initvals.h b/drivers/net/wireless/ath/ath9k/initvals.h index 8a3bf3ab998d..455e9d3b3f13 100644 --- a/drivers/net/wireless/ath/ath9k/initvals.h +++ b/drivers/net/wireless/ath/ath9k/initvals.h | |||
@@ -4184,7 +4184,7 @@ static const u_int32_t ar9285Modes_9285_1_2[][6] = { | |||
4184 | { 0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, | 4184 | { 0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, |
4185 | { 0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, | 4185 | { 0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, |
4186 | { 0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, | 4186 | { 0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, |
4187 | { 0x00009a50, 0x00000000, 0x00000000, 0x00058220, 0x00058220, 0x00000000 }, | 4187 | { 0x00009a50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000 }, |
4188 | { 0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, | 4188 | { 0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, |
4189 | { 0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, | 4189 | { 0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, |
4190 | { 0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, | 4190 | { 0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, |
@@ -4198,8 +4198,8 @@ static const u_int32_t ar9285Modes_9285_1_2[][6] = { | |||
4198 | { 0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, | 4198 | { 0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, |
4199 | { 0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, | 4199 | { 0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, |
4200 | { 0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, | 4200 | { 0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, |
4201 | { 0x00009a88, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, | 4201 | { 0x00009a88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000 }, |
4202 | { 0x00009a8c, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, | 4202 | { 0x00009a8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, |
4203 | { 0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, | 4203 | { 0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, |
4204 | { 0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, | 4204 | { 0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, |
4205 | { 0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, | 4205 | { 0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, |
@@ -4312,7 +4312,7 @@ static const u_int32_t ar9285Modes_9285_1_2[][6] = { | |||
4312 | { 0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, | 4312 | { 0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, |
4313 | { 0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, | 4313 | { 0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, |
4314 | { 0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, | 4314 | { 0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, |
4315 | { 0x0000aa50, 0x00000000, 0x00000000, 0x00058220, 0x00058220, 0x00000000 }, | 4315 | { 0x0000aa50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000 }, |
4316 | { 0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, | 4316 | { 0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, |
4317 | { 0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, | 4317 | { 0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, |
4318 | { 0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, | 4318 | { 0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, |
@@ -4326,8 +4326,8 @@ static const u_int32_t ar9285Modes_9285_1_2[][6] = { | |||
4326 | { 0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, | 4326 | { 0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, |
4327 | { 0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, | 4327 | { 0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, |
4328 | { 0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, | 4328 | { 0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, |
4329 | { 0x0000aa88, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, | 4329 | { 0x0000aa88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000 }, |
4330 | { 0x0000aa8c, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, | 4330 | { 0x0000aa8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, |
4331 | { 0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, | 4331 | { 0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, |
4332 | { 0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, | 4332 | { 0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, |
4333 | { 0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, | 4333 | { 0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, |
@@ -4731,17 +4731,12 @@ static const u_int32_t ar9285Common_9285_1_2[][2] = { | |||
4731 | { 0x00007808, 0x54214514 }, | 4731 | { 0x00007808, 0x54214514 }, |
4732 | { 0x0000780c, 0x02025830 }, | 4732 | { 0x0000780c, 0x02025830 }, |
4733 | { 0x00007810, 0x71c0d388 }, | 4733 | { 0x00007810, 0x71c0d388 }, |
4734 | { 0x00007814, 0x924934a8 }, | ||
4735 | { 0x0000781c, 0x00000000 }, | 4734 | { 0x0000781c, 0x00000000 }, |
4736 | { 0x00007824, 0x00d86fff }, | 4735 | { 0x00007824, 0x00d86fff }, |
4737 | { 0x00007828, 0x26d2491b }, | ||
4738 | { 0x0000782c, 0x6e36d97b }, | 4736 | { 0x0000782c, 0x6e36d97b }, |
4739 | { 0x00007830, 0xedb6d96e }, | ||
4740 | { 0x00007834, 0x71400087 }, | 4737 | { 0x00007834, 0x71400087 }, |
4741 | { 0x0000783c, 0x0001fffe }, | ||
4742 | { 0x00007840, 0xffeb1a20 }, | ||
4743 | { 0x00007844, 0x000c0db6 }, | 4738 | { 0x00007844, 0x000c0db6 }, |
4744 | { 0x00007848, 0x6db61b6f }, | 4739 | { 0x00007848, 0x6db6246f }, |
4745 | { 0x0000784c, 0x6d9b66db }, | 4740 | { 0x0000784c, 0x6d9b66db }, |
4746 | { 0x00007850, 0x6d8c6dba }, | 4741 | { 0x00007850, 0x6d8c6dba }, |
4747 | { 0x00007854, 0x00040000 }, | 4742 | { 0x00007854, 0x00040000 }, |
@@ -4777,7 +4772,12 @@ static const u_int32_t ar9285Modes_high_power_tx_gain_9285_1_2[][6] = { | |||
4777 | { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | 4772 | { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, |
4778 | { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | 4773 | { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, |
4779 | { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | 4774 | { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, |
4775 | { 0x00007814, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8 }, | ||
4776 | { 0x00007828, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b }, | ||
4777 | { 0x00007830, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e }, | ||
4780 | { 0x00007838, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803 }, | 4778 | { 0x00007838, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803 }, |
4779 | { 0x0000783c, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe }, | ||
4780 | { 0x00007840, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20 }, | ||
4781 | { 0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe }, | 4781 | { 0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe }, |
4782 | { 0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00 }, | 4782 | { 0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00 }, |
4783 | { 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652, 0x0a22a652 }, | 4783 | { 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652, 0x0a22a652 }, |
@@ -4813,7 +4813,12 @@ static const u_int32_t ar9285Modes_original_tx_gain_9285_1_2[][6] = { | |||
4813 | { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | 4813 | { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, |
4814 | { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | 4814 | { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, |
4815 | { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | 4815 | { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, |
4816 | { 0x00007814, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8 }, | ||
4817 | { 0x00007828, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b }, | ||
4818 | { 0x00007830, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e }, | ||
4816 | { 0x00007838, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801 }, | 4819 | { 0x00007838, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801 }, |
4820 | { 0x0000783c, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe }, | ||
4821 | { 0x00007840, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20 }, | ||
4817 | { 0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4 }, | 4822 | { 0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4 }, |
4818 | { 0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04 }, | 4823 | { 0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04 }, |
4819 | { 0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652, 0x0a22a652 }, | 4824 | { 0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652, 0x0a22a652 }, |
@@ -4825,6 +4830,86 @@ static const u_int32_t ar9285Modes_original_tx_gain_9285_1_2[][6] = { | |||
4825 | { 0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c }, | 4830 | { 0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c }, |
4826 | }; | 4831 | }; |
4827 | 4832 | ||
4833 | static const u_int32_t ar9285Modes_XE2_0_normal_power[][6] = { | ||
4834 | { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | ||
4835 | { 0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000 }, | ||
4836 | { 0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000 }, | ||
4837 | { 0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000 }, | ||
4838 | { 0x0000a310, 0x00000000, 0x00000000, 0x00022618, 0x00022618, 0x00000000 }, | ||
4839 | { 0x0000a314, 0x00000000, 0x00000000, 0x0002a6c9, 0x0002a6c9, 0x00000000 }, | ||
4840 | { 0x0000a318, 0x00000000, 0x00000000, 0x00031710, 0x00031710, 0x00000000 }, | ||
4841 | { 0x0000a31c, 0x00000000, 0x00000000, 0x00035718, 0x00035718, 0x00000000 }, | ||
4842 | { 0x0000a320, 0x00000000, 0x00000000, 0x00038758, 0x00038758, 0x00000000 }, | ||
4843 | { 0x0000a324, 0x00000000, 0x00000000, 0x0003c75a, 0x0003c75a, 0x00000000 }, | ||
4844 | { 0x0000a328, 0x00000000, 0x00000000, 0x0004075c, 0x0004075c, 0x00000000 }, | ||
4845 | { 0x0000a32c, 0x00000000, 0x00000000, 0x0004475e, 0x0004475e, 0x00000000 }, | ||
4846 | { 0x0000a330, 0x00000000, 0x00000000, 0x0004679f, 0x0004679f, 0x00000000 }, | ||
4847 | { 0x0000a334, 0x00000000, 0x00000000, 0x000487df, 0x000487df, 0x00000000 }, | ||
4848 | { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, | ||
4849 | { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, | ||
4850 | { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
4851 | { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
4852 | { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
4853 | { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
4854 | { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
4855 | { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
4856 | { 0x00007814, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8 }, | ||
4857 | { 0x00007828, 0x4ad2491b, 0x4ad2491b, 0x2ad2491b, 0x4ad2491b, 0x4ad2491b }, | ||
4858 | { 0x00007830, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6dbae }, | ||
4859 | { 0x00007838, 0xdac71441, 0xdac71441, 0xdac71441, 0xdac71441, 0xdac71441 }, | ||
4860 | { 0x0000783c, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe }, | ||
4861 | { 0x00007840, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c }, | ||
4862 | { 0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4 }, | ||
4863 | { 0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04 }, | ||
4864 | { 0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652, 0x0a22a652 }, | ||
4865 | { 0x0000a278, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, | ||
4866 | { 0x0000a27c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c }, | ||
4867 | { 0x0000a394, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, | ||
4868 | { 0x0000a398, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c }, | ||
4869 | { 0x0000a3dc, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, | ||
4870 | { 0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c }, | ||
4871 | }; | ||
4872 | |||
4873 | static const u_int32_t ar9285Modes_XE2_0_high_power[][6] = { | ||
4874 | { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | ||
4875 | { 0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200, 0x00000000 }, | ||
4876 | { 0x0000a308, 0x00000000, 0x00000000, 0x00008201, 0x00008201, 0x00000000 }, | ||
4877 | { 0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240, 0x00000000 }, | ||
4878 | { 0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241, 0x00000000 }, | ||
4879 | { 0x0000a314, 0x00000000, 0x00000000, 0x0000f600, 0x0000f600, 0x00000000 }, | ||
4880 | { 0x0000a318, 0x00000000, 0x00000000, 0x00012800, 0x00012800, 0x00000000 }, | ||
4881 | { 0x0000a31c, 0x00000000, 0x00000000, 0x00016802, 0x00016802, 0x00000000 }, | ||
4882 | { 0x0000a320, 0x00000000, 0x00000000, 0x0001b805, 0x0001b805, 0x00000000 }, | ||
4883 | { 0x0000a324, 0x00000000, 0x00000000, 0x00021a80, 0x00021a80, 0x00000000 }, | ||
4884 | { 0x0000a328, 0x00000000, 0x00000000, 0x00028b00, 0x00028b00, 0x00000000 }, | ||
4885 | { 0x0000a32c, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40, 0x00000000 }, | ||
4886 | { 0x0000a330, 0x00000000, 0x00000000, 0x0002cd80, 0x0002cd80, 0x00000000 }, | ||
4887 | { 0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82, 0x00000000 }, | ||
4888 | { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, | ||
4889 | { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, | ||
4890 | { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
4891 | { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
4892 | { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
4893 | { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
4894 | { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
4895 | { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
4896 | { 0x00007814, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8 }, | ||
4897 | { 0x00007828, 0x4ad2491b, 0x4ad2491b, 0x2ad2491b, 0x4ad2491b, 0x4ad2491b }, | ||
4898 | { 0x00007830, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e }, | ||
4899 | { 0x00007838, 0xdac71443, 0xdac71443, 0xdac71443, 0xdac71443, 0xdac71443 }, | ||
4900 | { 0x0000783c, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe }, | ||
4901 | { 0x00007840, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c }, | ||
4902 | { 0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe }, | ||
4903 | { 0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00 }, | ||
4904 | { 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652, 0x0a22a652 }, | ||
4905 | { 0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, | ||
4906 | { 0x0000a27c, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7 }, | ||
4907 | { 0x0000a394, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, | ||
4908 | { 0x0000a398, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7 }, | ||
4909 | { 0x0000a3dc, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, | ||
4910 | { 0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7 }, | ||
4911 | }; | ||
4912 | |||
4828 | static const u_int32_t ar9285PciePhy_clkreq_always_on_L1_9285_1_2[][2] = { | 4913 | static const u_int32_t ar9285PciePhy_clkreq_always_on_L1_9285_1_2[][2] = { |
4829 | {0x00004040, 0x9248fd00 }, | 4914 | {0x00004040, 0x9248fd00 }, |
4830 | {0x00004040, 0x24924924 }, | 4915 | {0x00004040, 0x24924924 }, |
@@ -6441,7 +6526,7 @@ static const u_int32_t ar9271Modes_9271[][6] = { | |||
6441 | { 0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, | 6526 | { 0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, |
6442 | { 0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, | 6527 | { 0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, |
6443 | { 0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, | 6528 | { 0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, |
6444 | { 0x00009a50, 0x00000000, 0x00000000, 0x00058220, 0x00058220, 0x00000000 }, | 6529 | { 0x00009a50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000 }, |
6445 | { 0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, | 6530 | { 0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, |
6446 | { 0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, | 6531 | { 0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, |
6447 | { 0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, | 6532 | { 0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, |
@@ -6455,8 +6540,8 @@ static const u_int32_t ar9271Modes_9271[][6] = { | |||
6455 | { 0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, | 6540 | { 0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, |
6456 | { 0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, | 6541 | { 0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, |
6457 | { 0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, | 6542 | { 0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, |
6458 | { 0x00009a88, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, | 6543 | { 0x00009a88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000 }, |
6459 | { 0x00009a8c, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, | 6544 | { 0x00009a8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, |
6460 | { 0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, | 6545 | { 0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, |
6461 | { 0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, | 6546 | { 0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, |
6462 | { 0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, | 6547 | { 0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, |
@@ -6569,7 +6654,7 @@ static const u_int32_t ar9271Modes_9271[][6] = { | |||
6569 | { 0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, | 6654 | { 0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, |
6570 | { 0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, | 6655 | { 0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, |
6571 | { 0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, | 6656 | { 0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, |
6572 | { 0x0000aa50, 0x00000000, 0x00000000, 0x00058220, 0x00058220, 0x00000000 }, | 6657 | { 0x0000aa50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000 }, |
6573 | { 0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, | 6658 | { 0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, |
6574 | { 0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, | 6659 | { 0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, |
6575 | { 0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, | 6660 | { 0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, |
@@ -6583,8 +6668,8 @@ static const u_int32_t ar9271Modes_9271[][6] = { | |||
6583 | { 0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, | 6668 | { 0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, |
6584 | { 0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, | 6669 | { 0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, |
6585 | { 0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, | 6670 | { 0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, |
6586 | { 0x0000aa88, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, | 6671 | { 0x0000aa88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000 }, |
6587 | { 0x0000aa8c, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, | 6672 | { 0x0000aa8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, |
6588 | { 0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, | 6673 | { 0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, |
6589 | { 0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, | 6674 | { 0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, |
6590 | { 0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, | 6675 | { 0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, |
@@ -6683,25 +6768,6 @@ static const u_int32_t ar9271Modes_9271[][6] = { | |||
6683 | { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, | 6768 | { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, |
6684 | { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, | 6769 | { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, |
6685 | { 0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000, 0x0004a000 }, | 6770 | { 0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000, 0x0004a000 }, |
6686 | { 0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a218652, 0x0a218652, 0x0a22a652 }, | ||
6687 | { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | ||
6688 | { 0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000 }, | ||
6689 | { 0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000 }, | ||
6690 | { 0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000 }, | ||
6691 | { 0x0000a310, 0x00000000, 0x00000000, 0x0001e610, 0x0001e610, 0x00000000 }, | ||
6692 | { 0x0000a314, 0x00000000, 0x00000000, 0x0002d6d0, 0x0002d6d0, 0x00000000 }, | ||
6693 | { 0x0000a318, 0x00000000, 0x00000000, 0x00039758, 0x00039758, 0x00000000 }, | ||
6694 | { 0x0000a31c, 0x00000000, 0x00000000, 0x0003b759, 0x0003b759, 0x00000000 }, | ||
6695 | { 0x0000a320, 0x00000000, 0x00000000, 0x0003d75a, 0x0003d75a, 0x00000000 }, | ||
6696 | { 0x0000a324, 0x00000000, 0x00000000, 0x0004175c, 0x0004175c, 0x00000000 }, | ||
6697 | { 0x0000a328, 0x00000000, 0x00000000, 0x0004575e, 0x0004575e, 0x00000000 }, | ||
6698 | { 0x0000a32c, 0x00000000, 0x00000000, 0x0004979f, 0x0004979f, 0x00000000 }, | ||
6699 | { 0x0000a330, 0x00000000, 0x00000000, 0x0004d7df, 0x0004d7df, 0x00000000 }, | ||
6700 | { 0x0000a334, 0x000368de, 0x000368de, 0x000368de, 0x000368de, 0x00000000 }, | ||
6701 | { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, | ||
6702 | { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, | ||
6703 | { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
6704 | { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
6705 | { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, | 6771 | { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, |
6706 | }; | 6772 | }; |
6707 | 6773 | ||
@@ -6879,7 +6945,7 @@ static const u_int32_t ar9271Common_9271[][2] = { | |||
6879 | { 0x00008258, 0x00000000 }, | 6945 | { 0x00008258, 0x00000000 }, |
6880 | { 0x0000825c, 0x400000ff }, | 6946 | { 0x0000825c, 0x400000ff }, |
6881 | { 0x00008260, 0x00080922 }, | 6947 | { 0x00008260, 0x00080922 }, |
6882 | { 0x00008264, 0x88a00010 }, | 6948 | { 0x00008264, 0xa8a00010 }, |
6883 | { 0x00008270, 0x00000000 }, | 6949 | { 0x00008270, 0x00000000 }, |
6884 | { 0x00008274, 0x40000000 }, | 6950 | { 0x00008274, 0x40000000 }, |
6885 | { 0x00008278, 0x003e4180 }, | 6951 | { 0x00008278, 0x003e4180 }, |
@@ -6910,13 +6976,10 @@ static const u_int32_t ar9271Common_9271[][2] = { | |||
6910 | { 0x00007810, 0x71c0d388 }, | 6976 | { 0x00007810, 0x71c0d388 }, |
6911 | { 0x00007814, 0x924934a8 }, | 6977 | { 0x00007814, 0x924934a8 }, |
6912 | { 0x0000781c, 0x00000000 }, | 6978 | { 0x0000781c, 0x00000000 }, |
6913 | { 0x00007820, 0x00000c04 }, | ||
6914 | { 0x00007824, 0x00d8abff }, | ||
6915 | { 0x00007828, 0x66964300 }, | 6979 | { 0x00007828, 0x66964300 }, |
6916 | { 0x0000782c, 0x8db6d961 }, | 6980 | { 0x0000782c, 0x8db6d961 }, |
6917 | { 0x00007830, 0x8db6d96c }, | 6981 | { 0x00007830, 0x8db6d96c }, |
6918 | { 0x00007834, 0x6140008b }, | 6982 | { 0x00007834, 0x6140008b }, |
6919 | { 0x00007838, 0x00000029 }, | ||
6920 | { 0x0000783c, 0x72ee0a72 }, | 6983 | { 0x0000783c, 0x72ee0a72 }, |
6921 | { 0x00007840, 0xbbfffffc }, | 6984 | { 0x00007840, 0xbbfffffc }, |
6922 | { 0x00007844, 0x000c0db6 }, | 6985 | { 0x00007844, 0x000c0db6 }, |
@@ -6929,7 +6992,6 @@ static const u_int32_t ar9271Common_9271[][2] = { | |||
6929 | { 0x00007860, 0x21084210 }, | 6992 | { 0x00007860, 0x21084210 }, |
6930 | { 0x00007864, 0xf7d7ffde }, | 6993 | { 0x00007864, 0xf7d7ffde }, |
6931 | { 0x00007868, 0xc2034080 }, | 6994 | { 0x00007868, 0xc2034080 }, |
6932 | { 0x0000786c, 0x48609eb4 }, | ||
6933 | { 0x00007870, 0x10142c00 }, | 6995 | { 0x00007870, 0x10142c00 }, |
6934 | { 0x00009808, 0x00000000 }, | 6996 | { 0x00009808, 0x00000000 }, |
6935 | { 0x0000980c, 0xafe68e30 }, | 6997 | { 0x0000980c, 0xafe68e30 }, |
@@ -6982,9 +7044,6 @@ static const u_int32_t ar9271Common_9271[][2] = { | |||
6982 | { 0x000099e8, 0x3c466478 }, | 7044 | { 0x000099e8, 0x3c466478 }, |
6983 | { 0x000099ec, 0x0cc80caa }, | 7045 | { 0x000099ec, 0x0cc80caa }, |
6984 | { 0x000099f0, 0x00000000 }, | 7046 | { 0x000099f0, 0x00000000 }, |
6985 | { 0x0000a1f4, 0x00000000 }, | ||
6986 | { 0x0000a1f8, 0x71733d01 }, | ||
6987 | { 0x0000a1fc, 0xd0ad5c12 }, | ||
6988 | { 0x0000a208, 0x803e68c8 }, | 7047 | { 0x0000a208, 0x803e68c8 }, |
6989 | { 0x0000a210, 0x4080a333 }, | 7048 | { 0x0000a210, 0x4080a333 }, |
6990 | { 0x0000a214, 0x00206c10 }, | 7049 | { 0x0000a214, 0x00206c10 }, |
@@ -7004,13 +7063,9 @@ static const u_int32_t ar9271Common_9271[][2] = { | |||
7004 | { 0x0000a260, 0xdfa90f01 }, | 7063 | { 0x0000a260, 0xdfa90f01 }, |
7005 | { 0x0000a268, 0x00000000 }, | 7064 | { 0x0000a268, 0x00000000 }, |
7006 | { 0x0000a26c, 0x0ebae9e6 }, | 7065 | { 0x0000a26c, 0x0ebae9e6 }, |
7007 | { 0x0000a278, 0x3bdef7bd }, | ||
7008 | { 0x0000a27c, 0x050e83bd }, | ||
7009 | { 0x0000a388, 0x0c000000 }, | 7066 | { 0x0000a388, 0x0c000000 }, |
7010 | { 0x0000a38c, 0x20202020 }, | 7067 | { 0x0000a38c, 0x20202020 }, |
7011 | { 0x0000a390, 0x20202020 }, | 7068 | { 0x0000a390, 0x20202020 }, |
7012 | { 0x0000a394, 0x3bdef7bd }, | ||
7013 | { 0x0000a398, 0x000003bd }, | ||
7014 | { 0x0000a39c, 0x00000001 }, | 7069 | { 0x0000a39c, 0x00000001 }, |
7015 | { 0x0000a3a0, 0x00000000 }, | 7070 | { 0x0000a3a0, 0x00000000 }, |
7016 | { 0x0000a3a4, 0x00000000 }, | 7071 | { 0x0000a3a4, 0x00000000 }, |
@@ -7025,8 +7080,6 @@ static const u_int32_t ar9271Common_9271[][2] = { | |||
7025 | { 0x0000a3cc, 0x20202020 }, | 7080 | { 0x0000a3cc, 0x20202020 }, |
7026 | { 0x0000a3d0, 0x20202020 }, | 7081 | { 0x0000a3d0, 0x20202020 }, |
7027 | { 0x0000a3d4, 0x20202020 }, | 7082 | { 0x0000a3d4, 0x20202020 }, |
7028 | { 0x0000a3dc, 0x3bdef7bd }, | ||
7029 | { 0x0000a3e0, 0x000003bd }, | ||
7030 | { 0x0000a3e4, 0x00000000 }, | 7083 | { 0x0000a3e4, 0x00000000 }, |
7031 | { 0x0000a3e8, 0x18c43433 }, | 7084 | { 0x0000a3e8, 0x18c43433 }, |
7032 | { 0x0000a3ec, 0x00f70081 }, | 7085 | { 0x0000a3ec, 0x00f70081 }, |
@@ -7046,7 +7099,102 @@ static const u_int32_t ar9271Common_9271[][2] = { | |||
7046 | { 0x0000d384, 0xf3307ff0 }, | 7099 | { 0x0000d384, 0xf3307ff0 }, |
7047 | }; | 7100 | }; |
7048 | 7101 | ||
7102 | static const u_int32_t ar9271Common_normal_cck_fir_coeff_9271[][2] = { | ||
7103 | { 0x0000a1f4, 0x00fffeff }, | ||
7104 | { 0x0000a1f8, 0x00f5f9ff }, | ||
7105 | { 0x0000a1fc, 0xb79f6427 }, | ||
7106 | }; | ||
7107 | |||
7108 | static const u_int32_t ar9271Common_japan_2484_cck_fir_coeff_9271[][2] = { | ||
7109 | { 0x0000a1f4, 0x00000000 }, | ||
7110 | { 0x0000a1f8, 0xefff0301 }, | ||
7111 | { 0x0000a1fc, 0xca9228ee }, | ||
7112 | }; | ||
7113 | |||
7049 | static const u_int32_t ar9271Modes_9271_1_0_only[][6] = { | 7114 | static const u_int32_t ar9271Modes_9271_1_0_only[][6] = { |
7050 | { 0x00009910, 0x30002311, 0x30002311, 0x30002311, 0x30002311, 0x30002311 }, | 7115 | { 0x00009910, 0x30002311, 0x30002311, 0x30002311, 0x30002311, 0x30002311 }, |
7051 | { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, | 7116 | { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, |
7052 | }; | 7117 | }; |
7118 | |||
7119 | static const u_int32_t ar9271Modes_9271_ANI_reg[][6] = { | ||
7120 | { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 }, | ||
7121 | { 0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e }, | ||
7122 | { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, | ||
7123 | { 0x0000986c, 0x06903881, 0x06903881, 0x06903881, 0x06903881, 0x06903881 }, | ||
7124 | { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, | ||
7125 | { 0x0000a208, 0x803e68c8, 0x803e68c8, 0x803e68c8, 0x803e68c8, 0x803e68c8 }, | ||
7126 | { 0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d }, | ||
7127 | { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, | ||
7128 | }; | ||
7129 | |||
7130 | static const u_int32_t ar9271Modes_normal_power_tx_gain_9271[][6] = { | ||
7131 | { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | ||
7132 | { 0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000 }, | ||
7133 | { 0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000 }, | ||
7134 | { 0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000 }, | ||
7135 | { 0x0000a310, 0x00000000, 0x00000000, 0x0001e610, 0x0001e610, 0x00000000 }, | ||
7136 | { 0x0000a314, 0x00000000, 0x00000000, 0x0002d6d0, 0x0002d6d0, 0x00000000 }, | ||
7137 | { 0x0000a318, 0x00000000, 0x00000000, 0x00039758, 0x00039758, 0x00000000 }, | ||
7138 | { 0x0000a31c, 0x00000000, 0x00000000, 0x0003b759, 0x0003b759, 0x00000000 }, | ||
7139 | { 0x0000a320, 0x00000000, 0x00000000, 0x0003d75a, 0x0003d75a, 0x00000000 }, | ||
7140 | { 0x0000a324, 0x00000000, 0x00000000, 0x0004175c, 0x0004175c, 0x00000000 }, | ||
7141 | { 0x0000a328, 0x00000000, 0x00000000, 0x0004575e, 0x0004575e, 0x00000000 }, | ||
7142 | { 0x0000a32c, 0x00000000, 0x00000000, 0x0004979f, 0x0004979f, 0x00000000 }, | ||
7143 | { 0x0000a330, 0x00000000, 0x00000000, 0x0004d7df, 0x0004d7df, 0x00000000 }, | ||
7144 | { 0x0000a334, 0x000368de, 0x000368de, 0x000368de, 0x000368de, 0x00000000 }, | ||
7145 | { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, | ||
7146 | { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, | ||
7147 | { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
7148 | { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
7149 | { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
7150 | { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
7151 | { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
7152 | { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
7153 | { 0x00007838, 0x00000029, 0x00000029, 0x00000029, 0x00000029, 0x00000029 }, | ||
7154 | { 0x00007824, 0x00d8abff, 0x00d8abff, 0x00d8abff, 0x00d8abff, 0x00d8abff }, | ||
7155 | { 0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4 }, | ||
7156 | { 0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04 }, | ||
7157 | { 0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a218652, 0x0a218652, 0x0a22a652 }, | ||
7158 | { 0x0000a278, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd }, | ||
7159 | { 0x0000a27c, 0x050e83bd, 0x050e83bd, 0x050e83bd, 0x050e83bd, 0x050e83bd }, | ||
7160 | { 0x0000a394, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd }, | ||
7161 | { 0x0000a398, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd }, | ||
7162 | { 0x0000a3dc, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd }, | ||
7163 | { 0x0000a3e0, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd }, | ||
7164 | }; | ||
7165 | |||
7166 | static const u_int32_t ar9271Modes_high_power_tx_gain_9271[][6] = { | ||
7167 | { 0x0000a300, 0x00000000, 0x00000000, 0x00010000, 0x00010000, 0x00000000 }, | ||
7168 | { 0x0000a304, 0x00000000, 0x00000000, 0x00016200, 0x00016200, 0x00000000 }, | ||
7169 | { 0x0000a308, 0x00000000, 0x00000000, 0x00018201, 0x00018201, 0x00000000 }, | ||
7170 | { 0x0000a30c, 0x00000000, 0x00000000, 0x0001b240, 0x0001b240, 0x00000000 }, | ||
7171 | { 0x0000a310, 0x00000000, 0x00000000, 0x0001d241, 0x0001d241, 0x00000000 }, | ||
7172 | { 0x0000a314, 0x00000000, 0x00000000, 0x0001f600, 0x0001f600, 0x00000000 }, | ||
7173 | { 0x0000a318, 0x00000000, 0x00000000, 0x00022800, 0x00022800, 0x00000000 }, | ||
7174 | { 0x0000a31c, 0x00000000, 0x00000000, 0x00026802, 0x00026802, 0x00000000 }, | ||
7175 | { 0x0000a320, 0x00000000, 0x00000000, 0x0002b805, 0x0002b805, 0x00000000 }, | ||
7176 | { 0x0000a324, 0x00000000, 0x00000000, 0x0002ea41, 0x0002ea41, 0x00000000 }, | ||
7177 | { 0x0000a328, 0x00000000, 0x00000000, 0x00038b00, 0x00038b00, 0x00000000 }, | ||
7178 | { 0x0000a32c, 0x00000000, 0x00000000, 0x0003ab40, 0x0003ab40, 0x00000000 }, | ||
7179 | { 0x0000a330, 0x00000000, 0x00000000, 0x0003cd80, 0x0003cd80, 0x00000000 }, | ||
7180 | { 0x0000a334, 0x000368de, 0x000368de, 0x000368de, 0x000368de, 0x00000000 }, | ||
7181 | { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, | ||
7182 | { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, | ||
7183 | { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
7184 | { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
7185 | { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
7186 | { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
7187 | { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
7188 | { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
7189 | { 0x00007838, 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b }, | ||
7190 | { 0x00007824, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff }, | ||
7191 | { 0x0000786c, 0x08609eb6, 0x08609eb6, 0x08609eba, 0x08609eba, 0x08609eb6 }, | ||
7192 | { 0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00 }, | ||
7193 | { 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a212652, 0x0a212652, 0x0a22a652 }, | ||
7194 | { 0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, | ||
7195 | { 0x0000a27c, 0x05018063, 0x05038063, 0x05018063, 0x05018063, 0x05018063 }, | ||
7196 | { 0x0000a394, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63 }, | ||
7197 | { 0x0000a398, 0x00000063, 0x00000063, 0x00000063, 0x00000063, 0x00000063 }, | ||
7198 | { 0x0000a3dc, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63 }, | ||
7199 | { 0x0000a3e0, 0x00000063, 0x00000063, 0x00000063, 0x00000063, 0x00000063 }, | ||
7200 | }; | ||
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index efc420cd42bf..4a2060e5a777 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c | |||
@@ -31,8 +31,10 @@ static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah, | |||
31 | REG_WRITE(ah, AR_IMR_S1, | 31 | REG_WRITE(ah, AR_IMR_S1, |
32 | SM(ah->txerr_interrupt_mask, AR_IMR_S1_QCU_TXERR) | 32 | SM(ah->txerr_interrupt_mask, AR_IMR_S1_QCU_TXERR) |
33 | | SM(ah->txeol_interrupt_mask, AR_IMR_S1_QCU_TXEOL)); | 33 | | SM(ah->txeol_interrupt_mask, AR_IMR_S1_QCU_TXEOL)); |
34 | REG_RMW_FIELD(ah, AR_IMR_S2, | 34 | |
35 | AR_IMR_S2_QCU_TXURN, ah->txurn_interrupt_mask); | 35 | ah->imrs2_reg &= ~AR_IMR_S2_QCU_TXURN; |
36 | ah->imrs2_reg |= (ah->txurn_interrupt_mask & AR_IMR_S2_QCU_TXURN); | ||
37 | REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg); | ||
36 | } | 38 | } |
37 | 39 | ||
38 | u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q) | 40 | u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q) |
@@ -103,7 +105,7 @@ bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel) | |||
103 | if (ah->tx_trig_level >= ah->config.max_txtrig_level) | 105 | if (ah->tx_trig_level >= ah->config.max_txtrig_level) |
104 | return false; | 106 | return false; |
105 | 107 | ||
106 | omask = ath9k_hw_set_interrupts(ah, ah->mask_reg & ~ATH9K_INT_GLOBAL); | 108 | omask = ath9k_hw_set_interrupts(ah, ah->imask & ~ATH9K_INT_GLOBAL); |
107 | 109 | ||
108 | txcfg = REG_READ(ah, AR_TXCFG); | 110 | txcfg = REG_READ(ah, AR_TXCFG); |
109 | curLevel = MS(txcfg, AR_FTRIG); | 111 | curLevel = MS(txcfg, AR_FTRIG); |
@@ -244,79 +246,80 @@ void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds) | |||
244 | } | 246 | } |
245 | EXPORT_SYMBOL(ath9k_hw_cleartxdesc); | 247 | EXPORT_SYMBOL(ath9k_hw_cleartxdesc); |
246 | 248 | ||
247 | int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds) | 249 | int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds, |
250 | struct ath_tx_status *ts) | ||
248 | { | 251 | { |
249 | struct ar5416_desc *ads = AR5416DESC(ds); | 252 | struct ar5416_desc *ads = AR5416DESC(ds); |
250 | 253 | ||
251 | if ((ads->ds_txstatus9 & AR_TxDone) == 0) | 254 | if ((ads->ds_txstatus9 & AR_TxDone) == 0) |
252 | return -EINPROGRESS; | 255 | return -EINPROGRESS; |
253 | 256 | ||
254 | ds->ds_txstat.ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum); | 257 | ts->ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum); |
255 | ds->ds_txstat.ts_tstamp = ads->AR_SendTimestamp; | 258 | ts->ts_tstamp = ads->AR_SendTimestamp; |
256 | ds->ds_txstat.ts_status = 0; | 259 | ts->ts_status = 0; |
257 | ds->ds_txstat.ts_flags = 0; | 260 | ts->ts_flags = 0; |
258 | 261 | ||
259 | if (ads->ds_txstatus1 & AR_FrmXmitOK) | 262 | if (ads->ds_txstatus1 & AR_FrmXmitOK) |
260 | ds->ds_txstat.ts_status |= ATH9K_TX_ACKED; | 263 | ts->ts_status |= ATH9K_TX_ACKED; |
261 | if (ads->ds_txstatus1 & AR_ExcessiveRetries) | 264 | if (ads->ds_txstatus1 & AR_ExcessiveRetries) |
262 | ds->ds_txstat.ts_status |= ATH9K_TXERR_XRETRY; | 265 | ts->ts_status |= ATH9K_TXERR_XRETRY; |
263 | if (ads->ds_txstatus1 & AR_Filtered) | 266 | if (ads->ds_txstatus1 & AR_Filtered) |
264 | ds->ds_txstat.ts_status |= ATH9K_TXERR_FILT; | 267 | ts->ts_status |= ATH9K_TXERR_FILT; |
265 | if (ads->ds_txstatus1 & AR_FIFOUnderrun) { | 268 | if (ads->ds_txstatus1 & AR_FIFOUnderrun) { |
266 | ds->ds_txstat.ts_status |= ATH9K_TXERR_FIFO; | 269 | ts->ts_status |= ATH9K_TXERR_FIFO; |
267 | ath9k_hw_updatetxtriglevel(ah, true); | 270 | ath9k_hw_updatetxtriglevel(ah, true); |
268 | } | 271 | } |
269 | if (ads->ds_txstatus9 & AR_TxOpExceeded) | 272 | if (ads->ds_txstatus9 & AR_TxOpExceeded) |
270 | ds->ds_txstat.ts_status |= ATH9K_TXERR_XTXOP; | 273 | ts->ts_status |= ATH9K_TXERR_XTXOP; |
271 | if (ads->ds_txstatus1 & AR_TxTimerExpired) | 274 | if (ads->ds_txstatus1 & AR_TxTimerExpired) |
272 | ds->ds_txstat.ts_status |= ATH9K_TXERR_TIMER_EXPIRED; | 275 | ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED; |
273 | 276 | ||
274 | if (ads->ds_txstatus1 & AR_DescCfgErr) | 277 | if (ads->ds_txstatus1 & AR_DescCfgErr) |
275 | ds->ds_txstat.ts_flags |= ATH9K_TX_DESC_CFG_ERR; | 278 | ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR; |
276 | if (ads->ds_txstatus1 & AR_TxDataUnderrun) { | 279 | if (ads->ds_txstatus1 & AR_TxDataUnderrun) { |
277 | ds->ds_txstat.ts_flags |= ATH9K_TX_DATA_UNDERRUN; | 280 | ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN; |
278 | ath9k_hw_updatetxtriglevel(ah, true); | 281 | ath9k_hw_updatetxtriglevel(ah, true); |
279 | } | 282 | } |
280 | if (ads->ds_txstatus1 & AR_TxDelimUnderrun) { | 283 | if (ads->ds_txstatus1 & AR_TxDelimUnderrun) { |
281 | ds->ds_txstat.ts_flags |= ATH9K_TX_DELIM_UNDERRUN; | 284 | ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN; |
282 | ath9k_hw_updatetxtriglevel(ah, true); | 285 | ath9k_hw_updatetxtriglevel(ah, true); |
283 | } | 286 | } |
284 | if (ads->ds_txstatus0 & AR_TxBaStatus) { | 287 | if (ads->ds_txstatus0 & AR_TxBaStatus) { |
285 | ds->ds_txstat.ts_flags |= ATH9K_TX_BA; | 288 | ts->ts_flags |= ATH9K_TX_BA; |
286 | ds->ds_txstat.ba_low = ads->AR_BaBitmapLow; | 289 | ts->ba_low = ads->AR_BaBitmapLow; |
287 | ds->ds_txstat.ba_high = ads->AR_BaBitmapHigh; | 290 | ts->ba_high = ads->AR_BaBitmapHigh; |
288 | } | 291 | } |
289 | 292 | ||
290 | ds->ds_txstat.ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx); | 293 | ts->ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx); |
291 | switch (ds->ds_txstat.ts_rateindex) { | 294 | switch (ts->ts_rateindex) { |
292 | case 0: | 295 | case 0: |
293 | ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0); | 296 | ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0); |
294 | break; | 297 | break; |
295 | case 1: | 298 | case 1: |
296 | ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1); | 299 | ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1); |
297 | break; | 300 | break; |
298 | case 2: | 301 | case 2: |
299 | ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2); | 302 | ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2); |
300 | break; | 303 | break; |
301 | case 3: | 304 | case 3: |
302 | ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3); | 305 | ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3); |
303 | break; | 306 | break; |
304 | } | 307 | } |
305 | 308 | ||
306 | ds->ds_txstat.ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined); | 309 | ts->ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined); |
307 | ds->ds_txstat.ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00); | 310 | ts->ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00); |
308 | ds->ds_txstat.ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01); | 311 | ts->ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01); |
309 | ds->ds_txstat.ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02); | 312 | ts->ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02); |
310 | ds->ds_txstat.ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10); | 313 | ts->ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10); |
311 | ds->ds_txstat.ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11); | 314 | ts->ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11); |
312 | ds->ds_txstat.ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12); | 315 | ts->ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12); |
313 | ds->ds_txstat.evm0 = ads->AR_TxEVM0; | 316 | ts->evm0 = ads->AR_TxEVM0; |
314 | ds->ds_txstat.evm1 = ads->AR_TxEVM1; | 317 | ts->evm1 = ads->AR_TxEVM1; |
315 | ds->ds_txstat.evm2 = ads->AR_TxEVM2; | 318 | ts->evm2 = ads->AR_TxEVM2; |
316 | ds->ds_txstat.ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt); | 319 | ts->ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt); |
317 | ds->ds_txstat.ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt); | 320 | ts->ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt); |
318 | ds->ds_txstat.ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt); | 321 | ts->ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt); |
319 | ds->ds_txstat.ts_antenna = 0; | 322 | ts->ts_antenna = 0; |
320 | 323 | ||
321 | return 0; | 324 | return 0; |
322 | } | 325 | } |
@@ -349,7 +352,7 @@ void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds, | |||
349 | 352 | ||
350 | ads->ds_ctl6 = SM(keyType, AR_EncrType); | 353 | ads->ds_ctl6 = SM(keyType, AR_EncrType); |
351 | 354 | ||
352 | if (AR_SREV_9285(ah)) { | 355 | if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) { |
353 | ads->ds_ctl8 = 0; | 356 | ads->ds_ctl8 = 0; |
354 | ads->ds_ctl9 = 0; | 357 | ads->ds_ctl9 = 0; |
355 | ads->ds_ctl10 = 0; | 358 | ads->ds_ctl10 = 0; |
@@ -856,7 +859,7 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) | |||
856 | EXPORT_SYMBOL(ath9k_hw_resettxqueue); | 859 | EXPORT_SYMBOL(ath9k_hw_resettxqueue); |
857 | 860 | ||
858 | int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, | 861 | int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, |
859 | u32 pa, struct ath_desc *nds, u64 tsf) | 862 | struct ath_rx_status *rs, u64 tsf) |
860 | { | 863 | { |
861 | struct ar5416_desc ads; | 864 | struct ar5416_desc ads; |
862 | struct ar5416_desc *adsp = AR5416DESC(ds); | 865 | struct ar5416_desc *adsp = AR5416DESC(ds); |
@@ -867,70 +870,70 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, | |||
867 | 870 | ||
868 | ads.u.rx = adsp->u.rx; | 871 | ads.u.rx = adsp->u.rx; |
869 | 872 | ||
870 | ds->ds_rxstat.rs_status = 0; | 873 | rs->rs_status = 0; |
871 | ds->ds_rxstat.rs_flags = 0; | 874 | rs->rs_flags = 0; |
872 | 875 | ||
873 | ds->ds_rxstat.rs_datalen = ads.ds_rxstatus1 & AR_DataLen; | 876 | rs->rs_datalen = ads.ds_rxstatus1 & AR_DataLen; |
874 | ds->ds_rxstat.rs_tstamp = ads.AR_RcvTimestamp; | 877 | rs->rs_tstamp = ads.AR_RcvTimestamp; |
875 | 878 | ||
876 | if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) { | 879 | if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) { |
877 | ds->ds_rxstat.rs_rssi = ATH9K_RSSI_BAD; | 880 | rs->rs_rssi = ATH9K_RSSI_BAD; |
878 | ds->ds_rxstat.rs_rssi_ctl0 = ATH9K_RSSI_BAD; | 881 | rs->rs_rssi_ctl0 = ATH9K_RSSI_BAD; |
879 | ds->ds_rxstat.rs_rssi_ctl1 = ATH9K_RSSI_BAD; | 882 | rs->rs_rssi_ctl1 = ATH9K_RSSI_BAD; |
880 | ds->ds_rxstat.rs_rssi_ctl2 = ATH9K_RSSI_BAD; | 883 | rs->rs_rssi_ctl2 = ATH9K_RSSI_BAD; |
881 | ds->ds_rxstat.rs_rssi_ext0 = ATH9K_RSSI_BAD; | 884 | rs->rs_rssi_ext0 = ATH9K_RSSI_BAD; |
882 | ds->ds_rxstat.rs_rssi_ext1 = ATH9K_RSSI_BAD; | 885 | rs->rs_rssi_ext1 = ATH9K_RSSI_BAD; |
883 | ds->ds_rxstat.rs_rssi_ext2 = ATH9K_RSSI_BAD; | 886 | rs->rs_rssi_ext2 = ATH9K_RSSI_BAD; |
884 | } else { | 887 | } else { |
885 | ds->ds_rxstat.rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined); | 888 | rs->rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined); |
886 | ds->ds_rxstat.rs_rssi_ctl0 = MS(ads.ds_rxstatus0, | 889 | rs->rs_rssi_ctl0 = MS(ads.ds_rxstatus0, |
887 | AR_RxRSSIAnt00); | 890 | AR_RxRSSIAnt00); |
888 | ds->ds_rxstat.rs_rssi_ctl1 = MS(ads.ds_rxstatus0, | 891 | rs->rs_rssi_ctl1 = MS(ads.ds_rxstatus0, |
889 | AR_RxRSSIAnt01); | 892 | AR_RxRSSIAnt01); |
890 | ds->ds_rxstat.rs_rssi_ctl2 = MS(ads.ds_rxstatus0, | 893 | rs->rs_rssi_ctl2 = MS(ads.ds_rxstatus0, |
891 | AR_RxRSSIAnt02); | 894 | AR_RxRSSIAnt02); |
892 | ds->ds_rxstat.rs_rssi_ext0 = MS(ads.ds_rxstatus4, | 895 | rs->rs_rssi_ext0 = MS(ads.ds_rxstatus4, |
893 | AR_RxRSSIAnt10); | 896 | AR_RxRSSIAnt10); |
894 | ds->ds_rxstat.rs_rssi_ext1 = MS(ads.ds_rxstatus4, | 897 | rs->rs_rssi_ext1 = MS(ads.ds_rxstatus4, |
895 | AR_RxRSSIAnt11); | 898 | AR_RxRSSIAnt11); |
896 | ds->ds_rxstat.rs_rssi_ext2 = MS(ads.ds_rxstatus4, | 899 | rs->rs_rssi_ext2 = MS(ads.ds_rxstatus4, |
897 | AR_RxRSSIAnt12); | 900 | AR_RxRSSIAnt12); |
898 | } | 901 | } |
899 | if (ads.ds_rxstatus8 & AR_RxKeyIdxValid) | 902 | if (ads.ds_rxstatus8 & AR_RxKeyIdxValid) |
900 | ds->ds_rxstat.rs_keyix = MS(ads.ds_rxstatus8, AR_KeyIdx); | 903 | rs->rs_keyix = MS(ads.ds_rxstatus8, AR_KeyIdx); |
901 | else | 904 | else |
902 | ds->ds_rxstat.rs_keyix = ATH9K_RXKEYIX_INVALID; | 905 | rs->rs_keyix = ATH9K_RXKEYIX_INVALID; |
903 | 906 | ||
904 | ds->ds_rxstat.rs_rate = RXSTATUS_RATE(ah, (&ads)); | 907 | rs->rs_rate = RXSTATUS_RATE(ah, (&ads)); |
905 | ds->ds_rxstat.rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0; | 908 | rs->rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0; |
906 | 909 | ||
907 | ds->ds_rxstat.rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0; | 910 | rs->rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0; |
908 | ds->ds_rxstat.rs_moreaggr = | 911 | rs->rs_moreaggr = |
909 | (ads.ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0; | 912 | (ads.ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0; |
910 | ds->ds_rxstat.rs_antenna = MS(ads.ds_rxstatus3, AR_RxAntenna); | 913 | rs->rs_antenna = MS(ads.ds_rxstatus3, AR_RxAntenna); |
911 | ds->ds_rxstat.rs_flags = | 914 | rs->rs_flags = |
912 | (ads.ds_rxstatus3 & AR_GI) ? ATH9K_RX_GI : 0; | 915 | (ads.ds_rxstatus3 & AR_GI) ? ATH9K_RX_GI : 0; |
913 | ds->ds_rxstat.rs_flags |= | 916 | rs->rs_flags |= |
914 | (ads.ds_rxstatus3 & AR_2040) ? ATH9K_RX_2040 : 0; | 917 | (ads.ds_rxstatus3 & AR_2040) ? ATH9K_RX_2040 : 0; |
915 | 918 | ||
916 | if (ads.ds_rxstatus8 & AR_PreDelimCRCErr) | 919 | if (ads.ds_rxstatus8 & AR_PreDelimCRCErr) |
917 | ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_PRE; | 920 | rs->rs_flags |= ATH9K_RX_DELIM_CRC_PRE; |
918 | if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) | 921 | if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) |
919 | ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_POST; | 922 | rs->rs_flags |= ATH9K_RX_DELIM_CRC_POST; |
920 | if (ads.ds_rxstatus8 & AR_DecryptBusyErr) | 923 | if (ads.ds_rxstatus8 & AR_DecryptBusyErr) |
921 | ds->ds_rxstat.rs_flags |= ATH9K_RX_DECRYPT_BUSY; | 924 | rs->rs_flags |= ATH9K_RX_DECRYPT_BUSY; |
922 | 925 | ||
923 | if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) { | 926 | if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) { |
924 | if (ads.ds_rxstatus8 & AR_CRCErr) | 927 | if (ads.ds_rxstatus8 & AR_CRCErr) |
925 | ds->ds_rxstat.rs_status |= ATH9K_RXERR_CRC; | 928 | rs->rs_status |= ATH9K_RXERR_CRC; |
926 | else if (ads.ds_rxstatus8 & AR_PHYErr) { | 929 | else if (ads.ds_rxstatus8 & AR_PHYErr) { |
927 | ds->ds_rxstat.rs_status |= ATH9K_RXERR_PHY; | 930 | rs->rs_status |= ATH9K_RXERR_PHY; |
928 | phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode); | 931 | phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode); |
929 | ds->ds_rxstat.rs_phyerr = phyerr; | 932 | rs->rs_phyerr = phyerr; |
930 | } else if (ads.ds_rxstatus8 & AR_DecryptCRCErr) | 933 | } else if (ads.ds_rxstatus8 & AR_DecryptCRCErr) |
931 | ds->ds_rxstat.rs_status |= ATH9K_RXERR_DECRYPT; | 934 | rs->rs_status |= ATH9K_RXERR_DECRYPT; |
932 | else if (ads.ds_rxstatus8 & AR_MichaelErr) | 935 | else if (ads.ds_rxstatus8 & AR_MichaelErr) |
933 | ds->ds_rxstat.rs_status |= ATH9K_RXERR_MIC; | 936 | rs->rs_status |= ATH9K_RXERR_MIC; |
934 | } | 937 | } |
935 | 938 | ||
936 | return 0; | 939 | return 0; |
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 29851e6376a9..68dbd7a8ddca 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h | |||
@@ -150,6 +150,32 @@ struct ath_rx_status { | |||
150 | u32 evm2; | 150 | u32 evm2; |
151 | }; | 151 | }; |
152 | 152 | ||
153 | struct ath_htc_rx_status { | ||
154 | u64 rs_tstamp; | ||
155 | u16 rs_datalen; | ||
156 | u8 rs_status; | ||
157 | u8 rs_phyerr; | ||
158 | int8_t rs_rssi; | ||
159 | int8_t rs_rssi_ctl0; | ||
160 | int8_t rs_rssi_ctl1; | ||
161 | int8_t rs_rssi_ctl2; | ||
162 | int8_t rs_rssi_ext0; | ||
163 | int8_t rs_rssi_ext1; | ||
164 | int8_t rs_rssi_ext2; | ||
165 | u8 rs_keyix; | ||
166 | u8 rs_rate; | ||
167 | u8 rs_antenna; | ||
168 | u8 rs_more; | ||
169 | u8 rs_isaggr; | ||
170 | u8 rs_moreaggr; | ||
171 | u8 rs_num_delims; | ||
172 | u8 rs_flags; | ||
173 | u8 rs_dummy; | ||
174 | u32 evm0; | ||
175 | u32 evm1; | ||
176 | u32 evm2; | ||
177 | }; | ||
178 | |||
153 | #define ATH9K_RXERR_CRC 0x01 | 179 | #define ATH9K_RXERR_CRC 0x01 |
154 | #define ATH9K_RXERR_PHY 0x02 | 180 | #define ATH9K_RXERR_PHY 0x02 |
155 | #define ATH9K_RXERR_FIFO 0x04 | 181 | #define ATH9K_RXERR_FIFO 0x04 |
@@ -207,18 +233,9 @@ struct ath_desc { | |||
207 | u32 ds_ctl0; | 233 | u32 ds_ctl0; |
208 | u32 ds_ctl1; | 234 | u32 ds_ctl1; |
209 | u32 ds_hw[20]; | 235 | u32 ds_hw[20]; |
210 | union { | ||
211 | struct ath_tx_status tx; | ||
212 | struct ath_rx_status rx; | ||
213 | void *stats; | ||
214 | } ds_us; | ||
215 | void *ds_vdata; | 236 | void *ds_vdata; |
216 | } __packed; | 237 | } __packed; |
217 | 238 | ||
218 | #define ds_txstat ds_us.tx | ||
219 | #define ds_rxstat ds_us.rx | ||
220 | #define ds_stat ds_us.stats | ||
221 | |||
222 | #define ATH9K_TXDESC_CLRDMASK 0x0001 | 239 | #define ATH9K_TXDESC_CLRDMASK 0x0001 |
223 | #define ATH9K_TXDESC_NOACK 0x0002 | 240 | #define ATH9K_TXDESC_NOACK 0x0002 |
224 | #define ATH9K_TXDESC_RTSENA 0x0004 | 241 | #define ATH9K_TXDESC_RTSENA 0x0004 |
@@ -676,7 +693,8 @@ void ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds, | |||
676 | u32 segLen, bool firstSeg, | 693 | u32 segLen, bool firstSeg, |
677 | bool lastSeg, const struct ath_desc *ds0); | 694 | bool lastSeg, const struct ath_desc *ds0); |
678 | void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds); | 695 | void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds); |
679 | int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds); | 696 | int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds, |
697 | struct ath_tx_status *ts); | ||
680 | void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds, | 698 | void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds, |
681 | u32 pktLen, enum ath9k_pkt_type type, u32 txPower, | 699 | u32 pktLen, enum ath9k_pkt_type type, u32 txPower, |
682 | u32 keyIx, enum ath9k_key_type keyType, u32 flags); | 700 | u32 keyIx, enum ath9k_key_type keyType, u32 flags); |
@@ -706,7 +724,7 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type, | |||
706 | bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q); | 724 | bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q); |
707 | bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q); | 725 | bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q); |
708 | int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, | 726 | int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, |
709 | u32 pa, struct ath_desc *nds, u64 tsf); | 727 | struct ath_rx_status *rs, u64 tsf); |
710 | void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, | 728 | void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, |
711 | u32 size, u32 flags); | 729 | u32 size, u32 flags); |
712 | bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set); | 730 | bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set); |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 115e1aeedb59..f7ef11407e27 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -225,7 +225,7 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
225 | 225 | ||
226 | ath_cache_conf_rate(sc, &hw->conf); | 226 | ath_cache_conf_rate(sc, &hw->conf); |
227 | ath_update_txpow(sc); | 227 | ath_update_txpow(sc); |
228 | ath9k_hw_set_interrupts(ah, sc->imask); | 228 | ath9k_hw_set_interrupts(ah, ah->imask); |
229 | 229 | ||
230 | ps_restore: | 230 | ps_restore: |
231 | ath9k_ps_restore(sc); | 231 | ath9k_ps_restore(sc); |
@@ -434,7 +434,7 @@ void ath9k_tasklet(unsigned long data) | |||
434 | ath_gen_timer_isr(sc->sc_ah); | 434 | ath_gen_timer_isr(sc->sc_ah); |
435 | 435 | ||
436 | /* re-enable hardware interrupt */ | 436 | /* re-enable hardware interrupt */ |
437 | ath9k_hw_set_interrupts(ah, sc->imask); | 437 | ath9k_hw_set_interrupts(ah, ah->imask); |
438 | ath9k_ps_restore(sc); | 438 | ath9k_ps_restore(sc); |
439 | } | 439 | } |
440 | 440 | ||
@@ -477,7 +477,7 @@ irqreturn_t ath_isr(int irq, void *dev) | |||
477 | * value to insure we only process bits we requested. | 477 | * value to insure we only process bits we requested. |
478 | */ | 478 | */ |
479 | ath9k_hw_getisr(ah, &status); /* NB: clears ISR too */ | 479 | ath9k_hw_getisr(ah, &status); /* NB: clears ISR too */ |
480 | status &= sc->imask; /* discard unasked-for bits */ | 480 | status &= ah->imask; /* discard unasked-for bits */ |
481 | 481 | ||
482 | /* | 482 | /* |
483 | * If there are no status bits set, then this interrupt was not | 483 | * If there are no status bits set, then this interrupt was not |
@@ -518,7 +518,7 @@ irqreturn_t ath_isr(int irq, void *dev) | |||
518 | * the interrupt. | 518 | * the interrupt. |
519 | */ | 519 | */ |
520 | ath9k_hw_procmibevent(ah); | 520 | ath9k_hw_procmibevent(ah); |
521 | ath9k_hw_set_interrupts(ah, sc->imask); | 521 | ath9k_hw_set_interrupts(ah, ah->imask); |
522 | } | 522 | } |
523 | 523 | ||
524 | if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) | 524 | if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) |
@@ -536,7 +536,7 @@ chip_reset: | |||
536 | 536 | ||
537 | if (sched) { | 537 | if (sched) { |
538 | /* turn off every interrupt except SWBA */ | 538 | /* turn off every interrupt except SWBA */ |
539 | ath9k_hw_set_interrupts(ah, (sc->imask & ATH9K_INT_SWBA)); | 539 | ath9k_hw_set_interrupts(ah, (ah->imask & ATH9K_INT_SWBA)); |
540 | tasklet_schedule(&sc->intr_tq); | 540 | tasklet_schedule(&sc->intr_tq); |
541 | } | 541 | } |
542 | 542 | ||
@@ -887,7 +887,7 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
887 | ath_beacon_config(sc, NULL); /* restart beacons */ | 887 | ath_beacon_config(sc, NULL); /* restart beacons */ |
888 | 888 | ||
889 | /* Re-Enable interrupts */ | 889 | /* Re-Enable interrupts */ |
890 | ath9k_hw_set_interrupts(ah, sc->imask); | 890 | ath9k_hw_set_interrupts(ah, ah->imask); |
891 | 891 | ||
892 | /* Enable LED */ | 892 | /* Enable LED */ |
893 | ath9k_hw_cfg_output(ah, ah->led_pin, | 893 | ath9k_hw_cfg_output(ah, ah->led_pin, |
@@ -977,7 +977,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) | |||
977 | if (sc->sc_flags & SC_OP_BEACONS) | 977 | if (sc->sc_flags & SC_OP_BEACONS) |
978 | ath_beacon_config(sc, NULL); /* restart beacons */ | 978 | ath_beacon_config(sc, NULL); /* restart beacons */ |
979 | 979 | ||
980 | ath9k_hw_set_interrupts(ah, sc->imask); | 980 | ath9k_hw_set_interrupts(ah, ah->imask); |
981 | 981 | ||
982 | if (retry_tx) { | 982 | if (retry_tx) { |
983 | int i; | 983 | int i; |
@@ -1162,23 +1162,23 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
1162 | } | 1162 | } |
1163 | 1163 | ||
1164 | /* Setup our intr mask. */ | 1164 | /* Setup our intr mask. */ |
1165 | sc->imask = ATH9K_INT_RX | ATH9K_INT_TX | 1165 | ah->imask = ATH9K_INT_RX | ATH9K_INT_TX |
1166 | | ATH9K_INT_RXEOL | ATH9K_INT_RXORN | 1166 | | ATH9K_INT_RXEOL | ATH9K_INT_RXORN |
1167 | | ATH9K_INT_FATAL | ATH9K_INT_GLOBAL; | 1167 | | ATH9K_INT_FATAL | ATH9K_INT_GLOBAL; |
1168 | 1168 | ||
1169 | if (ah->caps.hw_caps & ATH9K_HW_CAP_GTT) | 1169 | if (ah->caps.hw_caps & ATH9K_HW_CAP_GTT) |
1170 | sc->imask |= ATH9K_INT_GTT; | 1170 | ah->imask |= ATH9K_INT_GTT; |
1171 | 1171 | ||
1172 | if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) | 1172 | if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) |
1173 | sc->imask |= ATH9K_INT_CST; | 1173 | ah->imask |= ATH9K_INT_CST; |
1174 | 1174 | ||
1175 | ath_cache_conf_rate(sc, &hw->conf); | 1175 | ath_cache_conf_rate(sc, &hw->conf); |
1176 | 1176 | ||
1177 | sc->sc_flags &= ~SC_OP_INVALID; | 1177 | sc->sc_flags &= ~SC_OP_INVALID; |
1178 | 1178 | ||
1179 | /* Disable BMISS interrupt when we're not associated */ | 1179 | /* Disable BMISS interrupt when we're not associated */ |
1180 | sc->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS); | 1180 | ah->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS); |
1181 | ath9k_hw_set_interrupts(ah, sc->imask); | 1181 | ath9k_hw_set_interrupts(ah, ah->imask); |
1182 | 1182 | ||
1183 | ieee80211_wake_queues(hw); | 1183 | ieee80211_wake_queues(hw); |
1184 | 1184 | ||
@@ -1372,14 +1372,15 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
1372 | { | 1372 | { |
1373 | struct ath_wiphy *aphy = hw->priv; | 1373 | struct ath_wiphy *aphy = hw->priv; |
1374 | struct ath_softc *sc = aphy->sc; | 1374 | struct ath_softc *sc = aphy->sc; |
1375 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1375 | struct ath_hw *ah = sc->sc_ah; |
1376 | struct ath_common *common = ath9k_hw_common(ah); | ||
1376 | struct ath_vif *avp = (void *)vif->drv_priv; | 1377 | struct ath_vif *avp = (void *)vif->drv_priv; |
1377 | enum nl80211_iftype ic_opmode = NL80211_IFTYPE_UNSPECIFIED; | 1378 | enum nl80211_iftype ic_opmode = NL80211_IFTYPE_UNSPECIFIED; |
1378 | int ret = 0; | 1379 | int ret = 0; |
1379 | 1380 | ||
1380 | mutex_lock(&sc->mutex); | 1381 | mutex_lock(&sc->mutex); |
1381 | 1382 | ||
1382 | if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) && | 1383 | if (!(ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) && |
1383 | sc->nvifs > 0) { | 1384 | sc->nvifs > 0) { |
1384 | ret = -ENOBUFS; | 1385 | ret = -ENOBUFS; |
1385 | goto out; | 1386 | goto out; |
@@ -1414,19 +1415,19 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
1414 | 1415 | ||
1415 | sc->nvifs++; | 1416 | sc->nvifs++; |
1416 | 1417 | ||
1417 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) | 1418 | if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) |
1418 | ath9k_set_bssid_mask(hw); | 1419 | ath9k_set_bssid_mask(hw); |
1419 | 1420 | ||
1420 | if (sc->nvifs > 1) | 1421 | if (sc->nvifs > 1) |
1421 | goto out; /* skip global settings for secondary vif */ | 1422 | goto out; /* skip global settings for secondary vif */ |
1422 | 1423 | ||
1423 | if (ic_opmode == NL80211_IFTYPE_AP) { | 1424 | if (ic_opmode == NL80211_IFTYPE_AP) { |
1424 | ath9k_hw_set_tsfadjust(sc->sc_ah, 1); | 1425 | ath9k_hw_set_tsfadjust(ah, 1); |
1425 | sc->sc_flags |= SC_OP_TSF_RESET; | 1426 | sc->sc_flags |= SC_OP_TSF_RESET; |
1426 | } | 1427 | } |
1427 | 1428 | ||
1428 | /* Set the device opmode */ | 1429 | /* Set the device opmode */ |
1429 | sc->sc_ah->opmode = ic_opmode; | 1430 | ah->opmode = ic_opmode; |
1430 | 1431 | ||
1431 | /* | 1432 | /* |
1432 | * Enable MIB interrupts when there are hardware phy counters. | 1433 | * Enable MIB interrupts when there are hardware phy counters. |
@@ -1435,11 +1436,11 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
1435 | if ((vif->type == NL80211_IFTYPE_STATION) || | 1436 | if ((vif->type == NL80211_IFTYPE_STATION) || |
1436 | (vif->type == NL80211_IFTYPE_ADHOC) || | 1437 | (vif->type == NL80211_IFTYPE_ADHOC) || |
1437 | (vif->type == NL80211_IFTYPE_MESH_POINT)) { | 1438 | (vif->type == NL80211_IFTYPE_MESH_POINT)) { |
1438 | sc->imask |= ATH9K_INT_MIB; | 1439 | ah->imask |= ATH9K_INT_MIB; |
1439 | sc->imask |= ATH9K_INT_TSFOOR; | 1440 | ah->imask |= ATH9K_INT_TSFOOR; |
1440 | } | 1441 | } |
1441 | 1442 | ||
1442 | ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); | 1443 | ath9k_hw_set_interrupts(ah, ah->imask); |
1443 | 1444 | ||
1444 | if (vif->type == NL80211_IFTYPE_AP || | 1445 | if (vif->type == NL80211_IFTYPE_AP || |
1445 | vif->type == NL80211_IFTYPE_ADHOC || | 1446 | vif->type == NL80211_IFTYPE_ADHOC || |
@@ -1495,15 +1496,16 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, | |||
1495 | 1496 | ||
1496 | void ath9k_enable_ps(struct ath_softc *sc) | 1497 | void ath9k_enable_ps(struct ath_softc *sc) |
1497 | { | 1498 | { |
1499 | struct ath_hw *ah = sc->sc_ah; | ||
1500 | |||
1498 | sc->ps_enabled = true; | 1501 | sc->ps_enabled = true; |
1499 | if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { | 1502 | if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { |
1500 | if ((sc->imask & ATH9K_INT_TIM_TIMER) == 0) { | 1503 | if ((ah->imask & ATH9K_INT_TIM_TIMER) == 0) { |
1501 | sc->imask |= ATH9K_INT_TIM_TIMER; | 1504 | ah->imask |= ATH9K_INT_TIM_TIMER; |
1502 | ath9k_hw_set_interrupts(sc->sc_ah, | 1505 | ath9k_hw_set_interrupts(ah, ah->imask); |
1503 | sc->imask); | ||
1504 | } | 1506 | } |
1505 | } | 1507 | } |
1506 | ath9k_hw_setrxabort(sc->sc_ah, 1); | 1508 | ath9k_hw_setrxabort(ah, 1); |
1507 | } | 1509 | } |
1508 | 1510 | ||
1509 | static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | 1511 | static int ath9k_config(struct ieee80211_hw *hw, u32 changed) |
@@ -1579,10 +1581,10 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
1579 | PS_WAIT_FOR_CAB | | 1581 | PS_WAIT_FOR_CAB | |
1580 | PS_WAIT_FOR_PSPOLL_DATA | | 1582 | PS_WAIT_FOR_PSPOLL_DATA | |
1581 | PS_WAIT_FOR_TX_ACK); | 1583 | PS_WAIT_FOR_TX_ACK); |
1582 | if (sc->imask & ATH9K_INT_TIM_TIMER) { | 1584 | if (ah->imask & ATH9K_INT_TIM_TIMER) { |
1583 | sc->imask &= ~ATH9K_INT_TIM_TIMER; | 1585 | ah->imask &= ~ATH9K_INT_TIM_TIMER; |
1584 | ath9k_hw_set_interrupts(sc->sc_ah, | 1586 | ath9k_hw_set_interrupts(sc->sc_ah, |
1585 | sc->imask); | 1587 | ah->imask); |
1586 | } | 1588 | } |
1587 | } | 1589 | } |
1588 | } | 1590 | } |
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 9441c6718a30..1ec836cf1c0d 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c | |||
@@ -88,6 +88,7 @@ static void ath_pci_bt_coex_prep(struct ath_common *common) | |||
88 | } | 88 | } |
89 | 89 | ||
90 | static const struct ath_bus_ops ath_pci_bus_ops = { | 90 | static const struct ath_bus_ops ath_pci_bus_ops = { |
91 | .ath_bus_type = ATH_PCI, | ||
91 | .read_cachesize = ath_pci_read_cachesize, | 92 | .read_cachesize = ath_pci_read_cachesize, |
92 | .eeprom_read = ath_pci_eeprom_read, | 93 | .eeprom_read = ath_pci_eeprom_read, |
93 | .bt_coex_prep = ath_pci_bt_coex_prep, | 94 | .bt_coex_prep = ath_pci_bt_coex_prep, |
diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h index 0999a495fd46..0132e4c9a9f9 100644 --- a/drivers/net/wireless/ath/ath9k/phy.h +++ b/drivers/net/wireless/ath/ath9k/phy.h | |||
@@ -503,6 +503,8 @@ bool ath9k_hw_set_rf_regs(struct ath_hw *ah, | |||
503 | #define AR_PHY_TX_PWRCTRL_ERR_EST_MODE_S 24 | 503 | #define AR_PHY_TX_PWRCTRL_ERR_EST_MODE_S 24 |
504 | 504 | ||
505 | #define AR_PHY_TX_PWRCTRL7 0xa274 | 505 | #define AR_PHY_TX_PWRCTRL7 0xa274 |
506 | #define AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX 0x0007E000 | ||
507 | #define AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX_S 13 | ||
506 | #define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN 0x01F80000 | 508 | #define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN 0x01F80000 |
507 | #define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN_S 19 | 509 | #define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN_S 19 |
508 | 510 | ||
@@ -513,8 +515,16 @@ bool ath9k_hw_set_rf_regs(struct ath_hw *ah, | |||
513 | #define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL_S 31 | 515 | #define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL_S 31 |
514 | 516 | ||
515 | #define AR_PHY_TX_GAIN_TBL1 0xa300 | 517 | #define AR_PHY_TX_GAIN_TBL1 0xa300 |
516 | #define AR_PHY_TX_GAIN 0x0007F000 | 518 | #define AR_PHY_TX_GAIN_CLC 0x0000001E |
517 | #define AR_PHY_TX_GAIN_S 12 | 519 | #define AR_PHY_TX_GAIN_CLC_S 1 |
520 | #define AR_PHY_TX_GAIN 0x0007F000 | ||
521 | #define AR_PHY_TX_GAIN_S 12 | ||
522 | |||
523 | #define AR_PHY_CLC_TBL1 0xa35c | ||
524 | #define AR_PHY_CLC_I0 0x07ff0000 | ||
525 | #define AR_PHY_CLC_I0_S 16 | ||
526 | #define AR_PHY_CLC_Q0 0x0000ffd0 | ||
527 | #define AR_PHY_CLC_Q0_S 5 | ||
518 | 528 | ||
519 | #define AR_PHY_CH0_TX_PWRCTRL11 0xa398 | 529 | #define AR_PHY_CH0_TX_PWRCTRL11 0xa398 |
520 | #define AR_PHY_CH1_TX_PWRCTRL11 0xb398 | 530 | #define AR_PHY_CH1_TX_PWRCTRL11 0xb398 |
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 0e79e58cf4c9..3c4b5d2d9e16 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c | |||
@@ -1226,8 +1226,12 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, | |||
1226 | long_retry = rate->count - 1; | 1226 | long_retry = rate->count - 1; |
1227 | } | 1227 | } |
1228 | 1228 | ||
1229 | if (!priv_sta || !ieee80211_is_data(fc) || | 1229 | if (!priv_sta || !ieee80211_is_data(fc)) |
1230 | !(tx_info->pad[0] & ATH_TX_INFO_UPDATE_RC)) | 1230 | return; |
1231 | |||
1232 | /* This packet was aggregated but doesn't carry status info */ | ||
1233 | if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && | ||
1234 | !(tx_info->flags & IEEE80211_TX_STAT_AMPDU)) | ||
1231 | return; | 1235 | return; |
1232 | 1236 | ||
1233 | if (tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) | 1237 | if (tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) |
diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h index 4f6d6fd442f4..3d8d40cdc99e 100644 --- a/drivers/net/wireless/ath/ath9k/rc.h +++ b/drivers/net/wireless/ath/ath9k/rc.h | |||
@@ -110,8 +110,8 @@ struct ath_rate_table { | |||
110 | int rate_cnt; | 110 | int rate_cnt; |
111 | int mcs_start; | 111 | int mcs_start; |
112 | struct { | 112 | struct { |
113 | int valid; | 113 | u8 valid; |
114 | int valid_single_stream; | 114 | u8 valid_single_stream; |
115 | u8 phy; | 115 | u8 phy; |
116 | u32 ratekbps; | 116 | u32 ratekbps; |
117 | u32 user_ratekbps; | 117 | u32 user_ratekbps; |
@@ -172,14 +172,13 @@ struct ath_rate_priv { | |||
172 | 172 | ||
173 | #define ATH_TX_INFO_FRAME_TYPE_INTERNAL (1 << 0) | 173 | #define ATH_TX_INFO_FRAME_TYPE_INTERNAL (1 << 0) |
174 | #define ATH_TX_INFO_FRAME_TYPE_PAUSE (1 << 1) | 174 | #define ATH_TX_INFO_FRAME_TYPE_PAUSE (1 << 1) |
175 | #define ATH_TX_INFO_UPDATE_RC (1 << 2) | ||
176 | #define ATH_TX_INFO_XRETRY (1 << 3) | 175 | #define ATH_TX_INFO_XRETRY (1 << 3) |
177 | #define ATH_TX_INFO_UNDERRUN (1 << 4) | 176 | #define ATH_TX_INFO_UNDERRUN (1 << 4) |
178 | 177 | ||
179 | enum ath9k_internal_frame_type { | 178 | enum ath9k_internal_frame_type { |
180 | ATH9K_NOT_INTERNAL, | 179 | ATH9K_IFT_NOT_INTERNAL, |
181 | ATH9K_INT_PAUSE, | 180 | ATH9K_IFT_PAUSE, |
182 | ATH9K_INT_UNPAUSE | 181 | ATH9K_IFT_UNPAUSE |
183 | }; | 182 | }; |
184 | 183 | ||
185 | int ath_rate_control_register(void); | 184 | int ath_rate_control_register(void); |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 1ca42e5148c8..94560e2fe376 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -477,7 +477,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
477 | 477 | ||
478 | struct ath_buf *bf; | 478 | struct ath_buf *bf; |
479 | struct ath_desc *ds; | 479 | struct ath_desc *ds; |
480 | struct ath_rx_status *rx_stats; | ||
481 | struct sk_buff *skb = NULL, *requeue_skb; | 480 | struct sk_buff *skb = NULL, *requeue_skb; |
482 | struct ieee80211_rx_status *rxs; | 481 | struct ieee80211_rx_status *rxs; |
483 | struct ath_hw *ah = sc->sc_ah; | 482 | struct ath_hw *ah = sc->sc_ah; |
@@ -491,6 +490,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
491 | struct ieee80211_hdr *hdr; | 490 | struct ieee80211_hdr *hdr; |
492 | int retval; | 491 | int retval; |
493 | bool decrypt_error = false; | 492 | bool decrypt_error = false; |
493 | struct ath_rx_status rs; | ||
494 | 494 | ||
495 | spin_lock_bh(&sc->rx.rxbuflock); | 495 | spin_lock_bh(&sc->rx.rxbuflock); |
496 | 496 | ||
@@ -518,14 +518,14 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
518 | * on. All this is necessary because of our use of | 518 | * on. All this is necessary because of our use of |
519 | * a self-linked list to avoid rx overruns. | 519 | * a self-linked list to avoid rx overruns. |
520 | */ | 520 | */ |
521 | retval = ath9k_hw_rxprocdesc(ah, ds, | 521 | memset(&rs, 0, sizeof(rs)); |
522 | bf->bf_daddr, | 522 | retval = ath9k_hw_rxprocdesc(ah, ds, &rs, 0); |
523 | PA2DESC(sc, ds->ds_link), | ||
524 | 0); | ||
525 | if (retval == -EINPROGRESS) { | 523 | if (retval == -EINPROGRESS) { |
524 | struct ath_rx_status trs; | ||
526 | struct ath_buf *tbf; | 525 | struct ath_buf *tbf; |
527 | struct ath_desc *tds; | 526 | struct ath_desc *tds; |
528 | 527 | ||
528 | memset(&trs, 0, sizeof(trs)); | ||
529 | if (list_is_last(&bf->list, &sc->rx.rxbuf)) { | 529 | if (list_is_last(&bf->list, &sc->rx.rxbuf)) { |
530 | sc->rx.rxlink = NULL; | 530 | sc->rx.rxlink = NULL; |
531 | break; | 531 | break; |
@@ -545,8 +545,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
545 | */ | 545 | */ |
546 | 546 | ||
547 | tds = tbf->bf_desc; | 547 | tds = tbf->bf_desc; |
548 | retval = ath9k_hw_rxprocdesc(ah, tds, tbf->bf_daddr, | 548 | retval = ath9k_hw_rxprocdesc(ah, tds, &trs, 0); |
549 | PA2DESC(sc, tds->ds_link), 0); | ||
550 | if (retval == -EINPROGRESS) { | 549 | if (retval == -EINPROGRESS) { |
551 | break; | 550 | break; |
552 | } | 551 | } |
@@ -569,9 +568,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
569 | rxs = IEEE80211_SKB_RXCB(skb); | 568 | rxs = IEEE80211_SKB_RXCB(skb); |
570 | 569 | ||
571 | hw = ath_get_virt_hw(sc, hdr); | 570 | hw = ath_get_virt_hw(sc, hdr); |
572 | rx_stats = &ds->ds_rxstat; | ||
573 | 571 | ||
574 | ath_debug_stat_rx(sc, bf); | 572 | ath_debug_stat_rx(sc, &rs); |
575 | 573 | ||
576 | /* | 574 | /* |
577 | * If we're asked to flush receive queue, directly | 575 | * If we're asked to flush receive queue, directly |
@@ -580,7 +578,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
580 | if (flush) | 578 | if (flush) |
581 | goto requeue; | 579 | goto requeue; |
582 | 580 | ||
583 | retval = ath9k_cmn_rx_skb_preprocess(common, hw, skb, rx_stats, | 581 | retval = ath9k_cmn_rx_skb_preprocess(common, hw, skb, &rs, |
584 | rxs, &decrypt_error); | 582 | rxs, &decrypt_error); |
585 | if (retval) | 583 | if (retval) |
586 | goto requeue; | 584 | goto requeue; |
@@ -601,9 +599,9 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
601 | common->rx_bufsize, | 599 | common->rx_bufsize, |
602 | DMA_FROM_DEVICE); | 600 | DMA_FROM_DEVICE); |
603 | 601 | ||
604 | skb_put(skb, rx_stats->rs_datalen); | 602 | skb_put(skb, rs.rs_datalen); |
605 | 603 | ||
606 | ath9k_cmn_rx_skb_postprocess(common, skb, rx_stats, | 604 | ath9k_cmn_rx_skb_postprocess(common, skb, &rs, |
607 | rxs, decrypt_error); | 605 | rxs, decrypt_error); |
608 | 606 | ||
609 | /* We will now give hardware our shiny new allocated skb */ | 607 | /* We will now give hardware our shiny new allocated skb */ |
@@ -626,9 +624,9 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
626 | * change the default rx antenna if rx diversity chooses the | 624 | * change the default rx antenna if rx diversity chooses the |
627 | * other antenna 3 times in a row. | 625 | * other antenna 3 times in a row. |
628 | */ | 626 | */ |
629 | if (sc->rx.defant != ds->ds_rxstat.rs_antenna) { | 627 | if (sc->rx.defant != rs.rs_antenna) { |
630 | if (++sc->rx.rxotherant >= 3) | 628 | if (++sc->rx.rxotherant >= 3) |
631 | ath_setdefantenna(sc, rx_stats->rs_antenna); | 629 | ath_setdefantenna(sc, rs.rs_antenna); |
632 | } else { | 630 | } else { |
633 | sc->rx.rxotherant = 0; | 631 | sc->rx.rxotherant = 0; |
634 | } | 632 | } |
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 72cfa8ebd9ae..7e36ad7421b7 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h | |||
@@ -679,7 +679,7 @@ | |||
679 | 679 | ||
680 | #define AR_WA 0x4004 | 680 | #define AR_WA 0x4004 |
681 | #define AR_WA_D3_L1_DISABLE (1 << 14) | 681 | #define AR_WA_D3_L1_DISABLE (1 << 14) |
682 | #define AR9285_WA_DEFAULT 0x004a05cb | 682 | #define AR9285_WA_DEFAULT 0x004a050b |
683 | #define AR9280_WA_DEFAULT 0x0040073b | 683 | #define AR9280_WA_DEFAULT 0x0040073b |
684 | #define AR_WA_DEFAULT 0x0000073f | 684 | #define AR_WA_DEFAULT 0x0000073f |
685 | 685 | ||
@@ -845,6 +845,10 @@ | |||
845 | (AR_SREV_9271(_ah) && \ | 845 | (AR_SREV_9271(_ah) && \ |
846 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9271_11)) | 846 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9271_11)) |
847 | 847 | ||
848 | #define AR_SREV_9285E_20(_ah) \ | ||
849 | (AR_SREV_9285_12_OR_LATER(_ah) && \ | ||
850 | ((REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1)) | ||
851 | |||
848 | #define AR_RADIO_SREV_MAJOR 0xf0 | 852 | #define AR_RADIO_SREV_MAJOR 0xf0 |
849 | #define AR_RAD5133_SREV_MAJOR 0xc0 | 853 | #define AR_RAD5133_SREV_MAJOR 0xc0 |
850 | #define AR_RAD2133_SREV_MAJOR 0xd0 | 854 | #define AR_RAD2133_SREV_MAJOR 0xd0 |
@@ -940,6 +944,7 @@ enum { | |||
940 | #define AR928X_NUM_GPIO 10 | 944 | #define AR928X_NUM_GPIO 10 |
941 | #define AR9285_NUM_GPIO 12 | 945 | #define AR9285_NUM_GPIO 12 |
942 | #define AR9287_NUM_GPIO 11 | 946 | #define AR9287_NUM_GPIO 11 |
947 | #define AR9271_NUM_GPIO 16 | ||
943 | 948 | ||
944 | #define AR_GPIO_IN_OUT 0x4048 | 949 | #define AR_GPIO_IN_OUT 0x4048 |
945 | #define AR_GPIO_IN_VAL 0x0FFFC000 | 950 | #define AR_GPIO_IN_VAL 0x0FFFC000 |
@@ -950,6 +955,8 @@ enum { | |||
950 | #define AR9285_GPIO_IN_VAL_S 12 | 955 | #define AR9285_GPIO_IN_VAL_S 12 |
951 | #define AR9287_GPIO_IN_VAL 0x003FF800 | 956 | #define AR9287_GPIO_IN_VAL 0x003FF800 |
952 | #define AR9287_GPIO_IN_VAL_S 11 | 957 | #define AR9287_GPIO_IN_VAL_S 11 |
958 | #define AR9271_GPIO_IN_VAL 0xFFFF0000 | ||
959 | #define AR9271_GPIO_IN_VAL_S 16 | ||
953 | 960 | ||
954 | #define AR_GPIO_OE_OUT 0x404c | 961 | #define AR_GPIO_OE_OUT 0x404c |
955 | #define AR_GPIO_OE_OUT_DRV 0x3 | 962 | #define AR_GPIO_OE_OUT_DRV 0x3 |
@@ -1178,6 +1185,13 @@ enum { | |||
1178 | #define AR9285_AN_RF2G4_DB2_4 0x00003800 | 1185 | #define AR9285_AN_RF2G4_DB2_4 0x00003800 |
1179 | #define AR9285_AN_RF2G4_DB2_4_S 11 | 1186 | #define AR9285_AN_RF2G4_DB2_4_S 11 |
1180 | 1187 | ||
1188 | #define AR9285_RF2G5 0x7830 | ||
1189 | #define AR9285_RF2G5_IC50TX 0xfffff8ff | ||
1190 | #define AR9285_RF2G5_IC50TX_SET 0x00000400 | ||
1191 | #define AR9285_RF2G5_IC50TX_XE_SET 0x00000500 | ||
1192 | #define AR9285_RF2G5_IC50TX_CLEAR 0x00000700 | ||
1193 | #define AR9285_RF2G5_IC50TX_CLEAR_S 8 | ||
1194 | |||
1181 | /* AR9271 : 0x7828, 0x782c different setting from AR9285 */ | 1195 | /* AR9271 : 0x7828, 0x782c different setting from AR9285 */ |
1182 | #define AR9271_AN_RF2G3_OB_cck 0x001C0000 | 1196 | #define AR9271_AN_RF2G3_OB_cck 0x001C0000 |
1183 | #define AR9271_AN_RF2G3_OB_cck_S 18 | 1197 | #define AR9271_AN_RF2G3_OB_cck_S 18 |
diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c index a43fbf84dab9..e95aaa3f18f3 100644 --- a/drivers/net/wireless/ath/ath9k/virtual.c +++ b/drivers/net/wireless/ath/ath9k/virtual.c | |||
@@ -218,7 +218,7 @@ static int ath9k_send_nullfunc(struct ath_wiphy *aphy, | |||
218 | 218 | ||
219 | memset(&txctl, 0, sizeof(struct ath_tx_control)); | 219 | memset(&txctl, 0, sizeof(struct ath_tx_control)); |
220 | txctl.txq = &sc->tx.txq[sc->tx.hwq_map[ATH9K_WME_AC_VO]]; | 220 | txctl.txq = &sc->tx.txq[sc->tx.hwq_map[ATH9K_WME_AC_VO]]; |
221 | txctl.frame_type = ps ? ATH9K_INT_PAUSE : ATH9K_INT_UNPAUSE; | 221 | txctl.frame_type = ps ? ATH9K_IFT_PAUSE : ATH9K_IFT_UNPAUSE; |
222 | 222 | ||
223 | if (ath_tx_start(aphy->hw, skb, &txctl) != 0) | 223 | if (ath_tx_start(aphy->hw, skb, &txctl) != 0) |
224 | goto exit; | 224 | goto exit; |
diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c new file mode 100644 index 000000000000..818dea0164ec --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/wmi.c | |||
@@ -0,0 +1,319 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include "htc.h" | ||
18 | |||
19 | static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd) | ||
20 | { | ||
21 | switch (wmi_cmd) { | ||
22 | case WMI_ECHO_CMDID: | ||
23 | return "WMI_ECHO_CMDID"; | ||
24 | case WMI_ACCESS_MEMORY_CMDID: | ||
25 | return "WMI_ACCESS_MEMORY_CMDID"; | ||
26 | case WMI_DISABLE_INTR_CMDID: | ||
27 | return "WMI_DISABLE_INTR_CMDID"; | ||
28 | case WMI_ENABLE_INTR_CMDID: | ||
29 | return "WMI_ENABLE_INTR_CMDID"; | ||
30 | case WMI_RX_LINK_CMDID: | ||
31 | return "WMI_RX_LINK_CMDID"; | ||
32 | case WMI_ATH_INIT_CMDID: | ||
33 | return "WMI_ATH_INIT_CMDID"; | ||
34 | case WMI_ABORT_TXQ_CMDID: | ||
35 | return "WMI_ABORT_TXQ_CMDID"; | ||
36 | case WMI_STOP_TX_DMA_CMDID: | ||
37 | return "WMI_STOP_TX_DMA_CMDID"; | ||
38 | case WMI_STOP_DMA_RECV_CMDID: | ||
39 | return "WMI_STOP_DMA_RECV_CMDID"; | ||
40 | case WMI_ABORT_TX_DMA_CMDID: | ||
41 | return "WMI_ABORT_TX_DMA_CMDID"; | ||
42 | case WMI_DRAIN_TXQ_CMDID: | ||
43 | return "WMI_DRAIN_TXQ_CMDID"; | ||
44 | case WMI_DRAIN_TXQ_ALL_CMDID: | ||
45 | return "WMI_DRAIN_TXQ_ALL_CMDID"; | ||
46 | case WMI_START_RECV_CMDID: | ||
47 | return "WMI_START_RECV_CMDID"; | ||
48 | case WMI_STOP_RECV_CMDID: | ||
49 | return "WMI_STOP_RECV_CMDID"; | ||
50 | case WMI_FLUSH_RECV_CMDID: | ||
51 | return "WMI_FLUSH_RECV_CMDID"; | ||
52 | case WMI_SET_MODE_CMDID: | ||
53 | return "WMI_SET_MODE_CMDID"; | ||
54 | case WMI_RESET_CMDID: | ||
55 | return "WMI_RESET_CMDID"; | ||
56 | case WMI_NODE_CREATE_CMDID: | ||
57 | return "WMI_NODE_CREATE_CMDID"; | ||
58 | case WMI_NODE_REMOVE_CMDID: | ||
59 | return "WMI_NODE_REMOVE_CMDID"; | ||
60 | case WMI_VAP_REMOVE_CMDID: | ||
61 | return "WMI_VAP_REMOVE_CMDID"; | ||
62 | case WMI_VAP_CREATE_CMDID: | ||
63 | return "WMI_VAP_CREATE_CMDID"; | ||
64 | case WMI_BEACON_UPDATE_CMDID: | ||
65 | return "WMI_BEACON_UPDATE_CMDID"; | ||
66 | case WMI_REG_READ_CMDID: | ||
67 | return "WMI_REG_READ_CMDID"; | ||
68 | case WMI_REG_WRITE_CMDID: | ||
69 | return "WMI_REG_WRITE_CMDID"; | ||
70 | case WMI_RC_STATE_CHANGE_CMDID: | ||
71 | return "WMI_RC_STATE_CHANGE_CMDID"; | ||
72 | case WMI_RC_RATE_UPDATE_CMDID: | ||
73 | return "WMI_RC_RATE_UPDATE_CMDID"; | ||
74 | case WMI_DEBUG_INFO_CMDID: | ||
75 | return "WMI_DEBUG_INFO_CMDID"; | ||
76 | case WMI_HOST_ATTACH: | ||
77 | return "WMI_HOST_ATTACH"; | ||
78 | case WMI_TARGET_IC_UPDATE_CMDID: | ||
79 | return "WMI_TARGET_IC_UPDATE_CMDID"; | ||
80 | case WMI_TGT_STATS_CMDID: | ||
81 | return "WMI_TGT_STATS_CMDID"; | ||
82 | case WMI_TX_AGGR_ENABLE_CMDID: | ||
83 | return "WMI_TX_AGGR_ENABLE_CMDID"; | ||
84 | case WMI_TGT_DETACH_CMDID: | ||
85 | return "WMI_TGT_DETACH_CMDID"; | ||
86 | case WMI_TGT_TXQ_ENABLE_CMDID: | ||
87 | return "WMI_TGT_TXQ_ENABLE_CMDID"; | ||
88 | } | ||
89 | |||
90 | return "Bogus"; | ||
91 | } | ||
92 | |||
93 | struct wmi *ath9k_init_wmi(struct ath9k_htc_priv *priv) | ||
94 | { | ||
95 | struct wmi *wmi; | ||
96 | |||
97 | wmi = kzalloc(sizeof(struct wmi), GFP_KERNEL); | ||
98 | if (!wmi) | ||
99 | return NULL; | ||
100 | |||
101 | wmi->drv_priv = priv; | ||
102 | wmi->stopped = false; | ||
103 | mutex_init(&wmi->op_mutex); | ||
104 | init_completion(&wmi->cmd_wait); | ||
105 | |||
106 | return wmi; | ||
107 | } | ||
108 | |||
109 | void ath9k_deinit_wmi(struct ath9k_htc_priv *priv) | ||
110 | { | ||
111 | struct wmi *wmi = priv->wmi; | ||
112 | |||
113 | mutex_lock(&wmi->op_mutex); | ||
114 | wmi->stopped = true; | ||
115 | mutex_unlock(&wmi->op_mutex); | ||
116 | |||
117 | kfree(priv->wmi); | ||
118 | } | ||
119 | |||
120 | void ath9k_wmi_tasklet(unsigned long data) | ||
121 | { | ||
122 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; | ||
123 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
124 | struct wmi_cmd_hdr *hdr; | ||
125 | struct wmi_swba *swba_hdr; | ||
126 | enum wmi_event_id event; | ||
127 | struct sk_buff *skb; | ||
128 | void *wmi_event; | ||
129 | unsigned long flags; | ||
130 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS | ||
131 | u32 txrate; | ||
132 | #endif | ||
133 | |||
134 | spin_lock_irqsave(&priv->wmi->wmi_lock, flags); | ||
135 | skb = priv->wmi->wmi_skb; | ||
136 | spin_unlock_irqrestore(&priv->wmi->wmi_lock, flags); | ||
137 | |||
138 | hdr = (struct wmi_cmd_hdr *) skb->data; | ||
139 | event = be16_to_cpu(hdr->command_id); | ||
140 | wmi_event = skb_pull(skb, sizeof(struct wmi_cmd_hdr)); | ||
141 | |||
142 | ath_print(common, ATH_DBG_WMI, | ||
143 | "WMI Event: 0x%x\n", event); | ||
144 | |||
145 | switch (event) { | ||
146 | case WMI_TGT_RDY_EVENTID: | ||
147 | break; | ||
148 | case WMI_SWBA_EVENTID: | ||
149 | swba_hdr = (struct wmi_swba *) wmi_event; | ||
150 | ath9k_htc_swba(priv, swba_hdr->beacon_pending); | ||
151 | break; | ||
152 | case WMI_FATAL_EVENTID: | ||
153 | break; | ||
154 | case WMI_TXTO_EVENTID: | ||
155 | break; | ||
156 | case WMI_BMISS_EVENTID: | ||
157 | break; | ||
158 | case WMI_WLAN_TXCOMP_EVENTID: | ||
159 | break; | ||
160 | case WMI_DELBA_EVENTID: | ||
161 | break; | ||
162 | case WMI_TXRATE_EVENTID: | ||
163 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS | ||
164 | txrate = ((struct wmi_event_txrate *)wmi_event)->txrate; | ||
165 | priv->debug.txrate = be32_to_cpu(txrate); | ||
166 | #endif | ||
167 | break; | ||
168 | default: | ||
169 | break; | ||
170 | } | ||
171 | |||
172 | dev_kfree_skb_any(skb); | ||
173 | } | ||
174 | |||
175 | static void ath9k_wmi_rsp_callback(struct wmi *wmi, struct sk_buff *skb) | ||
176 | { | ||
177 | skb_pull(skb, sizeof(struct wmi_cmd_hdr)); | ||
178 | |||
179 | if (wmi->cmd_rsp_buf != NULL && wmi->cmd_rsp_len != 0) | ||
180 | memcpy(wmi->cmd_rsp_buf, skb->data, wmi->cmd_rsp_len); | ||
181 | |||
182 | complete(&wmi->cmd_wait); | ||
183 | } | ||
184 | |||
185 | static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb, | ||
186 | enum htc_endpoint_id epid) | ||
187 | { | ||
188 | struct wmi *wmi = (struct wmi *) priv; | ||
189 | struct wmi_cmd_hdr *hdr; | ||
190 | u16 cmd_id; | ||
191 | |||
192 | if (unlikely(wmi->stopped)) | ||
193 | goto free_skb; | ||
194 | |||
195 | hdr = (struct wmi_cmd_hdr *) skb->data; | ||
196 | cmd_id = be16_to_cpu(hdr->command_id); | ||
197 | |||
198 | if (cmd_id & 0x1000) { | ||
199 | spin_lock(&wmi->wmi_lock); | ||
200 | wmi->wmi_skb = skb; | ||
201 | spin_unlock(&wmi->wmi_lock); | ||
202 | tasklet_schedule(&wmi->drv_priv->wmi_tasklet); | ||
203 | return; | ||
204 | } | ||
205 | |||
206 | /* WMI command response */ | ||
207 | ath9k_wmi_rsp_callback(wmi, skb); | ||
208 | |||
209 | free_skb: | ||
210 | dev_kfree_skb_any(skb); | ||
211 | } | ||
212 | |||
213 | static void ath9k_wmi_ctrl_tx(void *priv, struct sk_buff *skb, | ||
214 | enum htc_endpoint_id epid, bool txok) | ||
215 | { | ||
216 | dev_kfree_skb_any(skb); | ||
217 | } | ||
218 | |||
219 | int ath9k_wmi_connect(struct htc_target *htc, struct wmi *wmi, | ||
220 | enum htc_endpoint_id *wmi_ctrl_epid) | ||
221 | { | ||
222 | struct htc_service_connreq connect; | ||
223 | int ret; | ||
224 | |||
225 | wmi->htc = htc; | ||
226 | |||
227 | memset(&connect, 0, sizeof(connect)); | ||
228 | |||
229 | connect.ep_callbacks.priv = wmi; | ||
230 | connect.ep_callbacks.tx = ath9k_wmi_ctrl_tx; | ||
231 | connect.ep_callbacks.rx = ath9k_wmi_ctrl_rx; | ||
232 | connect.service_id = WMI_CONTROL_SVC; | ||
233 | |||
234 | ret = htc_connect_service(htc, &connect, &wmi->ctrl_epid); | ||
235 | if (ret) | ||
236 | return ret; | ||
237 | |||
238 | *wmi_ctrl_epid = wmi->ctrl_epid; | ||
239 | |||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | static int ath9k_wmi_cmd_issue(struct wmi *wmi, | ||
244 | struct sk_buff *skb, | ||
245 | enum wmi_cmd_id cmd, u16 len) | ||
246 | { | ||
247 | struct wmi_cmd_hdr *hdr; | ||
248 | |||
249 | hdr = (struct wmi_cmd_hdr *) skb_push(skb, sizeof(struct wmi_cmd_hdr)); | ||
250 | hdr->command_id = cpu_to_be16(cmd); | ||
251 | hdr->seq_no = cpu_to_be16(++wmi->tx_seq_id); | ||
252 | |||
253 | return htc_send(wmi->htc, skb, wmi->ctrl_epid, NULL); | ||
254 | } | ||
255 | |||
256 | int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, | ||
257 | u8 *cmd_buf, u32 cmd_len, | ||
258 | u8 *rsp_buf, u32 rsp_len, | ||
259 | u32 timeout) | ||
260 | { | ||
261 | struct ath_hw *ah = wmi->drv_priv->ah; | ||
262 | struct ath_common *common = ath9k_hw_common(ah); | ||
263 | u16 headroom = sizeof(struct htc_frame_hdr) + | ||
264 | sizeof(struct wmi_cmd_hdr); | ||
265 | struct sk_buff *skb; | ||
266 | u8 *data; | ||
267 | int time_left, ret = 0; | ||
268 | |||
269 | if (!wmi) | ||
270 | return -EINVAL; | ||
271 | |||
272 | skb = dev_alloc_skb(headroom + cmd_len); | ||
273 | if (!skb) | ||
274 | return -ENOMEM; | ||
275 | |||
276 | skb_reserve(skb, headroom); | ||
277 | |||
278 | if (cmd_len != 0 && cmd_buf != NULL) { | ||
279 | data = (u8 *) skb_put(skb, cmd_len); | ||
280 | memcpy(data, cmd_buf, cmd_len); | ||
281 | } | ||
282 | |||
283 | mutex_lock(&wmi->op_mutex); | ||
284 | |||
285 | /* check if wmi stopped flag is set */ | ||
286 | if (unlikely(wmi->stopped)) { | ||
287 | ret = -EPROTO; | ||
288 | goto out; | ||
289 | } | ||
290 | |||
291 | /* record the rsp buffer and length */ | ||
292 | wmi->cmd_rsp_buf = rsp_buf; | ||
293 | wmi->cmd_rsp_len = rsp_len; | ||
294 | |||
295 | ret = ath9k_wmi_cmd_issue(wmi, skb, cmd_id, cmd_len); | ||
296 | if (ret) | ||
297 | goto out; | ||
298 | |||
299 | time_left = wait_for_completion_timeout(&wmi->cmd_wait, timeout); | ||
300 | if (!time_left) { | ||
301 | ath_print(common, ATH_DBG_WMI, | ||
302 | "Timeout waiting for WMI command: %s\n", | ||
303 | wmi_cmd_to_name(cmd_id)); | ||
304 | mutex_unlock(&wmi->op_mutex); | ||
305 | return -ETIMEDOUT; | ||
306 | } | ||
307 | |||
308 | mutex_unlock(&wmi->op_mutex); | ||
309 | |||
310 | return 0; | ||
311 | |||
312 | out: | ||
313 | ath_print(common, ATH_DBG_WMI, | ||
314 | "WMI failure for: %s\n", wmi_cmd_to_name(cmd_id)); | ||
315 | mutex_unlock(&wmi->op_mutex); | ||
316 | dev_kfree_skb_any(skb); | ||
317 | |||
318 | return ret; | ||
319 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h new file mode 100644 index 000000000000..39ef926f27c2 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/wmi.h | |||
@@ -0,0 +1,126 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef WMI_H | ||
18 | #define WMI_H | ||
19 | |||
20 | |||
21 | struct wmi_event_txrate { | ||
22 | u32 txrate; | ||
23 | struct { | ||
24 | u8 rssi_thresh; | ||
25 | u8 per; | ||
26 | } rc_stats; | ||
27 | } __packed; | ||
28 | |||
29 | struct wmi_cmd_hdr { | ||
30 | u16 command_id; | ||
31 | u16 seq_no; | ||
32 | } __packed; | ||
33 | |||
34 | struct wmi_swba { | ||
35 | u8 beacon_pending; | ||
36 | } __packed; | ||
37 | |||
38 | enum wmi_cmd_id { | ||
39 | WMI_ECHO_CMDID = 0x0001, | ||
40 | WMI_ACCESS_MEMORY_CMDID, | ||
41 | |||
42 | /* Commands to Target */ | ||
43 | WMI_DISABLE_INTR_CMDID, | ||
44 | WMI_ENABLE_INTR_CMDID, | ||
45 | WMI_RX_LINK_CMDID, | ||
46 | WMI_ATH_INIT_CMDID, | ||
47 | WMI_ABORT_TXQ_CMDID, | ||
48 | WMI_STOP_TX_DMA_CMDID, | ||
49 | WMI_STOP_DMA_RECV_CMDID, | ||
50 | WMI_ABORT_TX_DMA_CMDID, | ||
51 | WMI_DRAIN_TXQ_CMDID, | ||
52 | WMI_DRAIN_TXQ_ALL_CMDID, | ||
53 | WMI_START_RECV_CMDID, | ||
54 | WMI_STOP_RECV_CMDID, | ||
55 | WMI_FLUSH_RECV_CMDID, | ||
56 | WMI_SET_MODE_CMDID, | ||
57 | WMI_RESET_CMDID, | ||
58 | WMI_NODE_CREATE_CMDID, | ||
59 | WMI_NODE_REMOVE_CMDID, | ||
60 | WMI_VAP_REMOVE_CMDID, | ||
61 | WMI_VAP_CREATE_CMDID, | ||
62 | WMI_BEACON_UPDATE_CMDID, | ||
63 | WMI_REG_READ_CMDID, | ||
64 | WMI_REG_WRITE_CMDID, | ||
65 | WMI_RC_STATE_CHANGE_CMDID, | ||
66 | WMI_RC_RATE_UPDATE_CMDID, | ||
67 | WMI_DEBUG_INFO_CMDID, | ||
68 | WMI_HOST_ATTACH, | ||
69 | WMI_TARGET_IC_UPDATE_CMDID, | ||
70 | WMI_TGT_STATS_CMDID, | ||
71 | WMI_TX_AGGR_ENABLE_CMDID, | ||
72 | WMI_TGT_DETACH_CMDID, | ||
73 | WMI_TGT_TXQ_ENABLE_CMDID, | ||
74 | }; | ||
75 | |||
76 | enum wmi_event_id { | ||
77 | WMI_TGT_RDY_EVENTID = 0x1001, | ||
78 | WMI_SWBA_EVENTID, | ||
79 | WMI_FATAL_EVENTID, | ||
80 | WMI_TXTO_EVENTID, | ||
81 | WMI_BMISS_EVENTID, | ||
82 | WMI_WLAN_TXCOMP_EVENTID, | ||
83 | WMI_DELBA_EVENTID, | ||
84 | WMI_TXRATE_EVENTID, | ||
85 | }; | ||
86 | |||
87 | struct wmi { | ||
88 | struct ath9k_htc_priv *drv_priv; | ||
89 | struct htc_target *htc; | ||
90 | enum htc_endpoint_id ctrl_epid; | ||
91 | struct mutex op_mutex; | ||
92 | struct completion cmd_wait; | ||
93 | u16 tx_seq_id; | ||
94 | u8 *cmd_rsp_buf; | ||
95 | u32 cmd_rsp_len; | ||
96 | bool stopped; | ||
97 | |||
98 | struct sk_buff *wmi_skb; | ||
99 | spinlock_t wmi_lock; | ||
100 | }; | ||
101 | |||
102 | struct wmi *ath9k_init_wmi(struct ath9k_htc_priv *priv); | ||
103 | void ath9k_deinit_wmi(struct ath9k_htc_priv *priv); | ||
104 | int ath9k_wmi_connect(struct htc_target *htc, struct wmi *wmi, | ||
105 | enum htc_endpoint_id *wmi_ctrl_epid); | ||
106 | int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, | ||
107 | u8 *cmd_buf, u32 cmd_len, | ||
108 | u8 *rsp_buf, u32 rsp_len, | ||
109 | u32 timeout); | ||
110 | void ath9k_wmi_tasklet(unsigned long data); | ||
111 | |||
112 | #define WMI_CMD(_wmi_cmd) \ | ||
113 | do { \ | ||
114 | ret = ath9k_wmi_cmd(priv->wmi, _wmi_cmd, NULL, 0, \ | ||
115 | (u8 *) &cmd_rsp, \ | ||
116 | sizeof(cmd_rsp), HZ); \ | ||
117 | } while (0) | ||
118 | |||
119 | #define WMI_CMD_BUF(_wmi_cmd, _buf) \ | ||
120 | do { \ | ||
121 | ret = ath9k_wmi_cmd(priv->wmi, _wmi_cmd, \ | ||
122 | (u8 *) _buf, sizeof(*_buf), \ | ||
123 | &cmd_rsp, sizeof(cmd_rsp), HZ); \ | ||
124 | } while (0) | ||
125 | |||
126 | #endif /* WMI_H */ | ||
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 294b486bc3ed..02df4cbf179f 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -59,15 +59,14 @@ static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq, | |||
59 | struct ath_atx_tid *tid, | 59 | struct ath_atx_tid *tid, |
60 | struct list_head *bf_head); | 60 | struct list_head *bf_head); |
61 | static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, | 61 | static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, |
62 | struct ath_txq *txq, | 62 | struct ath_txq *txq, struct list_head *bf_q, |
63 | struct list_head *bf_q, | 63 | struct ath_tx_status *ts, int txok, int sendbar); |
64 | int txok, int sendbar); | ||
65 | static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, | 64 | static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, |
66 | struct list_head *head); | 65 | struct list_head *head); |
67 | static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf); | 66 | static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf); |
68 | static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, | 67 | static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, |
69 | int txok); | 68 | struct ath_tx_status *ts, int txok); |
70 | static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, | 69 | static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts, |
71 | int nbad, int txok, bool update_rc); | 70 | int nbad, int txok, bool update_rc); |
72 | 71 | ||
73 | enum { | 72 | enum { |
@@ -223,6 +222,9 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, | |||
223 | { | 222 | { |
224 | struct ath_buf *bf; | 223 | struct ath_buf *bf; |
225 | struct list_head bf_head; | 224 | struct list_head bf_head; |
225 | struct ath_tx_status ts; | ||
226 | |||
227 | memset(&ts, 0, sizeof(ts)); | ||
226 | INIT_LIST_HEAD(&bf_head); | 228 | INIT_LIST_HEAD(&bf_head); |
227 | 229 | ||
228 | for (;;) { | 230 | for (;;) { |
@@ -236,7 +238,7 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, | |||
236 | ath_tx_update_baw(sc, tid, bf->bf_seqno); | 238 | ath_tx_update_baw(sc, tid, bf->bf_seqno); |
237 | 239 | ||
238 | spin_unlock(&txq->axq_lock); | 240 | spin_unlock(&txq->axq_lock); |
239 | ath_tx_complete_buf(sc, bf, txq, &bf_head, 0, 0); | 241 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); |
240 | spin_lock(&txq->axq_lock); | 242 | spin_lock(&txq->axq_lock); |
241 | } | 243 | } |
242 | 244 | ||
@@ -286,7 +288,7 @@ static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf) | |||
286 | 288 | ||
287 | static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | 289 | static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, |
288 | struct ath_buf *bf, struct list_head *bf_q, | 290 | struct ath_buf *bf, struct list_head *bf_q, |
289 | int txok) | 291 | struct ath_tx_status *ts, int txok) |
290 | { | 292 | { |
291 | struct ath_node *an = NULL; | 293 | struct ath_node *an = NULL; |
292 | struct sk_buff *skb; | 294 | struct sk_buff *skb; |
@@ -296,7 +298,6 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
296 | struct ieee80211_tx_info *tx_info; | 298 | struct ieee80211_tx_info *tx_info; |
297 | struct ath_atx_tid *tid = NULL; | 299 | struct ath_atx_tid *tid = NULL; |
298 | struct ath_buf *bf_next, *bf_last = bf->bf_lastbf; | 300 | struct ath_buf *bf_next, *bf_last = bf->bf_lastbf; |
299 | struct ath_desc *ds = bf_last->bf_desc; | ||
300 | struct list_head bf_head, bf_pending; | 301 | struct list_head bf_head, bf_pending; |
301 | u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0; | 302 | u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0; |
302 | u32 ba[WME_BA_BMP_SIZE >> 5]; | 303 | u32 ba[WME_BA_BMP_SIZE >> 5]; |
@@ -325,10 +326,9 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
325 | memset(ba, 0, WME_BA_BMP_SIZE >> 3); | 326 | memset(ba, 0, WME_BA_BMP_SIZE >> 3); |
326 | 327 | ||
327 | if (isaggr && txok) { | 328 | if (isaggr && txok) { |
328 | if (ATH_DS_TX_BA(ds)) { | 329 | if (ts->ts_flags & ATH9K_TX_BA) { |
329 | seq_st = ATH_DS_BA_SEQ(ds); | 330 | seq_st = ts->ts_seqnum; |
330 | memcpy(ba, ATH_DS_BA_BITMAP(ds), | 331 | memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3); |
331 | WME_BA_BMP_SIZE >> 3); | ||
332 | } else { | 332 | } else { |
333 | /* | 333 | /* |
334 | * AR5416 can become deaf/mute when BA | 334 | * AR5416 can become deaf/mute when BA |
@@ -345,7 +345,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
345 | INIT_LIST_HEAD(&bf_pending); | 345 | INIT_LIST_HEAD(&bf_pending); |
346 | INIT_LIST_HEAD(&bf_head); | 346 | INIT_LIST_HEAD(&bf_head); |
347 | 347 | ||
348 | nbad = ath_tx_num_badfrms(sc, bf, txok); | 348 | nbad = ath_tx_num_badfrms(sc, bf, ts, txok); |
349 | while (bf) { | 349 | while (bf) { |
350 | txfail = txpending = 0; | 350 | txfail = txpending = 0; |
351 | bf_next = bf->bf_next; | 351 | bf_next = bf->bf_next; |
@@ -359,7 +359,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
359 | acked_cnt++; | 359 | acked_cnt++; |
360 | } else { | 360 | } else { |
361 | if (!(tid->state & AGGR_CLEANUP) && | 361 | if (!(tid->state & AGGR_CLEANUP) && |
362 | ds->ds_txstat.ts_flags != ATH9K_TX_SW_ABORTED) { | 362 | ts->ts_flags != ATH9K_TX_SW_ABORTED) { |
363 | if (bf->bf_retries < ATH_MAX_SW_RETRIES) { | 363 | if (bf->bf_retries < ATH_MAX_SW_RETRIES) { |
364 | ath_tx_set_retry(sc, txq, bf); | 364 | ath_tx_set_retry(sc, txq, bf); |
365 | txpending = 1; | 365 | txpending = 1; |
@@ -402,13 +402,14 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
402 | spin_unlock_bh(&txq->axq_lock); | 402 | spin_unlock_bh(&txq->axq_lock); |
403 | 403 | ||
404 | if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) { | 404 | if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) { |
405 | ath_tx_rc_status(bf, ds, nbad, txok, true); | 405 | ath_tx_rc_status(bf, ts, nbad, txok, true); |
406 | rc_update = false; | 406 | rc_update = false; |
407 | } else { | 407 | } else { |
408 | ath_tx_rc_status(bf, ds, nbad, txok, false); | 408 | ath_tx_rc_status(bf, ts, nbad, txok, false); |
409 | } | 409 | } |
410 | 410 | ||
411 | ath_tx_complete_buf(sc, bf, txq, &bf_head, !txfail, sendbar); | 411 | ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, |
412 | !txfail, sendbar); | ||
412 | } else { | 413 | } else { |
413 | /* retry the un-acked ones */ | 414 | /* retry the un-acked ones */ |
414 | if (bf->bf_next == NULL && bf_last->bf_stale) { | 415 | if (bf->bf_next == NULL && bf_last->bf_stale) { |
@@ -426,10 +427,10 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
426 | spin_unlock_bh(&txq->axq_lock); | 427 | spin_unlock_bh(&txq->axq_lock); |
427 | 428 | ||
428 | bf->bf_state.bf_type |= BUF_XRETRY; | 429 | bf->bf_state.bf_type |= BUF_XRETRY; |
429 | ath_tx_rc_status(bf, ds, nbad, | 430 | ath_tx_rc_status(bf, ts, nbad, |
430 | 0, false); | 431 | 0, false); |
431 | ath_tx_complete_buf(sc, bf, txq, | 432 | ath_tx_complete_buf(sc, bf, txq, |
432 | &bf_head, 0, 0); | 433 | &bf_head, ts, 0, 0); |
433 | break; | 434 | break; |
434 | } | 435 | } |
435 | 436 | ||
@@ -752,8 +753,11 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) | |||
752 | struct ath_node *an = (struct ath_node *)sta->drv_priv; | 753 | struct ath_node *an = (struct ath_node *)sta->drv_priv; |
753 | struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid); | 754 | struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid); |
754 | struct ath_txq *txq = &sc->tx.txq[txtid->ac->qnum]; | 755 | struct ath_txq *txq = &sc->tx.txq[txtid->ac->qnum]; |
756 | struct ath_tx_status ts; | ||
755 | struct ath_buf *bf; | 757 | struct ath_buf *bf; |
756 | struct list_head bf_head; | 758 | struct list_head bf_head; |
759 | |||
760 | memset(&ts, 0, sizeof(ts)); | ||
757 | INIT_LIST_HEAD(&bf_head); | 761 | INIT_LIST_HEAD(&bf_head); |
758 | 762 | ||
759 | if (txtid->state & AGGR_CLEANUP) | 763 | if (txtid->state & AGGR_CLEANUP) |
@@ -780,7 +784,7 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) | |||
780 | } | 784 | } |
781 | list_move_tail(&bf->list, &bf_head); | 785 | list_move_tail(&bf->list, &bf_head); |
782 | ath_tx_update_baw(sc, txtid, bf->bf_seqno); | 786 | ath_tx_update_baw(sc, txtid, bf->bf_seqno); |
783 | ath_tx_complete_buf(sc, bf, txq, &bf_head, 0, 0); | 787 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); |
784 | } | 788 | } |
785 | spin_unlock_bh(&txq->axq_lock); | 789 | spin_unlock_bh(&txq->axq_lock); |
786 | 790 | ||
@@ -1028,6 +1032,11 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) | |||
1028 | { | 1032 | { |
1029 | struct ath_buf *bf, *lastbf; | 1033 | struct ath_buf *bf, *lastbf; |
1030 | struct list_head bf_head; | 1034 | struct list_head bf_head; |
1035 | struct ath_tx_status ts; | ||
1036 | |||
1037 | memset(&ts, 0, sizeof(ts)); | ||
1038 | if (!retry_tx) | ||
1039 | ts.ts_flags = ATH9K_TX_SW_ABORTED; | ||
1031 | 1040 | ||
1032 | INIT_LIST_HEAD(&bf_head); | 1041 | INIT_LIST_HEAD(&bf_head); |
1033 | 1042 | ||
@@ -1053,9 +1062,6 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) | |||
1053 | } | 1062 | } |
1054 | 1063 | ||
1055 | lastbf = bf->bf_lastbf; | 1064 | lastbf = bf->bf_lastbf; |
1056 | if (!retry_tx) | ||
1057 | lastbf->bf_desc->ds_txstat.ts_flags = | ||
1058 | ATH9K_TX_SW_ABORTED; | ||
1059 | 1065 | ||
1060 | /* remove ath_buf's of the same mpdu from txq */ | 1066 | /* remove ath_buf's of the same mpdu from txq */ |
1061 | list_cut_position(&bf_head, &txq->axq_q, &lastbf->list); | 1067 | list_cut_position(&bf_head, &txq->axq_q, &lastbf->list); |
@@ -1064,9 +1070,9 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) | |||
1064 | spin_unlock_bh(&txq->axq_lock); | 1070 | spin_unlock_bh(&txq->axq_lock); |
1065 | 1071 | ||
1066 | if (bf_isampdu(bf)) | 1072 | if (bf_isampdu(bf)) |
1067 | ath_tx_complete_aggr(sc, txq, bf, &bf_head, 0); | 1073 | ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0); |
1068 | else | 1074 | else |
1069 | ath_tx_complete_buf(sc, bf, txq, &bf_head, 0, 0); | 1075 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); |
1070 | } | 1076 | } |
1071 | 1077 | ||
1072 | spin_lock_bh(&txq->axq_lock); | 1078 | spin_lock_bh(&txq->axq_lock); |
@@ -1568,12 +1574,12 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, | |||
1568 | 1574 | ||
1569 | tx_info->pad[0] = 0; | 1575 | tx_info->pad[0] = 0; |
1570 | switch (txctl->frame_type) { | 1576 | switch (txctl->frame_type) { |
1571 | case ATH9K_NOT_INTERNAL: | 1577 | case ATH9K_IFT_NOT_INTERNAL: |
1572 | break; | 1578 | break; |
1573 | case ATH9K_INT_PAUSE: | 1579 | case ATH9K_IFT_PAUSE: |
1574 | tx_info->pad[0] |= ATH_TX_INFO_FRAME_TYPE_PAUSE; | 1580 | tx_info->pad[0] |= ATH_TX_INFO_FRAME_TYPE_PAUSE; |
1575 | /* fall through */ | 1581 | /* fall through */ |
1576 | case ATH9K_INT_UNPAUSE: | 1582 | case ATH9K_IFT_UNPAUSE: |
1577 | tx_info->pad[0] |= ATH_TX_INFO_FRAME_TYPE_INTERNAL; | 1583 | tx_info->pad[0] |= ATH_TX_INFO_FRAME_TYPE_INTERNAL; |
1578 | break; | 1584 | break; |
1579 | } | 1585 | } |
@@ -1852,9 +1858,8 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
1852 | } | 1858 | } |
1853 | 1859 | ||
1854 | static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, | 1860 | static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, |
1855 | struct ath_txq *txq, | 1861 | struct ath_txq *txq, struct list_head *bf_q, |
1856 | struct list_head *bf_q, | 1862 | struct ath_tx_status *ts, int txok, int sendbar) |
1857 | int txok, int sendbar) | ||
1858 | { | 1863 | { |
1859 | struct sk_buff *skb = bf->bf_mpdu; | 1864 | struct sk_buff *skb = bf->bf_mpdu; |
1860 | unsigned long flags; | 1865 | unsigned long flags; |
@@ -1872,7 +1877,7 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, | |||
1872 | 1877 | ||
1873 | dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE); | 1878 | dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE); |
1874 | ath_tx_complete(sc, skb, bf->aphy, tx_flags); | 1879 | ath_tx_complete(sc, skb, bf->aphy, tx_flags); |
1875 | ath_debug_stat_tx(sc, txq, bf); | 1880 | ath_debug_stat_tx(sc, txq, bf, ts); |
1876 | 1881 | ||
1877 | /* | 1882 | /* |
1878 | * Return the list of ath_buf of this mpdu to free queue | 1883 | * Return the list of ath_buf of this mpdu to free queue |
@@ -1883,23 +1888,21 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, | |||
1883 | } | 1888 | } |
1884 | 1889 | ||
1885 | static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, | 1890 | static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, |
1886 | int txok) | 1891 | struct ath_tx_status *ts, int txok) |
1887 | { | 1892 | { |
1888 | struct ath_buf *bf_last = bf->bf_lastbf; | ||
1889 | struct ath_desc *ds = bf_last->bf_desc; | ||
1890 | u16 seq_st = 0; | 1893 | u16 seq_st = 0; |
1891 | u32 ba[WME_BA_BMP_SIZE >> 5]; | 1894 | u32 ba[WME_BA_BMP_SIZE >> 5]; |
1892 | int ba_index; | 1895 | int ba_index; |
1893 | int nbad = 0; | 1896 | int nbad = 0; |
1894 | int isaggr = 0; | 1897 | int isaggr = 0; |
1895 | 1898 | ||
1896 | if (ds->ds_txstat.ts_flags == ATH9K_TX_SW_ABORTED) | 1899 | if (ts->ts_flags == ATH9K_TX_SW_ABORTED) |
1897 | return 0; | 1900 | return 0; |
1898 | 1901 | ||
1899 | isaggr = bf_isaggr(bf); | 1902 | isaggr = bf_isaggr(bf); |
1900 | if (isaggr) { | 1903 | if (isaggr) { |
1901 | seq_st = ATH_DS_BA_SEQ(ds); | 1904 | seq_st = ts->ts_seqnum; |
1902 | memcpy(ba, ATH_DS_BA_BITMAP(ds), WME_BA_BMP_SIZE >> 3); | 1905 | memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3); |
1903 | } | 1906 | } |
1904 | 1907 | ||
1905 | while (bf) { | 1908 | while (bf) { |
@@ -1913,7 +1916,7 @@ static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, | |||
1913 | return nbad; | 1916 | return nbad; |
1914 | } | 1917 | } |
1915 | 1918 | ||
1916 | static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, | 1919 | static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts, |
1917 | int nbad, int txok, bool update_rc) | 1920 | int nbad, int txok, bool update_rc) |
1918 | { | 1921 | { |
1919 | struct sk_buff *skb = bf->bf_mpdu; | 1922 | struct sk_buff *skb = bf->bf_mpdu; |
@@ -1923,24 +1926,24 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, | |||
1923 | u8 i, tx_rateindex; | 1926 | u8 i, tx_rateindex; |
1924 | 1927 | ||
1925 | if (txok) | 1928 | if (txok) |
1926 | tx_info->status.ack_signal = ds->ds_txstat.ts_rssi; | 1929 | tx_info->status.ack_signal = ts->ts_rssi; |
1927 | 1930 | ||
1928 | tx_rateindex = ds->ds_txstat.ts_rateindex; | 1931 | tx_rateindex = ts->ts_rateindex; |
1929 | WARN_ON(tx_rateindex >= hw->max_rates); | 1932 | WARN_ON(tx_rateindex >= hw->max_rates); |
1930 | 1933 | ||
1931 | if (update_rc) | 1934 | if (ts->ts_status & ATH9K_TXERR_FILT) |
1932 | tx_info->pad[0] |= ATH_TX_INFO_UPDATE_RC; | ||
1933 | if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) | ||
1934 | tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; | 1935 | tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; |
1936 | if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && update_rc) | ||
1937 | tx_info->flags |= IEEE80211_TX_STAT_AMPDU; | ||
1935 | 1938 | ||
1936 | if ((ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) == 0 && | 1939 | if ((ts->ts_status & ATH9K_TXERR_FILT) == 0 && |
1937 | (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) { | 1940 | (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) { |
1938 | if (ieee80211_is_data(hdr->frame_control)) { | 1941 | if (ieee80211_is_data(hdr->frame_control)) { |
1939 | if (ds->ds_txstat.ts_flags & | 1942 | if (ts->ts_flags & |
1940 | (ATH9K_TX_DATA_UNDERRUN | ATH9K_TX_DELIM_UNDERRUN)) | 1943 | (ATH9K_TX_DATA_UNDERRUN | ATH9K_TX_DELIM_UNDERRUN)) |
1941 | tx_info->pad[0] |= ATH_TX_INFO_UNDERRUN; | 1944 | tx_info->pad[0] |= ATH_TX_INFO_UNDERRUN; |
1942 | if ((ds->ds_txstat.ts_status & ATH9K_TXERR_XRETRY) || | 1945 | if ((ts->ts_status & ATH9K_TXERR_XRETRY) || |
1943 | (ds->ds_txstat.ts_status & ATH9K_TXERR_FIFO)) | 1946 | (ts->ts_status & ATH9K_TXERR_FIFO)) |
1944 | tx_info->pad[0] |= ATH_TX_INFO_XRETRY; | 1947 | tx_info->pad[0] |= ATH_TX_INFO_XRETRY; |
1945 | tx_info->status.ampdu_len = bf->bf_nframes; | 1948 | tx_info->status.ampdu_len = bf->bf_nframes; |
1946 | tx_info->status.ampdu_ack_len = bf->bf_nframes - nbad; | 1949 | tx_info->status.ampdu_ack_len = bf->bf_nframes - nbad; |
@@ -1978,6 +1981,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
1978 | struct ath_buf *bf, *lastbf, *bf_held = NULL; | 1981 | struct ath_buf *bf, *lastbf, *bf_held = NULL; |
1979 | struct list_head bf_head; | 1982 | struct list_head bf_head; |
1980 | struct ath_desc *ds; | 1983 | struct ath_desc *ds; |
1984 | struct ath_tx_status ts; | ||
1981 | int txok; | 1985 | int txok; |
1982 | int status; | 1986 | int status; |
1983 | 1987 | ||
@@ -2017,7 +2021,8 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
2017 | lastbf = bf->bf_lastbf; | 2021 | lastbf = bf->bf_lastbf; |
2018 | ds = lastbf->bf_desc; | 2022 | ds = lastbf->bf_desc; |
2019 | 2023 | ||
2020 | status = ath9k_hw_txprocdesc(ah, ds); | 2024 | memset(&ts, 0, sizeof(ts)); |
2025 | status = ath9k_hw_txprocdesc(ah, ds, &ts); | ||
2021 | if (status == -EINPROGRESS) { | 2026 | if (status == -EINPROGRESS) { |
2022 | spin_unlock_bh(&txq->axq_lock); | 2027 | spin_unlock_bh(&txq->axq_lock); |
2023 | break; | 2028 | break; |
@@ -2028,7 +2033,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
2028 | * can disable RX. | 2033 | * can disable RX. |
2029 | */ | 2034 | */ |
2030 | if (bf->bf_isnullfunc && | 2035 | if (bf->bf_isnullfunc && |
2031 | (ds->ds_txstat.ts_status & ATH9K_TX_ACKED)) { | 2036 | (ts.ts_status & ATH9K_TX_ACKED)) { |
2032 | if ((sc->ps_flags & PS_ENABLED)) | 2037 | if ((sc->ps_flags & PS_ENABLED)) |
2033 | ath9k_enable_ps(sc); | 2038 | ath9k_enable_ps(sc); |
2034 | else | 2039 | else |
@@ -2047,7 +2052,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
2047 | &txq->axq_q, lastbf->list.prev); | 2052 | &txq->axq_q, lastbf->list.prev); |
2048 | 2053 | ||
2049 | txq->axq_depth--; | 2054 | txq->axq_depth--; |
2050 | txok = !(ds->ds_txstat.ts_status & ATH9K_TXERR_MASK); | 2055 | txok = !(ts.ts_status & ATH9K_TXERR_MASK); |
2051 | txq->axq_tx_inprogress = false; | 2056 | txq->axq_tx_inprogress = false; |
2052 | spin_unlock_bh(&txq->axq_lock); | 2057 | spin_unlock_bh(&txq->axq_lock); |
2053 | 2058 | ||
@@ -2062,16 +2067,16 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
2062 | * This frame is sent out as a single frame. | 2067 | * This frame is sent out as a single frame. |
2063 | * Use hardware retry status for this frame. | 2068 | * Use hardware retry status for this frame. |
2064 | */ | 2069 | */ |
2065 | bf->bf_retries = ds->ds_txstat.ts_longretry; | 2070 | bf->bf_retries = ts.ts_longretry; |
2066 | if (ds->ds_txstat.ts_status & ATH9K_TXERR_XRETRY) | 2071 | if (ts.ts_status & ATH9K_TXERR_XRETRY) |
2067 | bf->bf_state.bf_type |= BUF_XRETRY; | 2072 | bf->bf_state.bf_type |= BUF_XRETRY; |
2068 | ath_tx_rc_status(bf, ds, 0, txok, true); | 2073 | ath_tx_rc_status(bf, &ts, 0, txok, true); |
2069 | } | 2074 | } |
2070 | 2075 | ||
2071 | if (bf_isampdu(bf)) | 2076 | if (bf_isampdu(bf)) |
2072 | ath_tx_complete_aggr(sc, txq, bf, &bf_head, txok); | 2077 | ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, txok); |
2073 | else | 2078 | else |
2074 | ath_tx_complete_buf(sc, bf, txq, &bf_head, txok, 0); | 2079 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, txok, 0); |
2075 | 2080 | ||
2076 | ath_wake_mac80211_queue(sc, txq); | 2081 | ath_wake_mac80211_queue(sc, txq); |
2077 | 2082 | ||
diff --git a/drivers/net/wireless/ath/debug.h b/drivers/net/wireless/ath/debug.h index 8263633c003c..873bf526e11f 100644 --- a/drivers/net/wireless/ath/debug.h +++ b/drivers/net/wireless/ath/debug.h | |||
@@ -59,6 +59,7 @@ enum ATH_DEBUG { | |||
59 | ATH_DBG_PS = 0x00000800, | 59 | ATH_DBG_PS = 0x00000800, |
60 | ATH_DBG_HWTIMER = 0x00001000, | 60 | ATH_DBG_HWTIMER = 0x00001000, |
61 | ATH_DBG_BTCOEX = 0x00002000, | 61 | ATH_DBG_BTCOEX = 0x00002000, |
62 | ATH_DBG_WMI = 0x00004000, | ||
62 | ATH_DBG_ANY = 0xffffffff | 63 | ATH_DBG_ANY = 0xffffffff |
63 | }; | 64 | }; |
64 | 65 | ||
diff --git a/drivers/net/wireless/ath/hw.c b/drivers/net/wireless/ath/hw.c index ecc9eb01f4fa..a8f81ea09f14 100644 --- a/drivers/net/wireless/ath/hw.c +++ b/drivers/net/wireless/ath/hw.c | |||
@@ -19,8 +19,8 @@ | |||
19 | #include "ath.h" | 19 | #include "ath.h" |
20 | #include "reg.h" | 20 | #include "reg.h" |
21 | 21 | ||
22 | #define REG_READ common->ops->read | 22 | #define REG_READ (common->ops->read) |
23 | #define REG_WRITE common->ops->write | 23 | #define REG_WRITE (common->ops->write) |
24 | 24 | ||
25 | /** | 25 | /** |
26 | * ath_hw_set_bssid_mask - filter out bssids we listen | 26 | * ath_hw_set_bssid_mask - filter out bssids we listen |
diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index 04abd1f556b7..d5c23328aef1 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c | |||
@@ -51,6 +51,7 @@ | |||
51 | 51 | ||
52 | #define ATH9K_5GHZ_ALL ATH9K_5GHZ_5150_5350, \ | 52 | #define ATH9K_5GHZ_ALL ATH9K_5GHZ_5150_5350, \ |
53 | ATH9K_5GHZ_5470_5850 | 53 | ATH9K_5GHZ_5470_5850 |
54 | |||
54 | /* This one skips what we call "mid band" */ | 55 | /* This one skips what we call "mid band" */ |
55 | #define ATH9K_5GHZ_NO_MIDBAND ATH9K_5GHZ_5150_5350, \ | 56 | #define ATH9K_5GHZ_NO_MIDBAND ATH9K_5GHZ_5150_5350, \ |
56 | ATH9K_5GHZ_5725_5850 | 57 | ATH9K_5GHZ_5725_5850 |
@@ -361,7 +362,7 @@ EXPORT_SYMBOL(ath_reg_notifier_apply); | |||
361 | 362 | ||
362 | static bool ath_regd_is_eeprom_valid(struct ath_regulatory *reg) | 363 | static bool ath_regd_is_eeprom_valid(struct ath_regulatory *reg) |
363 | { | 364 | { |
364 | u16 rd = ath_regd_get_eepromRD(reg); | 365 | u16 rd = ath_regd_get_eepromRD(reg); |
365 | int i; | 366 | int i; |
366 | 367 | ||
367 | if (rd & COUNTRY_ERD_FLAG) { | 368 | if (rd & COUNTRY_ERD_FLAG) { |
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index b8807fb12c92..3a003e6803a5 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h | |||
@@ -104,6 +104,7 @@ | |||
104 | #define B43_MMIO_MACFILTER_CONTROL 0x420 | 104 | #define B43_MMIO_MACFILTER_CONTROL 0x420 |
105 | #define B43_MMIO_MACFILTER_DATA 0x422 | 105 | #define B43_MMIO_MACFILTER_DATA 0x422 |
106 | #define B43_MMIO_RCMTA_COUNT 0x43C | 106 | #define B43_MMIO_RCMTA_COUNT 0x43C |
107 | #define B43_MMIO_PSM_PHY_HDR 0x492 | ||
107 | #define B43_MMIO_RADIO_HWENABLED_LO 0x49A | 108 | #define B43_MMIO_RADIO_HWENABLED_LO 0x49A |
108 | #define B43_MMIO_GPIO_CONTROL 0x49C | 109 | #define B43_MMIO_GPIO_CONTROL 0x49C |
109 | #define B43_MMIO_GPIO_MASK 0x49E | 110 | #define B43_MMIO_GPIO_MASK 0x49E |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 1521b1e78d21..14cf3bd7ea51 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -4348,11 +4348,10 @@ static int b43_wireless_core_init(struct b43_wldev *dev) | |||
4348 | b43_set_phytxctl_defaults(dev); | 4348 | b43_set_phytxctl_defaults(dev); |
4349 | 4349 | ||
4350 | /* Minimum Contention Window */ | 4350 | /* Minimum Contention Window */ |
4351 | if (phy->type == B43_PHYTYPE_B) { | 4351 | if (phy->type == B43_PHYTYPE_B) |
4352 | b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MINCONT, 0x1F); | 4352 | b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MINCONT, 0x1F); |
4353 | } else { | 4353 | else |
4354 | b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MINCONT, 0xF); | 4354 | b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MINCONT, 0xF); |
4355 | } | ||
4356 | /* Maximum Contention Window */ | 4355 | /* Maximum Contention Window */ |
4357 | b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF); | 4356 | b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF); |
4358 | 4357 | ||
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 795bb1e3345d..9e93eb4a17cf 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c | |||
@@ -72,6 +72,22 @@ static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field, | |||
72 | u16 value, u8 core, bool off); | 72 | u16 value, u8 core, bool off); |
73 | static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field, | 73 | static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field, |
74 | u16 value, u8 core); | 74 | u16 value, u8 core); |
75 | static int nphy_channel_switch(struct b43_wldev *dev, unsigned int channel); | ||
76 | |||
77 | static inline bool b43_empty_chanspec(struct b43_chanspec *chanspec) | ||
78 | { | ||
79 | return !chanspec->channel && !chanspec->sideband && | ||
80 | !chanspec->b_width && !chanspec->b_freq; | ||
81 | } | ||
82 | |||
83 | static inline bool b43_eq_chanspecs(struct b43_chanspec *chanspec1, | ||
84 | struct b43_chanspec *chanspec2) | ||
85 | { | ||
86 | return (chanspec1->channel == chanspec2->channel && | ||
87 | chanspec1->sideband == chanspec2->sideband && | ||
88 | chanspec1->b_width == chanspec2->b_width && | ||
89 | chanspec1->b_freq == chanspec2->b_freq); | ||
90 | } | ||
75 | 91 | ||
76 | void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna) | 92 | void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna) |
77 | {//TODO | 93 | {//TODO |
@@ -88,34 +104,44 @@ static enum b43_txpwr_result b43_nphy_op_recalc_txpower(struct b43_wldev *dev, | |||
88 | } | 104 | } |
89 | 105 | ||
90 | static void b43_chantab_radio_upload(struct b43_wldev *dev, | 106 | static void b43_chantab_radio_upload(struct b43_wldev *dev, |
91 | const struct b43_nphy_channeltab_entry *e) | 107 | const struct b43_nphy_channeltab_entry_rev2 *e) |
92 | { | 108 | { |
93 | b43_radio_write16(dev, B2055_PLL_REF, e->radio_pll_ref); | 109 | b43_radio_write(dev, B2055_PLL_REF, e->radio_pll_ref); |
94 | b43_radio_write16(dev, B2055_RF_PLLMOD0, e->radio_rf_pllmod0); | 110 | b43_radio_write(dev, B2055_RF_PLLMOD0, e->radio_rf_pllmod0); |
95 | b43_radio_write16(dev, B2055_RF_PLLMOD1, e->radio_rf_pllmod1); | 111 | b43_radio_write(dev, B2055_RF_PLLMOD1, e->radio_rf_pllmod1); |
96 | b43_radio_write16(dev, B2055_VCO_CAPTAIL, e->radio_vco_captail); | 112 | b43_radio_write(dev, B2055_VCO_CAPTAIL, e->radio_vco_captail); |
97 | b43_radio_write16(dev, B2055_VCO_CAL1, e->radio_vco_cal1); | 113 | b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */ |
98 | b43_radio_write16(dev, B2055_VCO_CAL2, e->radio_vco_cal2); | 114 | |
99 | b43_radio_write16(dev, B2055_PLL_LFC1, e->radio_pll_lfc1); | 115 | b43_radio_write(dev, B2055_VCO_CAL1, e->radio_vco_cal1); |
100 | b43_radio_write16(dev, B2055_PLL_LFR1, e->radio_pll_lfr1); | 116 | b43_radio_write(dev, B2055_VCO_CAL2, e->radio_vco_cal2); |
101 | b43_radio_write16(dev, B2055_PLL_LFC2, e->radio_pll_lfc2); | 117 | b43_radio_write(dev, B2055_PLL_LFC1, e->radio_pll_lfc1); |
102 | b43_radio_write16(dev, B2055_LGBUF_CENBUF, e->radio_lgbuf_cenbuf); | 118 | b43_radio_write(dev, B2055_PLL_LFR1, e->radio_pll_lfr1); |
103 | b43_radio_write16(dev, B2055_LGEN_TUNE1, e->radio_lgen_tune1); | 119 | b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */ |
104 | b43_radio_write16(dev, B2055_LGEN_TUNE2, e->radio_lgen_tune2); | 120 | |
105 | b43_radio_write16(dev, B2055_C1_LGBUF_ATUNE, e->radio_c1_lgbuf_atune); | 121 | b43_radio_write(dev, B2055_PLL_LFC2, e->radio_pll_lfc2); |
106 | b43_radio_write16(dev, B2055_C1_LGBUF_GTUNE, e->radio_c1_lgbuf_gtune); | 122 | b43_radio_write(dev, B2055_LGBUF_CENBUF, e->radio_lgbuf_cenbuf); |
107 | b43_radio_write16(dev, B2055_C1_RX_RFR1, e->radio_c1_rx_rfr1); | 123 | b43_radio_write(dev, B2055_LGEN_TUNE1, e->radio_lgen_tune1); |
108 | b43_radio_write16(dev, B2055_C1_TX_PGAPADTN, e->radio_c1_tx_pgapadtn); | 124 | b43_radio_write(dev, B2055_LGEN_TUNE2, e->radio_lgen_tune2); |
109 | b43_radio_write16(dev, B2055_C1_TX_MXBGTRIM, e->radio_c1_tx_mxbgtrim); | 125 | b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */ |
110 | b43_radio_write16(dev, B2055_C2_LGBUF_ATUNE, e->radio_c2_lgbuf_atune); | 126 | |
111 | b43_radio_write16(dev, B2055_C2_LGBUF_GTUNE, e->radio_c2_lgbuf_gtune); | 127 | b43_radio_write(dev, B2055_C1_LGBUF_ATUNE, e->radio_c1_lgbuf_atune); |
112 | b43_radio_write16(dev, B2055_C2_RX_RFR1, e->radio_c2_rx_rfr1); | 128 | b43_radio_write(dev, B2055_C1_LGBUF_GTUNE, e->radio_c1_lgbuf_gtune); |
113 | b43_radio_write16(dev, B2055_C2_TX_PGAPADTN, e->radio_c2_tx_pgapadtn); | 129 | b43_radio_write(dev, B2055_C1_RX_RFR1, e->radio_c1_rx_rfr1); |
114 | b43_radio_write16(dev, B2055_C2_TX_MXBGTRIM, e->radio_c2_tx_mxbgtrim); | 130 | b43_radio_write(dev, B2055_C1_TX_PGAPADTN, e->radio_c1_tx_pgapadtn); |
131 | b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */ | ||
132 | |||
133 | b43_radio_write(dev, B2055_C1_TX_MXBGTRIM, e->radio_c1_tx_mxbgtrim); | ||
134 | b43_radio_write(dev, B2055_C2_LGBUF_ATUNE, e->radio_c2_lgbuf_atune); | ||
135 | b43_radio_write(dev, B2055_C2_LGBUF_GTUNE, e->radio_c2_lgbuf_gtune); | ||
136 | b43_radio_write(dev, B2055_C2_RX_RFR1, e->radio_c2_rx_rfr1); | ||
137 | b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */ | ||
138 | |||
139 | b43_radio_write(dev, B2055_C2_TX_PGAPADTN, e->radio_c2_tx_pgapadtn); | ||
140 | b43_radio_write(dev, B2055_C2_TX_MXBGTRIM, e->radio_c2_tx_mxbgtrim); | ||
115 | } | 141 | } |
116 | 142 | ||
117 | static void b43_chantab_phy_upload(struct b43_wldev *dev, | 143 | static void b43_chantab_phy_upload(struct b43_wldev *dev, |
118 | const struct b43_nphy_channeltab_entry *e) | 144 | const struct b43_phy_n_sfo_cfg *e) |
119 | { | 145 | { |
120 | b43_phy_write(dev, B43_NPHY_BW1A, e->phy_bw1a); | 146 | b43_phy_write(dev, B43_NPHY_BW1A, e->phy_bw1a); |
121 | b43_phy_write(dev, B43_NPHY_BW2, e->phy_bw2); | 147 | b43_phy_write(dev, B43_NPHY_BW2, e->phy_bw2); |
@@ -130,34 +156,20 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev) | |||
130 | //TODO | 156 | //TODO |
131 | } | 157 | } |
132 | 158 | ||
133 | /* Tune the hardware to a new channel. */ | ||
134 | static int nphy_channel_switch(struct b43_wldev *dev, unsigned int channel) | ||
135 | { | ||
136 | const struct b43_nphy_channeltab_entry *tabent; | ||
137 | 159 | ||
138 | tabent = b43_nphy_get_chantabent(dev, channel); | 160 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2055Setup */ |
139 | if (!tabent) | 161 | static void b43_radio_2055_setup(struct b43_wldev *dev, |
140 | return -ESRCH; | 162 | const struct b43_nphy_channeltab_entry_rev2 *e) |
163 | { | ||
164 | B43_WARN_ON(dev->phy.rev >= 3); | ||
141 | 165 | ||
142 | //FIXME enable/disable band select upper20 in RXCTL | 166 | b43_chantab_radio_upload(dev, e); |
143 | if (0 /*FIXME 5Ghz*/) | ||
144 | b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, 0x20); | ||
145 | else | ||
146 | b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, 0x50); | ||
147 | b43_chantab_radio_upload(dev, tabent); | ||
148 | udelay(50); | 167 | udelay(50); |
149 | b43_radio_write16(dev, B2055_VCO_CAL10, 5); | 168 | b43_radio_write(dev, B2055_VCO_CAL10, 0x05); |
150 | b43_radio_write16(dev, B2055_VCO_CAL10, 45); | 169 | b43_radio_write(dev, B2055_VCO_CAL10, 0x45); |
151 | b43_radio_write16(dev, B2055_VCO_CAL10, 65); | 170 | b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */ |
171 | b43_radio_write(dev, B2055_VCO_CAL10, 0x65); | ||
152 | udelay(300); | 172 | udelay(300); |
153 | if (0 /*FIXME 5Ghz*/) | ||
154 | b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ); | ||
155 | else | ||
156 | b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ); | ||
157 | b43_chantab_phy_upload(dev, tabent); | ||
158 | b43_nphy_tx_power_fix(dev); | ||
159 | |||
160 | return 0; | ||
161 | } | 173 | } |
162 | 174 | ||
163 | static void b43_radio_init2055_pre(struct b43_wldev *dev) | 175 | static void b43_radio_init2055_pre(struct b43_wldev *dev) |
@@ -173,52 +185,64 @@ static void b43_radio_init2055_pre(struct b43_wldev *dev) | |||
173 | 185 | ||
174 | static void b43_radio_init2055_post(struct b43_wldev *dev) | 186 | static void b43_radio_init2055_post(struct b43_wldev *dev) |
175 | { | 187 | { |
188 | struct b43_phy_n *nphy = dev->phy.n; | ||
176 | struct ssb_sprom *sprom = &(dev->dev->bus->sprom); | 189 | struct ssb_sprom *sprom = &(dev->dev->bus->sprom); |
177 | struct ssb_boardinfo *binfo = &(dev->dev->bus->boardinfo); | 190 | struct ssb_boardinfo *binfo = &(dev->dev->bus->boardinfo); |
178 | int i; | 191 | int i; |
179 | u16 val; | 192 | u16 val; |
193 | bool workaround = false; | ||
194 | |||
195 | if (sprom->revision < 4) | ||
196 | workaround = (binfo->vendor != PCI_VENDOR_ID_BROADCOM || | ||
197 | binfo->type != 0x46D || | ||
198 | binfo->rev < 0x41); | ||
199 | else | ||
200 | workaround = ((sprom->boardflags_hi & B43_BFH_NOPA) == 0); | ||
180 | 201 | ||
181 | b43_radio_mask(dev, B2055_MASTER1, 0xFFF3); | 202 | b43_radio_mask(dev, B2055_MASTER1, 0xFFF3); |
182 | msleep(1); | 203 | if (workaround) { |
183 | if ((sprom->revision != 4) || | 204 | b43_radio_mask(dev, B2055_C1_RX_BB_REG, 0x7F); |
184 | !(sprom->boardflags_hi & B43_BFH_RSSIINV)) { | 205 | b43_radio_mask(dev, B2055_C2_RX_BB_REG, 0x7F); |
185 | if ((binfo->vendor != PCI_VENDOR_ID_BROADCOM) || | ||
186 | (binfo->type != 0x46D) || | ||
187 | (binfo->rev < 0x41)) { | ||
188 | b43_radio_mask(dev, B2055_C1_RX_BB_REG, 0x7F); | ||
189 | b43_radio_mask(dev, B2055_C1_RX_BB_REG, 0x7F); | ||
190 | msleep(1); | ||
191 | } | ||
192 | } | 206 | } |
193 | b43_radio_maskset(dev, B2055_RRCCAL_NOPTSEL, 0x3F, 0x2C); | 207 | b43_radio_maskset(dev, B2055_RRCCAL_NOPTSEL, 0xFFC0, 0x2C); |
194 | msleep(1); | 208 | b43_radio_write(dev, B2055_CAL_MISC, 0x3C); |
195 | b43_radio_write16(dev, B2055_CAL_MISC, 0x3C); | ||
196 | msleep(1); | ||
197 | b43_radio_mask(dev, B2055_CAL_MISC, 0xFFBE); | 209 | b43_radio_mask(dev, B2055_CAL_MISC, 0xFFBE); |
198 | msleep(1); | ||
199 | b43_radio_set(dev, B2055_CAL_LPOCTL, 0x80); | 210 | b43_radio_set(dev, B2055_CAL_LPOCTL, 0x80); |
200 | msleep(1); | ||
201 | b43_radio_set(dev, B2055_CAL_MISC, 0x1); | 211 | b43_radio_set(dev, B2055_CAL_MISC, 0x1); |
202 | msleep(1); | 212 | msleep(1); |
203 | b43_radio_set(dev, B2055_CAL_MISC, 0x40); | 213 | b43_radio_set(dev, B2055_CAL_MISC, 0x40); |
204 | msleep(1); | 214 | for (i = 0; i < 200; i++) { |
205 | for (i = 0; i < 100; i++) { | 215 | val = b43_radio_read(dev, B2055_CAL_COUT2); |
206 | val = b43_radio_read16(dev, B2055_CAL_COUT2); | 216 | if (val & 0x80) { |
207 | if (val & 0x80) | 217 | i = 0; |
208 | break; | 218 | break; |
219 | } | ||
209 | udelay(10); | 220 | udelay(10); |
210 | } | 221 | } |
211 | msleep(1); | 222 | if (i) |
223 | b43err(dev->wl, "radio post init timeout\n"); | ||
212 | b43_radio_mask(dev, B2055_CAL_LPOCTL, 0xFF7F); | 224 | b43_radio_mask(dev, B2055_CAL_LPOCTL, 0xFF7F); |
213 | msleep(1); | ||
214 | nphy_channel_switch(dev, dev->phy.channel); | 225 | nphy_channel_switch(dev, dev->phy.channel); |
215 | b43_radio_write16(dev, B2055_C1_RX_BB_LPF, 0x9); | 226 | b43_radio_write(dev, B2055_C1_RX_BB_LPF, 0x9); |
216 | b43_radio_write16(dev, B2055_C2_RX_BB_LPF, 0x9); | 227 | b43_radio_write(dev, B2055_C2_RX_BB_LPF, 0x9); |
217 | b43_radio_write16(dev, B2055_C1_RX_BB_MIDACHP, 0x83); | 228 | b43_radio_write(dev, B2055_C1_RX_BB_MIDACHP, 0x83); |
218 | b43_radio_write16(dev, B2055_C2_RX_BB_MIDACHP, 0x83); | 229 | b43_radio_write(dev, B2055_C2_RX_BB_MIDACHP, 0x83); |
230 | b43_radio_maskset(dev, B2055_C1_LNA_GAINBST, 0xFFF8, 0x6); | ||
231 | b43_radio_maskset(dev, B2055_C2_LNA_GAINBST, 0xFFF8, 0x6); | ||
232 | if (!nphy->gain_boost) { | ||
233 | b43_radio_set(dev, B2055_C1_RX_RFSPC1, 0x2); | ||
234 | b43_radio_set(dev, B2055_C2_RX_RFSPC1, 0x2); | ||
235 | } else { | ||
236 | b43_radio_mask(dev, B2055_C1_RX_RFSPC1, 0xFFFD); | ||
237 | b43_radio_mask(dev, B2055_C2_RX_RFSPC1, 0xFFFD); | ||
238 | } | ||
239 | udelay(2); | ||
219 | } | 240 | } |
220 | 241 | ||
221 | /* Initialize a Broadcom 2055 N-radio */ | 242 | /* |
243 | * Initialize a Broadcom 2055 N-radio | ||
244 | * http://bcm-v4.sipsolutions.net/802.11/Radio/2055/Init | ||
245 | */ | ||
222 | static void b43_radio_init2055(struct b43_wldev *dev) | 246 | static void b43_radio_init2055(struct b43_wldev *dev) |
223 | { | 247 | { |
224 | b43_radio_init2055_pre(dev); | 248 | b43_radio_init2055_pre(dev); |
@@ -229,16 +253,15 @@ static void b43_radio_init2055(struct b43_wldev *dev) | |||
229 | b43_radio_init2055_post(dev); | 253 | b43_radio_init2055_post(dev); |
230 | } | 254 | } |
231 | 255 | ||
232 | void b43_nphy_radio_turn_on(struct b43_wldev *dev) | 256 | /* |
257 | * Initialize a Broadcom 2056 N-radio | ||
258 | * http://bcm-v4.sipsolutions.net/802.11/Radio/2056/Init | ||
259 | */ | ||
260 | static void b43_radio_init2056(struct b43_wldev *dev) | ||
233 | { | 261 | { |
234 | b43_radio_init2055(dev); | 262 | /* TODO */ |
235 | } | 263 | } |
236 | 264 | ||
237 | void b43_nphy_radio_turn_off(struct b43_wldev *dev) | ||
238 | { | ||
239 | b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, | ||
240 | ~B43_NPHY_RFCTL_CMD_EN); | ||
241 | } | ||
242 | 265 | ||
243 | /* | 266 | /* |
244 | * Upload the N-PHY tables. | 267 | * Upload the N-PHY tables. |
@@ -646,6 +669,41 @@ static void b43_nphy_read_clip_detection(struct b43_wldev *dev, u16 *clip_st) | |||
646 | clip_st[1] = b43_phy_read(dev, B43_NPHY_C2_CLIP1THRES); | 669 | clip_st[1] = b43_phy_read(dev, B43_NPHY_C2_CLIP1THRES); |
647 | } | 670 | } |
648 | 671 | ||
672 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SuperSwitchInit */ | ||
673 | static void b43_nphy_superswitch_init(struct b43_wldev *dev, bool init) | ||
674 | { | ||
675 | if (dev->phy.rev >= 3) { | ||
676 | if (!init) | ||
677 | return; | ||
678 | if (0 /* FIXME */) { | ||
679 | b43_ntab_write(dev, B43_NTAB16(9, 2), 0x211); | ||
680 | b43_ntab_write(dev, B43_NTAB16(9, 3), 0x222); | ||
681 | b43_ntab_write(dev, B43_NTAB16(9, 8), 0x144); | ||
682 | b43_ntab_write(dev, B43_NTAB16(9, 12), 0x188); | ||
683 | } | ||
684 | } else { | ||
685 | b43_phy_write(dev, B43_NPHY_GPIO_LOOEN, 0); | ||
686 | b43_phy_write(dev, B43_NPHY_GPIO_HIOEN, 0); | ||
687 | |||
688 | ssb_chipco_gpio_control(&dev->dev->bus->chipco, 0xFC00, | ||
689 | 0xFC00); | ||
690 | b43_write32(dev, B43_MMIO_MACCTL, | ||
691 | b43_read32(dev, B43_MMIO_MACCTL) & | ||
692 | ~B43_MACCTL_GPOUTSMSK); | ||
693 | b43_write16(dev, B43_MMIO_GPIO_MASK, | ||
694 | b43_read16(dev, B43_MMIO_GPIO_MASK) | 0xFC00); | ||
695 | b43_write16(dev, B43_MMIO_GPIO_CONTROL, | ||
696 | b43_read16(dev, B43_MMIO_GPIO_CONTROL) & ~0xFC00); | ||
697 | |||
698 | if (init) { | ||
699 | b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8); | ||
700 | b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301); | ||
701 | b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8); | ||
702 | b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301); | ||
703 | } | ||
704 | } | ||
705 | } | ||
706 | |||
649 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/classifier */ | 707 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/classifier */ |
650 | static u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val) | 708 | static u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val) |
651 | { | 709 | { |
@@ -722,7 +780,7 @@ static void b43_nphy_spur_workaround(struct b43_wldev *dev) | |||
722 | { | 780 | { |
723 | struct b43_phy_n *nphy = dev->phy.n; | 781 | struct b43_phy_n *nphy = dev->phy.n; |
724 | 782 | ||
725 | unsigned int channel; | 783 | u8 channel = nphy->radio_chanspec.channel; |
726 | int tone[2] = { 57, 58 }; | 784 | int tone[2] = { 57, 58 }; |
727 | u32 noise[2] = { 0x3FF, 0x3FF }; | 785 | u32 noise[2] = { 0x3FF, 0x3FF }; |
728 | 786 | ||
@@ -731,8 +789,6 @@ static void b43_nphy_spur_workaround(struct b43_wldev *dev) | |||
731 | if (nphy->hang_avoid) | 789 | if (nphy->hang_avoid) |
732 | b43_nphy_stay_in_carrier_search(dev, 1); | 790 | b43_nphy_stay_in_carrier_search(dev, 1); |
733 | 791 | ||
734 | /* FIXME: channel = radio_chanspec */ | ||
735 | |||
736 | if (nphy->gband_spurwar_en) { | 792 | if (nphy->gband_spurwar_en) { |
737 | /* TODO: N PHY Adjust Analog Pfbw (7) */ | 793 | /* TODO: N PHY Adjust Analog Pfbw (7) */ |
738 | if (channel == 11 && dev->phy.is_40mhz) | 794 | if (channel == 11 && dev->phy.is_40mhz) |
@@ -778,6 +834,62 @@ static void b43_nphy_spur_workaround(struct b43_wldev *dev) | |||
778 | b43_nphy_stay_in_carrier_search(dev, 0); | 834 | b43_nphy_stay_in_carrier_search(dev, 0); |
779 | } | 835 | } |
780 | 836 | ||
837 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/AdjustLnaGainTbl */ | ||
838 | static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev) | ||
839 | { | ||
840 | struct b43_phy_n *nphy = dev->phy.n; | ||
841 | |||
842 | u8 i; | ||
843 | s16 tmp; | ||
844 | u16 data[4]; | ||
845 | s16 gain[2]; | ||
846 | u16 minmax[2]; | ||
847 | u16 lna_gain[4] = { -2, 10, 19, 25 }; | ||
848 | |||
849 | if (nphy->hang_avoid) | ||
850 | b43_nphy_stay_in_carrier_search(dev, 1); | ||
851 | |||
852 | if (nphy->gain_boost) { | ||
853 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { | ||
854 | gain[0] = 6; | ||
855 | gain[1] = 6; | ||
856 | } else { | ||
857 | tmp = 40370 - 315 * nphy->radio_chanspec.channel; | ||
858 | gain[0] = ((tmp >> 13) + ((tmp >> 12) & 1)); | ||
859 | tmp = 23242 - 224 * nphy->radio_chanspec.channel; | ||
860 | gain[1] = ((tmp >> 13) + ((tmp >> 12) & 1)); | ||
861 | } | ||
862 | } else { | ||
863 | gain[0] = 0; | ||
864 | gain[1] = 0; | ||
865 | } | ||
866 | |||
867 | for (i = 0; i < 2; i++) { | ||
868 | if (nphy->elna_gain_config) { | ||
869 | data[0] = 19 + gain[i]; | ||
870 | data[1] = 25 + gain[i]; | ||
871 | data[2] = 25 + gain[i]; | ||
872 | data[3] = 25 + gain[i]; | ||
873 | } else { | ||
874 | data[0] = lna_gain[0] + gain[i]; | ||
875 | data[1] = lna_gain[1] + gain[i]; | ||
876 | data[2] = lna_gain[2] + gain[i]; | ||
877 | data[3] = lna_gain[3] + gain[i]; | ||
878 | } | ||
879 | b43_ntab_write_bulk(dev, B43_NTAB16(10, 8), 4, data); | ||
880 | |||
881 | minmax[i] = 23 + gain[i]; | ||
882 | } | ||
883 | |||
884 | b43_phy_maskset(dev, B43_NPHY_C1_MINMAX_GAIN, ~B43_NPHY_C1_MINGAIN, | ||
885 | minmax[0] << B43_NPHY_C1_MINGAIN_SHIFT); | ||
886 | b43_phy_maskset(dev, B43_NPHY_C2_MINMAX_GAIN, ~B43_NPHY_C2_MINGAIN, | ||
887 | minmax[1] << B43_NPHY_C2_MINGAIN_SHIFT); | ||
888 | |||
889 | if (nphy->hang_avoid) | ||
890 | b43_nphy_stay_in_carrier_search(dev, 0); | ||
891 | } | ||
892 | |||
781 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */ | 893 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */ |
782 | static void b43_nphy_gain_crtl_workarounds(struct b43_wldev *dev) | 894 | static void b43_nphy_gain_crtl_workarounds(struct b43_wldev *dev) |
783 | { | 895 | { |
@@ -862,7 +974,7 @@ static void b43_nphy_gain_crtl_workarounds(struct b43_wldev *dev) | |||
862 | b43_phy_write(dev, B43_NPHY_TABLE_DATALO, | 974 | b43_phy_write(dev, B43_NPHY_TABLE_DATALO, |
863 | (code << 8 | 0x7C)); | 975 | (code << 8 | 0x7C)); |
864 | 976 | ||
865 | /* TODO: b43_nphy_adjust_lna_gain_table(dev); */ | 977 | b43_nphy_adjust_lna_gain_table(dev); |
866 | 978 | ||
867 | if (nphy->elna_gain_config) { | 979 | if (nphy->elna_gain_config) { |
868 | b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x0808); | 980 | b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x0808); |
@@ -1969,12 +2081,12 @@ static void b43_nphy_restore_rssi_cal(struct b43_wldev *dev) | |||
1969 | u16 *rssical_phy_regs = NULL; | 2081 | u16 *rssical_phy_regs = NULL; |
1970 | 2082 | ||
1971 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { | 2083 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { |
1972 | if (!nphy->rssical_chanspec_2G) | 2084 | if (b43_empty_chanspec(&nphy->rssical_chanspec_2G)) |
1973 | return; | 2085 | return; |
1974 | rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G; | 2086 | rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G; |
1975 | rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G; | 2087 | rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G; |
1976 | } else { | 2088 | } else { |
1977 | if (!nphy->rssical_chanspec_5G) | 2089 | if (b43_empty_chanspec(&nphy->rssical_chanspec_5G)) |
1978 | return; | 2090 | return; |
1979 | rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G; | 2091 | rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G; |
1980 | rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G; | 2092 | rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G; |
@@ -2394,7 +2506,7 @@ static void b43_nphy_save_cal(struct b43_wldev *dev) | |||
2394 | 2506 | ||
2395 | struct b43_phy_n_iq_comp *rxcal_coeffs = NULL; | 2507 | struct b43_phy_n_iq_comp *rxcal_coeffs = NULL; |
2396 | u16 *txcal_radio_regs = NULL; | 2508 | u16 *txcal_radio_regs = NULL; |
2397 | u8 *iqcal_chanspec; | 2509 | struct b43_chanspec *iqcal_chanspec; |
2398 | u16 *table = NULL; | 2510 | u16 *table = NULL; |
2399 | 2511 | ||
2400 | if (nphy->hang_avoid) | 2512 | if (nphy->hang_avoid) |
@@ -2450,12 +2562,12 @@ static void b43_nphy_restore_cal(struct b43_wldev *dev) | |||
2450 | struct b43_phy_n_iq_comp *rxcal_coeffs = NULL; | 2562 | struct b43_phy_n_iq_comp *rxcal_coeffs = NULL; |
2451 | 2563 | ||
2452 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { | 2564 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { |
2453 | if (nphy->iqcal_chanspec_2G == 0) | 2565 | if (b43_empty_chanspec(&nphy->iqcal_chanspec_2G)) |
2454 | return; | 2566 | return; |
2455 | table = nphy->cal_cache.txcal_coeffs_2G; | 2567 | table = nphy->cal_cache.txcal_coeffs_2G; |
2456 | loft = &nphy->cal_cache.txcal_coeffs_2G[5]; | 2568 | loft = &nphy->cal_cache.txcal_coeffs_2G[5]; |
2457 | } else { | 2569 | } else { |
2458 | if (nphy->iqcal_chanspec_5G == 0) | 2570 | if (b43_empty_chanspec(&nphy->iqcal_chanspec_5G)) |
2459 | return; | 2571 | return; |
2460 | table = nphy->cal_cache.txcal_coeffs_5G; | 2572 | table = nphy->cal_cache.txcal_coeffs_5G; |
2461 | loft = &nphy->cal_cache.txcal_coeffs_5G[5]; | 2573 | loft = &nphy->cal_cache.txcal_coeffs_5G[5]; |
@@ -2688,7 +2800,7 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev, | |||
2688 | } | 2800 | } |
2689 | b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4, | 2801 | b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4, |
2690 | buffer); | 2802 | buffer); |
2691 | b43_ntab_write_bulk(dev, B43_NTAB16(15, 101), 2, | 2803 | b43_ntab_read_bulk(dev, B43_NTAB16(15, 101), 2, |
2692 | buffer); | 2804 | buffer); |
2693 | b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2, | 2805 | b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2, |
2694 | buffer); | 2806 | buffer); |
@@ -2700,8 +2812,7 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev, | |||
2700 | b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length, | 2812 | b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length, |
2701 | nphy->txiqlocal_bestc); | 2813 | nphy->txiqlocal_bestc); |
2702 | nphy->txiqlocal_coeffsvalid = true; | 2814 | nphy->txiqlocal_coeffsvalid = true; |
2703 | /* TODO: Set nphy->txiqlocal_chanspec to | 2815 | nphy->txiqlocal_chanspec = nphy->radio_chanspec; |
2704 | the current channel */ | ||
2705 | } else { | 2816 | } else { |
2706 | length = 11; | 2817 | length = 11; |
2707 | if (dev->phy.rev < 3) | 2818 | if (dev->phy.rev < 3) |
@@ -2736,7 +2847,8 @@ static void b43_nphy_reapply_tx_cal_coeffs(struct b43_wldev *dev) | |||
2736 | u16 buffer[7]; | 2847 | u16 buffer[7]; |
2737 | bool equal = true; | 2848 | bool equal = true; |
2738 | 2849 | ||
2739 | if (!nphy->txiqlocal_coeffsvalid || 1 /* FIXME */) | 2850 | if (!nphy->txiqlocal_coeffsvalid || |
2851 | b43_eq_chanspecs(&nphy->txiqlocal_chanspec, &nphy->radio_chanspec)) | ||
2740 | return; | 2852 | return; |
2741 | 2853 | ||
2742 | b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer); | 2854 | b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer); |
@@ -3091,9 +3203,11 @@ int b43_phy_initn(struct b43_wldev *dev) | |||
3091 | do_rssi_cal = false; | 3203 | do_rssi_cal = false; |
3092 | if (phy->rev >= 3) { | 3204 | if (phy->rev >= 3) { |
3093 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) | 3205 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) |
3094 | do_rssi_cal = (nphy->rssical_chanspec_2G == 0); | 3206 | do_rssi_cal = |
3207 | b43_empty_chanspec(&nphy->rssical_chanspec_2G); | ||
3095 | else | 3208 | else |
3096 | do_rssi_cal = (nphy->rssical_chanspec_5G == 0); | 3209 | do_rssi_cal = |
3210 | b43_empty_chanspec(&nphy->rssical_chanspec_5G); | ||
3097 | 3211 | ||
3098 | if (do_rssi_cal) | 3212 | if (do_rssi_cal) |
3099 | b43_nphy_rssi_cal(dev); | 3213 | b43_nphy_rssi_cal(dev); |
@@ -3105,9 +3219,9 @@ int b43_phy_initn(struct b43_wldev *dev) | |||
3105 | 3219 | ||
3106 | if (!((nphy->measure_hold & 0x6) != 0)) { | 3220 | if (!((nphy->measure_hold & 0x6) != 0)) { |
3107 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) | 3221 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) |
3108 | do_cal = (nphy->iqcal_chanspec_2G == 0); | 3222 | do_cal = b43_empty_chanspec(&nphy->iqcal_chanspec_2G); |
3109 | else | 3223 | else |
3110 | do_cal = (nphy->iqcal_chanspec_5G == 0); | 3224 | do_cal = b43_empty_chanspec(&nphy->iqcal_chanspec_5G); |
3111 | 3225 | ||
3112 | if (nphy->mute) | 3226 | if (nphy->mute) |
3113 | do_cal = false; | 3227 | do_cal = false; |
@@ -3116,7 +3230,7 @@ int b43_phy_initn(struct b43_wldev *dev) | |||
3116 | target = b43_nphy_get_tx_gains(dev); | 3230 | target = b43_nphy_get_tx_gains(dev); |
3117 | 3231 | ||
3118 | if (nphy->antsel_type == 2) | 3232 | if (nphy->antsel_type == 2) |
3119 | ;/*TODO NPHY Superswitch Init with argument 1*/ | 3233 | b43_nphy_superswitch_init(dev, true); |
3120 | if (nphy->perical != 2) { | 3234 | if (nphy->perical != 2) { |
3121 | b43_nphy_rssi_cal(dev); | 3235 | b43_nphy_rssi_cal(dev); |
3122 | if (phy->rev >= 3) { | 3236 | if (phy->rev >= 3) { |
@@ -3154,6 +3268,133 @@ int b43_phy_initn(struct b43_wldev *dev) | |||
3154 | return 0; | 3268 | return 0; |
3155 | } | 3269 | } |
3156 | 3270 | ||
3271 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ChanspecSetup */ | ||
3272 | static void b43_nphy_chanspec_setup(struct b43_wldev *dev, | ||
3273 | const struct b43_phy_n_sfo_cfg *e, | ||
3274 | struct b43_chanspec chanspec) | ||
3275 | { | ||
3276 | struct b43_phy *phy = &dev->phy; | ||
3277 | struct b43_phy_n *nphy = dev->phy.n; | ||
3278 | |||
3279 | u16 tmp; | ||
3280 | u32 tmp32; | ||
3281 | |||
3282 | tmp = b43_phy_read(dev, B43_NPHY_BANDCTL) & B43_NPHY_BANDCTL_5GHZ; | ||
3283 | if (chanspec.b_freq == 1 && tmp == 0) { | ||
3284 | tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR); | ||
3285 | b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4); | ||
3286 | b43_phy_set(dev, B43_PHY_B_BBCFG, 0xC000); | ||
3287 | b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32); | ||
3288 | b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ); | ||
3289 | } else if (chanspec.b_freq == 1) { | ||
3290 | b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ); | ||
3291 | tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR); | ||
3292 | b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4); | ||
3293 | b43_phy_mask(dev, B43_PHY_B_BBCFG, (u16)~0xC000); | ||
3294 | b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32); | ||
3295 | } | ||
3296 | |||
3297 | b43_chantab_phy_upload(dev, e); | ||
3298 | |||
3299 | tmp = chanspec.channel; | ||
3300 | if (chanspec.b_freq == 1) | ||
3301 | tmp |= 0x0100; | ||
3302 | if (chanspec.b_width == 3) | ||
3303 | tmp |= 0x0200; | ||
3304 | b43_shm_write16(dev, B43_SHM_SHARED, 0xA0, tmp); | ||
3305 | |||
3306 | if (nphy->radio_chanspec.channel == 14) { | ||
3307 | b43_nphy_classifier(dev, 2, 0); | ||
3308 | b43_phy_set(dev, B43_PHY_B_TEST, 0x0800); | ||
3309 | } else { | ||
3310 | b43_nphy_classifier(dev, 2, 2); | ||
3311 | if (chanspec.b_freq == 2) | ||
3312 | b43_phy_mask(dev, B43_PHY_B_TEST, ~0x840); | ||
3313 | } | ||
3314 | |||
3315 | if (nphy->txpwrctrl) | ||
3316 | b43_nphy_tx_power_fix(dev); | ||
3317 | |||
3318 | if (dev->phy.rev < 3) | ||
3319 | b43_nphy_adjust_lna_gain_table(dev); | ||
3320 | |||
3321 | b43_nphy_tx_lp_fbw(dev); | ||
3322 | |||
3323 | if (dev->phy.rev >= 3 && 0) { | ||
3324 | /* TODO */ | ||
3325 | } | ||
3326 | |||
3327 | b43_phy_write(dev, B43_NPHY_NDATAT_DUP40, 0x3830); | ||
3328 | |||
3329 | if (phy->rev >= 3) | ||
3330 | b43_nphy_spur_workaround(dev); | ||
3331 | } | ||
3332 | |||
3333 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetChanspec */ | ||
3334 | static int b43_nphy_set_chanspec(struct b43_wldev *dev, | ||
3335 | struct b43_chanspec chanspec) | ||
3336 | { | ||
3337 | struct b43_phy_n *nphy = dev->phy.n; | ||
3338 | |||
3339 | const struct b43_nphy_channeltab_entry_rev2 *tabent_r2; | ||
3340 | const struct b43_nphy_channeltab_entry_rev3 *tabent_r3; | ||
3341 | |||
3342 | u8 tmp; | ||
3343 | u8 channel = chanspec.channel; | ||
3344 | |||
3345 | if (dev->phy.rev >= 3) { | ||
3346 | /* TODO */ | ||
3347 | tabent_r3 = NULL; | ||
3348 | if (!tabent_r3) | ||
3349 | return -ESRCH; | ||
3350 | } else { | ||
3351 | tabent_r2 = b43_nphy_get_chantabent_rev2(dev, channel); | ||
3352 | if (!tabent_r2) | ||
3353 | return -ESRCH; | ||
3354 | } | ||
3355 | |||
3356 | nphy->radio_chanspec = chanspec; | ||
3357 | |||
3358 | if (chanspec.b_width != nphy->b_width) | ||
3359 | ; /* TODO: BMAC BW Set (chanspec.b_width) */ | ||
3360 | |||
3361 | /* TODO: use defines */ | ||
3362 | if (chanspec.b_width == 3) { | ||
3363 | if (chanspec.sideband == 2) | ||
3364 | b43_phy_set(dev, B43_NPHY_RXCTL, | ||
3365 | B43_NPHY_RXCTL_BSELU20); | ||
3366 | else | ||
3367 | b43_phy_mask(dev, B43_NPHY_RXCTL, | ||
3368 | ~B43_NPHY_RXCTL_BSELU20); | ||
3369 | } | ||
3370 | |||
3371 | if (dev->phy.rev >= 3) { | ||
3372 | tmp = (chanspec.b_freq == 1) ? 4 : 0; | ||
3373 | b43_radio_maskset(dev, 0x08, 0xFFFB, tmp); | ||
3374 | /* TODO: PHY Radio2056 Setup (dev, tabent_r3); */ | ||
3375 | b43_nphy_chanspec_setup(dev, &(tabent_r3->phy_regs), chanspec); | ||
3376 | } else { | ||
3377 | tmp = (chanspec.b_freq == 1) ? 0x0020 : 0x0050; | ||
3378 | b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, tmp); | ||
3379 | b43_radio_2055_setup(dev, tabent_r2); | ||
3380 | b43_nphy_chanspec_setup(dev, &(tabent_r2->phy_regs), chanspec); | ||
3381 | } | ||
3382 | |||
3383 | return 0; | ||
3384 | } | ||
3385 | |||
3386 | /* Tune the hardware to a new channel */ | ||
3387 | static int nphy_channel_switch(struct b43_wldev *dev, unsigned int channel) | ||
3388 | { | ||
3389 | struct b43_phy_n *nphy = dev->phy.n; | ||
3390 | |||
3391 | struct b43_chanspec chanspec; | ||
3392 | chanspec = nphy->radio_chanspec; | ||
3393 | chanspec.channel = channel; | ||
3394 | |||
3395 | return b43_nphy_set_chanspec(dev, chanspec); | ||
3396 | } | ||
3397 | |||
3157 | static int b43_nphy_op_allocate(struct b43_wldev *dev) | 3398 | static int b43_nphy_op_allocate(struct b43_wldev *dev) |
3158 | { | 3399 | { |
3159 | struct b43_phy_n *nphy; | 3400 | struct b43_phy_n *nphy; |
@@ -3242,9 +3483,43 @@ static void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value) | |||
3242 | b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value); | 3483 | b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value); |
3243 | } | 3484 | } |
3244 | 3485 | ||
3486 | /* http://bcm-v4.sipsolutions.net/802.11/Radio/Switch%20Radio */ | ||
3245 | static void b43_nphy_op_software_rfkill(struct b43_wldev *dev, | 3487 | static void b43_nphy_op_software_rfkill(struct b43_wldev *dev, |
3246 | bool blocked) | 3488 | bool blocked) |
3247 | {//TODO | 3489 | { |
3490 | struct b43_phy_n *nphy = dev->phy.n; | ||
3491 | |||
3492 | if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED) | ||
3493 | b43err(dev->wl, "MAC not suspended\n"); | ||
3494 | |||
3495 | if (blocked) { | ||
3496 | b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, | ||
3497 | ~B43_NPHY_RFCTL_CMD_CHIP0PU); | ||
3498 | if (dev->phy.rev >= 3) { | ||
3499 | b43_radio_mask(dev, 0x09, ~0x2); | ||
3500 | |||
3501 | b43_radio_write(dev, 0x204D, 0); | ||
3502 | b43_radio_write(dev, 0x2053, 0); | ||
3503 | b43_radio_write(dev, 0x2058, 0); | ||
3504 | b43_radio_write(dev, 0x205E, 0); | ||
3505 | b43_radio_mask(dev, 0x2062, ~0xF0); | ||
3506 | b43_radio_write(dev, 0x2064, 0); | ||
3507 | |||
3508 | b43_radio_write(dev, 0x304D, 0); | ||
3509 | b43_radio_write(dev, 0x3053, 0); | ||
3510 | b43_radio_write(dev, 0x3058, 0); | ||
3511 | b43_radio_write(dev, 0x305E, 0); | ||
3512 | b43_radio_mask(dev, 0x3062, ~0xF0); | ||
3513 | b43_radio_write(dev, 0x3064, 0); | ||
3514 | } | ||
3515 | } else { | ||
3516 | if (dev->phy.rev >= 3) { | ||
3517 | b43_radio_init2056(dev); | ||
3518 | b43_nphy_set_chanspec(dev, nphy->radio_chanspec); | ||
3519 | } else { | ||
3520 | b43_radio_init2055(dev); | ||
3521 | } | ||
3522 | } | ||
3248 | } | 3523 | } |
3249 | 3524 | ||
3250 | static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on) | 3525 | static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on) |
diff --git a/drivers/net/wireless/b43/phy_n.h b/drivers/net/wireless/b43/phy_n.h index 403aad3f894f..8b6d570dd0aa 100644 --- a/drivers/net/wireless/b43/phy_n.h +++ b/drivers/net/wireless/b43/phy_n.h | |||
@@ -711,6 +711,8 @@ | |||
711 | #define B43_NPHY_PAPD_EN1 B43_PHY_N(0x29B) /* PAPD Enable1 TBD */ | 711 | #define B43_NPHY_PAPD_EN1 B43_PHY_N(0x29B) /* PAPD Enable1 TBD */ |
712 | #define B43_NPHY_EPS_TABLE_ADJ1 B43_PHY_N(0x29C) /* EPS Table Adj1 TBD */ | 712 | #define B43_NPHY_EPS_TABLE_ADJ1 B43_PHY_N(0x29C) /* EPS Table Adj1 TBD */ |
713 | 713 | ||
714 | #define B43_PHY_B_BBCFG B43_PHY_N_BMODE(0x001) /* BB config */ | ||
715 | #define B43_PHY_B_TEST B43_PHY_N_BMODE(0x00A) | ||
714 | 716 | ||
715 | 717 | ||
716 | /* Broadcom 2055 radio registers */ | 718 | /* Broadcom 2055 radio registers */ |
@@ -924,6 +926,13 @@ | |||
924 | 926 | ||
925 | struct b43_wldev; | 927 | struct b43_wldev; |
926 | 928 | ||
929 | struct b43_chanspec { | ||
930 | u8 channel; | ||
931 | u8 sideband; | ||
932 | u8 b_width; | ||
933 | u8 b_freq; | ||
934 | }; | ||
935 | |||
927 | struct b43_phy_n_iq_comp { | 936 | struct b43_phy_n_iq_comp { |
928 | s16 a0; | 937 | s16 a0; |
929 | s16 b0; | 938 | s16 b0; |
@@ -975,7 +984,8 @@ struct b43_phy_n { | |||
975 | u16 papd_epsilon_offset[2]; | 984 | u16 papd_epsilon_offset[2]; |
976 | s32 preamble_override; | 985 | s32 preamble_override; |
977 | u32 bb_mult_save; | 986 | u32 bb_mult_save; |
978 | u16 radio_chanspec; | 987 | u8 b_width; |
988 | struct b43_chanspec radio_chanspec; | ||
979 | 989 | ||
980 | bool gain_boost; | 990 | bool gain_boost; |
981 | bool elna_gain_config; | 991 | bool elna_gain_config; |
@@ -991,6 +1001,7 @@ struct b43_phy_n { | |||
991 | u16 txiqlocal_bestc[11]; | 1001 | u16 txiqlocal_bestc[11]; |
992 | bool txiqlocal_coeffsvalid; | 1002 | bool txiqlocal_coeffsvalid; |
993 | struct b43_phy_n_txpwrindex txpwrindex[2]; | 1003 | struct b43_phy_n_txpwrindex txpwrindex[2]; |
1004 | struct b43_chanspec txiqlocal_chanspec; | ||
994 | 1005 | ||
995 | u8 txrx_chain; | 1006 | u8 txrx_chain; |
996 | u16 tx_rx_cal_phy_saveregs[11]; | 1007 | u16 tx_rx_cal_phy_saveregs[11]; |
@@ -1006,12 +1017,12 @@ struct b43_phy_n { | |||
1006 | bool gband_spurwar_en; | 1017 | bool gband_spurwar_en; |
1007 | 1018 | ||
1008 | bool ipa2g_on; | 1019 | bool ipa2g_on; |
1009 | u8 iqcal_chanspec_2G; | 1020 | struct b43_chanspec iqcal_chanspec_2G; |
1010 | u8 rssical_chanspec_2G; | 1021 | struct b43_chanspec rssical_chanspec_2G; |
1011 | 1022 | ||
1012 | bool ipa5g_on; | 1023 | bool ipa5g_on; |
1013 | u8 iqcal_chanspec_5G; | 1024 | struct b43_chanspec iqcal_chanspec_5G; |
1014 | u8 rssical_chanspec_5G; | 1025 | struct b43_chanspec rssical_chanspec_5G; |
1015 | 1026 | ||
1016 | struct b43_phy_n_rssical_cache rssical_cache; | 1027 | struct b43_phy_n_rssical_cache rssical_cache; |
1017 | struct b43_phy_n_cal_cache cal_cache; | 1028 | struct b43_phy_n_cal_cache cal_cache; |
diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c index a00d509150f7..d96e870ab8fe 100644 --- a/drivers/net/wireless/b43/tables_nphy.c +++ b/drivers/net/wireless/b43/tables_nphy.c | |||
@@ -318,14 +318,14 @@ void b2055_upload_inittab(struct b43_wldev *dev, | |||
318 | .radio_c2_tx_mxbgtrim = r21 | 318 | .radio_c2_tx_mxbgtrim = r21 |
319 | 319 | ||
320 | #define PHYREGS(r0, r1, r2, r3, r4, r5) \ | 320 | #define PHYREGS(r0, r1, r2, r3, r4, r5) \ |
321 | .phy_bw1a = r0, \ | 321 | .phy_regs.phy_bw1a = r0, \ |
322 | .phy_bw2 = r1, \ | 322 | .phy_regs.phy_bw2 = r1, \ |
323 | .phy_bw3 = r2, \ | 323 | .phy_regs.phy_bw3 = r2, \ |
324 | .phy_bw4 = r3, \ | 324 | .phy_regs.phy_bw4 = r3, \ |
325 | .phy_bw5 = r4, \ | 325 | .phy_regs.phy_bw5 = r4, \ |
326 | .phy_bw6 = r5 | 326 | .phy_regs.phy_bw6 = r5 |
327 | 327 | ||
328 | static const struct b43_nphy_channeltab_entry b43_nphy_channeltab[] = { | 328 | static const struct b43_nphy_channeltab_entry_rev2 b43_nphy_channeltab[] = { |
329 | { .channel = 184, | 329 | { .channel = 184, |
330 | .freq = 4920, /* MHz */ | 330 | .freq = 4920, /* MHz */ |
331 | .unk2 = 3280, | 331 | .unk2 = 3280, |
@@ -1320,10 +1320,10 @@ static const struct b43_nphy_channeltab_entry b43_nphy_channeltab[] = { | |||
1320 | }, | 1320 | }, |
1321 | }; | 1321 | }; |
1322 | 1322 | ||
1323 | const struct b43_nphy_channeltab_entry * | 1323 | const struct b43_nphy_channeltab_entry_rev2 * |
1324 | b43_nphy_get_chantabent(struct b43_wldev *dev, u8 channel) | 1324 | b43_nphy_get_chantabent_rev2(struct b43_wldev *dev, u8 channel) |
1325 | { | 1325 | { |
1326 | const struct b43_nphy_channeltab_entry *e; | 1326 | const struct b43_nphy_channeltab_entry_rev2 *e; |
1327 | unsigned int i; | 1327 | unsigned int i; |
1328 | 1328 | ||
1329 | for (i = 0; i < ARRAY_SIZE(b43_nphy_channeltab); i++) { | 1329 | for (i = 0; i < ARRAY_SIZE(b43_nphy_channeltab); i++) { |
diff --git a/drivers/net/wireless/b43/tables_nphy.h b/drivers/net/wireless/b43/tables_nphy.h index 9c1c6ecd3672..8fc1da9f8fe5 100644 --- a/drivers/net/wireless/b43/tables_nphy.h +++ b/drivers/net/wireless/b43/tables_nphy.h | |||
@@ -4,9 +4,22 @@ | |||
4 | #include <linux/types.h> | 4 | #include <linux/types.h> |
5 | 5 | ||
6 | 6 | ||
7 | struct b43_nphy_channeltab_entry { | 7 | struct b43_phy_n_sfo_cfg { |
8 | u16 phy_bw1a; | ||
9 | u16 phy_bw2; | ||
10 | u16 phy_bw3; | ||
11 | u16 phy_bw4; | ||
12 | u16 phy_bw5; | ||
13 | u16 phy_bw6; | ||
14 | }; | ||
15 | |||
16 | struct b43_nphy_channeltab_entry_rev2 { | ||
8 | /* The channel number */ | 17 | /* The channel number */ |
9 | u8 channel; | 18 | u8 channel; |
19 | /* The channel frequency in MHz */ | ||
20 | u16 freq; | ||
21 | /* An unknown value */ | ||
22 | u16 unk2; | ||
10 | /* Radio register values on channelswitch */ | 23 | /* Radio register values on channelswitch */ |
11 | u8 radio_pll_ref; | 24 | u8 radio_pll_ref; |
12 | u8 radio_rf_pllmod0; | 25 | u8 radio_rf_pllmod0; |
@@ -31,16 +44,18 @@ struct b43_nphy_channeltab_entry { | |||
31 | u8 radio_c2_tx_pgapadtn; | 44 | u8 radio_c2_tx_pgapadtn; |
32 | u8 radio_c2_tx_mxbgtrim; | 45 | u8 radio_c2_tx_mxbgtrim; |
33 | /* PHY register values on channelswitch */ | 46 | /* PHY register values on channelswitch */ |
34 | u16 phy_bw1a; | 47 | struct b43_phy_n_sfo_cfg phy_regs; |
35 | u16 phy_bw2; | 48 | }; |
36 | u16 phy_bw3; | 49 | |
37 | u16 phy_bw4; | 50 | struct b43_nphy_channeltab_entry_rev3 { |
38 | u16 phy_bw5; | 51 | /* The channel number */ |
39 | u16 phy_bw6; | 52 | u8 channel; |
40 | /* The channel frequency in MHz */ | 53 | /* The channel frequency in MHz */ |
41 | u16 freq; | 54 | u16 freq; |
42 | /* An unknown value */ | 55 | /* Radio register values on channelswitch */ |
43 | u16 unk2; | 56 | /* TODO */ |
57 | /* PHY register values on channelswitch */ | ||
58 | struct b43_phy_n_sfo_cfg phy_regs; | ||
44 | }; | 59 | }; |
45 | 60 | ||
46 | 61 | ||
@@ -77,8 +92,8 @@ void b2055_upload_inittab(struct b43_wldev *dev, | |||
77 | 92 | ||
78 | /* Get the NPHY Channel Switch Table entry for a channel number. | 93 | /* Get the NPHY Channel Switch Table entry for a channel number. |
79 | * Returns NULL on failure to find an entry. */ | 94 | * Returns NULL on failure to find an entry. */ |
80 | const struct b43_nphy_channeltab_entry * | 95 | const struct b43_nphy_channeltab_entry_rev2 * |
81 | b43_nphy_get_chantabent(struct b43_wldev *dev, u8 channel); | 96 | b43_nphy_get_chantabent_rev2(struct b43_wldev *dev, u8 channel); |
82 | 97 | ||
83 | 98 | ||
84 | /* The N-PHY tables. */ | 99 | /* The N-PHY tables. */ |
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 9b72c45a7748..2088ac029b35 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c | |||
@@ -2140,7 +2140,7 @@ static void isr_indicate_association_lost(struct ipw2100_priv *priv, u32 status) | |||
2140 | DECLARE_SSID_BUF(ssid); | 2140 | DECLARE_SSID_BUF(ssid); |
2141 | 2141 | ||
2142 | IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | IPW_DL_ASSOC, | 2142 | IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | IPW_DL_ASSOC, |
2143 | "disassociated: '%s' %pM \n", | 2143 | "disassociated: '%s' %pM\n", |
2144 | print_ssid(ssid, priv->essid, priv->essid_len), | 2144 | print_ssid(ssid, priv->essid, priv->essid_len), |
2145 | priv->bssid); | 2145 | priv->bssid); |
2146 | 2146 | ||
@@ -3285,7 +3285,7 @@ static void ipw2100_irq_tasklet(struct ipw2100_priv *priv) | |||
3285 | 3285 | ||
3286 | if (inta & IPW2100_INTA_PARITY_ERROR) { | 3286 | if (inta & IPW2100_INTA_PARITY_ERROR) { |
3287 | printk(KERN_ERR DRV_NAME | 3287 | printk(KERN_ERR DRV_NAME |
3288 | ": ***** PARITY ERROR INTERRUPT !!!! \n"); | 3288 | ": ***** PARITY ERROR INTERRUPT !!!!\n"); |
3289 | priv->inta_other++; | 3289 | priv->inta_other++; |
3290 | write_register(dev, IPW_REG_INTA, IPW2100_INTA_PARITY_ERROR); | 3290 | write_register(dev, IPW_REG_INTA, IPW2100_INTA_PARITY_ERROR); |
3291 | } | 3291 | } |
@@ -6102,7 +6102,7 @@ static const struct net_device_ops ipw2100_netdev_ops = { | |||
6102 | .ndo_validate_addr = eth_validate_addr, | 6102 | .ndo_validate_addr = eth_validate_addr, |
6103 | }; | 6103 | }; |
6104 | 6104 | ||
6105 | /* Look into using netdev destructor to shutdown ieee80211? */ | 6105 | /* Look into using netdev destructor to shutdown libipw? */ |
6106 | 6106 | ||
6107 | static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev, | 6107 | static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev, |
6108 | void __iomem * base_addr, | 6108 | void __iomem * base_addr, |
@@ -6112,7 +6112,7 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev, | |||
6112 | struct ipw2100_priv *priv; | 6112 | struct ipw2100_priv *priv; |
6113 | struct net_device *dev; | 6113 | struct net_device *dev; |
6114 | 6114 | ||
6115 | dev = alloc_ieee80211(sizeof(struct ipw2100_priv), 0); | 6115 | dev = alloc_libipw(sizeof(struct ipw2100_priv), 0); |
6116 | if (!dev) | 6116 | if (!dev) |
6117 | return NULL; | 6117 | return NULL; |
6118 | priv = libipw_priv(dev); | 6118 | priv = libipw_priv(dev); |
@@ -6425,7 +6425,7 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, | |||
6425 | sysfs_remove_group(&pci_dev->dev.kobj, | 6425 | sysfs_remove_group(&pci_dev->dev.kobj, |
6426 | &ipw2100_attribute_group); | 6426 | &ipw2100_attribute_group); |
6427 | 6427 | ||
6428 | free_ieee80211(dev, 0); | 6428 | free_libipw(dev, 0); |
6429 | pci_set_drvdata(pci_dev, NULL); | 6429 | pci_set_drvdata(pci_dev, NULL); |
6430 | } | 6430 | } |
6431 | 6431 | ||
@@ -6483,10 +6483,10 @@ static void __devexit ipw2100_pci_remove_one(struct pci_dev *pci_dev) | |||
6483 | if (dev->base_addr) | 6483 | if (dev->base_addr) |
6484 | iounmap((void __iomem *)dev->base_addr); | 6484 | iounmap((void __iomem *)dev->base_addr); |
6485 | 6485 | ||
6486 | /* wiphy_unregister needs to be here, before free_ieee80211 */ | 6486 | /* wiphy_unregister needs to be here, before free_libipw */ |
6487 | wiphy_unregister(priv->ieee->wdev.wiphy); | 6487 | wiphy_unregister(priv->ieee->wdev.wiphy); |
6488 | kfree(priv->ieee->bg_band.channels); | 6488 | kfree(priv->ieee->bg_band.channels); |
6489 | free_ieee80211(dev, 0); | 6489 | free_libipw(dev, 0); |
6490 | } | 6490 | } |
6491 | 6491 | ||
6492 | pci_release_regions(pci_dev); | 6492 | pci_release_regions(pci_dev); |
@@ -6753,7 +6753,7 @@ static int ipw2100_wx_set_freq(struct net_device *dev, | |||
6753 | err = -EOPNOTSUPP; | 6753 | err = -EOPNOTSUPP; |
6754 | goto done; | 6754 | goto done; |
6755 | } else { /* Set the channel */ | 6755 | } else { /* Set the channel */ |
6756 | IPW_DEBUG_WX("SET Freq/Channel -> %d \n", fwrq->m); | 6756 | IPW_DEBUG_WX("SET Freq/Channel -> %d\n", fwrq->m); |
6757 | err = ipw2100_set_channel(priv, fwrq->m, 0); | 6757 | err = ipw2100_set_channel(priv, fwrq->m, 0); |
6758 | } | 6758 | } |
6759 | 6759 | ||
@@ -6782,7 +6782,7 @@ static int ipw2100_wx_get_freq(struct net_device *dev, | |||
6782 | else | 6782 | else |
6783 | wrqu->freq.m = 0; | 6783 | wrqu->freq.m = 0; |
6784 | 6784 | ||
6785 | IPW_DEBUG_WX("GET Freq/Channel -> %d \n", priv->channel); | 6785 | IPW_DEBUG_WX("GET Freq/Channel -> %d\n", priv->channel); |
6786 | return 0; | 6786 | return 0; |
6787 | 6787 | ||
6788 | } | 6788 | } |
@@ -6794,7 +6794,7 @@ static int ipw2100_wx_set_mode(struct net_device *dev, | |||
6794 | struct ipw2100_priv *priv = libipw_priv(dev); | 6794 | struct ipw2100_priv *priv = libipw_priv(dev); |
6795 | int err = 0; | 6795 | int err = 0; |
6796 | 6796 | ||
6797 | IPW_DEBUG_WX("SET Mode -> %d \n", wrqu->mode); | 6797 | IPW_DEBUG_WX("SET Mode -> %d\n", wrqu->mode); |
6798 | 6798 | ||
6799 | if (wrqu->mode == priv->ieee->iw_mode) | 6799 | if (wrqu->mode == priv->ieee->iw_mode) |
6800 | return 0; | 6800 | return 0; |
@@ -7149,7 +7149,7 @@ static int ipw2100_wx_set_nick(struct net_device *dev, | |||
7149 | memset(priv->nick, 0, sizeof(priv->nick)); | 7149 | memset(priv->nick, 0, sizeof(priv->nick)); |
7150 | memcpy(priv->nick, extra, wrqu->data.length); | 7150 | memcpy(priv->nick, extra, wrqu->data.length); |
7151 | 7151 | ||
7152 | IPW_DEBUG_WX("SET Nickname -> %s \n", priv->nick); | 7152 | IPW_DEBUG_WX("SET Nickname -> %s\n", priv->nick); |
7153 | 7153 | ||
7154 | return 0; | 7154 | return 0; |
7155 | } | 7155 | } |
@@ -7168,7 +7168,7 @@ static int ipw2100_wx_get_nick(struct net_device *dev, | |||
7168 | memcpy(extra, priv->nick, wrqu->data.length); | 7168 | memcpy(extra, priv->nick, wrqu->data.length); |
7169 | wrqu->data.flags = 1; /* active */ | 7169 | wrqu->data.flags = 1; /* active */ |
7170 | 7170 | ||
7171 | IPW_DEBUG_WX("GET Nickname -> %s \n", extra); | 7171 | IPW_DEBUG_WX("GET Nickname -> %s\n", extra); |
7172 | 7172 | ||
7173 | return 0; | 7173 | return 0; |
7174 | } | 7174 | } |
@@ -7207,7 +7207,7 @@ static int ipw2100_wx_set_rate(struct net_device *dev, | |||
7207 | 7207 | ||
7208 | err = ipw2100_set_tx_rates(priv, rate, 0); | 7208 | err = ipw2100_set_tx_rates(priv, rate, 0); |
7209 | 7209 | ||
7210 | IPW_DEBUG_WX("SET Rate -> %04X \n", rate); | 7210 | IPW_DEBUG_WX("SET Rate -> %04X\n", rate); |
7211 | done: | 7211 | done: |
7212 | mutex_unlock(&priv->action_mutex); | 7212 | mutex_unlock(&priv->action_mutex); |
7213 | return err; | 7213 | return err; |
@@ -7258,7 +7258,7 @@ static int ipw2100_wx_get_rate(struct net_device *dev, | |||
7258 | wrqu->bitrate.value = 0; | 7258 | wrqu->bitrate.value = 0; |
7259 | } | 7259 | } |
7260 | 7260 | ||
7261 | IPW_DEBUG_WX("GET Rate -> %d \n", wrqu->bitrate.value); | 7261 | IPW_DEBUG_WX("GET Rate -> %d\n", wrqu->bitrate.value); |
7262 | 7262 | ||
7263 | done: | 7263 | done: |
7264 | mutex_unlock(&priv->action_mutex); | 7264 | mutex_unlock(&priv->action_mutex); |
@@ -7294,7 +7294,7 @@ static int ipw2100_wx_set_rts(struct net_device *dev, | |||
7294 | 7294 | ||
7295 | err = ipw2100_set_rts_threshold(priv, value); | 7295 | err = ipw2100_set_rts_threshold(priv, value); |
7296 | 7296 | ||
7297 | IPW_DEBUG_WX("SET RTS Threshold -> 0x%08X \n", value); | 7297 | IPW_DEBUG_WX("SET RTS Threshold -> 0x%08X\n", value); |
7298 | done: | 7298 | done: |
7299 | mutex_unlock(&priv->action_mutex); | 7299 | mutex_unlock(&priv->action_mutex); |
7300 | return err; | 7300 | return err; |
@@ -7316,7 +7316,7 @@ static int ipw2100_wx_get_rts(struct net_device *dev, | |||
7316 | /* If RTS is set to the default value, then it is disabled */ | 7316 | /* If RTS is set to the default value, then it is disabled */ |
7317 | wrqu->rts.disabled = (priv->rts_threshold & RTS_DISABLED) ? 1 : 0; | 7317 | wrqu->rts.disabled = (priv->rts_threshold & RTS_DISABLED) ? 1 : 0; |
7318 | 7318 | ||
7319 | IPW_DEBUG_WX("GET RTS Threshold -> 0x%08X \n", wrqu->rts.value); | 7319 | IPW_DEBUG_WX("GET RTS Threshold -> 0x%08X\n", wrqu->rts.value); |
7320 | 7320 | ||
7321 | return 0; | 7321 | return 0; |
7322 | } | 7322 | } |
@@ -7355,7 +7355,7 @@ static int ipw2100_wx_set_txpow(struct net_device *dev, | |||
7355 | 7355 | ||
7356 | err = ipw2100_set_tx_power(priv, value); | 7356 | err = ipw2100_set_tx_power(priv, value); |
7357 | 7357 | ||
7358 | IPW_DEBUG_WX("SET TX Power -> %d \n", value); | 7358 | IPW_DEBUG_WX("SET TX Power -> %d\n", value); |
7359 | 7359 | ||
7360 | done: | 7360 | done: |
7361 | mutex_unlock(&priv->action_mutex); | 7361 | mutex_unlock(&priv->action_mutex); |
@@ -7384,7 +7384,7 @@ static int ipw2100_wx_get_txpow(struct net_device *dev, | |||
7384 | 7384 | ||
7385 | wrqu->txpower.flags = IW_TXPOW_DBM; | 7385 | wrqu->txpower.flags = IW_TXPOW_DBM; |
7386 | 7386 | ||
7387 | IPW_DEBUG_WX("GET TX Power -> %d \n", wrqu->txpower.value); | 7387 | IPW_DEBUG_WX("GET TX Power -> %d\n", wrqu->txpower.value); |
7388 | 7388 | ||
7389 | return 0; | 7389 | return 0; |
7390 | } | 7390 | } |
@@ -7414,7 +7414,7 @@ static int ipw2100_wx_set_frag(struct net_device *dev, | |||
7414 | priv->frag_threshold = priv->ieee->fts; | 7414 | priv->frag_threshold = priv->ieee->fts; |
7415 | } | 7415 | } |
7416 | 7416 | ||
7417 | IPW_DEBUG_WX("SET Frag Threshold -> %d \n", priv->ieee->fts); | 7417 | IPW_DEBUG_WX("SET Frag Threshold -> %d\n", priv->ieee->fts); |
7418 | 7418 | ||
7419 | return 0; | 7419 | return 0; |
7420 | } | 7420 | } |
@@ -7432,7 +7432,7 @@ static int ipw2100_wx_get_frag(struct net_device *dev, | |||
7432 | wrqu->frag.fixed = 0; /* no auto select */ | 7432 | wrqu->frag.fixed = 0; /* no auto select */ |
7433 | wrqu->frag.disabled = (priv->frag_threshold & FRAG_DISABLED) ? 1 : 0; | 7433 | wrqu->frag.disabled = (priv->frag_threshold & FRAG_DISABLED) ? 1 : 0; |
7434 | 7434 | ||
7435 | IPW_DEBUG_WX("GET Frag Threshold -> %d \n", wrqu->frag.value); | 7435 | IPW_DEBUG_WX("GET Frag Threshold -> %d\n", wrqu->frag.value); |
7436 | 7436 | ||
7437 | return 0; | 7437 | return 0; |
7438 | } | 7438 | } |
@@ -7458,14 +7458,14 @@ static int ipw2100_wx_set_retry(struct net_device *dev, | |||
7458 | 7458 | ||
7459 | if (wrqu->retry.flags & IW_RETRY_SHORT) { | 7459 | if (wrqu->retry.flags & IW_RETRY_SHORT) { |
7460 | err = ipw2100_set_short_retry(priv, wrqu->retry.value); | 7460 | err = ipw2100_set_short_retry(priv, wrqu->retry.value); |
7461 | IPW_DEBUG_WX("SET Short Retry Limit -> %d \n", | 7461 | IPW_DEBUG_WX("SET Short Retry Limit -> %d\n", |
7462 | wrqu->retry.value); | 7462 | wrqu->retry.value); |
7463 | goto done; | 7463 | goto done; |
7464 | } | 7464 | } |
7465 | 7465 | ||
7466 | if (wrqu->retry.flags & IW_RETRY_LONG) { | 7466 | if (wrqu->retry.flags & IW_RETRY_LONG) { |
7467 | err = ipw2100_set_long_retry(priv, wrqu->retry.value); | 7467 | err = ipw2100_set_long_retry(priv, wrqu->retry.value); |
7468 | IPW_DEBUG_WX("SET Long Retry Limit -> %d \n", | 7468 | IPW_DEBUG_WX("SET Long Retry Limit -> %d\n", |
7469 | wrqu->retry.value); | 7469 | wrqu->retry.value); |
7470 | goto done; | 7470 | goto done; |
7471 | } | 7471 | } |
@@ -7474,7 +7474,7 @@ static int ipw2100_wx_set_retry(struct net_device *dev, | |||
7474 | if (!err) | 7474 | if (!err) |
7475 | err = ipw2100_set_long_retry(priv, wrqu->retry.value); | 7475 | err = ipw2100_set_long_retry(priv, wrqu->retry.value); |
7476 | 7476 | ||
7477 | IPW_DEBUG_WX("SET Both Retry Limits -> %d \n", wrqu->retry.value); | 7477 | IPW_DEBUG_WX("SET Both Retry Limits -> %d\n", wrqu->retry.value); |
7478 | 7478 | ||
7479 | done: | 7479 | done: |
7480 | mutex_unlock(&priv->action_mutex); | 7480 | mutex_unlock(&priv->action_mutex); |
@@ -7508,7 +7508,7 @@ static int ipw2100_wx_get_retry(struct net_device *dev, | |||
7508 | wrqu->retry.value = priv->short_retry_limit; | 7508 | wrqu->retry.value = priv->short_retry_limit; |
7509 | } | 7509 | } |
7510 | 7510 | ||
7511 | IPW_DEBUG_WX("GET Retry -> %d \n", wrqu->retry.value); | 7511 | IPW_DEBUG_WX("GET Retry -> %d\n", wrqu->retry.value); |
7512 | 7512 | ||
7513 | return 0; | 7513 | return 0; |
7514 | } | 7514 | } |
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 5c7aa1b1eb56..9e2ae8f3ecb0 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c | |||
@@ -458,7 +458,7 @@ static u8 _ipw_read_reg8(struct ipw_priv *priv, u32 reg) | |||
458 | { | 458 | { |
459 | u32 word; | 459 | u32 word; |
460 | _ipw_write32(priv, IPW_INDIRECT_ADDR, reg & IPW_INDIRECT_ADDR_MASK); | 460 | _ipw_write32(priv, IPW_INDIRECT_ADDR, reg & IPW_INDIRECT_ADDR_MASK); |
461 | IPW_DEBUG_IO(" reg = 0x%8X : \n", reg); | 461 | IPW_DEBUG_IO(" reg = 0x%8X :\n", reg); |
462 | word = _ipw_read32(priv, IPW_INDIRECT_DATA); | 462 | word = _ipw_read32(priv, IPW_INDIRECT_DATA); |
463 | return (word >> ((reg & 0x3) * 8)) & 0xff; | 463 | return (word >> ((reg & 0x3) * 8)) & 0xff; |
464 | } | 464 | } |
@@ -472,7 +472,7 @@ static u32 _ipw_read_reg32(struct ipw_priv *priv, u32 reg) | |||
472 | 472 | ||
473 | _ipw_write32(priv, IPW_INDIRECT_ADDR, reg); | 473 | _ipw_write32(priv, IPW_INDIRECT_ADDR, reg); |
474 | value = _ipw_read32(priv, IPW_INDIRECT_DATA); | 474 | value = _ipw_read32(priv, IPW_INDIRECT_DATA); |
475 | IPW_DEBUG_IO(" reg = 0x%4X : value = 0x%4x \n", reg, value); | 475 | IPW_DEBUG_IO(" reg = 0x%4X : value = 0x%4x\n", reg, value); |
476 | return value; | 476 | return value; |
477 | } | 477 | } |
478 | 478 | ||
@@ -2348,16 +2348,25 @@ static void ipw_bg_adapter_restart(struct work_struct *work) | |||
2348 | mutex_unlock(&priv->mutex); | 2348 | mutex_unlock(&priv->mutex); |
2349 | } | 2349 | } |
2350 | 2350 | ||
2351 | #define IPW_SCAN_CHECK_WATCHDOG (5 * HZ) | 2351 | static void ipw_abort_scan(struct ipw_priv *priv); |
2352 | |||
2353 | #define IPW_SCAN_CHECK_WATCHDOG (5 * HZ) | ||
2352 | 2354 | ||
2353 | static void ipw_scan_check(void *data) | 2355 | static void ipw_scan_check(void *data) |
2354 | { | 2356 | { |
2355 | struct ipw_priv *priv = data; | 2357 | struct ipw_priv *priv = data; |
2356 | if (priv->status & (STATUS_SCANNING | STATUS_SCAN_ABORTING)) { | 2358 | |
2359 | if (priv->status & STATUS_SCAN_ABORTING) { | ||
2357 | IPW_DEBUG_SCAN("Scan completion watchdog resetting " | 2360 | IPW_DEBUG_SCAN("Scan completion watchdog resetting " |
2358 | "adapter after (%dms).\n", | 2361 | "adapter after (%dms).\n", |
2359 | jiffies_to_msecs(IPW_SCAN_CHECK_WATCHDOG)); | 2362 | jiffies_to_msecs(IPW_SCAN_CHECK_WATCHDOG)); |
2360 | queue_work(priv->workqueue, &priv->adapter_restart); | 2363 | queue_work(priv->workqueue, &priv->adapter_restart); |
2364 | } else if (priv->status & STATUS_SCANNING) { | ||
2365 | IPW_DEBUG_SCAN("Scan completion watchdog aborting scan " | ||
2366 | "after (%dms).\n", | ||
2367 | jiffies_to_msecs(IPW_SCAN_CHECK_WATCHDOG)); | ||
2368 | ipw_abort_scan(priv); | ||
2369 | queue_delayed_work(priv->workqueue, &priv->scan_check, HZ); | ||
2361 | } | 2370 | } |
2362 | } | 2371 | } |
2363 | 2372 | ||
@@ -2738,7 +2747,7 @@ static inline void ipw_fw_dma_reset_command_blocks(struct ipw_priv *priv) | |||
2738 | static int ipw_fw_dma_enable(struct ipw_priv *priv) | 2747 | static int ipw_fw_dma_enable(struct ipw_priv *priv) |
2739 | { /* start dma engine but no transfers yet */ | 2748 | { /* start dma engine but no transfers yet */ |
2740 | 2749 | ||
2741 | IPW_DEBUG_FW(">> : \n"); | 2750 | IPW_DEBUG_FW(">> :\n"); |
2742 | 2751 | ||
2743 | /* Start the dma */ | 2752 | /* Start the dma */ |
2744 | ipw_fw_dma_reset_command_blocks(priv); | 2753 | ipw_fw_dma_reset_command_blocks(priv); |
@@ -2746,7 +2755,7 @@ static int ipw_fw_dma_enable(struct ipw_priv *priv) | |||
2746 | /* Write CB base address */ | 2755 | /* Write CB base address */ |
2747 | ipw_write_reg32(priv, IPW_DMA_I_CB_BASE, IPW_SHARED_SRAM_DMA_CONTROL); | 2756 | ipw_write_reg32(priv, IPW_DMA_I_CB_BASE, IPW_SHARED_SRAM_DMA_CONTROL); |
2748 | 2757 | ||
2749 | IPW_DEBUG_FW("<< : \n"); | 2758 | IPW_DEBUG_FW("<< :\n"); |
2750 | return 0; | 2759 | return 0; |
2751 | } | 2760 | } |
2752 | 2761 | ||
@@ -2761,7 +2770,7 @@ static void ipw_fw_dma_abort(struct ipw_priv *priv) | |||
2761 | ipw_write_reg32(priv, IPW_DMA_I_DMA_CONTROL, control); | 2770 | ipw_write_reg32(priv, IPW_DMA_I_DMA_CONTROL, control); |
2762 | priv->sram_desc.last_cb_index = 0; | 2771 | priv->sram_desc.last_cb_index = 0; |
2763 | 2772 | ||
2764 | IPW_DEBUG_FW("<< \n"); | 2773 | IPW_DEBUG_FW("<<\n"); |
2765 | } | 2774 | } |
2766 | 2775 | ||
2767 | static int ipw_fw_dma_write_command_block(struct ipw_priv *priv, int index, | 2776 | static int ipw_fw_dma_write_command_block(struct ipw_priv *priv, int index, |
@@ -2812,29 +2821,29 @@ static void ipw_fw_dma_dump_command_block(struct ipw_priv *priv) | |||
2812 | 2821 | ||
2813 | IPW_DEBUG_FW(">> :\n"); | 2822 | IPW_DEBUG_FW(">> :\n"); |
2814 | address = ipw_read_reg32(priv, IPW_DMA_I_CURRENT_CB); | 2823 | address = ipw_read_reg32(priv, IPW_DMA_I_CURRENT_CB); |
2815 | IPW_DEBUG_FW_INFO("Current CB is 0x%x \n", address); | 2824 | IPW_DEBUG_FW_INFO("Current CB is 0x%x\n", address); |
2816 | 2825 | ||
2817 | /* Read the DMA Controlor register */ | 2826 | /* Read the DMA Controlor register */ |
2818 | register_value = ipw_read_reg32(priv, IPW_DMA_I_DMA_CONTROL); | 2827 | register_value = ipw_read_reg32(priv, IPW_DMA_I_DMA_CONTROL); |
2819 | IPW_DEBUG_FW_INFO("IPW_DMA_I_DMA_CONTROL is 0x%x \n", register_value); | 2828 | IPW_DEBUG_FW_INFO("IPW_DMA_I_DMA_CONTROL is 0x%x\n", register_value); |
2820 | 2829 | ||
2821 | /* Print the CB values */ | 2830 | /* Print the CB values */ |
2822 | cb_fields_address = address; | 2831 | cb_fields_address = address; |
2823 | register_value = ipw_read_reg32(priv, cb_fields_address); | 2832 | register_value = ipw_read_reg32(priv, cb_fields_address); |
2824 | IPW_DEBUG_FW_INFO("Current CB ControlField is 0x%x \n", register_value); | 2833 | IPW_DEBUG_FW_INFO("Current CB Control Field is 0x%x\n", register_value); |
2825 | 2834 | ||
2826 | cb_fields_address += sizeof(u32); | 2835 | cb_fields_address += sizeof(u32); |
2827 | register_value = ipw_read_reg32(priv, cb_fields_address); | 2836 | register_value = ipw_read_reg32(priv, cb_fields_address); |
2828 | IPW_DEBUG_FW_INFO("Current CB Source Field is 0x%x \n", register_value); | 2837 | IPW_DEBUG_FW_INFO("Current CB Source Field is 0x%x\n", register_value); |
2829 | 2838 | ||
2830 | cb_fields_address += sizeof(u32); | 2839 | cb_fields_address += sizeof(u32); |
2831 | register_value = ipw_read_reg32(priv, cb_fields_address); | 2840 | register_value = ipw_read_reg32(priv, cb_fields_address); |
2832 | IPW_DEBUG_FW_INFO("Current CB Destination Field is 0x%x \n", | 2841 | IPW_DEBUG_FW_INFO("Current CB Destination Field is 0x%x\n", |
2833 | register_value); | 2842 | register_value); |
2834 | 2843 | ||
2835 | cb_fields_address += sizeof(u32); | 2844 | cb_fields_address += sizeof(u32); |
2836 | register_value = ipw_read_reg32(priv, cb_fields_address); | 2845 | register_value = ipw_read_reg32(priv, cb_fields_address); |
2837 | IPW_DEBUG_FW_INFO("Current CB Status Field is 0x%x \n", register_value); | 2846 | IPW_DEBUG_FW_INFO("Current CB Status Field is 0x%x\n", register_value); |
2838 | 2847 | ||
2839 | IPW_DEBUG_FW(">> :\n"); | 2848 | IPW_DEBUG_FW(">> :\n"); |
2840 | } | 2849 | } |
@@ -2850,7 +2859,7 @@ static int ipw_fw_dma_command_block_index(struct ipw_priv *priv) | |||
2850 | current_cb_index = (current_cb_address - IPW_SHARED_SRAM_DMA_CONTROL) / | 2859 | current_cb_index = (current_cb_address - IPW_SHARED_SRAM_DMA_CONTROL) / |
2851 | sizeof(struct command_block); | 2860 | sizeof(struct command_block); |
2852 | 2861 | ||
2853 | IPW_DEBUG_FW_INFO("Current CB index 0x%x address = 0x%X \n", | 2862 | IPW_DEBUG_FW_INFO("Current CB index 0x%x address = 0x%X\n", |
2854 | current_cb_index, current_cb_address); | 2863 | current_cb_index, current_cb_address); |
2855 | 2864 | ||
2856 | IPW_DEBUG_FW(">> :\n"); | 2865 | IPW_DEBUG_FW(">> :\n"); |
@@ -2909,7 +2918,7 @@ static int ipw_fw_dma_add_buffer(struct ipw_priv *priv, dma_addr_t *src_address, | |||
2909 | int ret, i; | 2918 | int ret, i; |
2910 | u32 size; | 2919 | u32 size; |
2911 | 2920 | ||
2912 | IPW_DEBUG_FW(">> \n"); | 2921 | IPW_DEBUG_FW(">>\n"); |
2913 | IPW_DEBUG_FW_INFO("nr=%d dest_address=0x%x len=0x%x\n", | 2922 | IPW_DEBUG_FW_INFO("nr=%d dest_address=0x%x len=0x%x\n", |
2914 | nr, dest_address, len); | 2923 | nr, dest_address, len); |
2915 | 2924 | ||
@@ -2926,7 +2935,7 @@ static int ipw_fw_dma_add_buffer(struct ipw_priv *priv, dma_addr_t *src_address, | |||
2926 | IPW_DEBUG_FW_INFO(": Added new cb\n"); | 2935 | IPW_DEBUG_FW_INFO(": Added new cb\n"); |
2927 | } | 2936 | } |
2928 | 2937 | ||
2929 | IPW_DEBUG_FW("<< \n"); | 2938 | IPW_DEBUG_FW("<<\n"); |
2930 | return 0; | 2939 | return 0; |
2931 | } | 2940 | } |
2932 | 2941 | ||
@@ -2935,7 +2944,7 @@ static int ipw_fw_dma_wait(struct ipw_priv *priv) | |||
2935 | u32 current_index = 0, previous_index; | 2944 | u32 current_index = 0, previous_index; |
2936 | u32 watchdog = 0; | 2945 | u32 watchdog = 0; |
2937 | 2946 | ||
2938 | IPW_DEBUG_FW(">> : \n"); | 2947 | IPW_DEBUG_FW(">> :\n"); |
2939 | 2948 | ||
2940 | current_index = ipw_fw_dma_command_block_index(priv); | 2949 | current_index = ipw_fw_dma_command_block_index(priv); |
2941 | IPW_DEBUG_FW_INFO("sram_desc.last_cb_index:0x%08X\n", | 2950 | IPW_DEBUG_FW_INFO("sram_desc.last_cb_index:0x%08X\n", |
@@ -2964,7 +2973,7 @@ static int ipw_fw_dma_wait(struct ipw_priv *priv) | |||
2964 | ipw_set_bit(priv, IPW_RESET_REG, | 2973 | ipw_set_bit(priv, IPW_RESET_REG, |
2965 | IPW_RESET_REG_MASTER_DISABLED | IPW_RESET_REG_STOP_MASTER); | 2974 | IPW_RESET_REG_MASTER_DISABLED | IPW_RESET_REG_STOP_MASTER); |
2966 | 2975 | ||
2967 | IPW_DEBUG_FW("<< dmaWaitSync \n"); | 2976 | IPW_DEBUG_FW("<< dmaWaitSync\n"); |
2968 | return 0; | 2977 | return 0; |
2969 | } | 2978 | } |
2970 | 2979 | ||
@@ -3025,7 +3034,7 @@ static int ipw_stop_master(struct ipw_priv *priv) | |||
3025 | { | 3034 | { |
3026 | int rc; | 3035 | int rc; |
3027 | 3036 | ||
3028 | IPW_DEBUG_TRACE(">> \n"); | 3037 | IPW_DEBUG_TRACE(">>\n"); |
3029 | /* stop master. typical delay - 0 */ | 3038 | /* stop master. typical delay - 0 */ |
3030 | ipw_set_bit(priv, IPW_RESET_REG, IPW_RESET_REG_STOP_MASTER); | 3039 | ipw_set_bit(priv, IPW_RESET_REG, IPW_RESET_REG_STOP_MASTER); |
3031 | 3040 | ||
@@ -3044,7 +3053,7 @@ static int ipw_stop_master(struct ipw_priv *priv) | |||
3044 | 3053 | ||
3045 | static void ipw_arc_release(struct ipw_priv *priv) | 3054 | static void ipw_arc_release(struct ipw_priv *priv) |
3046 | { | 3055 | { |
3047 | IPW_DEBUG_TRACE(">> \n"); | 3056 | IPW_DEBUG_TRACE(">>\n"); |
3048 | mdelay(5); | 3057 | mdelay(5); |
3049 | 3058 | ||
3050 | ipw_clear_bit(priv, IPW_RESET_REG, CBD_RESET_REG_PRINCETON_RESET); | 3059 | ipw_clear_bit(priv, IPW_RESET_REG, CBD_RESET_REG_PRINCETON_RESET); |
@@ -3066,7 +3075,7 @@ static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len) | |||
3066 | 3075 | ||
3067 | image = (__le16 *) data; | 3076 | image = (__le16 *) data; |
3068 | 3077 | ||
3069 | IPW_DEBUG_TRACE(">> \n"); | 3078 | IPW_DEBUG_TRACE(">>\n"); |
3070 | 3079 | ||
3071 | rc = ipw_stop_master(priv); | 3080 | rc = ipw_stop_master(priv); |
3072 | 3081 | ||
@@ -3180,7 +3189,7 @@ static int ipw_load_firmware(struct ipw_priv *priv, u8 * data, size_t len) | |||
3180 | void **virts; | 3189 | void **virts; |
3181 | dma_addr_t *phys; | 3190 | dma_addr_t *phys; |
3182 | 3191 | ||
3183 | IPW_DEBUG_TRACE("<< : \n"); | 3192 | IPW_DEBUG_TRACE("<< :\n"); |
3184 | 3193 | ||
3185 | virts = kmalloc(sizeof(void *) * CB_NUMBER_OF_ELEMENTS_SMALL, | 3194 | virts = kmalloc(sizeof(void *) * CB_NUMBER_OF_ELEMENTS_SMALL, |
3186 | GFP_KERNEL); | 3195 | GFP_KERNEL); |
@@ -4481,7 +4490,7 @@ static void ipw_rx_notification(struct ipw_priv *priv, | |||
4481 | case CMAS_ASSOCIATED:{ | 4490 | case CMAS_ASSOCIATED:{ |
4482 | IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | | 4491 | IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | |
4483 | IPW_DL_ASSOC, | 4492 | IPW_DL_ASSOC, |
4484 | "associated: '%s' %pM \n", | 4493 | "associated: '%s' %pM\n", |
4485 | print_ssid(ssid, priv->essid, | 4494 | print_ssid(ssid, priv->essid, |
4486 | priv->essid_len), | 4495 | priv->essid_len), |
4487 | priv->bssid); | 4496 | priv->bssid); |
@@ -4562,7 +4571,7 @@ static void ipw_rx_notification(struct ipw_priv *priv, | |||
4562 | IPW_DL_ASSOC, | 4571 | IPW_DL_ASSOC, |
4563 | "deauthenticated: '%s' " | 4572 | "deauthenticated: '%s' " |
4564 | "%pM" | 4573 | "%pM" |
4565 | ": (0x%04X) - %s \n", | 4574 | ": (0x%04X) - %s\n", |
4566 | print_ssid(ssid, | 4575 | print_ssid(ssid, |
4567 | priv-> | 4576 | priv-> |
4568 | essid, | 4577 | essid, |
@@ -4613,7 +4622,7 @@ static void ipw_rx_notification(struct ipw_priv *priv, | |||
4613 | 4622 | ||
4614 | IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | | 4623 | IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | |
4615 | IPW_DL_ASSOC, | 4624 | IPW_DL_ASSOC, |
4616 | "disassociated: '%s' %pM \n", | 4625 | "disassociated: '%s' %pM\n", |
4617 | print_ssid(ssid, priv->essid, | 4626 | print_ssid(ssid, priv->essid, |
4618 | priv->essid_len), | 4627 | priv->essid_len), |
4619 | priv->bssid); | 4628 | priv->bssid); |
@@ -4651,7 +4660,7 @@ static void ipw_rx_notification(struct ipw_priv *priv, | |||
4651 | switch (auth->state) { | 4660 | switch (auth->state) { |
4652 | case CMAS_AUTHENTICATED: | 4661 | case CMAS_AUTHENTICATED: |
4653 | IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE, | 4662 | IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE, |
4654 | "authenticated: '%s' %pM \n", | 4663 | "authenticated: '%s' %pM\n", |
4655 | print_ssid(ssid, priv->essid, | 4664 | print_ssid(ssid, priv->essid, |
4656 | priv->essid_len), | 4665 | priv->essid_len), |
4657 | priv->bssid); | 4666 | priv->bssid); |
@@ -6924,7 +6933,7 @@ static u8 ipw_qos_current_mode(struct ipw_priv * priv) | |||
6924 | } else { | 6933 | } else { |
6925 | mode = priv->ieee->mode; | 6934 | mode = priv->ieee->mode; |
6926 | } | 6935 | } |
6927 | IPW_DEBUG_QOS("QoS network/card mode %d \n", mode); | 6936 | IPW_DEBUG_QOS("QoS network/card mode %d\n", mode); |
6928 | return mode; | 6937 | return mode; |
6929 | } | 6938 | } |
6930 | 6939 | ||
@@ -6964,7 +6973,7 @@ static int ipw_qos_handle_probe_response(struct ipw_priv *priv, | |||
6964 | &def_parameters_OFDM, size); | 6973 | &def_parameters_OFDM, size); |
6965 | 6974 | ||
6966 | if ((network->qos_data.active == 1) && (active_network == 1)) { | 6975 | if ((network->qos_data.active == 1) && (active_network == 1)) { |
6967 | IPW_DEBUG_QOS("QoS was disabled call qos_activate \n"); | 6976 | IPW_DEBUG_QOS("QoS was disabled call qos_activate\n"); |
6968 | schedule_work(&priv->qos_activate); | 6977 | schedule_work(&priv->qos_activate); |
6969 | } | 6978 | } |
6970 | 6979 | ||
@@ -7541,7 +7550,7 @@ static int ipw_associate_network(struct ipw_priv *priv, | |||
7541 | return err; | 7550 | return err; |
7542 | } | 7551 | } |
7543 | 7552 | ||
7544 | IPW_DEBUG(IPW_DL_STATE, "associating: '%s' %pM \n", | 7553 | IPW_DEBUG(IPW_DL_STATE, "associating: '%s' %pM\n", |
7545 | print_ssid(ssid, priv->essid, priv->essid_len), | 7554 | print_ssid(ssid, priv->essid, priv->essid_len), |
7546 | priv->bssid); | 7555 | priv->bssid); |
7547 | 7556 | ||
@@ -8792,7 +8801,7 @@ static int ipw_wx_set_freq(struct net_device *dev, | |||
8792 | } | 8801 | } |
8793 | } | 8802 | } |
8794 | 8803 | ||
8795 | IPW_DEBUG_WX("SET Freq/Channel -> %d \n", fwrq->m); | 8804 | IPW_DEBUG_WX("SET Freq/Channel -> %d\n", fwrq->m); |
8796 | mutex_lock(&priv->mutex); | 8805 | mutex_lock(&priv->mutex); |
8797 | ret = ipw_set_channel(priv, channel); | 8806 | ret = ipw_set_channel(priv, channel); |
8798 | mutex_unlock(&priv->mutex); | 8807 | mutex_unlock(&priv->mutex); |
@@ -8834,7 +8843,7 @@ static int ipw_wx_get_freq(struct net_device *dev, | |||
8834 | wrqu->freq.m = 0; | 8843 | wrqu->freq.m = 0; |
8835 | 8844 | ||
8836 | mutex_unlock(&priv->mutex); | 8845 | mutex_unlock(&priv->mutex); |
8837 | IPW_DEBUG_WX("GET Freq/Channel -> %d \n", priv->channel); | 8846 | IPW_DEBUG_WX("GET Freq/Channel -> %d\n", priv->channel); |
8838 | return 0; | 8847 | return 0; |
8839 | } | 8848 | } |
8840 | 8849 | ||
@@ -9229,7 +9238,7 @@ static int ipw_wx_get_sens(struct net_device *dev, | |||
9229 | wrqu->sens.value = priv->roaming_threshold; | 9238 | wrqu->sens.value = priv->roaming_threshold; |
9230 | mutex_unlock(&priv->mutex); | 9239 | mutex_unlock(&priv->mutex); |
9231 | 9240 | ||
9232 | IPW_DEBUG_WX("GET roaming threshold -> %s %d \n", | 9241 | IPW_DEBUG_WX("GET roaming threshold -> %s %d\n", |
9233 | wrqu->power.disabled ? "OFF" : "ON", wrqu->power.value); | 9242 | wrqu->power.disabled ? "OFF" : "ON", wrqu->power.value); |
9234 | 9243 | ||
9235 | return 0; | 9244 | return 0; |
@@ -9357,7 +9366,7 @@ static int ipw_wx_get_rate(struct net_device *dev, | |||
9357 | wrqu->bitrate.value = priv->last_rate; | 9366 | wrqu->bitrate.value = priv->last_rate; |
9358 | wrqu->bitrate.fixed = (priv->config & CFG_FIXED_RATE) ? 1 : 0; | 9367 | wrqu->bitrate.fixed = (priv->config & CFG_FIXED_RATE) ? 1 : 0; |
9359 | mutex_unlock(&priv->mutex); | 9368 | mutex_unlock(&priv->mutex); |
9360 | IPW_DEBUG_WX("GET Rate -> %d \n", wrqu->bitrate.value); | 9369 | IPW_DEBUG_WX("GET Rate -> %d\n", wrqu->bitrate.value); |
9361 | return 0; | 9370 | return 0; |
9362 | } | 9371 | } |
9363 | 9372 | ||
@@ -9380,7 +9389,7 @@ static int ipw_wx_set_rts(struct net_device *dev, | |||
9380 | 9389 | ||
9381 | ipw_send_rts_threshold(priv, priv->rts_threshold); | 9390 | ipw_send_rts_threshold(priv, priv->rts_threshold); |
9382 | mutex_unlock(&priv->mutex); | 9391 | mutex_unlock(&priv->mutex); |
9383 | IPW_DEBUG_WX("SET RTS Threshold -> %d \n", priv->rts_threshold); | 9392 | IPW_DEBUG_WX("SET RTS Threshold -> %d\n", priv->rts_threshold); |
9384 | return 0; | 9393 | return 0; |
9385 | } | 9394 | } |
9386 | 9395 | ||
@@ -9394,7 +9403,7 @@ static int ipw_wx_get_rts(struct net_device *dev, | |||
9394 | wrqu->rts.fixed = 0; /* no auto select */ | 9403 | wrqu->rts.fixed = 0; /* no auto select */ |
9395 | wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD); | 9404 | wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD); |
9396 | mutex_unlock(&priv->mutex); | 9405 | mutex_unlock(&priv->mutex); |
9397 | IPW_DEBUG_WX("GET RTS Threshold -> %d \n", wrqu->rts.value); | 9406 | IPW_DEBUG_WX("GET RTS Threshold -> %d\n", wrqu->rts.value); |
9398 | return 0; | 9407 | return 0; |
9399 | } | 9408 | } |
9400 | 9409 | ||
@@ -9444,7 +9453,7 @@ static int ipw_wx_get_txpow(struct net_device *dev, | |||
9444 | wrqu->power.disabled = (priv->status & STATUS_RF_KILL_MASK) ? 1 : 0; | 9453 | wrqu->power.disabled = (priv->status & STATUS_RF_KILL_MASK) ? 1 : 0; |
9445 | mutex_unlock(&priv->mutex); | 9454 | mutex_unlock(&priv->mutex); |
9446 | 9455 | ||
9447 | IPW_DEBUG_WX("GET TX Power -> %s %d \n", | 9456 | IPW_DEBUG_WX("GET TX Power -> %s %d\n", |
9448 | wrqu->power.disabled ? "OFF" : "ON", wrqu->power.value); | 9457 | wrqu->power.disabled ? "OFF" : "ON", wrqu->power.value); |
9449 | 9458 | ||
9450 | return 0; | 9459 | return 0; |
@@ -9470,7 +9479,7 @@ static int ipw_wx_set_frag(struct net_device *dev, | |||
9470 | 9479 | ||
9471 | ipw_send_frag_threshold(priv, wrqu->frag.value); | 9480 | ipw_send_frag_threshold(priv, wrqu->frag.value); |
9472 | mutex_unlock(&priv->mutex); | 9481 | mutex_unlock(&priv->mutex); |
9473 | IPW_DEBUG_WX("SET Frag Threshold -> %d \n", wrqu->frag.value); | 9482 | IPW_DEBUG_WX("SET Frag Threshold -> %d\n", wrqu->frag.value); |
9474 | return 0; | 9483 | return 0; |
9475 | } | 9484 | } |
9476 | 9485 | ||
@@ -9484,7 +9493,7 @@ static int ipw_wx_get_frag(struct net_device *dev, | |||
9484 | wrqu->frag.fixed = 0; /* no auto select */ | 9493 | wrqu->frag.fixed = 0; /* no auto select */ |
9485 | wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FTS); | 9494 | wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FTS); |
9486 | mutex_unlock(&priv->mutex); | 9495 | mutex_unlock(&priv->mutex); |
9487 | IPW_DEBUG_WX("GET Frag Threshold -> %d \n", wrqu->frag.value); | 9496 | IPW_DEBUG_WX("GET Frag Threshold -> %d\n", wrqu->frag.value); |
9488 | 9497 | ||
9489 | return 0; | 9498 | return 0; |
9490 | } | 9499 | } |
@@ -9548,7 +9557,7 @@ static int ipw_wx_get_retry(struct net_device *dev, | |||
9548 | } | 9557 | } |
9549 | mutex_unlock(&priv->mutex); | 9558 | mutex_unlock(&priv->mutex); |
9550 | 9559 | ||
9551 | IPW_DEBUG_WX("GET retry -> %d \n", wrqu->retry.value); | 9560 | IPW_DEBUG_WX("GET retry -> %d\n", wrqu->retry.value); |
9552 | 9561 | ||
9553 | return 0; | 9562 | return 0; |
9554 | } | 9563 | } |
@@ -9995,49 +10004,48 @@ static int ipw_wx_sw_reset(struct net_device *dev, | |||
9995 | } | 10004 | } |
9996 | 10005 | ||
9997 | /* Rebase the WE IOCTLs to zero for the handler array */ | 10006 | /* Rebase the WE IOCTLs to zero for the handler array */ |
9998 | #define IW_IOCTL(x) [(x)-SIOCSIWCOMMIT] | ||
9999 | static iw_handler ipw_wx_handlers[] = { | 10007 | static iw_handler ipw_wx_handlers[] = { |
10000 | IW_IOCTL(SIOCGIWNAME) = (iw_handler) cfg80211_wext_giwname, | 10008 | IW_HANDLER(SIOCGIWNAME, (iw_handler)cfg80211_wext_giwname), |
10001 | IW_IOCTL(SIOCSIWFREQ) = ipw_wx_set_freq, | 10009 | IW_HANDLER(SIOCSIWFREQ, ipw_wx_set_freq), |
10002 | IW_IOCTL(SIOCGIWFREQ) = ipw_wx_get_freq, | 10010 | IW_HANDLER(SIOCGIWFREQ, ipw_wx_get_freq), |
10003 | IW_IOCTL(SIOCSIWMODE) = ipw_wx_set_mode, | 10011 | IW_HANDLER(SIOCSIWMODE, ipw_wx_set_mode), |
10004 | IW_IOCTL(SIOCGIWMODE) = ipw_wx_get_mode, | 10012 | IW_HANDLER(SIOCGIWMODE, ipw_wx_get_mode), |
10005 | IW_IOCTL(SIOCSIWSENS) = ipw_wx_set_sens, | 10013 | IW_HANDLER(SIOCSIWSENS, ipw_wx_set_sens), |
10006 | IW_IOCTL(SIOCGIWSENS) = ipw_wx_get_sens, | 10014 | IW_HANDLER(SIOCGIWSENS, ipw_wx_get_sens), |
10007 | IW_IOCTL(SIOCGIWRANGE) = ipw_wx_get_range, | 10015 | IW_HANDLER(SIOCGIWRANGE, ipw_wx_get_range), |
10008 | IW_IOCTL(SIOCSIWAP) = ipw_wx_set_wap, | 10016 | IW_HANDLER(SIOCSIWAP, ipw_wx_set_wap), |
10009 | IW_IOCTL(SIOCGIWAP) = ipw_wx_get_wap, | 10017 | IW_HANDLER(SIOCGIWAP, ipw_wx_get_wap), |
10010 | IW_IOCTL(SIOCSIWSCAN) = ipw_wx_set_scan, | 10018 | IW_HANDLER(SIOCSIWSCAN, ipw_wx_set_scan), |
10011 | IW_IOCTL(SIOCGIWSCAN) = ipw_wx_get_scan, | 10019 | IW_HANDLER(SIOCGIWSCAN, ipw_wx_get_scan), |
10012 | IW_IOCTL(SIOCSIWESSID) = ipw_wx_set_essid, | 10020 | IW_HANDLER(SIOCSIWESSID, ipw_wx_set_essid), |
10013 | IW_IOCTL(SIOCGIWESSID) = ipw_wx_get_essid, | 10021 | IW_HANDLER(SIOCGIWESSID, ipw_wx_get_essid), |
10014 | IW_IOCTL(SIOCSIWNICKN) = ipw_wx_set_nick, | 10022 | IW_HANDLER(SIOCSIWNICKN, ipw_wx_set_nick), |
10015 | IW_IOCTL(SIOCGIWNICKN) = ipw_wx_get_nick, | 10023 | IW_HANDLER(SIOCGIWNICKN, ipw_wx_get_nick), |
10016 | IW_IOCTL(SIOCSIWRATE) = ipw_wx_set_rate, | 10024 | IW_HANDLER(SIOCSIWRATE, ipw_wx_set_rate), |
10017 | IW_IOCTL(SIOCGIWRATE) = ipw_wx_get_rate, | 10025 | IW_HANDLER(SIOCGIWRATE, ipw_wx_get_rate), |
10018 | IW_IOCTL(SIOCSIWRTS) = ipw_wx_set_rts, | 10026 | IW_HANDLER(SIOCSIWRTS, ipw_wx_set_rts), |
10019 | IW_IOCTL(SIOCGIWRTS) = ipw_wx_get_rts, | 10027 | IW_HANDLER(SIOCGIWRTS, ipw_wx_get_rts), |
10020 | IW_IOCTL(SIOCSIWFRAG) = ipw_wx_set_frag, | 10028 | IW_HANDLER(SIOCSIWFRAG, ipw_wx_set_frag), |
10021 | IW_IOCTL(SIOCGIWFRAG) = ipw_wx_get_frag, | 10029 | IW_HANDLER(SIOCGIWFRAG, ipw_wx_get_frag), |
10022 | IW_IOCTL(SIOCSIWTXPOW) = ipw_wx_set_txpow, | 10030 | IW_HANDLER(SIOCSIWTXPOW, ipw_wx_set_txpow), |
10023 | IW_IOCTL(SIOCGIWTXPOW) = ipw_wx_get_txpow, | 10031 | IW_HANDLER(SIOCGIWTXPOW, ipw_wx_get_txpow), |
10024 | IW_IOCTL(SIOCSIWRETRY) = ipw_wx_set_retry, | 10032 | IW_HANDLER(SIOCSIWRETRY, ipw_wx_set_retry), |
10025 | IW_IOCTL(SIOCGIWRETRY) = ipw_wx_get_retry, | 10033 | IW_HANDLER(SIOCGIWRETRY, ipw_wx_get_retry), |
10026 | IW_IOCTL(SIOCSIWENCODE) = ipw_wx_set_encode, | 10034 | IW_HANDLER(SIOCSIWENCODE, ipw_wx_set_encode), |
10027 | IW_IOCTL(SIOCGIWENCODE) = ipw_wx_get_encode, | 10035 | IW_HANDLER(SIOCGIWENCODE, ipw_wx_get_encode), |
10028 | IW_IOCTL(SIOCSIWPOWER) = ipw_wx_set_power, | 10036 | IW_HANDLER(SIOCSIWPOWER, ipw_wx_set_power), |
10029 | IW_IOCTL(SIOCGIWPOWER) = ipw_wx_get_power, | 10037 | IW_HANDLER(SIOCGIWPOWER, ipw_wx_get_power), |
10030 | IW_IOCTL(SIOCSIWSPY) = iw_handler_set_spy, | 10038 | IW_HANDLER(SIOCSIWSPY, iw_handler_set_spy), |
10031 | IW_IOCTL(SIOCGIWSPY) = iw_handler_get_spy, | 10039 | IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy), |
10032 | IW_IOCTL(SIOCSIWTHRSPY) = iw_handler_set_thrspy, | 10040 | IW_HANDLER(SIOCSIWTHRSPY, iw_handler_set_thrspy), |
10033 | IW_IOCTL(SIOCGIWTHRSPY) = iw_handler_get_thrspy, | 10041 | IW_HANDLER(SIOCGIWTHRSPY, iw_handler_get_thrspy), |
10034 | IW_IOCTL(SIOCSIWGENIE) = ipw_wx_set_genie, | 10042 | IW_HANDLER(SIOCSIWGENIE, ipw_wx_set_genie), |
10035 | IW_IOCTL(SIOCGIWGENIE) = ipw_wx_get_genie, | 10043 | IW_HANDLER(SIOCGIWGENIE, ipw_wx_get_genie), |
10036 | IW_IOCTL(SIOCSIWMLME) = ipw_wx_set_mlme, | 10044 | IW_HANDLER(SIOCSIWMLME, ipw_wx_set_mlme), |
10037 | IW_IOCTL(SIOCSIWAUTH) = ipw_wx_set_auth, | 10045 | IW_HANDLER(SIOCSIWAUTH, ipw_wx_set_auth), |
10038 | IW_IOCTL(SIOCGIWAUTH) = ipw_wx_get_auth, | 10046 | IW_HANDLER(SIOCGIWAUTH, ipw_wx_get_auth), |
10039 | IW_IOCTL(SIOCSIWENCODEEXT) = ipw_wx_set_encodeext, | 10047 | IW_HANDLER(SIOCSIWENCODEEXT, ipw_wx_set_encodeext), |
10040 | IW_IOCTL(SIOCGIWENCODEEXT) = ipw_wx_get_encodeext, | 10048 | IW_HANDLER(SIOCGIWENCODEEXT, ipw_wx_get_encodeext), |
10041 | }; | 10049 | }; |
10042 | 10050 | ||
10043 | enum { | 10051 | enum { |
@@ -11666,7 +11674,7 @@ static int ipw_prom_alloc(struct ipw_priv *priv) | |||
11666 | if (priv->prom_net_dev) | 11674 | if (priv->prom_net_dev) |
11667 | return -EPERM; | 11675 | return -EPERM; |
11668 | 11676 | ||
11669 | priv->prom_net_dev = alloc_ieee80211(sizeof(struct ipw_prom_priv), 1); | 11677 | priv->prom_net_dev = alloc_libipw(sizeof(struct ipw_prom_priv), 1); |
11670 | if (priv->prom_net_dev == NULL) | 11678 | if (priv->prom_net_dev == NULL) |
11671 | return -ENOMEM; | 11679 | return -ENOMEM; |
11672 | 11680 | ||
@@ -11685,7 +11693,7 @@ static int ipw_prom_alloc(struct ipw_priv *priv) | |||
11685 | 11693 | ||
11686 | rc = register_netdev(priv->prom_net_dev); | 11694 | rc = register_netdev(priv->prom_net_dev); |
11687 | if (rc) { | 11695 | if (rc) { |
11688 | free_ieee80211(priv->prom_net_dev, 1); | 11696 | free_libipw(priv->prom_net_dev, 1); |
11689 | priv->prom_net_dev = NULL; | 11697 | priv->prom_net_dev = NULL; |
11690 | return rc; | 11698 | return rc; |
11691 | } | 11699 | } |
@@ -11699,7 +11707,7 @@ static void ipw_prom_free(struct ipw_priv *priv) | |||
11699 | return; | 11707 | return; |
11700 | 11708 | ||
11701 | unregister_netdev(priv->prom_net_dev); | 11709 | unregister_netdev(priv->prom_net_dev); |
11702 | free_ieee80211(priv->prom_net_dev, 1); | 11710 | free_libipw(priv->prom_net_dev, 1); |
11703 | 11711 | ||
11704 | priv->prom_net_dev = NULL; | 11712 | priv->prom_net_dev = NULL; |
11705 | } | 11713 | } |
@@ -11727,7 +11735,7 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev, | |||
11727 | struct ipw_priv *priv; | 11735 | struct ipw_priv *priv; |
11728 | int i; | 11736 | int i; |
11729 | 11737 | ||
11730 | net_dev = alloc_ieee80211(sizeof(struct ipw_priv), 0); | 11738 | net_dev = alloc_libipw(sizeof(struct ipw_priv), 0); |
11731 | if (net_dev == NULL) { | 11739 | if (net_dev == NULL) { |
11732 | err = -ENOMEM; | 11740 | err = -ENOMEM; |
11733 | goto out; | 11741 | goto out; |
@@ -11747,7 +11755,7 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev, | |||
11747 | mutex_init(&priv->mutex); | 11755 | mutex_init(&priv->mutex); |
11748 | if (pci_enable_device(pdev)) { | 11756 | if (pci_enable_device(pdev)) { |
11749 | err = -ENODEV; | 11757 | err = -ENODEV; |
11750 | goto out_free_ieee80211; | 11758 | goto out_free_libipw; |
11751 | } | 11759 | } |
11752 | 11760 | ||
11753 | pci_set_master(pdev); | 11761 | pci_set_master(pdev); |
@@ -11874,8 +11882,8 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev, | |||
11874 | out_pci_disable_device: | 11882 | out_pci_disable_device: |
11875 | pci_disable_device(pdev); | 11883 | pci_disable_device(pdev); |
11876 | pci_set_drvdata(pdev, NULL); | 11884 | pci_set_drvdata(pdev, NULL); |
11877 | out_free_ieee80211: | 11885 | out_free_libipw: |
11878 | free_ieee80211(priv->net_dev, 0); | 11886 | free_libipw(priv->net_dev, 0); |
11879 | out: | 11887 | out: |
11880 | return err; | 11888 | return err; |
11881 | } | 11889 | } |
@@ -11942,11 +11950,11 @@ static void __devexit ipw_pci_remove(struct pci_dev *pdev) | |||
11942 | pci_release_regions(pdev); | 11950 | pci_release_regions(pdev); |
11943 | pci_disable_device(pdev); | 11951 | pci_disable_device(pdev); |
11944 | pci_set_drvdata(pdev, NULL); | 11952 | pci_set_drvdata(pdev, NULL); |
11945 | /* wiphy_unregister needs to be here, before free_ieee80211 */ | 11953 | /* wiphy_unregister needs to be here, before free_libipw */ |
11946 | wiphy_unregister(priv->ieee->wdev.wiphy); | 11954 | wiphy_unregister(priv->ieee->wdev.wiphy); |
11947 | kfree(priv->ieee->a_band.channels); | 11955 | kfree(priv->ieee->a_band.channels); |
11948 | kfree(priv->ieee->bg_band.channels); | 11956 | kfree(priv->ieee->bg_band.channels); |
11949 | free_ieee80211(priv->net_dev, 0); | 11957 | free_libipw(priv->net_dev, 0); |
11950 | free_firmware(); | 11958 | free_firmware(); |
11951 | } | 11959 | } |
11952 | 11960 | ||
diff --git a/drivers/net/wireless/ipw2x00/libipw.h b/drivers/net/wireless/ipw2x00/libipw.h index a6d5e42647e4..284b0e4cb815 100644 --- a/drivers/net/wireless/ipw2x00/libipw.h +++ b/drivers/net/wireless/ipw2x00/libipw.h | |||
@@ -64,7 +64,7 @@ | |||
64 | extern u32 libipw_debug_level; | 64 | extern u32 libipw_debug_level; |
65 | #define LIBIPW_DEBUG(level, fmt, args...) \ | 65 | #define LIBIPW_DEBUG(level, fmt, args...) \ |
66 | do { if (libipw_debug_level & (level)) \ | 66 | do { if (libipw_debug_level & (level)) \ |
67 | printk(KERN_DEBUG "ieee80211: %c %s " fmt, \ | 67 | printk(KERN_DEBUG "libipw: %c %s " fmt, \ |
68 | in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0) | 68 | in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0) |
69 | static inline bool libipw_ratelimit_debug(u32 level) | 69 | static inline bool libipw_ratelimit_debug(u32 level) |
70 | { | 70 | { |
@@ -116,8 +116,8 @@ static inline bool libipw_ratelimit_debug(u32 level) | |||
116 | #define LIBIPW_DL_RX (1<<9) | 116 | #define LIBIPW_DL_RX (1<<9) |
117 | #define LIBIPW_DL_QOS (1<<31) | 117 | #define LIBIPW_DL_QOS (1<<31) |
118 | 118 | ||
119 | #define LIBIPW_ERROR(f, a...) printk(KERN_ERR "ieee80211: " f, ## a) | 119 | #define LIBIPW_ERROR(f, a...) printk(KERN_ERR "libipw: " f, ## a) |
120 | #define LIBIPW_WARNING(f, a...) printk(KERN_WARNING "ieee80211: " f, ## a) | 120 | #define LIBIPW_WARNING(f, a...) printk(KERN_WARNING "libipw: " f, ## a) |
121 | #define LIBIPW_DEBUG_INFO(f, a...) LIBIPW_DEBUG(LIBIPW_DL_INFO, f, ## a) | 121 | #define LIBIPW_DEBUG_INFO(f, a...) LIBIPW_DEBUG(LIBIPW_DL_INFO, f, ## a) |
122 | 122 | ||
123 | #define LIBIPW_DEBUG_WX(f, a...) LIBIPW_DEBUG(LIBIPW_DL_WX, f, ## a) | 123 | #define LIBIPW_DEBUG_WX(f, a...) LIBIPW_DEBUG(LIBIPW_DL_WX, f, ## a) |
@@ -905,7 +905,7 @@ struct libipw_device { | |||
905 | struct libipw_reassoc_request * req); | 905 | struct libipw_reassoc_request * req); |
906 | 906 | ||
907 | /* This must be the last item so that it points to the data | 907 | /* This must be the last item so that it points to the data |
908 | * allocated beyond this structure by alloc_ieee80211 */ | 908 | * allocated beyond this structure by alloc_libipw */ |
909 | u8 priv[0]; | 909 | u8 priv[0]; |
910 | }; | 910 | }; |
911 | 911 | ||
@@ -1017,9 +1017,9 @@ static inline int libipw_is_cck_rate(u8 rate) | |||
1017 | return 0; | 1017 | return 0; |
1018 | } | 1018 | } |
1019 | 1019 | ||
1020 | /* ieee80211.c */ | 1020 | /* libipw.c */ |
1021 | extern void free_ieee80211(struct net_device *dev, int monitor); | 1021 | extern void free_libipw(struct net_device *dev, int monitor); |
1022 | extern struct net_device *alloc_ieee80211(int sizeof_priv, int monitor); | 1022 | extern struct net_device *alloc_libipw(int sizeof_priv, int monitor); |
1023 | extern int libipw_change_mtu(struct net_device *dev, int new_mtu); | 1023 | extern int libipw_change_mtu(struct net_device *dev, int new_mtu); |
1024 | 1024 | ||
1025 | extern void libipw_networks_age(struct libipw_device *ieee, | 1025 | extern void libipw_networks_age(struct libipw_device *ieee, |
diff --git a/drivers/net/wireless/ipw2x00/libipw_module.c b/drivers/net/wireless/ipw2x00/libipw_module.c index 2fa55867bd8b..55965408ff3f 100644 --- a/drivers/net/wireless/ipw2x00/libipw_module.c +++ b/drivers/net/wireless/ipw2x00/libipw_module.c | |||
@@ -53,7 +53,7 @@ | |||
53 | #include "libipw.h" | 53 | #include "libipw.h" |
54 | 54 | ||
55 | #define DRV_DESCRIPTION "802.11 data/management/control stack" | 55 | #define DRV_DESCRIPTION "802.11 data/management/control stack" |
56 | #define DRV_NAME "ieee80211" | 56 | #define DRV_NAME "libipw" |
57 | #define DRV_VERSION LIBIPW_VERSION | 57 | #define DRV_VERSION LIBIPW_VERSION |
58 | #define DRV_COPYRIGHT "Copyright (C) 2004-2005 Intel Corporation <jketreno@linux.intel.com>" | 58 | #define DRV_COPYRIGHT "Copyright (C) 2004-2005 Intel Corporation <jketreno@linux.intel.com>" |
59 | 59 | ||
@@ -140,7 +140,7 @@ int libipw_change_mtu(struct net_device *dev, int new_mtu) | |||
140 | } | 140 | } |
141 | EXPORT_SYMBOL(libipw_change_mtu); | 141 | EXPORT_SYMBOL(libipw_change_mtu); |
142 | 142 | ||
143 | struct net_device *alloc_ieee80211(int sizeof_priv, int monitor) | 143 | struct net_device *alloc_libipw(int sizeof_priv, int monitor) |
144 | { | 144 | { |
145 | struct libipw_device *ieee; | 145 | struct libipw_device *ieee; |
146 | struct net_device *dev; | 146 | struct net_device *dev; |
@@ -222,8 +222,9 @@ failed_free_netdev: | |||
222 | failed: | 222 | failed: |
223 | return NULL; | 223 | return NULL; |
224 | } | 224 | } |
225 | EXPORT_SYMBOL(alloc_libipw); | ||
225 | 226 | ||
226 | void free_ieee80211(struct net_device *dev, int monitor) | 227 | void free_libipw(struct net_device *dev, int monitor) |
227 | { | 228 | { |
228 | struct libipw_device *ieee = netdev_priv(dev); | 229 | struct libipw_device *ieee = netdev_priv(dev); |
229 | 230 | ||
@@ -237,6 +238,7 @@ void free_ieee80211(struct net_device *dev, int monitor) | |||
237 | 238 | ||
238 | free_netdev(dev); | 239 | free_netdev(dev); |
239 | } | 240 | } |
241 | EXPORT_SYMBOL(free_libipw); | ||
240 | 242 | ||
241 | #ifdef CONFIG_LIBIPW_DEBUG | 243 | #ifdef CONFIG_LIBIPW_DEBUG |
242 | 244 | ||
@@ -291,7 +293,7 @@ static int __init libipw_init(void) | |||
291 | struct proc_dir_entry *e; | 293 | struct proc_dir_entry *e; |
292 | 294 | ||
293 | libipw_debug_level = debug; | 295 | libipw_debug_level = debug; |
294 | libipw_proc = proc_mkdir(DRV_NAME, init_net.proc_net); | 296 | libipw_proc = proc_mkdir("ieee80211", init_net.proc_net); |
295 | if (libipw_proc == NULL) { | 297 | if (libipw_proc == NULL) { |
296 | LIBIPW_ERROR("Unable to create " DRV_NAME | 298 | LIBIPW_ERROR("Unable to create " DRV_NAME |
297 | " proc directory\n"); | 299 | " proc directory\n"); |
@@ -331,6 +333,3 @@ MODULE_PARM_DESC(debug, "debug output mask"); | |||
331 | 333 | ||
332 | module_exit(libipw_exit); | 334 | module_exit(libipw_exit); |
333 | module_init(libipw_init); | 335 | module_init(libipw_init); |
334 | |||
335 | EXPORT_SYMBOL(alloc_ieee80211); | ||
336 | EXPORT_SYMBOL(free_ieee80211); | ||
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 4e378faee650..a684a72eb6e9 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile | |||
@@ -9,7 +9,9 @@ CFLAGS_iwl-devtrace.o := -I$(src) | |||
9 | 9 | ||
10 | # AGN | 10 | # AGN |
11 | obj-$(CONFIG_IWLAGN) += iwlagn.o | 11 | obj-$(CONFIG_IWLAGN) += iwlagn.o |
12 | iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o | 12 | iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o |
13 | iwlagn-objs += iwl-agn-ucode.o iwl-agn-hcmd.o iwl-agn-tx.o | ||
14 | iwlagn-objs += iwl-agn-lib.o | ||
13 | 15 | ||
14 | iwlagn-$(CONFIG_IWL4965) += iwl-4965.o | 16 | iwlagn-$(CONFIG_IWL4965) += iwl-4965.o |
15 | iwlagn-$(CONFIG_IWL5000) += iwl-5000.o | 17 | iwlagn-$(CONFIG_IWL5000) += iwl-5000.o |
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 3bf2e6e9b2d9..b941b3e95697 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c | |||
@@ -42,8 +42,9 @@ | |||
42 | #include "iwl-core.h" | 42 | #include "iwl-core.h" |
43 | #include "iwl-io.h" | 43 | #include "iwl-io.h" |
44 | #include "iwl-sta.h" | 44 | #include "iwl-sta.h" |
45 | #include "iwl-agn.h" | ||
45 | #include "iwl-helpers.h" | 46 | #include "iwl-helpers.h" |
46 | #include "iwl-5000-hw.h" | 47 | #include "iwl-agn-hw.h" |
47 | #include "iwl-agn-led.h" | 48 | #include "iwl-agn-led.h" |
48 | 49 | ||
49 | /* Highest firmware API version supported */ | 50 | /* Highest firmware API version supported */ |
@@ -117,7 +118,7 @@ static struct iwl_sensitivity_ranges iwl1000_sensitivity = { | |||
117 | static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) | 118 | static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) |
118 | { | 119 | { |
119 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && | 120 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && |
120 | priv->cfg->mod_params->num_of_queues <= IWL50_NUM_QUEUES) | 121 | priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES) |
121 | priv->cfg->num_of_queues = | 122 | priv->cfg->num_of_queues = |
122 | priv->cfg->mod_params->num_of_queues; | 123 | priv->cfg->mod_params->num_of_queues; |
123 | 124 | ||
@@ -125,13 +126,13 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) | |||
125 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; | 126 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; |
126 | priv->hw_params.scd_bc_tbls_size = | 127 | priv->hw_params.scd_bc_tbls_size = |
127 | priv->cfg->num_of_queues * | 128 | priv->cfg->num_of_queues * |
128 | sizeof(struct iwl5000_scd_bc_tbl); | 129 | sizeof(struct iwlagn_scd_bc_tbl); |
129 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); | 130 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); |
130 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; | 131 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; |
131 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; | 132 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; |
132 | 133 | ||
133 | priv->hw_params.max_data_size = IWL50_RTC_DATA_SIZE; | 134 | priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; |
134 | priv->hw_params.max_inst_size = IWL50_RTC_INST_SIZE; | 135 | priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; |
135 | 136 | ||
136 | priv->hw_params.max_bsm_size = 0; | 137 | priv->hw_params.max_bsm_size = 0; |
137 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | | 138 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | |
@@ -161,25 +162,25 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) | |||
161 | 162 | ||
162 | static struct iwl_lib_ops iwl1000_lib = { | 163 | static struct iwl_lib_ops iwl1000_lib = { |
163 | .set_hw_params = iwl1000_hw_set_hw_params, | 164 | .set_hw_params = iwl1000_hw_set_hw_params, |
164 | .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, | 165 | .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, |
165 | .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, | 166 | .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, |
166 | .txq_set_sched = iwl5000_txq_set_sched, | 167 | .txq_set_sched = iwlagn_txq_set_sched, |
167 | .txq_agg_enable = iwl5000_txq_agg_enable, | 168 | .txq_agg_enable = iwlagn_txq_agg_enable, |
168 | .txq_agg_disable = iwl5000_txq_agg_disable, | 169 | .txq_agg_disable = iwlagn_txq_agg_disable, |
169 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, | 170 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, |
170 | .txq_free_tfd = iwl_hw_txq_free_tfd, | 171 | .txq_free_tfd = iwl_hw_txq_free_tfd, |
171 | .txq_init = iwl_hw_tx_queue_init, | 172 | .txq_init = iwl_hw_tx_queue_init, |
172 | .rx_handler_setup = iwl5000_rx_handler_setup, | 173 | .rx_handler_setup = iwlagn_rx_handler_setup, |
173 | .setup_deferred_work = iwl5000_setup_deferred_work, | 174 | .setup_deferred_work = iwlagn_setup_deferred_work, |
174 | .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, | 175 | .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, |
175 | .load_ucode = iwl5000_load_ucode, | 176 | .load_ucode = iwlagn_load_ucode, |
176 | .dump_nic_event_log = iwl_dump_nic_event_log, | 177 | .dump_nic_event_log = iwl_dump_nic_event_log, |
177 | .dump_nic_error_log = iwl_dump_nic_error_log, | 178 | .dump_nic_error_log = iwl_dump_nic_error_log, |
178 | .dump_csr = iwl_dump_csr, | 179 | .dump_csr = iwl_dump_csr, |
179 | .dump_fh = iwl_dump_fh, | 180 | .dump_fh = iwl_dump_fh, |
180 | .init_alive_start = iwl5000_init_alive_start, | 181 | .init_alive_start = iwlagn_init_alive_start, |
181 | .alive_notify = iwl5000_alive_notify, | 182 | .alive_notify = iwlagn_alive_notify, |
182 | .send_tx_power = iwl5000_send_tx_power, | 183 | .send_tx_power = iwlagn_send_tx_power, |
183 | .update_chain_flags = iwl_update_chain_flags, | 184 | .update_chain_flags = iwl_update_chain_flags, |
184 | .apm_ops = { | 185 | .apm_ops = { |
185 | .init = iwl_apm_init, | 186 | .init = iwl_apm_init, |
@@ -189,40 +190,43 @@ static struct iwl_lib_ops iwl1000_lib = { | |||
189 | }, | 190 | }, |
190 | .eeprom_ops = { | 191 | .eeprom_ops = { |
191 | .regulatory_bands = { | 192 | .regulatory_bands = { |
192 | EEPROM_5000_REG_BAND_1_CHANNELS, | 193 | EEPROM_REG_BAND_1_CHANNELS, |
193 | EEPROM_5000_REG_BAND_2_CHANNELS, | 194 | EEPROM_REG_BAND_2_CHANNELS, |
194 | EEPROM_5000_REG_BAND_3_CHANNELS, | 195 | EEPROM_REG_BAND_3_CHANNELS, |
195 | EEPROM_5000_REG_BAND_4_CHANNELS, | 196 | EEPROM_REG_BAND_4_CHANNELS, |
196 | EEPROM_5000_REG_BAND_5_CHANNELS, | 197 | EEPROM_REG_BAND_5_CHANNELS, |
197 | EEPROM_5000_REG_BAND_24_HT40_CHANNELS, | 198 | EEPROM_REG_BAND_24_HT40_CHANNELS, |
198 | EEPROM_5000_REG_BAND_52_HT40_CHANNELS | 199 | EEPROM_REG_BAND_52_HT40_CHANNELS |
199 | }, | 200 | }, |
200 | .verify_signature = iwlcore_eeprom_verify_signature, | 201 | .verify_signature = iwlcore_eeprom_verify_signature, |
201 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, | 202 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, |
202 | .release_semaphore = iwlcore_eeprom_release_semaphore, | 203 | .release_semaphore = iwlcore_eeprom_release_semaphore, |
203 | .calib_version = iwl5000_eeprom_calib_version, | 204 | .calib_version = iwlagn_eeprom_calib_version, |
204 | .query_addr = iwl5000_eeprom_query_addr, | 205 | .query_addr = iwlagn_eeprom_query_addr, |
205 | }, | 206 | }, |
206 | .post_associate = iwl_post_associate, | 207 | .post_associate = iwl_post_associate, |
207 | .isr = iwl_isr_ict, | 208 | .isr = iwl_isr_ict, |
208 | .config_ap = iwl_config_ap, | 209 | .config_ap = iwl_config_ap, |
209 | .temp_ops = { | 210 | .temp_ops = { |
210 | .temperature = iwl5000_temperature, | 211 | .temperature = iwlagn_temperature, |
211 | .set_ct_kill = iwl1000_set_ct_threshold, | 212 | .set_ct_kill = iwl1000_set_ct_threshold, |
212 | }, | 213 | }, |
213 | .add_bcast_station = iwl_add_bcast_station, | 214 | .add_bcast_station = iwl_add_bcast_station, |
215 | .recover_from_tx_stall = iwl_bg_monitor_recover, | ||
216 | .check_plcp_health = iwl_good_plcp_health, | ||
217 | .check_ack_health = iwl_good_ack_health, | ||
214 | }; | 218 | }; |
215 | 219 | ||
216 | static const struct iwl_ops iwl1000_ops = { | 220 | static const struct iwl_ops iwl1000_ops = { |
217 | .ucode = &iwl5000_ucode, | 221 | .ucode = &iwlagn_ucode, |
218 | .lib = &iwl1000_lib, | 222 | .lib = &iwl1000_lib, |
219 | .hcmd = &iwl5000_hcmd, | 223 | .hcmd = &iwlagn_hcmd, |
220 | .utils = &iwl5000_hcmd_utils, | 224 | .utils = &iwlagn_hcmd_utils, |
221 | .led = &iwlagn_led_ops, | 225 | .led = &iwlagn_led_ops, |
222 | }; | 226 | }; |
223 | 227 | ||
224 | struct iwl_cfg iwl1000_bgn_cfg = { | 228 | struct iwl_cfg iwl1000_bgn_cfg = { |
225 | .name = "1000 Series BGN", | 229 | .name = "Intel(R) Centrino(R) Wireless-N 1000 BGN", |
226 | .fw_name_pre = IWL1000_FW_PRE, | 230 | .fw_name_pre = IWL1000_FW_PRE, |
227 | .ucode_api_max = IWL1000_UCODE_API_MAX, | 231 | .ucode_api_max = IWL1000_UCODE_API_MAX, |
228 | .ucode_api_min = IWL1000_UCODE_API_MIN, | 232 | .ucode_api_min = IWL1000_UCODE_API_MIN, |
@@ -230,10 +234,10 @@ struct iwl_cfg iwl1000_bgn_cfg = { | |||
230 | .ops = &iwl1000_ops, | 234 | .ops = &iwl1000_ops, |
231 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 235 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
232 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, | 236 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, |
233 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 237 | .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, |
234 | .num_of_queues = IWL50_NUM_QUEUES, | 238 | .num_of_queues = IWLAGN_NUM_QUEUES, |
235 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 239 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
236 | .mod_params = &iwl50_mod_params, | 240 | .mod_params = &iwlagn_mod_params, |
237 | .valid_tx_ant = ANT_A, | 241 | .valid_tx_ant = ANT_A, |
238 | .valid_rx_ant = ANT_AB, | 242 | .valid_rx_ant = ANT_AB, |
239 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | 243 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
@@ -248,10 +252,11 @@ struct iwl_cfg iwl1000_bgn_cfg = { | |||
248 | .support_ct_kill_exit = true, | 252 | .support_ct_kill_exit = true, |
249 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, | 253 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, |
250 | .chain_noise_scale = 1000, | 254 | .chain_noise_scale = 1000, |
255 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
251 | }; | 256 | }; |
252 | 257 | ||
253 | struct iwl_cfg iwl1000_bg_cfg = { | 258 | struct iwl_cfg iwl1000_bg_cfg = { |
254 | .name = "1000 Series BG", | 259 | .name = "Intel(R) Centrino(R) Wireless-N 1000 BG", |
255 | .fw_name_pre = IWL1000_FW_PRE, | 260 | .fw_name_pre = IWL1000_FW_PRE, |
256 | .ucode_api_max = IWL1000_UCODE_API_MAX, | 261 | .ucode_api_max = IWL1000_UCODE_API_MAX, |
257 | .ucode_api_min = IWL1000_UCODE_API_MIN, | 262 | .ucode_api_min = IWL1000_UCODE_API_MIN, |
@@ -259,10 +264,10 @@ struct iwl_cfg iwl1000_bg_cfg = { | |||
259 | .ops = &iwl1000_ops, | 264 | .ops = &iwl1000_ops, |
260 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 265 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
261 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, | 266 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, |
262 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 267 | .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, |
263 | .num_of_queues = IWL50_NUM_QUEUES, | 268 | .num_of_queues = IWLAGN_NUM_QUEUES, |
264 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 269 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
265 | .mod_params = &iwl50_mod_params, | 270 | .mod_params = &iwlagn_mod_params, |
266 | .valid_tx_ant = ANT_A, | 271 | .valid_tx_ant = ANT_A, |
267 | .valid_rx_ant = ANT_AB, | 272 | .valid_rx_ant = ANT_AB, |
268 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | 273 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
@@ -276,6 +281,7 @@ struct iwl_cfg iwl1000_bg_cfg = { | |||
276 | .support_ct_kill_exit = true, | 281 | .support_ct_kill_exit = true, |
277 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, | 282 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, |
278 | .chain_noise_scale = 1000, | 283 | .chain_noise_scale = 1000, |
284 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
279 | }; | 285 | }; |
280 | 286 | ||
281 | MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX)); | 287 | MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX)); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index 3a876a8ece38..91bcb4e3cdfb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h | |||
@@ -71,13 +71,11 @@ | |||
71 | 71 | ||
72 | #include "iwl-eeprom.h" | 72 | #include "iwl-eeprom.h" |
73 | 73 | ||
74 | /* Time constants */ | ||
75 | #define SHORT_SLOT_TIME 9 | ||
76 | #define LONG_SLOT_TIME 20 | ||
77 | |||
78 | /* RSSI to dBm */ | 74 | /* RSSI to dBm */ |
79 | #define IWL39_RSSI_OFFSET 95 | 75 | #define IWL39_RSSI_OFFSET 95 |
80 | 76 | ||
77 | #define IWL_DEFAULT_TX_POWER 0x0F | ||
78 | |||
81 | /* | 79 | /* |
82 | * EEPROM related constants, enums, and structures. | 80 | * EEPROM related constants, enums, and structures. |
83 | */ | 81 | */ |
@@ -228,7 +226,6 @@ struct iwl3945_eeprom { | |||
228 | 226 | ||
229 | /* 4 DATA + 1 CMD. There are 2 HCCA queues that are not used. */ | 227 | /* 4 DATA + 1 CMD. There are 2 HCCA queues that are not used. */ |
230 | #define IWL39_NUM_QUEUES 5 | 228 | #define IWL39_NUM_QUEUES 5 |
231 | #define IWL_NUM_SCAN_RATES (2) | ||
232 | 229 | ||
233 | #define IWL_DEFAULT_TX_RETRY 15 | 230 | #define IWL_DEFAULT_TX_RETRY 15 |
234 | 231 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index 47909f94271e..9e411dc0e5e1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c | |||
@@ -329,16 +329,25 @@ static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta, | |||
329 | 329 | ||
330 | } | 330 | } |
331 | 331 | ||
332 | static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, | 332 | /* |
333 | struct ieee80211_sta *sta, void *priv_sta) | 333 | * Called after adding a new station to initialize rate scaling |
334 | */ | ||
335 | void iwl3945_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_id) | ||
334 | { | 336 | { |
335 | struct iwl3945_rs_sta *rs_sta = priv_sta; | 337 | struct ieee80211_hw *hw = priv->hw; |
336 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; | 338 | struct ieee80211_conf *conf = &priv->hw->conf; |
339 | struct iwl3945_sta_priv *psta; | ||
340 | struct iwl3945_rs_sta *rs_sta; | ||
341 | struct ieee80211_supported_band *sband; | ||
337 | int i; | 342 | int i; |
338 | 343 | ||
339 | IWL_DEBUG_RATE(priv, "enter\n"); | 344 | IWL_DEBUG_INFO(priv, "enter\n"); |
345 | if (sta_id == priv->hw_params.bcast_sta_id) | ||
346 | goto out; | ||
340 | 347 | ||
341 | spin_lock_init(&rs_sta->lock); | 348 | psta = (struct iwl3945_sta_priv *) sta->drv_priv; |
349 | rs_sta = &psta->rs_sta; | ||
350 | sband = hw->wiphy->bands[conf->channel->band]; | ||
342 | 351 | ||
343 | rs_sta->priv = priv; | 352 | rs_sta->priv = priv; |
344 | 353 | ||
@@ -351,9 +360,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, | |||
351 | rs_sta->last_flush = jiffies; | 360 | rs_sta->last_flush = jiffies; |
352 | rs_sta->flush_time = IWL_RATE_FLUSH; | 361 | rs_sta->flush_time = IWL_RATE_FLUSH; |
353 | rs_sta->last_tx_packets = 0; | 362 | rs_sta->last_tx_packets = 0; |
354 | rs_sta->ibss_sta_added = 0; | ||
355 | 363 | ||
356 | init_timer(&rs_sta->rate_scale_flush); | ||
357 | rs_sta->rate_scale_flush.data = (unsigned long)rs_sta; | 364 | rs_sta->rate_scale_flush.data = (unsigned long)rs_sta; |
358 | rs_sta->rate_scale_flush.function = iwl3945_bg_rate_scale_flush; | 365 | rs_sta->rate_scale_flush.function = iwl3945_bg_rate_scale_flush; |
359 | 366 | ||
@@ -372,16 +379,18 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, | |||
372 | } | 379 | } |
373 | } | 380 | } |
374 | 381 | ||
375 | priv->sta_supp_rates = sta->supp_rates[sband->band]; | 382 | priv->_3945.sta_supp_rates = sta->supp_rates[sband->band]; |
376 | /* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */ | 383 | /* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */ |
377 | if (sband->band == IEEE80211_BAND_5GHZ) { | 384 | if (sband->band == IEEE80211_BAND_5GHZ) { |
378 | rs_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; | 385 | rs_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; |
379 | priv->sta_supp_rates = priv->sta_supp_rates << | 386 | priv->_3945.sta_supp_rates = priv->_3945.sta_supp_rates << |
380 | IWL_FIRST_OFDM_RATE; | 387 | IWL_FIRST_OFDM_RATE; |
381 | } | 388 | } |
382 | 389 | ||
390 | out: | ||
391 | priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; | ||
383 | 392 | ||
384 | IWL_DEBUG_RATE(priv, "leave\n"); | 393 | IWL_DEBUG_INFO(priv, "leave\n"); |
385 | } | 394 | } |
386 | 395 | ||
387 | static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) | 396 | static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) |
@@ -405,6 +414,9 @@ static void *rs_alloc_sta(void *iwl_priv, struct ieee80211_sta *sta, gfp_t gfp) | |||
405 | 414 | ||
406 | rs_sta = &psta->rs_sta; | 415 | rs_sta = &psta->rs_sta; |
407 | 416 | ||
417 | spin_lock_init(&rs_sta->lock); | ||
418 | init_timer(&rs_sta->rate_scale_flush); | ||
419 | |||
408 | IWL_DEBUG_RATE(priv, "leave\n"); | 420 | IWL_DEBUG_RATE(priv, "leave\n"); |
409 | 421 | ||
410 | return rs_sta; | 422 | return rs_sta; |
@@ -413,13 +425,14 @@ static void *rs_alloc_sta(void *iwl_priv, struct ieee80211_sta *sta, gfp_t gfp) | |||
413 | static void rs_free_sta(void *iwl_priv, struct ieee80211_sta *sta, | 425 | static void rs_free_sta(void *iwl_priv, struct ieee80211_sta *sta, |
414 | void *priv_sta) | 426 | void *priv_sta) |
415 | { | 427 | { |
416 | struct iwl3945_sta_priv *psta = (void *) sta->drv_priv; | 428 | struct iwl3945_rs_sta *rs_sta = priv_sta; |
417 | struct iwl3945_rs_sta *rs_sta = &psta->rs_sta; | ||
418 | struct iwl_priv *priv __maybe_unused = rs_sta->priv; | ||
419 | 429 | ||
420 | IWL_DEBUG_RATE(priv, "enter\n"); | 430 | /* |
431 | * Be careful not to use any members of iwl3945_rs_sta (like trying | ||
432 | * to use iwl_priv to print out debugging) since it may not be fully | ||
433 | * initialized at this point. | ||
434 | */ | ||
421 | del_timer_sync(&rs_sta->rate_scale_flush); | 435 | del_timer_sync(&rs_sta->rate_scale_flush); |
422 | IWL_DEBUG_RATE(priv, "leave\n"); | ||
423 | } | 436 | } |
424 | 437 | ||
425 | 438 | ||
@@ -458,6 +471,13 @@ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband | |||
458 | return; | 471 | return; |
459 | } | 472 | } |
460 | 473 | ||
474 | /* Treat uninitialized rate scaling data same as non-existing. */ | ||
475 | if (!rs_sta->priv) { | ||
476 | IWL_DEBUG_RATE(priv, "leave: STA priv data uninitialized!\n"); | ||
477 | return; | ||
478 | } | ||
479 | |||
480 | |||
461 | rs_sta->tx_packets++; | 481 | rs_sta->tx_packets++; |
462 | 482 | ||
463 | scale_rate_index = first_index; | 483 | scale_rate_index = first_index; |
@@ -625,7 +645,6 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, | |||
625 | u32 fail_count; | 645 | u32 fail_count; |
626 | s8 scale_action = 0; | 646 | s8 scale_action = 0; |
627 | unsigned long flags; | 647 | unsigned long flags; |
628 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
629 | u16 rate_mask = sta ? sta->supp_rates[sband->band] : 0; | 648 | u16 rate_mask = sta ? sta->supp_rates[sband->band] : 0; |
630 | s8 max_rate_idx = -1; | 649 | s8 max_rate_idx = -1; |
631 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; | 650 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; |
@@ -633,6 +652,12 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, | |||
633 | 652 | ||
634 | IWL_DEBUG_RATE(priv, "enter\n"); | 653 | IWL_DEBUG_RATE(priv, "enter\n"); |
635 | 654 | ||
655 | /* Treat uninitialized rate scaling data same as non-existing. */ | ||
656 | if (rs_sta && !rs_sta->priv) { | ||
657 | IWL_DEBUG_RATE(priv, "Rate scaling information not initialized yet.\n"); | ||
658 | priv_sta = NULL; | ||
659 | } | ||
660 | |||
636 | if (rate_control_send_low(sta, priv_sta, txrc)) | 661 | if (rate_control_send_low(sta, priv_sta, txrc)) |
637 | return; | 662 | return; |
638 | 663 | ||
@@ -650,20 +675,6 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, | |||
650 | if (sband->band == IEEE80211_BAND_5GHZ) | 675 | if (sband->band == IEEE80211_BAND_5GHZ) |
651 | rate_mask = rate_mask << IWL_FIRST_OFDM_RATE; | 676 | rate_mask = rate_mask << IWL_FIRST_OFDM_RATE; |
652 | 677 | ||
653 | if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && | ||
654 | !rs_sta->ibss_sta_added) { | ||
655 | u8 sta_id = iwl_find_station(priv, hdr->addr1); | ||
656 | |||
657 | if (sta_id == IWL_INVALID_STATION) { | ||
658 | IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", | ||
659 | hdr->addr1); | ||
660 | sta_id = iwl_add_station(priv, hdr->addr1, false, | ||
661 | CMD_ASYNC, NULL); | ||
662 | } | ||
663 | if (sta_id != IWL_INVALID_STATION) | ||
664 | rs_sta->ibss_sta_added = 1; | ||
665 | } | ||
666 | |||
667 | spin_lock_irqsave(&rs_sta->lock, flags); | 678 | spin_lock_irqsave(&rs_sta->lock, flags); |
668 | 679 | ||
669 | /* for recent assoc, choose best rate regarding | 680 | /* for recent assoc, choose best rate regarding |
@@ -883,12 +894,22 @@ static void iwl3945_remove_debugfs(void *priv, void *priv_sta) | |||
883 | } | 894 | } |
884 | #endif | 895 | #endif |
885 | 896 | ||
897 | /* | ||
898 | * Initialization of rate scaling information is done by driver after | ||
899 | * the station is added. Since mac80211 calls this function before a | ||
900 | * station is added we ignore it. | ||
901 | */ | ||
902 | static void rs_rate_init_stub(void *priv_r, struct ieee80211_supported_band *sband, | ||
903 | struct ieee80211_sta *sta, void *priv_sta) | ||
904 | { | ||
905 | } | ||
906 | |||
886 | static struct rate_control_ops rs_ops = { | 907 | static struct rate_control_ops rs_ops = { |
887 | .module = NULL, | 908 | .module = NULL, |
888 | .name = RS_NAME, | 909 | .name = RS_NAME, |
889 | .tx_status = rs_tx_status, | 910 | .tx_status = rs_tx_status, |
890 | .get_rate = rs_get_rate, | 911 | .get_rate = rs_get_rate, |
891 | .rate_init = rs_rate_init, | 912 | .rate_init = rs_rate_init_stub, |
892 | .alloc = rs_alloc, | 913 | .alloc = rs_alloc, |
893 | .free = rs_free, | 914 | .free = rs_free, |
894 | .alloc_sta = rs_alloc_sta, | 915 | .alloc_sta = rs_alloc_sta, |
@@ -899,7 +920,6 @@ static struct rate_control_ops rs_ops = { | |||
899 | #endif | 920 | #endif |
900 | 921 | ||
901 | }; | 922 | }; |
902 | |||
903 | void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) | 923 | void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) |
904 | { | 924 | { |
905 | struct iwl_priv *priv = hw->priv; | 925 | struct iwl_priv *priv = hw->priv; |
@@ -916,6 +936,7 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) | |||
916 | sta = ieee80211_find_sta(priv->vif, | 936 | sta = ieee80211_find_sta(priv->vif, |
917 | priv->stations[sta_id].sta.sta.addr); | 937 | priv->stations[sta_id].sta.sta.addr); |
918 | if (!sta) { | 938 | if (!sta) { |
939 | IWL_DEBUG_RATE(priv, "Unable to find station to initialize rate scaling.\n"); | ||
919 | rcu_read_unlock(); | 940 | rcu_read_unlock(); |
920 | return; | 941 | return; |
921 | } | 942 | } |
@@ -946,7 +967,7 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) | |||
946 | 967 | ||
947 | spin_unlock_irqrestore(&rs_sta->lock, flags); | 968 | spin_unlock_irqrestore(&rs_sta->lock, flags); |
948 | 969 | ||
949 | rssi = priv->last_rx_rssi; | 970 | rssi = priv->_3945.last_rx_rssi; |
950 | if (rssi == 0) | 971 | if (rssi == 0) |
951 | rssi = IWL_MIN_RSSI_VAL; | 972 | rssi = IWL_MIN_RSSI_VAL; |
952 | 973 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index e0678d921055..f88f75dfd96e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c | |||
@@ -242,7 +242,7 @@ int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate) | |||
242 | next_rate = IWL_RATE_6M_INDEX; | 242 | next_rate = IWL_RATE_6M_INDEX; |
243 | break; | 243 | break; |
244 | case IEEE80211_BAND_2GHZ: | 244 | case IEEE80211_BAND_2GHZ: |
245 | if (!(priv->sta_supp_rates & IWL_OFDM_RATES_MASK) && | 245 | if (!(priv->_3945.sta_supp_rates & IWL_OFDM_RATES_MASK) && |
246 | iwl_is_associated(priv)) { | 246 | iwl_is_associated(priv)) { |
247 | if (rate == IWL_RATE_11M_INDEX) | 247 | if (rate == IWL_RATE_11M_INDEX) |
248 | next_rate = IWL_RATE_5M_INDEX; | 248 | next_rate = IWL_RATE_5M_INDEX; |
@@ -359,7 +359,7 @@ void iwl3945_hw_rx_statistics(struct iwl_priv *priv, | |||
359 | (int)sizeof(struct iwl3945_notif_statistics), | 359 | (int)sizeof(struct iwl3945_notif_statistics), |
360 | le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); | 360 | le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); |
361 | 361 | ||
362 | memcpy(&priv->statistics_39, pkt->u.raw, sizeof(priv->statistics_39)); | 362 | memcpy(&priv->_3945.statistics, pkt->u.raw, sizeof(priv->_3945.statistics)); |
363 | } | 363 | } |
364 | 364 | ||
365 | /****************************************************************************** | 365 | /****************************************************************************** |
@@ -486,7 +486,7 @@ static void _iwl3945_dbg_report_frame(struct iwl_priv *priv, | |||
486 | * but you can hack it to show more, if you'd like to. */ | 486 | * but you can hack it to show more, if you'd like to. */ |
487 | if (dataframe) | 487 | if (dataframe) |
488 | IWL_DEBUG_RX(priv, "%s: mhd=0x%04x, dst=0x%02x, " | 488 | IWL_DEBUG_RX(priv, "%s: mhd=0x%04x, dst=0x%02x, " |
489 | "len=%u, rssi=%d, chnl=%d, rate=%d, \n", | 489 | "len=%u, rssi=%d, chnl=%d, rate=%d,\n", |
490 | title, le16_to_cpu(fc), header->addr1[5], | 490 | title, le16_to_cpu(fc), header->addr1[5], |
491 | length, rssi, channel, rate); | 491 | length, rssi, channel, rate); |
492 | else { | 492 | else { |
@@ -548,7 +548,6 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv, | |||
548 | struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); | 548 | struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); |
549 | u16 len = le16_to_cpu(rx_hdr->len); | 549 | u16 len = le16_to_cpu(rx_hdr->len); |
550 | struct sk_buff *skb; | 550 | struct sk_buff *skb; |
551 | int ret; | ||
552 | __le16 fc = hdr->frame_control; | 551 | __le16 fc = hdr->frame_control; |
553 | 552 | ||
554 | /* We received data from the HW, so stop the watchdog */ | 553 | /* We received data from the HW, so stop the watchdog */ |
@@ -565,9 +564,9 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv, | |||
565 | return; | 564 | return; |
566 | } | 565 | } |
567 | 566 | ||
568 | skb = alloc_skb(IWL_LINK_HDR_MAX * 2, GFP_ATOMIC); | 567 | skb = dev_alloc_skb(128); |
569 | if (!skb) { | 568 | if (!skb) { |
570 | IWL_ERR(priv, "alloc_skb failed\n"); | 569 | IWL_ERR(priv, "dev_alloc_skb failed\n"); |
571 | return; | 570 | return; |
572 | } | 571 | } |
573 | 572 | ||
@@ -576,37 +575,13 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv, | |||
576 | (struct ieee80211_hdr *)rxb_addr(rxb), | 575 | (struct ieee80211_hdr *)rxb_addr(rxb), |
577 | le32_to_cpu(rx_end->status), stats); | 576 | le32_to_cpu(rx_end->status), stats); |
578 | 577 | ||
579 | skb_reserve(skb, IWL_LINK_HDR_MAX); | ||
580 | skb_add_rx_frag(skb, 0, rxb->page, | 578 | skb_add_rx_frag(skb, 0, rxb->page, |
581 | (void *)rx_hdr->payload - (void *)pkt, len); | 579 | (void *)rx_hdr->payload - (void *)pkt, len); |
582 | 580 | ||
583 | /* mac80211 currently doesn't support paged SKB. Convert it to | ||
584 | * linear SKB for management frame and data frame requires | ||
585 | * software decryption or software defragementation. */ | ||
586 | if (ieee80211_is_mgmt(fc) || | ||
587 | ieee80211_has_protected(fc) || | ||
588 | ieee80211_has_morefrags(fc) || | ||
589 | le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) | ||
590 | ret = skb_linearize(skb); | ||
591 | else | ||
592 | ret = __pskb_pull_tail(skb, min_t(u16, IWL_LINK_HDR_MAX, len)) ? | ||
593 | 0 : -ENOMEM; | ||
594 | |||
595 | if (ret) { | ||
596 | kfree_skb(skb); | ||
597 | goto out; | ||
598 | } | ||
599 | |||
600 | /* | ||
601 | * XXX: We cannot touch the page and its virtual memory (pkt) after | ||
602 | * here. It might have already been freed by the above skb change. | ||
603 | */ | ||
604 | |||
605 | iwl_update_stats(priv, false, fc, len); | 581 | iwl_update_stats(priv, false, fc, len); |
606 | memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); | 582 | memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); |
607 | 583 | ||
608 | ieee80211_rx(priv->hw, skb); | 584 | ieee80211_rx(priv->hw, skb); |
609 | out: | ||
610 | priv->alloc_rxb_page--; | 585 | priv->alloc_rxb_page--; |
611 | rxb->page = NULL; | 586 | rxb->page = NULL; |
612 | } | 587 | } |
@@ -622,7 +597,6 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv, | |||
622 | struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt); | 597 | struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt); |
623 | struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); | 598 | struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); |
624 | struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); | 599 | struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); |
625 | int snr; | ||
626 | u16 rx_stats_sig_avg = le16_to_cpu(rx_stats->sig_avg); | 600 | u16 rx_stats_sig_avg = le16_to_cpu(rx_stats->sig_avg); |
627 | u16 rx_stats_noise_diff = le16_to_cpu(rx_stats->noise_diff); | 601 | u16 rx_stats_noise_diff = le16_to_cpu(rx_stats->noise_diff); |
628 | u8 network_packet; | 602 | u8 network_packet; |
@@ -662,53 +636,29 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv, | |||
662 | /* Convert 3945's rssi indicator to dBm */ | 636 | /* Convert 3945's rssi indicator to dBm */ |
663 | rx_status.signal = rx_stats->rssi - IWL39_RSSI_OFFSET; | 637 | rx_status.signal = rx_stats->rssi - IWL39_RSSI_OFFSET; |
664 | 638 | ||
665 | /* Set default noise value to -127 */ | 639 | IWL_DEBUG_STATS(priv, "Rssi %d sig_avg %d noise_diff %d\n", |
666 | if (priv->last_rx_noise == 0) | 640 | rx_status.signal, rx_stats_sig_avg, |
667 | priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; | 641 | rx_stats_noise_diff); |
668 | |||
669 | /* 3945 provides noise info for OFDM frames only. | ||
670 | * sig_avg and noise_diff are measured by the 3945's digital signal | ||
671 | * processor (DSP), and indicate linear levels of signal level and | ||
672 | * distortion/noise within the packet preamble after | ||
673 | * automatic gain control (AGC). sig_avg should stay fairly | ||
674 | * constant if the radio's AGC is working well. | ||
675 | * Since these values are linear (not dB or dBm), linear | ||
676 | * signal-to-noise ratio (SNR) is (sig_avg / noise_diff). | ||
677 | * Convert linear SNR to dB SNR, then subtract that from rssi dBm | ||
678 | * to obtain noise level in dBm. | ||
679 | * Calculate rx_status.signal (quality indicator in %) based on SNR. */ | ||
680 | if (rx_stats_noise_diff) { | ||
681 | snr = rx_stats_sig_avg / rx_stats_noise_diff; | ||
682 | rx_status.noise = rx_status.signal - | ||
683 | iwl3945_calc_db_from_ratio(snr); | ||
684 | } else { | ||
685 | rx_status.noise = priv->last_rx_noise; | ||
686 | } | ||
687 | |||
688 | |||
689 | IWL_DEBUG_STATS(priv, "Rssi %d noise %d sig_avg %d noise_diff %d\n", | ||
690 | rx_status.signal, rx_status.noise, | ||
691 | rx_stats_sig_avg, rx_stats_noise_diff); | ||
692 | 642 | ||
693 | header = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); | 643 | header = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); |
694 | 644 | ||
695 | network_packet = iwl3945_is_network_packet(priv, header); | 645 | network_packet = iwl3945_is_network_packet(priv, header); |
696 | 646 | ||
697 | IWL_DEBUG_STATS_LIMIT(priv, "[%c] %d RSSI:%d Signal:%u, Noise:%u, Rate:%u\n", | 647 | IWL_DEBUG_STATS_LIMIT(priv, "[%c] %d RSSI:%d Signal:%u, Rate:%u\n", |
698 | network_packet ? '*' : ' ', | 648 | network_packet ? '*' : ' ', |
699 | le16_to_cpu(rx_hdr->channel), | 649 | le16_to_cpu(rx_hdr->channel), |
700 | rx_status.signal, rx_status.signal, | 650 | rx_status.signal, rx_status.signal, |
701 | rx_status.noise, rx_status.rate_idx); | 651 | rx_status.rate_idx); |
702 | 652 | ||
703 | /* Set "1" to report good data frames in groups of 100 */ | 653 | /* Set "1" to report good data frames in groups of 100 */ |
704 | iwl3945_dbg_report_frame(priv, pkt, header, 1); | 654 | iwl3945_dbg_report_frame(priv, pkt, header, 1); |
705 | iwl_dbg_log_rx_data_frame(priv, le16_to_cpu(rx_hdr->len), header); | 655 | iwl_dbg_log_rx_data_frame(priv, le16_to_cpu(rx_hdr->len), header); |
706 | 656 | ||
707 | if (network_packet) { | 657 | if (network_packet) { |
708 | priv->last_beacon_time = le32_to_cpu(rx_end->beacon_timestamp); | 658 | priv->_3945.last_beacon_time = |
709 | priv->last_tsf = le64_to_cpu(rx_end->timestamp); | 659 | le32_to_cpu(rx_end->beacon_timestamp); |
710 | priv->last_rx_rssi = rx_status.signal; | 660 | priv->_3945.last_tsf = le64_to_cpu(rx_end->timestamp); |
711 | priv->last_rx_noise = rx_status.noise; | 661 | priv->_3945.last_rx_rssi = rx_status.signal; |
712 | } | 662 | } |
713 | 663 | ||
714 | iwl3945_pass_packet_to_mac80211(priv, rxb, &rx_status); | 664 | iwl3945_pass_packet_to_mac80211(priv, rxb, &rx_status); |
@@ -956,7 +906,7 @@ static int iwl3945_tx_reset(struct iwl_priv *priv) | |||
956 | iwl_write_prph(priv, ALM_SCD_TXF5MF_REG, 0x000005); | 906 | iwl_write_prph(priv, ALM_SCD_TXF5MF_REG, 0x000005); |
957 | 907 | ||
958 | iwl_write_direct32(priv, FH39_TSSR_CBB_BASE, | 908 | iwl_write_direct32(priv, FH39_TSSR_CBB_BASE, |
959 | priv->shared_phys); | 909 | priv->_3945.shared_phys); |
960 | 910 | ||
961 | iwl_write_direct32(priv, FH39_TSSR_MSG_CONFIG, | 911 | iwl_write_direct32(priv, FH39_TSSR_MSG_CONFIG, |
962 | FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON | | 912 | FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON | |
@@ -1048,7 +998,7 @@ static void iwl3945_nic_config(struct iwl_priv *priv) | |||
1048 | IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", rev_id); | 998 | IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", rev_id); |
1049 | 999 | ||
1050 | if (rev_id & PCI_CFG_REV_ID_BIT_RTP) | 1000 | if (rev_id & PCI_CFG_REV_ID_BIT_RTP) |
1051 | IWL_DEBUG_INFO(priv, "RTP type \n"); | 1001 | IWL_DEBUG_INFO(priv, "RTP type\n"); |
1052 | else if (rev_id & PCI_CFG_REV_ID_BIT_BASIC_SKU) { | 1002 | else if (rev_id & PCI_CFG_REV_ID_BIT_BASIC_SKU) { |
1053 | IWL_DEBUG_INFO(priv, "3945 RADIO-MB type\n"); | 1003 | IWL_DEBUG_INFO(priv, "3945 RADIO-MB type\n"); |
1054 | iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, | 1004 | iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, |
@@ -1606,7 +1556,7 @@ static int iwl3945_hw_reg_set_new_power(struct iwl_priv *priv, | |||
1606 | int power; | 1556 | int power; |
1607 | 1557 | ||
1608 | /* Get this chnlgrp's rate-to-max/clip-powers table */ | 1558 | /* Get this chnlgrp's rate-to-max/clip-powers table */ |
1609 | clip_pwrs = priv->clip39_groups[ch_info->group_index].clip_powers; | 1559 | clip_pwrs = priv->_3945.clip_groups[ch_info->group_index].clip_powers; |
1610 | 1560 | ||
1611 | /* Get this channel's rate-to-current-power settings table */ | 1561 | /* Get this channel's rate-to-current-power settings table */ |
1612 | power_info = ch_info->power_info; | 1562 | power_info = ch_info->power_info; |
@@ -1732,7 +1682,7 @@ static int iwl3945_hw_reg_comp_txpower_temp(struct iwl_priv *priv) | |||
1732 | } | 1682 | } |
1733 | 1683 | ||
1734 | /* Get this chnlgrp's rate-to-max/clip-powers table */ | 1684 | /* Get this chnlgrp's rate-to-max/clip-powers table */ |
1735 | clip_pwrs = priv->clip39_groups[ch_info->group_index].clip_powers; | 1685 | clip_pwrs = priv->_3945.clip_groups[ch_info->group_index].clip_powers; |
1736 | 1686 | ||
1737 | /* set scan tx power, 1Mbit for CCK, 6Mbit for OFDM */ | 1687 | /* set scan tx power, 1Mbit for CCK, 6Mbit for OFDM */ |
1738 | for (scan_tbl_index = 0; | 1688 | for (scan_tbl_index = 0; |
@@ -1910,6 +1860,8 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) | |||
1910 | "configuration (%d).\n", rc); | 1860 | "configuration (%d).\n", rc); |
1911 | return rc; | 1861 | return rc; |
1912 | } | 1862 | } |
1863 | iwl_clear_ucode_stations(priv, false); | ||
1864 | iwl_restore_stations(priv); | ||
1913 | } | 1865 | } |
1914 | 1866 | ||
1915 | IWL_DEBUG_INFO(priv, "Sending RXON\n" | 1867 | IWL_DEBUG_INFO(priv, "Sending RXON\n" |
@@ -1940,7 +1892,10 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) | |||
1940 | 1892 | ||
1941 | memcpy(active_rxon, staging_rxon, sizeof(*active_rxon)); | 1893 | memcpy(active_rxon, staging_rxon, sizeof(*active_rxon)); |
1942 | 1894 | ||
1943 | iwl_clear_stations_table(priv); | 1895 | if (!new_assoc) { |
1896 | iwl_clear_ucode_stations(priv, false); | ||
1897 | iwl_restore_stations(priv); | ||
1898 | } | ||
1944 | 1899 | ||
1945 | /* If we issue a new RXON command which required a tune then we must | 1900 | /* If we issue a new RXON command which required a tune then we must |
1946 | * send a new TXPOWER command or we won't be able to Tx any frames */ | 1901 | * send a new TXPOWER command or we won't be able to Tx any frames */ |
@@ -1950,19 +1905,6 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) | |||
1950 | return rc; | 1905 | return rc; |
1951 | } | 1906 | } |
1952 | 1907 | ||
1953 | /* Add the broadcast address so we can send broadcast frames */ | ||
1954 | priv->cfg->ops->lib->add_bcast_station(priv); | ||
1955 | |||
1956 | /* If we have set the ASSOC_MSK and we are in BSS mode then | ||
1957 | * add the IWL_AP_ID to the station rate table */ | ||
1958 | if (iwl_is_associated(priv) && | ||
1959 | (priv->iw_mode == NL80211_IFTYPE_STATION)) | ||
1960 | if (iwl_add_station(priv, priv->active_rxon.bssid_addr, | ||
1961 | true, CMD_SYNC, NULL) == IWL_INVALID_STATION) { | ||
1962 | IWL_ERR(priv, "Error adding AP address for transmit\n"); | ||
1963 | return -EIO; | ||
1964 | } | ||
1965 | |||
1966 | /* Init the hardware's rate fallback order based on the band */ | 1908 | /* Init the hardware's rate fallback order based on the band */ |
1967 | rc = iwl3945_init_hw_rate_table(priv); | 1909 | rc = iwl3945_init_hw_rate_table(priv); |
1968 | if (rc) { | 1910 | if (rc) { |
@@ -1997,13 +1939,13 @@ void iwl3945_reg_txpower_periodic(struct iwl_priv *priv) | |||
1997 | 1939 | ||
1998 | reschedule: | 1940 | reschedule: |
1999 | queue_delayed_work(priv->workqueue, | 1941 | queue_delayed_work(priv->workqueue, |
2000 | &priv->thermal_periodic, REG_RECALIB_PERIOD * HZ); | 1942 | &priv->_3945.thermal_periodic, REG_RECALIB_PERIOD * HZ); |
2001 | } | 1943 | } |
2002 | 1944 | ||
2003 | static void iwl3945_bg_reg_txpower_periodic(struct work_struct *work) | 1945 | static void iwl3945_bg_reg_txpower_periodic(struct work_struct *work) |
2004 | { | 1946 | { |
2005 | struct iwl_priv *priv = container_of(work, struct iwl_priv, | 1947 | struct iwl_priv *priv = container_of(work, struct iwl_priv, |
2006 | thermal_periodic.work); | 1948 | _3945.thermal_periodic.work); |
2007 | 1949 | ||
2008 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 1950 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
2009 | return; | 1951 | return; |
@@ -2139,7 +2081,7 @@ static void iwl3945_hw_reg_init_channel_groups(struct iwl_priv *priv) | |||
2139 | * power peaks, without too much distortion (clipping). | 2081 | * power peaks, without too much distortion (clipping). |
2140 | */ | 2082 | */ |
2141 | /* we'll fill in this array with h/w max power levels */ | 2083 | /* we'll fill in this array with h/w max power levels */ |
2142 | clip_pwrs = (s8 *) priv->clip39_groups[i].clip_powers; | 2084 | clip_pwrs = (s8 *) priv->_3945.clip_groups[i].clip_powers; |
2143 | 2085 | ||
2144 | /* divide factory saturation power by 2 to find -3dB level */ | 2086 | /* divide factory saturation power by 2 to find -3dB level */ |
2145 | satur_pwr = (s8) (group->saturation_power >> 1); | 2087 | satur_pwr = (s8) (group->saturation_power >> 1); |
@@ -2223,7 +2165,7 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv) | |||
2223 | iwl3945_hw_reg_get_ch_grp_index(priv, ch_info); | 2165 | iwl3945_hw_reg_get_ch_grp_index(priv, ch_info); |
2224 | 2166 | ||
2225 | /* Get this chnlgrp's rate->max/clip-powers table */ | 2167 | /* Get this chnlgrp's rate->max/clip-powers table */ |
2226 | clip_pwrs = priv->clip39_groups[ch_info->group_index].clip_powers; | 2168 | clip_pwrs = priv->_3945.clip_groups[ch_info->group_index].clip_powers; |
2227 | 2169 | ||
2228 | /* calculate power index *adjustment* value according to | 2170 | /* calculate power index *adjustment* value according to |
2229 | * diff between current temperature and factory temperature */ | 2171 | * diff between current temperature and factory temperature */ |
@@ -2331,7 +2273,7 @@ int iwl3945_hw_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq) | |||
2331 | { | 2273 | { |
2332 | int txq_id = txq->q.id; | 2274 | int txq_id = txq->q.id; |
2333 | 2275 | ||
2334 | struct iwl3945_shared *shared_data = priv->shared_virt; | 2276 | struct iwl3945_shared *shared_data = priv->_3945.shared_virt; |
2335 | 2277 | ||
2336 | shared_data->tx_base_ptr[txq_id] = cpu_to_le32((u32)txq->q.dma_addr); | 2278 | shared_data->tx_base_ptr[txq_id] = cpu_to_le32((u32)txq->q.dma_addr); |
2337 | 2279 | ||
@@ -2431,7 +2373,7 @@ int iwl3945_init_hw_rate_table(struct iwl_priv *priv) | |||
2431 | /* If an OFDM rate is used, have it fall back to the | 2373 | /* If an OFDM rate is used, have it fall back to the |
2432 | * 1M CCK rates */ | 2374 | * 1M CCK rates */ |
2433 | 2375 | ||
2434 | if (!(priv->sta_supp_rates & IWL_OFDM_RATES_MASK) && | 2376 | if (!(priv->_3945.sta_supp_rates & IWL_OFDM_RATES_MASK) && |
2435 | iwl_is_associated(priv)) { | 2377 | iwl_is_associated(priv)) { |
2436 | 2378 | ||
2437 | index = IWL_FIRST_CCK_RATE; | 2379 | index = IWL_FIRST_CCK_RATE; |
@@ -2470,10 +2412,11 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv) | |||
2470 | memset((void *)&priv->hw_params, 0, | 2412 | memset((void *)&priv->hw_params, 0, |
2471 | sizeof(struct iwl_hw_params)); | 2413 | sizeof(struct iwl_hw_params)); |
2472 | 2414 | ||
2473 | priv->shared_virt = dma_alloc_coherent(&priv->pci_dev->dev, | 2415 | priv->_3945.shared_virt = |
2474 | sizeof(struct iwl3945_shared), | 2416 | dma_alloc_coherent(&priv->pci_dev->dev, |
2475 | &priv->shared_phys, GFP_KERNEL); | 2417 | sizeof(struct iwl3945_shared), |
2476 | if (!priv->shared_virt) { | 2418 | &priv->_3945.shared_phys, GFP_KERNEL); |
2419 | if (!priv->_3945.shared_virt) { | ||
2477 | IWL_ERR(priv, "failed to allocate pci memory\n"); | 2420 | IWL_ERR(priv, "failed to allocate pci memory\n"); |
2478 | mutex_unlock(&priv->mutex); | 2421 | mutex_unlock(&priv->mutex); |
2479 | return -ENOMEM; | 2422 | return -ENOMEM; |
@@ -2536,13 +2479,13 @@ void iwl3945_hw_rx_handler_setup(struct iwl_priv *priv) | |||
2536 | 2479 | ||
2537 | void iwl3945_hw_setup_deferred_work(struct iwl_priv *priv) | 2480 | void iwl3945_hw_setup_deferred_work(struct iwl_priv *priv) |
2538 | { | 2481 | { |
2539 | INIT_DELAYED_WORK(&priv->thermal_periodic, | 2482 | INIT_DELAYED_WORK(&priv->_3945.thermal_periodic, |
2540 | iwl3945_bg_reg_txpower_periodic); | 2483 | iwl3945_bg_reg_txpower_periodic); |
2541 | } | 2484 | } |
2542 | 2485 | ||
2543 | void iwl3945_hw_cancel_deferred_work(struct iwl_priv *priv) | 2486 | void iwl3945_hw_cancel_deferred_work(struct iwl_priv *priv) |
2544 | { | 2487 | { |
2545 | cancel_delayed_work(&priv->thermal_periodic); | 2488 | cancel_delayed_work(&priv->_3945.thermal_periodic); |
2546 | } | 2489 | } |
2547 | 2490 | ||
2548 | /* check contents of special bootstrap uCode SRAM */ | 2491 | /* check contents of special bootstrap uCode SRAM */ |
@@ -2826,6 +2769,7 @@ static struct iwl_cfg iwl3945_bg_cfg = { | |||
2826 | .led_compensation = 64, | 2769 | .led_compensation = 64, |
2827 | .broken_powersave = true, | 2770 | .broken_powersave = true, |
2828 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 2771 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
2772 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
2829 | }; | 2773 | }; |
2830 | 2774 | ||
2831 | static struct iwl_cfg iwl3945_abg_cfg = { | 2775 | static struct iwl_cfg iwl3945_abg_cfg = { |
@@ -2844,6 +2788,7 @@ static struct iwl_cfg iwl3945_abg_cfg = { | |||
2844 | .led_compensation = 64, | 2788 | .led_compensation = 64, |
2845 | .broken_powersave = true, | 2789 | .broken_powersave = true, |
2846 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 2790 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
2791 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
2847 | }; | 2792 | }; |
2848 | 2793 | ||
2849 | DEFINE_PCI_DEVICE_TABLE(iwl3945_hw_card_ids) = { | 2794 | DEFINE_PCI_DEVICE_TABLE(iwl3945_hw_card_ids) = { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 452dfd5456c6..b89219573b91 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h | |||
@@ -95,7 +95,6 @@ struct iwl3945_rs_sta { | |||
95 | u8 tgg; | 95 | u8 tgg; |
96 | u8 flush_pending; | 96 | u8 flush_pending; |
97 | u8 start_rate; | 97 | u8 start_rate; |
98 | u8 ibss_sta_added; | ||
99 | struct timer_list rate_scale_flush; | 98 | struct timer_list rate_scale_flush; |
100 | struct iwl3945_rate_scale_data win[IWL_RATE_COUNT_3945]; | 99 | struct iwl3945_rate_scale_data win[IWL_RATE_COUNT_3945]; |
101 | #ifdef CONFIG_MAC80211_DEBUGFS | 100 | #ifdef CONFIG_MAC80211_DEBUGFS |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index 67ef562e8db1..cd4b61ae25b7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h | |||
@@ -81,26 +81,6 @@ | |||
81 | */ | 81 | */ |
82 | #define IWL49_FIRST_AMPDU_QUEUE 7 | 82 | #define IWL49_FIRST_AMPDU_QUEUE 7 |
83 | 83 | ||
84 | /* Time constants */ | ||
85 | #define SHORT_SLOT_TIME 9 | ||
86 | #define LONG_SLOT_TIME 20 | ||
87 | |||
88 | /* RSSI to dBm */ | ||
89 | #define IWL49_RSSI_OFFSET 44 | ||
90 | |||
91 | |||
92 | /* PCI registers */ | ||
93 | #define PCI_CFG_RETRY_TIMEOUT 0x041 | ||
94 | |||
95 | /* PCI register values */ | ||
96 | #define PCI_CFG_LINK_CTRL_VAL_L0S_EN 0x01 | ||
97 | #define PCI_CFG_LINK_CTRL_VAL_L1_EN 0x02 | ||
98 | |||
99 | #define IWL_NUM_SCAN_RATES (2) | ||
100 | |||
101 | #define IWL_DEFAULT_TX_RETRY 15 | ||
102 | |||
103 | |||
104 | /* Sizes and addresses for instruction and data memory (SRAM) in | 84 | /* Sizes and addresses for instruction and data memory (SRAM) in |
105 | * 4965's embedded processor. Driver access is via HBUS_TARG_MEM_* regs. */ | 85 | * 4965's embedded processor. Driver access is via HBUS_TARG_MEM_* regs. */ |
106 | #define IWL49_RTC_INST_LOWER_BOUND (0x000000) | 86 | #define IWL49_RTC_INST_LOWER_BOUND (0x000000) |
@@ -393,10 +373,6 @@ static inline int iwl4965_hw_valid_rtc_data_addr(u32 addr) | |||
393 | * location(s) in command (struct iwl4965_txpowertable_cmd). | 373 | * location(s) in command (struct iwl4965_txpowertable_cmd). |
394 | */ | 374 | */ |
395 | 375 | ||
396 | /* Limit range of txpower output target to be between these values */ | ||
397 | #define IWL_TX_POWER_TARGET_POWER_MIN (0) /* 0 dBm = 1 milliwatt */ | ||
398 | #define IWL_TX_POWER_TARGET_POWER_MAX (16) /* 16 dBm */ | ||
399 | |||
400 | /** | 376 | /** |
401 | * When MIMO is used (2 transmitters operating simultaneously), driver should | 377 | * When MIMO is used (2 transmitters operating simultaneously), driver should |
402 | * limit each transmitter to deliver a max of 3 dB below the regulatory limit | 378 | * limit each transmitter to deliver a max of 3 dB below the regulatory limit |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 83c52a682622..6edae9b83bb7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include "iwl-calib.h" | 46 | #include "iwl-calib.h" |
47 | #include "iwl-sta.h" | 47 | #include "iwl-sta.h" |
48 | #include "iwl-agn-led.h" | 48 | #include "iwl-agn-led.h" |
49 | #include "iwl-agn.h" | ||
49 | 50 | ||
50 | static int iwl4965_send_tx_power(struct iwl_priv *priv); | 51 | static int iwl4965_send_tx_power(struct iwl_priv *priv); |
51 | static int iwl4965_hw_get_temperature(struct iwl_priv *priv); | 52 | static int iwl4965_hw_get_temperature(struct iwl_priv *priv); |
@@ -60,14 +61,6 @@ static int iwl4965_hw_get_temperature(struct iwl_priv *priv); | |||
60 | #define _IWL4965_MODULE_FIRMWARE(api) IWL4965_FW_PRE #api ".ucode" | 61 | #define _IWL4965_MODULE_FIRMWARE(api) IWL4965_FW_PRE #api ".ucode" |
61 | #define IWL4965_MODULE_FIRMWARE(api) _IWL4965_MODULE_FIRMWARE(api) | 62 | #define IWL4965_MODULE_FIRMWARE(api) _IWL4965_MODULE_FIRMWARE(api) |
62 | 63 | ||
63 | |||
64 | /* module parameters */ | ||
65 | static struct iwl_mod_params iwl4965_mod_params = { | ||
66 | .amsdu_size_8K = 1, | ||
67 | .restart_fw = 1, | ||
68 | /* the rest are 0 by default */ | ||
69 | }; | ||
70 | |||
71 | /* check contents of special bootstrap uCode SRAM */ | 64 | /* check contents of special bootstrap uCode SRAM */ |
72 | static int iwl4965_verify_bsm(struct iwl_priv *priv) | 65 | static int iwl4965_verify_bsm(struct iwl_priv *priv) |
73 | { | 66 | { |
@@ -417,7 +410,7 @@ static void iwl4965_gain_computation(struct iwl_priv *priv, | |||
417 | sizeof(cmd), &cmd); | 410 | sizeof(cmd), &cmd); |
418 | if (ret) | 411 | if (ret) |
419 | IWL_DEBUG_CALIB(priv, "fail sending cmd " | 412 | IWL_DEBUG_CALIB(priv, "fail sending cmd " |
420 | "REPLY_PHY_CALIBRATION_CMD \n"); | 413 | "REPLY_PHY_CALIBRATION_CMD\n"); |
421 | 414 | ||
422 | /* TODO we might want recalculate | 415 | /* TODO we might want recalculate |
423 | * rx_chain in rxon cmd */ | 416 | * rx_chain in rxon cmd */ |
@@ -502,14 +495,14 @@ static void iwl4965_tx_queue_set_status(struct iwl_priv *priv, | |||
502 | scd_retry ? "BA" : "AC", txq_id, tx_fifo_id); | 495 | scd_retry ? "BA" : "AC", txq_id, tx_fifo_id); |
503 | } | 496 | } |
504 | 497 | ||
505 | static const u16 default_queue_to_tx_fifo[] = { | 498 | static const s8 default_queue_to_tx_fifo[] = { |
506 | IWL_TX_FIFO_AC3, | 499 | IWL_TX_FIFO_VO, |
507 | IWL_TX_FIFO_AC2, | 500 | IWL_TX_FIFO_VI, |
508 | IWL_TX_FIFO_AC1, | 501 | IWL_TX_FIFO_BE, |
509 | IWL_TX_FIFO_AC0, | 502 | IWL_TX_FIFO_BK, |
510 | IWL49_CMD_FIFO_NUM, | 503 | IWL49_CMD_FIFO_NUM, |
511 | IWL_TX_FIFO_HCCA_1, | 504 | IWL_TX_FIFO_UNUSED, |
512 | IWL_TX_FIFO_HCCA_2 | 505 | IWL_TX_FIFO_UNUSED, |
513 | }; | 506 | }; |
514 | 507 | ||
515 | static int iwl4965_alive_notify(struct iwl_priv *priv) | 508 | static int iwl4965_alive_notify(struct iwl_priv *priv) |
@@ -589,9 +582,15 @@ static int iwl4965_alive_notify(struct iwl_priv *priv) | |||
589 | /* reset to 0 to enable all the queue first */ | 582 | /* reset to 0 to enable all the queue first */ |
590 | priv->txq_ctx_active_msk = 0; | 583 | priv->txq_ctx_active_msk = 0; |
591 | /* Map each Tx/cmd queue to its corresponding fifo */ | 584 | /* Map each Tx/cmd queue to its corresponding fifo */ |
585 | BUILD_BUG_ON(ARRAY_SIZE(default_queue_to_tx_fifo) != 7); | ||
592 | for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) { | 586 | for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) { |
593 | int ac = default_queue_to_tx_fifo[i]; | 587 | int ac = default_queue_to_tx_fifo[i]; |
588 | |||
594 | iwl_txq_ctx_activate(priv, i); | 589 | iwl_txq_ctx_activate(priv, i); |
590 | |||
591 | if (ac == IWL_TX_FIFO_UNUSED) | ||
592 | continue; | ||
593 | |||
595 | iwl4965_tx_queue_set_status(priv, &priv->txq[i], ac, 0); | 594 | iwl4965_tx_queue_set_status(priv, &priv->txq[i], ac, 0); |
596 | } | 595 | } |
597 | 596 | ||
@@ -1613,19 +1612,19 @@ static int iwl4965_is_temp_calib_needed(struct iwl_priv *priv) | |||
1613 | 1612 | ||
1614 | /* get absolute value */ | 1613 | /* get absolute value */ |
1615 | if (temp_diff < 0) { | 1614 | if (temp_diff < 0) { |
1616 | IWL_DEBUG_POWER(priv, "Getting cooler, delta %d, \n", temp_diff); | 1615 | IWL_DEBUG_POWER(priv, "Getting cooler, delta %d\n", temp_diff); |
1617 | temp_diff = -temp_diff; | 1616 | temp_diff = -temp_diff; |
1618 | } else if (temp_diff == 0) | 1617 | } else if (temp_diff == 0) |
1619 | IWL_DEBUG_POWER(priv, "Same temp, \n"); | 1618 | IWL_DEBUG_POWER(priv, "Temperature unchanged\n"); |
1620 | else | 1619 | else |
1621 | IWL_DEBUG_POWER(priv, "Getting warmer, delta %d, \n", temp_diff); | 1620 | IWL_DEBUG_POWER(priv, "Getting warmer, delta %d\n", temp_diff); |
1622 | 1621 | ||
1623 | if (temp_diff < IWL_TEMPERATURE_THRESHOLD) { | 1622 | if (temp_diff < IWL_TEMPERATURE_THRESHOLD) { |
1624 | IWL_DEBUG_POWER(priv, "Thermal txpower calib not needed\n"); | 1623 | IWL_DEBUG_POWER(priv, " => thermal txpower calib not needed\n"); |
1625 | return 0; | 1624 | return 0; |
1626 | } | 1625 | } |
1627 | 1626 | ||
1628 | IWL_DEBUG_POWER(priv, "Thermal txpower calib needed\n"); | 1627 | IWL_DEBUG_POWER(priv, " => thermal txpower calib needed\n"); |
1629 | 1628 | ||
1630 | return 1; | 1629 | return 1; |
1631 | } | 1630 | } |
@@ -1874,7 +1873,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, | |||
1874 | info->status.rates[0].count = tx_resp->failure_frame + 1; | 1873 | info->status.rates[0].count = tx_resp->failure_frame + 1; |
1875 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; | 1874 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; |
1876 | info->flags |= iwl_tx_status_to_mac80211(status); | 1875 | info->flags |= iwl_tx_status_to_mac80211(status); |
1877 | iwl_hwrate_to_tx_control(priv, rate_n_flags, info); | 1876 | iwlagn_hwrate_to_tx_control(priv, rate_n_flags, info); |
1878 | /* FIXME: code repetition end */ | 1877 | /* FIXME: code repetition end */ |
1879 | 1878 | ||
1880 | IWL_DEBUG_TX_REPLY(priv, "1 Frame 0x%x failure :%d\n", | 1879 | IWL_DEBUG_TX_REPLY(priv, "1 Frame 0x%x failure :%d\n", |
@@ -2014,7 +2013,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | |||
2014 | index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd); | 2013 | index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd); |
2015 | IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim scd_ssn " | 2014 | IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim scd_ssn " |
2016 | "%d index %d\n", scd_ssn , index); | 2015 | "%d index %d\n", scd_ssn , index); |
2017 | freed = iwl_tx_queue_reclaim(priv, txq_id, index); | 2016 | freed = iwlagn_tx_queue_reclaim(priv, txq_id, index); |
2018 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); | 2017 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); |
2019 | 2018 | ||
2020 | if (priv->mac80211_registered && | 2019 | if (priv->mac80211_registered && |
@@ -2029,7 +2028,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | |||
2029 | } else { | 2028 | } else { |
2030 | info->status.rates[0].count = tx_resp->failure_frame + 1; | 2029 | info->status.rates[0].count = tx_resp->failure_frame + 1; |
2031 | info->flags |= iwl_tx_status_to_mac80211(status); | 2030 | info->flags |= iwl_tx_status_to_mac80211(status); |
2032 | iwl_hwrate_to_tx_control(priv, | 2031 | iwlagn_hwrate_to_tx_control(priv, |
2033 | le32_to_cpu(tx_resp->rate_n_flags), | 2032 | le32_to_cpu(tx_resp->rate_n_flags), |
2034 | info); | 2033 | info); |
2035 | 2034 | ||
@@ -2040,7 +2039,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | |||
2040 | le32_to_cpu(tx_resp->rate_n_flags), | 2039 | le32_to_cpu(tx_resp->rate_n_flags), |
2041 | tx_resp->failure_frame); | 2040 | tx_resp->failure_frame); |
2042 | 2041 | ||
2043 | freed = iwl_tx_queue_reclaim(priv, txq_id, index); | 2042 | freed = iwlagn_tx_queue_reclaim(priv, txq_id, index); |
2044 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); | 2043 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); |
2045 | 2044 | ||
2046 | if (priv->mac80211_registered && | 2045 | if (priv->mac80211_registered && |
@@ -2048,7 +2047,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | |||
2048 | iwl_wake_queue(priv, txq_id); | 2047 | iwl_wake_queue(priv, txq_id); |
2049 | } | 2048 | } |
2050 | 2049 | ||
2051 | iwl_txq_check_empty(priv, sta_id, tid, txq_id); | 2050 | iwlagn_txq_check_empty(priv, sta_id, tid, txq_id); |
2052 | 2051 | ||
2053 | if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) | 2052 | if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) |
2054 | IWL_ERR(priv, "TODO: Implement Tx ABORT REQUIRED!!!\n"); | 2053 | IWL_ERR(priv, "TODO: Implement Tx ABORT REQUIRED!!!\n"); |
@@ -2085,7 +2084,7 @@ static int iwl4965_calc_rssi(struct iwl_priv *priv, | |||
2085 | 2084 | ||
2086 | /* dBm = max_rssi dB - agc dB - constant. | 2085 | /* dBm = max_rssi dB - agc dB - constant. |
2087 | * Higher AGC (higher radio gain) means lower signal. */ | 2086 | * Higher AGC (higher radio gain) means lower signal. */ |
2088 | return max_rssi - agc - IWL49_RSSI_OFFSET; | 2087 | return max_rssi - agc - IWLAGN_RSSI_OFFSET; |
2089 | } | 2088 | } |
2090 | 2089 | ||
2091 | 2090 | ||
@@ -2093,7 +2092,7 @@ static int iwl4965_calc_rssi(struct iwl_priv *priv, | |||
2093 | static void iwl4965_rx_handler_setup(struct iwl_priv *priv) | 2092 | static void iwl4965_rx_handler_setup(struct iwl_priv *priv) |
2094 | { | 2093 | { |
2095 | /* Legacy Rx frames */ | 2094 | /* Legacy Rx frames */ |
2096 | priv->rx_handlers[REPLY_RX] = iwl_rx_reply_rx; | 2095 | priv->rx_handlers[REPLY_RX] = iwlagn_rx_reply_rx; |
2097 | /* Tx response */ | 2096 | /* Tx response */ |
2098 | priv->rx_handlers[REPLY_TX] = iwl4965_rx_reply_tx; | 2097 | priv->rx_handlers[REPLY_TX] = iwl4965_rx_reply_tx; |
2099 | } | 2098 | } |
@@ -2179,6 +2178,7 @@ static struct iwl_lib_ops iwl4965_lib = { | |||
2179 | .load_ucode = iwl4965_load_bsm, | 2178 | .load_ucode = iwl4965_load_bsm, |
2180 | .dump_nic_event_log = iwl_dump_nic_event_log, | 2179 | .dump_nic_event_log = iwl_dump_nic_event_log, |
2181 | .dump_nic_error_log = iwl_dump_nic_error_log, | 2180 | .dump_nic_error_log = iwl_dump_nic_error_log, |
2181 | .dump_fh = iwl_dump_fh, | ||
2182 | .set_channel_switch = iwl4965_hw_channel_switch, | 2182 | .set_channel_switch = iwl4965_hw_channel_switch, |
2183 | .apm_ops = { | 2183 | .apm_ops = { |
2184 | .init = iwl_apm_init, | 2184 | .init = iwl_apm_init, |
@@ -2212,6 +2212,7 @@ static struct iwl_lib_ops iwl4965_lib = { | |||
2212 | .set_ct_kill = iwl4965_set_ct_threshold, | 2212 | .set_ct_kill = iwl4965_set_ct_threshold, |
2213 | }, | 2213 | }, |
2214 | .add_bcast_station = iwl_add_bcast_station, | 2214 | .add_bcast_station = iwl_add_bcast_station, |
2215 | .check_plcp_health = iwl_good_plcp_health, | ||
2215 | }; | 2216 | }; |
2216 | 2217 | ||
2217 | static const struct iwl_ops iwl4965_ops = { | 2218 | static const struct iwl_ops iwl4965_ops = { |
@@ -2223,7 +2224,7 @@ static const struct iwl_ops iwl4965_ops = { | |||
2223 | }; | 2224 | }; |
2224 | 2225 | ||
2225 | struct iwl_cfg iwl4965_agn_cfg = { | 2226 | struct iwl_cfg iwl4965_agn_cfg = { |
2226 | .name = "4965AGN", | 2227 | .name = "Intel(R) Wireless WiFi Link 4965AGN", |
2227 | .fw_name_pre = IWL4965_FW_PRE, | 2228 | .fw_name_pre = IWL4965_FW_PRE, |
2228 | .ucode_api_max = IWL4965_UCODE_API_MAX, | 2229 | .ucode_api_max = IWL4965_UCODE_API_MAX, |
2229 | .ucode_api_min = IWL4965_UCODE_API_MIN, | 2230 | .ucode_api_min = IWL4965_UCODE_API_MIN, |
@@ -2234,7 +2235,7 @@ struct iwl_cfg iwl4965_agn_cfg = { | |||
2234 | .ops = &iwl4965_ops, | 2235 | .ops = &iwl4965_ops, |
2235 | .num_of_queues = IWL49_NUM_QUEUES, | 2236 | .num_of_queues = IWL49_NUM_QUEUES, |
2236 | .num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES, | 2237 | .num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES, |
2237 | .mod_params = &iwl4965_mod_params, | 2238 | .mod_params = &iwlagn_mod_params, |
2238 | .valid_tx_ant = ANT_AB, | 2239 | .valid_tx_ant = ANT_AB, |
2239 | .valid_rx_ant = ANT_ABC, | 2240 | .valid_rx_ant = ANT_ABC, |
2240 | .pll_cfg_val = 0, | 2241 | .pll_cfg_val = 0, |
@@ -2246,27 +2247,11 @@ struct iwl_cfg iwl4965_agn_cfg = { | |||
2246 | .led_compensation = 61, | 2247 | .led_compensation = 61, |
2247 | .chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS, | 2248 | .chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS, |
2248 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 2249 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
2250 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
2251 | .temperature_kelvin = true, | ||
2252 | .off_channel_workaround = true, | ||
2249 | }; | 2253 | }; |
2250 | 2254 | ||
2251 | /* Module firmware */ | 2255 | /* Module firmware */ |
2252 | MODULE_FIRMWARE(IWL4965_MODULE_FIRMWARE(IWL4965_UCODE_API_MAX)); | 2256 | MODULE_FIRMWARE(IWL4965_MODULE_FIRMWARE(IWL4965_UCODE_API_MAX)); |
2253 | 2257 | ||
2254 | module_param_named(antenna, iwl4965_mod_params.antenna, int, S_IRUGO); | ||
2255 | MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); | ||
2256 | module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, S_IRUGO); | ||
2257 | MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])"); | ||
2258 | module_param_named( | ||
2259 | disable_hw_scan, iwl4965_mod_params.disable_hw_scan, int, S_IRUGO); | ||
2260 | MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); | ||
2261 | |||
2262 | module_param_named(queues_num, iwl4965_mod_params.num_of_queues, int, S_IRUGO); | ||
2263 | MODULE_PARM_DESC(queues_num, "number of hw queues."); | ||
2264 | /* 11n */ | ||
2265 | module_param_named(11n_disable, iwl4965_mod_params.disable_11n, int, S_IRUGO); | ||
2266 | MODULE_PARM_DESC(11n_disable, "disable 11n functionality"); | ||
2267 | module_param_named(amsdu_size_8K, iwl4965_mod_params.amsdu_size_8K, | ||
2268 | int, S_IRUGO); | ||
2269 | MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size"); | ||
2270 | |||
2271 | module_param_named(fw_restart4965, iwl4965_mod_params.restart_fw, int, S_IRUGO); | ||
2272 | MODULE_PARM_DESC(fw_restart4965, "restart firmware in case of error"); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h index 714e032f6217..146e6431ae95 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h | |||
@@ -68,25 +68,6 @@ | |||
68 | #ifndef __iwl_5000_hw_h__ | 68 | #ifndef __iwl_5000_hw_h__ |
69 | #define __iwl_5000_hw_h__ | 69 | #define __iwl_5000_hw_h__ |
70 | 70 | ||
71 | #define IWL50_RTC_INST_LOWER_BOUND (0x000000) | ||
72 | #define IWL50_RTC_INST_UPPER_BOUND (0x020000) | ||
73 | |||
74 | #define IWL50_RTC_DATA_LOWER_BOUND (0x800000) | ||
75 | #define IWL50_RTC_DATA_UPPER_BOUND (0x80C000) | ||
76 | |||
77 | #define IWL50_RTC_INST_SIZE (IWL50_RTC_INST_UPPER_BOUND - \ | ||
78 | IWL50_RTC_INST_LOWER_BOUND) | ||
79 | #define IWL50_RTC_DATA_SIZE (IWL50_RTC_DATA_UPPER_BOUND - \ | ||
80 | IWL50_RTC_DATA_LOWER_BOUND) | ||
81 | |||
82 | /* EEPROM */ | ||
83 | #define IWL_5000_EEPROM_IMG_SIZE 2048 | ||
84 | |||
85 | #define IWL50_CMD_FIFO_NUM 7 | ||
86 | #define IWL50_NUM_QUEUES 20 | ||
87 | #define IWL50_NUM_AMPDU_QUEUES 10 | ||
88 | #define IWL50_FIRST_AMPDU_QUEUE 10 | ||
89 | |||
90 | /* 5150 only */ | 71 | /* 5150 only */ |
91 | #define IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF (-5) | 72 | #define IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF (-5) |
92 | 73 | ||
@@ -103,19 +84,5 @@ static inline s32 iwl_temp_calib_to_offset(struct iwl_priv *priv) | |||
103 | return (s32)(temperature - voltage / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF); | 84 | return (s32)(temperature - voltage / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF); |
104 | } | 85 | } |
105 | 86 | ||
106 | /* Fixed (non-configurable) rx data from phy */ | ||
107 | |||
108 | /** | ||
109 | * struct iwl5000_schedq_bc_tbl scheduler byte count table | ||
110 | * base physical address of iwl5000_shared | ||
111 | * is provided to SCD_DRAM_BASE_ADDR | ||
112 | * @tfd_offset 0-12 - tx command byte count | ||
113 | * 12-16 - station index | ||
114 | */ | ||
115 | struct iwl5000_scd_bc_tbl { | ||
116 | __le16 tfd_offset[TFD_QUEUE_BC_SIZE]; | ||
117 | } __attribute__ ((packed)); | ||
118 | |||
119 | |||
120 | #endif /* __iwl_5000_hw_h__ */ | 87 | #endif /* __iwl_5000_hw_h__ */ |
121 | 88 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index e476acb53aa7..ecc302e4c205 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -19,6 +19,7 @@ | |||
19 | * file called LICENSE. | 19 | * file called LICENSE. |
20 | * | 20 | * |
21 | * Contact Information: | 21 | * Contact Information: |
22 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
22 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | 23 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 |
23 | * | 24 | * |
24 | *****************************************************************************/ | 25 | *****************************************************************************/ |
@@ -43,9 +44,10 @@ | |||
43 | #include "iwl-io.h" | 44 | #include "iwl-io.h" |
44 | #include "iwl-sta.h" | 45 | #include "iwl-sta.h" |
45 | #include "iwl-helpers.h" | 46 | #include "iwl-helpers.h" |
47 | #include "iwl-agn.h" | ||
46 | #include "iwl-agn-led.h" | 48 | #include "iwl-agn-led.h" |
49 | #include "iwl-agn-hw.h" | ||
47 | #include "iwl-5000-hw.h" | 50 | #include "iwl-5000-hw.h" |
48 | #include "iwl-6000-hw.h" | ||
49 | 51 | ||
50 | /* Highest firmware API version supported */ | 52 | /* Highest firmware API version supported */ |
51 | #define IWL5000_UCODE_API_MAX 2 | 53 | #define IWL5000_UCODE_API_MAX 2 |
@@ -63,18 +65,8 @@ | |||
63 | #define _IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE #api ".ucode" | 65 | #define _IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE #api ".ucode" |
64 | #define IWL5150_MODULE_FIRMWARE(api) _IWL5150_MODULE_FIRMWARE(api) | 66 | #define IWL5150_MODULE_FIRMWARE(api) _IWL5150_MODULE_FIRMWARE(api) |
65 | 67 | ||
66 | static const u16 iwl5000_default_queue_to_tx_fifo[] = { | ||
67 | IWL_TX_FIFO_AC3, | ||
68 | IWL_TX_FIFO_AC2, | ||
69 | IWL_TX_FIFO_AC1, | ||
70 | IWL_TX_FIFO_AC0, | ||
71 | IWL50_CMD_FIFO_NUM, | ||
72 | IWL_TX_FIFO_HCCA_1, | ||
73 | IWL_TX_FIFO_HCCA_2 | ||
74 | }; | ||
75 | |||
76 | /* NIC configuration for 5000 series */ | 68 | /* NIC configuration for 5000 series */ |
77 | void iwl5000_nic_config(struct iwl_priv *priv) | 69 | static void iwl5000_nic_config(struct iwl_priv *priv) |
78 | { | 70 | { |
79 | unsigned long flags; | 71 | unsigned long flags; |
80 | u16 radio_cfg; | 72 | u16 radio_cfg; |
@@ -107,162 +99,6 @@ void iwl5000_nic_config(struct iwl_priv *priv) | |||
107 | spin_unlock_irqrestore(&priv->lock, flags); | 99 | spin_unlock_irqrestore(&priv->lock, flags); |
108 | } | 100 | } |
109 | 101 | ||
110 | |||
111 | /* | ||
112 | * EEPROM | ||
113 | */ | ||
114 | static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address) | ||
115 | { | ||
116 | u16 offset = 0; | ||
117 | |||
118 | if ((address & INDIRECT_ADDRESS) == 0) | ||
119 | return address; | ||
120 | |||
121 | switch (address & INDIRECT_TYPE_MSK) { | ||
122 | case INDIRECT_HOST: | ||
123 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_HOST); | ||
124 | break; | ||
125 | case INDIRECT_GENERAL: | ||
126 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_GENERAL); | ||
127 | break; | ||
128 | case INDIRECT_REGULATORY: | ||
129 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_REGULATORY); | ||
130 | break; | ||
131 | case INDIRECT_CALIBRATION: | ||
132 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_CALIBRATION); | ||
133 | break; | ||
134 | case INDIRECT_PROCESS_ADJST: | ||
135 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_PROCESS_ADJST); | ||
136 | break; | ||
137 | case INDIRECT_OTHERS: | ||
138 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_OTHERS); | ||
139 | break; | ||
140 | default: | ||
141 | IWL_ERR(priv, "illegal indirect type: 0x%X\n", | ||
142 | address & INDIRECT_TYPE_MSK); | ||
143 | break; | ||
144 | } | ||
145 | |||
146 | /* translate the offset from words to byte */ | ||
147 | return (address & ADDRESS_MSK) + (offset << 1); | ||
148 | } | ||
149 | |||
150 | u16 iwl5000_eeprom_calib_version(struct iwl_priv *priv) | ||
151 | { | ||
152 | struct iwl_eeprom_calib_hdr { | ||
153 | u8 version; | ||
154 | u8 pa_type; | ||
155 | u16 voltage; | ||
156 | } *hdr; | ||
157 | |||
158 | hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv, | ||
159 | EEPROM_5000_CALIB_ALL); | ||
160 | return hdr->version; | ||
161 | |||
162 | } | ||
163 | |||
164 | static void iwl5000_gain_computation(struct iwl_priv *priv, | ||
165 | u32 average_noise[NUM_RX_CHAINS], | ||
166 | u16 min_average_noise_antenna_i, | ||
167 | u32 min_average_noise, | ||
168 | u8 default_chain) | ||
169 | { | ||
170 | int i; | ||
171 | s32 delta_g; | ||
172 | struct iwl_chain_noise_data *data = &priv->chain_noise_data; | ||
173 | |||
174 | /* | ||
175 | * Find Gain Code for the chains based on "default chain" | ||
176 | */ | ||
177 | for (i = default_chain + 1; i < NUM_RX_CHAINS; i++) { | ||
178 | if ((data->disconn_array[i])) { | ||
179 | data->delta_gain_code[i] = 0; | ||
180 | continue; | ||
181 | } | ||
182 | |||
183 | delta_g = (priv->cfg->chain_noise_scale * | ||
184 | ((s32)average_noise[default_chain] - | ||
185 | (s32)average_noise[i])) / 1500; | ||
186 | |||
187 | /* bound gain by 2 bits value max, 3rd bit is sign */ | ||
188 | data->delta_gain_code[i] = | ||
189 | min(abs(delta_g), (long) CHAIN_NOISE_MAX_DELTA_GAIN_CODE); | ||
190 | |||
191 | if (delta_g < 0) | ||
192 | /* | ||
193 | * set negative sign ... | ||
194 | * note to Intel developers: This is uCode API format, | ||
195 | * not the format of any internal device registers. | ||
196 | * Do not change this format for e.g. 6050 or similar | ||
197 | * devices. Change format only if more resolution | ||
198 | * (i.e. more than 2 bits magnitude) is needed. | ||
199 | */ | ||
200 | data->delta_gain_code[i] |= (1 << 2); | ||
201 | } | ||
202 | |||
203 | IWL_DEBUG_CALIB(priv, "Delta gains: ANT_B = %d ANT_C = %d\n", | ||
204 | data->delta_gain_code[1], data->delta_gain_code[2]); | ||
205 | |||
206 | if (!data->radio_write) { | ||
207 | struct iwl_calib_chain_noise_gain_cmd cmd; | ||
208 | |||
209 | memset(&cmd, 0, sizeof(cmd)); | ||
210 | |||
211 | cmd.hdr.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD; | ||
212 | cmd.hdr.first_group = 0; | ||
213 | cmd.hdr.groups_num = 1; | ||
214 | cmd.hdr.data_valid = 1; | ||
215 | cmd.delta_gain_1 = data->delta_gain_code[1]; | ||
216 | cmd.delta_gain_2 = data->delta_gain_code[2]; | ||
217 | iwl_send_cmd_pdu_async(priv, REPLY_PHY_CALIBRATION_CMD, | ||
218 | sizeof(cmd), &cmd, NULL); | ||
219 | |||
220 | data->radio_write = 1; | ||
221 | data->state = IWL_CHAIN_NOISE_CALIBRATED; | ||
222 | } | ||
223 | |||
224 | data->chain_noise_a = 0; | ||
225 | data->chain_noise_b = 0; | ||
226 | data->chain_noise_c = 0; | ||
227 | data->chain_signal_a = 0; | ||
228 | data->chain_signal_b = 0; | ||
229 | data->chain_signal_c = 0; | ||
230 | data->beacon_count = 0; | ||
231 | } | ||
232 | |||
233 | static void iwl5000_chain_noise_reset(struct iwl_priv *priv) | ||
234 | { | ||
235 | struct iwl_chain_noise_data *data = &priv->chain_noise_data; | ||
236 | int ret; | ||
237 | |||
238 | if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl_is_associated(priv)) { | ||
239 | struct iwl_calib_chain_noise_reset_cmd cmd; | ||
240 | memset(&cmd, 0, sizeof(cmd)); | ||
241 | |||
242 | cmd.hdr.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD; | ||
243 | cmd.hdr.first_group = 0; | ||
244 | cmd.hdr.groups_num = 1; | ||
245 | cmd.hdr.data_valid = 1; | ||
246 | ret = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD, | ||
247 | sizeof(cmd), &cmd); | ||
248 | if (ret) | ||
249 | IWL_ERR(priv, | ||
250 | "Could not send REPLY_PHY_CALIBRATION_CMD\n"); | ||
251 | data->state = IWL_CHAIN_NOISE_ACCUMULATE; | ||
252 | IWL_DEBUG_CALIB(priv, "Run chain_noise_calibrate\n"); | ||
253 | } | ||
254 | } | ||
255 | |||
256 | void iwl5000_rts_tx_cmd_flag(struct ieee80211_tx_info *info, | ||
257 | __le32 *tx_flags) | ||
258 | { | ||
259 | if ((info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || | ||
260 | (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) | ||
261 | *tx_flags |= TX_CMD_FLG_RTS_CTS_MSK; | ||
262 | else | ||
263 | *tx_flags &= ~TX_CMD_FLG_RTS_CTS_MSK; | ||
264 | } | ||
265 | |||
266 | static struct iwl_sensitivity_ranges iwl5000_sensitivity = { | 102 | static struct iwl_sensitivity_ranges iwl5000_sensitivity = { |
267 | .min_nrg_cck = 95, | 103 | .min_nrg_cck = 95, |
268 | .max_nrg_cck = 0, /* not used, set to 0 */ | 104 | .max_nrg_cck = 0, /* not used, set to 0 */ |
@@ -314,14 +150,6 @@ static struct iwl_sensitivity_ranges iwl5150_sensitivity = { | |||
314 | .nrg_th_cca = 62, | 150 | .nrg_th_cca = 62, |
315 | }; | 151 | }; |
316 | 152 | ||
317 | const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv, | ||
318 | size_t offset) | ||
319 | { | ||
320 | u32 address = eeprom_indirect_address(priv, offset); | ||
321 | BUG_ON(address >= priv->cfg->eeprom_size); | ||
322 | return &priv->eeprom[address]; | ||
323 | } | ||
324 | |||
325 | static void iwl5150_set_ct_threshold(struct iwl_priv *priv) | 153 | static void iwl5150_set_ct_threshold(struct iwl_priv *priv) |
326 | { | 154 | { |
327 | const s32 volt2temp_coef = IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF; | 155 | const s32 volt2temp_coef = IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF; |
@@ -337,356 +165,10 @@ static void iwl5000_set_ct_threshold(struct iwl_priv *priv) | |||
337 | priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY; | 165 | priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY; |
338 | } | 166 | } |
339 | 167 | ||
340 | /* | 168 | static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) |
341 | * Calibration | ||
342 | */ | ||
343 | static int iwl5000_set_Xtal_calib(struct iwl_priv *priv) | ||
344 | { | ||
345 | struct iwl_calib_xtal_freq_cmd cmd; | ||
346 | __le16 *xtal_calib = | ||
347 | (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_XTAL); | ||
348 | |||
349 | cmd.hdr.op_code = IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD; | ||
350 | cmd.hdr.first_group = 0; | ||
351 | cmd.hdr.groups_num = 1; | ||
352 | cmd.hdr.data_valid = 1; | ||
353 | cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]); | ||
354 | cmd.cap_pin2 = le16_to_cpu(xtal_calib[1]); | ||
355 | return iwl_calib_set(&priv->calib_results[IWL_CALIB_XTAL], | ||
356 | (u8 *)&cmd, sizeof(cmd)); | ||
357 | } | ||
358 | |||
359 | static int iwl5000_send_calib_cfg(struct iwl_priv *priv) | ||
360 | { | ||
361 | struct iwl_calib_cfg_cmd calib_cfg_cmd; | ||
362 | struct iwl_host_cmd cmd = { | ||
363 | .id = CALIBRATION_CFG_CMD, | ||
364 | .len = sizeof(struct iwl_calib_cfg_cmd), | ||
365 | .data = &calib_cfg_cmd, | ||
366 | }; | ||
367 | |||
368 | memset(&calib_cfg_cmd, 0, sizeof(calib_cfg_cmd)); | ||
369 | calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_INIT_CFG_ALL; | ||
370 | calib_cfg_cmd.ucd_calib_cfg.once.start = IWL_CALIB_INIT_CFG_ALL; | ||
371 | calib_cfg_cmd.ucd_calib_cfg.once.send_res = IWL_CALIB_INIT_CFG_ALL; | ||
372 | calib_cfg_cmd.ucd_calib_cfg.flags = IWL_CALIB_INIT_CFG_ALL; | ||
373 | |||
374 | return iwl_send_cmd(priv, &cmd); | ||
375 | } | ||
376 | |||
377 | static void iwl5000_rx_calib_result(struct iwl_priv *priv, | ||
378 | struct iwl_rx_mem_buffer *rxb) | ||
379 | { | ||
380 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
381 | struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw; | ||
382 | int len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | ||
383 | int index; | ||
384 | |||
385 | /* reduce the size of the length field itself */ | ||
386 | len -= 4; | ||
387 | |||
388 | /* Define the order in which the results will be sent to the runtime | ||
389 | * uCode. iwl_send_calib_results sends them in a row according to their | ||
390 | * index. We sort them here */ | ||
391 | switch (hdr->op_code) { | ||
392 | case IWL_PHY_CALIBRATE_DC_CMD: | ||
393 | index = IWL_CALIB_DC; | ||
394 | break; | ||
395 | case IWL_PHY_CALIBRATE_LO_CMD: | ||
396 | index = IWL_CALIB_LO; | ||
397 | break; | ||
398 | case IWL_PHY_CALIBRATE_TX_IQ_CMD: | ||
399 | index = IWL_CALIB_TX_IQ; | ||
400 | break; | ||
401 | case IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD: | ||
402 | index = IWL_CALIB_TX_IQ_PERD; | ||
403 | break; | ||
404 | case IWL_PHY_CALIBRATE_BASE_BAND_CMD: | ||
405 | index = IWL_CALIB_BASE_BAND; | ||
406 | break; | ||
407 | default: | ||
408 | IWL_ERR(priv, "Unknown calibration notification %d\n", | ||
409 | hdr->op_code); | ||
410 | return; | ||
411 | } | ||
412 | iwl_calib_set(&priv->calib_results[index], pkt->u.raw, len); | ||
413 | } | ||
414 | |||
415 | static void iwl5000_rx_calib_complete(struct iwl_priv *priv, | ||
416 | struct iwl_rx_mem_buffer *rxb) | ||
417 | { | ||
418 | IWL_DEBUG_INFO(priv, "Init. calibration is completed, restarting fw.\n"); | ||
419 | queue_work(priv->workqueue, &priv->restart); | ||
420 | } | ||
421 | |||
422 | /* | ||
423 | * ucode | ||
424 | */ | ||
425 | static int iwl5000_load_section(struct iwl_priv *priv, const char *name, | ||
426 | struct fw_desc *image, u32 dst_addr) | ||
427 | { | ||
428 | dma_addr_t phy_addr = image->p_addr; | ||
429 | u32 byte_cnt = image->len; | ||
430 | int ret; | ||
431 | |||
432 | priv->ucode_write_complete = 0; | ||
433 | |||
434 | iwl_write_direct32(priv, | ||
435 | FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), | ||
436 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE); | ||
437 | |||
438 | iwl_write_direct32(priv, | ||
439 | FH_SRVC_CHNL_SRAM_ADDR_REG(FH_SRVC_CHNL), dst_addr); | ||
440 | |||
441 | iwl_write_direct32(priv, | ||
442 | FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL), | ||
443 | phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK); | ||
444 | |||
445 | iwl_write_direct32(priv, | ||
446 | FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL), | ||
447 | (iwl_get_dma_hi_addr(phy_addr) | ||
448 | << FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt); | ||
449 | |||
450 | iwl_write_direct32(priv, | ||
451 | FH_TCSR_CHNL_TX_BUF_STS_REG(FH_SRVC_CHNL), | ||
452 | 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM | | ||
453 | 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX | | ||
454 | FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID); | ||
455 | |||
456 | iwl_write_direct32(priv, | ||
457 | FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), | ||
458 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | | ||
459 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | | ||
460 | FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); | ||
461 | |||
462 | IWL_DEBUG_INFO(priv, "%s uCode section being loaded...\n", name); | ||
463 | ret = wait_event_interruptible_timeout(priv->wait_command_queue, | ||
464 | priv->ucode_write_complete, 5 * HZ); | ||
465 | if (ret == -ERESTARTSYS) { | ||
466 | IWL_ERR(priv, "Could not load the %s uCode section due " | ||
467 | "to interrupt\n", name); | ||
468 | return ret; | ||
469 | } | ||
470 | if (!ret) { | ||
471 | IWL_ERR(priv, "Could not load the %s uCode section\n", | ||
472 | name); | ||
473 | return -ETIMEDOUT; | ||
474 | } | ||
475 | |||
476 | return 0; | ||
477 | } | ||
478 | |||
479 | static int iwl5000_load_given_ucode(struct iwl_priv *priv, | ||
480 | struct fw_desc *inst_image, | ||
481 | struct fw_desc *data_image) | ||
482 | { | ||
483 | int ret = 0; | ||
484 | |||
485 | ret = iwl5000_load_section(priv, "INST", inst_image, | ||
486 | IWL50_RTC_INST_LOWER_BOUND); | ||
487 | if (ret) | ||
488 | return ret; | ||
489 | |||
490 | return iwl5000_load_section(priv, "DATA", data_image, | ||
491 | IWL50_RTC_DATA_LOWER_BOUND); | ||
492 | } | ||
493 | |||
494 | int iwl5000_load_ucode(struct iwl_priv *priv) | ||
495 | { | ||
496 | int ret = 0; | ||
497 | |||
498 | /* check whether init ucode should be loaded, or rather runtime ucode */ | ||
499 | if (priv->ucode_init.len && (priv->ucode_type == UCODE_NONE)) { | ||
500 | IWL_DEBUG_INFO(priv, "Init ucode found. Loading init ucode...\n"); | ||
501 | ret = iwl5000_load_given_ucode(priv, | ||
502 | &priv->ucode_init, &priv->ucode_init_data); | ||
503 | if (!ret) { | ||
504 | IWL_DEBUG_INFO(priv, "Init ucode load complete.\n"); | ||
505 | priv->ucode_type = UCODE_INIT; | ||
506 | } | ||
507 | } else { | ||
508 | IWL_DEBUG_INFO(priv, "Init ucode not found, or already loaded. " | ||
509 | "Loading runtime ucode...\n"); | ||
510 | ret = iwl5000_load_given_ucode(priv, | ||
511 | &priv->ucode_code, &priv->ucode_data); | ||
512 | if (!ret) { | ||
513 | IWL_DEBUG_INFO(priv, "Runtime ucode load complete.\n"); | ||
514 | priv->ucode_type = UCODE_RT; | ||
515 | } | ||
516 | } | ||
517 | |||
518 | return ret; | ||
519 | } | ||
520 | |||
521 | void iwl5000_init_alive_start(struct iwl_priv *priv) | ||
522 | { | ||
523 | int ret = 0; | ||
524 | |||
525 | /* Check alive response for "valid" sign from uCode */ | ||
526 | if (priv->card_alive_init.is_valid != UCODE_VALID_OK) { | ||
527 | /* We had an error bringing up the hardware, so take it | ||
528 | * all the way back down so we can try again */ | ||
529 | IWL_DEBUG_INFO(priv, "Initialize Alive failed.\n"); | ||
530 | goto restart; | ||
531 | } | ||
532 | |||
533 | /* initialize uCode was loaded... verify inst image. | ||
534 | * This is a paranoid check, because we would not have gotten the | ||
535 | * "initialize" alive if code weren't properly loaded. */ | ||
536 | if (iwl_verify_ucode(priv)) { | ||
537 | /* Runtime instruction load was bad; | ||
538 | * take it all the way back down so we can try again */ | ||
539 | IWL_DEBUG_INFO(priv, "Bad \"initialize\" uCode load.\n"); | ||
540 | goto restart; | ||
541 | } | ||
542 | |||
543 | iwl_clear_stations_table(priv); | ||
544 | ret = priv->cfg->ops->lib->alive_notify(priv); | ||
545 | if (ret) { | ||
546 | IWL_WARN(priv, | ||
547 | "Could not complete ALIVE transition: %d\n", ret); | ||
548 | goto restart; | ||
549 | } | ||
550 | |||
551 | iwl5000_send_calib_cfg(priv); | ||
552 | return; | ||
553 | |||
554 | restart: | ||
555 | /* real restart (first load init_ucode) */ | ||
556 | queue_work(priv->workqueue, &priv->restart); | ||
557 | } | ||
558 | |||
559 | static void iwl5000_set_wr_ptrs(struct iwl_priv *priv, | ||
560 | int txq_id, u32 index) | ||
561 | { | ||
562 | iwl_write_direct32(priv, HBUS_TARG_WRPTR, | ||
563 | (index & 0xff) | (txq_id << 8)); | ||
564 | iwl_write_prph(priv, IWL50_SCD_QUEUE_RDPTR(txq_id), index); | ||
565 | } | ||
566 | |||
567 | static void iwl5000_tx_queue_set_status(struct iwl_priv *priv, | ||
568 | struct iwl_tx_queue *txq, | ||
569 | int tx_fifo_id, int scd_retry) | ||
570 | { | ||
571 | int txq_id = txq->q.id; | ||
572 | int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0; | ||
573 | |||
574 | iwl_write_prph(priv, IWL50_SCD_QUEUE_STATUS_BITS(txq_id), | ||
575 | (active << IWL50_SCD_QUEUE_STTS_REG_POS_ACTIVE) | | ||
576 | (tx_fifo_id << IWL50_SCD_QUEUE_STTS_REG_POS_TXF) | | ||
577 | (1 << IWL50_SCD_QUEUE_STTS_REG_POS_WSL) | | ||
578 | IWL50_SCD_QUEUE_STTS_REG_MSK); | ||
579 | |||
580 | txq->sched_retry = scd_retry; | ||
581 | |||
582 | IWL_DEBUG_INFO(priv, "%s %s Queue %d on AC %d\n", | ||
583 | active ? "Activate" : "Deactivate", | ||
584 | scd_retry ? "BA" : "AC", txq_id, tx_fifo_id); | ||
585 | } | ||
586 | |||
587 | int iwl5000_alive_notify(struct iwl_priv *priv) | ||
588 | { | ||
589 | u32 a; | ||
590 | unsigned long flags; | ||
591 | int i, chan; | ||
592 | u32 reg_val; | ||
593 | |||
594 | spin_lock_irqsave(&priv->lock, flags); | ||
595 | |||
596 | priv->scd_base_addr = iwl_read_prph(priv, IWL50_SCD_SRAM_BASE_ADDR); | ||
597 | a = priv->scd_base_addr + IWL50_SCD_CONTEXT_DATA_OFFSET; | ||
598 | for (; a < priv->scd_base_addr + IWL50_SCD_TX_STTS_BITMAP_OFFSET; | ||
599 | a += 4) | ||
600 | iwl_write_targ_mem(priv, a, 0); | ||
601 | for (; a < priv->scd_base_addr + IWL50_SCD_TRANSLATE_TBL_OFFSET; | ||
602 | a += 4) | ||
603 | iwl_write_targ_mem(priv, a, 0); | ||
604 | for (; a < priv->scd_base_addr + | ||
605 | IWL50_SCD_TRANSLATE_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4) | ||
606 | iwl_write_targ_mem(priv, a, 0); | ||
607 | |||
608 | iwl_write_prph(priv, IWL50_SCD_DRAM_BASE_ADDR, | ||
609 | priv->scd_bc_tbls.dma >> 10); | ||
610 | |||
611 | /* Enable DMA channel */ | ||
612 | for (chan = 0; chan < FH50_TCSR_CHNL_NUM ; chan++) | ||
613 | iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(chan), | ||
614 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | | ||
615 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE); | ||
616 | |||
617 | /* Update FH chicken bits */ | ||
618 | reg_val = iwl_read_direct32(priv, FH_TX_CHICKEN_BITS_REG); | ||
619 | iwl_write_direct32(priv, FH_TX_CHICKEN_BITS_REG, | ||
620 | reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); | ||
621 | |||
622 | iwl_write_prph(priv, IWL50_SCD_QUEUECHAIN_SEL, | ||
623 | IWL50_SCD_QUEUECHAIN_SEL_ALL(priv->hw_params.max_txq_num)); | ||
624 | iwl_write_prph(priv, IWL50_SCD_AGGR_SEL, 0); | ||
625 | |||
626 | /* initiate the queues */ | ||
627 | for (i = 0; i < priv->hw_params.max_txq_num; i++) { | ||
628 | iwl_write_prph(priv, IWL50_SCD_QUEUE_RDPTR(i), 0); | ||
629 | iwl_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8)); | ||
630 | iwl_write_targ_mem(priv, priv->scd_base_addr + | ||
631 | IWL50_SCD_CONTEXT_QUEUE_OFFSET(i), 0); | ||
632 | iwl_write_targ_mem(priv, priv->scd_base_addr + | ||
633 | IWL50_SCD_CONTEXT_QUEUE_OFFSET(i) + | ||
634 | sizeof(u32), | ||
635 | ((SCD_WIN_SIZE << | ||
636 | IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & | ||
637 | IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | | ||
638 | ((SCD_FRAME_LIMIT << | ||
639 | IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & | ||
640 | IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); | ||
641 | } | ||
642 | |||
643 | iwl_write_prph(priv, IWL50_SCD_INTERRUPT_MASK, | ||
644 | IWL_MASK(0, priv->hw_params.max_txq_num)); | ||
645 | |||
646 | /* Activate all Tx DMA/FIFO channels */ | ||
647 | priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 7)); | ||
648 | |||
649 | iwl5000_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); | ||
650 | |||
651 | /* make sure all queue are not stopped */ | ||
652 | memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); | ||
653 | for (i = 0; i < 4; i++) | ||
654 | atomic_set(&priv->queue_stop_count[i], 0); | ||
655 | |||
656 | /* reset to 0 to enable all the queue first */ | ||
657 | priv->txq_ctx_active_msk = 0; | ||
658 | /* map qos queues to fifos one-to-one */ | ||
659 | for (i = 0; i < ARRAY_SIZE(iwl5000_default_queue_to_tx_fifo); i++) { | ||
660 | int ac = iwl5000_default_queue_to_tx_fifo[i]; | ||
661 | iwl_txq_ctx_activate(priv, i); | ||
662 | iwl5000_tx_queue_set_status(priv, &priv->txq[i], ac, 0); | ||
663 | } | ||
664 | |||
665 | /* | ||
666 | * TODO - need to initialize these queues and map them to FIFOs | ||
667 | * in the loop above, not only mark them as active. We do this | ||
668 | * because we want the first aggregation queue to be queue #10, | ||
669 | * but do not use 8 or 9 otherwise yet. | ||
670 | */ | ||
671 | iwl_txq_ctx_activate(priv, 7); | ||
672 | iwl_txq_ctx_activate(priv, 8); | ||
673 | iwl_txq_ctx_activate(priv, 9); | ||
674 | |||
675 | spin_unlock_irqrestore(&priv->lock, flags); | ||
676 | |||
677 | |||
678 | iwl_send_wimax_coex(priv); | ||
679 | |||
680 | iwl5000_set_Xtal_calib(priv); | ||
681 | iwl_send_calib_results(priv); | ||
682 | |||
683 | return 0; | ||
684 | } | ||
685 | |||
686 | int iwl5000_hw_set_hw_params(struct iwl_priv *priv) | ||
687 | { | 169 | { |
688 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && | 170 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && |
689 | priv->cfg->mod_params->num_of_queues <= IWL50_NUM_QUEUES) | 171 | priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES) |
690 | priv->cfg->num_of_queues = | 172 | priv->cfg->num_of_queues = |
691 | priv->cfg->mod_params->num_of_queues; | 173 | priv->cfg->mod_params->num_of_queues; |
692 | 174 | ||
@@ -694,13 +176,13 @@ int iwl5000_hw_set_hw_params(struct iwl_priv *priv) | |||
694 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; | 176 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; |
695 | priv->hw_params.scd_bc_tbls_size = | 177 | priv->hw_params.scd_bc_tbls_size = |
696 | priv->cfg->num_of_queues * | 178 | priv->cfg->num_of_queues * |
697 | sizeof(struct iwl5000_scd_bc_tbl); | 179 | sizeof(struct iwlagn_scd_bc_tbl); |
698 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); | 180 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); |
699 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; | 181 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; |
700 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; | 182 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; |
701 | 183 | ||
702 | priv->hw_params.max_data_size = IWL50_RTC_DATA_SIZE; | 184 | priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; |
703 | priv->hw_params.max_inst_size = IWL50_RTC_INST_SIZE; | 185 | priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; |
704 | 186 | ||
705 | priv->hw_params.max_bsm_size = 0; | 187 | priv->hw_params.max_bsm_size = 0; |
706 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | | 188 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | |
@@ -741,547 +223,6 @@ int iwl5000_hw_set_hw_params(struct iwl_priv *priv) | |||
741 | return 0; | 223 | return 0; |
742 | } | 224 | } |
743 | 225 | ||
744 | /** | ||
745 | * iwl5000_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array | ||
746 | */ | ||
747 | void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv, | ||
748 | struct iwl_tx_queue *txq, | ||
749 | u16 byte_cnt) | ||
750 | { | ||
751 | struct iwl5000_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; | ||
752 | int write_ptr = txq->q.write_ptr; | ||
753 | int txq_id = txq->q.id; | ||
754 | u8 sec_ctl = 0; | ||
755 | u8 sta_id = 0; | ||
756 | u16 len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; | ||
757 | __le16 bc_ent; | ||
758 | |||
759 | WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX); | ||
760 | |||
761 | if (txq_id != IWL_CMD_QUEUE_NUM) { | ||
762 | sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id; | ||
763 | sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl; | ||
764 | |||
765 | switch (sec_ctl & TX_CMD_SEC_MSK) { | ||
766 | case TX_CMD_SEC_CCM: | ||
767 | len += CCMP_MIC_LEN; | ||
768 | break; | ||
769 | case TX_CMD_SEC_TKIP: | ||
770 | len += TKIP_ICV_LEN; | ||
771 | break; | ||
772 | case TX_CMD_SEC_WEP: | ||
773 | len += WEP_IV_LEN + WEP_ICV_LEN; | ||
774 | break; | ||
775 | } | ||
776 | } | ||
777 | |||
778 | bc_ent = cpu_to_le16((len & 0xFFF) | (sta_id << 12)); | ||
779 | |||
780 | scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent; | ||
781 | |||
782 | if (write_ptr < TFD_QUEUE_SIZE_BC_DUP) | ||
783 | scd_bc_tbl[txq_id]. | ||
784 | tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent; | ||
785 | } | ||
786 | |||
787 | void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, | ||
788 | struct iwl_tx_queue *txq) | ||
789 | { | ||
790 | struct iwl5000_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; | ||
791 | int txq_id = txq->q.id; | ||
792 | int read_ptr = txq->q.read_ptr; | ||
793 | u8 sta_id = 0; | ||
794 | __le16 bc_ent; | ||
795 | |||
796 | WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX); | ||
797 | |||
798 | if (txq_id != IWL_CMD_QUEUE_NUM) | ||
799 | sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id; | ||
800 | |||
801 | bc_ent = cpu_to_le16(1 | (sta_id << 12)); | ||
802 | scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent; | ||
803 | |||
804 | if (read_ptr < TFD_QUEUE_SIZE_BC_DUP) | ||
805 | scd_bc_tbl[txq_id]. | ||
806 | tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent; | ||
807 | } | ||
808 | |||
809 | static int iwl5000_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid, | ||
810 | u16 txq_id) | ||
811 | { | ||
812 | u32 tbl_dw_addr; | ||
813 | u32 tbl_dw; | ||
814 | u16 scd_q2ratid; | ||
815 | |||
816 | scd_q2ratid = ra_tid & IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK; | ||
817 | |||
818 | tbl_dw_addr = priv->scd_base_addr + | ||
819 | IWL50_SCD_TRANSLATE_TBL_OFFSET_QUEUE(txq_id); | ||
820 | |||
821 | tbl_dw = iwl_read_targ_mem(priv, tbl_dw_addr); | ||
822 | |||
823 | if (txq_id & 0x1) | ||
824 | tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF); | ||
825 | else | ||
826 | tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000); | ||
827 | |||
828 | iwl_write_targ_mem(priv, tbl_dw_addr, tbl_dw); | ||
829 | |||
830 | return 0; | ||
831 | } | ||
832 | static void iwl5000_tx_queue_stop_scheduler(struct iwl_priv *priv, u16 txq_id) | ||
833 | { | ||
834 | /* Simply stop the queue, but don't change any configuration; | ||
835 | * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */ | ||
836 | iwl_write_prph(priv, | ||
837 | IWL50_SCD_QUEUE_STATUS_BITS(txq_id), | ||
838 | (0 << IWL50_SCD_QUEUE_STTS_REG_POS_ACTIVE)| | ||
839 | (1 << IWL50_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); | ||
840 | } | ||
841 | |||
842 | int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id, | ||
843 | int tx_fifo, int sta_id, int tid, u16 ssn_idx) | ||
844 | { | ||
845 | unsigned long flags; | ||
846 | u16 ra_tid; | ||
847 | |||
848 | if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) || | ||
849 | (IWL50_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues | ||
850 | <= txq_id)) { | ||
851 | IWL_WARN(priv, | ||
852 | "queue number out of range: %d, must be %d to %d\n", | ||
853 | txq_id, IWL50_FIRST_AMPDU_QUEUE, | ||
854 | IWL50_FIRST_AMPDU_QUEUE + | ||
855 | priv->cfg->num_of_ampdu_queues - 1); | ||
856 | return -EINVAL; | ||
857 | } | ||
858 | |||
859 | ra_tid = BUILD_RAxTID(sta_id, tid); | ||
860 | |||
861 | /* Modify device's station table to Tx this TID */ | ||
862 | iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); | ||
863 | |||
864 | spin_lock_irqsave(&priv->lock, flags); | ||
865 | |||
866 | /* Stop this Tx queue before configuring it */ | ||
867 | iwl5000_tx_queue_stop_scheduler(priv, txq_id); | ||
868 | |||
869 | /* Map receiver-address / traffic-ID to this queue */ | ||
870 | iwl5000_tx_queue_set_q2ratid(priv, ra_tid, txq_id); | ||
871 | |||
872 | /* Set this queue as a chain-building queue */ | ||
873 | iwl_set_bits_prph(priv, IWL50_SCD_QUEUECHAIN_SEL, (1<<txq_id)); | ||
874 | |||
875 | /* enable aggregations for the queue */ | ||
876 | iwl_set_bits_prph(priv, IWL50_SCD_AGGR_SEL, (1<<txq_id)); | ||
877 | |||
878 | /* Place first TFD at index corresponding to start sequence number. | ||
879 | * Assumes that ssn_idx is valid (!= 0xFFF) */ | ||
880 | priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); | ||
881 | priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); | ||
882 | iwl5000_set_wr_ptrs(priv, txq_id, ssn_idx); | ||
883 | |||
884 | /* Set up Tx window size and frame limit for this queue */ | ||
885 | iwl_write_targ_mem(priv, priv->scd_base_addr + | ||
886 | IWL50_SCD_CONTEXT_QUEUE_OFFSET(txq_id) + | ||
887 | sizeof(u32), | ||
888 | ((SCD_WIN_SIZE << | ||
889 | IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & | ||
890 | IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | | ||
891 | ((SCD_FRAME_LIMIT << | ||
892 | IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & | ||
893 | IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); | ||
894 | |||
895 | iwl_set_bits_prph(priv, IWL50_SCD_INTERRUPT_MASK, (1 << txq_id)); | ||
896 | |||
897 | /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ | ||
898 | iwl5000_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1); | ||
899 | |||
900 | spin_unlock_irqrestore(&priv->lock, flags); | ||
901 | |||
902 | return 0; | ||
903 | } | ||
904 | |||
905 | int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, | ||
906 | u16 ssn_idx, u8 tx_fifo) | ||
907 | { | ||
908 | if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) || | ||
909 | (IWL50_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues | ||
910 | <= txq_id)) { | ||
911 | IWL_ERR(priv, | ||
912 | "queue number out of range: %d, must be %d to %d\n", | ||
913 | txq_id, IWL50_FIRST_AMPDU_QUEUE, | ||
914 | IWL50_FIRST_AMPDU_QUEUE + | ||
915 | priv->cfg->num_of_ampdu_queues - 1); | ||
916 | return -EINVAL; | ||
917 | } | ||
918 | |||
919 | iwl5000_tx_queue_stop_scheduler(priv, txq_id); | ||
920 | |||
921 | iwl_clear_bits_prph(priv, IWL50_SCD_AGGR_SEL, (1 << txq_id)); | ||
922 | |||
923 | priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); | ||
924 | priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); | ||
925 | /* supposes that ssn_idx is valid (!= 0xFFF) */ | ||
926 | iwl5000_set_wr_ptrs(priv, txq_id, ssn_idx); | ||
927 | |||
928 | iwl_clear_bits_prph(priv, IWL50_SCD_INTERRUPT_MASK, (1 << txq_id)); | ||
929 | iwl_txq_ctx_deactivate(priv, txq_id); | ||
930 | iwl5000_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0); | ||
931 | |||
932 | return 0; | ||
933 | } | ||
934 | |||
935 | u16 iwl5000_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) | ||
936 | { | ||
937 | u16 size = (u16)sizeof(struct iwl_addsta_cmd); | ||
938 | struct iwl_addsta_cmd *addsta = (struct iwl_addsta_cmd *)data; | ||
939 | memcpy(addsta, cmd, size); | ||
940 | /* resrved in 5000 */ | ||
941 | addsta->rate_n_flags = cpu_to_le16(0); | ||
942 | return size; | ||
943 | } | ||
944 | |||
945 | |||
946 | /* | ||
947 | * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask | ||
948 | * must be called under priv->lock and mac access | ||
949 | */ | ||
950 | void iwl5000_txq_set_sched(struct iwl_priv *priv, u32 mask) | ||
951 | { | ||
952 | iwl_write_prph(priv, IWL50_SCD_TXFACT, mask); | ||
953 | } | ||
954 | |||
955 | |||
956 | static inline u32 iwl5000_get_scd_ssn(struct iwl5000_tx_resp *tx_resp) | ||
957 | { | ||
958 | return le32_to_cpup((__le32 *)&tx_resp->status + | ||
959 | tx_resp->frame_count) & MAX_SN; | ||
960 | } | ||
961 | |||
962 | static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv, | ||
963 | struct iwl_ht_agg *agg, | ||
964 | struct iwl5000_tx_resp *tx_resp, | ||
965 | int txq_id, u16 start_idx) | ||
966 | { | ||
967 | u16 status; | ||
968 | struct agg_tx_status *frame_status = &tx_resp->status; | ||
969 | struct ieee80211_tx_info *info = NULL; | ||
970 | struct ieee80211_hdr *hdr = NULL; | ||
971 | u32 rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags); | ||
972 | int i, sh, idx; | ||
973 | u16 seq; | ||
974 | |||
975 | if (agg->wait_for_ba) | ||
976 | IWL_DEBUG_TX_REPLY(priv, "got tx response w/o block-ack\n"); | ||
977 | |||
978 | agg->frame_count = tx_resp->frame_count; | ||
979 | agg->start_idx = start_idx; | ||
980 | agg->rate_n_flags = rate_n_flags; | ||
981 | agg->bitmap = 0; | ||
982 | |||
983 | /* # frames attempted by Tx command */ | ||
984 | if (agg->frame_count == 1) { | ||
985 | /* Only one frame was attempted; no block-ack will arrive */ | ||
986 | status = le16_to_cpu(frame_status[0].status); | ||
987 | idx = start_idx; | ||
988 | |||
989 | /* FIXME: code repetition */ | ||
990 | IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n", | ||
991 | agg->frame_count, agg->start_idx, idx); | ||
992 | |||
993 | info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); | ||
994 | info->status.rates[0].count = tx_resp->failure_frame + 1; | ||
995 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; | ||
996 | info->flags |= iwl_tx_status_to_mac80211(status); | ||
997 | iwl_hwrate_to_tx_control(priv, rate_n_flags, info); | ||
998 | |||
999 | /* FIXME: code repetition end */ | ||
1000 | |||
1001 | IWL_DEBUG_TX_REPLY(priv, "1 Frame 0x%x failure :%d\n", | ||
1002 | status & 0xff, tx_resp->failure_frame); | ||
1003 | IWL_DEBUG_TX_REPLY(priv, "Rate Info rate_n_flags=%x\n", rate_n_flags); | ||
1004 | |||
1005 | agg->wait_for_ba = 0; | ||
1006 | } else { | ||
1007 | /* Two or more frames were attempted; expect block-ack */ | ||
1008 | u64 bitmap = 0; | ||
1009 | int start = agg->start_idx; | ||
1010 | |||
1011 | /* Construct bit-map of pending frames within Tx window */ | ||
1012 | for (i = 0; i < agg->frame_count; i++) { | ||
1013 | u16 sc; | ||
1014 | status = le16_to_cpu(frame_status[i].status); | ||
1015 | seq = le16_to_cpu(frame_status[i].sequence); | ||
1016 | idx = SEQ_TO_INDEX(seq); | ||
1017 | txq_id = SEQ_TO_QUEUE(seq); | ||
1018 | |||
1019 | if (status & (AGG_TX_STATE_FEW_BYTES_MSK | | ||
1020 | AGG_TX_STATE_ABORT_MSK)) | ||
1021 | continue; | ||
1022 | |||
1023 | IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, txq_id=%d idx=%d\n", | ||
1024 | agg->frame_count, txq_id, idx); | ||
1025 | |||
1026 | hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx); | ||
1027 | if (!hdr) { | ||
1028 | IWL_ERR(priv, | ||
1029 | "BUG_ON idx doesn't point to valid skb" | ||
1030 | " idx=%d, txq_id=%d\n", idx, txq_id); | ||
1031 | return -1; | ||
1032 | } | ||
1033 | |||
1034 | sc = le16_to_cpu(hdr->seq_ctrl); | ||
1035 | if (idx != (SEQ_TO_SN(sc) & 0xff)) { | ||
1036 | IWL_ERR(priv, | ||
1037 | "BUG_ON idx doesn't match seq control" | ||
1038 | " idx=%d, seq_idx=%d, seq=%d\n", | ||
1039 | idx, SEQ_TO_SN(sc), | ||
1040 | hdr->seq_ctrl); | ||
1041 | return -1; | ||
1042 | } | ||
1043 | |||
1044 | IWL_DEBUG_TX_REPLY(priv, "AGG Frame i=%d idx %d seq=%d\n", | ||
1045 | i, idx, SEQ_TO_SN(sc)); | ||
1046 | |||
1047 | sh = idx - start; | ||
1048 | if (sh > 64) { | ||
1049 | sh = (start - idx) + 0xff; | ||
1050 | bitmap = bitmap << sh; | ||
1051 | sh = 0; | ||
1052 | start = idx; | ||
1053 | } else if (sh < -64) | ||
1054 | sh = 0xff - (start - idx); | ||
1055 | else if (sh < 0) { | ||
1056 | sh = start - idx; | ||
1057 | start = idx; | ||
1058 | bitmap = bitmap << sh; | ||
1059 | sh = 0; | ||
1060 | } | ||
1061 | bitmap |= 1ULL << sh; | ||
1062 | IWL_DEBUG_TX_REPLY(priv, "start=%d bitmap=0x%llx\n", | ||
1063 | start, (unsigned long long)bitmap); | ||
1064 | } | ||
1065 | |||
1066 | agg->bitmap = bitmap; | ||
1067 | agg->start_idx = start; | ||
1068 | IWL_DEBUG_TX_REPLY(priv, "Frames %d start_idx=%d bitmap=0x%llx\n", | ||
1069 | agg->frame_count, agg->start_idx, | ||
1070 | (unsigned long long)agg->bitmap); | ||
1071 | |||
1072 | if (bitmap) | ||
1073 | agg->wait_for_ba = 1; | ||
1074 | } | ||
1075 | return 0; | ||
1076 | } | ||
1077 | |||
1078 | static void iwl5000_rx_reply_tx(struct iwl_priv *priv, | ||
1079 | struct iwl_rx_mem_buffer *rxb) | ||
1080 | { | ||
1081 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
1082 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); | ||
1083 | int txq_id = SEQ_TO_QUEUE(sequence); | ||
1084 | int index = SEQ_TO_INDEX(sequence); | ||
1085 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; | ||
1086 | struct ieee80211_tx_info *info; | ||
1087 | struct iwl5000_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; | ||
1088 | u32 status = le16_to_cpu(tx_resp->status.status); | ||
1089 | int tid; | ||
1090 | int sta_id; | ||
1091 | int freed; | ||
1092 | |||
1093 | if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) { | ||
1094 | IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d " | ||
1095 | "is out of range [0-%d] %d %d\n", txq_id, | ||
1096 | index, txq->q.n_bd, txq->q.write_ptr, | ||
1097 | txq->q.read_ptr); | ||
1098 | return; | ||
1099 | } | ||
1100 | |||
1101 | info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]); | ||
1102 | memset(&info->status, 0, sizeof(info->status)); | ||
1103 | |||
1104 | tid = (tx_resp->ra_tid & IWL50_TX_RES_TID_MSK) >> IWL50_TX_RES_TID_POS; | ||
1105 | sta_id = (tx_resp->ra_tid & IWL50_TX_RES_RA_MSK) >> IWL50_TX_RES_RA_POS; | ||
1106 | |||
1107 | if (txq->sched_retry) { | ||
1108 | const u32 scd_ssn = iwl5000_get_scd_ssn(tx_resp); | ||
1109 | struct iwl_ht_agg *agg = NULL; | ||
1110 | |||
1111 | agg = &priv->stations[sta_id].tid[tid].agg; | ||
1112 | |||
1113 | iwl5000_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index); | ||
1114 | |||
1115 | /* check if BAR is needed */ | ||
1116 | if ((tx_resp->frame_count == 1) && !iwl_is_tx_success(status)) | ||
1117 | info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; | ||
1118 | |||
1119 | if (txq->q.read_ptr != (scd_ssn & 0xff)) { | ||
1120 | index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd); | ||
1121 | IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim " | ||
1122 | "scd_ssn=%d idx=%d txq=%d swq=%d\n", | ||
1123 | scd_ssn , index, txq_id, txq->swq_id); | ||
1124 | |||
1125 | freed = iwl_tx_queue_reclaim(priv, txq_id, index); | ||
1126 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); | ||
1127 | |||
1128 | if (priv->mac80211_registered && | ||
1129 | (iwl_queue_space(&txq->q) > txq->q.low_mark) && | ||
1130 | (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) { | ||
1131 | if (agg->state == IWL_AGG_OFF) | ||
1132 | iwl_wake_queue(priv, txq_id); | ||
1133 | else | ||
1134 | iwl_wake_queue(priv, txq->swq_id); | ||
1135 | } | ||
1136 | } | ||
1137 | } else { | ||
1138 | BUG_ON(txq_id != txq->swq_id); | ||
1139 | |||
1140 | info->status.rates[0].count = tx_resp->failure_frame + 1; | ||
1141 | info->flags |= iwl_tx_status_to_mac80211(status); | ||
1142 | iwl_hwrate_to_tx_control(priv, | ||
1143 | le32_to_cpu(tx_resp->rate_n_flags), | ||
1144 | info); | ||
1145 | |||
1146 | IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x) rate_n_flags " | ||
1147 | "0x%x retries %d\n", | ||
1148 | txq_id, | ||
1149 | iwl_get_tx_fail_reason(status), status, | ||
1150 | le32_to_cpu(tx_resp->rate_n_flags), | ||
1151 | tx_resp->failure_frame); | ||
1152 | |||
1153 | freed = iwl_tx_queue_reclaim(priv, txq_id, index); | ||
1154 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); | ||
1155 | |||
1156 | if (priv->mac80211_registered && | ||
1157 | (iwl_queue_space(&txq->q) > txq->q.low_mark)) | ||
1158 | iwl_wake_queue(priv, txq_id); | ||
1159 | } | ||
1160 | |||
1161 | iwl_txq_check_empty(priv, sta_id, tid, txq_id); | ||
1162 | |||
1163 | if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) | ||
1164 | IWL_ERR(priv, "TODO: Implement Tx ABORT REQUIRED!!!\n"); | ||
1165 | } | ||
1166 | |||
1167 | /* Currently 5000 is the superset of everything */ | ||
1168 | u16 iwl5000_get_hcmd_size(u8 cmd_id, u16 len) | ||
1169 | { | ||
1170 | return len; | ||
1171 | } | ||
1172 | |||
1173 | void iwl5000_setup_deferred_work(struct iwl_priv *priv) | ||
1174 | { | ||
1175 | /* in 5000 the tx power calibration is done in uCode */ | ||
1176 | priv->disable_tx_power_cal = 1; | ||
1177 | } | ||
1178 | |||
1179 | void iwl5000_rx_handler_setup(struct iwl_priv *priv) | ||
1180 | { | ||
1181 | /* init calibration handlers */ | ||
1182 | priv->rx_handlers[CALIBRATION_RES_NOTIFICATION] = | ||
1183 | iwl5000_rx_calib_result; | ||
1184 | priv->rx_handlers[CALIBRATION_COMPLETE_NOTIFICATION] = | ||
1185 | iwl5000_rx_calib_complete; | ||
1186 | priv->rx_handlers[REPLY_TX] = iwl5000_rx_reply_tx; | ||
1187 | } | ||
1188 | |||
1189 | |||
1190 | int iwl5000_hw_valid_rtc_data_addr(u32 addr) | ||
1191 | { | ||
1192 | return (addr >= IWL50_RTC_DATA_LOWER_BOUND) && | ||
1193 | (addr < IWL50_RTC_DATA_UPPER_BOUND); | ||
1194 | } | ||
1195 | |||
1196 | static int iwl5000_send_rxon_assoc(struct iwl_priv *priv) | ||
1197 | { | ||
1198 | int ret = 0; | ||
1199 | struct iwl5000_rxon_assoc_cmd rxon_assoc; | ||
1200 | const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon; | ||
1201 | const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon; | ||
1202 | |||
1203 | if ((rxon1->flags == rxon2->flags) && | ||
1204 | (rxon1->filter_flags == rxon2->filter_flags) && | ||
1205 | (rxon1->cck_basic_rates == rxon2->cck_basic_rates) && | ||
1206 | (rxon1->ofdm_ht_single_stream_basic_rates == | ||
1207 | rxon2->ofdm_ht_single_stream_basic_rates) && | ||
1208 | (rxon1->ofdm_ht_dual_stream_basic_rates == | ||
1209 | rxon2->ofdm_ht_dual_stream_basic_rates) && | ||
1210 | (rxon1->ofdm_ht_triple_stream_basic_rates == | ||
1211 | rxon2->ofdm_ht_triple_stream_basic_rates) && | ||
1212 | (rxon1->acquisition_data == rxon2->acquisition_data) && | ||
1213 | (rxon1->rx_chain == rxon2->rx_chain) && | ||
1214 | (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) { | ||
1215 | IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC. Not resending.\n"); | ||
1216 | return 0; | ||
1217 | } | ||
1218 | |||
1219 | rxon_assoc.flags = priv->staging_rxon.flags; | ||
1220 | rxon_assoc.filter_flags = priv->staging_rxon.filter_flags; | ||
1221 | rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates; | ||
1222 | rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates; | ||
1223 | rxon_assoc.reserved1 = 0; | ||
1224 | rxon_assoc.reserved2 = 0; | ||
1225 | rxon_assoc.reserved3 = 0; | ||
1226 | rxon_assoc.ofdm_ht_single_stream_basic_rates = | ||
1227 | priv->staging_rxon.ofdm_ht_single_stream_basic_rates; | ||
1228 | rxon_assoc.ofdm_ht_dual_stream_basic_rates = | ||
1229 | priv->staging_rxon.ofdm_ht_dual_stream_basic_rates; | ||
1230 | rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain; | ||
1231 | rxon_assoc.ofdm_ht_triple_stream_basic_rates = | ||
1232 | priv->staging_rxon.ofdm_ht_triple_stream_basic_rates; | ||
1233 | rxon_assoc.acquisition_data = priv->staging_rxon.acquisition_data; | ||
1234 | |||
1235 | ret = iwl_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC, | ||
1236 | sizeof(rxon_assoc), &rxon_assoc, NULL); | ||
1237 | if (ret) | ||
1238 | return ret; | ||
1239 | |||
1240 | return ret; | ||
1241 | } | ||
1242 | int iwl5000_send_tx_power(struct iwl_priv *priv) | ||
1243 | { | ||
1244 | struct iwl5000_tx_power_dbm_cmd tx_power_cmd; | ||
1245 | u8 tx_ant_cfg_cmd; | ||
1246 | |||
1247 | /* half dBm need to multiply */ | ||
1248 | tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt); | ||
1249 | |||
1250 | if (priv->tx_power_lmt_in_half_dbm && | ||
1251 | priv->tx_power_lmt_in_half_dbm < tx_power_cmd.global_lmt) { | ||
1252 | /* | ||
1253 | * For the newer devices which using enhanced/extend tx power | ||
1254 | * table in EEPROM, the format is in half dBm. driver need to | ||
1255 | * convert to dBm format before report to mac80211. | ||
1256 | * By doing so, there is a possibility of 1/2 dBm resolution | ||
1257 | * lost. driver will perform "round-up" operation before | ||
1258 | * reporting, but it will cause 1/2 dBm tx power over the | ||
1259 | * regulatory limit. Perform the checking here, if the | ||
1260 | * "tx_power_user_lmt" is higher than EEPROM value (in | ||
1261 | * half-dBm format), lower the tx power based on EEPROM | ||
1262 | */ | ||
1263 | tx_power_cmd.global_lmt = priv->tx_power_lmt_in_half_dbm; | ||
1264 | } | ||
1265 | tx_power_cmd.flags = IWL50_TX_POWER_NO_CLOSED; | ||
1266 | tx_power_cmd.srv_chan_lmt = IWL50_TX_POWER_AUTO; | ||
1267 | |||
1268 | if (IWL_UCODE_API(priv->ucode_ver) == 1) | ||
1269 | tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD_V1; | ||
1270 | else | ||
1271 | tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD; | ||
1272 | |||
1273 | return iwl_send_cmd_pdu_async(priv, tx_ant_cfg_cmd, | ||
1274 | sizeof(tx_power_cmd), &tx_power_cmd, | ||
1275 | NULL); | ||
1276 | } | ||
1277 | |||
1278 | void iwl5000_temperature(struct iwl_priv *priv) | ||
1279 | { | ||
1280 | /* store temperature from statistics (in Celsius) */ | ||
1281 | priv->temperature = le32_to_cpu(priv->statistics.general.temperature); | ||
1282 | iwl_tt_handler(priv); | ||
1283 | } | ||
1284 | |||
1285 | static void iwl5150_temperature(struct iwl_priv *priv) | 226 | static void iwl5150_temperature(struct iwl_priv *priv) |
1286 | { | 227 | { |
1287 | u32 vt = 0; | 228 | u32 vt = 0; |
@@ -1294,100 +235,6 @@ static void iwl5150_temperature(struct iwl_priv *priv) | |||
1294 | iwl_tt_handler(priv); | 235 | iwl_tt_handler(priv); |
1295 | } | 236 | } |
1296 | 237 | ||
1297 | /* Calc max signal level (dBm) among 3 possible receivers */ | ||
1298 | int iwl5000_calc_rssi(struct iwl_priv *priv, | ||
1299 | struct iwl_rx_phy_res *rx_resp) | ||
1300 | { | ||
1301 | /* data from PHY/DSP regarding signal strength, etc., | ||
1302 | * contents are always there, not configurable by host | ||
1303 | */ | ||
1304 | struct iwl5000_non_cfg_phy *ncphy = | ||
1305 | (struct iwl5000_non_cfg_phy *)rx_resp->non_cfg_phy_buf; | ||
1306 | u32 val, rssi_a, rssi_b, rssi_c, max_rssi; | ||
1307 | u8 agc; | ||
1308 | |||
1309 | val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_AGC_IDX]); | ||
1310 | agc = (val & IWL50_OFDM_AGC_MSK) >> IWL50_OFDM_AGC_BIT_POS; | ||
1311 | |||
1312 | /* Find max rssi among 3 possible receivers. | ||
1313 | * These values are measured by the digital signal processor (DSP). | ||
1314 | * They should stay fairly constant even as the signal strength varies, | ||
1315 | * if the radio's automatic gain control (AGC) is working right. | ||
1316 | * AGC value (see below) will provide the "interesting" info. | ||
1317 | */ | ||
1318 | val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_AB_IDX]); | ||
1319 | rssi_a = (val & IWL50_OFDM_RSSI_A_MSK) >> IWL50_OFDM_RSSI_A_BIT_POS; | ||
1320 | rssi_b = (val & IWL50_OFDM_RSSI_B_MSK) >> IWL50_OFDM_RSSI_B_BIT_POS; | ||
1321 | val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_C_IDX]); | ||
1322 | rssi_c = (val & IWL50_OFDM_RSSI_C_MSK) >> IWL50_OFDM_RSSI_C_BIT_POS; | ||
1323 | |||
1324 | max_rssi = max_t(u32, rssi_a, rssi_b); | ||
1325 | max_rssi = max_t(u32, max_rssi, rssi_c); | ||
1326 | |||
1327 | IWL_DEBUG_STATS(priv, "Rssi In A %d B %d C %d Max %d AGC dB %d\n", | ||
1328 | rssi_a, rssi_b, rssi_c, max_rssi, agc); | ||
1329 | |||
1330 | /* dBm = max_rssi dB - agc dB - constant. | ||
1331 | * Higher AGC (higher radio gain) means lower signal. */ | ||
1332 | return max_rssi - agc - IWL49_RSSI_OFFSET; | ||
1333 | } | ||
1334 | |||
1335 | static int iwl5000_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant) | ||
1336 | { | ||
1337 | struct iwl_tx_ant_config_cmd tx_ant_cmd = { | ||
1338 | .valid = cpu_to_le32(valid_tx_ant), | ||
1339 | }; | ||
1340 | |||
1341 | if (IWL_UCODE_API(priv->ucode_ver) > 1) { | ||
1342 | IWL_DEBUG_HC(priv, "select valid tx ant: %u\n", valid_tx_ant); | ||
1343 | return iwl_send_cmd_pdu(priv, TX_ANT_CONFIGURATION_CMD, | ||
1344 | sizeof(struct iwl_tx_ant_config_cmd), | ||
1345 | &tx_ant_cmd); | ||
1346 | } else { | ||
1347 | IWL_DEBUG_HC(priv, "TX_ANT_CONFIGURATION_CMD not supported\n"); | ||
1348 | return -EOPNOTSUPP; | ||
1349 | } | ||
1350 | } | ||
1351 | |||
1352 | |||
1353 | #define IWL5000_UCODE_GET(item) \ | ||
1354 | static u32 iwl5000_ucode_get_##item(const struct iwl_ucode_header *ucode,\ | ||
1355 | u32 api_ver) \ | ||
1356 | { \ | ||
1357 | if (api_ver <= 2) \ | ||
1358 | return le32_to_cpu(ucode->u.v1.item); \ | ||
1359 | return le32_to_cpu(ucode->u.v2.item); \ | ||
1360 | } | ||
1361 | |||
1362 | static u32 iwl5000_ucode_get_header_size(u32 api_ver) | ||
1363 | { | ||
1364 | if (api_ver <= 2) | ||
1365 | return UCODE_HEADER_SIZE(1); | ||
1366 | return UCODE_HEADER_SIZE(2); | ||
1367 | } | ||
1368 | |||
1369 | static u32 iwl5000_ucode_get_build(const struct iwl_ucode_header *ucode, | ||
1370 | u32 api_ver) | ||
1371 | { | ||
1372 | if (api_ver <= 2) | ||
1373 | return 0; | ||
1374 | return le32_to_cpu(ucode->u.v2.build); | ||
1375 | } | ||
1376 | |||
1377 | static u8 *iwl5000_ucode_get_data(const struct iwl_ucode_header *ucode, | ||
1378 | u32 api_ver) | ||
1379 | { | ||
1380 | if (api_ver <= 2) | ||
1381 | return (u8 *) ucode->u.v1.data; | ||
1382 | return (u8 *) ucode->u.v2.data; | ||
1383 | } | ||
1384 | |||
1385 | IWL5000_UCODE_GET(inst_size); | ||
1386 | IWL5000_UCODE_GET(data_size); | ||
1387 | IWL5000_UCODE_GET(init_size); | ||
1388 | IWL5000_UCODE_GET(init_data_size); | ||
1389 | IWL5000_UCODE_GET(boot_size); | ||
1390 | |||
1391 | static int iwl5000_hw_channel_switch(struct iwl_priv *priv, u16 channel) | 238 | static int iwl5000_hw_channel_switch(struct iwl_priv *priv, u16 channel) |
1392 | { | 239 | { |
1393 | struct iwl5000_channel_switch_cmd cmd; | 240 | struct iwl5000_channel_switch_cmd cmd; |
@@ -1420,54 +267,27 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, u16 channel) | |||
1420 | return iwl_send_cmd_sync(priv, &hcmd); | 267 | return iwl_send_cmd_sync(priv, &hcmd); |
1421 | } | 268 | } |
1422 | 269 | ||
1423 | struct iwl_hcmd_ops iwl5000_hcmd = { | 270 | static struct iwl_lib_ops iwl5000_lib = { |
1424 | .rxon_assoc = iwl5000_send_rxon_assoc, | ||
1425 | .commit_rxon = iwl_commit_rxon, | ||
1426 | .set_rxon_chain = iwl_set_rxon_chain, | ||
1427 | .set_tx_ant = iwl5000_send_tx_ant_config, | ||
1428 | }; | ||
1429 | |||
1430 | struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = { | ||
1431 | .get_hcmd_size = iwl5000_get_hcmd_size, | ||
1432 | .build_addsta_hcmd = iwl5000_build_addsta_hcmd, | ||
1433 | .gain_computation = iwl5000_gain_computation, | ||
1434 | .chain_noise_reset = iwl5000_chain_noise_reset, | ||
1435 | .rts_tx_cmd_flag = iwl5000_rts_tx_cmd_flag, | ||
1436 | .calc_rssi = iwl5000_calc_rssi, | ||
1437 | }; | ||
1438 | |||
1439 | struct iwl_ucode_ops iwl5000_ucode = { | ||
1440 | .get_header_size = iwl5000_ucode_get_header_size, | ||
1441 | .get_build = iwl5000_ucode_get_build, | ||
1442 | .get_inst_size = iwl5000_ucode_get_inst_size, | ||
1443 | .get_data_size = iwl5000_ucode_get_data_size, | ||
1444 | .get_init_size = iwl5000_ucode_get_init_size, | ||
1445 | .get_init_data_size = iwl5000_ucode_get_init_data_size, | ||
1446 | .get_boot_size = iwl5000_ucode_get_boot_size, | ||
1447 | .get_data = iwl5000_ucode_get_data, | ||
1448 | }; | ||
1449 | |||
1450 | struct iwl_lib_ops iwl5000_lib = { | ||
1451 | .set_hw_params = iwl5000_hw_set_hw_params, | 271 | .set_hw_params = iwl5000_hw_set_hw_params, |
1452 | .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, | 272 | .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, |
1453 | .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, | 273 | .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, |
1454 | .txq_set_sched = iwl5000_txq_set_sched, | 274 | .txq_set_sched = iwlagn_txq_set_sched, |
1455 | .txq_agg_enable = iwl5000_txq_agg_enable, | 275 | .txq_agg_enable = iwlagn_txq_agg_enable, |
1456 | .txq_agg_disable = iwl5000_txq_agg_disable, | 276 | .txq_agg_disable = iwlagn_txq_agg_disable, |
1457 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, | 277 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, |
1458 | .txq_free_tfd = iwl_hw_txq_free_tfd, | 278 | .txq_free_tfd = iwl_hw_txq_free_tfd, |
1459 | .txq_init = iwl_hw_tx_queue_init, | 279 | .txq_init = iwl_hw_tx_queue_init, |
1460 | .rx_handler_setup = iwl5000_rx_handler_setup, | 280 | .rx_handler_setup = iwlagn_rx_handler_setup, |
1461 | .setup_deferred_work = iwl5000_setup_deferred_work, | 281 | .setup_deferred_work = iwlagn_setup_deferred_work, |
1462 | .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, | 282 | .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, |
1463 | .dump_nic_event_log = iwl_dump_nic_event_log, | 283 | .dump_nic_event_log = iwl_dump_nic_event_log, |
1464 | .dump_nic_error_log = iwl_dump_nic_error_log, | 284 | .dump_nic_error_log = iwl_dump_nic_error_log, |
1465 | .dump_csr = iwl_dump_csr, | 285 | .dump_csr = iwl_dump_csr, |
1466 | .dump_fh = iwl_dump_fh, | 286 | .dump_fh = iwl_dump_fh, |
1467 | .load_ucode = iwl5000_load_ucode, | 287 | .load_ucode = iwlagn_load_ucode, |
1468 | .init_alive_start = iwl5000_init_alive_start, | 288 | .init_alive_start = iwlagn_init_alive_start, |
1469 | .alive_notify = iwl5000_alive_notify, | 289 | .alive_notify = iwlagn_alive_notify, |
1470 | .send_tx_power = iwl5000_send_tx_power, | 290 | .send_tx_power = iwlagn_send_tx_power, |
1471 | .update_chain_flags = iwl_update_chain_flags, | 291 | .update_chain_flags = iwl_update_chain_flags, |
1472 | .set_channel_switch = iwl5000_hw_channel_switch, | 292 | .set_channel_switch = iwl5000_hw_channel_switch, |
1473 | .apm_ops = { | 293 | .apm_ops = { |
@@ -1478,50 +298,53 @@ struct iwl_lib_ops iwl5000_lib = { | |||
1478 | }, | 298 | }, |
1479 | .eeprom_ops = { | 299 | .eeprom_ops = { |
1480 | .regulatory_bands = { | 300 | .regulatory_bands = { |
1481 | EEPROM_5000_REG_BAND_1_CHANNELS, | 301 | EEPROM_REG_BAND_1_CHANNELS, |
1482 | EEPROM_5000_REG_BAND_2_CHANNELS, | 302 | EEPROM_REG_BAND_2_CHANNELS, |
1483 | EEPROM_5000_REG_BAND_3_CHANNELS, | 303 | EEPROM_REG_BAND_3_CHANNELS, |
1484 | EEPROM_5000_REG_BAND_4_CHANNELS, | 304 | EEPROM_REG_BAND_4_CHANNELS, |
1485 | EEPROM_5000_REG_BAND_5_CHANNELS, | 305 | EEPROM_REG_BAND_5_CHANNELS, |
1486 | EEPROM_5000_REG_BAND_24_HT40_CHANNELS, | 306 | EEPROM_REG_BAND_24_HT40_CHANNELS, |
1487 | EEPROM_5000_REG_BAND_52_HT40_CHANNELS | 307 | EEPROM_REG_BAND_52_HT40_CHANNELS |
1488 | }, | 308 | }, |
1489 | .verify_signature = iwlcore_eeprom_verify_signature, | 309 | .verify_signature = iwlcore_eeprom_verify_signature, |
1490 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, | 310 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, |
1491 | .release_semaphore = iwlcore_eeprom_release_semaphore, | 311 | .release_semaphore = iwlcore_eeprom_release_semaphore, |
1492 | .calib_version = iwl5000_eeprom_calib_version, | 312 | .calib_version = iwlagn_eeprom_calib_version, |
1493 | .query_addr = iwl5000_eeprom_query_addr, | 313 | .query_addr = iwlagn_eeprom_query_addr, |
1494 | }, | 314 | }, |
1495 | .post_associate = iwl_post_associate, | 315 | .post_associate = iwl_post_associate, |
1496 | .isr = iwl_isr_ict, | 316 | .isr = iwl_isr_ict, |
1497 | .config_ap = iwl_config_ap, | 317 | .config_ap = iwl_config_ap, |
1498 | .temp_ops = { | 318 | .temp_ops = { |
1499 | .temperature = iwl5000_temperature, | 319 | .temperature = iwlagn_temperature, |
1500 | .set_ct_kill = iwl5000_set_ct_threshold, | 320 | .set_ct_kill = iwl5000_set_ct_threshold, |
1501 | }, | 321 | }, |
1502 | .add_bcast_station = iwl_add_bcast_station, | 322 | .add_bcast_station = iwl_add_bcast_station, |
323 | .recover_from_tx_stall = iwl_bg_monitor_recover, | ||
324 | .check_plcp_health = iwl_good_plcp_health, | ||
325 | .check_ack_health = iwl_good_ack_health, | ||
1503 | }; | 326 | }; |
1504 | 327 | ||
1505 | static struct iwl_lib_ops iwl5150_lib = { | 328 | static struct iwl_lib_ops iwl5150_lib = { |
1506 | .set_hw_params = iwl5000_hw_set_hw_params, | 329 | .set_hw_params = iwl5000_hw_set_hw_params, |
1507 | .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, | 330 | .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, |
1508 | .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, | 331 | .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, |
1509 | .txq_set_sched = iwl5000_txq_set_sched, | 332 | .txq_set_sched = iwlagn_txq_set_sched, |
1510 | .txq_agg_enable = iwl5000_txq_agg_enable, | 333 | .txq_agg_enable = iwlagn_txq_agg_enable, |
1511 | .txq_agg_disable = iwl5000_txq_agg_disable, | 334 | .txq_agg_disable = iwlagn_txq_agg_disable, |
1512 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, | 335 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, |
1513 | .txq_free_tfd = iwl_hw_txq_free_tfd, | 336 | .txq_free_tfd = iwl_hw_txq_free_tfd, |
1514 | .txq_init = iwl_hw_tx_queue_init, | 337 | .txq_init = iwl_hw_tx_queue_init, |
1515 | .rx_handler_setup = iwl5000_rx_handler_setup, | 338 | .rx_handler_setup = iwlagn_rx_handler_setup, |
1516 | .setup_deferred_work = iwl5000_setup_deferred_work, | 339 | .setup_deferred_work = iwlagn_setup_deferred_work, |
1517 | .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, | 340 | .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, |
1518 | .dump_nic_event_log = iwl_dump_nic_event_log, | 341 | .dump_nic_event_log = iwl_dump_nic_event_log, |
1519 | .dump_nic_error_log = iwl_dump_nic_error_log, | 342 | .dump_nic_error_log = iwl_dump_nic_error_log, |
1520 | .dump_csr = iwl_dump_csr, | 343 | .dump_csr = iwl_dump_csr, |
1521 | .load_ucode = iwl5000_load_ucode, | 344 | .load_ucode = iwlagn_load_ucode, |
1522 | .init_alive_start = iwl5000_init_alive_start, | 345 | .init_alive_start = iwlagn_init_alive_start, |
1523 | .alive_notify = iwl5000_alive_notify, | 346 | .alive_notify = iwlagn_alive_notify, |
1524 | .send_tx_power = iwl5000_send_tx_power, | 347 | .send_tx_power = iwlagn_send_tx_power, |
1525 | .update_chain_flags = iwl_update_chain_flags, | 348 | .update_chain_flags = iwl_update_chain_flags, |
1526 | .set_channel_switch = iwl5000_hw_channel_switch, | 349 | .set_channel_switch = iwl5000_hw_channel_switch, |
1527 | .apm_ops = { | 350 | .apm_ops = { |
@@ -1532,19 +355,19 @@ static struct iwl_lib_ops iwl5150_lib = { | |||
1532 | }, | 355 | }, |
1533 | .eeprom_ops = { | 356 | .eeprom_ops = { |
1534 | .regulatory_bands = { | 357 | .regulatory_bands = { |
1535 | EEPROM_5000_REG_BAND_1_CHANNELS, | 358 | EEPROM_REG_BAND_1_CHANNELS, |
1536 | EEPROM_5000_REG_BAND_2_CHANNELS, | 359 | EEPROM_REG_BAND_2_CHANNELS, |
1537 | EEPROM_5000_REG_BAND_3_CHANNELS, | 360 | EEPROM_REG_BAND_3_CHANNELS, |
1538 | EEPROM_5000_REG_BAND_4_CHANNELS, | 361 | EEPROM_REG_BAND_4_CHANNELS, |
1539 | EEPROM_5000_REG_BAND_5_CHANNELS, | 362 | EEPROM_REG_BAND_5_CHANNELS, |
1540 | EEPROM_5000_REG_BAND_24_HT40_CHANNELS, | 363 | EEPROM_REG_BAND_24_HT40_CHANNELS, |
1541 | EEPROM_5000_REG_BAND_52_HT40_CHANNELS | 364 | EEPROM_REG_BAND_52_HT40_CHANNELS |
1542 | }, | 365 | }, |
1543 | .verify_signature = iwlcore_eeprom_verify_signature, | 366 | .verify_signature = iwlcore_eeprom_verify_signature, |
1544 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, | 367 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, |
1545 | .release_semaphore = iwlcore_eeprom_release_semaphore, | 368 | .release_semaphore = iwlcore_eeprom_release_semaphore, |
1546 | .calib_version = iwl5000_eeprom_calib_version, | 369 | .calib_version = iwlagn_eeprom_calib_version, |
1547 | .query_addr = iwl5000_eeprom_query_addr, | 370 | .query_addr = iwlagn_eeprom_query_addr, |
1548 | }, | 371 | }, |
1549 | .post_associate = iwl_post_associate, | 372 | .post_associate = iwl_post_associate, |
1550 | .isr = iwl_isr_ict, | 373 | .isr = iwl_isr_ict, |
@@ -1554,44 +377,40 @@ static struct iwl_lib_ops iwl5150_lib = { | |||
1554 | .set_ct_kill = iwl5150_set_ct_threshold, | 377 | .set_ct_kill = iwl5150_set_ct_threshold, |
1555 | }, | 378 | }, |
1556 | .add_bcast_station = iwl_add_bcast_station, | 379 | .add_bcast_station = iwl_add_bcast_station, |
380 | .recover_from_tx_stall = iwl_bg_monitor_recover, | ||
381 | .check_plcp_health = iwl_good_plcp_health, | ||
382 | .check_ack_health = iwl_good_ack_health, | ||
1557 | }; | 383 | }; |
1558 | 384 | ||
1559 | static const struct iwl_ops iwl5000_ops = { | 385 | static const struct iwl_ops iwl5000_ops = { |
1560 | .ucode = &iwl5000_ucode, | 386 | .ucode = &iwlagn_ucode, |
1561 | .lib = &iwl5000_lib, | 387 | .lib = &iwl5000_lib, |
1562 | .hcmd = &iwl5000_hcmd, | 388 | .hcmd = &iwlagn_hcmd, |
1563 | .utils = &iwl5000_hcmd_utils, | 389 | .utils = &iwlagn_hcmd_utils, |
1564 | .led = &iwlagn_led_ops, | 390 | .led = &iwlagn_led_ops, |
1565 | }; | 391 | }; |
1566 | 392 | ||
1567 | static const struct iwl_ops iwl5150_ops = { | 393 | static const struct iwl_ops iwl5150_ops = { |
1568 | .ucode = &iwl5000_ucode, | 394 | .ucode = &iwlagn_ucode, |
1569 | .lib = &iwl5150_lib, | 395 | .lib = &iwl5150_lib, |
1570 | .hcmd = &iwl5000_hcmd, | 396 | .hcmd = &iwlagn_hcmd, |
1571 | .utils = &iwl5000_hcmd_utils, | 397 | .utils = &iwlagn_hcmd_utils, |
1572 | .led = &iwlagn_led_ops, | 398 | .led = &iwlagn_led_ops, |
1573 | }; | 399 | }; |
1574 | 400 | ||
1575 | struct iwl_mod_params iwl50_mod_params = { | ||
1576 | .amsdu_size_8K = 1, | ||
1577 | .restart_fw = 1, | ||
1578 | /* the rest are 0 by default */ | ||
1579 | }; | ||
1580 | |||
1581 | |||
1582 | struct iwl_cfg iwl5300_agn_cfg = { | 401 | struct iwl_cfg iwl5300_agn_cfg = { |
1583 | .name = "5300AGN", | 402 | .name = "Intel(R) Ultimate N WiFi Link 5300 AGN", |
1584 | .fw_name_pre = IWL5000_FW_PRE, | 403 | .fw_name_pre = IWL5000_FW_PRE, |
1585 | .ucode_api_max = IWL5000_UCODE_API_MAX, | 404 | .ucode_api_max = IWL5000_UCODE_API_MAX, |
1586 | .ucode_api_min = IWL5000_UCODE_API_MIN, | 405 | .ucode_api_min = IWL5000_UCODE_API_MIN, |
1587 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 406 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
1588 | .ops = &iwl5000_ops, | 407 | .ops = &iwl5000_ops, |
1589 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 408 | .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, |
1590 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 409 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, |
1591 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 410 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
1592 | .num_of_queues = IWL50_NUM_QUEUES, | 411 | .num_of_queues = IWLAGN_NUM_QUEUES, |
1593 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 412 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
1594 | .mod_params = &iwl50_mod_params, | 413 | .mod_params = &iwlagn_mod_params, |
1595 | .valid_tx_ant = ANT_ABC, | 414 | .valid_tx_ant = ANT_ABC, |
1596 | .valid_rx_ant = ANT_ABC, | 415 | .valid_rx_ant = ANT_ABC, |
1597 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | 416 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
@@ -1603,21 +422,22 @@ struct iwl_cfg iwl5300_agn_cfg = { | |||
1603 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 422 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
1604 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | 423 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
1605 | .chain_noise_scale = 1000, | 424 | .chain_noise_scale = 1000, |
425 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
1606 | }; | 426 | }; |
1607 | 427 | ||
1608 | struct iwl_cfg iwl5100_bgn_cfg = { | 428 | struct iwl_cfg iwl5100_bgn_cfg = { |
1609 | .name = "5100BGN", | 429 | .name = "Intel(R) WiFi Link 5100 BGN", |
1610 | .fw_name_pre = IWL5000_FW_PRE, | 430 | .fw_name_pre = IWL5000_FW_PRE, |
1611 | .ucode_api_max = IWL5000_UCODE_API_MAX, | 431 | .ucode_api_max = IWL5000_UCODE_API_MAX, |
1612 | .ucode_api_min = IWL5000_UCODE_API_MIN, | 432 | .ucode_api_min = IWL5000_UCODE_API_MIN, |
1613 | .sku = IWL_SKU_G|IWL_SKU_N, | 433 | .sku = IWL_SKU_G|IWL_SKU_N, |
1614 | .ops = &iwl5000_ops, | 434 | .ops = &iwl5000_ops, |
1615 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 435 | .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, |
1616 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 436 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, |
1617 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 437 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
1618 | .num_of_queues = IWL50_NUM_QUEUES, | 438 | .num_of_queues = IWLAGN_NUM_QUEUES, |
1619 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 439 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
1620 | .mod_params = &iwl50_mod_params, | 440 | .mod_params = &iwlagn_mod_params, |
1621 | .valid_tx_ant = ANT_B, | 441 | .valid_tx_ant = ANT_B, |
1622 | .valid_rx_ant = ANT_AB, | 442 | .valid_rx_ant = ANT_AB, |
1623 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | 443 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
@@ -1629,21 +449,22 @@ struct iwl_cfg iwl5100_bgn_cfg = { | |||
1629 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 449 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
1630 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | 450 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
1631 | .chain_noise_scale = 1000, | 451 | .chain_noise_scale = 1000, |
452 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
1632 | }; | 453 | }; |
1633 | 454 | ||
1634 | struct iwl_cfg iwl5100_abg_cfg = { | 455 | struct iwl_cfg iwl5100_abg_cfg = { |
1635 | .name = "5100ABG", | 456 | .name = "Intel(R) WiFi Link 5100 ABG", |
1636 | .fw_name_pre = IWL5000_FW_PRE, | 457 | .fw_name_pre = IWL5000_FW_PRE, |
1637 | .ucode_api_max = IWL5000_UCODE_API_MAX, | 458 | .ucode_api_max = IWL5000_UCODE_API_MAX, |
1638 | .ucode_api_min = IWL5000_UCODE_API_MIN, | 459 | .ucode_api_min = IWL5000_UCODE_API_MIN, |
1639 | .sku = IWL_SKU_A|IWL_SKU_G, | 460 | .sku = IWL_SKU_A|IWL_SKU_G, |
1640 | .ops = &iwl5000_ops, | 461 | .ops = &iwl5000_ops, |
1641 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 462 | .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, |
1642 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 463 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, |
1643 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 464 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
1644 | .num_of_queues = IWL50_NUM_QUEUES, | 465 | .num_of_queues = IWLAGN_NUM_QUEUES, |
1645 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 466 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
1646 | .mod_params = &iwl50_mod_params, | 467 | .mod_params = &iwlagn_mod_params, |
1647 | .valid_tx_ant = ANT_B, | 468 | .valid_tx_ant = ANT_B, |
1648 | .valid_rx_ant = ANT_AB, | 469 | .valid_rx_ant = ANT_AB, |
1649 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | 470 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
@@ -1653,21 +474,22 @@ struct iwl_cfg iwl5100_abg_cfg = { | |||
1653 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 474 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
1654 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | 475 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
1655 | .chain_noise_scale = 1000, | 476 | .chain_noise_scale = 1000, |
477 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
1656 | }; | 478 | }; |
1657 | 479 | ||
1658 | struct iwl_cfg iwl5100_agn_cfg = { | 480 | struct iwl_cfg iwl5100_agn_cfg = { |
1659 | .name = "5100AGN", | 481 | .name = "Intel(R) WiFi Link 5100 AGN", |
1660 | .fw_name_pre = IWL5000_FW_PRE, | 482 | .fw_name_pre = IWL5000_FW_PRE, |
1661 | .ucode_api_max = IWL5000_UCODE_API_MAX, | 483 | .ucode_api_max = IWL5000_UCODE_API_MAX, |
1662 | .ucode_api_min = IWL5000_UCODE_API_MIN, | 484 | .ucode_api_min = IWL5000_UCODE_API_MIN, |
1663 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 485 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
1664 | .ops = &iwl5000_ops, | 486 | .ops = &iwl5000_ops, |
1665 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 487 | .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, |
1666 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 488 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, |
1667 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 489 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
1668 | .num_of_queues = IWL50_NUM_QUEUES, | 490 | .num_of_queues = IWLAGN_NUM_QUEUES, |
1669 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 491 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
1670 | .mod_params = &iwl50_mod_params, | 492 | .mod_params = &iwlagn_mod_params, |
1671 | .valid_tx_ant = ANT_B, | 493 | .valid_tx_ant = ANT_B, |
1672 | .valid_rx_ant = ANT_AB, | 494 | .valid_rx_ant = ANT_AB, |
1673 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | 495 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
@@ -1679,21 +501,22 @@ struct iwl_cfg iwl5100_agn_cfg = { | |||
1679 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 501 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
1680 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | 502 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
1681 | .chain_noise_scale = 1000, | 503 | .chain_noise_scale = 1000, |
504 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
1682 | }; | 505 | }; |
1683 | 506 | ||
1684 | struct iwl_cfg iwl5350_agn_cfg = { | 507 | struct iwl_cfg iwl5350_agn_cfg = { |
1685 | .name = "5350AGN", | 508 | .name = "Intel(R) WiMAX/WiFi Link 5350 AGN", |
1686 | .fw_name_pre = IWL5000_FW_PRE, | 509 | .fw_name_pre = IWL5000_FW_PRE, |
1687 | .ucode_api_max = IWL5000_UCODE_API_MAX, | 510 | .ucode_api_max = IWL5000_UCODE_API_MAX, |
1688 | .ucode_api_min = IWL5000_UCODE_API_MIN, | 511 | .ucode_api_min = IWL5000_UCODE_API_MIN, |
1689 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 512 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
1690 | .ops = &iwl5000_ops, | 513 | .ops = &iwl5000_ops, |
1691 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 514 | .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, |
1692 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, | 515 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, |
1693 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, | 516 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, |
1694 | .num_of_queues = IWL50_NUM_QUEUES, | 517 | .num_of_queues = IWLAGN_NUM_QUEUES, |
1695 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 518 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
1696 | .mod_params = &iwl50_mod_params, | 519 | .mod_params = &iwlagn_mod_params, |
1697 | .valid_tx_ant = ANT_ABC, | 520 | .valid_tx_ant = ANT_ABC, |
1698 | .valid_rx_ant = ANT_ABC, | 521 | .valid_rx_ant = ANT_ABC, |
1699 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | 522 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
@@ -1705,21 +528,22 @@ struct iwl_cfg iwl5350_agn_cfg = { | |||
1705 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 528 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
1706 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | 529 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
1707 | .chain_noise_scale = 1000, | 530 | .chain_noise_scale = 1000, |
531 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
1708 | }; | 532 | }; |
1709 | 533 | ||
1710 | struct iwl_cfg iwl5150_agn_cfg = { | 534 | struct iwl_cfg iwl5150_agn_cfg = { |
1711 | .name = "5150AGN", | 535 | .name = "Intel(R) WiMAX/WiFi Link 5150 AGN", |
1712 | .fw_name_pre = IWL5150_FW_PRE, | 536 | .fw_name_pre = IWL5150_FW_PRE, |
1713 | .ucode_api_max = IWL5150_UCODE_API_MAX, | 537 | .ucode_api_max = IWL5150_UCODE_API_MAX, |
1714 | .ucode_api_min = IWL5150_UCODE_API_MIN, | 538 | .ucode_api_min = IWL5150_UCODE_API_MIN, |
1715 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 539 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
1716 | .ops = &iwl5150_ops, | 540 | .ops = &iwl5150_ops, |
1717 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 541 | .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, |
1718 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, | 542 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, |
1719 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, | 543 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, |
1720 | .num_of_queues = IWL50_NUM_QUEUES, | 544 | .num_of_queues = IWLAGN_NUM_QUEUES, |
1721 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 545 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
1722 | .mod_params = &iwl50_mod_params, | 546 | .mod_params = &iwlagn_mod_params, |
1723 | .valid_tx_ant = ANT_A, | 547 | .valid_tx_ant = ANT_A, |
1724 | .valid_rx_ant = ANT_AB, | 548 | .valid_rx_ant = ANT_AB, |
1725 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | 549 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
@@ -1731,21 +555,22 @@ struct iwl_cfg iwl5150_agn_cfg = { | |||
1731 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 555 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
1732 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | 556 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
1733 | .chain_noise_scale = 1000, | 557 | .chain_noise_scale = 1000, |
558 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
1734 | }; | 559 | }; |
1735 | 560 | ||
1736 | struct iwl_cfg iwl5150_abg_cfg = { | 561 | struct iwl_cfg iwl5150_abg_cfg = { |
1737 | .name = "5150ABG", | 562 | .name = "Intel(R) WiMAX/WiFi Link 5150 ABG", |
1738 | .fw_name_pre = IWL5150_FW_PRE, | 563 | .fw_name_pre = IWL5150_FW_PRE, |
1739 | .ucode_api_max = IWL5150_UCODE_API_MAX, | 564 | .ucode_api_max = IWL5150_UCODE_API_MAX, |
1740 | .ucode_api_min = IWL5150_UCODE_API_MIN, | 565 | .ucode_api_min = IWL5150_UCODE_API_MIN, |
1741 | .sku = IWL_SKU_A|IWL_SKU_G, | 566 | .sku = IWL_SKU_A|IWL_SKU_G, |
1742 | .ops = &iwl5150_ops, | 567 | .ops = &iwl5150_ops, |
1743 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 568 | .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, |
1744 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, | 569 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, |
1745 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, | 570 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, |
1746 | .num_of_queues = IWL50_NUM_QUEUES, | 571 | .num_of_queues = IWLAGN_NUM_QUEUES, |
1747 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 572 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
1748 | .mod_params = &iwl50_mod_params, | 573 | .mod_params = &iwlagn_mod_params, |
1749 | .valid_tx_ant = ANT_A, | 574 | .valid_tx_ant = ANT_A, |
1750 | .valid_rx_ant = ANT_AB, | 575 | .valid_rx_ant = ANT_AB, |
1751 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | 576 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
@@ -1755,20 +580,8 @@ struct iwl_cfg iwl5150_abg_cfg = { | |||
1755 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 580 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
1756 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | 581 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
1757 | .chain_noise_scale = 1000, | 582 | .chain_noise_scale = 1000, |
583 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
1758 | }; | 584 | }; |
1759 | 585 | ||
1760 | MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); | 586 | MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); |
1761 | MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_MAX)); | 587 | MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_MAX)); |
1762 | |||
1763 | module_param_named(swcrypto50, iwl50_mod_params.sw_crypto, bool, S_IRUGO); | ||
1764 | MODULE_PARM_DESC(swcrypto50, | ||
1765 | "using software crypto engine (default 0 [hardware])\n"); | ||
1766 | module_param_named(queues_num50, iwl50_mod_params.num_of_queues, int, S_IRUGO); | ||
1767 | MODULE_PARM_DESC(queues_num50, "number of hw queues in 50xx series"); | ||
1768 | module_param_named(11n_disable50, iwl50_mod_params.disable_11n, int, S_IRUGO); | ||
1769 | MODULE_PARM_DESC(11n_disable50, "disable 50XX 11n functionality"); | ||
1770 | module_param_named(amsdu_size_8K50, iwl50_mod_params.amsdu_size_8K, | ||
1771 | int, S_IRUGO); | ||
1772 | MODULE_PARM_DESC(amsdu_size_8K50, "enable 8K amsdu size in 50XX series"); | ||
1773 | module_param_named(fw_restart50, iwl50_mod_params.restart_fw, int, S_IRUGO); | ||
1774 | MODULE_PARM_DESC(fw_restart50, "restart firmware in case of error"); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index c4844adff92a..7473518e7e0a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c | |||
@@ -42,8 +42,9 @@ | |||
42 | #include "iwl-core.h" | 42 | #include "iwl-core.h" |
43 | #include "iwl-io.h" | 43 | #include "iwl-io.h" |
44 | #include "iwl-sta.h" | 44 | #include "iwl-sta.h" |
45 | #include "iwl-agn.h" | ||
45 | #include "iwl-helpers.h" | 46 | #include "iwl-helpers.h" |
46 | #include "iwl-5000-hw.h" | 47 | #include "iwl-agn-hw.h" |
47 | #include "iwl-6000-hw.h" | 48 | #include "iwl-6000-hw.h" |
48 | #include "iwl-agn-led.h" | 49 | #include "iwl-agn-led.h" |
49 | 50 | ||
@@ -56,6 +57,7 @@ | |||
56 | #define IWL6050_UCODE_API_MIN 4 | 57 | #define IWL6050_UCODE_API_MIN 4 |
57 | 58 | ||
58 | #define IWL6000_FW_PRE "iwlwifi-6000-" | 59 | #define IWL6000_FW_PRE "iwlwifi-6000-" |
60 | #define IWL6000_G2_FW_PRE "iwlwifi-6005-" | ||
59 | #define _IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode" | 61 | #define _IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode" |
60 | #define IWL6000_MODULE_FIRMWARE(api) _IWL6000_MODULE_FIRMWARE(api) | 62 | #define IWL6000_MODULE_FIRMWARE(api) _IWL6000_MODULE_FIRMWARE(api) |
61 | 63 | ||
@@ -136,7 +138,7 @@ static struct iwl_sensitivity_ranges iwl6000_sensitivity = { | |||
136 | static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) | 138 | static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) |
137 | { | 139 | { |
138 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && | 140 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && |
139 | priv->cfg->mod_params->num_of_queues <= IWL50_NUM_QUEUES) | 141 | priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES) |
140 | priv->cfg->num_of_queues = | 142 | priv->cfg->num_of_queues = |
141 | priv->cfg->mod_params->num_of_queues; | 143 | priv->cfg->mod_params->num_of_queues; |
142 | 144 | ||
@@ -144,7 +146,7 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) | |||
144 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; | 146 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; |
145 | priv->hw_params.scd_bc_tbls_size = | 147 | priv->hw_params.scd_bc_tbls_size = |
146 | priv->cfg->num_of_queues * | 148 | priv->cfg->num_of_queues * |
147 | sizeof(struct iwl5000_scd_bc_tbl); | 149 | sizeof(struct iwlagn_scd_bc_tbl); |
148 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); | 150 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); |
149 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; | 151 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; |
150 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; | 152 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; |
@@ -225,25 +227,25 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, u16 channel) | |||
225 | 227 | ||
226 | static struct iwl_lib_ops iwl6000_lib = { | 228 | static struct iwl_lib_ops iwl6000_lib = { |
227 | .set_hw_params = iwl6000_hw_set_hw_params, | 229 | .set_hw_params = iwl6000_hw_set_hw_params, |
228 | .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, | 230 | .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, |
229 | .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, | 231 | .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, |
230 | .txq_set_sched = iwl5000_txq_set_sched, | 232 | .txq_set_sched = iwlagn_txq_set_sched, |
231 | .txq_agg_enable = iwl5000_txq_agg_enable, | 233 | .txq_agg_enable = iwlagn_txq_agg_enable, |
232 | .txq_agg_disable = iwl5000_txq_agg_disable, | 234 | .txq_agg_disable = iwlagn_txq_agg_disable, |
233 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, | 235 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, |
234 | .txq_free_tfd = iwl_hw_txq_free_tfd, | 236 | .txq_free_tfd = iwl_hw_txq_free_tfd, |
235 | .txq_init = iwl_hw_tx_queue_init, | 237 | .txq_init = iwl_hw_tx_queue_init, |
236 | .rx_handler_setup = iwl5000_rx_handler_setup, | 238 | .rx_handler_setup = iwlagn_rx_handler_setup, |
237 | .setup_deferred_work = iwl5000_setup_deferred_work, | 239 | .setup_deferred_work = iwlagn_setup_deferred_work, |
238 | .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, | 240 | .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, |
239 | .load_ucode = iwl5000_load_ucode, | 241 | .load_ucode = iwlagn_load_ucode, |
240 | .dump_nic_event_log = iwl_dump_nic_event_log, | 242 | .dump_nic_event_log = iwl_dump_nic_event_log, |
241 | .dump_nic_error_log = iwl_dump_nic_error_log, | 243 | .dump_nic_error_log = iwl_dump_nic_error_log, |
242 | .dump_csr = iwl_dump_csr, | 244 | .dump_csr = iwl_dump_csr, |
243 | .dump_fh = iwl_dump_fh, | 245 | .dump_fh = iwl_dump_fh, |
244 | .init_alive_start = iwl5000_init_alive_start, | 246 | .init_alive_start = iwlagn_init_alive_start, |
245 | .alive_notify = iwl5000_alive_notify, | 247 | .alive_notify = iwlagn_alive_notify, |
246 | .send_tx_power = iwl5000_send_tx_power, | 248 | .send_tx_power = iwlagn_send_tx_power, |
247 | .update_chain_flags = iwl_update_chain_flags, | 249 | .update_chain_flags = iwl_update_chain_flags, |
248 | .set_channel_switch = iwl6000_hw_channel_switch, | 250 | .set_channel_switch = iwl6000_hw_channel_switch, |
249 | .apm_ops = { | 251 | .apm_ops = { |
@@ -254,60 +256,63 @@ static struct iwl_lib_ops iwl6000_lib = { | |||
254 | }, | 256 | }, |
255 | .eeprom_ops = { | 257 | .eeprom_ops = { |
256 | .regulatory_bands = { | 258 | .regulatory_bands = { |
257 | EEPROM_5000_REG_BAND_1_CHANNELS, | 259 | EEPROM_REG_BAND_1_CHANNELS, |
258 | EEPROM_5000_REG_BAND_2_CHANNELS, | 260 | EEPROM_REG_BAND_2_CHANNELS, |
259 | EEPROM_5000_REG_BAND_3_CHANNELS, | 261 | EEPROM_REG_BAND_3_CHANNELS, |
260 | EEPROM_5000_REG_BAND_4_CHANNELS, | 262 | EEPROM_REG_BAND_4_CHANNELS, |
261 | EEPROM_5000_REG_BAND_5_CHANNELS, | 263 | EEPROM_REG_BAND_5_CHANNELS, |
262 | EEPROM_5000_REG_BAND_24_HT40_CHANNELS, | 264 | EEPROM_REG_BAND_24_HT40_CHANNELS, |
263 | EEPROM_5000_REG_BAND_52_HT40_CHANNELS | 265 | EEPROM_REG_BAND_52_HT40_CHANNELS |
264 | }, | 266 | }, |
265 | .verify_signature = iwlcore_eeprom_verify_signature, | 267 | .verify_signature = iwlcore_eeprom_verify_signature, |
266 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, | 268 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, |
267 | .release_semaphore = iwlcore_eeprom_release_semaphore, | 269 | .release_semaphore = iwlcore_eeprom_release_semaphore, |
268 | .calib_version = iwl5000_eeprom_calib_version, | 270 | .calib_version = iwlagn_eeprom_calib_version, |
269 | .query_addr = iwl5000_eeprom_query_addr, | 271 | .query_addr = iwlagn_eeprom_query_addr, |
270 | .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, | 272 | .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, |
271 | }, | 273 | }, |
272 | .post_associate = iwl_post_associate, | 274 | .post_associate = iwl_post_associate, |
273 | .isr = iwl_isr_ict, | 275 | .isr = iwl_isr_ict, |
274 | .config_ap = iwl_config_ap, | 276 | .config_ap = iwl_config_ap, |
275 | .temp_ops = { | 277 | .temp_ops = { |
276 | .temperature = iwl5000_temperature, | 278 | .temperature = iwlagn_temperature, |
277 | .set_ct_kill = iwl6000_set_ct_threshold, | 279 | .set_ct_kill = iwl6000_set_ct_threshold, |
278 | }, | 280 | }, |
279 | .add_bcast_station = iwl_add_bcast_station, | 281 | .add_bcast_station = iwl_add_bcast_station, |
282 | .recover_from_tx_stall = iwl_bg_monitor_recover, | ||
283 | .check_plcp_health = iwl_good_plcp_health, | ||
284 | .check_ack_health = iwl_good_ack_health, | ||
280 | }; | 285 | }; |
281 | 286 | ||
282 | static const struct iwl_ops iwl6000_ops = { | 287 | static const struct iwl_ops iwl6000_ops = { |
283 | .ucode = &iwl5000_ucode, | 288 | .ucode = &iwlagn_ucode, |
284 | .lib = &iwl6000_lib, | 289 | .lib = &iwl6000_lib, |
285 | .hcmd = &iwl5000_hcmd, | 290 | .hcmd = &iwlagn_hcmd, |
286 | .utils = &iwl5000_hcmd_utils, | 291 | .utils = &iwlagn_hcmd_utils, |
287 | .led = &iwlagn_led_ops, | 292 | .led = &iwlagn_led_ops, |
288 | }; | 293 | }; |
289 | 294 | ||
290 | static struct iwl_lib_ops iwl6050_lib = { | 295 | static struct iwl_lib_ops iwl6050_lib = { |
291 | .set_hw_params = iwl6000_hw_set_hw_params, | 296 | .set_hw_params = iwl6000_hw_set_hw_params, |
292 | .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, | 297 | .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, |
293 | .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, | 298 | .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, |
294 | .txq_set_sched = iwl5000_txq_set_sched, | 299 | .txq_set_sched = iwlagn_txq_set_sched, |
295 | .txq_agg_enable = iwl5000_txq_agg_enable, | 300 | .txq_agg_enable = iwlagn_txq_agg_enable, |
296 | .txq_agg_disable = iwl5000_txq_agg_disable, | 301 | .txq_agg_disable = iwlagn_txq_agg_disable, |
297 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, | 302 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, |
298 | .txq_free_tfd = iwl_hw_txq_free_tfd, | 303 | .txq_free_tfd = iwl_hw_txq_free_tfd, |
299 | .txq_init = iwl_hw_tx_queue_init, | 304 | .txq_init = iwl_hw_tx_queue_init, |
300 | .rx_handler_setup = iwl5000_rx_handler_setup, | 305 | .rx_handler_setup = iwlagn_rx_handler_setup, |
301 | .setup_deferred_work = iwl5000_setup_deferred_work, | 306 | .setup_deferred_work = iwlagn_setup_deferred_work, |
302 | .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, | 307 | .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, |
303 | .load_ucode = iwl5000_load_ucode, | 308 | .load_ucode = iwlagn_load_ucode, |
304 | .dump_nic_event_log = iwl_dump_nic_event_log, | 309 | .dump_nic_event_log = iwl_dump_nic_event_log, |
305 | .dump_nic_error_log = iwl_dump_nic_error_log, | 310 | .dump_nic_error_log = iwl_dump_nic_error_log, |
306 | .dump_csr = iwl_dump_csr, | 311 | .dump_csr = iwl_dump_csr, |
307 | .dump_fh = iwl_dump_fh, | 312 | .dump_fh = iwl_dump_fh, |
308 | .init_alive_start = iwl5000_init_alive_start, | 313 | .init_alive_start = iwlagn_init_alive_start, |
309 | .alive_notify = iwl5000_alive_notify, | 314 | .alive_notify = iwlagn_alive_notify, |
310 | .send_tx_power = iwl5000_send_tx_power, | 315 | .send_tx_power = iwlagn_send_tx_power, |
311 | .update_chain_flags = iwl_update_chain_flags, | 316 | .update_chain_flags = iwl_update_chain_flags, |
312 | .set_channel_switch = iwl6000_hw_channel_switch, | 317 | .set_channel_switch = iwl6000_hw_channel_switch, |
313 | .apm_ops = { | 318 | .apm_ops = { |
@@ -318,45 +323,81 @@ static struct iwl_lib_ops iwl6050_lib = { | |||
318 | }, | 323 | }, |
319 | .eeprom_ops = { | 324 | .eeprom_ops = { |
320 | .regulatory_bands = { | 325 | .regulatory_bands = { |
321 | EEPROM_5000_REG_BAND_1_CHANNELS, | 326 | EEPROM_REG_BAND_1_CHANNELS, |
322 | EEPROM_5000_REG_BAND_2_CHANNELS, | 327 | EEPROM_REG_BAND_2_CHANNELS, |
323 | EEPROM_5000_REG_BAND_3_CHANNELS, | 328 | EEPROM_REG_BAND_3_CHANNELS, |
324 | EEPROM_5000_REG_BAND_4_CHANNELS, | 329 | EEPROM_REG_BAND_4_CHANNELS, |
325 | EEPROM_5000_REG_BAND_5_CHANNELS, | 330 | EEPROM_REG_BAND_5_CHANNELS, |
326 | EEPROM_5000_REG_BAND_24_HT40_CHANNELS, | 331 | EEPROM_REG_BAND_24_HT40_CHANNELS, |
327 | EEPROM_5000_REG_BAND_52_HT40_CHANNELS | 332 | EEPROM_REG_BAND_52_HT40_CHANNELS |
328 | }, | 333 | }, |
329 | .verify_signature = iwlcore_eeprom_verify_signature, | 334 | .verify_signature = iwlcore_eeprom_verify_signature, |
330 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, | 335 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, |
331 | .release_semaphore = iwlcore_eeprom_release_semaphore, | 336 | .release_semaphore = iwlcore_eeprom_release_semaphore, |
332 | .calib_version = iwl5000_eeprom_calib_version, | 337 | .calib_version = iwlagn_eeprom_calib_version, |
333 | .query_addr = iwl5000_eeprom_query_addr, | 338 | .query_addr = iwlagn_eeprom_query_addr, |
334 | .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, | 339 | .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, |
335 | }, | 340 | }, |
336 | .post_associate = iwl_post_associate, | 341 | .post_associate = iwl_post_associate, |
337 | .isr = iwl_isr_ict, | 342 | .isr = iwl_isr_ict, |
338 | .config_ap = iwl_config_ap, | 343 | .config_ap = iwl_config_ap, |
339 | .temp_ops = { | 344 | .temp_ops = { |
340 | .temperature = iwl5000_temperature, | 345 | .temperature = iwlagn_temperature, |
341 | .set_ct_kill = iwl6000_set_ct_threshold, | 346 | .set_ct_kill = iwl6000_set_ct_threshold, |
342 | .set_calib_version = iwl6050_set_calib_version, | 347 | .set_calib_version = iwl6050_set_calib_version, |
343 | }, | 348 | }, |
344 | .add_bcast_station = iwl_add_bcast_station, | 349 | .add_bcast_station = iwl_add_bcast_station, |
350 | .recover_from_tx_stall = iwl_bg_monitor_recover, | ||
351 | .check_plcp_health = iwl_good_plcp_health, | ||
352 | .check_ack_health = iwl_good_ack_health, | ||
345 | }; | 353 | }; |
346 | 354 | ||
347 | static const struct iwl_ops iwl6050_ops = { | 355 | static const struct iwl_ops iwl6050_ops = { |
348 | .ucode = &iwl5000_ucode, | 356 | .ucode = &iwlagn_ucode, |
349 | .lib = &iwl6050_lib, | 357 | .lib = &iwl6050_lib, |
350 | .hcmd = &iwl5000_hcmd, | 358 | .hcmd = &iwlagn_hcmd, |
351 | .utils = &iwl5000_hcmd_utils, | 359 | .utils = &iwlagn_hcmd_utils, |
352 | .led = &iwlagn_led_ops, | 360 | .led = &iwlagn_led_ops, |
353 | }; | 361 | }; |
354 | 362 | ||
355 | /* | 363 | /* |
356 | * "i": Internal configuration, use internal Power Amplifier | 364 | * "i": Internal configuration, use internal Power Amplifier |
357 | */ | 365 | */ |
366 | struct iwl_cfg iwl6000i_g2_2agn_cfg = { | ||
367 | .name = "6000 Series 2x2 AGN Gen2", | ||
368 | .fw_name_pre = IWL6000_G2_FW_PRE, | ||
369 | .ucode_api_max = IWL6000_UCODE_API_MAX, | ||
370 | .ucode_api_min = IWL6000_UCODE_API_MIN, | ||
371 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | ||
372 | .ops = &iwl6000_ops, | ||
373 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | ||
374 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | ||
375 | .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, | ||
376 | .num_of_queues = IWLAGN_NUM_QUEUES, | ||
377 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
378 | .mod_params = &iwlagn_mod_params, | ||
379 | .valid_tx_ant = ANT_AB, | ||
380 | .valid_rx_ant = ANT_AB, | ||
381 | .pll_cfg_val = 0, | ||
382 | .set_l0s = true, | ||
383 | .use_bsm = false, | ||
384 | .pa_type = IWL_PA_INTERNAL, | ||
385 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
386 | .shadow_ram_support = true, | ||
387 | .ht_greenfield_support = true, | ||
388 | .led_compensation = 51, | ||
389 | .use_rts_for_ht = true, /* use rts/cts protection */ | ||
390 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
391 | .supports_idle = true, | ||
392 | .adv_thermal_throttle = true, | ||
393 | .support_ct_kill_exit = true, | ||
394 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
395 | .chain_noise_scale = 1000, | ||
396 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
397 | }; | ||
398 | |||
358 | struct iwl_cfg iwl6000i_2agn_cfg = { | 399 | struct iwl_cfg iwl6000i_2agn_cfg = { |
359 | .name = "6000 Series 2x2 AGN", | 400 | .name = "Intel(R) Centrino(R) Advanced-N 6200 AGN", |
360 | .fw_name_pre = IWL6000_FW_PRE, | 401 | .fw_name_pre = IWL6000_FW_PRE, |
361 | .ucode_api_max = IWL6000_UCODE_API_MAX, | 402 | .ucode_api_max = IWL6000_UCODE_API_MAX, |
362 | .ucode_api_min = IWL6000_UCODE_API_MIN, | 403 | .ucode_api_min = IWL6000_UCODE_API_MIN, |
@@ -364,10 +405,10 @@ struct iwl_cfg iwl6000i_2agn_cfg = { | |||
364 | .ops = &iwl6000_ops, | 405 | .ops = &iwl6000_ops, |
365 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 406 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
366 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | 407 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, |
367 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 408 | .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, |
368 | .num_of_queues = IWL50_NUM_QUEUES, | 409 | .num_of_queues = IWLAGN_NUM_QUEUES, |
369 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 410 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
370 | .mod_params = &iwl50_mod_params, | 411 | .mod_params = &iwlagn_mod_params, |
371 | .valid_tx_ant = ANT_BC, | 412 | .valid_tx_ant = ANT_BC, |
372 | .valid_rx_ant = ANT_BC, | 413 | .valid_rx_ant = ANT_BC, |
373 | .pll_cfg_val = 0, | 414 | .pll_cfg_val = 0, |
@@ -385,10 +426,11 @@ struct iwl_cfg iwl6000i_2agn_cfg = { | |||
385 | .support_ct_kill_exit = true, | 426 | .support_ct_kill_exit = true, |
386 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 427 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
387 | .chain_noise_scale = 1000, | 428 | .chain_noise_scale = 1000, |
429 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
388 | }; | 430 | }; |
389 | 431 | ||
390 | struct iwl_cfg iwl6000i_2abg_cfg = { | 432 | struct iwl_cfg iwl6000i_2abg_cfg = { |
391 | .name = "6000 Series 2x2 ABG", | 433 | .name = "Intel(R) Centrino(R) Advanced-N 6200 ABG", |
392 | .fw_name_pre = IWL6000_FW_PRE, | 434 | .fw_name_pre = IWL6000_FW_PRE, |
393 | .ucode_api_max = IWL6000_UCODE_API_MAX, | 435 | .ucode_api_max = IWL6000_UCODE_API_MAX, |
394 | .ucode_api_min = IWL6000_UCODE_API_MIN, | 436 | .ucode_api_min = IWL6000_UCODE_API_MIN, |
@@ -396,10 +438,10 @@ struct iwl_cfg iwl6000i_2abg_cfg = { | |||
396 | .ops = &iwl6000_ops, | 438 | .ops = &iwl6000_ops, |
397 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 439 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
398 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | 440 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, |
399 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 441 | .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, |
400 | .num_of_queues = IWL50_NUM_QUEUES, | 442 | .num_of_queues = IWLAGN_NUM_QUEUES, |
401 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 443 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
402 | .mod_params = &iwl50_mod_params, | 444 | .mod_params = &iwlagn_mod_params, |
403 | .valid_tx_ant = ANT_BC, | 445 | .valid_tx_ant = ANT_BC, |
404 | .valid_rx_ant = ANT_BC, | 446 | .valid_rx_ant = ANT_BC, |
405 | .pll_cfg_val = 0, | 447 | .pll_cfg_val = 0, |
@@ -416,10 +458,11 @@ struct iwl_cfg iwl6000i_2abg_cfg = { | |||
416 | .support_ct_kill_exit = true, | 458 | .support_ct_kill_exit = true, |
417 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 459 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
418 | .chain_noise_scale = 1000, | 460 | .chain_noise_scale = 1000, |
461 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
419 | }; | 462 | }; |
420 | 463 | ||
421 | struct iwl_cfg iwl6000i_2bg_cfg = { | 464 | struct iwl_cfg iwl6000i_2bg_cfg = { |
422 | .name = "6000 Series 2x2 BG", | 465 | .name = "Intel(R) Centrino(R) Advanced-N 6200 BG", |
423 | .fw_name_pre = IWL6000_FW_PRE, | 466 | .fw_name_pre = IWL6000_FW_PRE, |
424 | .ucode_api_max = IWL6000_UCODE_API_MAX, | 467 | .ucode_api_max = IWL6000_UCODE_API_MAX, |
425 | .ucode_api_min = IWL6000_UCODE_API_MIN, | 468 | .ucode_api_min = IWL6000_UCODE_API_MIN, |
@@ -427,10 +470,10 @@ struct iwl_cfg iwl6000i_2bg_cfg = { | |||
427 | .ops = &iwl6000_ops, | 470 | .ops = &iwl6000_ops, |
428 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 471 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
429 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | 472 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, |
430 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 473 | .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, |
431 | .num_of_queues = IWL50_NUM_QUEUES, | 474 | .num_of_queues = IWLAGN_NUM_QUEUES, |
432 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 475 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
433 | .mod_params = &iwl50_mod_params, | 476 | .mod_params = &iwlagn_mod_params, |
434 | .valid_tx_ant = ANT_BC, | 477 | .valid_tx_ant = ANT_BC, |
435 | .valid_rx_ant = ANT_BC, | 478 | .valid_rx_ant = ANT_BC, |
436 | .pll_cfg_val = 0, | 479 | .pll_cfg_val = 0, |
@@ -447,10 +490,11 @@ struct iwl_cfg iwl6000i_2bg_cfg = { | |||
447 | .support_ct_kill_exit = true, | 490 | .support_ct_kill_exit = true, |
448 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 491 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
449 | .chain_noise_scale = 1000, | 492 | .chain_noise_scale = 1000, |
493 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
450 | }; | 494 | }; |
451 | 495 | ||
452 | struct iwl_cfg iwl6050_2agn_cfg = { | 496 | struct iwl_cfg iwl6050_2agn_cfg = { |
453 | .name = "6050 Series 2x2 AGN", | 497 | .name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 AGN", |
454 | .fw_name_pre = IWL6050_FW_PRE, | 498 | .fw_name_pre = IWL6050_FW_PRE, |
455 | .ucode_api_max = IWL6050_UCODE_API_MAX, | 499 | .ucode_api_max = IWL6050_UCODE_API_MAX, |
456 | .ucode_api_min = IWL6050_UCODE_API_MIN, | 500 | .ucode_api_min = IWL6050_UCODE_API_MIN, |
@@ -458,10 +502,10 @@ struct iwl_cfg iwl6050_2agn_cfg = { | |||
458 | .ops = &iwl6050_ops, | 502 | .ops = &iwl6050_ops, |
459 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 503 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
460 | .eeprom_ver = EEPROM_6050_EEPROM_VERSION, | 504 | .eeprom_ver = EEPROM_6050_EEPROM_VERSION, |
461 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 505 | .eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION, |
462 | .num_of_queues = IWL50_NUM_QUEUES, | 506 | .num_of_queues = IWLAGN_NUM_QUEUES, |
463 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 507 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
464 | .mod_params = &iwl50_mod_params, | 508 | .mod_params = &iwlagn_mod_params, |
465 | .valid_tx_ant = ANT_AB, | 509 | .valid_tx_ant = ANT_AB, |
466 | .valid_rx_ant = ANT_AB, | 510 | .valid_rx_ant = ANT_AB, |
467 | .pll_cfg_val = 0, | 511 | .pll_cfg_val = 0, |
@@ -479,10 +523,11 @@ struct iwl_cfg iwl6050_2agn_cfg = { | |||
479 | .support_ct_kill_exit = true, | 523 | .support_ct_kill_exit = true, |
480 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 524 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
481 | .chain_noise_scale = 1500, | 525 | .chain_noise_scale = 1500, |
526 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
482 | }; | 527 | }; |
483 | 528 | ||
484 | struct iwl_cfg iwl6050_2abg_cfg = { | 529 | struct iwl_cfg iwl6050_2abg_cfg = { |
485 | .name = "6050 Series 2x2 ABG", | 530 | .name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 ABG", |
486 | .fw_name_pre = IWL6050_FW_PRE, | 531 | .fw_name_pre = IWL6050_FW_PRE, |
487 | .ucode_api_max = IWL6050_UCODE_API_MAX, | 532 | .ucode_api_max = IWL6050_UCODE_API_MAX, |
488 | .ucode_api_min = IWL6050_UCODE_API_MIN, | 533 | .ucode_api_min = IWL6050_UCODE_API_MIN, |
@@ -490,10 +535,10 @@ struct iwl_cfg iwl6050_2abg_cfg = { | |||
490 | .ops = &iwl6050_ops, | 535 | .ops = &iwl6050_ops, |
491 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 536 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
492 | .eeprom_ver = EEPROM_6050_EEPROM_VERSION, | 537 | .eeprom_ver = EEPROM_6050_EEPROM_VERSION, |
493 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 538 | .eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION, |
494 | .num_of_queues = IWL50_NUM_QUEUES, | 539 | .num_of_queues = IWLAGN_NUM_QUEUES, |
495 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 540 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
496 | .mod_params = &iwl50_mod_params, | 541 | .mod_params = &iwlagn_mod_params, |
497 | .valid_tx_ant = ANT_AB, | 542 | .valid_tx_ant = ANT_AB, |
498 | .valid_rx_ant = ANT_AB, | 543 | .valid_rx_ant = ANT_AB, |
499 | .pll_cfg_val = 0, | 544 | .pll_cfg_val = 0, |
@@ -510,10 +555,11 @@ struct iwl_cfg iwl6050_2abg_cfg = { | |||
510 | .support_ct_kill_exit = true, | 555 | .support_ct_kill_exit = true, |
511 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 556 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
512 | .chain_noise_scale = 1500, | 557 | .chain_noise_scale = 1500, |
558 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
513 | }; | 559 | }; |
514 | 560 | ||
515 | struct iwl_cfg iwl6000_3agn_cfg = { | 561 | struct iwl_cfg iwl6000_3agn_cfg = { |
516 | .name = "6000 Series 3x3 AGN", | 562 | .name = "Intel(R) Centrino(R) Ultimate-N 6300 AGN", |
517 | .fw_name_pre = IWL6000_FW_PRE, | 563 | .fw_name_pre = IWL6000_FW_PRE, |
518 | .ucode_api_max = IWL6000_UCODE_API_MAX, | 564 | .ucode_api_max = IWL6000_UCODE_API_MAX, |
519 | .ucode_api_min = IWL6000_UCODE_API_MIN, | 565 | .ucode_api_min = IWL6000_UCODE_API_MIN, |
@@ -521,10 +567,10 @@ struct iwl_cfg iwl6000_3agn_cfg = { | |||
521 | .ops = &iwl6000_ops, | 567 | .ops = &iwl6000_ops, |
522 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 568 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
523 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | 569 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, |
524 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 570 | .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, |
525 | .num_of_queues = IWL50_NUM_QUEUES, | 571 | .num_of_queues = IWLAGN_NUM_QUEUES, |
526 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 572 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
527 | .mod_params = &iwl50_mod_params, | 573 | .mod_params = &iwlagn_mod_params, |
528 | .valid_tx_ant = ANT_ABC, | 574 | .valid_tx_ant = ANT_ABC, |
529 | .valid_rx_ant = ANT_ABC, | 575 | .valid_rx_ant = ANT_ABC, |
530 | .pll_cfg_val = 0, | 576 | .pll_cfg_val = 0, |
@@ -542,6 +588,7 @@ struct iwl_cfg iwl6000_3agn_cfg = { | |||
542 | .support_ct_kill_exit = true, | 588 | .support_ct_kill_exit = true, |
543 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 589 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
544 | .chain_noise_scale = 1000, | 590 | .chain_noise_scale = 1000, |
591 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
545 | }; | 592 | }; |
546 | 593 | ||
547 | MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); | 594 | MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c new file mode 100644 index 000000000000..28bc8f8ba981 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | |||
@@ -0,0 +1,274 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * GPL LICENSE SUMMARY | ||
4 | * | ||
5 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of version 2 of the GNU General Public License as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
19 | * USA | ||
20 | * | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
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/sched.h> | ||
34 | |||
35 | #include "iwl-dev.h" | ||
36 | #include "iwl-core.h" | ||
37 | #include "iwl-io.h" | ||
38 | #include "iwl-agn.h" | ||
39 | |||
40 | static int iwlagn_send_rxon_assoc(struct iwl_priv *priv) | ||
41 | { | ||
42 | int ret = 0; | ||
43 | struct iwl5000_rxon_assoc_cmd rxon_assoc; | ||
44 | const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon; | ||
45 | const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon; | ||
46 | |||
47 | if ((rxon1->flags == rxon2->flags) && | ||
48 | (rxon1->filter_flags == rxon2->filter_flags) && | ||
49 | (rxon1->cck_basic_rates == rxon2->cck_basic_rates) && | ||
50 | (rxon1->ofdm_ht_single_stream_basic_rates == | ||
51 | rxon2->ofdm_ht_single_stream_basic_rates) && | ||
52 | (rxon1->ofdm_ht_dual_stream_basic_rates == | ||
53 | rxon2->ofdm_ht_dual_stream_basic_rates) && | ||
54 | (rxon1->ofdm_ht_triple_stream_basic_rates == | ||
55 | rxon2->ofdm_ht_triple_stream_basic_rates) && | ||
56 | (rxon1->acquisition_data == rxon2->acquisition_data) && | ||
57 | (rxon1->rx_chain == rxon2->rx_chain) && | ||
58 | (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) { | ||
59 | IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC. Not resending.\n"); | ||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | rxon_assoc.flags = priv->staging_rxon.flags; | ||
64 | rxon_assoc.filter_flags = priv->staging_rxon.filter_flags; | ||
65 | rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates; | ||
66 | rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates; | ||
67 | rxon_assoc.reserved1 = 0; | ||
68 | rxon_assoc.reserved2 = 0; | ||
69 | rxon_assoc.reserved3 = 0; | ||
70 | rxon_assoc.ofdm_ht_single_stream_basic_rates = | ||
71 | priv->staging_rxon.ofdm_ht_single_stream_basic_rates; | ||
72 | rxon_assoc.ofdm_ht_dual_stream_basic_rates = | ||
73 | priv->staging_rxon.ofdm_ht_dual_stream_basic_rates; | ||
74 | rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain; | ||
75 | rxon_assoc.ofdm_ht_triple_stream_basic_rates = | ||
76 | priv->staging_rxon.ofdm_ht_triple_stream_basic_rates; | ||
77 | rxon_assoc.acquisition_data = priv->staging_rxon.acquisition_data; | ||
78 | |||
79 | ret = iwl_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC, | ||
80 | sizeof(rxon_assoc), &rxon_assoc, NULL); | ||
81 | if (ret) | ||
82 | return ret; | ||
83 | |||
84 | return ret; | ||
85 | } | ||
86 | |||
87 | static int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant) | ||
88 | { | ||
89 | struct iwl_tx_ant_config_cmd tx_ant_cmd = { | ||
90 | .valid = cpu_to_le32(valid_tx_ant), | ||
91 | }; | ||
92 | |||
93 | if (IWL_UCODE_API(priv->ucode_ver) > 1) { | ||
94 | IWL_DEBUG_HC(priv, "select valid tx ant: %u\n", valid_tx_ant); | ||
95 | return iwl_send_cmd_pdu(priv, TX_ANT_CONFIGURATION_CMD, | ||
96 | sizeof(struct iwl_tx_ant_config_cmd), | ||
97 | &tx_ant_cmd); | ||
98 | } else { | ||
99 | IWL_DEBUG_HC(priv, "TX_ANT_CONFIGURATION_CMD not supported\n"); | ||
100 | return -EOPNOTSUPP; | ||
101 | } | ||
102 | } | ||
103 | |||
104 | /* Currently this is the superset of everything */ | ||
105 | static u16 iwlagn_get_hcmd_size(u8 cmd_id, u16 len) | ||
106 | { | ||
107 | return len; | ||
108 | } | ||
109 | |||
110 | static u16 iwlagn_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) | ||
111 | { | ||
112 | u16 size = (u16)sizeof(struct iwl_addsta_cmd); | ||
113 | struct iwl_addsta_cmd *addsta = (struct iwl_addsta_cmd *)data; | ||
114 | memcpy(addsta, cmd, size); | ||
115 | /* resrved in 5000 */ | ||
116 | addsta->rate_n_flags = cpu_to_le16(0); | ||
117 | return size; | ||
118 | } | ||
119 | |||
120 | static void iwlagn_gain_computation(struct iwl_priv *priv, | ||
121 | u32 average_noise[NUM_RX_CHAINS], | ||
122 | u16 min_average_noise_antenna_i, | ||
123 | u32 min_average_noise, | ||
124 | u8 default_chain) | ||
125 | { | ||
126 | int i; | ||
127 | s32 delta_g; | ||
128 | struct iwl_chain_noise_data *data = &priv->chain_noise_data; | ||
129 | |||
130 | /* | ||
131 | * Find Gain Code for the chains based on "default chain" | ||
132 | */ | ||
133 | for (i = default_chain + 1; i < NUM_RX_CHAINS; i++) { | ||
134 | if ((data->disconn_array[i])) { | ||
135 | data->delta_gain_code[i] = 0; | ||
136 | continue; | ||
137 | } | ||
138 | |||
139 | delta_g = (priv->cfg->chain_noise_scale * | ||
140 | ((s32)average_noise[default_chain] - | ||
141 | (s32)average_noise[i])) / 1500; | ||
142 | |||
143 | /* bound gain by 2 bits value max, 3rd bit is sign */ | ||
144 | data->delta_gain_code[i] = | ||
145 | min(abs(delta_g), (long) CHAIN_NOISE_MAX_DELTA_GAIN_CODE); | ||
146 | |||
147 | if (delta_g < 0) | ||
148 | /* | ||
149 | * set negative sign ... | ||
150 | * note to Intel developers: This is uCode API format, | ||
151 | * not the format of any internal device registers. | ||
152 | * Do not change this format for e.g. 6050 or similar | ||
153 | * devices. Change format only if more resolution | ||
154 | * (i.e. more than 2 bits magnitude) is needed. | ||
155 | */ | ||
156 | data->delta_gain_code[i] |= (1 << 2); | ||
157 | } | ||
158 | |||
159 | IWL_DEBUG_CALIB(priv, "Delta gains: ANT_B = %d ANT_C = %d\n", | ||
160 | data->delta_gain_code[1], data->delta_gain_code[2]); | ||
161 | |||
162 | if (!data->radio_write) { | ||
163 | struct iwl_calib_chain_noise_gain_cmd cmd; | ||
164 | |||
165 | memset(&cmd, 0, sizeof(cmd)); | ||
166 | |||
167 | cmd.hdr.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD; | ||
168 | cmd.hdr.first_group = 0; | ||
169 | cmd.hdr.groups_num = 1; | ||
170 | cmd.hdr.data_valid = 1; | ||
171 | cmd.delta_gain_1 = data->delta_gain_code[1]; | ||
172 | cmd.delta_gain_2 = data->delta_gain_code[2]; | ||
173 | iwl_send_cmd_pdu_async(priv, REPLY_PHY_CALIBRATION_CMD, | ||
174 | sizeof(cmd), &cmd, NULL); | ||
175 | |||
176 | data->radio_write = 1; | ||
177 | data->state = IWL_CHAIN_NOISE_CALIBRATED; | ||
178 | } | ||
179 | |||
180 | data->chain_noise_a = 0; | ||
181 | data->chain_noise_b = 0; | ||
182 | data->chain_noise_c = 0; | ||
183 | data->chain_signal_a = 0; | ||
184 | data->chain_signal_b = 0; | ||
185 | data->chain_signal_c = 0; | ||
186 | data->beacon_count = 0; | ||
187 | } | ||
188 | |||
189 | static void iwlagn_chain_noise_reset(struct iwl_priv *priv) | ||
190 | { | ||
191 | struct iwl_chain_noise_data *data = &priv->chain_noise_data; | ||
192 | int ret; | ||
193 | |||
194 | if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl_is_associated(priv)) { | ||
195 | struct iwl_calib_chain_noise_reset_cmd cmd; | ||
196 | memset(&cmd, 0, sizeof(cmd)); | ||
197 | |||
198 | cmd.hdr.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD; | ||
199 | cmd.hdr.first_group = 0; | ||
200 | cmd.hdr.groups_num = 1; | ||
201 | cmd.hdr.data_valid = 1; | ||
202 | ret = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD, | ||
203 | sizeof(cmd), &cmd); | ||
204 | if (ret) | ||
205 | IWL_ERR(priv, | ||
206 | "Could not send REPLY_PHY_CALIBRATION_CMD\n"); | ||
207 | data->state = IWL_CHAIN_NOISE_ACCUMULATE; | ||
208 | IWL_DEBUG_CALIB(priv, "Run chain_noise_calibrate\n"); | ||
209 | } | ||
210 | } | ||
211 | |||
212 | static void iwlagn_rts_tx_cmd_flag(struct ieee80211_tx_info *info, | ||
213 | __le32 *tx_flags) | ||
214 | { | ||
215 | if ((info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || | ||
216 | (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) | ||
217 | *tx_flags |= TX_CMD_FLG_RTS_CTS_MSK; | ||
218 | else | ||
219 | *tx_flags &= ~TX_CMD_FLG_RTS_CTS_MSK; | ||
220 | } | ||
221 | |||
222 | /* Calc max signal level (dBm) among 3 possible receivers */ | ||
223 | static int iwlagn_calc_rssi(struct iwl_priv *priv, | ||
224 | struct iwl_rx_phy_res *rx_resp) | ||
225 | { | ||
226 | /* data from PHY/DSP regarding signal strength, etc., | ||
227 | * contents are always there, not configurable by host | ||
228 | */ | ||
229 | struct iwl5000_non_cfg_phy *ncphy = | ||
230 | (struct iwl5000_non_cfg_phy *)rx_resp->non_cfg_phy_buf; | ||
231 | u32 val, rssi_a, rssi_b, rssi_c, max_rssi; | ||
232 | u8 agc; | ||
233 | |||
234 | val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_AGC_IDX]); | ||
235 | agc = (val & IWL50_OFDM_AGC_MSK) >> IWL50_OFDM_AGC_BIT_POS; | ||
236 | |||
237 | /* Find max rssi among 3 possible receivers. | ||
238 | * These values are measured by the digital signal processor (DSP). | ||
239 | * They should stay fairly constant even as the signal strength varies, | ||
240 | * if the radio's automatic gain control (AGC) is working right. | ||
241 | * AGC value (see below) will provide the "interesting" info. | ||
242 | */ | ||
243 | val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_AB_IDX]); | ||
244 | rssi_a = (val & IWL50_OFDM_RSSI_A_MSK) >> IWL50_OFDM_RSSI_A_BIT_POS; | ||
245 | rssi_b = (val & IWL50_OFDM_RSSI_B_MSK) >> IWL50_OFDM_RSSI_B_BIT_POS; | ||
246 | val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_C_IDX]); | ||
247 | rssi_c = (val & IWL50_OFDM_RSSI_C_MSK) >> IWL50_OFDM_RSSI_C_BIT_POS; | ||
248 | |||
249 | max_rssi = max_t(u32, rssi_a, rssi_b); | ||
250 | max_rssi = max_t(u32, max_rssi, rssi_c); | ||
251 | |||
252 | IWL_DEBUG_STATS(priv, "Rssi In A %d B %d C %d Max %d AGC dB %d\n", | ||
253 | rssi_a, rssi_b, rssi_c, max_rssi, agc); | ||
254 | |||
255 | /* dBm = max_rssi dB - agc dB - constant. | ||
256 | * Higher AGC (higher radio gain) means lower signal. */ | ||
257 | return max_rssi - agc - IWLAGN_RSSI_OFFSET; | ||
258 | } | ||
259 | |||
260 | struct iwl_hcmd_ops iwlagn_hcmd = { | ||
261 | .rxon_assoc = iwlagn_send_rxon_assoc, | ||
262 | .commit_rxon = iwl_commit_rxon, | ||
263 | .set_rxon_chain = iwl_set_rxon_chain, | ||
264 | .set_tx_ant = iwlagn_send_tx_ant_config, | ||
265 | }; | ||
266 | |||
267 | struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = { | ||
268 | .get_hcmd_size = iwlagn_get_hcmd_size, | ||
269 | .build_addsta_hcmd = iwlagn_build_addsta_hcmd, | ||
270 | .gain_computation = iwlagn_gain_computation, | ||
271 | .chain_noise_reset = iwlagn_chain_noise_reset, | ||
272 | .rts_tx_cmd_flag = iwlagn_rts_tx_cmd_flag, | ||
273 | .calc_rssi = iwlagn_calc_rssi, | ||
274 | }; | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h new file mode 100644 index 000000000000..f9a3fbb6338f --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h | |||
@@ -0,0 +1,118 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | * | ||
62 | *****************************************************************************/ | ||
63 | /* | ||
64 | * Please use this file (iwl-agn-hw.h) only for hardware-related definitions. | ||
65 | */ | ||
66 | |||
67 | #ifndef __iwl_agn_hw_h__ | ||
68 | #define __iwl_agn_hw_h__ | ||
69 | |||
70 | #define IWLAGN_RTC_INST_LOWER_BOUND (0x000000) | ||
71 | #define IWLAGN_RTC_INST_UPPER_BOUND (0x020000) | ||
72 | |||
73 | #define IWLAGN_RTC_DATA_LOWER_BOUND (0x800000) | ||
74 | #define IWLAGN_RTC_DATA_UPPER_BOUND (0x80C000) | ||
75 | |||
76 | #define IWLAGN_RTC_INST_SIZE (IWLAGN_RTC_INST_UPPER_BOUND - \ | ||
77 | IWLAGN_RTC_INST_LOWER_BOUND) | ||
78 | #define IWLAGN_RTC_DATA_SIZE (IWLAGN_RTC_DATA_UPPER_BOUND - \ | ||
79 | IWLAGN_RTC_DATA_LOWER_BOUND) | ||
80 | |||
81 | /* RSSI to dBm */ | ||
82 | #define IWLAGN_RSSI_OFFSET 44 | ||
83 | |||
84 | /* PCI registers */ | ||
85 | #define PCI_CFG_RETRY_TIMEOUT 0x041 | ||
86 | |||
87 | /* PCI register values */ | ||
88 | #define PCI_CFG_LINK_CTRL_VAL_L0S_EN 0x01 | ||
89 | #define PCI_CFG_LINK_CTRL_VAL_L1_EN 0x02 | ||
90 | |||
91 | #define IWLAGN_DEFAULT_TX_RETRY 15 | ||
92 | |||
93 | /* Limit range of txpower output target to be between these values */ | ||
94 | #define IWLAGN_TX_POWER_TARGET_POWER_MIN (0) /* 0 dBm: 1 milliwatt */ | ||
95 | #define IWLAGN_TX_POWER_TARGET_POWER_MAX (16) /* 16 dBm */ | ||
96 | |||
97 | /* EEPROM */ | ||
98 | #define IWLAGN_EEPROM_IMG_SIZE 2048 | ||
99 | |||
100 | #define IWLAGN_CMD_FIFO_NUM 7 | ||
101 | #define IWLAGN_NUM_QUEUES 20 | ||
102 | #define IWLAGN_NUM_AMPDU_QUEUES 10 | ||
103 | #define IWLAGN_FIRST_AMPDU_QUEUE 10 | ||
104 | |||
105 | /* Fixed (non-configurable) rx data from phy */ | ||
106 | |||
107 | /** | ||
108 | * struct iwlagn_schedq_bc_tbl scheduler byte count table | ||
109 | * base physical address provided by SCD_DRAM_BASE_ADDR | ||
110 | * @tfd_offset 0-12 - tx command byte count | ||
111 | * 12-16 - station index | ||
112 | */ | ||
113 | struct iwlagn_scd_bc_tbl { | ||
114 | __le16 tfd_offset[TFD_QUEUE_BC_SIZE]; | ||
115 | } __attribute__ ((packed)); | ||
116 | |||
117 | |||
118 | #endif /* __iwl_agn_hw_h__ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c new file mode 100644 index 000000000000..a273e373b7b0 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c | |||
@@ -0,0 +1,307 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * GPL LICENSE SUMMARY | ||
4 | * | ||
5 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of version 2 of the GNU General Public License as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
19 | * USA | ||
20 | * | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
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 | #include <linux/kernel.h> | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/etherdevice.h> | ||
32 | #include <linux/sched.h> | ||
33 | #include <net/mac80211.h> | ||
34 | |||
35 | #include "iwl-dev.h" | ||
36 | #include "iwl-core.h" | ||
37 | #include "iwl-agn.h" | ||
38 | #include "iwl-helpers.h" | ||
39 | |||
40 | #define ICT_COUNT (PAGE_SIZE/sizeof(u32)) | ||
41 | |||
42 | /* Free dram table */ | ||
43 | void iwl_free_isr_ict(struct iwl_priv *priv) | ||
44 | { | ||
45 | if (priv->_agn.ict_tbl_vir) { | ||
46 | dma_free_coherent(&priv->pci_dev->dev, | ||
47 | (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, | ||
48 | priv->_agn.ict_tbl_vir, | ||
49 | priv->_agn.ict_tbl_dma); | ||
50 | priv->_agn.ict_tbl_vir = NULL; | ||
51 | } | ||
52 | } | ||
53 | |||
54 | |||
55 | /* allocate dram shared table it is a PAGE_SIZE aligned | ||
56 | * also reset all data related to ICT table interrupt. | ||
57 | */ | ||
58 | int iwl_alloc_isr_ict(struct iwl_priv *priv) | ||
59 | { | ||
60 | |||
61 | if (priv->cfg->use_isr_legacy) | ||
62 | return 0; | ||
63 | /* allocate shrared data table */ | ||
64 | priv->_agn.ict_tbl_vir = | ||
65 | dma_alloc_coherent(&priv->pci_dev->dev, | ||
66 | (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, | ||
67 | &priv->_agn.ict_tbl_dma, GFP_KERNEL); | ||
68 | if (!priv->_agn.ict_tbl_vir) | ||
69 | return -ENOMEM; | ||
70 | |||
71 | /* align table to PAGE_SIZE boundry */ | ||
72 | priv->_agn.aligned_ict_tbl_dma = ALIGN(priv->_agn.ict_tbl_dma, PAGE_SIZE); | ||
73 | |||
74 | IWL_DEBUG_ISR(priv, "ict dma addr %Lx dma aligned %Lx diff %d\n", | ||
75 | (unsigned long long)priv->_agn.ict_tbl_dma, | ||
76 | (unsigned long long)priv->_agn.aligned_ict_tbl_dma, | ||
77 | (int)(priv->_agn.aligned_ict_tbl_dma - priv->_agn.ict_tbl_dma)); | ||
78 | |||
79 | priv->_agn.ict_tbl = priv->_agn.ict_tbl_vir + | ||
80 | (priv->_agn.aligned_ict_tbl_dma - priv->_agn.ict_tbl_dma); | ||
81 | |||
82 | IWL_DEBUG_ISR(priv, "ict vir addr %p vir aligned %p diff %d\n", | ||
83 | priv->_agn.ict_tbl, priv->_agn.ict_tbl_vir, | ||
84 | (int)(priv->_agn.aligned_ict_tbl_dma - priv->_agn.ict_tbl_dma)); | ||
85 | |||
86 | /* reset table and index to all 0 */ | ||
87 | memset(priv->_agn.ict_tbl_vir,0, (sizeof(u32) * ICT_COUNT) + PAGE_SIZE); | ||
88 | priv->_agn.ict_index = 0; | ||
89 | |||
90 | /* add periodic RX interrupt */ | ||
91 | priv->inta_mask |= CSR_INT_BIT_RX_PERIODIC; | ||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | /* Device is going up inform it about using ICT interrupt table, | ||
96 | * also we need to tell the driver to start using ICT interrupt. | ||
97 | */ | ||
98 | int iwl_reset_ict(struct iwl_priv *priv) | ||
99 | { | ||
100 | u32 val; | ||
101 | unsigned long flags; | ||
102 | |||
103 | if (!priv->_agn.ict_tbl_vir) | ||
104 | return 0; | ||
105 | |||
106 | spin_lock_irqsave(&priv->lock, flags); | ||
107 | iwl_disable_interrupts(priv); | ||
108 | |||
109 | memset(&priv->_agn.ict_tbl[0], 0, sizeof(u32) * ICT_COUNT); | ||
110 | |||
111 | val = priv->_agn.aligned_ict_tbl_dma >> PAGE_SHIFT; | ||
112 | |||
113 | val |= CSR_DRAM_INT_TBL_ENABLE; | ||
114 | val |= CSR_DRAM_INIT_TBL_WRAP_CHECK; | ||
115 | |||
116 | IWL_DEBUG_ISR(priv, "CSR_DRAM_INT_TBL_REG =0x%X " | ||
117 | "aligned dma address %Lx\n", | ||
118 | val, (unsigned long long)priv->_agn.aligned_ict_tbl_dma); | ||
119 | |||
120 | iwl_write32(priv, CSR_DRAM_INT_TBL_REG, val); | ||
121 | priv->_agn.use_ict = true; | ||
122 | priv->_agn.ict_index = 0; | ||
123 | iwl_write32(priv, CSR_INT, priv->inta_mask); | ||
124 | iwl_enable_interrupts(priv); | ||
125 | spin_unlock_irqrestore(&priv->lock, flags); | ||
126 | |||
127 | return 0; | ||
128 | } | ||
129 | |||
130 | /* Device is going down disable ict interrupt usage */ | ||
131 | void iwl_disable_ict(struct iwl_priv *priv) | ||
132 | { | ||
133 | unsigned long flags; | ||
134 | |||
135 | spin_lock_irqsave(&priv->lock, flags); | ||
136 | priv->_agn.use_ict = false; | ||
137 | spin_unlock_irqrestore(&priv->lock, flags); | ||
138 | } | ||
139 | |||
140 | static irqreturn_t iwl_isr(int irq, void *data) | ||
141 | { | ||
142 | struct iwl_priv *priv = data; | ||
143 | u32 inta, inta_mask; | ||
144 | unsigned long flags; | ||
145 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
146 | u32 inta_fh; | ||
147 | #endif | ||
148 | if (!priv) | ||
149 | return IRQ_NONE; | ||
150 | |||
151 | spin_lock_irqsave(&priv->lock, flags); | ||
152 | |||
153 | /* Disable (but don't clear!) interrupts here to avoid | ||
154 | * back-to-back ISRs and sporadic interrupts from our NIC. | ||
155 | * If we have something to service, the tasklet will re-enable ints. | ||
156 | * If we *don't* have something, we'll re-enable before leaving here. */ | ||
157 | inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */ | ||
158 | iwl_write32(priv, CSR_INT_MASK, 0x00000000); | ||
159 | |||
160 | /* Discover which interrupts are active/pending */ | ||
161 | inta = iwl_read32(priv, CSR_INT); | ||
162 | |||
163 | /* Ignore interrupt if there's nothing in NIC to service. | ||
164 | * This may be due to IRQ shared with another device, | ||
165 | * or due to sporadic interrupts thrown from our NIC. */ | ||
166 | if (!inta) { | ||
167 | IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n"); | ||
168 | goto none; | ||
169 | } | ||
170 | |||
171 | if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) { | ||
172 | /* Hardware disappeared. It might have already raised | ||
173 | * an interrupt */ | ||
174 | IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta); | ||
175 | goto unplugged; | ||
176 | } | ||
177 | |||
178 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
179 | if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) { | ||
180 | inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); | ||
181 | IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, " | ||
182 | "fh 0x%08x\n", inta, inta_mask, inta_fh); | ||
183 | } | ||
184 | #endif | ||
185 | |||
186 | priv->_agn.inta |= inta; | ||
187 | /* iwl_irq_tasklet() will service interrupts and re-enable them */ | ||
188 | if (likely(inta)) | ||
189 | tasklet_schedule(&priv->irq_tasklet); | ||
190 | else if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->_agn.inta) | ||
191 | iwl_enable_interrupts(priv); | ||
192 | |||
193 | unplugged: | ||
194 | spin_unlock_irqrestore(&priv->lock, flags); | ||
195 | return IRQ_HANDLED; | ||
196 | |||
197 | none: | ||
198 | /* re-enable interrupts here since we don't have anything to service. */ | ||
199 | /* only Re-enable if diabled by irq and no schedules tasklet. */ | ||
200 | if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->_agn.inta) | ||
201 | iwl_enable_interrupts(priv); | ||
202 | |||
203 | spin_unlock_irqrestore(&priv->lock, flags); | ||
204 | return IRQ_NONE; | ||
205 | } | ||
206 | |||
207 | /* interrupt handler using ict table, with this interrupt driver will | ||
208 | * stop using INTA register to get device's interrupt, reading this register | ||
209 | * is expensive, device will write interrupts in ICT dram table, increment | ||
210 | * index then will fire interrupt to driver, driver will OR all ICT table | ||
211 | * entries from current index up to table entry with 0 value. the result is | ||
212 | * the interrupt we need to service, driver will set the entries back to 0 and | ||
213 | * set index. | ||
214 | */ | ||
215 | irqreturn_t iwl_isr_ict(int irq, void *data) | ||
216 | { | ||
217 | struct iwl_priv *priv = data; | ||
218 | u32 inta, inta_mask; | ||
219 | u32 val = 0; | ||
220 | unsigned long flags; | ||
221 | |||
222 | if (!priv) | ||
223 | return IRQ_NONE; | ||
224 | |||
225 | /* dram interrupt table not set yet, | ||
226 | * use legacy interrupt. | ||
227 | */ | ||
228 | if (!priv->_agn.use_ict) | ||
229 | return iwl_isr(irq, data); | ||
230 | |||
231 | spin_lock_irqsave(&priv->lock, flags); | ||
232 | |||
233 | /* Disable (but don't clear!) interrupts here to avoid | ||
234 | * back-to-back ISRs and sporadic interrupts from our NIC. | ||
235 | * If we have something to service, the tasklet will re-enable ints. | ||
236 | * If we *don't* have something, we'll re-enable before leaving here. | ||
237 | */ | ||
238 | inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */ | ||
239 | iwl_write32(priv, CSR_INT_MASK, 0x00000000); | ||
240 | |||
241 | |||
242 | /* Ignore interrupt if there's nothing in NIC to service. | ||
243 | * This may be due to IRQ shared with another device, | ||
244 | * or due to sporadic interrupts thrown from our NIC. */ | ||
245 | if (!priv->_agn.ict_tbl[priv->_agn.ict_index]) { | ||
246 | IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n"); | ||
247 | goto none; | ||
248 | } | ||
249 | |||
250 | /* read all entries that not 0 start with ict_index */ | ||
251 | while (priv->_agn.ict_tbl[priv->_agn.ict_index]) { | ||
252 | |||
253 | val |= le32_to_cpu(priv->_agn.ict_tbl[priv->_agn.ict_index]); | ||
254 | IWL_DEBUG_ISR(priv, "ICT index %d value 0x%08X\n", | ||
255 | priv->_agn.ict_index, | ||
256 | le32_to_cpu(priv->_agn.ict_tbl[priv->_agn.ict_index])); | ||
257 | priv->_agn.ict_tbl[priv->_agn.ict_index] = 0; | ||
258 | priv->_agn.ict_index = iwl_queue_inc_wrap(priv->_agn.ict_index, | ||
259 | ICT_COUNT); | ||
260 | |||
261 | } | ||
262 | |||
263 | /* We should not get this value, just ignore it. */ | ||
264 | if (val == 0xffffffff) | ||
265 | val = 0; | ||
266 | |||
267 | /* | ||
268 | * this is a w/a for a h/w bug. the h/w bug may cause the Rx bit | ||
269 | * (bit 15 before shifting it to 31) to clear when using interrupt | ||
270 | * coalescing. fortunately, bits 18 and 19 stay set when this happens | ||
271 | * so we use them to decide on the real state of the Rx bit. | ||
272 | * In order words, bit 15 is set if bit 18 or bit 19 are set. | ||
273 | */ | ||
274 | if (val & 0xC0000) | ||
275 | val |= 0x8000; | ||
276 | |||
277 | inta = (0xff & val) | ((0xff00 & val) << 16); | ||
278 | IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n", | ||
279 | inta, inta_mask, val); | ||
280 | |||
281 | inta &= priv->inta_mask; | ||
282 | priv->_agn.inta |= inta; | ||
283 | |||
284 | /* iwl_irq_tasklet() will service interrupts and re-enable them */ | ||
285 | if (likely(inta)) | ||
286 | tasklet_schedule(&priv->irq_tasklet); | ||
287 | else if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->_agn.inta) { | ||
288 | /* Allow interrupt if was disabled by this handler and | ||
289 | * no tasklet was schedules, We should not enable interrupt, | ||
290 | * tasklet will enable it. | ||
291 | */ | ||
292 | iwl_enable_interrupts(priv); | ||
293 | } | ||
294 | |||
295 | spin_unlock_irqrestore(&priv->lock, flags); | ||
296 | return IRQ_HANDLED; | ||
297 | |||
298 | none: | ||
299 | /* re-enable interrupts here since we don't have anything to service. | ||
300 | * only Re-enable if disabled by irq. | ||
301 | */ | ||
302 | if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->_agn.inta) | ||
303 | iwl_enable_interrupts(priv); | ||
304 | |||
305 | spin_unlock_irqrestore(&priv->lock, flags); | ||
306 | return IRQ_NONE; | ||
307 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c new file mode 100644 index 000000000000..49e20f1acb7c --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c | |||
@@ -0,0 +1,1103 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * GPL LICENSE SUMMARY | ||
4 | * | ||
5 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of version 2 of the GNU General Public License as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
19 | * USA | ||
20 | * | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
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 | #include <linux/etherdevice.h> | ||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/sched.h> | ||
34 | |||
35 | #include "iwl-dev.h" | ||
36 | #include "iwl-core.h" | ||
37 | #include "iwl-io.h" | ||
38 | #include "iwl-helpers.h" | ||
39 | #include "iwl-agn-hw.h" | ||
40 | #include "iwl-agn.h" | ||
41 | |||
42 | static inline u32 iwlagn_get_scd_ssn(struct iwl5000_tx_resp *tx_resp) | ||
43 | { | ||
44 | return le32_to_cpup((__le32 *)&tx_resp->status + | ||
45 | tx_resp->frame_count) & MAX_SN; | ||
46 | } | ||
47 | |||
48 | static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv, | ||
49 | struct iwl_ht_agg *agg, | ||
50 | struct iwl5000_tx_resp *tx_resp, | ||
51 | int txq_id, u16 start_idx) | ||
52 | { | ||
53 | u16 status; | ||
54 | struct agg_tx_status *frame_status = &tx_resp->status; | ||
55 | struct ieee80211_tx_info *info = NULL; | ||
56 | struct ieee80211_hdr *hdr = NULL; | ||
57 | u32 rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags); | ||
58 | int i, sh, idx; | ||
59 | u16 seq; | ||
60 | |||
61 | if (agg->wait_for_ba) | ||
62 | IWL_DEBUG_TX_REPLY(priv, "got tx response w/o block-ack\n"); | ||
63 | |||
64 | agg->frame_count = tx_resp->frame_count; | ||
65 | agg->start_idx = start_idx; | ||
66 | agg->rate_n_flags = rate_n_flags; | ||
67 | agg->bitmap = 0; | ||
68 | |||
69 | /* # frames attempted by Tx command */ | ||
70 | if (agg->frame_count == 1) { | ||
71 | /* Only one frame was attempted; no block-ack will arrive */ | ||
72 | status = le16_to_cpu(frame_status[0].status); | ||
73 | idx = start_idx; | ||
74 | |||
75 | /* FIXME: code repetition */ | ||
76 | IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n", | ||
77 | agg->frame_count, agg->start_idx, idx); | ||
78 | |||
79 | info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); | ||
80 | info->status.rates[0].count = tx_resp->failure_frame + 1; | ||
81 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; | ||
82 | info->flags |= iwl_tx_status_to_mac80211(status); | ||
83 | iwlagn_hwrate_to_tx_control(priv, rate_n_flags, info); | ||
84 | |||
85 | /* FIXME: code repetition end */ | ||
86 | |||
87 | IWL_DEBUG_TX_REPLY(priv, "1 Frame 0x%x failure :%d\n", | ||
88 | status & 0xff, tx_resp->failure_frame); | ||
89 | IWL_DEBUG_TX_REPLY(priv, "Rate Info rate_n_flags=%x\n", rate_n_flags); | ||
90 | |||
91 | agg->wait_for_ba = 0; | ||
92 | } else { | ||
93 | /* Two or more frames were attempted; expect block-ack */ | ||
94 | u64 bitmap = 0; | ||
95 | int start = agg->start_idx; | ||
96 | |||
97 | /* Construct bit-map of pending frames within Tx window */ | ||
98 | for (i = 0; i < agg->frame_count; i++) { | ||
99 | u16 sc; | ||
100 | status = le16_to_cpu(frame_status[i].status); | ||
101 | seq = le16_to_cpu(frame_status[i].sequence); | ||
102 | idx = SEQ_TO_INDEX(seq); | ||
103 | txq_id = SEQ_TO_QUEUE(seq); | ||
104 | |||
105 | if (status & (AGG_TX_STATE_FEW_BYTES_MSK | | ||
106 | AGG_TX_STATE_ABORT_MSK)) | ||
107 | continue; | ||
108 | |||
109 | IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, txq_id=%d idx=%d\n", | ||
110 | agg->frame_count, txq_id, idx); | ||
111 | |||
112 | hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx); | ||
113 | if (!hdr) { | ||
114 | IWL_ERR(priv, | ||
115 | "BUG_ON idx doesn't point to valid skb" | ||
116 | " idx=%d, txq_id=%d\n", idx, txq_id); | ||
117 | return -1; | ||
118 | } | ||
119 | |||
120 | sc = le16_to_cpu(hdr->seq_ctrl); | ||
121 | if (idx != (SEQ_TO_SN(sc) & 0xff)) { | ||
122 | IWL_ERR(priv, | ||
123 | "BUG_ON idx doesn't match seq control" | ||
124 | " idx=%d, seq_idx=%d, seq=%d\n", | ||
125 | idx, SEQ_TO_SN(sc), | ||
126 | hdr->seq_ctrl); | ||
127 | return -1; | ||
128 | } | ||
129 | |||
130 | IWL_DEBUG_TX_REPLY(priv, "AGG Frame i=%d idx %d seq=%d\n", | ||
131 | i, idx, SEQ_TO_SN(sc)); | ||
132 | |||
133 | sh = idx - start; | ||
134 | if (sh > 64) { | ||
135 | sh = (start - idx) + 0xff; | ||
136 | bitmap = bitmap << sh; | ||
137 | sh = 0; | ||
138 | start = idx; | ||
139 | } else if (sh < -64) | ||
140 | sh = 0xff - (start - idx); | ||
141 | else if (sh < 0) { | ||
142 | sh = start - idx; | ||
143 | start = idx; | ||
144 | bitmap = bitmap << sh; | ||
145 | sh = 0; | ||
146 | } | ||
147 | bitmap |= 1ULL << sh; | ||
148 | IWL_DEBUG_TX_REPLY(priv, "start=%d bitmap=0x%llx\n", | ||
149 | start, (unsigned long long)bitmap); | ||
150 | } | ||
151 | |||
152 | agg->bitmap = bitmap; | ||
153 | agg->start_idx = start; | ||
154 | IWL_DEBUG_TX_REPLY(priv, "Frames %d start_idx=%d bitmap=0x%llx\n", | ||
155 | agg->frame_count, agg->start_idx, | ||
156 | (unsigned long long)agg->bitmap); | ||
157 | |||
158 | if (bitmap) | ||
159 | agg->wait_for_ba = 1; | ||
160 | } | ||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | static void iwlagn_rx_reply_tx(struct iwl_priv *priv, | ||
165 | struct iwl_rx_mem_buffer *rxb) | ||
166 | { | ||
167 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
168 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); | ||
169 | int txq_id = SEQ_TO_QUEUE(sequence); | ||
170 | int index = SEQ_TO_INDEX(sequence); | ||
171 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; | ||
172 | struct ieee80211_tx_info *info; | ||
173 | struct iwl5000_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; | ||
174 | u32 status = le16_to_cpu(tx_resp->status.status); | ||
175 | int tid; | ||
176 | int sta_id; | ||
177 | int freed; | ||
178 | |||
179 | if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) { | ||
180 | IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d " | ||
181 | "is out of range [0-%d] %d %d\n", txq_id, | ||
182 | index, txq->q.n_bd, txq->q.write_ptr, | ||
183 | txq->q.read_ptr); | ||
184 | return; | ||
185 | } | ||
186 | |||
187 | info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]); | ||
188 | memset(&info->status, 0, sizeof(info->status)); | ||
189 | |||
190 | tid = (tx_resp->ra_tid & IWL50_TX_RES_TID_MSK) >> IWL50_TX_RES_TID_POS; | ||
191 | sta_id = (tx_resp->ra_tid & IWL50_TX_RES_RA_MSK) >> IWL50_TX_RES_RA_POS; | ||
192 | |||
193 | if (txq->sched_retry) { | ||
194 | const u32 scd_ssn = iwlagn_get_scd_ssn(tx_resp); | ||
195 | struct iwl_ht_agg *agg = NULL; | ||
196 | |||
197 | agg = &priv->stations[sta_id].tid[tid].agg; | ||
198 | |||
199 | iwlagn_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index); | ||
200 | |||
201 | /* check if BAR is needed */ | ||
202 | if ((tx_resp->frame_count == 1) && !iwl_is_tx_success(status)) | ||
203 | info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; | ||
204 | |||
205 | if (txq->q.read_ptr != (scd_ssn & 0xff)) { | ||
206 | index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd); | ||
207 | IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim " | ||
208 | "scd_ssn=%d idx=%d txq=%d swq=%d\n", | ||
209 | scd_ssn , index, txq_id, txq->swq_id); | ||
210 | |||
211 | freed = iwlagn_tx_queue_reclaim(priv, txq_id, index); | ||
212 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); | ||
213 | |||
214 | if (priv->mac80211_registered && | ||
215 | (iwl_queue_space(&txq->q) > txq->q.low_mark) && | ||
216 | (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) { | ||
217 | if (agg->state == IWL_AGG_OFF) | ||
218 | iwl_wake_queue(priv, txq_id); | ||
219 | else | ||
220 | iwl_wake_queue(priv, txq->swq_id); | ||
221 | } | ||
222 | } | ||
223 | } else { | ||
224 | BUG_ON(txq_id != txq->swq_id); | ||
225 | |||
226 | info->status.rates[0].count = tx_resp->failure_frame + 1; | ||
227 | info->flags |= iwl_tx_status_to_mac80211(status); | ||
228 | iwlagn_hwrate_to_tx_control(priv, | ||
229 | le32_to_cpu(tx_resp->rate_n_flags), | ||
230 | info); | ||
231 | |||
232 | IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x) rate_n_flags " | ||
233 | "0x%x retries %d\n", | ||
234 | txq_id, | ||
235 | iwl_get_tx_fail_reason(status), status, | ||
236 | le32_to_cpu(tx_resp->rate_n_flags), | ||
237 | tx_resp->failure_frame); | ||
238 | |||
239 | freed = iwlagn_tx_queue_reclaim(priv, txq_id, index); | ||
240 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); | ||
241 | |||
242 | if (priv->mac80211_registered && | ||
243 | (iwl_queue_space(&txq->q) > txq->q.low_mark)) | ||
244 | iwl_wake_queue(priv, txq_id); | ||
245 | } | ||
246 | |||
247 | iwlagn_txq_check_empty(priv, sta_id, tid, txq_id); | ||
248 | |||
249 | if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) | ||
250 | IWL_ERR(priv, "TODO: Implement Tx ABORT REQUIRED!!!\n"); | ||
251 | } | ||
252 | |||
253 | void iwlagn_rx_handler_setup(struct iwl_priv *priv) | ||
254 | { | ||
255 | /* init calibration handlers */ | ||
256 | priv->rx_handlers[CALIBRATION_RES_NOTIFICATION] = | ||
257 | iwlagn_rx_calib_result; | ||
258 | priv->rx_handlers[CALIBRATION_COMPLETE_NOTIFICATION] = | ||
259 | iwlagn_rx_calib_complete; | ||
260 | priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx; | ||
261 | } | ||
262 | |||
263 | void iwlagn_setup_deferred_work(struct iwl_priv *priv) | ||
264 | { | ||
265 | /* in agn, the tx power calibration is done in uCode */ | ||
266 | priv->disable_tx_power_cal = 1; | ||
267 | } | ||
268 | |||
269 | int iwlagn_hw_valid_rtc_data_addr(u32 addr) | ||
270 | { | ||
271 | return (addr >= IWLAGN_RTC_DATA_LOWER_BOUND) && | ||
272 | (addr < IWLAGN_RTC_DATA_UPPER_BOUND); | ||
273 | } | ||
274 | |||
275 | int iwlagn_send_tx_power(struct iwl_priv *priv) | ||
276 | { | ||
277 | struct iwl5000_tx_power_dbm_cmd tx_power_cmd; | ||
278 | u8 tx_ant_cfg_cmd; | ||
279 | |||
280 | /* half dBm need to multiply */ | ||
281 | tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt); | ||
282 | |||
283 | if (priv->tx_power_lmt_in_half_dbm && | ||
284 | priv->tx_power_lmt_in_half_dbm < tx_power_cmd.global_lmt) { | ||
285 | /* | ||
286 | * For the newer devices which using enhanced/extend tx power | ||
287 | * table in EEPROM, the format is in half dBm. driver need to | ||
288 | * convert to dBm format before report to mac80211. | ||
289 | * By doing so, there is a possibility of 1/2 dBm resolution | ||
290 | * lost. driver will perform "round-up" operation before | ||
291 | * reporting, but it will cause 1/2 dBm tx power over the | ||
292 | * regulatory limit. Perform the checking here, if the | ||
293 | * "tx_power_user_lmt" is higher than EEPROM value (in | ||
294 | * half-dBm format), lower the tx power based on EEPROM | ||
295 | */ | ||
296 | tx_power_cmd.global_lmt = priv->tx_power_lmt_in_half_dbm; | ||
297 | } | ||
298 | tx_power_cmd.flags = IWL50_TX_POWER_NO_CLOSED; | ||
299 | tx_power_cmd.srv_chan_lmt = IWL50_TX_POWER_AUTO; | ||
300 | |||
301 | if (IWL_UCODE_API(priv->ucode_ver) == 1) | ||
302 | tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD_V1; | ||
303 | else | ||
304 | tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD; | ||
305 | |||
306 | return iwl_send_cmd_pdu_async(priv, tx_ant_cfg_cmd, | ||
307 | sizeof(tx_power_cmd), &tx_power_cmd, | ||
308 | NULL); | ||
309 | } | ||
310 | |||
311 | void iwlagn_temperature(struct iwl_priv *priv) | ||
312 | { | ||
313 | /* store temperature from statistics (in Celsius) */ | ||
314 | priv->temperature = le32_to_cpu(priv->statistics.general.temperature); | ||
315 | iwl_tt_handler(priv); | ||
316 | } | ||
317 | |||
318 | u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv) | ||
319 | { | ||
320 | struct iwl_eeprom_calib_hdr { | ||
321 | u8 version; | ||
322 | u8 pa_type; | ||
323 | u16 voltage; | ||
324 | } *hdr; | ||
325 | |||
326 | hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv, | ||
327 | EEPROM_5000_CALIB_ALL); | ||
328 | return hdr->version; | ||
329 | |||
330 | } | ||
331 | |||
332 | /* | ||
333 | * EEPROM | ||
334 | */ | ||
335 | static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address) | ||
336 | { | ||
337 | u16 offset = 0; | ||
338 | |||
339 | if ((address & INDIRECT_ADDRESS) == 0) | ||
340 | return address; | ||
341 | |||
342 | switch (address & INDIRECT_TYPE_MSK) { | ||
343 | case INDIRECT_HOST: | ||
344 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_HOST); | ||
345 | break; | ||
346 | case INDIRECT_GENERAL: | ||
347 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_GENERAL); | ||
348 | break; | ||
349 | case INDIRECT_REGULATORY: | ||
350 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_REGULATORY); | ||
351 | break; | ||
352 | case INDIRECT_CALIBRATION: | ||
353 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_CALIBRATION); | ||
354 | break; | ||
355 | case INDIRECT_PROCESS_ADJST: | ||
356 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_PROCESS_ADJST); | ||
357 | break; | ||
358 | case INDIRECT_OTHERS: | ||
359 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_OTHERS); | ||
360 | break; | ||
361 | default: | ||
362 | IWL_ERR(priv, "illegal indirect type: 0x%X\n", | ||
363 | address & INDIRECT_TYPE_MSK); | ||
364 | break; | ||
365 | } | ||
366 | |||
367 | /* translate the offset from words to byte */ | ||
368 | return (address & ADDRESS_MSK) + (offset << 1); | ||
369 | } | ||
370 | |||
371 | const u8 *iwlagn_eeprom_query_addr(const struct iwl_priv *priv, | ||
372 | size_t offset) | ||
373 | { | ||
374 | u32 address = eeprom_indirect_address(priv, offset); | ||
375 | BUG_ON(address >= priv->cfg->eeprom_size); | ||
376 | return &priv->eeprom[address]; | ||
377 | } | ||
378 | |||
379 | struct iwl_mod_params iwlagn_mod_params = { | ||
380 | .amsdu_size_8K = 1, | ||
381 | .restart_fw = 1, | ||
382 | /* the rest are 0 by default */ | ||
383 | }; | ||
384 | |||
385 | void iwlagn_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | ||
386 | { | ||
387 | unsigned long flags; | ||
388 | int i; | ||
389 | spin_lock_irqsave(&rxq->lock, flags); | ||
390 | INIT_LIST_HEAD(&rxq->rx_free); | ||
391 | INIT_LIST_HEAD(&rxq->rx_used); | ||
392 | /* Fill the rx_used queue with _all_ of the Rx buffers */ | ||
393 | for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) { | ||
394 | /* In the reset function, these buffers may have been allocated | ||
395 | * to an SKB, so we need to unmap and free potential storage */ | ||
396 | if (rxq->pool[i].page != NULL) { | ||
397 | pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma, | ||
398 | PAGE_SIZE << priv->hw_params.rx_page_order, | ||
399 | PCI_DMA_FROMDEVICE); | ||
400 | __iwl_free_pages(priv, rxq->pool[i].page); | ||
401 | rxq->pool[i].page = NULL; | ||
402 | } | ||
403 | list_add_tail(&rxq->pool[i].list, &rxq->rx_used); | ||
404 | } | ||
405 | |||
406 | for (i = 0; i < RX_QUEUE_SIZE; i++) | ||
407 | rxq->queue[i] = NULL; | ||
408 | |||
409 | /* Set us so that we have processed and used all buffers, but have | ||
410 | * not restocked the Rx queue with fresh buffers */ | ||
411 | rxq->read = rxq->write = 0; | ||
412 | rxq->write_actual = 0; | ||
413 | rxq->free_count = 0; | ||
414 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
415 | } | ||
416 | |||
417 | int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | ||
418 | { | ||
419 | u32 rb_size; | ||
420 | const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */ | ||
421 | u32 rb_timeout = 0; /* FIXME: RX_RB_TIMEOUT for all devices? */ | ||
422 | |||
423 | if (!priv->cfg->use_isr_legacy) | ||
424 | rb_timeout = RX_RB_TIMEOUT; | ||
425 | |||
426 | if (priv->cfg->mod_params->amsdu_size_8K) | ||
427 | rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K; | ||
428 | else | ||
429 | rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K; | ||
430 | |||
431 | /* Stop Rx DMA */ | ||
432 | iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); | ||
433 | |||
434 | /* Reset driver's Rx queue write index */ | ||
435 | iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0); | ||
436 | |||
437 | /* Tell device where to find RBD circular buffer in DRAM */ | ||
438 | iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG, | ||
439 | (u32)(rxq->dma_addr >> 8)); | ||
440 | |||
441 | /* Tell device where in DRAM to update its Rx status */ | ||
442 | iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG, | ||
443 | rxq->rb_stts_dma >> 4); | ||
444 | |||
445 | /* Enable Rx DMA | ||
446 | * FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY is set because of HW bug in | ||
447 | * the credit mechanism in 5000 HW RX FIFO | ||
448 | * Direct rx interrupts to hosts | ||
449 | * Rx buffer size 4 or 8k | ||
450 | * RB timeout 0x10 | ||
451 | * 256 RBDs | ||
452 | */ | ||
453 | iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, | ||
454 | FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | | ||
455 | FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY | | ||
456 | FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | | ||
457 | FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK | | ||
458 | rb_size| | ||
459 | (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)| | ||
460 | (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); | ||
461 | |||
462 | /* Set interrupt coalescing timer to default (2048 usecs) */ | ||
463 | iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); | ||
464 | |||
465 | return 0; | ||
466 | } | ||
467 | |||
468 | int iwlagn_hw_nic_init(struct iwl_priv *priv) | ||
469 | { | ||
470 | unsigned long flags; | ||
471 | struct iwl_rx_queue *rxq = &priv->rxq; | ||
472 | int ret; | ||
473 | |||
474 | /* nic_init */ | ||
475 | spin_lock_irqsave(&priv->lock, flags); | ||
476 | priv->cfg->ops->lib->apm_ops.init(priv); | ||
477 | |||
478 | /* Set interrupt coalescing calibration timer to default (512 usecs) */ | ||
479 | iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF); | ||
480 | |||
481 | spin_unlock_irqrestore(&priv->lock, flags); | ||
482 | |||
483 | ret = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN); | ||
484 | |||
485 | priv->cfg->ops->lib->apm_ops.config(priv); | ||
486 | |||
487 | /* Allocate the RX queue, or reset if it is already allocated */ | ||
488 | if (!rxq->bd) { | ||
489 | ret = iwl_rx_queue_alloc(priv); | ||
490 | if (ret) { | ||
491 | IWL_ERR(priv, "Unable to initialize Rx queue\n"); | ||
492 | return -ENOMEM; | ||
493 | } | ||
494 | } else | ||
495 | iwlagn_rx_queue_reset(priv, rxq); | ||
496 | |||
497 | iwlagn_rx_replenish(priv); | ||
498 | |||
499 | iwlagn_rx_init(priv, rxq); | ||
500 | |||
501 | spin_lock_irqsave(&priv->lock, flags); | ||
502 | |||
503 | rxq->need_update = 1; | ||
504 | iwl_rx_queue_update_write_ptr(priv, rxq); | ||
505 | |||
506 | spin_unlock_irqrestore(&priv->lock, flags); | ||
507 | |||
508 | /* Allocate and init all Tx and Command queues */ | ||
509 | ret = iwlagn_txq_ctx_reset(priv); | ||
510 | if (ret) | ||
511 | return ret; | ||
512 | |||
513 | set_bit(STATUS_INIT, &priv->status); | ||
514 | |||
515 | return 0; | ||
516 | } | ||
517 | |||
518 | /** | ||
519 | * iwlagn_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr | ||
520 | */ | ||
521 | static inline __le32 iwlagn_dma_addr2rbd_ptr(struct iwl_priv *priv, | ||
522 | dma_addr_t dma_addr) | ||
523 | { | ||
524 | return cpu_to_le32((u32)(dma_addr >> 8)); | ||
525 | } | ||
526 | |||
527 | /** | ||
528 | * iwlagn_rx_queue_restock - refill RX queue from pre-allocated pool | ||
529 | * | ||
530 | * If there are slots in the RX queue that need to be restocked, | ||
531 | * and we have free pre-allocated buffers, fill the ranks as much | ||
532 | * as we can, pulling from rx_free. | ||
533 | * | ||
534 | * This moves the 'write' index forward to catch up with 'processed', and | ||
535 | * also updates the memory address in the firmware to reference the new | ||
536 | * target buffer. | ||
537 | */ | ||
538 | void iwlagn_rx_queue_restock(struct iwl_priv *priv) | ||
539 | { | ||
540 | struct iwl_rx_queue *rxq = &priv->rxq; | ||
541 | struct list_head *element; | ||
542 | struct iwl_rx_mem_buffer *rxb; | ||
543 | unsigned long flags; | ||
544 | |||
545 | spin_lock_irqsave(&rxq->lock, flags); | ||
546 | while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) { | ||
547 | /* The overwritten rxb must be a used one */ | ||
548 | rxb = rxq->queue[rxq->write]; | ||
549 | BUG_ON(rxb && rxb->page); | ||
550 | |||
551 | /* Get next free Rx buffer, remove from free list */ | ||
552 | element = rxq->rx_free.next; | ||
553 | rxb = list_entry(element, struct iwl_rx_mem_buffer, list); | ||
554 | list_del(element); | ||
555 | |||
556 | /* Point to Rx buffer via next RBD in circular buffer */ | ||
557 | rxq->bd[rxq->write] = iwlagn_dma_addr2rbd_ptr(priv, | ||
558 | rxb->page_dma); | ||
559 | rxq->queue[rxq->write] = rxb; | ||
560 | rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; | ||
561 | rxq->free_count--; | ||
562 | } | ||
563 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
564 | /* If the pre-allocated buffer pool is dropping low, schedule to | ||
565 | * refill it */ | ||
566 | if (rxq->free_count <= RX_LOW_WATERMARK) | ||
567 | queue_work(priv->workqueue, &priv->rx_replenish); | ||
568 | |||
569 | |||
570 | /* If we've added more space for the firmware to place data, tell it. | ||
571 | * Increment device's write pointer in multiples of 8. */ | ||
572 | if (rxq->write_actual != (rxq->write & ~0x7)) { | ||
573 | spin_lock_irqsave(&rxq->lock, flags); | ||
574 | rxq->need_update = 1; | ||
575 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
576 | iwl_rx_queue_update_write_ptr(priv, rxq); | ||
577 | } | ||
578 | } | ||
579 | |||
580 | /** | ||
581 | * iwlagn_rx_replenish - Move all used packet from rx_used to rx_free | ||
582 | * | ||
583 | * When moving to rx_free an SKB is allocated for the slot. | ||
584 | * | ||
585 | * Also restock the Rx queue via iwl_rx_queue_restock. | ||
586 | * This is called as a scheduled work item (except for during initialization) | ||
587 | */ | ||
588 | void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority) | ||
589 | { | ||
590 | struct iwl_rx_queue *rxq = &priv->rxq; | ||
591 | struct list_head *element; | ||
592 | struct iwl_rx_mem_buffer *rxb; | ||
593 | struct page *page; | ||
594 | unsigned long flags; | ||
595 | gfp_t gfp_mask = priority; | ||
596 | |||
597 | while (1) { | ||
598 | spin_lock_irqsave(&rxq->lock, flags); | ||
599 | if (list_empty(&rxq->rx_used)) { | ||
600 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
601 | return; | ||
602 | } | ||
603 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
604 | |||
605 | if (rxq->free_count > RX_LOW_WATERMARK) | ||
606 | gfp_mask |= __GFP_NOWARN; | ||
607 | |||
608 | if (priv->hw_params.rx_page_order > 0) | ||
609 | gfp_mask |= __GFP_COMP; | ||
610 | |||
611 | /* Alloc a new receive buffer */ | ||
612 | page = alloc_pages(gfp_mask, priv->hw_params.rx_page_order); | ||
613 | if (!page) { | ||
614 | if (net_ratelimit()) | ||
615 | IWL_DEBUG_INFO(priv, "alloc_pages failed, " | ||
616 | "order: %d\n", | ||
617 | priv->hw_params.rx_page_order); | ||
618 | |||
619 | if ((rxq->free_count <= RX_LOW_WATERMARK) && | ||
620 | net_ratelimit()) | ||
621 | IWL_CRIT(priv, "Failed to alloc_pages with %s. Only %u free buffers remaining.\n", | ||
622 | priority == GFP_ATOMIC ? "GFP_ATOMIC" : "GFP_KERNEL", | ||
623 | rxq->free_count); | ||
624 | /* We don't reschedule replenish work here -- we will | ||
625 | * call the restock method and if it still needs | ||
626 | * more buffers it will schedule replenish */ | ||
627 | return; | ||
628 | } | ||
629 | |||
630 | spin_lock_irqsave(&rxq->lock, flags); | ||
631 | |||
632 | if (list_empty(&rxq->rx_used)) { | ||
633 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
634 | __free_pages(page, priv->hw_params.rx_page_order); | ||
635 | return; | ||
636 | } | ||
637 | element = rxq->rx_used.next; | ||
638 | rxb = list_entry(element, struct iwl_rx_mem_buffer, list); | ||
639 | list_del(element); | ||
640 | |||
641 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
642 | |||
643 | BUG_ON(rxb->page); | ||
644 | rxb->page = page; | ||
645 | /* Get physical address of the RB */ | ||
646 | rxb->page_dma = pci_map_page(priv->pci_dev, page, 0, | ||
647 | PAGE_SIZE << priv->hw_params.rx_page_order, | ||
648 | PCI_DMA_FROMDEVICE); | ||
649 | /* dma address must be no more than 36 bits */ | ||
650 | BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36)); | ||
651 | /* and also 256 byte aligned! */ | ||
652 | BUG_ON(rxb->page_dma & DMA_BIT_MASK(8)); | ||
653 | |||
654 | spin_lock_irqsave(&rxq->lock, flags); | ||
655 | |||
656 | list_add_tail(&rxb->list, &rxq->rx_free); | ||
657 | rxq->free_count++; | ||
658 | priv->alloc_rxb_page++; | ||
659 | |||
660 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
661 | } | ||
662 | } | ||
663 | |||
664 | void iwlagn_rx_replenish(struct iwl_priv *priv) | ||
665 | { | ||
666 | unsigned long flags; | ||
667 | |||
668 | iwlagn_rx_allocate(priv, GFP_KERNEL); | ||
669 | |||
670 | spin_lock_irqsave(&priv->lock, flags); | ||
671 | iwlagn_rx_queue_restock(priv); | ||
672 | spin_unlock_irqrestore(&priv->lock, flags); | ||
673 | } | ||
674 | |||
675 | void iwlagn_rx_replenish_now(struct iwl_priv *priv) | ||
676 | { | ||
677 | iwlagn_rx_allocate(priv, GFP_ATOMIC); | ||
678 | |||
679 | iwlagn_rx_queue_restock(priv); | ||
680 | } | ||
681 | |||
682 | /* Assumes that the skb field of the buffers in 'pool' is kept accurate. | ||
683 | * If an SKB has been detached, the POOL needs to have its SKB set to NULL | ||
684 | * This free routine walks the list of POOL entries and if SKB is set to | ||
685 | * non NULL it is unmapped and freed | ||
686 | */ | ||
687 | void iwlagn_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | ||
688 | { | ||
689 | int i; | ||
690 | for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) { | ||
691 | if (rxq->pool[i].page != NULL) { | ||
692 | pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma, | ||
693 | PAGE_SIZE << priv->hw_params.rx_page_order, | ||
694 | PCI_DMA_FROMDEVICE); | ||
695 | __iwl_free_pages(priv, rxq->pool[i].page); | ||
696 | rxq->pool[i].page = NULL; | ||
697 | } | ||
698 | } | ||
699 | |||
700 | dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, | ||
701 | rxq->dma_addr); | ||
702 | dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status), | ||
703 | rxq->rb_stts, rxq->rb_stts_dma); | ||
704 | rxq->bd = NULL; | ||
705 | rxq->rb_stts = NULL; | ||
706 | } | ||
707 | |||
708 | int iwlagn_rxq_stop(struct iwl_priv *priv) | ||
709 | { | ||
710 | |||
711 | /* stop Rx DMA */ | ||
712 | iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); | ||
713 | iwl_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG, | ||
714 | FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000); | ||
715 | |||
716 | return 0; | ||
717 | } | ||
718 | |||
719 | int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band) | ||
720 | { | ||
721 | int idx = 0; | ||
722 | int band_offset = 0; | ||
723 | |||
724 | /* HT rate format: mac80211 wants an MCS number, which is just LSB */ | ||
725 | if (rate_n_flags & RATE_MCS_HT_MSK) { | ||
726 | idx = (rate_n_flags & 0xff); | ||
727 | return idx; | ||
728 | /* Legacy rate format, search for match in table */ | ||
729 | } else { | ||
730 | if (band == IEEE80211_BAND_5GHZ) | ||
731 | band_offset = IWL_FIRST_OFDM_RATE; | ||
732 | for (idx = band_offset; idx < IWL_RATE_COUNT_LEGACY; idx++) | ||
733 | if (iwl_rates[idx].plcp == (rate_n_flags & 0xFF)) | ||
734 | return idx - band_offset; | ||
735 | } | ||
736 | |||
737 | return -1; | ||
738 | } | ||
739 | |||
740 | /* Calc max signal level (dBm) among 3 possible receivers */ | ||
741 | static inline int iwlagn_calc_rssi(struct iwl_priv *priv, | ||
742 | struct iwl_rx_phy_res *rx_resp) | ||
743 | { | ||
744 | return priv->cfg->ops->utils->calc_rssi(priv, rx_resp); | ||
745 | } | ||
746 | |||
747 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
748 | /** | ||
749 | * iwlagn_dbg_report_frame - dump frame to syslog during debug sessions | ||
750 | * | ||
751 | * You may hack this function to show different aspects of received frames, | ||
752 | * including selective frame dumps. | ||
753 | * group100 parameter selects whether to show 1 out of 100 good data frames. | ||
754 | * All beacon and probe response frames are printed. | ||
755 | */ | ||
756 | static void iwlagn_dbg_report_frame(struct iwl_priv *priv, | ||
757 | struct iwl_rx_phy_res *phy_res, u16 length, | ||
758 | struct ieee80211_hdr *header, int group100) | ||
759 | { | ||
760 | u32 to_us; | ||
761 | u32 print_summary = 0; | ||
762 | u32 print_dump = 0; /* set to 1 to dump all frames' contents */ | ||
763 | u32 hundred = 0; | ||
764 | u32 dataframe = 0; | ||
765 | __le16 fc; | ||
766 | u16 seq_ctl; | ||
767 | u16 channel; | ||
768 | u16 phy_flags; | ||
769 | u32 rate_n_flags; | ||
770 | u32 tsf_low; | ||
771 | int rssi; | ||
772 | |||
773 | if (likely(!(iwl_get_debug_level(priv) & IWL_DL_RX))) | ||
774 | return; | ||
775 | |||
776 | /* MAC header */ | ||
777 | fc = header->frame_control; | ||
778 | seq_ctl = le16_to_cpu(header->seq_ctrl); | ||
779 | |||
780 | /* metadata */ | ||
781 | channel = le16_to_cpu(phy_res->channel); | ||
782 | phy_flags = le16_to_cpu(phy_res->phy_flags); | ||
783 | rate_n_flags = le32_to_cpu(phy_res->rate_n_flags); | ||
784 | |||
785 | /* signal statistics */ | ||
786 | rssi = iwlagn_calc_rssi(priv, phy_res); | ||
787 | tsf_low = le64_to_cpu(phy_res->timestamp) & 0x0ffffffff; | ||
788 | |||
789 | to_us = !compare_ether_addr(header->addr1, priv->mac_addr); | ||
790 | |||
791 | /* if data frame is to us and all is good, | ||
792 | * (optionally) print summary for only 1 out of every 100 */ | ||
793 | if (to_us && (fc & ~cpu_to_le16(IEEE80211_FCTL_PROTECTED)) == | ||
794 | cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) { | ||
795 | dataframe = 1; | ||
796 | if (!group100) | ||
797 | print_summary = 1; /* print each frame */ | ||
798 | else if (priv->framecnt_to_us < 100) { | ||
799 | priv->framecnt_to_us++; | ||
800 | print_summary = 0; | ||
801 | } else { | ||
802 | priv->framecnt_to_us = 0; | ||
803 | print_summary = 1; | ||
804 | hundred = 1; | ||
805 | } | ||
806 | } else { | ||
807 | /* print summary for all other frames */ | ||
808 | print_summary = 1; | ||
809 | } | ||
810 | |||
811 | if (print_summary) { | ||
812 | char *title; | ||
813 | int rate_idx; | ||
814 | u32 bitrate; | ||
815 | |||
816 | if (hundred) | ||
817 | title = "100Frames"; | ||
818 | else if (ieee80211_has_retry(fc)) | ||
819 | title = "Retry"; | ||
820 | else if (ieee80211_is_assoc_resp(fc)) | ||
821 | title = "AscRsp"; | ||
822 | else if (ieee80211_is_reassoc_resp(fc)) | ||
823 | title = "RasRsp"; | ||
824 | else if (ieee80211_is_probe_resp(fc)) { | ||
825 | title = "PrbRsp"; | ||
826 | print_dump = 1; /* dump frame contents */ | ||
827 | } else if (ieee80211_is_beacon(fc)) { | ||
828 | title = "Beacon"; | ||
829 | print_dump = 1; /* dump frame contents */ | ||
830 | } else if (ieee80211_is_atim(fc)) | ||
831 | title = "ATIM"; | ||
832 | else if (ieee80211_is_auth(fc)) | ||
833 | title = "Auth"; | ||
834 | else if (ieee80211_is_deauth(fc)) | ||
835 | title = "DeAuth"; | ||
836 | else if (ieee80211_is_disassoc(fc)) | ||
837 | title = "DisAssoc"; | ||
838 | else | ||
839 | title = "Frame"; | ||
840 | |||
841 | rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags); | ||
842 | if (unlikely((rate_idx < 0) || (rate_idx >= IWL_RATE_COUNT))) { | ||
843 | bitrate = 0; | ||
844 | WARN_ON_ONCE(1); | ||
845 | } else { | ||
846 | bitrate = iwl_rates[rate_idx].ieee / 2; | ||
847 | } | ||
848 | |||
849 | /* print frame summary. | ||
850 | * MAC addresses show just the last byte (for brevity), | ||
851 | * but you can hack it to show more, if you'd like to. */ | ||
852 | if (dataframe) | ||
853 | IWL_DEBUG_RX(priv, "%s: mhd=0x%04x, dst=0x%02x, " | ||
854 | "len=%u, rssi=%d, chnl=%d, rate=%u,\n", | ||
855 | title, le16_to_cpu(fc), header->addr1[5], | ||
856 | length, rssi, channel, bitrate); | ||
857 | else { | ||
858 | /* src/dst addresses assume managed mode */ | ||
859 | IWL_DEBUG_RX(priv, "%s: 0x%04x, dst=0x%02x, src=0x%02x, " | ||
860 | "len=%u, rssi=%d, tim=%lu usec, " | ||
861 | "phy=0x%02x, chnl=%d\n", | ||
862 | title, le16_to_cpu(fc), header->addr1[5], | ||
863 | header->addr3[5], length, rssi, | ||
864 | tsf_low - priv->scan_start_tsf, | ||
865 | phy_flags, channel); | ||
866 | } | ||
867 | } | ||
868 | if (print_dump) | ||
869 | iwl_print_hex_dump(priv, IWL_DL_RX, header, length); | ||
870 | } | ||
871 | #endif | ||
872 | |||
873 | static u32 iwlagn_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in) | ||
874 | { | ||
875 | u32 decrypt_out = 0; | ||
876 | |||
877 | if ((decrypt_in & RX_RES_STATUS_STATION_FOUND) == | ||
878 | RX_RES_STATUS_STATION_FOUND) | ||
879 | decrypt_out |= (RX_RES_STATUS_STATION_FOUND | | ||
880 | RX_RES_STATUS_NO_STATION_INFO_MISMATCH); | ||
881 | |||
882 | decrypt_out |= (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK); | ||
883 | |||
884 | /* packet was not encrypted */ | ||
885 | if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) == | ||
886 | RX_RES_STATUS_SEC_TYPE_NONE) | ||
887 | return decrypt_out; | ||
888 | |||
889 | /* packet was encrypted with unknown alg */ | ||
890 | if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) == | ||
891 | RX_RES_STATUS_SEC_TYPE_ERR) | ||
892 | return decrypt_out; | ||
893 | |||
894 | /* decryption was not done in HW */ | ||
895 | if ((decrypt_in & RX_MPDU_RES_STATUS_DEC_DONE_MSK) != | ||
896 | RX_MPDU_RES_STATUS_DEC_DONE_MSK) | ||
897 | return decrypt_out; | ||
898 | |||
899 | switch (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) { | ||
900 | |||
901 | case RX_RES_STATUS_SEC_TYPE_CCMP: | ||
902 | /* alg is CCM: check MIC only */ | ||
903 | if (!(decrypt_in & RX_MPDU_RES_STATUS_MIC_OK)) | ||
904 | /* Bad MIC */ | ||
905 | decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; | ||
906 | else | ||
907 | decrypt_out |= RX_RES_STATUS_DECRYPT_OK; | ||
908 | |||
909 | break; | ||
910 | |||
911 | case RX_RES_STATUS_SEC_TYPE_TKIP: | ||
912 | if (!(decrypt_in & RX_MPDU_RES_STATUS_TTAK_OK)) { | ||
913 | /* Bad TTAK */ | ||
914 | decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK; | ||
915 | break; | ||
916 | } | ||
917 | /* fall through if TTAK OK */ | ||
918 | default: | ||
919 | if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK)) | ||
920 | decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; | ||
921 | else | ||
922 | decrypt_out |= RX_RES_STATUS_DECRYPT_OK; | ||
923 | break; | ||
924 | }; | ||
925 | |||
926 | IWL_DEBUG_RX(priv, "decrypt_in:0x%x decrypt_out = 0x%x\n", | ||
927 | decrypt_in, decrypt_out); | ||
928 | |||
929 | return decrypt_out; | ||
930 | } | ||
931 | |||
932 | static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv, | ||
933 | struct ieee80211_hdr *hdr, | ||
934 | u16 len, | ||
935 | u32 ampdu_status, | ||
936 | struct iwl_rx_mem_buffer *rxb, | ||
937 | struct ieee80211_rx_status *stats) | ||
938 | { | ||
939 | struct sk_buff *skb; | ||
940 | __le16 fc = hdr->frame_control; | ||
941 | |||
942 | /* We only process data packets if the interface is open */ | ||
943 | if (unlikely(!priv->is_open)) { | ||
944 | IWL_DEBUG_DROP_LIMIT(priv, | ||
945 | "Dropping packet while interface is not open.\n"); | ||
946 | return; | ||
947 | } | ||
948 | |||
949 | /* In case of HW accelerated crypto and bad decryption, drop */ | ||
950 | if (!priv->cfg->mod_params->sw_crypto && | ||
951 | iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats)) | ||
952 | return; | ||
953 | |||
954 | skb = dev_alloc_skb(128); | ||
955 | if (!skb) { | ||
956 | IWL_ERR(priv, "dev_alloc_skb failed\n"); | ||
957 | return; | ||
958 | } | ||
959 | |||
960 | skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len); | ||
961 | |||
962 | iwl_update_stats(priv, false, fc, len); | ||
963 | memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); | ||
964 | |||
965 | ieee80211_rx(priv->hw, skb); | ||
966 | priv->alloc_rxb_page--; | ||
967 | rxb->page = NULL; | ||
968 | } | ||
969 | |||
970 | /* Called for REPLY_RX (legacy ABG frames), or | ||
971 | * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */ | ||
972 | void iwlagn_rx_reply_rx(struct iwl_priv *priv, | ||
973 | struct iwl_rx_mem_buffer *rxb) | ||
974 | { | ||
975 | struct ieee80211_hdr *header; | ||
976 | struct ieee80211_rx_status rx_status; | ||
977 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
978 | struct iwl_rx_phy_res *phy_res; | ||
979 | __le32 rx_pkt_status; | ||
980 | struct iwl4965_rx_mpdu_res_start *amsdu; | ||
981 | u32 len; | ||
982 | u32 ampdu_status; | ||
983 | u32 rate_n_flags; | ||
984 | |||
985 | /** | ||
986 | * REPLY_RX and REPLY_RX_MPDU_CMD are handled differently. | ||
987 | * REPLY_RX: physical layer info is in this buffer | ||
988 | * REPLY_RX_MPDU_CMD: physical layer info was sent in separate | ||
989 | * command and cached in priv->last_phy_res | ||
990 | * | ||
991 | * Here we set up local variables depending on which command is | ||
992 | * received. | ||
993 | */ | ||
994 | if (pkt->hdr.cmd == REPLY_RX) { | ||
995 | phy_res = (struct iwl_rx_phy_res *)pkt->u.raw; | ||
996 | header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*phy_res) | ||
997 | + phy_res->cfg_phy_cnt); | ||
998 | |||
999 | len = le16_to_cpu(phy_res->byte_count); | ||
1000 | rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*phy_res) + | ||
1001 | phy_res->cfg_phy_cnt + len); | ||
1002 | ampdu_status = le32_to_cpu(rx_pkt_status); | ||
1003 | } else { | ||
1004 | if (!priv->last_phy_res[0]) { | ||
1005 | IWL_ERR(priv, "MPDU frame without cached PHY data\n"); | ||
1006 | return; | ||
1007 | } | ||
1008 | phy_res = (struct iwl_rx_phy_res *)&priv->last_phy_res[1]; | ||
1009 | amsdu = (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw; | ||
1010 | header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu)); | ||
1011 | len = le16_to_cpu(amsdu->byte_count); | ||
1012 | rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*amsdu) + len); | ||
1013 | ampdu_status = iwlagn_translate_rx_status(priv, | ||
1014 | le32_to_cpu(rx_pkt_status)); | ||
1015 | } | ||
1016 | |||
1017 | if ((unlikely(phy_res->cfg_phy_cnt > 20))) { | ||
1018 | IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n", | ||
1019 | phy_res->cfg_phy_cnt); | ||
1020 | return; | ||
1021 | } | ||
1022 | |||
1023 | if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) || | ||
1024 | !(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) { | ||
1025 | IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n", | ||
1026 | le32_to_cpu(rx_pkt_status)); | ||
1027 | return; | ||
1028 | } | ||
1029 | |||
1030 | /* This will be used in several places later */ | ||
1031 | rate_n_flags = le32_to_cpu(phy_res->rate_n_flags); | ||
1032 | |||
1033 | /* rx_status carries information about the packet to mac80211 */ | ||
1034 | rx_status.mactime = le64_to_cpu(phy_res->timestamp); | ||
1035 | rx_status.freq = | ||
1036 | ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel)); | ||
1037 | rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? | ||
1038 | IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; | ||
1039 | rx_status.rate_idx = | ||
1040 | iwlagn_hwrate_to_mac80211_idx(rate_n_flags, rx_status.band); | ||
1041 | rx_status.flag = 0; | ||
1042 | |||
1043 | /* TSF isn't reliable. In order to allow smooth user experience, | ||
1044 | * this W/A doesn't propagate it to the mac80211 */ | ||
1045 | /*rx_status.flag |= RX_FLAG_TSFT;*/ | ||
1046 | |||
1047 | priv->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp); | ||
1048 | |||
1049 | /* Find max signal strength (dBm) among 3 antenna/receiver chains */ | ||
1050 | rx_status.signal = iwlagn_calc_rssi(priv, phy_res); | ||
1051 | |||
1052 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1053 | /* Set "1" to report good data frames in groups of 100 */ | ||
1054 | if (unlikely(iwl_get_debug_level(priv) & IWL_DL_RX)) | ||
1055 | iwlagn_dbg_report_frame(priv, phy_res, len, header, 1); | ||
1056 | #endif | ||
1057 | iwl_dbg_log_rx_data_frame(priv, len, header); | ||
1058 | IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, TSF %llu\n", | ||
1059 | rx_status.signal, (unsigned long long)rx_status.mactime); | ||
1060 | |||
1061 | /* | ||
1062 | * "antenna number" | ||
1063 | * | ||
1064 | * It seems that the antenna field in the phy flags value | ||
1065 | * is actually a bit field. This is undefined by radiotap, | ||
1066 | * it wants an actual antenna number but I always get "7" | ||
1067 | * for most legacy frames I receive indicating that the | ||
1068 | * same frame was received on all three RX chains. | ||
1069 | * | ||
1070 | * I think this field should be removed in favor of a | ||
1071 | * new 802.11n radiotap field "RX chains" that is defined | ||
1072 | * as a bitmask. | ||
1073 | */ | ||
1074 | rx_status.antenna = | ||
1075 | (le16_to_cpu(phy_res->phy_flags) & RX_RES_PHY_FLAGS_ANTENNA_MSK) | ||
1076 | >> RX_RES_PHY_FLAGS_ANTENNA_POS; | ||
1077 | |||
1078 | /* set the preamble flag if appropriate */ | ||
1079 | if (phy_res->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK) | ||
1080 | rx_status.flag |= RX_FLAG_SHORTPRE; | ||
1081 | |||
1082 | /* Set up the HT phy flags */ | ||
1083 | if (rate_n_flags & RATE_MCS_HT_MSK) | ||
1084 | rx_status.flag |= RX_FLAG_HT; | ||
1085 | if (rate_n_flags & RATE_MCS_HT40_MSK) | ||
1086 | rx_status.flag |= RX_FLAG_40MHZ; | ||
1087 | if (rate_n_flags & RATE_MCS_SGI_MSK) | ||
1088 | rx_status.flag |= RX_FLAG_SHORT_GI; | ||
1089 | |||
1090 | iwlagn_pass_packet_to_mac80211(priv, header, len, ampdu_status, | ||
1091 | rxb, &rx_status); | ||
1092 | } | ||
1093 | |||
1094 | /* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD). | ||
1095 | * This will be used later in iwl_rx_reply_rx() for REPLY_RX_MPDU_CMD. */ | ||
1096 | void iwlagn_rx_reply_rx_phy(struct iwl_priv *priv, | ||
1097 | struct iwl_rx_mem_buffer *rxb) | ||
1098 | { | ||
1099 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
1100 | priv->last_phy_res[0] = 1; | ||
1101 | memcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]), | ||
1102 | sizeof(struct iwl_rx_phy_res)); | ||
1103 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index be00cb3b1d0e..0c3c76803c5e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |||
@@ -610,10 +610,6 @@ static u16 rs_get_supported_rates(struct iwl_lq_sta *lq_sta, | |||
610 | struct ieee80211_hdr *hdr, | 610 | struct ieee80211_hdr *hdr, |
611 | enum iwl_table_type rate_type) | 611 | enum iwl_table_type rate_type) |
612 | { | 612 | { |
613 | if (hdr && is_multicast_ether_addr(hdr->addr1) && | ||
614 | lq_sta->active_rate_basic) | ||
615 | return lq_sta->active_rate_basic; | ||
616 | |||
617 | if (is_legacy(rate_type)) { | 613 | if (is_legacy(rate_type)) { |
618 | return lq_sta->active_legacy_rate; | 614 | return lq_sta->active_legacy_rate; |
619 | } else { | 615 | } else { |
@@ -774,6 +770,15 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
774 | 770 | ||
775 | IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n"); | 771 | IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n"); |
776 | 772 | ||
773 | /* Treat uninitialized rate scaling data same as non-existing. */ | ||
774 | if (!lq_sta) { | ||
775 | IWL_DEBUG_RATE(priv, "Station rate scaling not created yet.\n"); | ||
776 | return; | ||
777 | } else if (!lq_sta->drv) { | ||
778 | IWL_DEBUG_RATE(priv, "Rate scaling not initialized yet.\n"); | ||
779 | return; | ||
780 | } | ||
781 | |||
777 | if (!ieee80211_is_data(hdr->frame_control) || | 782 | if (!ieee80211_is_data(hdr->frame_control) || |
778 | info->flags & IEEE80211_TX_CTL_NO_ACK) | 783 | info->flags & IEEE80211_TX_CTL_NO_ACK) |
779 | return; | 784 | return; |
@@ -783,10 +788,6 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
783 | !(info->flags & IEEE80211_TX_STAT_AMPDU)) | 788 | !(info->flags & IEEE80211_TX_STAT_AMPDU)) |
784 | return; | 789 | return; |
785 | 790 | ||
786 | if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && | ||
787 | !lq_sta->ibss_sta_added) | ||
788 | return; | ||
789 | |||
790 | /* | 791 | /* |
791 | * Ignore this Tx frame response if its initial rate doesn't match | 792 | * Ignore this Tx frame response if its initial rate doesn't match |
792 | * that of latest Link Quality command. There may be stragglers | 793 | * that of latest Link Quality command. There may be stragglers |
@@ -832,7 +833,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
832 | lq_sta->missed_rate_counter++; | 833 | lq_sta->missed_rate_counter++; |
833 | if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) { | 834 | if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) { |
834 | lq_sta->missed_rate_counter = 0; | 835 | lq_sta->missed_rate_counter = 0; |
835 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); | 836 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC, false); |
836 | } | 837 | } |
837 | /* Regardless, ignore this status info for outdated rate */ | 838 | /* Regardless, ignore this status info for outdated rate */ |
838 | return; | 839 | return; |
@@ -1912,7 +1913,7 @@ static u32 rs_update_rate_tbl(struct iwl_priv *priv, | |||
1912 | /* Update uCode's rate table. */ | 1913 | /* Update uCode's rate table. */ |
1913 | rate = rate_n_flags_from_tbl(priv, tbl, index, is_green); | 1914 | rate = rate_n_flags_from_tbl(priv, tbl, index, is_green); |
1914 | rs_fill_link_cmd(priv, lq_sta, rate); | 1915 | rs_fill_link_cmd(priv, lq_sta, rate); |
1915 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); | 1916 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC, false); |
1916 | 1917 | ||
1917 | return rate; | 1918 | return rate; |
1918 | } | 1919 | } |
@@ -2001,7 +2002,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, | |||
2001 | /* rates available for this association, and for modulation mode */ | 2002 | /* rates available for this association, and for modulation mode */ |
2002 | rate_mask = rs_get_supported_rates(lq_sta, hdr, tbl->lq_type); | 2003 | rate_mask = rs_get_supported_rates(lq_sta, hdr, tbl->lq_type); |
2003 | 2004 | ||
2004 | IWL_DEBUG_RATE(priv, "mask 0x%04X \n", rate_mask); | 2005 | IWL_DEBUG_RATE(priv, "mask 0x%04X\n", rate_mask); |
2005 | 2006 | ||
2006 | /* mask with station rate restriction */ | 2007 | /* mask with station rate restriction */ |
2007 | if (is_legacy(tbl->lq_type)) { | 2008 | if (is_legacy(tbl->lq_type)) { |
@@ -2288,7 +2289,7 @@ lq_update: | |||
2288 | IWL_DEBUG_RATE(priv, "Switch current mcs: %X index: %d\n", | 2289 | IWL_DEBUG_RATE(priv, "Switch current mcs: %X index: %d\n", |
2289 | tbl->current_rate, index); | 2290 | tbl->current_rate, index); |
2290 | rs_fill_link_cmd(priv, lq_sta, tbl->current_rate); | 2291 | rs_fill_link_cmd(priv, lq_sta, tbl->current_rate); |
2291 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); | 2292 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC, false); |
2292 | } else | 2293 | } else |
2293 | done_search = 1; | 2294 | done_search = 1; |
2294 | } | 2295 | } |
@@ -2337,7 +2338,20 @@ out: | |||
2337 | return; | 2338 | return; |
2338 | } | 2339 | } |
2339 | 2340 | ||
2340 | 2341 | /** | |
2342 | * rs_initialize_lq - Initialize a station's hardware rate table | ||
2343 | * | ||
2344 | * The uCode's station table contains a table of fallback rates | ||
2345 | * for automatic fallback during transmission. | ||
2346 | * | ||
2347 | * NOTE: This sets up a default set of values. These will be replaced later | ||
2348 | * if the driver's iwl-agn-rs rate scaling algorithm is used, instead of | ||
2349 | * rc80211_simple. | ||
2350 | * | ||
2351 | * NOTE: Run REPLY_ADD_STA command to set up station table entry, before | ||
2352 | * calling this function (which runs REPLY_TX_LINK_QUALITY_CMD, | ||
2353 | * which requires station table entry to exist). | ||
2354 | */ | ||
2341 | static void rs_initialize_lq(struct iwl_priv *priv, | 2355 | static void rs_initialize_lq(struct iwl_priv *priv, |
2342 | struct ieee80211_conf *conf, | 2356 | struct ieee80211_conf *conf, |
2343 | struct ieee80211_sta *sta, | 2357 | struct ieee80211_sta *sta, |
@@ -2356,10 +2370,6 @@ static void rs_initialize_lq(struct iwl_priv *priv, | |||
2356 | 2370 | ||
2357 | i = lq_sta->last_txrate_idx; | 2371 | i = lq_sta->last_txrate_idx; |
2358 | 2372 | ||
2359 | if ((lq_sta->lq.sta_id == 0xff) && | ||
2360 | (priv->iw_mode == NL80211_IFTYPE_ADHOC)) | ||
2361 | goto out; | ||
2362 | |||
2363 | valid_tx_ant = priv->hw_params.valid_tx_ant; | 2373 | valid_tx_ant = priv->hw_params.valid_tx_ant; |
2364 | 2374 | ||
2365 | if (!lq_sta->search_better_tbl) | 2375 | if (!lq_sta->search_better_tbl) |
@@ -2387,7 +2397,8 @@ static void rs_initialize_lq(struct iwl_priv *priv, | |||
2387 | tbl->current_rate = rate; | 2397 | tbl->current_rate = rate; |
2388 | rs_set_expected_tpt_table(lq_sta, tbl); | 2398 | rs_set_expected_tpt_table(lq_sta, tbl); |
2389 | rs_fill_link_cmd(NULL, lq_sta, rate); | 2399 | rs_fill_link_cmd(NULL, lq_sta, rate); |
2390 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); | 2400 | priv->stations[lq_sta->lq.sta_id].lq = &lq_sta->lq; |
2401 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_SYNC, true); | ||
2391 | out: | 2402 | out: |
2392 | return; | 2403 | return; |
2393 | } | 2404 | } |
@@ -2399,9 +2410,6 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, | |||
2399 | struct sk_buff *skb = txrc->skb; | 2410 | struct sk_buff *skb = txrc->skb; |
2400 | struct ieee80211_supported_band *sband = txrc->sband; | 2411 | struct ieee80211_supported_band *sband = txrc->sband; |
2401 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; | 2412 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; |
2402 | struct ieee80211_conf *conf = &priv->hw->conf; | ||
2403 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; | ||
2404 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
2405 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 2413 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
2406 | struct iwl_lq_sta *lq_sta = priv_sta; | 2414 | struct iwl_lq_sta *lq_sta = priv_sta; |
2407 | int rate_idx; | 2415 | int rate_idx; |
@@ -2419,30 +2427,18 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, | |||
2419 | lq_sta->max_rate_idx = -1; | 2427 | lq_sta->max_rate_idx = -1; |
2420 | } | 2428 | } |
2421 | 2429 | ||
2430 | /* Treat uninitialized rate scaling data same as non-existing. */ | ||
2431 | if (lq_sta && !lq_sta->drv) { | ||
2432 | IWL_DEBUG_RATE(priv, "Rate scaling not initialized yet.\n"); | ||
2433 | priv_sta = NULL; | ||
2434 | } | ||
2435 | |||
2422 | /* Send management frames and NO_ACK data using lowest rate. */ | 2436 | /* Send management frames and NO_ACK data using lowest rate. */ |
2423 | if (rate_control_send_low(sta, priv_sta, txrc)) | 2437 | if (rate_control_send_low(sta, priv_sta, txrc)) |
2424 | return; | 2438 | return; |
2425 | 2439 | ||
2426 | rate_idx = lq_sta->last_txrate_idx; | 2440 | rate_idx = lq_sta->last_txrate_idx; |
2427 | 2441 | ||
2428 | if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && | ||
2429 | !lq_sta->ibss_sta_added) { | ||
2430 | u8 sta_id = iwl_find_station(priv, hdr->addr1); | ||
2431 | |||
2432 | if (sta_id == IWL_INVALID_STATION) { | ||
2433 | IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", | ||
2434 | hdr->addr1); | ||
2435 | sta_id = iwl_add_station(priv, hdr->addr1, | ||
2436 | false, CMD_ASYNC, ht_cap); | ||
2437 | } | ||
2438 | if ((sta_id != IWL_INVALID_STATION)) { | ||
2439 | lq_sta->lq.sta_id = sta_id; | ||
2440 | lq_sta->lq.rs_table[0].rate_n_flags = 0; | ||
2441 | lq_sta->ibss_sta_added = 1; | ||
2442 | rs_initialize_lq(priv, conf, sta, lq_sta); | ||
2443 | } | ||
2444 | } | ||
2445 | |||
2446 | if (lq_sta->last_rate_n_flags & RATE_MCS_HT_MSK) { | 2442 | if (lq_sta->last_rate_n_flags & RATE_MCS_HT_MSK) { |
2447 | rate_idx -= IWL_FIRST_OFDM_RATE; | 2443 | rate_idx -= IWL_FIRST_OFDM_RATE; |
2448 | /* 6M and 9M shared same MCS index */ | 2444 | /* 6M and 9M shared same MCS index */ |
@@ -2492,16 +2488,25 @@ static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta, | |||
2492 | return lq_sta; | 2488 | return lq_sta; |
2493 | } | 2489 | } |
2494 | 2490 | ||
2495 | static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, | 2491 | /* |
2496 | struct ieee80211_sta *sta, void *priv_sta) | 2492 | * Called after adding a new station to initialize rate scaling |
2493 | */ | ||
2494 | void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_id) | ||
2497 | { | 2495 | { |
2498 | int i, j; | 2496 | int i, j; |
2499 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; | 2497 | struct ieee80211_hw *hw = priv->hw; |
2500 | struct ieee80211_conf *conf = &priv->hw->conf; | 2498 | struct ieee80211_conf *conf = &priv->hw->conf; |
2501 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; | 2499 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; |
2502 | struct iwl_lq_sta *lq_sta = priv_sta; | 2500 | struct iwl_station_priv *sta_priv; |
2501 | struct iwl_lq_sta *lq_sta; | ||
2502 | struct ieee80211_supported_band *sband; | ||
2503 | |||
2504 | sta_priv = (struct iwl_station_priv *) sta->drv_priv; | ||
2505 | lq_sta = &sta_priv->lq_sta; | ||
2506 | sband = hw->wiphy->bands[conf->channel->band]; | ||
2507 | |||
2503 | 2508 | ||
2504 | lq_sta->lq.sta_id = 0xff; | 2509 | lq_sta->lq.sta_id = sta_id; |
2505 | 2510 | ||
2506 | for (j = 0; j < LQ_SIZE; j++) | 2511 | for (j = 0; j < LQ_SIZE; j++) |
2507 | for (i = 0; i < IWL_RATE_COUNT; i++) | 2512 | for (i = 0; i < IWL_RATE_COUNT; i++) |
@@ -2513,39 +2518,18 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, | |||
2513 | for (i = 0; i < IWL_RATE_COUNT; i++) | 2518 | for (i = 0; i < IWL_RATE_COUNT; i++) |
2514 | rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]); | 2519 | rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]); |
2515 | 2520 | ||
2516 | IWL_DEBUG_RATE(priv, "LQ: *** rate scale station global init ***\n"); | 2521 | IWL_DEBUG_RATE(priv, "LQ: *** rate scale station global init for station %d ***\n", |
2522 | sta_id); | ||
2517 | /* TODO: what is a good starting rate for STA? About middle? Maybe not | 2523 | /* TODO: what is a good starting rate for STA? About middle? Maybe not |
2518 | * the lowest or the highest rate.. Could consider using RSSI from | 2524 | * the lowest or the highest rate.. Could consider using RSSI from |
2519 | * previous packets? Need to have IEEE 802.1X auth succeed immediately | 2525 | * previous packets? Need to have IEEE 802.1X auth succeed immediately |
2520 | * after assoc.. */ | 2526 | * after assoc.. */ |
2521 | 2527 | ||
2522 | lq_sta->ibss_sta_added = 0; | ||
2523 | if (priv->iw_mode == NL80211_IFTYPE_AP) { | ||
2524 | u8 sta_id = iwl_find_station(priv, | ||
2525 | sta->addr); | ||
2526 | |||
2527 | /* for IBSS the call are from tasklet */ | ||
2528 | IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", sta->addr); | ||
2529 | |||
2530 | if (sta_id == IWL_INVALID_STATION) { | ||
2531 | IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", sta->addr); | ||
2532 | sta_id = iwl_add_station(priv, sta->addr, false, | ||
2533 | CMD_ASYNC, ht_cap); | ||
2534 | } | ||
2535 | if ((sta_id != IWL_INVALID_STATION)) { | ||
2536 | lq_sta->lq.sta_id = sta_id; | ||
2537 | lq_sta->lq.rs_table[0].rate_n_flags = 0; | ||
2538 | } | ||
2539 | /* FIXME: this is w/a remove it later */ | ||
2540 | priv->assoc_station_added = 1; | ||
2541 | } | ||
2542 | |||
2543 | lq_sta->is_dup = 0; | 2528 | lq_sta->is_dup = 0; |
2544 | lq_sta->max_rate_idx = -1; | 2529 | lq_sta->max_rate_idx = -1; |
2545 | lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX; | 2530 | lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX; |
2546 | lq_sta->is_green = rs_use_green(sta, &priv->current_ht_config); | 2531 | lq_sta->is_green = rs_use_green(sta, &priv->current_ht_config); |
2547 | lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000); | 2532 | lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000); |
2548 | lq_sta->active_rate_basic = priv->active_rate_basic; | ||
2549 | lq_sta->band = priv->band; | 2533 | lq_sta->band = priv->band; |
2550 | /* | 2534 | /* |
2551 | * active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3), | 2535 | * active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3), |
@@ -2793,7 +2777,7 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file, | |||
2793 | 2777 | ||
2794 | if (lq_sta->dbg_fixed_rate) { | 2778 | if (lq_sta->dbg_fixed_rate) { |
2795 | rs_fill_link_cmd(NULL, lq_sta, lq_sta->dbg_fixed_rate); | 2779 | rs_fill_link_cmd(NULL, lq_sta, lq_sta->dbg_fixed_rate); |
2796 | iwl_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC); | 2780 | iwl_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC, false); |
2797 | } | 2781 | } |
2798 | 2782 | ||
2799 | return count; | 2783 | return count; |
@@ -2949,12 +2933,6 @@ static ssize_t rs_sta_dbgfs_rate_scale_data_read(struct file *file, | |||
2949 | desc += sprintf(buff+desc, | 2933 | desc += sprintf(buff+desc, |
2950 | "Bit Rate= %d Mb/s\n", | 2934 | "Bit Rate= %d Mb/s\n", |
2951 | iwl_rates[lq_sta->last_txrate_idx].ieee >> 1); | 2935 | iwl_rates[lq_sta->last_txrate_idx].ieee >> 1); |
2952 | desc += sprintf(buff+desc, | ||
2953 | "Signal Level= %d dBm\tNoise Level= %d dBm\n", | ||
2954 | priv->last_rx_rssi, priv->last_rx_noise); | ||
2955 | desc += sprintf(buff+desc, | ||
2956 | "Tsf= 0x%llx\tBeacon time= 0x%08X\n", | ||
2957 | priv->last_tsf, priv->last_beacon_time); | ||
2958 | 2936 | ||
2959 | ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc); | 2937 | ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc); |
2960 | return ret; | 2938 | return ret; |
@@ -2994,12 +2972,21 @@ static void rs_remove_debugfs(void *priv, void *priv_sta) | |||
2994 | } | 2972 | } |
2995 | #endif | 2973 | #endif |
2996 | 2974 | ||
2975 | /* | ||
2976 | * Initialization of rate scaling information is done by driver after | ||
2977 | * the station is added. Since mac80211 calls this function before a | ||
2978 | * station is added we ignore it. | ||
2979 | */ | ||
2980 | static void rs_rate_init_stub(void *priv_r, struct ieee80211_supported_band *sband, | ||
2981 | struct ieee80211_sta *sta, void *priv_sta) | ||
2982 | { | ||
2983 | } | ||
2997 | static struct rate_control_ops rs_ops = { | 2984 | static struct rate_control_ops rs_ops = { |
2998 | .module = NULL, | 2985 | .module = NULL, |
2999 | .name = RS_NAME, | 2986 | .name = RS_NAME, |
3000 | .tx_status = rs_tx_status, | 2987 | .tx_status = rs_tx_status, |
3001 | .get_rate = rs_get_rate, | 2988 | .get_rate = rs_get_rate, |
3002 | .rate_init = rs_rate_init, | 2989 | .rate_init = rs_rate_init_stub, |
3003 | .alloc = rs_alloc, | 2990 | .alloc = rs_alloc, |
3004 | .free = rs_free, | 2991 | .free = rs_free, |
3005 | .alloc_sta = rs_alloc_sta, | 2992 | .alloc_sta = rs_alloc_sta, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h index e71923961e69..8292f6d48ec6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h | |||
@@ -403,7 +403,6 @@ struct iwl_lq_sta { | |||
403 | u8 is_green; | 403 | u8 is_green; |
404 | u8 is_dup; | 404 | u8 is_dup; |
405 | enum ieee80211_band band; | 405 | enum ieee80211_band band; |
406 | u8 ibss_sta_added; | ||
407 | 406 | ||
408 | /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ | 407 | /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ |
409 | u32 supp_rates; | 408 | u32 supp_rates; |
@@ -411,7 +410,6 @@ struct iwl_lq_sta { | |||
411 | u16 active_siso_rate; | 410 | u16 active_siso_rate; |
412 | u16 active_mimo2_rate; | 411 | u16 active_mimo2_rate; |
413 | u16 active_mimo3_rate; | 412 | u16 active_mimo3_rate; |
414 | u16 active_rate_basic; | ||
415 | s8 max_rate_idx; /* Max rate set by user */ | 413 | s8 max_rate_idx; /* Max rate set by user */ |
416 | u8 missed_rate_counter; | 414 | u8 missed_rate_counter; |
417 | 415 | ||
@@ -479,6 +477,12 @@ static inline u8 iwl3945_get_prev_ieee_rate(u8 rate_index) | |||
479 | */ | 477 | */ |
480 | extern void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id); | 478 | extern void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id); |
481 | 479 | ||
480 | /* Initialize station's rate scaling information after adding station */ | ||
481 | extern void iwl_rs_rate_init(struct iwl_priv *priv, | ||
482 | struct ieee80211_sta *sta, u8 sta_id); | ||
483 | extern void iwl3945_rs_rate_init(struct iwl_priv *priv, | ||
484 | struct ieee80211_sta *sta, u8 sta_id); | ||
485 | |||
482 | /** | 486 | /** |
483 | * iwl_rate_control_register - Register the rate control algorithm callbacks | 487 | * iwl_rate_control_register - Register the rate control algorithm callbacks |
484 | * | 488 | * |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c new file mode 100644 index 000000000000..a76e14351b5a --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c | |||
@@ -0,0 +1,1314 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * GPL LICENSE SUMMARY | ||
4 | * | ||
5 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of version 2 of the GNU General Public License as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
19 | * USA | ||
20 | * | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
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/sched.h> | ||
34 | |||
35 | #include "iwl-dev.h" | ||
36 | #include "iwl-core.h" | ||
37 | #include "iwl-sta.h" | ||
38 | #include "iwl-io.h" | ||
39 | #include "iwl-helpers.h" | ||
40 | #include "iwl-agn-hw.h" | ||
41 | #include "iwl-agn.h" | ||
42 | |||
43 | /* | ||
44 | * mac80211 queues, ACs, hardware queues, FIFOs. | ||
45 | * | ||
46 | * Cf. http://wireless.kernel.org/en/developers/Documentation/mac80211/queues | ||
47 | * | ||
48 | * Mac80211 uses the following numbers, which we get as from it | ||
49 | * by way of skb_get_queue_mapping(skb): | ||
50 | * | ||
51 | * VO 0 | ||
52 | * VI 1 | ||
53 | * BE 2 | ||
54 | * BK 3 | ||
55 | * | ||
56 | * | ||
57 | * Regular (not A-MPDU) frames are put into hardware queues corresponding | ||
58 | * to the FIFOs, see comments in iwl-prph.h. Aggregated frames get their | ||
59 | * own queue per aggregation session (RA/TID combination), such queues are | ||
60 | * set up to map into FIFOs too, for which we need an AC->FIFO mapping. In | ||
61 | * order to map frames to the right queue, we also need an AC->hw queue | ||
62 | * mapping. This is implemented here. | ||
63 | * | ||
64 | * Due to the way hw queues are set up (by the hw specific modules like | ||
65 | * iwl-4965.c, iwl-5000.c etc.), the AC->hw queue mapping is the identity | ||
66 | * mapping. | ||
67 | */ | ||
68 | |||
69 | static const u8 tid_to_ac[] = { | ||
70 | /* this matches the mac80211 numbers */ | ||
71 | 2, 3, 3, 2, 1, 1, 0, 0 | ||
72 | }; | ||
73 | |||
74 | static const u8 ac_to_fifo[] = { | ||
75 | IWL_TX_FIFO_VO, | ||
76 | IWL_TX_FIFO_VI, | ||
77 | IWL_TX_FIFO_BE, | ||
78 | IWL_TX_FIFO_BK, | ||
79 | }; | ||
80 | |||
81 | static inline int get_fifo_from_ac(u8 ac) | ||
82 | { | ||
83 | return ac_to_fifo[ac]; | ||
84 | } | ||
85 | |||
86 | static inline int get_fifo_from_tid(u16 tid) | ||
87 | { | ||
88 | if (likely(tid < ARRAY_SIZE(tid_to_ac))) | ||
89 | return get_fifo_from_ac(tid_to_ac[tid]); | ||
90 | |||
91 | /* no support for TIDs 8-15 yet */ | ||
92 | return -EINVAL; | ||
93 | } | ||
94 | |||
95 | /** | ||
96 | * iwlagn_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array | ||
97 | */ | ||
98 | void iwlagn_txq_update_byte_cnt_tbl(struct iwl_priv *priv, | ||
99 | struct iwl_tx_queue *txq, | ||
100 | u16 byte_cnt) | ||
101 | { | ||
102 | struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; | ||
103 | int write_ptr = txq->q.write_ptr; | ||
104 | int txq_id = txq->q.id; | ||
105 | u8 sec_ctl = 0; | ||
106 | u8 sta_id = 0; | ||
107 | u16 len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; | ||
108 | __le16 bc_ent; | ||
109 | |||
110 | WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX); | ||
111 | |||
112 | if (txq_id != IWL_CMD_QUEUE_NUM) { | ||
113 | sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id; | ||
114 | sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl; | ||
115 | |||
116 | switch (sec_ctl & TX_CMD_SEC_MSK) { | ||
117 | case TX_CMD_SEC_CCM: | ||
118 | len += CCMP_MIC_LEN; | ||
119 | break; | ||
120 | case TX_CMD_SEC_TKIP: | ||
121 | len += TKIP_ICV_LEN; | ||
122 | break; | ||
123 | case TX_CMD_SEC_WEP: | ||
124 | len += WEP_IV_LEN + WEP_ICV_LEN; | ||
125 | break; | ||
126 | } | ||
127 | } | ||
128 | |||
129 | bc_ent = cpu_to_le16((len & 0xFFF) | (sta_id << 12)); | ||
130 | |||
131 | scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent; | ||
132 | |||
133 | if (write_ptr < TFD_QUEUE_SIZE_BC_DUP) | ||
134 | scd_bc_tbl[txq_id]. | ||
135 | tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent; | ||
136 | } | ||
137 | |||
138 | void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, | ||
139 | struct iwl_tx_queue *txq) | ||
140 | { | ||
141 | struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; | ||
142 | int txq_id = txq->q.id; | ||
143 | int read_ptr = txq->q.read_ptr; | ||
144 | u8 sta_id = 0; | ||
145 | __le16 bc_ent; | ||
146 | |||
147 | WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX); | ||
148 | |||
149 | if (txq_id != IWL_CMD_QUEUE_NUM) | ||
150 | sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id; | ||
151 | |||
152 | bc_ent = cpu_to_le16(1 | (sta_id << 12)); | ||
153 | scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent; | ||
154 | |||
155 | if (read_ptr < TFD_QUEUE_SIZE_BC_DUP) | ||
156 | scd_bc_tbl[txq_id]. | ||
157 | tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent; | ||
158 | } | ||
159 | |||
160 | static int iwlagn_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid, | ||
161 | u16 txq_id) | ||
162 | { | ||
163 | u32 tbl_dw_addr; | ||
164 | u32 tbl_dw; | ||
165 | u16 scd_q2ratid; | ||
166 | |||
167 | scd_q2ratid = ra_tid & IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK; | ||
168 | |||
169 | tbl_dw_addr = priv->scd_base_addr + | ||
170 | IWL50_SCD_TRANSLATE_TBL_OFFSET_QUEUE(txq_id); | ||
171 | |||
172 | tbl_dw = iwl_read_targ_mem(priv, tbl_dw_addr); | ||
173 | |||
174 | if (txq_id & 0x1) | ||
175 | tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF); | ||
176 | else | ||
177 | tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000); | ||
178 | |||
179 | iwl_write_targ_mem(priv, tbl_dw_addr, tbl_dw); | ||
180 | |||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | static void iwlagn_tx_queue_stop_scheduler(struct iwl_priv *priv, u16 txq_id) | ||
185 | { | ||
186 | /* Simply stop the queue, but don't change any configuration; | ||
187 | * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */ | ||
188 | iwl_write_prph(priv, | ||
189 | IWL50_SCD_QUEUE_STATUS_BITS(txq_id), | ||
190 | (0 << IWL50_SCD_QUEUE_STTS_REG_POS_ACTIVE)| | ||
191 | (1 << IWL50_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); | ||
192 | } | ||
193 | |||
194 | void iwlagn_set_wr_ptrs(struct iwl_priv *priv, | ||
195 | int txq_id, u32 index) | ||
196 | { | ||
197 | iwl_write_direct32(priv, HBUS_TARG_WRPTR, | ||
198 | (index & 0xff) | (txq_id << 8)); | ||
199 | iwl_write_prph(priv, IWL50_SCD_QUEUE_RDPTR(txq_id), index); | ||
200 | } | ||
201 | |||
202 | void iwlagn_tx_queue_set_status(struct iwl_priv *priv, | ||
203 | struct iwl_tx_queue *txq, | ||
204 | int tx_fifo_id, int scd_retry) | ||
205 | { | ||
206 | int txq_id = txq->q.id; | ||
207 | int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0; | ||
208 | |||
209 | iwl_write_prph(priv, IWL50_SCD_QUEUE_STATUS_BITS(txq_id), | ||
210 | (active << IWL50_SCD_QUEUE_STTS_REG_POS_ACTIVE) | | ||
211 | (tx_fifo_id << IWL50_SCD_QUEUE_STTS_REG_POS_TXF) | | ||
212 | (1 << IWL50_SCD_QUEUE_STTS_REG_POS_WSL) | | ||
213 | IWL50_SCD_QUEUE_STTS_REG_MSK); | ||
214 | |||
215 | txq->sched_retry = scd_retry; | ||
216 | |||
217 | IWL_DEBUG_INFO(priv, "%s %s Queue %d on FIFO %d\n", | ||
218 | active ? "Activate" : "Deactivate", | ||
219 | scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id); | ||
220 | } | ||
221 | |||
222 | int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, | ||
223 | int tx_fifo, int sta_id, int tid, u16 ssn_idx) | ||
224 | { | ||
225 | unsigned long flags; | ||
226 | u16 ra_tid; | ||
227 | |||
228 | if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || | ||
229 | (IWLAGN_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues | ||
230 | <= txq_id)) { | ||
231 | IWL_WARN(priv, | ||
232 | "queue number out of range: %d, must be %d to %d\n", | ||
233 | txq_id, IWLAGN_FIRST_AMPDU_QUEUE, | ||
234 | IWLAGN_FIRST_AMPDU_QUEUE + | ||
235 | priv->cfg->num_of_ampdu_queues - 1); | ||
236 | return -EINVAL; | ||
237 | } | ||
238 | |||
239 | ra_tid = BUILD_RAxTID(sta_id, tid); | ||
240 | |||
241 | /* Modify device's station table to Tx this TID */ | ||
242 | iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); | ||
243 | |||
244 | spin_lock_irqsave(&priv->lock, flags); | ||
245 | |||
246 | /* Stop this Tx queue before configuring it */ | ||
247 | iwlagn_tx_queue_stop_scheduler(priv, txq_id); | ||
248 | |||
249 | /* Map receiver-address / traffic-ID to this queue */ | ||
250 | iwlagn_tx_queue_set_q2ratid(priv, ra_tid, txq_id); | ||
251 | |||
252 | /* Set this queue as a chain-building queue */ | ||
253 | iwl_set_bits_prph(priv, IWL50_SCD_QUEUECHAIN_SEL, (1<<txq_id)); | ||
254 | |||
255 | /* enable aggregations for the queue */ | ||
256 | iwl_set_bits_prph(priv, IWL50_SCD_AGGR_SEL, (1<<txq_id)); | ||
257 | |||
258 | /* Place first TFD at index corresponding to start sequence number. | ||
259 | * Assumes that ssn_idx is valid (!= 0xFFF) */ | ||
260 | priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); | ||
261 | priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); | ||
262 | iwlagn_set_wr_ptrs(priv, txq_id, ssn_idx); | ||
263 | |||
264 | /* Set up Tx window size and frame limit for this queue */ | ||
265 | iwl_write_targ_mem(priv, priv->scd_base_addr + | ||
266 | IWL50_SCD_CONTEXT_QUEUE_OFFSET(txq_id) + | ||
267 | sizeof(u32), | ||
268 | ((SCD_WIN_SIZE << | ||
269 | IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & | ||
270 | IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | | ||
271 | ((SCD_FRAME_LIMIT << | ||
272 | IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & | ||
273 | IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); | ||
274 | |||
275 | iwl_set_bits_prph(priv, IWL50_SCD_INTERRUPT_MASK, (1 << txq_id)); | ||
276 | |||
277 | /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ | ||
278 | iwlagn_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1); | ||
279 | |||
280 | spin_unlock_irqrestore(&priv->lock, flags); | ||
281 | |||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, | ||
286 | u16 ssn_idx, u8 tx_fifo) | ||
287 | { | ||
288 | if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || | ||
289 | (IWLAGN_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues | ||
290 | <= txq_id)) { | ||
291 | IWL_ERR(priv, | ||
292 | "queue number out of range: %d, must be %d to %d\n", | ||
293 | txq_id, IWLAGN_FIRST_AMPDU_QUEUE, | ||
294 | IWLAGN_FIRST_AMPDU_QUEUE + | ||
295 | priv->cfg->num_of_ampdu_queues - 1); | ||
296 | return -EINVAL; | ||
297 | } | ||
298 | |||
299 | iwlagn_tx_queue_stop_scheduler(priv, txq_id); | ||
300 | |||
301 | iwl_clear_bits_prph(priv, IWL50_SCD_AGGR_SEL, (1 << txq_id)); | ||
302 | |||
303 | priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); | ||
304 | priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); | ||
305 | /* supposes that ssn_idx is valid (!= 0xFFF) */ | ||
306 | iwlagn_set_wr_ptrs(priv, txq_id, ssn_idx); | ||
307 | |||
308 | iwl_clear_bits_prph(priv, IWL50_SCD_INTERRUPT_MASK, (1 << txq_id)); | ||
309 | iwl_txq_ctx_deactivate(priv, txq_id); | ||
310 | iwlagn_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0); | ||
311 | |||
312 | return 0; | ||
313 | } | ||
314 | |||
315 | /* | ||
316 | * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask | ||
317 | * must be called under priv->lock and mac access | ||
318 | */ | ||
319 | void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask) | ||
320 | { | ||
321 | iwl_write_prph(priv, IWL50_SCD_TXFACT, mask); | ||
322 | } | ||
323 | |||
324 | static inline int get_queue_from_ac(u16 ac) | ||
325 | { | ||
326 | return ac; | ||
327 | } | ||
328 | |||
329 | /* | ||
330 | * handle build REPLY_TX command notification. | ||
331 | */ | ||
332 | static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv, | ||
333 | struct iwl_tx_cmd *tx_cmd, | ||
334 | struct ieee80211_tx_info *info, | ||
335 | struct ieee80211_hdr *hdr, | ||
336 | u8 std_id) | ||
337 | { | ||
338 | __le16 fc = hdr->frame_control; | ||
339 | __le32 tx_flags = tx_cmd->tx_flags; | ||
340 | |||
341 | tx_cmd->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; | ||
342 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { | ||
343 | tx_flags |= TX_CMD_FLG_ACK_MSK; | ||
344 | if (ieee80211_is_mgmt(fc)) | ||
345 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; | ||
346 | if (ieee80211_is_probe_resp(fc) && | ||
347 | !(le16_to_cpu(hdr->seq_ctrl) & 0xf)) | ||
348 | tx_flags |= TX_CMD_FLG_TSF_MSK; | ||
349 | } else { | ||
350 | tx_flags &= (~TX_CMD_FLG_ACK_MSK); | ||
351 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; | ||
352 | } | ||
353 | |||
354 | if (ieee80211_is_back_req(fc)) | ||
355 | tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK; | ||
356 | |||
357 | |||
358 | tx_cmd->sta_id = std_id; | ||
359 | if (ieee80211_has_morefrags(fc)) | ||
360 | tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK; | ||
361 | |||
362 | if (ieee80211_is_data_qos(fc)) { | ||
363 | u8 *qc = ieee80211_get_qos_ctl(hdr); | ||
364 | tx_cmd->tid_tspec = qc[0] & 0xf; | ||
365 | tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK; | ||
366 | } else { | ||
367 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; | ||
368 | } | ||
369 | |||
370 | priv->cfg->ops->utils->rts_tx_cmd_flag(info, &tx_flags); | ||
371 | |||
372 | if ((tx_flags & TX_CMD_FLG_RTS_MSK) || (tx_flags & TX_CMD_FLG_CTS_MSK)) | ||
373 | tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; | ||
374 | |||
375 | tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK); | ||
376 | if (ieee80211_is_mgmt(fc)) { | ||
377 | if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc)) | ||
378 | tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(3); | ||
379 | else | ||
380 | tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(2); | ||
381 | } else { | ||
382 | tx_cmd->timeout.pm_frame_timeout = 0; | ||
383 | } | ||
384 | |||
385 | tx_cmd->driver_txop = 0; | ||
386 | tx_cmd->tx_flags = tx_flags; | ||
387 | tx_cmd->next_frame_len = 0; | ||
388 | } | ||
389 | |||
390 | #define RTS_DFAULT_RETRY_LIMIT 60 | ||
391 | |||
392 | static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, | ||
393 | struct iwl_tx_cmd *tx_cmd, | ||
394 | struct ieee80211_tx_info *info, | ||
395 | __le16 fc) | ||
396 | { | ||
397 | u32 rate_flags; | ||
398 | int rate_idx; | ||
399 | u8 rts_retry_limit; | ||
400 | u8 data_retry_limit; | ||
401 | u8 rate_plcp; | ||
402 | |||
403 | /* Set retry limit on DATA packets and Probe Responses*/ | ||
404 | if (ieee80211_is_probe_resp(fc)) | ||
405 | data_retry_limit = 3; | ||
406 | else | ||
407 | data_retry_limit = IWLAGN_DEFAULT_TX_RETRY; | ||
408 | tx_cmd->data_retry_limit = data_retry_limit; | ||
409 | |||
410 | /* Set retry limit on RTS packets */ | ||
411 | rts_retry_limit = RTS_DFAULT_RETRY_LIMIT; | ||
412 | if (data_retry_limit < rts_retry_limit) | ||
413 | rts_retry_limit = data_retry_limit; | ||
414 | tx_cmd->rts_retry_limit = rts_retry_limit; | ||
415 | |||
416 | /* DATA packets will use the uCode station table for rate/antenna | ||
417 | * selection */ | ||
418 | if (ieee80211_is_data(fc)) { | ||
419 | tx_cmd->initial_rate_index = 0; | ||
420 | tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK; | ||
421 | return; | ||
422 | } | ||
423 | |||
424 | /** | ||
425 | * If the current TX rate stored in mac80211 has the MCS bit set, it's | ||
426 | * not really a TX rate. Thus, we use the lowest supported rate for | ||
427 | * this band. Also use the lowest supported rate if the stored rate | ||
428 | * index is invalid. | ||
429 | */ | ||
430 | rate_idx = info->control.rates[0].idx; | ||
431 | if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS || | ||
432 | (rate_idx < 0) || (rate_idx > IWL_RATE_COUNT_LEGACY)) | ||
433 | rate_idx = rate_lowest_index(&priv->bands[info->band], | ||
434 | info->control.sta); | ||
435 | /* For 5 GHZ band, remap mac80211 rate indices into driver indices */ | ||
436 | if (info->band == IEEE80211_BAND_5GHZ) | ||
437 | rate_idx += IWL_FIRST_OFDM_RATE; | ||
438 | /* Get PLCP rate for tx_cmd->rate_n_flags */ | ||
439 | rate_plcp = iwl_rates[rate_idx].plcp; | ||
440 | /* Zero out flags for this packet */ | ||
441 | rate_flags = 0; | ||
442 | |||
443 | /* Set CCK flag as needed */ | ||
444 | if ((rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE)) | ||
445 | rate_flags |= RATE_MCS_CCK_MSK; | ||
446 | |||
447 | /* Set up RTS and CTS flags for certain packets */ | ||
448 | switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { | ||
449 | case cpu_to_le16(IEEE80211_STYPE_AUTH): | ||
450 | case cpu_to_le16(IEEE80211_STYPE_DEAUTH): | ||
451 | case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ): | ||
452 | case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ): | ||
453 | if (tx_cmd->tx_flags & TX_CMD_FLG_RTS_MSK) { | ||
454 | tx_cmd->tx_flags &= ~TX_CMD_FLG_RTS_MSK; | ||
455 | tx_cmd->tx_flags |= TX_CMD_FLG_CTS_MSK; | ||
456 | } | ||
457 | break; | ||
458 | default: | ||
459 | break; | ||
460 | } | ||
461 | |||
462 | /* Set up antennas */ | ||
463 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant); | ||
464 | rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant); | ||
465 | |||
466 | /* Set the rate in the TX cmd */ | ||
467 | tx_cmd->rate_n_flags = iwl_hw_set_rate_n_flags(rate_plcp, rate_flags); | ||
468 | } | ||
469 | |||
470 | static void iwlagn_tx_cmd_build_hwcrypto(struct iwl_priv *priv, | ||
471 | struct ieee80211_tx_info *info, | ||
472 | struct iwl_tx_cmd *tx_cmd, | ||
473 | struct sk_buff *skb_frag, | ||
474 | int sta_id) | ||
475 | { | ||
476 | struct ieee80211_key_conf *keyconf = info->control.hw_key; | ||
477 | |||
478 | switch (keyconf->alg) { | ||
479 | case ALG_CCMP: | ||
480 | tx_cmd->sec_ctl = TX_CMD_SEC_CCM; | ||
481 | memcpy(tx_cmd->key, keyconf->key, keyconf->keylen); | ||
482 | if (info->flags & IEEE80211_TX_CTL_AMPDU) | ||
483 | tx_cmd->tx_flags |= TX_CMD_FLG_AGG_CCMP_MSK; | ||
484 | IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n"); | ||
485 | break; | ||
486 | |||
487 | case ALG_TKIP: | ||
488 | tx_cmd->sec_ctl = TX_CMD_SEC_TKIP; | ||
489 | ieee80211_get_tkip_key(keyconf, skb_frag, | ||
490 | IEEE80211_TKIP_P2_KEY, tx_cmd->key); | ||
491 | IWL_DEBUG_TX(priv, "tx_cmd with tkip hwcrypto\n"); | ||
492 | break; | ||
493 | |||
494 | case ALG_WEP: | ||
495 | tx_cmd->sec_ctl |= (TX_CMD_SEC_WEP | | ||
496 | (keyconf->keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT); | ||
497 | |||
498 | if (keyconf->keylen == WEP_KEY_LEN_128) | ||
499 | tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128; | ||
500 | |||
501 | memcpy(&tx_cmd->key[3], keyconf->key, keyconf->keylen); | ||
502 | |||
503 | IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption " | ||
504 | "with key %d\n", keyconf->keyidx); | ||
505 | break; | ||
506 | |||
507 | default: | ||
508 | IWL_ERR(priv, "Unknown encode alg %d\n", keyconf->alg); | ||
509 | break; | ||
510 | } | ||
511 | } | ||
512 | |||
513 | /* | ||
514 | * start REPLY_TX command process | ||
515 | */ | ||
516 | int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | ||
517 | { | ||
518 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
519 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
520 | struct ieee80211_sta *sta = info->control.sta; | ||
521 | struct iwl_station_priv *sta_priv = NULL; | ||
522 | struct iwl_tx_queue *txq; | ||
523 | struct iwl_queue *q; | ||
524 | struct iwl_device_cmd *out_cmd; | ||
525 | struct iwl_cmd_meta *out_meta; | ||
526 | struct iwl_tx_cmd *tx_cmd; | ||
527 | int swq_id, txq_id; | ||
528 | dma_addr_t phys_addr; | ||
529 | dma_addr_t txcmd_phys; | ||
530 | dma_addr_t scratch_phys; | ||
531 | u16 len, len_org, firstlen, secondlen; | ||
532 | u16 seq_number = 0; | ||
533 | __le16 fc; | ||
534 | u8 hdr_len; | ||
535 | u8 sta_id; | ||
536 | u8 wait_write_ptr = 0; | ||
537 | u8 tid = 0; | ||
538 | u8 *qc = NULL; | ||
539 | unsigned long flags; | ||
540 | |||
541 | spin_lock_irqsave(&priv->lock, flags); | ||
542 | if (iwl_is_rfkill(priv)) { | ||
543 | IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n"); | ||
544 | goto drop_unlock; | ||
545 | } | ||
546 | |||
547 | fc = hdr->frame_control; | ||
548 | |||
549 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
550 | if (ieee80211_is_auth(fc)) | ||
551 | IWL_DEBUG_TX(priv, "Sending AUTH frame\n"); | ||
552 | else if (ieee80211_is_assoc_req(fc)) | ||
553 | IWL_DEBUG_TX(priv, "Sending ASSOC frame\n"); | ||
554 | else if (ieee80211_is_reassoc_req(fc)) | ||
555 | IWL_DEBUG_TX(priv, "Sending REASSOC frame\n"); | ||
556 | #endif | ||
557 | |||
558 | hdr_len = ieee80211_hdrlen(fc); | ||
559 | |||
560 | /* Find (or create) index into station table for destination station */ | ||
561 | if (info->flags & IEEE80211_TX_CTL_INJECTED) | ||
562 | sta_id = priv->hw_params.bcast_sta_id; | ||
563 | else | ||
564 | sta_id = iwl_get_sta_id(priv, hdr); | ||
565 | if (sta_id == IWL_INVALID_STATION) { | ||
566 | IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", | ||
567 | hdr->addr1); | ||
568 | goto drop_unlock; | ||
569 | } | ||
570 | |||
571 | IWL_DEBUG_TX(priv, "station Id %d\n", sta_id); | ||
572 | |||
573 | if (sta) | ||
574 | sta_priv = (void *)sta->drv_priv; | ||
575 | |||
576 | if (sta_priv && sta_id != priv->hw_params.bcast_sta_id && | ||
577 | sta_priv->asleep) { | ||
578 | WARN_ON(!(info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE)); | ||
579 | /* | ||
580 | * This sends an asynchronous command to the device, | ||
581 | * but we can rely on it being processed before the | ||
582 | * next frame is processed -- and the next frame to | ||
583 | * this station is the one that will consume this | ||
584 | * counter. | ||
585 | * For now set the counter to just 1 since we do not | ||
586 | * support uAPSD yet. | ||
587 | */ | ||
588 | iwl_sta_modify_sleep_tx_count(priv, sta_id, 1); | ||
589 | } | ||
590 | |||
591 | txq_id = get_queue_from_ac(skb_get_queue_mapping(skb)); | ||
592 | if (ieee80211_is_data_qos(fc)) { | ||
593 | qc = ieee80211_get_qos_ctl(hdr); | ||
594 | tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; | ||
595 | if (unlikely(tid >= MAX_TID_COUNT)) | ||
596 | goto drop_unlock; | ||
597 | seq_number = priv->stations[sta_id].tid[tid].seq_number; | ||
598 | seq_number &= IEEE80211_SCTL_SEQ; | ||
599 | hdr->seq_ctrl = hdr->seq_ctrl & | ||
600 | cpu_to_le16(IEEE80211_SCTL_FRAG); | ||
601 | hdr->seq_ctrl |= cpu_to_le16(seq_number); | ||
602 | seq_number += 0x10; | ||
603 | /* aggregation is on for this <sta,tid> */ | ||
604 | if (info->flags & IEEE80211_TX_CTL_AMPDU && | ||
605 | priv->stations[sta_id].tid[tid].agg.state == IWL_AGG_ON) { | ||
606 | txq_id = priv->stations[sta_id].tid[tid].agg.txq_id; | ||
607 | } | ||
608 | } | ||
609 | |||
610 | txq = &priv->txq[txq_id]; | ||
611 | swq_id = txq->swq_id; | ||
612 | q = &txq->q; | ||
613 | |||
614 | if (unlikely(iwl_queue_space(q) < q->high_mark)) | ||
615 | goto drop_unlock; | ||
616 | |||
617 | if (ieee80211_is_data_qos(fc)) | ||
618 | priv->stations[sta_id].tid[tid].tfds_in_queue++; | ||
619 | |||
620 | /* Set up driver data for this TFD */ | ||
621 | memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); | ||
622 | txq->txb[q->write_ptr].skb[0] = skb; | ||
623 | |||
624 | /* Set up first empty entry in queue's array of Tx/cmd buffers */ | ||
625 | out_cmd = txq->cmd[q->write_ptr]; | ||
626 | out_meta = &txq->meta[q->write_ptr]; | ||
627 | tx_cmd = &out_cmd->cmd.tx; | ||
628 | memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr)); | ||
629 | memset(tx_cmd, 0, sizeof(struct iwl_tx_cmd)); | ||
630 | |||
631 | /* | ||
632 | * Set up the Tx-command (not MAC!) header. | ||
633 | * Store the chosen Tx queue and TFD index within the sequence field; | ||
634 | * after Tx, uCode's Tx response will return this value so driver can | ||
635 | * locate the frame within the tx queue and do post-tx processing. | ||
636 | */ | ||
637 | out_cmd->hdr.cmd = REPLY_TX; | ||
638 | out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) | | ||
639 | INDEX_TO_SEQ(q->write_ptr))); | ||
640 | |||
641 | /* Copy MAC header from skb into command buffer */ | ||
642 | memcpy(tx_cmd->hdr, hdr, hdr_len); | ||
643 | |||
644 | |||
645 | /* Total # bytes to be transmitted */ | ||
646 | len = (u16)skb->len; | ||
647 | tx_cmd->len = cpu_to_le16(len); | ||
648 | |||
649 | if (info->control.hw_key) | ||
650 | iwlagn_tx_cmd_build_hwcrypto(priv, info, tx_cmd, skb, sta_id); | ||
651 | |||
652 | /* TODO need this for burst mode later on */ | ||
653 | iwlagn_tx_cmd_build_basic(priv, tx_cmd, info, hdr, sta_id); | ||
654 | iwl_dbg_log_tx_data_frame(priv, len, hdr); | ||
655 | |||
656 | iwlagn_tx_cmd_build_rate(priv, tx_cmd, info, fc); | ||
657 | |||
658 | iwl_update_stats(priv, true, fc, len); | ||
659 | /* | ||
660 | * Use the first empty entry in this queue's command buffer array | ||
661 | * to contain the Tx command and MAC header concatenated together | ||
662 | * (payload data will be in another buffer). | ||
663 | * Size of this varies, due to varying MAC header length. | ||
664 | * If end is not dword aligned, we'll have 2 extra bytes at the end | ||
665 | * of the MAC header (device reads on dword boundaries). | ||
666 | * We'll tell device about this padding later. | ||
667 | */ | ||
668 | len = sizeof(struct iwl_tx_cmd) + | ||
669 | sizeof(struct iwl_cmd_header) + hdr_len; | ||
670 | |||
671 | len_org = len; | ||
672 | firstlen = len = (len + 3) & ~3; | ||
673 | |||
674 | if (len_org != len) | ||
675 | len_org = 1; | ||
676 | else | ||
677 | len_org = 0; | ||
678 | |||
679 | /* Tell NIC about any 2-byte padding after MAC header */ | ||
680 | if (len_org) | ||
681 | tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK; | ||
682 | |||
683 | /* Physical address of this Tx command's header (not MAC header!), | ||
684 | * within command buffer array. */ | ||
685 | txcmd_phys = pci_map_single(priv->pci_dev, | ||
686 | &out_cmd->hdr, len, | ||
687 | PCI_DMA_BIDIRECTIONAL); | ||
688 | pci_unmap_addr_set(out_meta, mapping, txcmd_phys); | ||
689 | pci_unmap_len_set(out_meta, len, len); | ||
690 | /* Add buffer containing Tx command and MAC(!) header to TFD's | ||
691 | * first entry */ | ||
692 | priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, | ||
693 | txcmd_phys, len, 1, 0); | ||
694 | |||
695 | if (!ieee80211_has_morefrags(hdr->frame_control)) { | ||
696 | txq->need_update = 1; | ||
697 | if (qc) | ||
698 | priv->stations[sta_id].tid[tid].seq_number = seq_number; | ||
699 | } else { | ||
700 | wait_write_ptr = 1; | ||
701 | txq->need_update = 0; | ||
702 | } | ||
703 | |||
704 | /* Set up TFD's 2nd entry to point directly to remainder of skb, | ||
705 | * if any (802.11 null frames have no payload). */ | ||
706 | secondlen = len = skb->len - hdr_len; | ||
707 | if (len) { | ||
708 | phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len, | ||
709 | len, PCI_DMA_TODEVICE); | ||
710 | priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, | ||
711 | phys_addr, len, | ||
712 | 0, 0); | ||
713 | } | ||
714 | |||
715 | scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) + | ||
716 | offsetof(struct iwl_tx_cmd, scratch); | ||
717 | |||
718 | len = sizeof(struct iwl_tx_cmd) + | ||
719 | sizeof(struct iwl_cmd_header) + hdr_len; | ||
720 | /* take back ownership of DMA buffer to enable update */ | ||
721 | pci_dma_sync_single_for_cpu(priv->pci_dev, txcmd_phys, | ||
722 | len, PCI_DMA_BIDIRECTIONAL); | ||
723 | tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys); | ||
724 | tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys); | ||
725 | |||
726 | IWL_DEBUG_TX(priv, "sequence nr = 0X%x\n", | ||
727 | le16_to_cpu(out_cmd->hdr.sequence)); | ||
728 | IWL_DEBUG_TX(priv, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags)); | ||
729 | iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd)); | ||
730 | iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len); | ||
731 | |||
732 | /* Set up entry for this TFD in Tx byte-count array */ | ||
733 | if (info->flags & IEEE80211_TX_CTL_AMPDU) | ||
734 | priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, | ||
735 | le16_to_cpu(tx_cmd->len)); | ||
736 | |||
737 | pci_dma_sync_single_for_device(priv->pci_dev, txcmd_phys, | ||
738 | len, PCI_DMA_BIDIRECTIONAL); | ||
739 | |||
740 | trace_iwlwifi_dev_tx(priv, | ||
741 | &((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr], | ||
742 | sizeof(struct iwl_tfd), | ||
743 | &out_cmd->hdr, firstlen, | ||
744 | skb->data + hdr_len, secondlen); | ||
745 | |||
746 | /* Tell device the write index *just past* this latest filled TFD */ | ||
747 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); | ||
748 | iwl_txq_update_write_ptr(priv, txq); | ||
749 | spin_unlock_irqrestore(&priv->lock, flags); | ||
750 | |||
751 | /* | ||
752 | * At this point the frame is "transmitted" successfully | ||
753 | * and we will get a TX status notification eventually, | ||
754 | * regardless of the value of ret. "ret" only indicates | ||
755 | * whether or not we should update the write pointer. | ||
756 | */ | ||
757 | |||
758 | /* avoid atomic ops if it isn't an associated client */ | ||
759 | if (sta_priv && sta_priv->client) | ||
760 | atomic_inc(&sta_priv->pending_frames); | ||
761 | |||
762 | if ((iwl_queue_space(q) < q->high_mark) && priv->mac80211_registered) { | ||
763 | if (wait_write_ptr) { | ||
764 | spin_lock_irqsave(&priv->lock, flags); | ||
765 | txq->need_update = 1; | ||
766 | iwl_txq_update_write_ptr(priv, txq); | ||
767 | spin_unlock_irqrestore(&priv->lock, flags); | ||
768 | } else { | ||
769 | iwl_stop_queue(priv, txq->swq_id); | ||
770 | } | ||
771 | } | ||
772 | |||
773 | return 0; | ||
774 | |||
775 | drop_unlock: | ||
776 | spin_unlock_irqrestore(&priv->lock, flags); | ||
777 | return -1; | ||
778 | } | ||
779 | |||
780 | static inline int iwlagn_alloc_dma_ptr(struct iwl_priv *priv, | ||
781 | struct iwl_dma_ptr *ptr, size_t size) | ||
782 | { | ||
783 | ptr->addr = dma_alloc_coherent(&priv->pci_dev->dev, size, &ptr->dma, | ||
784 | GFP_KERNEL); | ||
785 | if (!ptr->addr) | ||
786 | return -ENOMEM; | ||
787 | ptr->size = size; | ||
788 | return 0; | ||
789 | } | ||
790 | |||
791 | static inline void iwlagn_free_dma_ptr(struct iwl_priv *priv, | ||
792 | struct iwl_dma_ptr *ptr) | ||
793 | { | ||
794 | if (unlikely(!ptr->addr)) | ||
795 | return; | ||
796 | |||
797 | dma_free_coherent(&priv->pci_dev->dev, ptr->size, ptr->addr, ptr->dma); | ||
798 | memset(ptr, 0, sizeof(*ptr)); | ||
799 | } | ||
800 | |||
801 | /** | ||
802 | * iwlagn_hw_txq_ctx_free - Free TXQ Context | ||
803 | * | ||
804 | * Destroy all TX DMA queues and structures | ||
805 | */ | ||
806 | void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv) | ||
807 | { | ||
808 | int txq_id; | ||
809 | |||
810 | /* Tx queues */ | ||
811 | if (priv->txq) { | ||
812 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; | ||
813 | txq_id++) | ||
814 | if (txq_id == IWL_CMD_QUEUE_NUM) | ||
815 | iwl_cmd_queue_free(priv); | ||
816 | else | ||
817 | iwl_tx_queue_free(priv, txq_id); | ||
818 | } | ||
819 | iwlagn_free_dma_ptr(priv, &priv->kw); | ||
820 | |||
821 | iwlagn_free_dma_ptr(priv, &priv->scd_bc_tbls); | ||
822 | |||
823 | /* free tx queue structure */ | ||
824 | iwl_free_txq_mem(priv); | ||
825 | } | ||
826 | |||
827 | /** | ||
828 | * iwlagn_txq_ctx_reset - Reset TX queue context | ||
829 | * Destroys all DMA structures and initialize them again | ||
830 | * | ||
831 | * @param priv | ||
832 | * @return error code | ||
833 | */ | ||
834 | int iwlagn_txq_ctx_reset(struct iwl_priv *priv) | ||
835 | { | ||
836 | int ret = 0; | ||
837 | int txq_id, slots_num; | ||
838 | unsigned long flags; | ||
839 | |||
840 | /* Free all tx/cmd queues and keep-warm buffer */ | ||
841 | iwlagn_hw_txq_ctx_free(priv); | ||
842 | |||
843 | ret = iwlagn_alloc_dma_ptr(priv, &priv->scd_bc_tbls, | ||
844 | priv->hw_params.scd_bc_tbls_size); | ||
845 | if (ret) { | ||
846 | IWL_ERR(priv, "Scheduler BC Table allocation failed\n"); | ||
847 | goto error_bc_tbls; | ||
848 | } | ||
849 | /* Alloc keep-warm buffer */ | ||
850 | ret = iwlagn_alloc_dma_ptr(priv, &priv->kw, IWL_KW_SIZE); | ||
851 | if (ret) { | ||
852 | IWL_ERR(priv, "Keep Warm allocation failed\n"); | ||
853 | goto error_kw; | ||
854 | } | ||
855 | |||
856 | /* allocate tx queue structure */ | ||
857 | ret = iwl_alloc_txq_mem(priv); | ||
858 | if (ret) | ||
859 | goto error; | ||
860 | |||
861 | spin_lock_irqsave(&priv->lock, flags); | ||
862 | |||
863 | /* Turn off all Tx DMA fifos */ | ||
864 | priv->cfg->ops->lib->txq_set_sched(priv, 0); | ||
865 | |||
866 | /* Tell NIC where to find the "keep warm" buffer */ | ||
867 | iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); | ||
868 | |||
869 | spin_unlock_irqrestore(&priv->lock, flags); | ||
870 | |||
871 | /* Alloc and init all Tx queues, including the command queue (#4) */ | ||
872 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { | ||
873 | slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ? | ||
874 | TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; | ||
875 | ret = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num, | ||
876 | txq_id); | ||
877 | if (ret) { | ||
878 | IWL_ERR(priv, "Tx %d queue init failed\n", txq_id); | ||
879 | goto error; | ||
880 | } | ||
881 | } | ||
882 | |||
883 | return ret; | ||
884 | |||
885 | error: | ||
886 | iwlagn_hw_txq_ctx_free(priv); | ||
887 | iwlagn_free_dma_ptr(priv, &priv->kw); | ||
888 | error_kw: | ||
889 | iwlagn_free_dma_ptr(priv, &priv->scd_bc_tbls); | ||
890 | error_bc_tbls: | ||
891 | return ret; | ||
892 | } | ||
893 | |||
894 | /** | ||
895 | * iwlagn_txq_ctx_stop - Stop all Tx DMA channels, free Tx queue memory | ||
896 | */ | ||
897 | void iwlagn_txq_ctx_stop(struct iwl_priv *priv) | ||
898 | { | ||
899 | int ch; | ||
900 | unsigned long flags; | ||
901 | |||
902 | /* Turn off all Tx DMA fifos */ | ||
903 | spin_lock_irqsave(&priv->lock, flags); | ||
904 | |||
905 | priv->cfg->ops->lib->txq_set_sched(priv, 0); | ||
906 | |||
907 | /* Stop each Tx DMA channel, and wait for it to be idle */ | ||
908 | for (ch = 0; ch < priv->hw_params.dma_chnl_num; ch++) { | ||
909 | iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); | ||
910 | iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG, | ||
911 | FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), | ||
912 | 1000); | ||
913 | } | ||
914 | spin_unlock_irqrestore(&priv->lock, flags); | ||
915 | |||
916 | /* Deallocate memory for all Tx queues */ | ||
917 | iwlagn_hw_txq_ctx_free(priv); | ||
918 | } | ||
919 | |||
920 | /* | ||
921 | * Find first available (lowest unused) Tx Queue, mark it "active". | ||
922 | * Called only when finding queue for aggregation. | ||
923 | * Should never return anything < 7, because they should already | ||
924 | * be in use as EDCA AC (0-3), Command (4), reserved (5, 6) | ||
925 | */ | ||
926 | static int iwlagn_txq_ctx_activate_free(struct iwl_priv *priv) | ||
927 | { | ||
928 | int txq_id; | ||
929 | |||
930 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) | ||
931 | if (!test_and_set_bit(txq_id, &priv->txq_ctx_active_msk)) | ||
932 | return txq_id; | ||
933 | return -1; | ||
934 | } | ||
935 | |||
936 | int iwlagn_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn) | ||
937 | { | ||
938 | int sta_id; | ||
939 | int tx_fifo; | ||
940 | int txq_id; | ||
941 | int ret; | ||
942 | unsigned long flags; | ||
943 | struct iwl_tid_data *tid_data; | ||
944 | |||
945 | tx_fifo = get_fifo_from_tid(tid); | ||
946 | if (unlikely(tx_fifo < 0)) | ||
947 | return tx_fifo; | ||
948 | |||
949 | IWL_WARN(priv, "%s on ra = %pM tid = %d\n", | ||
950 | __func__, ra, tid); | ||
951 | |||
952 | sta_id = iwl_find_station(priv, ra); | ||
953 | if (sta_id == IWL_INVALID_STATION) { | ||
954 | IWL_ERR(priv, "Start AGG on invalid station\n"); | ||
955 | return -ENXIO; | ||
956 | } | ||
957 | if (unlikely(tid >= MAX_TID_COUNT)) | ||
958 | return -EINVAL; | ||
959 | |||
960 | if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_OFF) { | ||
961 | IWL_ERR(priv, "Start AGG when state is not IWL_AGG_OFF !\n"); | ||
962 | return -ENXIO; | ||
963 | } | ||
964 | |||
965 | txq_id = iwlagn_txq_ctx_activate_free(priv); | ||
966 | if (txq_id == -1) { | ||
967 | IWL_ERR(priv, "No free aggregation queue available\n"); | ||
968 | return -ENXIO; | ||
969 | } | ||
970 | |||
971 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
972 | tid_data = &priv->stations[sta_id].tid[tid]; | ||
973 | *ssn = SEQ_TO_SN(tid_data->seq_number); | ||
974 | tid_data->agg.txq_id = txq_id; | ||
975 | priv->txq[txq_id].swq_id = iwl_virtual_agg_queue_num(tx_fifo, txq_id); | ||
976 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
977 | |||
978 | ret = priv->cfg->ops->lib->txq_agg_enable(priv, txq_id, tx_fifo, | ||
979 | sta_id, tid, *ssn); | ||
980 | if (ret) | ||
981 | return ret; | ||
982 | |||
983 | if (tid_data->tfds_in_queue == 0) { | ||
984 | IWL_DEBUG_HT(priv, "HW queue is empty\n"); | ||
985 | tid_data->agg.state = IWL_AGG_ON; | ||
986 | ieee80211_start_tx_ba_cb_irqsafe(priv->vif, ra, tid); | ||
987 | } else { | ||
988 | IWL_DEBUG_HT(priv, "HW queue is NOT empty: %d packets in HW queue\n", | ||
989 | tid_data->tfds_in_queue); | ||
990 | tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA; | ||
991 | } | ||
992 | return ret; | ||
993 | } | ||
994 | |||
995 | int iwlagn_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid) | ||
996 | { | ||
997 | int tx_fifo_id, txq_id, sta_id, ssn = -1; | ||
998 | struct iwl_tid_data *tid_data; | ||
999 | int write_ptr, read_ptr; | ||
1000 | unsigned long flags; | ||
1001 | |||
1002 | if (!ra) { | ||
1003 | IWL_ERR(priv, "ra = NULL\n"); | ||
1004 | return -EINVAL; | ||
1005 | } | ||
1006 | |||
1007 | tx_fifo_id = get_fifo_from_tid(tid); | ||
1008 | if (unlikely(tx_fifo_id < 0)) | ||
1009 | return tx_fifo_id; | ||
1010 | |||
1011 | sta_id = iwl_find_station(priv, ra); | ||
1012 | |||
1013 | if (sta_id == IWL_INVALID_STATION) { | ||
1014 | IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid); | ||
1015 | return -ENXIO; | ||
1016 | } | ||
1017 | |||
1018 | if (priv->stations[sta_id].tid[tid].agg.state == | ||
1019 | IWL_EMPTYING_HW_QUEUE_ADDBA) { | ||
1020 | IWL_DEBUG_HT(priv, "AGG stop before setup done\n"); | ||
1021 | ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid); | ||
1022 | priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; | ||
1023 | return 0; | ||
1024 | } | ||
1025 | |||
1026 | if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_ON) | ||
1027 | IWL_WARN(priv, "Stopping AGG while state not ON or starting\n"); | ||
1028 | |||
1029 | tid_data = &priv->stations[sta_id].tid[tid]; | ||
1030 | ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4; | ||
1031 | txq_id = tid_data->agg.txq_id; | ||
1032 | write_ptr = priv->txq[txq_id].q.write_ptr; | ||
1033 | read_ptr = priv->txq[txq_id].q.read_ptr; | ||
1034 | |||
1035 | /* The queue is not empty */ | ||
1036 | if (write_ptr != read_ptr) { | ||
1037 | IWL_DEBUG_HT(priv, "Stopping a non empty AGG HW QUEUE\n"); | ||
1038 | priv->stations[sta_id].tid[tid].agg.state = | ||
1039 | IWL_EMPTYING_HW_QUEUE_DELBA; | ||
1040 | return 0; | ||
1041 | } | ||
1042 | |||
1043 | IWL_DEBUG_HT(priv, "HW queue is empty\n"); | ||
1044 | priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; | ||
1045 | |||
1046 | spin_lock_irqsave(&priv->lock, flags); | ||
1047 | /* | ||
1048 | * the only reason this call can fail is queue number out of range, | ||
1049 | * which can happen if uCode is reloaded and all the station | ||
1050 | * information are lost. if it is outside the range, there is no need | ||
1051 | * to deactivate the uCode queue, just return "success" to allow | ||
1052 | * mac80211 to clean up it own data. | ||
1053 | */ | ||
1054 | priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, ssn, | ||
1055 | tx_fifo_id); | ||
1056 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1057 | |||
1058 | ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid); | ||
1059 | |||
1060 | return 0; | ||
1061 | } | ||
1062 | |||
1063 | int iwlagn_txq_check_empty(struct iwl_priv *priv, | ||
1064 | int sta_id, u8 tid, int txq_id) | ||
1065 | { | ||
1066 | struct iwl_queue *q = &priv->txq[txq_id].q; | ||
1067 | u8 *addr = priv->stations[sta_id].sta.sta.addr; | ||
1068 | struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid]; | ||
1069 | |||
1070 | switch (priv->stations[sta_id].tid[tid].agg.state) { | ||
1071 | case IWL_EMPTYING_HW_QUEUE_DELBA: | ||
1072 | /* We are reclaiming the last packet of the */ | ||
1073 | /* aggregated HW queue */ | ||
1074 | if ((txq_id == tid_data->agg.txq_id) && | ||
1075 | (q->read_ptr == q->write_ptr)) { | ||
1076 | u16 ssn = SEQ_TO_SN(tid_data->seq_number); | ||
1077 | int tx_fifo = get_fifo_from_tid(tid); | ||
1078 | IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n"); | ||
1079 | priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, | ||
1080 | ssn, tx_fifo); | ||
1081 | tid_data->agg.state = IWL_AGG_OFF; | ||
1082 | ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, addr, tid); | ||
1083 | } | ||
1084 | break; | ||
1085 | case IWL_EMPTYING_HW_QUEUE_ADDBA: | ||
1086 | /* We are reclaiming the last packet of the queue */ | ||
1087 | if (tid_data->tfds_in_queue == 0) { | ||
1088 | IWL_DEBUG_HT(priv, "HW queue empty: continue ADDBA flow\n"); | ||
1089 | tid_data->agg.state = IWL_AGG_ON; | ||
1090 | ieee80211_start_tx_ba_cb_irqsafe(priv->vif, addr, tid); | ||
1091 | } | ||
1092 | break; | ||
1093 | } | ||
1094 | return 0; | ||
1095 | } | ||
1096 | |||
1097 | static void iwlagn_tx_status(struct iwl_priv *priv, struct sk_buff *skb) | ||
1098 | { | ||
1099 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
1100 | struct ieee80211_sta *sta; | ||
1101 | struct iwl_station_priv *sta_priv; | ||
1102 | |||
1103 | sta = ieee80211_find_sta(priv->vif, hdr->addr1); | ||
1104 | if (sta) { | ||
1105 | sta_priv = (void *)sta->drv_priv; | ||
1106 | /* avoid atomic ops if this isn't a client */ | ||
1107 | if (sta_priv->client && | ||
1108 | atomic_dec_return(&sta_priv->pending_frames) == 0) | ||
1109 | ieee80211_sta_block_awake(priv->hw, sta, false); | ||
1110 | } | ||
1111 | |||
1112 | ieee80211_tx_status_irqsafe(priv->hw, skb); | ||
1113 | } | ||
1114 | |||
1115 | int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) | ||
1116 | { | ||
1117 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; | ||
1118 | struct iwl_queue *q = &txq->q; | ||
1119 | struct iwl_tx_info *tx_info; | ||
1120 | int nfreed = 0; | ||
1121 | struct ieee80211_hdr *hdr; | ||
1122 | |||
1123 | if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) { | ||
1124 | IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, " | ||
1125 | "is out of range [0-%d] %d %d.\n", txq_id, | ||
1126 | index, q->n_bd, q->write_ptr, q->read_ptr); | ||
1127 | return 0; | ||
1128 | } | ||
1129 | |||
1130 | for (index = iwl_queue_inc_wrap(index, q->n_bd); | ||
1131 | q->read_ptr != index; | ||
1132 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { | ||
1133 | |||
1134 | tx_info = &txq->txb[txq->q.read_ptr]; | ||
1135 | iwlagn_tx_status(priv, tx_info->skb[0]); | ||
1136 | |||
1137 | hdr = (struct ieee80211_hdr *)tx_info->skb[0]->data; | ||
1138 | if (hdr && ieee80211_is_data_qos(hdr->frame_control)) | ||
1139 | nfreed++; | ||
1140 | tx_info->skb[0] = NULL; | ||
1141 | |||
1142 | if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl) | ||
1143 | priv->cfg->ops->lib->txq_inval_byte_cnt_tbl(priv, txq); | ||
1144 | |||
1145 | priv->cfg->ops->lib->txq_free_tfd(priv, txq); | ||
1146 | } | ||
1147 | return nfreed; | ||
1148 | } | ||
1149 | |||
1150 | /** | ||
1151 | * iwlagn_tx_status_reply_compressed_ba - Update tx status from block-ack | ||
1152 | * | ||
1153 | * Go through block-ack's bitmap of ACK'd frames, update driver's record of | ||
1154 | * ACK vs. not. This gets sent to mac80211, then to rate scaling algo. | ||
1155 | */ | ||
1156 | static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv, | ||
1157 | struct iwl_ht_agg *agg, | ||
1158 | struct iwl_compressed_ba_resp *ba_resp) | ||
1159 | |||
1160 | { | ||
1161 | int i, sh, ack; | ||
1162 | u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl); | ||
1163 | u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); | ||
1164 | u64 bitmap; | ||
1165 | int successes = 0; | ||
1166 | struct ieee80211_tx_info *info; | ||
1167 | |||
1168 | if (unlikely(!agg->wait_for_ba)) { | ||
1169 | IWL_ERR(priv, "Received BA when not expected\n"); | ||
1170 | return -EINVAL; | ||
1171 | } | ||
1172 | |||
1173 | /* Mark that the expected block-ack response arrived */ | ||
1174 | agg->wait_for_ba = 0; | ||
1175 | IWL_DEBUG_TX_REPLY(priv, "BA %d %d\n", agg->start_idx, ba_resp->seq_ctl); | ||
1176 | |||
1177 | /* Calculate shift to align block-ack bits with our Tx window bits */ | ||
1178 | sh = agg->start_idx - SEQ_TO_INDEX(seq_ctl >> 4); | ||
1179 | if (sh < 0) /* tbw something is wrong with indices */ | ||
1180 | sh += 0x100; | ||
1181 | |||
1182 | /* don't use 64-bit values for now */ | ||
1183 | bitmap = le64_to_cpu(ba_resp->bitmap) >> sh; | ||
1184 | |||
1185 | if (agg->frame_count > (64 - sh)) { | ||
1186 | IWL_DEBUG_TX_REPLY(priv, "more frames than bitmap size"); | ||
1187 | return -1; | ||
1188 | } | ||
1189 | |||
1190 | /* check for success or failure according to the | ||
1191 | * transmitted bitmap and block-ack bitmap */ | ||
1192 | bitmap &= agg->bitmap; | ||
1193 | |||
1194 | /* For each frame attempted in aggregation, | ||
1195 | * update driver's record of tx frame's status. */ | ||
1196 | for (i = 0; i < agg->frame_count ; i++) { | ||
1197 | ack = bitmap & (1ULL << i); | ||
1198 | successes += !!ack; | ||
1199 | IWL_DEBUG_TX_REPLY(priv, "%s ON i=%d idx=%d raw=%d\n", | ||
1200 | ack ? "ACK" : "NACK", i, (agg->start_idx + i) & 0xff, | ||
1201 | agg->start_idx + i); | ||
1202 | } | ||
1203 | |||
1204 | info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb[0]); | ||
1205 | memset(&info->status, 0, sizeof(info->status)); | ||
1206 | info->flags |= IEEE80211_TX_STAT_ACK; | ||
1207 | info->flags |= IEEE80211_TX_STAT_AMPDU; | ||
1208 | info->status.ampdu_ack_map = successes; | ||
1209 | info->status.ampdu_ack_len = agg->frame_count; | ||
1210 | iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, info); | ||
1211 | |||
1212 | IWL_DEBUG_TX_REPLY(priv, "Bitmap %llx\n", (unsigned long long)bitmap); | ||
1213 | |||
1214 | return 0; | ||
1215 | } | ||
1216 | |||
1217 | /** | ||
1218 | * translate ucode response to mac80211 tx status control values | ||
1219 | */ | ||
1220 | void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, | ||
1221 | struct ieee80211_tx_info *info) | ||
1222 | { | ||
1223 | struct ieee80211_tx_rate *r = &info->control.rates[0]; | ||
1224 | |||
1225 | info->antenna_sel_tx = | ||
1226 | ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS); | ||
1227 | if (rate_n_flags & RATE_MCS_HT_MSK) | ||
1228 | r->flags |= IEEE80211_TX_RC_MCS; | ||
1229 | if (rate_n_flags & RATE_MCS_GF_MSK) | ||
1230 | r->flags |= IEEE80211_TX_RC_GREEN_FIELD; | ||
1231 | if (rate_n_flags & RATE_MCS_HT40_MSK) | ||
1232 | r->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; | ||
1233 | if (rate_n_flags & RATE_MCS_DUP_MSK) | ||
1234 | r->flags |= IEEE80211_TX_RC_DUP_DATA; | ||
1235 | if (rate_n_flags & RATE_MCS_SGI_MSK) | ||
1236 | r->flags |= IEEE80211_TX_RC_SHORT_GI; | ||
1237 | r->idx = iwlagn_hwrate_to_mac80211_idx(rate_n_flags, info->band); | ||
1238 | } | ||
1239 | |||
1240 | /** | ||
1241 | * iwlagn_rx_reply_compressed_ba - Handler for REPLY_COMPRESSED_BA | ||
1242 | * | ||
1243 | * Handles block-acknowledge notification from device, which reports success | ||
1244 | * of frames sent via aggregation. | ||
1245 | */ | ||
1246 | void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, | ||
1247 | struct iwl_rx_mem_buffer *rxb) | ||
1248 | { | ||
1249 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
1250 | struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba; | ||
1251 | struct iwl_tx_queue *txq = NULL; | ||
1252 | struct iwl_ht_agg *agg; | ||
1253 | int index; | ||
1254 | int sta_id; | ||
1255 | int tid; | ||
1256 | |||
1257 | /* "flow" corresponds to Tx queue */ | ||
1258 | u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); | ||
1259 | |||
1260 | /* "ssn" is start of block-ack Tx window, corresponds to index | ||
1261 | * (in Tx queue's circular buffer) of first TFD/frame in window */ | ||
1262 | u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn); | ||
1263 | |||
1264 | if (scd_flow >= priv->hw_params.max_txq_num) { | ||
1265 | IWL_ERR(priv, | ||
1266 | "BUG_ON scd_flow is bigger than number of queues\n"); | ||
1267 | return; | ||
1268 | } | ||
1269 | |||
1270 | txq = &priv->txq[scd_flow]; | ||
1271 | sta_id = ba_resp->sta_id; | ||
1272 | tid = ba_resp->tid; | ||
1273 | agg = &priv->stations[sta_id].tid[tid].agg; | ||
1274 | |||
1275 | /* Find index just before block-ack window */ | ||
1276 | index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd); | ||
1277 | |||
1278 | /* TODO: Need to get this copy more safely - now good for debug */ | ||
1279 | |||
1280 | IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, " | ||
1281 | "sta_id = %d\n", | ||
1282 | agg->wait_for_ba, | ||
1283 | (u8 *) &ba_resp->sta_addr_lo32, | ||
1284 | ba_resp->sta_id); | ||
1285 | IWL_DEBUG_TX_REPLY(priv, "TID = %d, SeqCtl = %d, bitmap = 0x%llx, scd_flow = " | ||
1286 | "%d, scd_ssn = %d\n", | ||
1287 | ba_resp->tid, | ||
1288 | ba_resp->seq_ctl, | ||
1289 | (unsigned long long)le64_to_cpu(ba_resp->bitmap), | ||
1290 | ba_resp->scd_flow, | ||
1291 | ba_resp->scd_ssn); | ||
1292 | IWL_DEBUG_TX_REPLY(priv, "DAT start_idx = %d, bitmap = 0x%llx\n", | ||
1293 | agg->start_idx, | ||
1294 | (unsigned long long)agg->bitmap); | ||
1295 | |||
1296 | /* Update driver's record of ACK vs. not for each frame in window */ | ||
1297 | iwlagn_tx_status_reply_compressed_ba(priv, agg, ba_resp); | ||
1298 | |||
1299 | /* Release all TFDs before the SSN, i.e. all TFDs in front of | ||
1300 | * block-ack window (we assume that they've been successfully | ||
1301 | * transmitted ... if not, it's too late anyway). */ | ||
1302 | if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) { | ||
1303 | /* calculate mac80211 ampdu sw queue to wake */ | ||
1304 | int freed = iwlagn_tx_queue_reclaim(priv, scd_flow, index); | ||
1305 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); | ||
1306 | |||
1307 | if ((iwl_queue_space(&txq->q) > txq->q.low_mark) && | ||
1308 | priv->mac80211_registered && | ||
1309 | (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) | ||
1310 | iwl_wake_queue(priv, txq->swq_id); | ||
1311 | |||
1312 | iwlagn_txq_check_empty(priv, sta_id, tid, scd_flow); | ||
1313 | } | ||
1314 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c new file mode 100644 index 000000000000..52ae157968b2 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | |||
@@ -0,0 +1,416 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * GPL LICENSE SUMMARY | ||
4 | * | ||
5 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of version 2 of the GNU General Public License as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
19 | * USA | ||
20 | * | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
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/sched.h> | ||
34 | |||
35 | #include "iwl-dev.h" | ||
36 | #include "iwl-core.h" | ||
37 | #include "iwl-io.h" | ||
38 | #include "iwl-helpers.h" | ||
39 | #include "iwl-agn-hw.h" | ||
40 | #include "iwl-agn.h" | ||
41 | |||
42 | static const s8 iwlagn_default_queue_to_tx_fifo[] = { | ||
43 | IWL_TX_FIFO_VO, | ||
44 | IWL_TX_FIFO_VI, | ||
45 | IWL_TX_FIFO_BE, | ||
46 | IWL_TX_FIFO_BK, | ||
47 | IWLAGN_CMD_FIFO_NUM, | ||
48 | IWL_TX_FIFO_UNUSED, | ||
49 | IWL_TX_FIFO_UNUSED, | ||
50 | IWL_TX_FIFO_UNUSED, | ||
51 | IWL_TX_FIFO_UNUSED, | ||
52 | IWL_TX_FIFO_UNUSED, | ||
53 | }; | ||
54 | |||
55 | /* | ||
56 | * ucode | ||
57 | */ | ||
58 | static int iwlagn_load_section(struct iwl_priv *priv, const char *name, | ||
59 | struct fw_desc *image, u32 dst_addr) | ||
60 | { | ||
61 | dma_addr_t phy_addr = image->p_addr; | ||
62 | u32 byte_cnt = image->len; | ||
63 | int ret; | ||
64 | |||
65 | priv->ucode_write_complete = 0; | ||
66 | |||
67 | iwl_write_direct32(priv, | ||
68 | FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), | ||
69 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE); | ||
70 | |||
71 | iwl_write_direct32(priv, | ||
72 | FH_SRVC_CHNL_SRAM_ADDR_REG(FH_SRVC_CHNL), dst_addr); | ||
73 | |||
74 | iwl_write_direct32(priv, | ||
75 | FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL), | ||
76 | phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK); | ||
77 | |||
78 | iwl_write_direct32(priv, | ||
79 | FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL), | ||
80 | (iwl_get_dma_hi_addr(phy_addr) | ||
81 | << FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt); | ||
82 | |||
83 | iwl_write_direct32(priv, | ||
84 | FH_TCSR_CHNL_TX_BUF_STS_REG(FH_SRVC_CHNL), | ||
85 | 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM | | ||
86 | 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX | | ||
87 | FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID); | ||
88 | |||
89 | iwl_write_direct32(priv, | ||
90 | FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), | ||
91 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | | ||
92 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | | ||
93 | FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); | ||
94 | |||
95 | IWL_DEBUG_INFO(priv, "%s uCode section being loaded...\n", name); | ||
96 | ret = wait_event_interruptible_timeout(priv->wait_command_queue, | ||
97 | priv->ucode_write_complete, 5 * HZ); | ||
98 | if (ret == -ERESTARTSYS) { | ||
99 | IWL_ERR(priv, "Could not load the %s uCode section due " | ||
100 | "to interrupt\n", name); | ||
101 | return ret; | ||
102 | } | ||
103 | if (!ret) { | ||
104 | IWL_ERR(priv, "Could not load the %s uCode section\n", | ||
105 | name); | ||
106 | return -ETIMEDOUT; | ||
107 | } | ||
108 | |||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | static int iwlagn_load_given_ucode(struct iwl_priv *priv, | ||
113 | struct fw_desc *inst_image, | ||
114 | struct fw_desc *data_image) | ||
115 | { | ||
116 | int ret = 0; | ||
117 | |||
118 | ret = iwlagn_load_section(priv, "INST", inst_image, | ||
119 | IWLAGN_RTC_INST_LOWER_BOUND); | ||
120 | if (ret) | ||
121 | return ret; | ||
122 | |||
123 | return iwlagn_load_section(priv, "DATA", data_image, | ||
124 | IWLAGN_RTC_DATA_LOWER_BOUND); | ||
125 | } | ||
126 | |||
127 | int iwlagn_load_ucode(struct iwl_priv *priv) | ||
128 | { | ||
129 | int ret = 0; | ||
130 | |||
131 | /* check whether init ucode should be loaded, or rather runtime ucode */ | ||
132 | if (priv->ucode_init.len && (priv->ucode_type == UCODE_NONE)) { | ||
133 | IWL_DEBUG_INFO(priv, "Init ucode found. Loading init ucode...\n"); | ||
134 | ret = iwlagn_load_given_ucode(priv, | ||
135 | &priv->ucode_init, &priv->ucode_init_data); | ||
136 | if (!ret) { | ||
137 | IWL_DEBUG_INFO(priv, "Init ucode load complete.\n"); | ||
138 | priv->ucode_type = UCODE_INIT; | ||
139 | } | ||
140 | } else { | ||
141 | IWL_DEBUG_INFO(priv, "Init ucode not found, or already loaded. " | ||
142 | "Loading runtime ucode...\n"); | ||
143 | ret = iwlagn_load_given_ucode(priv, | ||
144 | &priv->ucode_code, &priv->ucode_data); | ||
145 | if (!ret) { | ||
146 | IWL_DEBUG_INFO(priv, "Runtime ucode load complete.\n"); | ||
147 | priv->ucode_type = UCODE_RT; | ||
148 | } | ||
149 | } | ||
150 | |||
151 | return ret; | ||
152 | } | ||
153 | |||
154 | #define IWL_UCODE_GET(item) \ | ||
155 | static u32 iwlagn_ucode_get_##item(const struct iwl_ucode_header *ucode,\ | ||
156 | u32 api_ver) \ | ||
157 | { \ | ||
158 | if (api_ver <= 2) \ | ||
159 | return le32_to_cpu(ucode->u.v1.item); \ | ||
160 | return le32_to_cpu(ucode->u.v2.item); \ | ||
161 | } | ||
162 | |||
163 | static u32 iwlagn_ucode_get_header_size(u32 api_ver) | ||
164 | { | ||
165 | if (api_ver <= 2) | ||
166 | return UCODE_HEADER_SIZE(1); | ||
167 | return UCODE_HEADER_SIZE(2); | ||
168 | } | ||
169 | |||
170 | static u32 iwlagn_ucode_get_build(const struct iwl_ucode_header *ucode, | ||
171 | u32 api_ver) | ||
172 | { | ||
173 | if (api_ver <= 2) | ||
174 | return 0; | ||
175 | return le32_to_cpu(ucode->u.v2.build); | ||
176 | } | ||
177 | |||
178 | static u8 *iwlagn_ucode_get_data(const struct iwl_ucode_header *ucode, | ||
179 | u32 api_ver) | ||
180 | { | ||
181 | if (api_ver <= 2) | ||
182 | return (u8 *) ucode->u.v1.data; | ||
183 | return (u8 *) ucode->u.v2.data; | ||
184 | } | ||
185 | |||
186 | IWL_UCODE_GET(inst_size); | ||
187 | IWL_UCODE_GET(data_size); | ||
188 | IWL_UCODE_GET(init_size); | ||
189 | IWL_UCODE_GET(init_data_size); | ||
190 | IWL_UCODE_GET(boot_size); | ||
191 | |||
192 | struct iwl_ucode_ops iwlagn_ucode = { | ||
193 | .get_header_size = iwlagn_ucode_get_header_size, | ||
194 | .get_build = iwlagn_ucode_get_build, | ||
195 | .get_inst_size = iwlagn_ucode_get_inst_size, | ||
196 | .get_data_size = iwlagn_ucode_get_data_size, | ||
197 | .get_init_size = iwlagn_ucode_get_init_size, | ||
198 | .get_init_data_size = iwlagn_ucode_get_init_data_size, | ||
199 | .get_boot_size = iwlagn_ucode_get_boot_size, | ||
200 | .get_data = iwlagn_ucode_get_data, | ||
201 | }; | ||
202 | |||
203 | /* | ||
204 | * Calibration | ||
205 | */ | ||
206 | static int iwlagn_set_Xtal_calib(struct iwl_priv *priv) | ||
207 | { | ||
208 | struct iwl_calib_xtal_freq_cmd cmd; | ||
209 | __le16 *xtal_calib = | ||
210 | (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_XTAL); | ||
211 | |||
212 | cmd.hdr.op_code = IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD; | ||
213 | cmd.hdr.first_group = 0; | ||
214 | cmd.hdr.groups_num = 1; | ||
215 | cmd.hdr.data_valid = 1; | ||
216 | cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]); | ||
217 | cmd.cap_pin2 = le16_to_cpu(xtal_calib[1]); | ||
218 | return iwl_calib_set(&priv->calib_results[IWL_CALIB_XTAL], | ||
219 | (u8 *)&cmd, sizeof(cmd)); | ||
220 | } | ||
221 | |||
222 | static int iwlagn_send_calib_cfg(struct iwl_priv *priv) | ||
223 | { | ||
224 | struct iwl_calib_cfg_cmd calib_cfg_cmd; | ||
225 | struct iwl_host_cmd cmd = { | ||
226 | .id = CALIBRATION_CFG_CMD, | ||
227 | .len = sizeof(struct iwl_calib_cfg_cmd), | ||
228 | .data = &calib_cfg_cmd, | ||
229 | }; | ||
230 | |||
231 | memset(&calib_cfg_cmd, 0, sizeof(calib_cfg_cmd)); | ||
232 | calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_INIT_CFG_ALL; | ||
233 | calib_cfg_cmd.ucd_calib_cfg.once.start = IWL_CALIB_INIT_CFG_ALL; | ||
234 | calib_cfg_cmd.ucd_calib_cfg.once.send_res = IWL_CALIB_INIT_CFG_ALL; | ||
235 | calib_cfg_cmd.ucd_calib_cfg.flags = IWL_CALIB_INIT_CFG_ALL; | ||
236 | |||
237 | return iwl_send_cmd(priv, &cmd); | ||
238 | } | ||
239 | |||
240 | void iwlagn_rx_calib_result(struct iwl_priv *priv, | ||
241 | struct iwl_rx_mem_buffer *rxb) | ||
242 | { | ||
243 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
244 | struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw; | ||
245 | int len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | ||
246 | int index; | ||
247 | |||
248 | /* reduce the size of the length field itself */ | ||
249 | len -= 4; | ||
250 | |||
251 | /* Define the order in which the results will be sent to the runtime | ||
252 | * uCode. iwl_send_calib_results sends them in a row according to | ||
253 | * their index. We sort them here | ||
254 | */ | ||
255 | switch (hdr->op_code) { | ||
256 | case IWL_PHY_CALIBRATE_DC_CMD: | ||
257 | index = IWL_CALIB_DC; | ||
258 | break; | ||
259 | case IWL_PHY_CALIBRATE_LO_CMD: | ||
260 | index = IWL_CALIB_LO; | ||
261 | break; | ||
262 | case IWL_PHY_CALIBRATE_TX_IQ_CMD: | ||
263 | index = IWL_CALIB_TX_IQ; | ||
264 | break; | ||
265 | case IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD: | ||
266 | index = IWL_CALIB_TX_IQ_PERD; | ||
267 | break; | ||
268 | case IWL_PHY_CALIBRATE_BASE_BAND_CMD: | ||
269 | index = IWL_CALIB_BASE_BAND; | ||
270 | break; | ||
271 | default: | ||
272 | IWL_ERR(priv, "Unknown calibration notification %d\n", | ||
273 | hdr->op_code); | ||
274 | return; | ||
275 | } | ||
276 | iwl_calib_set(&priv->calib_results[index], pkt->u.raw, len); | ||
277 | } | ||
278 | |||
279 | void iwlagn_rx_calib_complete(struct iwl_priv *priv, | ||
280 | struct iwl_rx_mem_buffer *rxb) | ||
281 | { | ||
282 | IWL_DEBUG_INFO(priv, "Init. calibration is completed, restarting fw.\n"); | ||
283 | queue_work(priv->workqueue, &priv->restart); | ||
284 | } | ||
285 | |||
286 | void iwlagn_init_alive_start(struct iwl_priv *priv) | ||
287 | { | ||
288 | int ret = 0; | ||
289 | |||
290 | /* Check alive response for "valid" sign from uCode */ | ||
291 | if (priv->card_alive_init.is_valid != UCODE_VALID_OK) { | ||
292 | /* We had an error bringing up the hardware, so take it | ||
293 | * all the way back down so we can try again */ | ||
294 | IWL_DEBUG_INFO(priv, "Initialize Alive failed.\n"); | ||
295 | goto restart; | ||
296 | } | ||
297 | |||
298 | /* initialize uCode was loaded... verify inst image. | ||
299 | * This is a paranoid check, because we would not have gotten the | ||
300 | * "initialize" alive if code weren't properly loaded. */ | ||
301 | if (iwl_verify_ucode(priv)) { | ||
302 | /* Runtime instruction load was bad; | ||
303 | * take it all the way back down so we can try again */ | ||
304 | IWL_DEBUG_INFO(priv, "Bad \"initialize\" uCode load.\n"); | ||
305 | goto restart; | ||
306 | } | ||
307 | |||
308 | ret = priv->cfg->ops->lib->alive_notify(priv); | ||
309 | if (ret) { | ||
310 | IWL_WARN(priv, | ||
311 | "Could not complete ALIVE transition: %d\n", ret); | ||
312 | goto restart; | ||
313 | } | ||
314 | |||
315 | iwlagn_send_calib_cfg(priv); | ||
316 | return; | ||
317 | |||
318 | restart: | ||
319 | /* real restart (first load init_ucode) */ | ||
320 | queue_work(priv->workqueue, &priv->restart); | ||
321 | } | ||
322 | |||
323 | int iwlagn_alive_notify(struct iwl_priv *priv) | ||
324 | { | ||
325 | u32 a; | ||
326 | unsigned long flags; | ||
327 | int i, chan; | ||
328 | u32 reg_val; | ||
329 | |||
330 | spin_lock_irqsave(&priv->lock, flags); | ||
331 | |||
332 | priv->scd_base_addr = iwl_read_prph(priv, IWL50_SCD_SRAM_BASE_ADDR); | ||
333 | a = priv->scd_base_addr + IWL50_SCD_CONTEXT_DATA_OFFSET; | ||
334 | for (; a < priv->scd_base_addr + IWL50_SCD_TX_STTS_BITMAP_OFFSET; | ||
335 | a += 4) | ||
336 | iwl_write_targ_mem(priv, a, 0); | ||
337 | for (; a < priv->scd_base_addr + IWL50_SCD_TRANSLATE_TBL_OFFSET; | ||
338 | a += 4) | ||
339 | iwl_write_targ_mem(priv, a, 0); | ||
340 | for (; a < priv->scd_base_addr + | ||
341 | IWL50_SCD_TRANSLATE_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4) | ||
342 | iwl_write_targ_mem(priv, a, 0); | ||
343 | |||
344 | iwl_write_prph(priv, IWL50_SCD_DRAM_BASE_ADDR, | ||
345 | priv->scd_bc_tbls.dma >> 10); | ||
346 | |||
347 | /* Enable DMA channel */ | ||
348 | for (chan = 0; chan < FH50_TCSR_CHNL_NUM ; chan++) | ||
349 | iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(chan), | ||
350 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | | ||
351 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE); | ||
352 | |||
353 | /* Update FH chicken bits */ | ||
354 | reg_val = iwl_read_direct32(priv, FH_TX_CHICKEN_BITS_REG); | ||
355 | iwl_write_direct32(priv, FH_TX_CHICKEN_BITS_REG, | ||
356 | reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); | ||
357 | |||
358 | iwl_write_prph(priv, IWL50_SCD_QUEUECHAIN_SEL, | ||
359 | IWL50_SCD_QUEUECHAIN_SEL_ALL(priv->hw_params.max_txq_num)); | ||
360 | iwl_write_prph(priv, IWL50_SCD_AGGR_SEL, 0); | ||
361 | |||
362 | /* initiate the queues */ | ||
363 | for (i = 0; i < priv->hw_params.max_txq_num; i++) { | ||
364 | iwl_write_prph(priv, IWL50_SCD_QUEUE_RDPTR(i), 0); | ||
365 | iwl_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8)); | ||
366 | iwl_write_targ_mem(priv, priv->scd_base_addr + | ||
367 | IWL50_SCD_CONTEXT_QUEUE_OFFSET(i), 0); | ||
368 | iwl_write_targ_mem(priv, priv->scd_base_addr + | ||
369 | IWL50_SCD_CONTEXT_QUEUE_OFFSET(i) + | ||
370 | sizeof(u32), | ||
371 | ((SCD_WIN_SIZE << | ||
372 | IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & | ||
373 | IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | | ||
374 | ((SCD_FRAME_LIMIT << | ||
375 | IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & | ||
376 | IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); | ||
377 | } | ||
378 | |||
379 | iwl_write_prph(priv, IWL50_SCD_INTERRUPT_MASK, | ||
380 | IWL_MASK(0, priv->hw_params.max_txq_num)); | ||
381 | |||
382 | /* Activate all Tx DMA/FIFO channels */ | ||
383 | priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 7)); | ||
384 | |||
385 | iwlagn_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); | ||
386 | |||
387 | /* make sure all queue are not stopped */ | ||
388 | memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); | ||
389 | for (i = 0; i < 4; i++) | ||
390 | atomic_set(&priv->queue_stop_count[i], 0); | ||
391 | |||
392 | /* reset to 0 to enable all the queue first */ | ||
393 | priv->txq_ctx_active_msk = 0; | ||
394 | /* map qos queues to fifos one-to-one */ | ||
395 | BUILD_BUG_ON(ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo) != 10); | ||
396 | |||
397 | for (i = 0; i < ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo); i++) { | ||
398 | int ac = iwlagn_default_queue_to_tx_fifo[i]; | ||
399 | |||
400 | iwl_txq_ctx_activate(priv, i); | ||
401 | |||
402 | if (ac == IWL_TX_FIFO_UNUSED) | ||
403 | continue; | ||
404 | |||
405 | iwlagn_tx_queue_set_status(priv, &priv->txq[i], ac, 0); | ||
406 | } | ||
407 | |||
408 | spin_unlock_irqrestore(&priv->lock, flags); | ||
409 | |||
410 | iwl_send_wimax_coex(priv); | ||
411 | |||
412 | iwlagn_set_Xtal_calib(priv); | ||
413 | iwl_send_calib_results(priv); | ||
414 | |||
415 | return 0; | ||
416 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index e4c2e1e448ad..4f0cb803f732 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -54,6 +54,7 @@ | |||
54 | #include "iwl-helpers.h" | 54 | #include "iwl-helpers.h" |
55 | #include "iwl-sta.h" | 55 | #include "iwl-sta.h" |
56 | #include "iwl-calib.h" | 56 | #include "iwl-calib.h" |
57 | #include "iwl-agn.h" | ||
57 | 58 | ||
58 | 59 | ||
59 | /****************************************************************************** | 60 | /****************************************************************************** |
@@ -82,13 +83,6 @@ MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); | |||
82 | MODULE_LICENSE("GPL"); | 83 | MODULE_LICENSE("GPL"); |
83 | MODULE_ALIAS("iwl4965"); | 84 | MODULE_ALIAS("iwl4965"); |
84 | 85 | ||
85 | /*************** STATION TABLE MANAGEMENT **** | ||
86 | * mac80211 should be examined to determine if sta_info is duplicating | ||
87 | * the functionality provided here | ||
88 | */ | ||
89 | |||
90 | /**************************************************************/ | ||
91 | |||
92 | /** | 86 | /** |
93 | * iwl_commit_rxon - commit staging_rxon to hardware | 87 | * iwl_commit_rxon - commit staging_rxon to hardware |
94 | * | 88 | * |
@@ -143,9 +137,6 @@ int iwl_commit_rxon(struct iwl_priv *priv) | |||
143 | return 0; | 137 | return 0; |
144 | } | 138 | } |
145 | 139 | ||
146 | /* station table will be cleared */ | ||
147 | priv->assoc_station_added = 0; | ||
148 | |||
149 | /* If we are currently associated and the new config requires | 140 | /* If we are currently associated and the new config requires |
150 | * an RXON_ASSOC and the new config wants the associated mask enabled, | 141 | * an RXON_ASSOC and the new config wants the associated mask enabled, |
151 | * we must clear the associated from the active configuration | 142 | * we must clear the associated from the active configuration |
@@ -165,6 +156,8 @@ int iwl_commit_rxon(struct iwl_priv *priv) | |||
165 | IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret); | 156 | IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret); |
166 | return ret; | 157 | return ret; |
167 | } | 158 | } |
159 | iwl_clear_ucode_stations(priv, false); | ||
160 | iwl_restore_stations(priv); | ||
168 | } | 161 | } |
169 | 162 | ||
170 | IWL_DEBUG_INFO(priv, "Sending RXON\n" | 163 | IWL_DEBUG_INFO(priv, "Sending RXON\n" |
@@ -178,9 +171,8 @@ int iwl_commit_rxon(struct iwl_priv *priv) | |||
178 | iwl_set_rxon_hwcrypto(priv, !priv->cfg->mod_params->sw_crypto); | 171 | iwl_set_rxon_hwcrypto(priv, !priv->cfg->mod_params->sw_crypto); |
179 | 172 | ||
180 | /* Apply the new configuration | 173 | /* Apply the new configuration |
181 | * RXON unassoc clears the station table in uCode, send it before | 174 | * RXON unassoc clears the station table in uCode so restoration of |
182 | * we add the bcast station. If assoc bit is set, we will send RXON | 175 | * stations is needed after it (the RXON command) completes |
183 | * after having added the bcast and bssid station. | ||
184 | */ | 176 | */ |
185 | if (!new_assoc) { | 177 | if (!new_assoc) { |
186 | ret = iwl_send_cmd_pdu(priv, REPLY_RXON, | 178 | ret = iwl_send_cmd_pdu(priv, REPLY_RXON, |
@@ -189,35 +181,14 @@ int iwl_commit_rxon(struct iwl_priv *priv) | |||
189 | IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); | 181 | IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); |
190 | return ret; | 182 | return ret; |
191 | } | 183 | } |
184 | IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON.\n"); | ||
192 | memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); | 185 | memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); |
186 | iwl_clear_ucode_stations(priv, false); | ||
187 | iwl_restore_stations(priv); | ||
193 | } | 188 | } |
194 | 189 | ||
195 | iwl_clear_stations_table(priv); | ||
196 | |||
197 | priv->start_calib = 0; | 190 | priv->start_calib = 0; |
198 | |||
199 | /* Add the broadcast address so we can send broadcast frames */ | ||
200 | priv->cfg->ops->lib->add_bcast_station(priv); | ||
201 | |||
202 | |||
203 | /* If we have set the ASSOC_MSK and we are in BSS mode then | ||
204 | * add the IWL_AP_ID to the station rate table */ | ||
205 | if (new_assoc) { | 191 | if (new_assoc) { |
206 | if (priv->iw_mode == NL80211_IFTYPE_STATION) { | ||
207 | ret = iwl_rxon_add_station(priv, | ||
208 | priv->active_rxon.bssid_addr, 1); | ||
209 | if (ret == IWL_INVALID_STATION) { | ||
210 | IWL_ERR(priv, | ||
211 | "Error adding AP address for TX.\n"); | ||
212 | return -EIO; | ||
213 | } | ||
214 | priv->assoc_station_added = 1; | ||
215 | if (priv->default_wep_key && | ||
216 | iwl_send_static_wepkey_cmd(priv, 0)) | ||
217 | IWL_ERR(priv, | ||
218 | "Could not send WEP static key.\n"); | ||
219 | } | ||
220 | |||
221 | /* | 192 | /* |
222 | * allow CTS-to-self if possible for new association. | 193 | * allow CTS-to-self if possible for new association. |
223 | * this is relevant only for 5000 series and up, | 194 | * this is relevant only for 5000 series and up, |
@@ -906,10 +877,10 @@ static void iwl_setup_rx_handlers(struct iwl_priv *priv) | |||
906 | priv->rx_handlers[MISSED_BEACONS_NOTIFICATION] = | 877 | priv->rx_handlers[MISSED_BEACONS_NOTIFICATION] = |
907 | iwl_rx_missed_beacon_notif; | 878 | iwl_rx_missed_beacon_notif; |
908 | /* Rx handlers */ | 879 | /* Rx handlers */ |
909 | priv->rx_handlers[REPLY_RX_PHY_CMD] = iwl_rx_reply_rx_phy; | 880 | priv->rx_handlers[REPLY_RX_PHY_CMD] = iwlagn_rx_reply_rx_phy; |
910 | priv->rx_handlers[REPLY_RX_MPDU_CMD] = iwl_rx_reply_rx; | 881 | priv->rx_handlers[REPLY_RX_MPDU_CMD] = iwlagn_rx_reply_rx; |
911 | /* block ack */ | 882 | /* block ack */ |
912 | priv->rx_handlers[REPLY_COMPRESSED_BA] = iwl_rx_reply_compressed_ba; | 883 | priv->rx_handlers[REPLY_COMPRESSED_BA] = iwlagn_rx_reply_compressed_ba; |
913 | /* Set up hardware specific Rx handlers */ | 884 | /* Set up hardware specific Rx handlers */ |
914 | priv->cfg->ops->lib->rx_handler_setup(priv); | 885 | priv->cfg->ops->lib->rx_handler_setup(priv); |
915 | } | 886 | } |
@@ -1037,7 +1008,7 @@ void iwl_rx_handle(struct iwl_priv *priv) | |||
1037 | count++; | 1008 | count++; |
1038 | if (count >= 8) { | 1009 | if (count >= 8) { |
1039 | rxq->read = i; | 1010 | rxq->read = i; |
1040 | iwl_rx_replenish_now(priv); | 1011 | iwlagn_rx_replenish_now(priv); |
1041 | count = 0; | 1012 | count = 0; |
1042 | } | 1013 | } |
1043 | } | 1014 | } |
@@ -1046,9 +1017,9 @@ void iwl_rx_handle(struct iwl_priv *priv) | |||
1046 | /* Backtrack one entry */ | 1017 | /* Backtrack one entry */ |
1047 | rxq->read = i; | 1018 | rxq->read = i; |
1048 | if (fill_rx) | 1019 | if (fill_rx) |
1049 | iwl_rx_replenish_now(priv); | 1020 | iwlagn_rx_replenish_now(priv); |
1050 | else | 1021 | else |
1051 | iwl_rx_queue_restock(priv); | 1022 | iwlagn_rx_queue_restock(priv); |
1052 | } | 1023 | } |
1053 | 1024 | ||
1054 | /* call this function to flush any scheduled tasklet */ | 1025 | /* call this function to flush any scheduled tasklet */ |
@@ -1266,9 +1237,9 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) | |||
1266 | * hardware bugs here by ACKing all the possible interrupts so that | 1237 | * hardware bugs here by ACKing all the possible interrupts so that |
1267 | * interrupt coalescing can still be achieved. | 1238 | * interrupt coalescing can still be achieved. |
1268 | */ | 1239 | */ |
1269 | iwl_write32(priv, CSR_INT, priv->inta | ~priv->inta_mask); | 1240 | iwl_write32(priv, CSR_INT, priv->_agn.inta | ~priv->inta_mask); |
1270 | 1241 | ||
1271 | inta = priv->inta; | 1242 | inta = priv->_agn.inta; |
1272 | 1243 | ||
1273 | #ifdef CONFIG_IWLWIFI_DEBUG | 1244 | #ifdef CONFIG_IWLWIFI_DEBUG |
1274 | if (iwl_get_debug_level(priv) & IWL_DL_ISR) { | 1245 | if (iwl_get_debug_level(priv) & IWL_DL_ISR) { |
@@ -1281,8 +1252,8 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) | |||
1281 | 1252 | ||
1282 | spin_unlock_irqrestore(&priv->lock, flags); | 1253 | spin_unlock_irqrestore(&priv->lock, flags); |
1283 | 1254 | ||
1284 | /* saved interrupt in inta variable now we can reset priv->inta */ | 1255 | /* saved interrupt in inta variable now we can reset priv->_agn.inta */ |
1285 | priv->inta = 0; | 1256 | priv->_agn.inta = 0; |
1286 | 1257 | ||
1287 | /* Now service all interrupt bits discovered above. */ | 1258 | /* Now service all interrupt bits discovered above. */ |
1288 | if (inta & CSR_INT_BIT_HW_ERR) { | 1259 | if (inta & CSR_INT_BIT_HW_ERR) { |
@@ -1447,6 +1418,60 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) | |||
1447 | iwl_enable_interrupts(priv); | 1418 | iwl_enable_interrupts(priv); |
1448 | } | 1419 | } |
1449 | 1420 | ||
1421 | /* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */ | ||
1422 | #define ACK_CNT_RATIO (50) | ||
1423 | #define BA_TIMEOUT_CNT (5) | ||
1424 | #define BA_TIMEOUT_MAX (16) | ||
1425 | |||
1426 | /** | ||
1427 | * iwl_good_ack_health - checks for ACK count ratios, BA timeout retries. | ||
1428 | * | ||
1429 | * When the ACK count ratio is 0 and aggregated BA timeout retries exceeding | ||
1430 | * the BA_TIMEOUT_MAX, reload firmware and bring system back to normal | ||
1431 | * operation state. | ||
1432 | */ | ||
1433 | bool iwl_good_ack_health(struct iwl_priv *priv, | ||
1434 | struct iwl_rx_packet *pkt) | ||
1435 | { | ||
1436 | bool rc = true; | ||
1437 | int actual_ack_cnt_delta, expected_ack_cnt_delta; | ||
1438 | int ba_timeout_delta; | ||
1439 | |||
1440 | actual_ack_cnt_delta = | ||
1441 | le32_to_cpu(pkt->u.stats.tx.actual_ack_cnt) - | ||
1442 | le32_to_cpu(priv->statistics.tx.actual_ack_cnt); | ||
1443 | expected_ack_cnt_delta = | ||
1444 | le32_to_cpu(pkt->u.stats.tx.expected_ack_cnt) - | ||
1445 | le32_to_cpu(priv->statistics.tx.expected_ack_cnt); | ||
1446 | ba_timeout_delta = | ||
1447 | le32_to_cpu(pkt->u.stats.tx.agg.ba_timeout) - | ||
1448 | le32_to_cpu(priv->statistics.tx.agg.ba_timeout); | ||
1449 | if ((priv->_agn.agg_tids_count > 0) && | ||
1450 | (expected_ack_cnt_delta > 0) && | ||
1451 | (((actual_ack_cnt_delta * 100) / expected_ack_cnt_delta) | ||
1452 | < ACK_CNT_RATIO) && | ||
1453 | (ba_timeout_delta > BA_TIMEOUT_CNT)) { | ||
1454 | IWL_DEBUG_RADIO(priv, "actual_ack_cnt delta = %d," | ||
1455 | " expected_ack_cnt = %d\n", | ||
1456 | actual_ack_cnt_delta, expected_ack_cnt_delta); | ||
1457 | |||
1458 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1459 | IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta = %d\n", | ||
1460 | priv->delta_statistics.tx.rx_detected_cnt); | ||
1461 | IWL_DEBUG_RADIO(priv, | ||
1462 | "ack_or_ba_timeout_collision delta = %d\n", | ||
1463 | priv->delta_statistics.tx. | ||
1464 | ack_or_ba_timeout_collision); | ||
1465 | #endif | ||
1466 | IWL_DEBUG_RADIO(priv, "agg ba_timeout delta = %d\n", | ||
1467 | ba_timeout_delta); | ||
1468 | if (!actual_ack_cnt_delta && | ||
1469 | (ba_timeout_delta >= BA_TIMEOUT_MAX)) | ||
1470 | rc = false; | ||
1471 | } | ||
1472 | return rc; | ||
1473 | } | ||
1474 | |||
1450 | 1475 | ||
1451 | /****************************************************************************** | 1476 | /****************************************************************************** |
1452 | * | 1477 | * |
@@ -2094,7 +2119,6 @@ static void iwl_alive_start(struct iwl_priv *priv) | |||
2094 | goto restart; | 2119 | goto restart; |
2095 | } | 2120 | } |
2096 | 2121 | ||
2097 | iwl_clear_stations_table(priv); | ||
2098 | ret = priv->cfg->ops->lib->alive_notify(priv); | 2122 | ret = priv->cfg->ops->lib->alive_notify(priv); |
2099 | if (ret) { | 2123 | if (ret) { |
2100 | IWL_WARN(priv, | 2124 | IWL_WARN(priv, |
@@ -2105,13 +2129,19 @@ static void iwl_alive_start(struct iwl_priv *priv) | |||
2105 | /* After the ALIVE response, we can send host commands to the uCode */ | 2129 | /* After the ALIVE response, we can send host commands to the uCode */ |
2106 | set_bit(STATUS_ALIVE, &priv->status); | 2130 | set_bit(STATUS_ALIVE, &priv->status); |
2107 | 2131 | ||
2132 | if (priv->cfg->ops->lib->recover_from_tx_stall) { | ||
2133 | /* Enable timer to monitor the driver queues */ | ||
2134 | mod_timer(&priv->monitor_recover, | ||
2135 | jiffies + | ||
2136 | msecs_to_jiffies(priv->cfg->monitor_recover_period)); | ||
2137 | } | ||
2138 | |||
2108 | if (iwl_is_rfkill(priv)) | 2139 | if (iwl_is_rfkill(priv)) |
2109 | return; | 2140 | return; |
2110 | 2141 | ||
2111 | ieee80211_wake_queues(priv->hw); | 2142 | ieee80211_wake_queues(priv->hw); |
2112 | 2143 | ||
2113 | priv->active_rate = priv->rates_mask; | 2144 | priv->active_rate = IWL_RATES_MASK; |
2114 | priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK; | ||
2115 | 2145 | ||
2116 | /* Configure Tx antenna selection based on H/W config */ | 2146 | /* Configure Tx antenna selection based on H/W config */ |
2117 | if (priv->cfg->ops->hcmd->set_tx_ant) | 2147 | if (priv->cfg->ops->hcmd->set_tx_ant) |
@@ -2151,18 +2181,8 @@ static void iwl_alive_start(struct iwl_priv *priv) | |||
2151 | wake_up_interruptible(&priv->wait_command_queue); | 2181 | wake_up_interruptible(&priv->wait_command_queue); |
2152 | 2182 | ||
2153 | iwl_power_update_mode(priv, true); | 2183 | iwl_power_update_mode(priv, true); |
2184 | IWL_DEBUG_INFO(priv, "Updated power mode\n"); | ||
2154 | 2185 | ||
2155 | /* reassociate for ADHOC mode */ | ||
2156 | if (priv->vif && (priv->iw_mode == NL80211_IFTYPE_ADHOC)) { | ||
2157 | struct sk_buff *beacon = ieee80211_beacon_get(priv->hw, | ||
2158 | priv->vif); | ||
2159 | if (beacon) | ||
2160 | iwl_mac_beacon_update(priv->hw, beacon); | ||
2161 | } | ||
2162 | |||
2163 | |||
2164 | if (test_and_clear_bit(STATUS_MODE_PENDING, &priv->status)) | ||
2165 | iwl_set_mode(priv, priv->iw_mode); | ||
2166 | 2186 | ||
2167 | return; | 2187 | return; |
2168 | 2188 | ||
@@ -2182,7 +2202,7 @@ static void __iwl_down(struct iwl_priv *priv) | |||
2182 | if (!exit_pending) | 2202 | if (!exit_pending) |
2183 | set_bit(STATUS_EXIT_PENDING, &priv->status); | 2203 | set_bit(STATUS_EXIT_PENDING, &priv->status); |
2184 | 2204 | ||
2185 | iwl_clear_stations_table(priv); | 2205 | iwl_clear_ucode_stations(priv, true); |
2186 | 2206 | ||
2187 | /* Unblock any waiting calls */ | 2207 | /* Unblock any waiting calls */ |
2188 | wake_up_interruptible_all(&priv->wait_command_queue); | 2208 | wake_up_interruptible_all(&priv->wait_command_queue); |
@@ -2230,8 +2250,8 @@ static void __iwl_down(struct iwl_priv *priv) | |||
2230 | /* device going down, Stop using ICT table */ | 2250 | /* device going down, Stop using ICT table */ |
2231 | iwl_disable_ict(priv); | 2251 | iwl_disable_ict(priv); |
2232 | 2252 | ||
2233 | iwl_txq_ctx_stop(priv); | 2253 | iwlagn_txq_ctx_stop(priv); |
2234 | iwl_rxq_stop(priv); | 2254 | iwlagn_rxq_stop(priv); |
2235 | 2255 | ||
2236 | /* Power-down device's busmaster DMA clocks */ | 2256 | /* Power-down device's busmaster DMA clocks */ |
2237 | iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT); | 2257 | iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT); |
@@ -2291,7 +2311,7 @@ static int iwl_prepare_card_hw(struct iwl_priv *priv) | |||
2291 | { | 2311 | { |
2292 | int ret = 0; | 2312 | int ret = 0; |
2293 | 2313 | ||
2294 | IWL_DEBUG_INFO(priv, "iwl_prepare_card_hw enter \n"); | 2314 | IWL_DEBUG_INFO(priv, "iwl_prepare_card_hw enter\n"); |
2295 | 2315 | ||
2296 | ret = iwl_set_hw_ready(priv); | 2316 | ret = iwl_set_hw_ready(priv); |
2297 | if (priv->hw_ready) | 2317 | if (priv->hw_ready) |
@@ -2352,7 +2372,7 @@ static int __iwl_up(struct iwl_priv *priv) | |||
2352 | 2372 | ||
2353 | iwl_write32(priv, CSR_INT, 0xFFFFFFFF); | 2373 | iwl_write32(priv, CSR_INT, 0xFFFFFFFF); |
2354 | 2374 | ||
2355 | ret = iwl_hw_nic_init(priv); | 2375 | ret = iwlagn_hw_nic_init(priv); |
2356 | if (ret) { | 2376 | if (ret) { |
2357 | IWL_ERR(priv, "Unable to init nic\n"); | 2377 | IWL_ERR(priv, "Unable to init nic\n"); |
2358 | return ret; | 2378 | return ret; |
@@ -2379,8 +2399,6 @@ static int __iwl_up(struct iwl_priv *priv) | |||
2379 | 2399 | ||
2380 | for (i = 0; i < MAX_HW_RESTARTS; i++) { | 2400 | for (i = 0; i < MAX_HW_RESTARTS; i++) { |
2381 | 2401 | ||
2382 | iwl_clear_stations_table(priv); | ||
2383 | |||
2384 | /* load bootstrap state machine, | 2402 | /* load bootstrap state machine, |
2385 | * load bootstrap program into processor's memory, | 2403 | * load bootstrap program into processor's memory, |
2386 | * prepare to load the "initialize" uCode */ | 2404 | * prepare to load the "initialize" uCode */ |
@@ -2504,7 +2522,7 @@ static void iwl_bg_rx_replenish(struct work_struct *data) | |||
2504 | return; | 2522 | return; |
2505 | 2523 | ||
2506 | mutex_lock(&priv->mutex); | 2524 | mutex_lock(&priv->mutex); |
2507 | iwl_rx_replenish(priv); | 2525 | iwlagn_rx_replenish(priv); |
2508 | mutex_unlock(&priv->mutex); | 2526 | mutex_unlock(&priv->mutex); |
2509 | } | 2527 | } |
2510 | 2528 | ||
@@ -2514,17 +2532,12 @@ void iwl_post_associate(struct iwl_priv *priv) | |||
2514 | { | 2532 | { |
2515 | struct ieee80211_conf *conf = NULL; | 2533 | struct ieee80211_conf *conf = NULL; |
2516 | int ret = 0; | 2534 | int ret = 0; |
2517 | unsigned long flags; | ||
2518 | 2535 | ||
2519 | if (priv->iw_mode == NL80211_IFTYPE_AP) { | 2536 | if (priv->iw_mode == NL80211_IFTYPE_AP) { |
2520 | IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__); | 2537 | IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__); |
2521 | return; | 2538 | return; |
2522 | } | 2539 | } |
2523 | 2540 | ||
2524 | IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n", | ||
2525 | priv->assoc_id, priv->active_rxon.bssid_addr); | ||
2526 | |||
2527 | |||
2528 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 2541 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
2529 | return; | 2542 | return; |
2530 | 2543 | ||
@@ -2576,6 +2589,9 @@ void iwl_post_associate(struct iwl_priv *priv) | |||
2576 | 2589 | ||
2577 | iwlcore_commit_rxon(priv); | 2590 | iwlcore_commit_rxon(priv); |
2578 | 2591 | ||
2592 | IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n", | ||
2593 | priv->assoc_id, priv->active_rxon.bssid_addr); | ||
2594 | |||
2579 | switch (priv->iw_mode) { | 2595 | switch (priv->iw_mode) { |
2580 | case NL80211_IFTYPE_STATION: | 2596 | case NL80211_IFTYPE_STATION: |
2581 | break; | 2597 | break; |
@@ -2585,7 +2601,7 @@ void iwl_post_associate(struct iwl_priv *priv) | |||
2585 | /* assume default assoc id */ | 2601 | /* assume default assoc id */ |
2586 | priv->assoc_id = 1; | 2602 | priv->assoc_id = 1; |
2587 | 2603 | ||
2588 | iwl_rxon_add_station(priv, priv->bssid, 0); | 2604 | iwl_add_local_station(priv, priv->bssid, true); |
2589 | iwl_send_beacon_cmd(priv); | 2605 | iwl_send_beacon_cmd(priv); |
2590 | 2606 | ||
2591 | break; | 2607 | break; |
@@ -2596,13 +2612,6 @@ void iwl_post_associate(struct iwl_priv *priv) | |||
2596 | break; | 2612 | break; |
2597 | } | 2613 | } |
2598 | 2614 | ||
2599 | if (priv->iw_mode == NL80211_IFTYPE_ADHOC) | ||
2600 | priv->assoc_station_added = 1; | ||
2601 | |||
2602 | spin_lock_irqsave(&priv->lock, flags); | ||
2603 | iwl_activate_qos(priv, 0); | ||
2604 | spin_unlock_irqrestore(&priv->lock, flags); | ||
2605 | |||
2606 | /* the chain noise calibration will enabled PM upon completion | 2615 | /* the chain noise calibration will enabled PM upon completion |
2607 | * If chain noise has already been run, then we need to enable | 2616 | * If chain noise has already been run, then we need to enable |
2608 | * power management here */ | 2617 | * power management here */ |
@@ -2769,7 +2778,7 @@ static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
2769 | IWL_DEBUG_TX(priv, "dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, | 2778 | IWL_DEBUG_TX(priv, "dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, |
2770 | ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate); | 2779 | ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate); |
2771 | 2780 | ||
2772 | if (iwl_tx_skb(priv, skb)) | 2781 | if (iwlagn_tx_skb(priv, skb)) |
2773 | dev_kfree_skb_any(skb); | 2782 | dev_kfree_skb_any(skb); |
2774 | 2783 | ||
2775 | IWL_DEBUG_MACDUMP(priv, "leave\n"); | 2784 | IWL_DEBUG_MACDUMP(priv, "leave\n"); |
@@ -2779,7 +2788,6 @@ static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
2779 | void iwl_config_ap(struct iwl_priv *priv) | 2788 | void iwl_config_ap(struct iwl_priv *priv) |
2780 | { | 2789 | { |
2781 | int ret = 0; | 2790 | int ret = 0; |
2782 | unsigned long flags; | ||
2783 | 2791 | ||
2784 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 2792 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
2785 | return; | 2793 | return; |
@@ -2831,10 +2839,6 @@ void iwl_config_ap(struct iwl_priv *priv) | |||
2831 | /* restore RXON assoc */ | 2839 | /* restore RXON assoc */ |
2832 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; | 2840 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; |
2833 | iwlcore_commit_rxon(priv); | 2841 | iwlcore_commit_rxon(priv); |
2834 | iwl_reset_qos(priv); | ||
2835 | spin_lock_irqsave(&priv->lock, flags); | ||
2836 | iwl_activate_qos(priv, 1); | ||
2837 | spin_unlock_irqrestore(&priv->lock, flags); | ||
2838 | iwl_add_bcast_station(priv); | 2842 | iwl_add_bcast_station(priv); |
2839 | } | 2843 | } |
2840 | iwl_send_beacon_cmd(priv); | 2844 | iwl_send_beacon_cmd(priv); |
@@ -2889,7 +2893,6 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
2889 | 2893 | ||
2890 | mutex_lock(&priv->mutex); | 2894 | mutex_lock(&priv->mutex); |
2891 | iwl_scan_cancel_timeout(priv, 100); | 2895 | iwl_scan_cancel_timeout(priv, 100); |
2892 | mutex_unlock(&priv->mutex); | ||
2893 | 2896 | ||
2894 | /* If we are getting WEP group key and we didn't receive any key mapping | 2897 | /* If we are getting WEP group key and we didn't receive any key mapping |
2895 | * so far, we are in legacy wep mode (group key only), otherwise we are | 2898 | * so far, we are in legacy wep mode (group key only), otherwise we are |
@@ -2925,6 +2928,7 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
2925 | ret = -EINVAL; | 2928 | ret = -EINVAL; |
2926 | } | 2929 | } |
2927 | 2930 | ||
2931 | mutex_unlock(&priv->mutex); | ||
2928 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 2932 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
2929 | 2933 | ||
2930 | return ret; | 2934 | return ret; |
@@ -2957,10 +2961,21 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, | |||
2957 | return ret; | 2961 | return ret; |
2958 | case IEEE80211_AMPDU_TX_START: | 2962 | case IEEE80211_AMPDU_TX_START: |
2959 | IWL_DEBUG_HT(priv, "start Tx\n"); | 2963 | IWL_DEBUG_HT(priv, "start Tx\n"); |
2960 | return iwl_tx_agg_start(priv, sta->addr, tid, ssn); | 2964 | ret = iwlagn_tx_agg_start(priv, sta->addr, tid, ssn); |
2965 | if (ret == 0) { | ||
2966 | priv->_agn.agg_tids_count++; | ||
2967 | IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n", | ||
2968 | priv->_agn.agg_tids_count); | ||
2969 | } | ||
2970 | return ret; | ||
2961 | case IEEE80211_AMPDU_TX_STOP: | 2971 | case IEEE80211_AMPDU_TX_STOP: |
2962 | IWL_DEBUG_HT(priv, "stop Tx\n"); | 2972 | IWL_DEBUG_HT(priv, "stop Tx\n"); |
2963 | ret = iwl_tx_agg_stop(priv, sta->addr, tid); | 2973 | ret = iwlagn_tx_agg_stop(priv, sta->addr, tid); |
2974 | if ((ret == 0) && (priv->_agn.agg_tids_count > 0)) { | ||
2975 | priv->_agn.agg_tids_count--; | ||
2976 | IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n", | ||
2977 | priv->_agn.agg_tids_count); | ||
2978 | } | ||
2964 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 2979 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
2965 | return 0; | 2980 | return 0; |
2966 | else | 2981 | else |
@@ -2997,18 +3012,7 @@ static void iwl_mac_sta_notify(struct ieee80211_hw *hw, | |||
2997 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; | 3012 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; |
2998 | int sta_id; | 3013 | int sta_id; |
2999 | 3014 | ||
3000 | /* | ||
3001 | * TODO: We really should use this callback to | ||
3002 | * actually maintain the station table in | ||
3003 | * the device. | ||
3004 | */ | ||
3005 | |||
3006 | switch (cmd) { | 3015 | switch (cmd) { |
3007 | case STA_NOTIFY_ADD: | ||
3008 | atomic_set(&sta_priv->pending_frames, 0); | ||
3009 | if (vif->type == NL80211_IFTYPE_AP) | ||
3010 | sta_priv->client = true; | ||
3011 | break; | ||
3012 | case STA_NOTIFY_SLEEP: | 3016 | case STA_NOTIFY_SLEEP: |
3013 | WARN_ON(!sta_priv->client); | 3017 | WARN_ON(!sta_priv->client); |
3014 | sta_priv->asleep = true; | 3018 | sta_priv->asleep = true; |
@@ -3029,6 +3033,55 @@ static void iwl_mac_sta_notify(struct ieee80211_hw *hw, | |||
3029 | } | 3033 | } |
3030 | } | 3034 | } |
3031 | 3035 | ||
3036 | /** | ||
3037 | * iwl_restore_wepkeys - Restore WEP keys to device | ||
3038 | */ | ||
3039 | static void iwl_restore_wepkeys(struct iwl_priv *priv) | ||
3040 | { | ||
3041 | mutex_lock(&priv->mutex); | ||
3042 | if (priv->iw_mode == NL80211_IFTYPE_STATION && | ||
3043 | priv->default_wep_key && | ||
3044 | iwl_send_static_wepkey_cmd(priv, 0)) | ||
3045 | IWL_ERR(priv, "Could not send WEP static key\n"); | ||
3046 | mutex_unlock(&priv->mutex); | ||
3047 | } | ||
3048 | |||
3049 | static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, | ||
3050 | struct ieee80211_vif *vif, | ||
3051 | struct ieee80211_sta *sta) | ||
3052 | { | ||
3053 | struct iwl_priv *priv = hw->priv; | ||
3054 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; | ||
3055 | bool is_ap = priv->iw_mode == NL80211_IFTYPE_STATION; | ||
3056 | int ret; | ||
3057 | u8 sta_id; | ||
3058 | |||
3059 | IWL_DEBUG_INFO(priv, "received request to add station %pM\n", | ||
3060 | sta->addr); | ||
3061 | |||
3062 | atomic_set(&sta_priv->pending_frames, 0); | ||
3063 | if (vif->type == NL80211_IFTYPE_AP) | ||
3064 | sta_priv->client = true; | ||
3065 | |||
3066 | ret = iwl_add_station_common(priv, sta->addr, is_ap, &sta->ht_cap, | ||
3067 | &sta_id); | ||
3068 | if (ret) { | ||
3069 | IWL_ERR(priv, "Unable to add station %pM (%d)\n", | ||
3070 | sta->addr, ret); | ||
3071 | /* Should we return success if return code is EEXIST ? */ | ||
3072 | return ret; | ||
3073 | } | ||
3074 | |||
3075 | iwl_restore_wepkeys(priv); | ||
3076 | |||
3077 | /* Initialize rate scaling */ | ||
3078 | IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n", | ||
3079 | sta->addr); | ||
3080 | iwl_rs_rate_init(priv, sta, sta_id); | ||
3081 | |||
3082 | return ret; | ||
3083 | } | ||
3084 | |||
3032 | /***************************************************************************** | 3085 | /***************************************************************************** |
3033 | * | 3086 | * |
3034 | * sysfs attributes | 3087 | * sysfs attributes |
@@ -3129,87 +3182,6 @@ static ssize_t store_tx_power(struct device *d, | |||
3129 | 3182 | ||
3130 | static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power); | 3183 | static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power); |
3131 | 3184 | ||
3132 | static ssize_t show_flags(struct device *d, | ||
3133 | struct device_attribute *attr, char *buf) | ||
3134 | { | ||
3135 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3136 | |||
3137 | return sprintf(buf, "0x%04X\n", priv->active_rxon.flags); | ||
3138 | } | ||
3139 | |||
3140 | static ssize_t store_flags(struct device *d, | ||
3141 | struct device_attribute *attr, | ||
3142 | const char *buf, size_t count) | ||
3143 | { | ||
3144 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3145 | unsigned long val; | ||
3146 | u32 flags; | ||
3147 | int ret = strict_strtoul(buf, 0, &val); | ||
3148 | if (ret) | ||
3149 | return ret; | ||
3150 | flags = (u32)val; | ||
3151 | |||
3152 | mutex_lock(&priv->mutex); | ||
3153 | if (le32_to_cpu(priv->staging_rxon.flags) != flags) { | ||
3154 | /* Cancel any currently running scans... */ | ||
3155 | if (iwl_scan_cancel_timeout(priv, 100)) | ||
3156 | IWL_WARN(priv, "Could not cancel scan.\n"); | ||
3157 | else { | ||
3158 | IWL_DEBUG_INFO(priv, "Commit rxon.flags = 0x%04X\n", flags); | ||
3159 | priv->staging_rxon.flags = cpu_to_le32(flags); | ||
3160 | iwlcore_commit_rxon(priv); | ||
3161 | } | ||
3162 | } | ||
3163 | mutex_unlock(&priv->mutex); | ||
3164 | |||
3165 | return count; | ||
3166 | } | ||
3167 | |||
3168 | static DEVICE_ATTR(flags, S_IWUSR | S_IRUGO, show_flags, store_flags); | ||
3169 | |||
3170 | static ssize_t show_filter_flags(struct device *d, | ||
3171 | struct device_attribute *attr, char *buf) | ||
3172 | { | ||
3173 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3174 | |||
3175 | return sprintf(buf, "0x%04X\n", | ||
3176 | le32_to_cpu(priv->active_rxon.filter_flags)); | ||
3177 | } | ||
3178 | |||
3179 | static ssize_t store_filter_flags(struct device *d, | ||
3180 | struct device_attribute *attr, | ||
3181 | const char *buf, size_t count) | ||
3182 | { | ||
3183 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3184 | unsigned long val; | ||
3185 | u32 filter_flags; | ||
3186 | int ret = strict_strtoul(buf, 0, &val); | ||
3187 | if (ret) | ||
3188 | return ret; | ||
3189 | filter_flags = (u32)val; | ||
3190 | |||
3191 | mutex_lock(&priv->mutex); | ||
3192 | if (le32_to_cpu(priv->staging_rxon.filter_flags) != filter_flags) { | ||
3193 | /* Cancel any currently running scans... */ | ||
3194 | if (iwl_scan_cancel_timeout(priv, 100)) | ||
3195 | IWL_WARN(priv, "Could not cancel scan.\n"); | ||
3196 | else { | ||
3197 | IWL_DEBUG_INFO(priv, "Committing rxon.filter_flags = " | ||
3198 | "0x%04X\n", filter_flags); | ||
3199 | priv->staging_rxon.filter_flags = | ||
3200 | cpu_to_le32(filter_flags); | ||
3201 | iwlcore_commit_rxon(priv); | ||
3202 | } | ||
3203 | } | ||
3204 | mutex_unlock(&priv->mutex); | ||
3205 | |||
3206 | return count; | ||
3207 | } | ||
3208 | |||
3209 | static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags, | ||
3210 | store_filter_flags); | ||
3211 | |||
3212 | |||
3213 | static ssize_t show_statistics(struct device *d, | 3185 | static ssize_t show_statistics(struct device *d, |
3214 | struct device_attribute *attr, char *buf) | 3186 | struct device_attribute *attr, char *buf) |
3215 | { | 3187 | { |
@@ -3315,6 +3287,13 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) | |||
3315 | priv->ucode_trace.data = (unsigned long)priv; | 3287 | priv->ucode_trace.data = (unsigned long)priv; |
3316 | priv->ucode_trace.function = iwl_bg_ucode_trace; | 3288 | priv->ucode_trace.function = iwl_bg_ucode_trace; |
3317 | 3289 | ||
3290 | if (priv->cfg->ops->lib->recover_from_tx_stall) { | ||
3291 | init_timer(&priv->monitor_recover); | ||
3292 | priv->monitor_recover.data = (unsigned long)priv; | ||
3293 | priv->monitor_recover.function = | ||
3294 | priv->cfg->ops->lib->recover_from_tx_stall; | ||
3295 | } | ||
3296 | |||
3318 | if (!priv->cfg->use_isr_legacy) | 3297 | if (!priv->cfg->use_isr_legacy) |
3319 | tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) | 3298 | tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) |
3320 | iwl_irq_tasklet, (unsigned long)priv); | 3299 | iwl_irq_tasklet, (unsigned long)priv); |
@@ -3334,6 +3313,8 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv) | |||
3334 | cancel_work_sync(&priv->beacon_update); | 3313 | cancel_work_sync(&priv->beacon_update); |
3335 | del_timer_sync(&priv->statistics_periodic); | 3314 | del_timer_sync(&priv->statistics_periodic); |
3336 | del_timer_sync(&priv->ucode_trace); | 3315 | del_timer_sync(&priv->ucode_trace); |
3316 | if (priv->cfg->ops->lib->recover_from_tx_stall) | ||
3317 | del_timer_sync(&priv->monitor_recover); | ||
3337 | } | 3318 | } |
3338 | 3319 | ||
3339 | static void iwl_init_hw_rates(struct iwl_priv *priv, | 3320 | static void iwl_init_hw_rates(struct iwl_priv *priv, |
@@ -3371,9 +3352,6 @@ static int iwl_init_drv(struct iwl_priv *priv) | |||
3371 | mutex_init(&priv->mutex); | 3352 | mutex_init(&priv->mutex); |
3372 | mutex_init(&priv->sync_cmd_mutex); | 3353 | mutex_init(&priv->sync_cmd_mutex); |
3373 | 3354 | ||
3374 | /* Clear the driver's (not device's) station table */ | ||
3375 | iwl_clear_stations_table(priv); | ||
3376 | |||
3377 | priv->ieee_channels = NULL; | 3355 | priv->ieee_channels = NULL; |
3378 | priv->ieee_rates = NULL; | 3356 | priv->ieee_rates = NULL; |
3379 | priv->band = IEEE80211_BAND_2GHZ; | 3357 | priv->band = IEEE80211_BAND_2GHZ; |
@@ -3381,6 +3359,7 @@ static int iwl_init_drv(struct iwl_priv *priv) | |||
3381 | priv->iw_mode = NL80211_IFTYPE_STATION; | 3359 | priv->iw_mode = NL80211_IFTYPE_STATION; |
3382 | priv->current_ht_config.smps = IEEE80211_SMPS_STATIC; | 3360 | priv->current_ht_config.smps = IEEE80211_SMPS_STATIC; |
3383 | priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; | 3361 | priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; |
3362 | priv->_agn.agg_tids_count = 0; | ||
3384 | 3363 | ||
3385 | /* initialize force reset */ | 3364 | /* initialize force reset */ |
3386 | priv->force_reset[IWL_RF_RESET].reset_duration = | 3365 | priv->force_reset[IWL_RF_RESET].reset_duration = |
@@ -3394,16 +3373,10 @@ static int iwl_init_drv(struct iwl_priv *priv) | |||
3394 | 3373 | ||
3395 | iwl_init_scan_params(priv); | 3374 | iwl_init_scan_params(priv); |
3396 | 3375 | ||
3397 | iwl_reset_qos(priv); | ||
3398 | |||
3399 | priv->qos_data.qos_active = 0; | ||
3400 | priv->qos_data.qos_cap.val = 0; | ||
3401 | |||
3402 | priv->rates_mask = IWL_RATES_MASK; | ||
3403 | /* Set the tx_power_user_lmt to the lowest power level | 3376 | /* Set the tx_power_user_lmt to the lowest power level |
3404 | * this value will get overwritten by channel max power avg | 3377 | * this value will get overwritten by channel max power avg |
3405 | * from eeprom */ | 3378 | * from eeprom */ |
3406 | priv->tx_power_user_lmt = IWL_TX_POWER_TARGET_POWER_MIN; | 3379 | priv->tx_power_user_lmt = IWLAGN_TX_POWER_TARGET_POWER_MIN; |
3407 | 3380 | ||
3408 | ret = iwl_init_channel_map(priv); | 3381 | ret = iwl_init_channel_map(priv); |
3409 | if (ret) { | 3382 | if (ret) { |
@@ -3435,8 +3408,6 @@ static void iwl_uninit_drv(struct iwl_priv *priv) | |||
3435 | } | 3408 | } |
3436 | 3409 | ||
3437 | static struct attribute *iwl_sysfs_entries[] = { | 3410 | static struct attribute *iwl_sysfs_entries[] = { |
3438 | &dev_attr_flags.attr, | ||
3439 | &dev_attr_filter_flags.attr, | ||
3440 | &dev_attr_statistics.attr, | 3411 | &dev_attr_statistics.attr, |
3441 | &dev_attr_temperature.attr, | 3412 | &dev_attr_temperature.attr, |
3442 | &dev_attr_tx_power.attr, | 3413 | &dev_attr_tx_power.attr, |
@@ -3469,6 +3440,8 @@ static struct ieee80211_ops iwl_hw_ops = { | |||
3469 | .ampdu_action = iwl_mac_ampdu_action, | 3440 | .ampdu_action = iwl_mac_ampdu_action, |
3470 | .hw_scan = iwl_mac_hw_scan, | 3441 | .hw_scan = iwl_mac_hw_scan, |
3471 | .sta_notify = iwl_mac_sta_notify, | 3442 | .sta_notify = iwl_mac_sta_notify, |
3443 | .sta_add = iwlagn_mac_sta_add, | ||
3444 | .sta_remove = iwl_mac_sta_remove, | ||
3472 | }; | 3445 | }; |
3473 | 3446 | ||
3474 | static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | 3447 | static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |
@@ -3572,7 +3545,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
3572 | iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); | 3545 | iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); |
3573 | 3546 | ||
3574 | iwl_hw_detect(priv); | 3547 | iwl_hw_detect(priv); |
3575 | IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s REV=0x%X\n", | 3548 | IWL_INFO(priv, "Detected %s, REV=0x%X\n", |
3576 | priv->cfg->name, priv->hw_rev); | 3549 | priv->cfg->name, priv->hw_rev); |
3577 | 3550 | ||
3578 | /* We disable the RETRY_TIMEOUT register (0x41) to keep | 3551 | /* We disable the RETRY_TIMEOUT register (0x41) to keep |
@@ -3750,10 +3723,9 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) | |||
3750 | iwl_dealloc_ucode_pci(priv); | 3723 | iwl_dealloc_ucode_pci(priv); |
3751 | 3724 | ||
3752 | if (priv->rxq.bd) | 3725 | if (priv->rxq.bd) |
3753 | iwl_rx_queue_free(priv, &priv->rxq); | 3726 | iwlagn_rx_queue_free(priv, &priv->rxq); |
3754 | iwl_hw_txq_ctx_free(priv); | 3727 | iwlagn_hw_txq_ctx_free(priv); |
3755 | 3728 | ||
3756 | iwl_clear_stations_table(priv); | ||
3757 | iwl_eeprom_free(priv); | 3729 | iwl_eeprom_free(priv); |
3758 | 3730 | ||
3759 | 3731 | ||
@@ -3867,6 +3839,7 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { | |||
3867 | {IWL_PCI_DEVICE(0x4238, 0x1111, iwl6000_3agn_cfg)}, | 3839 | {IWL_PCI_DEVICE(0x4238, 0x1111, iwl6000_3agn_cfg)}, |
3868 | {IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)}, | 3840 | {IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)}, |
3869 | {IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)}, | 3841 | {IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)}, |
3842 | {IWL_PCI_DEVICE(0x0082, 0x1201, iwl6000i_g2_2agn_cfg)}, | ||
3870 | 3843 | ||
3871 | /* 6x50 WiFi/WiMax Series */ | 3844 | /* 6x50 WiFi/WiMax Series */ |
3872 | {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)}, | 3845 | {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)}, |
@@ -3949,3 +3922,33 @@ module_param_named(debug, iwl_debug_level, uint, S_IRUGO | S_IWUSR); | |||
3949 | MODULE_PARM_DESC(debug, "debug output mask"); | 3922 | MODULE_PARM_DESC(debug, "debug output mask"); |
3950 | #endif | 3923 | #endif |
3951 | 3924 | ||
3925 | module_param_named(swcrypto50, iwlagn_mod_params.sw_crypto, bool, S_IRUGO); | ||
3926 | MODULE_PARM_DESC(swcrypto50, | ||
3927 | "using crypto in software (default 0 [hardware]) (deprecated)"); | ||
3928 | module_param_named(swcrypto, iwlagn_mod_params.sw_crypto, int, S_IRUGO); | ||
3929 | MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])"); | ||
3930 | module_param_named(queues_num50, | ||
3931 | iwlagn_mod_params.num_of_queues, int, S_IRUGO); | ||
3932 | MODULE_PARM_DESC(queues_num50, | ||
3933 | "number of hw queues in 50xx series (deprecated)"); | ||
3934 | module_param_named(queues_num, iwlagn_mod_params.num_of_queues, int, S_IRUGO); | ||
3935 | MODULE_PARM_DESC(queues_num, "number of hw queues."); | ||
3936 | module_param_named(11n_disable50, iwlagn_mod_params.disable_11n, int, S_IRUGO); | ||
3937 | MODULE_PARM_DESC(11n_disable50, "disable 50XX 11n functionality (deprecated)"); | ||
3938 | module_param_named(11n_disable, iwlagn_mod_params.disable_11n, int, S_IRUGO); | ||
3939 | MODULE_PARM_DESC(11n_disable, "disable 11n functionality"); | ||
3940 | module_param_named(amsdu_size_8K50, iwlagn_mod_params.amsdu_size_8K, | ||
3941 | int, S_IRUGO); | ||
3942 | MODULE_PARM_DESC(amsdu_size_8K50, | ||
3943 | "enable 8K amsdu size in 50XX series (deprecated)"); | ||
3944 | module_param_named(amsdu_size_8K, iwlagn_mod_params.amsdu_size_8K, | ||
3945 | int, S_IRUGO); | ||
3946 | MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size"); | ||
3947 | module_param_named(fw_restart50, iwlagn_mod_params.restart_fw, int, S_IRUGO); | ||
3948 | MODULE_PARM_DESC(fw_restart50, | ||
3949 | "restart firmware in case of error (deprecated)"); | ||
3950 | module_param_named(fw_restart, iwlagn_mod_params.restart_fw, int, S_IRUGO); | ||
3951 | MODULE_PARM_DESC(fw_restart, "restart firmware in case of error"); | ||
3952 | module_param_named( | ||
3953 | disable_hw_scan, iwlagn_mod_params.disable_hw_scan, int, S_IRUGO); | ||
3954 | MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h new file mode 100644 index 000000000000..5ad14055eda3 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h | |||
@@ -0,0 +1,149 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | *****************************************************************************/ | ||
62 | |||
63 | #ifndef __iwl_agn_h__ | ||
64 | #define __iwl_agn_h__ | ||
65 | |||
66 | #include "iwl-dev.h" | ||
67 | |||
68 | extern struct iwl_mod_params iwlagn_mod_params; | ||
69 | extern struct iwl_ucode_ops iwlagn_ucode; | ||
70 | extern struct iwl_hcmd_ops iwlagn_hcmd; | ||
71 | extern struct iwl_hcmd_utils_ops iwlagn_hcmd_utils; | ||
72 | |||
73 | int iwl_reset_ict(struct iwl_priv *priv); | ||
74 | void iwl_disable_ict(struct iwl_priv *priv); | ||
75 | int iwl_alloc_isr_ict(struct iwl_priv *priv); | ||
76 | void iwl_free_isr_ict(struct iwl_priv *priv); | ||
77 | irqreturn_t iwl_isr_ict(int irq, void *data); | ||
78 | bool iwl_good_ack_health(struct iwl_priv *priv, | ||
79 | struct iwl_rx_packet *pkt); | ||
80 | |||
81 | /* tx queue */ | ||
82 | void iwlagn_set_wr_ptrs(struct iwl_priv *priv, | ||
83 | int txq_id, u32 index); | ||
84 | void iwlagn_tx_queue_set_status(struct iwl_priv *priv, | ||
85 | struct iwl_tx_queue *txq, | ||
86 | int tx_fifo_id, int scd_retry); | ||
87 | void iwlagn_txq_update_byte_cnt_tbl(struct iwl_priv *priv, | ||
88 | struct iwl_tx_queue *txq, | ||
89 | u16 byte_cnt); | ||
90 | void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, | ||
91 | struct iwl_tx_queue *txq); | ||
92 | int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, | ||
93 | int tx_fifo, int sta_id, int tid, u16 ssn_idx); | ||
94 | int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, | ||
95 | u16 ssn_idx, u8 tx_fifo); | ||
96 | void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask); | ||
97 | |||
98 | /* uCode */ | ||
99 | int iwlagn_load_ucode(struct iwl_priv *priv); | ||
100 | void iwlagn_rx_calib_result(struct iwl_priv *priv, | ||
101 | struct iwl_rx_mem_buffer *rxb); | ||
102 | void iwlagn_rx_calib_complete(struct iwl_priv *priv, | ||
103 | struct iwl_rx_mem_buffer *rxb); | ||
104 | void iwlagn_init_alive_start(struct iwl_priv *priv); | ||
105 | int iwlagn_alive_notify(struct iwl_priv *priv); | ||
106 | |||
107 | /* lib */ | ||
108 | void iwlagn_rx_handler_setup(struct iwl_priv *priv); | ||
109 | void iwlagn_setup_deferred_work(struct iwl_priv *priv); | ||
110 | int iwlagn_hw_valid_rtc_data_addr(u32 addr); | ||
111 | int iwlagn_send_tx_power(struct iwl_priv *priv); | ||
112 | void iwlagn_temperature(struct iwl_priv *priv); | ||
113 | u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv); | ||
114 | const u8 *iwlagn_eeprom_query_addr(const struct iwl_priv *priv, | ||
115 | size_t offset); | ||
116 | void iwlagn_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | ||
117 | int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | ||
118 | int iwlagn_hw_nic_init(struct iwl_priv *priv); | ||
119 | |||
120 | /* rx */ | ||
121 | void iwlagn_rx_queue_restock(struct iwl_priv *priv); | ||
122 | void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority); | ||
123 | void iwlagn_rx_replenish(struct iwl_priv *priv); | ||
124 | void iwlagn_rx_replenish_now(struct iwl_priv *priv); | ||
125 | void iwlagn_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | ||
126 | int iwlagn_rxq_stop(struct iwl_priv *priv); | ||
127 | int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band); | ||
128 | void iwlagn_rx_reply_rx(struct iwl_priv *priv, | ||
129 | struct iwl_rx_mem_buffer *rxb); | ||
130 | void iwlagn_rx_reply_rx_phy(struct iwl_priv *priv, | ||
131 | struct iwl_rx_mem_buffer *rxb); | ||
132 | |||
133 | /* tx */ | ||
134 | void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, | ||
135 | struct ieee80211_tx_info *info); | ||
136 | int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb); | ||
137 | int iwlagn_tx_agg_start(struct iwl_priv *priv, | ||
138 | const u8 *ra, u16 tid, u16 *ssn); | ||
139 | int iwlagn_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid); | ||
140 | int iwlagn_txq_check_empty(struct iwl_priv *priv, | ||
141 | int sta_id, u8 tid, int txq_id); | ||
142 | void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, | ||
143 | struct iwl_rx_mem_buffer *rxb); | ||
144 | int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index); | ||
145 | void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv); | ||
146 | int iwlagn_txq_ctx_reset(struct iwl_priv *priv); | ||
147 | void iwlagn_txq_ctx_stop(struct iwl_priv *priv); | ||
148 | |||
149 | #endif /* __iwl_agn_h__ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c index 845831ac053e..dbb50a8e0ce3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-calib.c | |||
@@ -592,7 +592,7 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv, | |||
592 | IWL_DEBUG_CALIB(priv, "rx_enable_time = %u usecs\n", rx_enable_time); | 592 | IWL_DEBUG_CALIB(priv, "rx_enable_time = %u usecs\n", rx_enable_time); |
593 | 593 | ||
594 | if (!rx_enable_time) { | 594 | if (!rx_enable_time) { |
595 | IWL_DEBUG_CALIB(priv, "<< RX Enable Time == 0! \n"); | 595 | IWL_DEBUG_CALIB(priv, "<< RX Enable Time == 0!\n"); |
596 | return; | 596 | return; |
597 | } | 597 | } |
598 | 598 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 894bcb8b8b37..f09bff823ab6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -65,7 +65,7 @@ MODULE_LICENSE("GPL"); | |||
65 | */ | 65 | */ |
66 | static bool bt_coex_active = true; | 66 | static bool bt_coex_active = true; |
67 | module_param(bt_coex_active, bool, S_IRUGO); | 67 | module_param(bt_coex_active, bool, S_IRUGO); |
68 | MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist\n"); | 68 | MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist"); |
69 | 69 | ||
70 | static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { | 70 | static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { |
71 | {COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP, | 71 | {COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP, |
@@ -114,8 +114,6 @@ static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { | |||
114 | u32 iwl_debug_level; | 114 | u32 iwl_debug_level; |
115 | EXPORT_SYMBOL(iwl_debug_level); | 115 | EXPORT_SYMBOL(iwl_debug_level); |
116 | 116 | ||
117 | static irqreturn_t iwl_isr(int irq, void *data); | ||
118 | |||
119 | /* | 117 | /* |
120 | * Parameter order: | 118 | * Parameter order: |
121 | * rate, ht rate, prev rate, next rate, prev tgg rate, next tgg rate | 119 | * rate, ht rate, prev rate, next rate, prev tgg rate, next tgg rate |
@@ -142,30 +140,6 @@ const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT] = { | |||
142 | }; | 140 | }; |
143 | EXPORT_SYMBOL(iwl_rates); | 141 | EXPORT_SYMBOL(iwl_rates); |
144 | 142 | ||
145 | /** | ||
146 | * translate ucode response to mac80211 tx status control values | ||
147 | */ | ||
148 | void iwl_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, | ||
149 | struct ieee80211_tx_info *info) | ||
150 | { | ||
151 | struct ieee80211_tx_rate *r = &info->control.rates[0]; | ||
152 | |||
153 | info->antenna_sel_tx = | ||
154 | ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS); | ||
155 | if (rate_n_flags & RATE_MCS_HT_MSK) | ||
156 | r->flags |= IEEE80211_TX_RC_MCS; | ||
157 | if (rate_n_flags & RATE_MCS_GF_MSK) | ||
158 | r->flags |= IEEE80211_TX_RC_GREEN_FIELD; | ||
159 | if (rate_n_flags & RATE_MCS_HT40_MSK) | ||
160 | r->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; | ||
161 | if (rate_n_flags & RATE_MCS_DUP_MSK) | ||
162 | r->flags |= IEEE80211_TX_RC_DUP_DATA; | ||
163 | if (rate_n_flags & RATE_MCS_SGI_MSK) | ||
164 | r->flags |= IEEE80211_TX_RC_SHORT_GI; | ||
165 | r->idx = iwl_hwrate_to_mac80211_idx(rate_n_flags, info->band); | ||
166 | } | ||
167 | EXPORT_SYMBOL(iwl_hwrate_to_tx_control); | ||
168 | |||
169 | int iwl_hwrate_to_plcp_idx(u32 rate_n_flags) | 143 | int iwl_hwrate_to_plcp_idx(u32 rate_n_flags) |
170 | { | 144 | { |
171 | int idx = 0; | 145 | int idx = 0; |
@@ -197,27 +171,6 @@ int iwl_hwrate_to_plcp_idx(u32 rate_n_flags) | |||
197 | } | 171 | } |
198 | EXPORT_SYMBOL(iwl_hwrate_to_plcp_idx); | 172 | EXPORT_SYMBOL(iwl_hwrate_to_plcp_idx); |
199 | 173 | ||
200 | int iwl_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band) | ||
201 | { | ||
202 | int idx = 0; | ||
203 | int band_offset = 0; | ||
204 | |||
205 | /* HT rate format: mac80211 wants an MCS number, which is just LSB */ | ||
206 | if (rate_n_flags & RATE_MCS_HT_MSK) { | ||
207 | idx = (rate_n_flags & 0xff); | ||
208 | return idx; | ||
209 | /* Legacy rate format, search for match in table */ | ||
210 | } else { | ||
211 | if (band == IEEE80211_BAND_5GHZ) | ||
212 | band_offset = IWL_FIRST_OFDM_RATE; | ||
213 | for (idx = band_offset; idx < IWL_RATE_COUNT_LEGACY; idx++) | ||
214 | if (iwl_rates[idx].plcp == (rate_n_flags & 0xFF)) | ||
215 | return idx - band_offset; | ||
216 | } | ||
217 | |||
218 | return -1; | ||
219 | } | ||
220 | |||
221 | u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant) | 174 | u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant) |
222 | { | 175 | { |
223 | int i; | 176 | int i; |
@@ -267,74 +220,16 @@ void iwl_hw_detect(struct iwl_priv *priv) | |||
267 | } | 220 | } |
268 | EXPORT_SYMBOL(iwl_hw_detect); | 221 | EXPORT_SYMBOL(iwl_hw_detect); |
269 | 222 | ||
270 | int iwl_hw_nic_init(struct iwl_priv *priv) | ||
271 | { | ||
272 | unsigned long flags; | ||
273 | struct iwl_rx_queue *rxq = &priv->rxq; | ||
274 | int ret; | ||
275 | |||
276 | /* nic_init */ | ||
277 | spin_lock_irqsave(&priv->lock, flags); | ||
278 | priv->cfg->ops->lib->apm_ops.init(priv); | ||
279 | |||
280 | /* Set interrupt coalescing calibration timer to default (512 usecs) */ | ||
281 | iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF); | ||
282 | |||
283 | spin_unlock_irqrestore(&priv->lock, flags); | ||
284 | |||
285 | ret = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN); | ||
286 | |||
287 | priv->cfg->ops->lib->apm_ops.config(priv); | ||
288 | |||
289 | /* Allocate the RX queue, or reset if it is already allocated */ | ||
290 | if (!rxq->bd) { | ||
291 | ret = iwl_rx_queue_alloc(priv); | ||
292 | if (ret) { | ||
293 | IWL_ERR(priv, "Unable to initialize Rx queue\n"); | ||
294 | return -ENOMEM; | ||
295 | } | ||
296 | } else | ||
297 | iwl_rx_queue_reset(priv, rxq); | ||
298 | |||
299 | iwl_rx_replenish(priv); | ||
300 | |||
301 | iwl_rx_init(priv, rxq); | ||
302 | |||
303 | spin_lock_irqsave(&priv->lock, flags); | ||
304 | |||
305 | rxq->need_update = 1; | ||
306 | iwl_rx_queue_update_write_ptr(priv, rxq); | ||
307 | |||
308 | spin_unlock_irqrestore(&priv->lock, flags); | ||
309 | |||
310 | /* Allocate or reset and init all Tx and Command queues */ | ||
311 | if (!priv->txq) { | ||
312 | ret = iwl_txq_ctx_alloc(priv); | ||
313 | if (ret) | ||
314 | return ret; | ||
315 | } else | ||
316 | iwl_txq_ctx_reset(priv); | ||
317 | |||
318 | set_bit(STATUS_INIT, &priv->status); | ||
319 | |||
320 | return 0; | ||
321 | } | ||
322 | EXPORT_SYMBOL(iwl_hw_nic_init); | ||
323 | |||
324 | /* | 223 | /* |
325 | * QoS support | 224 | * QoS support |
326 | */ | 225 | */ |
327 | void iwl_activate_qos(struct iwl_priv *priv, u8 force) | 226 | static void iwl_update_qos(struct iwl_priv *priv) |
328 | { | 227 | { |
329 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 228 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
330 | return; | 229 | return; |
331 | 230 | ||
332 | priv->qos_data.def_qos_parm.qos_flags = 0; | 231 | priv->qos_data.def_qos_parm.qos_flags = 0; |
333 | 232 | ||
334 | if (priv->qos_data.qos_cap.q_AP.queue_request && | ||
335 | !priv->qos_data.qos_cap.q_AP.txop_request) | ||
336 | priv->qos_data.def_qos_parm.qos_flags |= | ||
337 | QOS_PARAM_FLG_TXOP_TYPE_MSK; | ||
338 | if (priv->qos_data.qos_active) | 233 | if (priv->qos_data.qos_active) |
339 | priv->qos_data.def_qos_parm.qos_flags |= | 234 | priv->qos_data.def_qos_parm.qos_flags |= |
340 | QOS_PARAM_FLG_UPDATE_EDCA_MSK; | 235 | QOS_PARAM_FLG_UPDATE_EDCA_MSK; |
@@ -342,118 +237,14 @@ void iwl_activate_qos(struct iwl_priv *priv, u8 force) | |||
342 | if (priv->current_ht_config.is_ht) | 237 | if (priv->current_ht_config.is_ht) |
343 | priv->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK; | 238 | priv->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK; |
344 | 239 | ||
345 | if (force || iwl_is_associated(priv)) { | 240 | IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n", |
346 | IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n", | 241 | priv->qos_data.qos_active, |
347 | priv->qos_data.qos_active, | 242 | priv->qos_data.def_qos_parm.qos_flags); |
348 | priv->qos_data.def_qos_parm.qos_flags); | ||
349 | 243 | ||
350 | iwl_send_cmd_pdu_async(priv, REPLY_QOS_PARAM, | 244 | iwl_send_cmd_pdu_async(priv, REPLY_QOS_PARAM, |
351 | sizeof(struct iwl_qosparam_cmd), | 245 | sizeof(struct iwl_qosparam_cmd), |
352 | &priv->qos_data.def_qos_parm, NULL); | 246 | &priv->qos_data.def_qos_parm, NULL); |
353 | } | ||
354 | } | 247 | } |
355 | EXPORT_SYMBOL(iwl_activate_qos); | ||
356 | |||
357 | /* | ||
358 | * AC CWmin CW max AIFSN TXOP Limit TXOP Limit | ||
359 | * (802.11b) (802.11a/g) | ||
360 | * AC_BK 15 1023 7 0 0 | ||
361 | * AC_BE 15 1023 3 0 0 | ||
362 | * AC_VI 7 15 2 6.016ms 3.008ms | ||
363 | * AC_VO 3 7 2 3.264ms 1.504ms | ||
364 | */ | ||
365 | void iwl_reset_qos(struct iwl_priv *priv) | ||
366 | { | ||
367 | u16 cw_min = 15; | ||
368 | u16 cw_max = 1023; | ||
369 | u8 aifs = 2; | ||
370 | bool is_legacy = false; | ||
371 | unsigned long flags; | ||
372 | int i; | ||
373 | |||
374 | spin_lock_irqsave(&priv->lock, flags); | ||
375 | /* QoS always active in AP and ADHOC mode | ||
376 | * In STA mode wait for association | ||
377 | */ | ||
378 | if (priv->iw_mode == NL80211_IFTYPE_ADHOC || | ||
379 | priv->iw_mode == NL80211_IFTYPE_AP) | ||
380 | priv->qos_data.qos_active = 1; | ||
381 | else | ||
382 | priv->qos_data.qos_active = 0; | ||
383 | |||
384 | /* check for legacy mode */ | ||
385 | if ((priv->iw_mode == NL80211_IFTYPE_ADHOC && | ||
386 | (priv->active_rate & IWL_OFDM_RATES_MASK) == 0) || | ||
387 | (priv->iw_mode == NL80211_IFTYPE_STATION && | ||
388 | (priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK) == 0)) { | ||
389 | cw_min = 31; | ||
390 | is_legacy = 1; | ||
391 | } | ||
392 | |||
393 | if (priv->qos_data.qos_active) | ||
394 | aifs = 3; | ||
395 | |||
396 | /* AC_BE */ | ||
397 | priv->qos_data.def_qos_parm.ac[0].cw_min = cpu_to_le16(cw_min); | ||
398 | priv->qos_data.def_qos_parm.ac[0].cw_max = cpu_to_le16(cw_max); | ||
399 | priv->qos_data.def_qos_parm.ac[0].aifsn = aifs; | ||
400 | priv->qos_data.def_qos_parm.ac[0].edca_txop = 0; | ||
401 | priv->qos_data.def_qos_parm.ac[0].reserved1 = 0; | ||
402 | |||
403 | if (priv->qos_data.qos_active) { | ||
404 | /* AC_BK */ | ||
405 | i = 1; | ||
406 | priv->qos_data.def_qos_parm.ac[i].cw_min = cpu_to_le16(cw_min); | ||
407 | priv->qos_data.def_qos_parm.ac[i].cw_max = cpu_to_le16(cw_max); | ||
408 | priv->qos_data.def_qos_parm.ac[i].aifsn = 7; | ||
409 | priv->qos_data.def_qos_parm.ac[i].edca_txop = 0; | ||
410 | priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; | ||
411 | |||
412 | /* AC_VI */ | ||
413 | i = 2; | ||
414 | priv->qos_data.def_qos_parm.ac[i].cw_min = | ||
415 | cpu_to_le16((cw_min + 1) / 2 - 1); | ||
416 | priv->qos_data.def_qos_parm.ac[i].cw_max = | ||
417 | cpu_to_le16(cw_min); | ||
418 | priv->qos_data.def_qos_parm.ac[i].aifsn = 2; | ||
419 | if (is_legacy) | ||
420 | priv->qos_data.def_qos_parm.ac[i].edca_txop = | ||
421 | cpu_to_le16(6016); | ||
422 | else | ||
423 | priv->qos_data.def_qos_parm.ac[i].edca_txop = | ||
424 | cpu_to_le16(3008); | ||
425 | priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; | ||
426 | |||
427 | /* AC_VO */ | ||
428 | i = 3; | ||
429 | priv->qos_data.def_qos_parm.ac[i].cw_min = | ||
430 | cpu_to_le16((cw_min + 1) / 4 - 1); | ||
431 | priv->qos_data.def_qos_parm.ac[i].cw_max = | ||
432 | cpu_to_le16((cw_min + 1) / 2 - 1); | ||
433 | priv->qos_data.def_qos_parm.ac[i].aifsn = 2; | ||
434 | priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; | ||
435 | if (is_legacy) | ||
436 | priv->qos_data.def_qos_parm.ac[i].edca_txop = | ||
437 | cpu_to_le16(3264); | ||
438 | else | ||
439 | priv->qos_data.def_qos_parm.ac[i].edca_txop = | ||
440 | cpu_to_le16(1504); | ||
441 | } else { | ||
442 | for (i = 1; i < 4; i++) { | ||
443 | priv->qos_data.def_qos_parm.ac[i].cw_min = | ||
444 | cpu_to_le16(cw_min); | ||
445 | priv->qos_data.def_qos_parm.ac[i].cw_max = | ||
446 | cpu_to_le16(cw_max); | ||
447 | priv->qos_data.def_qos_parm.ac[i].aifsn = aifs; | ||
448 | priv->qos_data.def_qos_parm.ac[i].edca_txop = 0; | ||
449 | priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; | ||
450 | } | ||
451 | } | ||
452 | IWL_DEBUG_QOS(priv, "set QoS to default \n"); | ||
453 | |||
454 | spin_unlock_irqrestore(&priv->lock, flags); | ||
455 | } | ||
456 | EXPORT_SYMBOL(iwl_reset_qos); | ||
457 | 248 | ||
458 | #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */ | 249 | #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */ |
459 | #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */ | 250 | #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */ |
@@ -902,23 +693,10 @@ EXPORT_SYMBOL(iwl_full_rxon_required); | |||
902 | 693 | ||
903 | u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv) | 694 | u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv) |
904 | { | 695 | { |
905 | int i; | 696 | /* |
906 | int rate_mask; | 697 | * Assign the lowest rate -- should really get this from |
907 | 698 | * the beacon skb from mac80211. | |
908 | /* Set rate mask*/ | 699 | */ |
909 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) | ||
910 | rate_mask = priv->active_rate_basic & IWL_CCK_RATES_MASK; | ||
911 | else | ||
912 | rate_mask = priv->active_rate_basic & IWL_OFDM_RATES_MASK; | ||
913 | |||
914 | /* Find lowest valid rate */ | ||
915 | for (i = IWL_RATE_1M_INDEX; i != IWL_RATE_INVALID; | ||
916 | i = iwl_rates[i].next_ieee) { | ||
917 | if (rate_mask & (1 << i)) | ||
918 | return iwl_rates[i].plcp; | ||
919 | } | ||
920 | |||
921 | /* No valid rate was found. Assign the lowest one */ | ||
922 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) | 700 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) |
923 | return IWL_RATE_1M_PLCP; | 701 | return IWL_RATE_1M_PLCP; |
924 | else | 702 | else |
@@ -1106,12 +884,12 @@ void iwl_set_rxon_chain(struct iwl_priv *priv) | |||
1106 | rx_chain |= idle_rx_cnt << RXON_RX_CHAIN_CNT_POS; | 884 | rx_chain |= idle_rx_cnt << RXON_RX_CHAIN_CNT_POS; |
1107 | 885 | ||
1108 | /* copied from 'iwl_bg_request_scan()' */ | 886 | /* copied from 'iwl_bg_request_scan()' */ |
1109 | /* Force use of chains B and C (0x6) for Rx for 4965 | 887 | /* Force use of chains B and C (0x6) for Rx |
1110 | * Avoid A (0x1) because of its off-channel reception on A-band. | 888 | * Avoid A (0x1) for the device has off-channel reception on A-band. |
1111 | * MIMO is not used here, but value is required */ | 889 | * MIMO is not used here, but value is required */ |
1112 | if (iwl_is_monitor_mode(priv) && | 890 | if (iwl_is_monitor_mode(priv) && |
1113 | !(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) && | 891 | !(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) && |
1114 | ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965)) { | 892 | priv->cfg->off_channel_workaround) { |
1115 | rx_chain = ANT_ABC << RXON_RX_CHAIN_VALID_POS; | 893 | rx_chain = ANT_ABC << RXON_RX_CHAIN_VALID_POS; |
1116 | rx_chain |= ANT_BC << RXON_RX_CHAIN_FORCE_SEL_POS; | 894 | rx_chain |= ANT_BC << RXON_RX_CHAIN_FORCE_SEL_POS; |
1117 | rx_chain |= ANT_ABC << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; | 895 | rx_chain |= ANT_ABC << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; |
@@ -1243,14 +1021,6 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv, int mode) | |||
1243 | if (!ch_info) | 1021 | if (!ch_info) |
1244 | ch_info = &priv->channel_info[0]; | 1022 | ch_info = &priv->channel_info[0]; |
1245 | 1023 | ||
1246 | /* | ||
1247 | * in some case A channels are all non IBSS | ||
1248 | * in this case force B/G channel | ||
1249 | */ | ||
1250 | if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && | ||
1251 | !(is_channel_ibss(ch_info))) | ||
1252 | ch_info = &priv->channel_info[0]; | ||
1253 | |||
1254 | priv->staging_rxon.channel = cpu_to_le16(ch_info->channel); | 1024 | priv->staging_rxon.channel = cpu_to_le16(ch_info->channel); |
1255 | priv->band = ch_info->band; | 1025 | priv->band = ch_info->band; |
1256 | 1026 | ||
@@ -1285,7 +1055,6 @@ static void iwl_set_rate(struct iwl_priv *priv) | |||
1285 | } | 1055 | } |
1286 | 1056 | ||
1287 | priv->active_rate = 0; | 1057 | priv->active_rate = 0; |
1288 | priv->active_rate_basic = 0; | ||
1289 | 1058 | ||
1290 | for (i = 0; i < hw->n_bitrates; i++) { | 1059 | for (i = 0; i < hw->n_bitrates; i++) { |
1291 | rate = &(hw->bitrates[i]); | 1060 | rate = &(hw->bitrates[i]); |
@@ -1293,30 +1062,13 @@ static void iwl_set_rate(struct iwl_priv *priv) | |||
1293 | priv->active_rate |= (1 << rate->hw_value); | 1062 | priv->active_rate |= (1 << rate->hw_value); |
1294 | } | 1063 | } |
1295 | 1064 | ||
1296 | IWL_DEBUG_RATE(priv, "Set active_rate = %0x, active_rate_basic = %0x\n", | 1065 | IWL_DEBUG_RATE(priv, "Set active_rate = %0x\n", priv->active_rate); |
1297 | priv->active_rate, priv->active_rate_basic); | ||
1298 | 1066 | ||
1299 | /* | 1067 | priv->staging_rxon.cck_basic_rates = |
1300 | * If a basic rate is configured, then use it (adding IWL_RATE_1M_MASK) | 1068 | (IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF; |
1301 | * otherwise set it to the default of all CCK rates and 6, 12, 24 for | 1069 | |
1302 | * OFDM | 1070 | priv->staging_rxon.ofdm_basic_rates = |
1303 | */ | 1071 | (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; |
1304 | if (priv->active_rate_basic & IWL_CCK_BASIC_RATES_MASK) | ||
1305 | priv->staging_rxon.cck_basic_rates = | ||
1306 | ((priv->active_rate_basic & | ||
1307 | IWL_CCK_RATES_MASK) >> IWL_FIRST_CCK_RATE) & 0xF; | ||
1308 | else | ||
1309 | priv->staging_rxon.cck_basic_rates = | ||
1310 | (IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF; | ||
1311 | |||
1312 | if (priv->active_rate_basic & IWL_OFDM_BASIC_RATES_MASK) | ||
1313 | priv->staging_rxon.ofdm_basic_rates = | ||
1314 | ((priv->active_rate_basic & | ||
1315 | (IWL_OFDM_BASIC_RATES_MASK | IWL_RATE_6M_MASK)) >> | ||
1316 | IWL_FIRST_OFDM_RATE) & 0xFF; | ||
1317 | else | ||
1318 | priv->staging_rxon.ofdm_basic_rates = | ||
1319 | (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; | ||
1320 | } | 1072 | } |
1321 | 1073 | ||
1322 | void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | 1074 | void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) |
@@ -1400,7 +1152,7 @@ void iwl_irq_handle_error(struct iwl_priv *priv) | |||
1400 | } | 1152 | } |
1401 | EXPORT_SYMBOL(iwl_irq_handle_error); | 1153 | EXPORT_SYMBOL(iwl_irq_handle_error); |
1402 | 1154 | ||
1403 | int iwl_apm_stop_master(struct iwl_priv *priv) | 1155 | static int iwl_apm_stop_master(struct iwl_priv *priv) |
1404 | { | 1156 | { |
1405 | int ret = 0; | 1157 | int ret = 0; |
1406 | 1158 | ||
@@ -1416,7 +1168,6 @@ int iwl_apm_stop_master(struct iwl_priv *priv) | |||
1416 | 1168 | ||
1417 | return ret; | 1169 | return ret; |
1418 | } | 1170 | } |
1419 | EXPORT_SYMBOL(iwl_apm_stop_master); | ||
1420 | 1171 | ||
1421 | void iwl_apm_stop(struct iwl_priv *priv) | 1172 | void iwl_apm_stop(struct iwl_priv *priv) |
1422 | { | 1173 | { |
@@ -1625,10 +1376,11 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) | |||
1625 | int ret = 0; | 1376 | int ret = 0; |
1626 | s8 prev_tx_power = priv->tx_power_user_lmt; | 1377 | s8 prev_tx_power = priv->tx_power_user_lmt; |
1627 | 1378 | ||
1628 | if (tx_power < IWL_TX_POWER_TARGET_POWER_MIN) { | 1379 | if (tx_power < IWLAGN_TX_POWER_TARGET_POWER_MIN) { |
1629 | IWL_WARN(priv, "Requested user TXPOWER %d below lower limit %d.\n", | 1380 | IWL_WARN(priv, |
1381 | "Requested user TXPOWER %d below lower limit %d.\n", | ||
1630 | tx_power, | 1382 | tx_power, |
1631 | IWL_TX_POWER_TARGET_POWER_MIN); | 1383 | IWLAGN_TX_POWER_TARGET_POWER_MIN); |
1632 | return -EINVAL; | 1384 | return -EINVAL; |
1633 | } | 1385 | } |
1634 | 1386 | ||
@@ -1667,286 +1419,16 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) | |||
1667 | } | 1419 | } |
1668 | EXPORT_SYMBOL(iwl_set_tx_power); | 1420 | EXPORT_SYMBOL(iwl_set_tx_power); |
1669 | 1421 | ||
1670 | #define ICT_COUNT (PAGE_SIZE/sizeof(u32)) | ||
1671 | |||
1672 | /* Free dram table */ | ||
1673 | void iwl_free_isr_ict(struct iwl_priv *priv) | ||
1674 | { | ||
1675 | if (priv->ict_tbl_vir) { | ||
1676 | dma_free_coherent(&priv->pci_dev->dev, | ||
1677 | (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, | ||
1678 | priv->ict_tbl_vir, priv->ict_tbl_dma); | ||
1679 | priv->ict_tbl_vir = NULL; | ||
1680 | } | ||
1681 | } | ||
1682 | EXPORT_SYMBOL(iwl_free_isr_ict); | ||
1683 | |||
1684 | |||
1685 | /* allocate dram shared table it is a PAGE_SIZE aligned | ||
1686 | * also reset all data related to ICT table interrupt. | ||
1687 | */ | ||
1688 | int iwl_alloc_isr_ict(struct iwl_priv *priv) | ||
1689 | { | ||
1690 | |||
1691 | if (priv->cfg->use_isr_legacy) | ||
1692 | return 0; | ||
1693 | /* allocate shrared data table */ | ||
1694 | priv->ict_tbl_vir = dma_alloc_coherent(&priv->pci_dev->dev, | ||
1695 | (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, | ||
1696 | &priv->ict_tbl_dma, GFP_KERNEL); | ||
1697 | if (!priv->ict_tbl_vir) | ||
1698 | return -ENOMEM; | ||
1699 | |||
1700 | /* align table to PAGE_SIZE boundry */ | ||
1701 | priv->aligned_ict_tbl_dma = ALIGN(priv->ict_tbl_dma, PAGE_SIZE); | ||
1702 | |||
1703 | IWL_DEBUG_ISR(priv, "ict dma addr %Lx dma aligned %Lx diff %d\n", | ||
1704 | (unsigned long long)priv->ict_tbl_dma, | ||
1705 | (unsigned long long)priv->aligned_ict_tbl_dma, | ||
1706 | (int)(priv->aligned_ict_tbl_dma - priv->ict_tbl_dma)); | ||
1707 | |||
1708 | priv->ict_tbl = priv->ict_tbl_vir + | ||
1709 | (priv->aligned_ict_tbl_dma - priv->ict_tbl_dma); | ||
1710 | |||
1711 | IWL_DEBUG_ISR(priv, "ict vir addr %p vir aligned %p diff %d\n", | ||
1712 | priv->ict_tbl, priv->ict_tbl_vir, | ||
1713 | (int)(priv->aligned_ict_tbl_dma - priv->ict_tbl_dma)); | ||
1714 | |||
1715 | /* reset table and index to all 0 */ | ||
1716 | memset(priv->ict_tbl_vir,0, (sizeof(u32) * ICT_COUNT) + PAGE_SIZE); | ||
1717 | priv->ict_index = 0; | ||
1718 | |||
1719 | /* add periodic RX interrupt */ | ||
1720 | priv->inta_mask |= CSR_INT_BIT_RX_PERIODIC; | ||
1721 | return 0; | ||
1722 | } | ||
1723 | EXPORT_SYMBOL(iwl_alloc_isr_ict); | ||
1724 | |||
1725 | /* Device is going up inform it about using ICT interrupt table, | ||
1726 | * also we need to tell the driver to start using ICT interrupt. | ||
1727 | */ | ||
1728 | int iwl_reset_ict(struct iwl_priv *priv) | ||
1729 | { | ||
1730 | u32 val; | ||
1731 | unsigned long flags; | ||
1732 | |||
1733 | if (!priv->ict_tbl_vir) | ||
1734 | return 0; | ||
1735 | |||
1736 | spin_lock_irqsave(&priv->lock, flags); | ||
1737 | iwl_disable_interrupts(priv); | ||
1738 | |||
1739 | memset(&priv->ict_tbl[0], 0, sizeof(u32) * ICT_COUNT); | ||
1740 | |||
1741 | val = priv->aligned_ict_tbl_dma >> PAGE_SHIFT; | ||
1742 | |||
1743 | val |= CSR_DRAM_INT_TBL_ENABLE; | ||
1744 | val |= CSR_DRAM_INIT_TBL_WRAP_CHECK; | ||
1745 | |||
1746 | IWL_DEBUG_ISR(priv, "CSR_DRAM_INT_TBL_REG =0x%X " | ||
1747 | "aligned dma address %Lx\n", | ||
1748 | val, (unsigned long long)priv->aligned_ict_tbl_dma); | ||
1749 | |||
1750 | iwl_write32(priv, CSR_DRAM_INT_TBL_REG, val); | ||
1751 | priv->use_ict = true; | ||
1752 | priv->ict_index = 0; | ||
1753 | iwl_write32(priv, CSR_INT, priv->inta_mask); | ||
1754 | iwl_enable_interrupts(priv); | ||
1755 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1756 | |||
1757 | return 0; | ||
1758 | } | ||
1759 | EXPORT_SYMBOL(iwl_reset_ict); | ||
1760 | |||
1761 | /* Device is going down disable ict interrupt usage */ | ||
1762 | void iwl_disable_ict(struct iwl_priv *priv) | ||
1763 | { | ||
1764 | unsigned long flags; | ||
1765 | |||
1766 | spin_lock_irqsave(&priv->lock, flags); | ||
1767 | priv->use_ict = false; | ||
1768 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1769 | } | ||
1770 | EXPORT_SYMBOL(iwl_disable_ict); | ||
1771 | |||
1772 | /* interrupt handler using ict table, with this interrupt driver will | ||
1773 | * stop using INTA register to get device's interrupt, reading this register | ||
1774 | * is expensive, device will write interrupts in ICT dram table, increment | ||
1775 | * index then will fire interrupt to driver, driver will OR all ICT table | ||
1776 | * entries from current index up to table entry with 0 value. the result is | ||
1777 | * the interrupt we need to service, driver will set the entries back to 0 and | ||
1778 | * set index. | ||
1779 | */ | ||
1780 | irqreturn_t iwl_isr_ict(int irq, void *data) | ||
1781 | { | ||
1782 | struct iwl_priv *priv = data; | ||
1783 | u32 inta, inta_mask; | ||
1784 | u32 val = 0; | ||
1785 | |||
1786 | if (!priv) | ||
1787 | return IRQ_NONE; | ||
1788 | |||
1789 | /* dram interrupt table not set yet, | ||
1790 | * use legacy interrupt. | ||
1791 | */ | ||
1792 | if (!priv->use_ict) | ||
1793 | return iwl_isr(irq, data); | ||
1794 | |||
1795 | spin_lock(&priv->lock); | ||
1796 | |||
1797 | /* Disable (but don't clear!) interrupts here to avoid | ||
1798 | * back-to-back ISRs and sporadic interrupts from our NIC. | ||
1799 | * If we have something to service, the tasklet will re-enable ints. | ||
1800 | * If we *don't* have something, we'll re-enable before leaving here. | ||
1801 | */ | ||
1802 | inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */ | ||
1803 | iwl_write32(priv, CSR_INT_MASK, 0x00000000); | ||
1804 | |||
1805 | |||
1806 | /* Ignore interrupt if there's nothing in NIC to service. | ||
1807 | * This may be due to IRQ shared with another device, | ||
1808 | * or due to sporadic interrupts thrown from our NIC. */ | ||
1809 | if (!priv->ict_tbl[priv->ict_index]) { | ||
1810 | IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n"); | ||
1811 | goto none; | ||
1812 | } | ||
1813 | |||
1814 | /* read all entries that not 0 start with ict_index */ | ||
1815 | while (priv->ict_tbl[priv->ict_index]) { | ||
1816 | |||
1817 | val |= le32_to_cpu(priv->ict_tbl[priv->ict_index]); | ||
1818 | IWL_DEBUG_ISR(priv, "ICT index %d value 0x%08X\n", | ||
1819 | priv->ict_index, | ||
1820 | le32_to_cpu(priv->ict_tbl[priv->ict_index])); | ||
1821 | priv->ict_tbl[priv->ict_index] = 0; | ||
1822 | priv->ict_index = iwl_queue_inc_wrap(priv->ict_index, | ||
1823 | ICT_COUNT); | ||
1824 | |||
1825 | } | ||
1826 | |||
1827 | /* We should not get this value, just ignore it. */ | ||
1828 | if (val == 0xffffffff) | ||
1829 | val = 0; | ||
1830 | |||
1831 | /* | ||
1832 | * this is a w/a for a h/w bug. the h/w bug may cause the Rx bit | ||
1833 | * (bit 15 before shifting it to 31) to clear when using interrupt | ||
1834 | * coalescing. fortunately, bits 18 and 19 stay set when this happens | ||
1835 | * so we use them to decide on the real state of the Rx bit. | ||
1836 | * In order words, bit 15 is set if bit 18 or bit 19 are set. | ||
1837 | */ | ||
1838 | if (val & 0xC0000) | ||
1839 | val |= 0x8000; | ||
1840 | |||
1841 | inta = (0xff & val) | ((0xff00 & val) << 16); | ||
1842 | IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n", | ||
1843 | inta, inta_mask, val); | ||
1844 | |||
1845 | inta &= priv->inta_mask; | ||
1846 | priv->inta |= inta; | ||
1847 | |||
1848 | /* iwl_irq_tasklet() will service interrupts and re-enable them */ | ||
1849 | if (likely(inta)) | ||
1850 | tasklet_schedule(&priv->irq_tasklet); | ||
1851 | else if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) { | ||
1852 | /* Allow interrupt if was disabled by this handler and | ||
1853 | * no tasklet was schedules, We should not enable interrupt, | ||
1854 | * tasklet will enable it. | ||
1855 | */ | ||
1856 | iwl_enable_interrupts(priv); | ||
1857 | } | ||
1858 | |||
1859 | spin_unlock(&priv->lock); | ||
1860 | return IRQ_HANDLED; | ||
1861 | |||
1862 | none: | ||
1863 | /* re-enable interrupts here since we don't have anything to service. | ||
1864 | * only Re-enable if disabled by irq. | ||
1865 | */ | ||
1866 | if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) | ||
1867 | iwl_enable_interrupts(priv); | ||
1868 | |||
1869 | spin_unlock(&priv->lock); | ||
1870 | return IRQ_NONE; | ||
1871 | } | ||
1872 | EXPORT_SYMBOL(iwl_isr_ict); | ||
1873 | |||
1874 | |||
1875 | static irqreturn_t iwl_isr(int irq, void *data) | ||
1876 | { | ||
1877 | struct iwl_priv *priv = data; | ||
1878 | u32 inta, inta_mask; | ||
1879 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1880 | u32 inta_fh; | ||
1881 | #endif | ||
1882 | if (!priv) | ||
1883 | return IRQ_NONE; | ||
1884 | |||
1885 | spin_lock(&priv->lock); | ||
1886 | |||
1887 | /* Disable (but don't clear!) interrupts here to avoid | ||
1888 | * back-to-back ISRs and sporadic interrupts from our NIC. | ||
1889 | * If we have something to service, the tasklet will re-enable ints. | ||
1890 | * If we *don't* have something, we'll re-enable before leaving here. */ | ||
1891 | inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */ | ||
1892 | iwl_write32(priv, CSR_INT_MASK, 0x00000000); | ||
1893 | |||
1894 | /* Discover which interrupts are active/pending */ | ||
1895 | inta = iwl_read32(priv, CSR_INT); | ||
1896 | |||
1897 | /* Ignore interrupt if there's nothing in NIC to service. | ||
1898 | * This may be due to IRQ shared with another device, | ||
1899 | * or due to sporadic interrupts thrown from our NIC. */ | ||
1900 | if (!inta) { | ||
1901 | IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n"); | ||
1902 | goto none; | ||
1903 | } | ||
1904 | |||
1905 | if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) { | ||
1906 | /* Hardware disappeared. It might have already raised | ||
1907 | * an interrupt */ | ||
1908 | IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta); | ||
1909 | goto unplugged; | ||
1910 | } | ||
1911 | |||
1912 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1913 | if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) { | ||
1914 | inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); | ||
1915 | IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, " | ||
1916 | "fh 0x%08x\n", inta, inta_mask, inta_fh); | ||
1917 | } | ||
1918 | #endif | ||
1919 | |||
1920 | priv->inta |= inta; | ||
1921 | /* iwl_irq_tasklet() will service interrupts and re-enable them */ | ||
1922 | if (likely(inta)) | ||
1923 | tasklet_schedule(&priv->irq_tasklet); | ||
1924 | else if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) | ||
1925 | iwl_enable_interrupts(priv); | ||
1926 | |||
1927 | unplugged: | ||
1928 | spin_unlock(&priv->lock); | ||
1929 | return IRQ_HANDLED; | ||
1930 | |||
1931 | none: | ||
1932 | /* re-enable interrupts here since we don't have anything to service. */ | ||
1933 | /* only Re-enable if diabled by irq and no schedules tasklet. */ | ||
1934 | if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) | ||
1935 | iwl_enable_interrupts(priv); | ||
1936 | |||
1937 | spin_unlock(&priv->lock); | ||
1938 | return IRQ_NONE; | ||
1939 | } | ||
1940 | |||
1941 | irqreturn_t iwl_isr_legacy(int irq, void *data) | 1422 | irqreturn_t iwl_isr_legacy(int irq, void *data) |
1942 | { | 1423 | { |
1943 | struct iwl_priv *priv = data; | 1424 | struct iwl_priv *priv = data; |
1944 | u32 inta, inta_mask; | 1425 | u32 inta, inta_mask; |
1945 | u32 inta_fh; | 1426 | u32 inta_fh; |
1427 | unsigned long flags; | ||
1946 | if (!priv) | 1428 | if (!priv) |
1947 | return IRQ_NONE; | 1429 | return IRQ_NONE; |
1948 | 1430 | ||
1949 | spin_lock(&priv->lock); | 1431 | spin_lock_irqsave(&priv->lock, flags); |
1950 | 1432 | ||
1951 | /* Disable (but don't clear!) interrupts here to avoid | 1433 | /* Disable (but don't clear!) interrupts here to avoid |
1952 | * back-to-back ISRs and sporadic interrupts from our NIC. | 1434 | * back-to-back ISRs and sporadic interrupts from our NIC. |
@@ -1984,7 +1466,7 @@ irqreturn_t iwl_isr_legacy(int irq, void *data) | |||
1984 | tasklet_schedule(&priv->irq_tasklet); | 1466 | tasklet_schedule(&priv->irq_tasklet); |
1985 | 1467 | ||
1986 | unplugged: | 1468 | unplugged: |
1987 | spin_unlock(&priv->lock); | 1469 | spin_unlock_irqrestore(&priv->lock, flags); |
1988 | return IRQ_HANDLED; | 1470 | return IRQ_HANDLED; |
1989 | 1471 | ||
1990 | none: | 1472 | none: |
@@ -1992,7 +1474,7 @@ irqreturn_t iwl_isr_legacy(int irq, void *data) | |||
1992 | /* only Re-enable if diabled by irq */ | 1474 | /* only Re-enable if diabled by irq */ |
1993 | if (test_bit(STATUS_INT_ENABLED, &priv->status)) | 1475 | if (test_bit(STATUS_INT_ENABLED, &priv->status)) |
1994 | iwl_enable_interrupts(priv); | 1476 | iwl_enable_interrupts(priv); |
1995 | spin_unlock(&priv->lock); | 1477 | spin_unlock_irqrestore(&priv->lock, flags); |
1996 | return IRQ_NONE; | 1478 | return IRQ_NONE; |
1997 | } | 1479 | } |
1998 | EXPORT_SYMBOL(iwl_isr_legacy); | 1480 | EXPORT_SYMBOL(iwl_isr_legacy); |
@@ -2305,12 +1787,6 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
2305 | cpu_to_le16((params->txop * 32)); | 1787 | cpu_to_le16((params->txop * 32)); |
2306 | 1788 | ||
2307 | priv->qos_data.def_qos_parm.ac[q].reserved1 = 0; | 1789 | priv->qos_data.def_qos_parm.ac[q].reserved1 = 0; |
2308 | priv->qos_data.qos_active = 1; | ||
2309 | |||
2310 | if (priv->iw_mode == NL80211_IFTYPE_AP) | ||
2311 | iwl_activate_qos(priv, 1); | ||
2312 | else if (priv->assoc_id && iwl_is_associated(priv)) | ||
2313 | iwl_activate_qos(priv, 0); | ||
2314 | 1790 | ||
2315 | spin_unlock_irqrestore(&priv->lock, flags); | 1791 | spin_unlock_irqrestore(&priv->lock, flags); |
2316 | 1792 | ||
@@ -2325,7 +1801,7 @@ static void iwl_ht_conf(struct iwl_priv *priv, | |||
2325 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; | 1801 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; |
2326 | struct ieee80211_sta *sta; | 1802 | struct ieee80211_sta *sta; |
2327 | 1803 | ||
2328 | IWL_DEBUG_MAC80211(priv, "enter: \n"); | 1804 | IWL_DEBUG_MAC80211(priv, "enter:\n"); |
2329 | 1805 | ||
2330 | if (!ht_conf->is_ht) | 1806 | if (!ht_conf->is_ht) |
2331 | return; | 1807 | return; |
@@ -2567,11 +2043,6 @@ int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
2567 | return -EIO; | 2043 | return -EIO; |
2568 | } | 2044 | } |
2569 | 2045 | ||
2570 | if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { | ||
2571 | IWL_DEBUG_MAC80211(priv, "leave - not IBSS\n"); | ||
2572 | return -EIO; | ||
2573 | } | ||
2574 | |||
2575 | spin_lock_irqsave(&priv->lock, flags); | 2046 | spin_lock_irqsave(&priv->lock, flags); |
2576 | 2047 | ||
2577 | if (priv->ibss_beacon) | 2048 | if (priv->ibss_beacon) |
@@ -2586,52 +2057,25 @@ int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
2586 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 2057 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
2587 | spin_unlock_irqrestore(&priv->lock, flags); | 2058 | spin_unlock_irqrestore(&priv->lock, flags); |
2588 | 2059 | ||
2589 | iwl_reset_qos(priv); | ||
2590 | |||
2591 | priv->cfg->ops->lib->post_associate(priv); | 2060 | priv->cfg->ops->lib->post_associate(priv); |
2592 | 2061 | ||
2593 | |||
2594 | return 0; | 2062 | return 0; |
2595 | } | 2063 | } |
2596 | EXPORT_SYMBOL(iwl_mac_beacon_update); | 2064 | EXPORT_SYMBOL(iwl_mac_beacon_update); |
2597 | 2065 | ||
2598 | int iwl_set_mode(struct iwl_priv *priv, int mode) | 2066 | static int iwl_set_mode(struct iwl_priv *priv, struct ieee80211_vif *vif) |
2599 | { | 2067 | { |
2600 | if (mode == NL80211_IFTYPE_ADHOC) { | 2068 | iwl_connection_init_rx_config(priv, vif->type); |
2601 | const struct iwl_channel_info *ch_info; | ||
2602 | |||
2603 | ch_info = iwl_get_channel_info(priv, | ||
2604 | priv->band, | ||
2605 | le16_to_cpu(priv->staging_rxon.channel)); | ||
2606 | |||
2607 | if (!ch_info || !is_channel_ibss(ch_info)) { | ||
2608 | IWL_ERR(priv, "channel %d not IBSS channel\n", | ||
2609 | le16_to_cpu(priv->staging_rxon.channel)); | ||
2610 | return -EINVAL; | ||
2611 | } | ||
2612 | } | ||
2613 | |||
2614 | iwl_connection_init_rx_config(priv, mode); | ||
2615 | 2069 | ||
2616 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 2070 | if (priv->cfg->ops->hcmd->set_rxon_chain) |
2617 | priv->cfg->ops->hcmd->set_rxon_chain(priv); | 2071 | priv->cfg->ops->hcmd->set_rxon_chain(priv); |
2618 | 2072 | ||
2619 | memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); | 2073 | memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); |
2620 | 2074 | ||
2621 | iwl_clear_stations_table(priv); | 2075 | return iwlcore_commit_rxon(priv); |
2622 | |||
2623 | /* dont commit rxon if rf-kill is on*/ | ||
2624 | if (!iwl_is_ready_rf(priv)) | ||
2625 | return -EAGAIN; | ||
2626 | |||
2627 | iwlcore_commit_rxon(priv); | ||
2628 | |||
2629 | return 0; | ||
2630 | } | 2076 | } |
2631 | EXPORT_SYMBOL(iwl_set_mode); | ||
2632 | 2077 | ||
2633 | int iwl_mac_add_interface(struct ieee80211_hw *hw, | 2078 | int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) |
2634 | struct ieee80211_vif *vif) | ||
2635 | { | 2079 | { |
2636 | struct iwl_priv *priv = hw->priv; | 2080 | struct iwl_priv *priv = hw->priv; |
2637 | int err = 0; | 2081 | int err = 0; |
@@ -2640,6 +2084,11 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, | |||
2640 | 2084 | ||
2641 | mutex_lock(&priv->mutex); | 2085 | mutex_lock(&priv->mutex); |
2642 | 2086 | ||
2087 | if (WARN_ON(!iwl_is_ready_rf(priv))) { | ||
2088 | err = -EINVAL; | ||
2089 | goto out; | ||
2090 | } | ||
2091 | |||
2643 | if (priv->vif) { | 2092 | if (priv->vif) { |
2644 | IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n"); | 2093 | IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n"); |
2645 | err = -EOPNOTSUPP; | 2094 | err = -EOPNOTSUPP; |
@@ -2649,15 +2098,21 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, | |||
2649 | priv->vif = vif; | 2098 | priv->vif = vif; |
2650 | priv->iw_mode = vif->type; | 2099 | priv->iw_mode = vif->type; |
2651 | 2100 | ||
2652 | if (vif->addr) { | 2101 | IWL_DEBUG_MAC80211(priv, "Set %pM\n", vif->addr); |
2653 | IWL_DEBUG_MAC80211(priv, "Set %pM\n", vif->addr); | 2102 | memcpy(priv->mac_addr, vif->addr, ETH_ALEN); |
2654 | memcpy(priv->mac_addr, vif->addr, ETH_ALEN); | 2103 | |
2655 | } | 2104 | err = iwl_set_mode(priv, vif); |
2105 | if (err) | ||
2106 | goto out_err; | ||
2107 | |||
2108 | /* Add the broadcast address so we can send broadcast frames */ | ||
2109 | priv->cfg->ops->lib->add_bcast_station(priv); | ||
2656 | 2110 | ||
2657 | if (iwl_set_mode(priv, vif->type) == -EAGAIN) | 2111 | goto out; |
2658 | /* we are not ready, will run again when ready */ | ||
2659 | set_bit(STATUS_MODE_PENDING, &priv->status); | ||
2660 | 2112 | ||
2113 | out_err: | ||
2114 | priv->vif = NULL; | ||
2115 | priv->iw_mode = NL80211_IFTYPE_STATION; | ||
2661 | out: | 2116 | out: |
2662 | mutex_unlock(&priv->mutex); | 2117 | mutex_unlock(&priv->mutex); |
2663 | 2118 | ||
@@ -2667,7 +2122,7 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, | |||
2667 | EXPORT_SYMBOL(iwl_mac_add_interface); | 2122 | EXPORT_SYMBOL(iwl_mac_add_interface); |
2668 | 2123 | ||
2669 | void iwl_mac_remove_interface(struct ieee80211_hw *hw, | 2124 | void iwl_mac_remove_interface(struct ieee80211_hw *hw, |
2670 | struct ieee80211_vif *vif) | 2125 | struct ieee80211_vif *vif) |
2671 | { | 2126 | { |
2672 | struct iwl_priv *priv = hw->priv; | 2127 | struct iwl_priv *priv = hw->priv; |
2673 | 2128 | ||
@@ -2675,6 +2130,8 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, | |||
2675 | 2130 | ||
2676 | mutex_lock(&priv->mutex); | 2131 | mutex_lock(&priv->mutex); |
2677 | 2132 | ||
2133 | iwl_clear_ucode_stations(priv, true); | ||
2134 | |||
2678 | if (iwl_is_ready_rf(priv)) { | 2135 | if (iwl_is_ready_rf(priv)) { |
2679 | iwl_scan_cancel_timeout(priv, 100); | 2136 | iwl_scan_cancel_timeout(priv, 100); |
2680 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 2137 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
@@ -2751,15 +2208,6 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
2751 | goto set_ch_out; | 2208 | goto set_ch_out; |
2752 | } | 2209 | } |
2753 | 2210 | ||
2754 | if (priv->iw_mode == NL80211_IFTYPE_ADHOC && | ||
2755 | !is_channel_ibss(ch_info)) { | ||
2756 | IWL_ERR(priv, "channel %d in band %d not " | ||
2757 | "IBSS channel\n", | ||
2758 | conf->channel->hw_value, conf->channel->band); | ||
2759 | ret = -EINVAL; | ||
2760 | goto set_ch_out; | ||
2761 | } | ||
2762 | |||
2763 | spin_lock_irqsave(&priv->lock, flags); | 2211 | spin_lock_irqsave(&priv->lock, flags); |
2764 | 2212 | ||
2765 | /* Configure HT40 channels */ | 2213 | /* Configure HT40 channels */ |
@@ -2832,6 +2280,15 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
2832 | iwl_set_tx_power(priv, conf->power_level, false); | 2280 | iwl_set_tx_power(priv, conf->power_level, false); |
2833 | } | 2281 | } |
2834 | 2282 | ||
2283 | if (changed & IEEE80211_CONF_CHANGE_QOS) { | ||
2284 | bool qos_active = !!(conf->flags & IEEE80211_CONF_QOS); | ||
2285 | |||
2286 | spin_lock_irqsave(&priv->lock, flags); | ||
2287 | priv->qos_data.qos_active = qos_active; | ||
2288 | iwl_update_qos(priv); | ||
2289 | spin_unlock_irqrestore(&priv->lock, flags); | ||
2290 | } | ||
2291 | |||
2835 | if (!iwl_is_ready(priv)) { | 2292 | if (!iwl_is_ready(priv)) { |
2836 | IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); | 2293 | IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); |
2837 | goto out; | 2294 | goto out; |
@@ -2866,12 +2323,9 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw) | |||
2866 | memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_config)); | 2323 | memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_config)); |
2867 | spin_unlock_irqrestore(&priv->lock, flags); | 2324 | spin_unlock_irqrestore(&priv->lock, flags); |
2868 | 2325 | ||
2869 | iwl_reset_qos(priv); | ||
2870 | |||
2871 | spin_lock_irqsave(&priv->lock, flags); | 2326 | spin_lock_irqsave(&priv->lock, flags); |
2872 | priv->assoc_id = 0; | 2327 | priv->assoc_id = 0; |
2873 | priv->assoc_capability = 0; | 2328 | priv->assoc_capability = 0; |
2874 | priv->assoc_station_added = 0; | ||
2875 | 2329 | ||
2876 | /* new association get rid of ibss beacon skb */ | 2330 | /* new association get rid of ibss beacon skb */ |
2877 | if (priv->ibss_beacon) | 2331 | if (priv->ibss_beacon) |
@@ -2881,8 +2335,6 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw) | |||
2881 | 2335 | ||
2882 | priv->beacon_int = priv->vif->bss_conf.beacon_int; | 2336 | priv->beacon_int = priv->vif->bss_conf.beacon_int; |
2883 | priv->timestamp = 0; | 2337 | priv->timestamp = 0; |
2884 | if ((priv->iw_mode == NL80211_IFTYPE_STATION)) | ||
2885 | priv->beacon_int = 0; | ||
2886 | 2338 | ||
2887 | spin_unlock_irqrestore(&priv->lock, flags); | 2339 | spin_unlock_irqrestore(&priv->lock, flags); |
2888 | 2340 | ||
@@ -2895,17 +2347,9 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw) | |||
2895 | /* we are restarting association process | 2347 | /* we are restarting association process |
2896 | * clear RXON_FILTER_ASSOC_MSK bit | 2348 | * clear RXON_FILTER_ASSOC_MSK bit |
2897 | */ | 2349 | */ |
2898 | if (priv->iw_mode != NL80211_IFTYPE_AP) { | 2350 | iwl_scan_cancel_timeout(priv, 100); |
2899 | iwl_scan_cancel_timeout(priv, 100); | 2351 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
2900 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 2352 | iwlcore_commit_rxon(priv); |
2901 | iwlcore_commit_rxon(priv); | ||
2902 | } | ||
2903 | |||
2904 | if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { | ||
2905 | IWL_DEBUG_MAC80211(priv, "leave - not in IBSS\n"); | ||
2906 | mutex_unlock(&priv->mutex); | ||
2907 | return; | ||
2908 | } | ||
2909 | 2353 | ||
2910 | iwl_set_rate(priv); | 2354 | iwl_set_rate(priv); |
2911 | 2355 | ||
@@ -2922,7 +2366,7 @@ int iwl_alloc_txq_mem(struct iwl_priv *priv) | |||
2922 | sizeof(struct iwl_tx_queue) * priv->cfg->num_of_queues, | 2366 | sizeof(struct iwl_tx_queue) * priv->cfg->num_of_queues, |
2923 | GFP_KERNEL); | 2367 | GFP_KERNEL); |
2924 | if (!priv->txq) { | 2368 | if (!priv->txq) { |
2925 | IWL_ERR(priv, "Not enough memory for txq \n"); | 2369 | IWL_ERR(priv, "Not enough memory for txq\n"); |
2926 | return -ENOMEM; | 2370 | return -ENOMEM; |
2927 | } | 2371 | } |
2928 | return 0; | 2372 | return 0; |
@@ -3403,6 +2847,99 @@ int iwl_force_reset(struct iwl_priv *priv, int mode) | |||
3403 | } | 2847 | } |
3404 | return 0; | 2848 | return 0; |
3405 | } | 2849 | } |
2850 | EXPORT_SYMBOL(iwl_force_reset); | ||
2851 | |||
2852 | /** | ||
2853 | * iwl_bg_monitor_recover - Timer callback to check for stuck queue and recover | ||
2854 | * | ||
2855 | * During normal condition (no queue is stuck), the timer is continually set to | ||
2856 | * execute every monitor_recover_period milliseconds after the last timer | ||
2857 | * expired. When the queue read_ptr is at the same place, the timer is | ||
2858 | * shorten to 100mSecs. This is | ||
2859 | * 1) to reduce the chance that the read_ptr may wrap around (not stuck) | ||
2860 | * 2) to detect the stuck queues quicker before the station and AP can | ||
2861 | * disassociate each other. | ||
2862 | * | ||
2863 | * This function monitors all the tx queues and recover from it if any | ||
2864 | * of the queues are stuck. | ||
2865 | * 1. It first check the cmd queue for stuck conditions. If it is stuck, | ||
2866 | * it will recover by resetting the firmware and return. | ||
2867 | * 2. Then, it checks for station association. If it associates it will check | ||
2868 | * other queues. If any queue is stuck, it will recover by resetting | ||
2869 | * the firmware. | ||
2870 | * Note: It the number of times the queue read_ptr to be at the same place to | ||
2871 | * be MAX_REPEAT+1 in order to consider to be stuck. | ||
2872 | */ | ||
2873 | /* | ||
2874 | * The maximum number of times the read pointer of the tx queue at the | ||
2875 | * same place without considering to be stuck. | ||
2876 | */ | ||
2877 | #define MAX_REPEAT (2) | ||
2878 | static int iwl_check_stuck_queue(struct iwl_priv *priv, int cnt) | ||
2879 | { | ||
2880 | struct iwl_tx_queue *txq; | ||
2881 | struct iwl_queue *q; | ||
2882 | |||
2883 | txq = &priv->txq[cnt]; | ||
2884 | q = &txq->q; | ||
2885 | /* queue is empty, skip */ | ||
2886 | if (q->read_ptr != q->write_ptr) { | ||
2887 | if (q->read_ptr == q->last_read_ptr) { | ||
2888 | /* a queue has not been read from last time */ | ||
2889 | if (q->repeat_same_read_ptr > MAX_REPEAT) { | ||
2890 | IWL_ERR(priv, | ||
2891 | "queue %d stuck %d time. Fw reload.\n", | ||
2892 | q->id, q->repeat_same_read_ptr); | ||
2893 | q->repeat_same_read_ptr = 0; | ||
2894 | iwl_force_reset(priv, IWL_FW_RESET); | ||
2895 | } else { | ||
2896 | q->repeat_same_read_ptr++; | ||
2897 | IWL_DEBUG_RADIO(priv, | ||
2898 | "queue %d, not read %d time\n", | ||
2899 | q->id, | ||
2900 | q->repeat_same_read_ptr); | ||
2901 | mod_timer(&priv->monitor_recover, jiffies + | ||
2902 | msecs_to_jiffies(IWL_ONE_HUNDRED_MSECS)); | ||
2903 | } | ||
2904 | return 1; | ||
2905 | } else { | ||
2906 | q->last_read_ptr = q->read_ptr; | ||
2907 | q->repeat_same_read_ptr = 0; | ||
2908 | } | ||
2909 | } | ||
2910 | return 0; | ||
2911 | } | ||
2912 | |||
2913 | void iwl_bg_monitor_recover(unsigned long data) | ||
2914 | { | ||
2915 | struct iwl_priv *priv = (struct iwl_priv *)data; | ||
2916 | int cnt; | ||
2917 | |||
2918 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
2919 | return; | ||
2920 | |||
2921 | /* monitor and check for stuck cmd queue */ | ||
2922 | if (iwl_check_stuck_queue(priv, IWL_CMD_QUEUE_NUM)) | ||
2923 | return; | ||
2924 | |||
2925 | /* monitor and check for other stuck queues */ | ||
2926 | if (iwl_is_associated(priv)) { | ||
2927 | for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) { | ||
2928 | /* skip as we already checked the command queue */ | ||
2929 | if (cnt == IWL_CMD_QUEUE_NUM) | ||
2930 | continue; | ||
2931 | if (iwl_check_stuck_queue(priv, cnt)) | ||
2932 | return; | ||
2933 | } | ||
2934 | } | ||
2935 | /* | ||
2936 | * Reschedule the timer to occur in | ||
2937 | * priv->cfg->monitor_recover_period | ||
2938 | */ | ||
2939 | mod_timer(&priv->monitor_recover, | ||
2940 | jiffies + msecs_to_jiffies(priv->cfg->monitor_recover_period)); | ||
2941 | } | ||
2942 | EXPORT_SYMBOL(iwl_bg_monitor_recover); | ||
3406 | 2943 | ||
3407 | #ifdef CONFIG_PM | 2944 | #ifdef CONFIG_PM |
3408 | 2945 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 732590f5fe30..10f95724536f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -191,6 +191,14 @@ struct iwl_lib_ops { | |||
191 | struct iwl_temp_ops temp_ops; | 191 | struct iwl_temp_ops temp_ops; |
192 | /* station management */ | 192 | /* station management */ |
193 | void (*add_bcast_station)(struct iwl_priv *priv); | 193 | void (*add_bcast_station)(struct iwl_priv *priv); |
194 | /* recover from tx queue stall */ | ||
195 | void (*recover_from_tx_stall)(unsigned long data); | ||
196 | /* check for plcp health */ | ||
197 | bool (*check_plcp_health)(struct iwl_priv *priv, | ||
198 | struct iwl_rx_packet *pkt); | ||
199 | /* check for ack health */ | ||
200 | bool (*check_ack_health)(struct iwl_priv *priv, | ||
201 | struct iwl_rx_packet *pkt); | ||
194 | }; | 202 | }; |
195 | 203 | ||
196 | struct iwl_led_ops { | 204 | struct iwl_led_ops { |
@@ -295,6 +303,10 @@ struct iwl_cfg { | |||
295 | const bool support_wimax_coexist; | 303 | const bool support_wimax_coexist; |
296 | u8 plcp_delta_threshold; | 304 | u8 plcp_delta_threshold; |
297 | s32 chain_noise_scale; | 305 | s32 chain_noise_scale; |
306 | /* timer period for monitor the driver queues */ | ||
307 | u32 monitor_recover_period; | ||
308 | bool temperature_kelvin; | ||
309 | bool off_channel_workaround; | ||
298 | }; | 310 | }; |
299 | 311 | ||
300 | /*************************** | 312 | /*************************** |
@@ -304,8 +316,7 @@ struct iwl_cfg { | |||
304 | struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg, | 316 | struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg, |
305 | struct ieee80211_ops *hw_ops); | 317 | struct ieee80211_ops *hw_ops); |
306 | void iwl_hw_detect(struct iwl_priv *priv); | 318 | void iwl_hw_detect(struct iwl_priv *priv); |
307 | void iwl_reset_qos(struct iwl_priv *priv); | 319 | void iwl_activate_qos(struct iwl_priv *priv); |
308 | void iwl_activate_qos(struct iwl_priv *priv, u8 force); | ||
309 | int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, | 320 | int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, |
310 | const struct ieee80211_tx_queue_params *params); | 321 | const struct ieee80211_tx_queue_params *params); |
311 | void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt); | 322 | void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt); |
@@ -326,7 +337,6 @@ void iwl_irq_handle_error(struct iwl_priv *priv); | |||
326 | void iwl_configure_filter(struct ieee80211_hw *hw, | 337 | void iwl_configure_filter(struct ieee80211_hw *hw, |
327 | unsigned int changed_flags, | 338 | unsigned int changed_flags, |
328 | unsigned int *total_flags, u64 multicast); | 339 | unsigned int *total_flags, u64 multicast); |
329 | int iwl_hw_nic_init(struct iwl_priv *priv); | ||
330 | int iwl_set_hw_params(struct iwl_priv *priv); | 340 | int iwl_set_hw_params(struct iwl_priv *priv); |
331 | bool iwl_is_monitor_mode(struct iwl_priv *priv); | 341 | bool iwl_is_monitor_mode(struct iwl_priv *priv); |
332 | void iwl_post_associate(struct iwl_priv *priv); | 342 | void iwl_post_associate(struct iwl_priv *priv); |
@@ -336,7 +346,6 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, | |||
336 | u32 changes); | 346 | u32 changes); |
337 | int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb); | 347 | int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb); |
338 | int iwl_commit_rxon(struct iwl_priv *priv); | 348 | int iwl_commit_rxon(struct iwl_priv *priv); |
339 | int iwl_set_mode(struct iwl_priv *priv, int mode); | ||
340 | int iwl_mac_add_interface(struct ieee80211_hw *hw, | 349 | int iwl_mac_add_interface(struct ieee80211_hw *hw, |
341 | struct ieee80211_vif *vif); | 350 | struct ieee80211_vif *vif); |
342 | void iwl_mac_remove_interface(struct ieee80211_hw *hw, | 351 | void iwl_mac_remove_interface(struct ieee80211_hw *hw, |
@@ -411,26 +420,22 @@ void iwl_rx_reply_error(struct iwl_priv *priv, | |||
411 | /***************************************************** | 420 | /***************************************************** |
412 | * RX | 421 | * RX |
413 | ******************************************************/ | 422 | ******************************************************/ |
414 | void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | ||
415 | void iwl_cmd_queue_free(struct iwl_priv *priv); | 423 | void iwl_cmd_queue_free(struct iwl_priv *priv); |
416 | int iwl_rx_queue_alloc(struct iwl_priv *priv); | 424 | int iwl_rx_queue_alloc(struct iwl_priv *priv); |
417 | void iwl_rx_handle(struct iwl_priv *priv); | 425 | void iwl_rx_handle(struct iwl_priv *priv); |
418 | void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, | 426 | void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, |
419 | struct iwl_rx_queue *q); | 427 | struct iwl_rx_queue *q); |
420 | void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | ||
421 | void iwl_rx_replenish(struct iwl_priv *priv); | ||
422 | void iwl_rx_replenish_now(struct iwl_priv *priv); | ||
423 | int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | ||
424 | void iwl_rx_queue_restock(struct iwl_priv *priv); | ||
425 | int iwl_rx_queue_space(const struct iwl_rx_queue *q); | 428 | int iwl_rx_queue_space(const struct iwl_rx_queue *q); |
426 | void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority); | ||
427 | void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); | 429 | void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); |
428 | int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index); | ||
429 | /* Handlers */ | 430 | /* Handlers */ |
430 | void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, | 431 | void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, |
431 | struct iwl_rx_mem_buffer *rxb); | 432 | struct iwl_rx_mem_buffer *rxb); |
432 | void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, | 433 | void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, |
433 | struct iwl_rx_mem_buffer *rxb); | 434 | struct iwl_rx_mem_buffer *rxb); |
435 | bool iwl_good_plcp_health(struct iwl_priv *priv, | ||
436 | struct iwl_rx_packet *pkt); | ||
437 | bool iwl_good_ack_health(struct iwl_priv *priv, | ||
438 | struct iwl_rx_packet *pkt); | ||
434 | void iwl_rx_statistics(struct iwl_priv *priv, | 439 | void iwl_rx_statistics(struct iwl_priv *priv, |
435 | struct iwl_rx_mem_buffer *rxb); | 440 | struct iwl_rx_mem_buffer *rxb); |
436 | void iwl_reply_statistics(struct iwl_priv *priv, | 441 | void iwl_reply_statistics(struct iwl_priv *priv, |
@@ -442,14 +447,10 @@ void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); | |||
442 | /***************************************************** | 447 | /***************************************************** |
443 | * TX | 448 | * TX |
444 | ******************************************************/ | 449 | ******************************************************/ |
445 | int iwl_txq_ctx_alloc(struct iwl_priv *priv); | ||
446 | void iwl_txq_ctx_reset(struct iwl_priv *priv); | ||
447 | void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); | 450 | void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); |
448 | int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, | 451 | int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, |
449 | struct iwl_tx_queue *txq, | 452 | struct iwl_tx_queue *txq, |
450 | dma_addr_t addr, u16 len, u8 reset, u8 pad); | 453 | dma_addr_t addr, u16 len, u8 reset, u8 pad); |
451 | int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb); | ||
452 | void iwl_hw_txq_ctx_free(struct iwl_priv *priv); | ||
453 | int iwl_hw_tx_queue_init(struct iwl_priv *priv, | 454 | int iwl_hw_tx_queue_init(struct iwl_priv *priv, |
454 | struct iwl_tx_queue *txq); | 455 | struct iwl_tx_queue *txq); |
455 | void iwl_free_tfds_in_queue(struct iwl_priv *priv, | 456 | void iwl_free_tfds_in_queue(struct iwl_priv *priv, |
@@ -460,9 +461,6 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, | |||
460 | void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq, | 461 | void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq, |
461 | int slots_num, u32 txq_id); | 462 | int slots_num, u32 txq_id); |
462 | void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); | 463 | void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); |
463 | int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn); | ||
464 | int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid); | ||
465 | int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id); | ||
466 | /***************************************************** | 464 | /***************************************************** |
467 | * TX power | 465 | * TX power |
468 | ****************************************************/ | 466 | ****************************************************/ |
@@ -472,10 +470,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force); | |||
472 | * Rate | 470 | * Rate |
473 | ******************************************************************************/ | 471 | ******************************************************************************/ |
474 | 472 | ||
475 | void iwl_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, | ||
476 | struct ieee80211_tx_info *info); | ||
477 | int iwl_hwrate_to_plcp_idx(u32 rate_n_flags); | 473 | int iwl_hwrate_to_plcp_idx(u32 rate_n_flags); |
478 | int iwl_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band); | ||
479 | 474 | ||
480 | u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv); | 475 | u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv); |
481 | 476 | ||
@@ -563,11 +558,6 @@ int iwl_send_card_state(struct iwl_priv *priv, u32 flags, | |||
563 | * PCI * | 558 | * PCI * |
564 | *****************************************************/ | 559 | *****************************************************/ |
565 | irqreturn_t iwl_isr_legacy(int irq, void *data); | 560 | irqreturn_t iwl_isr_legacy(int irq, void *data); |
566 | int iwl_reset_ict(struct iwl_priv *priv); | ||
567 | void iwl_disable_ict(struct iwl_priv *priv); | ||
568 | int iwl_alloc_isr_ict(struct iwl_priv *priv); | ||
569 | void iwl_free_isr_ict(struct iwl_priv *priv); | ||
570 | irqreturn_t iwl_isr_ict(int irq, void *data); | ||
571 | 561 | ||
572 | static inline u16 iwl_pcie_link_ctl(struct iwl_priv *priv) | 562 | static inline u16 iwl_pcie_link_ctl(struct iwl_priv *priv) |
573 | { | 563 | { |
@@ -577,6 +567,9 @@ static inline u16 iwl_pcie_link_ctl(struct iwl_priv *priv) | |||
577 | pci_read_config_word(priv->pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl); | 567 | pci_read_config_word(priv->pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl); |
578 | return pci_lnk_ctl; | 568 | return pci_lnk_ctl; |
579 | } | 569 | } |
570 | |||
571 | void iwl_bg_monitor_recover(unsigned long data); | ||
572 | |||
580 | #ifdef CONFIG_PM | 573 | #ifdef CONFIG_PM |
581 | int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state); | 574 | int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state); |
582 | int iwl_pci_resume(struct pci_dev *pdev); | 575 | int iwl_pci_resume(struct pci_dev *pdev); |
@@ -625,7 +618,6 @@ void iwlcore_free_geos(struct iwl_priv *priv); | |||
625 | #define STATUS_SCAN_HW 15 | 618 | #define STATUS_SCAN_HW 15 |
626 | #define STATUS_POWER_PMI 16 | 619 | #define STATUS_POWER_PMI 16 |
627 | #define STATUS_FW_ERROR 17 | 620 | #define STATUS_FW_ERROR 17 |
628 | #define STATUS_MODE_PENDING 18 | ||
629 | 621 | ||
630 | 622 | ||
631 | static inline int iwl_is_ready(struct iwl_priv *priv) | 623 | static inline int iwl_is_ready(struct iwl_priv *priv) |
@@ -677,15 +669,8 @@ extern int iwl_send_statistics_request(struct iwl_priv *priv, | |||
677 | u8 flags, bool clear); | 669 | u8 flags, bool clear); |
678 | extern int iwl_verify_ucode(struct iwl_priv *priv); | 670 | extern int iwl_verify_ucode(struct iwl_priv *priv); |
679 | extern int iwl_send_lq_cmd(struct iwl_priv *priv, | 671 | extern int iwl_send_lq_cmd(struct iwl_priv *priv, |
680 | struct iwl_link_quality_cmd *lq, u8 flags); | 672 | struct iwl_link_quality_cmd *lq, u8 flags, bool init); |
681 | extern void iwl_rx_reply_rx(struct iwl_priv *priv, | ||
682 | struct iwl_rx_mem_buffer *rxb); | ||
683 | extern void iwl_rx_reply_rx_phy(struct iwl_priv *priv, | ||
684 | struct iwl_rx_mem_buffer *rxb); | ||
685 | void iwl_rx_reply_compressed_ba(struct iwl_priv *priv, | ||
686 | struct iwl_rx_mem_buffer *rxb); | ||
687 | void iwl_apm_stop(struct iwl_priv *priv); | 673 | void iwl_apm_stop(struct iwl_priv *priv); |
688 | int iwl_apm_stop_master(struct iwl_priv *priv); | ||
689 | int iwl_apm_init(struct iwl_priv *priv); | 674 | int iwl_apm_init(struct iwl_priv *priv); |
690 | 675 | ||
691 | void iwl_setup_rxon_timing(struct iwl_priv *priv); | 676 | void iwl_setup_rxon_timing(struct iwl_priv *priv); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 7bf44f146799..5f5820249a29 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c | |||
@@ -560,8 +560,6 @@ static ssize_t iwl_dbgfs_status_read(struct file *file, | |||
560 | test_bit(STATUS_POWER_PMI, &priv->status)); | 560 | test_bit(STATUS_POWER_PMI, &priv->status)); |
561 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n", | 561 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n", |
562 | test_bit(STATUS_FW_ERROR, &priv->status)); | 562 | test_bit(STATUS_FW_ERROR, &priv->status)); |
563 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_MODE_PENDING:\t %d\n", | ||
564 | test_bit(STATUS_MODE_PENDING, &priv->status)); | ||
565 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 563 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
566 | } | 564 | } |
567 | 565 | ||
@@ -660,7 +658,6 @@ static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf, | |||
660 | int pos = 0, i; | 658 | int pos = 0, i; |
661 | char buf[256]; | 659 | char buf[256]; |
662 | const size_t bufsz = sizeof(buf); | 660 | const size_t bufsz = sizeof(buf); |
663 | ssize_t ret; | ||
664 | 661 | ||
665 | for (i = 0; i < AC_NUM; i++) { | 662 | for (i = 0; i < AC_NUM; i++) { |
666 | pos += scnprintf(buf + pos, bufsz - pos, | 663 | pos += scnprintf(buf + pos, bufsz - pos, |
@@ -672,8 +669,7 @@ static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf, | |||
672 | priv->qos_data.def_qos_parm.ac[i].aifsn, | 669 | priv->qos_data.def_qos_parm.ac[i].aifsn, |
673 | priv->qos_data.def_qos_parm.ac[i].edca_txop); | 670 | priv->qos_data.def_qos_parm.ac[i].edca_txop); |
674 | } | 671 | } |
675 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 672 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
676 | return ret; | ||
677 | } | 673 | } |
678 | 674 | ||
679 | static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf, | 675 | static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf, |
@@ -683,7 +679,6 @@ static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf, | |||
683 | int pos = 0; | 679 | int pos = 0; |
684 | char buf[256]; | 680 | char buf[256]; |
685 | const size_t bufsz = sizeof(buf); | 681 | const size_t bufsz = sizeof(buf); |
686 | ssize_t ret; | ||
687 | 682 | ||
688 | pos += scnprintf(buf + pos, bufsz - pos, | 683 | pos += scnprintf(buf + pos, bufsz - pos, |
689 | "allow blinking: %s\n", | 684 | "allow blinking: %s\n", |
@@ -697,8 +692,7 @@ static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf, | |||
697 | priv->last_blink_time); | 692 | priv->last_blink_time); |
698 | } | 693 | } |
699 | 694 | ||
700 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 695 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
701 | return ret; | ||
702 | } | 696 | } |
703 | 697 | ||
704 | static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file, | 698 | static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file, |
@@ -711,7 +705,6 @@ static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file, | |||
711 | char buf[100]; | 705 | char buf[100]; |
712 | int pos = 0; | 706 | int pos = 0; |
713 | const size_t bufsz = sizeof(buf); | 707 | const size_t bufsz = sizeof(buf); |
714 | ssize_t ret; | ||
715 | 708 | ||
716 | pos += scnprintf(buf + pos, bufsz - pos, | 709 | pos += scnprintf(buf + pos, bufsz - pos, |
717 | "Thermal Throttling Mode: %s\n", | 710 | "Thermal Throttling Mode: %s\n", |
@@ -731,8 +724,7 @@ static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file, | |||
731 | "HT mode: %d\n", | 724 | "HT mode: %d\n", |
732 | restriction->is_ht); | 725 | restriction->is_ht); |
733 | } | 726 | } |
734 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 727 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
735 | return ret; | ||
736 | } | 728 | } |
737 | 729 | ||
738 | static ssize_t iwl_dbgfs_disable_ht40_write(struct file *file, | 730 | static ssize_t iwl_dbgfs_disable_ht40_write(struct file *file, |
@@ -769,13 +761,11 @@ static ssize_t iwl_dbgfs_disable_ht40_read(struct file *file, | |||
769 | char buf[100]; | 761 | char buf[100]; |
770 | int pos = 0; | 762 | int pos = 0; |
771 | const size_t bufsz = sizeof(buf); | 763 | const size_t bufsz = sizeof(buf); |
772 | ssize_t ret; | ||
773 | 764 | ||
774 | pos += scnprintf(buf + pos, bufsz - pos, | 765 | pos += scnprintf(buf + pos, bufsz - pos, |
775 | "11n 40MHz Mode: %s\n", | 766 | "11n 40MHz Mode: %s\n", |
776 | priv->disable_ht40 ? "Disabled" : "Enabled"); | 767 | priv->disable_ht40 ? "Disabled" : "Enabled"); |
777 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 768 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
778 | return ret; | ||
779 | } | 769 | } |
780 | 770 | ||
781 | static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file, | 771 | static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file, |
@@ -2051,7 +2041,6 @@ static ssize_t iwl_dbgfs_ucode_tracing_read(struct file *file, | |||
2051 | int pos = 0; | 2041 | int pos = 0; |
2052 | char buf[128]; | 2042 | char buf[128]; |
2053 | const size_t bufsz = sizeof(buf); | 2043 | const size_t bufsz = sizeof(buf); |
2054 | ssize_t ret; | ||
2055 | 2044 | ||
2056 | pos += scnprintf(buf + pos, bufsz - pos, "ucode trace timer is %s\n", | 2045 | pos += scnprintf(buf + pos, bufsz - pos, "ucode trace timer is %s\n", |
2057 | priv->event_log.ucode_trace ? "On" : "Off"); | 2046 | priv->event_log.ucode_trace ? "On" : "Off"); |
@@ -2062,8 +2051,7 @@ static ssize_t iwl_dbgfs_ucode_tracing_read(struct file *file, | |||
2062 | pos += scnprintf(buf + pos, bufsz - pos, "wraps_more_count:\t\t %u\n", | 2051 | pos += scnprintf(buf + pos, bufsz - pos, "wraps_more_count:\t\t %u\n", |
2063 | priv->event_log.wraps_more_count); | 2052 | priv->event_log.wraps_more_count); |
2064 | 2053 | ||
2065 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 2054 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
2066 | return ret; | ||
2067 | } | 2055 | } |
2068 | 2056 | ||
2069 | static ssize_t iwl_dbgfs_ucode_tracing_write(struct file *file, | 2057 | static ssize_t iwl_dbgfs_ucode_tracing_write(struct file *file, |
@@ -2095,6 +2083,31 @@ static ssize_t iwl_dbgfs_ucode_tracing_write(struct file *file, | |||
2095 | return count; | 2083 | return count; |
2096 | } | 2084 | } |
2097 | 2085 | ||
2086 | static ssize_t iwl_dbgfs_rxon_flags_read(struct file *file, | ||
2087 | char __user *user_buf, | ||
2088 | size_t count, loff_t *ppos) { | ||
2089 | |||
2090 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | ||
2091 | int len = 0; | ||
2092 | char buf[20]; | ||
2093 | |||
2094 | len = sprintf(buf, "0x%04X\n", le32_to_cpu(priv->active_rxon.flags)); | ||
2095 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
2096 | } | ||
2097 | |||
2098 | static ssize_t iwl_dbgfs_rxon_filter_flags_read(struct file *file, | ||
2099 | char __user *user_buf, | ||
2100 | size_t count, loff_t *ppos) { | ||
2101 | |||
2102 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | ||
2103 | int len = 0; | ||
2104 | char buf[20]; | ||
2105 | |||
2106 | len = sprintf(buf, "0x%04X\n", | ||
2107 | le32_to_cpu(priv->active_rxon.filter_flags)); | ||
2108 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
2109 | } | ||
2110 | |||
2098 | static ssize_t iwl_dbgfs_fh_reg_read(struct file *file, | 2111 | static ssize_t iwl_dbgfs_fh_reg_read(struct file *file, |
2099 | char __user *user_buf, | 2112 | char __user *user_buf, |
2100 | size_t count, loff_t *ppos) | 2113 | size_t count, loff_t *ppos) |
@@ -2124,13 +2137,11 @@ static ssize_t iwl_dbgfs_missed_beacon_read(struct file *file, | |||
2124 | int pos = 0; | 2137 | int pos = 0; |
2125 | char buf[12]; | 2138 | char buf[12]; |
2126 | const size_t bufsz = sizeof(buf); | 2139 | const size_t bufsz = sizeof(buf); |
2127 | ssize_t ret; | ||
2128 | 2140 | ||
2129 | pos += scnprintf(buf + pos, bufsz - pos, "%d\n", | 2141 | pos += scnprintf(buf + pos, bufsz - pos, "%d\n", |
2130 | priv->missed_beacon_threshold); | 2142 | priv->missed_beacon_threshold); |
2131 | 2143 | ||
2132 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 2144 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
2133 | return ret; | ||
2134 | } | 2145 | } |
2135 | 2146 | ||
2136 | static ssize_t iwl_dbgfs_missed_beacon_write(struct file *file, | 2147 | static ssize_t iwl_dbgfs_missed_beacon_write(struct file *file, |
@@ -2159,27 +2170,6 @@ static ssize_t iwl_dbgfs_missed_beacon_write(struct file *file, | |||
2159 | return count; | 2170 | return count; |
2160 | } | 2171 | } |
2161 | 2172 | ||
2162 | static ssize_t iwl_dbgfs_internal_scan_write(struct file *file, | ||
2163 | const char __user *user_buf, | ||
2164 | size_t count, loff_t *ppos) | ||
2165 | { | ||
2166 | struct iwl_priv *priv = file->private_data; | ||
2167 | char buf[8]; | ||
2168 | int buf_size; | ||
2169 | int scan; | ||
2170 | |||
2171 | memset(buf, 0, sizeof(buf)); | ||
2172 | buf_size = min(count, sizeof(buf) - 1); | ||
2173 | if (copy_from_user(buf, user_buf, buf_size)) | ||
2174 | return -EFAULT; | ||
2175 | if (sscanf(buf, "%d", &scan) != 1) | ||
2176 | return -EINVAL; | ||
2177 | |||
2178 | iwl_internal_short_hw_scan(priv); | ||
2179 | |||
2180 | return count; | ||
2181 | } | ||
2182 | |||
2183 | static ssize_t iwl_dbgfs_plcp_delta_read(struct file *file, | 2173 | static ssize_t iwl_dbgfs_plcp_delta_read(struct file *file, |
2184 | char __user *user_buf, | 2174 | char __user *user_buf, |
2185 | size_t count, loff_t *ppos) { | 2175 | size_t count, loff_t *ppos) { |
@@ -2188,13 +2178,11 @@ static ssize_t iwl_dbgfs_plcp_delta_read(struct file *file, | |||
2188 | int pos = 0; | 2178 | int pos = 0; |
2189 | char buf[12]; | 2179 | char buf[12]; |
2190 | const size_t bufsz = sizeof(buf); | 2180 | const size_t bufsz = sizeof(buf); |
2191 | ssize_t ret; | ||
2192 | 2181 | ||
2193 | pos += scnprintf(buf + pos, bufsz - pos, "%u\n", | 2182 | pos += scnprintf(buf + pos, bufsz - pos, "%u\n", |
2194 | priv->cfg->plcp_delta_threshold); | 2183 | priv->cfg->plcp_delta_threshold); |
2195 | 2184 | ||
2196 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 2185 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
2197 | return ret; | ||
2198 | } | 2186 | } |
2199 | 2187 | ||
2200 | static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file, | 2188 | static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file, |
@@ -2295,9 +2283,10 @@ DEBUGFS_WRITE_FILE_OPS(csr); | |||
2295 | DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing); | 2283 | DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing); |
2296 | DEBUGFS_READ_FILE_OPS(fh_reg); | 2284 | DEBUGFS_READ_FILE_OPS(fh_reg); |
2297 | DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon); | 2285 | DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon); |
2298 | DEBUGFS_WRITE_FILE_OPS(internal_scan); | ||
2299 | DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta); | 2286 | DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta); |
2300 | DEBUGFS_READ_WRITE_FILE_OPS(force_reset); | 2287 | DEBUGFS_READ_WRITE_FILE_OPS(force_reset); |
2288 | DEBUGFS_READ_FILE_OPS(rxon_flags); | ||
2289 | DEBUGFS_READ_FILE_OPS(rxon_filter_flags); | ||
2301 | 2290 | ||
2302 | /* | 2291 | /* |
2303 | * Create the debugfs files and directories | 2292 | * Create the debugfs files and directories |
@@ -2349,7 +2338,6 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | |||
2349 | DEBUGFS_ADD_FILE(csr, dir_debug, S_IWUSR); | 2338 | DEBUGFS_ADD_FILE(csr, dir_debug, S_IWUSR); |
2350 | DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR); | 2339 | DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR); |
2351 | DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR); | 2340 | DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR); |
2352 | DEBUGFS_ADD_FILE(internal_scan, dir_debug, S_IWUSR); | ||
2353 | DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR); | 2341 | DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR); |
2354 | DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR); | 2342 | DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR); |
2355 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { | 2343 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { |
@@ -2360,6 +2348,8 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | |||
2360 | DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); | 2348 | DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); |
2361 | DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR); | 2349 | DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR); |
2362 | } | 2350 | } |
2351 | DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR); | ||
2352 | DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR); | ||
2363 | DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, &priv->disable_sens_cal); | 2353 | DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, &priv->disable_sens_cal); |
2364 | DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, | 2354 | DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, |
2365 | &priv->disable_chain_noise_cal); | 2355 | &priv->disable_chain_noise_cal); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 6054c5fba0c1..4319bda487d9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -43,6 +43,7 @@ | |||
43 | #include "iwl-debug.h" | 43 | #include "iwl-debug.h" |
44 | #include "iwl-4965-hw.h" | 44 | #include "iwl-4965-hw.h" |
45 | #include "iwl-3945-hw.h" | 45 | #include "iwl-3945-hw.h" |
46 | #include "iwl-agn-hw.h" | ||
46 | #include "iwl-led.h" | 47 | #include "iwl-led.h" |
47 | #include "iwl-power.h" | 48 | #include "iwl-power.h" |
48 | #include "iwl-agn-rs.h" | 49 | #include "iwl-agn-rs.h" |
@@ -57,6 +58,7 @@ extern struct iwl_cfg iwl5100_abg_cfg; | |||
57 | extern struct iwl_cfg iwl5150_agn_cfg; | 58 | extern struct iwl_cfg iwl5150_agn_cfg; |
58 | extern struct iwl_cfg iwl5150_abg_cfg; | 59 | extern struct iwl_cfg iwl5150_abg_cfg; |
59 | extern struct iwl_cfg iwl6000i_2agn_cfg; | 60 | extern struct iwl_cfg iwl6000i_2agn_cfg; |
61 | extern struct iwl_cfg iwl6000i_g2_2agn_cfg; | ||
60 | extern struct iwl_cfg iwl6000i_2abg_cfg; | 62 | extern struct iwl_cfg iwl6000i_2abg_cfg; |
61 | extern struct iwl_cfg iwl6000i_2bg_cfg; | 63 | extern struct iwl_cfg iwl6000i_2bg_cfg; |
62 | extern struct iwl_cfg iwl6000_3agn_cfg; | 64 | extern struct iwl_cfg iwl6000_3agn_cfg; |
@@ -67,45 +69,6 @@ extern struct iwl_cfg iwl1000_bg_cfg; | |||
67 | 69 | ||
68 | struct iwl_tx_queue; | 70 | struct iwl_tx_queue; |
69 | 71 | ||
70 | /* shared structures from iwl-5000.c */ | ||
71 | extern struct iwl_mod_params iwl50_mod_params; | ||
72 | extern struct iwl_ucode_ops iwl5000_ucode; | ||
73 | extern struct iwl_lib_ops iwl5000_lib; | ||
74 | extern struct iwl_hcmd_ops iwl5000_hcmd; | ||
75 | extern struct iwl_hcmd_utils_ops iwl5000_hcmd_utils; | ||
76 | |||
77 | /* shared functions from iwl-5000.c */ | ||
78 | extern u16 iwl5000_get_hcmd_size(u8 cmd_id, u16 len); | ||
79 | extern u16 iwl5000_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, | ||
80 | u8 *data); | ||
81 | extern void iwl5000_rts_tx_cmd_flag(struct ieee80211_tx_info *info, | ||
82 | __le32 *tx_flags); | ||
83 | extern int iwl5000_calc_rssi(struct iwl_priv *priv, | ||
84 | struct iwl_rx_phy_res *rx_resp); | ||
85 | extern void iwl5000_nic_config(struct iwl_priv *priv); | ||
86 | extern u16 iwl5000_eeprom_calib_version(struct iwl_priv *priv); | ||
87 | extern const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv, | ||
88 | size_t offset); | ||
89 | extern void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv, | ||
90 | struct iwl_tx_queue *txq, | ||
91 | u16 byte_cnt); | ||
92 | extern void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, | ||
93 | struct iwl_tx_queue *txq); | ||
94 | extern int iwl5000_load_ucode(struct iwl_priv *priv); | ||
95 | extern void iwl5000_init_alive_start(struct iwl_priv *priv); | ||
96 | extern int iwl5000_alive_notify(struct iwl_priv *priv); | ||
97 | extern int iwl5000_hw_set_hw_params(struct iwl_priv *priv); | ||
98 | extern int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id, | ||
99 | int tx_fifo, int sta_id, int tid, u16 ssn_idx); | ||
100 | extern int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, | ||
101 | u16 ssn_idx, u8 tx_fifo); | ||
102 | extern void iwl5000_txq_set_sched(struct iwl_priv *priv, u32 mask); | ||
103 | extern void iwl5000_setup_deferred_work(struct iwl_priv *priv); | ||
104 | extern void iwl5000_rx_handler_setup(struct iwl_priv *priv); | ||
105 | extern int iwl5000_hw_valid_rtc_data_addr(u32 addr); | ||
106 | extern int iwl5000_send_tx_power(struct iwl_priv *priv); | ||
107 | extern void iwl5000_temperature(struct iwl_priv *priv); | ||
108 | |||
109 | /* CT-KILL constants */ | 72 | /* CT-KILL constants */ |
110 | #define CT_KILL_THRESHOLD_LEGACY 110 /* in Celsius */ | 73 | #define CT_KILL_THRESHOLD_LEGACY 110 /* in Celsius */ |
111 | #define CT_KILL_THRESHOLD 114 /* in Celsius */ | 74 | #define CT_KILL_THRESHOLD 114 /* in Celsius */ |
@@ -183,6 +146,10 @@ struct iwl_queue { | |||
183 | int n_bd; /* number of BDs in this queue */ | 146 | int n_bd; /* number of BDs in this queue */ |
184 | int write_ptr; /* 1-st empty entry (index) host_w*/ | 147 | int write_ptr; /* 1-st empty entry (index) host_w*/ |
185 | int read_ptr; /* last used entry (index) host_r*/ | 148 | int read_ptr; /* last used entry (index) host_r*/ |
149 | /* use for monitoring and recovering the stuck queue */ | ||
150 | int last_read_ptr; /* storing the last read_ptr */ | ||
151 | /* number of time read_ptr and last_read_ptr are the same */ | ||
152 | u8 repeat_same_read_ptr; | ||
186 | dma_addr_t dma_addr; /* physical addr for BD's */ | 153 | dma_addr_t dma_addr; /* physical addr for BD's */ |
187 | int n_window; /* safe queue window */ | 154 | int n_window; /* safe queue window */ |
188 | u32 id; | 155 | u32 id; |
@@ -304,13 +271,11 @@ struct iwl_channel_info { | |||
304 | struct iwl3945_scan_power_info scan_pwr_info[IWL_NUM_SCAN_RATES]; | 271 | struct iwl3945_scan_power_info scan_pwr_info[IWL_NUM_SCAN_RATES]; |
305 | }; | 272 | }; |
306 | 273 | ||
307 | #define IWL_TX_FIFO_AC0 0 | 274 | #define IWL_TX_FIFO_BK 0 |
308 | #define IWL_TX_FIFO_AC1 1 | 275 | #define IWL_TX_FIFO_BE 1 |
309 | #define IWL_TX_FIFO_AC2 2 | 276 | #define IWL_TX_FIFO_VI 2 |
310 | #define IWL_TX_FIFO_AC3 3 | 277 | #define IWL_TX_FIFO_VO 3 |
311 | #define IWL_TX_FIFO_HCCA_1 5 | 278 | #define IWL_TX_FIFO_UNUSED -1 |
312 | #define IWL_TX_FIFO_HCCA_2 6 | ||
313 | #define IWL_TX_FIFO_NONE 7 | ||
314 | 279 | ||
315 | /* Minimum number of queues. MAX_NUM is defined in hw specific files. | 280 | /* Minimum number of queues. MAX_NUM is defined in hw specific files. |
316 | * Set the minimum to accommodate the 4 standard TX queues, 1 command | 281 | * Set the minimum to accommodate the 4 standard TX queues, 1 command |
@@ -361,13 +326,6 @@ enum { | |||
361 | 326 | ||
362 | #define DEF_CMD_PAYLOAD_SIZE 320 | 327 | #define DEF_CMD_PAYLOAD_SIZE 320 |
363 | 328 | ||
364 | /* | ||
365 | * IWL_LINK_HDR_MAX should include ieee80211_hdr, radiotap header, | ||
366 | * SNAP header and alignment. It should also be big enough for 802.11 | ||
367 | * control frames. | ||
368 | */ | ||
369 | #define IWL_LINK_HDR_MAX 64 | ||
370 | |||
371 | /** | 329 | /** |
372 | * struct iwl_device_cmd | 330 | * struct iwl_device_cmd |
373 | * | 331 | * |
@@ -519,38 +477,24 @@ struct iwl_ht_config { | |||
519 | u8 non_GF_STA_present; | 477 | u8 non_GF_STA_present; |
520 | }; | 478 | }; |
521 | 479 | ||
522 | union iwl_qos_capabity { | ||
523 | struct { | ||
524 | u8 edca_count:4; /* bit 0-3 */ | ||
525 | u8 q_ack:1; /* bit 4 */ | ||
526 | u8 queue_request:1; /* bit 5 */ | ||
527 | u8 txop_request:1; /* bit 6 */ | ||
528 | u8 reserved:1; /* bit 7 */ | ||
529 | } q_AP; | ||
530 | struct { | ||
531 | u8 acvo_APSD:1; /* bit 0 */ | ||
532 | u8 acvi_APSD:1; /* bit 1 */ | ||
533 | u8 ac_bk_APSD:1; /* bit 2 */ | ||
534 | u8 ac_be_APSD:1; /* bit 3 */ | ||
535 | u8 q_ack:1; /* bit 4 */ | ||
536 | u8 max_len:2; /* bit 5-6 */ | ||
537 | u8 more_data_ack:1; /* bit 7 */ | ||
538 | } q_STA; | ||
539 | u8 val; | ||
540 | }; | ||
541 | |||
542 | /* QoS structures */ | 480 | /* QoS structures */ |
543 | struct iwl_qos_info { | 481 | struct iwl_qos_info { |
544 | int qos_active; | 482 | int qos_active; |
545 | union iwl_qos_capabity qos_cap; | ||
546 | struct iwl_qosparam_cmd def_qos_parm; | 483 | struct iwl_qosparam_cmd def_qos_parm; |
547 | }; | 484 | }; |
548 | 485 | ||
486 | /* | ||
487 | * Structure should be accessed with sta_lock held. When station addition | ||
488 | * is in progress (IWL_STA_UCODE_INPROGRESS) it is possible to access only | ||
489 | * the commands (iwl_addsta_cmd and iwl_link_quality_cmd) without sta_lock | ||
490 | * held. | ||
491 | */ | ||
549 | struct iwl_station_entry { | 492 | struct iwl_station_entry { |
550 | struct iwl_addsta_cmd sta; | 493 | struct iwl_addsta_cmd sta; |
551 | struct iwl_tid_data tid[MAX_TID_COUNT]; | 494 | struct iwl_tid_data tid[MAX_TID_COUNT]; |
552 | u8 used; | 495 | u8 used; |
553 | struct iwl_hw_key keyinfo; | 496 | struct iwl_hw_key keyinfo; |
497 | struct iwl_link_quality_cmd *lq; | ||
554 | }; | 498 | }; |
555 | 499 | ||
556 | /* | 500 | /* |
@@ -1039,6 +983,11 @@ struct iwl_event_log { | |||
1039 | #define IWL_DELAY_NEXT_FORCE_RF_RESET (HZ*3) | 983 | #define IWL_DELAY_NEXT_FORCE_RF_RESET (HZ*3) |
1040 | #define IWL_DELAY_NEXT_FORCE_FW_RELOAD (HZ*5) | 984 | #define IWL_DELAY_NEXT_FORCE_FW_RELOAD (HZ*5) |
1041 | 985 | ||
986 | /* timer constants use to monitor and recover stuck tx queues in mSecs */ | ||
987 | #define IWL_MONITORING_PERIOD (1000) | ||
988 | #define IWL_ONE_HUNDRED_MSECS (100) | ||
989 | #define IWL_SIXTY_SECS (60000) | ||
990 | |||
1042 | enum iwl_reset { | 991 | enum iwl_reset { |
1043 | IWL_RF_RESET = 0, | 992 | IWL_RF_RESET = 0, |
1044 | IWL_FW_RESET, | 993 | IWL_FW_RESET, |
@@ -1092,10 +1041,6 @@ struct iwl_priv { | |||
1092 | struct iwl_channel_info *channel_info; /* channel info array */ | 1041 | struct iwl_channel_info *channel_info; /* channel info array */ |
1093 | u8 channel_count; /* # of channels */ | 1042 | u8 channel_count; /* # of channels */ |
1094 | 1043 | ||
1095 | /* each calibration channel group in the EEPROM has a derived | ||
1096 | * clip setting for each rate. 3945 only.*/ | ||
1097 | const struct iwl3945_clip_group clip39_groups[5]; | ||
1098 | |||
1099 | /* thermal calibration */ | 1044 | /* thermal calibration */ |
1100 | s32 temperature; /* degrees Kelvin */ | 1045 | s32 temperature; /* degrees Kelvin */ |
1101 | s32 last_temperature; | 1046 | s32 last_temperature; |
@@ -1168,9 +1113,7 @@ struct iwl_priv { | |||
1168 | u64 led_tpt; | 1113 | u64 led_tpt; |
1169 | 1114 | ||
1170 | u16 active_rate; | 1115 | u16 active_rate; |
1171 | u16 active_rate_basic; | ||
1172 | 1116 | ||
1173 | u8 assoc_station_added; | ||
1174 | u8 start_calib; | 1117 | u8 start_calib; |
1175 | struct iwl_sensitivity_data sensitivity_data; | 1118 | struct iwl_sensitivity_data sensitivity_data; |
1176 | struct iwl_chain_noise_data chain_noise_data; | 1119 | struct iwl_chain_noise_data chain_noise_data; |
@@ -1197,9 +1140,6 @@ struct iwl_priv { | |||
1197 | 1140 | ||
1198 | unsigned long status; | 1141 | unsigned long status; |
1199 | 1142 | ||
1200 | int last_rx_rssi; /* From Rx packet statistics */ | ||
1201 | int last_rx_noise; /* From beacon statistics */ | ||
1202 | |||
1203 | /* counts mgmt, ctl, and data packets */ | 1143 | /* counts mgmt, ctl, and data packets */ |
1204 | struct traffic_stats tx_stats; | 1144 | struct traffic_stats tx_stats; |
1205 | struct traffic_stats rx_stats; | 1145 | struct traffic_stats rx_stats; |
@@ -1218,8 +1158,6 @@ struct iwl_priv { | |||
1218 | #endif | 1158 | #endif |
1219 | 1159 | ||
1220 | /* context information */ | 1160 | /* context information */ |
1221 | u16 rates_mask; | ||
1222 | |||
1223 | u8 bssid[ETH_ALEN]; | 1161 | u8 bssid[ETH_ALEN]; |
1224 | u16 rts_threshold; | 1162 | u16 rts_threshold; |
1225 | u8 mac_addr[ETH_ALEN]; | 1163 | u8 mac_addr[ETH_ALEN]; |
@@ -1228,7 +1166,7 @@ struct iwl_priv { | |||
1228 | spinlock_t sta_lock; | 1166 | spinlock_t sta_lock; |
1229 | int num_stations; | 1167 | int num_stations; |
1230 | struct iwl_station_entry stations[IWL_STATION_COUNT]; | 1168 | struct iwl_station_entry stations[IWL_STATION_COUNT]; |
1231 | struct iwl_wep_key wep_keys[WEP_KEYS_MAX]; | 1169 | struct iwl_wep_key wep_keys[WEP_KEYS_MAX]; /* protected by mutex */ |
1232 | u8 default_wep_key; | 1170 | u8 default_wep_key; |
1233 | u8 key_mapping_key; | 1171 | u8 key_mapping_key; |
1234 | unsigned long ucode_key_table; | 1172 | unsigned long ucode_key_table; |
@@ -1244,10 +1182,6 @@ struct iwl_priv { | |||
1244 | 1182 | ||
1245 | u8 mac80211_registered; | 1183 | u8 mac80211_registered; |
1246 | 1184 | ||
1247 | /* Rx'd packet timing information */ | ||
1248 | u32 last_beacon_time; | ||
1249 | u64 last_tsf; | ||
1250 | |||
1251 | /* eeprom -- this is in the card's little endian byte order */ | 1185 | /* eeprom -- this is in the card's little endian byte order */ |
1252 | u8 *eeprom; | 1186 | u8 *eeprom; |
1253 | int nvm_device_type; | 1187 | int nvm_device_type; |
@@ -1262,20 +1196,53 @@ struct iwl_priv { | |||
1262 | u16 beacon_int; | 1196 | u16 beacon_int; |
1263 | struct ieee80211_vif *vif; | 1197 | struct ieee80211_vif *vif; |
1264 | 1198 | ||
1265 | /*Added for 3945 */ | 1199 | union { |
1266 | void *shared_virt; | 1200 | #if defined(CONFIG_IWL3945) || defined(CONFIG_IWL3945_MODULE) |
1267 | dma_addr_t shared_phys; | 1201 | struct { |
1268 | /*End*/ | 1202 | void *shared_virt; |
1269 | struct iwl_hw_params hw_params; | 1203 | dma_addr_t shared_phys; |
1204 | |||
1205 | struct delayed_work thermal_periodic; | ||
1206 | struct delayed_work rfkill_poll; | ||
1207 | |||
1208 | struct iwl3945_notif_statistics statistics; | ||
1209 | |||
1210 | u32 sta_supp_rates; | ||
1211 | int last_rx_rssi; /* From Rx packet statistics */ | ||
1212 | |||
1213 | /* Rx'd packet timing information */ | ||
1214 | u32 last_beacon_time; | ||
1215 | u64 last_tsf; | ||
1216 | |||
1217 | /* | ||
1218 | * each calibration channel group in the | ||
1219 | * EEPROM has a derived clip setting for | ||
1220 | * each rate. | ||
1221 | */ | ||
1222 | const struct iwl3945_clip_group clip_groups[5]; | ||
1223 | |||
1224 | } _3945; | ||
1225 | #endif | ||
1226 | #if defined(CONFIG_IWLAGN) || defined(CONFIG_IWLAGN_MODULE) | ||
1227 | struct { | ||
1228 | /* INT ICT Table */ | ||
1229 | __le32 *ict_tbl; | ||
1230 | void *ict_tbl_vir; | ||
1231 | dma_addr_t ict_tbl_dma; | ||
1232 | dma_addr_t aligned_ict_tbl_dma; | ||
1233 | int ict_index; | ||
1234 | u32 inta; | ||
1235 | bool use_ict; | ||
1236 | /* | ||
1237 | * reporting the number of tids has AGG on. 0 means | ||
1238 | * no AGGREGATION | ||
1239 | */ | ||
1240 | u8 agg_tids_count; | ||
1241 | } _agn; | ||
1242 | #endif | ||
1243 | }; | ||
1270 | 1244 | ||
1271 | /* INT ICT Table */ | 1245 | struct iwl_hw_params hw_params; |
1272 | __le32 *ict_tbl; | ||
1273 | dma_addr_t ict_tbl_dma; | ||
1274 | dma_addr_t aligned_ict_tbl_dma; | ||
1275 | int ict_index; | ||
1276 | void *ict_tbl_vir; | ||
1277 | u32 inta; | ||
1278 | bool use_ict; | ||
1279 | 1246 | ||
1280 | u32 inta_mask; | 1247 | u32 inta_mask; |
1281 | /* Current association information needed to configure the | 1248 | /* Current association information needed to configure the |
@@ -1303,10 +1270,6 @@ struct iwl_priv { | |||
1303 | struct delayed_work alive_start; | 1270 | struct delayed_work alive_start; |
1304 | struct delayed_work scan_check; | 1271 | struct delayed_work scan_check; |
1305 | 1272 | ||
1306 | /*For 3945 only*/ | ||
1307 | struct delayed_work thermal_periodic; | ||
1308 | struct delayed_work rfkill_poll; | ||
1309 | |||
1310 | /* TX Power */ | 1273 | /* TX Power */ |
1311 | s8 tx_power_user_lmt; | 1274 | s8 tx_power_user_lmt; |
1312 | s8 tx_power_device_lmt; | 1275 | s8 tx_power_device_lmt; |
@@ -1338,13 +1301,8 @@ struct iwl_priv { | |||
1338 | struct work_struct run_time_calib_work; | 1301 | struct work_struct run_time_calib_work; |
1339 | struct timer_list statistics_periodic; | 1302 | struct timer_list statistics_periodic; |
1340 | struct timer_list ucode_trace; | 1303 | struct timer_list ucode_trace; |
1304 | struct timer_list monitor_recover; | ||
1341 | bool hw_ready; | 1305 | bool hw_ready; |
1342 | /*For 3945*/ | ||
1343 | #define IWL_DEFAULT_TX_POWER 0x0F | ||
1344 | |||
1345 | struct iwl3945_notif_statistics statistics_39; | ||
1346 | |||
1347 | u32 sta_supp_rates; | ||
1348 | 1306 | ||
1349 | struct iwl_event_log event_log; | 1307 | struct iwl_event_log event_log; |
1350 | }; /*iwl_priv */ | 1308 | }; /*iwl_priv */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.c b/drivers/net/wireless/iwlwifi/iwl-devtrace.c index 36580d8d8b8d..f469aa92316a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.c +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.c | |||
@@ -35,6 +35,7 @@ EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_iowrite8); | |||
35 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ioread32); | 35 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ioread32); |
36 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_iowrite32); | 36 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_iowrite32); |
37 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_rx); | 37 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_rx); |
38 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_tx); | ||
38 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_event); | 39 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_event); |
39 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_error); | 40 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_error); |
40 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_cont_event); | 41 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_cont_event); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index 4e1ba824dc50..cb6d50b78140 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h | |||
@@ -188,19 +188,19 @@ struct iwl_eeprom_enhanced_txpwr { | |||
188 | /* 5000 regulatory - indirect access */ | 188 | /* 5000 regulatory - indirect access */ |
189 | #define EEPROM_5000_REG_SKU_ID ((0x02)\ | 189 | #define EEPROM_5000_REG_SKU_ID ((0x02)\ |
190 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 4 bytes */ | 190 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 4 bytes */ |
191 | #define EEPROM_5000_REG_BAND_1_CHANNELS ((0x08)\ | 191 | #define EEPROM_REG_BAND_1_CHANNELS ((0x08)\ |
192 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 28 bytes */ | 192 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 28 bytes */ |
193 | #define EEPROM_5000_REG_BAND_2_CHANNELS ((0x26)\ | 193 | #define EEPROM_REG_BAND_2_CHANNELS ((0x26)\ |
194 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 26 bytes */ | 194 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 26 bytes */ |
195 | #define EEPROM_5000_REG_BAND_3_CHANNELS ((0x42)\ | 195 | #define EEPROM_REG_BAND_3_CHANNELS ((0x42)\ |
196 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 24 bytes */ | 196 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 24 bytes */ |
197 | #define EEPROM_5000_REG_BAND_4_CHANNELS ((0x5C)\ | 197 | #define EEPROM_REG_BAND_4_CHANNELS ((0x5C)\ |
198 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 22 bytes */ | 198 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 22 bytes */ |
199 | #define EEPROM_5000_REG_BAND_5_CHANNELS ((0x74)\ | 199 | #define EEPROM_REG_BAND_5_CHANNELS ((0x74)\ |
200 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 12 bytes */ | 200 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 12 bytes */ |
201 | #define EEPROM_5000_REG_BAND_24_HT40_CHANNELS ((0x82)\ | 201 | #define EEPROM_REG_BAND_24_HT40_CHANNELS ((0x82)\ |
202 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 14 bytes */ | 202 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 14 bytes */ |
203 | #define EEPROM_5000_REG_BAND_52_HT40_CHANNELS ((0x92)\ | 203 | #define EEPROM_REG_BAND_52_HT40_CHANNELS ((0x92)\ |
204 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 22 bytes */ | 204 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 22 bytes */ |
205 | 205 | ||
206 | /* 6000 and up regulatory tx power - indirect access */ | 206 | /* 6000 and up regulatory tx power - indirect access */ |
@@ -261,12 +261,15 @@ struct iwl_eeprom_enhanced_txpwr { | |||
261 | #define EEPROM_5050_EEPROM_VERSION (0x21E) | 261 | #define EEPROM_5050_EEPROM_VERSION (0x21E) |
262 | 262 | ||
263 | /* 1000 Specific */ | 263 | /* 1000 Specific */ |
264 | #define EEPROM_1000_TX_POWER_VERSION (4) | ||
264 | #define EEPROM_1000_EEPROM_VERSION (0x15C) | 265 | #define EEPROM_1000_EEPROM_VERSION (0x15C) |
265 | 266 | ||
266 | /* 6x00 Specific */ | 267 | /* 6x00 Specific */ |
268 | #define EEPROM_6000_TX_POWER_VERSION (4) | ||
267 | #define EEPROM_6000_EEPROM_VERSION (0x434) | 269 | #define EEPROM_6000_EEPROM_VERSION (0x434) |
268 | 270 | ||
269 | /* 6x50 Specific */ | 271 | /* 6x50 Specific */ |
272 | #define EEPROM_6050_TX_POWER_VERSION (4) | ||
270 | #define EEPROM_6050_EEPROM_VERSION (0x532) | 273 | #define EEPROM_6050_EEPROM_VERSION (0x532) |
271 | 274 | ||
272 | /* OTP */ | 275 | /* OTP */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 73681c4fefe7..51f89e7ba681 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c | |||
@@ -169,7 +169,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
169 | mutex_lock(&priv->sync_cmd_mutex); | 169 | mutex_lock(&priv->sync_cmd_mutex); |
170 | 170 | ||
171 | set_bit(STATUS_HCMD_ACTIVE, &priv->status); | 171 | set_bit(STATUS_HCMD_ACTIVE, &priv->status); |
172 | IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s \n", | 172 | IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s\n", |
173 | get_cmd_string(cmd->id)); | 173 | get_cmd_string(cmd->id)); |
174 | 174 | ||
175 | cmd_idx = iwl_enqueue_hcmd(priv, cmd); | 175 | cmd_idx = iwl_enqueue_hcmd(priv, cmd); |
@@ -191,7 +191,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
191 | jiffies_to_msecs(HOST_COMPLETE_TIMEOUT)); | 191 | jiffies_to_msecs(HOST_COMPLETE_TIMEOUT)); |
192 | 192 | ||
193 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); | 193 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); |
194 | IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s \n", | 194 | IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s\n", |
195 | get_cmd_string(cmd->id)); | 195 | get_cmd_string(cmd->id)); |
196 | ret = -ETIMEDOUT; | 196 | ret = -ETIMEDOUT; |
197 | goto cancel; | 197 | goto cancel; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h index 51a67fb2e185..3ff6b9d25a10 100644 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h | |||
@@ -31,6 +31,9 @@ | |||
31 | #define __iwl_helpers_h__ | 31 | #define __iwl_helpers_h__ |
32 | 32 | ||
33 | #include <linux/ctype.h> | 33 | #include <linux/ctype.h> |
34 | #include <net/mac80211.h> | ||
35 | |||
36 | #include "iwl-io.h" | ||
34 | 37 | ||
35 | #define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo)))) | 38 | #define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo)))) |
36 | 39 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index c719baf2585a..4f54a5f71cd5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h | |||
@@ -297,7 +297,7 @@ static inline u32 __iwl_read_direct32(const char *f, u32 l, | |||
297 | struct iwl_priv *priv, u32 reg) | 297 | struct iwl_priv *priv, u32 reg) |
298 | { | 298 | { |
299 | u32 value = _iwl_read_direct32(priv, reg); | 299 | u32 value = _iwl_read_direct32(priv, reg); |
300 | IWL_DEBUG_IO(priv, "read_direct32(0x%4X) = 0x%08x - %s %d \n", reg, value, | 300 | IWL_DEBUG_IO(priv, "read_direct32(0x%4X) = 0x%08x - %s %d\n", reg, value, |
301 | f, l); | 301 | f, l); |
302 | return value; | 302 | return value; |
303 | } | 303 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index a6f9c918aabc..db5bfcb036ca 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c | |||
@@ -46,7 +46,7 @@ | |||
46 | static int led_mode; | 46 | static int led_mode; |
47 | module_param(led_mode, int, S_IRUGO); | 47 | module_param(led_mode, int, S_IRUGO); |
48 | MODULE_PARM_DESC(led_mode, "led mode: 0=blinking, 1=On(RF On)/Off(RF Off), " | 48 | MODULE_PARM_DESC(led_mode, "led mode: 0=blinking, 1=On(RF On)/Off(RF Off), " |
49 | "(default 0)\n"); | 49 | "(default 0)"); |
50 | 50 | ||
51 | 51 | ||
52 | static const struct { | 52 | static const struct { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 1a1a9f081cc7..2655dbdc8175 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c | |||
@@ -383,10 +383,10 @@ EXPORT_SYMBOL(iwl_ht_enabled); | |||
383 | 383 | ||
384 | bool iwl_within_ct_kill_margin(struct iwl_priv *priv) | 384 | bool iwl_within_ct_kill_margin(struct iwl_priv *priv) |
385 | { | 385 | { |
386 | s32 temp = priv->temperature; /* degrees CELSIUS except 4965 */ | 386 | s32 temp = priv->temperature; /* degrees CELSIUS except specified */ |
387 | bool within_margin = false; | 387 | bool within_margin = false; |
388 | 388 | ||
389 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) | 389 | if (priv->cfg->temperature_kelvin) |
390 | temp = KELVIN_TO_CELSIUS(priv->temperature); | 390 | temp = KELVIN_TO_CELSIUS(priv->temperature); |
391 | 391 | ||
392 | if (!priv->thermal_throttle.advanced_tt) | 392 | if (!priv->thermal_throttle.advanced_tt) |
@@ -839,12 +839,12 @@ EXPORT_SYMBOL(iwl_tt_exit_ct_kill); | |||
839 | static void iwl_bg_tt_work(struct work_struct *work) | 839 | static void iwl_bg_tt_work(struct work_struct *work) |
840 | { | 840 | { |
841 | struct iwl_priv *priv = container_of(work, struct iwl_priv, tt_work); | 841 | struct iwl_priv *priv = container_of(work, struct iwl_priv, tt_work); |
842 | s32 temp = priv->temperature; /* degrees CELSIUS except 4965 */ | 842 | s32 temp = priv->temperature; /* degrees CELSIUS except specified */ |
843 | 843 | ||
844 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 844 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
845 | return; | 845 | return; |
846 | 846 | ||
847 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) | 847 | if (priv->cfg->temperature_kelvin) |
848 | temp = KELVIN_TO_CELSIUS(priv->temperature); | 848 | temp = KELVIN_TO_CELSIUS(priv->temperature); |
849 | 849 | ||
850 | if (!priv->thermal_throttle.advanced_tt) | 850 | if (!priv->thermal_throttle.advanced_tt) |
@@ -874,7 +874,7 @@ void iwl_tt_initialize(struct iwl_priv *priv) | |||
874 | int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1); | 874 | int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1); |
875 | struct iwl_tt_trans *transaction; | 875 | struct iwl_tt_trans *transaction; |
876 | 876 | ||
877 | IWL_DEBUG_POWER(priv, "Initialize Thermal Throttling \n"); | 877 | IWL_DEBUG_POWER(priv, "Initialize Thermal Throttling\n"); |
878 | 878 | ||
879 | memset(tt, 0, sizeof(struct iwl_tt_mgmt)); | 879 | memset(tt, 0, sizeof(struct iwl_tt_mgmt)); |
880 | 880 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index d2d2a9174900..5944de7a98a2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h | |||
@@ -254,7 +254,7 @@ | |||
254 | * device. A queue maps to only one (selectable by driver) Tx DMA channel, | 254 | * device. A queue maps to only one (selectable by driver) Tx DMA channel, |
255 | * but one DMA channel may take input from several queues. | 255 | * but one DMA channel may take input from several queues. |
256 | * | 256 | * |
257 | * Tx DMA channels have dedicated purposes. For 4965, they are used as follows | 257 | * Tx DMA FIFOs have dedicated purposes. For 4965, they are used as follows |
258 | * (cf. default_queue_to_tx_fifo in iwl-4965.c): | 258 | * (cf. default_queue_to_tx_fifo in iwl-4965.c): |
259 | * | 259 | * |
260 | * 0 -- EDCA BK (background) frames, lowest priority | 260 | * 0 -- EDCA BK (background) frames, lowest priority |
@@ -262,20 +262,20 @@ | |||
262 | * 2 -- EDCA VI (video) frames, higher priority | 262 | * 2 -- EDCA VI (video) frames, higher priority |
263 | * 3 -- EDCA VO (voice) and management frames, highest priority | 263 | * 3 -- EDCA VO (voice) and management frames, highest priority |
264 | * 4 -- Commands (e.g. RXON, etc.) | 264 | * 4 -- Commands (e.g. RXON, etc.) |
265 | * 5 -- HCCA short frames | 265 | * 5 -- unused (HCCA) |
266 | * 6 -- HCCA long frames | 266 | * 6 -- unused (HCCA) |
267 | * 7 -- not used by driver (device-internal only) | 267 | * 7 -- not used by driver (device-internal only) |
268 | * | 268 | * |
269 | * For 5000 series and up, they are used slightly differently | 269 | * For 5000 series and up, they are used differently |
270 | * (cf. iwl5000_default_queue_to_tx_fifo in iwl-5000.c): | 270 | * (cf. iwl5000_default_queue_to_tx_fifo in iwl-5000.c): |
271 | * | 271 | * |
272 | * 0 -- EDCA BK (background) frames, lowest priority | 272 | * 0 -- EDCA BK (background) frames, lowest priority |
273 | * 1 -- EDCA BE (best effort) frames, normal priority | 273 | * 1 -- EDCA BE (best effort) frames, normal priority |
274 | * 2 -- EDCA VI (video) frames, higher priority | 274 | * 2 -- EDCA VI (video) frames, higher priority |
275 | * 3 -- EDCA VO (voice) and management frames, highest priority | 275 | * 3 -- EDCA VO (voice) and management frames, highest priority |
276 | * 4 -- (TBD) | 276 | * 4 -- unused |
277 | * 5 -- HCCA short frames | 277 | * 5 -- unused |
278 | * 6 -- HCCA long frames | 278 | * 6 -- unused |
279 | * 7 -- Commands | 279 | * 7 -- Commands |
280 | * | 280 | * |
281 | * Driver should normally map queues 0-6 to Tx DMA/FIFO channels 0-6. | 281 | * Driver should normally map queues 0-6 to Tx DMA/FIFO channels 0-6. |
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index df257bc15f49..1dff14a67b2c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c | |||
@@ -162,197 +162,6 @@ void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q | |||
162 | spin_unlock_irqrestore(&q->lock, flags); | 162 | spin_unlock_irqrestore(&q->lock, flags); |
163 | } | 163 | } |
164 | EXPORT_SYMBOL(iwl_rx_queue_update_write_ptr); | 164 | EXPORT_SYMBOL(iwl_rx_queue_update_write_ptr); |
165 | /** | ||
166 | * iwl_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr | ||
167 | */ | ||
168 | static inline __le32 iwl_dma_addr2rbd_ptr(struct iwl_priv *priv, | ||
169 | dma_addr_t dma_addr) | ||
170 | { | ||
171 | return cpu_to_le32((u32)(dma_addr >> 8)); | ||
172 | } | ||
173 | |||
174 | /** | ||
175 | * iwl_rx_queue_restock - refill RX queue from pre-allocated pool | ||
176 | * | ||
177 | * If there are slots in the RX queue that need to be restocked, | ||
178 | * and we have free pre-allocated buffers, fill the ranks as much | ||
179 | * as we can, pulling from rx_free. | ||
180 | * | ||
181 | * This moves the 'write' index forward to catch up with 'processed', and | ||
182 | * also updates the memory address in the firmware to reference the new | ||
183 | * target buffer. | ||
184 | */ | ||
185 | void iwl_rx_queue_restock(struct iwl_priv *priv) | ||
186 | { | ||
187 | struct iwl_rx_queue *rxq = &priv->rxq; | ||
188 | struct list_head *element; | ||
189 | struct iwl_rx_mem_buffer *rxb; | ||
190 | unsigned long flags; | ||
191 | int write; | ||
192 | |||
193 | spin_lock_irqsave(&rxq->lock, flags); | ||
194 | write = rxq->write & ~0x7; | ||
195 | while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) { | ||
196 | /* Get next free Rx buffer, remove from free list */ | ||
197 | element = rxq->rx_free.next; | ||
198 | rxb = list_entry(element, struct iwl_rx_mem_buffer, list); | ||
199 | list_del(element); | ||
200 | |||
201 | /* Point to Rx buffer via next RBD in circular buffer */ | ||
202 | rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(priv, rxb->page_dma); | ||
203 | rxq->queue[rxq->write] = rxb; | ||
204 | rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; | ||
205 | rxq->free_count--; | ||
206 | } | ||
207 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
208 | /* If the pre-allocated buffer pool is dropping low, schedule to | ||
209 | * refill it */ | ||
210 | if (rxq->free_count <= RX_LOW_WATERMARK) | ||
211 | queue_work(priv->workqueue, &priv->rx_replenish); | ||
212 | |||
213 | |||
214 | /* If we've added more space for the firmware to place data, tell it. | ||
215 | * Increment device's write pointer in multiples of 8. */ | ||
216 | if (rxq->write_actual != (rxq->write & ~0x7)) { | ||
217 | spin_lock_irqsave(&rxq->lock, flags); | ||
218 | rxq->need_update = 1; | ||
219 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
220 | iwl_rx_queue_update_write_ptr(priv, rxq); | ||
221 | } | ||
222 | } | ||
223 | EXPORT_SYMBOL(iwl_rx_queue_restock); | ||
224 | |||
225 | |||
226 | /** | ||
227 | * iwl_rx_replenish - Move all used packet from rx_used to rx_free | ||
228 | * | ||
229 | * When moving to rx_free an SKB is allocated for the slot. | ||
230 | * | ||
231 | * Also restock the Rx queue via iwl_rx_queue_restock. | ||
232 | * This is called as a scheduled work item (except for during initialization) | ||
233 | */ | ||
234 | void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority) | ||
235 | { | ||
236 | struct iwl_rx_queue *rxq = &priv->rxq; | ||
237 | struct list_head *element; | ||
238 | struct iwl_rx_mem_buffer *rxb; | ||
239 | struct page *page; | ||
240 | unsigned long flags; | ||
241 | gfp_t gfp_mask = priority; | ||
242 | |||
243 | while (1) { | ||
244 | spin_lock_irqsave(&rxq->lock, flags); | ||
245 | if (list_empty(&rxq->rx_used)) { | ||
246 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
247 | return; | ||
248 | } | ||
249 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
250 | |||
251 | if (rxq->free_count > RX_LOW_WATERMARK) | ||
252 | gfp_mask |= __GFP_NOWARN; | ||
253 | |||
254 | if (priv->hw_params.rx_page_order > 0) | ||
255 | gfp_mask |= __GFP_COMP; | ||
256 | |||
257 | /* Alloc a new receive buffer */ | ||
258 | page = alloc_pages(gfp_mask, priv->hw_params.rx_page_order); | ||
259 | if (!page) { | ||
260 | if (net_ratelimit()) | ||
261 | IWL_DEBUG_INFO(priv, "alloc_pages failed, " | ||
262 | "order: %d\n", | ||
263 | priv->hw_params.rx_page_order); | ||
264 | |||
265 | if ((rxq->free_count <= RX_LOW_WATERMARK) && | ||
266 | net_ratelimit()) | ||
267 | IWL_CRIT(priv, "Failed to alloc_pages with %s. Only %u free buffers remaining.\n", | ||
268 | priority == GFP_ATOMIC ? "GFP_ATOMIC" : "GFP_KERNEL", | ||
269 | rxq->free_count); | ||
270 | /* We don't reschedule replenish work here -- we will | ||
271 | * call the restock method and if it still needs | ||
272 | * more buffers it will schedule replenish */ | ||
273 | return; | ||
274 | } | ||
275 | |||
276 | spin_lock_irqsave(&rxq->lock, flags); | ||
277 | |||
278 | if (list_empty(&rxq->rx_used)) { | ||
279 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
280 | __free_pages(page, priv->hw_params.rx_page_order); | ||
281 | return; | ||
282 | } | ||
283 | element = rxq->rx_used.next; | ||
284 | rxb = list_entry(element, struct iwl_rx_mem_buffer, list); | ||
285 | list_del(element); | ||
286 | |||
287 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
288 | |||
289 | rxb->page = page; | ||
290 | /* Get physical address of the RB */ | ||
291 | rxb->page_dma = pci_map_page(priv->pci_dev, page, 0, | ||
292 | PAGE_SIZE << priv->hw_params.rx_page_order, | ||
293 | PCI_DMA_FROMDEVICE); | ||
294 | /* dma address must be no more than 36 bits */ | ||
295 | BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36)); | ||
296 | /* and also 256 byte aligned! */ | ||
297 | BUG_ON(rxb->page_dma & DMA_BIT_MASK(8)); | ||
298 | |||
299 | spin_lock_irqsave(&rxq->lock, flags); | ||
300 | |||
301 | list_add_tail(&rxb->list, &rxq->rx_free); | ||
302 | rxq->free_count++; | ||
303 | priv->alloc_rxb_page++; | ||
304 | |||
305 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
306 | } | ||
307 | } | ||
308 | |||
309 | void iwl_rx_replenish(struct iwl_priv *priv) | ||
310 | { | ||
311 | unsigned long flags; | ||
312 | |||
313 | iwl_rx_allocate(priv, GFP_KERNEL); | ||
314 | |||
315 | spin_lock_irqsave(&priv->lock, flags); | ||
316 | iwl_rx_queue_restock(priv); | ||
317 | spin_unlock_irqrestore(&priv->lock, flags); | ||
318 | } | ||
319 | EXPORT_SYMBOL(iwl_rx_replenish); | ||
320 | |||
321 | void iwl_rx_replenish_now(struct iwl_priv *priv) | ||
322 | { | ||
323 | iwl_rx_allocate(priv, GFP_ATOMIC); | ||
324 | |||
325 | iwl_rx_queue_restock(priv); | ||
326 | } | ||
327 | EXPORT_SYMBOL(iwl_rx_replenish_now); | ||
328 | |||
329 | |||
330 | /* Assumes that the skb field of the buffers in 'pool' is kept accurate. | ||
331 | * If an SKB has been detached, the POOL needs to have its SKB set to NULL | ||
332 | * This free routine walks the list of POOL entries and if SKB is set to | ||
333 | * non NULL it is unmapped and freed | ||
334 | */ | ||
335 | void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | ||
336 | { | ||
337 | int i; | ||
338 | for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) { | ||
339 | if (rxq->pool[i].page != NULL) { | ||
340 | pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma, | ||
341 | PAGE_SIZE << priv->hw_params.rx_page_order, | ||
342 | PCI_DMA_FROMDEVICE); | ||
343 | __iwl_free_pages(priv, rxq->pool[i].page); | ||
344 | rxq->pool[i].page = NULL; | ||
345 | } | ||
346 | } | ||
347 | |||
348 | dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, | ||
349 | rxq->dma_addr); | ||
350 | dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status), | ||
351 | rxq->rb_stts, rxq->rb_stts_dma); | ||
352 | rxq->bd = NULL; | ||
353 | rxq->rb_stts = NULL; | ||
354 | } | ||
355 | EXPORT_SYMBOL(iwl_rx_queue_free); | ||
356 | 165 | ||
357 | int iwl_rx_queue_alloc(struct iwl_priv *priv) | 166 | int iwl_rx_queue_alloc(struct iwl_priv *priv) |
358 | { | 167 | { |
@@ -395,98 +204,6 @@ err_bd: | |||
395 | } | 204 | } |
396 | EXPORT_SYMBOL(iwl_rx_queue_alloc); | 205 | EXPORT_SYMBOL(iwl_rx_queue_alloc); |
397 | 206 | ||
398 | void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | ||
399 | { | ||
400 | unsigned long flags; | ||
401 | int i; | ||
402 | spin_lock_irqsave(&rxq->lock, flags); | ||
403 | INIT_LIST_HEAD(&rxq->rx_free); | ||
404 | INIT_LIST_HEAD(&rxq->rx_used); | ||
405 | /* Fill the rx_used queue with _all_ of the Rx buffers */ | ||
406 | for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) { | ||
407 | /* In the reset function, these buffers may have been allocated | ||
408 | * to an SKB, so we need to unmap and free potential storage */ | ||
409 | if (rxq->pool[i].page != NULL) { | ||
410 | pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma, | ||
411 | PAGE_SIZE << priv->hw_params.rx_page_order, | ||
412 | PCI_DMA_FROMDEVICE); | ||
413 | __iwl_free_pages(priv, rxq->pool[i].page); | ||
414 | rxq->pool[i].page = NULL; | ||
415 | } | ||
416 | list_add_tail(&rxq->pool[i].list, &rxq->rx_used); | ||
417 | } | ||
418 | |||
419 | /* Set us so that we have processed and used all buffers, but have | ||
420 | * not restocked the Rx queue with fresh buffers */ | ||
421 | rxq->read = rxq->write = 0; | ||
422 | rxq->write_actual = 0; | ||
423 | rxq->free_count = 0; | ||
424 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
425 | } | ||
426 | |||
427 | int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | ||
428 | { | ||
429 | u32 rb_size; | ||
430 | const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */ | ||
431 | u32 rb_timeout = 0; /* FIXME: RX_RB_TIMEOUT for all devices? */ | ||
432 | |||
433 | if (!priv->cfg->use_isr_legacy) | ||
434 | rb_timeout = RX_RB_TIMEOUT; | ||
435 | |||
436 | if (priv->cfg->mod_params->amsdu_size_8K) | ||
437 | rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K; | ||
438 | else | ||
439 | rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K; | ||
440 | |||
441 | /* Stop Rx DMA */ | ||
442 | iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); | ||
443 | |||
444 | /* Reset driver's Rx queue write index */ | ||
445 | iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0); | ||
446 | |||
447 | /* Tell device where to find RBD circular buffer in DRAM */ | ||
448 | iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG, | ||
449 | (u32)(rxq->dma_addr >> 8)); | ||
450 | |||
451 | /* Tell device where in DRAM to update its Rx status */ | ||
452 | iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG, | ||
453 | rxq->rb_stts_dma >> 4); | ||
454 | |||
455 | /* Enable Rx DMA | ||
456 | * FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY is set because of HW bug in | ||
457 | * the credit mechanism in 5000 HW RX FIFO | ||
458 | * Direct rx interrupts to hosts | ||
459 | * Rx buffer size 4 or 8k | ||
460 | * RB timeout 0x10 | ||
461 | * 256 RBDs | ||
462 | */ | ||
463 | iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, | ||
464 | FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | | ||
465 | FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY | | ||
466 | FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | | ||
467 | FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK | | ||
468 | rb_size| | ||
469 | (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)| | ||
470 | (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); | ||
471 | |||
472 | /* Set interrupt coalescing timer to default (2048 usecs) */ | ||
473 | iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); | ||
474 | |||
475 | return 0; | ||
476 | } | ||
477 | |||
478 | int iwl_rxq_stop(struct iwl_priv *priv) | ||
479 | { | ||
480 | |||
481 | /* stop Rx DMA */ | ||
482 | iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); | ||
483 | iwl_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG, | ||
484 | FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000); | ||
485 | |||
486 | return 0; | ||
487 | } | ||
488 | EXPORT_SYMBOL(iwl_rxq_stop); | ||
489 | |||
490 | void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, | 207 | void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, |
491 | struct iwl_rx_mem_buffer *rxb) | 208 | struct iwl_rx_mem_buffer *rxb) |
492 | 209 | ||
@@ -542,6 +259,7 @@ static void iwl_rx_calc_noise(struct iwl_priv *priv) | |||
542 | le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER; | 259 | le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER; |
543 | int bcn_silence_c = | 260 | int bcn_silence_c = |
544 | le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER; | 261 | le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER; |
262 | int last_rx_noise; | ||
545 | 263 | ||
546 | if (bcn_silence_a) { | 264 | if (bcn_silence_a) { |
547 | total_silence += bcn_silence_a; | 265 | total_silence += bcn_silence_a; |
@@ -558,13 +276,13 @@ static void iwl_rx_calc_noise(struct iwl_priv *priv) | |||
558 | 276 | ||
559 | /* Average among active antennas */ | 277 | /* Average among active antennas */ |
560 | if (num_active_rx) | 278 | if (num_active_rx) |
561 | priv->last_rx_noise = (total_silence / num_active_rx) - 107; | 279 | last_rx_noise = (total_silence / num_active_rx) - 107; |
562 | else | 280 | else |
563 | priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; | 281 | last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; |
564 | 282 | ||
565 | IWL_DEBUG_CALIB(priv, "inband silence a %u, b %u, c %u, dBm %d\n", | 283 | IWL_DEBUG_CALIB(priv, "inband silence a %u, b %u, c %u, dBm %d\n", |
566 | bcn_silence_a, bcn_silence_b, bcn_silence_c, | 284 | bcn_silence_a, bcn_silence_b, bcn_silence_c, |
567 | priv->last_rx_noise); | 285 | last_rx_noise); |
568 | } | 286 | } |
569 | 287 | ||
570 | #ifdef CONFIG_IWLWIFI_DEBUG | 288 | #ifdef CONFIG_IWLWIFI_DEBUG |
@@ -616,29 +334,20 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv, | |||
616 | 334 | ||
617 | #define REG_RECALIB_PERIOD (60) | 335 | #define REG_RECALIB_PERIOD (60) |
618 | 336 | ||
619 | #define PLCP_MSG "plcp_err exceeded %u, %u, %u, %u, %u, %d, %u mSecs\n" | 337 | /** |
620 | void iwl_rx_statistics(struct iwl_priv *priv, | 338 | * iwl_good_plcp_health - checks for plcp error. |
621 | struct iwl_rx_mem_buffer *rxb) | 339 | * |
340 | * When the plcp error is exceeding the thresholds, reset the radio | ||
341 | * to improve the throughput. | ||
342 | */ | ||
343 | bool iwl_good_plcp_health(struct iwl_priv *priv, | ||
344 | struct iwl_rx_packet *pkt) | ||
622 | { | 345 | { |
623 | int change; | 346 | bool rc = true; |
624 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
625 | int combined_plcp_delta; | 347 | int combined_plcp_delta; |
626 | unsigned int plcp_msec; | 348 | unsigned int plcp_msec; |
627 | unsigned long plcp_received_jiffies; | 349 | unsigned long plcp_received_jiffies; |
628 | 350 | ||
629 | IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", | ||
630 | (int)sizeof(priv->statistics), | ||
631 | le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); | ||
632 | |||
633 | change = ((priv->statistics.general.temperature != | ||
634 | pkt->u.stats.general.temperature) || | ||
635 | ((priv->statistics.flag & | ||
636 | STATISTICS_REPLY_FLG_HT40_MODE_MSK) != | ||
637 | (pkt->u.stats.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK))); | ||
638 | |||
639 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
640 | iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); | ||
641 | #endif | ||
642 | /* | 351 | /* |
643 | * check for plcp_err and trigger radio reset if it exceeds | 352 | * check for plcp_err and trigger radio reset if it exceeds |
644 | * the plcp error threshold plcp_delta. | 353 | * the plcp error threshold plcp_delta. |
@@ -659,11 +368,11 @@ void iwl_rx_statistics(struct iwl_priv *priv, | |||
659 | le32_to_cpu(priv->statistics.rx.ofdm_ht.plcp_err)); | 368 | le32_to_cpu(priv->statistics.rx.ofdm_ht.plcp_err)); |
660 | 369 | ||
661 | if ((combined_plcp_delta > 0) && | 370 | if ((combined_plcp_delta > 0) && |
662 | ((combined_plcp_delta * 100) / plcp_msec) > | 371 | ((combined_plcp_delta * 100) / plcp_msec) > |
663 | priv->cfg->plcp_delta_threshold) { | 372 | priv->cfg->plcp_delta_threshold) { |
664 | /* | 373 | /* |
665 | * if plcp_err exceed the threshold, the following | 374 | * if plcp_err exceed the threshold, |
666 | * data is printed in csv format: | 375 | * the following data is printed in csv format: |
667 | * Text: plcp_err exceeded %d, | 376 | * Text: plcp_err exceeded %d, |
668 | * Received ofdm.plcp_err, | 377 | * Received ofdm.plcp_err, |
669 | * Current ofdm.plcp_err, | 378 | * Current ofdm.plcp_err, |
@@ -672,22 +381,73 @@ void iwl_rx_statistics(struct iwl_priv *priv, | |||
672 | * combined_plcp_delta, | 381 | * combined_plcp_delta, |
673 | * plcp_msec | 382 | * plcp_msec |
674 | */ | 383 | */ |
675 | IWL_DEBUG_RADIO(priv, PLCP_MSG, | 384 | IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, " |
385 | "%u, %u, %u, %u, %d, %u mSecs\n", | ||
676 | priv->cfg->plcp_delta_threshold, | 386 | priv->cfg->plcp_delta_threshold, |
677 | le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err), | 387 | le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err), |
678 | le32_to_cpu(priv->statistics.rx.ofdm.plcp_err), | 388 | le32_to_cpu(priv->statistics.rx.ofdm.plcp_err), |
679 | le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err), | 389 | le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err), |
680 | le32_to_cpu( | 390 | le32_to_cpu( |
681 | priv->statistics.rx.ofdm_ht.plcp_err), | 391 | priv->statistics.rx.ofdm_ht.plcp_err), |
682 | combined_plcp_delta, plcp_msec); | 392 | combined_plcp_delta, plcp_msec); |
393 | rc = false; | ||
394 | } | ||
395 | } | ||
396 | return rc; | ||
397 | } | ||
398 | EXPORT_SYMBOL(iwl_good_plcp_health); | ||
683 | 399 | ||
684 | /* | 400 | static void iwl_recover_from_statistics(struct iwl_priv *priv, |
685 | * Reset the RF radio due to the high plcp | 401 | struct iwl_rx_packet *pkt) |
686 | * error rate | 402 | { |
687 | */ | 403 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
688 | iwl_force_reset(priv, IWL_RF_RESET); | 404 | return; |
405 | if (iwl_is_associated(priv)) { | ||
406 | if (priv->cfg->ops->lib->check_ack_health) { | ||
407 | if (!priv->cfg->ops->lib->check_ack_health( | ||
408 | priv, pkt)) { | ||
409 | /* | ||
410 | * low ack count detected | ||
411 | * restart Firmware | ||
412 | */ | ||
413 | IWL_ERR(priv, "low ack count detected, " | ||
414 | "restart firmware\n"); | ||
415 | iwl_force_reset(priv, IWL_FW_RESET); | ||
416 | } | ||
417 | } else if (priv->cfg->ops->lib->check_plcp_health) { | ||
418 | if (!priv->cfg->ops->lib->check_plcp_health( | ||
419 | priv, pkt)) { | ||
420 | /* | ||
421 | * high plcp error detected | ||
422 | * reset Radio | ||
423 | */ | ||
424 | iwl_force_reset(priv, IWL_RF_RESET); | ||
425 | } | ||
689 | } | 426 | } |
690 | } | 427 | } |
428 | } | ||
429 | |||
430 | void iwl_rx_statistics(struct iwl_priv *priv, | ||
431 | struct iwl_rx_mem_buffer *rxb) | ||
432 | { | ||
433 | int change; | ||
434 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
435 | |||
436 | |||
437 | IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", | ||
438 | (int)sizeof(priv->statistics), | ||
439 | le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); | ||
440 | |||
441 | change = ((priv->statistics.general.temperature != | ||
442 | pkt->u.stats.general.temperature) || | ||
443 | ((priv->statistics.flag & | ||
444 | STATISTICS_REPLY_FLG_HT40_MODE_MSK) != | ||
445 | (pkt->u.stats.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK))); | ||
446 | |||
447 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
448 | iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); | ||
449 | #endif | ||
450 | iwl_recover_from_statistics(priv, pkt); | ||
691 | 451 | ||
692 | memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics)); | 452 | memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics)); |
693 | 453 | ||
@@ -730,139 +490,6 @@ void iwl_reply_statistics(struct iwl_priv *priv, | |||
730 | } | 490 | } |
731 | EXPORT_SYMBOL(iwl_reply_statistics); | 491 | EXPORT_SYMBOL(iwl_reply_statistics); |
732 | 492 | ||
733 | /* Calc max signal level (dBm) among 3 possible receivers */ | ||
734 | static inline int iwl_calc_rssi(struct iwl_priv *priv, | ||
735 | struct iwl_rx_phy_res *rx_resp) | ||
736 | { | ||
737 | return priv->cfg->ops->utils->calc_rssi(priv, rx_resp); | ||
738 | } | ||
739 | |||
740 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
741 | /** | ||
742 | * iwl_dbg_report_frame - dump frame to syslog during debug sessions | ||
743 | * | ||
744 | * You may hack this function to show different aspects of received frames, | ||
745 | * including selective frame dumps. | ||
746 | * group100 parameter selects whether to show 1 out of 100 good data frames. | ||
747 | * All beacon and probe response frames are printed. | ||
748 | */ | ||
749 | static void iwl_dbg_report_frame(struct iwl_priv *priv, | ||
750 | struct iwl_rx_phy_res *phy_res, u16 length, | ||
751 | struct ieee80211_hdr *header, int group100) | ||
752 | { | ||
753 | u32 to_us; | ||
754 | u32 print_summary = 0; | ||
755 | u32 print_dump = 0; /* set to 1 to dump all frames' contents */ | ||
756 | u32 hundred = 0; | ||
757 | u32 dataframe = 0; | ||
758 | __le16 fc; | ||
759 | u16 seq_ctl; | ||
760 | u16 channel; | ||
761 | u16 phy_flags; | ||
762 | u32 rate_n_flags; | ||
763 | u32 tsf_low; | ||
764 | int rssi; | ||
765 | |||
766 | if (likely(!(iwl_get_debug_level(priv) & IWL_DL_RX))) | ||
767 | return; | ||
768 | |||
769 | /* MAC header */ | ||
770 | fc = header->frame_control; | ||
771 | seq_ctl = le16_to_cpu(header->seq_ctrl); | ||
772 | |||
773 | /* metadata */ | ||
774 | channel = le16_to_cpu(phy_res->channel); | ||
775 | phy_flags = le16_to_cpu(phy_res->phy_flags); | ||
776 | rate_n_flags = le32_to_cpu(phy_res->rate_n_flags); | ||
777 | |||
778 | /* signal statistics */ | ||
779 | rssi = iwl_calc_rssi(priv, phy_res); | ||
780 | tsf_low = le64_to_cpu(phy_res->timestamp) & 0x0ffffffff; | ||
781 | |||
782 | to_us = !compare_ether_addr(header->addr1, priv->mac_addr); | ||
783 | |||
784 | /* if data frame is to us and all is good, | ||
785 | * (optionally) print summary for only 1 out of every 100 */ | ||
786 | if (to_us && (fc & ~cpu_to_le16(IEEE80211_FCTL_PROTECTED)) == | ||
787 | cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) { | ||
788 | dataframe = 1; | ||
789 | if (!group100) | ||
790 | print_summary = 1; /* print each frame */ | ||
791 | else if (priv->framecnt_to_us < 100) { | ||
792 | priv->framecnt_to_us++; | ||
793 | print_summary = 0; | ||
794 | } else { | ||
795 | priv->framecnt_to_us = 0; | ||
796 | print_summary = 1; | ||
797 | hundred = 1; | ||
798 | } | ||
799 | } else { | ||
800 | /* print summary for all other frames */ | ||
801 | print_summary = 1; | ||
802 | } | ||
803 | |||
804 | if (print_summary) { | ||
805 | char *title; | ||
806 | int rate_idx; | ||
807 | u32 bitrate; | ||
808 | |||
809 | if (hundred) | ||
810 | title = "100Frames"; | ||
811 | else if (ieee80211_has_retry(fc)) | ||
812 | title = "Retry"; | ||
813 | else if (ieee80211_is_assoc_resp(fc)) | ||
814 | title = "AscRsp"; | ||
815 | else if (ieee80211_is_reassoc_resp(fc)) | ||
816 | title = "RasRsp"; | ||
817 | else if (ieee80211_is_probe_resp(fc)) { | ||
818 | title = "PrbRsp"; | ||
819 | print_dump = 1; /* dump frame contents */ | ||
820 | } else if (ieee80211_is_beacon(fc)) { | ||
821 | title = "Beacon"; | ||
822 | print_dump = 1; /* dump frame contents */ | ||
823 | } else if (ieee80211_is_atim(fc)) | ||
824 | title = "ATIM"; | ||
825 | else if (ieee80211_is_auth(fc)) | ||
826 | title = "Auth"; | ||
827 | else if (ieee80211_is_deauth(fc)) | ||
828 | title = "DeAuth"; | ||
829 | else if (ieee80211_is_disassoc(fc)) | ||
830 | title = "DisAssoc"; | ||
831 | else | ||
832 | title = "Frame"; | ||
833 | |||
834 | rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags); | ||
835 | if (unlikely((rate_idx < 0) || (rate_idx >= IWL_RATE_COUNT))) { | ||
836 | bitrate = 0; | ||
837 | WARN_ON_ONCE(1); | ||
838 | } else { | ||
839 | bitrate = iwl_rates[rate_idx].ieee / 2; | ||
840 | } | ||
841 | |||
842 | /* print frame summary. | ||
843 | * MAC addresses show just the last byte (for brevity), | ||
844 | * but you can hack it to show more, if you'd like to. */ | ||
845 | if (dataframe) | ||
846 | IWL_DEBUG_RX(priv, "%s: mhd=0x%04x, dst=0x%02x, " | ||
847 | "len=%u, rssi=%d, chnl=%d, rate=%u, \n", | ||
848 | title, le16_to_cpu(fc), header->addr1[5], | ||
849 | length, rssi, channel, bitrate); | ||
850 | else { | ||
851 | /* src/dst addresses assume managed mode */ | ||
852 | IWL_DEBUG_RX(priv, "%s: 0x%04x, dst=0x%02x, src=0x%02x, " | ||
853 | "len=%u, rssi=%d, tim=%lu usec, " | ||
854 | "phy=0x%02x, chnl=%d\n", | ||
855 | title, le16_to_cpu(fc), header->addr1[5], | ||
856 | header->addr3[5], length, rssi, | ||
857 | tsf_low - priv->scan_start_tsf, | ||
858 | phy_flags, channel); | ||
859 | } | ||
860 | } | ||
861 | if (print_dump) | ||
862 | iwl_print_hex_dump(priv, IWL_DL_RX, header, length); | ||
863 | } | ||
864 | #endif | ||
865 | |||
866 | /* | 493 | /* |
867 | * returns non-zero if packet should be dropped | 494 | * returns non-zero if packet should be dropped |
868 | */ | 495 | */ |
@@ -910,305 +537,3 @@ int iwl_set_decrypted_flag(struct iwl_priv *priv, | |||
910 | return 0; | 537 | return 0; |
911 | } | 538 | } |
912 | EXPORT_SYMBOL(iwl_set_decrypted_flag); | 539 | EXPORT_SYMBOL(iwl_set_decrypted_flag); |
913 | |||
914 | static u32 iwl_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in) | ||
915 | { | ||
916 | u32 decrypt_out = 0; | ||
917 | |||
918 | if ((decrypt_in & RX_RES_STATUS_STATION_FOUND) == | ||
919 | RX_RES_STATUS_STATION_FOUND) | ||
920 | decrypt_out |= (RX_RES_STATUS_STATION_FOUND | | ||
921 | RX_RES_STATUS_NO_STATION_INFO_MISMATCH); | ||
922 | |||
923 | decrypt_out |= (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK); | ||
924 | |||
925 | /* packet was not encrypted */ | ||
926 | if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) == | ||
927 | RX_RES_STATUS_SEC_TYPE_NONE) | ||
928 | return decrypt_out; | ||
929 | |||
930 | /* packet was encrypted with unknown alg */ | ||
931 | if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) == | ||
932 | RX_RES_STATUS_SEC_TYPE_ERR) | ||
933 | return decrypt_out; | ||
934 | |||
935 | /* decryption was not done in HW */ | ||
936 | if ((decrypt_in & RX_MPDU_RES_STATUS_DEC_DONE_MSK) != | ||
937 | RX_MPDU_RES_STATUS_DEC_DONE_MSK) | ||
938 | return decrypt_out; | ||
939 | |||
940 | switch (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) { | ||
941 | |||
942 | case RX_RES_STATUS_SEC_TYPE_CCMP: | ||
943 | /* alg is CCM: check MIC only */ | ||
944 | if (!(decrypt_in & RX_MPDU_RES_STATUS_MIC_OK)) | ||
945 | /* Bad MIC */ | ||
946 | decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; | ||
947 | else | ||
948 | decrypt_out |= RX_RES_STATUS_DECRYPT_OK; | ||
949 | |||
950 | break; | ||
951 | |||
952 | case RX_RES_STATUS_SEC_TYPE_TKIP: | ||
953 | if (!(decrypt_in & RX_MPDU_RES_STATUS_TTAK_OK)) { | ||
954 | /* Bad TTAK */ | ||
955 | decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK; | ||
956 | break; | ||
957 | } | ||
958 | /* fall through if TTAK OK */ | ||
959 | default: | ||
960 | if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK)) | ||
961 | decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; | ||
962 | else | ||
963 | decrypt_out |= RX_RES_STATUS_DECRYPT_OK; | ||
964 | break; | ||
965 | }; | ||
966 | |||
967 | IWL_DEBUG_RX(priv, "decrypt_in:0x%x decrypt_out = 0x%x\n", | ||
968 | decrypt_in, decrypt_out); | ||
969 | |||
970 | return decrypt_out; | ||
971 | } | ||
972 | |||
973 | static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, | ||
974 | struct ieee80211_hdr *hdr, | ||
975 | u16 len, | ||
976 | u32 ampdu_status, | ||
977 | struct iwl_rx_mem_buffer *rxb, | ||
978 | struct ieee80211_rx_status *stats) | ||
979 | { | ||
980 | struct sk_buff *skb; | ||
981 | int ret = 0; | ||
982 | __le16 fc = hdr->frame_control; | ||
983 | |||
984 | /* We only process data packets if the interface is open */ | ||
985 | if (unlikely(!priv->is_open)) { | ||
986 | IWL_DEBUG_DROP_LIMIT(priv, | ||
987 | "Dropping packet while interface is not open.\n"); | ||
988 | return; | ||
989 | } | ||
990 | |||
991 | /* In case of HW accelerated crypto and bad decryption, drop */ | ||
992 | if (!priv->cfg->mod_params->sw_crypto && | ||
993 | iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats)) | ||
994 | return; | ||
995 | |||
996 | skb = alloc_skb(IWL_LINK_HDR_MAX * 2, GFP_ATOMIC); | ||
997 | if (!skb) { | ||
998 | IWL_ERR(priv, "alloc_skb failed\n"); | ||
999 | return; | ||
1000 | } | ||
1001 | |||
1002 | skb_reserve(skb, IWL_LINK_HDR_MAX); | ||
1003 | skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len); | ||
1004 | |||
1005 | /* mac80211 currently doesn't support paged SKB. Convert it to | ||
1006 | * linear SKB for management frame and data frame requires | ||
1007 | * software decryption or software defragementation. */ | ||
1008 | if (ieee80211_is_mgmt(fc) || | ||
1009 | ieee80211_has_protected(fc) || | ||
1010 | ieee80211_has_morefrags(fc) || | ||
1011 | le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG || | ||
1012 | (ieee80211_is_data_qos(fc) && | ||
1013 | *ieee80211_get_qos_ctl(hdr) & | ||
1014 | IEEE80211_QOS_CONTROL_A_MSDU_PRESENT)) | ||
1015 | ret = skb_linearize(skb); | ||
1016 | else | ||
1017 | ret = __pskb_pull_tail(skb, min_t(u16, IWL_LINK_HDR_MAX, len)) ? | ||
1018 | 0 : -ENOMEM; | ||
1019 | |||
1020 | if (ret) { | ||
1021 | kfree_skb(skb); | ||
1022 | goto out; | ||
1023 | } | ||
1024 | |||
1025 | /* | ||
1026 | * XXX: We cannot touch the page and its virtual memory (hdr) after | ||
1027 | * here. It might have already been freed by the above skb change. | ||
1028 | */ | ||
1029 | |||
1030 | iwl_update_stats(priv, false, fc, len); | ||
1031 | memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); | ||
1032 | |||
1033 | ieee80211_rx(priv->hw, skb); | ||
1034 | out: | ||
1035 | priv->alloc_rxb_page--; | ||
1036 | rxb->page = NULL; | ||
1037 | } | ||
1038 | |||
1039 | /* This is necessary only for a number of statistics, see the caller. */ | ||
1040 | static int iwl_is_network_packet(struct iwl_priv *priv, | ||
1041 | struct ieee80211_hdr *header) | ||
1042 | { | ||
1043 | /* Filter incoming packets to determine if they are targeted toward | ||
1044 | * this network, discarding packets coming from ourselves */ | ||
1045 | switch (priv->iw_mode) { | ||
1046 | case NL80211_IFTYPE_ADHOC: /* Header: Dest. | Source | BSSID */ | ||
1047 | /* packets to our IBSS update information */ | ||
1048 | return !compare_ether_addr(header->addr3, priv->bssid); | ||
1049 | case NL80211_IFTYPE_STATION: /* Header: Dest. | AP{BSSID} | Source */ | ||
1050 | /* packets to our IBSS update information */ | ||
1051 | return !compare_ether_addr(header->addr2, priv->bssid); | ||
1052 | default: | ||
1053 | return 1; | ||
1054 | } | ||
1055 | } | ||
1056 | |||
1057 | /* Called for REPLY_RX (legacy ABG frames), or | ||
1058 | * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */ | ||
1059 | void iwl_rx_reply_rx(struct iwl_priv *priv, | ||
1060 | struct iwl_rx_mem_buffer *rxb) | ||
1061 | { | ||
1062 | struct ieee80211_hdr *header; | ||
1063 | struct ieee80211_rx_status rx_status; | ||
1064 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
1065 | struct iwl_rx_phy_res *phy_res; | ||
1066 | __le32 rx_pkt_status; | ||
1067 | struct iwl4965_rx_mpdu_res_start *amsdu; | ||
1068 | u32 len; | ||
1069 | u32 ampdu_status; | ||
1070 | u32 rate_n_flags; | ||
1071 | |||
1072 | /** | ||
1073 | * REPLY_RX and REPLY_RX_MPDU_CMD are handled differently. | ||
1074 | * REPLY_RX: physical layer info is in this buffer | ||
1075 | * REPLY_RX_MPDU_CMD: physical layer info was sent in separate | ||
1076 | * command and cached in priv->last_phy_res | ||
1077 | * | ||
1078 | * Here we set up local variables depending on which command is | ||
1079 | * received. | ||
1080 | */ | ||
1081 | if (pkt->hdr.cmd == REPLY_RX) { | ||
1082 | phy_res = (struct iwl_rx_phy_res *)pkt->u.raw; | ||
1083 | header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*phy_res) | ||
1084 | + phy_res->cfg_phy_cnt); | ||
1085 | |||
1086 | len = le16_to_cpu(phy_res->byte_count); | ||
1087 | rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*phy_res) + | ||
1088 | phy_res->cfg_phy_cnt + len); | ||
1089 | ampdu_status = le32_to_cpu(rx_pkt_status); | ||
1090 | } else { | ||
1091 | if (!priv->last_phy_res[0]) { | ||
1092 | IWL_ERR(priv, "MPDU frame without cached PHY data\n"); | ||
1093 | return; | ||
1094 | } | ||
1095 | phy_res = (struct iwl_rx_phy_res *)&priv->last_phy_res[1]; | ||
1096 | amsdu = (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw; | ||
1097 | header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu)); | ||
1098 | len = le16_to_cpu(amsdu->byte_count); | ||
1099 | rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*amsdu) + len); | ||
1100 | ampdu_status = iwl_translate_rx_status(priv, | ||
1101 | le32_to_cpu(rx_pkt_status)); | ||
1102 | } | ||
1103 | |||
1104 | if ((unlikely(phy_res->cfg_phy_cnt > 20))) { | ||
1105 | IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n", | ||
1106 | phy_res->cfg_phy_cnt); | ||
1107 | return; | ||
1108 | } | ||
1109 | |||
1110 | if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) || | ||
1111 | !(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) { | ||
1112 | IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n", | ||
1113 | le32_to_cpu(rx_pkt_status)); | ||
1114 | return; | ||
1115 | } | ||
1116 | |||
1117 | /* This will be used in several places later */ | ||
1118 | rate_n_flags = le32_to_cpu(phy_res->rate_n_flags); | ||
1119 | |||
1120 | /* rx_status carries information about the packet to mac80211 */ | ||
1121 | rx_status.mactime = le64_to_cpu(phy_res->timestamp); | ||
1122 | rx_status.freq = | ||
1123 | ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel)); | ||
1124 | rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? | ||
1125 | IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; | ||
1126 | rx_status.rate_idx = | ||
1127 | iwl_hwrate_to_mac80211_idx(rate_n_flags, rx_status.band); | ||
1128 | rx_status.flag = 0; | ||
1129 | |||
1130 | /* TSF isn't reliable. In order to allow smooth user experience, | ||
1131 | * this W/A doesn't propagate it to the mac80211 */ | ||
1132 | /*rx_status.flag |= RX_FLAG_TSFT;*/ | ||
1133 | |||
1134 | priv->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp); | ||
1135 | |||
1136 | /* Find max signal strength (dBm) among 3 antenna/receiver chains */ | ||
1137 | rx_status.signal = iwl_calc_rssi(priv, phy_res); | ||
1138 | |||
1139 | /* Meaningful noise values are available only from beacon statistics, | ||
1140 | * which are gathered only when associated, and indicate noise | ||
1141 | * only for the associated network channel ... | ||
1142 | * Ignore these noise values while scanning (other channels) */ | ||
1143 | if (iwl_is_associated(priv) && | ||
1144 | !test_bit(STATUS_SCANNING, &priv->status)) { | ||
1145 | rx_status.noise = priv->last_rx_noise; | ||
1146 | } else { | ||
1147 | rx_status.noise = IWL_NOISE_MEAS_NOT_AVAILABLE; | ||
1148 | } | ||
1149 | |||
1150 | /* Reset beacon noise level if not associated. */ | ||
1151 | if (!iwl_is_associated(priv)) | ||
1152 | priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; | ||
1153 | |||
1154 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1155 | /* Set "1" to report good data frames in groups of 100 */ | ||
1156 | if (unlikely(iwl_get_debug_level(priv) & IWL_DL_RX)) | ||
1157 | iwl_dbg_report_frame(priv, phy_res, len, header, 1); | ||
1158 | #endif | ||
1159 | iwl_dbg_log_rx_data_frame(priv, len, header); | ||
1160 | IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, TSF %llu\n", | ||
1161 | rx_status.signal, rx_status.noise, | ||
1162 | (unsigned long long)rx_status.mactime); | ||
1163 | |||
1164 | /* | ||
1165 | * "antenna number" | ||
1166 | * | ||
1167 | * It seems that the antenna field in the phy flags value | ||
1168 | * is actually a bit field. This is undefined by radiotap, | ||
1169 | * it wants an actual antenna number but I always get "7" | ||
1170 | * for most legacy frames I receive indicating that the | ||
1171 | * same frame was received on all three RX chains. | ||
1172 | * | ||
1173 | * I think this field should be removed in favor of a | ||
1174 | * new 802.11n radiotap field "RX chains" that is defined | ||
1175 | * as a bitmask. | ||
1176 | */ | ||
1177 | rx_status.antenna = | ||
1178 | (le16_to_cpu(phy_res->phy_flags) & RX_RES_PHY_FLAGS_ANTENNA_MSK) | ||
1179 | >> RX_RES_PHY_FLAGS_ANTENNA_POS; | ||
1180 | |||
1181 | /* set the preamble flag if appropriate */ | ||
1182 | if (phy_res->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK) | ||
1183 | rx_status.flag |= RX_FLAG_SHORTPRE; | ||
1184 | |||
1185 | /* Set up the HT phy flags */ | ||
1186 | if (rate_n_flags & RATE_MCS_HT_MSK) | ||
1187 | rx_status.flag |= RX_FLAG_HT; | ||
1188 | if (rate_n_flags & RATE_MCS_HT40_MSK) | ||
1189 | rx_status.flag |= RX_FLAG_40MHZ; | ||
1190 | if (rate_n_flags & RATE_MCS_SGI_MSK) | ||
1191 | rx_status.flag |= RX_FLAG_SHORT_GI; | ||
1192 | |||
1193 | if (iwl_is_network_packet(priv, header)) { | ||
1194 | priv->last_rx_rssi = rx_status.signal; | ||
1195 | priv->last_beacon_time = priv->ucode_beacon_time; | ||
1196 | priv->last_tsf = le64_to_cpu(phy_res->timestamp); | ||
1197 | } | ||
1198 | |||
1199 | iwl_pass_packet_to_mac80211(priv, header, len, ampdu_status, | ||
1200 | rxb, &rx_status); | ||
1201 | } | ||
1202 | EXPORT_SYMBOL(iwl_rx_reply_rx); | ||
1203 | |||
1204 | /* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD). | ||
1205 | * This will be used later in iwl_rx_reply_rx() for REPLY_RX_MPDU_CMD. */ | ||
1206 | void iwl_rx_reply_rx_phy(struct iwl_priv *priv, | ||
1207 | struct iwl_rx_mem_buffer *rxb) | ||
1208 | { | ||
1209 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
1210 | priv->last_phy_res[0] = 1; | ||
1211 | memcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]), | ||
1212 | sizeof(struct iwl_rx_phy_res)); | ||
1213 | } | ||
1214 | EXPORT_SYMBOL(iwl_rx_reply_rx_phy); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index bd2f7c420563..d817c9c184a5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c | |||
@@ -453,7 +453,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, | |||
453 | added++; | 453 | added++; |
454 | } | 454 | } |
455 | 455 | ||
456 | IWL_DEBUG_SCAN(priv, "total channels to scan %d \n", added); | 456 | IWL_DEBUG_SCAN(priv, "total channels to scan %d\n", added); |
457 | return added; | 457 | return added; |
458 | } | 458 | } |
459 | 459 | ||
@@ -580,7 +580,6 @@ int iwl_internal_short_hw_scan(struct iwl_priv *priv) | |||
580 | out: | 580 | out: |
581 | return ret; | 581 | return ret; |
582 | } | 582 | } |
583 | EXPORT_SYMBOL(iwl_internal_short_hw_scan); | ||
584 | 583 | ||
585 | #define IWL_SCAN_CHECK_WATCHDOG (7 * HZ) | 584 | #define IWL_SCAN_CHECK_WATCHDOG (7 * HZ) |
586 | 585 | ||
@@ -665,7 +664,6 @@ static void iwl_bg_request_scan(struct work_struct *data) | |||
665 | }; | 664 | }; |
666 | struct iwl_scan_cmd *scan; | 665 | struct iwl_scan_cmd *scan; |
667 | struct ieee80211_conf *conf = NULL; | 666 | struct ieee80211_conf *conf = NULL; |
668 | int ret = 0; | ||
669 | u32 rate_flags = 0; | 667 | u32 rate_flags = 0; |
670 | u16 cmd_len; | 668 | u16 cmd_len; |
671 | u16 rx_chain = 0; | 669 | u16 rx_chain = 0; |
@@ -698,7 +696,6 @@ static void iwl_bg_request_scan(struct work_struct *data) | |||
698 | if (test_bit(STATUS_SCAN_HW, &priv->status)) { | 696 | if (test_bit(STATUS_SCAN_HW, &priv->status)) { |
699 | IWL_DEBUG_INFO(priv, "Multiple concurrent scan requests in parallel. " | 697 | IWL_DEBUG_INFO(priv, "Multiple concurrent scan requests in parallel. " |
700 | "Ignoring second request.\n"); | 698 | "Ignoring second request.\n"); |
701 | ret = -EIO; | ||
702 | goto done; | 699 | goto done; |
703 | } | 700 | } |
704 | 701 | ||
@@ -731,7 +728,8 @@ static void iwl_bg_request_scan(struct work_struct *data) | |||
731 | priv->scan = kmalloc(sizeof(struct iwl_scan_cmd) + | 728 | priv->scan = kmalloc(sizeof(struct iwl_scan_cmd) + |
732 | IWL_MAX_SCAN_SIZE, GFP_KERNEL); | 729 | IWL_MAX_SCAN_SIZE, GFP_KERNEL); |
733 | if (!priv->scan) { | 730 | if (!priv->scan) { |
734 | ret = -ENOMEM; | 731 | IWL_DEBUG_SCAN(priv, |
732 | "fail to allocate memory for scan\n"); | ||
735 | goto done; | 733 | goto done; |
736 | } | 734 | } |
737 | } | 735 | } |
@@ -815,10 +813,11 @@ static void iwl_bg_request_scan(struct work_struct *data) | |||
815 | */ | 813 | */ |
816 | scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0; | 814 | scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0; |
817 | 815 | ||
818 | /* Force use of chains B and C (0x6) for scan Rx for 4965 | 816 | /* Force use of chains B and C (0x6) for scan Rx |
819 | * Avoid A (0x1) because of its off-channel reception on A-band. | 817 | * Avoid A (0x1) for the device has off-channel reception |
818 | * on A-band. | ||
820 | */ | 819 | */ |
821 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) | 820 | if (priv->cfg->off_channel_workaround) |
822 | rx_ant = ANT_BC; | 821 | rx_ant = ANT_BC; |
823 | } else { | 822 | } else { |
824 | IWL_WARN(priv, "Invalid scan band count\n"); | 823 | IWL_WARN(priv, "Invalid scan band count\n"); |
@@ -892,8 +891,7 @@ static void iwl_bg_request_scan(struct work_struct *data) | |||
892 | scan->len = cpu_to_le16(cmd.len); | 891 | scan->len = cpu_to_le16(cmd.len); |
893 | 892 | ||
894 | set_bit(STATUS_SCAN_HW, &priv->status); | 893 | set_bit(STATUS_SCAN_HW, &priv->status); |
895 | ret = iwl_send_cmd_sync(priv, &cmd); | 894 | if (iwl_send_cmd_sync(priv, &cmd)) |
896 | if (ret) | ||
897 | goto done; | 895 | goto done; |
898 | 896 | ||
899 | queue_delayed_work(priv->workqueue, &priv->scan_check, | 897 | queue_delayed_work(priv->workqueue, &priv->scan_check, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 4a6686fa6b36..e34ac0355c75 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c | |||
@@ -29,14 +29,12 @@ | |||
29 | 29 | ||
30 | #include <net/mac80211.h> | 30 | #include <net/mac80211.h> |
31 | #include <linux/etherdevice.h> | 31 | #include <linux/etherdevice.h> |
32 | #include <linux/sched.h> | ||
32 | 33 | ||
33 | #include "iwl-dev.h" | 34 | #include "iwl-dev.h" |
34 | #include "iwl-core.h" | 35 | #include "iwl-core.h" |
35 | #include "iwl-sta.h" | 36 | #include "iwl-sta.h" |
36 | 37 | ||
37 | #define IWL_STA_DRIVER_ACTIVE BIT(0) /* driver entry is active */ | ||
38 | #define IWL_STA_UCODE_ACTIVE BIT(1) /* ucode entry is active */ | ||
39 | |||
40 | u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr) | 38 | u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr) |
41 | { | 39 | { |
42 | int i; | 40 | int i; |
@@ -64,6 +62,19 @@ u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr) | |||
64 | addr, priv->num_stations); | 62 | addr, priv->num_stations); |
65 | 63 | ||
66 | out: | 64 | out: |
65 | /* | ||
66 | * It may be possible that more commands interacting with stations | ||
67 | * arrive before we completed processing the adding of | ||
68 | * station | ||
69 | */ | ||
70 | if (ret != IWL_INVALID_STATION && | ||
71 | (!(priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) || | ||
72 | ((priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) && | ||
73 | (priv->stations[ret].used & IWL_STA_UCODE_INPROGRESS)))) { | ||
74 | IWL_ERR(priv, "Requested station info for sta %d before ready.\n", | ||
75 | ret); | ||
76 | ret = IWL_INVALID_STATION; | ||
77 | } | ||
67 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 78 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
68 | return ret; | 79 | return ret; |
69 | } | 80 | } |
@@ -132,7 +143,7 @@ static void iwl_process_add_sta_resp(struct iwl_priv *priv, | |||
132 | sta_id); | 143 | sta_id); |
133 | break; | 144 | break; |
134 | case ADD_STA_MODIFY_NON_EXIST_STA: | 145 | case ADD_STA_MODIFY_NON_EXIST_STA: |
135 | IWL_ERR(priv, "Attempting to modify non-existing station %d \n", | 146 | IWL_ERR(priv, "Attempting to modify non-existing station %d\n", |
136 | sta_id); | 147 | sta_id); |
137 | break; | 148 | break; |
138 | default: | 149 | default: |
@@ -158,13 +169,6 @@ static void iwl_process_add_sta_resp(struct iwl_priv *priv, | |||
158 | priv->stations[sta_id].sta.mode == | 169 | priv->stations[sta_id].sta.mode == |
159 | STA_CONTROL_MODIFY_MSK ? "Modified" : "Added", | 170 | STA_CONTROL_MODIFY_MSK ? "Modified" : "Added", |
160 | addsta->sta.addr); | 171 | addsta->sta.addr); |
161 | |||
162 | /* | ||
163 | * Determine if we wanted to modify or add a station, | ||
164 | * if adding a station succeeded we have some more initialization | ||
165 | * to do when using station notification. TODO | ||
166 | */ | ||
167 | |||
168 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 172 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
169 | } | 173 | } |
170 | 174 | ||
@@ -190,6 +194,10 @@ int iwl_send_add_sta(struct iwl_priv *priv, | |||
190 | .flags = flags, | 194 | .flags = flags, |
191 | .data = data, | 195 | .data = data, |
192 | }; | 196 | }; |
197 | u8 sta_id = sta->sta.sta_id; | ||
198 | |||
199 | IWL_DEBUG_INFO(priv, "Adding sta %u (%pM) %ssynchronously\n", | ||
200 | sta_id, sta->sta.addr, flags & CMD_ASYNC ? "a" : ""); | ||
193 | 201 | ||
194 | if (flags & CMD_ASYNC) | 202 | if (flags & CMD_ASYNC) |
195 | cmd.callback = iwl_add_sta_callback; | 203 | cmd.callback = iwl_add_sta_callback; |
@@ -263,18 +271,19 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, | |||
263 | } | 271 | } |
264 | 272 | ||
265 | /** | 273 | /** |
266 | * iwl_add_station - Add station to tables in driver and device | 274 | * iwl_prep_station - Prepare station information for addition |
275 | * | ||
276 | * should be called with sta_lock held | ||
267 | */ | 277 | */ |
268 | u8 iwl_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap, u8 flags, | 278 | static u8 iwl_prep_station(struct iwl_priv *priv, const u8 *addr, |
269 | struct ieee80211_sta_ht_cap *ht_info) | 279 | bool is_ap, |
280 | struct ieee80211_sta_ht_cap *ht_info) | ||
270 | { | 281 | { |
271 | struct iwl_station_entry *station; | 282 | struct iwl_station_entry *station; |
272 | unsigned long flags_spin; | ||
273 | int i; | 283 | int i; |
274 | int sta_id = IWL_INVALID_STATION; | 284 | u8 sta_id = IWL_INVALID_STATION; |
275 | u16 rate; | 285 | u16 rate; |
276 | 286 | ||
277 | spin_lock_irqsave(&priv->sta_lock, flags_spin); | ||
278 | if (is_ap) | 287 | if (is_ap) |
279 | sta_id = IWL_AP_ID; | 288 | sta_id = IWL_AP_ID; |
280 | else if (is_broadcast_ether_addr(addr)) | 289 | else if (is_broadcast_ether_addr(addr)) |
@@ -292,20 +301,32 @@ u8 iwl_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap, u8 flags, | |||
292 | sta_id = i; | 301 | sta_id = i; |
293 | } | 302 | } |
294 | 303 | ||
295 | /* These two conditions have the same outcome, but keep them separate | 304 | /* |
296 | since they have different meanings */ | 305 | * These two conditions have the same outcome, but keep them |
297 | if (unlikely(sta_id == IWL_INVALID_STATION)) { | 306 | * separate |
298 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | 307 | */ |
308 | if (unlikely(sta_id == IWL_INVALID_STATION)) | ||
309 | return sta_id; | ||
310 | |||
311 | /* | ||
312 | * uCode is not able to deal with multiple requests to add a | ||
313 | * station. Keep track if one is in progress so that we do not send | ||
314 | * another. | ||
315 | */ | ||
316 | if (priv->stations[sta_id].used & IWL_STA_UCODE_INPROGRESS) { | ||
317 | IWL_DEBUG_INFO(priv, "STA %d already in process of being added.\n", | ||
318 | sta_id); | ||
299 | return sta_id; | 319 | return sta_id; |
300 | } | 320 | } |
301 | 321 | ||
302 | if (priv->stations[sta_id].used && | 322 | if ((priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE) && |
323 | (priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE) && | ||
303 | !compare_ether_addr(priv->stations[sta_id].sta.sta.addr, addr)) { | 324 | !compare_ether_addr(priv->stations[sta_id].sta.sta.addr, addr)) { |
304 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | 325 | IWL_DEBUG_ASSOC(priv, "STA %d (%pM) already added, not adding again.\n", |
326 | sta_id, addr); | ||
305 | return sta_id; | 327 | return sta_id; |
306 | } | 328 | } |
307 | 329 | ||
308 | |||
309 | station = &priv->stations[sta_id]; | 330 | station = &priv->stations[sta_id]; |
310 | station->used = IWL_STA_DRIVER_ACTIVE; | 331 | station->used = IWL_STA_DRIVER_ACTIVE; |
311 | IWL_DEBUG_ASSOC(priv, "Add STA to driver ID %d: %pM\n", | 332 | IWL_DEBUG_ASSOC(priv, "Add STA to driver ID %d: %pM\n", |
@@ -330,86 +351,185 @@ u8 iwl_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap, u8 flags, | |||
330 | /* Turn on both antennas for the station... */ | 351 | /* Turn on both antennas for the station... */ |
331 | station->sta.rate_n_flags = cpu_to_le16(rate | RATE_MCS_ANT_AB_MSK); | 352 | station->sta.rate_n_flags = cpu_to_le16(rate | RATE_MCS_ANT_AB_MSK); |
332 | 353 | ||
354 | return sta_id; | ||
355 | |||
356 | } | ||
357 | |||
358 | #define STA_WAIT_TIMEOUT (HZ/2) | ||
359 | |||
360 | /** | ||
361 | * iwl_add_station_common - | ||
362 | */ | ||
363 | int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr, | ||
364 | bool is_ap, | ||
365 | struct ieee80211_sta_ht_cap *ht_info, | ||
366 | u8 *sta_id_r) | ||
367 | { | ||
368 | struct iwl_station_entry *station; | ||
369 | unsigned long flags_spin; | ||
370 | int ret = 0; | ||
371 | u8 sta_id; | ||
372 | |||
373 | *sta_id_r = 0; | ||
374 | spin_lock_irqsave(&priv->sta_lock, flags_spin); | ||
375 | sta_id = iwl_prep_station(priv, addr, is_ap, ht_info); | ||
376 | if (sta_id == IWL_INVALID_STATION) { | ||
377 | IWL_ERR(priv, "Unable to prepare station %pM for addition\n", | ||
378 | addr); | ||
379 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | ||
380 | return -EINVAL; | ||
381 | } | ||
382 | |||
383 | /* | ||
384 | * uCode is not able to deal with multiple requests to add a | ||
385 | * station. Keep track if one is in progress so that we do not send | ||
386 | * another. | ||
387 | */ | ||
388 | if (priv->stations[sta_id].used & IWL_STA_UCODE_INPROGRESS) { | ||
389 | IWL_DEBUG_INFO(priv, "STA %d already in process of being added.\n", | ||
390 | sta_id); | ||
391 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | ||
392 | return -EEXIST; | ||
393 | } | ||
394 | |||
395 | if ((priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE) && | ||
396 | (priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) { | ||
397 | IWL_DEBUG_ASSOC(priv, "STA %d (%pM) already added, not adding again.\n", | ||
398 | sta_id, addr); | ||
399 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | ||
400 | return -EEXIST; | ||
401 | } | ||
402 | |||
403 | priv->stations[sta_id].used |= IWL_STA_UCODE_INPROGRESS; | ||
404 | station = &priv->stations[sta_id]; | ||
333 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | 405 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); |
334 | 406 | ||
335 | /* Add station to device's station table */ | 407 | /* Add station to device's station table */ |
336 | iwl_send_add_sta(priv, &station->sta, flags); | 408 | ret = iwl_send_add_sta(priv, &station->sta, CMD_SYNC); |
337 | return sta_id; | 409 | if (ret) { |
338 | 410 | IWL_ERR(priv, "Adding station %pM failed.\n", station->sta.sta.addr); | |
411 | spin_lock_irqsave(&priv->sta_lock, flags_spin); | ||
412 | priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE; | ||
413 | priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; | ||
414 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | ||
415 | } | ||
416 | *sta_id_r = sta_id; | ||
417 | return ret; | ||
339 | } | 418 | } |
340 | EXPORT_SYMBOL(iwl_add_station); | 419 | EXPORT_SYMBOL(iwl_add_station_common); |
341 | 420 | ||
342 | static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, const u8 *addr) | 421 | static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, bool is_ap) |
343 | { | 422 | { |
344 | unsigned long flags; | 423 | int i, r; |
345 | u8 sta_id = iwl_find_station(priv, addr); | 424 | struct iwl_link_quality_cmd link_cmd = { |
425 | .reserved1 = 0, | ||
426 | }; | ||
427 | u32 rate_flags; | ||
346 | 428 | ||
347 | BUG_ON(sta_id == IWL_INVALID_STATION); | 429 | /* Set up the rate scaling to start at selected rate, fall back |
430 | * all the way down to 1M in IEEE order, and then spin on 1M */ | ||
431 | if (is_ap) | ||
432 | r = IWL_RATE_54M_INDEX; | ||
433 | else if (priv->band == IEEE80211_BAND_5GHZ) | ||
434 | r = IWL_RATE_6M_INDEX; | ||
435 | else | ||
436 | r = IWL_RATE_1M_INDEX; | ||
348 | 437 | ||
349 | IWL_DEBUG_ASSOC(priv, "Removed STA from Ucode: %pM\n", addr); | 438 | for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) { |
439 | rate_flags = 0; | ||
440 | if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE) | ||
441 | rate_flags |= RATE_MCS_CCK_MSK; | ||
350 | 442 | ||
351 | spin_lock_irqsave(&priv->sta_lock, flags); | 443 | rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) << |
444 | RATE_MCS_ANT_POS; | ||
352 | 445 | ||
353 | /* Ucode must be active and driver must be non active */ | 446 | link_cmd.rs_table[i].rate_n_flags = |
354 | if (priv->stations[sta_id].used != IWL_STA_UCODE_ACTIVE) | 447 | iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags); |
355 | IWL_ERR(priv, "removed non active STA %d\n", sta_id); | 448 | r = iwl_get_prev_ieee_rate(r); |
449 | } | ||
356 | 450 | ||
357 | priv->stations[sta_id].used &= ~IWL_STA_UCODE_ACTIVE; | 451 | link_cmd.general_params.single_stream_ant_msk = |
452 | first_antenna(priv->hw_params.valid_tx_ant); | ||
453 | link_cmd.general_params.dual_stream_ant_msk = 3; | ||
454 | link_cmd.agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; | ||
455 | link_cmd.agg_params.agg_time_limit = | ||
456 | cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); | ||
358 | 457 | ||
359 | memset(&priv->stations[sta_id], 0, sizeof(struct iwl_station_entry)); | 458 | /* Update the rate scaling for control frame Tx to AP */ |
360 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 459 | link_cmd.sta_id = is_ap ? IWL_AP_ID : priv->hw_params.bcast_sta_id; |
460 | |||
461 | iwl_send_cmd_pdu(priv, REPLY_TX_LINK_QUALITY_CMD, | ||
462 | sizeof(link_cmd), &link_cmd); | ||
361 | } | 463 | } |
362 | 464 | ||
363 | static void iwl_remove_sta_callback(struct iwl_priv *priv, | 465 | /* |
364 | struct iwl_device_cmd *cmd, | 466 | * iwl_add_local_stations - Add stations not requested by mac80211 |
365 | struct iwl_rx_packet *pkt) | 467 | * |
468 | * This will be either the broadcast station or the bssid station needed by | ||
469 | * ad-hoc. | ||
470 | * | ||
471 | * Function sleeps. | ||
472 | */ | ||
473 | int iwl_add_local_station(struct iwl_priv *priv, const u8 *addr, bool init_rs) | ||
366 | { | 474 | { |
367 | struct iwl_rem_sta_cmd *rm_sta = | 475 | int ret; |
368 | (struct iwl_rem_sta_cmd *)cmd->cmd.payload; | 476 | u8 sta_id; |
369 | const u8 *addr = rm_sta->addr; | ||
370 | 477 | ||
371 | if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { | 478 | ret = iwl_add_station_common(priv, addr, 0, NULL, &sta_id); |
372 | IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n", | 479 | if (ret) { |
373 | pkt->hdr.flags); | 480 | IWL_ERR(priv, "Unable to add station %pM\n", addr); |
374 | return; | 481 | return ret; |
375 | } | 482 | } |
376 | 483 | ||
377 | switch (pkt->u.rem_sta.status) { | 484 | if (init_rs) |
378 | case REM_STA_SUCCESS_MSK: | 485 | /* Set up default rate scaling table in device's station table */ |
379 | iwl_sta_ucode_deactivate(priv, addr); | 486 | iwl_sta_init_lq(priv, addr, false); |
380 | break; | 487 | return 0; |
381 | default: | 488 | } |
382 | IWL_ERR(priv, "REPLY_REMOVE_STA failed\n"); | 489 | EXPORT_SYMBOL(iwl_add_local_station); |
383 | break; | 490 | |
384 | } | 491 | /** |
492 | * iwl_sta_ucode_deactivate - deactivate ucode status for a station | ||
493 | * | ||
494 | * priv->sta_lock must be held | ||
495 | */ | ||
496 | static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, u8 sta_id) | ||
497 | { | ||
498 | /* Ucode must be active and driver must be non active */ | ||
499 | if (priv->stations[sta_id].used != IWL_STA_UCODE_ACTIVE) | ||
500 | IWL_ERR(priv, "removed non active STA %u\n", sta_id); | ||
501 | |||
502 | priv->stations[sta_id].used &= ~IWL_STA_UCODE_ACTIVE; | ||
503 | |||
504 | memset(&priv->stations[sta_id], 0, sizeof(struct iwl_station_entry)); | ||
505 | IWL_DEBUG_ASSOC(priv, "Removed STA %u\n", sta_id); | ||
385 | } | 506 | } |
386 | 507 | ||
387 | static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr, | 508 | static int iwl_send_remove_station(struct iwl_priv *priv, |
388 | u8 flags) | 509 | struct iwl_station_entry *station) |
389 | { | 510 | { |
390 | struct iwl_rx_packet *pkt; | 511 | struct iwl_rx_packet *pkt; |
391 | int ret; | 512 | int ret; |
392 | 513 | ||
514 | unsigned long flags_spin; | ||
393 | struct iwl_rem_sta_cmd rm_sta_cmd; | 515 | struct iwl_rem_sta_cmd rm_sta_cmd; |
394 | 516 | ||
395 | struct iwl_host_cmd cmd = { | 517 | struct iwl_host_cmd cmd = { |
396 | .id = REPLY_REMOVE_STA, | 518 | .id = REPLY_REMOVE_STA, |
397 | .len = sizeof(struct iwl_rem_sta_cmd), | 519 | .len = sizeof(struct iwl_rem_sta_cmd), |
398 | .flags = flags, | 520 | .flags = CMD_SYNC, |
399 | .data = &rm_sta_cmd, | 521 | .data = &rm_sta_cmd, |
400 | }; | 522 | }; |
401 | 523 | ||
402 | memset(&rm_sta_cmd, 0, sizeof(rm_sta_cmd)); | 524 | memset(&rm_sta_cmd, 0, sizeof(rm_sta_cmd)); |
403 | rm_sta_cmd.num_sta = 1; | 525 | rm_sta_cmd.num_sta = 1; |
404 | memcpy(&rm_sta_cmd.addr, addr , ETH_ALEN); | 526 | memcpy(&rm_sta_cmd.addr, &station->sta.sta.addr , ETH_ALEN); |
527 | |||
528 | cmd.flags |= CMD_WANT_SKB; | ||
405 | 529 | ||
406 | if (flags & CMD_ASYNC) | ||
407 | cmd.callback = iwl_remove_sta_callback; | ||
408 | else | ||
409 | cmd.flags |= CMD_WANT_SKB; | ||
410 | ret = iwl_send_cmd(priv, &cmd); | 530 | ret = iwl_send_cmd(priv, &cmd); |
411 | 531 | ||
412 | if (ret || (flags & CMD_ASYNC)) | 532 | if (ret) |
413 | return ret; | 533 | return ret; |
414 | 534 | ||
415 | pkt = (struct iwl_rx_packet *)cmd.reply_page; | 535 | pkt = (struct iwl_rx_packet *)cmd.reply_page; |
@@ -422,7 +542,9 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr, | |||
422 | if (!ret) { | 542 | if (!ret) { |
423 | switch (pkt->u.rem_sta.status) { | 543 | switch (pkt->u.rem_sta.status) { |
424 | case REM_STA_SUCCESS_MSK: | 544 | case REM_STA_SUCCESS_MSK: |
425 | iwl_sta_ucode_deactivate(priv, addr); | 545 | spin_lock_irqsave(&priv->sta_lock, flags_spin); |
546 | iwl_sta_ucode_deactivate(priv, station->sta.sta.sta_id); | ||
547 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | ||
426 | IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n"); | 548 | IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n"); |
427 | break; | 549 | break; |
428 | default: | 550 | default: |
@@ -439,23 +561,35 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr, | |||
439 | /** | 561 | /** |
440 | * iwl_remove_station - Remove driver's knowledge of station. | 562 | * iwl_remove_station - Remove driver's knowledge of station. |
441 | */ | 563 | */ |
442 | int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, bool is_ap) | 564 | static int iwl_remove_station(struct iwl_priv *priv, struct ieee80211_sta *sta) |
443 | { | 565 | { |
444 | int sta_id = IWL_INVALID_STATION; | 566 | int sta_id = IWL_INVALID_STATION; |
445 | int i, ret = -EINVAL; | 567 | int i, ret = -EINVAL; |
446 | unsigned long flags; | 568 | unsigned long flags; |
569 | bool is_ap = priv->iw_mode == NL80211_IFTYPE_STATION; | ||
570 | struct iwl_station_entry *station; | ||
571 | |||
572 | if (!iwl_is_ready(priv)) { | ||
573 | IWL_DEBUG_INFO(priv, | ||
574 | "Unable to remove station %pM, device not ready.\n", | ||
575 | sta->addr); | ||
576 | /* | ||
577 | * It is typical for stations to be removed when we are | ||
578 | * going down. Return success since device will be down | ||
579 | * soon anyway | ||
580 | */ | ||
581 | return 0; | ||
582 | } | ||
447 | 583 | ||
448 | spin_lock_irqsave(&priv->sta_lock, flags); | 584 | spin_lock_irqsave(&priv->sta_lock, flags); |
449 | 585 | ||
450 | if (is_ap) | 586 | if (is_ap) |
451 | sta_id = IWL_AP_ID; | 587 | sta_id = IWL_AP_ID; |
452 | else if (is_broadcast_ether_addr(addr)) | ||
453 | sta_id = priv->hw_params.bcast_sta_id; | ||
454 | else | 588 | else |
455 | for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) | 589 | for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) |
456 | if (priv->stations[i].used && | 590 | if (priv->stations[i].used && |
457 | !compare_ether_addr(priv->stations[i].sta.sta.addr, | 591 | !compare_ether_addr(priv->stations[i].sta.sta.addr, |
458 | addr)) { | 592 | sta->addr)) { |
459 | sta_id = i; | 593 | sta_id = i; |
460 | break; | 594 | break; |
461 | } | 595 | } |
@@ -464,17 +598,17 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, bool is_ap) | |||
464 | goto out; | 598 | goto out; |
465 | 599 | ||
466 | IWL_DEBUG_ASSOC(priv, "Removing STA from driver:%d %pM\n", | 600 | IWL_DEBUG_ASSOC(priv, "Removing STA from driver:%d %pM\n", |
467 | sta_id, addr); | 601 | sta_id, sta->addr); |
468 | 602 | ||
469 | if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) { | 603 | if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) { |
470 | IWL_ERR(priv, "Removing %pM but non DRIVER active\n", | 604 | IWL_DEBUG_INFO(priv, "Removing %pM but non DRIVER active\n", |
471 | addr); | 605 | sta->addr); |
472 | goto out; | 606 | goto out; |
473 | } | 607 | } |
474 | 608 | ||
475 | if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) { | 609 | if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) { |
476 | IWL_ERR(priv, "Removing %pM but non UCODE active\n", | 610 | IWL_DEBUG_INFO(priv, "Removing %pM but non UCODE active\n", |
477 | addr); | 611 | sta->addr); |
478 | goto out; | 612 | goto out; |
479 | } | 613 | } |
480 | 614 | ||
@@ -485,9 +619,10 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, bool is_ap) | |||
485 | 619 | ||
486 | BUG_ON(priv->num_stations < 0); | 620 | BUG_ON(priv->num_stations < 0); |
487 | 621 | ||
622 | station = &priv->stations[sta_id]; | ||
488 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 623 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
489 | 624 | ||
490 | ret = iwl_send_remove_station(priv, addr, CMD_ASYNC); | 625 | ret = iwl_send_remove_station(priv, station); |
491 | return ret; | 626 | return ret; |
492 | out: | 627 | out: |
493 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 628 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
@@ -495,37 +630,122 @@ out: | |||
495 | } | 630 | } |
496 | 631 | ||
497 | /** | 632 | /** |
498 | * iwl_clear_stations_table - Clear the driver's station table | 633 | * iwl_clear_ucode_stations() - clear entire station table driver and/or ucode |
499 | * | 634 | * @priv: |
500 | * NOTE: This does not clear or otherwise alter the device's station table. | 635 | * @force: If set then the uCode station table needs to be cleared here. If |
636 | * not set then the uCode station table has already been cleared, | ||
637 | * for example after sending it a RXON command without ASSOC bit | ||
638 | * set, and we just need to change driver state here. | ||
501 | */ | 639 | */ |
502 | void iwl_clear_stations_table(struct iwl_priv *priv) | 640 | void iwl_clear_ucode_stations(struct iwl_priv *priv, bool force) |
503 | { | 641 | { |
504 | unsigned long flags; | ||
505 | int i; | 642 | int i; |
643 | unsigned long flags_spin; | ||
644 | bool cleared = false; | ||
645 | |||
646 | IWL_DEBUG_INFO(priv, "Clearing ucode stations in driver%s\n", | ||
647 | force ? " and ucode" : ""); | ||
648 | |||
649 | if (force) { | ||
650 | if (!iwl_is_ready(priv)) { | ||
651 | /* | ||
652 | * If device is not ready at this point the station | ||
653 | * table is likely already empty (uCode not ready | ||
654 | * to receive station requests) or will soon be | ||
655 | * due to interface going down. | ||
656 | */ | ||
657 | IWL_DEBUG_INFO(priv, "Unable to remove stations from device - device not ready\n"); | ||
658 | } else { | ||
659 | iwl_send_cmd_pdu_async(priv, REPLY_REMOVE_ALL_STA, 0, NULL, NULL); | ||
660 | } | ||
661 | } | ||
506 | 662 | ||
507 | spin_lock_irqsave(&priv->sta_lock, flags); | 663 | spin_lock_irqsave(&priv->sta_lock, flags_spin); |
664 | if (force) { | ||
665 | IWL_DEBUG_INFO(priv, "Clearing all station information in driver\n"); | ||
666 | priv->num_stations = 0; | ||
667 | memset(priv->stations, 0, sizeof(priv->stations)); | ||
668 | } else { | ||
669 | for (i = 0; i < priv->hw_params.max_stations; i++) { | ||
670 | if (priv->stations[i].used & IWL_STA_UCODE_ACTIVE) { | ||
671 | IWL_DEBUG_INFO(priv, "Clearing ucode active for station %d\n", i); | ||
672 | priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE; | ||
673 | cleared = true; | ||
674 | } | ||
675 | } | ||
676 | } | ||
677 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | ||
508 | 678 | ||
509 | if (iwl_is_alive(priv) && | 679 | if (!cleared) |
510 | !test_bit(STATUS_EXIT_PENDING, &priv->status) && | 680 | IWL_DEBUG_INFO(priv, "No active stations found to be cleared\n"); |
511 | iwl_send_cmd_pdu_async(priv, REPLY_REMOVE_ALL_STA, 0, NULL, NULL)) | 681 | } |
512 | IWL_ERR(priv, "Couldn't clear the station table\n"); | 682 | EXPORT_SYMBOL(iwl_clear_ucode_stations); |
683 | |||
684 | /** | ||
685 | * iwl_restore_stations() - Restore driver known stations to device | ||
686 | * | ||
687 | * All stations considered active by driver, but not present in ucode, is | ||
688 | * restored. | ||
689 | * | ||
690 | * Function sleeps. | ||
691 | */ | ||
692 | void iwl_restore_stations(struct iwl_priv *priv) | ||
693 | { | ||
694 | struct iwl_station_entry *station; | ||
695 | unsigned long flags_spin; | ||
696 | int i; | ||
697 | bool found = false; | ||
698 | int ret; | ||
513 | 699 | ||
514 | priv->num_stations = 0; | 700 | if (!iwl_is_ready(priv)) { |
515 | memset(priv->stations, 0, sizeof(priv->stations)); | 701 | IWL_DEBUG_INFO(priv, "Not ready yet, not restoring any stations.\n"); |
702 | return; | ||
703 | } | ||
516 | 704 | ||
517 | /* clean ucode key table bit map */ | 705 | IWL_DEBUG_ASSOC(priv, "Restoring all known stations ... start.\n"); |
518 | priv->ucode_key_table = 0; | 706 | spin_lock_irqsave(&priv->sta_lock, flags_spin); |
707 | for (i = 0; i < priv->hw_params.max_stations; i++) { | ||
708 | if ((priv->stations[i].used & IWL_STA_DRIVER_ACTIVE) && | ||
709 | !(priv->stations[i].used & IWL_STA_UCODE_ACTIVE)) { | ||
710 | IWL_DEBUG_ASSOC(priv, "Restoring sta %pM\n", | ||
711 | priv->stations[i].sta.sta.addr); | ||
712 | priv->stations[i].sta.mode = 0; | ||
713 | priv->stations[i].used |= IWL_STA_UCODE_INPROGRESS; | ||
714 | found = true; | ||
715 | } | ||
716 | } | ||
519 | 717 | ||
520 | /* keep track of static keys */ | 718 | for (i = 0; i < priv->hw_params.max_stations; i++) { |
521 | for (i = 0; i < WEP_KEYS_MAX ; i++) { | 719 | if ((priv->stations[i].used & IWL_STA_UCODE_INPROGRESS)) { |
522 | if (priv->wep_keys[i].key_size) | 720 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); |
523 | set_bit(i, &priv->ucode_key_table); | 721 | station = &priv->stations[i]; |
722 | ret = iwl_send_add_sta(priv, &priv->stations[i].sta, CMD_SYNC); | ||
723 | if (ret) { | ||
724 | IWL_ERR(priv, "Adding station %pM failed.\n", | ||
725 | station->sta.sta.addr); | ||
726 | spin_lock_irqsave(&priv->sta_lock, flags_spin); | ||
727 | priv->stations[i].used &= ~IWL_STA_DRIVER_ACTIVE; | ||
728 | priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS; | ||
729 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | ||
730 | } | ||
731 | /* | ||
732 | * Rate scaling has already been initialized, send | ||
733 | * current LQ command | ||
734 | */ | ||
735 | if (station->lq) | ||
736 | iwl_send_lq_cmd(priv, station->lq, CMD_SYNC, true); | ||
737 | spin_lock_irqsave(&priv->sta_lock, flags_spin); | ||
738 | priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS; | ||
739 | } | ||
524 | } | 740 | } |
525 | 741 | ||
526 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 742 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); |
743 | if (!found) | ||
744 | IWL_DEBUG_INFO(priv, "Restoring all known stations .... no stations to be restored.\n"); | ||
745 | else | ||
746 | IWL_DEBUG_INFO(priv, "Restoring all known stations .... complete.\n"); | ||
527 | } | 747 | } |
528 | EXPORT_SYMBOL(iwl_clear_stations_table); | 748 | EXPORT_SYMBOL(iwl_restore_stations); |
529 | 749 | ||
530 | int iwl_get_free_ucode_key_index(struct iwl_priv *priv) | 750 | int iwl_get_free_ucode_key_index(struct iwl_priv *priv) |
531 | { | 751 | { |
@@ -549,9 +769,11 @@ int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty) | |||
549 | struct iwl_host_cmd cmd = { | 769 | struct iwl_host_cmd cmd = { |
550 | .id = REPLY_WEPKEY, | 770 | .id = REPLY_WEPKEY, |
551 | .data = wep_cmd, | 771 | .data = wep_cmd, |
552 | .flags = CMD_ASYNC, | 772 | .flags = CMD_SYNC, |
553 | }; | 773 | }; |
554 | 774 | ||
775 | might_sleep(); | ||
776 | |||
555 | memset(wep_cmd, 0, cmd_size + | 777 | memset(wep_cmd, 0, cmd_size + |
556 | (sizeof(struct iwl_wep_key) * WEP_KEYS_MAX)); | 778 | (sizeof(struct iwl_wep_key) * WEP_KEYS_MAX)); |
557 | 779 | ||
@@ -587,9 +809,9 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv, | |||
587 | struct ieee80211_key_conf *keyconf) | 809 | struct ieee80211_key_conf *keyconf) |
588 | { | 810 | { |
589 | int ret; | 811 | int ret; |
590 | unsigned long flags; | ||
591 | 812 | ||
592 | spin_lock_irqsave(&priv->sta_lock, flags); | 813 | WARN_ON(!mutex_is_locked(&priv->mutex)); |
814 | |||
593 | IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n", | 815 | IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n", |
594 | keyconf->keyidx); | 816 | keyconf->keyidx); |
595 | 817 | ||
@@ -601,13 +823,12 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv, | |||
601 | memset(&priv->wep_keys[keyconf->keyidx], 0, sizeof(priv->wep_keys[0])); | 823 | memset(&priv->wep_keys[keyconf->keyidx], 0, sizeof(priv->wep_keys[0])); |
602 | if (iwl_is_rfkill(priv)) { | 824 | if (iwl_is_rfkill(priv)) { |
603 | IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n"); | 825 | IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n"); |
604 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 826 | /* but keys in device are clear anyway so return success */ |
605 | return 0; | 827 | return 0; |
606 | } | 828 | } |
607 | ret = iwl_send_static_wepkey_cmd(priv, 1); | 829 | ret = iwl_send_static_wepkey_cmd(priv, 1); |
608 | IWL_DEBUG_WEP(priv, "Remove default WEP key: idx=%d ret=%d\n", | 830 | IWL_DEBUG_WEP(priv, "Remove default WEP key: idx=%d ret=%d\n", |
609 | keyconf->keyidx, ret); | 831 | keyconf->keyidx, ret); |
610 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
611 | 832 | ||
612 | return ret; | 833 | return ret; |
613 | } | 834 | } |
@@ -617,7 +838,8 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, | |||
617 | struct ieee80211_key_conf *keyconf) | 838 | struct ieee80211_key_conf *keyconf) |
618 | { | 839 | { |
619 | int ret; | 840 | int ret; |
620 | unsigned long flags; | 841 | |
842 | WARN_ON(!mutex_is_locked(&priv->mutex)); | ||
621 | 843 | ||
622 | if (keyconf->keylen != WEP_KEY_LEN_128 && | 844 | if (keyconf->keylen != WEP_KEY_LEN_128 && |
623 | keyconf->keylen != WEP_KEY_LEN_64) { | 845 | keyconf->keylen != WEP_KEY_LEN_64) { |
@@ -629,12 +851,11 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, | |||
629 | keyconf->hw_key_idx = HW_KEY_DEFAULT; | 851 | keyconf->hw_key_idx = HW_KEY_DEFAULT; |
630 | priv->stations[IWL_AP_ID].keyinfo.alg = ALG_WEP; | 852 | priv->stations[IWL_AP_ID].keyinfo.alg = ALG_WEP; |
631 | 853 | ||
632 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
633 | priv->default_wep_key++; | 854 | priv->default_wep_key++; |
634 | 855 | ||
635 | if (test_and_set_bit(keyconf->keyidx, &priv->ucode_key_table)) | 856 | if (test_and_set_bit(keyconf->keyidx, &priv->ucode_key_table)) |
636 | IWL_ERR(priv, "index %d already used in uCode key table.\n", | 857 | IWL_ERR(priv, "index %d already used in uCode key table.\n", |
637 | keyconf->keyidx); | 858 | keyconf->keyidx); |
638 | 859 | ||
639 | priv->wep_keys[keyconf->keyidx].key_size = keyconf->keylen; | 860 | priv->wep_keys[keyconf->keyidx].key_size = keyconf->keylen; |
640 | memcpy(&priv->wep_keys[keyconf->keyidx].key, &keyconf->key, | 861 | memcpy(&priv->wep_keys[keyconf->keyidx].key, &keyconf->key, |
@@ -643,7 +864,6 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, | |||
643 | ret = iwl_send_static_wepkey_cmd(priv, 0); | 864 | ret = iwl_send_static_wepkey_cmd(priv, 0); |
644 | IWL_DEBUG_WEP(priv, "Set default WEP key: len=%d idx=%d ret=%d\n", | 865 | IWL_DEBUG_WEP(priv, "Set default WEP key: len=%d idx=%d ret=%d\n", |
645 | keyconf->keylen, keyconf->keyidx, ret); | 866 | keyconf->keylen, keyconf->keyidx, ret); |
646 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
647 | 867 | ||
648 | return ret; | 868 | return ret; |
649 | } | 869 | } |
@@ -885,7 +1105,7 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, | |||
885 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | 1105 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; |
886 | 1106 | ||
887 | if (iwl_is_rfkill(priv)) { | 1107 | if (iwl_is_rfkill(priv)) { |
888 | IWL_DEBUG_WEP(priv, "Not sending REPLY_ADD_STA command because RFKILL enabled. \n"); | 1108 | IWL_DEBUG_WEP(priv, "Not sending REPLY_ADD_STA command because RFKILL enabled.\n"); |
889 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 1109 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
890 | return 0; | 1110 | return 0; |
891 | } | 1111 | } |
@@ -948,9 +1168,22 @@ static inline void iwl_dump_lq_cmd(struct iwl_priv *priv, | |||
948 | } | 1168 | } |
949 | #endif | 1169 | #endif |
950 | 1170 | ||
1171 | /** | ||
1172 | * iwl_send_lq_cmd() - Send link quality command | ||
1173 | * @init: This command is sent as part of station initialization right | ||
1174 | * after station has been added. | ||
1175 | * | ||
1176 | * The link quality command is sent as the last step of station creation. | ||
1177 | * This is the special case in which init is set and we call a callback in | ||
1178 | * this case to clear the state indicating that station creation is in | ||
1179 | * progress. | ||
1180 | */ | ||
951 | int iwl_send_lq_cmd(struct iwl_priv *priv, | 1181 | int iwl_send_lq_cmd(struct iwl_priv *priv, |
952 | struct iwl_link_quality_cmd *lq, u8 flags) | 1182 | struct iwl_link_quality_cmd *lq, u8 flags, bool init) |
953 | { | 1183 | { |
1184 | int ret = 0; | ||
1185 | unsigned long flags_spin; | ||
1186 | |||
954 | struct iwl_host_cmd cmd = { | 1187 | struct iwl_host_cmd cmd = { |
955 | .id = REPLY_TX_LINK_QUALITY_CMD, | 1188 | .id = REPLY_TX_LINK_QUALITY_CMD, |
956 | .len = sizeof(struct iwl_link_quality_cmd), | 1189 | .len = sizeof(struct iwl_link_quality_cmd), |
@@ -966,167 +1199,31 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, | |||
966 | lq->sta_id = IWL_AP_ID; | 1199 | lq->sta_id = IWL_AP_ID; |
967 | 1200 | ||
968 | iwl_dump_lq_cmd(priv, lq); | 1201 | iwl_dump_lq_cmd(priv, lq); |
1202 | BUG_ON(init && (cmd.flags & CMD_ASYNC)); | ||
969 | 1203 | ||
970 | if (iwl_is_associated(priv) && priv->assoc_station_added) | 1204 | iwl_dump_lq_cmd(priv, lq); |
971 | return iwl_send_cmd(priv, &cmd); | 1205 | ret = iwl_send_cmd(priv, &cmd); |
1206 | if (ret || (cmd.flags & CMD_ASYNC)) | ||
1207 | return ret; | ||
972 | 1208 | ||
1209 | if (init) { | ||
1210 | IWL_DEBUG_INFO(priv, "init LQ command complete, clearing sta addition status for sta %d\n", | ||
1211 | lq->sta_id); | ||
1212 | spin_lock_irqsave(&priv->sta_lock, flags_spin); | ||
1213 | priv->stations[lq->sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; | ||
1214 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | ||
1215 | } | ||
973 | return 0; | 1216 | return 0; |
974 | } | 1217 | } |
975 | EXPORT_SYMBOL(iwl_send_lq_cmd); | 1218 | EXPORT_SYMBOL(iwl_send_lq_cmd); |
976 | 1219 | ||
977 | /** | 1220 | /** |
978 | * iwl_sta_init_lq - Initialize a station's hardware rate table | ||
979 | * | ||
980 | * The uCode's station table contains a table of fallback rates | ||
981 | * for automatic fallback during transmission. | ||
982 | * | ||
983 | * NOTE: This sets up a default set of values. These will be replaced later | ||
984 | * if the driver's iwl-agn-rs rate scaling algorithm is used, instead of | ||
985 | * rc80211_simple. | ||
986 | * | ||
987 | * NOTE: Run REPLY_ADD_STA command to set up station table entry, before | ||
988 | * calling this function (which runs REPLY_TX_LINK_QUALITY_CMD, | ||
989 | * which requires station table entry to exist). | ||
990 | */ | ||
991 | static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, bool is_ap) | ||
992 | { | ||
993 | int i, r; | ||
994 | struct iwl_link_quality_cmd link_cmd = { | ||
995 | .reserved1 = 0, | ||
996 | }; | ||
997 | u32 rate_flags; | ||
998 | |||
999 | /* Set up the rate scaling to start at selected rate, fall back | ||
1000 | * all the way down to 1M in IEEE order, and then spin on 1M */ | ||
1001 | if (is_ap) | ||
1002 | r = IWL_RATE_54M_INDEX; | ||
1003 | else if (priv->band == IEEE80211_BAND_5GHZ) | ||
1004 | r = IWL_RATE_6M_INDEX; | ||
1005 | else | ||
1006 | r = IWL_RATE_1M_INDEX; | ||
1007 | |||
1008 | for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) { | ||
1009 | rate_flags = 0; | ||
1010 | if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE) | ||
1011 | rate_flags |= RATE_MCS_CCK_MSK; | ||
1012 | |||
1013 | rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) << | ||
1014 | RATE_MCS_ANT_POS; | ||
1015 | |||
1016 | link_cmd.rs_table[i].rate_n_flags = | ||
1017 | iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags); | ||
1018 | r = iwl_get_prev_ieee_rate(r); | ||
1019 | } | ||
1020 | |||
1021 | link_cmd.general_params.single_stream_ant_msk = | ||
1022 | first_antenna(priv->hw_params.valid_tx_ant); | ||
1023 | link_cmd.general_params.dual_stream_ant_msk = 3; | ||
1024 | link_cmd.agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; | ||
1025 | link_cmd.agg_params.agg_time_limit = | ||
1026 | cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); | ||
1027 | |||
1028 | /* Update the rate scaling for control frame Tx to AP */ | ||
1029 | link_cmd.sta_id = is_ap ? IWL_AP_ID : priv->hw_params.bcast_sta_id; | ||
1030 | |||
1031 | iwl_send_cmd_pdu_async(priv, REPLY_TX_LINK_QUALITY_CMD, | ||
1032 | sizeof(link_cmd), &link_cmd, NULL); | ||
1033 | } | ||
1034 | |||
1035 | /** | ||
1036 | * iwl_rxon_add_station - add station into station table. | ||
1037 | * | ||
1038 | * there is only one AP station with id= IWL_AP_ID | ||
1039 | * NOTE: mutex must be held before calling this function | ||
1040 | */ | ||
1041 | int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap) | ||
1042 | { | ||
1043 | struct ieee80211_sta *sta; | ||
1044 | struct ieee80211_sta_ht_cap ht_config; | ||
1045 | struct ieee80211_sta_ht_cap *cur_ht_config = NULL; | ||
1046 | u8 sta_id; | ||
1047 | |||
1048 | /* | ||
1049 | * Set HT capabilities. It is ok to set this struct even if not using | ||
1050 | * HT config: the priv->current_ht_config.is_ht flag will just be false | ||
1051 | */ | ||
1052 | rcu_read_lock(); | ||
1053 | sta = ieee80211_find_sta(priv->vif, addr); | ||
1054 | if (sta) { | ||
1055 | memcpy(&ht_config, &sta->ht_cap, sizeof(ht_config)); | ||
1056 | cur_ht_config = &ht_config; | ||
1057 | } | ||
1058 | rcu_read_unlock(); | ||
1059 | |||
1060 | /* Add station to device's station table */ | ||
1061 | sta_id = iwl_add_station(priv, addr, is_ap, CMD_SYNC, cur_ht_config); | ||
1062 | |||
1063 | /* Set up default rate scaling table in device's station table */ | ||
1064 | iwl_sta_init_lq(priv, addr, is_ap); | ||
1065 | |||
1066 | return sta_id; | ||
1067 | } | ||
1068 | EXPORT_SYMBOL(iwl_rxon_add_station); | ||
1069 | |||
1070 | /** | ||
1071 | * iwl_sta_init_bcast_lq - Initialize a bcast station's hardware rate table | ||
1072 | * | ||
1073 | * NOTE: Run REPLY_ADD_STA command to set up station table entry, before | ||
1074 | * calling this function (which runs REPLY_TX_LINK_QUALITY_CMD, | ||
1075 | * which requires station table entry to exist). | ||
1076 | */ | ||
1077 | static void iwl_sta_init_bcast_lq(struct iwl_priv *priv) | ||
1078 | { | ||
1079 | int i, r; | ||
1080 | struct iwl_link_quality_cmd link_cmd = { | ||
1081 | .reserved1 = 0, | ||
1082 | }; | ||
1083 | u32 rate_flags; | ||
1084 | |||
1085 | /* Set up the rate scaling to start at selected rate, fall back | ||
1086 | * all the way down to 1M in IEEE order, and then spin on 1M */ | ||
1087 | if (priv->band == IEEE80211_BAND_5GHZ) | ||
1088 | r = IWL_RATE_6M_INDEX; | ||
1089 | else | ||
1090 | r = IWL_RATE_1M_INDEX; | ||
1091 | |||
1092 | for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) { | ||
1093 | rate_flags = 0; | ||
1094 | if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE) | ||
1095 | rate_flags |= RATE_MCS_CCK_MSK; | ||
1096 | |||
1097 | rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) << | ||
1098 | RATE_MCS_ANT_POS; | ||
1099 | |||
1100 | link_cmd.rs_table[i].rate_n_flags = | ||
1101 | iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags); | ||
1102 | r = iwl_get_prev_ieee_rate(r); | ||
1103 | } | ||
1104 | |||
1105 | link_cmd.general_params.single_stream_ant_msk = | ||
1106 | first_antenna(priv->hw_params.valid_tx_ant); | ||
1107 | link_cmd.general_params.dual_stream_ant_msk = 3; | ||
1108 | link_cmd.agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; | ||
1109 | link_cmd.agg_params.agg_time_limit = | ||
1110 | cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); | ||
1111 | |||
1112 | /* Update the rate scaling for control frame Tx to AP */ | ||
1113 | link_cmd.sta_id = priv->hw_params.bcast_sta_id; | ||
1114 | |||
1115 | iwl_send_cmd_pdu_async(priv, REPLY_TX_LINK_QUALITY_CMD, | ||
1116 | sizeof(link_cmd), &link_cmd, NULL); | ||
1117 | } | ||
1118 | |||
1119 | |||
1120 | /** | ||
1121 | * iwl_add_bcast_station - add broadcast station into station table. | 1221 | * iwl_add_bcast_station - add broadcast station into station table. |
1122 | */ | 1222 | */ |
1123 | void iwl_add_bcast_station(struct iwl_priv *priv) | 1223 | void iwl_add_bcast_station(struct iwl_priv *priv) |
1124 | { | 1224 | { |
1125 | IWL_DEBUG_INFO(priv, "Adding broadcast station to station table\n"); | 1225 | IWL_DEBUG_INFO(priv, "Adding broadcast station to station table\n"); |
1126 | iwl_add_station(priv, iwl_bcast_addr, false, CMD_SYNC, NULL); | 1226 | iwl_add_local_station(priv, iwl_bcast_addr, true); |
1127 | |||
1128 | /* Set up default rate scaling table in device's station table */ | ||
1129 | iwl_sta_init_bcast_lq(priv); | ||
1130 | } | 1227 | } |
1131 | EXPORT_SYMBOL(iwl_add_bcast_station); | 1228 | EXPORT_SYMBOL(iwl_add_bcast_station); |
1132 | 1229 | ||
@@ -1136,7 +1233,14 @@ EXPORT_SYMBOL(iwl_add_bcast_station); | |||
1136 | void iwl3945_add_bcast_station(struct iwl_priv *priv) | 1233 | void iwl3945_add_bcast_station(struct iwl_priv *priv) |
1137 | { | 1234 | { |
1138 | IWL_DEBUG_INFO(priv, "Adding broadcast station to station table\n"); | 1235 | IWL_DEBUG_INFO(priv, "Adding broadcast station to station table\n"); |
1139 | iwl_add_station(priv, iwl_bcast_addr, false, CMD_SYNC, NULL); | 1236 | iwl_add_local_station(priv, iwl_bcast_addr, false); |
1237 | /* | ||
1238 | * It is assumed that when station is added more initialization | ||
1239 | * needs to be done, but for 3945 it is not the case and we can | ||
1240 | * just release station table access right here. | ||
1241 | */ | ||
1242 | priv->stations[priv->hw_params.bcast_sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; | ||
1243 | |||
1140 | } | 1244 | } |
1141 | EXPORT_SYMBOL(iwl3945_add_bcast_station); | 1245 | EXPORT_SYMBOL(iwl3945_add_bcast_station); |
1142 | 1246 | ||
@@ -1159,6 +1263,13 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) | |||
1159 | /* If we are a client station in a BSS network, use the special | 1263 | /* If we are a client station in a BSS network, use the special |
1160 | * AP station entry (that's the only station we communicate with) */ | 1264 | * AP station entry (that's the only station we communicate with) */ |
1161 | case NL80211_IFTYPE_STATION: | 1265 | case NL80211_IFTYPE_STATION: |
1266 | /* | ||
1267 | * If addition of station not complete yet, which means | ||
1268 | * that rate scaling has not been initialized, then return | ||
1269 | * the broadcast station. | ||
1270 | */ | ||
1271 | if (!(priv->stations[IWL_AP_ID].used & IWL_STA_UCODE_ACTIVE)) | ||
1272 | return priv->hw_params.bcast_sta_id; | ||
1162 | return IWL_AP_ID; | 1273 | return IWL_AP_ID; |
1163 | 1274 | ||
1164 | /* If we are an AP, then find the station, or use BCAST */ | 1275 | /* If we are an AP, then find the station, or use BCAST */ |
@@ -1175,13 +1286,6 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) | |||
1175 | if (sta_id != IWL_INVALID_STATION) | 1286 | if (sta_id != IWL_INVALID_STATION) |
1176 | return sta_id; | 1287 | return sta_id; |
1177 | 1288 | ||
1178 | /* Create new station table entry */ | ||
1179 | sta_id = iwl_add_station(priv, hdr->addr1, false, | ||
1180 | CMD_ASYNC, NULL); | ||
1181 | |||
1182 | if (sta_id != IWL_INVALID_STATION) | ||
1183 | return sta_id; | ||
1184 | |||
1185 | IWL_DEBUG_DROP(priv, "Station %pM not in station map. " | 1289 | IWL_DEBUG_DROP(priv, "Station %pM not in station map. " |
1186 | "Defaulting to broadcast...\n", | 1290 | "Defaulting to broadcast...\n", |
1187 | hdr->addr1); | 1291 | hdr->addr1); |
@@ -1291,3 +1395,20 @@ void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt) | |||
1291 | 1395 | ||
1292 | iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); | 1396 | iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); |
1293 | } | 1397 | } |
1398 | EXPORT_SYMBOL(iwl_sta_modify_sleep_tx_count); | ||
1399 | |||
1400 | int iwl_mac_sta_remove(struct ieee80211_hw *hw, | ||
1401 | struct ieee80211_vif *vif, | ||
1402 | struct ieee80211_sta *sta) | ||
1403 | { | ||
1404 | int ret; | ||
1405 | struct iwl_priv *priv = hw->priv; | ||
1406 | IWL_DEBUG_INFO(priv, "received request to remove station %pM\n", | ||
1407 | sta->addr); | ||
1408 | ret = iwl_remove_station(priv, sta); | ||
1409 | if (ret) | ||
1410 | IWL_ERR(priv, "Error removing station %pM\n", | ||
1411 | sta->addr); | ||
1412 | return ret; | ||
1413 | } | ||
1414 | EXPORT_SYMBOL(iwl_mac_sta_remove); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 2dc35fe28f56..87a34997a758 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h | |||
@@ -32,6 +32,12 @@ | |||
32 | #define HW_KEY_DYNAMIC 0 | 32 | #define HW_KEY_DYNAMIC 0 |
33 | #define HW_KEY_DEFAULT 1 | 33 | #define HW_KEY_DEFAULT 1 |
34 | 34 | ||
35 | #define IWL_STA_DRIVER_ACTIVE BIT(0) /* driver entry is active */ | ||
36 | #define IWL_STA_UCODE_ACTIVE BIT(1) /* ucode entry is active */ | ||
37 | #define IWL_STA_UCODE_INPROGRESS BIT(2) /* ucode entry is in process of | ||
38 | being activated */ | ||
39 | |||
40 | |||
35 | /** | 41 | /** |
36 | * iwl_find_station - Find station id for a given BSSID | 42 | * iwl_find_station - Find station id for a given BSSID |
37 | * @bssid: MAC address of station ID to find | 43 | * @bssid: MAC address of station ID to find |
@@ -51,18 +57,22 @@ void iwl_update_tkip_key(struct iwl_priv *priv, | |||
51 | struct ieee80211_key_conf *keyconf, | 57 | struct ieee80211_key_conf *keyconf, |
52 | const u8 *addr, u32 iv32, u16 *phase1key); | 58 | const u8 *addr, u32 iv32, u16 *phase1key); |
53 | 59 | ||
54 | int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap); | ||
55 | void iwl_add_bcast_station(struct iwl_priv *priv); | 60 | void iwl_add_bcast_station(struct iwl_priv *priv); |
56 | void iwl3945_add_bcast_station(struct iwl_priv *priv); | 61 | void iwl3945_add_bcast_station(struct iwl_priv *priv); |
57 | int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, bool is_ap); | 62 | void iwl_restore_stations(struct iwl_priv *priv); |
58 | void iwl_clear_stations_table(struct iwl_priv *priv); | 63 | void iwl_clear_ucode_stations(struct iwl_priv *priv, bool force); |
59 | int iwl_get_free_ucode_key_index(struct iwl_priv *priv); | 64 | int iwl_get_free_ucode_key_index(struct iwl_priv *priv); |
60 | int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr); | 65 | int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr); |
61 | int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr); | 66 | int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr); |
62 | int iwl_send_add_sta(struct iwl_priv *priv, | 67 | int iwl_send_add_sta(struct iwl_priv *priv, |
63 | struct iwl_addsta_cmd *sta, u8 flags); | 68 | struct iwl_addsta_cmd *sta, u8 flags); |
64 | u8 iwl_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap, u8 flags, | 69 | int iwl_add_local_station(struct iwl_priv *priv, const u8 *addr, bool init_rs); |
65 | struct ieee80211_sta_ht_cap *ht_info); | 70 | int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr, |
71 | bool is_ap, | ||
72 | struct ieee80211_sta_ht_cap *ht_info, | ||
73 | u8 *sta_id_r); | ||
74 | int iwl_mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | ||
75 | struct ieee80211_sta *sta); | ||
66 | void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid); | 76 | void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid); |
67 | int iwl_sta_rx_agg_start(struct iwl_priv *priv, | 77 | int iwl_sta_rx_agg_start(struct iwl_priv *priv, |
68 | const u8 *addr, int tid, u16 ssn); | 78 | const u8 *addr, int tid, u16 ssn); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 343d81ad2653..a631afef5e33 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
@@ -37,47 +37,6 @@ | |||
37 | #include "iwl-io.h" | 37 | #include "iwl-io.h" |
38 | #include "iwl-helpers.h" | 38 | #include "iwl-helpers.h" |
39 | 39 | ||
40 | static const u16 default_tid_to_tx_fifo[] = { | ||
41 | IWL_TX_FIFO_AC1, | ||
42 | IWL_TX_FIFO_AC0, | ||
43 | IWL_TX_FIFO_AC0, | ||
44 | IWL_TX_FIFO_AC1, | ||
45 | IWL_TX_FIFO_AC2, | ||
46 | IWL_TX_FIFO_AC2, | ||
47 | IWL_TX_FIFO_AC3, | ||
48 | IWL_TX_FIFO_AC3, | ||
49 | IWL_TX_FIFO_NONE, | ||
50 | IWL_TX_FIFO_NONE, | ||
51 | IWL_TX_FIFO_NONE, | ||
52 | IWL_TX_FIFO_NONE, | ||
53 | IWL_TX_FIFO_NONE, | ||
54 | IWL_TX_FIFO_NONE, | ||
55 | IWL_TX_FIFO_NONE, | ||
56 | IWL_TX_FIFO_NONE, | ||
57 | IWL_TX_FIFO_AC3 | ||
58 | }; | ||
59 | |||
60 | static inline int iwl_alloc_dma_ptr(struct iwl_priv *priv, | ||
61 | struct iwl_dma_ptr *ptr, size_t size) | ||
62 | { | ||
63 | ptr->addr = dma_alloc_coherent(&priv->pci_dev->dev, size, &ptr->dma, | ||
64 | GFP_KERNEL); | ||
65 | if (!ptr->addr) | ||
66 | return -ENOMEM; | ||
67 | ptr->size = size; | ||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | static inline void iwl_free_dma_ptr(struct iwl_priv *priv, | ||
72 | struct iwl_dma_ptr *ptr) | ||
73 | { | ||
74 | if (unlikely(!ptr->addr)) | ||
75 | return; | ||
76 | |||
77 | dma_free_coherent(&priv->pci_dev->dev, ptr->size, ptr->addr, ptr->dma); | ||
78 | memset(ptr, 0, sizeof(*ptr)); | ||
79 | } | ||
80 | |||
81 | /** | 40 | /** |
82 | * iwl_txq_update_write_ptr - Send new write index to hardware | 41 | * iwl_txq_update_write_ptr - Send new write index to hardware |
83 | */ | 42 | */ |
@@ -309,6 +268,8 @@ static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, | |||
309 | q->high_mark = 2; | 268 | q->high_mark = 2; |
310 | 269 | ||
311 | q->write_ptr = q->read_ptr = 0; | 270 | q->write_ptr = q->read_ptr = 0; |
271 | q->last_read_ptr = 0; | ||
272 | q->repeat_same_read_ptr = 0; | ||
312 | 273 | ||
313 | return 0; | 274 | return 0; |
314 | } | 275 | } |
@@ -433,631 +394,6 @@ out_free_arrays: | |||
433 | } | 394 | } |
434 | EXPORT_SYMBOL(iwl_tx_queue_init); | 395 | EXPORT_SYMBOL(iwl_tx_queue_init); |
435 | 396 | ||
436 | void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq, | ||
437 | int slots_num, u32 txq_id) | ||
438 | { | ||
439 | int actual_slots = slots_num; | ||
440 | |||
441 | if (txq_id == IWL_CMD_QUEUE_NUM) | ||
442 | actual_slots++; | ||
443 | |||
444 | memset(txq->meta, 0, sizeof(struct iwl_cmd_meta) * actual_slots); | ||
445 | |||
446 | txq->need_update = 0; | ||
447 | |||
448 | /* Initialize queue's high/low-water marks, and head/tail indexes */ | ||
449 | iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); | ||
450 | |||
451 | /* Tell device where to find queue */ | ||
452 | priv->cfg->ops->lib->txq_init(priv, txq); | ||
453 | } | ||
454 | EXPORT_SYMBOL(iwl_tx_queue_reset); | ||
455 | |||
456 | /** | ||
457 | * iwl_hw_txq_ctx_free - Free TXQ Context | ||
458 | * | ||
459 | * Destroy all TX DMA queues and structures | ||
460 | */ | ||
461 | void iwl_hw_txq_ctx_free(struct iwl_priv *priv) | ||
462 | { | ||
463 | int txq_id; | ||
464 | |||
465 | /* Tx queues */ | ||
466 | if (priv->txq) { | ||
467 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) | ||
468 | if (txq_id == IWL_CMD_QUEUE_NUM) | ||
469 | iwl_cmd_queue_free(priv); | ||
470 | else | ||
471 | iwl_tx_queue_free(priv, txq_id); | ||
472 | } | ||
473 | iwl_free_dma_ptr(priv, &priv->kw); | ||
474 | |||
475 | iwl_free_dma_ptr(priv, &priv->scd_bc_tbls); | ||
476 | |||
477 | /* free tx queue structure */ | ||
478 | iwl_free_txq_mem(priv); | ||
479 | } | ||
480 | EXPORT_SYMBOL(iwl_hw_txq_ctx_free); | ||
481 | |||
482 | /** | ||
483 | * iwl_txq_ctx_alloc - allocate TX queue context | ||
484 | * Allocate all Tx DMA structures and initialize them | ||
485 | * | ||
486 | * @param priv | ||
487 | * @return error code | ||
488 | */ | ||
489 | int iwl_txq_ctx_alloc(struct iwl_priv *priv) | ||
490 | { | ||
491 | int ret; | ||
492 | int txq_id, slots_num; | ||
493 | unsigned long flags; | ||
494 | |||
495 | /* Free all tx/cmd queues and keep-warm buffer */ | ||
496 | iwl_hw_txq_ctx_free(priv); | ||
497 | |||
498 | ret = iwl_alloc_dma_ptr(priv, &priv->scd_bc_tbls, | ||
499 | priv->hw_params.scd_bc_tbls_size); | ||
500 | if (ret) { | ||
501 | IWL_ERR(priv, "Scheduler BC Table allocation failed\n"); | ||
502 | goto error_bc_tbls; | ||
503 | } | ||
504 | /* Alloc keep-warm buffer */ | ||
505 | ret = iwl_alloc_dma_ptr(priv, &priv->kw, IWL_KW_SIZE); | ||
506 | if (ret) { | ||
507 | IWL_ERR(priv, "Keep Warm allocation failed\n"); | ||
508 | goto error_kw; | ||
509 | } | ||
510 | |||
511 | /* allocate tx queue structure */ | ||
512 | ret = iwl_alloc_txq_mem(priv); | ||
513 | if (ret) | ||
514 | goto error; | ||
515 | |||
516 | spin_lock_irqsave(&priv->lock, flags); | ||
517 | |||
518 | /* Turn off all Tx DMA fifos */ | ||
519 | priv->cfg->ops->lib->txq_set_sched(priv, 0); | ||
520 | |||
521 | /* Tell NIC where to find the "keep warm" buffer */ | ||
522 | iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); | ||
523 | |||
524 | spin_unlock_irqrestore(&priv->lock, flags); | ||
525 | |||
526 | /* Alloc and init all Tx queues, including the command queue (#4) */ | ||
527 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { | ||
528 | slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ? | ||
529 | TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; | ||
530 | ret = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num, | ||
531 | txq_id); | ||
532 | if (ret) { | ||
533 | IWL_ERR(priv, "Tx %d queue init failed\n", txq_id); | ||
534 | goto error; | ||
535 | } | ||
536 | } | ||
537 | |||
538 | return ret; | ||
539 | |||
540 | error: | ||
541 | iwl_hw_txq_ctx_free(priv); | ||
542 | iwl_free_dma_ptr(priv, &priv->kw); | ||
543 | error_kw: | ||
544 | iwl_free_dma_ptr(priv, &priv->scd_bc_tbls); | ||
545 | error_bc_tbls: | ||
546 | return ret; | ||
547 | } | ||
548 | |||
549 | void iwl_txq_ctx_reset(struct iwl_priv *priv) | ||
550 | { | ||
551 | int txq_id, slots_num; | ||
552 | unsigned long flags; | ||
553 | |||
554 | spin_lock_irqsave(&priv->lock, flags); | ||
555 | |||
556 | /* Turn off all Tx DMA fifos */ | ||
557 | priv->cfg->ops->lib->txq_set_sched(priv, 0); | ||
558 | |||
559 | /* Tell NIC where to find the "keep warm" buffer */ | ||
560 | iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); | ||
561 | |||
562 | spin_unlock_irqrestore(&priv->lock, flags); | ||
563 | |||
564 | /* Alloc and init all Tx queues, including the command queue (#4) */ | ||
565 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { | ||
566 | slots_num = txq_id == IWL_CMD_QUEUE_NUM ? | ||
567 | TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; | ||
568 | iwl_tx_queue_reset(priv, &priv->txq[txq_id], slots_num, txq_id); | ||
569 | } | ||
570 | } | ||
571 | |||
572 | /** | ||
573 | * iwl_txq_ctx_stop - Stop all Tx DMA channels | ||
574 | */ | ||
575 | void iwl_txq_ctx_stop(struct iwl_priv *priv) | ||
576 | { | ||
577 | int ch; | ||
578 | unsigned long flags; | ||
579 | |||
580 | /* Turn off all Tx DMA fifos */ | ||
581 | spin_lock_irqsave(&priv->lock, flags); | ||
582 | |||
583 | priv->cfg->ops->lib->txq_set_sched(priv, 0); | ||
584 | |||
585 | /* Stop each Tx DMA channel, and wait for it to be idle */ | ||
586 | for (ch = 0; ch < priv->hw_params.dma_chnl_num; ch++) { | ||
587 | iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); | ||
588 | iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG, | ||
589 | FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), | ||
590 | 1000); | ||
591 | } | ||
592 | spin_unlock_irqrestore(&priv->lock, flags); | ||
593 | } | ||
594 | EXPORT_SYMBOL(iwl_txq_ctx_stop); | ||
595 | |||
596 | /* | ||
597 | * handle build REPLY_TX command notification. | ||
598 | */ | ||
599 | static void iwl_tx_cmd_build_basic(struct iwl_priv *priv, | ||
600 | struct iwl_tx_cmd *tx_cmd, | ||
601 | struct ieee80211_tx_info *info, | ||
602 | struct ieee80211_hdr *hdr, | ||
603 | u8 std_id) | ||
604 | { | ||
605 | __le16 fc = hdr->frame_control; | ||
606 | __le32 tx_flags = tx_cmd->tx_flags; | ||
607 | |||
608 | tx_cmd->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; | ||
609 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { | ||
610 | tx_flags |= TX_CMD_FLG_ACK_MSK; | ||
611 | if (ieee80211_is_mgmt(fc)) | ||
612 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; | ||
613 | if (ieee80211_is_probe_resp(fc) && | ||
614 | !(le16_to_cpu(hdr->seq_ctrl) & 0xf)) | ||
615 | tx_flags |= TX_CMD_FLG_TSF_MSK; | ||
616 | } else { | ||
617 | tx_flags &= (~TX_CMD_FLG_ACK_MSK); | ||
618 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; | ||
619 | } | ||
620 | |||
621 | if (ieee80211_is_back_req(fc)) | ||
622 | tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK; | ||
623 | |||
624 | |||
625 | tx_cmd->sta_id = std_id; | ||
626 | if (ieee80211_has_morefrags(fc)) | ||
627 | tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK; | ||
628 | |||
629 | if (ieee80211_is_data_qos(fc)) { | ||
630 | u8 *qc = ieee80211_get_qos_ctl(hdr); | ||
631 | tx_cmd->tid_tspec = qc[0] & 0xf; | ||
632 | tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK; | ||
633 | } else { | ||
634 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; | ||
635 | } | ||
636 | |||
637 | priv->cfg->ops->utils->rts_tx_cmd_flag(info, &tx_flags); | ||
638 | |||
639 | if ((tx_flags & TX_CMD_FLG_RTS_MSK) || (tx_flags & TX_CMD_FLG_CTS_MSK)) | ||
640 | tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; | ||
641 | |||
642 | tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK); | ||
643 | if (ieee80211_is_mgmt(fc)) { | ||
644 | if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc)) | ||
645 | tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(3); | ||
646 | else | ||
647 | tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(2); | ||
648 | } else { | ||
649 | tx_cmd->timeout.pm_frame_timeout = 0; | ||
650 | } | ||
651 | |||
652 | tx_cmd->driver_txop = 0; | ||
653 | tx_cmd->tx_flags = tx_flags; | ||
654 | tx_cmd->next_frame_len = 0; | ||
655 | } | ||
656 | |||
657 | #define RTS_HCCA_RETRY_LIMIT 3 | ||
658 | #define RTS_DFAULT_RETRY_LIMIT 60 | ||
659 | |||
660 | static void iwl_tx_cmd_build_rate(struct iwl_priv *priv, | ||
661 | struct iwl_tx_cmd *tx_cmd, | ||
662 | struct ieee80211_tx_info *info, | ||
663 | __le16 fc, int is_hcca) | ||
664 | { | ||
665 | u32 rate_flags; | ||
666 | int rate_idx; | ||
667 | u8 rts_retry_limit; | ||
668 | u8 data_retry_limit; | ||
669 | u8 rate_plcp; | ||
670 | |||
671 | /* Set retry limit on DATA packets and Probe Responses*/ | ||
672 | if (ieee80211_is_probe_resp(fc)) | ||
673 | data_retry_limit = 3; | ||
674 | else | ||
675 | data_retry_limit = IWL_DEFAULT_TX_RETRY; | ||
676 | tx_cmd->data_retry_limit = data_retry_limit; | ||
677 | |||
678 | /* Set retry limit on RTS packets */ | ||
679 | rts_retry_limit = (is_hcca) ? RTS_HCCA_RETRY_LIMIT : | ||
680 | RTS_DFAULT_RETRY_LIMIT; | ||
681 | if (data_retry_limit < rts_retry_limit) | ||
682 | rts_retry_limit = data_retry_limit; | ||
683 | tx_cmd->rts_retry_limit = rts_retry_limit; | ||
684 | |||
685 | /* DATA packets will use the uCode station table for rate/antenna | ||
686 | * selection */ | ||
687 | if (ieee80211_is_data(fc)) { | ||
688 | tx_cmd->initial_rate_index = 0; | ||
689 | tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK; | ||
690 | return; | ||
691 | } | ||
692 | |||
693 | /** | ||
694 | * If the current TX rate stored in mac80211 has the MCS bit set, it's | ||
695 | * not really a TX rate. Thus, we use the lowest supported rate for | ||
696 | * this band. Also use the lowest supported rate if the stored rate | ||
697 | * index is invalid. | ||
698 | */ | ||
699 | rate_idx = info->control.rates[0].idx; | ||
700 | if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS || | ||
701 | (rate_idx < 0) || (rate_idx > IWL_RATE_COUNT_LEGACY)) | ||
702 | rate_idx = rate_lowest_index(&priv->bands[info->band], | ||
703 | info->control.sta); | ||
704 | /* For 5 GHZ band, remap mac80211 rate indices into driver indices */ | ||
705 | if (info->band == IEEE80211_BAND_5GHZ) | ||
706 | rate_idx += IWL_FIRST_OFDM_RATE; | ||
707 | /* Get PLCP rate for tx_cmd->rate_n_flags */ | ||
708 | rate_plcp = iwl_rates[rate_idx].plcp; | ||
709 | /* Zero out flags for this packet */ | ||
710 | rate_flags = 0; | ||
711 | |||
712 | /* Set CCK flag as needed */ | ||
713 | if ((rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE)) | ||
714 | rate_flags |= RATE_MCS_CCK_MSK; | ||
715 | |||
716 | /* Set up RTS and CTS flags for certain packets */ | ||
717 | switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { | ||
718 | case cpu_to_le16(IEEE80211_STYPE_AUTH): | ||
719 | case cpu_to_le16(IEEE80211_STYPE_DEAUTH): | ||
720 | case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ): | ||
721 | case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ): | ||
722 | if (tx_cmd->tx_flags & TX_CMD_FLG_RTS_MSK) { | ||
723 | tx_cmd->tx_flags &= ~TX_CMD_FLG_RTS_MSK; | ||
724 | tx_cmd->tx_flags |= TX_CMD_FLG_CTS_MSK; | ||
725 | } | ||
726 | break; | ||
727 | default: | ||
728 | break; | ||
729 | } | ||
730 | |||
731 | /* Set up antennas */ | ||
732 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant); | ||
733 | rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant); | ||
734 | |||
735 | /* Set the rate in the TX cmd */ | ||
736 | tx_cmd->rate_n_flags = iwl_hw_set_rate_n_flags(rate_plcp, rate_flags); | ||
737 | } | ||
738 | |||
739 | static void iwl_tx_cmd_build_hwcrypto(struct iwl_priv *priv, | ||
740 | struct ieee80211_tx_info *info, | ||
741 | struct iwl_tx_cmd *tx_cmd, | ||
742 | struct sk_buff *skb_frag, | ||
743 | int sta_id) | ||
744 | { | ||
745 | struct ieee80211_key_conf *keyconf = info->control.hw_key; | ||
746 | |||
747 | switch (keyconf->alg) { | ||
748 | case ALG_CCMP: | ||
749 | tx_cmd->sec_ctl = TX_CMD_SEC_CCM; | ||
750 | memcpy(tx_cmd->key, keyconf->key, keyconf->keylen); | ||
751 | if (info->flags & IEEE80211_TX_CTL_AMPDU) | ||
752 | tx_cmd->tx_flags |= TX_CMD_FLG_AGG_CCMP_MSK; | ||
753 | IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n"); | ||
754 | break; | ||
755 | |||
756 | case ALG_TKIP: | ||
757 | tx_cmd->sec_ctl = TX_CMD_SEC_TKIP; | ||
758 | ieee80211_get_tkip_key(keyconf, skb_frag, | ||
759 | IEEE80211_TKIP_P2_KEY, tx_cmd->key); | ||
760 | IWL_DEBUG_TX(priv, "tx_cmd with tkip hwcrypto\n"); | ||
761 | break; | ||
762 | |||
763 | case ALG_WEP: | ||
764 | tx_cmd->sec_ctl |= (TX_CMD_SEC_WEP | | ||
765 | (keyconf->keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT); | ||
766 | |||
767 | if (keyconf->keylen == WEP_KEY_LEN_128) | ||
768 | tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128; | ||
769 | |||
770 | memcpy(&tx_cmd->key[3], keyconf->key, keyconf->keylen); | ||
771 | |||
772 | IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption " | ||
773 | "with key %d\n", keyconf->keyidx); | ||
774 | break; | ||
775 | |||
776 | default: | ||
777 | IWL_ERR(priv, "Unknown encode alg %d\n", keyconf->alg); | ||
778 | break; | ||
779 | } | ||
780 | } | ||
781 | |||
782 | /* | ||
783 | * start REPLY_TX command process | ||
784 | */ | ||
785 | int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | ||
786 | { | ||
787 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
788 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
789 | struct ieee80211_sta *sta = info->control.sta; | ||
790 | struct iwl_station_priv *sta_priv = NULL; | ||
791 | struct iwl_tx_queue *txq; | ||
792 | struct iwl_queue *q; | ||
793 | struct iwl_device_cmd *out_cmd; | ||
794 | struct iwl_cmd_meta *out_meta; | ||
795 | struct iwl_tx_cmd *tx_cmd; | ||
796 | int swq_id, txq_id; | ||
797 | dma_addr_t phys_addr; | ||
798 | dma_addr_t txcmd_phys; | ||
799 | dma_addr_t scratch_phys; | ||
800 | u16 len, len_org, firstlen, secondlen; | ||
801 | u16 seq_number = 0; | ||
802 | __le16 fc; | ||
803 | u8 hdr_len; | ||
804 | u8 sta_id; | ||
805 | u8 wait_write_ptr = 0; | ||
806 | u8 tid = 0; | ||
807 | u8 *qc = NULL; | ||
808 | unsigned long flags; | ||
809 | |||
810 | spin_lock_irqsave(&priv->lock, flags); | ||
811 | if (iwl_is_rfkill(priv)) { | ||
812 | IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n"); | ||
813 | goto drop_unlock; | ||
814 | } | ||
815 | |||
816 | fc = hdr->frame_control; | ||
817 | |||
818 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
819 | if (ieee80211_is_auth(fc)) | ||
820 | IWL_DEBUG_TX(priv, "Sending AUTH frame\n"); | ||
821 | else if (ieee80211_is_assoc_req(fc)) | ||
822 | IWL_DEBUG_TX(priv, "Sending ASSOC frame\n"); | ||
823 | else if (ieee80211_is_reassoc_req(fc)) | ||
824 | IWL_DEBUG_TX(priv, "Sending REASSOC frame\n"); | ||
825 | #endif | ||
826 | |||
827 | /* drop all non-injected data frame if we are not associated */ | ||
828 | if (ieee80211_is_data(fc) && | ||
829 | !(info->flags & IEEE80211_TX_CTL_INJECTED) && | ||
830 | (!iwl_is_associated(priv) || | ||
831 | ((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id) || | ||
832 | !priv->assoc_station_added)) { | ||
833 | IWL_DEBUG_DROP(priv, "Dropping - !iwl_is_associated\n"); | ||
834 | goto drop_unlock; | ||
835 | } | ||
836 | |||
837 | hdr_len = ieee80211_hdrlen(fc); | ||
838 | |||
839 | /* Find (or create) index into station table for destination station */ | ||
840 | if (info->flags & IEEE80211_TX_CTL_INJECTED) | ||
841 | sta_id = priv->hw_params.bcast_sta_id; | ||
842 | else | ||
843 | sta_id = iwl_get_sta_id(priv, hdr); | ||
844 | if (sta_id == IWL_INVALID_STATION) { | ||
845 | IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", | ||
846 | hdr->addr1); | ||
847 | goto drop_unlock; | ||
848 | } | ||
849 | |||
850 | IWL_DEBUG_TX(priv, "station Id %d\n", sta_id); | ||
851 | |||
852 | if (sta) | ||
853 | sta_priv = (void *)sta->drv_priv; | ||
854 | |||
855 | if (sta_priv && sta_id != priv->hw_params.bcast_sta_id && | ||
856 | sta_priv->asleep) { | ||
857 | WARN_ON(!(info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE)); | ||
858 | /* | ||
859 | * This sends an asynchronous command to the device, | ||
860 | * but we can rely on it being processed before the | ||
861 | * next frame is processed -- and the next frame to | ||
862 | * this station is the one that will consume this | ||
863 | * counter. | ||
864 | * For now set the counter to just 1 since we do not | ||
865 | * support uAPSD yet. | ||
866 | */ | ||
867 | iwl_sta_modify_sleep_tx_count(priv, sta_id, 1); | ||
868 | } | ||
869 | |||
870 | txq_id = skb_get_queue_mapping(skb); | ||
871 | if (ieee80211_is_data_qos(fc)) { | ||
872 | qc = ieee80211_get_qos_ctl(hdr); | ||
873 | tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; | ||
874 | if (unlikely(tid >= MAX_TID_COUNT)) | ||
875 | goto drop_unlock; | ||
876 | seq_number = priv->stations[sta_id].tid[tid].seq_number; | ||
877 | seq_number &= IEEE80211_SCTL_SEQ; | ||
878 | hdr->seq_ctrl = hdr->seq_ctrl & | ||
879 | cpu_to_le16(IEEE80211_SCTL_FRAG); | ||
880 | hdr->seq_ctrl |= cpu_to_le16(seq_number); | ||
881 | seq_number += 0x10; | ||
882 | /* aggregation is on for this <sta,tid> */ | ||
883 | if (info->flags & IEEE80211_TX_CTL_AMPDU && | ||
884 | priv->stations[sta_id].tid[tid].agg.state == IWL_AGG_ON) { | ||
885 | txq_id = priv->stations[sta_id].tid[tid].agg.txq_id; | ||
886 | } | ||
887 | } | ||
888 | |||
889 | txq = &priv->txq[txq_id]; | ||
890 | swq_id = txq->swq_id; | ||
891 | q = &txq->q; | ||
892 | |||
893 | if (unlikely(iwl_queue_space(q) < q->high_mark)) | ||
894 | goto drop_unlock; | ||
895 | |||
896 | if (ieee80211_is_data_qos(fc)) | ||
897 | priv->stations[sta_id].tid[tid].tfds_in_queue++; | ||
898 | |||
899 | /* Set up driver data for this TFD */ | ||
900 | memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); | ||
901 | txq->txb[q->write_ptr].skb[0] = skb; | ||
902 | |||
903 | /* Set up first empty entry in queue's array of Tx/cmd buffers */ | ||
904 | out_cmd = txq->cmd[q->write_ptr]; | ||
905 | out_meta = &txq->meta[q->write_ptr]; | ||
906 | tx_cmd = &out_cmd->cmd.tx; | ||
907 | memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr)); | ||
908 | memset(tx_cmd, 0, sizeof(struct iwl_tx_cmd)); | ||
909 | |||
910 | /* | ||
911 | * Set up the Tx-command (not MAC!) header. | ||
912 | * Store the chosen Tx queue and TFD index within the sequence field; | ||
913 | * after Tx, uCode's Tx response will return this value so driver can | ||
914 | * locate the frame within the tx queue and do post-tx processing. | ||
915 | */ | ||
916 | out_cmd->hdr.cmd = REPLY_TX; | ||
917 | out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) | | ||
918 | INDEX_TO_SEQ(q->write_ptr))); | ||
919 | |||
920 | /* Copy MAC header from skb into command buffer */ | ||
921 | memcpy(tx_cmd->hdr, hdr, hdr_len); | ||
922 | |||
923 | |||
924 | /* Total # bytes to be transmitted */ | ||
925 | len = (u16)skb->len; | ||
926 | tx_cmd->len = cpu_to_le16(len); | ||
927 | |||
928 | if (info->control.hw_key) | ||
929 | iwl_tx_cmd_build_hwcrypto(priv, info, tx_cmd, skb, sta_id); | ||
930 | |||
931 | /* TODO need this for burst mode later on */ | ||
932 | iwl_tx_cmd_build_basic(priv, tx_cmd, info, hdr, sta_id); | ||
933 | iwl_dbg_log_tx_data_frame(priv, len, hdr); | ||
934 | |||
935 | /* set is_hcca to 0; it probably will never be implemented */ | ||
936 | iwl_tx_cmd_build_rate(priv, tx_cmd, info, fc, 0); | ||
937 | |||
938 | iwl_update_stats(priv, true, fc, len); | ||
939 | /* | ||
940 | * Use the first empty entry in this queue's command buffer array | ||
941 | * to contain the Tx command and MAC header concatenated together | ||
942 | * (payload data will be in another buffer). | ||
943 | * Size of this varies, due to varying MAC header length. | ||
944 | * If end is not dword aligned, we'll have 2 extra bytes at the end | ||
945 | * of the MAC header (device reads on dword boundaries). | ||
946 | * We'll tell device about this padding later. | ||
947 | */ | ||
948 | len = sizeof(struct iwl_tx_cmd) + | ||
949 | sizeof(struct iwl_cmd_header) + hdr_len; | ||
950 | |||
951 | len_org = len; | ||
952 | firstlen = len = (len + 3) & ~3; | ||
953 | |||
954 | if (len_org != len) | ||
955 | len_org = 1; | ||
956 | else | ||
957 | len_org = 0; | ||
958 | |||
959 | /* Tell NIC about any 2-byte padding after MAC header */ | ||
960 | if (len_org) | ||
961 | tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK; | ||
962 | |||
963 | /* Physical address of this Tx command's header (not MAC header!), | ||
964 | * within command buffer array. */ | ||
965 | txcmd_phys = pci_map_single(priv->pci_dev, | ||
966 | &out_cmd->hdr, len, | ||
967 | PCI_DMA_BIDIRECTIONAL); | ||
968 | pci_unmap_addr_set(out_meta, mapping, txcmd_phys); | ||
969 | pci_unmap_len_set(out_meta, len, len); | ||
970 | /* Add buffer containing Tx command and MAC(!) header to TFD's | ||
971 | * first entry */ | ||
972 | priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, | ||
973 | txcmd_phys, len, 1, 0); | ||
974 | |||
975 | if (!ieee80211_has_morefrags(hdr->frame_control)) { | ||
976 | txq->need_update = 1; | ||
977 | if (qc) | ||
978 | priv->stations[sta_id].tid[tid].seq_number = seq_number; | ||
979 | } else { | ||
980 | wait_write_ptr = 1; | ||
981 | txq->need_update = 0; | ||
982 | } | ||
983 | |||
984 | /* Set up TFD's 2nd entry to point directly to remainder of skb, | ||
985 | * if any (802.11 null frames have no payload). */ | ||
986 | secondlen = len = skb->len - hdr_len; | ||
987 | if (len) { | ||
988 | phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len, | ||
989 | len, PCI_DMA_TODEVICE); | ||
990 | priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, | ||
991 | phys_addr, len, | ||
992 | 0, 0); | ||
993 | } | ||
994 | |||
995 | scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) + | ||
996 | offsetof(struct iwl_tx_cmd, scratch); | ||
997 | |||
998 | len = sizeof(struct iwl_tx_cmd) + | ||
999 | sizeof(struct iwl_cmd_header) + hdr_len; | ||
1000 | /* take back ownership of DMA buffer to enable update */ | ||
1001 | pci_dma_sync_single_for_cpu(priv->pci_dev, txcmd_phys, | ||
1002 | len, PCI_DMA_BIDIRECTIONAL); | ||
1003 | tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys); | ||
1004 | tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys); | ||
1005 | |||
1006 | IWL_DEBUG_TX(priv, "sequence nr = 0X%x \n", | ||
1007 | le16_to_cpu(out_cmd->hdr.sequence)); | ||
1008 | IWL_DEBUG_TX(priv, "tx_flags = 0X%x \n", le32_to_cpu(tx_cmd->tx_flags)); | ||
1009 | iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd)); | ||
1010 | iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len); | ||
1011 | |||
1012 | /* Set up entry for this TFD in Tx byte-count array */ | ||
1013 | if (info->flags & IEEE80211_TX_CTL_AMPDU) | ||
1014 | priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, | ||
1015 | le16_to_cpu(tx_cmd->len)); | ||
1016 | |||
1017 | pci_dma_sync_single_for_device(priv->pci_dev, txcmd_phys, | ||
1018 | len, PCI_DMA_BIDIRECTIONAL); | ||
1019 | |||
1020 | trace_iwlwifi_dev_tx(priv, | ||
1021 | &((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr], | ||
1022 | sizeof(struct iwl_tfd), | ||
1023 | &out_cmd->hdr, firstlen, | ||
1024 | skb->data + hdr_len, secondlen); | ||
1025 | |||
1026 | /* Tell device the write index *just past* this latest filled TFD */ | ||
1027 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); | ||
1028 | iwl_txq_update_write_ptr(priv, txq); | ||
1029 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1030 | |||
1031 | /* | ||
1032 | * At this point the frame is "transmitted" successfully | ||
1033 | * and we will get a TX status notification eventually, | ||
1034 | * regardless of the value of ret. "ret" only indicates | ||
1035 | * whether or not we should update the write pointer. | ||
1036 | */ | ||
1037 | |||
1038 | /* avoid atomic ops if it isn't an associated client */ | ||
1039 | if (sta_priv && sta_priv->client) | ||
1040 | atomic_inc(&sta_priv->pending_frames); | ||
1041 | |||
1042 | if ((iwl_queue_space(q) < q->high_mark) && priv->mac80211_registered) { | ||
1043 | if (wait_write_ptr) { | ||
1044 | spin_lock_irqsave(&priv->lock, flags); | ||
1045 | txq->need_update = 1; | ||
1046 | iwl_txq_update_write_ptr(priv, txq); | ||
1047 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1048 | } else { | ||
1049 | iwl_stop_queue(priv, txq->swq_id); | ||
1050 | } | ||
1051 | } | ||
1052 | |||
1053 | return 0; | ||
1054 | |||
1055 | drop_unlock: | ||
1056 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1057 | return -1; | ||
1058 | } | ||
1059 | EXPORT_SYMBOL(iwl_tx_skb); | ||
1060 | |||
1061 | /*************** HOST COMMAND QUEUE FUNCTIONS *****/ | 397 | /*************** HOST COMMAND QUEUE FUNCTIONS *****/ |
1062 | 398 | ||
1063 | /** | 399 | /** |
@@ -1191,61 +527,6 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
1191 | return idx; | 527 | return idx; |
1192 | } | 528 | } |
1193 | 529 | ||
1194 | static void iwl_tx_status(struct iwl_priv *priv, struct sk_buff *skb) | ||
1195 | { | ||
1196 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
1197 | struct ieee80211_sta *sta; | ||
1198 | struct iwl_station_priv *sta_priv; | ||
1199 | |||
1200 | sta = ieee80211_find_sta(priv->vif, hdr->addr1); | ||
1201 | if (sta) { | ||
1202 | sta_priv = (void *)sta->drv_priv; | ||
1203 | /* avoid atomic ops if this isn't a client */ | ||
1204 | if (sta_priv->client && | ||
1205 | atomic_dec_return(&sta_priv->pending_frames) == 0) | ||
1206 | ieee80211_sta_block_awake(priv->hw, sta, false); | ||
1207 | } | ||
1208 | |||
1209 | ieee80211_tx_status_irqsafe(priv->hw, skb); | ||
1210 | } | ||
1211 | |||
1212 | int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) | ||
1213 | { | ||
1214 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; | ||
1215 | struct iwl_queue *q = &txq->q; | ||
1216 | struct iwl_tx_info *tx_info; | ||
1217 | int nfreed = 0; | ||
1218 | struct ieee80211_hdr *hdr; | ||
1219 | |||
1220 | if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) { | ||
1221 | IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, " | ||
1222 | "is out of range [0-%d] %d %d.\n", txq_id, | ||
1223 | index, q->n_bd, q->write_ptr, q->read_ptr); | ||
1224 | return 0; | ||
1225 | } | ||
1226 | |||
1227 | for (index = iwl_queue_inc_wrap(index, q->n_bd); | ||
1228 | q->read_ptr != index; | ||
1229 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { | ||
1230 | |||
1231 | tx_info = &txq->txb[txq->q.read_ptr]; | ||
1232 | iwl_tx_status(priv, tx_info->skb[0]); | ||
1233 | |||
1234 | hdr = (struct ieee80211_hdr *)tx_info->skb[0]->data; | ||
1235 | if (hdr && ieee80211_is_data_qos(hdr->frame_control)) | ||
1236 | nfreed++; | ||
1237 | tx_info->skb[0] = NULL; | ||
1238 | |||
1239 | if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl) | ||
1240 | priv->cfg->ops->lib->txq_inval_byte_cnt_tbl(priv, txq); | ||
1241 | |||
1242 | priv->cfg->ops->lib->txq_free_tfd(priv, txq); | ||
1243 | } | ||
1244 | return nfreed; | ||
1245 | } | ||
1246 | EXPORT_SYMBOL(iwl_tx_queue_reclaim); | ||
1247 | |||
1248 | |||
1249 | /** | 530 | /** |
1250 | * iwl_hcmd_queue_reclaim - Reclaim TX command queue entries already Tx'd | 531 | * iwl_hcmd_queue_reclaim - Reclaim TX command queue entries already Tx'd |
1251 | * | 532 | * |
@@ -1339,7 +620,7 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
1339 | 620 | ||
1340 | if (!(meta->flags & CMD_ASYNC)) { | 621 | if (!(meta->flags & CMD_ASYNC)) { |
1341 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); | 622 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); |
1342 | IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s \n", | 623 | IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s\n", |
1343 | get_cmd_string(cmd->hdr.cmd)); | 624 | get_cmd_string(cmd->hdr.cmd)); |
1344 | wake_up_interruptible(&priv->wait_command_queue); | 625 | wake_up_interruptible(&priv->wait_command_queue); |
1345 | } | 626 | } |
@@ -1347,334 +628,6 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
1347 | } | 628 | } |
1348 | EXPORT_SYMBOL(iwl_tx_cmd_complete); | 629 | EXPORT_SYMBOL(iwl_tx_cmd_complete); |
1349 | 630 | ||
1350 | /* | ||
1351 | * Find first available (lowest unused) Tx Queue, mark it "active". | ||
1352 | * Called only when finding queue for aggregation. | ||
1353 | * Should never return anything < 7, because they should already | ||
1354 | * be in use as EDCA AC (0-3), Command (4), HCCA (5, 6). | ||
1355 | */ | ||
1356 | static int iwl_txq_ctx_activate_free(struct iwl_priv *priv) | ||
1357 | { | ||
1358 | int txq_id; | ||
1359 | |||
1360 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) | ||
1361 | if (!test_and_set_bit(txq_id, &priv->txq_ctx_active_msk)) | ||
1362 | return txq_id; | ||
1363 | return -1; | ||
1364 | } | ||
1365 | |||
1366 | int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn) | ||
1367 | { | ||
1368 | int sta_id; | ||
1369 | int tx_fifo; | ||
1370 | int txq_id; | ||
1371 | int ret; | ||
1372 | unsigned long flags; | ||
1373 | struct iwl_tid_data *tid_data; | ||
1374 | |||
1375 | if (likely(tid < ARRAY_SIZE(default_tid_to_tx_fifo))) | ||
1376 | tx_fifo = default_tid_to_tx_fifo[tid]; | ||
1377 | else | ||
1378 | return -EINVAL; | ||
1379 | |||
1380 | IWL_WARN(priv, "%s on ra = %pM tid = %d\n", | ||
1381 | __func__, ra, tid); | ||
1382 | |||
1383 | sta_id = iwl_find_station(priv, ra); | ||
1384 | if (sta_id == IWL_INVALID_STATION) { | ||
1385 | IWL_ERR(priv, "Start AGG on invalid station\n"); | ||
1386 | return -ENXIO; | ||
1387 | } | ||
1388 | if (unlikely(tid >= MAX_TID_COUNT)) | ||
1389 | return -EINVAL; | ||
1390 | |||
1391 | if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_OFF) { | ||
1392 | IWL_ERR(priv, "Start AGG when state is not IWL_AGG_OFF !\n"); | ||
1393 | return -ENXIO; | ||
1394 | } | ||
1395 | |||
1396 | txq_id = iwl_txq_ctx_activate_free(priv); | ||
1397 | if (txq_id == -1) { | ||
1398 | IWL_ERR(priv, "No free aggregation queue available\n"); | ||
1399 | return -ENXIO; | ||
1400 | } | ||
1401 | |||
1402 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
1403 | tid_data = &priv->stations[sta_id].tid[tid]; | ||
1404 | *ssn = SEQ_TO_SN(tid_data->seq_number); | ||
1405 | tid_data->agg.txq_id = txq_id; | ||
1406 | priv->txq[txq_id].swq_id = iwl_virtual_agg_queue_num(tx_fifo, txq_id); | ||
1407 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
1408 | |||
1409 | ret = priv->cfg->ops->lib->txq_agg_enable(priv, txq_id, tx_fifo, | ||
1410 | sta_id, tid, *ssn); | ||
1411 | if (ret) | ||
1412 | return ret; | ||
1413 | |||
1414 | if (tid_data->tfds_in_queue == 0) { | ||
1415 | IWL_DEBUG_HT(priv, "HW queue is empty\n"); | ||
1416 | tid_data->agg.state = IWL_AGG_ON; | ||
1417 | ieee80211_start_tx_ba_cb_irqsafe(priv->vif, ra, tid); | ||
1418 | } else { | ||
1419 | IWL_DEBUG_HT(priv, "HW queue is NOT empty: %d packets in HW queue\n", | ||
1420 | tid_data->tfds_in_queue); | ||
1421 | tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA; | ||
1422 | } | ||
1423 | return ret; | ||
1424 | } | ||
1425 | EXPORT_SYMBOL(iwl_tx_agg_start); | ||
1426 | |||
1427 | int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid) | ||
1428 | { | ||
1429 | int tx_fifo_id, txq_id, sta_id, ssn = -1; | ||
1430 | struct iwl_tid_data *tid_data; | ||
1431 | int write_ptr, read_ptr; | ||
1432 | unsigned long flags; | ||
1433 | |||
1434 | if (!ra) { | ||
1435 | IWL_ERR(priv, "ra = NULL\n"); | ||
1436 | return -EINVAL; | ||
1437 | } | ||
1438 | |||
1439 | if (unlikely(tid >= MAX_TID_COUNT)) | ||
1440 | return -EINVAL; | ||
1441 | |||
1442 | if (likely(tid < ARRAY_SIZE(default_tid_to_tx_fifo))) | ||
1443 | tx_fifo_id = default_tid_to_tx_fifo[tid]; | ||
1444 | else | ||
1445 | return -EINVAL; | ||
1446 | |||
1447 | sta_id = iwl_find_station(priv, ra); | ||
1448 | |||
1449 | if (sta_id == IWL_INVALID_STATION) { | ||
1450 | IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid); | ||
1451 | return -ENXIO; | ||
1452 | } | ||
1453 | |||
1454 | if (priv->stations[sta_id].tid[tid].agg.state == | ||
1455 | IWL_EMPTYING_HW_QUEUE_ADDBA) { | ||
1456 | IWL_DEBUG_HT(priv, "AGG stop before setup done\n"); | ||
1457 | ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid); | ||
1458 | priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; | ||
1459 | return 0; | ||
1460 | } | ||
1461 | |||
1462 | if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_ON) | ||
1463 | IWL_WARN(priv, "Stopping AGG while state not ON or starting\n"); | ||
1464 | |||
1465 | tid_data = &priv->stations[sta_id].tid[tid]; | ||
1466 | ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4; | ||
1467 | txq_id = tid_data->agg.txq_id; | ||
1468 | write_ptr = priv->txq[txq_id].q.write_ptr; | ||
1469 | read_ptr = priv->txq[txq_id].q.read_ptr; | ||
1470 | |||
1471 | /* The queue is not empty */ | ||
1472 | if (write_ptr != read_ptr) { | ||
1473 | IWL_DEBUG_HT(priv, "Stopping a non empty AGG HW QUEUE\n"); | ||
1474 | priv->stations[sta_id].tid[tid].agg.state = | ||
1475 | IWL_EMPTYING_HW_QUEUE_DELBA; | ||
1476 | return 0; | ||
1477 | } | ||
1478 | |||
1479 | IWL_DEBUG_HT(priv, "HW queue is empty\n"); | ||
1480 | priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; | ||
1481 | |||
1482 | spin_lock_irqsave(&priv->lock, flags); | ||
1483 | /* | ||
1484 | * the only reason this call can fail is queue number out of range, | ||
1485 | * which can happen if uCode is reloaded and all the station | ||
1486 | * information are lost. if it is outside the range, there is no need | ||
1487 | * to deactivate the uCode queue, just return "success" to allow | ||
1488 | * mac80211 to clean up it own data. | ||
1489 | */ | ||
1490 | priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, ssn, | ||
1491 | tx_fifo_id); | ||
1492 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1493 | |||
1494 | ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid); | ||
1495 | |||
1496 | return 0; | ||
1497 | } | ||
1498 | EXPORT_SYMBOL(iwl_tx_agg_stop); | ||
1499 | |||
1500 | int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id) | ||
1501 | { | ||
1502 | struct iwl_queue *q = &priv->txq[txq_id].q; | ||
1503 | u8 *addr = priv->stations[sta_id].sta.sta.addr; | ||
1504 | struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid]; | ||
1505 | |||
1506 | switch (priv->stations[sta_id].tid[tid].agg.state) { | ||
1507 | case IWL_EMPTYING_HW_QUEUE_DELBA: | ||
1508 | /* We are reclaiming the last packet of the */ | ||
1509 | /* aggregated HW queue */ | ||
1510 | if ((txq_id == tid_data->agg.txq_id) && | ||
1511 | (q->read_ptr == q->write_ptr)) { | ||
1512 | u16 ssn = SEQ_TO_SN(tid_data->seq_number); | ||
1513 | int tx_fifo = default_tid_to_tx_fifo[tid]; | ||
1514 | IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n"); | ||
1515 | priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, | ||
1516 | ssn, tx_fifo); | ||
1517 | tid_data->agg.state = IWL_AGG_OFF; | ||
1518 | ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, addr, tid); | ||
1519 | } | ||
1520 | break; | ||
1521 | case IWL_EMPTYING_HW_QUEUE_ADDBA: | ||
1522 | /* We are reclaiming the last packet of the queue */ | ||
1523 | if (tid_data->tfds_in_queue == 0) { | ||
1524 | IWL_DEBUG_HT(priv, "HW queue empty: continue ADDBA flow\n"); | ||
1525 | tid_data->agg.state = IWL_AGG_ON; | ||
1526 | ieee80211_start_tx_ba_cb_irqsafe(priv->vif, addr, tid); | ||
1527 | } | ||
1528 | break; | ||
1529 | } | ||
1530 | return 0; | ||
1531 | } | ||
1532 | EXPORT_SYMBOL(iwl_txq_check_empty); | ||
1533 | |||
1534 | /** | ||
1535 | * iwl_tx_status_reply_compressed_ba - Update tx status from block-ack | ||
1536 | * | ||
1537 | * Go through block-ack's bitmap of ACK'd frames, update driver's record of | ||
1538 | * ACK vs. not. This gets sent to mac80211, then to rate scaling algo. | ||
1539 | */ | ||
1540 | static int iwl_tx_status_reply_compressed_ba(struct iwl_priv *priv, | ||
1541 | struct iwl_ht_agg *agg, | ||
1542 | struct iwl_compressed_ba_resp *ba_resp) | ||
1543 | |||
1544 | { | ||
1545 | int i, sh, ack; | ||
1546 | u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl); | ||
1547 | u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); | ||
1548 | u64 bitmap; | ||
1549 | int successes = 0; | ||
1550 | struct ieee80211_tx_info *info; | ||
1551 | |||
1552 | if (unlikely(!agg->wait_for_ba)) { | ||
1553 | IWL_ERR(priv, "Received BA when not expected\n"); | ||
1554 | return -EINVAL; | ||
1555 | } | ||
1556 | |||
1557 | /* Mark that the expected block-ack response arrived */ | ||
1558 | agg->wait_for_ba = 0; | ||
1559 | IWL_DEBUG_TX_REPLY(priv, "BA %d %d\n", agg->start_idx, ba_resp->seq_ctl); | ||
1560 | |||
1561 | /* Calculate shift to align block-ack bits with our Tx window bits */ | ||
1562 | sh = agg->start_idx - SEQ_TO_INDEX(seq_ctl >> 4); | ||
1563 | if (sh < 0) /* tbw something is wrong with indices */ | ||
1564 | sh += 0x100; | ||
1565 | |||
1566 | /* don't use 64-bit values for now */ | ||
1567 | bitmap = le64_to_cpu(ba_resp->bitmap) >> sh; | ||
1568 | |||
1569 | if (agg->frame_count > (64 - sh)) { | ||
1570 | IWL_DEBUG_TX_REPLY(priv, "more frames than bitmap size"); | ||
1571 | return -1; | ||
1572 | } | ||
1573 | |||
1574 | /* check for success or failure according to the | ||
1575 | * transmitted bitmap and block-ack bitmap */ | ||
1576 | bitmap &= agg->bitmap; | ||
1577 | |||
1578 | /* For each frame attempted in aggregation, | ||
1579 | * update driver's record of tx frame's status. */ | ||
1580 | for (i = 0; i < agg->frame_count ; i++) { | ||
1581 | ack = bitmap & (1ULL << i); | ||
1582 | successes += !!ack; | ||
1583 | IWL_DEBUG_TX_REPLY(priv, "%s ON i=%d idx=%d raw=%d\n", | ||
1584 | ack ? "ACK" : "NACK", i, (agg->start_idx + i) & 0xff, | ||
1585 | agg->start_idx + i); | ||
1586 | } | ||
1587 | |||
1588 | info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb[0]); | ||
1589 | memset(&info->status, 0, sizeof(info->status)); | ||
1590 | info->flags |= IEEE80211_TX_STAT_ACK; | ||
1591 | info->flags |= IEEE80211_TX_STAT_AMPDU; | ||
1592 | info->status.ampdu_ack_map = successes; | ||
1593 | info->status.ampdu_ack_len = agg->frame_count; | ||
1594 | iwl_hwrate_to_tx_control(priv, agg->rate_n_flags, info); | ||
1595 | |||
1596 | IWL_DEBUG_TX_REPLY(priv, "Bitmap %llx\n", (unsigned long long)bitmap); | ||
1597 | |||
1598 | return 0; | ||
1599 | } | ||
1600 | |||
1601 | /** | ||
1602 | * iwl_rx_reply_compressed_ba - Handler for REPLY_COMPRESSED_BA | ||
1603 | * | ||
1604 | * Handles block-acknowledge notification from device, which reports success | ||
1605 | * of frames sent via aggregation. | ||
1606 | */ | ||
1607 | void iwl_rx_reply_compressed_ba(struct iwl_priv *priv, | ||
1608 | struct iwl_rx_mem_buffer *rxb) | ||
1609 | { | ||
1610 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
1611 | struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba; | ||
1612 | struct iwl_tx_queue *txq = NULL; | ||
1613 | struct iwl_ht_agg *agg; | ||
1614 | int index; | ||
1615 | int sta_id; | ||
1616 | int tid; | ||
1617 | |||
1618 | /* "flow" corresponds to Tx queue */ | ||
1619 | u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); | ||
1620 | |||
1621 | /* "ssn" is start of block-ack Tx window, corresponds to index | ||
1622 | * (in Tx queue's circular buffer) of first TFD/frame in window */ | ||
1623 | u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn); | ||
1624 | |||
1625 | if (scd_flow >= priv->hw_params.max_txq_num) { | ||
1626 | IWL_ERR(priv, | ||
1627 | "BUG_ON scd_flow is bigger than number of queues\n"); | ||
1628 | return; | ||
1629 | } | ||
1630 | |||
1631 | txq = &priv->txq[scd_flow]; | ||
1632 | sta_id = ba_resp->sta_id; | ||
1633 | tid = ba_resp->tid; | ||
1634 | agg = &priv->stations[sta_id].tid[tid].agg; | ||
1635 | |||
1636 | /* Find index just before block-ack window */ | ||
1637 | index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd); | ||
1638 | |||
1639 | /* TODO: Need to get this copy more safely - now good for debug */ | ||
1640 | |||
1641 | IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, " | ||
1642 | "sta_id = %d\n", | ||
1643 | agg->wait_for_ba, | ||
1644 | (u8 *) &ba_resp->sta_addr_lo32, | ||
1645 | ba_resp->sta_id); | ||
1646 | IWL_DEBUG_TX_REPLY(priv, "TID = %d, SeqCtl = %d, bitmap = 0x%llx, scd_flow = " | ||
1647 | "%d, scd_ssn = %d\n", | ||
1648 | ba_resp->tid, | ||
1649 | ba_resp->seq_ctl, | ||
1650 | (unsigned long long)le64_to_cpu(ba_resp->bitmap), | ||
1651 | ba_resp->scd_flow, | ||
1652 | ba_resp->scd_ssn); | ||
1653 | IWL_DEBUG_TX_REPLY(priv, "DAT start_idx = %d, bitmap = 0x%llx \n", | ||
1654 | agg->start_idx, | ||
1655 | (unsigned long long)agg->bitmap); | ||
1656 | |||
1657 | /* Update driver's record of ACK vs. not for each frame in window */ | ||
1658 | iwl_tx_status_reply_compressed_ba(priv, agg, ba_resp); | ||
1659 | |||
1660 | /* Release all TFDs before the SSN, i.e. all TFDs in front of | ||
1661 | * block-ack window (we assume that they've been successfully | ||
1662 | * transmitted ... if not, it's too late anyway). */ | ||
1663 | if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) { | ||
1664 | /* calculate mac80211 ampdu sw queue to wake */ | ||
1665 | int freed = iwl_tx_queue_reclaim(priv, scd_flow, index); | ||
1666 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); | ||
1667 | |||
1668 | if ((iwl_queue_space(&txq->q) > txq->q.low_mark) && | ||
1669 | priv->mac80211_registered && | ||
1670 | (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) | ||
1671 | iwl_wake_queue(priv, txq->swq_id); | ||
1672 | |||
1673 | iwl_txq_check_empty(priv, sta_id, tid, scd_flow); | ||
1674 | } | ||
1675 | } | ||
1676 | EXPORT_SYMBOL(iwl_rx_reply_compressed_ba); | ||
1677 | |||
1678 | #ifdef CONFIG_IWLWIFI_DEBUG | 631 | #ifdef CONFIG_IWLWIFI_DEBUG |
1679 | #define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x | 632 | #define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x |
1680 | 633 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index e276f2a4e835..c9188b9c5651 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -351,11 +351,11 @@ static int iwl3945_send_beacon_cmd(struct iwl_priv *priv) | |||
351 | 351 | ||
352 | static void iwl3945_unset_hw_params(struct iwl_priv *priv) | 352 | static void iwl3945_unset_hw_params(struct iwl_priv *priv) |
353 | { | 353 | { |
354 | if (priv->shared_virt) | 354 | if (priv->_3945.shared_virt) |
355 | dma_free_coherent(&priv->pci_dev->dev, | 355 | dma_free_coherent(&priv->pci_dev->dev, |
356 | sizeof(struct iwl3945_shared), | 356 | sizeof(struct iwl3945_shared), |
357 | priv->shared_virt, | 357 | priv->_3945.shared_virt, |
358 | priv->shared_phys); | 358 | priv->_3945.shared_phys); |
359 | } | 359 | } |
360 | 360 | ||
361 | static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv, | 361 | static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv, |
@@ -504,15 +504,6 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
504 | IWL_DEBUG_TX(priv, "Sending REASSOC frame\n"); | 504 | IWL_DEBUG_TX(priv, "Sending REASSOC frame\n"); |
505 | #endif | 505 | #endif |
506 | 506 | ||
507 | /* drop all non-injected data frame if we are not associated */ | ||
508 | if (ieee80211_is_data(fc) && | ||
509 | !(info->flags & IEEE80211_TX_CTL_INJECTED) && | ||
510 | (!iwl_is_associated(priv) || | ||
511 | ((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id))) { | ||
512 | IWL_DEBUG_DROP(priv, "Dropping - !iwl_is_associated\n"); | ||
513 | goto drop_unlock; | ||
514 | } | ||
515 | |||
516 | spin_unlock_irqrestore(&priv->lock, flags); | 507 | spin_unlock_irqrestore(&priv->lock, flags); |
517 | 508 | ||
518 | hdr_len = ieee80211_hdrlen(fc); | 509 | hdr_len = ieee80211_hdrlen(fc); |
@@ -606,9 +597,9 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
606 | txq->need_update = 0; | 597 | txq->need_update = 0; |
607 | } | 598 | } |
608 | 599 | ||
609 | IWL_DEBUG_TX(priv, "sequence nr = 0X%x \n", | 600 | IWL_DEBUG_TX(priv, "sequence nr = 0X%x\n", |
610 | le16_to_cpu(out_cmd->hdr.sequence)); | 601 | le16_to_cpu(out_cmd->hdr.sequence)); |
611 | IWL_DEBUG_TX(priv, "tx_flags = 0X%x \n", le32_to_cpu(tx_cmd->tx_flags)); | 602 | IWL_DEBUG_TX(priv, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags)); |
612 | iwl_print_hex_dump(priv, IWL_DL_TX, tx_cmd, sizeof(*tx_cmd)); | 603 | iwl_print_hex_dump(priv, IWL_DL_TX, tx_cmd, sizeof(*tx_cmd)); |
613 | iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, | 604 | iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, |
614 | ieee80211_hdrlen(fc)); | 605 | ieee80211_hdrlen(fc)); |
@@ -753,7 +744,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv, | |||
753 | if (iwl_is_associated(priv)) | 744 | if (iwl_is_associated(priv)) |
754 | add_time = | 745 | add_time = |
755 | iwl3945_usecs_to_beacons( | 746 | iwl3945_usecs_to_beacons( |
756 | le64_to_cpu(params->start_time) - priv->last_tsf, | 747 | le64_to_cpu(params->start_time) - priv->_3945.last_tsf, |
757 | le16_to_cpu(priv->rxon_timing.beacon_interval)); | 748 | le16_to_cpu(priv->rxon_timing.beacon_interval)); |
758 | 749 | ||
759 | memset(&spectrum, 0, sizeof(spectrum)); | 750 | memset(&spectrum, 0, sizeof(spectrum)); |
@@ -767,7 +758,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv, | |||
767 | 758 | ||
768 | if (iwl_is_associated(priv)) | 759 | if (iwl_is_associated(priv)) |
769 | spectrum.start_time = | 760 | spectrum.start_time = |
770 | iwl3945_add_beacon_time(priv->last_beacon_time, | 761 | iwl3945_add_beacon_time(priv->_3945.last_beacon_time, |
771 | add_time, | 762 | add_time, |
772 | le16_to_cpu(priv->rxon_timing.beacon_interval)); | 763 | le16_to_cpu(priv->rxon_timing.beacon_interval)); |
773 | else | 764 | else |
@@ -1946,7 +1937,7 @@ static int iwl3945_get_channels_for_scan(struct iwl_priv *priv, | |||
1946 | added++; | 1937 | added++; |
1947 | } | 1938 | } |
1948 | 1939 | ||
1949 | IWL_DEBUG_SCAN(priv, "total channels to scan %d \n", added); | 1940 | IWL_DEBUG_SCAN(priv, "total channels to scan %d\n", added); |
1950 | return added; | 1941 | return added; |
1951 | } | 1942 | } |
1952 | 1943 | ||
@@ -2489,8 +2480,6 @@ static void iwl3945_alive_start(struct iwl_priv *priv) | |||
2489 | goto restart; | 2480 | goto restart; |
2490 | } | 2481 | } |
2491 | 2482 | ||
2492 | iwl_clear_stations_table(priv); | ||
2493 | |||
2494 | rfkill = iwl_read_prph(priv, APMG_RFKILL_REG); | 2483 | rfkill = iwl_read_prph(priv, APMG_RFKILL_REG); |
2495 | IWL_DEBUG_INFO(priv, "RFKILL status: 0x%x\n", rfkill); | 2484 | IWL_DEBUG_INFO(priv, "RFKILL status: 0x%x\n", rfkill); |
2496 | 2485 | ||
@@ -2512,13 +2501,19 @@ static void iwl3945_alive_start(struct iwl_priv *priv) | |||
2512 | /* After the ALIVE response, we can send commands to 3945 uCode */ | 2501 | /* After the ALIVE response, we can send commands to 3945 uCode */ |
2513 | set_bit(STATUS_ALIVE, &priv->status); | 2502 | set_bit(STATUS_ALIVE, &priv->status); |
2514 | 2503 | ||
2504 | if (priv->cfg->ops->lib->recover_from_tx_stall) { | ||
2505 | /* Enable timer to monitor the driver queues */ | ||
2506 | mod_timer(&priv->monitor_recover, | ||
2507 | jiffies + | ||
2508 | msecs_to_jiffies(priv->cfg->monitor_recover_period)); | ||
2509 | } | ||
2510 | |||
2515 | if (iwl_is_rfkill(priv)) | 2511 | if (iwl_is_rfkill(priv)) |
2516 | return; | 2512 | return; |
2517 | 2513 | ||
2518 | ieee80211_wake_queues(priv->hw); | 2514 | ieee80211_wake_queues(priv->hw); |
2519 | 2515 | ||
2520 | priv->active_rate = priv->rates_mask; | 2516 | priv->active_rate = IWL_RATES_MASK; |
2521 | priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK; | ||
2522 | 2517 | ||
2523 | iwl_power_update_mode(priv, true); | 2518 | iwl_power_update_mode(priv, true); |
2524 | 2519 | ||
@@ -2547,17 +2542,6 @@ static void iwl3945_alive_start(struct iwl_priv *priv) | |||
2547 | set_bit(STATUS_READY, &priv->status); | 2542 | set_bit(STATUS_READY, &priv->status); |
2548 | wake_up_interruptible(&priv->wait_command_queue); | 2543 | wake_up_interruptible(&priv->wait_command_queue); |
2549 | 2544 | ||
2550 | /* reassociate for ADHOC mode */ | ||
2551 | if (priv->vif && (priv->iw_mode == NL80211_IFTYPE_ADHOC)) { | ||
2552 | struct sk_buff *beacon = ieee80211_beacon_get(priv->hw, | ||
2553 | priv->vif); | ||
2554 | if (beacon) | ||
2555 | iwl_mac_beacon_update(priv->hw, beacon); | ||
2556 | } | ||
2557 | |||
2558 | if (test_and_clear_bit(STATUS_MODE_PENDING, &priv->status)) | ||
2559 | iwl_set_mode(priv, priv->iw_mode); | ||
2560 | |||
2561 | return; | 2545 | return; |
2562 | 2546 | ||
2563 | restart: | 2547 | restart: |
@@ -2579,7 +2563,8 @@ static void __iwl3945_down(struct iwl_priv *priv) | |||
2579 | if (!exit_pending) | 2563 | if (!exit_pending) |
2580 | set_bit(STATUS_EXIT_PENDING, &priv->status); | 2564 | set_bit(STATUS_EXIT_PENDING, &priv->status); |
2581 | 2565 | ||
2582 | iwl_clear_stations_table(priv); | 2566 | /* Station information will now be cleared in device */ |
2567 | iwl_clear_ucode_stations(priv, true); | ||
2583 | 2568 | ||
2584 | /* Unblock any waiting calls */ | 2569 | /* Unblock any waiting calls */ |
2585 | wake_up_interruptible_all(&priv->wait_command_queue); | 2570 | wake_up_interruptible_all(&priv->wait_command_queue); |
@@ -2713,12 +2698,10 @@ static int __iwl3945_up(struct iwl_priv *priv) | |||
2713 | 2698 | ||
2714 | for (i = 0; i < MAX_HW_RESTARTS; i++) { | 2699 | for (i = 0; i < MAX_HW_RESTARTS; i++) { |
2715 | 2700 | ||
2716 | iwl_clear_stations_table(priv); | ||
2717 | |||
2718 | /* load bootstrap state machine, | 2701 | /* load bootstrap state machine, |
2719 | * load bootstrap program into processor's memory, | 2702 | * load bootstrap program into processor's memory, |
2720 | * prepare to load the "initialize" uCode */ | 2703 | * prepare to load the "initialize" uCode */ |
2721 | priv->cfg->ops->lib->load_ucode(priv); | 2704 | rc = priv->cfg->ops->lib->load_ucode(priv); |
2722 | 2705 | ||
2723 | if (rc) { | 2706 | if (rc) { |
2724 | IWL_ERR(priv, | 2707 | IWL_ERR(priv, |
@@ -2786,7 +2769,7 @@ static void iwl3945_bg_alive_start(struct work_struct *data) | |||
2786 | static void iwl3945_rfkill_poll(struct work_struct *data) | 2769 | static void iwl3945_rfkill_poll(struct work_struct *data) |
2787 | { | 2770 | { |
2788 | struct iwl_priv *priv = | 2771 | struct iwl_priv *priv = |
2789 | container_of(data, struct iwl_priv, rfkill_poll.work); | 2772 | container_of(data, struct iwl_priv, _3945.rfkill_poll.work); |
2790 | bool old_rfkill = test_bit(STATUS_RF_KILL_HW, &priv->status); | 2773 | bool old_rfkill = test_bit(STATUS_RF_KILL_HW, &priv->status); |
2791 | bool new_rfkill = !(iwl_read32(priv, CSR_GP_CNTRL) | 2774 | bool new_rfkill = !(iwl_read32(priv, CSR_GP_CNTRL) |
2792 | & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW); | 2775 | & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW); |
@@ -2805,7 +2788,7 @@ static void iwl3945_rfkill_poll(struct work_struct *data) | |||
2805 | 2788 | ||
2806 | /* Keep this running, even if radio now enabled. This will be | 2789 | /* Keep this running, even if radio now enabled. This will be |
2807 | * cancelled in mac_start() if system decides to start again */ | 2790 | * cancelled in mac_start() if system decides to start again */ |
2808 | queue_delayed_work(priv->workqueue, &priv->rfkill_poll, | 2791 | queue_delayed_work(priv->workqueue, &priv->_3945.rfkill_poll, |
2809 | round_jiffies_relative(2 * HZ)); | 2792 | round_jiffies_relative(2 * HZ)); |
2810 | 2793 | ||
2811 | } | 2794 | } |
@@ -2820,7 +2803,6 @@ static void iwl3945_bg_request_scan(struct work_struct *data) | |||
2820 | .len = sizeof(struct iwl3945_scan_cmd), | 2803 | .len = sizeof(struct iwl3945_scan_cmd), |
2821 | .flags = CMD_SIZE_HUGE, | 2804 | .flags = CMD_SIZE_HUGE, |
2822 | }; | 2805 | }; |
2823 | int rc = 0; | ||
2824 | struct iwl3945_scan_cmd *scan; | 2806 | struct iwl3945_scan_cmd *scan; |
2825 | struct ieee80211_conf *conf = NULL; | 2807 | struct ieee80211_conf *conf = NULL; |
2826 | u8 n_probes = 0; | 2808 | u8 n_probes = 0; |
@@ -2848,7 +2830,6 @@ static void iwl3945_bg_request_scan(struct work_struct *data) | |||
2848 | if (test_bit(STATUS_SCAN_HW, &priv->status)) { | 2830 | if (test_bit(STATUS_SCAN_HW, &priv->status)) { |
2849 | IWL_DEBUG_INFO(priv, "Multiple concurrent scan requests " | 2831 | IWL_DEBUG_INFO(priv, "Multiple concurrent scan requests " |
2850 | "Ignoring second request.\n"); | 2832 | "Ignoring second request.\n"); |
2851 | rc = -EIO; | ||
2852 | goto done; | 2833 | goto done; |
2853 | } | 2834 | } |
2854 | 2835 | ||
@@ -2883,7 +2864,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data) | |||
2883 | priv->scan = kmalloc(sizeof(struct iwl3945_scan_cmd) + | 2864 | priv->scan = kmalloc(sizeof(struct iwl3945_scan_cmd) + |
2884 | IWL_MAX_SCAN_SIZE, GFP_KERNEL); | 2865 | IWL_MAX_SCAN_SIZE, GFP_KERNEL); |
2885 | if (!priv->scan) { | 2866 | if (!priv->scan) { |
2886 | rc = -ENOMEM; | 2867 | IWL_DEBUG_SCAN(priv, "Fail to allocate scan memory\n"); |
2887 | goto done; | 2868 | goto done; |
2888 | } | 2869 | } |
2889 | } | 2870 | } |
@@ -2926,7 +2907,9 @@ static void iwl3945_bg_request_scan(struct work_struct *data) | |||
2926 | scan_suspend_time, interval); | 2907 | scan_suspend_time, interval); |
2927 | } | 2908 | } |
2928 | 2909 | ||
2929 | if (priv->scan_request->n_ssids) { | 2910 | if (priv->is_internal_short_scan) { |
2911 | IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n"); | ||
2912 | } else if (priv->scan_request->n_ssids) { | ||
2930 | int i, p = 0; | 2913 | int i, p = 0; |
2931 | IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); | 2914 | IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); |
2932 | for (i = 0; i < priv->scan_request->n_ssids; i++) { | 2915 | for (i = 0; i < priv->scan_request->n_ssids; i++) { |
@@ -2973,13 +2956,20 @@ static void iwl3945_bg_request_scan(struct work_struct *data) | |||
2973 | goto done; | 2956 | goto done; |
2974 | } | 2957 | } |
2975 | 2958 | ||
2976 | scan->tx_cmd.len = cpu_to_le16( | 2959 | if (!priv->is_internal_short_scan) { |
2960 | scan->tx_cmd.len = cpu_to_le16( | ||
2977 | iwl_fill_probe_req(priv, | 2961 | iwl_fill_probe_req(priv, |
2978 | (struct ieee80211_mgmt *)scan->data, | 2962 | (struct ieee80211_mgmt *)scan->data, |
2979 | priv->scan_request->ie, | 2963 | priv->scan_request->ie, |
2980 | priv->scan_request->ie_len, | 2964 | priv->scan_request->ie_len, |
2981 | IWL_MAX_SCAN_SIZE - sizeof(*scan))); | 2965 | IWL_MAX_SCAN_SIZE - sizeof(*scan))); |
2982 | 2966 | } else { | |
2967 | scan->tx_cmd.len = cpu_to_le16( | ||
2968 | iwl_fill_probe_req(priv, | ||
2969 | (struct ieee80211_mgmt *)scan->data, | ||
2970 | NULL, 0, | ||
2971 | IWL_MAX_SCAN_SIZE - sizeof(*scan))); | ||
2972 | } | ||
2983 | /* select Rx antennas */ | 2973 | /* select Rx antennas */ |
2984 | scan->flags |= iwl3945_get_antenna_flags(priv); | 2974 | scan->flags |= iwl3945_get_antenna_flags(priv); |
2985 | 2975 | ||
@@ -3001,8 +2991,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data) | |||
3001 | scan->len = cpu_to_le16(cmd.len); | 2991 | scan->len = cpu_to_le16(cmd.len); |
3002 | 2992 | ||
3003 | set_bit(STATUS_SCAN_HW, &priv->status); | 2993 | set_bit(STATUS_SCAN_HW, &priv->status); |
3004 | rc = iwl_send_cmd_sync(priv, &cmd); | 2994 | if (iwl_send_cmd_sync(priv, &cmd)) |
3005 | if (rc) | ||
3006 | goto done; | 2995 | goto done; |
3007 | 2996 | ||
3008 | queue_delayed_work(priv->workqueue, &priv->scan_check, | 2997 | queue_delayed_work(priv->workqueue, &priv->scan_check, |
@@ -3134,12 +3123,13 @@ void iwl3945_post_associate(struct iwl_priv *priv) | |||
3134 | case NL80211_IFTYPE_ADHOC: | 3123 | case NL80211_IFTYPE_ADHOC: |
3135 | 3124 | ||
3136 | priv->assoc_id = 1; | 3125 | priv->assoc_id = 1; |
3137 | iwl_add_station(priv, priv->bssid, 0, CMD_SYNC, NULL); | 3126 | iwl_add_local_station(priv, priv->bssid, false); |
3138 | iwl3945_sync_sta(priv, IWL_STA_ID, | 3127 | iwl3945_sync_sta(priv, IWL_STA_ID, |
3139 | (priv->band == IEEE80211_BAND_5GHZ) ? | 3128 | (priv->band == IEEE80211_BAND_5GHZ) ? |
3140 | IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP, | 3129 | IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP, |
3141 | CMD_ASYNC); | 3130 | CMD_ASYNC); |
3142 | iwl3945_rate_scale_init(priv->hw, IWL_STA_ID); | 3131 | iwl3945_rate_scale_init(priv->hw, IWL_STA_ID); |
3132 | |||
3143 | iwl3945_send_beacon_cmd(priv); | 3133 | iwl3945_send_beacon_cmd(priv); |
3144 | 3134 | ||
3145 | break; | 3135 | break; |
@@ -3150,8 +3140,6 @@ void iwl3945_post_associate(struct iwl_priv *priv) | |||
3150 | break; | 3140 | break; |
3151 | } | 3141 | } |
3152 | 3142 | ||
3153 | iwl_activate_qos(priv, 0); | ||
3154 | |||
3155 | /* we have just associated, don't start scan too early */ | 3143 | /* we have just associated, don't start scan too early */ |
3156 | priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN; | 3144 | priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN; |
3157 | } | 3145 | } |
@@ -3212,7 +3200,7 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw) | |||
3212 | 3200 | ||
3213 | /* ucode is running and will send rfkill notifications, | 3201 | /* ucode is running and will send rfkill notifications, |
3214 | * no need to poll the killswitch state anymore */ | 3202 | * no need to poll the killswitch state anymore */ |
3215 | cancel_delayed_work(&priv->rfkill_poll); | 3203 | cancel_delayed_work(&priv->_3945.rfkill_poll); |
3216 | 3204 | ||
3217 | iwl_led_start(priv); | 3205 | iwl_led_start(priv); |
3218 | 3206 | ||
@@ -3253,7 +3241,7 @@ static void iwl3945_mac_stop(struct ieee80211_hw *hw) | |||
3253 | flush_workqueue(priv->workqueue); | 3241 | flush_workqueue(priv->workqueue); |
3254 | 3242 | ||
3255 | /* start polling the killswitch state again */ | 3243 | /* start polling the killswitch state again */ |
3256 | queue_delayed_work(priv->workqueue, &priv->rfkill_poll, | 3244 | queue_delayed_work(priv->workqueue, &priv->_3945.rfkill_poll, |
3257 | round_jiffies_relative(2 * HZ)); | 3245 | round_jiffies_relative(2 * HZ)); |
3258 | 3246 | ||
3259 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 3247 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
@@ -3324,7 +3312,7 @@ void iwl3945_config_ap(struct iwl_priv *priv) | |||
3324 | /* restore RXON assoc */ | 3312 | /* restore RXON assoc */ |
3325 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; | 3313 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; |
3326 | iwlcore_commit_rxon(priv); | 3314 | iwlcore_commit_rxon(priv); |
3327 | iwl_add_station(priv, iwl_bcast_addr, 0, CMD_SYNC, NULL); | 3315 | iwl_add_local_station(priv, iwl_bcast_addr, false); |
3328 | } | 3316 | } |
3329 | iwl3945_send_beacon_cmd(priv); | 3317 | iwl3945_send_beacon_cmd(priv); |
3330 | 3318 | ||
@@ -3365,7 +3353,6 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3365 | 3353 | ||
3366 | mutex_lock(&priv->mutex); | 3354 | mutex_lock(&priv->mutex); |
3367 | iwl_scan_cancel_timeout(priv, 100); | 3355 | iwl_scan_cancel_timeout(priv, 100); |
3368 | mutex_unlock(&priv->mutex); | ||
3369 | 3356 | ||
3370 | switch (cmd) { | 3357 | switch (cmd) { |
3371 | case SET_KEY: | 3358 | case SET_KEY: |
@@ -3386,11 +3373,44 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3386 | ret = -EINVAL; | 3373 | ret = -EINVAL; |
3387 | } | 3374 | } |
3388 | 3375 | ||
3376 | mutex_unlock(&priv->mutex); | ||
3389 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 3377 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
3390 | 3378 | ||
3391 | return ret; | 3379 | return ret; |
3392 | } | 3380 | } |
3393 | 3381 | ||
3382 | static int iwl3945_mac_sta_add(struct ieee80211_hw *hw, | ||
3383 | struct ieee80211_vif *vif, | ||
3384 | struct ieee80211_sta *sta) | ||
3385 | { | ||
3386 | struct iwl_priv *priv = hw->priv; | ||
3387 | int ret; | ||
3388 | bool is_ap = priv->iw_mode == NL80211_IFTYPE_STATION; | ||
3389 | u8 sta_id; | ||
3390 | |||
3391 | IWL_DEBUG_INFO(priv, "received request to add station %pM\n", | ||
3392 | sta->addr); | ||
3393 | |||
3394 | ret = iwl_add_station_common(priv, sta->addr, is_ap, &sta->ht_cap, | ||
3395 | &sta_id); | ||
3396 | if (ret) { | ||
3397 | IWL_ERR(priv, "Unable to add station %pM (%d)\n", | ||
3398 | sta->addr, ret); | ||
3399 | /* Should we return success if return code is EEXIST ? */ | ||
3400 | return ret; | ||
3401 | } | ||
3402 | |||
3403 | /* Initialize rate scaling */ | ||
3404 | IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n", | ||
3405 | sta->addr); | ||
3406 | iwl3945_rs_rate_init(priv, sta, sta_id); | ||
3407 | |||
3408 | return 0; | ||
3409 | |||
3410 | |||
3411 | |||
3412 | return ret; | ||
3413 | } | ||
3394 | /***************************************************************************** | 3414 | /***************************************************************************** |
3395 | * | 3415 | * |
3396 | * sysfs attributes | 3416 | * sysfs attributes |
@@ -3590,7 +3610,7 @@ static ssize_t store_measurement(struct device *d, | |||
3590 | struct iwl_priv *priv = dev_get_drvdata(d); | 3610 | struct iwl_priv *priv = dev_get_drvdata(d); |
3591 | struct ieee80211_measurement_params params = { | 3611 | struct ieee80211_measurement_params params = { |
3592 | .channel = le16_to_cpu(priv->active_rxon.channel), | 3612 | .channel = le16_to_cpu(priv->active_rxon.channel), |
3593 | .start_time = cpu_to_le64(priv->last_tsf), | 3613 | .start_time = cpu_to_le64(priv->_3945.last_tsf), |
3594 | .duration = cpu_to_le16(1), | 3614 | .duration = cpu_to_le16(1), |
3595 | }; | 3615 | }; |
3596 | u8 type = IWL_MEASURE_BASIC; | 3616 | u8 type = IWL_MEASURE_BASIC; |
@@ -3660,7 +3680,7 @@ static ssize_t show_statistics(struct device *d, | |||
3660 | struct iwl_priv *priv = dev_get_drvdata(d); | 3680 | struct iwl_priv *priv = dev_get_drvdata(d); |
3661 | u32 size = sizeof(struct iwl3945_notif_statistics); | 3681 | u32 size = sizeof(struct iwl3945_notif_statistics); |
3662 | u32 len = 0, ofs = 0; | 3682 | u32 len = 0, ofs = 0; |
3663 | u8 *data = (u8 *)&priv->statistics_39; | 3683 | u8 *data = (u8 *)&priv->_3945.statistics; |
3664 | int rc = 0; | 3684 | int rc = 0; |
3665 | 3685 | ||
3666 | if (!iwl_is_alive(priv)) | 3686 | if (!iwl_is_alive(priv)) |
@@ -3773,7 +3793,7 @@ static void iwl3945_setup_deferred_work(struct iwl_priv *priv) | |||
3773 | INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update); | 3793 | INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update); |
3774 | INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start); | 3794 | INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start); |
3775 | INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start); | 3795 | INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start); |
3776 | INIT_DELAYED_WORK(&priv->rfkill_poll, iwl3945_rfkill_poll); | 3796 | INIT_DELAYED_WORK(&priv->_3945.rfkill_poll, iwl3945_rfkill_poll); |
3777 | INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed); | 3797 | INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed); |
3778 | INIT_WORK(&priv->request_scan, iwl3945_bg_request_scan); | 3798 | INIT_WORK(&priv->request_scan, iwl3945_bg_request_scan); |
3779 | INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan); | 3799 | INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan); |
@@ -3781,6 +3801,13 @@ static void iwl3945_setup_deferred_work(struct iwl_priv *priv) | |||
3781 | 3801 | ||
3782 | iwl3945_hw_setup_deferred_work(priv); | 3802 | iwl3945_hw_setup_deferred_work(priv); |
3783 | 3803 | ||
3804 | if (priv->cfg->ops->lib->recover_from_tx_stall) { | ||
3805 | init_timer(&priv->monitor_recover); | ||
3806 | priv->monitor_recover.data = (unsigned long)priv; | ||
3807 | priv->monitor_recover.function = | ||
3808 | priv->cfg->ops->lib->recover_from_tx_stall; | ||
3809 | } | ||
3810 | |||
3784 | tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) | 3811 | tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) |
3785 | iwl3945_irq_tasklet, (unsigned long)priv); | 3812 | iwl3945_irq_tasklet, (unsigned long)priv); |
3786 | } | 3813 | } |
@@ -3793,6 +3820,8 @@ static void iwl3945_cancel_deferred_work(struct iwl_priv *priv) | |||
3793 | cancel_delayed_work(&priv->scan_check); | 3820 | cancel_delayed_work(&priv->scan_check); |
3794 | cancel_delayed_work(&priv->alive_start); | 3821 | cancel_delayed_work(&priv->alive_start); |
3795 | cancel_work_sync(&priv->beacon_update); | 3822 | cancel_work_sync(&priv->beacon_update); |
3823 | if (priv->cfg->ops->lib->recover_from_tx_stall) | ||
3824 | del_timer_sync(&priv->monitor_recover); | ||
3796 | } | 3825 | } |
3797 | 3826 | ||
3798 | static struct attribute *iwl3945_sysfs_entries[] = { | 3827 | static struct attribute *iwl3945_sysfs_entries[] = { |
@@ -3830,7 +3859,9 @@ static struct ieee80211_ops iwl3945_hw_ops = { | |||
3830 | .conf_tx = iwl_mac_conf_tx, | 3859 | .conf_tx = iwl_mac_conf_tx, |
3831 | .reset_tsf = iwl_mac_reset_tsf, | 3860 | .reset_tsf = iwl_mac_reset_tsf, |
3832 | .bss_info_changed = iwl_bss_info_changed, | 3861 | .bss_info_changed = iwl_bss_info_changed, |
3833 | .hw_scan = iwl_mac_hw_scan | 3862 | .hw_scan = iwl_mac_hw_scan, |
3863 | .sta_add = iwl3945_mac_sta_add, | ||
3864 | .sta_remove = iwl_mac_sta_remove, | ||
3834 | }; | 3865 | }; |
3835 | 3866 | ||
3836 | static int iwl3945_init_drv(struct iwl_priv *priv) | 3867 | static int iwl3945_init_drv(struct iwl_priv *priv) |
@@ -3849,9 +3880,6 @@ static int iwl3945_init_drv(struct iwl_priv *priv) | |||
3849 | mutex_init(&priv->mutex); | 3880 | mutex_init(&priv->mutex); |
3850 | mutex_init(&priv->sync_cmd_mutex); | 3881 | mutex_init(&priv->sync_cmd_mutex); |
3851 | 3882 | ||
3852 | /* Clear the driver's (not device's) station table */ | ||
3853 | iwl_clear_stations_table(priv); | ||
3854 | |||
3855 | priv->ieee_channels = NULL; | 3883 | priv->ieee_channels = NULL; |
3856 | priv->ieee_rates = NULL; | 3884 | priv->ieee_rates = NULL; |
3857 | priv->band = IEEE80211_BAND_2GHZ; | 3885 | priv->band = IEEE80211_BAND_2GHZ; |
@@ -3859,12 +3887,6 @@ static int iwl3945_init_drv(struct iwl_priv *priv) | |||
3859 | priv->iw_mode = NL80211_IFTYPE_STATION; | 3887 | priv->iw_mode = NL80211_IFTYPE_STATION; |
3860 | priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; | 3888 | priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; |
3861 | 3889 | ||
3862 | iwl_reset_qos(priv); | ||
3863 | |||
3864 | priv->qos_data.qos_active = 0; | ||
3865 | priv->qos_data.qos_cap.val = 0; | ||
3866 | |||
3867 | priv->rates_mask = IWL_RATES_MASK; | ||
3868 | priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER; | 3890 | priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER; |
3869 | 3891 | ||
3870 | if (eeprom->version < EEPROM_3945_EEPROM_VERSION) { | 3892 | if (eeprom->version < EEPROM_3945_EEPROM_VERSION) { |
@@ -4129,7 +4151,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
4129 | IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err); | 4151 | IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err); |
4130 | 4152 | ||
4131 | /* Start monitoring the killswitch */ | 4153 | /* Start monitoring the killswitch */ |
4132 | queue_delayed_work(priv->workqueue, &priv->rfkill_poll, | 4154 | queue_delayed_work(priv->workqueue, &priv->_3945.rfkill_poll, |
4133 | 2 * HZ); | 4155 | 2 * HZ); |
4134 | 4156 | ||
4135 | return 0; | 4157 | return 0; |
@@ -4203,7 +4225,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) | |||
4203 | 4225 | ||
4204 | sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group); | 4226 | sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group); |
4205 | 4227 | ||
4206 | cancel_delayed_work_sync(&priv->rfkill_poll); | 4228 | cancel_delayed_work_sync(&priv->_3945.rfkill_poll); |
4207 | 4229 | ||
4208 | iwl3945_dealloc_ucode_pci(priv); | 4230 | iwl3945_dealloc_ucode_pci(priv); |
4209 | 4231 | ||
@@ -4212,7 +4234,6 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) | |||
4212 | iwl3945_hw_txq_ctx_free(priv); | 4234 | iwl3945_hw_txq_ctx_free(priv); |
4213 | 4235 | ||
4214 | iwl3945_unset_hw_params(priv); | 4236 | iwl3945_unset_hw_params(priv); |
4215 | iwl_clear_stations_table(priv); | ||
4216 | 4237 | ||
4217 | /*netif_stop_queue(dev); */ | 4238 | /*netif_stop_queue(dev); */ |
4218 | flush_workqueue(priv->workqueue); | 4239 | flush_workqueue(priv->workqueue); |
diff --git a/drivers/net/wireless/iwmc3200wifi/Kconfig b/drivers/net/wireless/iwmc3200wifi/Kconfig index b9d34a766964..03f998d098c5 100644 --- a/drivers/net/wireless/iwmc3200wifi/Kconfig +++ b/drivers/net/wireless/iwmc3200wifi/Kconfig | |||
@@ -17,7 +17,7 @@ config IWM | |||
17 | config IWM_DEBUG | 17 | config IWM_DEBUG |
18 | bool "Enable full debugging output in iwmc3200wifi" | 18 | bool "Enable full debugging output in iwmc3200wifi" |
19 | depends on IWM && DEBUG_FS | 19 | depends on IWM && DEBUG_FS |
20 | ---help--- | 20 | help |
21 | This option will enable debug tracing and setting for iwm | 21 | This option will enable debug tracing and setting for iwm |
22 | 22 | ||
23 | You can set the debug level and module through debugfs. By | 23 | You can set the debug level and module through debugfs. By |
@@ -30,3 +30,10 @@ config IWM_DEBUG | |||
30 | Or, if you want the full debug, for all modules: | 30 | Or, if you want the full debug, for all modules: |
31 | echo 0xff > /sys/kernel/debug/iwm/phyN/debug/level | 31 | echo 0xff > /sys/kernel/debug/iwm/phyN/debug/level |
32 | echo 0xff > /sys/kernel/debug/iwm/phyN/debug/modules | 32 | echo 0xff > /sys/kernel/debug/iwm/phyN/debug/modules |
33 | |||
34 | config IWM_TRACING | ||
35 | bool "Enable event tracing for iwmc3200wifi" | ||
36 | depends on IWM && EVENT_TRACING | ||
37 | help | ||
38 | Say Y here to trace all the commands and responses between | ||
39 | the driver and firmware (including TX/RX frames) with ftrace. | ||
diff --git a/drivers/net/wireless/iwmc3200wifi/Makefile b/drivers/net/wireless/iwmc3200wifi/Makefile index d34291b652d3..aeed5cd80819 100644 --- a/drivers/net/wireless/iwmc3200wifi/Makefile +++ b/drivers/net/wireless/iwmc3200wifi/Makefile | |||
@@ -3,3 +3,6 @@ iwmc3200wifi-objs += main.o netdev.o rx.o tx.o sdio.o hal.o fw.o | |||
3 | iwmc3200wifi-objs += commands.o cfg80211.o eeprom.o | 3 | iwmc3200wifi-objs += commands.o cfg80211.o eeprom.o |
4 | 4 | ||
5 | iwmc3200wifi-$(CONFIG_IWM_DEBUG) += debugfs.o | 5 | iwmc3200wifi-$(CONFIG_IWM_DEBUG) += debugfs.o |
6 | iwmc3200wifi-$(CONFIG_IWM_TRACING) += trace.o | ||
7 | |||
8 | CFLAGS_trace.o := -I$(src) | ||
diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c index 7c4f44a9c3e6..fc239a32cb6b 100644 --- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c +++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c | |||
@@ -263,7 +263,7 @@ static int iwm_cfg80211_get_station(struct wiphy *wiphy, | |||
263 | int iwm_cfg80211_inform_bss(struct iwm_priv *iwm) | 263 | int iwm_cfg80211_inform_bss(struct iwm_priv *iwm) |
264 | { | 264 | { |
265 | struct wiphy *wiphy = iwm_to_wiphy(iwm); | 265 | struct wiphy *wiphy = iwm_to_wiphy(iwm); |
266 | struct iwm_bss_info *bss, *next; | 266 | struct iwm_bss_info *bss; |
267 | struct iwm_umac_notif_bss_info *umac_bss; | 267 | struct iwm_umac_notif_bss_info *umac_bss; |
268 | struct ieee80211_mgmt *mgmt; | 268 | struct ieee80211_mgmt *mgmt; |
269 | struct ieee80211_channel *channel; | 269 | struct ieee80211_channel *channel; |
@@ -271,7 +271,7 @@ int iwm_cfg80211_inform_bss(struct iwm_priv *iwm) | |||
271 | s32 signal; | 271 | s32 signal; |
272 | int freq; | 272 | int freq; |
273 | 273 | ||
274 | list_for_each_entry_safe(bss, next, &iwm->bss_list, node) { | 274 | list_for_each_entry(bss, &iwm->bss_list, node) { |
275 | umac_bss = bss->bss; | 275 | umac_bss = bss->bss; |
276 | mgmt = (struct ieee80211_mgmt *)(umac_bss->frame_buf); | 276 | mgmt = (struct ieee80211_mgmt *)(umac_bss->frame_buf); |
277 | 277 | ||
@@ -725,23 +725,26 @@ static int iwm_cfg80211_set_power_mgmt(struct wiphy *wiphy, | |||
725 | CFG_POWER_INDEX, iwm->conf.power_index); | 725 | CFG_POWER_INDEX, iwm->conf.power_index); |
726 | } | 726 | } |
727 | 727 | ||
728 | int iwm_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *netdev, | 728 | static int iwm_cfg80211_set_pmksa(struct wiphy *wiphy, |
729 | struct cfg80211_pmksa *pmksa) | 729 | struct net_device *netdev, |
730 | struct cfg80211_pmksa *pmksa) | ||
730 | { | 731 | { |
731 | struct iwm_priv *iwm = wiphy_to_iwm(wiphy); | 732 | struct iwm_priv *iwm = wiphy_to_iwm(wiphy); |
732 | 733 | ||
733 | return iwm_send_pmkid_update(iwm, pmksa, IWM_CMD_PMKID_ADD); | 734 | return iwm_send_pmkid_update(iwm, pmksa, IWM_CMD_PMKID_ADD); |
734 | } | 735 | } |
735 | 736 | ||
736 | int iwm_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *netdev, | 737 | static int iwm_cfg80211_del_pmksa(struct wiphy *wiphy, |
737 | struct cfg80211_pmksa *pmksa) | 738 | struct net_device *netdev, |
739 | struct cfg80211_pmksa *pmksa) | ||
738 | { | 740 | { |
739 | struct iwm_priv *iwm = wiphy_to_iwm(wiphy); | 741 | struct iwm_priv *iwm = wiphy_to_iwm(wiphy); |
740 | 742 | ||
741 | return iwm_send_pmkid_update(iwm, pmksa, IWM_CMD_PMKID_DEL); | 743 | return iwm_send_pmkid_update(iwm, pmksa, IWM_CMD_PMKID_DEL); |
742 | } | 744 | } |
743 | 745 | ||
744 | int iwm_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev) | 746 | static int iwm_cfg80211_flush_pmksa(struct wiphy *wiphy, |
747 | struct net_device *netdev) | ||
745 | { | 748 | { |
746 | struct iwm_priv *iwm = wiphy_to_iwm(wiphy); | 749 | struct iwm_priv *iwm = wiphy_to_iwm(wiphy); |
747 | struct cfg80211_pmksa pmksa; | 750 | struct cfg80211_pmksa pmksa; |
diff --git a/drivers/net/wireless/iwmc3200wifi/commands.c b/drivers/net/wireless/iwmc3200wifi/commands.c index 1e41ad0fcad5..b5cbd2bfd52a 100644 --- a/drivers/net/wireless/iwmc3200wifi/commands.c +++ b/drivers/net/wireless/iwmc3200wifi/commands.c | |||
@@ -506,7 +506,7 @@ static int iwm_target_read(struct iwm_priv *iwm, __le32 address, | |||
506 | return ret; | 506 | return ret; |
507 | } | 507 | } |
508 | 508 | ||
509 | /* When succeding, the send_target routine returns the seq number */ | 509 | /* When succeeding, the send_target routine returns the seq number */ |
510 | seq_num = ret; | 510 | seq_num = ret; |
511 | 511 | ||
512 | ret = wait_event_interruptible_timeout(iwm->nonwifi_queue, | 512 | ret = wait_event_interruptible_timeout(iwm->nonwifi_queue, |
@@ -781,10 +781,9 @@ int iwm_send_mlme_profile(struct iwm_priv *iwm) | |||
781 | return 0; | 781 | return 0; |
782 | } | 782 | } |
783 | 783 | ||
784 | int iwm_invalidate_mlme_profile(struct iwm_priv *iwm) | 784 | int __iwm_invalidate_mlme_profile(struct iwm_priv *iwm) |
785 | { | 785 | { |
786 | struct iwm_umac_invalidate_profile invalid; | 786 | struct iwm_umac_invalidate_profile invalid; |
787 | int ret; | ||
788 | 787 | ||
789 | invalid.hdr.oid = UMAC_WIFI_IF_CMD_INVALIDATE_PROFILE; | 788 | invalid.hdr.oid = UMAC_WIFI_IF_CMD_INVALIDATE_PROFILE; |
790 | invalid.hdr.buf_size = | 789 | invalid.hdr.buf_size = |
@@ -793,7 +792,14 @@ int iwm_invalidate_mlme_profile(struct iwm_priv *iwm) | |||
793 | 792 | ||
794 | invalid.reason = WLAN_REASON_UNSPECIFIED; | 793 | invalid.reason = WLAN_REASON_UNSPECIFIED; |
795 | 794 | ||
796 | ret = iwm_send_wifi_if_cmd(iwm, &invalid, sizeof(invalid), 1); | 795 | return iwm_send_wifi_if_cmd(iwm, &invalid, sizeof(invalid), 1); |
796 | } | ||
797 | |||
798 | int iwm_invalidate_mlme_profile(struct iwm_priv *iwm) | ||
799 | { | ||
800 | int ret; | ||
801 | |||
802 | ret = __iwm_invalidate_mlme_profile(iwm); | ||
797 | if (ret) | 803 | if (ret) |
798 | return ret; | 804 | return ret; |
799 | 805 | ||
diff --git a/drivers/net/wireless/iwmc3200wifi/commands.h b/drivers/net/wireless/iwmc3200wifi/commands.h index 3dfd9f0e9003..7e16bcf59978 100644 --- a/drivers/net/wireless/iwmc3200wifi/commands.h +++ b/drivers/net/wireless/iwmc3200wifi/commands.h | |||
@@ -488,6 +488,7 @@ int iwm_umac_set_config_var(struct iwm_priv *iwm, u16 key, | |||
488 | void *payload, u16 payload_size); | 488 | void *payload, u16 payload_size); |
489 | int iwm_send_umac_config(struct iwm_priv *iwm, __le32 reset_flags); | 489 | int iwm_send_umac_config(struct iwm_priv *iwm, __le32 reset_flags); |
490 | int iwm_send_mlme_profile(struct iwm_priv *iwm); | 490 | int iwm_send_mlme_profile(struct iwm_priv *iwm); |
491 | int __iwm_invalidate_mlme_profile(struct iwm_priv *iwm); | ||
491 | int iwm_invalidate_mlme_profile(struct iwm_priv *iwm); | 492 | int iwm_invalidate_mlme_profile(struct iwm_priv *iwm); |
492 | int iwm_send_packet(struct iwm_priv *iwm, struct sk_buff *skb, int pool_id); | 493 | int iwm_send_packet(struct iwm_priv *iwm, struct sk_buff *skb, int pool_id); |
493 | int iwm_set_tx_key(struct iwm_priv *iwm, u8 key_idx); | 494 | int iwm_set_tx_key(struct iwm_priv *iwm, u8 key_idx); |
diff --git a/drivers/net/wireless/iwmc3200wifi/debugfs.c b/drivers/net/wireless/iwmc3200wifi/debugfs.c index be992ca41cf1..48930c1a0f76 100644 --- a/drivers/net/wireless/iwmc3200wifi/debugfs.c +++ b/drivers/net/wireless/iwmc3200wifi/debugfs.c | |||
@@ -265,7 +265,7 @@ static ssize_t iwm_debugfs_rx_ticket_read(struct file *filp, | |||
265 | size_t count, loff_t *ppos) | 265 | size_t count, loff_t *ppos) |
266 | { | 266 | { |
267 | struct iwm_priv *iwm = filp->private_data; | 267 | struct iwm_priv *iwm = filp->private_data; |
268 | struct iwm_rx_ticket_node *ticket, *next; | 268 | struct iwm_rx_ticket_node *ticket; |
269 | char *buf; | 269 | char *buf; |
270 | int buf_len = 4096, i; | 270 | int buf_len = 4096, i; |
271 | size_t len = 0; | 271 | size_t len = 0; |
@@ -280,7 +280,8 @@ static ssize_t iwm_debugfs_rx_ticket_read(struct file *filp, | |||
280 | if (!buf) | 280 | if (!buf) |
281 | return -ENOMEM; | 281 | return -ENOMEM; |
282 | 282 | ||
283 | list_for_each_entry_safe(ticket, next, &iwm->rx_tickets, node) { | 283 | spin_lock(&iwm->ticket_lock); |
284 | list_for_each_entry(ticket, &iwm->rx_tickets, node) { | ||
284 | len += snprintf(buf + len, buf_len - len, "Ticket #%d\n", | 285 | len += snprintf(buf + len, buf_len - len, "Ticket #%d\n", |
285 | ticket->ticket->id); | 286 | ticket->ticket->id); |
286 | len += snprintf(buf + len, buf_len - len, "\taction: 0x%x\n", | 287 | len += snprintf(buf + len, buf_len - len, "\taction: 0x%x\n", |
@@ -288,14 +289,17 @@ static ssize_t iwm_debugfs_rx_ticket_read(struct file *filp, | |||
288 | len += snprintf(buf + len, buf_len - len, "\tflags: 0x%x\n", | 289 | len += snprintf(buf + len, buf_len - len, "\tflags: 0x%x\n", |
289 | ticket->ticket->flags); | 290 | ticket->ticket->flags); |
290 | } | 291 | } |
292 | spin_unlock(&iwm->ticket_lock); | ||
291 | 293 | ||
292 | for (i = 0; i < IWM_RX_ID_HASH; i++) { | 294 | for (i = 0; i < IWM_RX_ID_HASH; i++) { |
293 | struct iwm_rx_packet *packet, *nxt; | 295 | struct iwm_rx_packet *packet; |
294 | struct list_head *pkt_list = &iwm->rx_packets[i]; | 296 | struct list_head *pkt_list = &iwm->rx_packets[i]; |
297 | |||
295 | if (!list_empty(pkt_list)) { | 298 | if (!list_empty(pkt_list)) { |
296 | len += snprintf(buf + len, buf_len - len, | 299 | len += snprintf(buf + len, buf_len - len, |
297 | "Packet hash #%d\n", i); | 300 | "Packet hash #%d\n", i); |
298 | list_for_each_entry_safe(packet, nxt, pkt_list, node) { | 301 | spin_lock(&iwm->packet_lock[i]); |
302 | list_for_each_entry(packet, pkt_list, node) { | ||
299 | len += snprintf(buf + len, buf_len - len, | 303 | len += snprintf(buf + len, buf_len - len, |
300 | "\tPacket id: %d\n", | 304 | "\tPacket id: %d\n", |
301 | packet->id); | 305 | packet->id); |
@@ -303,6 +307,7 @@ static ssize_t iwm_debugfs_rx_ticket_read(struct file *filp, | |||
303 | "\tPacket length: %lu\n", | 307 | "\tPacket length: %lu\n", |
304 | packet->pkt_size); | 308 | packet->pkt_size); |
305 | } | 309 | } |
310 | spin_unlock(&iwm->packet_lock[i]); | ||
306 | } | 311 | } |
307 | } | 312 | } |
308 | 313 | ||
diff --git a/drivers/net/wireless/iwmc3200wifi/hal.c b/drivers/net/wireless/iwmc3200wifi/hal.c index d13c8853ee82..373b5b5001d2 100644 --- a/drivers/net/wireless/iwmc3200wifi/hal.c +++ b/drivers/net/wireless/iwmc3200wifi/hal.c | |||
@@ -104,6 +104,7 @@ | |||
104 | #include "hal.h" | 104 | #include "hal.h" |
105 | #include "umac.h" | 105 | #include "umac.h" |
106 | #include "debug.h" | 106 | #include "debug.h" |
107 | #include "trace.h" | ||
107 | 108 | ||
108 | static int iwm_nonwifi_cmd_init(struct iwm_priv *iwm, | 109 | static int iwm_nonwifi_cmd_init(struct iwm_priv *iwm, |
109 | struct iwm_nonwifi_cmd *cmd, | 110 | struct iwm_nonwifi_cmd *cmd, |
@@ -206,9 +207,9 @@ void iwm_cmd_flush(struct iwm_priv *iwm) | |||
206 | 207 | ||
207 | struct iwm_wifi_cmd *iwm_get_pending_wifi_cmd(struct iwm_priv *iwm, u16 seq_num) | 208 | struct iwm_wifi_cmd *iwm_get_pending_wifi_cmd(struct iwm_priv *iwm, u16 seq_num) |
208 | { | 209 | { |
209 | struct iwm_wifi_cmd *cmd, *next; | 210 | struct iwm_wifi_cmd *cmd; |
210 | 211 | ||
211 | list_for_each_entry_safe(cmd, next, &iwm->wifi_pending_cmd, pending) | 212 | list_for_each_entry(cmd, &iwm->wifi_pending_cmd, pending) |
212 | if (cmd->seq_num == seq_num) { | 213 | if (cmd->seq_num == seq_num) { |
213 | list_del(&cmd->pending); | 214 | list_del(&cmd->pending); |
214 | return cmd; | 215 | return cmd; |
@@ -217,12 +218,12 @@ struct iwm_wifi_cmd *iwm_get_pending_wifi_cmd(struct iwm_priv *iwm, u16 seq_num) | |||
217 | return NULL; | 218 | return NULL; |
218 | } | 219 | } |
219 | 220 | ||
220 | struct iwm_nonwifi_cmd * | 221 | struct iwm_nonwifi_cmd *iwm_get_pending_nonwifi_cmd(struct iwm_priv *iwm, |
221 | iwm_get_pending_nonwifi_cmd(struct iwm_priv *iwm, u8 seq_num, u8 cmd_opcode) | 222 | u8 seq_num, u8 cmd_opcode) |
222 | { | 223 | { |
223 | struct iwm_nonwifi_cmd *cmd, *next; | 224 | struct iwm_nonwifi_cmd *cmd; |
224 | 225 | ||
225 | list_for_each_entry_safe(cmd, next, &iwm->nonwifi_pending_cmd, pending) | 226 | list_for_each_entry(cmd, &iwm->nonwifi_pending_cmd, pending) |
226 | if ((cmd->seq_num == seq_num) && | 227 | if ((cmd->seq_num == seq_num) && |
227 | (cmd->udma_cmd.opcode == cmd_opcode) && | 228 | (cmd->udma_cmd.opcode == cmd_opcode) && |
228 | (cmd->resp_received)) { | 229 | (cmd->resp_received)) { |
@@ -276,6 +277,7 @@ static int iwm_send_udma_nonwifi_cmd(struct iwm_priv *iwm, | |||
276 | udma_cmd->handle_by_hw, cmd->seq_num, udma_cmd->addr, | 277 | udma_cmd->handle_by_hw, cmd->seq_num, udma_cmd->addr, |
277 | udma_cmd->op1_sz, udma_cmd->op2); | 278 | udma_cmd->op1_sz, udma_cmd->op2); |
278 | 279 | ||
280 | trace_iwm_tx_nonwifi_cmd(iwm, udma_hdr); | ||
279 | return iwm_bus_send_chunk(iwm, buf->start, buf->len); | 281 | return iwm_bus_send_chunk(iwm, buf->start, buf->len); |
280 | } | 282 | } |
281 | 283 | ||
@@ -362,6 +364,7 @@ static int iwm_send_udma_wifi_cmd(struct iwm_priv *iwm, | |||
362 | return ret; | 364 | return ret; |
363 | } | 365 | } |
364 | 366 | ||
367 | trace_iwm_tx_wifi_cmd(iwm, umac_hdr); | ||
365 | return iwm_bus_send_chunk(iwm, buf->start, buf->len); | 368 | return iwm_bus_send_chunk(iwm, buf->start, buf->len); |
366 | } | 369 | } |
367 | 370 | ||
diff --git a/drivers/net/wireless/iwmc3200wifi/hal.h b/drivers/net/wireless/iwmc3200wifi/hal.h index 0adfdc85765d..c20936d9b6b7 100644 --- a/drivers/net/wireless/iwmc3200wifi/hal.h +++ b/drivers/net/wireless/iwmc3200wifi/hal.h | |||
@@ -75,7 +75,8 @@ do { \ | |||
75 | 75 | ||
76 | 76 | ||
77 | /* UDMA IN OP CODE -- cmd bits [3:0] */ | 77 | /* UDMA IN OP CODE -- cmd bits [3:0] */ |
78 | #define UDMA_IN_OPCODE_MASK 0xF | 78 | #define UDMA_HDI_IN_NW_CMD_OPCODE_POS 0 |
79 | #define UDMA_HDI_IN_NW_CMD_OPCODE_SEED 0xF | ||
79 | 80 | ||
80 | #define UDMA_IN_OPCODE_GENERAL_RESP 0x0 | 81 | #define UDMA_IN_OPCODE_GENERAL_RESP 0x0 |
81 | #define UDMA_IN_OPCODE_READ_RESP 0x1 | 82 | #define UDMA_IN_OPCODE_READ_RESP 0x1 |
@@ -130,7 +131,7 @@ do { \ | |||
130 | #define IWM_MAX_WIFI_CMD_BUFF_SIZE (IWM_SDIO_FW_MAX_CHUNK_SIZE - \ | 131 | #define IWM_MAX_WIFI_CMD_BUFF_SIZE (IWM_SDIO_FW_MAX_CHUNK_SIZE - \ |
131 | IWM_MAX_WIFI_HEADERS_SIZE) | 132 | IWM_MAX_WIFI_HEADERS_SIZE) |
132 | 133 | ||
133 | #define IWM_HAL_CONCATENATE_BUF_SIZE 8192 | 134 | #define IWM_HAL_CONCATENATE_BUF_SIZE (32 * 1024) |
134 | 135 | ||
135 | struct iwm_wifi_cmd_buff { | 136 | struct iwm_wifi_cmd_buff { |
136 | u16 len; | 137 | u16 len; |
diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h index 79ffa3b98d73..13266c3842f8 100644 --- a/drivers/net/wireless/iwmc3200wifi/iwm.h +++ b/drivers/net/wireless/iwmc3200wifi/iwm.h | |||
@@ -48,6 +48,7 @@ | |||
48 | #include "umac.h" | 48 | #include "umac.h" |
49 | #include "lmac.h" | 49 | #include "lmac.h" |
50 | #include "eeprom.h" | 50 | #include "eeprom.h" |
51 | #include "trace.h" | ||
51 | 52 | ||
52 | #define IWM_COPYRIGHT "Copyright(c) 2009 Intel Corporation" | 53 | #define IWM_COPYRIGHT "Copyright(c) 2009 Intel Corporation" |
53 | #define IWM_AUTHOR "<ilw@linux.intel.com>" | 54 | #define IWM_AUTHOR "<ilw@linux.intel.com>" |
@@ -268,7 +269,9 @@ struct iwm_priv { | |||
268 | 269 | ||
269 | struct sk_buff_head rx_list; | 270 | struct sk_buff_head rx_list; |
270 | struct list_head rx_tickets; | 271 | struct list_head rx_tickets; |
272 | spinlock_t ticket_lock; | ||
271 | struct list_head rx_packets[IWM_RX_ID_HASH]; | 273 | struct list_head rx_packets[IWM_RX_ID_HASH]; |
274 | spinlock_t packet_lock[IWM_RX_ID_HASH]; | ||
272 | struct workqueue_struct *rx_wq; | 275 | struct workqueue_struct *rx_wq; |
273 | struct work_struct rx_worker; | 276 | struct work_struct rx_worker; |
274 | 277 | ||
diff --git a/drivers/net/wireless/iwmc3200wifi/main.c b/drivers/net/wireless/iwmc3200wifi/main.c index 7f34d6dd3c41..3a3510a6223a 100644 --- a/drivers/net/wireless/iwmc3200wifi/main.c +++ b/drivers/net/wireless/iwmc3200wifi/main.c | |||
@@ -276,8 +276,11 @@ int iwm_priv_init(struct iwm_priv *iwm) | |||
276 | 276 | ||
277 | skb_queue_head_init(&iwm->rx_list); | 277 | skb_queue_head_init(&iwm->rx_list); |
278 | INIT_LIST_HEAD(&iwm->rx_tickets); | 278 | INIT_LIST_HEAD(&iwm->rx_tickets); |
279 | for (i = 0; i < IWM_RX_ID_HASH; i++) | 279 | spin_lock_init(&iwm->ticket_lock); |
280 | for (i = 0; i < IWM_RX_ID_HASH; i++) { | ||
280 | INIT_LIST_HEAD(&iwm->rx_packets[i]); | 281 | INIT_LIST_HEAD(&iwm->rx_packets[i]); |
282 | spin_lock_init(&iwm->packet_lock[i]); | ||
283 | } | ||
281 | 284 | ||
282 | INIT_WORK(&iwm->rx_worker, iwm_rx_worker); | 285 | INIT_WORK(&iwm->rx_worker, iwm_rx_worker); |
283 | 286 | ||
@@ -423,9 +426,9 @@ int iwm_notif_send(struct iwm_priv *iwm, struct iwm_wifi_cmd *cmd, | |||
423 | static struct iwm_notif *iwm_notif_find(struct iwm_priv *iwm, u32 cmd, | 426 | static struct iwm_notif *iwm_notif_find(struct iwm_priv *iwm, u32 cmd, |
424 | u8 source) | 427 | u8 source) |
425 | { | 428 | { |
426 | struct iwm_notif *notif, *next; | 429 | struct iwm_notif *notif; |
427 | 430 | ||
428 | list_for_each_entry_safe(notif, next, &iwm->pending_notif, pending) { | 431 | list_for_each_entry(notif, &iwm->pending_notif, pending) { |
429 | if ((notif->cmd_id == cmd) && (notif->src == source)) { | 432 | if ((notif->cmd_id == cmd) && (notif->src == source)) { |
430 | list_del(¬if->pending); | 433 | list_del(¬if->pending); |
431 | return notif; | 434 | return notif; |
diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index ad8f7eabb5aa..5090a8a61887 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c | |||
@@ -342,15 +342,17 @@ static void iwm_rx_ticket_node_free(struct iwm_rx_ticket_node *ticket_node) | |||
342 | static struct iwm_rx_packet *iwm_rx_packet_get(struct iwm_priv *iwm, u16 id) | 342 | static struct iwm_rx_packet *iwm_rx_packet_get(struct iwm_priv *iwm, u16 id) |
343 | { | 343 | { |
344 | u8 id_hash = IWM_RX_ID_GET_HASH(id); | 344 | u8 id_hash = IWM_RX_ID_GET_HASH(id); |
345 | struct list_head *packet_list; | 345 | struct iwm_rx_packet *packet; |
346 | struct iwm_rx_packet *packet, *next; | ||
347 | |||
348 | packet_list = &iwm->rx_packets[id_hash]; | ||
349 | 346 | ||
350 | list_for_each_entry_safe(packet, next, packet_list, node) | 347 | spin_lock(&iwm->packet_lock[id_hash]); |
351 | if (packet->id == id) | 348 | list_for_each_entry(packet, &iwm->rx_packets[id_hash], node) |
349 | if (packet->id == id) { | ||
350 | list_del(&packet->node); | ||
351 | spin_unlock(&iwm->packet_lock[id_hash]); | ||
352 | return packet; | 352 | return packet; |
353 | } | ||
353 | 354 | ||
355 | spin_unlock(&iwm->packet_lock[id_hash]); | ||
354 | return NULL; | 356 | return NULL; |
355 | } | 357 | } |
356 | 358 | ||
@@ -388,18 +390,22 @@ void iwm_rx_free(struct iwm_priv *iwm) | |||
388 | struct iwm_rx_packet *packet, *np; | 390 | struct iwm_rx_packet *packet, *np; |
389 | int i; | 391 | int i; |
390 | 392 | ||
393 | spin_lock(&iwm->ticket_lock); | ||
391 | list_for_each_entry_safe(ticket, nt, &iwm->rx_tickets, node) { | 394 | list_for_each_entry_safe(ticket, nt, &iwm->rx_tickets, node) { |
392 | list_del(&ticket->node); | 395 | list_del(&ticket->node); |
393 | iwm_rx_ticket_node_free(ticket); | 396 | iwm_rx_ticket_node_free(ticket); |
394 | } | 397 | } |
398 | spin_unlock(&iwm->ticket_lock); | ||
395 | 399 | ||
396 | for (i = 0; i < IWM_RX_ID_HASH; i++) { | 400 | for (i = 0; i < IWM_RX_ID_HASH; i++) { |
401 | spin_lock(&iwm->packet_lock[i]); | ||
397 | list_for_each_entry_safe(packet, np, &iwm->rx_packets[i], | 402 | list_for_each_entry_safe(packet, np, &iwm->rx_packets[i], |
398 | node) { | 403 | node) { |
399 | list_del(&packet->node); | 404 | list_del(&packet->node); |
400 | kfree_skb(packet->skb); | 405 | kfree_skb(packet->skb); |
401 | kfree(packet); | 406 | kfree(packet); |
402 | } | 407 | } |
408 | spin_unlock(&iwm->packet_lock[i]); | ||
403 | } | 409 | } |
404 | } | 410 | } |
405 | 411 | ||
@@ -427,7 +433,9 @@ static int iwm_ntf_rx_ticket(struct iwm_priv *iwm, u8 *buf, | |||
427 | ticket->action == IWM_RX_TICKET_RELEASE ? | 433 | ticket->action == IWM_RX_TICKET_RELEASE ? |
428 | "RELEASE" : "DROP", | 434 | "RELEASE" : "DROP", |
429 | ticket->id); | 435 | ticket->id); |
436 | spin_lock(&iwm->ticket_lock); | ||
430 | list_add_tail(&ticket_node->node, &iwm->rx_tickets); | 437 | list_add_tail(&ticket_node->node, &iwm->rx_tickets); |
438 | spin_unlock(&iwm->ticket_lock); | ||
431 | 439 | ||
432 | /* | 440 | /* |
433 | * We received an Rx ticket, most likely there's | 441 | * We received an Rx ticket, most likely there's |
@@ -460,6 +468,7 @@ static int iwm_ntf_rx_packet(struct iwm_priv *iwm, u8 *buf, | |||
460 | struct iwm_rx_packet *packet; | 468 | struct iwm_rx_packet *packet; |
461 | u16 id, buf_offset; | 469 | u16 id, buf_offset; |
462 | u32 packet_size; | 470 | u32 packet_size; |
471 | u8 id_hash; | ||
463 | 472 | ||
464 | IWM_DBG_RX(iwm, DBG, "\n"); | 473 | IWM_DBG_RX(iwm, DBG, "\n"); |
465 | 474 | ||
@@ -477,7 +486,10 @@ static int iwm_ntf_rx_packet(struct iwm_priv *iwm, u8 *buf, | |||
477 | if (IS_ERR(packet)) | 486 | if (IS_ERR(packet)) |
478 | return PTR_ERR(packet); | 487 | return PTR_ERR(packet); |
479 | 488 | ||
480 | list_add_tail(&packet->node, &iwm->rx_packets[IWM_RX_ID_GET_HASH(id)]); | 489 | id_hash = IWM_RX_ID_GET_HASH(id); |
490 | spin_lock(&iwm->packet_lock[id_hash]); | ||
491 | list_add_tail(&packet->node, &iwm->rx_packets[id_hash]); | ||
492 | spin_unlock(&iwm->packet_lock[id_hash]); | ||
481 | 493 | ||
482 | /* We might (unlikely) have received the packet _after_ the ticket */ | 494 | /* We might (unlikely) have received the packet _after_ the ticket */ |
483 | queue_work(iwm->rx_wq, &iwm->rx_worker); | 495 | queue_work(iwm->rx_wq, &iwm->rx_worker); |
@@ -518,6 +530,8 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, | |||
518 | unsigned long buf_size, | 530 | unsigned long buf_size, |
519 | struct iwm_wifi_cmd *cmd) | 531 | struct iwm_wifi_cmd *cmd) |
520 | { | 532 | { |
533 | struct wiphy *wiphy = iwm_to_wiphy(iwm); | ||
534 | struct ieee80211_channel *chan; | ||
521 | struct iwm_umac_notif_assoc_complete *complete = | 535 | struct iwm_umac_notif_assoc_complete *complete = |
522 | (struct iwm_umac_notif_assoc_complete *)buf; | 536 | (struct iwm_umac_notif_assoc_complete *)buf; |
523 | 537 | ||
@@ -526,6 +540,18 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, | |||
526 | 540 | ||
527 | switch (le32_to_cpu(complete->status)) { | 541 | switch (le32_to_cpu(complete->status)) { |
528 | case UMAC_ASSOC_COMPLETE_SUCCESS: | 542 | case UMAC_ASSOC_COMPLETE_SUCCESS: |
543 | chan = ieee80211_get_channel(wiphy, | ||
544 | ieee80211_channel_to_frequency(complete->channel)); | ||
545 | if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) { | ||
546 | /* Associated to a unallowed channel, disassociate. */ | ||
547 | __iwm_invalidate_mlme_profile(iwm); | ||
548 | IWM_WARN(iwm, "Couldn't associate with %pM due to " | ||
549 | "channel %d is disabled. Check your local " | ||
550 | "regulatory setting.\n", | ||
551 | complete->bssid, complete->channel); | ||
552 | goto failure; | ||
553 | } | ||
554 | |||
529 | set_bit(IWM_STATUS_ASSOCIATED, &iwm->status); | 555 | set_bit(IWM_STATUS_ASSOCIATED, &iwm->status); |
530 | memcpy(iwm->bssid, complete->bssid, ETH_ALEN); | 556 | memcpy(iwm->bssid, complete->bssid, ETH_ALEN); |
531 | iwm->channel = complete->channel; | 557 | iwm->channel = complete->channel; |
@@ -562,6 +588,7 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, | |||
562 | GFP_KERNEL); | 588 | GFP_KERNEL); |
563 | break; | 589 | break; |
564 | case UMAC_ASSOC_COMPLETE_FAILURE: | 590 | case UMAC_ASSOC_COMPLETE_FAILURE: |
591 | failure: | ||
565 | clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status); | 592 | clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status); |
566 | memset(iwm->bssid, 0, ETH_ALEN); | 593 | memset(iwm->bssid, 0, ETH_ALEN); |
567 | iwm->channel = 0; | 594 | iwm->channel = 0; |
@@ -756,7 +783,7 @@ static int iwm_mlme_update_bss_table(struct iwm_priv *iwm, u8 *buf, | |||
756 | (struct iwm_umac_notif_bss_info *)buf; | 783 | (struct iwm_umac_notif_bss_info *)buf; |
757 | struct ieee80211_channel *channel; | 784 | struct ieee80211_channel *channel; |
758 | struct ieee80211_supported_band *band; | 785 | struct ieee80211_supported_band *band; |
759 | struct iwm_bss_info *bss, *next; | 786 | struct iwm_bss_info *bss; |
760 | s32 signal; | 787 | s32 signal; |
761 | int freq; | 788 | int freq; |
762 | u16 frame_len = le16_to_cpu(umac_bss->frame_len); | 789 | u16 frame_len = le16_to_cpu(umac_bss->frame_len); |
@@ -775,7 +802,7 @@ static int iwm_mlme_update_bss_table(struct iwm_priv *iwm, u8 *buf, | |||
775 | IWM_DBG_MLME(iwm, DBG, "\tRSSI: %d\n", umac_bss->rssi); | 802 | IWM_DBG_MLME(iwm, DBG, "\tRSSI: %d\n", umac_bss->rssi); |
776 | IWM_DBG_MLME(iwm, DBG, "\tFrame Length: %d\n", frame_len); | 803 | IWM_DBG_MLME(iwm, DBG, "\tFrame Length: %d\n", frame_len); |
777 | 804 | ||
778 | list_for_each_entry_safe(bss, next, &iwm->bss_list, node) | 805 | list_for_each_entry(bss, &iwm->bss_list, node) |
779 | if (bss->bss->table_idx == umac_bss->table_idx) | 806 | if (bss->bss->table_idx == umac_bss->table_idx) |
780 | break; | 807 | break; |
781 | 808 | ||
@@ -842,16 +869,15 @@ static int iwm_mlme_remove_bss(struct iwm_priv *iwm, u8 *buf, | |||
842 | int i; | 869 | int i; |
843 | 870 | ||
844 | for (i = 0; i < le32_to_cpu(bss_rm->count); i++) { | 871 | for (i = 0; i < le32_to_cpu(bss_rm->count); i++) { |
845 | table_idx = (le16_to_cpu(bss_rm->entries[i]) | 872 | table_idx = le16_to_cpu(bss_rm->entries[i]) & |
846 | & IWM_BSS_REMOVE_INDEX_MSK); | 873 | IWM_BSS_REMOVE_INDEX_MSK; |
847 | list_for_each_entry_safe(bss, next, &iwm->bss_list, node) | 874 | list_for_each_entry_safe(bss, next, &iwm->bss_list, node) |
848 | if (bss->bss->table_idx == cpu_to_le16(table_idx)) { | 875 | if (bss->bss->table_idx == cpu_to_le16(table_idx)) { |
849 | struct ieee80211_mgmt *mgmt; | 876 | struct ieee80211_mgmt *mgmt; |
850 | 877 | ||
851 | mgmt = (struct ieee80211_mgmt *) | 878 | mgmt = (struct ieee80211_mgmt *) |
852 | (bss->bss->frame_buf); | 879 | (bss->bss->frame_buf); |
853 | IWM_DBG_MLME(iwm, ERR, | 880 | IWM_DBG_MLME(iwm, ERR, "BSS removed: %pM\n", |
854 | "BSS removed: %pM\n", | ||
855 | mgmt->bssid); | 881 | mgmt->bssid); |
856 | list_del(&bss->node); | 882 | list_del(&bss->node); |
857 | kfree(bss->bss); | 883 | kfree(bss->bss); |
@@ -1223,18 +1249,24 @@ static int iwm_rx_handle_wifi(struct iwm_priv *iwm, u8 *buf, | |||
1223 | u8 source, cmd_id; | 1249 | u8 source, cmd_id; |
1224 | u16 seq_num; | 1250 | u16 seq_num; |
1225 | u32 count; | 1251 | u32 count; |
1226 | u8 resp; | ||
1227 | 1252 | ||
1228 | wifi_hdr = (struct iwm_umac_wifi_in_hdr *)buf; | 1253 | wifi_hdr = (struct iwm_umac_wifi_in_hdr *)buf; |
1229 | cmd_id = wifi_hdr->sw_hdr.cmd.cmd; | 1254 | cmd_id = wifi_hdr->sw_hdr.cmd.cmd; |
1230 | |||
1231 | source = GET_VAL32(wifi_hdr->hw_hdr.cmd, UMAC_HDI_IN_CMD_SOURCE); | 1255 | source = GET_VAL32(wifi_hdr->hw_hdr.cmd, UMAC_HDI_IN_CMD_SOURCE); |
1232 | if (source >= IWM_SRC_NUM) { | 1256 | if (source >= IWM_SRC_NUM) { |
1233 | IWM_CRIT(iwm, "invalid source %d\n", source); | 1257 | IWM_CRIT(iwm, "invalid source %d\n", source); |
1234 | return -EINVAL; | 1258 | return -EINVAL; |
1235 | } | 1259 | } |
1236 | 1260 | ||
1237 | count = (GET_VAL32(wifi_hdr->sw_hdr.meta_data, UMAC_FW_CMD_BYTE_COUNT)); | 1261 | if (cmd_id == REPLY_RX_MPDU_CMD) |
1262 | trace_iwm_rx_packet(iwm, buf, buf_size); | ||
1263 | else if ((cmd_id == UMAC_NOTIFY_OPCODE_RX_TICKET) && | ||
1264 | (source == UMAC_HDI_IN_SOURCE_FW)) | ||
1265 | trace_iwm_rx_ticket(iwm, buf, buf_size); | ||
1266 | else | ||
1267 | trace_iwm_rx_wifi_cmd(iwm, wifi_hdr); | ||
1268 | |||
1269 | count = GET_VAL32(wifi_hdr->sw_hdr.meta_data, UMAC_FW_CMD_BYTE_COUNT); | ||
1238 | count += sizeof(struct iwm_umac_wifi_in_hdr) - | 1270 | count += sizeof(struct iwm_umac_wifi_in_hdr) - |
1239 | sizeof(struct iwm_dev_cmd_hdr); | 1271 | sizeof(struct iwm_dev_cmd_hdr); |
1240 | if (count > buf_size) { | 1272 | if (count > buf_size) { |
@@ -1242,8 +1274,6 @@ static int iwm_rx_handle_wifi(struct iwm_priv *iwm, u8 *buf, | |||
1242 | return -EINVAL; | 1274 | return -EINVAL; |
1243 | } | 1275 | } |
1244 | 1276 | ||
1245 | resp = GET_VAL32(wifi_hdr->sw_hdr.meta_data, UMAC_FW_CMD_STATUS); | ||
1246 | |||
1247 | seq_num = le16_to_cpu(wifi_hdr->sw_hdr.cmd.seq_num); | 1277 | seq_num = le16_to_cpu(wifi_hdr->sw_hdr.cmd.seq_num); |
1248 | 1278 | ||
1249 | IWM_DBG_RX(iwm, DBG, "CMD:0x%x, source: 0x%x, seqnum: %d\n", | 1279 | IWM_DBG_RX(iwm, DBG, "CMD:0x%x, source: 0x%x, seqnum: %d\n", |
@@ -1316,8 +1346,9 @@ static int iwm_rx_handle_nonwifi(struct iwm_priv *iwm, u8 *buf, | |||
1316 | { | 1346 | { |
1317 | u8 seq_num; | 1347 | u8 seq_num; |
1318 | struct iwm_udma_in_hdr *hdr = (struct iwm_udma_in_hdr *)buf; | 1348 | struct iwm_udma_in_hdr *hdr = (struct iwm_udma_in_hdr *)buf; |
1319 | struct iwm_nonwifi_cmd *cmd, *next; | 1349 | struct iwm_nonwifi_cmd *cmd; |
1320 | 1350 | ||
1351 | trace_iwm_rx_nonwifi_cmd(iwm, buf, buf_size); | ||
1321 | seq_num = GET_VAL32(hdr->cmd, UDMA_HDI_IN_CMD_NON_WIFI_HW_SEQ_NUM); | 1352 | seq_num = GET_VAL32(hdr->cmd, UDMA_HDI_IN_CMD_NON_WIFI_HW_SEQ_NUM); |
1322 | 1353 | ||
1323 | /* | 1354 | /* |
@@ -1328,7 +1359,7 @@ static int iwm_rx_handle_nonwifi(struct iwm_priv *iwm, u8 *buf, | |||
1328 | * That means we only support synchronised non wifi command response | 1359 | * That means we only support synchronised non wifi command response |
1329 | * schemes. | 1360 | * schemes. |
1330 | */ | 1361 | */ |
1331 | list_for_each_entry_safe(cmd, next, &iwm->nonwifi_pending_cmd, pending) | 1362 | list_for_each_entry(cmd, &iwm->nonwifi_pending_cmd, pending) |
1332 | if (cmd->seq_num == seq_num) { | 1363 | if (cmd->seq_num == seq_num) { |
1333 | cmd->resp_received = 1; | 1364 | cmd->resp_received = 1; |
1334 | cmd->buf.len = buf_size; | 1365 | cmd->buf.len = buf_size; |
@@ -1647,6 +1678,7 @@ void iwm_rx_worker(struct work_struct *work) | |||
1647 | * We stop whenever a ticket is missing its packet, as we're | 1678 | * We stop whenever a ticket is missing its packet, as we're |
1648 | * supposed to send the packets in order. | 1679 | * supposed to send the packets in order. |
1649 | */ | 1680 | */ |
1681 | spin_lock(&iwm->ticket_lock); | ||
1650 | list_for_each_entry_safe(ticket, next, &iwm->rx_tickets, node) { | 1682 | list_for_each_entry_safe(ticket, next, &iwm->rx_tickets, node) { |
1651 | struct iwm_rx_packet *packet = | 1683 | struct iwm_rx_packet *packet = |
1652 | iwm_rx_packet_get(iwm, le16_to_cpu(ticket->ticket->id)); | 1684 | iwm_rx_packet_get(iwm, le16_to_cpu(ticket->ticket->id)); |
@@ -1655,12 +1687,12 @@ void iwm_rx_worker(struct work_struct *work) | |||
1655 | IWM_DBG_RX(iwm, DBG, "Skip rx_work: Wait for ticket %d " | 1687 | IWM_DBG_RX(iwm, DBG, "Skip rx_work: Wait for ticket %d " |
1656 | "to be handled first\n", | 1688 | "to be handled first\n", |
1657 | le16_to_cpu(ticket->ticket->id)); | 1689 | le16_to_cpu(ticket->ticket->id)); |
1658 | return; | 1690 | break; |
1659 | } | 1691 | } |
1660 | 1692 | ||
1661 | list_del(&ticket->node); | 1693 | list_del(&ticket->node); |
1662 | list_del(&packet->node); | ||
1663 | iwm_rx_process_packet(iwm, packet, ticket); | 1694 | iwm_rx_process_packet(iwm, packet, ticket); |
1664 | } | 1695 | } |
1696 | spin_unlock(&iwm->ticket_lock); | ||
1665 | } | 1697 | } |
1666 | 1698 | ||
diff --git a/drivers/net/wireless/iwmc3200wifi/trace.c b/drivers/net/wireless/iwmc3200wifi/trace.c new file mode 100644 index 000000000000..904d36f22311 --- /dev/null +++ b/drivers/net/wireless/iwmc3200wifi/trace.c | |||
@@ -0,0 +1,3 @@ | |||
1 | #include "iwm.h" | ||
2 | #define CREATE_TRACE_POINTS | ||
3 | #include "trace.h" | ||
diff --git a/drivers/net/wireless/iwmc3200wifi/trace.h b/drivers/net/wireless/iwmc3200wifi/trace.h new file mode 100644 index 000000000000..320e54fbb38c --- /dev/null +++ b/drivers/net/wireless/iwmc3200wifi/trace.h | |||
@@ -0,0 +1,283 @@ | |||
1 | #if !defined(__IWM_TRACE_H__) || defined(TRACE_HEADER_MULTI_READ) | ||
2 | #define __IWM_TRACE_H__ | ||
3 | |||
4 | #include <linux/tracepoint.h> | ||
5 | |||
6 | #if !defined(CONFIG_IWM_TRACING) | ||
7 | #undef TRACE_EVENT | ||
8 | #define TRACE_EVENT(name, proto, ...) \ | ||
9 | static inline void trace_ ## name(proto) {} | ||
10 | #endif | ||
11 | |||
12 | #undef TRACE_SYSTEM | ||
13 | #define TRACE_SYSTEM iwm | ||
14 | |||
15 | #define IWM_ENTRY __array(char, ndev_name, 16) | ||
16 | #define IWM_ASSIGN strlcpy(__entry->ndev_name, iwm_to_ndev(iwm)->name, 16) | ||
17 | #define IWM_PR_FMT "%s" | ||
18 | #define IWM_PR_ARG __entry->ndev_name | ||
19 | |||
20 | TRACE_EVENT(iwm_tx_nonwifi_cmd, | ||
21 | TP_PROTO(struct iwm_priv *iwm, struct iwm_udma_out_nonwifi_hdr *hdr), | ||
22 | |||
23 | TP_ARGS(iwm, hdr), | ||
24 | |||
25 | TP_STRUCT__entry( | ||
26 | IWM_ENTRY | ||
27 | __field(u8, opcode) | ||
28 | __field(u8, resp) | ||
29 | __field(u8, eot) | ||
30 | __field(u8, hw) | ||
31 | __field(u16, seq) | ||
32 | __field(u32, addr) | ||
33 | __field(u32, op1) | ||
34 | __field(u32, op2) | ||
35 | ), | ||
36 | |||
37 | TP_fast_assign( | ||
38 | IWM_ASSIGN; | ||
39 | __entry->opcode = GET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_OPCODE); | ||
40 | __entry->resp = GET_VAL32(hdr->cmd, UDMA_HDI_OUT_NW_CMD_RESP); | ||
41 | __entry->eot = GET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_EOT); | ||
42 | __entry->hw = GET_VAL32(hdr->cmd, UDMA_HDI_OUT_NW_CMD_HANDLE_BY_HW); | ||
43 | __entry->seq = GET_VAL32(hdr->cmd, UDMA_HDI_OUT_CMD_NON_WIFI_HW_SEQ_NUM); | ||
44 | __entry->addr = le32_to_cpu(hdr->addr); | ||
45 | __entry->op1 = le32_to_cpu(hdr->op1_sz); | ||
46 | __entry->op2 = le32_to_cpu(hdr->op2); | ||
47 | ), | ||
48 | |||
49 | TP_printk( | ||
50 | IWM_PR_FMT " Tx TARGET CMD: opcode 0x%x, resp %d, eot %d, " | ||
51 | "hw %d, seq 0x%x, addr 0x%x, op1 0x%x, op2 0x%x", | ||
52 | IWM_PR_ARG, __entry->opcode, __entry->resp, __entry->eot, | ||
53 | __entry->hw, __entry->seq, __entry->addr, __entry->op1, | ||
54 | __entry->op2 | ||
55 | ) | ||
56 | ); | ||
57 | |||
58 | TRACE_EVENT(iwm_tx_wifi_cmd, | ||
59 | TP_PROTO(struct iwm_priv *iwm, struct iwm_umac_wifi_out_hdr *hdr), | ||
60 | |||
61 | TP_ARGS(iwm, hdr), | ||
62 | |||
63 | TP_STRUCT__entry( | ||
64 | IWM_ENTRY | ||
65 | __field(u8, opcode) | ||
66 | __field(u8, lmac) | ||
67 | __field(u8, resp) | ||
68 | __field(u8, eot) | ||
69 | __field(u8, ra_tid) | ||
70 | __field(u8, credit_group) | ||
71 | __field(u8, color) | ||
72 | __field(u16, seq) | ||
73 | ), | ||
74 | |||
75 | TP_fast_assign( | ||
76 | IWM_ASSIGN; | ||
77 | __entry->opcode = hdr->sw_hdr.cmd.cmd; | ||
78 | __entry->lmac = 0; | ||
79 | __entry->seq = hdr->sw_hdr.cmd.seq_num; | ||
80 | __entry->resp = GET_VAL8(hdr->sw_hdr.cmd.flags, UMAC_DEV_CMD_FLAGS_RESP_REQ); | ||
81 | __entry->color = GET_VAL32(hdr->sw_hdr.meta_data, UMAC_FW_CMD_TX_STA_COLOR); | ||
82 | __entry->eot = GET_VAL32(hdr->hw_hdr.cmd, UMAC_HDI_OUT_CMD_EOT); | ||
83 | __entry->ra_tid = GET_VAL32(hdr->hw_hdr.meta_data, UMAC_HDI_OUT_RATID); | ||
84 | __entry->credit_group = GET_VAL32(hdr->hw_hdr.meta_data, UMAC_HDI_OUT_CREDIT_GRP); | ||
85 | if (__entry->opcode == UMAC_CMD_OPCODE_WIFI_PASS_THROUGH || | ||
86 | __entry->opcode == UMAC_CMD_OPCODE_WIFI_IF_WRAPPER) { | ||
87 | __entry->lmac = 1; | ||
88 | __entry->opcode = ((struct iwm_lmac_hdr *)(hdr + 1))->id; | ||
89 | } | ||
90 | ), | ||
91 | |||
92 | TP_printk( | ||
93 | IWM_PR_FMT " Tx %cMAC CMD: opcode 0x%x, resp %d, eot %d, " | ||
94 | "seq 0x%x, sta_color 0x%x, ra_tid 0x%x, credit_group 0x%x", | ||
95 | IWM_PR_ARG, __entry->lmac ? 'L' : 'U', __entry->opcode, | ||
96 | __entry->resp, __entry->eot, __entry->seq, __entry->color, | ||
97 | __entry->ra_tid, __entry->credit_group | ||
98 | ) | ||
99 | ); | ||
100 | |||
101 | TRACE_EVENT(iwm_tx_packets, | ||
102 | TP_PROTO(struct iwm_priv *iwm, u8 *buf, int len), | ||
103 | |||
104 | TP_ARGS(iwm, buf, len), | ||
105 | |||
106 | TP_STRUCT__entry( | ||
107 | IWM_ENTRY | ||
108 | __field(u8, eot) | ||
109 | __field(u8, ra_tid) | ||
110 | __field(u8, credit_group) | ||
111 | __field(u8, color) | ||
112 | __field(u16, seq) | ||
113 | __field(u8, npkt) | ||
114 | __field(u32, bytes) | ||
115 | ), | ||
116 | |||
117 | TP_fast_assign( | ||
118 | struct iwm_umac_wifi_out_hdr *hdr = | ||
119 | (struct iwm_umac_wifi_out_hdr *)buf; | ||
120 | |||
121 | IWM_ASSIGN; | ||
122 | __entry->eot = GET_VAL32(hdr->hw_hdr.cmd, UMAC_HDI_OUT_CMD_EOT); | ||
123 | __entry->ra_tid = GET_VAL32(hdr->hw_hdr.meta_data, UMAC_HDI_OUT_RATID); | ||
124 | __entry->credit_group = GET_VAL32(hdr->hw_hdr.meta_data, UMAC_HDI_OUT_CREDIT_GRP); | ||
125 | __entry->color = GET_VAL32(hdr->sw_hdr.meta_data, UMAC_FW_CMD_TX_STA_COLOR); | ||
126 | __entry->seq = hdr->sw_hdr.cmd.seq_num; | ||
127 | __entry->npkt = 1; | ||
128 | __entry->bytes = len; | ||
129 | |||
130 | if (!__entry->eot) { | ||
131 | int count; | ||
132 | u8 *ptr = buf; | ||
133 | |||
134 | __entry->npkt = 0; | ||
135 | while (ptr < buf + len) { | ||
136 | count = GET_VAL32(hdr->sw_hdr.meta_data, | ||
137 | UMAC_FW_CMD_BYTE_COUNT); | ||
138 | ptr += ALIGN(sizeof(*hdr) + count, 16); | ||
139 | hdr = (struct iwm_umac_wifi_out_hdr *)ptr; | ||
140 | __entry->npkt++; | ||
141 | } | ||
142 | } | ||
143 | ), | ||
144 | |||
145 | TP_printk( | ||
146 | IWM_PR_FMT " Tx %spacket: eot %d, seq 0x%x, sta_color 0x%x, " | ||
147 | "ra_tid 0x%x, credit_group 0x%x, embeded_packets %d, %d bytes", | ||
148 | IWM_PR_ARG, !__entry->eot ? "concatenated " : "", | ||
149 | __entry->eot, __entry->seq, __entry->color, __entry->ra_tid, | ||
150 | __entry->credit_group, __entry->npkt, __entry->bytes | ||
151 | ) | ||
152 | ); | ||
153 | |||
154 | TRACE_EVENT(iwm_rx_nonwifi_cmd, | ||
155 | TP_PROTO(struct iwm_priv *iwm, void *buf, int len), | ||
156 | |||
157 | TP_ARGS(iwm, buf, len), | ||
158 | |||
159 | TP_STRUCT__entry( | ||
160 | IWM_ENTRY | ||
161 | __field(u8, opcode) | ||
162 | __field(u16, seq) | ||
163 | __field(u32, len) | ||
164 | ), | ||
165 | |||
166 | TP_fast_assign( | ||
167 | struct iwm_udma_in_hdr *hdr = buf; | ||
168 | |||
169 | IWM_ASSIGN; | ||
170 | __entry->opcode = GET_VAL32(hdr->cmd, UDMA_HDI_IN_NW_CMD_OPCODE); | ||
171 | __entry->seq = GET_VAL32(hdr->cmd, UDMA_HDI_IN_CMD_NON_WIFI_HW_SEQ_NUM); | ||
172 | __entry->len = len; | ||
173 | ), | ||
174 | |||
175 | TP_printk( | ||
176 | IWM_PR_FMT " Rx TARGET RESP: opcode 0x%x, seq 0x%x, len 0x%x", | ||
177 | IWM_PR_ARG, __entry->opcode, __entry->seq, __entry->len | ||
178 | ) | ||
179 | ); | ||
180 | |||
181 | TRACE_EVENT(iwm_rx_wifi_cmd, | ||
182 | TP_PROTO(struct iwm_priv *iwm, struct iwm_umac_wifi_in_hdr *hdr), | ||
183 | |||
184 | TP_ARGS(iwm, hdr), | ||
185 | |||
186 | TP_STRUCT__entry( | ||
187 | IWM_ENTRY | ||
188 | __field(u8, cmd) | ||
189 | __field(u8, source) | ||
190 | __field(u16, seq) | ||
191 | __field(u32, count) | ||
192 | ), | ||
193 | |||
194 | TP_fast_assign( | ||
195 | IWM_ASSIGN; | ||
196 | __entry->cmd = hdr->sw_hdr.cmd.cmd; | ||
197 | __entry->source = GET_VAL32(hdr->hw_hdr.cmd, UMAC_HDI_IN_CMD_SOURCE); | ||
198 | __entry->count = GET_VAL32(hdr->sw_hdr.meta_data, UMAC_FW_CMD_BYTE_COUNT); | ||
199 | __entry->seq = le16_to_cpu(hdr->sw_hdr.cmd.seq_num); | ||
200 | ), | ||
201 | |||
202 | TP_printk( | ||
203 | IWM_PR_FMT " Rx %s RESP: cmd 0x%x, seq 0x%x, count 0x%x", | ||
204 | IWM_PR_ARG, __entry->source == UMAC_HDI_IN_SOURCE_FHRX ? "LMAC" : | ||
205 | __entry->source == UMAC_HDI_IN_SOURCE_FW ? "UMAC" : "UDMA", | ||
206 | __entry->cmd, __entry->seq, __entry->count | ||
207 | ) | ||
208 | ); | ||
209 | |||
210 | #define iwm_ticket_action_symbol \ | ||
211 | { IWM_RX_TICKET_DROP, "DROP" }, \ | ||
212 | { IWM_RX_TICKET_RELEASE, "RELEASE" }, \ | ||
213 | { IWM_RX_TICKET_SNIFFER, "SNIFFER" }, \ | ||
214 | { IWM_RX_TICKET_ENQUEUE, "ENQUEUE" } | ||
215 | |||
216 | TRACE_EVENT(iwm_rx_ticket, | ||
217 | TP_PROTO(struct iwm_priv *iwm, void *buf, int len), | ||
218 | |||
219 | TP_ARGS(iwm, buf, len), | ||
220 | |||
221 | TP_STRUCT__entry( | ||
222 | IWM_ENTRY | ||
223 | __field(u8, action) | ||
224 | __field(u8, reason) | ||
225 | __field(u16, id) | ||
226 | __field(u16, flags) | ||
227 | ), | ||
228 | |||
229 | TP_fast_assign( | ||
230 | struct iwm_rx_ticket *ticket = | ||
231 | ((struct iwm_umac_notif_rx_ticket *)buf)->tickets; | ||
232 | |||
233 | IWM_ASSIGN; | ||
234 | __entry->id = le16_to_cpu(ticket->id); | ||
235 | __entry->action = le16_to_cpu(ticket->action); | ||
236 | __entry->flags = le16_to_cpu(ticket->flags); | ||
237 | __entry->reason = (__entry->flags & IWM_RX_TICKET_DROP_REASON_MSK) >> IWM_RX_TICKET_DROP_REASON_POS; | ||
238 | ), | ||
239 | |||
240 | TP_printk( | ||
241 | IWM_PR_FMT " Rx ticket: id 0x%x, action %s, %s 0x%x%s", | ||
242 | IWM_PR_ARG, __entry->id, | ||
243 | __print_symbolic(__entry->action, iwm_ticket_action_symbol), | ||
244 | __entry->reason ? "reason" : "flags", | ||
245 | __entry->reason ? __entry->reason : __entry->flags, | ||
246 | __entry->flags & IWM_RX_TICKET_AMSDU_MSK ? ", AMSDU frame" : "" | ||
247 | ) | ||
248 | ); | ||
249 | |||
250 | TRACE_EVENT(iwm_rx_packet, | ||
251 | TP_PROTO(struct iwm_priv *iwm, void *buf, int len), | ||
252 | |||
253 | TP_ARGS(iwm, buf, len), | ||
254 | |||
255 | TP_STRUCT__entry( | ||
256 | IWM_ENTRY | ||
257 | __field(u8, source) | ||
258 | __field(u16, id) | ||
259 | __field(u32, len) | ||
260 | ), | ||
261 | |||
262 | TP_fast_assign( | ||
263 | struct iwm_umac_wifi_in_hdr *hdr = buf; | ||
264 | |||
265 | IWM_ASSIGN; | ||
266 | __entry->source = GET_VAL32(hdr->hw_hdr.cmd, UMAC_HDI_IN_CMD_SOURCE); | ||
267 | __entry->id = le16_to_cpu(hdr->sw_hdr.cmd.seq_num); | ||
268 | __entry->len = len - sizeof(*hdr); | ||
269 | ), | ||
270 | |||
271 | TP_printk( | ||
272 | IWM_PR_FMT " Rx %s packet: id 0x%x, %d bytes", | ||
273 | IWM_PR_ARG, __entry->source == UMAC_HDI_IN_SOURCE_FHRX ? | ||
274 | "LMAC" : "UMAC", __entry->id, __entry->len | ||
275 | ) | ||
276 | ); | ||
277 | #endif | ||
278 | |||
279 | #undef TRACE_INCLUDE_PATH | ||
280 | #define TRACE_INCLUDE_PATH . | ||
281 | #undef TRACE_INCLUDE_FILE | ||
282 | #define TRACE_INCLUDE_FILE trace | ||
283 | #include <trace/define_trace.h> | ||
diff --git a/drivers/net/wireless/iwmc3200wifi/tx.c b/drivers/net/wireless/iwmc3200wifi/tx.c index 55905f02309c..a20b936ae21f 100644 --- a/drivers/net/wireless/iwmc3200wifi/tx.c +++ b/drivers/net/wireless/iwmc3200wifi/tx.c | |||
@@ -346,6 +346,7 @@ static int iwm_tx_send_concat_packets(struct iwm_priv *iwm, | |||
346 | /* mark EOP for the last packet */ | 346 | /* mark EOP for the last packet */ |
347 | iwm_udma_wifi_hdr_set_eop(iwm, txq->concat_ptr, 1); | 347 | iwm_udma_wifi_hdr_set_eop(iwm, txq->concat_ptr, 1); |
348 | 348 | ||
349 | trace_iwm_tx_packets(iwm, txq->concat_buf, txq->concat_count); | ||
349 | ret = iwm_bus_send_chunk(iwm, txq->concat_buf, txq->concat_count); | 350 | ret = iwm_bus_send_chunk(iwm, txq->concat_buf, txq->concat_count); |
350 | 351 | ||
351 | txq->concat_count = 0; | 352 | txq->concat_count = 0; |
@@ -450,7 +451,6 @@ void iwm_tx_worker(struct work_struct *work) | |||
450 | int iwm_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | 451 | int iwm_xmit_frame(struct sk_buff *skb, struct net_device *netdev) |
451 | { | 452 | { |
452 | struct iwm_priv *iwm = ndev_to_iwm(netdev); | 453 | struct iwm_priv *iwm = ndev_to_iwm(netdev); |
453 | struct net_device *ndev = iwm_to_ndev(iwm); | ||
454 | struct wireless_dev *wdev = iwm_to_wdev(iwm); | 454 | struct wireless_dev *wdev = iwm_to_wdev(iwm); |
455 | struct iwm_tx_info *tx_info; | 455 | struct iwm_tx_info *tx_info; |
456 | struct iwm_tx_queue *txq; | 456 | struct iwm_tx_queue *txq; |
@@ -517,12 +517,12 @@ int iwm_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
517 | 517 | ||
518 | queue_work(iwm->txq[queue].wq, &iwm->txq[queue].worker); | 518 | queue_work(iwm->txq[queue].wq, &iwm->txq[queue].worker); |
519 | 519 | ||
520 | ndev->stats.tx_packets++; | 520 | netdev->stats.tx_packets++; |
521 | ndev->stats.tx_bytes += skb->len; | 521 | netdev->stats.tx_bytes += skb->len; |
522 | return NETDEV_TX_OK; | 522 | return NETDEV_TX_OK; |
523 | 523 | ||
524 | drop: | 524 | drop: |
525 | ndev->stats.tx_dropped++; | 525 | netdev->stats.tx_dropped++; |
526 | dev_kfree_skb_any(skb); | 526 | dev_kfree_skb_any(skb); |
527 | return NETDEV_TX_OK; | 527 | return NETDEV_TX_OK; |
528 | } | 528 | } |
diff --git a/drivers/net/wireless/iwmc3200wifi/umac.h b/drivers/net/wireless/iwmc3200wifi/umac.h index 7f54a145ca65..0cbba3ecc813 100644 --- a/drivers/net/wireless/iwmc3200wifi/umac.h +++ b/drivers/net/wireless/iwmc3200wifi/umac.h | |||
@@ -362,7 +362,7 @@ struct iwm_udma_out_wifi_hdr { | |||
362 | #define IWM_RX_TICKET_SPECIAL_SNAP_MSK 0x4 | 362 | #define IWM_RX_TICKET_SPECIAL_SNAP_MSK 0x4 |
363 | #define IWM_RX_TICKET_AMSDU_MSK 0x8 | 363 | #define IWM_RX_TICKET_AMSDU_MSK 0x8 |
364 | #define IWM_RX_TICKET_DROP_REASON_POS 4 | 364 | #define IWM_RX_TICKET_DROP_REASON_POS 4 |
365 | #define IWM_RX_TICKET_DROP_REASON_MSK (0x1F << RX_TICKET_FLAGS_DROP_REASON_POS) | 365 | #define IWM_RX_TICKET_DROP_REASON_MSK (0x1F << IWM_RX_TICKET_DROP_REASON_POS) |
366 | 366 | ||
367 | #define IWM_RX_DROP_NO_DROP 0x0 | 367 | #define IWM_RX_DROP_NO_DROP 0x0 |
368 | #define IWM_RX_DROP_BAD_CRC 0x1 | 368 | #define IWM_RX_DROP_BAD_CRC 0x1 |
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index f03d5e4e59c3..95d3d4c5e08b 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c | |||
@@ -31,6 +31,9 @@ u8 lbs_bg_rates[MAX_RATES] = | |||
31 | 0x00, 0x00 }; | 31 | 0x00, 0x00 }; |
32 | 32 | ||
33 | 33 | ||
34 | static int assoc_helper_wep_keys(struct lbs_private *priv, | ||
35 | struct assoc_request *assoc_req); | ||
36 | |||
34 | /** | 37 | /** |
35 | * @brief This function finds common rates between rates and card rates. | 38 | * @brief This function finds common rates between rates and card rates. |
36 | * | 39 | * |
@@ -610,7 +613,7 @@ static int lbs_assoc_post(struct lbs_private *priv, | |||
610 | 613 | ||
611 | if (status_code) { | 614 | if (status_code) { |
612 | lbs_mac_event_disconnected(priv); | 615 | lbs_mac_event_disconnected(priv); |
613 | ret = -1; | 616 | ret = status_code; |
614 | goto done; | 617 | goto done; |
615 | } | 618 | } |
616 | 619 | ||
@@ -813,7 +816,24 @@ static int lbs_try_associate(struct lbs_private *priv, | |||
813 | goto out; | 816 | goto out; |
814 | 817 | ||
815 | ret = lbs_associate(priv, assoc_req, CMD_802_11_ASSOCIATE); | 818 | ret = lbs_associate(priv, assoc_req, CMD_802_11_ASSOCIATE); |
819 | /* If the association fails with current auth mode, let's | ||
820 | * try by changing the auth mode | ||
821 | */ | ||
822 | if ((priv->authtype_auto) && | ||
823 | (ret == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) && | ||
824 | (assoc_req->secinfo.wep_enabled) && | ||
825 | (priv->connect_status != LBS_CONNECTED)) { | ||
826 | if (priv->secinfo.auth_mode == IW_AUTH_ALG_OPEN_SYSTEM) | ||
827 | priv->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY; | ||
828 | else | ||
829 | priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; | ||
830 | if (!assoc_helper_wep_keys(priv, assoc_req)) | ||
831 | ret = lbs_associate(priv, assoc_req, | ||
832 | CMD_802_11_ASSOCIATE); | ||
833 | } | ||
816 | 834 | ||
835 | if (ret) | ||
836 | ret = -1; | ||
817 | out: | 837 | out: |
818 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); | 838 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); |
819 | return ret; | 839 | return ret; |
diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c index 587b0cb0088d..9c3c2f82f033 100644 --- a/drivers/net/wireless/libertas/debugfs.c +++ b/drivers/net/wireless/libertas/debugfs.c | |||
@@ -74,7 +74,7 @@ static ssize_t lbs_getscantable(struct file *file, char __user *userbuf, | |||
74 | return -ENOMEM; | 74 | return -ENOMEM; |
75 | 75 | ||
76 | pos += snprintf(buf+pos, len-pos, | 76 | pos += snprintf(buf+pos, len-pos, |
77 | "# | ch | rssi | bssid | cap | Qual | SSID \n"); | 77 | "# | ch | rssi | bssid | cap | Qual | SSID\n"); |
78 | 78 | ||
79 | mutex_lock(&priv->lock); | 79 | mutex_lock(&priv->lock); |
80 | list_for_each_entry (iter_bss, &priv->network_list, list) { | 80 | list_for_each_entry (iter_bss, &priv->network_list, list) { |
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index 6875e1498bd5..a54880e4ad2b 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h | |||
@@ -134,6 +134,7 @@ struct lbs_private { | |||
134 | u8 wpa_ie_len; | 134 | u8 wpa_ie_len; |
135 | u16 wep_tx_keyidx; | 135 | u16 wep_tx_keyidx; |
136 | struct enc_key wep_keys[4]; | 136 | struct enc_key wep_keys[4]; |
137 | u8 authtype_auto; | ||
137 | 138 | ||
138 | /* Wake On LAN */ | 139 | /* Wake On LAN */ |
139 | uint32_t wol_criteria; | 140 | uint32_t wol_criteria; |
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index 7a73f625273b..33206a98a572 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c | |||
@@ -34,6 +34,8 @@ | |||
34 | #include <linux/mmc/card.h> | 34 | #include <linux/mmc/card.h> |
35 | #include <linux/mmc/sdio_func.h> | 35 | #include <linux/mmc/sdio_func.h> |
36 | #include <linux/mmc/sdio_ids.h> | 36 | #include <linux/mmc/sdio_ids.h> |
37 | #include <linux/mmc/sdio.h> | ||
38 | #include <linux/mmc/host.h> | ||
37 | 39 | ||
38 | #include "host.h" | 40 | #include "host.h" |
39 | #include "decl.h" | 41 | #include "decl.h" |
@@ -942,6 +944,7 @@ static int if_sdio_probe(struct sdio_func *func, | |||
942 | int ret, i; | 944 | int ret, i; |
943 | unsigned int model; | 945 | unsigned int model; |
944 | struct if_sdio_packet *packet; | 946 | struct if_sdio_packet *packet; |
947 | struct mmc_host *host = func->card->host; | ||
945 | 948 | ||
946 | lbs_deb_enter(LBS_DEB_SDIO); | 949 | lbs_deb_enter(LBS_DEB_SDIO); |
947 | 950 | ||
@@ -1022,6 +1025,25 @@ static int if_sdio_probe(struct sdio_func *func, | |||
1022 | if (ret) | 1025 | if (ret) |
1023 | goto disable; | 1026 | goto disable; |
1024 | 1027 | ||
1028 | /* For 1-bit transfers to the 8686 model, we need to enable the | ||
1029 | * interrupt flag in the CCCR register. Set the MMC_QUIRK_LENIENT_FN0 | ||
1030 | * bit to allow access to non-vendor registers. */ | ||
1031 | if ((card->model == IF_SDIO_MODEL_8686) && | ||
1032 | (host->caps & MMC_CAP_SDIO_IRQ) && | ||
1033 | (host->ios.bus_width == MMC_BUS_WIDTH_1)) { | ||
1034 | u8 reg; | ||
1035 | |||
1036 | func->card->quirks |= MMC_QUIRK_LENIENT_FN0; | ||
1037 | reg = sdio_f0_readb(func, SDIO_CCCR_IF, &ret); | ||
1038 | if (ret) | ||
1039 | goto release_int; | ||
1040 | |||
1041 | reg |= SDIO_BUS_ECSI; | ||
1042 | sdio_f0_writeb(func, reg, SDIO_CCCR_IF, &ret); | ||
1043 | if (ret) | ||
1044 | goto release_int; | ||
1045 | } | ||
1046 | |||
1025 | card->ioport = sdio_readb(func, IF_SDIO_IOPORT, &ret); | 1047 | card->ioport = sdio_readb(func, IF_SDIO_IOPORT, &ret); |
1026 | if (ret) | 1048 | if (ret) |
1027 | goto release_int; | 1049 | goto release_int; |
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 28a1c9d1627a..3c889f43d909 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c | |||
@@ -835,6 +835,7 @@ static int lbs_init_adapter(struct lbs_private *priv) | |||
835 | priv->is_auto_deep_sleep_enabled = 0; | 835 | priv->is_auto_deep_sleep_enabled = 0; |
836 | priv->wakeup_dev_required = 0; | 836 | priv->wakeup_dev_required = 0; |
837 | init_waitqueue_head(&priv->ds_awake_q); | 837 | init_waitqueue_head(&priv->ds_awake_q); |
838 | priv->authtype_auto = 1; | ||
838 | 839 | ||
839 | mutex_init(&priv->lock); | 840 | mutex_init(&priv->lock); |
840 | 841 | ||
diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c index 2daf8ffdb7e1..7a867e31ca5a 100644 --- a/drivers/net/wireless/libertas/rx.c +++ b/drivers/net/wireless/libertas/rx.c | |||
@@ -38,10 +38,10 @@ static int process_rxed_802_11_packet(struct lbs_private *priv, | |||
38 | struct sk_buff *skb); | 38 | struct sk_buff *skb); |
39 | 39 | ||
40 | /** | 40 | /** |
41 | * @brief This function computes the avgSNR . | 41 | * @brief This function computes the avgSNR . |
42 | * | 42 | * |
43 | * @param priv A pointer to struct lbs_private structure | 43 | * @param priv A pointer to struct lbs_private structure |
44 | * @return avgSNR | 44 | * @return avgSNR |
45 | */ | 45 | */ |
46 | static u8 lbs_getavgsnr(struct lbs_private *priv) | 46 | static u8 lbs_getavgsnr(struct lbs_private *priv) |
47 | { | 47 | { |
@@ -56,10 +56,10 @@ static u8 lbs_getavgsnr(struct lbs_private *priv) | |||
56 | } | 56 | } |
57 | 57 | ||
58 | /** | 58 | /** |
59 | * @brief This function computes the AvgNF | 59 | * @brief This function computes the AvgNF |
60 | * | 60 | * |
61 | * @param priv A pointer to struct lbs_private structure | 61 | * @param priv A pointer to struct lbs_private structure |
62 | * @return AvgNF | 62 | * @return AvgNF |
63 | */ | 63 | */ |
64 | static u8 lbs_getavgnf(struct lbs_private *priv) | 64 | static u8 lbs_getavgnf(struct lbs_private *priv) |
65 | { | 65 | { |
@@ -74,11 +74,11 @@ static u8 lbs_getavgnf(struct lbs_private *priv) | |||
74 | } | 74 | } |
75 | 75 | ||
76 | /** | 76 | /** |
77 | * @brief This function save the raw SNR/NF to our internel buffer | 77 | * @brief This function save the raw SNR/NF to our internel buffer |
78 | * | 78 | * |
79 | * @param priv A pointer to struct lbs_private structure | 79 | * @param priv A pointer to struct lbs_private structure |
80 | * @param prxpd A pointer to rxpd structure of received packet | 80 | * @param prxpd A pointer to rxpd structure of received packet |
81 | * @return n/a | 81 | * @return n/a |
82 | */ | 82 | */ |
83 | static void lbs_save_rawSNRNF(struct lbs_private *priv, struct rxpd *p_rx_pd) | 83 | static void lbs_save_rawSNRNF(struct lbs_private *priv, struct rxpd *p_rx_pd) |
84 | { | 84 | { |
@@ -93,11 +93,11 @@ static void lbs_save_rawSNRNF(struct lbs_private *priv, struct rxpd *p_rx_pd) | |||
93 | } | 93 | } |
94 | 94 | ||
95 | /** | 95 | /** |
96 | * @brief This function computes the RSSI in received packet. | 96 | * @brief This function computes the RSSI in received packet. |
97 | * | 97 | * |
98 | * @param priv A pointer to struct lbs_private structure | 98 | * @param priv A pointer to struct lbs_private structure |
99 | * @param prxpd A pointer to rxpd structure of received packet | 99 | * @param prxpd A pointer to rxpd structure of received packet |
100 | * @return n/a | 100 | * @return n/a |
101 | */ | 101 | */ |
102 | static void lbs_compute_rssi(struct lbs_private *priv, struct rxpd *p_rx_pd) | 102 | static void lbs_compute_rssi(struct lbs_private *priv, struct rxpd *p_rx_pd) |
103 | { | 103 | { |
@@ -134,9 +134,9 @@ static void lbs_compute_rssi(struct lbs_private *priv, struct rxpd *p_rx_pd) | |||
134 | * @brief This function processes received packet and forwards it | 134 | * @brief This function processes received packet and forwards it |
135 | * to kernel/upper layer | 135 | * to kernel/upper layer |
136 | * | 136 | * |
137 | * @param priv A pointer to struct lbs_private | 137 | * @param priv A pointer to struct lbs_private |
138 | * @param skb A pointer to skb which includes the received packet | 138 | * @param skb A pointer to skb which includes the received packet |
139 | * @return 0 or -1 | 139 | * @return 0 or -1 |
140 | */ | 140 | */ |
141 | int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) | 141 | int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) |
142 | { | 142 | { |
@@ -196,7 +196,7 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) | |||
196 | * before the snap_type. | 196 | * before the snap_type. |
197 | */ | 197 | */ |
198 | p_ethhdr = (struct ethhdr *) | 198 | p_ethhdr = (struct ethhdr *) |
199 | ((u8 *) & p_rx_pkt->eth803_hdr | 199 | ((u8 *) &p_rx_pkt->eth803_hdr |
200 | + sizeof(p_rx_pkt->eth803_hdr) + sizeof(p_rx_pkt->rfc1042_hdr) | 200 | + sizeof(p_rx_pkt->eth803_hdr) + sizeof(p_rx_pkt->rfc1042_hdr) |
201 | - sizeof(p_rx_pkt->eth803_hdr.dest_addr) | 201 | - sizeof(p_rx_pkt->eth803_hdr.dest_addr) |
202 | - sizeof(p_rx_pkt->eth803_hdr.src_addr) | 202 | - sizeof(p_rx_pkt->eth803_hdr.src_addr) |
@@ -213,7 +213,7 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) | |||
213 | hdrchop = (u8 *)p_ethhdr - (u8 *)p_rx_pd; | 213 | hdrchop = (u8 *)p_ethhdr - (u8 *)p_rx_pd; |
214 | } else { | 214 | } else { |
215 | lbs_deb_hex(LBS_DEB_RX, "RX Data: LLC/SNAP", | 215 | lbs_deb_hex(LBS_DEB_RX, "RX Data: LLC/SNAP", |
216 | (u8 *) & p_rx_pkt->rfc1042_hdr, | 216 | (u8 *) &p_rx_pkt->rfc1042_hdr, |
217 | sizeof(p_rx_pkt->rfc1042_hdr)); | 217 | sizeof(p_rx_pkt->rfc1042_hdr)); |
218 | 218 | ||
219 | /* Chop off the rxpd */ | 219 | /* Chop off the rxpd */ |
@@ -254,8 +254,8 @@ EXPORT_SYMBOL_GPL(lbs_process_rxed_packet); | |||
254 | * @brief This function converts Tx/Rx rates from the Marvell WLAN format | 254 | * @brief This function converts Tx/Rx rates from the Marvell WLAN format |
255 | * (see Table 2 in Section 3.1) to IEEE80211_RADIOTAP_RATE units (500 Kb/s) | 255 | * (see Table 2 in Section 3.1) to IEEE80211_RADIOTAP_RATE units (500 Kb/s) |
256 | * | 256 | * |
257 | * @param rate Input rate | 257 | * @param rate Input rate |
258 | * @return Output Rate (0 if invalid) | 258 | * @return Output Rate (0 if invalid) |
259 | */ | 259 | */ |
260 | static u8 convert_mv_rate_to_radiotap(u8 rate) | 260 | static u8 convert_mv_rate_to_radiotap(u8 rate) |
261 | { | 261 | { |
@@ -294,9 +294,9 @@ static u8 convert_mv_rate_to_radiotap(u8 rate) | |||
294 | * @brief This function processes a received 802.11 packet and forwards it | 294 | * @brief This function processes a received 802.11 packet and forwards it |
295 | * to kernel/upper layer | 295 | * to kernel/upper layer |
296 | * | 296 | * |
297 | * @param priv A pointer to struct lbs_private | 297 | * @param priv A pointer to struct lbs_private |
298 | * @param skb A pointer to skb which includes the received packet | 298 | * @param skb A pointer to skb which includes the received packet |
299 | * @return 0 or -1 | 299 | * @return 0 or -1 |
300 | */ | 300 | */ |
301 | static int process_rxed_802_11_packet(struct lbs_private *priv, | 301 | static int process_rxed_802_11_packet(struct lbs_private *priv, |
302 | struct sk_buff *skb) | 302 | struct sk_buff *skb) |
@@ -313,7 +313,7 @@ static int process_rxed_802_11_packet(struct lbs_private *priv, | |||
313 | p_rx_pkt = (struct rx80211packethdr *) skb->data; | 313 | p_rx_pkt = (struct rx80211packethdr *) skb->data; |
314 | prxpd = &p_rx_pkt->rx_pd; | 314 | prxpd = &p_rx_pkt->rx_pd; |
315 | 315 | ||
316 | // lbs_deb_hex(LBS_DEB_RX, "RX Data: Before chop rxpd", skb->data, min(skb->len, 100)); | 316 | /* lbs_deb_hex(LBS_DEB_RX, "RX Data: Before chop rxpd", skb->data, min(skb->len, 100)); */ |
317 | 317 | ||
318 | if (skb->len < (ETH_HLEN + 8 + sizeof(struct rxpd))) { | 318 | if (skb->len < (ETH_HLEN + 8 + sizeof(struct rxpd))) { |
319 | lbs_deb_rx("rx err: frame received with bad length\n"); | 319 | lbs_deb_rx("rx err: frame received with bad length\n"); |
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index 71f88a08e090..aad6263dee6d 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c | |||
@@ -1440,8 +1440,10 @@ static int lbs_set_encode(struct net_device *dev, | |||
1440 | set_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags); | 1440 | set_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags); |
1441 | 1441 | ||
1442 | if (dwrq->flags & IW_ENCODE_RESTRICTED) { | 1442 | if (dwrq->flags & IW_ENCODE_RESTRICTED) { |
1443 | priv->authtype_auto = 0; | ||
1443 | assoc_req->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY; | 1444 | assoc_req->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY; |
1444 | } else if (dwrq->flags & IW_ENCODE_OPEN) { | 1445 | } else if (dwrq->flags & IW_ENCODE_OPEN) { |
1446 | priv->authtype_auto = 0; | ||
1445 | assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; | 1447 | assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; |
1446 | } | 1448 | } |
1447 | 1449 | ||
@@ -1620,8 +1622,10 @@ static int lbs_set_encodeext(struct net_device *dev, | |||
1620 | goto out; | 1622 | goto out; |
1621 | 1623 | ||
1622 | if (dwrq->flags & IW_ENCODE_RESTRICTED) { | 1624 | if (dwrq->flags & IW_ENCODE_RESTRICTED) { |
1625 | priv->authtype_auto = 0; | ||
1623 | assoc_req->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY; | 1626 | assoc_req->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY; |
1624 | } else if (dwrq->flags & IW_ENCODE_OPEN) { | 1627 | } else if (dwrq->flags & IW_ENCODE_OPEN) { |
1628 | priv->authtype_auto = 0; | ||
1625 | assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; | 1629 | assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; |
1626 | } | 1630 | } |
1627 | 1631 | ||
diff --git a/drivers/net/wireless/orinoco/Kconfig b/drivers/net/wireless/orinoco/Kconfig index e2a2c18920aa..6116b546861d 100644 --- a/drivers/net/wireless/orinoco/Kconfig +++ b/drivers/net/wireless/orinoco/Kconfig | |||
@@ -27,6 +27,17 @@ config HERMES | |||
27 | configure your card and that /etc/pcmcia/wireless.opts works : | 27 | configure your card and that /etc/pcmcia/wireless.opts works : |
28 | <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html> | 28 | <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html> |
29 | 29 | ||
30 | config HERMES_PRISM | ||
31 | bool "Support Prism 2/2.5 chipset" | ||
32 | depends on HERMES | ||
33 | ---help--- | ||
34 | |||
35 | Say Y to enable support for Prism 2 and 2.5 chipsets. These | ||
36 | chipsets are better handled by the hostap driver. This driver | ||
37 | would not support WPA or firmware download for Prism chipset. | ||
38 | |||
39 | If you are not sure, say N. | ||
40 | |||
30 | config HERMES_CACHE_FW_ON_INIT | 41 | config HERMES_CACHE_FW_ON_INIT |
31 | bool "Cache Hermes firmware on driver initialisation" | 42 | bool "Cache Hermes firmware on driver initialisation" |
32 | depends on HERMES | 43 | depends on HERMES |
@@ -86,7 +97,7 @@ config NORTEL_HERMES | |||
86 | 97 | ||
87 | config PCI_HERMES | 98 | config PCI_HERMES |
88 | tristate "Prism 2.5 PCI 802.11b adaptor support" | 99 | tristate "Prism 2.5 PCI 802.11b adaptor support" |
89 | depends on PCI && HERMES | 100 | depends on PCI && HERMES && HERMES_PRISM |
90 | help | 101 | help |
91 | Enable support for PCI and mini-PCI 802.11b wireless NICs based on | 102 | Enable support for PCI and mini-PCI 802.11b wireless NICs based on |
92 | the Prism 2.5 chipset. These are true PCI cards, not the 802.11b | 103 | the Prism 2.5 chipset. These are true PCI cards, not the 802.11b |
diff --git a/drivers/net/wireless/orinoco/hw.c b/drivers/net/wireless/orinoco/hw.c index e6369242e49c..883b8f868626 100644 --- a/drivers/net/wireless/orinoco/hw.c +++ b/drivers/net/wireless/orinoco/hw.c | |||
@@ -262,6 +262,13 @@ int determine_fw_capabilities(struct orinoco_private *priv, | |||
262 | if (fw_name) | 262 | if (fw_name) |
263 | dev_info(dev, "Firmware determined as %s\n", fw_name); | 263 | dev_info(dev, "Firmware determined as %s\n", fw_name); |
264 | 264 | ||
265 | #ifndef CONFIG_HERMES_PRISM | ||
266 | if (priv->firmware_type == FIRMWARE_TYPE_INTERSIL) { | ||
267 | dev_err(dev, "Support for Prism chipset is not enabled\n"); | ||
268 | return -ENODEV; | ||
269 | } | ||
270 | #endif | ||
271 | |||
265 | return 0; | 272 | return 0; |
266 | } | 273 | } |
267 | 274 | ||
diff --git a/drivers/net/wireless/orinoco/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c index 1d4ada188eda..fdc961379170 100644 --- a/drivers/net/wireless/orinoco/orinoco_cs.c +++ b/drivers/net/wireless/orinoco/orinoco_cs.c | |||
@@ -374,87 +374,90 @@ static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION | |||
374 | "Pavel Roskin <proski@gnu.org>, et al)"; | 374 | "Pavel Roskin <proski@gnu.org>, et al)"; |
375 | 375 | ||
376 | static struct pcmcia_device_id orinoco_cs_ids[] = { | 376 | static struct pcmcia_device_id orinoco_cs_ids[] = { |
377 | PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7100), /* SonicWALL Long Range Wireless Card */ | ||
378 | PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300), /* Sohoware NCP110, Philips 802.11b */ | ||
379 | PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0002), /* AnyPoint(TM) Wireless II PC Card */ | ||
380 | PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0777), /* 3Com AirConnect PCI 777A */ | 377 | PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0777), /* 3Com AirConnect PCI 777A */ |
381 | PCMCIA_DEVICE_MANF_CARD(0x0126, 0x8000), /* PROXIM RangeLAN-DS/LAN PC CARD */ | ||
382 | PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002), /* Compaq WL100 11 Mbps Wireless Adapter */ | ||
383 | PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002), /* Lucent Orinoco and old Intersil */ | 378 | PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002), /* Lucent Orinoco and old Intersil */ |
384 | PCMCIA_DEVICE_MANF_CARD(0x016b, 0x0001), /* Ericsson WLAN Card C11 */ | 379 | PCMCIA_DEVICE_MANF_CARD(0x016b, 0x0001), /* Ericsson WLAN Card C11 */ |
385 | PCMCIA_DEVICE_MANF_CARD(0x01eb, 0x080a), /* Nortel Networks eMobility 802.11 Wireless Adapter */ | 380 | PCMCIA_DEVICE_MANF_CARD(0x01eb, 0x080a), /* Nortel Networks eMobility 802.11 Wireless Adapter */ |
386 | PCMCIA_DEVICE_MANF_CARD(0x01ff, 0x0008), /* Intermec MobileLAN 11Mbps 802.11b WLAN Card */ | ||
387 | PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002), /* Samsung SWL2000-N 11Mb/s WLAN Card */ | ||
388 | PCMCIA_DEVICE_MANF_CARD(0x0261, 0x0002), /* AirWay 802.11 Adapter (PCMCIA) */ | 381 | PCMCIA_DEVICE_MANF_CARD(0x0261, 0x0002), /* AirWay 802.11 Adapter (PCMCIA) */ |
389 | PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0001), /* ARtem Onair */ | 382 | PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0001), /* ARtem Onair */ |
390 | PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0003), /* ARtem Onair Comcard 11 */ | 383 | PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0003), /* ARtem Onair Comcard 11 */ |
391 | PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0305), /* Buffalo WLI-PCM-S11 */ | 384 | PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0305), /* Buffalo WLI-PCM-S11 */ |
392 | PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1612), /* Linksys WPC11 Version 2.5 */ | ||
393 | PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613), /* Linksys WPC11 Version 3 */ | ||
394 | PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002), /* Compaq HNW-100 11 Mbps Wireless Adapter */ | ||
395 | PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0673), /* Linksys WCF12 Wireless CompactFlash Card */ | ||
396 | PCMCIA_DEVICE_MANF_CARD(0x02aa, 0x0002), /* ASUS SpaceLink WL-100 */ | 385 | PCMCIA_DEVICE_MANF_CARD(0x02aa, 0x0002), /* ASUS SpaceLink WL-100 */ |
397 | PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x0002), /* SpeedStream SS1021 Wireless Adapter */ | 386 | PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x0002), /* SpeedStream SS1021 Wireless Adapter */ |
398 | PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x3021), /* SpeedStream Wireless Adapter */ | 387 | PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x3021), /* SpeedStream Wireless Adapter */ |
399 | PCMCIA_DEVICE_MANF_CARD(0x14ea, 0xb001), /* PLANEX RoadLannerWave GW-NS11H */ | 388 | PCMCIA_DEVICE_MANF_CARD(0x14ea, 0xb001), /* PLANEX RoadLannerWave GW-NS11H */ |
389 | PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE737A AirConnect Wireless LAN PC Card", 0x41240e5b, 0x56010af3), | ||
390 | PCMCIA_DEVICE_PROD_ID12("Allied Telesyn", "AT-WCL452 Wireless PCMCIA Radio", 0x5cd01705, 0x4271660f), | ||
391 | PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11B_CF_CARD_25", 0x78fc06ee, 0x45a50c1e), | ||
392 | PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11b_PC_CARD_25", 0x78fc06ee, 0xdb9aa842), | ||
393 | PCMCIA_DEVICE_PROD_ID12("Avaya Communication", "Avaya Wireless PC Card", 0xd8a43b78, 0x0d341169), | ||
394 | PCMCIA_DEVICE_PROD_ID12("BENQ", "AWL100 PCMCIA ADAPTER", 0x35dadc74, 0x01f7fedb), | ||
395 | PCMCIA_DEVICE_PROD_ID12("Cabletron", "RoamAbout 802.11 DS", 0x32d445f5, 0xedeffd90), | ||
396 | PCMCIA_DEVICE_PROD_ID12("D-Link Corporation", "D-Link DWL-650H 11Mbps WLAN Adapter", 0xef544d24, 0xcd8ea916), | ||
397 | PCMCIA_DEVICE_PROD_ID12("ELSA", "AirLancer MC-11", 0x4507a33a, 0xef54f0e3), | ||
398 | PCMCIA_DEVICE_PROD_ID12("HyperLink", "Wireless PC Card 11Mbps", 0x56cc3f1a, 0x0bcf220c), | ||
399 | PCMCIA_DEVICE_PROD_ID12("Intel", "PRO/Wireless 2011 LAN PC Card", 0x816cc815, 0x07f58077), | ||
400 | PCMCIA_DEVICE_PROD_ID12("LeArtery", "SYNCBYAIR 11Mbps Wireless LAN PC Card", 0x7e3b326a, 0x49893e92), | ||
401 | PCMCIA_DEVICE_PROD_ID12("Lucent Technologies", "WaveLAN/IEEE", 0x23eb9949, 0xc562e72a), | ||
402 | PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11", 0x481e0094, 0x7360e410), | ||
403 | PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11G", 0x481e0094, 0xf57ca4b3), | ||
404 | PCMCIA_DEVICE_PROD_ID12("NCR", "WaveLAN/IEEE", 0x24358cd4, 0xc562e72a), | ||
405 | PCMCIA_DEVICE_PROD_ID12("Nortel Networks", "emobility 802.11 Wireless LAN PC Card", 0x2d617ea0, 0x88cd5767), | ||
406 | PCMCIA_DEVICE_PROD_ID12("OTC", "Wireless AirEZY 2411-PCC WLAN Card", 0x4ac44287, 0x235a6bed), | ||
407 | PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PC CARD HARMONY 80211B", 0xc6536a5e, 0x090c3cd9), | ||
408 | PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PCI CARD HARMONY 80211B", 0xc6536a5e, 0x9f494e26), | ||
409 | PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "11Mbps WLAN Card", 0x43d74cb4, 0x579bd91b), | ||
410 | PCMCIA_DEVICE_PROD_ID12("Symbol Technologies", "LA4111 Spectrum24 Wireless LAN PC Card", 0x3f02b4d6, 0x3663cb0e), | ||
411 | #ifdef CONFIG_HERMES_PRISM | ||
412 | /* Only entries that certainly identify Prism chipset */ | ||
413 | PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7100), /* SonicWALL Long Range Wireless Card */ | ||
414 | PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300), /* Sohoware NCP110, Philips 802.11b */ | ||
415 | PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0002), /* AnyPoint(TM) Wireless II PC Card */ | ||
416 | PCMCIA_DEVICE_MANF_CARD(0x0126, 0x8000), /* PROXIM RangeLAN-DS/LAN PC CARD */ | ||
417 | PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002), /* Compaq WL100 11 Mbps Wireless Adapter */ | ||
418 | PCMCIA_DEVICE_MANF_CARD(0x01ff, 0x0008), /* Intermec MobileLAN 11Mbps 802.11b WLAN Card */ | ||
419 | PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002), /* Samsung SWL2000-N 11Mb/s WLAN Card */ | ||
420 | PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1612), /* Linksys WPC11 Version 2.5 */ | ||
421 | PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613), /* Linksys WPC11 Version 3 */ | ||
422 | PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002), /* Compaq HNW-100 11 Mbps Wireless Adapter */ | ||
423 | PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0673), /* Linksys WCF12 Wireless CompactFlash Card */ | ||
400 | PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x7300), /* Airvast WN-100 */ | 424 | PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x7300), /* Airvast WN-100 */ |
401 | PCMCIA_DEVICE_MANF_CARD(0x9005, 0x0021), /* Adaptec Ultra Wireless ANW-8030 */ | 425 | PCMCIA_DEVICE_MANF_CARD(0x9005, 0x0021), /* Adaptec Ultra Wireless ANW-8030 */ |
402 | PCMCIA_DEVICE_MANF_CARD(0xc001, 0x0008), /* CONTEC FLEXSCAN/FX-DDS110-PCC */ | 426 | PCMCIA_DEVICE_MANF_CARD(0xc001, 0x0008), /* CONTEC FLEXSCAN/FX-DDS110-PCC */ |
403 | PCMCIA_DEVICE_MANF_CARD(0xc250, 0x0002), /* Conceptronic CON11Cpro, EMTAC A2424i */ | 427 | PCMCIA_DEVICE_MANF_CARD(0xc250, 0x0002), /* Conceptronic CON11Cpro, EMTAC A2424i */ |
404 | PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002), /* Safeway 802.11b, ZCOMAX AirRunner/XI-300 */ | 428 | PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002), /* Safeway 802.11b, ZCOMAX AirRunner/XI-300 */ |
405 | PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005), /* D-Link DCF660, Sandisk Connect SDWCFB-000 */ | 429 | PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005), /* D-Link DCF660, Sandisk Connect SDWCFB-000 */ |
406 | PCMCIA_DEVICE_PROD_ID12(" ", "IEEE 802.11 Wireless LAN/PC Card", 0x3b6e20c8, 0xefccafe9), | 430 | PCMCIA_DEVICE_PROD_ID123("Instant Wireless ", " Network PC CARD", "Version 01.02", 0x11d901af, 0x6e9bd926, 0x4b74baa0), |
407 | PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE737A AirConnect Wireless LAN PC Card", 0x41240e5b, 0x56010af3), | ||
408 | PCMCIA_DEVICE_PROD_ID12("ACTIONTEC", "PRISM Wireless LAN PC Card", 0x393089da, 0xa71e69d5), | 431 | PCMCIA_DEVICE_PROD_ID12("ACTIONTEC", "PRISM Wireless LAN PC Card", 0x393089da, 0xa71e69d5), |
409 | PCMCIA_DEVICE_PROD_ID12("Addtron", "AWP-100 Wireless PCMCIA", 0xe6ec52ce, 0x08649af2), | 432 | PCMCIA_DEVICE_PROD_ID12("Addtron", "AWP-100 Wireless PCMCIA", 0xe6ec52ce, 0x08649af2), |
410 | PCMCIA_DEVICE_PROD_ID12("Allied Telesyn", "AT-WCL452 Wireless PCMCIA Radio", 0x5cd01705, 0x4271660f), | ||
411 | PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11b_PC_CARD_25", 0x78fc06ee, 0xdb9aa842), | ||
412 | PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11B_CF_CARD_25", 0x78fc06ee, 0x45a50c1e), | ||
413 | PCMCIA_DEVICE_PROD_ID12("Avaya Communication", "Avaya Wireless PC Card", 0xd8a43b78, 0x0d341169), | ||
414 | PCMCIA_DEVICE_PROD_ID12("BENQ", "AWL100 PCMCIA ADAPTER", 0x35dadc74, 0x01f7fedb), | ||
415 | PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-PCM-L11G", 0x2decece3, 0xf57ca4b3), | ||
416 | PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-CF-S11G", 0x2decece3, 0x82067c18), | 433 | PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-CF-S11G", 0x2decece3, 0x82067c18), |
417 | PCMCIA_DEVICE_PROD_ID12("Cabletron", "RoamAbout 802.11 DS", 0x32d445f5, 0xedeffd90), | 434 | PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-PCM-L11G", 0x2decece3, 0xf57ca4b3), |
418 | PCMCIA_DEVICE_PROD_ID12("Compaq", "WL200_11Mbps_Wireless_PCI_Card", 0x54f7c49c, 0x15a75e5b), | 435 | PCMCIA_DEVICE_PROD_ID12("Compaq", "WL200_11Mbps_Wireless_PCI_Card", 0x54f7c49c, 0x15a75e5b), |
419 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCC-11", 0x5261440f, 0xa6405584), | 436 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCC-11", 0x5261440f, 0xa6405584), |
420 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCCA-11", 0x5261440f, 0xdf6115f9), | 437 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCCA-11", 0x5261440f, 0xdf6115f9), |
421 | PCMCIA_DEVICE_PROD_ID12("corega_K.K.", "Wireless_LAN_PCCB-11", 0x29e33311, 0xee7a27ae), | 438 | PCMCIA_DEVICE_PROD_ID12("corega_K.K.", "Wireless_LAN_PCCB-11", 0x29e33311, 0xee7a27ae), |
439 | PCMCIA_DEVICE_PROD_ID12("Digital Data Communications", "WPC-0100", 0xfdd73470, 0xe0b6f146), | ||
422 | PCMCIA_DEVICE_PROD_ID12("D", "Link DRC-650 11Mbps WLAN Card", 0x71b18589, 0xf144e3ac), | 440 | PCMCIA_DEVICE_PROD_ID12("D", "Link DRC-650 11Mbps WLAN Card", 0x71b18589, 0xf144e3ac), |
423 | PCMCIA_DEVICE_PROD_ID12("D", "Link DWL-650 11Mbps WLAN Card", 0x71b18589, 0xb6f1b0ab), | 441 | PCMCIA_DEVICE_PROD_ID12("D", "Link DWL-650 11Mbps WLAN Card", 0x71b18589, 0xb6f1b0ab), |
424 | PCMCIA_DEVICE_PROD_ID12("D-Link Corporation", "D-Link DWL-650H 11Mbps WLAN Adapter", 0xef544d24, 0xcd8ea916), | 442 | PCMCIA_DEVICE_PROD_ID12(" ", "IEEE 802.11 Wireless LAN/PC Card", 0x3b6e20c8, 0xefccafe9), |
425 | PCMCIA_DEVICE_PROD_ID12("Digital Data Communications", "WPC-0100", 0xfdd73470, 0xe0b6f146), | ||
426 | PCMCIA_DEVICE_PROD_ID12("ELSA", "AirLancer MC-11", 0x4507a33a, 0xef54f0e3), | ||
427 | PCMCIA_DEVICE_PROD_ID12("HyperLink", "Wireless PC Card 11Mbps", 0x56cc3f1a, 0x0bcf220c), | ||
428 | PCMCIA_DEVICE_PROD_ID123("Instant Wireless ", " Network PC CARD", "Version 01.02", 0x11d901af, 0x6e9bd926, 0x4b74baa0), | ||
429 | PCMCIA_DEVICE_PROD_ID12("Intel", "PRO/Wireless 2011 LAN PC Card", 0x816cc815, 0x07f58077), | ||
430 | PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE", 0x74c5e40d, 0xdb472a18), | 443 | PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE", 0x74c5e40d, 0xdb472a18), |
431 | PCMCIA_DEVICE_PROD_ID12("INTERSIL", "I-GATE 11M PC Card / PC Card plus", 0x74c5e40d, 0x8304ff77), | 444 | PCMCIA_DEVICE_PROD_ID12("INTERSIL", "I-GATE 11M PC Card / PC Card plus", 0x74c5e40d, 0x8304ff77), |
432 | PCMCIA_DEVICE_PROD_ID12("Intersil", "PRISM 2_5 PCMCIA ADAPTER", 0x4b801a17, 0x6345a0bf), | 445 | PCMCIA_DEVICE_PROD_ID12("Intersil", "PRISM 2_5 PCMCIA ADAPTER", 0x4b801a17, 0x6345a0bf), |
433 | PCMCIA_DEVICE_PROD_ID12("LeArtery", "SYNCBYAIR 11Mbps Wireless LAN PC Card", 0x7e3b326a, 0x49893e92), | ||
434 | PCMCIA_DEVICE_PROD_ID12("Linksys", "Wireless CompactFlash Card", 0x0733cc81, 0x0c52f395), | 446 | PCMCIA_DEVICE_PROD_ID12("Linksys", "Wireless CompactFlash Card", 0x0733cc81, 0x0c52f395), |
435 | PCMCIA_DEVICE_PROD_ID12("Lucent Technologies", "WaveLAN/IEEE", 0x23eb9949, 0xc562e72a), | ||
436 | PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11", 0x481e0094, 0x7360e410), | ||
437 | PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11G", 0x481e0094, 0xf57ca4b3), | ||
438 | PCMCIA_DEVICE_PROD_ID12("Microsoft", "Wireless Notebook Adapter MN-520", 0x5961bf85, 0x6eec8c01), | 447 | PCMCIA_DEVICE_PROD_ID12("Microsoft", "Wireless Notebook Adapter MN-520", 0x5961bf85, 0x6eec8c01), |
439 | PCMCIA_DEVICE_PROD_ID12("NCR", "WaveLAN/IEEE", 0x24358cd4, 0xc562e72a), | ||
440 | PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401 Wireless PC", "Card", 0xa37434e9, 0x9762e8f1), | ||
441 | PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401RA Wireless PC", "Card", 0x0306467f, 0x9762e8f1), | 448 | PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401RA Wireless PC", "Card", 0x0306467f, 0x9762e8f1), |
442 | PCMCIA_DEVICE_PROD_ID12("Nortel Networks", "emobility 802.11 Wireless LAN PC Card", 0x2d617ea0, 0x88cd5767), | 449 | PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401 Wireless PC", "Card", 0xa37434e9, 0x9762e8f1), |
443 | PCMCIA_DEVICE_PROD_ID12("OEM", "PRISM2 IEEE 802.11 PC-Card", 0xfea54c90, 0x48f2bdd6), | 450 | PCMCIA_DEVICE_PROD_ID12("OEM", "PRISM2 IEEE 802.11 PC-Card", 0xfea54c90, 0x48f2bdd6), |
444 | PCMCIA_DEVICE_PROD_ID12("OTC", "Wireless AirEZY 2411-PCC WLAN Card", 0x4ac44287, 0x235a6bed), | ||
445 | PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-CF110", 0x209f40ab, 0xd9715264), | 451 | PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-CF110", 0x209f40ab, 0xd9715264), |
446 | PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-NS110", 0x209f40ab, 0x46263178), | 452 | PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-NS110", 0x209f40ab, 0x46263178), |
447 | PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PC CARD HARMONY 80211B", 0xc6536a5e, 0x090c3cd9), | ||
448 | PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PCI CARD HARMONY 80211B", 0xc6536a5e, 0x9f494e26), | ||
449 | PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "11Mbps WLAN Card", 0x43d74cb4, 0x579bd91b), | ||
450 | PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2532W-B EliteConnect Wireless Adapter", 0xc4f8b18b, 0x196bd757), | 453 | PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2532W-B EliteConnect Wireless Adapter", 0xc4f8b18b, 0x196bd757), |
451 | PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2632W", 0xc4f8b18b, 0x474a1f2a), | 454 | PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2632W", 0xc4f8b18b, 0x474a1f2a), |
452 | PCMCIA_DEVICE_PROD_ID12("Symbol Technologies", "LA4111 Spectrum24 Wireless LAN PC Card", 0x3f02b4d6, 0x3663cb0e), | ||
453 | PCMCIA_DEVICE_PROD_ID12("ZoomAir 11Mbps High", "Rate wireless Networking", 0x273fe3db, 0x32a1eaee), | 455 | PCMCIA_DEVICE_PROD_ID12("ZoomAir 11Mbps High", "Rate wireless Networking", 0x273fe3db, 0x32a1eaee), |
454 | PCMCIA_DEVICE_PROD_ID3("HFA3863", 0x355cb092), | 456 | PCMCIA_DEVICE_PROD_ID3("HFA3863", 0x355cb092), |
455 | PCMCIA_DEVICE_PROD_ID3("ISL37100P", 0x630d52b2), | 457 | PCMCIA_DEVICE_PROD_ID3("ISL37100P", 0x630d52b2), |
456 | PCMCIA_DEVICE_PROD_ID3("ISL37101P-10", 0xdd97a26b), | 458 | PCMCIA_DEVICE_PROD_ID3("ISL37101P-10", 0xdd97a26b), |
457 | PCMCIA_DEVICE_PROD_ID3("ISL37300P", 0xc9049a39), | 459 | PCMCIA_DEVICE_PROD_ID3("ISL37300P", 0xc9049a39), |
460 | #endif | ||
458 | PCMCIA_DEVICE_NULL, | 461 | PCMCIA_DEVICE_NULL, |
459 | }; | 462 | }; |
460 | MODULE_DEVICE_TABLE(pcmcia, orinoco_cs_ids); | 463 | MODULE_DEVICE_TABLE(pcmcia, orinoco_cs_ids); |
diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c index 31ca241f7753..29f9bc03190a 100644 --- a/drivers/net/wireless/orinoco/wext.c +++ b/drivers/net/wireless/orinoco/wext.c | |||
@@ -1505,46 +1505,44 @@ static const struct iw_priv_args orinoco_privtab[] = { | |||
1505 | * Structures to export the Wireless Handlers | 1505 | * Structures to export the Wireless Handlers |
1506 | */ | 1506 | */ |
1507 | 1507 | ||
1508 | #define STD_IW_HANDLER(id, func) \ | ||
1509 | [IW_IOCTL_IDX(id)] = (iw_handler) func | ||
1510 | static const iw_handler orinoco_handler[] = { | 1508 | static const iw_handler orinoco_handler[] = { |
1511 | STD_IW_HANDLER(SIOCSIWCOMMIT, orinoco_ioctl_commit), | 1509 | IW_HANDLER(SIOCSIWCOMMIT, (iw_handler)orinoco_ioctl_commit), |
1512 | STD_IW_HANDLER(SIOCGIWNAME, cfg80211_wext_giwname), | 1510 | IW_HANDLER(SIOCGIWNAME, (iw_handler)cfg80211_wext_giwname), |
1513 | STD_IW_HANDLER(SIOCSIWFREQ, orinoco_ioctl_setfreq), | 1511 | IW_HANDLER(SIOCSIWFREQ, (iw_handler)orinoco_ioctl_setfreq), |
1514 | STD_IW_HANDLER(SIOCGIWFREQ, orinoco_ioctl_getfreq), | 1512 | IW_HANDLER(SIOCGIWFREQ, (iw_handler)orinoco_ioctl_getfreq), |
1515 | STD_IW_HANDLER(SIOCSIWMODE, cfg80211_wext_siwmode), | 1513 | IW_HANDLER(SIOCSIWMODE, (iw_handler)cfg80211_wext_siwmode), |
1516 | STD_IW_HANDLER(SIOCGIWMODE, cfg80211_wext_giwmode), | 1514 | IW_HANDLER(SIOCGIWMODE, (iw_handler)cfg80211_wext_giwmode), |
1517 | STD_IW_HANDLER(SIOCSIWSENS, orinoco_ioctl_setsens), | 1515 | IW_HANDLER(SIOCSIWSENS, (iw_handler)orinoco_ioctl_setsens), |
1518 | STD_IW_HANDLER(SIOCGIWSENS, orinoco_ioctl_getsens), | 1516 | IW_HANDLER(SIOCGIWSENS, (iw_handler)orinoco_ioctl_getsens), |
1519 | STD_IW_HANDLER(SIOCGIWRANGE, cfg80211_wext_giwrange), | 1517 | IW_HANDLER(SIOCGIWRANGE, (iw_handler)cfg80211_wext_giwrange), |
1520 | STD_IW_HANDLER(SIOCSIWSPY, iw_handler_set_spy), | 1518 | IW_HANDLER(SIOCSIWSPY, iw_handler_set_spy), |
1521 | STD_IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy), | 1519 | IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy), |
1522 | STD_IW_HANDLER(SIOCSIWTHRSPY, iw_handler_set_thrspy), | 1520 | IW_HANDLER(SIOCSIWTHRSPY, iw_handler_set_thrspy), |
1523 | STD_IW_HANDLER(SIOCGIWTHRSPY, iw_handler_get_thrspy), | 1521 | IW_HANDLER(SIOCGIWTHRSPY, iw_handler_get_thrspy), |
1524 | STD_IW_HANDLER(SIOCSIWAP, orinoco_ioctl_setwap), | 1522 | IW_HANDLER(SIOCSIWAP, (iw_handler)orinoco_ioctl_setwap), |
1525 | STD_IW_HANDLER(SIOCGIWAP, orinoco_ioctl_getwap), | 1523 | IW_HANDLER(SIOCGIWAP, (iw_handler)orinoco_ioctl_getwap), |
1526 | STD_IW_HANDLER(SIOCSIWSCAN, cfg80211_wext_siwscan), | 1524 | IW_HANDLER(SIOCSIWSCAN, (iw_handler)cfg80211_wext_siwscan), |
1527 | STD_IW_HANDLER(SIOCGIWSCAN, cfg80211_wext_giwscan), | 1525 | IW_HANDLER(SIOCGIWSCAN, (iw_handler)cfg80211_wext_giwscan), |
1528 | STD_IW_HANDLER(SIOCSIWESSID, orinoco_ioctl_setessid), | 1526 | IW_HANDLER(SIOCSIWESSID, (iw_handler)orinoco_ioctl_setessid), |
1529 | STD_IW_HANDLER(SIOCGIWESSID, orinoco_ioctl_getessid), | 1527 | IW_HANDLER(SIOCGIWESSID, (iw_handler)orinoco_ioctl_getessid), |
1530 | STD_IW_HANDLER(SIOCSIWRATE, orinoco_ioctl_setrate), | 1528 | IW_HANDLER(SIOCSIWRATE, (iw_handler)orinoco_ioctl_setrate), |
1531 | STD_IW_HANDLER(SIOCGIWRATE, orinoco_ioctl_getrate), | 1529 | IW_HANDLER(SIOCGIWRATE, (iw_handler)orinoco_ioctl_getrate), |
1532 | STD_IW_HANDLER(SIOCSIWRTS, orinoco_ioctl_setrts), | 1530 | IW_HANDLER(SIOCSIWRTS, (iw_handler)orinoco_ioctl_setrts), |
1533 | STD_IW_HANDLER(SIOCGIWRTS, orinoco_ioctl_getrts), | 1531 | IW_HANDLER(SIOCGIWRTS, (iw_handler)orinoco_ioctl_getrts), |
1534 | STD_IW_HANDLER(SIOCSIWFRAG, orinoco_ioctl_setfrag), | 1532 | IW_HANDLER(SIOCSIWFRAG, (iw_handler)orinoco_ioctl_setfrag), |
1535 | STD_IW_HANDLER(SIOCGIWFRAG, orinoco_ioctl_getfrag), | 1533 | IW_HANDLER(SIOCGIWFRAG, (iw_handler)orinoco_ioctl_getfrag), |
1536 | STD_IW_HANDLER(SIOCGIWRETRY, orinoco_ioctl_getretry), | 1534 | IW_HANDLER(SIOCGIWRETRY, (iw_handler)orinoco_ioctl_getretry), |
1537 | STD_IW_HANDLER(SIOCSIWENCODE, orinoco_ioctl_setiwencode), | 1535 | IW_HANDLER(SIOCSIWENCODE, (iw_handler)orinoco_ioctl_setiwencode), |
1538 | STD_IW_HANDLER(SIOCGIWENCODE, orinoco_ioctl_getiwencode), | 1536 | IW_HANDLER(SIOCGIWENCODE, (iw_handler)orinoco_ioctl_getiwencode), |
1539 | STD_IW_HANDLER(SIOCSIWPOWER, orinoco_ioctl_setpower), | 1537 | IW_HANDLER(SIOCSIWPOWER, (iw_handler)orinoco_ioctl_setpower), |
1540 | STD_IW_HANDLER(SIOCGIWPOWER, orinoco_ioctl_getpower), | 1538 | IW_HANDLER(SIOCGIWPOWER, (iw_handler)orinoco_ioctl_getpower), |
1541 | STD_IW_HANDLER(SIOCSIWGENIE, orinoco_ioctl_set_genie), | 1539 | IW_HANDLER(SIOCSIWGENIE, orinoco_ioctl_set_genie), |
1542 | STD_IW_HANDLER(SIOCGIWGENIE, orinoco_ioctl_get_genie), | 1540 | IW_HANDLER(SIOCGIWGENIE, orinoco_ioctl_get_genie), |
1543 | STD_IW_HANDLER(SIOCSIWMLME, orinoco_ioctl_set_mlme), | 1541 | IW_HANDLER(SIOCSIWMLME, orinoco_ioctl_set_mlme), |
1544 | STD_IW_HANDLER(SIOCSIWAUTH, orinoco_ioctl_set_auth), | 1542 | IW_HANDLER(SIOCSIWAUTH, orinoco_ioctl_set_auth), |
1545 | STD_IW_HANDLER(SIOCGIWAUTH, orinoco_ioctl_get_auth), | 1543 | IW_HANDLER(SIOCGIWAUTH, orinoco_ioctl_get_auth), |
1546 | STD_IW_HANDLER(SIOCSIWENCODEEXT, orinoco_ioctl_set_encodeext), | 1544 | IW_HANDLER(SIOCSIWENCODEEXT, orinoco_ioctl_set_encodeext), |
1547 | STD_IW_HANDLER(SIOCGIWENCODEEXT, orinoco_ioctl_get_encodeext), | 1545 | IW_HANDLER(SIOCGIWENCODEEXT, orinoco_ioctl_get_encodeext), |
1548 | }; | 1546 | }; |
1549 | 1547 | ||
1550 | 1548 | ||
@@ -1552,15 +1550,15 @@ static const iw_handler orinoco_handler[] = { | |||
1552 | Added typecasting since we no longer use iwreq_data -- Moustafa | 1550 | Added typecasting since we no longer use iwreq_data -- Moustafa |
1553 | */ | 1551 | */ |
1554 | static const iw_handler orinoco_private_handler[] = { | 1552 | static const iw_handler orinoco_private_handler[] = { |
1555 | [0] = (iw_handler) orinoco_ioctl_reset, | 1553 | [0] = (iw_handler)orinoco_ioctl_reset, |
1556 | [1] = (iw_handler) orinoco_ioctl_reset, | 1554 | [1] = (iw_handler)orinoco_ioctl_reset, |
1557 | [2] = (iw_handler) orinoco_ioctl_setport3, | 1555 | [2] = (iw_handler)orinoco_ioctl_setport3, |
1558 | [3] = (iw_handler) orinoco_ioctl_getport3, | 1556 | [3] = (iw_handler)orinoco_ioctl_getport3, |
1559 | [4] = (iw_handler) orinoco_ioctl_setpreamble, | 1557 | [4] = (iw_handler)orinoco_ioctl_setpreamble, |
1560 | [5] = (iw_handler) orinoco_ioctl_getpreamble, | 1558 | [5] = (iw_handler)orinoco_ioctl_getpreamble, |
1561 | [6] = (iw_handler) orinoco_ioctl_setibssport, | 1559 | [6] = (iw_handler)orinoco_ioctl_setibssport, |
1562 | [7] = (iw_handler) orinoco_ioctl_getibssport, | 1560 | [7] = (iw_handler)orinoco_ioctl_getibssport, |
1563 | [9] = (iw_handler) orinoco_ioctl_getrid, | 1561 | [9] = (iw_handler)orinoco_ioctl_getrid, |
1564 | }; | 1562 | }; |
1565 | 1563 | ||
1566 | const struct iw_handler_def orinoco_handler_def = { | 1564 | const struct iw_handler_def orinoco_handler_def = { |
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index 4f752a21495f..36f4c820ad01 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c | |||
@@ -545,6 +545,7 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) | |||
545 | IEEE80211_HW_SUPPORTS_PS | | 545 | IEEE80211_HW_SUPPORTS_PS | |
546 | IEEE80211_HW_PS_NULLFUNC_STACK | | 546 | IEEE80211_HW_PS_NULLFUNC_STACK | |
547 | IEEE80211_HW_BEACON_FILTER | | 547 | IEEE80211_HW_BEACON_FILTER | |
548 | IEEE80211_HW_REPORTS_TX_ACK_STATUS | | ||
548 | IEEE80211_HW_NOISE_DBM; | 549 | IEEE80211_HW_NOISE_DBM; |
549 | 550 | ||
550 | dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | 551 | dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c index 66057999a93c..2ceff5480355 100644 --- a/drivers/net/wireless/p54/txrx.c +++ b/drivers/net/wireless/p54/txrx.c | |||
@@ -38,7 +38,7 @@ static void p54_dump_tx_queue(struct p54_common *priv) | |||
38 | u32 largest_hole = 0, free; | 38 | u32 largest_hole = 0, free; |
39 | 39 | ||
40 | spin_lock_irqsave(&priv->tx_queue.lock, flags); | 40 | spin_lock_irqsave(&priv->tx_queue.lock, flags); |
41 | printk(KERN_DEBUG "%s: / --- tx queue dump (%d entries) --- \n", | 41 | printk(KERN_DEBUG "%s: / --- tx queue dump (%d entries) ---\n", |
42 | wiphy_name(priv->hw->wiphy), skb_queue_len(&priv->tx_queue)); | 42 | wiphy_name(priv->hw->wiphy), skb_queue_len(&priv->tx_queue)); |
43 | 43 | ||
44 | prev_addr = priv->rx_start; | 44 | prev_addr = priv->rx_start; |
diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c index a3ba3539db02..7c82e432cca7 100644 --- a/drivers/net/wireless/prism54/islpci_dev.c +++ b/drivers/net/wireless/prism54/islpci_dev.c | |||
@@ -227,14 +227,14 @@ islpci_interrupt(int irq, void *config) | |||
227 | 227 | ||
228 | #if VERBOSE > SHOW_ERROR_MESSAGES | 228 | #if VERBOSE > SHOW_ERROR_MESSAGES |
229 | DEBUG(SHOW_FUNCTION_CALLS, | 229 | DEBUG(SHOW_FUNCTION_CALLS, |
230 | "IRQ: Identification register 0x%p 0x%x \n", device, reg); | 230 | "IRQ: Identification register 0x%p 0x%x\n", device, reg); |
231 | #endif | 231 | #endif |
232 | 232 | ||
233 | /* check for each bit in the register separately */ | 233 | /* check for each bit in the register separately */ |
234 | if (reg & ISL38XX_INT_IDENT_UPDATE) { | 234 | if (reg & ISL38XX_INT_IDENT_UPDATE) { |
235 | #if VERBOSE > SHOW_ERROR_MESSAGES | 235 | #if VERBOSE > SHOW_ERROR_MESSAGES |
236 | /* Queue has been updated */ | 236 | /* Queue has been updated */ |
237 | DEBUG(SHOW_TRACING, "IRQ: Update flag \n"); | 237 | DEBUG(SHOW_TRACING, "IRQ: Update flag\n"); |
238 | 238 | ||
239 | DEBUG(SHOW_QUEUE_INDEXES, | 239 | DEBUG(SHOW_QUEUE_INDEXES, |
240 | "CB drv Qs: [%i][%i][%i][%i][%i][%i]\n", | 240 | "CB drv Qs: [%i][%i][%i][%i][%i][%i]\n", |
@@ -300,7 +300,7 @@ islpci_interrupt(int irq, void *config) | |||
300 | ISL38XX_CB_RX_DATA_LQ) != 0) { | 300 | ISL38XX_CB_RX_DATA_LQ) != 0) { |
301 | #if VERBOSE > SHOW_ERROR_MESSAGES | 301 | #if VERBOSE > SHOW_ERROR_MESSAGES |
302 | DEBUG(SHOW_TRACING, | 302 | DEBUG(SHOW_TRACING, |
303 | "Received frame in Data Low Queue \n"); | 303 | "Received frame in Data Low Queue\n"); |
304 | #endif | 304 | #endif |
305 | islpci_eth_receive(priv); | 305 | islpci_eth_receive(priv); |
306 | } | 306 | } |
@@ -325,7 +325,7 @@ islpci_interrupt(int irq, void *config) | |||
325 | /* Device has been initialized */ | 325 | /* Device has been initialized */ |
326 | #if VERBOSE > SHOW_ERROR_MESSAGES | 326 | #if VERBOSE > SHOW_ERROR_MESSAGES |
327 | DEBUG(SHOW_TRACING, | 327 | DEBUG(SHOW_TRACING, |
328 | "IRQ: Init flag, device initialized \n"); | 328 | "IRQ: Init flag, device initialized\n"); |
329 | #endif | 329 | #endif |
330 | wake_up(&priv->reset_done); | 330 | wake_up(&priv->reset_done); |
331 | } | 331 | } |
@@ -333,7 +333,7 @@ islpci_interrupt(int irq, void *config) | |||
333 | if (reg & ISL38XX_INT_IDENT_SLEEP) { | 333 | if (reg & ISL38XX_INT_IDENT_SLEEP) { |
334 | /* Device intends to move to powersave state */ | 334 | /* Device intends to move to powersave state */ |
335 | #if VERBOSE > SHOW_ERROR_MESSAGES | 335 | #if VERBOSE > SHOW_ERROR_MESSAGES |
336 | DEBUG(SHOW_TRACING, "IRQ: Sleep flag \n"); | 336 | DEBUG(SHOW_TRACING, "IRQ: Sleep flag\n"); |
337 | #endif | 337 | #endif |
338 | isl38xx_handle_sleep_request(priv->control_block, | 338 | isl38xx_handle_sleep_request(priv->control_block, |
339 | &powerstate, | 339 | &powerstate, |
@@ -343,7 +343,7 @@ islpci_interrupt(int irq, void *config) | |||
343 | if (reg & ISL38XX_INT_IDENT_WAKEUP) { | 343 | if (reg & ISL38XX_INT_IDENT_WAKEUP) { |
344 | /* Device has been woken up to active state */ | 344 | /* Device has been woken up to active state */ |
345 | #if VERBOSE > SHOW_ERROR_MESSAGES | 345 | #if VERBOSE > SHOW_ERROR_MESSAGES |
346 | DEBUG(SHOW_TRACING, "IRQ: Wakeup flag \n"); | 346 | DEBUG(SHOW_TRACING, "IRQ: Wakeup flag\n"); |
347 | #endif | 347 | #endif |
348 | 348 | ||
349 | isl38xx_handle_wakeup(priv->control_block, | 349 | isl38xx_handle_wakeup(priv->control_block, |
@@ -634,7 +634,7 @@ islpci_alloc_memory(islpci_private *priv) | |||
634 | ioremap(pci_resource_start(priv->pdev, 0), | 634 | ioremap(pci_resource_start(priv->pdev, 0), |
635 | ISL38XX_PCI_MEM_SIZE))) { | 635 | ISL38XX_PCI_MEM_SIZE))) { |
636 | /* error in remapping the PCI device memory address range */ | 636 | /* error in remapping the PCI device memory address range */ |
637 | printk(KERN_ERR "PCI memory remapping failed \n"); | 637 | printk(KERN_ERR "PCI memory remapping failed\n"); |
638 | return -1; | 638 | return -1; |
639 | } | 639 | } |
640 | 640 | ||
@@ -901,7 +901,7 @@ islpci_setup(struct pci_dev *pdev) | |||
901 | 901 | ||
902 | if (register_netdev(ndev)) { | 902 | if (register_netdev(ndev)) { |
903 | DEBUG(SHOW_ERROR_MESSAGES, | 903 | DEBUG(SHOW_ERROR_MESSAGES, |
904 | "ERROR: register_netdev() failed \n"); | 904 | "ERROR: register_netdev() failed\n"); |
905 | goto do_islpci_free_memory; | 905 | goto do_islpci_free_memory; |
906 | } | 906 | } |
907 | 907 | ||
diff --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c index 872b64783e78..af9e7fbd7640 100644 --- a/drivers/net/wireless/prism54/islpci_eth.c +++ b/drivers/net/wireless/prism54/islpci_eth.c | |||
@@ -89,7 +89,7 @@ islpci_eth_transmit(struct sk_buff *skb, struct net_device *ndev) | |||
89 | u32 curr_frag; | 89 | u32 curr_frag; |
90 | 90 | ||
91 | #if VERBOSE > SHOW_ERROR_MESSAGES | 91 | #if VERBOSE > SHOW_ERROR_MESSAGES |
92 | DEBUG(SHOW_FUNCTION_CALLS, "islpci_eth_transmit \n"); | 92 | DEBUG(SHOW_FUNCTION_CALLS, "islpci_eth_transmit\n"); |
93 | #endif | 93 | #endif |
94 | 94 | ||
95 | /* lock the driver code */ | 95 | /* lock the driver code */ |
@@ -140,7 +140,7 @@ islpci_eth_transmit(struct sk_buff *skb, struct net_device *ndev) | |||
140 | } | 140 | } |
141 | 141 | ||
142 | #if VERBOSE > SHOW_ERROR_MESSAGES | 142 | #if VERBOSE > SHOW_ERROR_MESSAGES |
143 | DEBUG(SHOW_TRACING, "memmove %p %p %i \n", skb->data, | 143 | DEBUG(SHOW_TRACING, "memmove %p %p %i\n", skb->data, |
144 | src, skb->len); | 144 | src, skb->len); |
145 | #endif | 145 | #endif |
146 | } else { | 146 | } else { |
@@ -319,7 +319,7 @@ islpci_eth_receive(islpci_private *priv) | |||
319 | int discard = 0; | 319 | int discard = 0; |
320 | 320 | ||
321 | #if VERBOSE > SHOW_ERROR_MESSAGES | 321 | #if VERBOSE > SHOW_ERROR_MESSAGES |
322 | DEBUG(SHOW_FUNCTION_CALLS, "islpci_eth_receive \n"); | 322 | DEBUG(SHOW_FUNCTION_CALLS, "islpci_eth_receive\n"); |
323 | #endif | 323 | #endif |
324 | 324 | ||
325 | /* the device has written an Ethernet frame in the data area | 325 | /* the device has written an Ethernet frame in the data area |
@@ -431,7 +431,7 @@ islpci_eth_receive(islpci_private *priv) | |||
431 | skb = dev_alloc_skb(MAX_FRAGMENT_SIZE_RX + 2); | 431 | skb = dev_alloc_skb(MAX_FRAGMENT_SIZE_RX + 2); |
432 | if (unlikely(skb == NULL)) { | 432 | if (unlikely(skb == NULL)) { |
433 | /* error allocating an sk_buff structure elements */ | 433 | /* error allocating an sk_buff structure elements */ |
434 | DEBUG(SHOW_ERROR_MESSAGES, "Error allocating skb \n"); | 434 | DEBUG(SHOW_ERROR_MESSAGES, "Error allocating skb\n"); |
435 | break; | 435 | break; |
436 | } | 436 | } |
437 | skb_reserve(skb, (4 - (long) skb->data) & 0x03); | 437 | skb_reserve(skb, (4 - (long) skb->data) & 0x03); |
diff --git a/drivers/net/wireless/prism54/islpci_mgt.c b/drivers/net/wireless/prism54/islpci_mgt.c index 69d2f882fd06..89b0278eb7e8 100644 --- a/drivers/net/wireless/prism54/islpci_mgt.c +++ b/drivers/net/wireless/prism54/islpci_mgt.c | |||
@@ -113,7 +113,7 @@ islpci_mgmt_rx_fill(struct net_device *ndev) | |||
113 | u32 curr = le32_to_cpu(cb->driver_curr_frag[ISL38XX_CB_RX_MGMTQ]); | 113 | u32 curr = le32_to_cpu(cb->driver_curr_frag[ISL38XX_CB_RX_MGMTQ]); |
114 | 114 | ||
115 | #if VERBOSE > SHOW_ERROR_MESSAGES | 115 | #if VERBOSE > SHOW_ERROR_MESSAGES |
116 | DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgmt_rx_fill \n"); | 116 | DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgmt_rx_fill\n"); |
117 | #endif | 117 | #endif |
118 | 118 | ||
119 | while (curr - priv->index_mgmt_rx < ISL38XX_CB_MGMT_QSIZE) { | 119 | while (curr - priv->index_mgmt_rx < ISL38XX_CB_MGMT_QSIZE) { |
@@ -211,7 +211,7 @@ islpci_mgt_transmit(struct net_device *ndev, int operation, unsigned long oid, | |||
211 | { | 211 | { |
212 | pimfor_header_t *h = buf.mem; | 212 | pimfor_header_t *h = buf.mem; |
213 | DEBUG(SHOW_PIMFOR_FRAMES, | 213 | DEBUG(SHOW_PIMFOR_FRAMES, |
214 | "PIMFOR: op %i, oid 0x%08lx, device %i, flags 0x%x length 0x%x \n", | 214 | "PIMFOR: op %i, oid 0x%08lx, device %i, flags 0x%x length 0x%x\n", |
215 | h->operation, oid, h->device_id, h->flags, length); | 215 | h->operation, oid, h->device_id, h->flags, length); |
216 | 216 | ||
217 | /* display the buffer contents for debugging */ | 217 | /* display the buffer contents for debugging */ |
@@ -279,7 +279,7 @@ islpci_mgt_receive(struct net_device *ndev) | |||
279 | u32 curr_frag; | 279 | u32 curr_frag; |
280 | 280 | ||
281 | #if VERBOSE > SHOW_ERROR_MESSAGES | 281 | #if VERBOSE > SHOW_ERROR_MESSAGES |
282 | DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgt_receive \n"); | 282 | DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgt_receive\n"); |
283 | #endif | 283 | #endif |
284 | 284 | ||
285 | /* Only once per interrupt, determine fragment range to | 285 | /* Only once per interrupt, determine fragment range to |
@@ -338,7 +338,7 @@ islpci_mgt_receive(struct net_device *ndev) | |||
338 | 338 | ||
339 | #if VERBOSE > SHOW_ERROR_MESSAGES | 339 | #if VERBOSE > SHOW_ERROR_MESSAGES |
340 | DEBUG(SHOW_PIMFOR_FRAMES, | 340 | DEBUG(SHOW_PIMFOR_FRAMES, |
341 | "PIMFOR: op %i, oid 0x%08x, device %i, flags 0x%x length 0x%x \n", | 341 | "PIMFOR: op %i, oid 0x%08x, device %i, flags 0x%x length 0x%x\n", |
342 | header->operation, header->oid, header->device_id, | 342 | header->operation, header->oid, header->device_id, |
343 | header->flags, header->length); | 343 | header->flags, header->length); |
344 | 344 | ||
diff --git a/drivers/net/wireless/prism54/oid_mgt.c b/drivers/net/wireless/prism54/oid_mgt.c index 1187e6112a64..07df70a10071 100644 --- a/drivers/net/wireless/prism54/oid_mgt.c +++ b/drivers/net/wireless/prism54/oid_mgt.c | |||
@@ -819,7 +819,7 @@ mgt_response_to_str(enum oid_num_t n, union oid_res_t *r, char *str) | |||
819 | k = snprintf(str, PRIV_STR_SIZE, "nr=%u\n", list->nr); | 819 | k = snprintf(str, PRIV_STR_SIZE, "nr=%u\n", list->nr); |
820 | for (i = 0; i < list->nr; i++) | 820 | for (i = 0; i < list->nr; i++) |
821 | k += snprintf(str + k, PRIV_STR_SIZE - k, | 821 | k += snprintf(str + k, PRIV_STR_SIZE - k, |
822 | "bss[%u] : \nage=%u\nchannel=%u\n" | 822 | "bss[%u] :\nage=%u\nchannel=%u\n" |
823 | "capinfo=0x%X\nrates=0x%X\n" | 823 | "capinfo=0x%X\nrates=0x%X\n" |
824 | "basic_rates=0x%X\n", | 824 | "basic_rates=0x%X\n", |
825 | i, list->bsslist[i].age, | 825 | i, list->bsslist[i].age, |
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 84c530aa52f9..f1e916a31668 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c | |||
@@ -556,7 +556,7 @@ static int ray_init(struct net_device *dev) | |||
556 | local->fw_ver = local->startup_res.firmware_version[0]; | 556 | local->fw_ver = local->startup_res.firmware_version[0]; |
557 | local->fw_bld = local->startup_res.firmware_version[1]; | 557 | local->fw_bld = local->startup_res.firmware_version[1]; |
558 | local->fw_var = local->startup_res.firmware_version[2]; | 558 | local->fw_var = local->startup_res.firmware_version[2]; |
559 | dev_dbg(&link->dev, "ray_init firmware version %d.%d \n", local->fw_ver, | 559 | dev_dbg(&link->dev, "ray_init firmware version %d.%d\n", local->fw_ver, |
560 | local->fw_bld); | 560 | local->fw_bld); |
561 | 561 | ||
562 | local->tib_length = 0x20; | 562 | local->tib_length = 0x20; |
@@ -1113,10 +1113,10 @@ static const struct ethtool_ops netdev_ethtool_ops = { | |||
1113 | /* | 1113 | /* |
1114 | * Wireless Handler : get protocol name | 1114 | * Wireless Handler : get protocol name |
1115 | */ | 1115 | */ |
1116 | static int ray_get_name(struct net_device *dev, | 1116 | static int ray_get_name(struct net_device *dev, struct iw_request_info *info, |
1117 | struct iw_request_info *info, char *cwrq, char *extra) | 1117 | union iwreq_data *wrqu, char *extra) |
1118 | { | 1118 | { |
1119 | strcpy(cwrq, "IEEE 802.11-FH"); | 1119 | strcpy(wrqu->name, "IEEE 802.11-FH"); |
1120 | return 0; | 1120 | return 0; |
1121 | } | 1121 | } |
1122 | 1122 | ||
@@ -1124,9 +1124,8 @@ static int ray_get_name(struct net_device *dev, | |||
1124 | /* | 1124 | /* |
1125 | * Wireless Handler : set frequency | 1125 | * Wireless Handler : set frequency |
1126 | */ | 1126 | */ |
1127 | static int ray_set_freq(struct net_device *dev, | 1127 | static int ray_set_freq(struct net_device *dev, struct iw_request_info *info, |
1128 | struct iw_request_info *info, | 1128 | union iwreq_data *wrqu, char *extra) |
1129 | struct iw_freq *fwrq, char *extra) | ||
1130 | { | 1129 | { |
1131 | ray_dev_t *local = netdev_priv(dev); | 1130 | ray_dev_t *local = netdev_priv(dev); |
1132 | int err = -EINPROGRESS; /* Call commit handler */ | 1131 | int err = -EINPROGRESS; /* Call commit handler */ |
@@ -1136,10 +1135,10 @@ static int ray_set_freq(struct net_device *dev, | |||
1136 | return -EBUSY; | 1135 | return -EBUSY; |
1137 | 1136 | ||
1138 | /* Setting by channel number */ | 1137 | /* Setting by channel number */ |
1139 | if ((fwrq->m > USA_HOP_MOD) || (fwrq->e > 0)) | 1138 | if ((wrqu->freq.m > USA_HOP_MOD) || (wrqu->freq.e > 0)) |
1140 | err = -EOPNOTSUPP; | 1139 | err = -EOPNOTSUPP; |
1141 | else | 1140 | else |
1142 | local->sparm.b5.a_hop_pattern = fwrq->m; | 1141 | local->sparm.b5.a_hop_pattern = wrqu->freq.m; |
1143 | 1142 | ||
1144 | return err; | 1143 | return err; |
1145 | } | 1144 | } |
@@ -1148,14 +1147,13 @@ static int ray_set_freq(struct net_device *dev, | |||
1148 | /* | 1147 | /* |
1149 | * Wireless Handler : get frequency | 1148 | * Wireless Handler : get frequency |
1150 | */ | 1149 | */ |
1151 | static int ray_get_freq(struct net_device *dev, | 1150 | static int ray_get_freq(struct net_device *dev, struct iw_request_info *info, |
1152 | struct iw_request_info *info, | 1151 | union iwreq_data *wrqu, char *extra) |
1153 | struct iw_freq *fwrq, char *extra) | ||
1154 | { | 1152 | { |
1155 | ray_dev_t *local = netdev_priv(dev); | 1153 | ray_dev_t *local = netdev_priv(dev); |
1156 | 1154 | ||
1157 | fwrq->m = local->sparm.b5.a_hop_pattern; | 1155 | wrqu->freq.m = local->sparm.b5.a_hop_pattern; |
1158 | fwrq->e = 0; | 1156 | wrqu->freq.e = 0; |
1159 | return 0; | 1157 | return 0; |
1160 | } | 1158 | } |
1161 | 1159 | ||
@@ -1163,9 +1161,8 @@ static int ray_get_freq(struct net_device *dev, | |||
1163 | /* | 1161 | /* |
1164 | * Wireless Handler : set ESSID | 1162 | * Wireless Handler : set ESSID |
1165 | */ | 1163 | */ |
1166 | static int ray_set_essid(struct net_device *dev, | 1164 | static int ray_set_essid(struct net_device *dev, struct iw_request_info *info, |
1167 | struct iw_request_info *info, | 1165 | union iwreq_data *wrqu, char *extra) |
1168 | struct iw_point *dwrq, char *extra) | ||
1169 | { | 1166 | { |
1170 | ray_dev_t *local = netdev_priv(dev); | 1167 | ray_dev_t *local = netdev_priv(dev); |
1171 | 1168 | ||
@@ -1174,19 +1171,17 @@ static int ray_set_essid(struct net_device *dev, | |||
1174 | return -EBUSY; | 1171 | return -EBUSY; |
1175 | 1172 | ||
1176 | /* Check if we asked for `any' */ | 1173 | /* Check if we asked for `any' */ |
1177 | if (dwrq->flags == 0) { | 1174 | if (wrqu->essid.flags == 0) |
1178 | /* Corey : can you do that ? */ | 1175 | /* Corey : can you do that ? */ |
1179 | return -EOPNOTSUPP; | 1176 | return -EOPNOTSUPP; |
1180 | } else { | ||
1181 | /* Check the size of the string */ | ||
1182 | if (dwrq->length > IW_ESSID_MAX_SIZE) { | ||
1183 | return -E2BIG; | ||
1184 | } | ||
1185 | 1177 | ||
1186 | /* Set the ESSID in the card */ | 1178 | /* Check the size of the string */ |
1187 | memset(local->sparm.b5.a_current_ess_id, 0, IW_ESSID_MAX_SIZE); | 1179 | if (wrqu->essid.length > IW_ESSID_MAX_SIZE) |
1188 | memcpy(local->sparm.b5.a_current_ess_id, extra, dwrq->length); | 1180 | return -E2BIG; |
1189 | } | 1181 | |
1182 | /* Set the ESSID in the card */ | ||
1183 | memset(local->sparm.b5.a_current_ess_id, 0, IW_ESSID_MAX_SIZE); | ||
1184 | memcpy(local->sparm.b5.a_current_ess_id, extra, wrqu->essid.length); | ||
1190 | 1185 | ||
1191 | return -EINPROGRESS; /* Call commit handler */ | 1186 | return -EINPROGRESS; /* Call commit handler */ |
1192 | } | 1187 | } |
@@ -1195,9 +1190,8 @@ static int ray_set_essid(struct net_device *dev, | |||
1195 | /* | 1190 | /* |
1196 | * Wireless Handler : get ESSID | 1191 | * Wireless Handler : get ESSID |
1197 | */ | 1192 | */ |
1198 | static int ray_get_essid(struct net_device *dev, | 1193 | static int ray_get_essid(struct net_device *dev, struct iw_request_info *info, |
1199 | struct iw_request_info *info, | 1194 | union iwreq_data *wrqu, char *extra) |
1200 | struct iw_point *dwrq, char *extra) | ||
1201 | { | 1195 | { |
1202 | ray_dev_t *local = netdev_priv(dev); | 1196 | ray_dev_t *local = netdev_priv(dev); |
1203 | 1197 | ||
@@ -1205,8 +1199,8 @@ static int ray_get_essid(struct net_device *dev, | |||
1205 | memcpy(extra, local->sparm.b5.a_current_ess_id, IW_ESSID_MAX_SIZE); | 1199 | memcpy(extra, local->sparm.b5.a_current_ess_id, IW_ESSID_MAX_SIZE); |
1206 | 1200 | ||
1207 | /* Push it out ! */ | 1201 | /* Push it out ! */ |
1208 | dwrq->length = strlen(extra); | 1202 | wrqu->essid.length = strlen(extra); |
1209 | dwrq->flags = 1; /* active */ | 1203 | wrqu->essid.flags = 1; /* active */ |
1210 | 1204 | ||
1211 | return 0; | 1205 | return 0; |
1212 | } | 1206 | } |
@@ -1215,14 +1209,13 @@ static int ray_get_essid(struct net_device *dev, | |||
1215 | /* | 1209 | /* |
1216 | * Wireless Handler : get AP address | 1210 | * Wireless Handler : get AP address |
1217 | */ | 1211 | */ |
1218 | static int ray_get_wap(struct net_device *dev, | 1212 | static int ray_get_wap(struct net_device *dev, struct iw_request_info *info, |
1219 | struct iw_request_info *info, | 1213 | union iwreq_data *wrqu, char *extra) |
1220 | struct sockaddr *awrq, char *extra) | ||
1221 | { | 1214 | { |
1222 | ray_dev_t *local = netdev_priv(dev); | 1215 | ray_dev_t *local = netdev_priv(dev); |
1223 | 1216 | ||
1224 | memcpy(awrq->sa_data, local->bss_id, ETH_ALEN); | 1217 | memcpy(wrqu->ap_addr.sa_data, local->bss_id, ETH_ALEN); |
1225 | awrq->sa_family = ARPHRD_ETHER; | 1218 | wrqu->ap_addr.sa_family = ARPHRD_ETHER; |
1226 | 1219 | ||
1227 | return 0; | 1220 | return 0; |
1228 | } | 1221 | } |
@@ -1231,9 +1224,8 @@ static int ray_get_wap(struct net_device *dev, | |||
1231 | /* | 1224 | /* |
1232 | * Wireless Handler : set Bit-Rate | 1225 | * Wireless Handler : set Bit-Rate |
1233 | */ | 1226 | */ |
1234 | static int ray_set_rate(struct net_device *dev, | 1227 | static int ray_set_rate(struct net_device *dev, struct iw_request_info *info, |
1235 | struct iw_request_info *info, | 1228 | union iwreq_data *wrqu, char *extra) |
1236 | struct iw_param *vwrq, char *extra) | ||
1237 | { | 1229 | { |
1238 | ray_dev_t *local = netdev_priv(dev); | 1230 | ray_dev_t *local = netdev_priv(dev); |
1239 | 1231 | ||
@@ -1242,15 +1234,15 @@ static int ray_set_rate(struct net_device *dev, | |||
1242 | return -EBUSY; | 1234 | return -EBUSY; |
1243 | 1235 | ||
1244 | /* Check if rate is in range */ | 1236 | /* Check if rate is in range */ |
1245 | if ((vwrq->value != 1000000) && (vwrq->value != 2000000)) | 1237 | if ((wrqu->bitrate.value != 1000000) && (wrqu->bitrate.value != 2000000)) |
1246 | return -EINVAL; | 1238 | return -EINVAL; |
1247 | 1239 | ||
1248 | /* Hack for 1.5 Mb/s instead of 2 Mb/s */ | 1240 | /* Hack for 1.5 Mb/s instead of 2 Mb/s */ |
1249 | if ((local->fw_ver == 0x55) && /* Please check */ | 1241 | if ((local->fw_ver == 0x55) && /* Please check */ |
1250 | (vwrq->value == 2000000)) | 1242 | (wrqu->bitrate.value == 2000000)) |
1251 | local->net_default_tx_rate = 3; | 1243 | local->net_default_tx_rate = 3; |
1252 | else | 1244 | else |
1253 | local->net_default_tx_rate = vwrq->value / 500000; | 1245 | local->net_default_tx_rate = wrqu->bitrate.value / 500000; |
1254 | 1246 | ||
1255 | return 0; | 1247 | return 0; |
1256 | } | 1248 | } |
@@ -1259,17 +1251,16 @@ static int ray_set_rate(struct net_device *dev, | |||
1259 | /* | 1251 | /* |
1260 | * Wireless Handler : get Bit-Rate | 1252 | * Wireless Handler : get Bit-Rate |
1261 | */ | 1253 | */ |
1262 | static int ray_get_rate(struct net_device *dev, | 1254 | static int ray_get_rate(struct net_device *dev, struct iw_request_info *info, |
1263 | struct iw_request_info *info, | 1255 | union iwreq_data *wrqu, char *extra) |
1264 | struct iw_param *vwrq, char *extra) | ||
1265 | { | 1256 | { |
1266 | ray_dev_t *local = netdev_priv(dev); | 1257 | ray_dev_t *local = netdev_priv(dev); |
1267 | 1258 | ||
1268 | if (local->net_default_tx_rate == 3) | 1259 | if (local->net_default_tx_rate == 3) |
1269 | vwrq->value = 2000000; /* Hum... */ | 1260 | wrqu->bitrate.value = 2000000; /* Hum... */ |
1270 | else | 1261 | else |
1271 | vwrq->value = local->net_default_tx_rate * 500000; | 1262 | wrqu->bitrate.value = local->net_default_tx_rate * 500000; |
1272 | vwrq->fixed = 0; /* We are in auto mode */ | 1263 | wrqu->bitrate.fixed = 0; /* We are in auto mode */ |
1273 | 1264 | ||
1274 | return 0; | 1265 | return 0; |
1275 | } | 1266 | } |
@@ -1278,19 +1269,18 @@ static int ray_get_rate(struct net_device *dev, | |||
1278 | /* | 1269 | /* |
1279 | * Wireless Handler : set RTS threshold | 1270 | * Wireless Handler : set RTS threshold |
1280 | */ | 1271 | */ |
1281 | static int ray_set_rts(struct net_device *dev, | 1272 | static int ray_set_rts(struct net_device *dev, struct iw_request_info *info, |
1282 | struct iw_request_info *info, | 1273 | union iwreq_data *wrqu, char *extra) |
1283 | struct iw_param *vwrq, char *extra) | ||
1284 | { | 1274 | { |
1285 | ray_dev_t *local = netdev_priv(dev); | 1275 | ray_dev_t *local = netdev_priv(dev); |
1286 | int rthr = vwrq->value; | 1276 | int rthr = wrqu->rts.value; |
1287 | 1277 | ||
1288 | /* Reject if card is already initialised */ | 1278 | /* Reject if card is already initialised */ |
1289 | if (local->card_status != CARD_AWAITING_PARAM) | 1279 | if (local->card_status != CARD_AWAITING_PARAM) |
1290 | return -EBUSY; | 1280 | return -EBUSY; |
1291 | 1281 | ||
1292 | /* if(wrq->u.rts.fixed == 0) we should complain */ | 1282 | /* if(wrq->u.rts.fixed == 0) we should complain */ |
1293 | if (vwrq->disabled) | 1283 | if (wrqu->rts.disabled) |
1294 | rthr = 32767; | 1284 | rthr = 32767; |
1295 | else { | 1285 | else { |
1296 | if ((rthr < 0) || (rthr > 2347)) /* What's the max packet size ??? */ | 1286 | if ((rthr < 0) || (rthr > 2347)) /* What's the max packet size ??? */ |
@@ -1306,16 +1296,15 @@ static int ray_set_rts(struct net_device *dev, | |||
1306 | /* | 1296 | /* |
1307 | * Wireless Handler : get RTS threshold | 1297 | * Wireless Handler : get RTS threshold |
1308 | */ | 1298 | */ |
1309 | static int ray_get_rts(struct net_device *dev, | 1299 | static int ray_get_rts(struct net_device *dev, struct iw_request_info *info, |
1310 | struct iw_request_info *info, | 1300 | union iwreq_data *wrqu, char *extra) |
1311 | struct iw_param *vwrq, char *extra) | ||
1312 | { | 1301 | { |
1313 | ray_dev_t *local = netdev_priv(dev); | 1302 | ray_dev_t *local = netdev_priv(dev); |
1314 | 1303 | ||
1315 | vwrq->value = (local->sparm.b5.a_rts_threshold[0] << 8) | 1304 | wrqu->rts.value = (local->sparm.b5.a_rts_threshold[0] << 8) |
1316 | + local->sparm.b5.a_rts_threshold[1]; | 1305 | + local->sparm.b5.a_rts_threshold[1]; |
1317 | vwrq->disabled = (vwrq->value == 32767); | 1306 | wrqu->rts.disabled = (wrqu->rts.value == 32767); |
1318 | vwrq->fixed = 1; | 1307 | wrqu->rts.fixed = 1; |
1319 | 1308 | ||
1320 | return 0; | 1309 | return 0; |
1321 | } | 1310 | } |
@@ -1324,19 +1313,18 @@ static int ray_get_rts(struct net_device *dev, | |||
1324 | /* | 1313 | /* |
1325 | * Wireless Handler : set Fragmentation threshold | 1314 | * Wireless Handler : set Fragmentation threshold |
1326 | */ | 1315 | */ |
1327 | static int ray_set_frag(struct net_device *dev, | 1316 | static int ray_set_frag(struct net_device *dev, struct iw_request_info *info, |
1328 | struct iw_request_info *info, | 1317 | union iwreq_data *wrqu, char *extra) |
1329 | struct iw_param *vwrq, char *extra) | ||
1330 | { | 1318 | { |
1331 | ray_dev_t *local = netdev_priv(dev); | 1319 | ray_dev_t *local = netdev_priv(dev); |
1332 | int fthr = vwrq->value; | 1320 | int fthr = wrqu->frag.value; |
1333 | 1321 | ||
1334 | /* Reject if card is already initialised */ | 1322 | /* Reject if card is already initialised */ |
1335 | if (local->card_status != CARD_AWAITING_PARAM) | 1323 | if (local->card_status != CARD_AWAITING_PARAM) |
1336 | return -EBUSY; | 1324 | return -EBUSY; |
1337 | 1325 | ||
1338 | /* if(wrq->u.frag.fixed == 0) should complain */ | 1326 | /* if(wrq->u.frag.fixed == 0) should complain */ |
1339 | if (vwrq->disabled) | 1327 | if (wrqu->frag.disabled) |
1340 | fthr = 32767; | 1328 | fthr = 32767; |
1341 | else { | 1329 | else { |
1342 | if ((fthr < 256) || (fthr > 2347)) /* To check out ! */ | 1330 | if ((fthr < 256) || (fthr > 2347)) /* To check out ! */ |
@@ -1352,16 +1340,15 @@ static int ray_set_frag(struct net_device *dev, | |||
1352 | /* | 1340 | /* |
1353 | * Wireless Handler : get Fragmentation threshold | 1341 | * Wireless Handler : get Fragmentation threshold |
1354 | */ | 1342 | */ |
1355 | static int ray_get_frag(struct net_device *dev, | 1343 | static int ray_get_frag(struct net_device *dev, struct iw_request_info *info, |
1356 | struct iw_request_info *info, | 1344 | union iwreq_data *wrqu, char *extra) |
1357 | struct iw_param *vwrq, char *extra) | ||
1358 | { | 1345 | { |
1359 | ray_dev_t *local = netdev_priv(dev); | 1346 | ray_dev_t *local = netdev_priv(dev); |
1360 | 1347 | ||
1361 | vwrq->value = (local->sparm.b5.a_frag_threshold[0] << 8) | 1348 | wrqu->frag.value = (local->sparm.b5.a_frag_threshold[0] << 8) |
1362 | + local->sparm.b5.a_frag_threshold[1]; | 1349 | + local->sparm.b5.a_frag_threshold[1]; |
1363 | vwrq->disabled = (vwrq->value == 32767); | 1350 | wrqu->frag.disabled = (wrqu->frag.value == 32767); |
1364 | vwrq->fixed = 1; | 1351 | wrqu->frag.fixed = 1; |
1365 | 1352 | ||
1366 | return 0; | 1353 | return 0; |
1367 | } | 1354 | } |
@@ -1370,8 +1357,8 @@ static int ray_get_frag(struct net_device *dev, | |||
1370 | /* | 1357 | /* |
1371 | * Wireless Handler : set Mode of Operation | 1358 | * Wireless Handler : set Mode of Operation |
1372 | */ | 1359 | */ |
1373 | static int ray_set_mode(struct net_device *dev, | 1360 | static int ray_set_mode(struct net_device *dev, struct iw_request_info *info, |
1374 | struct iw_request_info *info, __u32 *uwrq, char *extra) | 1361 | union iwreq_data *wrqu, char *extra) |
1375 | { | 1362 | { |
1376 | ray_dev_t *local = netdev_priv(dev); | 1363 | ray_dev_t *local = netdev_priv(dev); |
1377 | int err = -EINPROGRESS; /* Call commit handler */ | 1364 | int err = -EINPROGRESS; /* Call commit handler */ |
@@ -1381,7 +1368,7 @@ static int ray_set_mode(struct net_device *dev, | |||
1381 | if (local->card_status != CARD_AWAITING_PARAM) | 1368 | if (local->card_status != CARD_AWAITING_PARAM) |
1382 | return -EBUSY; | 1369 | return -EBUSY; |
1383 | 1370 | ||
1384 | switch (*uwrq) { | 1371 | switch (wrqu->mode) { |
1385 | case IW_MODE_ADHOC: | 1372 | case IW_MODE_ADHOC: |
1386 | card_mode = 0; | 1373 | card_mode = 0; |
1387 | /* Fall through */ | 1374 | /* Fall through */ |
@@ -1399,15 +1386,15 @@ static int ray_set_mode(struct net_device *dev, | |||
1399 | /* | 1386 | /* |
1400 | * Wireless Handler : get Mode of Operation | 1387 | * Wireless Handler : get Mode of Operation |
1401 | */ | 1388 | */ |
1402 | static int ray_get_mode(struct net_device *dev, | 1389 | static int ray_get_mode(struct net_device *dev, struct iw_request_info *info, |
1403 | struct iw_request_info *info, __u32 *uwrq, char *extra) | 1390 | union iwreq_data *wrqu, char *extra) |
1404 | { | 1391 | { |
1405 | ray_dev_t *local = netdev_priv(dev); | 1392 | ray_dev_t *local = netdev_priv(dev); |
1406 | 1393 | ||
1407 | if (local->sparm.b5.a_network_type) | 1394 | if (local->sparm.b5.a_network_type) |
1408 | *uwrq = IW_MODE_INFRA; | 1395 | wrqu->mode = IW_MODE_INFRA; |
1409 | else | 1396 | else |
1410 | *uwrq = IW_MODE_ADHOC; | 1397 | wrqu->mode = IW_MODE_ADHOC; |
1411 | 1398 | ||
1412 | return 0; | 1399 | return 0; |
1413 | } | 1400 | } |
@@ -1416,16 +1403,15 @@ static int ray_get_mode(struct net_device *dev, | |||
1416 | /* | 1403 | /* |
1417 | * Wireless Handler : get range info | 1404 | * Wireless Handler : get range info |
1418 | */ | 1405 | */ |
1419 | static int ray_get_range(struct net_device *dev, | 1406 | static int ray_get_range(struct net_device *dev, struct iw_request_info *info, |
1420 | struct iw_request_info *info, | 1407 | union iwreq_data *wrqu, char *extra) |
1421 | struct iw_point *dwrq, char *extra) | ||
1422 | { | 1408 | { |
1423 | struct iw_range *range = (struct iw_range *)extra; | 1409 | struct iw_range *range = (struct iw_range *)extra; |
1424 | 1410 | ||
1425 | memset((char *)range, 0, sizeof(struct iw_range)); | 1411 | memset(range, 0, sizeof(struct iw_range)); |
1426 | 1412 | ||
1427 | /* Set the length (very important for backward compatibility) */ | 1413 | /* Set the length (very important for backward compatibility) */ |
1428 | dwrq->length = sizeof(struct iw_range); | 1414 | wrqu->data.length = sizeof(struct iw_range); |
1429 | 1415 | ||
1430 | /* Set the Wireless Extension versions */ | 1416 | /* Set the Wireless Extension versions */ |
1431 | range->we_version_compiled = WIRELESS_EXT; | 1417 | range->we_version_compiled = WIRELESS_EXT; |
@@ -1448,8 +1434,7 @@ static int ray_get_range(struct net_device *dev, | |||
1448 | /* | 1434 | /* |
1449 | * Wireless Private Handler : set framing mode | 1435 | * Wireless Private Handler : set framing mode |
1450 | */ | 1436 | */ |
1451 | static int ray_set_framing(struct net_device *dev, | 1437 | static int ray_set_framing(struct net_device *dev, struct iw_request_info *info, |
1452 | struct iw_request_info *info, | ||
1453 | union iwreq_data *wrqu, char *extra) | 1438 | union iwreq_data *wrqu, char *extra) |
1454 | { | 1439 | { |
1455 | translate = *(extra); /* Set framing mode */ | 1440 | translate = *(extra); /* Set framing mode */ |
@@ -1461,8 +1446,7 @@ static int ray_set_framing(struct net_device *dev, | |||
1461 | /* | 1446 | /* |
1462 | * Wireless Private Handler : get framing mode | 1447 | * Wireless Private Handler : get framing mode |
1463 | */ | 1448 | */ |
1464 | static int ray_get_framing(struct net_device *dev, | 1449 | static int ray_get_framing(struct net_device *dev, struct iw_request_info *info, |
1465 | struct iw_request_info *info, | ||
1466 | union iwreq_data *wrqu, char *extra) | 1450 | union iwreq_data *wrqu, char *extra) |
1467 | { | 1451 | { |
1468 | *(extra) = translate; | 1452 | *(extra) = translate; |
@@ -1474,8 +1458,7 @@ static int ray_get_framing(struct net_device *dev, | |||
1474 | /* | 1458 | /* |
1475 | * Wireless Private Handler : get country | 1459 | * Wireless Private Handler : get country |
1476 | */ | 1460 | */ |
1477 | static int ray_get_country(struct net_device *dev, | 1461 | static int ray_get_country(struct net_device *dev, struct iw_request_info *info, |
1478 | struct iw_request_info *info, | ||
1479 | union iwreq_data *wrqu, char *extra) | 1462 | union iwreq_data *wrqu, char *extra) |
1480 | { | 1463 | { |
1481 | *(extra) = country; | 1464 | *(extra) = country; |
@@ -1487,10 +1470,9 @@ static int ray_get_country(struct net_device *dev, | |||
1487 | /* | 1470 | /* |
1488 | * Commit handler : called after a bunch of SET operations | 1471 | * Commit handler : called after a bunch of SET operations |
1489 | */ | 1472 | */ |
1490 | static int ray_commit(struct net_device *dev, struct iw_request_info *info, /* NULL */ | 1473 | static int ray_commit(struct net_device *dev, struct iw_request_info *info, |
1491 | void *zwrq, /* NULL */ | 1474 | union iwreq_data *wrqu, char *extra) |
1492 | char *extra) | 1475 | { |
1493 | { /* NULL */ | ||
1494 | return 0; | 1476 | return 0; |
1495 | } | 1477 | } |
1496 | 1478 | ||
@@ -1531,28 +1513,28 @@ static iw_stats *ray_get_wireless_stats(struct net_device *dev) | |||
1531 | */ | 1513 | */ |
1532 | 1514 | ||
1533 | static const iw_handler ray_handler[] = { | 1515 | static const iw_handler ray_handler[] = { |
1534 | [SIOCSIWCOMMIT - SIOCIWFIRST] = (iw_handler) ray_commit, | 1516 | IW_HANDLER(SIOCSIWCOMMIT, ray_commit), |
1535 | [SIOCGIWNAME - SIOCIWFIRST] = (iw_handler) ray_get_name, | 1517 | IW_HANDLER(SIOCGIWNAME, ray_get_name), |
1536 | [SIOCSIWFREQ - SIOCIWFIRST] = (iw_handler) ray_set_freq, | 1518 | IW_HANDLER(SIOCSIWFREQ, ray_set_freq), |
1537 | [SIOCGIWFREQ - SIOCIWFIRST] = (iw_handler) ray_get_freq, | 1519 | IW_HANDLER(SIOCGIWFREQ, ray_get_freq), |
1538 | [SIOCSIWMODE - SIOCIWFIRST] = (iw_handler) ray_set_mode, | 1520 | IW_HANDLER(SIOCSIWMODE, ray_set_mode), |
1539 | [SIOCGIWMODE - SIOCIWFIRST] = (iw_handler) ray_get_mode, | 1521 | IW_HANDLER(SIOCGIWMODE, ray_get_mode), |
1540 | [SIOCGIWRANGE - SIOCIWFIRST] = (iw_handler) ray_get_range, | 1522 | IW_HANDLER(SIOCGIWRANGE, ray_get_range), |
1541 | #ifdef WIRELESS_SPY | 1523 | #ifdef WIRELESS_SPY |
1542 | [SIOCSIWSPY - SIOCIWFIRST] = (iw_handler) iw_handler_set_spy, | 1524 | IW_HANDLER(SIOCSIWSPY, iw_handler_set_spy), |
1543 | [SIOCGIWSPY - SIOCIWFIRST] = (iw_handler) iw_handler_get_spy, | 1525 | IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy), |
1544 | [SIOCSIWTHRSPY - SIOCIWFIRST] = (iw_handler) iw_handler_set_thrspy, | 1526 | IW_HANDLER(SIOCSIWTHRSPY, iw_handler_set_thrspy), |
1545 | [SIOCGIWTHRSPY - SIOCIWFIRST] = (iw_handler) iw_handler_get_thrspy, | 1527 | IW_HANDLER(SIOCGIWTHRSPY, iw_handler_get_thrspy), |
1546 | #endif /* WIRELESS_SPY */ | 1528 | #endif /* WIRELESS_SPY */ |
1547 | [SIOCGIWAP - SIOCIWFIRST] = (iw_handler) ray_get_wap, | 1529 | IW_HANDLER(SIOCGIWAP, ray_get_wap), |
1548 | [SIOCSIWESSID - SIOCIWFIRST] = (iw_handler) ray_set_essid, | 1530 | IW_HANDLER(SIOCSIWESSID, ray_set_essid), |
1549 | [SIOCGIWESSID - SIOCIWFIRST] = (iw_handler) ray_get_essid, | 1531 | IW_HANDLER(SIOCGIWESSID, ray_get_essid), |
1550 | [SIOCSIWRATE - SIOCIWFIRST] = (iw_handler) ray_set_rate, | 1532 | IW_HANDLER(SIOCSIWRATE, ray_set_rate), |
1551 | [SIOCGIWRATE - SIOCIWFIRST] = (iw_handler) ray_get_rate, | 1533 | IW_HANDLER(SIOCGIWRATE, ray_get_rate), |
1552 | [SIOCSIWRTS - SIOCIWFIRST] = (iw_handler) ray_set_rts, | 1534 | IW_HANDLER(SIOCSIWRTS, ray_set_rts), |
1553 | [SIOCGIWRTS - SIOCIWFIRST] = (iw_handler) ray_get_rts, | 1535 | IW_HANDLER(SIOCGIWRTS, ray_get_rts), |
1554 | [SIOCSIWFRAG - SIOCIWFIRST] = (iw_handler) ray_set_frag, | 1536 | IW_HANDLER(SIOCSIWFRAG, ray_set_frag), |
1555 | [SIOCGIWFRAG - SIOCIWFIRST] = (iw_handler) ray_get_frag, | 1537 | IW_HANDLER(SIOCGIWFRAG, ray_get_frag), |
1556 | }; | 1538 | }; |
1557 | 1539 | ||
1558 | #define SIOCSIPFRAMING SIOCIWFIRSTPRIV /* Set framing mode */ | 1540 | #define SIOCSIPFRAMING SIOCIWFIRSTPRIV /* Set framing mode */ |
@@ -1560,9 +1542,9 @@ static const iw_handler ray_handler[] = { | |||
1560 | #define SIOCGIPCOUNTRY SIOCIWFIRSTPRIV + 3 /* Get country code */ | 1542 | #define SIOCGIPCOUNTRY SIOCIWFIRSTPRIV + 3 /* Get country code */ |
1561 | 1543 | ||
1562 | static const iw_handler ray_private_handler[] = { | 1544 | static const iw_handler ray_private_handler[] = { |
1563 | [0] = (iw_handler) ray_set_framing, | 1545 | [0] = ray_set_framing, |
1564 | [1] = (iw_handler) ray_get_framing, | 1546 | [1] = ray_get_framing, |
1565 | [3] = (iw_handler) ray_get_country, | 1547 | [3] = ray_get_country, |
1566 | }; | 1548 | }; |
1567 | 1549 | ||
1568 | static const struct iw_priv_args ray_private_args[] = { | 1550 | static const struct iw_priv_args ray_private_args[] = { |
@@ -2252,7 +2234,7 @@ static void rx_data(struct net_device *dev, struct rcs __iomem *prcs, | |||
2252 | (dev->mtu + RX_MAC_HEADER_LENGTH + ETH_HLEN + | 2234 | (dev->mtu + RX_MAC_HEADER_LENGTH + ETH_HLEN + |
2253 | FCS_LEN)) { | 2235 | FCS_LEN)) { |
2254 | pr_debug( | 2236 | pr_debug( |
2255 | "ray_cs invalid packet length %d received \n", | 2237 | "ray_cs invalid packet length %d received\n", |
2256 | rx_len); | 2238 | rx_len); |
2257 | return; | 2239 | return; |
2258 | } | 2240 | } |
@@ -2263,7 +2245,7 @@ static void rx_data(struct net_device *dev, struct rcs __iomem *prcs, | |||
2263 | (dev->mtu + RX_MAC_HEADER_LENGTH + ETH_HLEN + | 2245 | (dev->mtu + RX_MAC_HEADER_LENGTH + ETH_HLEN + |
2264 | FCS_LEN)) { | 2246 | FCS_LEN)) { |
2265 | pr_debug( | 2247 | pr_debug( |
2266 | "ray_cs invalid packet length %d received \n", | 2248 | "ray_cs invalid packet length %d received\n", |
2267 | rx_len); | 2249 | rx_len); |
2268 | return; | 2250 | return; |
2269 | } | 2251 | } |
@@ -2771,11 +2753,11 @@ static int ray_cs_proc_show(struct seq_file *m, void *v) | |||
2771 | seq_printf(m, "Hop dwell = %d Kus\n", | 2753 | seq_printf(m, "Hop dwell = %d Kus\n", |
2772 | pfh->dwell_time[0] + | 2754 | pfh->dwell_time[0] + |
2773 | 256 * pfh->dwell_time[1]); | 2755 | 256 * pfh->dwell_time[1]); |
2774 | seq_printf(m, "Hop set = %d \n", | 2756 | seq_printf(m, "Hop set = %d\n", |
2775 | pfh->hop_set); | 2757 | pfh->hop_set); |
2776 | seq_printf(m, "Hop pattern = %d \n", | 2758 | seq_printf(m, "Hop pattern = %d\n", |
2777 | pfh->hop_pattern); | 2759 | pfh->hop_pattern); |
2778 | seq_printf(m, "Hop index = %d \n", | 2760 | seq_printf(m, "Hop index = %d\n", |
2779 | pfh->hop_index); | 2761 | pfh->hop_index); |
2780 | p += p[1] + 2; | 2762 | p += p[1] + 2; |
2781 | } else { | 2763 | } else { |
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 2887047069f2..aceb95ef7274 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c | |||
@@ -117,6 +117,7 @@ MODULE_PARM_DESC(workaround_interval, | |||
117 | #define OID_802_11_ADD_KEY cpu_to_le32(0x0d01011d) | 117 | #define OID_802_11_ADD_KEY cpu_to_le32(0x0d01011d) |
118 | #define OID_802_11_REMOVE_KEY cpu_to_le32(0x0d01011e) | 118 | #define OID_802_11_REMOVE_KEY cpu_to_le32(0x0d01011e) |
119 | #define OID_802_11_ASSOCIATION_INFORMATION cpu_to_le32(0x0d01011f) | 119 | #define OID_802_11_ASSOCIATION_INFORMATION cpu_to_le32(0x0d01011f) |
120 | #define OID_802_11_CAPABILITY cpu_to_le32(0x0d010122) | ||
120 | #define OID_802_11_PMKID cpu_to_le32(0x0d010123) | 121 | #define OID_802_11_PMKID cpu_to_le32(0x0d010123) |
121 | #define OID_802_11_NETWORK_TYPES_SUPPORTED cpu_to_le32(0x0d010203) | 122 | #define OID_802_11_NETWORK_TYPES_SUPPORTED cpu_to_le32(0x0d010203) |
122 | #define OID_802_11_NETWORK_TYPE_IN_USE cpu_to_le32(0x0d010204) | 123 | #define OID_802_11_NETWORK_TYPE_IN_USE cpu_to_le32(0x0d010204) |
@@ -358,6 +359,30 @@ struct ndis_80211_assoc_info { | |||
358 | __le32 offset_resp_ies; | 359 | __le32 offset_resp_ies; |
359 | } __attribute__((packed)); | 360 | } __attribute__((packed)); |
360 | 361 | ||
362 | struct ndis_80211_auth_encr_pair { | ||
363 | __le32 auth_mode; | ||
364 | __le32 encr_mode; | ||
365 | } __attribute__((packed)); | ||
366 | |||
367 | struct ndis_80211_capability { | ||
368 | __le32 length; | ||
369 | __le32 version; | ||
370 | __le32 num_pmkids; | ||
371 | __le32 num_auth_encr_pair; | ||
372 | struct ndis_80211_auth_encr_pair auth_encr_pair[0]; | ||
373 | } __attribute__((packed)); | ||
374 | |||
375 | struct ndis_80211_bssid_info { | ||
376 | u8 bssid[6]; | ||
377 | u8 pmkid[16]; | ||
378 | }; | ||
379 | |||
380 | struct ndis_80211_pmkid { | ||
381 | __le32 length; | ||
382 | __le32 bssid_info_count; | ||
383 | struct ndis_80211_bssid_info bssid_info[0]; | ||
384 | }; | ||
385 | |||
361 | /* | 386 | /* |
362 | * private data | 387 | * private data |
363 | */ | 388 | */ |
@@ -476,13 +501,7 @@ struct rndis_wlan_private { | |||
476 | /* encryption stuff */ | 501 | /* encryption stuff */ |
477 | int encr_tx_key_index; | 502 | int encr_tx_key_index; |
478 | struct rndis_wlan_encr_key encr_keys[4]; | 503 | struct rndis_wlan_encr_key encr_keys[4]; |
479 | enum nl80211_auth_type wpa_auth_type; | ||
480 | int wpa_version; | 504 | int wpa_version; |
481 | int wpa_keymgmt; | ||
482 | int wpa_ie_len; | ||
483 | u8 *wpa_ie; | ||
484 | int wpa_cipher_pair; | ||
485 | int wpa_cipher_group; | ||
486 | 505 | ||
487 | u8 command_buffer[COMMAND_BUFFER_SIZE]; | 506 | u8 command_buffer[COMMAND_BUFFER_SIZE]; |
488 | }; | 507 | }; |
@@ -534,6 +553,14 @@ static int rndis_get_station(struct wiphy *wiphy, struct net_device *dev, | |||
534 | static int rndis_dump_station(struct wiphy *wiphy, struct net_device *dev, | 553 | static int rndis_dump_station(struct wiphy *wiphy, struct net_device *dev, |
535 | int idx, u8 *mac, struct station_info *sinfo); | 554 | int idx, u8 *mac, struct station_info *sinfo); |
536 | 555 | ||
556 | static int rndis_set_pmksa(struct wiphy *wiphy, struct net_device *netdev, | ||
557 | struct cfg80211_pmksa *pmksa); | ||
558 | |||
559 | static int rndis_del_pmksa(struct wiphy *wiphy, struct net_device *netdev, | ||
560 | struct cfg80211_pmksa *pmksa); | ||
561 | |||
562 | static int rndis_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev); | ||
563 | |||
537 | static struct cfg80211_ops rndis_config_ops = { | 564 | static struct cfg80211_ops rndis_config_ops = { |
538 | .change_virtual_intf = rndis_change_virtual_intf, | 565 | .change_virtual_intf = rndis_change_virtual_intf, |
539 | .scan = rndis_scan, | 566 | .scan = rndis_scan, |
@@ -550,6 +577,9 @@ static struct cfg80211_ops rndis_config_ops = { | |||
550 | .set_default_key = rndis_set_default_key, | 577 | .set_default_key = rndis_set_default_key, |
551 | .get_station = rndis_get_station, | 578 | .get_station = rndis_get_station, |
552 | .dump_station = rndis_dump_station, | 579 | .dump_station = rndis_dump_station, |
580 | .set_pmksa = rndis_set_pmksa, | ||
581 | .del_pmksa = rndis_del_pmksa, | ||
582 | .flush_pmksa = rndis_flush_pmksa, | ||
553 | }; | 583 | }; |
554 | 584 | ||
555 | static void *rndis_wiphy_privid = &rndis_wiphy_privid; | 585 | static void *rndis_wiphy_privid = &rndis_wiphy_privid; |
@@ -704,6 +734,7 @@ static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len) | |||
704 | struct rndis_query_c *get_c; | 734 | struct rndis_query_c *get_c; |
705 | } u; | 735 | } u; |
706 | int ret, buflen; | 736 | int ret, buflen; |
737 | int resplen, respoffs, copylen; | ||
707 | 738 | ||
708 | buflen = *len + sizeof(*u.get); | 739 | buflen = *len + sizeof(*u.get); |
709 | if (buflen < CONTROL_BUFFER_SIZE) | 740 | if (buflen < CONTROL_BUFFER_SIZE) |
@@ -733,11 +764,34 @@ static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len) | |||
733 | le32_to_cpu(u.get_c->status)); | 764 | le32_to_cpu(u.get_c->status)); |
734 | 765 | ||
735 | if (ret == 0) { | 766 | if (ret == 0) { |
736 | memcpy(data, u.buf + le32_to_cpu(u.get_c->offset) + 8, *len); | 767 | resplen = le32_to_cpu(u.get_c->len); |
768 | respoffs = le32_to_cpu(u.get_c->offset) + 8; | ||
737 | 769 | ||
738 | ret = le32_to_cpu(u.get_c->len); | 770 | if (respoffs > buflen) { |
739 | if (ret > *len) | 771 | /* Device returned data offset outside buffer, error. */ |
740 | *len = ret; | 772 | netdev_dbg(dev->net, "%s(%s): received invalid " |
773 | "data offset: %d > %d\n", __func__, | ||
774 | oid_to_string(oid), respoffs, buflen); | ||
775 | |||
776 | ret = -EINVAL; | ||
777 | goto exit_unlock; | ||
778 | } | ||
779 | |||
780 | if ((resplen + respoffs) > buflen) { | ||
781 | /* Device would have returned more data if buffer would | ||
782 | * have been big enough. Copy just the bits that we got. | ||
783 | */ | ||
784 | copylen = buflen - respoffs; | ||
785 | } else { | ||
786 | copylen = resplen; | ||
787 | } | ||
788 | |||
789 | if (copylen > *len) | ||
790 | copylen = *len; | ||
791 | |||
792 | memcpy(data, u.buf + respoffs, copylen); | ||
793 | |||
794 | *len = resplen; | ||
741 | 795 | ||
742 | ret = rndis_error_status(u.get_c->status); | 796 | ret = rndis_error_status(u.get_c->status); |
743 | if (ret < 0) | 797 | if (ret < 0) |
@@ -746,6 +800,7 @@ static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len) | |||
746 | le32_to_cpu(u.get_c->status), ret); | 800 | le32_to_cpu(u.get_c->status), ret); |
747 | } | 801 | } |
748 | 802 | ||
803 | exit_unlock: | ||
749 | mutex_unlock(&priv->command_lock); | 804 | mutex_unlock(&priv->command_lock); |
750 | 805 | ||
751 | if (u.buf != priv->command_buffer) | 806 | if (u.buf != priv->command_buffer) |
@@ -1091,8 +1146,6 @@ static int set_auth_mode(struct usbnet *usbdev, u32 wpa_version, | |||
1091 | } | 1146 | } |
1092 | 1147 | ||
1093 | priv->wpa_version = wpa_version; | 1148 | priv->wpa_version = wpa_version; |
1094 | priv->wpa_auth_type = auth_type; | ||
1095 | priv->wpa_keymgmt = keymgmt; | ||
1096 | 1149 | ||
1097 | return 0; | 1150 | return 0; |
1098 | } | 1151 | } |
@@ -1117,7 +1170,6 @@ static int set_priv_filter(struct usbnet *usbdev) | |||
1117 | 1170 | ||
1118 | static int set_encr_mode(struct usbnet *usbdev, int pairwise, int groupwise) | 1171 | static int set_encr_mode(struct usbnet *usbdev, int pairwise, int groupwise) |
1119 | { | 1172 | { |
1120 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | ||
1121 | __le32 tmp; | 1173 | __le32 tmp; |
1122 | int encr_mode, ret; | 1174 | int encr_mode, ret; |
1123 | 1175 | ||
@@ -1146,8 +1198,6 @@ static int set_encr_mode(struct usbnet *usbdev, int pairwise, int groupwise) | |||
1146 | return ret; | 1198 | return ret; |
1147 | } | 1199 | } |
1148 | 1200 | ||
1149 | priv->wpa_cipher_pair = pairwise; | ||
1150 | priv->wpa_cipher_group = groupwise; | ||
1151 | return 0; | 1201 | return 0; |
1152 | } | 1202 | } |
1153 | 1203 | ||
@@ -1568,6 +1618,194 @@ set_filter: | |||
1568 | le32_to_cpu(filter), ret); | 1618 | le32_to_cpu(filter), ret); |
1569 | } | 1619 | } |
1570 | 1620 | ||
1621 | #ifdef DEBUG | ||
1622 | static void debug_print_pmkids(struct usbnet *usbdev, | ||
1623 | struct ndis_80211_pmkid *pmkids, | ||
1624 | const char *func_str) | ||
1625 | { | ||
1626 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | ||
1627 | int i, len, count, max_pmkids, entry_len; | ||
1628 | |||
1629 | max_pmkids = priv->wdev.wiphy->max_num_pmkids; | ||
1630 | len = le32_to_cpu(pmkids->length); | ||
1631 | count = le32_to_cpu(pmkids->bssid_info_count); | ||
1632 | |||
1633 | entry_len = (count > 0) ? (len - sizeof(*pmkids)) / count : -1; | ||
1634 | |||
1635 | netdev_dbg(usbdev->net, "%s(): %d PMKIDs (data len: %d, entry len: " | ||
1636 | "%d)\n", func_str, count, len, entry_len); | ||
1637 | |||
1638 | if (count > max_pmkids) | ||
1639 | count = max_pmkids; | ||
1640 | |||
1641 | for (i = 0; i < count; i++) { | ||
1642 | u32 *tmp = (u32 *)pmkids->bssid_info[i].pmkid; | ||
1643 | |||
1644 | netdev_dbg(usbdev->net, "%s(): bssid: %pM, " | ||
1645 | "pmkid: %08X:%08X:%08X:%08X\n", | ||
1646 | func_str, pmkids->bssid_info[i].bssid, | ||
1647 | cpu_to_be32(tmp[0]), cpu_to_be32(tmp[1]), | ||
1648 | cpu_to_be32(tmp[2]), cpu_to_be32(tmp[3])); | ||
1649 | } | ||
1650 | } | ||
1651 | #else | ||
1652 | static void debug_print_pmkids(struct usbnet *usbdev, | ||
1653 | struct ndis_80211_pmkid *pmkids, | ||
1654 | const char *func_str) | ||
1655 | { | ||
1656 | return; | ||
1657 | } | ||
1658 | #endif | ||
1659 | |||
1660 | static struct ndis_80211_pmkid *get_device_pmkids(struct usbnet *usbdev) | ||
1661 | { | ||
1662 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | ||
1663 | struct ndis_80211_pmkid *pmkids; | ||
1664 | int len, ret, max_pmkids; | ||
1665 | |||
1666 | max_pmkids = priv->wdev.wiphy->max_num_pmkids; | ||
1667 | len = sizeof(*pmkids) + max_pmkids * sizeof(pmkids->bssid_info[0]); | ||
1668 | |||
1669 | pmkids = kzalloc(len, GFP_KERNEL); | ||
1670 | if (!pmkids) | ||
1671 | return ERR_PTR(-ENOMEM); | ||
1672 | |||
1673 | pmkids->length = cpu_to_le32(len); | ||
1674 | pmkids->bssid_info_count = cpu_to_le32(max_pmkids); | ||
1675 | |||
1676 | ret = rndis_query_oid(usbdev, OID_802_11_PMKID, pmkids, &len); | ||
1677 | if (ret < 0) { | ||
1678 | netdev_dbg(usbdev->net, "%s(): OID_802_11_PMKID(%d, %d)" | ||
1679 | " -> %d\n", __func__, len, max_pmkids, ret); | ||
1680 | |||
1681 | kfree(pmkids); | ||
1682 | return ERR_PTR(ret); | ||
1683 | } | ||
1684 | |||
1685 | if (le32_to_cpu(pmkids->bssid_info_count) > max_pmkids) | ||
1686 | pmkids->bssid_info_count = cpu_to_le32(max_pmkids); | ||
1687 | |||
1688 | debug_print_pmkids(usbdev, pmkids, __func__); | ||
1689 | |||
1690 | return pmkids; | ||
1691 | } | ||
1692 | |||
1693 | static int set_device_pmkids(struct usbnet *usbdev, | ||
1694 | struct ndis_80211_pmkid *pmkids) | ||
1695 | { | ||
1696 | int ret, len, num_pmkids; | ||
1697 | |||
1698 | num_pmkids = le32_to_cpu(pmkids->bssid_info_count); | ||
1699 | len = sizeof(*pmkids) + num_pmkids * sizeof(pmkids->bssid_info[0]); | ||
1700 | pmkids->length = cpu_to_le32(len); | ||
1701 | |||
1702 | debug_print_pmkids(usbdev, pmkids, __func__); | ||
1703 | |||
1704 | ret = rndis_set_oid(usbdev, OID_802_11_PMKID, pmkids, | ||
1705 | le32_to_cpu(pmkids->length)); | ||
1706 | if (ret < 0) { | ||
1707 | netdev_dbg(usbdev->net, "%s(): OID_802_11_PMKID(%d, %d) -> %d" | ||
1708 | "\n", __func__, len, num_pmkids, ret); | ||
1709 | } | ||
1710 | |||
1711 | kfree(pmkids); | ||
1712 | return ret; | ||
1713 | } | ||
1714 | |||
1715 | static struct ndis_80211_pmkid *remove_pmkid(struct usbnet *usbdev, | ||
1716 | struct ndis_80211_pmkid *pmkids, | ||
1717 | struct cfg80211_pmksa *pmksa, | ||
1718 | int max_pmkids) | ||
1719 | { | ||
1720 | int i, len, count, newlen, err; | ||
1721 | |||
1722 | len = le32_to_cpu(pmkids->length); | ||
1723 | count = le32_to_cpu(pmkids->bssid_info_count); | ||
1724 | |||
1725 | if (count > max_pmkids) | ||
1726 | count = max_pmkids; | ||
1727 | |||
1728 | for (i = 0; i < count; i++) | ||
1729 | if (!compare_ether_addr(pmkids->bssid_info[i].bssid, | ||
1730 | pmksa->bssid)) | ||
1731 | break; | ||
1732 | |||
1733 | /* pmkid not found */ | ||
1734 | if (i == count) { | ||
1735 | netdev_dbg(usbdev->net, "%s(): bssid not found (%pM)\n", | ||
1736 | __func__, pmksa->bssid); | ||
1737 | err = -ENOENT; | ||
1738 | goto error; | ||
1739 | } | ||
1740 | |||
1741 | for (; i + 1 < count; i++) | ||
1742 | pmkids->bssid_info[i] = pmkids->bssid_info[i + 1]; | ||
1743 | |||
1744 | count--; | ||
1745 | newlen = sizeof(*pmkids) + count * sizeof(pmkids->bssid_info[0]); | ||
1746 | |||
1747 | pmkids->length = cpu_to_le32(newlen); | ||
1748 | pmkids->bssid_info_count = cpu_to_le32(count); | ||
1749 | |||
1750 | return pmkids; | ||
1751 | error: | ||
1752 | kfree(pmkids); | ||
1753 | return ERR_PTR(err); | ||
1754 | } | ||
1755 | |||
1756 | static struct ndis_80211_pmkid *update_pmkid(struct usbnet *usbdev, | ||
1757 | struct ndis_80211_pmkid *pmkids, | ||
1758 | struct cfg80211_pmksa *pmksa, | ||
1759 | int max_pmkids) | ||
1760 | { | ||
1761 | int i, err, len, count, newlen; | ||
1762 | |||
1763 | len = le32_to_cpu(pmkids->length); | ||
1764 | count = le32_to_cpu(pmkids->bssid_info_count); | ||
1765 | |||
1766 | if (count > max_pmkids) | ||
1767 | count = max_pmkids; | ||
1768 | |||
1769 | /* update with new pmkid */ | ||
1770 | for (i = 0; i < count; i++) { | ||
1771 | if (compare_ether_addr(pmkids->bssid_info[i].bssid, | ||
1772 | pmksa->bssid)) | ||
1773 | continue; | ||
1774 | |||
1775 | memcpy(pmkids->bssid_info[i].pmkid, pmksa->pmkid, | ||
1776 | WLAN_PMKID_LEN); | ||
1777 | |||
1778 | return pmkids; | ||
1779 | } | ||
1780 | |||
1781 | /* out of space, return error */ | ||
1782 | if (i == max_pmkids) { | ||
1783 | netdev_dbg(usbdev->net, "%s(): out of space\n", __func__); | ||
1784 | err = -ENOSPC; | ||
1785 | goto error; | ||
1786 | } | ||
1787 | |||
1788 | /* add new pmkid */ | ||
1789 | newlen = sizeof(*pmkids) + (count + 1) * sizeof(pmkids->bssid_info[0]); | ||
1790 | |||
1791 | pmkids = krealloc(pmkids, newlen, GFP_KERNEL); | ||
1792 | if (!pmkids) { | ||
1793 | err = -ENOMEM; | ||
1794 | goto error; | ||
1795 | } | ||
1796 | |||
1797 | pmkids->length = cpu_to_le32(newlen); | ||
1798 | pmkids->bssid_info_count = cpu_to_le32(count + 1); | ||
1799 | |||
1800 | memcpy(pmkids->bssid_info[count].bssid, pmksa->bssid, ETH_ALEN); | ||
1801 | memcpy(pmkids->bssid_info[count].pmkid, pmksa->pmkid, WLAN_PMKID_LEN); | ||
1802 | |||
1803 | return pmkids; | ||
1804 | error: | ||
1805 | kfree(pmkids); | ||
1806 | return ERR_PTR(err); | ||
1807 | } | ||
1808 | |||
1571 | /* | 1809 | /* |
1572 | * cfg80211 ops | 1810 | * cfg80211 ops |
1573 | */ | 1811 | */ |
@@ -2178,6 +2416,78 @@ static int rndis_dump_station(struct wiphy *wiphy, struct net_device *dev, | |||
2178 | return 0; | 2416 | return 0; |
2179 | } | 2417 | } |
2180 | 2418 | ||
2419 | static int rndis_set_pmksa(struct wiphy *wiphy, struct net_device *netdev, | ||
2420 | struct cfg80211_pmksa *pmksa) | ||
2421 | { | ||
2422 | struct rndis_wlan_private *priv = wiphy_priv(wiphy); | ||
2423 | struct usbnet *usbdev = priv->usbdev; | ||
2424 | struct ndis_80211_pmkid *pmkids; | ||
2425 | u32 *tmp = (u32 *)pmksa->pmkid; | ||
2426 | |||
2427 | netdev_dbg(usbdev->net, "%s(%pM, %08X:%08X:%08X:%08X)\n", __func__, | ||
2428 | pmksa->bssid, | ||
2429 | cpu_to_be32(tmp[0]), cpu_to_be32(tmp[1]), | ||
2430 | cpu_to_be32(tmp[2]), cpu_to_be32(tmp[3])); | ||
2431 | |||
2432 | pmkids = get_device_pmkids(usbdev); | ||
2433 | if (IS_ERR(pmkids)) { | ||
2434 | /* couldn't read PMKID cache from device */ | ||
2435 | return PTR_ERR(pmkids); | ||
2436 | } | ||
2437 | |||
2438 | pmkids = update_pmkid(usbdev, pmkids, pmksa, wiphy->max_num_pmkids); | ||
2439 | if (IS_ERR(pmkids)) { | ||
2440 | /* not found, list full, etc */ | ||
2441 | return PTR_ERR(pmkids); | ||
2442 | } | ||
2443 | |||
2444 | return set_device_pmkids(usbdev, pmkids); | ||
2445 | } | ||
2446 | |||
2447 | static int rndis_del_pmksa(struct wiphy *wiphy, struct net_device *netdev, | ||
2448 | struct cfg80211_pmksa *pmksa) | ||
2449 | { | ||
2450 | struct rndis_wlan_private *priv = wiphy_priv(wiphy); | ||
2451 | struct usbnet *usbdev = priv->usbdev; | ||
2452 | struct ndis_80211_pmkid *pmkids; | ||
2453 | u32 *tmp = (u32 *)pmksa->pmkid; | ||
2454 | |||
2455 | netdev_dbg(usbdev->net, "%s(%pM, %08X:%08X:%08X:%08X)\n", __func__, | ||
2456 | pmksa->bssid, | ||
2457 | cpu_to_be32(tmp[0]), cpu_to_be32(tmp[1]), | ||
2458 | cpu_to_be32(tmp[2]), cpu_to_be32(tmp[3])); | ||
2459 | |||
2460 | pmkids = get_device_pmkids(usbdev); | ||
2461 | if (IS_ERR(pmkids)) { | ||
2462 | /* Couldn't read PMKID cache from device */ | ||
2463 | return PTR_ERR(pmkids); | ||
2464 | } | ||
2465 | |||
2466 | pmkids = remove_pmkid(usbdev, pmkids, pmksa, wiphy->max_num_pmkids); | ||
2467 | if (IS_ERR(pmkids)) { | ||
2468 | /* not found, etc */ | ||
2469 | return PTR_ERR(pmkids); | ||
2470 | } | ||
2471 | |||
2472 | return set_device_pmkids(usbdev, pmkids); | ||
2473 | } | ||
2474 | |||
2475 | static int rndis_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev) | ||
2476 | { | ||
2477 | struct rndis_wlan_private *priv = wiphy_priv(wiphy); | ||
2478 | struct usbnet *usbdev = priv->usbdev; | ||
2479 | struct ndis_80211_pmkid pmkid; | ||
2480 | |||
2481 | netdev_dbg(usbdev->net, "%s()\n", __func__); | ||
2482 | |||
2483 | memset(&pmkid, 0, sizeof(pmkid)); | ||
2484 | |||
2485 | pmkid.length = cpu_to_le32(sizeof(pmkid)); | ||
2486 | pmkid.bssid_info_count = cpu_to_le32(0); | ||
2487 | |||
2488 | return rndis_set_oid(usbdev, OID_802_11_PMKID, &pmkid, sizeof(pmkid)); | ||
2489 | } | ||
2490 | |||
2181 | /* | 2491 | /* |
2182 | * workers, indication handlers, device poller | 2492 | * workers, indication handlers, device poller |
2183 | */ | 2493 | */ |
@@ -2522,12 +2832,14 @@ static void rndis_wlan_indication(struct usbnet *usbdev, void *ind, int buflen) | |||
2522 | } | 2832 | } |
2523 | } | 2833 | } |
2524 | 2834 | ||
2525 | static int rndis_wlan_get_caps(struct usbnet *usbdev) | 2835 | static int rndis_wlan_get_caps(struct usbnet *usbdev, struct wiphy *wiphy) |
2526 | { | 2836 | { |
2527 | struct { | 2837 | struct { |
2528 | __le32 num_items; | 2838 | __le32 num_items; |
2529 | __le32 items[8]; | 2839 | __le32 items[8]; |
2530 | } networks_supported; | 2840 | } networks_supported; |
2841 | struct ndis_80211_capability *caps; | ||
2842 | u8 caps_buf[sizeof(*caps) + sizeof(caps->auth_encr_pair) * 16]; | ||
2531 | int len, retval, i, n; | 2843 | int len, retval, i, n; |
2532 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | 2844 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); |
2533 | 2845 | ||
@@ -2555,6 +2867,21 @@ static int rndis_wlan_get_caps(struct usbnet *usbdev) | |||
2555 | } | 2867 | } |
2556 | } | 2868 | } |
2557 | 2869 | ||
2870 | /* get device 802.11 capabilities, number of PMKIDs */ | ||
2871 | caps = (struct ndis_80211_capability *)caps_buf; | ||
2872 | len = sizeof(caps_buf); | ||
2873 | retval = rndis_query_oid(usbdev, OID_802_11_CAPABILITY, caps, &len); | ||
2874 | if (retval >= 0) { | ||
2875 | netdev_dbg(usbdev->net, "OID_802_11_CAPABILITY -> len %d, " | ||
2876 | "ver %d, pmkids %d, auth-encr-pairs %d\n", | ||
2877 | le32_to_cpu(caps->length), | ||
2878 | le32_to_cpu(caps->version), | ||
2879 | le32_to_cpu(caps->num_pmkids), | ||
2880 | le32_to_cpu(caps->num_auth_encr_pair)); | ||
2881 | wiphy->max_num_pmkids = le32_to_cpu(caps->num_pmkids); | ||
2882 | } else | ||
2883 | wiphy->max_num_pmkids = 0; | ||
2884 | |||
2558 | return retval; | 2885 | return retval; |
2559 | } | 2886 | } |
2560 | 2887 | ||
@@ -2802,7 +3129,7 @@ static int rndis_wlan_bind(struct usbnet *usbdev, struct usb_interface *intf) | |||
2802 | wiphy->max_scan_ssids = 1; | 3129 | wiphy->max_scan_ssids = 1; |
2803 | 3130 | ||
2804 | /* TODO: fill-out band/encr information based on priv->caps */ | 3131 | /* TODO: fill-out band/encr information based on priv->caps */ |
2805 | rndis_wlan_get_caps(usbdev); | 3132 | rndis_wlan_get_caps(usbdev, wiphy); |
2806 | 3133 | ||
2807 | memcpy(priv->channels, rndis_channels, sizeof(rndis_channels)); | 3134 | memcpy(priv->channels, rndis_channels, sizeof(rndis_channels)); |
2808 | memcpy(priv->rates, rndis_rates, sizeof(rndis_rates)); | 3135 | memcpy(priv->rates, rndis_rates, sizeof(rndis_rates)); |
@@ -2862,9 +3189,6 @@ static void rndis_wlan_unbind(struct usbnet *usbdev, struct usb_interface *intf) | |||
2862 | flush_workqueue(priv->workqueue); | 3189 | flush_workqueue(priv->workqueue); |
2863 | destroy_workqueue(priv->workqueue); | 3190 | destroy_workqueue(priv->workqueue); |
2864 | 3191 | ||
2865 | if (priv && priv->wpa_ie_len) | ||
2866 | kfree(priv->wpa_ie); | ||
2867 | |||
2868 | rndis_unbind(usbdev, intf); | 3192 | rndis_unbind(usbdev, intf); |
2869 | 3193 | ||
2870 | wiphy_unregister(priv->wdev.wiphy); | 3194 | wiphy_unregister(priv->wdev.wiphy); |
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index c22b04042d5c..08a4789fc2d8 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c | |||
@@ -525,6 +525,10 @@ static void rt2400pci_config_ps(struct rt2x00_dev *rt2x00dev, | |||
525 | 525 | ||
526 | rt2x00_set_field32(®, CSR20_AUTOWAKE, 1); | 526 | rt2x00_set_field32(®, CSR20_AUTOWAKE, 1); |
527 | rt2x00pci_register_write(rt2x00dev, CSR20, reg); | 527 | rt2x00pci_register_write(rt2x00dev, CSR20, reg); |
528 | } else { | ||
529 | rt2x00pci_register_read(rt2x00dev, CSR20, ®); | ||
530 | rt2x00_set_field32(®, CSR20_AUTOWAKE, 0); | ||
531 | rt2x00pci_register_write(rt2x00dev, CSR20, reg); | ||
528 | } | 532 | } |
529 | 533 | ||
530 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); | 534 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); |
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 52bbcf1bd17c..d084d70e5fe2 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c | |||
@@ -573,6 +573,10 @@ static void rt2500pci_config_ps(struct rt2x00_dev *rt2x00dev, | |||
573 | 573 | ||
574 | rt2x00_set_field32(®, CSR20_AUTOWAKE, 1); | 574 | rt2x00_set_field32(®, CSR20_AUTOWAKE, 1); |
575 | rt2x00pci_register_write(rt2x00dev, CSR20, reg); | 575 | rt2x00pci_register_write(rt2x00dev, CSR20, reg); |
576 | } else { | ||
577 | rt2x00pci_register_read(rt2x00dev, CSR20, ®); | ||
578 | rt2x00_set_field32(®, CSR20_AUTOWAKE, 0); | ||
579 | rt2x00pci_register_write(rt2x00dev, CSR20, reg); | ||
576 | } | 580 | } |
577 | 581 | ||
578 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); | 582 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); |
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index dbaa78138437..54d2716e389c 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c | |||
@@ -648,6 +648,10 @@ static void rt2500usb_config_ps(struct rt2x00_dev *rt2x00dev, | |||
648 | 648 | ||
649 | rt2x00_set_field16(®, MAC_CSR18_AUTO_WAKE, 1); | 649 | rt2x00_set_field16(®, MAC_CSR18_AUTO_WAKE, 1); |
650 | rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg); | 650 | rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg); |
651 | } else { | ||
652 | rt2500usb_register_read(rt2x00dev, MAC_CSR18, ®); | ||
653 | rt2x00_set_field16(®, MAC_CSR18_AUTO_WAKE, 0); | ||
654 | rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg); | ||
651 | } | 655 | } |
652 | 656 | ||
653 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); | 657 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 326fce78489d..68d0cfee3f20 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
@@ -1014,13 +1014,13 @@ static void rt2800_config_ps(struct rt2x00_dev *rt2x00dev, | |||
1014 | 1014 | ||
1015 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); | 1015 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); |
1016 | } else { | 1016 | } else { |
1017 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); | ||
1018 | |||
1019 | rt2800_register_read(rt2x00dev, AUTOWAKEUP_CFG, ®); | 1017 | rt2800_register_read(rt2x00dev, AUTOWAKEUP_CFG, ®); |
1020 | rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0); | 1018 | rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0); |
1021 | rt2x00_set_field32(®, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, 0); | 1019 | rt2x00_set_field32(®, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, 0); |
1022 | rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTOWAKE, 0); | 1020 | rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTOWAKE, 0); |
1023 | rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg); | 1021 | rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg); |
1022 | |||
1023 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); | ||
1024 | } | 1024 | } |
1025 | } | 1025 | } |
1026 | 1026 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 91cce2d0f6db..a2b37d38d400 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c | |||
@@ -60,6 +60,12 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token) | |||
60 | unsigned int i; | 60 | unsigned int i; |
61 | u32 reg; | 61 | u32 reg; |
62 | 62 | ||
63 | /* | ||
64 | * SOC devices don't support MCU requests. | ||
65 | */ | ||
66 | if (rt2x00_is_soc(rt2x00dev)) | ||
67 | return; | ||
68 | |||
63 | for (i = 0; i < 200; i++) { | 69 | for (i = 0; i < 200; i++) { |
64 | rt2800_register_read(rt2x00dev, H2M_MAILBOX_CID, ®); | 70 | rt2800_register_read(rt2x00dev, H2M_MAILBOX_CID, ®); |
65 | 71 | ||
@@ -907,14 +913,12 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) | |||
907 | { | 913 | { |
908 | struct data_queue *queue; | 914 | struct data_queue *queue; |
909 | struct queue_entry *entry; | 915 | struct queue_entry *entry; |
910 | struct queue_entry *entry_done; | 916 | __le32 *txwi; |
911 | struct queue_entry_priv_pci *entry_priv; | ||
912 | struct txdone_entry_desc txdesc; | 917 | struct txdone_entry_desc txdesc; |
913 | u32 word; | 918 | u32 word; |
914 | u32 reg; | 919 | u32 reg; |
915 | u32 old_reg; | 920 | u32 old_reg; |
916 | unsigned int type; | 921 | int wcid, ack, pid, tx_wcid, tx_ack, tx_pid; |
917 | unsigned int index; | ||
918 | u16 mcs, real_mcs; | 922 | u16 mcs, real_mcs; |
919 | 923 | ||
920 | /* | 924 | /* |
@@ -936,76 +940,89 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) | |||
936 | break; | 940 | break; |
937 | old_reg = reg; | 941 | old_reg = reg; |
938 | 942 | ||
943 | wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID); | ||
944 | ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED); | ||
945 | pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE); | ||
946 | |||
939 | /* | 947 | /* |
940 | * Skip this entry when it contains an invalid | 948 | * Skip this entry when it contains an invalid |
941 | * queue identication number. | 949 | * queue identication number. |
942 | */ | 950 | */ |
943 | type = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE) - 1; | 951 | if (pid <= 0 || pid > QID_RX) |
944 | if (type >= QID_RX) | ||
945 | continue; | 952 | continue; |
946 | 953 | ||
947 | queue = rt2x00queue_get_queue(rt2x00dev, type); | 954 | queue = rt2x00queue_get_queue(rt2x00dev, pid - 1); |
948 | if (unlikely(!queue)) | 955 | if (unlikely(!queue)) |
949 | continue; | 956 | continue; |
950 | 957 | ||
951 | /* | 958 | /* |
952 | * Skip this entry when it contains an invalid | 959 | * Inside each queue, we process each entry in a chronological |
953 | * index number. | 960 | * order. We first check that the queue is not empty. |
954 | */ | 961 | */ |
955 | index = rt2x00_get_field32(reg, TX_STA_FIFO_WCID) - 1; | 962 | if (rt2x00queue_empty(queue)) |
956 | if (unlikely(index >= queue->limit)) | ||
957 | continue; | 963 | continue; |
964 | entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); | ||
958 | 965 | ||
959 | entry = &queue->entries[index]; | 966 | /* Check if we got a match by looking at WCID/ACK/PID |
960 | entry_priv = entry->priv_data; | 967 | * fields */ |
961 | rt2x00_desc_read((__le32 *)entry->skb->data, 0, &word); | 968 | txwi = (__le32 *)(entry->skb->data - |
969 | rt2x00dev->ops->extra_tx_headroom); | ||
962 | 970 | ||
963 | entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE); | 971 | rt2x00_desc_read(txwi, 1, &word); |
964 | while (entry != entry_done) { | 972 | tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID); |
965 | /* | 973 | tx_ack = rt2x00_get_field32(word, TXWI_W1_ACK); |
966 | * Catch up. | 974 | tx_pid = rt2x00_get_field32(word, TXWI_W1_PACKETID); |
967 | * Just report any entries we missed as failed. | ||
968 | */ | ||
969 | WARNING(rt2x00dev, | ||
970 | "TX status report missed for entry %d\n", | ||
971 | entry_done->entry_idx); | ||
972 | |||
973 | txdesc.flags = 0; | ||
974 | __set_bit(TXDONE_UNKNOWN, &txdesc.flags); | ||
975 | txdesc.retry = 0; | ||
976 | 975 | ||
977 | rt2x00lib_txdone(entry_done, &txdesc); | 976 | if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid)) |
978 | entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE); | 977 | WARNING(rt2x00dev, "invalid TX_STA_FIFO content\n"); |
979 | } | ||
980 | 978 | ||
981 | /* | 979 | /* |
982 | * Obtain the status about this packet. | 980 | * Obtain the status about this packet. |
983 | */ | 981 | */ |
984 | txdesc.flags = 0; | 982 | txdesc.flags = 0; |
985 | if (rt2x00_get_field32(reg, TX_STA_FIFO_TX_SUCCESS)) | 983 | rt2x00_desc_read(txwi, 0, &word); |
986 | __set_bit(TXDONE_SUCCESS, &txdesc.flags); | 984 | mcs = rt2x00_get_field32(word, TXWI_W0_MCS); |
987 | else | 985 | real_mcs = rt2x00_get_field32(reg, TX_STA_FIFO_MCS); |
988 | __set_bit(TXDONE_FAILURE, &txdesc.flags); | ||
989 | 986 | ||
990 | /* | 987 | /* |
991 | * Ralink has a retry mechanism using a global fallback | 988 | * Ralink has a retry mechanism using a global fallback |
992 | * table. We setup this fallback table to try immediate | 989 | * table. We setup this fallback table to try the immediate |
993 | * lower rate for all rates. In the TX_STA_FIFO, | 990 | * lower rate for all rates. In the TX_STA_FIFO, the MCS field |
994 | * the MCS field contains the MCS used for the successfull | 991 | * always contains the MCS used for the last transmission, be |
995 | * transmission. If the first transmission succeed, | 992 | * it successful or not. |
996 | * we have mcs == tx_mcs. On the second transmission, | ||
997 | * we have mcs = tx_mcs - 1. So the number of | ||
998 | * retry is (tx_mcs - mcs). | ||
999 | */ | 993 | */ |
1000 | mcs = rt2x00_get_field32(word, TXWI_W0_MCS); | 994 | if (rt2x00_get_field32(reg, TX_STA_FIFO_TX_SUCCESS)) { |
1001 | real_mcs = rt2x00_get_field32(reg, TX_STA_FIFO_MCS); | 995 | /* |
996 | * Transmission succeeded. The number of retries is | ||
997 | * mcs - real_mcs | ||
998 | */ | ||
999 | __set_bit(TXDONE_SUCCESS, &txdesc.flags); | ||
1000 | txdesc.retry = ((mcs > real_mcs) ? mcs - real_mcs : 0); | ||
1001 | } else { | ||
1002 | /* | ||
1003 | * Transmission failed. The number of retries is | ||
1004 | * always 7 in this case (for a total number of 8 | ||
1005 | * frames sent). | ||
1006 | */ | ||
1007 | __set_bit(TXDONE_FAILURE, &txdesc.flags); | ||
1008 | txdesc.retry = 7; | ||
1009 | } | ||
1010 | |||
1002 | __set_bit(TXDONE_FALLBACK, &txdesc.flags); | 1011 | __set_bit(TXDONE_FALLBACK, &txdesc.flags); |
1003 | txdesc.retry = mcs - min(mcs, real_mcs); | 1012 | |
1004 | 1013 | ||
1005 | rt2x00lib_txdone(entry, &txdesc); | 1014 | rt2x00lib_txdone(entry, &txdesc); |
1006 | } | 1015 | } |
1007 | } | 1016 | } |
1008 | 1017 | ||
1018 | static void rt2800pci_wakeup(struct rt2x00_dev *rt2x00dev) | ||
1019 | { | ||
1020 | struct ieee80211_conf conf = { .flags = 0 }; | ||
1021 | struct rt2x00lib_conf libconf = { .conf = &conf }; | ||
1022 | |||
1023 | rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); | ||
1024 | } | ||
1025 | |||
1009 | static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) | 1026 | static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) |
1010 | { | 1027 | { |
1011 | struct rt2x00_dev *rt2x00dev = dev_instance; | 1028 | struct rt2x00_dev *rt2x00dev = dev_instance; |
@@ -1030,6 +1047,9 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) | |||
1030 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) | 1047 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) |
1031 | rt2800pci_txdone(rt2x00dev); | 1048 | rt2800pci_txdone(rt2x00dev); |
1032 | 1049 | ||
1050 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP)) | ||
1051 | rt2800pci_wakeup(rt2x00dev); | ||
1052 | |||
1033 | return IRQ_HANDLED; | 1053 | return IRQ_HANDLED; |
1034 | } | 1054 | } |
1035 | 1055 | ||
@@ -1184,6 +1204,7 @@ static const struct rt2x00_ops rt2800pci_ops = { | |||
1184 | /* | 1204 | /* |
1185 | * RT2800pci module information. | 1205 | * RT2800pci module information. |
1186 | */ | 1206 | */ |
1207 | #ifdef CONFIG_RT2800PCI_PCI | ||
1187 | static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { | 1208 | static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { |
1188 | { PCI_DEVICE(0x1814, 0x0601), PCI_DEVICE_DATA(&rt2800pci_ops) }, | 1209 | { PCI_DEVICE(0x1814, 0x0601), PCI_DEVICE_DATA(&rt2800pci_ops) }, |
1189 | { PCI_DEVICE(0x1814, 0x0681), PCI_DEVICE_DATA(&rt2800pci_ops) }, | 1210 | { PCI_DEVICE(0x1814, 0x0681), PCI_DEVICE_DATA(&rt2800pci_ops) }, |
@@ -1208,9 +1229,11 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { | |||
1208 | { PCI_DEVICE(0x1814, 0x3062), PCI_DEVICE_DATA(&rt2800pci_ops) }, | 1229 | { PCI_DEVICE(0x1814, 0x3062), PCI_DEVICE_DATA(&rt2800pci_ops) }, |
1209 | { PCI_DEVICE(0x1814, 0x3562), PCI_DEVICE_DATA(&rt2800pci_ops) }, | 1230 | { PCI_DEVICE(0x1814, 0x3562), PCI_DEVICE_DATA(&rt2800pci_ops) }, |
1210 | { PCI_DEVICE(0x1814, 0x3592), PCI_DEVICE_DATA(&rt2800pci_ops) }, | 1231 | { PCI_DEVICE(0x1814, 0x3592), PCI_DEVICE_DATA(&rt2800pci_ops) }, |
1232 | { PCI_DEVICE(0x1814, 0x3593), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
1211 | #endif | 1233 | #endif |
1212 | { 0, } | 1234 | { 0, } |
1213 | }; | 1235 | }; |
1236 | #endif /* CONFIG_RT2800PCI_PCI */ | ||
1214 | 1237 | ||
1215 | MODULE_AUTHOR(DRV_PROJECT); | 1238 | MODULE_AUTHOR(DRV_PROJECT); |
1216 | MODULE_VERSION(DRV_VERSION); | 1239 | MODULE_VERSION(DRV_VERSION); |
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 5e4ee2023fcf..39877880869a 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c | |||
@@ -905,8 +905,13 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
905 | { USB_DEVICE(0x07b8, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, | 905 | { USB_DEVICE(0x07b8, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, |
906 | /* AirTies */ | 906 | /* AirTies */ |
907 | { USB_DEVICE(0x1eda, 0x2310), USB_DEVICE_DATA(&rt2800usb_ops) }, | 907 | { USB_DEVICE(0x1eda, 0x2310), USB_DEVICE_DATA(&rt2800usb_ops) }, |
908 | /* ASUS */ | ||
909 | { USB_DEVICE(0x0b05, 0x1784), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
908 | /* AzureWave */ | 910 | /* AzureWave */ |
909 | { USB_DEVICE(0x13d3, 0x3273), USB_DEVICE_DATA(&rt2800usb_ops) }, | 911 | { USB_DEVICE(0x13d3, 0x3273), USB_DEVICE_DATA(&rt2800usb_ops) }, |
912 | { USB_DEVICE(0x13d3, 0x3305), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
913 | { USB_DEVICE(0x13d3, 0x3307), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
914 | { USB_DEVICE(0x13d3, 0x3321), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
910 | /* Conceptronic */ | 915 | /* Conceptronic */ |
911 | { USB_DEVICE(0x14b2, 0x3c12), USB_DEVICE_DATA(&rt2800usb_ops) }, | 916 | { USB_DEVICE(0x14b2, 0x3c12), USB_DEVICE_DATA(&rt2800usb_ops) }, |
912 | /* Corega */ | 917 | /* Corega */ |
@@ -916,20 +921,46 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
916 | { USB_DEVICE(0x07d1, 0x3c0d), USB_DEVICE_DATA(&rt2800usb_ops) }, | 921 | { USB_DEVICE(0x07d1, 0x3c0d), USB_DEVICE_DATA(&rt2800usb_ops) }, |
917 | { USB_DEVICE(0x07d1, 0x3c0e), USB_DEVICE_DATA(&rt2800usb_ops) }, | 922 | { USB_DEVICE(0x07d1, 0x3c0e), USB_DEVICE_DATA(&rt2800usb_ops) }, |
918 | { USB_DEVICE(0x07d1, 0x3c0f), USB_DEVICE_DATA(&rt2800usb_ops) }, | 923 | { USB_DEVICE(0x07d1, 0x3c0f), USB_DEVICE_DATA(&rt2800usb_ops) }, |
924 | { USB_DEVICE(0x07d1, 0x3c16), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
925 | /* Draytek */ | ||
926 | { USB_DEVICE(0x07fa, 0x7712), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
919 | /* Edimax */ | 927 | /* Edimax */ |
920 | { USB_DEVICE(0x7392, 0x7711), USB_DEVICE_DATA(&rt2800usb_ops) }, | 928 | { USB_DEVICE(0x7392, 0x7711), USB_DEVICE_DATA(&rt2800usb_ops) }, |
921 | /* Encore */ | 929 | /* Encore */ |
922 | { USB_DEVICE(0x203d, 0x1480), USB_DEVICE_DATA(&rt2800usb_ops) }, | 930 | { USB_DEVICE(0x203d, 0x1480), USB_DEVICE_DATA(&rt2800usb_ops) }, |
931 | { USB_DEVICE(0x203d, 0x14a9), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
923 | /* EnGenius */ | 932 | /* EnGenius */ |
924 | { USB_DEVICE(0x1740, 0x9703), USB_DEVICE_DATA(&rt2800usb_ops) }, | 933 | { USB_DEVICE(0x1740, 0x9703), USB_DEVICE_DATA(&rt2800usb_ops) }, |
925 | { USB_DEVICE(0x1740, 0x9705), USB_DEVICE_DATA(&rt2800usb_ops) }, | 934 | { USB_DEVICE(0x1740, 0x9705), USB_DEVICE_DATA(&rt2800usb_ops) }, |
926 | { USB_DEVICE(0x1740, 0x9706), USB_DEVICE_DATA(&rt2800usb_ops) }, | 935 | { USB_DEVICE(0x1740, 0x9706), USB_DEVICE_DATA(&rt2800usb_ops) }, |
936 | { USB_DEVICE(0x1740, 0x9707), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
937 | { USB_DEVICE(0x1740, 0x9708), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
938 | { USB_DEVICE(0x1740, 0x9709), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
927 | /* Gigabyte */ | 939 | /* Gigabyte */ |
928 | { USB_DEVICE(0x1044, 0x800d), USB_DEVICE_DATA(&rt2800usb_ops) }, | 940 | { USB_DEVICE(0x1044, 0x800d), USB_DEVICE_DATA(&rt2800usb_ops) }, |
929 | /* I-O DATA */ | 941 | /* I-O DATA */ |
930 | { USB_DEVICE(0x04bb, 0x0945), USB_DEVICE_DATA(&rt2800usb_ops) }, | 942 | { USB_DEVICE(0x04bb, 0x0945), USB_DEVICE_DATA(&rt2800usb_ops) }, |
943 | { USB_DEVICE(0x04bb, 0x0947), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
944 | { USB_DEVICE(0x04bb, 0x0948), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
945 | /* Logitec */ | ||
946 | { USB_DEVICE(0x0789, 0x0166), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
931 | /* MSI */ | 947 | /* MSI */ |
932 | { USB_DEVICE(0x0db0, 0x3820), USB_DEVICE_DATA(&rt2800usb_ops) }, | 948 | { USB_DEVICE(0x0db0, 0x3820), USB_DEVICE_DATA(&rt2800usb_ops) }, |
949 | { USB_DEVICE(0x0db0, 0x3821), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
950 | { USB_DEVICE(0x0db0, 0x3822), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
951 | { USB_DEVICE(0x0db0, 0x3870), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
952 | { USB_DEVICE(0x0db0, 0x3871), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
953 | { USB_DEVICE(0x0db0, 0x821a), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
954 | { USB_DEVICE(0x0db0, 0x822a), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
955 | { USB_DEVICE(0x0db0, 0x822b), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
956 | { USB_DEVICE(0x0db0, 0x822c), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
957 | { USB_DEVICE(0x0db0, 0x870a), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
958 | { USB_DEVICE(0x0db0, 0x871a), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
959 | { USB_DEVICE(0x0db0, 0x871b), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
960 | { USB_DEVICE(0x0db0, 0x871c), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
961 | { USB_DEVICE(0x0db0, 0x899a), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
962 | /* Para */ | ||
963 | { USB_DEVICE(0x20b8, 0x8888), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
933 | /* Pegatron */ | 964 | /* Pegatron */ |
934 | { USB_DEVICE(0x1d4d, 0x000c), USB_DEVICE_DATA(&rt2800usb_ops) }, | 965 | { USB_DEVICE(0x1d4d, 0x000c), USB_DEVICE_DATA(&rt2800usb_ops) }, |
935 | { USB_DEVICE(0x1d4d, 0x000e), USB_DEVICE_DATA(&rt2800usb_ops) }, | 966 | { USB_DEVICE(0x1d4d, 0x000e), USB_DEVICE_DATA(&rt2800usb_ops) }, |
@@ -945,8 +976,13 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
945 | /* Sitecom */ | 976 | /* Sitecom */ |
946 | { USB_DEVICE(0x0df6, 0x003e), USB_DEVICE_DATA(&rt2800usb_ops) }, | 977 | { USB_DEVICE(0x0df6, 0x003e), USB_DEVICE_DATA(&rt2800usb_ops) }, |
947 | { USB_DEVICE(0x0df6, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) }, | 978 | { USB_DEVICE(0x0df6, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) }, |
979 | { USB_DEVICE(0x0df6, 0x0047), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
980 | { USB_DEVICE(0x0df6, 0x0048), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
948 | /* SMC */ | 981 | /* SMC */ |
949 | { USB_DEVICE(0x083a, 0x7511), USB_DEVICE_DATA(&rt2800usb_ops) }, | 982 | { USB_DEVICE(0x083a, 0x7511), USB_DEVICE_DATA(&rt2800usb_ops) }, |
983 | { USB_DEVICE(0x083a, 0xa701), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
984 | { USB_DEVICE(0x083a, 0xa702), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
985 | { USB_DEVICE(0x083a, 0xa703), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
950 | /* Zinwell */ | 986 | /* Zinwell */ |
951 | { USB_DEVICE(0x5a57, 0x0283), USB_DEVICE_DATA(&rt2800usb_ops) }, | 987 | { USB_DEVICE(0x5a57, 0x0283), USB_DEVICE_DATA(&rt2800usb_ops) }, |
952 | { USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) }, | 988 | { USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) }, |
@@ -985,18 +1021,14 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
985 | /* Amigo */ | 1021 | /* Amigo */ |
986 | { USB_DEVICE(0x0e0b, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1022 | { USB_DEVICE(0x0e0b, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) }, |
987 | { USB_DEVICE(0x0e0b, 0x9041), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1023 | { USB_DEVICE(0x0e0b, 0x9041), USB_DEVICE_DATA(&rt2800usb_ops) }, |
988 | /* Askey */ | ||
989 | { USB_DEVICE(0x0930, 0x0a07), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
990 | /* ASUS */ | 1024 | /* ASUS */ |
991 | { USB_DEVICE(0x0b05, 0x1760), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1025 | { USB_DEVICE(0x0b05, 0x1760), USB_DEVICE_DATA(&rt2800usb_ops) }, |
992 | { USB_DEVICE(0x0b05, 0x1761), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1026 | { USB_DEVICE(0x0b05, 0x1761), USB_DEVICE_DATA(&rt2800usb_ops) }, |
993 | { USB_DEVICE(0x0b05, 0x1784), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
994 | { USB_DEVICE(0x0b05, 0x1790), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1027 | { USB_DEVICE(0x0b05, 0x1790), USB_DEVICE_DATA(&rt2800usb_ops) }, |
995 | { USB_DEVICE(0x1761, 0x0b05), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1028 | { USB_DEVICE(0x1761, 0x0b05), USB_DEVICE_DATA(&rt2800usb_ops) }, |
996 | /* AzureWave */ | 1029 | /* AzureWave */ |
997 | { USB_DEVICE(0x13d3, 0x3262), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1030 | { USB_DEVICE(0x13d3, 0x3262), USB_DEVICE_DATA(&rt2800usb_ops) }, |
998 | { USB_DEVICE(0x13d3, 0x3284), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1031 | { USB_DEVICE(0x13d3, 0x3284), USB_DEVICE_DATA(&rt2800usb_ops) }, |
999 | { USB_DEVICE(0x13d3, 0x3305), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1000 | /* Belkin */ | 1032 | /* Belkin */ |
1001 | { USB_DEVICE(0x050d, 0x825a), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1033 | { USB_DEVICE(0x050d, 0x825a), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1002 | /* Buffalo */ | 1034 | /* Buffalo */ |
@@ -1015,14 +1047,8 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
1015 | { USB_DEVICE(0x07d1, 0x3c0b), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1047 | { USB_DEVICE(0x07d1, 0x3c0b), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1016 | { USB_DEVICE(0x07d1, 0x3c13), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1048 | { USB_DEVICE(0x07d1, 0x3c13), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1017 | { USB_DEVICE(0x07d1, 0x3c15), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1049 | { USB_DEVICE(0x07d1, 0x3c15), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1018 | { USB_DEVICE(0x07d1, 0x3c16), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1019 | /* Encore */ | 1050 | /* Encore */ |
1020 | { USB_DEVICE(0x203d, 0x14a1), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1051 | { USB_DEVICE(0x203d, 0x14a1), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1021 | { USB_DEVICE(0x203d, 0x14a9), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1022 | /* EnGenius */ | ||
1023 | { USB_DEVICE(0x1740, 0x9707), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1024 | { USB_DEVICE(0x1740, 0x9708), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1025 | { USB_DEVICE(0x1740, 0x9709), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1026 | /* Gemtek */ | 1052 | /* Gemtek */ |
1027 | { USB_DEVICE(0x15a9, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1053 | { USB_DEVICE(0x15a9, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1028 | /* Gigabyte */ | 1054 | /* Gigabyte */ |
@@ -1030,9 +1056,6 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
1030 | /* Hawking */ | 1056 | /* Hawking */ |
1031 | { USB_DEVICE(0x0e66, 0x0009), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1057 | { USB_DEVICE(0x0e66, 0x0009), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1032 | { USB_DEVICE(0x0e66, 0x000b), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1058 | { USB_DEVICE(0x0e66, 0x000b), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1033 | /* I-O DATA */ | ||
1034 | { USB_DEVICE(0x04bb, 0x0947), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1035 | { USB_DEVICE(0x04bb, 0x0948), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1036 | /* LevelOne */ | 1059 | /* LevelOne */ |
1037 | { USB_DEVICE(0x1740, 0x0605), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1060 | { USB_DEVICE(0x1740, 0x0605), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1038 | { USB_DEVICE(0x1740, 0x0615), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1061 | { USB_DEVICE(0x1740, 0x0615), USB_DEVICE_DATA(&rt2800usb_ops) }, |
@@ -1042,20 +1065,8 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
1042 | { USB_DEVICE(0x1737, 0x0079), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1065 | { USB_DEVICE(0x1737, 0x0079), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1043 | /* Motorola */ | 1066 | /* Motorola */ |
1044 | { USB_DEVICE(0x100d, 0x9032), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1067 | { USB_DEVICE(0x100d, 0x9032), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1045 | /* MSI */ | ||
1046 | { USB_DEVICE(0x0db0, 0x3821), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1047 | { USB_DEVICE(0x0db0, 0x3822), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1048 | { USB_DEVICE(0x0db0, 0x3870), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1049 | { USB_DEVICE(0x0db0, 0x3871), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1050 | { USB_DEVICE(0x0db0, 0x821a), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1051 | { USB_DEVICE(0x0db0, 0x822a), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1052 | { USB_DEVICE(0x0db0, 0x870a), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1053 | { USB_DEVICE(0x0db0, 0x871a), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1054 | { USB_DEVICE(0x0db0, 0x899a), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1055 | /* Ovislink */ | 1068 | /* Ovislink */ |
1056 | { USB_DEVICE(0x1b75, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1069 | { USB_DEVICE(0x1b75, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1057 | /* Para */ | ||
1058 | { USB_DEVICE(0x20b8, 0x8888), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1059 | /* Pegatron */ | 1070 | /* Pegatron */ |
1060 | { USB_DEVICE(0x05a6, 0x0101), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1071 | { USB_DEVICE(0x05a6, 0x0101), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1061 | { USB_DEVICE(0x1d4d, 0x0002), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1072 | { USB_DEVICE(0x1d4d, 0x0002), USB_DEVICE_DATA(&rt2800usb_ops) }, |
@@ -1069,14 +1080,10 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
1069 | { USB_DEVICE(0x0df6, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1080 | { USB_DEVICE(0x0df6, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1070 | { USB_DEVICE(0x0df6, 0x003d), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1081 | { USB_DEVICE(0x0df6, 0x003d), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1071 | { USB_DEVICE(0x0df6, 0x0040), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1082 | { USB_DEVICE(0x0df6, 0x0040), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1072 | { USB_DEVICE(0x0df6, 0x0047), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1073 | { USB_DEVICE(0x0df6, 0x0048), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1074 | { USB_DEVICE(0x0df6, 0x004a), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1083 | { USB_DEVICE(0x0df6, 0x004a), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1075 | { USB_DEVICE(0x0df6, 0x004d), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1084 | { USB_DEVICE(0x0df6, 0x004d), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1076 | /* SMC */ | 1085 | /* SMC */ |
1077 | { USB_DEVICE(0x083a, 0xa512), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1086 | { USB_DEVICE(0x083a, 0xa512), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1078 | { USB_DEVICE(0x083a, 0xa701), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1079 | { USB_DEVICE(0x083a, 0xa702), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1080 | { USB_DEVICE(0x083a, 0xc522), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1087 | { USB_DEVICE(0x083a, 0xc522), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1081 | { USB_DEVICE(0x083a, 0xd522), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1088 | { USB_DEVICE(0x083a, 0xd522), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1082 | /* Sweex */ | 1089 | /* Sweex */ |
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index e2da928dd9f0..ac69dbe5719b 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
@@ -2117,6 +2117,14 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) | |||
2117 | } | 2117 | } |
2118 | } | 2118 | } |
2119 | 2119 | ||
2120 | static void rt61pci_wakeup(struct rt2x00_dev *rt2x00dev) | ||
2121 | { | ||
2122 | struct ieee80211_conf conf = { .flags = 0 }; | ||
2123 | struct rt2x00lib_conf libconf = { .conf = &conf }; | ||
2124 | |||
2125 | rt61pci_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); | ||
2126 | } | ||
2127 | |||
2120 | static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance) | 2128 | static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance) |
2121 | { | 2129 | { |
2122 | struct rt2x00_dev *rt2x00dev = dev_instance; | 2130 | struct rt2x00_dev *rt2x00dev = dev_instance; |
@@ -2164,6 +2172,12 @@ static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance) | |||
2164 | rt2x00pci_register_write(rt2x00dev, | 2172 | rt2x00pci_register_write(rt2x00dev, |
2165 | M2H_CMD_DONE_CSR, 0xffffffff); | 2173 | M2H_CMD_DONE_CSR, 0xffffffff); |
2166 | 2174 | ||
2175 | /* | ||
2176 | * 4 - MCU Autowakeup interrupt. | ||
2177 | */ | ||
2178 | if (rt2x00_get_field32(reg_mcu, MCU_INT_SOURCE_CSR_TWAKEUP)) | ||
2179 | rt61pci_wakeup(rt2x00dev); | ||
2180 | |||
2167 | return IRQ_HANDLED; | 2181 | return IRQ_HANDLED; |
2168 | } | 2182 | } |
2169 | 2183 | ||
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 47f3e4a26d77..7ebe14b64fe8 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -860,15 +860,15 @@ static void rt73usb_config_ps(struct rt2x00_dev *rt2x00dev, | |||
860 | rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, | 860 | rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, |
861 | USB_MODE_SLEEP, REGISTER_TIMEOUT); | 861 | USB_MODE_SLEEP, REGISTER_TIMEOUT); |
862 | } else { | 862 | } else { |
863 | rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, | ||
864 | USB_MODE_WAKEUP, REGISTER_TIMEOUT); | ||
865 | |||
866 | rt2x00usb_register_read(rt2x00dev, MAC_CSR11, ®); | 863 | rt2x00usb_register_read(rt2x00dev, MAC_CSR11, ®); |
867 | rt2x00_set_field32(®, MAC_CSR11_DELAY_AFTER_TBCN, 0); | 864 | rt2x00_set_field32(®, MAC_CSR11_DELAY_AFTER_TBCN, 0); |
868 | rt2x00_set_field32(®, MAC_CSR11_TBCN_BEFORE_WAKEUP, 0); | 865 | rt2x00_set_field32(®, MAC_CSR11_TBCN_BEFORE_WAKEUP, 0); |
869 | rt2x00_set_field32(®, MAC_CSR11_AUTOWAKE, 0); | 866 | rt2x00_set_field32(®, MAC_CSR11_AUTOWAKE, 0); |
870 | rt2x00_set_field32(®, MAC_CSR11_WAKEUP_LATENCY, 0); | 867 | rt2x00_set_field32(®, MAC_CSR11_WAKEUP_LATENCY, 0); |
871 | rt2x00usb_register_write(rt2x00dev, MAC_CSR11, reg); | 868 | rt2x00usb_register_write(rt2x00dev, MAC_CSR11, reg); |
869 | |||
870 | rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, | ||
871 | USB_MODE_WAKEUP, REGISTER_TIMEOUT); | ||
872 | } | 872 | } |
873 | } | 873 | } |
874 | 874 | ||
diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig index 785e0244e305..337fc7bec5a5 100644 --- a/drivers/net/wireless/wl12xx/Kconfig +++ b/drivers/net/wireless/wl12xx/Kconfig | |||
@@ -51,3 +51,27 @@ config WL1271 | |||
51 | 51 | ||
52 | If you choose to build a module, it'll be called wl1271. Say N if | 52 | If you choose to build a module, it'll be called wl1271. Say N if |
53 | unsure. | 53 | unsure. |
54 | |||
55 | config WL1271_SPI | ||
56 | tristate "TI wl1271 SPI support" | ||
57 | depends on WL1271 && SPI_MASTER | ||
58 | ---help--- | ||
59 | This module adds support for the SPI interface of adapters using | ||
60 | TI wl1271 chipset. Select this if your platform is using | ||
61 | the SPI bus. | ||
62 | |||
63 | If you choose to build a module, it'll be called wl1251_spi. | ||
64 | Say N if unsure. | ||
65 | |||
66 | config WL1271_SDIO | ||
67 | tristate "TI wl1271 SDIO support" | ||
68 | depends on WL1271 && MMC && ARM | ||
69 | ---help--- | ||
70 | This module adds support for the SDIO interface of adapters using | ||
71 | TI wl1271 chipset. Select this if your platform is using | ||
72 | the SDIO bus. | ||
73 | |||
74 | If you choose to build a module, it'll be called | ||
75 | wl1271_sdio. Say N if unsure. | ||
76 | |||
77 | |||
diff --git a/drivers/net/wireless/wl12xx/Makefile b/drivers/net/wireless/wl12xx/Makefile index f47ec94c16dc..27ddd2be0a91 100644 --- a/drivers/net/wireless/wl12xx/Makefile +++ b/drivers/net/wireless/wl12xx/Makefile | |||
@@ -7,10 +7,12 @@ obj-$(CONFIG_WL1251) += wl1251.o | |||
7 | obj-$(CONFIG_WL1251_SPI) += wl1251_spi.o | 7 | obj-$(CONFIG_WL1251_SPI) += wl1251_spi.o |
8 | obj-$(CONFIG_WL1251_SDIO) += wl1251_sdio.o | 8 | obj-$(CONFIG_WL1251_SDIO) += wl1251_sdio.o |
9 | 9 | ||
10 | wl1271-objs = wl1271_main.o wl1271_spi.o wl1271_cmd.o \ | 10 | wl1271-objs = wl1271_main.o wl1271_cmd.o wl1271_io.o \ |
11 | wl1271_event.o wl1271_tx.o wl1271_rx.o \ | 11 | wl1271_event.o wl1271_tx.o wl1271_rx.o \ |
12 | wl1271_ps.o wl1271_acx.o wl1271_boot.o \ | 12 | wl1271_ps.o wl1271_acx.o wl1271_boot.o \ |
13 | wl1271_init.o wl1271_debugfs.o wl1271_io.o | 13 | wl1271_init.o wl1271_debugfs.o |
14 | 14 | ||
15 | wl1271-$(CONFIG_NL80211_TESTMODE) += wl1271_testmode.o | 15 | wl1271-$(CONFIG_NL80211_TESTMODE) += wl1271_testmode.o |
16 | obj-$(CONFIG_WL1271) += wl1271.o | 16 | obj-$(CONFIG_WL1271) += wl1271.o |
17 | obj-$(CONFIG_WL1271_SPI) += wl1271_spi.o | ||
18 | obj-$(CONFIG_WL1271_SDIO) += wl1271_sdio.o | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251.h b/drivers/net/wireless/wl12xx/wl1251.h index 37c61c19cae5..4f5f02a26e62 100644 --- a/drivers/net/wireless/wl12xx/wl1251.h +++ b/drivers/net/wireless/wl12xx/wl1251.h | |||
@@ -256,6 +256,8 @@ struct wl1251_debugfs { | |||
256 | struct wl1251_if_operations { | 256 | struct wl1251_if_operations { |
257 | void (*read)(struct wl1251 *wl, int addr, void *buf, size_t len); | 257 | void (*read)(struct wl1251 *wl, int addr, void *buf, size_t len); |
258 | void (*write)(struct wl1251 *wl, int addr, void *buf, size_t len); | 258 | void (*write)(struct wl1251 *wl, int addr, void *buf, size_t len); |
259 | void (*read_elp)(struct wl1251 *wl, int addr, u32 *val); | ||
260 | void (*write_elp)(struct wl1251 *wl, int addr, u32 val); | ||
259 | void (*reset)(struct wl1251 *wl); | 261 | void (*reset)(struct wl1251 *wl); |
260 | void (*enable_irq)(struct wl1251 *wl); | 262 | void (*enable_irq)(struct wl1251 *wl); |
261 | void (*disable_irq)(struct wl1251 *wl); | 263 | void (*disable_irq)(struct wl1251 *wl); |
diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.c b/drivers/net/wireless/wl12xx/wl1251_boot.c index 28a808674080..acb334184d70 100644 --- a/drivers/net/wireless/wl12xx/wl1251_boot.c +++ b/drivers/net/wireless/wl12xx/wl1251_boot.c | |||
@@ -496,7 +496,8 @@ int wl1251_boot(struct wl1251 *wl) | |||
496 | /* 2. start processing NVS file */ | 496 | /* 2. start processing NVS file */ |
497 | if (wl->use_eeprom) { | 497 | if (wl->use_eeprom) { |
498 | wl1251_reg_write32(wl, ACX_REG_EE_START, START_EEPROM_MGR); | 498 | wl1251_reg_write32(wl, ACX_REG_EE_START, START_EEPROM_MGR); |
499 | msleep(4000); | 499 | /* Wait for EEPROM NVS burst read to complete */ |
500 | msleep(40); | ||
500 | wl1251_reg_write32(wl, ACX_EEPROMLESS_IND_REG, USE_EEPROM); | 501 | wl1251_reg_write32(wl, ACX_EEPROMLESS_IND_REG, USE_EEPROM); |
501 | } else { | 502 | } else { |
502 | ret = wl1251_boot_upload_nvs(wl); | 503 | ret = wl1251_boot_upload_nvs(wl); |
diff --git a/drivers/net/wireless/wl12xx/wl1251_io.h b/drivers/net/wireless/wl12xx/wl1251_io.h index b89d2ac62efb..c545e9d5f512 100644 --- a/drivers/net/wireless/wl12xx/wl1251_io.h +++ b/drivers/net/wireless/wl12xx/wl1251_io.h | |||
@@ -48,6 +48,26 @@ static inline void wl1251_write32(struct wl1251 *wl, int addr, u32 val) | |||
48 | wl->if_ops->write(wl, addr, &val, sizeof(u32)); | 48 | wl->if_ops->write(wl, addr, &val, sizeof(u32)); |
49 | } | 49 | } |
50 | 50 | ||
51 | static inline u32 wl1251_read_elp(struct wl1251 *wl, int addr) | ||
52 | { | ||
53 | u32 response; | ||
54 | |||
55 | if (wl->if_ops->read_elp) | ||
56 | wl->if_ops->read_elp(wl, addr, &response); | ||
57 | else | ||
58 | wl->if_ops->read(wl, addr, &response, sizeof(u32)); | ||
59 | |||
60 | return response; | ||
61 | } | ||
62 | |||
63 | static inline void wl1251_write_elp(struct wl1251 *wl, int addr, u32 val) | ||
64 | { | ||
65 | if (wl->if_ops->write_elp) | ||
66 | wl->if_ops->write_elp(wl, addr, val); | ||
67 | else | ||
68 | wl->if_ops->write(wl, addr, &val, sizeof(u32)); | ||
69 | } | ||
70 | |||
51 | /* Memory target IO, address is translated to partition 0 */ | 71 | /* Memory target IO, address is translated to partition 0 */ |
52 | void wl1251_mem_read(struct wl1251 *wl, int addr, void *buf, size_t len); | 72 | void wl1251_mem_read(struct wl1251 *wl, int addr, void *buf, size_t len); |
53 | void wl1251_mem_write(struct wl1251 *wl, int addr, void *buf, size_t len); | 73 | void wl1251_mem_write(struct wl1251 *wl, int addr, void *buf, size_t len); |
diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 24ae6a360ac8..0155653b7105 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c | |||
@@ -146,8 +146,8 @@ static void wl1251_fw_wakeup(struct wl1251 *wl) | |||
146 | u32 elp_reg; | 146 | u32 elp_reg; |
147 | 147 | ||
148 | elp_reg = ELPCTRL_WAKE_UP; | 148 | elp_reg = ELPCTRL_WAKE_UP; |
149 | wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg); | 149 | wl1251_write_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg); |
150 | elp_reg = wl1251_read32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR); | 150 | elp_reg = wl1251_read_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR); |
151 | 151 | ||
152 | if (!(elp_reg & ELPCTRL_WLAN_READY)) | 152 | if (!(elp_reg & ELPCTRL_WLAN_READY)) |
153 | wl1251_warning("WLAN not ready"); | 153 | wl1251_warning("WLAN not ready"); |
diff --git a/drivers/net/wireless/wl12xx/wl1251_ps.c b/drivers/net/wireless/wl12xx/wl1251_ps.c index 851dfb65e474..b55cb2bd459a 100644 --- a/drivers/net/wireless/wl12xx/wl1251_ps.c +++ b/drivers/net/wireless/wl12xx/wl1251_ps.c | |||
@@ -45,7 +45,7 @@ void wl1251_elp_work(struct work_struct *work) | |||
45 | goto out; | 45 | goto out; |
46 | 46 | ||
47 | wl1251_debug(DEBUG_PSM, "chip to elp"); | 47 | wl1251_debug(DEBUG_PSM, "chip to elp"); |
48 | wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP); | 48 | wl1251_write_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP); |
49 | wl->elp = true; | 49 | wl->elp = true; |
50 | 50 | ||
51 | out: | 51 | out: |
@@ -79,9 +79,9 @@ int wl1251_ps_elp_wakeup(struct wl1251 *wl) | |||
79 | start = jiffies; | 79 | start = jiffies; |
80 | timeout = jiffies + msecs_to_jiffies(WL1251_WAKEUP_TIMEOUT); | 80 | timeout = jiffies + msecs_to_jiffies(WL1251_WAKEUP_TIMEOUT); |
81 | 81 | ||
82 | wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP); | 82 | wl1251_write_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP); |
83 | 83 | ||
84 | elp_reg = wl1251_read32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR); | 84 | elp_reg = wl1251_read_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR); |
85 | 85 | ||
86 | /* | 86 | /* |
87 | * FIXME: we should wait for irq from chip but, as a temporary | 87 | * FIXME: we should wait for irq from chip but, as a temporary |
@@ -93,7 +93,7 @@ int wl1251_ps_elp_wakeup(struct wl1251 *wl) | |||
93 | return -ETIMEDOUT; | 93 | return -ETIMEDOUT; |
94 | } | 94 | } |
95 | msleep(1); | 95 | msleep(1); |
96 | elp_reg = wl1251_read32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR); | 96 | elp_reg = wl1251_read_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR); |
97 | } | 97 | } |
98 | 98 | ||
99 | wl1251_debug(DEBUG_PSM, "wakeup time: %u ms", | 99 | wl1251_debug(DEBUG_PSM, "wakeup time: %u ms", |
diff --git a/drivers/net/wireless/wl12xx/wl1251_sdio.c b/drivers/net/wireless/wl12xx/wl1251_sdio.c index 9423f22bdced..2051ef06e9ec 100644 --- a/drivers/net/wireless/wl12xx/wl1251_sdio.c +++ b/drivers/net/wireless/wl12xx/wl1251_sdio.c | |||
@@ -20,20 +20,11 @@ | |||
20 | * Copyright (C) 2009 Bob Copeland (me@bobcopeland.com) | 20 | * Copyright (C) 2009 Bob Copeland (me@bobcopeland.com) |
21 | */ | 21 | */ |
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/crc7.h> | ||
24 | #include <linux/mod_devicetable.h> | 23 | #include <linux/mod_devicetable.h> |
25 | #include <linux/irq.h> | ||
26 | #include <linux/mmc/sdio_func.h> | 24 | #include <linux/mmc/sdio_func.h> |
27 | #include <linux/mmc/sdio_ids.h> | 25 | #include <linux/mmc/sdio_ids.h> |
28 | #include <linux/platform_device.h> | ||
29 | 26 | ||
30 | #include "wl1251.h" | 27 | #include "wl1251.h" |
31 | #include "wl12xx_80211.h" | ||
32 | #include "wl1251_reg.h" | ||
33 | #include "wl1251_ps.h" | ||
34 | #include "wl1251_io.h" | ||
35 | #include "wl1251_tx.h" | ||
36 | #include "wl1251_debugfs.h" | ||
37 | 28 | ||
38 | #ifndef SDIO_VENDOR_ID_TI | 29 | #ifndef SDIO_VENDOR_ID_TI |
39 | #define SDIO_VENDOR_ID_TI 0x104c | 30 | #define SDIO_VENDOR_ID_TI 0x104c |
@@ -65,7 +56,8 @@ static const struct sdio_device_id wl1251_devices[] = { | |||
65 | MODULE_DEVICE_TABLE(sdio, wl1251_devices); | 56 | MODULE_DEVICE_TABLE(sdio, wl1251_devices); |
66 | 57 | ||
67 | 58 | ||
68 | void wl1251_sdio_read(struct wl1251 *wl, int addr, void *buf, size_t len) | 59 | static void wl1251_sdio_read(struct wl1251 *wl, int addr, |
60 | void *buf, size_t len) | ||
69 | { | 61 | { |
70 | int ret; | 62 | int ret; |
71 | struct sdio_func *func = wl_to_func(wl); | 63 | struct sdio_func *func = wl_to_func(wl); |
@@ -77,7 +69,8 @@ void wl1251_sdio_read(struct wl1251 *wl, int addr, void *buf, size_t len) | |||
77 | sdio_release_host(func); | 69 | sdio_release_host(func); |
78 | } | 70 | } |
79 | 71 | ||
80 | void wl1251_sdio_write(struct wl1251 *wl, int addr, void *buf, size_t len) | 72 | static void wl1251_sdio_write(struct wl1251 *wl, int addr, |
73 | void *buf, size_t len) | ||
81 | { | 74 | { |
82 | int ret; | 75 | int ret; |
83 | struct sdio_func *func = wl_to_func(wl); | 76 | struct sdio_func *func = wl_to_func(wl); |
@@ -89,7 +82,33 @@ void wl1251_sdio_write(struct wl1251 *wl, int addr, void *buf, size_t len) | |||
89 | sdio_release_host(func); | 82 | sdio_release_host(func); |
90 | } | 83 | } |
91 | 84 | ||
92 | void wl1251_sdio_reset(struct wl1251 *wl) | 85 | static void wl1251_sdio_read_elp(struct wl1251 *wl, int addr, u32 *val) |
86 | { | ||
87 | int ret = 0; | ||
88 | struct sdio_func *func = wl_to_func(wl); | ||
89 | |||
90 | sdio_claim_host(func); | ||
91 | *val = sdio_readb(func, addr, &ret); | ||
92 | sdio_release_host(func); | ||
93 | |||
94 | if (ret) | ||
95 | wl1251_error("sdio_readb failed (%d)", ret); | ||
96 | } | ||
97 | |||
98 | static void wl1251_sdio_write_elp(struct wl1251 *wl, int addr, u32 val) | ||
99 | { | ||
100 | int ret = 0; | ||
101 | struct sdio_func *func = wl_to_func(wl); | ||
102 | |||
103 | sdio_claim_host(func); | ||
104 | sdio_writeb(func, val, addr, &ret); | ||
105 | sdio_release_host(func); | ||
106 | |||
107 | if (ret) | ||
108 | wl1251_error("sdio_writeb failed (%d)", ret); | ||
109 | } | ||
110 | |||
111 | static void wl1251_sdio_reset(struct wl1251 *wl) | ||
93 | { | 112 | { |
94 | } | 113 | } |
95 | 114 | ||
@@ -111,19 +130,22 @@ static void wl1251_sdio_disable_irq(struct wl1251 *wl) | |||
111 | sdio_release_host(func); | 130 | sdio_release_host(func); |
112 | } | 131 | } |
113 | 132 | ||
114 | void wl1251_sdio_set_power(bool enable) | 133 | static void wl1251_sdio_set_power(bool enable) |
115 | { | 134 | { |
116 | } | 135 | } |
117 | 136 | ||
118 | struct wl1251_if_operations wl1251_sdio_ops = { | 137 | static const struct wl1251_if_operations wl1251_sdio_ops = { |
119 | .read = wl1251_sdio_read, | 138 | .read = wl1251_sdio_read, |
120 | .write = wl1251_sdio_write, | 139 | .write = wl1251_sdio_write, |
140 | .write_elp = wl1251_sdio_write_elp, | ||
141 | .read_elp = wl1251_sdio_read_elp, | ||
121 | .reset = wl1251_sdio_reset, | 142 | .reset = wl1251_sdio_reset, |
122 | .enable_irq = wl1251_sdio_enable_irq, | 143 | .enable_irq = wl1251_sdio_enable_irq, |
123 | .disable_irq = wl1251_sdio_disable_irq, | 144 | .disable_irq = wl1251_sdio_disable_irq, |
124 | }; | 145 | }; |
125 | 146 | ||
126 | int wl1251_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) | 147 | static int wl1251_sdio_probe(struct sdio_func *func, |
148 | const struct sdio_device_id *id) | ||
127 | { | 149 | { |
128 | int ret; | 150 | int ret; |
129 | struct wl1251 *wl; | 151 | struct wl1251 *wl; |
diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.c b/drivers/net/wireless/wl12xx/wl1251_spi.c index 9cc8c323830f..df2ff8bc8ef4 100644 --- a/drivers/net/wireless/wl12xx/wl1251_spi.c +++ b/drivers/net/wireless/wl12xx/wl1251_spi.c | |||
@@ -309,7 +309,7 @@ static int __devexit wl1251_spi_remove(struct spi_device *spi) | |||
309 | 309 | ||
310 | static struct spi_driver wl1251_spi_driver = { | 310 | static struct spi_driver wl1251_spi_driver = { |
311 | .driver = { | 311 | .driver = { |
312 | .name = "wl1251", | 312 | .name = DRIVER_NAME, |
313 | .bus = &spi_bus_type, | 313 | .bus = &spi_bus_type, |
314 | .owner = THIS_MODULE, | 314 | .owner = THIS_MODULE, |
315 | }, | 315 | }, |
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 97ea5096bc8c..a29969efc861 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h | |||
@@ -53,6 +53,9 @@ enum { | |||
53 | DEBUG_MAC80211 = BIT(11), | 53 | DEBUG_MAC80211 = BIT(11), |
54 | DEBUG_CMD = BIT(12), | 54 | DEBUG_CMD = BIT(12), |
55 | DEBUG_ACX = BIT(13), | 55 | DEBUG_ACX = BIT(13), |
56 | DEBUG_SDIO = BIT(14), | ||
57 | DEBUG_FILTERS = BIT(15), | ||
58 | DEBUG_ADHOC = BIT(16), | ||
56 | DEBUG_ALL = ~0, | 59 | DEBUG_ALL = ~0, |
57 | }; | 60 | }; |
58 | 61 | ||
@@ -110,6 +113,9 @@ enum { | |||
110 | #define WL1271_FW_NAME "wl1271-fw.bin" | 113 | #define WL1271_FW_NAME "wl1271-fw.bin" |
111 | #define WL1271_NVS_NAME "wl1271-nvs.bin" | 114 | #define WL1271_NVS_NAME "wl1271-nvs.bin" |
112 | 115 | ||
116 | #define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff)) | ||
117 | #define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff)) | ||
118 | |||
113 | /* NVS data structure */ | 119 | /* NVS data structure */ |
114 | #define WL1271_NVS_SECTION_SIZE 468 | 120 | #define WL1271_NVS_SECTION_SIZE 468 |
115 | 121 | ||
@@ -142,14 +148,7 @@ struct wl1271_nvs_file { | |||
142 | */ | 148 | */ |
143 | #undef WL1271_80211A_ENABLED | 149 | #undef WL1271_80211A_ENABLED |
144 | 150 | ||
145 | /* | 151 | #define WL1271_BUSY_WORD_CNT 1 |
146 | * FIXME: for the wl1271, a busy word count of 1 here will result in a more | ||
147 | * optimal SPI interface. There is some SPI bug however, causing RXS time outs | ||
148 | * with this mode occasionally on boot, so lets have three for now. A value of | ||
149 | * three should make sure, that the chipset will always be ready, though this | ||
150 | * will impact throughput and latencies slightly. | ||
151 | */ | ||
152 | #define WL1271_BUSY_WORD_CNT 3 | ||
153 | #define WL1271_BUSY_WORD_LEN (WL1271_BUSY_WORD_CNT * sizeof(u32)) | 152 | #define WL1271_BUSY_WORD_LEN (WL1271_BUSY_WORD_CNT * sizeof(u32)) |
154 | 153 | ||
155 | #define WL1271_ELP_HW_STATE_ASLEEP 0 | 154 | #define WL1271_ELP_HW_STATE_ASLEEP 0 |
@@ -334,11 +333,27 @@ struct wl1271_scan { | |||
334 | u8 probe_requests; | 333 | u8 probe_requests; |
335 | }; | 334 | }; |
336 | 335 | ||
336 | struct wl1271_if_operations { | ||
337 | void (*read)(struct wl1271 *wl, int addr, void *buf, size_t len, | ||
338 | bool fixed); | ||
339 | void (*write)(struct wl1271 *wl, int addr, void *buf, size_t len, | ||
340 | bool fixed); | ||
341 | void (*reset)(struct wl1271 *wl); | ||
342 | void (*init)(struct wl1271 *wl); | ||
343 | void (*power)(struct wl1271 *wl, bool enable); | ||
344 | struct device* (*dev)(struct wl1271 *wl); | ||
345 | void (*enable_irq)(struct wl1271 *wl); | ||
346 | void (*disable_irq)(struct wl1271 *wl); | ||
347 | }; | ||
348 | |||
337 | struct wl1271 { | 349 | struct wl1271 { |
350 | struct platform_device *plat_dev; | ||
338 | struct ieee80211_hw *hw; | 351 | struct ieee80211_hw *hw; |
339 | bool mac80211_registered; | 352 | bool mac80211_registered; |
340 | 353 | ||
341 | struct spi_device *spi; | 354 | void *if_priv; |
355 | |||
356 | struct wl1271_if_operations *if_ops; | ||
342 | 357 | ||
343 | void (*set_power)(bool enable); | 358 | void (*set_power)(bool enable); |
344 | int irq; | 359 | int irq; |
@@ -357,6 +372,8 @@ struct wl1271 { | |||
357 | #define WL1271_FLAG_IN_ELP (6) | 372 | #define WL1271_FLAG_IN_ELP (6) |
358 | #define WL1271_FLAG_PSM (7) | 373 | #define WL1271_FLAG_PSM (7) |
359 | #define WL1271_FLAG_PSM_REQUESTED (8) | 374 | #define WL1271_FLAG_PSM_REQUESTED (8) |
375 | #define WL1271_FLAG_IRQ_PENDING (9) | ||
376 | #define WL1271_FLAG_IRQ_RUNNING (10) | ||
360 | unsigned long flags; | 377 | unsigned long flags; |
361 | 378 | ||
362 | struct wl1271_partition_set part; | 379 | struct wl1271_partition_set part; |
@@ -373,6 +390,7 @@ struct wl1271 { | |||
373 | u8 bssid[ETH_ALEN]; | 390 | u8 bssid[ETH_ALEN]; |
374 | u8 mac_addr[ETH_ALEN]; | 391 | u8 mac_addr[ETH_ALEN]; |
375 | u8 bss_type; | 392 | u8 bss_type; |
393 | u8 set_bss_type; | ||
376 | u8 ssid[IW_ESSID_MAX_SIZE + 1]; | 394 | u8 ssid[IW_ESSID_MAX_SIZE + 1]; |
377 | u8 ssid_len; | 395 | u8 ssid_len; |
378 | int channel; | 396 | int channel; |
@@ -382,13 +400,13 @@ struct wl1271 { | |||
382 | /* Accounting for allocated / available TX blocks on HW */ | 400 | /* Accounting for allocated / available TX blocks on HW */ |
383 | u32 tx_blocks_freed[NUM_TX_QUEUES]; | 401 | u32 tx_blocks_freed[NUM_TX_QUEUES]; |
384 | u32 tx_blocks_available; | 402 | u32 tx_blocks_available; |
385 | u8 tx_results_count; | 403 | u32 tx_results_count; |
386 | 404 | ||
387 | /* Transmitted TX packets counter for chipset interface */ | 405 | /* Transmitted TX packets counter for chipset interface */ |
388 | int tx_packets_count; | 406 | u32 tx_packets_count; |
389 | 407 | ||
390 | /* Time-offset between host and chipset clocks */ | 408 | /* Time-offset between host and chipset clocks */ |
391 | int time_offset; | 409 | s64 time_offset; |
392 | 410 | ||
393 | /* Session counter for the chipset */ | 411 | /* Session counter for the chipset */ |
394 | int session_counter; | 412 | int session_counter; |
@@ -403,8 +421,7 @@ struct wl1271 { | |||
403 | 421 | ||
404 | /* Security sequence number counters */ | 422 | /* Security sequence number counters */ |
405 | u8 tx_security_last_seq; | 423 | u8 tx_security_last_seq; |
406 | u16 tx_security_seq_16; | 424 | s64 tx_security_seq; |
407 | u32 tx_security_seq_32; | ||
408 | 425 | ||
409 | /* FW Rx counter */ | 426 | /* FW Rx counter */ |
410 | u32 rx_counter; | 427 | u32 rx_counter; |
@@ -430,14 +447,19 @@ struct wl1271 { | |||
430 | /* currently configured rate set */ | 447 | /* currently configured rate set */ |
431 | u32 sta_rate_set; | 448 | u32 sta_rate_set; |
432 | u32 basic_rate_set; | 449 | u32 basic_rate_set; |
450 | u32 basic_rate; | ||
433 | u32 rate_set; | 451 | u32 rate_set; |
434 | 452 | ||
435 | /* The current band */ | 453 | /* The current band */ |
436 | enum ieee80211_band band; | 454 | enum ieee80211_band band; |
437 | 455 | ||
456 | /* Beaconing interval (needed for ad-hoc) */ | ||
457 | u32 beacon_int; | ||
458 | |||
438 | /* Default key (for WEP) */ | 459 | /* Default key (for WEP) */ |
439 | u32 default_key; | 460 | u32 default_key; |
440 | 461 | ||
462 | unsigned int filters; | ||
441 | unsigned int rx_config; | 463 | unsigned int rx_config; |
442 | unsigned int rx_filter; | 464 | unsigned int rx_filter; |
443 | 465 | ||
@@ -465,6 +487,8 @@ struct wl1271 { | |||
465 | /* Current chipset configuration */ | 487 | /* Current chipset configuration */ |
466 | struct conf_drv_settings conf; | 488 | struct conf_drv_settings conf; |
467 | 489 | ||
490 | bool sg_enabled; | ||
491 | |||
468 | struct list_head list; | 492 | struct list_head list; |
469 | }; | 493 | }; |
470 | 494 | ||
@@ -477,7 +501,8 @@ int wl1271_plt_stop(struct wl1271 *wl); | |||
477 | 501 | ||
478 | #define WL1271_DEFAULT_POWER_LEVEL 0 | 502 | #define WL1271_DEFAULT_POWER_LEVEL 0 |
479 | 503 | ||
480 | #define WL1271_TX_QUEUE_MAX_LENGTH 20 | 504 | #define WL1271_TX_QUEUE_LOW_WATERMARK 10 |
505 | #define WL1271_TX_QUEUE_HIGH_WATERMARK 25 | ||
481 | 506 | ||
482 | /* WL1271 needs a 200ms sleep after power on, and a 20ms sleep before power | 507 | /* WL1271 needs a 200ms sleep after power on, and a 20ms sleep before power |
483 | on in case is has been shut down shortly before */ | 508 | on in case is has been shut down shortly before */ |
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c index 60f10dce4800..621c94691e7e 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/drivers/net/wireless/wl12xx/wl1271_acx.c | |||
@@ -31,7 +31,6 @@ | |||
31 | #include "wl1271.h" | 31 | #include "wl1271.h" |
32 | #include "wl12xx_80211.h" | 32 | #include "wl12xx_80211.h" |
33 | #include "wl1271_reg.h" | 33 | #include "wl1271_reg.h" |
34 | #include "wl1271_spi.h" | ||
35 | #include "wl1271_ps.h" | 34 | #include "wl1271_ps.h" |
36 | 35 | ||
37 | int wl1271_acx_wake_up_conditions(struct wl1271 *wl) | 36 | int wl1271_acx_wake_up_conditions(struct wl1271 *wl) |
@@ -136,12 +135,7 @@ int wl1271_acx_tx_power(struct wl1271 *wl, int power) | |||
136 | goto out; | 135 | goto out; |
137 | } | 136 | } |
138 | 137 | ||
139 | /* | 138 | acx->current_tx_power = power * 10; |
140 | * FIXME: This is a workaround needed while we don't the correct | ||
141 | * calibration, to avoid distortions | ||
142 | */ | ||
143 | /* acx->current_tx_power = power * 10; */ | ||
144 | acx->current_tx_power = 120; | ||
145 | 139 | ||
146 | ret = wl1271_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx)); | 140 | ret = wl1271_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx)); |
147 | if (ret < 0) { | 141 | if (ret < 0) { |
@@ -510,12 +504,17 @@ out: | |||
510 | return ret; | 504 | return ret; |
511 | } | 505 | } |
512 | 506 | ||
513 | int wl1271_acx_conn_monit_params(struct wl1271 *wl) | 507 | #define ACX_CONN_MONIT_DISABLE_VALUE 0xffffffff |
508 | |||
509 | int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable) | ||
514 | { | 510 | { |
515 | struct acx_conn_monit_params *acx; | 511 | struct acx_conn_monit_params *acx; |
512 | u32 threshold = ACX_CONN_MONIT_DISABLE_VALUE; | ||
513 | u32 timeout = ACX_CONN_MONIT_DISABLE_VALUE; | ||
516 | int ret; | 514 | int ret; |
517 | 515 | ||
518 | wl1271_debug(DEBUG_ACX, "acx connection monitor parameters"); | 516 | wl1271_debug(DEBUG_ACX, "acx connection monitor parameters: %s", |
517 | enable ? "enabled" : "disabled"); | ||
519 | 518 | ||
520 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | 519 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); |
521 | if (!acx) { | 520 | if (!acx) { |
@@ -523,8 +522,13 @@ int wl1271_acx_conn_monit_params(struct wl1271 *wl) | |||
523 | goto out; | 522 | goto out; |
524 | } | 523 | } |
525 | 524 | ||
526 | acx->synch_fail_thold = cpu_to_le32(wl->conf.conn.synch_fail_thold); | 525 | if (enable) { |
527 | acx->bss_lose_timeout = cpu_to_le32(wl->conf.conn.bss_lose_timeout); | 526 | threshold = wl->conf.conn.synch_fail_thold; |
527 | timeout = wl->conf.conn.bss_lose_timeout; | ||
528 | } | ||
529 | |||
530 | acx->synch_fail_thold = cpu_to_le32(threshold); | ||
531 | acx->bss_lose_timeout = cpu_to_le32(timeout); | ||
528 | 532 | ||
529 | ret = wl1271_cmd_configure(wl, ACX_CONN_MONIT_PARAMS, | 533 | ret = wl1271_cmd_configure(wl, ACX_CONN_MONIT_PARAMS, |
530 | acx, sizeof(*acx)); | 534 | acx, sizeof(*acx)); |
@@ -540,7 +544,7 @@ out: | |||
540 | } | 544 | } |
541 | 545 | ||
542 | 546 | ||
543 | int wl1271_acx_sg_enable(struct wl1271 *wl) | 547 | int wl1271_acx_sg_enable(struct wl1271 *wl, bool enable) |
544 | { | 548 | { |
545 | struct acx_bt_wlan_coex *pta; | 549 | struct acx_bt_wlan_coex *pta; |
546 | int ret; | 550 | int ret; |
@@ -553,7 +557,10 @@ int wl1271_acx_sg_enable(struct wl1271 *wl) | |||
553 | goto out; | 557 | goto out; |
554 | } | 558 | } |
555 | 559 | ||
556 | pta->enable = SG_ENABLE; | 560 | if (enable) |
561 | pta->enable = wl->conf.sg.state; | ||
562 | else | ||
563 | pta->enable = CONF_SG_DISABLE; | ||
557 | 564 | ||
558 | ret = wl1271_cmd_configure(wl, ACX_SG_ENABLE, pta, sizeof(*pta)); | 565 | ret = wl1271_cmd_configure(wl, ACX_SG_ENABLE, pta, sizeof(*pta)); |
559 | if (ret < 0) { | 566 | if (ret < 0) { |
@@ -570,7 +577,7 @@ int wl1271_acx_sg_cfg(struct wl1271 *wl) | |||
570 | { | 577 | { |
571 | struct acx_bt_wlan_coex_param *param; | 578 | struct acx_bt_wlan_coex_param *param; |
572 | struct conf_sg_settings *c = &wl->conf.sg; | 579 | struct conf_sg_settings *c = &wl->conf.sg; |
573 | int ret; | 580 | int i, ret; |
574 | 581 | ||
575 | wl1271_debug(DEBUG_ACX, "acx sg cfg"); | 582 | wl1271_debug(DEBUG_ACX, "acx sg cfg"); |
576 | 583 | ||
@@ -581,19 +588,9 @@ int wl1271_acx_sg_cfg(struct wl1271 *wl) | |||
581 | } | 588 | } |
582 | 589 | ||
583 | /* BT-WLAN coext parameters */ | 590 | /* BT-WLAN coext parameters */ |
584 | param->per_threshold = cpu_to_le32(c->per_threshold); | 591 | for (i = 0; i < CONF_SG_PARAMS_MAX; i++) |
585 | param->max_scan_compensation_time = | 592 | param->params[i] = c->params[i]; |
586 | cpu_to_le32(c->max_scan_compensation_time); | 593 | param->param_idx = CONF_SG_PARAMS_ALL; |
587 | param->nfs_sample_interval = cpu_to_le16(c->nfs_sample_interval); | ||
588 | param->load_ratio = c->load_ratio; | ||
589 | param->auto_ps_mode = c->auto_ps_mode; | ||
590 | param->probe_req_compensation = c->probe_req_compensation; | ||
591 | param->scan_window_compensation = c->scan_window_compensation; | ||
592 | param->antenna_config = c->antenna_config; | ||
593 | param->beacon_miss_threshold = c->beacon_miss_threshold; | ||
594 | param->rate_adaptation_threshold = | ||
595 | cpu_to_le32(c->rate_adaptation_threshold); | ||
596 | param->rate_adaptation_snr = c->rate_adaptation_snr; | ||
597 | 594 | ||
598 | ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param)); | 595 | ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param)); |
599 | if (ret < 0) { | 596 | if (ret < 0) { |
@@ -805,7 +802,7 @@ int wl1271_acx_rate_policies(struct wl1271 *wl) | |||
805 | 802 | ||
806 | /* configure one basic rate class */ | 803 | /* configure one basic rate class */ |
807 | idx = ACX_TX_BASIC_RATE; | 804 | idx = ACX_TX_BASIC_RATE; |
808 | acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->basic_rate_set); | 805 | acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->basic_rate); |
809 | acx->rate_class[idx].short_retry_limit = c->short_retry_limit; | 806 | acx->rate_class[idx].short_retry_limit = c->short_retry_limit; |
810 | acx->rate_class[idx].long_retry_limit = c->long_retry_limit; | 807 | acx->rate_class[idx].long_retry_limit = c->long_retry_limit; |
811 | acx->rate_class[idx].aflags = c->aflags; | 808 | acx->rate_class[idx].aflags = c->aflags; |
@@ -1142,3 +1139,58 @@ out: | |||
1142 | kfree(acx); | 1139 | kfree(acx); |
1143 | return ret; | 1140 | return ret; |
1144 | } | 1141 | } |
1142 | |||
1143 | int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable) | ||
1144 | { | ||
1145 | struct wl1271_acx_keep_alive_mode *acx = NULL; | ||
1146 | int ret = 0; | ||
1147 | |||
1148 | wl1271_debug(DEBUG_ACX, "acx keep alive mode: %d", enable); | ||
1149 | |||
1150 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1151 | if (!acx) { | ||
1152 | ret = -ENOMEM; | ||
1153 | goto out; | ||
1154 | } | ||
1155 | |||
1156 | acx->enabled = enable; | ||
1157 | |||
1158 | ret = wl1271_cmd_configure(wl, ACX_KEEP_ALIVE_MODE, acx, sizeof(*acx)); | ||
1159 | if (ret < 0) { | ||
1160 | wl1271_warning("acx keep alive mode failed: %d", ret); | ||
1161 | goto out; | ||
1162 | } | ||
1163 | |||
1164 | out: | ||
1165 | kfree(acx); | ||
1166 | return ret; | ||
1167 | } | ||
1168 | int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid) | ||
1169 | { | ||
1170 | struct wl1271_acx_keep_alive_config *acx = NULL; | ||
1171 | int ret = 0; | ||
1172 | |||
1173 | wl1271_debug(DEBUG_ACX, "acx keep alive config"); | ||
1174 | |||
1175 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1176 | if (!acx) { | ||
1177 | ret = -ENOMEM; | ||
1178 | goto out; | ||
1179 | } | ||
1180 | |||
1181 | acx->period = cpu_to_le32(wl->conf.conn.keep_alive_interval); | ||
1182 | acx->index = index; | ||
1183 | acx->tpl_validation = tpl_valid; | ||
1184 | acx->trigger = ACX_KEEP_ALIVE_NO_TX; | ||
1185 | |||
1186 | ret = wl1271_cmd_configure(wl, ACX_SET_KEEP_ALIVE_CONFIG, | ||
1187 | acx, sizeof(*acx)); | ||
1188 | if (ret < 0) { | ||
1189 | wl1271_warning("acx keep alive config failed: %d", ret); | ||
1190 | goto out; | ||
1191 | } | ||
1192 | |||
1193 | out: | ||
1194 | kfree(acx); | ||
1195 | return ret; | ||
1196 | } | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h index aeccc98581eb..15cc56192de9 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.h +++ b/drivers/net/wireless/wl12xx/wl1271_acx.h | |||
@@ -392,81 +392,27 @@ struct acx_conn_monit_params { | |||
392 | __le32 bss_lose_timeout; /* number of TU's from synch fail */ | 392 | __le32 bss_lose_timeout; /* number of TU's from synch fail */ |
393 | } __attribute__ ((packed)); | 393 | } __attribute__ ((packed)); |
394 | 394 | ||
395 | enum { | ||
396 | SG_ENABLE = 0, | ||
397 | SG_DISABLE, | ||
398 | SG_SENSE_NO_ACTIVITY, | ||
399 | SG_SENSE_ACTIVE | ||
400 | }; | ||
401 | |||
402 | struct acx_bt_wlan_coex { | 395 | struct acx_bt_wlan_coex { |
403 | struct acx_header header; | 396 | struct acx_header header; |
404 | 397 | ||
405 | /* | ||
406 | * 0 -> PTA enabled | ||
407 | * 1 -> PTA disabled | ||
408 | * 2 -> sense no active mode, i.e. | ||
409 | * an interrupt is sent upon | ||
410 | * BT activity. | ||
411 | * 3 -> PTA is switched on in response | ||
412 | * to the interrupt sending. | ||
413 | */ | ||
414 | u8 enable; | 398 | u8 enable; |
415 | u8 pad[3]; | 399 | u8 pad[3]; |
416 | } __attribute__ ((packed)); | 400 | } __attribute__ ((packed)); |
417 | 401 | ||
418 | struct acx_dco_itrim_params { | 402 | struct acx_bt_wlan_coex_param { |
419 | struct acx_header header; | 403 | struct acx_header header; |
420 | 404 | ||
421 | u8 enable; | 405 | __le32 params[CONF_SG_PARAMS_MAX]; |
406 | u8 param_idx; | ||
422 | u8 padding[3]; | 407 | u8 padding[3]; |
423 | __le32 timeout; | ||
424 | } __attribute__ ((packed)); | 408 | } __attribute__ ((packed)); |
425 | 409 | ||
426 | #define PTA_ANTENNA_TYPE_DEF (0) | 410 | struct acx_dco_itrim_params { |
427 | #define PTA_BT_HP_MAXTIME_DEF (2000) | ||
428 | #define PTA_WLAN_HP_MAX_TIME_DEF (5000) | ||
429 | #define PTA_SENSE_DISABLE_TIMER_DEF (1350) | ||
430 | #define PTA_PROTECTIVE_RX_TIME_DEF (1500) | ||
431 | #define PTA_PROTECTIVE_TX_TIME_DEF (1500) | ||
432 | #define PTA_TIMEOUT_NEXT_BT_LP_PACKET_DEF (3000) | ||
433 | #define PTA_SIGNALING_TYPE_DEF (1) | ||
434 | #define PTA_AFH_LEVERAGE_ON_DEF (0) | ||
435 | #define PTA_NUMBER_QUIET_CYCLE_DEF (0) | ||
436 | #define PTA_MAX_NUM_CTS_DEF (3) | ||
437 | #define PTA_NUMBER_OF_WLAN_PACKETS_DEF (2) | ||
438 | #define PTA_NUMBER_OF_BT_PACKETS_DEF (2) | ||
439 | #define PTA_PROTECTIVE_RX_TIME_FAST_DEF (1500) | ||
440 | #define PTA_PROTECTIVE_TX_TIME_FAST_DEF (3000) | ||
441 | #define PTA_CYCLE_TIME_FAST_DEF (8700) | ||
442 | #define PTA_RX_FOR_AVALANCHE_DEF (5) | ||
443 | #define PTA_ELP_HP_DEF (0) | ||
444 | #define PTA_ANTI_STARVE_PERIOD_DEF (500) | ||
445 | #define PTA_ANTI_STARVE_NUM_CYCLE_DEF (4) | ||
446 | #define PTA_ALLOW_PA_SD_DEF (1) | ||
447 | #define PTA_TIME_BEFORE_BEACON_DEF (6300) | ||
448 | #define PTA_HPDM_MAX_TIME_DEF (1600) | ||
449 | #define PTA_TIME_OUT_NEXT_WLAN_DEF (2550) | ||
450 | #define PTA_AUTO_MODE_NO_CTS_DEF (0) | ||
451 | #define PTA_BT_HP_RESPECTED_DEF (3) | ||
452 | #define PTA_WLAN_RX_MIN_RATE_DEF (24) | ||
453 | #define PTA_ACK_MODE_DEF (1) | ||
454 | |||
455 | struct acx_bt_wlan_coex_param { | ||
456 | struct acx_header header; | 411 | struct acx_header header; |
457 | 412 | ||
458 | __le32 per_threshold; | 413 | u8 enable; |
459 | __le32 max_scan_compensation_time; | ||
460 | __le16 nfs_sample_interval; | ||
461 | u8 load_ratio; | ||
462 | u8 auto_ps_mode; | ||
463 | u8 probe_req_compensation; | ||
464 | u8 scan_window_compensation; | ||
465 | u8 antenna_config; | ||
466 | u8 beacon_miss_threshold; | ||
467 | __le32 rate_adaptation_threshold; | ||
468 | s8 rate_adaptation_snr; | ||
469 | u8 padding[3]; | 414 | u8 padding[3]; |
415 | __le32 timeout; | ||
470 | } __attribute__ ((packed)); | 416 | } __attribute__ ((packed)); |
471 | 417 | ||
472 | struct acx_energy_detection { | 418 | struct acx_energy_detection { |
@@ -969,6 +915,33 @@ struct wl1271_acx_pm_config { | |||
969 | u8 padding[3]; | 915 | u8 padding[3]; |
970 | } __attribute__ ((packed)); | 916 | } __attribute__ ((packed)); |
971 | 917 | ||
918 | struct wl1271_acx_keep_alive_mode { | ||
919 | struct acx_header header; | ||
920 | |||
921 | u8 enabled; | ||
922 | u8 padding[3]; | ||
923 | } __attribute__ ((packed)); | ||
924 | |||
925 | enum { | ||
926 | ACX_KEEP_ALIVE_NO_TX = 0, | ||
927 | ACX_KEEP_ALIVE_PERIOD_ONLY | ||
928 | }; | ||
929 | |||
930 | enum { | ||
931 | ACX_KEEP_ALIVE_TPL_INVALID = 0, | ||
932 | ACX_KEEP_ALIVE_TPL_VALID | ||
933 | }; | ||
934 | |||
935 | struct wl1271_acx_keep_alive_config { | ||
936 | struct acx_header header; | ||
937 | |||
938 | __le32 period; | ||
939 | u8 index; | ||
940 | u8 tpl_validation; | ||
941 | u8 trigger; | ||
942 | u8 padding; | ||
943 | } __attribute__ ((packed)); | ||
944 | |||
972 | enum { | 945 | enum { |
973 | ACX_WAKE_UP_CONDITIONS = 0x0002, | 946 | ACX_WAKE_UP_CONDITIONS = 0x0002, |
974 | ACX_MEM_CFG = 0x0003, | 947 | ACX_MEM_CFG = 0x0003, |
@@ -1018,7 +991,7 @@ enum { | |||
1018 | ACX_BET_ENABLE = 0x0050, | 991 | ACX_BET_ENABLE = 0x0050, |
1019 | ACX_RSSI_SNR_TRIGGER = 0x0051, | 992 | ACX_RSSI_SNR_TRIGGER = 0x0051, |
1020 | ACX_RSSI_SNR_WEIGHTS = 0x0051, | 993 | ACX_RSSI_SNR_WEIGHTS = 0x0051, |
1021 | ACX_KEEP_ALIVE_MODE = 0x0052, | 994 | ACX_KEEP_ALIVE_MODE = 0x0053, |
1022 | ACX_SET_KEEP_ALIVE_CONFIG = 0x0054, | 995 | ACX_SET_KEEP_ALIVE_CONFIG = 0x0054, |
1023 | ACX_BA_SESSION_RESPONDER_POLICY = 0x0055, | 996 | ACX_BA_SESSION_RESPONDER_POLICY = 0x0055, |
1024 | ACX_BA_SESSION_INITIATOR_POLICY = 0x0056, | 997 | ACX_BA_SESSION_INITIATOR_POLICY = 0x0056, |
@@ -1058,8 +1031,8 @@ int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold); | |||
1058 | int wl1271_acx_dco_itrim_params(struct wl1271 *wl); | 1031 | int wl1271_acx_dco_itrim_params(struct wl1271 *wl); |
1059 | int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter); | 1032 | int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter); |
1060 | int wl1271_acx_beacon_filter_table(struct wl1271 *wl); | 1033 | int wl1271_acx_beacon_filter_table(struct wl1271 *wl); |
1061 | int wl1271_acx_conn_monit_params(struct wl1271 *wl); | 1034 | int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable); |
1062 | int wl1271_acx_sg_enable(struct wl1271 *wl); | 1035 | int wl1271_acx_sg_enable(struct wl1271 *wl, bool enable); |
1063 | int wl1271_acx_sg_cfg(struct wl1271 *wl); | 1036 | int wl1271_acx_sg_cfg(struct wl1271 *wl); |
1064 | int wl1271_acx_cca_threshold(struct wl1271 *wl); | 1037 | int wl1271_acx_cca_threshold(struct wl1271 *wl); |
1065 | int wl1271_acx_bcn_dtim_options(struct wl1271 *wl); | 1038 | int wl1271_acx_bcn_dtim_options(struct wl1271 *wl); |
@@ -1085,5 +1058,7 @@ int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable); | |||
1085 | int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address, | 1058 | int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address, |
1086 | u8 version); | 1059 | u8 version); |
1087 | int wl1271_acx_pm_config(struct wl1271 *wl); | 1060 | int wl1271_acx_pm_config(struct wl1271 *wl); |
1061 | int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable); | ||
1062 | int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid); | ||
1088 | 1063 | ||
1089 | #endif /* __WL1271_ACX_H__ */ | 1064 | #endif /* __WL1271_ACX_H__ */ |
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c index 2be76ee42bb9..7acef88df1fe 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.c +++ b/drivers/net/wireless/wl12xx/wl1271_boot.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * This file is part of wl1271 | 2 | * This file is part of wl1271 |
3 | * | 3 | * |
4 | * Copyright (C) 2008-2009 Nokia Corporation | 4 | * Copyright (C) 2008-2010 Nokia Corporation |
5 | * | 5 | * |
6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> | 6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> |
7 | * | 7 | * |
@@ -26,7 +26,6 @@ | |||
26 | #include "wl1271_acx.h" | 26 | #include "wl1271_acx.h" |
27 | #include "wl1271_reg.h" | 27 | #include "wl1271_reg.h" |
28 | #include "wl1271_boot.h" | 28 | #include "wl1271_boot.h" |
29 | #include "wl1271_spi.h" | ||
30 | #include "wl1271_io.h" | 29 | #include "wl1271_io.h" |
31 | #include "wl1271_event.h" | 30 | #include "wl1271_event.h" |
32 | 31 | ||
@@ -229,6 +228,14 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) | |||
229 | nvs_len = sizeof(wl->nvs->nvs); | 228 | nvs_len = sizeof(wl->nvs->nvs); |
230 | nvs_ptr = (u8 *)wl->nvs->nvs; | 229 | nvs_ptr = (u8 *)wl->nvs->nvs; |
231 | 230 | ||
231 | /* update current MAC address to NVS */ | ||
232 | nvs_ptr[11] = wl->mac_addr[0]; | ||
233 | nvs_ptr[10] = wl->mac_addr[1]; | ||
234 | nvs_ptr[6] = wl->mac_addr[2]; | ||
235 | nvs_ptr[5] = wl->mac_addr[3]; | ||
236 | nvs_ptr[4] = wl->mac_addr[4]; | ||
237 | nvs_ptr[3] = wl->mac_addr[5]; | ||
238 | |||
232 | /* | 239 | /* |
233 | * Layout before the actual NVS tables: | 240 | * Layout before the actual NVS tables: |
234 | * 1 byte : burst length. | 241 | * 1 byte : burst length. |
@@ -299,7 +306,7 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) | |||
299 | 306 | ||
300 | static void wl1271_boot_enable_interrupts(struct wl1271 *wl) | 307 | static void wl1271_boot_enable_interrupts(struct wl1271 *wl) |
301 | { | 308 | { |
302 | enable_irq(wl->irq); | 309 | wl1271_enable_interrupts(wl); |
303 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, | 310 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, |
304 | WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); | 311 | WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); |
305 | wl1271_write32(wl, HI_CFG, HI_CFG_DEF_VAL); | 312 | wl1271_write32(wl, HI_CFG, HI_CFG_DEF_VAL); |
@@ -403,7 +410,9 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) | |||
403 | /* unmask required mbox events */ | 410 | /* unmask required mbox events */ |
404 | wl->event_mask = BSS_LOSE_EVENT_ID | | 411 | wl->event_mask = BSS_LOSE_EVENT_ID | |
405 | SCAN_COMPLETE_EVENT_ID | | 412 | SCAN_COMPLETE_EVENT_ID | |
406 | PS_REPORT_EVENT_ID; | 413 | PS_REPORT_EVENT_ID | |
414 | JOIN_EVENT_COMPLETE_ID | | ||
415 | DISCONNECT_EVENT_COMPLETE_ID; | ||
407 | 416 | ||
408 | ret = wl1271_event_unmask(wl); | 417 | ret = wl1271_event_unmask(wl); |
409 | if (ret < 0) { | 418 | if (ret < 0) { |
@@ -444,11 +453,15 @@ int wl1271_boot(struct wl1271 *wl) | |||
444 | 453 | ||
445 | if (REF_CLOCK != 0) { | 454 | if (REF_CLOCK != 0) { |
446 | u16 val; | 455 | u16 val; |
447 | /* Set clock type */ | 456 | /* Set clock type (open drain) */ |
448 | val = wl1271_top_reg_read(wl, OCP_REG_CLK_TYPE); | 457 | val = wl1271_top_reg_read(wl, OCP_REG_CLK_TYPE); |
449 | val &= FREF_CLK_TYPE_BITS; | 458 | val &= FREF_CLK_TYPE_BITS; |
450 | val |= CLK_REQ_PRCM; | ||
451 | wl1271_top_reg_write(wl, OCP_REG_CLK_TYPE, val); | 459 | wl1271_top_reg_write(wl, OCP_REG_CLK_TYPE, val); |
460 | |||
461 | /* Set clock pull mode (no pull) */ | ||
462 | val = wl1271_top_reg_read(wl, OCP_REG_CLK_PULL); | ||
463 | val |= NO_PULL; | ||
464 | wl1271_top_reg_write(wl, OCP_REG_CLK_PULL, val); | ||
452 | } else { | 465 | } else { |
453 | u16 val; | 466 | u16 val; |
454 | /* Set clock polarity */ | 467 | /* Set clock polarity */ |
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.h b/drivers/net/wireless/wl12xx/wl1271_boot.h index 412443ee655a..95ecc5241959 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.h +++ b/drivers/net/wireless/wl12xx/wl1271_boot.h | |||
@@ -53,10 +53,13 @@ struct wl1271_static_data { | |||
53 | #define OCP_REG_POLARITY 0x0064 | 53 | #define OCP_REG_POLARITY 0x0064 |
54 | #define OCP_REG_CLK_TYPE 0x0448 | 54 | #define OCP_REG_CLK_TYPE 0x0448 |
55 | #define OCP_REG_CLK_POLARITY 0x0cb2 | 55 | #define OCP_REG_CLK_POLARITY 0x0cb2 |
56 | #define OCP_REG_CLK_PULL 0x0cb4 | ||
56 | 57 | ||
57 | #define CMD_MBOX_ADDRESS 0x407B4 | ||
58 | 58 | ||
59 | #define POLARITY_LOW BIT(1) | 59 | #define CMD_MBOX_ADDRESS 0x407B4 |
60 | |||
61 | #define POLARITY_LOW BIT(1) | ||
62 | #define NO_PULL (BIT(14) | BIT(15)) | ||
60 | 63 | ||
61 | #define FREF_CLK_TYPE_BITS 0xfffffe7f | 64 | #define FREF_CLK_TYPE_BITS 0xfffffe7f |
62 | #define CLK_REQ_PRCM 0x100 | 65 | #define CLK_REQ_PRCM 0x100 |
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index 36a64e06f290..b19090334bc0 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * This file is part of wl1271 | 2 | * This file is part of wl1271 |
3 | * | 3 | * |
4 | * Copyright (C) 2009 Nokia Corporation | 4 | * Copyright (C) 2009-2010 Nokia Corporation |
5 | * | 5 | * |
6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> | 6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> |
7 | * | 7 | * |
@@ -26,14 +26,17 @@ | |||
26 | #include <linux/crc7.h> | 26 | #include <linux/crc7.h> |
27 | #include <linux/spi/spi.h> | 27 | #include <linux/spi/spi.h> |
28 | #include <linux/etherdevice.h> | 28 | #include <linux/etherdevice.h> |
29 | #include <linux/ieee80211.h> | ||
29 | 30 | ||
30 | #include "wl1271.h" | 31 | #include "wl1271.h" |
31 | #include "wl1271_reg.h" | 32 | #include "wl1271_reg.h" |
32 | #include "wl1271_spi.h" | ||
33 | #include "wl1271_io.h" | 33 | #include "wl1271_io.h" |
34 | #include "wl1271_acx.h" | 34 | #include "wl1271_acx.h" |
35 | #include "wl12xx_80211.h" | 35 | #include "wl12xx_80211.h" |
36 | #include "wl1271_cmd.h" | 36 | #include "wl1271_cmd.h" |
37 | #include "wl1271_event.h" | ||
38 | |||
39 | #define WL1271_CMD_POLL_COUNT 5 | ||
37 | 40 | ||
38 | /* | 41 | /* |
39 | * send command to firmware | 42 | * send command to firmware |
@@ -51,6 +54,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
51 | u32 intr; | 54 | u32 intr; |
52 | int ret = 0; | 55 | int ret = 0; |
53 | u16 status; | 56 | u16 status; |
57 | u16 poll_count = 0; | ||
54 | 58 | ||
55 | cmd = buf; | 59 | cmd = buf; |
56 | cmd->id = cpu_to_le16(id); | 60 | cmd->id = cpu_to_le16(id); |
@@ -72,7 +76,11 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
72 | goto out; | 76 | goto out; |
73 | } | 77 | } |
74 | 78 | ||
75 | msleep(1); | 79 | udelay(10); |
80 | poll_count++; | ||
81 | if (poll_count == WL1271_CMD_POLL_COUNT) | ||
82 | wl1271_info("cmd polling took over %d cycles", | ||
83 | poll_count); | ||
76 | 84 | ||
77 | intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); | 85 | intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); |
78 | } | 86 | } |
@@ -248,7 +256,36 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) | |||
248 | return ret; | 256 | return ret; |
249 | } | 257 | } |
250 | 258 | ||
251 | int wl1271_cmd_join(struct wl1271 *wl) | 259 | /* |
260 | * Poll the mailbox event field until any of the bits in the mask is set or a | ||
261 | * timeout occurs (WL1271_EVENT_TIMEOUT in msecs) | ||
262 | */ | ||
263 | static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask) | ||
264 | { | ||
265 | u32 events_vector, event; | ||
266 | unsigned long timeout; | ||
267 | |||
268 | timeout = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT); | ||
269 | |||
270 | do { | ||
271 | if (time_after(jiffies, timeout)) | ||
272 | return -ETIMEDOUT; | ||
273 | |||
274 | msleep(1); | ||
275 | |||
276 | /* read from both event fields */ | ||
277 | wl1271_read(wl, wl->mbox_ptr[0], &events_vector, | ||
278 | sizeof(events_vector), false); | ||
279 | event = events_vector & mask; | ||
280 | wl1271_read(wl, wl->mbox_ptr[1], &events_vector, | ||
281 | sizeof(events_vector), false); | ||
282 | event |= events_vector & mask; | ||
283 | } while (!event); | ||
284 | |||
285 | return 0; | ||
286 | } | ||
287 | |||
288 | int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type) | ||
252 | { | 289 | { |
253 | static bool do_cal = true; | 290 | static bool do_cal = true; |
254 | struct wl1271_cmd_join *join; | 291 | struct wl1271_cmd_join *join; |
@@ -279,30 +316,13 @@ int wl1271_cmd_join(struct wl1271 *wl) | |||
279 | 316 | ||
280 | join->rx_config_options = cpu_to_le32(wl->rx_config); | 317 | join->rx_config_options = cpu_to_le32(wl->rx_config); |
281 | join->rx_filter_options = cpu_to_le32(wl->rx_filter); | 318 | join->rx_filter_options = cpu_to_le32(wl->rx_filter); |
282 | join->bss_type = wl->bss_type; | 319 | join->bss_type = bss_type; |
320 | join->basic_rate_set = wl->basic_rate_set; | ||
283 | 321 | ||
284 | /* | 322 | if (wl->band == IEEE80211_BAND_5GHZ) |
285 | * FIXME: disable temporarily all filters because after commit | ||
286 | * 9cef8737 "mac80211: fix managed mode BSSID handling" broke | ||
287 | * association. The filter logic needs to be implemented properly | ||
288 | * and once that is done, this hack can be removed. | ||
289 | */ | ||
290 | join->rx_config_options = cpu_to_le32(0); | ||
291 | join->rx_filter_options = cpu_to_le32(WL1271_DEFAULT_RX_FILTER); | ||
292 | |||
293 | if (wl->band == IEEE80211_BAND_2GHZ) | ||
294 | join->basic_rate_set = cpu_to_le32(CONF_HW_BIT_RATE_1MBPS | | ||
295 | CONF_HW_BIT_RATE_2MBPS | | ||
296 | CONF_HW_BIT_RATE_5_5MBPS | | ||
297 | CONF_HW_BIT_RATE_11MBPS); | ||
298 | else { | ||
299 | join->bss_type |= WL1271_JOIN_CMD_BSS_TYPE_5GHZ; | 323 | join->bss_type |= WL1271_JOIN_CMD_BSS_TYPE_5GHZ; |
300 | join->basic_rate_set = cpu_to_le32(CONF_HW_BIT_RATE_6MBPS | | ||
301 | CONF_HW_BIT_RATE_12MBPS | | ||
302 | CONF_HW_BIT_RATE_24MBPS); | ||
303 | } | ||
304 | 324 | ||
305 | join->beacon_interval = cpu_to_le16(WL1271_DEFAULT_BEACON_INT); | 325 | join->beacon_interval = cpu_to_le16(wl->beacon_int); |
306 | join->dtim_interval = WL1271_DEFAULT_DTIM_PERIOD; | 326 | join->dtim_interval = WL1271_DEFAULT_DTIM_PERIOD; |
307 | 327 | ||
308 | join->channel = wl->channel; | 328 | join->channel = wl->channel; |
@@ -319,8 +339,7 @@ int wl1271_cmd_join(struct wl1271 *wl) | |||
319 | 339 | ||
320 | /* reset TX security counters */ | 340 | /* reset TX security counters */ |
321 | wl->tx_security_last_seq = 0; | 341 | wl->tx_security_last_seq = 0; |
322 | wl->tx_security_seq_16 = 0; | 342 | wl->tx_security_seq = 0; |
323 | wl->tx_security_seq_32 = 0; | ||
324 | 343 | ||
325 | ret = wl1271_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join), 0); | 344 | ret = wl1271_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join), 0); |
326 | if (ret < 0) { | 345 | if (ret < 0) { |
@@ -328,11 +347,9 @@ int wl1271_cmd_join(struct wl1271 *wl) | |||
328 | goto out_free; | 347 | goto out_free; |
329 | } | 348 | } |
330 | 349 | ||
331 | /* | 350 | ret = wl1271_cmd_wait_for_event(wl, JOIN_EVENT_COMPLETE_ID); |
332 | * ugly hack: we should wait for JOIN_EVENT_COMPLETE_ID but to | 351 | if (ret < 0) |
333 | * simplify locking we just sleep instead, for now | 352 | wl1271_error("cmd join event completion error"); |
334 | */ | ||
335 | msleep(10); | ||
336 | 353 | ||
337 | out_free: | 354 | out_free: |
338 | kfree(join); | 355 | kfree(join); |
@@ -464,7 +481,7 @@ int wl1271_cmd_data_path(struct wl1271 *wl, bool enable) | |||
464 | if (ret < 0) { | 481 | if (ret < 0) { |
465 | wl1271_error("tx %s cmd for channel %d failed", | 482 | wl1271_error("tx %s cmd for channel %d failed", |
466 | enable ? "start" : "stop", cmd->channel); | 483 | enable ? "start" : "stop", cmd->channel); |
467 | return ret; | 484 | goto out; |
468 | } | 485 | } |
469 | 486 | ||
470 | wl1271_debug(DEBUG_BOOT, "tx %s cmd channel %d", | 487 | wl1271_debug(DEBUG_BOOT, "tx %s cmd channel %d", |
@@ -548,25 +565,29 @@ out: | |||
548 | return ret; | 565 | return ret; |
549 | } | 566 | } |
550 | 567 | ||
551 | int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, | 568 | int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, |
552 | u8 active_scan, u8 high_prio, u8 band, | 569 | const u8 *ie, size_t ie_len, u8 active_scan, |
553 | u8 probe_requests) | 570 | u8 high_prio, u8 band, u8 probe_requests) |
554 | { | 571 | { |
555 | 572 | ||
556 | struct wl1271_cmd_trigger_scan_to *trigger = NULL; | 573 | struct wl1271_cmd_trigger_scan_to *trigger = NULL; |
557 | struct wl1271_cmd_scan *params = NULL; | 574 | struct wl1271_cmd_scan *params = NULL; |
558 | struct ieee80211_channel *channels; | 575 | struct ieee80211_channel *channels; |
576 | u32 rate; | ||
559 | int i, j, n_ch, ret; | 577 | int i, j, n_ch, ret; |
560 | u16 scan_options = 0; | 578 | u16 scan_options = 0; |
561 | u8 ieee_band; | 579 | u8 ieee_band; |
562 | 580 | ||
563 | if (band == WL1271_SCAN_BAND_2_4_GHZ) | 581 | if (band == WL1271_SCAN_BAND_2_4_GHZ) { |
564 | ieee_band = IEEE80211_BAND_2GHZ; | 582 | ieee_band = IEEE80211_BAND_2GHZ; |
565 | else if (band == WL1271_SCAN_BAND_DUAL && wl1271_11a_enabled()) | 583 | rate = wl->conf.tx.basic_rate; |
584 | } else if (band == WL1271_SCAN_BAND_DUAL && wl1271_11a_enabled()) { | ||
566 | ieee_band = IEEE80211_BAND_2GHZ; | 585 | ieee_band = IEEE80211_BAND_2GHZ; |
567 | else if (band == WL1271_SCAN_BAND_5_GHZ && wl1271_11a_enabled()) | 586 | rate = wl->conf.tx.basic_rate; |
587 | } else if (band == WL1271_SCAN_BAND_5_GHZ && wl1271_11a_enabled()) { | ||
568 | ieee_band = IEEE80211_BAND_5GHZ; | 588 | ieee_band = IEEE80211_BAND_5GHZ; |
569 | else | 589 | rate = wl->conf.tx.basic_rate_5; |
590 | } else | ||
570 | return -EINVAL; | 591 | return -EINVAL; |
571 | 592 | ||
572 | if (wl->hw->wiphy->bands[ieee_band]->channels == NULL) | 593 | if (wl->hw->wiphy->bands[ieee_band]->channels == NULL) |
@@ -593,8 +614,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, | |||
593 | params->params.scan_options = cpu_to_le16(scan_options); | 614 | params->params.scan_options = cpu_to_le16(scan_options); |
594 | 615 | ||
595 | params->params.num_probe_requests = probe_requests; | 616 | params->params.num_probe_requests = probe_requests; |
596 | /* Let the fw autodetect suitable tx_rate for probes */ | 617 | params->params.tx_rate = rate; |
597 | params->params.tx_rate = 0; | ||
598 | params->params.tid_trigger = 0; | 618 | params->params.tid_trigger = 0; |
599 | params->params.scan_tag = WL1271_SCAN_DEFAULT_TAG; | 619 | params->params.scan_tag = WL1271_SCAN_DEFAULT_TAG; |
600 | 620 | ||
@@ -621,12 +641,13 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, | |||
621 | 641 | ||
622 | params->params.num_channels = j; | 642 | params->params.num_channels = j; |
623 | 643 | ||
624 | if (len && ssid) { | 644 | if (ssid_len && ssid) { |
625 | params->params.ssid_len = len; | 645 | params->params.ssid_len = ssid_len; |
626 | memcpy(params->params.ssid, ssid, len); | 646 | memcpy(params->params.ssid, ssid, ssid_len); |
627 | } | 647 | } |
628 | 648 | ||
629 | ret = wl1271_cmd_build_probe_req(wl, ssid, len, ieee_band); | 649 | ret = wl1271_cmd_build_probe_req(wl, ssid, ssid_len, |
650 | ie, ie_len, ieee_band); | ||
630 | if (ret < 0) { | 651 | if (ret < 0) { |
631 | wl1271_error("PROBE request template failed"); | 652 | wl1271_error("PROBE request template failed"); |
632 | goto out; | 653 | goto out; |
@@ -657,9 +678,9 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, | |||
657 | wl->scan.active = active_scan; | 678 | wl->scan.active = active_scan; |
658 | wl->scan.high_prio = high_prio; | 679 | wl->scan.high_prio = high_prio; |
659 | wl->scan.probe_requests = probe_requests; | 680 | wl->scan.probe_requests = probe_requests; |
660 | if (len && ssid) { | 681 | if (ssid_len && ssid) { |
661 | wl->scan.ssid_len = len; | 682 | wl->scan.ssid_len = ssid_len; |
662 | memcpy(wl->scan.ssid, ssid, len); | 683 | memcpy(wl->scan.ssid, ssid, ssid_len); |
663 | } else | 684 | } else |
664 | wl->scan.ssid_len = 0; | 685 | wl->scan.ssid_len = 0; |
665 | } | 686 | } |
@@ -674,11 +695,12 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, | |||
674 | 695 | ||
675 | out: | 696 | out: |
676 | kfree(params); | 697 | kfree(params); |
698 | kfree(trigger); | ||
677 | return ret; | 699 | return ret; |
678 | } | 700 | } |
679 | 701 | ||
680 | int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, | 702 | int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, |
681 | void *buf, size_t buf_len) | 703 | void *buf, size_t buf_len, int index, u32 rates) |
682 | { | 704 | { |
683 | struct wl1271_cmd_template_set *cmd; | 705 | struct wl1271_cmd_template_set *cmd; |
684 | int ret = 0; | 706 | int ret = 0; |
@@ -696,9 +718,10 @@ int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, | |||
696 | 718 | ||
697 | cmd->len = cpu_to_le16(buf_len); | 719 | cmd->len = cpu_to_le16(buf_len); |
698 | cmd->template_type = template_id; | 720 | cmd->template_type = template_id; |
699 | cmd->enabled_rates = cpu_to_le32(wl->conf.tx.rc_conf.enabled_rates); | 721 | cmd->enabled_rates = cpu_to_le32(rates); |
700 | cmd->short_retry_limit = wl->conf.tx.rc_conf.short_retry_limit; | 722 | cmd->short_retry_limit = wl->conf.tx.rc_conf.short_retry_limit; |
701 | cmd->long_retry_limit = wl->conf.tx.rc_conf.long_retry_limit; | 723 | cmd->long_retry_limit = wl->conf.tx.rc_conf.long_retry_limit; |
724 | cmd->index = index; | ||
702 | 725 | ||
703 | if (buf) | 726 | if (buf) |
704 | memcpy(cmd->template_data, buf, buf_len); | 727 | memcpy(cmd->template_data, buf, buf_len); |
@@ -716,155 +739,129 @@ out: | |||
716 | return ret; | 739 | return ret; |
717 | } | 740 | } |
718 | 741 | ||
719 | static int wl1271_build_basic_rates(u8 *rates, u8 band) | 742 | int wl1271_cmd_build_null_data(struct wl1271 *wl) |
720 | { | 743 | { |
721 | u8 index = 0; | 744 | struct sk_buff *skb = NULL; |
722 | 745 | int size; | |
723 | if (band == IEEE80211_BAND_2GHZ) { | 746 | void *ptr; |
724 | rates[index++] = | 747 | int ret = -ENOMEM; |
725 | IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB; | ||
726 | rates[index++] = | ||
727 | IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB; | ||
728 | rates[index++] = | ||
729 | IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB; | ||
730 | rates[index++] = | ||
731 | IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB; | ||
732 | } else if (band == IEEE80211_BAND_5GHZ) { | ||
733 | rates[index++] = | ||
734 | IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB; | ||
735 | rates[index++] = | ||
736 | IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB; | ||
737 | rates[index++] = | ||
738 | IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB; | ||
739 | } else { | ||
740 | wl1271_error("build_basic_rates invalid band: %d", band); | ||
741 | } | ||
742 | 748 | ||
743 | return index; | ||
744 | } | ||
745 | 749 | ||
746 | static int wl1271_build_extended_rates(u8 *rates, u8 band) | 750 | if (wl->bss_type == BSS_TYPE_IBSS) { |
747 | { | 751 | size = sizeof(struct wl12xx_null_data_template); |
748 | u8 index = 0; | 752 | ptr = NULL; |
749 | |||
750 | if (band == IEEE80211_BAND_2GHZ) { | ||
751 | rates[index++] = IEEE80211_OFDM_RATE_6MB; | ||
752 | rates[index++] = IEEE80211_OFDM_RATE_9MB; | ||
753 | rates[index++] = IEEE80211_OFDM_RATE_12MB; | ||
754 | rates[index++] = IEEE80211_OFDM_RATE_18MB; | ||
755 | rates[index++] = IEEE80211_OFDM_RATE_24MB; | ||
756 | rates[index++] = IEEE80211_OFDM_RATE_36MB; | ||
757 | rates[index++] = IEEE80211_OFDM_RATE_48MB; | ||
758 | rates[index++] = IEEE80211_OFDM_RATE_54MB; | ||
759 | } else if (band == IEEE80211_BAND_5GHZ) { | ||
760 | rates[index++] = | ||
761 | IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB; | ||
762 | rates[index++] = | ||
763 | IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB; | ||
764 | rates[index++] = | ||
765 | IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB; | ||
766 | rates[index++] = | ||
767 | IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB; | ||
768 | rates[index++] = | ||
769 | IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB; | ||
770 | rates[index++] = | ||
771 | IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB; | ||
772 | } else { | 753 | } else { |
773 | wl1271_error("build_basic_rates invalid band: %d", band); | 754 | skb = ieee80211_nullfunc_get(wl->hw, wl->vif); |
755 | if (!skb) | ||
756 | goto out; | ||
757 | size = skb->len; | ||
758 | ptr = skb->data; | ||
774 | } | 759 | } |
775 | 760 | ||
776 | return index; | 761 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, ptr, size, 0, |
762 | WL1271_RATE_AUTOMATIC); | ||
763 | |||
764 | out: | ||
765 | dev_kfree_skb(skb); | ||
766 | if (ret) | ||
767 | wl1271_warning("cmd buld null data failed %d", ret); | ||
768 | |||
769 | return ret; | ||
770 | |||
777 | } | 771 | } |
778 | 772 | ||
779 | int wl1271_cmd_build_null_data(struct wl1271 *wl) | 773 | int wl1271_cmd_build_klv_null_data(struct wl1271 *wl) |
780 | { | 774 | { |
781 | struct wl12xx_null_data_template template; | 775 | struct sk_buff *skb = NULL; |
776 | int ret = -ENOMEM; | ||
782 | 777 | ||
783 | if (!is_zero_ether_addr(wl->bssid)) { | 778 | skb = ieee80211_nullfunc_get(wl->hw, wl->vif); |
784 | memcpy(template.header.da, wl->bssid, ETH_ALEN); | 779 | if (!skb) |
785 | memcpy(template.header.bssid, wl->bssid, ETH_ALEN); | 780 | goto out; |
786 | } else { | 781 | |
787 | memset(template.header.da, 0xff, ETH_ALEN); | 782 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, |
788 | memset(template.header.bssid, 0xff, ETH_ALEN); | 783 | skb->data, skb->len, |
789 | } | 784 | CMD_TEMPL_KLV_IDX_NULL_DATA, |
785 | WL1271_RATE_AUTOMATIC); | ||
790 | 786 | ||
791 | memcpy(template.header.sa, wl->mac_addr, ETH_ALEN); | 787 | out: |
792 | template.header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA | | 788 | dev_kfree_skb(skb); |
793 | IEEE80211_STYPE_NULLFUNC | | 789 | if (ret) |
794 | IEEE80211_FCTL_TODS); | 790 | wl1271_warning("cmd build klv null data failed %d", ret); |
795 | 791 | ||
796 | return wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, &template, | 792 | return ret; |
797 | sizeof(template)); | ||
798 | 793 | ||
799 | } | 794 | } |
800 | 795 | ||
801 | int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid) | 796 | int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid) |
802 | { | 797 | { |
803 | struct wl12xx_ps_poll_template template; | 798 | struct sk_buff *skb; |
804 | 799 | int ret = 0; | |
805 | memcpy(template.bssid, wl->bssid, ETH_ALEN); | ||
806 | memcpy(template.ta, wl->mac_addr, ETH_ALEN); | ||
807 | |||
808 | /* aid in PS-Poll has its two MSBs each set to 1 */ | ||
809 | template.aid = cpu_to_le16(1 << 15 | 1 << 14 | aid); | ||
810 | 800 | ||
811 | template.fc = cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL); | 801 | skb = ieee80211_pspoll_get(wl->hw, wl->vif); |
802 | if (!skb) | ||
803 | goto out; | ||
812 | 804 | ||
813 | return wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, &template, | 805 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, skb->data, |
814 | sizeof(template)); | 806 | skb->len, 0, wl->basic_rate); |
815 | 807 | ||
808 | out: | ||
809 | dev_kfree_skb(skb); | ||
810 | return ret; | ||
816 | } | 811 | } |
817 | 812 | ||
818 | int wl1271_cmd_build_probe_req(struct wl1271 *wl, u8 *ssid, size_t ssid_len, | 813 | int wl1271_cmd_build_probe_req(struct wl1271 *wl, |
819 | u8 band) | 814 | const u8 *ssid, size_t ssid_len, |
815 | const u8 *ie, size_t ie_len, u8 band) | ||
820 | { | 816 | { |
821 | struct wl12xx_probe_req_template template; | 817 | struct sk_buff *skb; |
822 | struct wl12xx_ie_rates *rates; | ||
823 | char *ptr; | ||
824 | u16 size; | ||
825 | int ret; | 818 | int ret; |
826 | 819 | ||
827 | ptr = (char *)&template; | 820 | skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len, |
828 | size = sizeof(struct ieee80211_header); | 821 | ie, ie_len); |
829 | 822 | if (!skb) { | |
830 | memset(template.header.da, 0xff, ETH_ALEN); | 823 | ret = -ENOMEM; |
831 | memset(template.header.bssid, 0xff, ETH_ALEN); | 824 | goto out; |
832 | memcpy(template.header.sa, wl->mac_addr, ETH_ALEN); | 825 | } |
833 | template.header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); | 826 | |
834 | 827 | wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", skb->data, skb->len); | |
835 | /* IEs */ | ||
836 | /* SSID */ | ||
837 | template.ssid.header.id = WLAN_EID_SSID; | ||
838 | template.ssid.header.len = ssid_len; | ||
839 | if (ssid_len && ssid) | ||
840 | memcpy(template.ssid.ssid, ssid, ssid_len); | ||
841 | size += sizeof(struct wl12xx_ie_header) + ssid_len; | ||
842 | ptr += size; | ||
843 | |||
844 | /* Basic Rates */ | ||
845 | rates = (struct wl12xx_ie_rates *)ptr; | ||
846 | rates->header.id = WLAN_EID_SUPP_RATES; | ||
847 | rates->header.len = wl1271_build_basic_rates(rates->rates, band); | ||
848 | size += sizeof(struct wl12xx_ie_header) + rates->header.len; | ||
849 | ptr += sizeof(struct wl12xx_ie_header) + rates->header.len; | ||
850 | |||
851 | /* Extended rates */ | ||
852 | rates = (struct wl12xx_ie_rates *)ptr; | ||
853 | rates->header.id = WLAN_EID_EXT_SUPP_RATES; | ||
854 | rates->header.len = wl1271_build_extended_rates(rates->rates, band); | ||
855 | size += sizeof(struct wl12xx_ie_header) + rates->header.len; | ||
856 | |||
857 | wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", &template, size); | ||
858 | 828 | ||
859 | if (band == IEEE80211_BAND_2GHZ) | 829 | if (band == IEEE80211_BAND_2GHZ) |
860 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, | 830 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, |
861 | &template, size); | 831 | skb->data, skb->len, 0, |
832 | wl->conf.tx.basic_rate); | ||
862 | else | 833 | else |
863 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, | 834 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, |
864 | &template, size); | 835 | skb->data, skb->len, 0, |
836 | wl->conf.tx.basic_rate_5); | ||
837 | |||
838 | out: | ||
839 | dev_kfree_skb(skb); | ||
865 | return ret; | 840 | return ret; |
866 | } | 841 | } |
867 | 842 | ||
843 | int wl1271_build_qos_null_data(struct wl1271 *wl) | ||
844 | { | ||
845 | struct ieee80211_qos_hdr template; | ||
846 | |||
847 | memset(&template, 0, sizeof(template)); | ||
848 | |||
849 | memcpy(template.addr1, wl->bssid, ETH_ALEN); | ||
850 | memcpy(template.addr2, wl->mac_addr, ETH_ALEN); | ||
851 | memcpy(template.addr3, wl->bssid, ETH_ALEN); | ||
852 | |||
853 | template.frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | | ||
854 | IEEE80211_STYPE_QOS_NULLFUNC | | ||
855 | IEEE80211_FCTL_TODS); | ||
856 | |||
857 | /* FIXME: not sure what priority to use here */ | ||
858 | template.qos_ctrl = cpu_to_le16(0); | ||
859 | |||
860 | return wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, &template, | ||
861 | sizeof(template), 0, | ||
862 | WL1271_RATE_AUTOMATIC); | ||
863 | } | ||
864 | |||
868 | int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id) | 865 | int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id) |
869 | { | 866 | { |
870 | struct wl1271_cmd_set_keys *cmd; | 867 | struct wl1271_cmd_set_keys *cmd; |
@@ -975,6 +972,10 @@ int wl1271_cmd_disconnect(struct wl1271 *wl) | |||
975 | goto out_free; | 972 | goto out_free; |
976 | } | 973 | } |
977 | 974 | ||
975 | ret = wl1271_cmd_wait_for_event(wl, DISCONNECT_EVENT_COMPLETE_ID); | ||
976 | if (ret < 0) | ||
977 | wl1271_error("cmd disconnect event completion error"); | ||
978 | |||
978 | out_free: | 979 | out_free: |
979 | kfree(cmd); | 980 | kfree(cmd); |
980 | 981 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h index 2dc06c73532b..00f78b7aa384 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h | |||
@@ -33,7 +33,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
33 | size_t res_len); | 33 | size_t res_len); |
34 | int wl1271_cmd_general_parms(struct wl1271 *wl); | 34 | int wl1271_cmd_general_parms(struct wl1271 *wl); |
35 | int wl1271_cmd_radio_parms(struct wl1271 *wl); | 35 | int wl1271_cmd_radio_parms(struct wl1271 *wl); |
36 | int wl1271_cmd_join(struct wl1271 *wl); | 36 | int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type); |
37 | int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); | 37 | int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); |
38 | int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); | 38 | int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); |
39 | int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); | 39 | int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); |
@@ -41,15 +41,18 @@ int wl1271_cmd_data_path(struct wl1271 *wl, bool enable); | |||
41 | int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send); | 41 | int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send); |
42 | int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, | 42 | int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, |
43 | size_t len); | 43 | size_t len); |
44 | int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, | 44 | int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, |
45 | u8 active_scan, u8 high_prio, u8 band, | 45 | const u8 *ie, size_t ie_len, u8 active_scan, |
46 | u8 probe_requests); | 46 | u8 high_prio, u8 band, u8 probe_requests); |
47 | int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, | 47 | int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, |
48 | void *buf, size_t buf_len); | 48 | void *buf, size_t buf_len, int index, u32 rates); |
49 | int wl1271_cmd_build_null_data(struct wl1271 *wl); | 49 | int wl1271_cmd_build_null_data(struct wl1271 *wl); |
50 | int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid); | 50 | int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid); |
51 | int wl1271_cmd_build_probe_req(struct wl1271 *wl, u8 *ssid, size_t ssid_len, | 51 | int wl1271_cmd_build_probe_req(struct wl1271 *wl, |
52 | u8 band); | 52 | const u8 *ssid, size_t ssid_len, |
53 | const u8 *ie, size_t ie_len, u8 band); | ||
54 | int wl1271_build_qos_null_data(struct wl1271 *wl); | ||
55 | int wl1271_cmd_build_klv_null_data(struct wl1271 *wl); | ||
53 | int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id); | 56 | int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id); |
54 | int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, | 57 | int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, |
55 | u8 key_size, const u8 *key, const u8 *addr, | 58 | u8 key_size, const u8 *key, const u8 *addr, |
@@ -99,6 +102,11 @@ enum wl1271_commands { | |||
99 | 102 | ||
100 | #define MAX_CMD_PARAMS 572 | 103 | #define MAX_CMD_PARAMS 572 |
101 | 104 | ||
105 | enum { | ||
106 | CMD_TEMPL_KLV_IDX_NULL_DATA = 0, | ||
107 | CMD_TEMPL_KLV_IDX_MAX = 4 | ||
108 | }; | ||
109 | |||
102 | enum cmd_templ { | 110 | enum cmd_templ { |
103 | CMD_TEMPL_NULL_DATA = 0, | 111 | CMD_TEMPL_NULL_DATA = 0, |
104 | CMD_TEMPL_BEACON, | 112 | CMD_TEMPL_BEACON, |
@@ -121,6 +129,7 @@ enum cmd_templ { | |||
121 | /* unit ms */ | 129 | /* unit ms */ |
122 | #define WL1271_COMMAND_TIMEOUT 2000 | 130 | #define WL1271_COMMAND_TIMEOUT 2000 |
123 | #define WL1271_CMD_TEMPL_MAX_SIZE 252 | 131 | #define WL1271_CMD_TEMPL_MAX_SIZE 252 |
132 | #define WL1271_EVENT_TIMEOUT 100 | ||
124 | 133 | ||
125 | struct wl1271_cmd_header { | 134 | struct wl1271_cmd_header { |
126 | __le16 id; | 135 | __le16 id; |
@@ -243,6 +252,8 @@ struct cmd_enabledisable_path { | |||
243 | u8 padding[3]; | 252 | u8 padding[3]; |
244 | } __attribute__ ((packed)); | 253 | } __attribute__ ((packed)); |
245 | 254 | ||
255 | #define WL1271_RATE_AUTOMATIC 0 | ||
256 | |||
246 | struct wl1271_cmd_template_set { | 257 | struct wl1271_cmd_template_set { |
247 | struct wl1271_cmd_header header; | 258 | struct wl1271_cmd_header header; |
248 | 259 | ||
@@ -509,6 +520,8 @@ enum wl1271_disconnect_type { | |||
509 | }; | 520 | }; |
510 | 521 | ||
511 | struct wl1271_cmd_disconnect { | 522 | struct wl1271_cmd_disconnect { |
523 | struct wl1271_cmd_header header; | ||
524 | |||
512 | __le32 rx_config_options; | 525 | __le32 rx_config_options; |
513 | __le32 rx_filter_options; | 526 | __le32 rx_filter_options; |
514 | 527 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h index 6f9e75cc5640..d76ae03762a3 100644 --- a/drivers/net/wireless/wl12xx/wl1271_conf.h +++ b/drivers/net/wireless/wl12xx/wl1271_conf.h | |||
@@ -65,110 +65,344 @@ enum { | |||
65 | CONF_HW_RATE_INDEX_MAX = CONF_HW_RATE_INDEX_54MBPS, | 65 | CONF_HW_RATE_INDEX_MAX = CONF_HW_RATE_INDEX_54MBPS, |
66 | }; | 66 | }; |
67 | 67 | ||
68 | struct conf_sg_settings { | 68 | enum { |
69 | CONF_HW_RXTX_RATE_MCS7 = 0, | ||
70 | CONF_HW_RXTX_RATE_MCS6, | ||
71 | CONF_HW_RXTX_RATE_MCS5, | ||
72 | CONF_HW_RXTX_RATE_MCS4, | ||
73 | CONF_HW_RXTX_RATE_MCS3, | ||
74 | CONF_HW_RXTX_RATE_MCS2, | ||
75 | CONF_HW_RXTX_RATE_MCS1, | ||
76 | CONF_HW_RXTX_RATE_MCS0, | ||
77 | CONF_HW_RXTX_RATE_54, | ||
78 | CONF_HW_RXTX_RATE_48, | ||
79 | CONF_HW_RXTX_RATE_36, | ||
80 | CONF_HW_RXTX_RATE_24, | ||
81 | CONF_HW_RXTX_RATE_22, | ||
82 | CONF_HW_RXTX_RATE_18, | ||
83 | CONF_HW_RXTX_RATE_12, | ||
84 | CONF_HW_RXTX_RATE_11, | ||
85 | CONF_HW_RXTX_RATE_9, | ||
86 | CONF_HW_RXTX_RATE_6, | ||
87 | CONF_HW_RXTX_RATE_5_5, | ||
88 | CONF_HW_RXTX_RATE_2, | ||
89 | CONF_HW_RXTX_RATE_1, | ||
90 | CONF_HW_RXTX_RATE_MAX, | ||
91 | CONF_HW_RXTX_RATE_UNSUPPORTED = 0xff | ||
92 | }; | ||
93 | |||
94 | enum { | ||
95 | CONF_SG_DISABLE = 0, | ||
96 | CONF_SG_PROTECTIVE, | ||
97 | CONF_SG_OPPORTUNISTIC | ||
98 | }; | ||
99 | |||
100 | enum { | ||
69 | /* | 101 | /* |
70 | * Defines the PER threshold in PPM of the BT voice of which reaching | 102 | * PER threshold in PPM of the BT voice |
71 | * this value will trigger raising the priority of the BT voice by | ||
72 | * the BT IP until next NFS sample interval time as defined in | ||
73 | * nfs_sample_interval. | ||
74 | * | 103 | * |
75 | * Unit: PER value in PPM (parts per million) | 104 | * Range: 0 - 10000000 |
76 | * #Error_packets / #Total_packets | 105 | */ |
106 | CONF_SG_BT_PER_THRESHOLD = 0, | ||
77 | 107 | ||
78 | * Range: u32 | 108 | /* |
109 | * Number of consequent RX_ACTIVE activities to override BT voice | ||
110 | * frames to ensure WLAN connection | ||
111 | * | ||
112 | * Range: 0 - 100 | ||
113 | */ | ||
114 | CONF_SG_HV3_MAX_OVERRIDE, | ||
115 | |||
116 | /* | ||
117 | * Defines the PER threshold of the BT voice | ||
118 | * | ||
119 | * Range: 0 - 65000 | ||
120 | */ | ||
121 | CONF_SG_BT_NFS_SAMPLE_INTERVAL, | ||
122 | |||
123 | /* | ||
124 | * Defines the load ratio of BT | ||
125 | * | ||
126 | * Range: 0 - 100 (%) | ||
127 | */ | ||
128 | CONF_SG_BT_LOAD_RATIO, | ||
129 | |||
130 | /* | ||
131 | * Defines whether the SG will force WLAN host to enter/exit PSM | ||
132 | * | ||
133 | * Range: 1 - SG can force, 0 - host handles PSM | ||
134 | */ | ||
135 | CONF_SG_AUTO_PS_MODE, | ||
136 | |||
137 | /* | ||
138 | * Compensation percentage of probe requests when scan initiated | ||
139 | * during BT voice/ACL link. | ||
140 | * | ||
141 | * Range: 0 - 255 (%) | ||
142 | */ | ||
143 | CONF_SG_AUTO_SCAN_PROBE_REQ, | ||
144 | |||
145 | /* | ||
146 | * Compensation percentage of probe requests when active scan initiated | ||
147 | * during BT voice | ||
148 | * | ||
149 | * Range: 0 - 255 (%) | ||
150 | */ | ||
151 | CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3, | ||
152 | |||
153 | /* | ||
154 | * Defines antenna configuration (single/dual antenna) | ||
155 | * | ||
156 | * Range: 0 - single antenna, 1 - dual antenna | ||
157 | */ | ||
158 | CONF_SG_ANTENNA_CONFIGURATION, | ||
159 | |||
160 | /* | ||
161 | * The threshold (percent) of max consequtive beacon misses before | ||
162 | * increasing priority of beacon reception. | ||
163 | * | ||
164 | * Range: 0 - 100 (%) | ||
165 | */ | ||
166 | CONF_SG_BEACON_MISS_PERCENT, | ||
167 | |||
168 | /* | ||
169 | * The rate threshold below which receiving a data frame from the AP | ||
170 | * will increase the priority of the data frame above BT traffic. | ||
171 | * | ||
172 | * Range: 0,2, 5(=5.5), 6, 9, 11, 12, 18, 24, 36, 48, 54 | ||
173 | */ | ||
174 | CONF_SG_RATE_ADAPT_THRESH, | ||
175 | |||
176 | /* | ||
177 | * Not used currently. | ||
178 | * | ||
179 | * Range: 0 | ||
180 | */ | ||
181 | CONF_SG_RATE_ADAPT_SNR, | ||
182 | |||
183 | /* | ||
184 | * Configure the min and max time BT gains the antenna | ||
185 | * in WLAN PSM / BT master basic rate | ||
186 | * | ||
187 | * Range: 0 - 255 (ms) | ||
79 | */ | 188 | */ |
80 | u32 per_threshold; | 189 | CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_BR, |
190 | CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_BR, | ||
81 | 191 | ||
82 | /* | 192 | /* |
83 | * This value is an absolute time in micro-seconds to limit the | 193 | * The time after it expires no new WLAN trigger frame is trasmitted |
84 | * maximum scan duration compensation while in SG | 194 | * in WLAN PSM / BT master basic rate |
195 | * | ||
196 | * Range: 0 - 255 (ms) | ||
85 | */ | 197 | */ |
86 | u32 max_scan_compensation_time; | 198 | CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_BR, |
87 | 199 | ||
88 | /* Defines the PER threshold of the BT voice of which reaching this | 200 | /* |
89 | * value will trigger raising the priority of the BT voice until next | 201 | * Configure the min and max time BT gains the antenna |
90 | * NFS sample interval time as defined in sample_interval. | 202 | * in WLAN PSM / BT slave basic rate |
91 | * | 203 | * |
92 | * Unit: msec | 204 | * Range: 0 - 255 (ms) |
93 | * Range: 1-65000 | ||
94 | */ | 205 | */ |
95 | u16 nfs_sample_interval; | 206 | CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_BR, |
207 | CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_BR, | ||
96 | 208 | ||
97 | /* | 209 | /* |
98 | * Defines the load ratio for the BT. | 210 | * The time after it expires no new WLAN trigger frame is trasmitted |
99 | * The WLAN ratio is: 100 - load_ratio | 211 | * in WLAN PSM / BT slave basic rate |
100 | * | 212 | * |
101 | * Unit: Percent | 213 | * Range: 0 - 255 (ms) |
102 | * Range: 0-100 | ||
103 | */ | 214 | */ |
104 | u8 load_ratio; | 215 | CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_BR, |
105 | 216 | ||
106 | /* | 217 | /* |
107 | * true - Co-ex is allowed to enter/exit P.S automatically and | 218 | * Configure the min and max time BT gains the antenna |
108 | * transparently to the host | 219 | * in WLAN PSM / BT master EDR |
109 | * | 220 | * |
110 | * false - Co-ex is disallowed to enter/exit P.S and will trigger an | 221 | * Range: 0 - 255 (ms) |
111 | * event to the host to notify for the need to enter/exit P.S | 222 | */ |
112 | * due to BT change state | 223 | CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_EDR, |
224 | CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_EDR, | ||
225 | |||
226 | /* | ||
227 | * The time after it expires no new WLAN trigger frame is trasmitted | ||
228 | * in WLAN PSM / BT master EDR | ||
113 | * | 229 | * |
230 | * Range: 0 - 255 (ms) | ||
114 | */ | 231 | */ |
115 | u8 auto_ps_mode; | 232 | CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_EDR, |
116 | 233 | ||
117 | /* | 234 | /* |
118 | * This parameter defines the compensation percentage of num of probe | 235 | * Configure the min and max time BT gains the antenna |
119 | * requests in case scan is initiated during BT voice/BT ACL | 236 | * in WLAN PSM / BT slave EDR |
120 | * guaranteed link. | ||
121 | * | 237 | * |
122 | * Unit: Percent | 238 | * Range: 0 - 255 (ms) |
123 | * Range: 0-255 (0 - No compensation) | ||
124 | */ | 239 | */ |
125 | u8 probe_req_compensation; | 240 | CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_EDR, |
241 | CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_EDR, | ||
126 | 242 | ||
127 | /* | 243 | /* |
128 | * This parameter defines the compensation percentage of scan window | 244 | * The time after it expires no new WLAN trigger frame is trasmitted |
129 | * size in case scan is initiated during BT voice/BT ACL Guaranteed | 245 | * in WLAN PSM / BT slave EDR |
130 | * link. | ||
131 | * | 246 | * |
132 | * Unit: Percent | 247 | * Range: 0 - 255 (ms) |
133 | * Range: 0-255 (0 - No compensation) | ||
134 | */ | 248 | */ |
135 | u8 scan_window_compensation; | 249 | CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_EDR, |
136 | 250 | ||
137 | /* | 251 | /* |
138 | * Defines the antenna configuration. | 252 | * RX guard time before the beginning of a new BT voice frame during |
253 | * which no new WLAN trigger frame is transmitted. | ||
139 | * | 254 | * |
140 | * Range: 0 - Single Antenna; 1 - Dual Antenna | 255 | * Range: 0 - 100000 (us) |
141 | */ | 256 | */ |
142 | u8 antenna_config; | 257 | CONF_SG_RXT, |
143 | 258 | ||
144 | /* | 259 | /* |
145 | * The percent out of the Max consecutive beacon miss roaming trigger | 260 | * TX guard time before the beginning of a new BT voice frame during |
146 | * which is the threshold for raising the priority of beacon | 261 | * which no new WLAN frame is transmitted. |
147 | * reception. | ||
148 | * | 262 | * |
149 | * Range: 1-100 | 263 | * Range: 0 - 100000 (us) |
150 | * N = MaxConsecutiveBeaconMiss | ||
151 | * P = coexMaxConsecutiveBeaconMissPrecent | ||
152 | * Threshold = MIN( N-1, round(N * P / 100)) | ||
153 | */ | 264 | */ |
154 | u8 beacon_miss_threshold; | 265 | |
266 | CONF_SG_TXT, | ||
155 | 267 | ||
156 | /* | 268 | /* |
157 | * The RX rate threshold below which rate adaptation is assumed to be | 269 | * Enable adaptive RXT/TXT algorithm. If disabled, the host values |
158 | * occurring at the AP which will raise priority for ACTIVE_RX and RX | 270 | * will be utilized. |
159 | * SP. | ||
160 | * | 271 | * |
161 | * Range: HW_BIT_RATE_* | 272 | * Range: 0 - disable, 1 - enable |
162 | */ | 273 | */ |
163 | u32 rate_adaptation_threshold; | 274 | CONF_SG_ADAPTIVE_RXT_TXT, |
164 | 275 | ||
165 | /* | 276 | /* |
166 | * The SNR above which the RX rate threshold indicating AP rate | 277 | * The used WLAN legacy service period during active BT ACL link |
167 | * adaptation is valid | ||
168 | * | 278 | * |
169 | * Range: -128 - 127 | 279 | * Range: 0 - 255 (ms) |
170 | */ | 280 | */ |
171 | s8 rate_adaptation_snr; | 281 | CONF_SG_PS_POLL_TIMEOUT, |
282 | |||
283 | /* | ||
284 | * The used WLAN UPSD service period during active BT ACL link | ||
285 | * | ||
286 | * Range: 0 - 255 (ms) | ||
287 | */ | ||
288 | CONF_SG_UPSD_TIMEOUT, | ||
289 | |||
290 | /* | ||
291 | * Configure the min and max time BT gains the antenna | ||
292 | * in WLAN Active / BT master EDR | ||
293 | * | ||
294 | * Range: 0 - 255 (ms) | ||
295 | */ | ||
296 | CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MIN_EDR, | ||
297 | CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MAX_EDR, | ||
298 | |||
299 | /* | ||
300 | * The maximum time WLAN can gain the antenna for | ||
301 | * in WLAN Active / BT master EDR | ||
302 | * | ||
303 | * Range: 0 - 255 (ms) | ||
304 | */ | ||
305 | CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_MASTER_EDR, | ||
306 | |||
307 | /* | ||
308 | * Configure the min and max time BT gains the antenna | ||
309 | * in WLAN Active / BT slave EDR | ||
310 | * | ||
311 | * Range: 0 - 255 (ms) | ||
312 | */ | ||
313 | CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MIN_EDR, | ||
314 | CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MAX_EDR, | ||
315 | |||
316 | /* | ||
317 | * The maximum time WLAN can gain the antenna for | ||
318 | * in WLAN Active / BT slave EDR | ||
319 | * | ||
320 | * Range: 0 - 255 (ms) | ||
321 | */ | ||
322 | CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_SLAVE_EDR, | ||
323 | |||
324 | /* | ||
325 | * Configure the min and max time BT gains the antenna | ||
326 | * in WLAN Active / BT basic rate | ||
327 | * | ||
328 | * Range: 0 - 255 (ms) | ||
329 | */ | ||
330 | CONF_SG_WLAN_ACTIVE_BT_ACL_MIN_BR, | ||
331 | CONF_SG_WLAN_ACTIVE_BT_ACL_MAX_BR, | ||
332 | |||
333 | /* | ||
334 | * The maximum time WLAN can gain the antenna for | ||
335 | * in WLAN Active / BT basic rate | ||
336 | * | ||
337 | * Range: 0 - 255 (ms) | ||
338 | */ | ||
339 | CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_BR, | ||
340 | |||
341 | /* | ||
342 | * Compensation percentage of WLAN passive scan window if initiated | ||
343 | * during BT voice | ||
344 | * | ||
345 | * Range: 0 - 1000 (%) | ||
346 | */ | ||
347 | CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3, | ||
348 | |||
349 | /* | ||
350 | * Compensation percentage of WLAN passive scan window if initiated | ||
351 | * during BT A2DP | ||
352 | * | ||
353 | * Range: 0 - 1000 (%) | ||
354 | */ | ||
355 | CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP, | ||
356 | |||
357 | /* | ||
358 | * Fixed time ensured for BT traffic to gain the antenna during WLAN | ||
359 | * passive scan. | ||
360 | * | ||
361 | * Range: 0 - 1000 ms | ||
362 | */ | ||
363 | CONF_SG_PASSIVE_SCAN_A2DP_BT_TIME, | ||
364 | |||
365 | /* | ||
366 | * Fixed time ensured for WLAN traffic to gain the antenna during WLAN | ||
367 | * passive scan. | ||
368 | * | ||
369 | * Range: 0 - 1000 ms | ||
370 | */ | ||
371 | CONF_SG_PASSIVE_SCAN_A2DP_WLAN_TIME, | ||
372 | |||
373 | /* | ||
374 | * Number of consequent BT voice frames not interrupted by WLAN | ||
375 | * | ||
376 | * Range: 0 - 100 | ||
377 | */ | ||
378 | CONF_SG_HV3_MAX_SERVED, | ||
379 | |||
380 | /* | ||
381 | * Protection time of the DHCP procedure. | ||
382 | * | ||
383 | * Range: 0 - 100000 (ms) | ||
384 | */ | ||
385 | CONF_SG_DHCP_TIME, | ||
386 | |||
387 | /* | ||
388 | * Compensation percentage of WLAN active scan window if initiated | ||
389 | * during BT A2DP | ||
390 | * | ||
391 | * Range: 0 - 1000 (%) | ||
392 | */ | ||
393 | CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP, | ||
394 | CONF_SG_TEMP_PARAM_1, | ||
395 | CONF_SG_TEMP_PARAM_2, | ||
396 | CONF_SG_TEMP_PARAM_3, | ||
397 | CONF_SG_TEMP_PARAM_4, | ||
398 | CONF_SG_TEMP_PARAM_5, | ||
399 | CONF_SG_PARAMS_MAX, | ||
400 | CONF_SG_PARAMS_ALL = 0xff | ||
401 | }; | ||
402 | |||
403 | struct conf_sg_settings { | ||
404 | __le32 params[CONF_SG_PARAMS_MAX]; | ||
405 | u8 state; | ||
172 | }; | 406 | }; |
173 | 407 | ||
174 | enum conf_rx_queue_type { | 408 | enum conf_rx_queue_type { |
@@ -440,6 +674,19 @@ struct conf_tx_settings { | |||
440 | */ | 674 | */ |
441 | u16 tx_compl_threshold; | 675 | u16 tx_compl_threshold; |
442 | 676 | ||
677 | /* | ||
678 | * The rate used for control messages and scanning on the 2.4GHz band | ||
679 | * | ||
680 | * Range: CONF_HW_BIT_RATE_* bit mask | ||
681 | */ | ||
682 | u32 basic_rate; | ||
683 | |||
684 | /* | ||
685 | * The rate used for control messages and scanning on the 5GHz band | ||
686 | * | ||
687 | * Range: CONF_HW_BIT_RATE_* bit mask | ||
688 | */ | ||
689 | u32 basic_rate_5; | ||
443 | }; | 690 | }; |
444 | 691 | ||
445 | enum { | 692 | enum { |
@@ -721,6 +968,22 @@ struct conf_conn_settings { | |||
721 | * Range 0 - 255 | 968 | * Range 0 - 255 |
722 | */ | 969 | */ |
723 | u8 psm_entry_retries; | 970 | u8 psm_entry_retries; |
971 | |||
972 | /* | ||
973 | * | ||
974 | * Specifies the interval of the connection keep-alive null-func | ||
975 | * frame in ms. | ||
976 | * | ||
977 | * Range: 1000 - 3600000 | ||
978 | */ | ||
979 | u32 keep_alive_interval; | ||
980 | |||
981 | /* | ||
982 | * Maximum listen interval supported by the driver in units of beacons. | ||
983 | * | ||
984 | * Range: u16 | ||
985 | */ | ||
986 | u8 max_listen_interval; | ||
724 | }; | 987 | }; |
725 | 988 | ||
726 | enum { | 989 | enum { |
diff --git a/drivers/net/wireless/wl12xx/wl1271_debugfs.c b/drivers/net/wireless/wl12xx/wl1271_debugfs.c index 8d7588ca68fd..3c0f5b1ac272 100644 --- a/drivers/net/wireless/wl12xx/wl1271_debugfs.c +++ b/drivers/net/wireless/wl12xx/wl1271_debugfs.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include "wl1271.h" | 28 | #include "wl1271.h" |
29 | #include "wl1271_acx.h" | 29 | #include "wl1271_acx.h" |
30 | #include "wl1271_ps.h" | 30 | #include "wl1271_ps.h" |
31 | #include "wl1271_io.h" | ||
31 | 32 | ||
32 | /* ms */ | 33 | /* ms */ |
33 | #define WL1271_DEBUGFS_STATS_LIFETIME 1000 | 34 | #define WL1271_DEBUGFS_STATS_LIFETIME 1000 |
@@ -276,13 +277,10 @@ static ssize_t gpio_power_write(struct file *file, | |||
276 | goto out; | 277 | goto out; |
277 | } | 278 | } |
278 | 279 | ||
279 | if (value) { | 280 | if (value) |
280 | wl->set_power(true); | 281 | wl1271_power_on(wl); |
281 | set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | 282 | else |
282 | } else { | 283 | wl1271_power_off(wl); |
283 | wl->set_power(false); | ||
284 | clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
285 | } | ||
286 | 284 | ||
287 | out: | 285 | out: |
288 | mutex_unlock(&wl->mutex); | 286 | mutex_unlock(&wl->mutex); |
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c index 7468ef10194b..daacf176cf09 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.c +++ b/drivers/net/wireless/wl12xx/wl1271_event.c | |||
@@ -23,7 +23,6 @@ | |||
23 | 23 | ||
24 | #include "wl1271.h" | 24 | #include "wl1271.h" |
25 | #include "wl1271_reg.h" | 25 | #include "wl1271_reg.h" |
26 | #include "wl1271_spi.h" | ||
27 | #include "wl1271_io.h" | 26 | #include "wl1271_io.h" |
28 | #include "wl1271_event.h" | 27 | #include "wl1271_event.h" |
29 | #include "wl1271_ps.h" | 28 | #include "wl1271_ps.h" |
@@ -32,34 +31,24 @@ | |||
32 | static int wl1271_event_scan_complete(struct wl1271 *wl, | 31 | static int wl1271_event_scan_complete(struct wl1271 *wl, |
33 | struct event_mailbox *mbox) | 32 | struct event_mailbox *mbox) |
34 | { | 33 | { |
35 | int size = sizeof(struct wl12xx_probe_req_template); | ||
36 | wl1271_debug(DEBUG_EVENT, "status: 0x%x", | 34 | wl1271_debug(DEBUG_EVENT, "status: 0x%x", |
37 | mbox->scheduled_scan_status); | 35 | mbox->scheduled_scan_status); |
38 | 36 | ||
39 | if (test_bit(WL1271_FLAG_SCANNING, &wl->flags)) { | 37 | if (test_bit(WL1271_FLAG_SCANNING, &wl->flags)) { |
40 | if (wl->scan.state == WL1271_SCAN_BAND_DUAL) { | 38 | if (wl->scan.state == WL1271_SCAN_BAND_DUAL) { |
41 | wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, | ||
42 | NULL, size); | ||
43 | /* 2.4 GHz band scanned, scan 5 GHz band, pretend | 39 | /* 2.4 GHz band scanned, scan 5 GHz band, pretend |
44 | * to the wl1271_cmd_scan function that we are not | 40 | * to the wl1271_cmd_scan function that we are not |
45 | * scanning as it checks that. | 41 | * scanning as it checks that. |
46 | */ | 42 | */ |
47 | clear_bit(WL1271_FLAG_SCANNING, &wl->flags); | 43 | clear_bit(WL1271_FLAG_SCANNING, &wl->flags); |
44 | /* FIXME: ie missing! */ | ||
48 | wl1271_cmd_scan(wl, wl->scan.ssid, wl->scan.ssid_len, | 45 | wl1271_cmd_scan(wl, wl->scan.ssid, wl->scan.ssid_len, |
46 | NULL, 0, | ||
49 | wl->scan.active, | 47 | wl->scan.active, |
50 | wl->scan.high_prio, | 48 | wl->scan.high_prio, |
51 | WL1271_SCAN_BAND_5_GHZ, | 49 | WL1271_SCAN_BAND_5_GHZ, |
52 | wl->scan.probe_requests); | 50 | wl->scan.probe_requests); |
53 | } else { | 51 | } else { |
54 | if (wl->scan.state == WL1271_SCAN_BAND_2_4_GHZ) | ||
55 | wl1271_cmd_template_set(wl, | ||
56 | CMD_TEMPL_CFG_PROBE_REQ_2_4, | ||
57 | NULL, size); | ||
58 | else | ||
59 | wl1271_cmd_template_set(wl, | ||
60 | CMD_TEMPL_CFG_PROBE_REQ_5, | ||
61 | NULL, size); | ||
62 | |||
63 | mutex_unlock(&wl->mutex); | 52 | mutex_unlock(&wl->mutex); |
64 | ieee80211_scan_completed(wl->hw, false); | 53 | ieee80211_scan_completed(wl->hw, false); |
65 | mutex_lock(&wl->mutex); | 54 | mutex_lock(&wl->mutex); |
@@ -92,16 +81,9 @@ static int wl1271_event_ps_report(struct wl1271 *wl, | |||
92 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, | 81 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, |
93 | true); | 82 | true); |
94 | } else { | 83 | } else { |
95 | wl1271_error("PSM entry failed, giving up.\n"); | 84 | wl1271_info("No ack to nullfunc from AP."); |
96 | /* FIXME: this may need to be reconsidered. for now it | ||
97 | is not possible to indicate to the mac80211 | ||
98 | afterwards that PSM entry failed. To maximize | ||
99 | functionality (receiving data and remaining | ||
100 | associated) make sure that we are in sync with the | ||
101 | AP in regard of PSM mode. */ | ||
102 | ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, | ||
103 | false); | ||
104 | wl->psm_entry_retry = 0; | 85 | wl->psm_entry_retry = 0; |
86 | *beacon_loss = true; | ||
105 | } | 87 | } |
106 | break; | 88 | break; |
107 | case EVENT_ENTER_POWER_SAVE_SUCCESS: | 89 | case EVENT_ENTER_POWER_SAVE_SUCCESS: |
@@ -172,10 +154,13 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
172 | * The BSS_LOSE_EVENT_ID is only needed while psm (and hence beacon | 154 | * The BSS_LOSE_EVENT_ID is only needed while psm (and hence beacon |
173 | * filtering) is enabled. Without PSM, the stack will receive all | 155 | * filtering) is enabled. Without PSM, the stack will receive all |
174 | * beacons and can detect beacon loss by itself. | 156 | * beacons and can detect beacon loss by itself. |
157 | * | ||
158 | * As there's possibility that the driver disables PSM before receiving | ||
159 | * BSS_LOSE_EVENT, beacon loss has to be reported to the stack. | ||
160 | * | ||
175 | */ | 161 | */ |
176 | if (vector & BSS_LOSE_EVENT_ID && | 162 | if (vector & BSS_LOSE_EVENT_ID) { |
177 | test_bit(WL1271_FLAG_PSM, &wl->flags)) { | 163 | wl1271_info("Beacon loss detected."); |
178 | wl1271_debug(DEBUG_EVENT, "BSS_LOSE_EVENT"); | ||
179 | 164 | ||
180 | /* indicate to the stack, that beacons have been lost */ | 165 | /* indicate to the stack, that beacons have been lost */ |
181 | beacon_loss = true; | 166 | beacon_loss = true; |
@@ -188,16 +173,8 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
188 | return ret; | 173 | return ret; |
189 | } | 174 | } |
190 | 175 | ||
191 | if (wl->vif && beacon_loss) { | 176 | if (wl->vif && beacon_loss) |
192 | /* Obviously, it's dangerous to release the mutex while | 177 | ieee80211_connection_loss(wl->vif); |
193 | we are holding many of the variables in the wl struct. | ||
194 | That's why it's done last in the function, and care must | ||
195 | be taken that nothing more is done after this function | ||
196 | returns. */ | ||
197 | mutex_unlock(&wl->mutex); | ||
198 | ieee80211_beacon_loss(wl->vif); | ||
199 | mutex_lock(&wl->mutex); | ||
200 | } | ||
201 | 178 | ||
202 | return 0; | 179 | return 0; |
203 | } | 180 | } |
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c index 86c30a86a456..9ab336829044 100644 --- a/drivers/net/wireless/wl12xx/wl1271_init.c +++ b/drivers/net/wireless/wl12xx/wl1271_init.c | |||
@@ -51,50 +51,65 @@ static int wl1271_init_hwenc_config(struct wl1271 *wl) | |||
51 | 51 | ||
52 | int wl1271_init_templates_config(struct wl1271 *wl) | 52 | int wl1271_init_templates_config(struct wl1271 *wl) |
53 | { | 53 | { |
54 | int ret; | 54 | int ret, i; |
55 | 55 | ||
56 | /* send empty templates for fw memory reservation */ | 56 | /* send empty templates for fw memory reservation */ |
57 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL, | 57 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL, |
58 | sizeof(struct wl12xx_probe_req_template)); | 58 | sizeof(struct wl12xx_probe_req_template), |
59 | 0, WL1271_RATE_AUTOMATIC); | ||
59 | if (ret < 0) | 60 | if (ret < 0) |
60 | return ret; | 61 | return ret; |
61 | 62 | ||
62 | if (wl1271_11a_enabled()) { | 63 | if (wl1271_11a_enabled()) { |
64 | size_t size = sizeof(struct wl12xx_probe_req_template); | ||
63 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, | 65 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, |
64 | NULL, | 66 | NULL, size, 0, |
65 | sizeof(struct wl12xx_probe_req_template)); | 67 | WL1271_RATE_AUTOMATIC); |
66 | if (ret < 0) | 68 | if (ret < 0) |
67 | return ret; | 69 | return ret; |
68 | } | 70 | } |
69 | 71 | ||
70 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL, | 72 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL, |
71 | sizeof(struct wl12xx_null_data_template)); | 73 | sizeof(struct wl12xx_null_data_template), |
74 | 0, WL1271_RATE_AUTOMATIC); | ||
72 | if (ret < 0) | 75 | if (ret < 0) |
73 | return ret; | 76 | return ret; |
74 | 77 | ||
75 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, NULL, | 78 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, NULL, |
76 | sizeof(struct wl12xx_ps_poll_template)); | 79 | sizeof(struct wl12xx_ps_poll_template), |
80 | 0, WL1271_RATE_AUTOMATIC); | ||
77 | if (ret < 0) | 81 | if (ret < 0) |
78 | return ret; | 82 | return ret; |
79 | 83 | ||
80 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, NULL, | 84 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, NULL, |
81 | sizeof | 85 | sizeof |
82 | (struct wl12xx_qos_null_data_template)); | 86 | (struct wl12xx_qos_null_data_template), |
87 | 0, WL1271_RATE_AUTOMATIC); | ||
83 | if (ret < 0) | 88 | if (ret < 0) |
84 | return ret; | 89 | return ret; |
85 | 90 | ||
86 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, NULL, | 91 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, NULL, |
87 | sizeof | 92 | sizeof |
88 | (struct wl12xx_probe_resp_template)); | 93 | (struct wl12xx_probe_resp_template), |
94 | 0, WL1271_RATE_AUTOMATIC); | ||
89 | if (ret < 0) | 95 | if (ret < 0) |
90 | return ret; | 96 | return ret; |
91 | 97 | ||
92 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, NULL, | 98 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, NULL, |
93 | sizeof | 99 | sizeof |
94 | (struct wl12xx_beacon_template)); | 100 | (struct wl12xx_beacon_template), |
101 | 0, WL1271_RATE_AUTOMATIC); | ||
95 | if (ret < 0) | 102 | if (ret < 0) |
96 | return ret; | 103 | return ret; |
97 | 104 | ||
105 | for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) { | ||
106 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, NULL, | ||
107 | WL1271_CMD_TEMPL_MAX_SIZE, i, | ||
108 | WL1271_RATE_AUTOMATIC); | ||
109 | if (ret < 0) | ||
110 | return ret; | ||
111 | } | ||
112 | |||
98 | return 0; | 113 | return 0; |
99 | } | 114 | } |
100 | 115 | ||
@@ -160,11 +175,11 @@ int wl1271_init_pta(struct wl1271 *wl) | |||
160 | { | 175 | { |
161 | int ret; | 176 | int ret; |
162 | 177 | ||
163 | ret = wl1271_acx_sg_enable(wl); | 178 | ret = wl1271_acx_sg_cfg(wl); |
164 | if (ret < 0) | 179 | if (ret < 0) |
165 | return ret; | 180 | return ret; |
166 | 181 | ||
167 | ret = wl1271_acx_sg_cfg(wl); | 182 | ret = wl1271_acx_sg_enable(wl, wl->sg_enabled); |
168 | if (ret < 0) | 183 | if (ret < 0) |
169 | return ret; | 184 | return ret; |
170 | 185 | ||
@@ -236,7 +251,7 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
236 | goto out_free_memmap; | 251 | goto out_free_memmap; |
237 | 252 | ||
238 | /* Initialize connection monitoring thresholds */ | 253 | /* Initialize connection monitoring thresholds */ |
239 | ret = wl1271_acx_conn_monit_params(wl); | 254 | ret = wl1271_acx_conn_monit_params(wl, false); |
240 | if (ret < 0) | 255 | if (ret < 0) |
241 | goto out_free_memmap; | 256 | goto out_free_memmap; |
242 | 257 | ||
@@ -324,6 +339,19 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
324 | if (ret < 0) | 339 | if (ret < 0) |
325 | goto out_free_memmap; | 340 | goto out_free_memmap; |
326 | 341 | ||
342 | /* disable all keep-alive templates */ | ||
343 | for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) { | ||
344 | ret = wl1271_acx_keep_alive_config(wl, i, | ||
345 | ACX_KEEP_ALIVE_TPL_INVALID); | ||
346 | if (ret < 0) | ||
347 | goto out_free_memmap; | ||
348 | } | ||
349 | |||
350 | /* disable the keep-alive feature */ | ||
351 | ret = wl1271_acx_keep_alive_mode(wl, false); | ||
352 | if (ret < 0) | ||
353 | goto out_free_memmap; | ||
354 | |||
327 | return 0; | 355 | return 0; |
328 | 356 | ||
329 | out_free_memmap: | 357 | out_free_memmap: |
diff --git a/drivers/net/wireless/wl12xx/wl1271_io.c b/drivers/net/wireless/wl12xx/wl1271_io.c index 5cd94d5666c2..c8759acef131 100644 --- a/drivers/net/wireless/wl12xx/wl1271_io.c +++ b/drivers/net/wireless/wl12xx/wl1271_io.c | |||
@@ -28,30 +28,29 @@ | |||
28 | 28 | ||
29 | #include "wl1271.h" | 29 | #include "wl1271.h" |
30 | #include "wl12xx_80211.h" | 30 | #include "wl12xx_80211.h" |
31 | #include "wl1271_spi.h" | ||
32 | #include "wl1271_io.h" | 31 | #include "wl1271_io.h" |
33 | 32 | ||
34 | static int wl1271_translate_addr(struct wl1271 *wl, int addr) | 33 | #define OCP_CMD_LOOP 32 |
34 | |||
35 | #define OCP_CMD_WRITE 0x1 | ||
36 | #define OCP_CMD_READ 0x2 | ||
37 | |||
38 | #define OCP_READY_MASK BIT(18) | ||
39 | #define OCP_STATUS_MASK (BIT(16) | BIT(17)) | ||
40 | |||
41 | #define OCP_STATUS_NO_RESP 0x00000 | ||
42 | #define OCP_STATUS_OK 0x10000 | ||
43 | #define OCP_STATUS_REQ_FAILED 0x20000 | ||
44 | #define OCP_STATUS_RESP_ERROR 0x30000 | ||
45 | |||
46 | void wl1271_disable_interrupts(struct wl1271 *wl) | ||
35 | { | 47 | { |
36 | /* | 48 | wl->if_ops->disable_irq(wl); |
37 | * To translate, first check to which window of addresses the | 49 | } |
38 | * particular address belongs. Then subtract the starting address | 50 | |
39 | * of that window from the address. Then, add offset of the | 51 | void wl1271_enable_interrupts(struct wl1271 *wl) |
40 | * translated region. | 52 | { |
41 | * | 53 | wl->if_ops->enable_irq(wl); |
42 | * The translated regions occur next to each other in physical device | ||
43 | * memory, so just add the sizes of the preceeding address regions to | ||
44 | * get the offset to the new region. | ||
45 | * | ||
46 | * Currently, only the two first regions are addressed, and the | ||
47 | * assumption is that all addresses will fall into either of those | ||
48 | * two. | ||
49 | */ | ||
50 | if ((addr >= wl->part.reg.start) && | ||
51 | (addr < wl->part.reg.start + wl->part.reg.size)) | ||
52 | return addr - wl->part.reg.start + wl->part.mem.size; | ||
53 | else | ||
54 | return addr - wl->part.mem.start; | ||
55 | } | 54 | } |
56 | 55 | ||
57 | /* Set the SPI partitions to access the chip addresses | 56 | /* Set the SPI partitions to access the chip addresses |
@@ -117,54 +116,12 @@ int wl1271_set_partition(struct wl1271 *wl, | |||
117 | 116 | ||
118 | void wl1271_io_reset(struct wl1271 *wl) | 117 | void wl1271_io_reset(struct wl1271 *wl) |
119 | { | 118 | { |
120 | wl1271_spi_reset(wl); | 119 | wl->if_ops->reset(wl); |
121 | } | 120 | } |
122 | 121 | ||
123 | void wl1271_io_init(struct wl1271 *wl) | 122 | void wl1271_io_init(struct wl1271 *wl) |
124 | { | 123 | { |
125 | wl1271_spi_init(wl); | 124 | wl->if_ops->init(wl); |
126 | } | ||
127 | |||
128 | void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf, | ||
129 | size_t len, bool fixed) | ||
130 | { | ||
131 | wl1271_spi_raw_write(wl, addr, buf, len, fixed); | ||
132 | } | ||
133 | |||
134 | void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf, | ||
135 | size_t len, bool fixed) | ||
136 | { | ||
137 | wl1271_spi_raw_read(wl, addr, buf, len, fixed); | ||
138 | } | ||
139 | |||
140 | void wl1271_read(struct wl1271 *wl, int addr, void *buf, size_t len, | ||
141 | bool fixed) | ||
142 | { | ||
143 | int physical; | ||
144 | |||
145 | physical = wl1271_translate_addr(wl, addr); | ||
146 | |||
147 | wl1271_spi_raw_read(wl, physical, buf, len, fixed); | ||
148 | } | ||
149 | |||
150 | void wl1271_write(struct wl1271 *wl, int addr, void *buf, size_t len, | ||
151 | bool fixed) | ||
152 | { | ||
153 | int physical; | ||
154 | |||
155 | physical = wl1271_translate_addr(wl, addr); | ||
156 | |||
157 | wl1271_spi_raw_write(wl, physical, buf, len, fixed); | ||
158 | } | ||
159 | |||
160 | u32 wl1271_read32(struct wl1271 *wl, int addr) | ||
161 | { | ||
162 | return wl1271_raw_read32(wl, wl1271_translate_addr(wl, addr)); | ||
163 | } | ||
164 | |||
165 | void wl1271_write32(struct wl1271 *wl, int addr, u32 val) | ||
166 | { | ||
167 | wl1271_raw_write32(wl, wl1271_translate_addr(wl, addr), val); | ||
168 | } | 125 | } |
169 | 126 | ||
170 | void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val) | 127 | void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val) |
diff --git a/drivers/net/wireless/wl12xx/wl1271_io.h b/drivers/net/wireless/wl12xx/wl1271_io.h index fa9a0b35788f..d8837ef0bb40 100644 --- a/drivers/net/wireless/wl12xx/wl1271_io.h +++ b/drivers/net/wireless/wl12xx/wl1271_io.h | |||
@@ -25,31 +25,49 @@ | |||
25 | #ifndef __WL1271_IO_H__ | 25 | #ifndef __WL1271_IO_H__ |
26 | #define __WL1271_IO_H__ | 26 | #define __WL1271_IO_H__ |
27 | 27 | ||
28 | #include "wl1271_reg.h" | ||
29 | |||
30 | #define HW_ACCESS_MEMORY_MAX_RANGE 0x1FFC0 | ||
31 | |||
32 | #define HW_PARTITION_REGISTERS_ADDR 0x1FFC0 | ||
33 | #define HW_PART0_SIZE_ADDR (HW_PARTITION_REGISTERS_ADDR) | ||
34 | #define HW_PART0_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 4) | ||
35 | #define HW_PART1_SIZE_ADDR (HW_PARTITION_REGISTERS_ADDR + 8) | ||
36 | #define HW_PART1_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 12) | ||
37 | #define HW_PART2_SIZE_ADDR (HW_PARTITION_REGISTERS_ADDR + 16) | ||
38 | #define HW_PART2_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 20) | ||
39 | #define HW_PART3_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 24) | ||
40 | |||
41 | #define HW_ACCESS_REGISTER_SIZE 4 | ||
42 | |||
43 | #define HW_ACCESS_PRAM_MAX_RANGE 0x3c000 | ||
44 | |||
28 | struct wl1271; | 45 | struct wl1271; |
29 | 46 | ||
47 | void wl1271_disable_interrupts(struct wl1271 *wl); | ||
48 | void wl1271_enable_interrupts(struct wl1271 *wl); | ||
49 | |||
30 | void wl1271_io_reset(struct wl1271 *wl); | 50 | void wl1271_io_reset(struct wl1271 *wl); |
31 | void wl1271_io_init(struct wl1271 *wl); | 51 | void wl1271_io_init(struct wl1271 *wl); |
32 | 52 | ||
33 | /* Raw target IO, address is not translated */ | 53 | static inline struct device *wl1271_wl_to_dev(struct wl1271 *wl) |
34 | void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf, | 54 | { |
35 | size_t len, bool fixed); | 55 | return wl->if_ops->dev(wl); |
36 | void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf, | 56 | } |
37 | size_t len, bool fixed); | ||
38 | 57 | ||
39 | /* Translated target IO */ | ||
40 | void wl1271_read(struct wl1271 *wl, int addr, void *buf, size_t len, | ||
41 | bool fixed); | ||
42 | void wl1271_write(struct wl1271 *wl, int addr, void *buf, size_t len, | ||
43 | bool fixed); | ||
44 | u32 wl1271_read32(struct wl1271 *wl, int addr); | ||
45 | void wl1271_write32(struct wl1271 *wl, int addr, u32 val); | ||
46 | 58 | ||
47 | /* Top Register IO */ | 59 | /* Raw target IO, address is not translated */ |
48 | void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val); | 60 | static inline void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf, |
49 | u16 wl1271_top_reg_read(struct wl1271 *wl, int addr); | 61 | size_t len, bool fixed) |
62 | { | ||
63 | wl->if_ops->write(wl, addr, buf, len, fixed); | ||
64 | } | ||
50 | 65 | ||
51 | int wl1271_set_partition(struct wl1271 *wl, | 66 | static inline void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf, |
52 | struct wl1271_partition_set *p); | 67 | size_t len, bool fixed) |
68 | { | ||
69 | wl->if_ops->read(wl, addr, buf, len, fixed); | ||
70 | } | ||
53 | 71 | ||
54 | static inline u32 wl1271_raw_read32(struct wl1271 *wl, int addr) | 72 | static inline u32 wl1271_raw_read32(struct wl1271 *wl, int addr) |
55 | { | 73 | { |
@@ -65,4 +83,87 @@ static inline void wl1271_raw_write32(struct wl1271 *wl, int addr, u32 val) | |||
65 | wl1271_raw_write(wl, addr, &wl->buffer_32, | 83 | wl1271_raw_write(wl, addr, &wl->buffer_32, |
66 | sizeof(wl->buffer_32), false); | 84 | sizeof(wl->buffer_32), false); |
67 | } | 85 | } |
86 | |||
87 | /* Translated target IO */ | ||
88 | static inline int wl1271_translate_addr(struct wl1271 *wl, int addr) | ||
89 | { | ||
90 | /* | ||
91 | * To translate, first check to which window of addresses the | ||
92 | * particular address belongs. Then subtract the starting address | ||
93 | * of that window from the address. Then, add offset of the | ||
94 | * translated region. | ||
95 | * | ||
96 | * The translated regions occur next to each other in physical device | ||
97 | * memory, so just add the sizes of the preceeding address regions to | ||
98 | * get the offset to the new region. | ||
99 | * | ||
100 | * Currently, only the two first regions are addressed, and the | ||
101 | * assumption is that all addresses will fall into either of those | ||
102 | * two. | ||
103 | */ | ||
104 | if ((addr >= wl->part.reg.start) && | ||
105 | (addr < wl->part.reg.start + wl->part.reg.size)) | ||
106 | return addr - wl->part.reg.start + wl->part.mem.size; | ||
107 | else | ||
108 | return addr - wl->part.mem.start; | ||
109 | } | ||
110 | |||
111 | static inline void wl1271_read(struct wl1271 *wl, int addr, void *buf, | ||
112 | size_t len, bool fixed) | ||
113 | { | ||
114 | int physical; | ||
115 | |||
116 | physical = wl1271_translate_addr(wl, addr); | ||
117 | |||
118 | wl1271_raw_read(wl, physical, buf, len, fixed); | ||
119 | } | ||
120 | |||
121 | static inline void wl1271_write(struct wl1271 *wl, int addr, void *buf, | ||
122 | size_t len, bool fixed) | ||
123 | { | ||
124 | int physical; | ||
125 | |||
126 | physical = wl1271_translate_addr(wl, addr); | ||
127 | |||
128 | wl1271_raw_write(wl, physical, buf, len, fixed); | ||
129 | } | ||
130 | |||
131 | static inline u32 wl1271_read32(struct wl1271 *wl, int addr) | ||
132 | { | ||
133 | return wl1271_raw_read32(wl, wl1271_translate_addr(wl, addr)); | ||
134 | } | ||
135 | |||
136 | static inline void wl1271_write32(struct wl1271 *wl, int addr, u32 val) | ||
137 | { | ||
138 | wl1271_raw_write32(wl, wl1271_translate_addr(wl, addr), val); | ||
139 | } | ||
140 | |||
141 | static inline void wl1271_power_off(struct wl1271 *wl) | ||
142 | { | ||
143 | wl->if_ops->power(wl, false); | ||
144 | clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
145 | } | ||
146 | |||
147 | static inline void wl1271_power_on(struct wl1271 *wl) | ||
148 | { | ||
149 | wl->if_ops->power(wl, true); | ||
150 | set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
151 | } | ||
152 | |||
153 | |||
154 | /* Top Register IO */ | ||
155 | void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val); | ||
156 | u16 wl1271_top_reg_read(struct wl1271 *wl, int addr); | ||
157 | |||
158 | int wl1271_set_partition(struct wl1271 *wl, | ||
159 | struct wl1271_partition_set *p); | ||
160 | |||
161 | /* Functions from wl1271_main.c */ | ||
162 | |||
163 | int wl1271_register_hw(struct wl1271 *wl); | ||
164 | void wl1271_unregister_hw(struct wl1271 *wl); | ||
165 | int wl1271_init_ieee80211(struct wl1271 *wl); | ||
166 | struct ieee80211_hw *wl1271_alloc_hw(void); | ||
167 | int wl1271_free_hw(struct wl1271 *wl); | ||
168 | |||
68 | #endif | 169 | #endif |
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 2a864b24291d..5c32d8d72361 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c | |||
@@ -22,22 +22,18 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/interrupt.h> | ||
27 | #include <linux/firmware.h> | 25 | #include <linux/firmware.h> |
28 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
29 | #include <linux/irq.h> | ||
30 | #include <linux/spi/spi.h> | 27 | #include <linux/spi/spi.h> |
31 | #include <linux/crc32.h> | 28 | #include <linux/crc32.h> |
32 | #include <linux/etherdevice.h> | 29 | #include <linux/etherdevice.h> |
33 | #include <linux/vmalloc.h> | 30 | #include <linux/vmalloc.h> |
34 | #include <linux/spi/wl12xx.h> | ||
35 | #include <linux/inetdevice.h> | 31 | #include <linux/inetdevice.h> |
32 | #include <linux/platform_device.h> | ||
36 | 33 | ||
37 | #include "wl1271.h" | 34 | #include "wl1271.h" |
38 | #include "wl12xx_80211.h" | 35 | #include "wl12xx_80211.h" |
39 | #include "wl1271_reg.h" | 36 | #include "wl1271_reg.h" |
40 | #include "wl1271_spi.h" | ||
41 | #include "wl1271_io.h" | 37 | #include "wl1271_io.h" |
42 | #include "wl1271_event.h" | 38 | #include "wl1271_event.h" |
43 | #include "wl1271_tx.h" | 39 | #include "wl1271_tx.h" |
@@ -53,17 +49,57 @@ | |||
53 | 49 | ||
54 | static struct conf_drv_settings default_conf = { | 50 | static struct conf_drv_settings default_conf = { |
55 | .sg = { | 51 | .sg = { |
56 | .per_threshold = 7500, | 52 | .params = { |
57 | .max_scan_compensation_time = 120000, | 53 | [CONF_SG_BT_PER_THRESHOLD] = 7500, |
58 | .nfs_sample_interval = 400, | 54 | [CONF_SG_HV3_MAX_OVERRIDE] = 0, |
59 | .load_ratio = 50, | 55 | [CONF_SG_BT_NFS_SAMPLE_INTERVAL] = 400, |
60 | .auto_ps_mode = 0, | 56 | [CONF_SG_BT_LOAD_RATIO] = 50, |
61 | .probe_req_compensation = 170, | 57 | [CONF_SG_AUTO_PS_MODE] = 0, |
62 | .scan_window_compensation = 50, | 58 | [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170, |
63 | .antenna_config = 0, | 59 | [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50, |
64 | .beacon_miss_threshold = 60, | 60 | [CONF_SG_ANTENNA_CONFIGURATION] = 0, |
65 | .rate_adaptation_threshold = CONF_HW_BIT_RATE_12MBPS, | 61 | [CONF_SG_BEACON_MISS_PERCENT] = 60, |
66 | .rate_adaptation_snr = 0 | 62 | [CONF_SG_RATE_ADAPT_THRESH] = 12, |
63 | [CONF_SG_RATE_ADAPT_SNR] = 0, | ||
64 | [CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_BR] = 10, | ||
65 | [CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_BR] = 30, | ||
66 | [CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_BR] = 8, | ||
67 | [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_BR] = 20, | ||
68 | [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_BR] = 50, | ||
69 | /* Note: with UPSD, this should be 4 */ | ||
70 | [CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_BR] = 8, | ||
71 | [CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_EDR] = 7, | ||
72 | [CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_EDR] = 25, | ||
73 | [CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_EDR] = 20, | ||
74 | /* Note: with UPDS, this should be 15 */ | ||
75 | [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_EDR] = 8, | ||
76 | /* Note: with UPDS, this should be 50 */ | ||
77 | [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_EDR] = 40, | ||
78 | /* Note: with UPDS, this should be 10 */ | ||
79 | [CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_EDR] = 20, | ||
80 | [CONF_SG_RXT] = 1200, | ||
81 | [CONF_SG_TXT] = 1000, | ||
82 | [CONF_SG_ADAPTIVE_RXT_TXT] = 1, | ||
83 | [CONF_SG_PS_POLL_TIMEOUT] = 10, | ||
84 | [CONF_SG_UPSD_TIMEOUT] = 10, | ||
85 | [CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MIN_EDR] = 7, | ||
86 | [CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MAX_EDR] = 15, | ||
87 | [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_MASTER_EDR] = 15, | ||
88 | [CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MIN_EDR] = 8, | ||
89 | [CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MAX_EDR] = 20, | ||
90 | [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_SLAVE_EDR] = 15, | ||
91 | [CONF_SG_WLAN_ACTIVE_BT_ACL_MIN_BR] = 20, | ||
92 | [CONF_SG_WLAN_ACTIVE_BT_ACL_MAX_BR] = 50, | ||
93 | [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_BR] = 10, | ||
94 | [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3] = 200, | ||
95 | [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP] = 800, | ||
96 | [CONF_SG_PASSIVE_SCAN_A2DP_BT_TIME] = 75, | ||
97 | [CONF_SG_PASSIVE_SCAN_A2DP_WLAN_TIME] = 15, | ||
98 | [CONF_SG_HV3_MAX_SERVED] = 6, | ||
99 | [CONF_SG_DHCP_TIME] = 5000, | ||
100 | [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100, | ||
101 | }, | ||
102 | .state = CONF_SG_PROTECTIVE, | ||
67 | }, | 103 | }, |
68 | .rx = { | 104 | .rx = { |
69 | .rx_msdu_life_time = 512000, | 105 | .rx_msdu_life_time = 512000, |
@@ -80,8 +116,7 @@ static struct conf_drv_settings default_conf = { | |||
80 | .tx = { | 116 | .tx = { |
81 | .tx_energy_detection = 0, | 117 | .tx_energy_detection = 0, |
82 | .rc_conf = { | 118 | .rc_conf = { |
83 | .enabled_rates = CONF_HW_BIT_RATE_1MBPS | | 119 | .enabled_rates = 0, |
84 | CONF_HW_BIT_RATE_2MBPS, | ||
85 | .short_retry_limit = 10, | 120 | .short_retry_limit = 10, |
86 | .long_retry_limit = 10, | 121 | .long_retry_limit = 10, |
87 | .aflags = 0 | 122 | .aflags = 0 |
@@ -178,11 +213,13 @@ static struct conf_drv_settings default_conf = { | |||
178 | }, | 213 | }, |
179 | .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD, | 214 | .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD, |
180 | .tx_compl_timeout = 700, | 215 | .tx_compl_timeout = 700, |
181 | .tx_compl_threshold = 4 | 216 | .tx_compl_threshold = 4, |
217 | .basic_rate = CONF_HW_BIT_RATE_1MBPS, | ||
218 | .basic_rate_5 = CONF_HW_BIT_RATE_6MBPS, | ||
182 | }, | 219 | }, |
183 | .conn = { | 220 | .conn = { |
184 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, | 221 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, |
185 | .listen_interval = 0, | 222 | .listen_interval = 1, |
186 | .bcn_filt_mode = CONF_BCN_FILT_MODE_ENABLED, | 223 | .bcn_filt_mode = CONF_BCN_FILT_MODE_ENABLED, |
187 | .bcn_filt_ie_count = 1, | 224 | .bcn_filt_ie_count = 1, |
188 | .bcn_filt_ie = { | 225 | .bcn_filt_ie = { |
@@ -228,7 +265,9 @@ static struct conf_drv_settings default_conf = { | |||
228 | }, | 265 | }, |
229 | .bet_enable = CONF_BET_MODE_ENABLE, | 266 | .bet_enable = CONF_BET_MODE_ENABLE, |
230 | .bet_max_consecutive = 10, | 267 | .bet_max_consecutive = 10, |
231 | .psm_entry_retries = 3 | 268 | .psm_entry_retries = 3, |
269 | .keep_alive_interval = 55000, | ||
270 | .max_listen_interval = 20, | ||
232 | }, | 271 | }, |
233 | .init = { | 272 | .init = { |
234 | .radioparam = { | 273 | .radioparam = { |
@@ -245,6 +284,21 @@ static struct conf_drv_settings default_conf = { | |||
245 | } | 284 | } |
246 | }; | 285 | }; |
247 | 286 | ||
287 | static void wl1271_device_release(struct device *dev) | ||
288 | { | ||
289 | |||
290 | } | ||
291 | |||
292 | static struct platform_device wl1271_device = { | ||
293 | .name = "wl1271", | ||
294 | .id = -1, | ||
295 | |||
296 | /* device model insists to have a release function */ | ||
297 | .dev = { | ||
298 | .release = wl1271_device_release, | ||
299 | }, | ||
300 | }; | ||
301 | |||
248 | static LIST_HEAD(wl_list); | 302 | static LIST_HEAD(wl_list); |
249 | 303 | ||
250 | static void wl1271_conf_init(struct wl1271 *wl) | 304 | static void wl1271_conf_init(struct wl1271 *wl) |
@@ -297,7 +351,7 @@ static int wl1271_plt_init(struct wl1271 *wl) | |||
297 | goto out_free_memmap; | 351 | goto out_free_memmap; |
298 | 352 | ||
299 | /* Initialize connection monitoring thresholds */ | 353 | /* Initialize connection monitoring thresholds */ |
300 | ret = wl1271_acx_conn_monit_params(wl); | 354 | ret = wl1271_acx_conn_monit_params(wl, false); |
301 | if (ret < 0) | 355 | if (ret < 0) |
302 | goto out_free_memmap; | 356 | goto out_free_memmap; |
303 | 357 | ||
@@ -364,30 +418,14 @@ static int wl1271_plt_init(struct wl1271 *wl) | |||
364 | return ret; | 418 | return ret; |
365 | } | 419 | } |
366 | 420 | ||
367 | static void wl1271_disable_interrupts(struct wl1271 *wl) | ||
368 | { | ||
369 | disable_irq(wl->irq); | ||
370 | } | ||
371 | |||
372 | static void wl1271_power_off(struct wl1271 *wl) | ||
373 | { | ||
374 | wl->set_power(false); | ||
375 | clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
376 | } | ||
377 | |||
378 | static void wl1271_power_on(struct wl1271 *wl) | ||
379 | { | ||
380 | wl->set_power(true); | ||
381 | set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
382 | } | ||
383 | |||
384 | static void wl1271_fw_status(struct wl1271 *wl, | 421 | static void wl1271_fw_status(struct wl1271 *wl, |
385 | struct wl1271_fw_status *status) | 422 | struct wl1271_fw_status *status) |
386 | { | 423 | { |
424 | struct timespec ts; | ||
387 | u32 total = 0; | 425 | u32 total = 0; |
388 | int i; | 426 | int i; |
389 | 427 | ||
390 | wl1271_read(wl, FW_STATUS_ADDR, status, sizeof(*status), false); | 428 | wl1271_raw_read(wl, FW_STATUS_ADDR, status, sizeof(*status), false); |
391 | 429 | ||
392 | wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " | 430 | wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " |
393 | "drv_rx_counter = %d, tx_results_counter = %d)", | 431 | "drv_rx_counter = %d, tx_results_counter = %d)", |
@@ -412,14 +450,19 @@ static void wl1271_fw_status(struct wl1271 *wl, | |||
412 | ieee80211_queue_work(wl->hw, &wl->tx_work); | 450 | ieee80211_queue_work(wl->hw, &wl->tx_work); |
413 | 451 | ||
414 | /* update the host-chipset time offset */ | 452 | /* update the host-chipset time offset */ |
415 | wl->time_offset = jiffies_to_usecs(jiffies) - | 453 | getnstimeofday(&ts); |
416 | le32_to_cpu(status->fw_localtime); | 454 | wl->time_offset = (timespec_to_ns(&ts) >> 10) - |
455 | (s64)le32_to_cpu(status->fw_localtime); | ||
417 | } | 456 | } |
418 | 457 | ||
458 | #define WL1271_IRQ_MAX_LOOPS 10 | ||
459 | |||
419 | static void wl1271_irq_work(struct work_struct *work) | 460 | static void wl1271_irq_work(struct work_struct *work) |
420 | { | 461 | { |
421 | int ret; | 462 | int ret; |
422 | u32 intr; | 463 | u32 intr; |
464 | int loopcount = WL1271_IRQ_MAX_LOOPS; | ||
465 | unsigned long flags; | ||
423 | struct wl1271 *wl = | 466 | struct wl1271 *wl = |
424 | container_of(work, struct wl1271, irq_work); | 467 | container_of(work, struct wl1271, irq_work); |
425 | 468 | ||
@@ -427,91 +470,77 @@ static void wl1271_irq_work(struct work_struct *work) | |||
427 | 470 | ||
428 | wl1271_debug(DEBUG_IRQ, "IRQ work"); | 471 | wl1271_debug(DEBUG_IRQ, "IRQ work"); |
429 | 472 | ||
430 | if (wl->state == WL1271_STATE_OFF) | 473 | if (unlikely(wl->state == WL1271_STATE_OFF)) |
431 | goto out; | 474 | goto out; |
432 | 475 | ||
433 | ret = wl1271_ps_elp_wakeup(wl, true); | 476 | ret = wl1271_ps_elp_wakeup(wl, true); |
434 | if (ret < 0) | 477 | if (ret < 0) |
435 | goto out; | 478 | goto out; |
436 | 479 | ||
437 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); | 480 | spin_lock_irqsave(&wl->wl_lock, flags); |
438 | 481 | while (test_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags) && loopcount) { | |
439 | wl1271_fw_status(wl, wl->fw_status); | 482 | clear_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags); |
440 | intr = le32_to_cpu(wl->fw_status->intr); | 483 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
441 | if (!intr) { | 484 | loopcount--; |
442 | wl1271_debug(DEBUG_IRQ, "Zero interrupt received."); | 485 | |
443 | goto out_sleep; | 486 | wl1271_fw_status(wl, wl->fw_status); |
444 | } | 487 | intr = le32_to_cpu(wl->fw_status->intr); |
488 | if (!intr) { | ||
489 | wl1271_debug(DEBUG_IRQ, "Zero interrupt received."); | ||
490 | continue; | ||
491 | } | ||
445 | 492 | ||
446 | intr &= WL1271_INTR_MASK; | 493 | intr &= WL1271_INTR_MASK; |
447 | 494 | ||
448 | if (intr & WL1271_ACX_INTR_EVENT_A) { | 495 | if (intr & WL1271_ACX_INTR_DATA) { |
449 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A"); | 496 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA"); |
450 | wl1271_event_handle(wl, 0); | ||
451 | } | ||
452 | 497 | ||
453 | if (intr & WL1271_ACX_INTR_EVENT_B) { | 498 | /* check for tx results */ |
454 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B"); | 499 | if (wl->fw_status->tx_results_counter != |
455 | wl1271_event_handle(wl, 1); | 500 | (wl->tx_results_count & 0xff)) |
456 | } | 501 | wl1271_tx_complete(wl); |
457 | 502 | ||
458 | if (intr & WL1271_ACX_INTR_INIT_COMPLETE) | 503 | wl1271_rx(wl, wl->fw_status); |
459 | wl1271_debug(DEBUG_IRQ, | 504 | } |
460 | "WL1271_ACX_INTR_INIT_COMPLETE"); | ||
461 | 505 | ||
462 | if (intr & WL1271_ACX_INTR_HW_AVAILABLE) | 506 | if (intr & WL1271_ACX_INTR_EVENT_A) { |
463 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_HW_AVAILABLE"); | 507 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A"); |
508 | wl1271_event_handle(wl, 0); | ||
509 | } | ||
464 | 510 | ||
465 | if (intr & WL1271_ACX_INTR_DATA) { | 511 | if (intr & WL1271_ACX_INTR_EVENT_B) { |
466 | u8 tx_res_cnt = wl->fw_status->tx_results_counter - | 512 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B"); |
467 | wl->tx_results_count; | 513 | wl1271_event_handle(wl, 1); |
514 | } | ||
468 | 515 | ||
469 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA"); | 516 | if (intr & WL1271_ACX_INTR_INIT_COMPLETE) |
517 | wl1271_debug(DEBUG_IRQ, | ||
518 | "WL1271_ACX_INTR_INIT_COMPLETE"); | ||
470 | 519 | ||
471 | /* check for tx results */ | 520 | if (intr & WL1271_ACX_INTR_HW_AVAILABLE) |
472 | if (tx_res_cnt) | 521 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_HW_AVAILABLE"); |
473 | wl1271_tx_complete(wl, tx_res_cnt); | ||
474 | 522 | ||
475 | wl1271_rx(wl, wl->fw_status); | 523 | spin_lock_irqsave(&wl->wl_lock, flags); |
476 | } | 524 | } |
477 | 525 | ||
478 | out_sleep: | 526 | if (test_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags)) |
479 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, | 527 | ieee80211_queue_work(wl->hw, &wl->irq_work); |
480 | WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); | 528 | else |
529 | clear_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags); | ||
530 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
531 | |||
481 | wl1271_ps_elp_sleep(wl); | 532 | wl1271_ps_elp_sleep(wl); |
482 | 533 | ||
483 | out: | 534 | out: |
484 | mutex_unlock(&wl->mutex); | 535 | mutex_unlock(&wl->mutex); |
485 | } | 536 | } |
486 | 537 | ||
487 | static irqreturn_t wl1271_irq(int irq, void *cookie) | ||
488 | { | ||
489 | struct wl1271 *wl; | ||
490 | unsigned long flags; | ||
491 | |||
492 | wl1271_debug(DEBUG_IRQ, "IRQ"); | ||
493 | |||
494 | wl = cookie; | ||
495 | |||
496 | /* complete the ELP completion */ | ||
497 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
498 | if (wl->elp_compl) { | ||
499 | complete(wl->elp_compl); | ||
500 | wl->elp_compl = NULL; | ||
501 | } | ||
502 | |||
503 | ieee80211_queue_work(wl->hw, &wl->irq_work); | ||
504 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
505 | |||
506 | return IRQ_HANDLED; | ||
507 | } | ||
508 | |||
509 | static int wl1271_fetch_firmware(struct wl1271 *wl) | 538 | static int wl1271_fetch_firmware(struct wl1271 *wl) |
510 | { | 539 | { |
511 | const struct firmware *fw; | 540 | const struct firmware *fw; |
512 | int ret; | 541 | int ret; |
513 | 542 | ||
514 | ret = request_firmware(&fw, WL1271_FW_NAME, &wl->spi->dev); | 543 | ret = request_firmware(&fw, WL1271_FW_NAME, wl1271_wl_to_dev(wl)); |
515 | 544 | ||
516 | if (ret < 0) { | 545 | if (ret < 0) { |
517 | wl1271_error("could not get firmware: %d", ret); | 546 | wl1271_error("could not get firmware: %d", ret); |
@@ -544,46 +573,12 @@ out: | |||
544 | return ret; | 573 | return ret; |
545 | } | 574 | } |
546 | 575 | ||
547 | static int wl1271_update_mac_addr(struct wl1271 *wl) | ||
548 | { | ||
549 | int ret = 0; | ||
550 | u8 *nvs_ptr = (u8 *)wl->nvs->nvs; | ||
551 | |||
552 | /* get mac address from the NVS */ | ||
553 | wl->mac_addr[0] = nvs_ptr[11]; | ||
554 | wl->mac_addr[1] = nvs_ptr[10]; | ||
555 | wl->mac_addr[2] = nvs_ptr[6]; | ||
556 | wl->mac_addr[3] = nvs_ptr[5]; | ||
557 | wl->mac_addr[4] = nvs_ptr[4]; | ||
558 | wl->mac_addr[5] = nvs_ptr[3]; | ||
559 | |||
560 | /* FIXME: if it is a zero-address, we should bail out. Now, instead, | ||
561 | we randomize an address */ | ||
562 | if (is_zero_ether_addr(wl->mac_addr)) { | ||
563 | static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf}; | ||
564 | memcpy(wl->mac_addr, nokia_oui, 3); | ||
565 | get_random_bytes(wl->mac_addr + 3, 3); | ||
566 | |||
567 | /* update this address to the NVS */ | ||
568 | nvs_ptr[11] = wl->mac_addr[0]; | ||
569 | nvs_ptr[10] = wl->mac_addr[1]; | ||
570 | nvs_ptr[6] = wl->mac_addr[2]; | ||
571 | nvs_ptr[5] = wl->mac_addr[3]; | ||
572 | nvs_ptr[4] = wl->mac_addr[4]; | ||
573 | nvs_ptr[3] = wl->mac_addr[5]; | ||
574 | } | ||
575 | |||
576 | SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr); | ||
577 | |||
578 | return ret; | ||
579 | } | ||
580 | |||
581 | static int wl1271_fetch_nvs(struct wl1271 *wl) | 576 | static int wl1271_fetch_nvs(struct wl1271 *wl) |
582 | { | 577 | { |
583 | const struct firmware *fw; | 578 | const struct firmware *fw; |
584 | int ret; | 579 | int ret; |
585 | 580 | ||
586 | ret = request_firmware(&fw, WL1271_NVS_NAME, &wl->spi->dev); | 581 | ret = request_firmware(&fw, WL1271_NVS_NAME, wl1271_wl_to_dev(wl)); |
587 | 582 | ||
588 | if (ret < 0) { | 583 | if (ret < 0) { |
589 | wl1271_error("could not get nvs file: %d", ret); | 584 | wl1271_error("could not get nvs file: %d", ret); |
@@ -607,8 +602,6 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) | |||
607 | 602 | ||
608 | memcpy(wl->nvs, fw->data, sizeof(struct wl1271_nvs_file)); | 603 | memcpy(wl->nvs, fw->data, sizeof(struct wl1271_nvs_file)); |
609 | 604 | ||
610 | ret = wl1271_update_mac_addr(wl); | ||
611 | |||
612 | out: | 605 | out: |
613 | release_firmware(fw); | 606 | release_firmware(fw); |
614 | 607 | ||
@@ -825,15 +818,13 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
825 | * The workqueue is slow to process the tx_queue and we need stop | 818 | * The workqueue is slow to process the tx_queue and we need stop |
826 | * the queue here, otherwise the queue will get too long. | 819 | * the queue here, otherwise the queue will get too long. |
827 | */ | 820 | */ |
828 | if (skb_queue_len(&wl->tx_queue) >= WL1271_TX_QUEUE_MAX_LENGTH) { | 821 | if (skb_queue_len(&wl->tx_queue) >= WL1271_TX_QUEUE_HIGH_WATERMARK) { |
829 | ieee80211_stop_queues(wl->hw); | 822 | wl1271_debug(DEBUG_TX, "op_tx: stopping queues"); |
830 | 823 | ||
831 | /* | 824 | spin_lock_irqsave(&wl->wl_lock, flags); |
832 | * FIXME: this is racy, the variable is not properly | 825 | ieee80211_stop_queues(wl->hw); |
833 | * protected. Maybe fix this by removing the stupid | ||
834 | * variable altogether and checking the real queue state? | ||
835 | */ | ||
836 | set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); | 826 | set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); |
827 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
837 | } | 828 | } |
838 | 829 | ||
839 | return NETDEV_TX_OK; | 830 | return NETDEV_TX_OK; |
@@ -928,13 +919,60 @@ static struct notifier_block wl1271_dev_notifier = { | |||
928 | 919 | ||
929 | static int wl1271_op_start(struct ieee80211_hw *hw) | 920 | static int wl1271_op_start(struct ieee80211_hw *hw) |
930 | { | 921 | { |
922 | wl1271_debug(DEBUG_MAC80211, "mac80211 start"); | ||
923 | |||
924 | /* | ||
925 | * We have to delay the booting of the hardware because | ||
926 | * we need to know the local MAC address before downloading and | ||
927 | * initializing the firmware. The MAC address cannot be changed | ||
928 | * after boot, and without the proper MAC address, the firmware | ||
929 | * will not function properly. | ||
930 | * | ||
931 | * The MAC address is first known when the corresponding interface | ||
932 | * is added. That is where we will initialize the hardware. | ||
933 | */ | ||
934 | |||
935 | return 0; | ||
936 | } | ||
937 | |||
938 | static void wl1271_op_stop(struct ieee80211_hw *hw) | ||
939 | { | ||
940 | wl1271_debug(DEBUG_MAC80211, "mac80211 stop"); | ||
941 | } | ||
942 | |||
943 | static int wl1271_op_add_interface(struct ieee80211_hw *hw, | ||
944 | struct ieee80211_vif *vif) | ||
945 | { | ||
931 | struct wl1271 *wl = hw->priv; | 946 | struct wl1271 *wl = hw->priv; |
932 | int retries = WL1271_BOOT_RETRIES; | 947 | int retries = WL1271_BOOT_RETRIES; |
933 | int ret = 0; | 948 | int ret = 0; |
934 | 949 | ||
935 | wl1271_debug(DEBUG_MAC80211, "mac80211 start"); | 950 | wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", |
951 | vif->type, vif->addr); | ||
936 | 952 | ||
937 | mutex_lock(&wl->mutex); | 953 | mutex_lock(&wl->mutex); |
954 | if (wl->vif) { | ||
955 | ret = -EBUSY; | ||
956 | goto out; | ||
957 | } | ||
958 | |||
959 | wl->vif = vif; | ||
960 | |||
961 | switch (vif->type) { | ||
962 | case NL80211_IFTYPE_STATION: | ||
963 | wl->bss_type = BSS_TYPE_STA_BSS; | ||
964 | wl->set_bss_type = BSS_TYPE_STA_BSS; | ||
965 | break; | ||
966 | case NL80211_IFTYPE_ADHOC: | ||
967 | wl->bss_type = BSS_TYPE_IBSS; | ||
968 | wl->set_bss_type = BSS_TYPE_STA_BSS; | ||
969 | break; | ||
970 | default: | ||
971 | ret = -EOPNOTSUPP; | ||
972 | goto out; | ||
973 | } | ||
974 | |||
975 | memcpy(wl->mac_addr, vif->addr, ETH_ALEN); | ||
938 | 976 | ||
939 | if (wl->state != WL1271_STATE_OFF) { | 977 | if (wl->state != WL1271_STATE_OFF) { |
940 | wl1271_error("cannot start because not in off state: %d", | 978 | wl1271_error("cannot start because not in off state: %d", |
@@ -990,19 +1028,20 @@ out: | |||
990 | return ret; | 1028 | return ret; |
991 | } | 1029 | } |
992 | 1030 | ||
993 | static void wl1271_op_stop(struct ieee80211_hw *hw) | 1031 | static void wl1271_op_remove_interface(struct ieee80211_hw *hw, |
1032 | struct ieee80211_vif *vif) | ||
994 | { | 1033 | { |
995 | struct wl1271 *wl = hw->priv; | 1034 | struct wl1271 *wl = hw->priv; |
996 | int i; | 1035 | int i; |
997 | 1036 | ||
998 | wl1271_info("down"); | ||
999 | |||
1000 | wl1271_debug(DEBUG_MAC80211, "mac80211 stop"); | ||
1001 | |||
1002 | unregister_inetaddr_notifier(&wl1271_dev_notifier); | 1037 | unregister_inetaddr_notifier(&wl1271_dev_notifier); |
1003 | list_del(&wl->list); | ||
1004 | 1038 | ||
1005 | mutex_lock(&wl->mutex); | 1039 | mutex_lock(&wl->mutex); |
1040 | wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); | ||
1041 | |||
1042 | wl1271_info("down"); | ||
1043 | |||
1044 | list_del(&wl->list); | ||
1006 | 1045 | ||
1007 | WARN_ON(wl->state != WL1271_STATE_ON); | 1046 | WARN_ON(wl->state != WL1271_STATE_ON); |
1008 | 1047 | ||
@@ -1031,6 +1070,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
1031 | memset(wl->ssid, 0, IW_ESSID_MAX_SIZE + 1); | 1070 | memset(wl->ssid, 0, IW_ESSID_MAX_SIZE + 1); |
1032 | wl->ssid_len = 0; | 1071 | wl->ssid_len = 0; |
1033 | wl->bss_type = MAX_BSS_TYPE; | 1072 | wl->bss_type = MAX_BSS_TYPE; |
1073 | wl->set_bss_type = MAX_BSS_TYPE; | ||
1034 | wl->band = IEEE80211_BAND_2GHZ; | 1074 | wl->band = IEEE80211_BAND_2GHZ; |
1035 | 1075 | ||
1036 | wl->rx_counter = 0; | 1076 | wl->rx_counter = 0; |
@@ -1040,13 +1080,14 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
1040 | wl->tx_results_count = 0; | 1080 | wl->tx_results_count = 0; |
1041 | wl->tx_packets_count = 0; | 1081 | wl->tx_packets_count = 0; |
1042 | wl->tx_security_last_seq = 0; | 1082 | wl->tx_security_last_seq = 0; |
1043 | wl->tx_security_seq_16 = 0; | 1083 | wl->tx_security_seq = 0; |
1044 | wl->tx_security_seq_32 = 0; | ||
1045 | wl->time_offset = 0; | 1084 | wl->time_offset = 0; |
1046 | wl->session_counter = 0; | 1085 | wl->session_counter = 0; |
1047 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; | 1086 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; |
1048 | wl->sta_rate_set = 0; | 1087 | wl->sta_rate_set = 0; |
1049 | wl->flags = 0; | 1088 | wl->flags = 0; |
1089 | wl->vif = NULL; | ||
1090 | wl->filters = 0; | ||
1050 | 1091 | ||
1051 | for (i = 0; i < NUM_TX_QUEUES; i++) | 1092 | for (i = 0; i < NUM_TX_QUEUES; i++) |
1052 | wl->tx_blocks_freed[i] = 0; | 1093 | wl->tx_blocks_freed[i] = 0; |
@@ -1055,119 +1096,39 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
1055 | mutex_unlock(&wl->mutex); | 1096 | mutex_unlock(&wl->mutex); |
1056 | } | 1097 | } |
1057 | 1098 | ||
1058 | static int wl1271_op_add_interface(struct ieee80211_hw *hw, | 1099 | static void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters) |
1059 | struct ieee80211_vif *vif) | ||
1060 | { | 1100 | { |
1061 | struct wl1271 *wl = hw->priv; | 1101 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; |
1062 | int ret = 0; | 1102 | wl->rx_filter = WL1271_DEFAULT_RX_FILTER; |
1063 | |||
1064 | wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", | ||
1065 | vif->type, vif->addr); | ||
1066 | 1103 | ||
1067 | mutex_lock(&wl->mutex); | 1104 | /* combine requested filters with current filter config */ |
1068 | if (wl->vif) { | 1105 | filters = wl->filters | filters; |
1069 | ret = -EBUSY; | ||
1070 | goto out; | ||
1071 | } | ||
1072 | 1106 | ||
1073 | wl->vif = vif; | 1107 | wl1271_debug(DEBUG_FILTERS, "RX filters set: "); |
1074 | 1108 | ||
1075 | switch (vif->type) { | 1109 | if (filters & FIF_PROMISC_IN_BSS) { |
1076 | case NL80211_IFTYPE_STATION: | 1110 | wl1271_debug(DEBUG_FILTERS, " - FIF_PROMISC_IN_BSS"); |
1077 | wl->bss_type = BSS_TYPE_STA_BSS; | 1111 | wl->rx_config &= ~CFG_UNI_FILTER_EN; |
1078 | break; | 1112 | wl->rx_config |= CFG_BSSID_FILTER_EN; |
1079 | case NL80211_IFTYPE_ADHOC: | ||
1080 | wl->bss_type = BSS_TYPE_IBSS; | ||
1081 | break; | ||
1082 | default: | ||
1083 | ret = -EOPNOTSUPP; | ||
1084 | goto out; | ||
1085 | } | 1113 | } |
1086 | 1114 | if (filters & FIF_BCN_PRBRESP_PROMISC) { | |
1087 | /* FIXME: what if conf->mac_addr changes? */ | 1115 | wl1271_debug(DEBUG_FILTERS, " - FIF_BCN_PRBRESP_PROMISC"); |
1088 | 1116 | wl->rx_config &= ~CFG_BSSID_FILTER_EN; | |
1089 | out: | 1117 | wl->rx_config &= ~CFG_SSID_FILTER_EN; |
1090 | mutex_unlock(&wl->mutex); | ||
1091 | return ret; | ||
1092 | } | ||
1093 | |||
1094 | static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | ||
1095 | struct ieee80211_vif *vif) | ||
1096 | { | ||
1097 | struct wl1271 *wl = hw->priv; | ||
1098 | |||
1099 | mutex_lock(&wl->mutex); | ||
1100 | wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); | ||
1101 | wl->vif = NULL; | ||
1102 | mutex_unlock(&wl->mutex); | ||
1103 | } | ||
1104 | |||
1105 | #if 0 | ||
1106 | static int wl1271_op_config_interface(struct ieee80211_hw *hw, | ||
1107 | struct ieee80211_vif *vif, | ||
1108 | struct ieee80211_if_conf *conf) | ||
1109 | { | ||
1110 | struct wl1271 *wl = hw->priv; | ||
1111 | struct sk_buff *beacon; | ||
1112 | int ret; | ||
1113 | |||
1114 | wl1271_debug(DEBUG_MAC80211, "mac80211 config_interface bssid %pM", | ||
1115 | conf->bssid); | ||
1116 | wl1271_dump_ascii(DEBUG_MAC80211, "ssid: ", conf->ssid, | ||
1117 | conf->ssid_len); | ||
1118 | |||
1119 | mutex_lock(&wl->mutex); | ||
1120 | |||
1121 | ret = wl1271_ps_elp_wakeup(wl, false); | ||
1122 | if (ret < 0) | ||
1123 | goto out; | ||
1124 | |||
1125 | if (memcmp(wl->bssid, conf->bssid, ETH_ALEN)) { | ||
1126 | wl1271_debug(DEBUG_MAC80211, "bssid changed"); | ||
1127 | |||
1128 | memcpy(wl->bssid, conf->bssid, ETH_ALEN); | ||
1129 | |||
1130 | ret = wl1271_cmd_join(wl); | ||
1131 | if (ret < 0) | ||
1132 | goto out_sleep; | ||
1133 | |||
1134 | ret = wl1271_cmd_build_null_data(wl); | ||
1135 | if (ret < 0) | ||
1136 | goto out_sleep; | ||
1137 | } | 1118 | } |
1138 | 1119 | if (filters & FIF_OTHER_BSS) { | |
1139 | wl->ssid_len = conf->ssid_len; | 1120 | wl1271_debug(DEBUG_FILTERS, " - FIF_OTHER_BSS"); |
1140 | if (wl->ssid_len) | 1121 | wl->rx_config &= ~CFG_BSSID_FILTER_EN; |
1141 | memcpy(wl->ssid, conf->ssid, wl->ssid_len); | 1122 | } |
1142 | 1123 | if (filters & FIF_CONTROL) { | |
1143 | if (conf->changed & IEEE80211_IFCC_BEACON) { | 1124 | wl1271_debug(DEBUG_FILTERS, " - FIF_CONTROL"); |
1144 | beacon = ieee80211_beacon_get(hw, vif); | 1125 | wl->rx_filter |= CFG_RX_CTL_EN; |
1145 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, | 1126 | } |
1146 | beacon->data, beacon->len); | 1127 | if (filters & FIF_FCSFAIL) { |
1147 | 1128 | wl1271_debug(DEBUG_FILTERS, " - FIF_FCSFAIL"); | |
1148 | if (ret < 0) { | 1129 | wl->rx_filter |= CFG_RX_FCS_ERROR; |
1149 | dev_kfree_skb(beacon); | ||
1150 | goto out_sleep; | ||
1151 | } | ||
1152 | |||
1153 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, | ||
1154 | beacon->data, beacon->len); | ||
1155 | |||
1156 | dev_kfree_skb(beacon); | ||
1157 | |||
1158 | if (ret < 0) | ||
1159 | goto out_sleep; | ||
1160 | } | 1130 | } |
1161 | |||
1162 | out_sleep: | ||
1163 | wl1271_ps_elp_sleep(wl); | ||
1164 | |||
1165 | out: | ||
1166 | mutex_unlock(&wl->mutex); | ||
1167 | |||
1168 | return ret; | ||
1169 | } | 1131 | } |
1170 | #endif | ||
1171 | 1132 | ||
1172 | static int wl1271_join_channel(struct wl1271 *wl, int channel) | 1133 | static int wl1271_join_channel(struct wl1271 *wl, int channel) |
1173 | { | 1134 | { |
@@ -1176,17 +1137,13 @@ static int wl1271_join_channel(struct wl1271 *wl, int channel) | |||
1176 | static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde, | 1137 | static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde, |
1177 | 0xad, 0xbe, 0xef }; | 1138 | 0xad, 0xbe, 0xef }; |
1178 | 1139 | ||
1179 | /* the dummy join is not required for ad-hoc */ | ||
1180 | if (wl->bss_type == BSS_TYPE_IBSS) | ||
1181 | goto out; | ||
1182 | |||
1183 | /* disable mac filter, so we hear everything */ | ||
1184 | wl->rx_config &= ~CFG_BSSID_FILTER_EN; | ||
1185 | |||
1186 | wl->channel = channel; | 1140 | wl->channel = channel; |
1187 | memcpy(wl->bssid, dummy_bssid, ETH_ALEN); | 1141 | memcpy(wl->bssid, dummy_bssid, ETH_ALEN); |
1188 | 1142 | ||
1189 | ret = wl1271_cmd_join(wl); | 1143 | /* pass through frames from all BSS */ |
1144 | wl1271_configure_filters(wl, FIF_OTHER_BSS); | ||
1145 | |||
1146 | ret = wl1271_cmd_join(wl, wl->set_bss_type); | ||
1190 | if (ret < 0) | 1147 | if (ret < 0) |
1191 | goto out; | 1148 | goto out; |
1192 | 1149 | ||
@@ -1208,12 +1165,40 @@ static int wl1271_unjoin_channel(struct wl1271 *wl) | |||
1208 | clear_bit(WL1271_FLAG_JOINED, &wl->flags); | 1165 | clear_bit(WL1271_FLAG_JOINED, &wl->flags); |
1209 | wl->channel = 0; | 1166 | wl->channel = 0; |
1210 | memset(wl->bssid, 0, ETH_ALEN); | 1167 | memset(wl->bssid, 0, ETH_ALEN); |
1211 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; | 1168 | |
1169 | /* stop filterting packets based on bssid */ | ||
1170 | wl1271_configure_filters(wl, FIF_OTHER_BSS); | ||
1212 | 1171 | ||
1213 | out: | 1172 | out: |
1214 | return ret; | 1173 | return ret; |
1215 | } | 1174 | } |
1216 | 1175 | ||
1176 | static void wl1271_set_band_rate(struct wl1271 *wl) | ||
1177 | { | ||
1178 | if (wl->band == IEEE80211_BAND_2GHZ) | ||
1179 | wl->basic_rate_set = wl->conf.tx.basic_rate; | ||
1180 | else | ||
1181 | wl->basic_rate_set = wl->conf.tx.basic_rate_5; | ||
1182 | } | ||
1183 | |||
1184 | static u32 wl1271_min_rate_get(struct wl1271 *wl) | ||
1185 | { | ||
1186 | int i; | ||
1187 | u32 rate = 0; | ||
1188 | |||
1189 | if (!wl->basic_rate_set) { | ||
1190 | WARN_ON(1); | ||
1191 | wl->basic_rate_set = wl->conf.tx.basic_rate; | ||
1192 | } | ||
1193 | |||
1194 | for (i = 0; !rate; i++) { | ||
1195 | if ((wl->basic_rate_set >> i) & 0x1) | ||
1196 | rate = 1 << i; | ||
1197 | } | ||
1198 | |||
1199 | return rate; | ||
1200 | } | ||
1201 | |||
1217 | static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | 1202 | static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) |
1218 | { | 1203 | { |
1219 | struct wl1271 *wl = hw->priv; | 1204 | struct wl1271 *wl = hw->priv; |
@@ -1230,12 +1215,38 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1230 | 1215 | ||
1231 | mutex_lock(&wl->mutex); | 1216 | mutex_lock(&wl->mutex); |
1232 | 1217 | ||
1233 | wl->band = conf->channel->band; | ||
1234 | |||
1235 | ret = wl1271_ps_elp_wakeup(wl, false); | 1218 | ret = wl1271_ps_elp_wakeup(wl, false); |
1236 | if (ret < 0) | 1219 | if (ret < 0) |
1237 | goto out; | 1220 | goto out; |
1238 | 1221 | ||
1222 | /* if the channel changes while joined, join again */ | ||
1223 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { | ||
1224 | wl->band = conf->channel->band; | ||
1225 | wl->channel = channel; | ||
1226 | |||
1227 | /* | ||
1228 | * FIXME: the mac80211 should really provide a fixed rate | ||
1229 | * to use here. for now, just use the smallest possible rate | ||
1230 | * for the band as a fixed rate for association frames and | ||
1231 | * other control messages. | ||
1232 | */ | ||
1233 | if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) | ||
1234 | wl1271_set_band_rate(wl); | ||
1235 | |||
1236 | wl->basic_rate = wl1271_min_rate_get(wl); | ||
1237 | ret = wl1271_acx_rate_policies(wl); | ||
1238 | if (ret < 0) | ||
1239 | wl1271_warning("rate policy for update channel " | ||
1240 | "failed %d", ret); | ||
1241 | |||
1242 | if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) { | ||
1243 | ret = wl1271_cmd_join(wl, wl->set_bss_type); | ||
1244 | if (ret < 0) | ||
1245 | wl1271_warning("cmd join to update channel " | ||
1246 | "failed %d", ret); | ||
1247 | } | ||
1248 | } | ||
1249 | |||
1239 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { | 1250 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { |
1240 | if (conf->flags & IEEE80211_CONF_IDLE && | 1251 | if (conf->flags & IEEE80211_CONF_IDLE && |
1241 | test_bit(WL1271_FLAG_JOINED, &wl->flags)) | 1252 | test_bit(WL1271_FLAG_JOINED, &wl->flags)) |
@@ -1244,24 +1255,15 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1244 | wl1271_join_channel(wl, channel); | 1255 | wl1271_join_channel(wl, channel); |
1245 | 1256 | ||
1246 | if (conf->flags & IEEE80211_CONF_IDLE) { | 1257 | if (conf->flags & IEEE80211_CONF_IDLE) { |
1247 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; | 1258 | wl->rate_set = wl1271_min_rate_get(wl); |
1248 | wl->sta_rate_set = 0; | 1259 | wl->sta_rate_set = 0; |
1249 | wl1271_acx_rate_policies(wl); | 1260 | wl1271_acx_rate_policies(wl); |
1261 | wl1271_acx_keep_alive_config( | ||
1262 | wl, CMD_TEMPL_KLV_IDX_NULL_DATA, | ||
1263 | ACX_KEEP_ALIVE_TPL_INVALID); | ||
1250 | } | 1264 | } |
1251 | } | 1265 | } |
1252 | 1266 | ||
1253 | /* if the channel changes while joined, join again */ | ||
1254 | if (channel != wl->channel && | ||
1255 | test_bit(WL1271_FLAG_JOINED, &wl->flags)) { | ||
1256 | wl->channel = channel; | ||
1257 | /* FIXME: maybe use CMD_CHANNEL_SWITCH for this? */ | ||
1258 | ret = wl1271_cmd_join(wl); | ||
1259 | if (ret < 0) | ||
1260 | wl1271_warning("cmd join to update channel failed %d", | ||
1261 | ret); | ||
1262 | } else | ||
1263 | wl->channel = channel; | ||
1264 | |||
1265 | if (conf->flags & IEEE80211_CONF_PS && | 1267 | if (conf->flags & IEEE80211_CONF_PS && |
1266 | !test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { | 1268 | !test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { |
1267 | set_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); | 1269 | set_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); |
@@ -1272,13 +1274,13 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1272 | * through the bss_info_changed() hook. | 1274 | * through the bss_info_changed() hook. |
1273 | */ | 1275 | */ |
1274 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { | 1276 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { |
1275 | wl1271_info("psm enabled"); | 1277 | wl1271_debug(DEBUG_PSM, "psm enabled"); |
1276 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, | 1278 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, |
1277 | true); | 1279 | true); |
1278 | } | 1280 | } |
1279 | } else if (!(conf->flags & IEEE80211_CONF_PS) && | 1281 | } else if (!(conf->flags & IEEE80211_CONF_PS) && |
1280 | test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { | 1282 | test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { |
1281 | wl1271_info("psm disabled"); | 1283 | wl1271_debug(DEBUG_PSM, "psm disabled"); |
1282 | 1284 | ||
1283 | clear_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); | 1285 | clear_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); |
1284 | 1286 | ||
@@ -1381,14 +1383,14 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw, | |||
1381 | if (ret < 0) | 1383 | if (ret < 0) |
1382 | goto out_sleep; | 1384 | goto out_sleep; |
1383 | 1385 | ||
1384 | kfree(fp); | ||
1385 | |||
1386 | /* FIXME: We still need to set our filters properly */ | ||
1387 | |||
1388 | /* determine, whether supported filter values have changed */ | 1386 | /* determine, whether supported filter values have changed */ |
1389 | if (changed == 0) | 1387 | if (changed == 0) |
1390 | goto out_sleep; | 1388 | goto out_sleep; |
1391 | 1389 | ||
1390 | /* configure filters */ | ||
1391 | wl->filters = *total; | ||
1392 | wl1271_configure_filters(wl, 0); | ||
1393 | |||
1392 | /* apply configured filters */ | 1394 | /* apply configured filters */ |
1393 | ret = wl1271_acx_rx_config(wl, wl->rx_config, wl->rx_filter); | 1395 | ret = wl1271_acx_rx_config(wl, wl->rx_config, wl->rx_filter); |
1394 | if (ret < 0) | 1396 | if (ret < 0) |
@@ -1399,6 +1401,7 @@ out_sleep: | |||
1399 | 1401 | ||
1400 | out: | 1402 | out: |
1401 | mutex_unlock(&wl->mutex); | 1403 | mutex_unlock(&wl->mutex); |
1404 | kfree(fp); | ||
1402 | } | 1405 | } |
1403 | 1406 | ||
1404 | static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | 1407 | static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, |
@@ -1449,15 +1452,15 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
1449 | key_type = KEY_TKIP; | 1452 | key_type = KEY_TKIP; |
1450 | 1453 | ||
1451 | key_conf->hw_key_idx = key_conf->keyidx; | 1454 | key_conf->hw_key_idx = key_conf->keyidx; |
1452 | tx_seq_32 = wl->tx_security_seq_32; | 1455 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq); |
1453 | tx_seq_16 = wl->tx_security_seq_16; | 1456 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); |
1454 | break; | 1457 | break; |
1455 | case ALG_CCMP: | 1458 | case ALG_CCMP: |
1456 | key_type = KEY_AES; | 1459 | key_type = KEY_AES; |
1457 | 1460 | ||
1458 | key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | 1461 | key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; |
1459 | tx_seq_32 = wl->tx_security_seq_32; | 1462 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq); |
1460 | tx_seq_16 = wl->tx_security_seq_16; | 1463 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); |
1461 | break; | 1464 | break; |
1462 | default: | 1465 | default: |
1463 | wl1271_error("Unknown key algo 0x%x", key_conf->alg); | 1466 | wl1271_error("Unknown key algo 0x%x", key_conf->alg); |
@@ -1544,10 +1547,12 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw, | |||
1544 | goto out; | 1547 | goto out; |
1545 | 1548 | ||
1546 | if (wl1271_11a_enabled()) | 1549 | if (wl1271_11a_enabled()) |
1547 | ret = wl1271_cmd_scan(hw->priv, ssid, len, 1, 0, | 1550 | ret = wl1271_cmd_scan(hw->priv, ssid, len, |
1551 | req->ie, req->ie_len, 1, 0, | ||
1548 | WL1271_SCAN_BAND_DUAL, 3); | 1552 | WL1271_SCAN_BAND_DUAL, 3); |
1549 | else | 1553 | else |
1550 | ret = wl1271_cmd_scan(hw->priv, ssid, len, 1, 0, | 1554 | ret = wl1271_cmd_scan(hw->priv, ssid, len, |
1555 | req->ie, req->ie_len, 1, 0, | ||
1551 | WL1271_SCAN_BAND_2_4_GHZ, 3); | 1556 | WL1271_SCAN_BAND_2_4_GHZ, 3); |
1552 | 1557 | ||
1553 | wl1271_ps_elp_sleep(wl); | 1558 | wl1271_ps_elp_sleep(wl); |
@@ -1606,6 +1611,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1606 | enum wl1271_cmd_ps_mode mode; | 1611 | enum wl1271_cmd_ps_mode mode; |
1607 | struct wl1271 *wl = hw->priv; | 1612 | struct wl1271 *wl = hw->priv; |
1608 | bool do_join = false; | 1613 | bool do_join = false; |
1614 | bool do_keepalive = false; | ||
1609 | int ret; | 1615 | int ret; |
1610 | 1616 | ||
1611 | wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed"); | 1617 | wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed"); |
@@ -1616,20 +1622,29 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1616 | if (ret < 0) | 1622 | if (ret < 0) |
1617 | goto out; | 1623 | goto out; |
1618 | 1624 | ||
1619 | if (wl->bss_type == BSS_TYPE_IBSS) { | 1625 | if ((changed && BSS_CHANGED_BEACON_INT) && |
1620 | /* FIXME: This implements rudimentary ad-hoc support - | 1626 | (wl->bss_type == BSS_TYPE_IBSS)) { |
1621 | proper templates are on the wish list and notification | 1627 | wl1271_debug(DEBUG_ADHOC, "ad-hoc beacon interval updated: %d", |
1622 | on when they change. This patch will update the templates | 1628 | bss_conf->beacon_int); |
1623 | on every call to this function. */ | 1629 | |
1630 | wl->beacon_int = bss_conf->beacon_int; | ||
1631 | do_join = true; | ||
1632 | } | ||
1633 | |||
1634 | if ((changed && BSS_CHANGED_BEACON) && | ||
1635 | (wl->bss_type == BSS_TYPE_IBSS)) { | ||
1624 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); | 1636 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); |
1625 | 1637 | ||
1638 | wl1271_debug(DEBUG_ADHOC, "ad-hoc beacon updated"); | ||
1639 | |||
1626 | if (beacon) { | 1640 | if (beacon) { |
1627 | struct ieee80211_hdr *hdr; | 1641 | struct ieee80211_hdr *hdr; |
1628 | 1642 | ||
1629 | wl1271_ssid_set(wl, beacon); | 1643 | wl1271_ssid_set(wl, beacon); |
1630 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, | 1644 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, |
1631 | beacon->data, | 1645 | beacon->data, |
1632 | beacon->len); | 1646 | beacon->len, 0, |
1647 | wl1271_min_rate_get(wl)); | ||
1633 | 1648 | ||
1634 | if (ret < 0) { | 1649 | if (ret < 0) { |
1635 | dev_kfree_skb(beacon); | 1650 | dev_kfree_skb(beacon); |
@@ -1644,7 +1659,8 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1644 | ret = wl1271_cmd_template_set(wl, | 1659 | ret = wl1271_cmd_template_set(wl, |
1645 | CMD_TEMPL_PROBE_RESPONSE, | 1660 | CMD_TEMPL_PROBE_RESPONSE, |
1646 | beacon->data, | 1661 | beacon->data, |
1647 | beacon->len); | 1662 | beacon->len, 0, |
1663 | wl1271_min_rate_get(wl)); | ||
1648 | dev_kfree_skb(beacon); | 1664 | dev_kfree_skb(beacon); |
1649 | if (ret < 0) | 1665 | if (ret < 0) |
1650 | goto out_sleep; | 1666 | goto out_sleep; |
@@ -1654,20 +1670,32 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1654 | } | 1670 | } |
1655 | } | 1671 | } |
1656 | 1672 | ||
1673 | if ((changed & BSS_CHANGED_BEACON_ENABLED) && | ||
1674 | (wl->bss_type == BSS_TYPE_IBSS)) { | ||
1675 | wl1271_debug(DEBUG_ADHOC, "ad-hoc beaconing: %s", | ||
1676 | bss_conf->enable_beacon ? "enabled" : "disabled"); | ||
1677 | |||
1678 | if (bss_conf->enable_beacon) | ||
1679 | wl->set_bss_type = BSS_TYPE_IBSS; | ||
1680 | else | ||
1681 | wl->set_bss_type = BSS_TYPE_STA_BSS; | ||
1682 | do_join = true; | ||
1683 | } | ||
1684 | |||
1657 | if ((changed & BSS_CHANGED_BSSID) && | 1685 | if ((changed & BSS_CHANGED_BSSID) && |
1658 | /* | 1686 | /* |
1659 | * Now we know the correct bssid, so we send a new join command | 1687 | * Now we know the correct bssid, so we send a new join command |
1660 | * and enable the BSSID filter | 1688 | * and enable the BSSID filter |
1661 | */ | 1689 | */ |
1662 | memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) { | 1690 | memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) { |
1663 | wl->rx_config |= CFG_BSSID_FILTER_EN; | ||
1664 | memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); | 1691 | memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); |
1692 | |||
1665 | ret = wl1271_cmd_build_null_data(wl); | 1693 | ret = wl1271_cmd_build_null_data(wl); |
1666 | if (ret < 0) { | 1694 | if (ret < 0) |
1667 | wl1271_warning("cmd buld null data failed %d", | ||
1668 | ret); | ||
1669 | goto out_sleep; | 1695 | goto out_sleep; |
1670 | } | 1696 | |
1697 | /* filter out all packets not from this BSSID */ | ||
1698 | wl1271_configure_filters(wl, 0); | ||
1671 | 1699 | ||
1672 | /* Need to update the BSSID (for filtering etc) */ | 1700 | /* Need to update the BSSID (for filtering etc) */ |
1673 | do_join = true; | 1701 | do_join = true; |
@@ -1675,10 +1703,23 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1675 | 1703 | ||
1676 | if (changed & BSS_CHANGED_ASSOC) { | 1704 | if (changed & BSS_CHANGED_ASSOC) { |
1677 | if (bss_conf->assoc) { | 1705 | if (bss_conf->assoc) { |
1706 | u32 rates; | ||
1678 | wl->aid = bss_conf->aid; | 1707 | wl->aid = bss_conf->aid; |
1679 | set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); | 1708 | set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); |
1680 | 1709 | ||
1681 | /* | 1710 | /* |
1711 | * use basic rates from AP, and determine lowest rate | ||
1712 | * to use with control frames. | ||
1713 | */ | ||
1714 | rates = bss_conf->basic_rates; | ||
1715 | wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, | ||
1716 | rates); | ||
1717 | wl->basic_rate = wl1271_min_rate_get(wl); | ||
1718 | ret = wl1271_acx_rate_policies(wl); | ||
1719 | if (ret < 0) | ||
1720 | goto out_sleep; | ||
1721 | |||
1722 | /* | ||
1682 | * with wl1271, we don't need to update the | 1723 | * with wl1271, we don't need to update the |
1683 | * beacon_int and dtim_period, because the firmware | 1724 | * beacon_int and dtim_period, because the firmware |
1684 | * updates it by itself when the first beacon is | 1725 | * updates it by itself when the first beacon is |
@@ -1688,7 +1729,30 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1688 | if (ret < 0) | 1729 | if (ret < 0) |
1689 | goto out_sleep; | 1730 | goto out_sleep; |
1690 | 1731 | ||
1691 | ret = wl1271_acx_aid(wl, wl->aid); | 1732 | /* |
1733 | * The SSID is intentionally set to NULL here - the | ||
1734 | * firmware will set the probe request with a | ||
1735 | * broadcast SSID regardless of what we set in the | ||
1736 | * template. | ||
1737 | */ | ||
1738 | ret = wl1271_cmd_build_probe_req(wl, NULL, 0, | ||
1739 | NULL, 0, wl->band); | ||
1740 | |||
1741 | /* Enable the keep-alive feature */ | ||
1742 | ret = wl1271_acx_keep_alive_mode(wl, true); | ||
1743 | if (ret < 0) | ||
1744 | goto out_sleep; | ||
1745 | |||
1746 | /* | ||
1747 | * This is awkward. The keep-alive configs must be done | ||
1748 | * *after* the join command, because otherwise it will | ||
1749 | * not work, but it must only be done *once* because | ||
1750 | * otherwise the firmware will start complaining. | ||
1751 | */ | ||
1752 | do_keepalive = true; | ||
1753 | |||
1754 | /* enable the connection monitoring feature */ | ||
1755 | ret = wl1271_acx_conn_monit_params(wl, true); | ||
1692 | if (ret < 0) | 1756 | if (ret < 0) |
1693 | goto out_sleep; | 1757 | goto out_sleep; |
1694 | 1758 | ||
@@ -1704,6 +1768,22 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1704 | /* use defaults when not associated */ | 1768 | /* use defaults when not associated */ |
1705 | clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); | 1769 | clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); |
1706 | wl->aid = 0; | 1770 | wl->aid = 0; |
1771 | |||
1772 | /* revert back to minimum rates for the current band */ | ||
1773 | wl1271_set_band_rate(wl); | ||
1774 | wl->basic_rate = wl1271_min_rate_get(wl); | ||
1775 | ret = wl1271_acx_rate_policies(wl); | ||
1776 | if (ret < 0) | ||
1777 | goto out_sleep; | ||
1778 | |||
1779 | /* disable connection monitor features */ | ||
1780 | ret = wl1271_acx_conn_monit_params(wl, false); | ||
1781 | |||
1782 | /* Disable the keep-alive feature */ | ||
1783 | ret = wl1271_acx_keep_alive_mode(wl, false); | ||
1784 | |||
1785 | if (ret < 0) | ||
1786 | goto out_sleep; | ||
1707 | } | 1787 | } |
1708 | 1788 | ||
1709 | } | 1789 | } |
@@ -1738,7 +1818,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1738 | } | 1818 | } |
1739 | 1819 | ||
1740 | if (do_join) { | 1820 | if (do_join) { |
1741 | ret = wl1271_cmd_join(wl); | 1821 | ret = wl1271_cmd_join(wl, wl->set_bss_type); |
1742 | if (ret < 0) { | 1822 | if (ret < 0) { |
1743 | wl1271_warning("cmd join failed %d", ret); | 1823 | wl1271_warning("cmd join failed %d", ret); |
1744 | goto out_sleep; | 1824 | goto out_sleep; |
@@ -1746,6 +1826,29 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1746 | set_bit(WL1271_FLAG_JOINED, &wl->flags); | 1826 | set_bit(WL1271_FLAG_JOINED, &wl->flags); |
1747 | } | 1827 | } |
1748 | 1828 | ||
1829 | /* | ||
1830 | * The JOIN operation shuts down the firmware keep-alive as a side | ||
1831 | * effect, and the ACX_AID will start the keep-alive as a side effect. | ||
1832 | * Hence, for non-IBSS, the ACX_AID must always happen *after* the | ||
1833 | * JOIN operation, and the template config after the ACX_AID. | ||
1834 | */ | ||
1835 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { | ||
1836 | ret = wl1271_acx_aid(wl, wl->aid); | ||
1837 | if (ret < 0) | ||
1838 | goto out_sleep; | ||
1839 | } | ||
1840 | |||
1841 | if (do_keepalive) { | ||
1842 | ret = wl1271_cmd_build_klv_null_data(wl); | ||
1843 | if (ret < 0) | ||
1844 | goto out_sleep; | ||
1845 | ret = wl1271_acx_keep_alive_config( | ||
1846 | wl, CMD_TEMPL_KLV_IDX_NULL_DATA, | ||
1847 | ACX_KEEP_ALIVE_TPL_VALID); | ||
1848 | if (ret < 0) | ||
1849 | goto out_sleep; | ||
1850 | } | ||
1851 | |||
1749 | out_sleep: | 1852 | out_sleep: |
1750 | wl1271_ps_elp_sleep(wl); | 1853 | wl1271_ps_elp_sleep(wl); |
1751 | 1854 | ||
@@ -1757,6 +1860,7 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
1757 | const struct ieee80211_tx_queue_params *params) | 1860 | const struct ieee80211_tx_queue_params *params) |
1758 | { | 1861 | { |
1759 | struct wl1271 *wl = hw->priv; | 1862 | struct wl1271 *wl = hw->priv; |
1863 | u8 ps_scheme; | ||
1760 | int ret; | 1864 | int ret; |
1761 | 1865 | ||
1762 | mutex_lock(&wl->mutex); | 1866 | mutex_lock(&wl->mutex); |
@@ -1767,17 +1871,22 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
1767 | if (ret < 0) | 1871 | if (ret < 0) |
1768 | goto out; | 1872 | goto out; |
1769 | 1873 | ||
1874 | /* the txop is confed in units of 32us by the mac80211, we need us */ | ||
1770 | ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue), | 1875 | ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue), |
1771 | params->cw_min, params->cw_max, | 1876 | params->cw_min, params->cw_max, |
1772 | params->aifs, params->txop); | 1877 | params->aifs, params->txop << 5); |
1773 | if (ret < 0) | 1878 | if (ret < 0) |
1774 | goto out_sleep; | 1879 | goto out_sleep; |
1775 | 1880 | ||
1881 | if (params->uapsd) | ||
1882 | ps_scheme = CONF_PS_SCHEME_UPSD_TRIGGER; | ||
1883 | else | ||
1884 | ps_scheme = CONF_PS_SCHEME_LEGACY; | ||
1885 | |||
1776 | ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue), | 1886 | ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue), |
1777 | CONF_CHANNEL_TYPE_EDCF, | 1887 | CONF_CHANNEL_TYPE_EDCF, |
1778 | wl1271_tx_get_queue(queue), | 1888 | wl1271_tx_get_queue(queue), |
1779 | CONF_PS_SCHEME_LEGACY_PSPOLL, | 1889 | ps_scheme, CONF_ACK_POLICY_LEGACY, 0, 0); |
1780 | CONF_ACK_POLICY_LEGACY, 0, 0); | ||
1781 | if (ret < 0) | 1890 | if (ret < 0) |
1782 | goto out_sleep; | 1891 | goto out_sleep; |
1783 | 1892 | ||
@@ -1851,6 +1960,36 @@ static struct ieee80211_channel wl1271_channels[] = { | |||
1851 | { .hw_value = 13, .center_freq = 2472, .max_power = 25 }, | 1960 | { .hw_value = 13, .center_freq = 2472, .max_power = 25 }, |
1852 | }; | 1961 | }; |
1853 | 1962 | ||
1963 | /* mapping to indexes for wl1271_rates */ | ||
1964 | const static u8 wl1271_rate_to_idx_2ghz[] = { | ||
1965 | /* MCS rates are used only with 11n */ | ||
1966 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS7 */ | ||
1967 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS6 */ | ||
1968 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS5 */ | ||
1969 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS4 */ | ||
1970 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS3 */ | ||
1971 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS2 */ | ||
1972 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS1 */ | ||
1973 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS0 */ | ||
1974 | |||
1975 | 11, /* CONF_HW_RXTX_RATE_54 */ | ||
1976 | 10, /* CONF_HW_RXTX_RATE_48 */ | ||
1977 | 9, /* CONF_HW_RXTX_RATE_36 */ | ||
1978 | 8, /* CONF_HW_RXTX_RATE_24 */ | ||
1979 | |||
1980 | /* TI-specific rate */ | ||
1981 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_22 */ | ||
1982 | |||
1983 | 7, /* CONF_HW_RXTX_RATE_18 */ | ||
1984 | 6, /* CONF_HW_RXTX_RATE_12 */ | ||
1985 | 3, /* CONF_HW_RXTX_RATE_11 */ | ||
1986 | 5, /* CONF_HW_RXTX_RATE_9 */ | ||
1987 | 4, /* CONF_HW_RXTX_RATE_6 */ | ||
1988 | 2, /* CONF_HW_RXTX_RATE_5_5 */ | ||
1989 | 1, /* CONF_HW_RXTX_RATE_2 */ | ||
1990 | 0 /* CONF_HW_RXTX_RATE_1 */ | ||
1991 | }; | ||
1992 | |||
1854 | /* can't be const, mac80211 writes to this */ | 1993 | /* can't be const, mac80211 writes to this */ |
1855 | static struct ieee80211_supported_band wl1271_band_2ghz = { | 1994 | static struct ieee80211_supported_band wl1271_band_2ghz = { |
1856 | .channels = wl1271_channels, | 1995 | .channels = wl1271_channels, |
@@ -1933,6 +2072,35 @@ static struct ieee80211_channel wl1271_channels_5ghz[] = { | |||
1933 | { .hw_value = 165, .center_freq = 5825}, | 2072 | { .hw_value = 165, .center_freq = 5825}, |
1934 | }; | 2073 | }; |
1935 | 2074 | ||
2075 | /* mapping to indexes for wl1271_rates_5ghz */ | ||
2076 | const static u8 wl1271_rate_to_idx_5ghz[] = { | ||
2077 | /* MCS rates are used only with 11n */ | ||
2078 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS7 */ | ||
2079 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS6 */ | ||
2080 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS5 */ | ||
2081 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS4 */ | ||
2082 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS3 */ | ||
2083 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS2 */ | ||
2084 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS1 */ | ||
2085 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS0 */ | ||
2086 | |||
2087 | 7, /* CONF_HW_RXTX_RATE_54 */ | ||
2088 | 6, /* CONF_HW_RXTX_RATE_48 */ | ||
2089 | 5, /* CONF_HW_RXTX_RATE_36 */ | ||
2090 | 4, /* CONF_HW_RXTX_RATE_24 */ | ||
2091 | |||
2092 | /* TI-specific rate */ | ||
2093 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_22 */ | ||
2094 | |||
2095 | 3, /* CONF_HW_RXTX_RATE_18 */ | ||
2096 | 2, /* CONF_HW_RXTX_RATE_12 */ | ||
2097 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_11 */ | ||
2098 | 1, /* CONF_HW_RXTX_RATE_9 */ | ||
2099 | 0, /* CONF_HW_RXTX_RATE_6 */ | ||
2100 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_5_5 */ | ||
2101 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_2 */ | ||
2102 | CONF_HW_RXTX_RATE_UNSUPPORTED /* CONF_HW_RXTX_RATE_1 */ | ||
2103 | }; | ||
1936 | 2104 | ||
1937 | static struct ieee80211_supported_band wl1271_band_5ghz = { | 2105 | static struct ieee80211_supported_band wl1271_band_5ghz = { |
1938 | .channels = wl1271_channels_5ghz, | 2106 | .channels = wl1271_channels_5ghz, |
@@ -1941,13 +2109,17 @@ static struct ieee80211_supported_band wl1271_band_5ghz = { | |||
1941 | .n_bitrates = ARRAY_SIZE(wl1271_rates_5ghz), | 2109 | .n_bitrates = ARRAY_SIZE(wl1271_rates_5ghz), |
1942 | }; | 2110 | }; |
1943 | 2111 | ||
2112 | const static u8 *wl1271_band_rate_to_idx[] = { | ||
2113 | [IEEE80211_BAND_2GHZ] = wl1271_rate_to_idx_2ghz, | ||
2114 | [IEEE80211_BAND_5GHZ] = wl1271_rate_to_idx_5ghz | ||
2115 | }; | ||
2116 | |||
1944 | static const struct ieee80211_ops wl1271_ops = { | 2117 | static const struct ieee80211_ops wl1271_ops = { |
1945 | .start = wl1271_op_start, | 2118 | .start = wl1271_op_start, |
1946 | .stop = wl1271_op_stop, | 2119 | .stop = wl1271_op_stop, |
1947 | .add_interface = wl1271_op_add_interface, | 2120 | .add_interface = wl1271_op_add_interface, |
1948 | .remove_interface = wl1271_op_remove_interface, | 2121 | .remove_interface = wl1271_op_remove_interface, |
1949 | .config = wl1271_op_config, | 2122 | .config = wl1271_op_config, |
1950 | /* .config_interface = wl1271_op_config_interface, */ | ||
1951 | .prepare_multicast = wl1271_op_prepare_multicast, | 2123 | .prepare_multicast = wl1271_op_prepare_multicast, |
1952 | .configure_filter = wl1271_op_configure_filter, | 2124 | .configure_filter = wl1271_op_configure_filter, |
1953 | .tx = wl1271_op_tx, | 2125 | .tx = wl1271_op_tx, |
@@ -1959,7 +2131,90 @@ static const struct ieee80211_ops wl1271_ops = { | |||
1959 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) | 2131 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) |
1960 | }; | 2132 | }; |
1961 | 2133 | ||
1962 | static int wl1271_register_hw(struct wl1271 *wl) | 2134 | |
2135 | u8 wl1271_rate_to_idx(struct wl1271 *wl, int rate) | ||
2136 | { | ||
2137 | u8 idx; | ||
2138 | |||
2139 | BUG_ON(wl->band >= sizeof(wl1271_band_rate_to_idx)/sizeof(u8 *)); | ||
2140 | |||
2141 | if (unlikely(rate >= CONF_HW_RXTX_RATE_MAX)) { | ||
2142 | wl1271_error("Illegal RX rate from HW: %d", rate); | ||
2143 | return 0; | ||
2144 | } | ||
2145 | |||
2146 | idx = wl1271_band_rate_to_idx[wl->band][rate]; | ||
2147 | if (unlikely(idx == CONF_HW_RXTX_RATE_UNSUPPORTED)) { | ||
2148 | wl1271_error("Unsupported RX rate from HW: %d", rate); | ||
2149 | return 0; | ||
2150 | } | ||
2151 | |||
2152 | return idx; | ||
2153 | } | ||
2154 | |||
2155 | static ssize_t wl1271_sysfs_show_bt_coex_state(struct device *dev, | ||
2156 | struct device_attribute *attr, | ||
2157 | char *buf) | ||
2158 | { | ||
2159 | struct wl1271 *wl = dev_get_drvdata(dev); | ||
2160 | ssize_t len; | ||
2161 | |||
2162 | /* FIXME: what's the maximum length of buf? page size?*/ | ||
2163 | len = 500; | ||
2164 | |||
2165 | mutex_lock(&wl->mutex); | ||
2166 | len = snprintf(buf, len, "%d\n\n0 - off\n1 - on\n", | ||
2167 | wl->sg_enabled); | ||
2168 | mutex_unlock(&wl->mutex); | ||
2169 | |||
2170 | return len; | ||
2171 | |||
2172 | } | ||
2173 | |||
2174 | static ssize_t wl1271_sysfs_store_bt_coex_state(struct device *dev, | ||
2175 | struct device_attribute *attr, | ||
2176 | const char *buf, size_t count) | ||
2177 | { | ||
2178 | struct wl1271 *wl = dev_get_drvdata(dev); | ||
2179 | unsigned long res; | ||
2180 | int ret; | ||
2181 | |||
2182 | ret = strict_strtoul(buf, 10, &res); | ||
2183 | |||
2184 | if (ret < 0) { | ||
2185 | wl1271_warning("incorrect value written to bt_coex_mode"); | ||
2186 | return count; | ||
2187 | } | ||
2188 | |||
2189 | mutex_lock(&wl->mutex); | ||
2190 | |||
2191 | res = !!res; | ||
2192 | |||
2193 | if (res == wl->sg_enabled) | ||
2194 | goto out; | ||
2195 | |||
2196 | wl->sg_enabled = res; | ||
2197 | |||
2198 | if (wl->state == WL1271_STATE_OFF) | ||
2199 | goto out; | ||
2200 | |||
2201 | ret = wl1271_ps_elp_wakeup(wl, false); | ||
2202 | if (ret < 0) | ||
2203 | goto out; | ||
2204 | |||
2205 | wl1271_acx_sg_enable(wl, wl->sg_enabled); | ||
2206 | wl1271_ps_elp_sleep(wl); | ||
2207 | |||
2208 | out: | ||
2209 | mutex_unlock(&wl->mutex); | ||
2210 | return count; | ||
2211 | } | ||
2212 | |||
2213 | static DEVICE_ATTR(bt_coex_state, S_IRUGO | S_IWUSR, | ||
2214 | wl1271_sysfs_show_bt_coex_state, | ||
2215 | wl1271_sysfs_store_bt_coex_state); | ||
2216 | |||
2217 | int wl1271_register_hw(struct wl1271 *wl) | ||
1963 | { | 2218 | { |
1964 | int ret; | 2219 | int ret; |
1965 | 2220 | ||
@@ -1980,8 +2235,17 @@ static int wl1271_register_hw(struct wl1271 *wl) | |||
1980 | 2235 | ||
1981 | return 0; | 2236 | return 0; |
1982 | } | 2237 | } |
2238 | EXPORT_SYMBOL_GPL(wl1271_register_hw); | ||
1983 | 2239 | ||
1984 | static int wl1271_init_ieee80211(struct wl1271 *wl) | 2240 | void wl1271_unregister_hw(struct wl1271 *wl) |
2241 | { | ||
2242 | ieee80211_unregister_hw(wl->hw); | ||
2243 | wl->mac80211_registered = false; | ||
2244 | |||
2245 | } | ||
2246 | EXPORT_SYMBOL_GPL(wl1271_unregister_hw); | ||
2247 | |||
2248 | int wl1271_init_ieee80211(struct wl1271 *wl) | ||
1985 | { | 2249 | { |
1986 | /* The tx descriptor buffer and the TKIP space. */ | 2250 | /* The tx descriptor buffer and the TKIP space. */ |
1987 | wl->hw->extra_tx_headroom = WL1271_TKIP_IV_SPACE + | 2251 | wl->hw->extra_tx_headroom = WL1271_TKIP_IV_SPACE + |
@@ -1990,11 +2254,15 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) | |||
1990 | /* unit us */ | 2254 | /* unit us */ |
1991 | /* FIXME: find a proper value */ | 2255 | /* FIXME: find a proper value */ |
1992 | wl->hw->channel_change_time = 10000; | 2256 | wl->hw->channel_change_time = 10000; |
2257 | wl->hw->max_listen_interval = wl->conf.conn.max_listen_interval; | ||
1993 | 2258 | ||
1994 | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | | 2259 | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | |
1995 | IEEE80211_HW_NOISE_DBM | | 2260 | IEEE80211_HW_NOISE_DBM | |
1996 | IEEE80211_HW_BEACON_FILTER | | 2261 | IEEE80211_HW_BEACON_FILTER | |
1997 | IEEE80211_HW_SUPPORTS_PS; | 2262 | IEEE80211_HW_SUPPORTS_PS | |
2263 | IEEE80211_HW_SUPPORTS_UAPSD | | ||
2264 | IEEE80211_HW_HAS_RATE_CONTROL | | ||
2265 | IEEE80211_HW_CONNECTION_MONITOR; | ||
1998 | 2266 | ||
1999 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | 2267 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
2000 | BIT(NL80211_IFTYPE_ADHOC); | 2268 | BIT(NL80211_IFTYPE_ADHOC); |
@@ -2004,51 +2272,53 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) | |||
2004 | if (wl1271_11a_enabled()) | 2272 | if (wl1271_11a_enabled()) |
2005 | wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz; | 2273 | wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz; |
2006 | 2274 | ||
2007 | SET_IEEE80211_DEV(wl->hw, &wl->spi->dev); | 2275 | wl->hw->queues = 4; |
2276 | wl->hw->max_rates = 1; | ||
2008 | 2277 | ||
2009 | return 0; | 2278 | SET_IEEE80211_DEV(wl->hw, wl1271_wl_to_dev(wl)); |
2010 | } | ||
2011 | |||
2012 | static void wl1271_device_release(struct device *dev) | ||
2013 | { | ||
2014 | 2279 | ||
2280 | return 0; | ||
2015 | } | 2281 | } |
2016 | 2282 | EXPORT_SYMBOL_GPL(wl1271_init_ieee80211); | |
2017 | static struct platform_device wl1271_device = { | ||
2018 | .name = "wl1271", | ||
2019 | .id = -1, | ||
2020 | |||
2021 | /* device model insists to have a release function */ | ||
2022 | .dev = { | ||
2023 | .release = wl1271_device_release, | ||
2024 | }, | ||
2025 | }; | ||
2026 | 2283 | ||
2027 | #define WL1271_DEFAULT_CHANNEL 0 | 2284 | #define WL1271_DEFAULT_CHANNEL 0 |
2028 | 2285 | ||
2029 | static struct ieee80211_hw *wl1271_alloc_hw(void) | 2286 | struct ieee80211_hw *wl1271_alloc_hw(void) |
2030 | { | 2287 | { |
2031 | struct ieee80211_hw *hw; | 2288 | struct ieee80211_hw *hw; |
2289 | struct platform_device *plat_dev = NULL; | ||
2032 | struct wl1271 *wl; | 2290 | struct wl1271 *wl; |
2033 | int i; | 2291 | int i, ret; |
2034 | 2292 | ||
2035 | hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); | 2293 | hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); |
2036 | if (!hw) { | 2294 | if (!hw) { |
2037 | wl1271_error("could not alloc ieee80211_hw"); | 2295 | wl1271_error("could not alloc ieee80211_hw"); |
2038 | return ERR_PTR(-ENOMEM); | 2296 | ret = -ENOMEM; |
2297 | goto err_hw_alloc; | ||
2298 | } | ||
2299 | |||
2300 | plat_dev = kmalloc(sizeof(wl1271_device), GFP_KERNEL); | ||
2301 | if (!plat_dev) { | ||
2302 | wl1271_error("could not allocate platform_device"); | ||
2303 | ret = -ENOMEM; | ||
2304 | goto err_plat_alloc; | ||
2039 | } | 2305 | } |
2040 | 2306 | ||
2307 | memcpy(plat_dev, &wl1271_device, sizeof(wl1271_device)); | ||
2308 | |||
2041 | wl = hw->priv; | 2309 | wl = hw->priv; |
2042 | memset(wl, 0, sizeof(*wl)); | 2310 | memset(wl, 0, sizeof(*wl)); |
2043 | 2311 | ||
2044 | INIT_LIST_HEAD(&wl->list); | 2312 | INIT_LIST_HEAD(&wl->list); |
2045 | 2313 | ||
2046 | wl->hw = hw; | 2314 | wl->hw = hw; |
2315 | wl->plat_dev = plat_dev; | ||
2047 | 2316 | ||
2048 | skb_queue_head_init(&wl->tx_queue); | 2317 | skb_queue_head_init(&wl->tx_queue); |
2049 | 2318 | ||
2050 | INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); | 2319 | INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); |
2051 | wl->channel = WL1271_DEFAULT_CHANNEL; | 2320 | wl->channel = WL1271_DEFAULT_CHANNEL; |
2321 | wl->beacon_int = WL1271_DEFAULT_BEACON_INT; | ||
2052 | wl->default_key = 0; | 2322 | wl->default_key = 0; |
2053 | wl->rx_counter = 0; | 2323 | wl->rx_counter = 0; |
2054 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; | 2324 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; |
@@ -2056,11 +2326,13 @@ static struct ieee80211_hw *wl1271_alloc_hw(void) | |||
2056 | wl->psm_entry_retry = 0; | 2326 | wl->psm_entry_retry = 0; |
2057 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; | 2327 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; |
2058 | wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; | 2328 | wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; |
2329 | wl->basic_rate = CONF_TX_RATE_MASK_BASIC; | ||
2059 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; | 2330 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; |
2060 | wl->sta_rate_set = 0; | 2331 | wl->sta_rate_set = 0; |
2061 | wl->band = IEEE80211_BAND_2GHZ; | 2332 | wl->band = IEEE80211_BAND_2GHZ; |
2062 | wl->vif = NULL; | 2333 | wl->vif = NULL; |
2063 | wl->flags = 0; | 2334 | wl->flags = 0; |
2335 | wl->sg_enabled = true; | ||
2064 | 2336 | ||
2065 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) | 2337 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) |
2066 | wl->tx_frames[i] = NULL; | 2338 | wl->tx_frames[i] = NULL; |
@@ -2073,12 +2345,45 @@ static struct ieee80211_hw *wl1271_alloc_hw(void) | |||
2073 | /* Apply default driver configuration. */ | 2345 | /* Apply default driver configuration. */ |
2074 | wl1271_conf_init(wl); | 2346 | wl1271_conf_init(wl); |
2075 | 2347 | ||
2348 | wl1271_debugfs_init(wl); | ||
2349 | |||
2350 | /* Register platform device */ | ||
2351 | ret = platform_device_register(wl->plat_dev); | ||
2352 | if (ret) { | ||
2353 | wl1271_error("couldn't register platform device"); | ||
2354 | goto err_hw; | ||
2355 | } | ||
2356 | dev_set_drvdata(&wl->plat_dev->dev, wl); | ||
2357 | |||
2358 | /* Create sysfs file to control bt coex state */ | ||
2359 | ret = device_create_file(&wl->plat_dev->dev, &dev_attr_bt_coex_state); | ||
2360 | if (ret < 0) { | ||
2361 | wl1271_error("failed to create sysfs file bt_coex_state"); | ||
2362 | goto err_platform; | ||
2363 | } | ||
2364 | |||
2076 | return hw; | 2365 | return hw; |
2366 | |||
2367 | err_platform: | ||
2368 | platform_device_unregister(wl->plat_dev); | ||
2369 | |||
2370 | err_hw: | ||
2371 | wl1271_debugfs_exit(wl); | ||
2372 | kfree(plat_dev); | ||
2373 | |||
2374 | err_plat_alloc: | ||
2375 | ieee80211_free_hw(hw); | ||
2376 | |||
2377 | err_hw_alloc: | ||
2378 | |||
2379 | return ERR_PTR(ret); | ||
2077 | } | 2380 | } |
2381 | EXPORT_SYMBOL_GPL(wl1271_alloc_hw); | ||
2078 | 2382 | ||
2079 | int wl1271_free_hw(struct wl1271 *wl) | 2383 | int wl1271_free_hw(struct wl1271 *wl) |
2080 | { | 2384 | { |
2081 | ieee80211_unregister_hw(wl->hw); | 2385 | platform_device_unregister(wl->plat_dev); |
2386 | kfree(wl->plat_dev); | ||
2082 | 2387 | ||
2083 | wl1271_debugfs_exit(wl); | 2388 | wl1271_debugfs_exit(wl); |
2084 | 2389 | ||
@@ -2095,145 +2400,8 @@ int wl1271_free_hw(struct wl1271 *wl) | |||
2095 | 2400 | ||
2096 | return 0; | 2401 | return 0; |
2097 | } | 2402 | } |
2098 | 2403 | EXPORT_SYMBOL_GPL(wl1271_free_hw); | |
2099 | static int __devinit wl1271_probe(struct spi_device *spi) | ||
2100 | { | ||
2101 | struct wl12xx_platform_data *pdata; | ||
2102 | struct ieee80211_hw *hw; | ||
2103 | struct wl1271 *wl; | ||
2104 | int ret; | ||
2105 | |||
2106 | pdata = spi->dev.platform_data; | ||
2107 | if (!pdata) { | ||
2108 | wl1271_error("no platform data"); | ||
2109 | return -ENODEV; | ||
2110 | } | ||
2111 | |||
2112 | hw = wl1271_alloc_hw(); | ||
2113 | if (IS_ERR(hw)) | ||
2114 | return PTR_ERR(hw); | ||
2115 | |||
2116 | wl = hw->priv; | ||
2117 | |||
2118 | dev_set_drvdata(&spi->dev, wl); | ||
2119 | wl->spi = spi; | ||
2120 | |||
2121 | /* This is the only SPI value that we need to set here, the rest | ||
2122 | * comes from the board-peripherals file */ | ||
2123 | spi->bits_per_word = 32; | ||
2124 | |||
2125 | ret = spi_setup(spi); | ||
2126 | if (ret < 0) { | ||
2127 | wl1271_error("spi_setup failed"); | ||
2128 | goto out_free; | ||
2129 | } | ||
2130 | |||
2131 | wl->set_power = pdata->set_power; | ||
2132 | if (!wl->set_power) { | ||
2133 | wl1271_error("set power function missing in platform data"); | ||
2134 | ret = -ENODEV; | ||
2135 | goto out_free; | ||
2136 | } | ||
2137 | |||
2138 | wl->irq = spi->irq; | ||
2139 | if (wl->irq < 0) { | ||
2140 | wl1271_error("irq missing in platform data"); | ||
2141 | ret = -ENODEV; | ||
2142 | goto out_free; | ||
2143 | } | ||
2144 | |||
2145 | ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl); | ||
2146 | if (ret < 0) { | ||
2147 | wl1271_error("request_irq() failed: %d", ret); | ||
2148 | goto out_free; | ||
2149 | } | ||
2150 | |||
2151 | set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING); | ||
2152 | |||
2153 | disable_irq(wl->irq); | ||
2154 | |||
2155 | ret = platform_device_register(&wl1271_device); | ||
2156 | if (ret) { | ||
2157 | wl1271_error("couldn't register platform device"); | ||
2158 | goto out_irq; | ||
2159 | } | ||
2160 | dev_set_drvdata(&wl1271_device.dev, wl); | ||
2161 | |||
2162 | ret = wl1271_init_ieee80211(wl); | ||
2163 | if (ret) | ||
2164 | goto out_platform; | ||
2165 | |||
2166 | ret = wl1271_register_hw(wl); | ||
2167 | if (ret) | ||
2168 | goto out_platform; | ||
2169 | |||
2170 | wl1271_debugfs_init(wl); | ||
2171 | |||
2172 | wl1271_notice("initialized"); | ||
2173 | |||
2174 | return 0; | ||
2175 | |||
2176 | out_platform: | ||
2177 | platform_device_unregister(&wl1271_device); | ||
2178 | |||
2179 | out_irq: | ||
2180 | free_irq(wl->irq, wl); | ||
2181 | |||
2182 | out_free: | ||
2183 | ieee80211_free_hw(hw); | ||
2184 | |||
2185 | return ret; | ||
2186 | } | ||
2187 | |||
2188 | static int __devexit wl1271_remove(struct spi_device *spi) | ||
2189 | { | ||
2190 | struct wl1271 *wl = dev_get_drvdata(&spi->dev); | ||
2191 | |||
2192 | platform_device_unregister(&wl1271_device); | ||
2193 | free_irq(wl->irq, wl); | ||
2194 | |||
2195 | wl1271_free_hw(wl); | ||
2196 | |||
2197 | return 0; | ||
2198 | } | ||
2199 | |||
2200 | |||
2201 | static struct spi_driver wl1271_spi_driver = { | ||
2202 | .driver = { | ||
2203 | .name = "wl1271", | ||
2204 | .bus = &spi_bus_type, | ||
2205 | .owner = THIS_MODULE, | ||
2206 | }, | ||
2207 | |||
2208 | .probe = wl1271_probe, | ||
2209 | .remove = __devexit_p(wl1271_remove), | ||
2210 | }; | ||
2211 | |||
2212 | static int __init wl1271_init(void) | ||
2213 | { | ||
2214 | int ret; | ||
2215 | |||
2216 | ret = spi_register_driver(&wl1271_spi_driver); | ||
2217 | if (ret < 0) { | ||
2218 | wl1271_error("failed to register spi driver: %d", ret); | ||
2219 | goto out; | ||
2220 | } | ||
2221 | |||
2222 | out: | ||
2223 | return ret; | ||
2224 | } | ||
2225 | |||
2226 | static void __exit wl1271_exit(void) | ||
2227 | { | ||
2228 | spi_unregister_driver(&wl1271_spi_driver); | ||
2229 | |||
2230 | wl1271_notice("unloaded"); | ||
2231 | } | ||
2232 | |||
2233 | module_init(wl1271_init); | ||
2234 | module_exit(wl1271_exit); | ||
2235 | 2404 | ||
2236 | MODULE_LICENSE("GPL"); | 2405 | MODULE_LICENSE("GPL"); |
2237 | MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>"); | 2406 | MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>"); |
2238 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); | 2407 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); |
2239 | MODULE_FIRMWARE(WL1271_FW_NAME); | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.c b/drivers/net/wireless/wl12xx/wl1271_ps.c index e2b1ebf096e8..5a04482b9353 100644 --- a/drivers/net/wireless/wl12xx/wl1271_ps.c +++ b/drivers/net/wireless/wl12xx/wl1271_ps.c | |||
@@ -23,7 +23,6 @@ | |||
23 | 23 | ||
24 | #include "wl1271_reg.h" | 24 | #include "wl1271_reg.h" |
25 | #include "wl1271_ps.h" | 25 | #include "wl1271_ps.h" |
26 | #include "wl1271_spi.h" | ||
27 | #include "wl1271_io.h" | 26 | #include "wl1271_io.h" |
28 | 27 | ||
29 | #define WL1271_WAKEUP_TIMEOUT 500 | 28 | #define WL1271_WAKEUP_TIMEOUT 500 |
diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c index 6730f5b96e76..ca442703d1ab 100644 --- a/drivers/net/wireless/wl12xx/wl1271_rx.c +++ b/drivers/net/wireless/wl12xx/wl1271_rx.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include "wl1271_acx.h" | 25 | #include "wl1271_acx.h" |
26 | #include "wl1271_reg.h" | 26 | #include "wl1271_reg.h" |
27 | #include "wl1271_rx.h" | 27 | #include "wl1271_rx.h" |
28 | #include "wl1271_spi.h" | ||
29 | #include "wl1271_io.h" | 28 | #include "wl1271_io.h" |
30 | 29 | ||
31 | static u8 wl1271_rx_get_mem_block(struct wl1271_fw_status *status, | 30 | static u8 wl1271_rx_get_mem_block(struct wl1271_fw_status *status, |
@@ -42,66 +41,6 @@ static u32 wl1271_rx_get_buf_size(struct wl1271_fw_status *status, | |||
42 | RX_BUF_SIZE_MASK) >> RX_BUF_SIZE_SHIFT_DIV; | 41 | RX_BUF_SIZE_MASK) >> RX_BUF_SIZE_SHIFT_DIV; |
43 | } | 42 | } |
44 | 43 | ||
45 | /* The values of this table must match the wl1271_rates[] array */ | ||
46 | static u8 wl1271_rx_rate_to_idx[] = { | ||
47 | /* MCS rates are used only with 11n */ | ||
48 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS7 */ | ||
49 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS6 */ | ||
50 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS5 */ | ||
51 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS4 */ | ||
52 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS3 */ | ||
53 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS2 */ | ||
54 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS1 */ | ||
55 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS0 */ | ||
56 | |||
57 | 11, /* WL1271_RATE_54 */ | ||
58 | 10, /* WL1271_RATE_48 */ | ||
59 | 9, /* WL1271_RATE_36 */ | ||
60 | 8, /* WL1271_RATE_24 */ | ||
61 | |||
62 | /* TI-specific rate */ | ||
63 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_22 */ | ||
64 | |||
65 | 7, /* WL1271_RATE_18 */ | ||
66 | 6, /* WL1271_RATE_12 */ | ||
67 | 3, /* WL1271_RATE_11 */ | ||
68 | 5, /* WL1271_RATE_9 */ | ||
69 | 4, /* WL1271_RATE_6 */ | ||
70 | 2, /* WL1271_RATE_5_5 */ | ||
71 | 1, /* WL1271_RATE_2 */ | ||
72 | 0 /* WL1271_RATE_1 */ | ||
73 | }; | ||
74 | |||
75 | /* The values of this table must match the wl1271_rates[] array */ | ||
76 | static u8 wl1271_5_ghz_rx_rate_to_idx[] = { | ||
77 | /* MCS rates are used only with 11n */ | ||
78 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS7 */ | ||
79 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS6 */ | ||
80 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS5 */ | ||
81 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS4 */ | ||
82 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS3 */ | ||
83 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS2 */ | ||
84 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS1 */ | ||
85 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS0 */ | ||
86 | |||
87 | 7, /* WL1271_RATE_54 */ | ||
88 | 6, /* WL1271_RATE_48 */ | ||
89 | 5, /* WL1271_RATE_36 */ | ||
90 | 4, /* WL1271_RATE_24 */ | ||
91 | |||
92 | /* TI-specific rate */ | ||
93 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_22 */ | ||
94 | |||
95 | 3, /* WL1271_RATE_18 */ | ||
96 | 2, /* WL1271_RATE_12 */ | ||
97 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_11 */ | ||
98 | 1, /* WL1271_RATE_9 */ | ||
99 | 0, /* WL1271_RATE_6 */ | ||
100 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_5_5 */ | ||
101 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_2 */ | ||
102 | WL1271_RX_RATE_UNSUPPORTED /* WL1271_RATE_1 */ | ||
103 | }; | ||
104 | |||
105 | static void wl1271_rx_status(struct wl1271 *wl, | 44 | static void wl1271_rx_status(struct wl1271 *wl, |
106 | struct wl1271_rx_descriptor *desc, | 45 | struct wl1271_rx_descriptor *desc, |
107 | struct ieee80211_rx_status *status, | 46 | struct ieee80211_rx_status *status, |
@@ -109,20 +48,8 @@ static void wl1271_rx_status(struct wl1271 *wl, | |||
109 | { | 48 | { |
110 | memset(status, 0, sizeof(struct ieee80211_rx_status)); | 49 | memset(status, 0, sizeof(struct ieee80211_rx_status)); |
111 | 50 | ||
112 | if ((desc->flags & WL1271_RX_DESC_BAND_MASK) == | 51 | status->band = wl->band; |
113 | WL1271_RX_DESC_BAND_BG) { | 52 | status->rate_idx = wl1271_rate_to_idx(wl, desc->rate); |
114 | status->band = IEEE80211_BAND_2GHZ; | ||
115 | status->rate_idx = wl1271_rx_rate_to_idx[desc->rate]; | ||
116 | } else if ((desc->flags & WL1271_RX_DESC_BAND_MASK) == | ||
117 | WL1271_RX_DESC_BAND_A) { | ||
118 | status->band = IEEE80211_BAND_5GHZ; | ||
119 | status->rate_idx = wl1271_5_ghz_rx_rate_to_idx[desc->rate]; | ||
120 | } else | ||
121 | wl1271_warning("unsupported band 0x%x", | ||
122 | desc->flags & WL1271_RX_DESC_BAND_MASK); | ||
123 | |||
124 | if (unlikely(status->rate_idx == WL1271_RX_RATE_UNSUPPORTED)) | ||
125 | wl1271_warning("unsupported rate"); | ||
126 | 53 | ||
127 | /* | 54 | /* |
128 | * FIXME: Add mactime handling. For IBSS (ad-hoc) we need to get the | 55 | * FIXME: Add mactime handling. For IBSS (ad-hoc) we need to get the |
@@ -132,13 +59,6 @@ static void wl1271_rx_status(struct wl1271 *wl, | |||
132 | */ | 59 | */ |
133 | status->signal = desc->rssi; | 60 | status->signal = desc->rssi; |
134 | 61 | ||
135 | /* | ||
136 | * FIXME: In wl1251, the SNR should be divided by two. In wl1271 we | ||
137 | * need to divide by two for now, but TI has been discussing about | ||
138 | * changing it. This needs to be rechecked. | ||
139 | */ | ||
140 | status->noise = desc->rssi - (desc->snr >> 1); | ||
141 | |||
142 | status->freq = ieee80211_channel_to_frequency(desc->channel); | 62 | status->freq = ieee80211_channel_to_frequency(desc->channel); |
143 | 63 | ||
144 | if (desc->flags & WL1271_RX_DESC_ENCRYPT_MASK) { | 64 | if (desc->flags & WL1271_RX_DESC_ENCRYPT_MASK) { |
@@ -160,6 +80,13 @@ static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length) | |||
160 | u8 *buf; | 80 | u8 *buf; |
161 | u8 beacon = 0; | 81 | u8 beacon = 0; |
162 | 82 | ||
83 | /* | ||
84 | * In PLT mode we seem to get frames and mac80211 warns about them, | ||
85 | * workaround this by not retrieving them at all. | ||
86 | */ | ||
87 | if (unlikely(wl->state == WL1271_STATE_PLT)) | ||
88 | return; | ||
89 | |||
163 | skb = __dev_alloc_skb(length, GFP_KERNEL); | 90 | skb = __dev_alloc_skb(length, GFP_KERNEL); |
164 | if (!skb) { | 91 | if (!skb) { |
165 | wl1271_error("Couldn't allocate RX frame"); | 92 | wl1271_error("Couldn't allocate RX frame"); |
@@ -218,6 +145,7 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status) | |||
218 | 145 | ||
219 | wl->rx_counter++; | 146 | wl->rx_counter++; |
220 | drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK; | 147 | drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK; |
221 | wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter); | ||
222 | } | 148 | } |
149 | |||
150 | wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter); | ||
223 | } | 151 | } |
diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.h b/drivers/net/wireless/wl12xx/wl1271_rx.h index 1ae6d1783ed4..b89be4758e78 100644 --- a/drivers/net/wireless/wl12xx/wl1271_rx.h +++ b/drivers/net/wireless/wl12xx/wl1271_rx.h | |||
@@ -43,7 +43,6 @@ | |||
43 | #define RX_MAX_PACKET_ID 3 | 43 | #define RX_MAX_PACKET_ID 3 |
44 | 44 | ||
45 | #define NUM_RX_PKT_DESC_MOD_MASK 7 | 45 | #define NUM_RX_PKT_DESC_MOD_MASK 7 |
46 | #define WL1271_RX_RATE_UNSUPPORTED 0xFF | ||
47 | 46 | ||
48 | #define RX_DESC_VALID_FCS 0x0001 | 47 | #define RX_DESC_VALID_FCS 0x0001 |
49 | #define RX_DESC_MATCH_RXADDR1 0x0002 | 48 | #define RX_DESC_MATCH_RXADDR1 0x0002 |
@@ -117,5 +116,6 @@ struct wl1271_rx_descriptor { | |||
117 | } __attribute__ ((packed)); | 116 | } __attribute__ ((packed)); |
118 | 117 | ||
119 | void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status); | 118 | void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status); |
119 | u8 wl1271_rate_to_idx(struct wl1271 *wl, int rate); | ||
120 | 120 | ||
121 | #endif | 121 | #endif |
diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/wl1271_sdio.c new file mode 100644 index 000000000000..d3d6f302f705 --- /dev/null +++ b/drivers/net/wireless/wl12xx/wl1271_sdio.c | |||
@@ -0,0 +1,291 @@ | |||
1 | /* | ||
2 | * This file is part of wl1271 | ||
3 | * | ||
4 | * Copyright (C) 2009-2010 Nokia Corporation | ||
5 | * | ||
6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #include <linux/irq.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/crc7.h> | ||
27 | #include <linux/vmalloc.h> | ||
28 | #include <linux/mmc/sdio_func.h> | ||
29 | #include <linux/mmc/sdio_ids.h> | ||
30 | #include <linux/mmc/card.h> | ||
31 | #include <plat/gpio.h> | ||
32 | |||
33 | #include "wl1271.h" | ||
34 | #include "wl12xx_80211.h" | ||
35 | #include "wl1271_io.h" | ||
36 | |||
37 | |||
38 | #define RX71_WL1271_IRQ_GPIO 42 | ||
39 | |||
40 | #ifndef SDIO_VENDOR_ID_TI | ||
41 | #define SDIO_VENDOR_ID_TI 0x0097 | ||
42 | #endif | ||
43 | |||
44 | #ifndef SDIO_DEVICE_ID_TI_WL1271 | ||
45 | #define SDIO_DEVICE_ID_TI_WL1271 0x4076 | ||
46 | #endif | ||
47 | |||
48 | static const struct sdio_device_id wl1271_devices[] = { | ||
49 | { SDIO_DEVICE(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271) }, | ||
50 | {} | ||
51 | }; | ||
52 | MODULE_DEVICE_TABLE(sdio, wl1271_devices); | ||
53 | |||
54 | static inline struct sdio_func *wl_to_func(struct wl1271 *wl) | ||
55 | { | ||
56 | return wl->if_priv; | ||
57 | } | ||
58 | |||
59 | static struct device *wl1271_sdio_wl_to_dev(struct wl1271 *wl) | ||
60 | { | ||
61 | return &(wl_to_func(wl)->dev); | ||
62 | } | ||
63 | |||
64 | static irqreturn_t wl1271_irq(int irq, void *cookie) | ||
65 | { | ||
66 | struct wl1271 *wl = cookie; | ||
67 | unsigned long flags; | ||
68 | |||
69 | wl1271_debug(DEBUG_IRQ, "IRQ"); | ||
70 | |||
71 | /* complete the ELP completion */ | ||
72 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
73 | if (wl->elp_compl) { | ||
74 | complete(wl->elp_compl); | ||
75 | wl->elp_compl = NULL; | ||
76 | } | ||
77 | |||
78 | if (!test_and_set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags)) | ||
79 | ieee80211_queue_work(wl->hw, &wl->irq_work); | ||
80 | set_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags); | ||
81 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
82 | |||
83 | return IRQ_HANDLED; | ||
84 | } | ||
85 | |||
86 | static void wl1271_sdio_disable_interrupts(struct wl1271 *wl) | ||
87 | { | ||
88 | disable_irq(wl->irq); | ||
89 | } | ||
90 | |||
91 | static void wl1271_sdio_enable_interrupts(struct wl1271 *wl) | ||
92 | { | ||
93 | enable_irq(wl->irq); | ||
94 | } | ||
95 | |||
96 | static void wl1271_sdio_reset(struct wl1271 *wl) | ||
97 | { | ||
98 | } | ||
99 | |||
100 | static void wl1271_sdio_init(struct wl1271 *wl) | ||
101 | { | ||
102 | } | ||
103 | |||
104 | static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf, | ||
105 | size_t len, bool fixed) | ||
106 | { | ||
107 | int ret; | ||
108 | struct sdio_func *func = wl_to_func(wl); | ||
109 | |||
110 | if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { | ||
111 | ((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret); | ||
112 | wl1271_debug(DEBUG_SDIO, "sdio read 52 addr 0x%x, byte 0x%02x", | ||
113 | addr, ((u8 *)buf)[0]); | ||
114 | } else { | ||
115 | if (fixed) | ||
116 | ret = sdio_readsb(func, buf, addr, len); | ||
117 | else | ||
118 | ret = sdio_memcpy_fromio(func, buf, addr, len); | ||
119 | |||
120 | wl1271_debug(DEBUG_SDIO, "sdio read 53 addr 0x%x, %zu bytes", | ||
121 | addr, len); | ||
122 | wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len); | ||
123 | } | ||
124 | |||
125 | if (ret) | ||
126 | wl1271_error("sdio read failed (%d)", ret); | ||
127 | |||
128 | } | ||
129 | |||
130 | static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf, | ||
131 | size_t len, bool fixed) | ||
132 | { | ||
133 | int ret; | ||
134 | struct sdio_func *func = wl_to_func(wl); | ||
135 | |||
136 | if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { | ||
137 | sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret); | ||
138 | wl1271_debug(DEBUG_SDIO, "sdio write 52 addr 0x%x, byte 0x%02x", | ||
139 | addr, ((u8 *)buf)[0]); | ||
140 | } else { | ||
141 | wl1271_debug(DEBUG_SDIO, "sdio write 53 addr 0x%x, %zu bytes", | ||
142 | addr, len); | ||
143 | wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len); | ||
144 | |||
145 | if (fixed) | ||
146 | ret = sdio_writesb(func, addr, buf, len); | ||
147 | else | ||
148 | ret = sdio_memcpy_toio(func, addr, buf, len); | ||
149 | } | ||
150 | if (ret) | ||
151 | wl1271_error("sdio write failed (%d)", ret); | ||
152 | |||
153 | } | ||
154 | |||
155 | static void wl1271_sdio_set_power(struct wl1271 *wl, bool enable) | ||
156 | { | ||
157 | struct sdio_func *func = wl_to_func(wl); | ||
158 | |||
159 | /* Let the SDIO stack handle wlan_enable control, so we | ||
160 | * keep host claimed while wlan is in use to keep wl1271 | ||
161 | * alive. | ||
162 | */ | ||
163 | if (enable) { | ||
164 | sdio_claim_host(func); | ||
165 | sdio_enable_func(func); | ||
166 | } else { | ||
167 | sdio_disable_func(func); | ||
168 | sdio_release_host(func); | ||
169 | } | ||
170 | } | ||
171 | |||
172 | static struct wl1271_if_operations sdio_ops = { | ||
173 | .read = wl1271_sdio_raw_read, | ||
174 | .write = wl1271_sdio_raw_write, | ||
175 | .reset = wl1271_sdio_reset, | ||
176 | .init = wl1271_sdio_init, | ||
177 | .power = wl1271_sdio_set_power, | ||
178 | .dev = wl1271_sdio_wl_to_dev, | ||
179 | .enable_irq = wl1271_sdio_enable_interrupts, | ||
180 | .disable_irq = wl1271_sdio_disable_interrupts | ||
181 | }; | ||
182 | |||
183 | static int __devinit wl1271_probe(struct sdio_func *func, | ||
184 | const struct sdio_device_id *id) | ||
185 | { | ||
186 | struct ieee80211_hw *hw; | ||
187 | struct wl1271 *wl; | ||
188 | int ret; | ||
189 | |||
190 | /* We are only able to handle the wlan function */ | ||
191 | if (func->num != 0x02) | ||
192 | return -ENODEV; | ||
193 | |||
194 | hw = wl1271_alloc_hw(); | ||
195 | if (IS_ERR(hw)) | ||
196 | return PTR_ERR(hw); | ||
197 | |||
198 | wl = hw->priv; | ||
199 | |||
200 | wl->if_priv = func; | ||
201 | wl->if_ops = &sdio_ops; | ||
202 | |||
203 | /* Grab access to FN0 for ELP reg. */ | ||
204 | func->card->quirks |= MMC_QUIRK_LENIENT_FN0; | ||
205 | |||
206 | wl->irq = gpio_to_irq(RX71_WL1271_IRQ_GPIO); | ||
207 | if (wl->irq < 0) { | ||
208 | ret = wl->irq; | ||
209 | wl1271_error("could not get irq!"); | ||
210 | goto out_free; | ||
211 | } | ||
212 | |||
213 | ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl); | ||
214 | if (ret < 0) { | ||
215 | wl1271_error("request_irq() failed: %d", ret); | ||
216 | goto out_free; | ||
217 | } | ||
218 | |||
219 | set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING); | ||
220 | |||
221 | disable_irq(wl->irq); | ||
222 | |||
223 | ret = wl1271_init_ieee80211(wl); | ||
224 | if (ret) | ||
225 | goto out_irq; | ||
226 | |||
227 | ret = wl1271_register_hw(wl); | ||
228 | if (ret) | ||
229 | goto out_irq; | ||
230 | |||
231 | sdio_set_drvdata(func, wl); | ||
232 | |||
233 | wl1271_notice("initialized"); | ||
234 | |||
235 | return 0; | ||
236 | |||
237 | out_irq: | ||
238 | free_irq(wl->irq, wl); | ||
239 | |||
240 | |||
241 | out_free: | ||
242 | wl1271_free_hw(wl); | ||
243 | |||
244 | return ret; | ||
245 | } | ||
246 | |||
247 | static void __devexit wl1271_remove(struct sdio_func *func) | ||
248 | { | ||
249 | struct wl1271 *wl = sdio_get_drvdata(func); | ||
250 | |||
251 | free_irq(wl->irq, wl); | ||
252 | |||
253 | wl1271_unregister_hw(wl); | ||
254 | wl1271_free_hw(wl); | ||
255 | } | ||
256 | |||
257 | static struct sdio_driver wl1271_sdio_driver = { | ||
258 | .name = "wl1271_sdio", | ||
259 | .id_table = wl1271_devices, | ||
260 | .probe = wl1271_probe, | ||
261 | .remove = __devexit_p(wl1271_remove), | ||
262 | }; | ||
263 | |||
264 | static int __init wl1271_init(void) | ||
265 | { | ||
266 | int ret; | ||
267 | |||
268 | ret = sdio_register_driver(&wl1271_sdio_driver); | ||
269 | if (ret < 0) { | ||
270 | wl1271_error("failed to register sdio driver: %d", ret); | ||
271 | goto out; | ||
272 | } | ||
273 | |||
274 | out: | ||
275 | return ret; | ||
276 | } | ||
277 | |||
278 | static void __exit wl1271_exit(void) | ||
279 | { | ||
280 | sdio_unregister_driver(&wl1271_sdio_driver); | ||
281 | |||
282 | wl1271_notice("unloaded"); | ||
283 | } | ||
284 | |||
285 | module_init(wl1271_init); | ||
286 | module_exit(wl1271_exit); | ||
287 | |||
288 | MODULE_LICENSE("GPL"); | ||
289 | MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>"); | ||
290 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); | ||
291 | MODULE_FIRMWARE(WL1271_FW_NAME); | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c index 67a82934f36e..7a7db011a797 100644 --- a/drivers/net/wireless/wl12xx/wl1271_spi.c +++ b/drivers/net/wireless/wl12xx/wl1271_spi.c | |||
@@ -21,17 +21,68 @@ | |||
21 | * | 21 | * |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <linux/irq.h> | ||
24 | #include <linux/module.h> | 25 | #include <linux/module.h> |
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/crc7.h> | 26 | #include <linux/crc7.h> |
27 | #include <linux/spi/spi.h> | 27 | #include <linux/spi/spi.h> |
28 | #include <linux/spi/wl12xx.h> | ||
28 | 29 | ||
29 | #include "wl1271.h" | 30 | #include "wl1271.h" |
30 | #include "wl12xx_80211.h" | 31 | #include "wl12xx_80211.h" |
31 | #include "wl1271_spi.h" | 32 | #include "wl1271_io.h" |
33 | |||
34 | #include "wl1271_reg.h" | ||
35 | |||
36 | #define WSPI_CMD_READ 0x40000000 | ||
37 | #define WSPI_CMD_WRITE 0x00000000 | ||
38 | #define WSPI_CMD_FIXED 0x20000000 | ||
39 | #define WSPI_CMD_BYTE_LENGTH 0x1FFE0000 | ||
40 | #define WSPI_CMD_BYTE_LENGTH_OFFSET 17 | ||
41 | #define WSPI_CMD_BYTE_ADDR 0x0001FFFF | ||
42 | |||
43 | #define WSPI_INIT_CMD_CRC_LEN 5 | ||
44 | |||
45 | #define WSPI_INIT_CMD_START 0x00 | ||
46 | #define WSPI_INIT_CMD_TX 0x40 | ||
47 | /* the extra bypass bit is sampled by the TNET as '1' */ | ||
48 | #define WSPI_INIT_CMD_BYPASS_BIT 0x80 | ||
49 | #define WSPI_INIT_CMD_FIXEDBUSY_LEN 0x07 | ||
50 | #define WSPI_INIT_CMD_EN_FIXEDBUSY 0x80 | ||
51 | #define WSPI_INIT_CMD_DIS_FIXEDBUSY 0x00 | ||
52 | #define WSPI_INIT_CMD_IOD 0x40 | ||
53 | #define WSPI_INIT_CMD_IP 0x20 | ||
54 | #define WSPI_INIT_CMD_CS 0x10 | ||
55 | #define WSPI_INIT_CMD_WS 0x08 | ||
56 | #define WSPI_INIT_CMD_WSPI 0x01 | ||
57 | #define WSPI_INIT_CMD_END 0x01 | ||
58 | |||
59 | #define WSPI_INIT_CMD_LEN 8 | ||
60 | |||
61 | #define HW_ACCESS_WSPI_FIXED_BUSY_LEN \ | ||
62 | ((WL1271_BUSY_WORD_LEN - 4) / sizeof(u32)) | ||
63 | #define HW_ACCESS_WSPI_INIT_CMD_MASK 0 | ||
64 | |||
65 | static inline struct spi_device *wl_to_spi(struct wl1271 *wl) | ||
66 | { | ||
67 | return wl->if_priv; | ||
68 | } | ||
32 | 69 | ||
70 | static struct device *wl1271_spi_wl_to_dev(struct wl1271 *wl) | ||
71 | { | ||
72 | return &(wl_to_spi(wl)->dev); | ||
73 | } | ||
33 | 74 | ||
34 | void wl1271_spi_reset(struct wl1271 *wl) | 75 | static void wl1271_spi_disable_interrupts(struct wl1271 *wl) |
76 | { | ||
77 | disable_irq(wl->irq); | ||
78 | } | ||
79 | |||
80 | static void wl1271_spi_enable_interrupts(struct wl1271 *wl) | ||
81 | { | ||
82 | enable_irq(wl->irq); | ||
83 | } | ||
84 | |||
85 | static void wl1271_spi_reset(struct wl1271 *wl) | ||
35 | { | 86 | { |
36 | u8 *cmd; | 87 | u8 *cmd; |
37 | struct spi_transfer t; | 88 | struct spi_transfer t; |
@@ -52,12 +103,13 @@ void wl1271_spi_reset(struct wl1271 *wl) | |||
52 | t.len = WSPI_INIT_CMD_LEN; | 103 | t.len = WSPI_INIT_CMD_LEN; |
53 | spi_message_add_tail(&t, &m); | 104 | spi_message_add_tail(&t, &m); |
54 | 105 | ||
55 | spi_sync(wl->spi, &m); | 106 | spi_sync(wl_to_spi(wl), &m); |
107 | kfree(cmd); | ||
56 | 108 | ||
57 | wl1271_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN); | 109 | wl1271_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN); |
58 | } | 110 | } |
59 | 111 | ||
60 | void wl1271_spi_init(struct wl1271 *wl) | 112 | static void wl1271_spi_init(struct wl1271 *wl) |
61 | { | 113 | { |
62 | u8 crc[WSPI_INIT_CMD_CRC_LEN], *cmd; | 114 | u8 crc[WSPI_INIT_CMD_CRC_LEN], *cmd; |
63 | struct spi_transfer t; | 115 | struct spi_transfer t; |
@@ -106,48 +158,25 @@ void wl1271_spi_init(struct wl1271 *wl) | |||
106 | t.len = WSPI_INIT_CMD_LEN; | 158 | t.len = WSPI_INIT_CMD_LEN; |
107 | spi_message_add_tail(&t, &m); | 159 | spi_message_add_tail(&t, &m); |
108 | 160 | ||
109 | spi_sync(wl->spi, &m); | 161 | spi_sync(wl_to_spi(wl), &m); |
162 | kfree(cmd); | ||
110 | 163 | ||
111 | wl1271_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN); | 164 | wl1271_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN); |
112 | } | 165 | } |
113 | 166 | ||
114 | #define WL1271_BUSY_WORD_TIMEOUT 1000 | 167 | #define WL1271_BUSY_WORD_TIMEOUT 1000 |
115 | 168 | ||
116 | /* FIXME: Check busy words, removed due to SPI bug */ | 169 | static int wl1271_spi_read_busy(struct wl1271 *wl) |
117 | #if 0 | ||
118 | static void wl1271_spi_read_busy(struct wl1271 *wl, void *buf, size_t len) | ||
119 | { | 170 | { |
120 | struct spi_transfer t[1]; | 171 | struct spi_transfer t[1]; |
121 | struct spi_message m; | 172 | struct spi_message m; |
122 | u32 *busy_buf; | 173 | u32 *busy_buf; |
123 | int num_busy_bytes = 0; | 174 | int num_busy_bytes = 0; |
124 | 175 | ||
125 | wl1271_info("spi read BUSY!"); | ||
126 | |||
127 | /* | ||
128 | * Look for the non-busy word in the read buffer, and if found, | ||
129 | * read in the remaining data into the buffer. | ||
130 | */ | ||
131 | busy_buf = (u32 *)buf; | ||
132 | for (; (u32)busy_buf < (u32)buf + len; busy_buf++) { | ||
133 | num_busy_bytes += sizeof(u32); | ||
134 | if (*busy_buf & 0x1) { | ||
135 | spi_message_init(&m); | ||
136 | memset(t, 0, sizeof(t)); | ||
137 | memmove(buf, busy_buf, len - num_busy_bytes); | ||
138 | t[0].rx_buf = buf + (len - num_busy_bytes); | ||
139 | t[0].len = num_busy_bytes; | ||
140 | spi_message_add_tail(&t[0], &m); | ||
141 | spi_sync(wl->spi, &m); | ||
142 | return; | ||
143 | } | ||
144 | } | ||
145 | |||
146 | /* | 176 | /* |
147 | * Read further busy words from SPI until a non-busy word is | 177 | * Read further busy words from SPI until a non-busy word is |
148 | * encountered, then read the data itself into the buffer. | 178 | * encountered, then read the data itself into the buffer. |
149 | */ | 179 | */ |
150 | wl1271_info("spi read BUSY-polling needed!"); | ||
151 | 180 | ||
152 | num_busy_bytes = WL1271_BUSY_WORD_TIMEOUT; | 181 | num_busy_bytes = WL1271_BUSY_WORD_TIMEOUT; |
153 | busy_buf = wl->buffer_busyword; | 182 | busy_buf = wl->buffer_busyword; |
@@ -157,28 +186,21 @@ static void wl1271_spi_read_busy(struct wl1271 *wl, void *buf, size_t len) | |||
157 | memset(t, 0, sizeof(t)); | 186 | memset(t, 0, sizeof(t)); |
158 | t[0].rx_buf = busy_buf; | 187 | t[0].rx_buf = busy_buf; |
159 | t[0].len = sizeof(u32); | 188 | t[0].len = sizeof(u32); |
189 | t[0].cs_change = true; | ||
160 | spi_message_add_tail(&t[0], &m); | 190 | spi_message_add_tail(&t[0], &m); |
161 | spi_sync(wl->spi, &m); | 191 | spi_sync(wl_to_spi(wl), &m); |
162 | 192 | ||
163 | if (*busy_buf & 0x1) { | 193 | if (*busy_buf & 0x1) |
164 | spi_message_init(&m); | 194 | return 0; |
165 | memset(t, 0, sizeof(t)); | ||
166 | t[0].rx_buf = buf; | ||
167 | t[0].len = len; | ||
168 | spi_message_add_tail(&t[0], &m); | ||
169 | spi_sync(wl->spi, &m); | ||
170 | return; | ||
171 | } | ||
172 | } | 195 | } |
173 | 196 | ||
174 | /* The SPI bus is unresponsive, the read failed. */ | 197 | /* The SPI bus is unresponsive, the read failed. */ |
175 | memset(buf, 0, len); | ||
176 | wl1271_error("SPI read busy-word timeout!\n"); | 198 | wl1271_error("SPI read busy-word timeout!\n"); |
199 | return -ETIMEDOUT; | ||
177 | } | 200 | } |
178 | #endif | ||
179 | 201 | ||
180 | void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, | 202 | static void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, |
181 | size_t len, bool fixed) | 203 | size_t len, bool fixed) |
182 | { | 204 | { |
183 | struct spi_transfer t[3]; | 205 | struct spi_transfer t[3]; |
184 | struct spi_message m; | 206 | struct spi_message m; |
@@ -201,28 +223,38 @@ void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, | |||
201 | 223 | ||
202 | t[0].tx_buf = cmd; | 224 | t[0].tx_buf = cmd; |
203 | t[0].len = 4; | 225 | t[0].len = 4; |
226 | t[0].cs_change = true; | ||
204 | spi_message_add_tail(&t[0], &m); | 227 | spi_message_add_tail(&t[0], &m); |
205 | 228 | ||
206 | /* Busy and non busy words read */ | 229 | /* Busy and non busy words read */ |
207 | t[1].rx_buf = busy_buf; | 230 | t[1].rx_buf = busy_buf; |
208 | t[1].len = WL1271_BUSY_WORD_LEN; | 231 | t[1].len = WL1271_BUSY_WORD_LEN; |
232 | t[1].cs_change = true; | ||
209 | spi_message_add_tail(&t[1], &m); | 233 | spi_message_add_tail(&t[1], &m); |
210 | 234 | ||
211 | t[2].rx_buf = buf; | 235 | spi_sync(wl_to_spi(wl), &m); |
212 | t[2].len = len; | ||
213 | spi_message_add_tail(&t[2], &m); | ||
214 | 236 | ||
215 | spi_sync(wl->spi, &m); | 237 | if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1) && |
238 | wl1271_spi_read_busy(wl)) { | ||
239 | memset(buf, 0, len); | ||
240 | return; | ||
241 | } | ||
216 | 242 | ||
217 | /* FIXME: Check busy words, removed due to SPI bug */ | 243 | spi_message_init(&m); |
218 | /* if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1)) | 244 | memset(t, 0, sizeof(t)); |
219 | wl1271_spi_read_busy(wl, buf, len); */ | 245 | |
246 | t[0].rx_buf = buf; | ||
247 | t[0].len = len; | ||
248 | t[0].cs_change = true; | ||
249 | spi_message_add_tail(&t[0], &m); | ||
250 | |||
251 | spi_sync(wl_to_spi(wl), &m); | ||
220 | 252 | ||
221 | wl1271_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd)); | 253 | wl1271_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd)); |
222 | wl1271_dump(DEBUG_SPI, "spi_read buf <- ", buf, len); | 254 | wl1271_dump(DEBUG_SPI, "spi_read buf <- ", buf, len); |
223 | } | 255 | } |
224 | 256 | ||
225 | void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf, | 257 | static void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf, |
226 | size_t len, bool fixed) | 258 | size_t len, bool fixed) |
227 | { | 259 | { |
228 | struct spi_transfer t[2]; | 260 | struct spi_transfer t[2]; |
@@ -250,8 +282,181 @@ void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf, | |||
250 | t[1].len = len; | 282 | t[1].len = len; |
251 | spi_message_add_tail(&t[1], &m); | 283 | spi_message_add_tail(&t[1], &m); |
252 | 284 | ||
253 | spi_sync(wl->spi, &m); | 285 | spi_sync(wl_to_spi(wl), &m); |
254 | 286 | ||
255 | wl1271_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd)); | 287 | wl1271_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd)); |
256 | wl1271_dump(DEBUG_SPI, "spi_write buf -> ", buf, len); | 288 | wl1271_dump(DEBUG_SPI, "spi_write buf -> ", buf, len); |
257 | } | 289 | } |
290 | |||
291 | static irqreturn_t wl1271_irq(int irq, void *cookie) | ||
292 | { | ||
293 | struct wl1271 *wl; | ||
294 | unsigned long flags; | ||
295 | |||
296 | wl1271_debug(DEBUG_IRQ, "IRQ"); | ||
297 | |||
298 | wl = cookie; | ||
299 | |||
300 | /* complete the ELP completion */ | ||
301 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
302 | if (wl->elp_compl) { | ||
303 | complete(wl->elp_compl); | ||
304 | wl->elp_compl = NULL; | ||
305 | } | ||
306 | |||
307 | if (!test_and_set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags)) | ||
308 | ieee80211_queue_work(wl->hw, &wl->irq_work); | ||
309 | set_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags); | ||
310 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
311 | |||
312 | return IRQ_HANDLED; | ||
313 | } | ||
314 | |||
315 | static void wl1271_spi_set_power(struct wl1271 *wl, bool enable) | ||
316 | { | ||
317 | if (wl->set_power) | ||
318 | wl->set_power(enable); | ||
319 | } | ||
320 | |||
321 | static struct wl1271_if_operations spi_ops = { | ||
322 | .read = wl1271_spi_raw_read, | ||
323 | .write = wl1271_spi_raw_write, | ||
324 | .reset = wl1271_spi_reset, | ||
325 | .init = wl1271_spi_init, | ||
326 | .power = wl1271_spi_set_power, | ||
327 | .dev = wl1271_spi_wl_to_dev, | ||
328 | .enable_irq = wl1271_spi_enable_interrupts, | ||
329 | .disable_irq = wl1271_spi_disable_interrupts | ||
330 | }; | ||
331 | |||
332 | static int __devinit wl1271_probe(struct spi_device *spi) | ||
333 | { | ||
334 | struct wl12xx_platform_data *pdata; | ||
335 | struct ieee80211_hw *hw; | ||
336 | struct wl1271 *wl; | ||
337 | int ret; | ||
338 | |||
339 | pdata = spi->dev.platform_data; | ||
340 | if (!pdata) { | ||
341 | wl1271_error("no platform data"); | ||
342 | return -ENODEV; | ||
343 | } | ||
344 | |||
345 | hw = wl1271_alloc_hw(); | ||
346 | if (IS_ERR(hw)) | ||
347 | return PTR_ERR(hw); | ||
348 | |||
349 | wl = hw->priv; | ||
350 | |||
351 | dev_set_drvdata(&spi->dev, wl); | ||
352 | wl->if_priv = spi; | ||
353 | |||
354 | wl->if_ops = &spi_ops; | ||
355 | |||
356 | /* This is the only SPI value that we need to set here, the rest | ||
357 | * comes from the board-peripherals file */ | ||
358 | spi->bits_per_word = 32; | ||
359 | |||
360 | ret = spi_setup(spi); | ||
361 | if (ret < 0) { | ||
362 | wl1271_error("spi_setup failed"); | ||
363 | goto out_free; | ||
364 | } | ||
365 | |||
366 | wl->set_power = pdata->set_power; | ||
367 | if (!wl->set_power) { | ||
368 | wl1271_error("set power function missing in platform data"); | ||
369 | ret = -ENODEV; | ||
370 | goto out_free; | ||
371 | } | ||
372 | |||
373 | wl->irq = spi->irq; | ||
374 | if (wl->irq < 0) { | ||
375 | wl1271_error("irq missing in platform data"); | ||
376 | ret = -ENODEV; | ||
377 | goto out_free; | ||
378 | } | ||
379 | |||
380 | ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl); | ||
381 | if (ret < 0) { | ||
382 | wl1271_error("request_irq() failed: %d", ret); | ||
383 | goto out_free; | ||
384 | } | ||
385 | |||
386 | set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING); | ||
387 | |||
388 | disable_irq(wl->irq); | ||
389 | |||
390 | ret = wl1271_init_ieee80211(wl); | ||
391 | if (ret) | ||
392 | goto out_irq; | ||
393 | |||
394 | ret = wl1271_register_hw(wl); | ||
395 | if (ret) | ||
396 | goto out_irq; | ||
397 | |||
398 | wl1271_notice("initialized"); | ||
399 | |||
400 | return 0; | ||
401 | |||
402 | out_irq: | ||
403 | free_irq(wl->irq, wl); | ||
404 | |||
405 | out_free: | ||
406 | wl1271_free_hw(wl); | ||
407 | |||
408 | return ret; | ||
409 | } | ||
410 | |||
411 | static int __devexit wl1271_remove(struct spi_device *spi) | ||
412 | { | ||
413 | struct wl1271 *wl = dev_get_drvdata(&spi->dev); | ||
414 | |||
415 | free_irq(wl->irq, wl); | ||
416 | |||
417 | wl1271_unregister_hw(wl); | ||
418 | wl1271_free_hw(wl); | ||
419 | |||
420 | return 0; | ||
421 | } | ||
422 | |||
423 | |||
424 | static struct spi_driver wl1271_spi_driver = { | ||
425 | .driver = { | ||
426 | .name = "wl1271_spi", | ||
427 | .bus = &spi_bus_type, | ||
428 | .owner = THIS_MODULE, | ||
429 | }, | ||
430 | |||
431 | .probe = wl1271_probe, | ||
432 | .remove = __devexit_p(wl1271_remove), | ||
433 | }; | ||
434 | |||
435 | static int __init wl1271_init(void) | ||
436 | { | ||
437 | int ret; | ||
438 | |||
439 | ret = spi_register_driver(&wl1271_spi_driver); | ||
440 | if (ret < 0) { | ||
441 | wl1271_error("failed to register spi driver: %d", ret); | ||
442 | goto out; | ||
443 | } | ||
444 | |||
445 | out: | ||
446 | return ret; | ||
447 | } | ||
448 | |||
449 | static void __exit wl1271_exit(void) | ||
450 | { | ||
451 | spi_unregister_driver(&wl1271_spi_driver); | ||
452 | |||
453 | wl1271_notice("unloaded"); | ||
454 | } | ||
455 | |||
456 | module_init(wl1271_init); | ||
457 | module_exit(wl1271_exit); | ||
458 | |||
459 | MODULE_LICENSE("GPL"); | ||
460 | MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>"); | ||
461 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); | ||
462 | MODULE_FIRMWARE(WL1271_FW_NAME); | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.h b/drivers/net/wireless/wl12xx/wl1271_spi.h deleted file mode 100644 index a803596dad4a..000000000000 --- a/drivers/net/wireless/wl12xx/wl1271_spi.h +++ /dev/null | |||
@@ -1,96 +0,0 @@ | |||
1 | /* | ||
2 | * This file is part of wl1271 | ||
3 | * | ||
4 | * Copyright (C) 1998-2009 Texas Instruments. All rights reserved. | ||
5 | * Copyright (C) 2008-2009 Nokia Corporation | ||
6 | * | ||
7 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * version 2 as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
21 | * 02110-1301 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #ifndef __WL1271_SPI_H__ | ||
26 | #define __WL1271_SPI_H__ | ||
27 | |||
28 | #include "wl1271_reg.h" | ||
29 | |||
30 | #define HW_ACCESS_MEMORY_MAX_RANGE 0x1FFC0 | ||
31 | |||
32 | #define HW_PARTITION_REGISTERS_ADDR 0x1ffc0 | ||
33 | #define HW_PART0_SIZE_ADDR (HW_PARTITION_REGISTERS_ADDR) | ||
34 | #define HW_PART0_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 4) | ||
35 | #define HW_PART1_SIZE_ADDR (HW_PARTITION_REGISTERS_ADDR + 8) | ||
36 | #define HW_PART1_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 12) | ||
37 | #define HW_PART2_SIZE_ADDR (HW_PARTITION_REGISTERS_ADDR + 16) | ||
38 | #define HW_PART2_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 20) | ||
39 | #define HW_PART3_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 24) | ||
40 | |||
41 | #define HW_ACCESS_REGISTER_SIZE 4 | ||
42 | |||
43 | #define HW_ACCESS_PRAM_MAX_RANGE 0x3c000 | ||
44 | |||
45 | #define WSPI_CMD_READ 0x40000000 | ||
46 | #define WSPI_CMD_WRITE 0x00000000 | ||
47 | #define WSPI_CMD_FIXED 0x20000000 | ||
48 | #define WSPI_CMD_BYTE_LENGTH 0x1FFE0000 | ||
49 | #define WSPI_CMD_BYTE_LENGTH_OFFSET 17 | ||
50 | #define WSPI_CMD_BYTE_ADDR 0x0001FFFF | ||
51 | |||
52 | #define WSPI_INIT_CMD_CRC_LEN 5 | ||
53 | |||
54 | #define WSPI_INIT_CMD_START 0x00 | ||
55 | #define WSPI_INIT_CMD_TX 0x40 | ||
56 | /* the extra bypass bit is sampled by the TNET as '1' */ | ||
57 | #define WSPI_INIT_CMD_BYPASS_BIT 0x80 | ||
58 | #define WSPI_INIT_CMD_FIXEDBUSY_LEN 0x07 | ||
59 | #define WSPI_INIT_CMD_EN_FIXEDBUSY 0x80 | ||
60 | #define WSPI_INIT_CMD_DIS_FIXEDBUSY 0x00 | ||
61 | #define WSPI_INIT_CMD_IOD 0x40 | ||
62 | #define WSPI_INIT_CMD_IP 0x20 | ||
63 | #define WSPI_INIT_CMD_CS 0x10 | ||
64 | #define WSPI_INIT_CMD_WS 0x08 | ||
65 | #define WSPI_INIT_CMD_WSPI 0x01 | ||
66 | #define WSPI_INIT_CMD_END 0x01 | ||
67 | |||
68 | #define WSPI_INIT_CMD_LEN 8 | ||
69 | |||
70 | #define HW_ACCESS_WSPI_FIXED_BUSY_LEN \ | ||
71 | ((WL1271_BUSY_WORD_LEN - 4) / sizeof(u32)) | ||
72 | #define HW_ACCESS_WSPI_INIT_CMD_MASK 0 | ||
73 | |||
74 | #define OCP_CMD_LOOP 32 | ||
75 | |||
76 | #define OCP_CMD_WRITE 0x1 | ||
77 | #define OCP_CMD_READ 0x2 | ||
78 | |||
79 | #define OCP_READY_MASK BIT(18) | ||
80 | #define OCP_STATUS_MASK (BIT(16) | BIT(17)) | ||
81 | |||
82 | #define OCP_STATUS_NO_RESP 0x00000 | ||
83 | #define OCP_STATUS_OK 0x10000 | ||
84 | #define OCP_STATUS_REQ_FAILED 0x20000 | ||
85 | #define OCP_STATUS_RESP_ERROR 0x30000 | ||
86 | |||
87 | /* Raw target IO, address is not translated */ | ||
88 | void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf, | ||
89 | size_t len, bool fixed); | ||
90 | void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, | ||
91 | size_t len, bool fixed); | ||
92 | |||
93 | /* INIT and RESET words */ | ||
94 | void wl1271_spi_reset(struct wl1271 *wl); | ||
95 | void wl1271_spi_init(struct wl1271 *wl); | ||
96 | #endif /* __WL1271_SPI_H__ */ | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_testmode.c b/drivers/net/wireless/wl12xx/wl1271_testmode.c index 3919102e942e..2401e6035d51 100644 --- a/drivers/net/wireless/wl12xx/wl1271_testmode.c +++ b/drivers/net/wireless/wl12xx/wl1271_testmode.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <net/genetlink.h> | 25 | #include <net/genetlink.h> |
26 | 26 | ||
27 | #include "wl1271.h" | 27 | #include "wl1271.h" |
28 | #include "wl1271_spi.h" | ||
29 | #include "wl1271_acx.h" | 28 | #include "wl1271_acx.h" |
30 | 29 | ||
31 | #define WL1271_TM_MAX_DATA_LENGTH 1024 | 30 | #define WL1271_TM_MAX_DATA_LENGTH 1024 |
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c index 811e739d05bf..62db79508ddf 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.c +++ b/drivers/net/wireless/wl12xx/wl1271_tx.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | 26 | ||
27 | #include "wl1271.h" | 27 | #include "wl1271.h" |
28 | #include "wl1271_spi.h" | ||
29 | #include "wl1271_io.h" | 28 | #include "wl1271_io.h" |
30 | #include "wl1271_reg.h" | 29 | #include "wl1271_reg.h" |
31 | #include "wl1271_ps.h" | 30 | #include "wl1271_ps.h" |
@@ -47,7 +46,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra) | |||
47 | { | 46 | { |
48 | struct wl1271_tx_hw_descr *desc; | 47 | struct wl1271_tx_hw_descr *desc; |
49 | u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra; | 48 | u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra; |
50 | u32 total_blocks, excluded; | 49 | u32 total_blocks; |
51 | int id, ret = -EBUSY; | 50 | int id, ret = -EBUSY; |
52 | 51 | ||
53 | /* allocate free identifier for the packet */ | 52 | /* allocate free identifier for the packet */ |
@@ -57,12 +56,8 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra) | |||
57 | 56 | ||
58 | /* approximate the number of blocks required for this packet | 57 | /* approximate the number of blocks required for this packet |
59 | in the firmware */ | 58 | in the firmware */ |
60 | /* FIXME: try to figure out what is done here and make it cleaner */ | 59 | total_blocks = total_len + TX_HW_BLOCK_SIZE - 1; |
61 | total_blocks = (total_len + 20) >> TX_HW_BLOCK_SHIFT_DIV; | 60 | total_blocks = total_blocks / TX_HW_BLOCK_SIZE + TX_HW_BLOCK_SPARE; |
62 | excluded = (total_blocks << 2) + ((total_len + 20) & 0xff) + 34; | ||
63 | total_blocks += (excluded > 252) ? 2 : 1; | ||
64 | total_blocks += TX_HW_BLOCK_SPARE; | ||
65 | |||
66 | if (total_blocks <= wl->tx_blocks_available) { | 61 | if (total_blocks <= wl->tx_blocks_available) { |
67 | desc = (struct wl1271_tx_hw_descr *)skb_push( | 62 | desc = (struct wl1271_tx_hw_descr *)skb_push( |
68 | skb, total_len - skb->len); | 63 | skb, total_len - skb->len); |
@@ -87,8 +82,10 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra) | |||
87 | static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, | 82 | static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, |
88 | u32 extra, struct ieee80211_tx_info *control) | 83 | u32 extra, struct ieee80211_tx_info *control) |
89 | { | 84 | { |
85 | struct timespec ts; | ||
90 | struct wl1271_tx_hw_descr *desc; | 86 | struct wl1271_tx_hw_descr *desc; |
91 | int pad, ac; | 87 | int pad, ac; |
88 | s64 hosttime; | ||
92 | u16 tx_attr; | 89 | u16 tx_attr; |
93 | 90 | ||
94 | desc = (struct wl1271_tx_hw_descr *) skb->data; | 91 | desc = (struct wl1271_tx_hw_descr *) skb->data; |
@@ -102,8 +99,9 @@ static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, | |||
102 | } | 99 | } |
103 | 100 | ||
104 | /* configure packet life time */ | 101 | /* configure packet life time */ |
105 | desc->start_time = cpu_to_le32(jiffies_to_usecs(jiffies) - | 102 | getnstimeofday(&ts); |
106 | wl->time_offset); | 103 | hosttime = (timespec_to_ns(&ts) >> 10); |
104 | desc->start_time = cpu_to_le32(hosttime - wl->time_offset); | ||
107 | desc->life_time = cpu_to_le16(TX_HW_MGMT_PKT_LIFETIME_TU); | 105 | desc->life_time = cpu_to_le16(TX_HW_MGMT_PKT_LIFETIME_TU); |
108 | 106 | ||
109 | /* configure the tx attributes */ | 107 | /* configure the tx attributes */ |
@@ -170,7 +168,6 @@ static int wl1271_tx_send_packet(struct wl1271 *wl, struct sk_buff *skb, | |||
170 | 168 | ||
171 | /* write packet new counter into the write access register */ | 169 | /* write packet new counter into the write access register */ |
172 | wl->tx_packets_count++; | 170 | wl->tx_packets_count++; |
173 | wl1271_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count); | ||
174 | 171 | ||
175 | desc = (struct wl1271_tx_hw_descr *) skb->data; | 172 | desc = (struct wl1271_tx_hw_descr *) skb->data; |
176 | wl1271_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u (%u words)", | 173 | wl1271_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u (%u words)", |
@@ -223,7 +220,7 @@ static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb) | |||
223 | return ret; | 220 | return ret; |
224 | } | 221 | } |
225 | 222 | ||
226 | static u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set) | 223 | u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set) |
227 | { | 224 | { |
228 | struct ieee80211_supported_band *band; | 225 | struct ieee80211_supported_band *band; |
229 | u32 enabled_rates = 0; | 226 | u32 enabled_rates = 0; |
@@ -245,6 +242,7 @@ void wl1271_tx_work(struct work_struct *work) | |||
245 | struct sk_buff *skb; | 242 | struct sk_buff *skb; |
246 | bool woken_up = false; | 243 | bool woken_up = false; |
247 | u32 sta_rates = 0; | 244 | u32 sta_rates = 0; |
245 | u32 prev_tx_packets_count; | ||
248 | int ret; | 246 | int ret; |
249 | 247 | ||
250 | /* check if the rates supported by the AP have changed */ | 248 | /* check if the rates supported by the AP have changed */ |
@@ -261,6 +259,8 @@ void wl1271_tx_work(struct work_struct *work) | |||
261 | if (unlikely(wl->state == WL1271_STATE_OFF)) | 259 | if (unlikely(wl->state == WL1271_STATE_OFF)) |
262 | goto out; | 260 | goto out; |
263 | 261 | ||
262 | prev_tx_packets_count = wl->tx_packets_count; | ||
263 | |||
264 | /* if rates have changed, re-configure the rate policy */ | 264 | /* if rates have changed, re-configure the rate policy */ |
265 | if (unlikely(sta_rates)) { | 265 | if (unlikely(sta_rates)) { |
266 | wl->rate_set = wl1271_tx_enabled_rates_get(wl, sta_rates); | 266 | wl->rate_set = wl1271_tx_enabled_rates_get(wl, sta_rates); |
@@ -271,31 +271,26 @@ void wl1271_tx_work(struct work_struct *work) | |||
271 | if (!woken_up) { | 271 | if (!woken_up) { |
272 | ret = wl1271_ps_elp_wakeup(wl, false); | 272 | ret = wl1271_ps_elp_wakeup(wl, false); |
273 | if (ret < 0) | 273 | if (ret < 0) |
274 | goto out; | 274 | goto out_ack; |
275 | woken_up = true; | 275 | woken_up = true; |
276 | } | 276 | } |
277 | 277 | ||
278 | ret = wl1271_tx_frame(wl, skb); | 278 | ret = wl1271_tx_frame(wl, skb); |
279 | if (ret == -EBUSY) { | 279 | if (ret == -EBUSY) { |
280 | /* firmware buffer is full, stop queues */ | 280 | /* firmware buffer is full, lets stop transmitting. */ |
281 | wl1271_debug(DEBUG_TX, "tx_work: fw buffer full, " | ||
282 | "stop queues"); | ||
283 | ieee80211_stop_queues(wl->hw); | ||
284 | set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); | ||
285 | skb_queue_head(&wl->tx_queue, skb); | 281 | skb_queue_head(&wl->tx_queue, skb); |
286 | goto out; | 282 | goto out_ack; |
287 | } else if (ret < 0) { | 283 | } else if (ret < 0) { |
288 | dev_kfree_skb(skb); | 284 | dev_kfree_skb(skb); |
289 | goto out; | 285 | goto out_ack; |
290 | } else if (test_and_clear_bit(WL1271_FLAG_TX_QUEUE_STOPPED, | ||
291 | &wl->flags)) { | ||
292 | /* firmware buffer has space, restart queues */ | ||
293 | wl1271_debug(DEBUG_TX, | ||
294 | "complete_packet: waking queues"); | ||
295 | ieee80211_wake_queues(wl->hw); | ||
296 | } | 286 | } |
297 | } | 287 | } |
298 | 288 | ||
289 | out_ack: | ||
290 | /* interrupt the firmware with the new packets */ | ||
291 | if (prev_tx_packets_count != wl->tx_packets_count) | ||
292 | wl1271_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count); | ||
293 | |||
299 | out: | 294 | out: |
300 | if (woken_up) | 295 | if (woken_up) |
301 | wl1271_ps_elp_sleep(wl); | 296 | wl1271_ps_elp_sleep(wl); |
@@ -308,11 +303,12 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, | |||
308 | { | 303 | { |
309 | struct ieee80211_tx_info *info; | 304 | struct ieee80211_tx_info *info; |
310 | struct sk_buff *skb; | 305 | struct sk_buff *skb; |
311 | u16 seq; | ||
312 | int id = result->id; | 306 | int id = result->id; |
307 | int rate = -1; | ||
308 | u8 retries = 0; | ||
313 | 309 | ||
314 | /* check for id legality */ | 310 | /* check for id legality */ |
315 | if (id >= ACX_TX_DESCRIPTORS || wl->tx_frames[id] == NULL) { | 311 | if (unlikely(id >= ACX_TX_DESCRIPTORS || wl->tx_frames[id] == NULL)) { |
316 | wl1271_warning("TX result illegal id: %d", id); | 312 | wl1271_warning("TX result illegal id: %d", id); |
317 | return; | 313 | return; |
318 | } | 314 | } |
@@ -320,31 +316,29 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, | |||
320 | skb = wl->tx_frames[id]; | 316 | skb = wl->tx_frames[id]; |
321 | info = IEEE80211_SKB_CB(skb); | 317 | info = IEEE80211_SKB_CB(skb); |
322 | 318 | ||
323 | /* update packet status */ | 319 | /* update the TX status info */ |
324 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { | 320 | if (result->status == TX_SUCCESS) { |
325 | if (result->status == TX_SUCCESS) | 321 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) |
326 | info->flags |= IEEE80211_TX_STAT_ACK; | 322 | info->flags |= IEEE80211_TX_STAT_ACK; |
327 | if (result->status & TX_RETRY_EXCEEDED) { | 323 | rate = wl1271_rate_to_idx(wl, result->rate_class_index); |
328 | /* FIXME */ | 324 | retries = result->ack_failures; |
329 | /* info->status.excessive_retries = 1; */ | 325 | } else if (result->status == TX_RETRY_EXCEEDED) { |
330 | wl->stats.excessive_retries++; | 326 | wl->stats.excessive_retries++; |
331 | } | 327 | retries = result->ack_failures; |
332 | } | 328 | } |
333 | 329 | ||
334 | /* FIXME */ | 330 | info->status.rates[0].idx = rate; |
335 | /* info->status.retry_count = result->ack_failures; */ | 331 | info->status.rates[0].count = retries; |
332 | info->status.rates[0].flags = 0; | ||
333 | info->status.ack_signal = -1; | ||
334 | |||
336 | wl->stats.retry_count += result->ack_failures; | 335 | wl->stats.retry_count += result->ack_failures; |
337 | 336 | ||
338 | /* update security sequence number */ | 337 | /* update security sequence number */ |
339 | seq = wl->tx_security_seq_16 + | 338 | wl->tx_security_seq += (result->lsb_security_sequence_number - |
340 | (result->lsb_security_sequence_number - | 339 | wl->tx_security_last_seq); |
341 | wl->tx_security_last_seq); | ||
342 | wl->tx_security_last_seq = result->lsb_security_sequence_number; | 340 | wl->tx_security_last_seq = result->lsb_security_sequence_number; |
343 | 341 | ||
344 | if (seq < wl->tx_security_seq_16) | ||
345 | wl->tx_security_seq_32++; | ||
346 | wl->tx_security_seq_16 = seq; | ||
347 | |||
348 | /* remove private header from packet */ | 342 | /* remove private header from packet */ |
349 | skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); | 343 | skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); |
350 | 344 | ||
@@ -367,23 +361,29 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, | |||
367 | } | 361 | } |
368 | 362 | ||
369 | /* Called upon reception of a TX complete interrupt */ | 363 | /* Called upon reception of a TX complete interrupt */ |
370 | void wl1271_tx_complete(struct wl1271 *wl, u32 count) | 364 | void wl1271_tx_complete(struct wl1271 *wl) |
371 | { | 365 | { |
372 | struct wl1271_acx_mem_map *memmap = | 366 | struct wl1271_acx_mem_map *memmap = |
373 | (struct wl1271_acx_mem_map *)wl->target_mem_map; | 367 | (struct wl1271_acx_mem_map *)wl->target_mem_map; |
368 | u32 count, fw_counter; | ||
374 | u32 i; | 369 | u32 i; |
375 | 370 | ||
376 | wl1271_debug(DEBUG_TX, "tx_complete received, packets: %d", count); | ||
377 | |||
378 | /* read the tx results from the chipset */ | 371 | /* read the tx results from the chipset */ |
379 | wl1271_read(wl, le32_to_cpu(memmap->tx_result), | 372 | wl1271_read(wl, le32_to_cpu(memmap->tx_result), |
380 | wl->tx_res_if, sizeof(*wl->tx_res_if), false); | 373 | wl->tx_res_if, sizeof(*wl->tx_res_if), false); |
374 | fw_counter = le32_to_cpu(wl->tx_res_if->tx_result_fw_counter); | ||
375 | |||
376 | /* write host counter to chipset (to ack) */ | ||
377 | wl1271_write32(wl, le32_to_cpu(memmap->tx_result) + | ||
378 | offsetof(struct wl1271_tx_hw_res_if, | ||
379 | tx_result_host_counter), fw_counter); | ||
380 | |||
381 | count = fw_counter - wl->tx_results_count; | ||
382 | wl1271_debug(DEBUG_TX, "tx_complete received, packets: %d", count); | ||
381 | 383 | ||
382 | /* verify that the result buffer is not getting overrun */ | 384 | /* verify that the result buffer is not getting overrun */ |
383 | if (count > TX_HW_RESULT_QUEUE_LEN) { | 385 | if (unlikely(count > TX_HW_RESULT_QUEUE_LEN)) |
384 | wl1271_warning("TX result overflow from chipset: %d", count); | 386 | wl1271_warning("TX result overflow from chipset: %d", count); |
385 | count = TX_HW_RESULT_QUEUE_LEN; | ||
386 | } | ||
387 | 387 | ||
388 | /* process the results */ | 388 | /* process the results */ |
389 | for (i = 0; i < count; i++) { | 389 | for (i = 0; i < count; i++) { |
@@ -397,11 +397,18 @@ void wl1271_tx_complete(struct wl1271 *wl, u32 count) | |||
397 | wl->tx_results_count++; | 397 | wl->tx_results_count++; |
398 | } | 398 | } |
399 | 399 | ||
400 | /* write host counter to chipset (to ack) */ | 400 | if (test_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags) && |
401 | wl1271_write32(wl, le32_to_cpu(memmap->tx_result) + | 401 | skb_queue_len(&wl->tx_queue) <= WL1271_TX_QUEUE_LOW_WATERMARK) { |
402 | offsetof(struct wl1271_tx_hw_res_if, | 402 | unsigned long flags; |
403 | tx_result_host_counter), | 403 | |
404 | le32_to_cpu(wl->tx_res_if->tx_result_fw_counter)); | 404 | /* firmware buffer has space, restart queues */ |
405 | wl1271_debug(DEBUG_TX, "tx_complete: waking queues"); | ||
406 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
407 | ieee80211_wake_queues(wl->hw); | ||
408 | clear_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); | ||
409 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
410 | ieee80211_queue_work(wl->hw, &wl->tx_work); | ||
411 | } | ||
405 | } | 412 | } |
406 | 413 | ||
407 | /* caller must hold wl->mutex */ | 414 | /* caller must hold wl->mutex */ |
@@ -409,31 +416,19 @@ void wl1271_tx_flush(struct wl1271 *wl) | |||
409 | { | 416 | { |
410 | int i; | 417 | int i; |
411 | struct sk_buff *skb; | 418 | struct sk_buff *skb; |
412 | struct ieee80211_tx_info *info; | ||
413 | 419 | ||
414 | /* TX failure */ | 420 | /* TX failure */ |
415 | /* control->flags = 0; FIXME */ | 421 | /* control->flags = 0; FIXME */ |
416 | 422 | ||
417 | while ((skb = skb_dequeue(&wl->tx_queue))) { | 423 | while ((skb = skb_dequeue(&wl->tx_queue))) { |
418 | info = IEEE80211_SKB_CB(skb); | ||
419 | |||
420 | wl1271_debug(DEBUG_TX, "flushing skb 0x%p", skb); | 424 | wl1271_debug(DEBUG_TX, "flushing skb 0x%p", skb); |
421 | |||
422 | if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) | ||
423 | continue; | ||
424 | |||
425 | ieee80211_tx_status(wl->hw, skb); | 425 | ieee80211_tx_status(wl->hw, skb); |
426 | } | 426 | } |
427 | 427 | ||
428 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) | 428 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) |
429 | if (wl->tx_frames[i] != NULL) { | 429 | if (wl->tx_frames[i] != NULL) { |
430 | skb = wl->tx_frames[i]; | 430 | skb = wl->tx_frames[i]; |
431 | info = IEEE80211_SKB_CB(skb); | ||
432 | |||
433 | if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) | ||
434 | continue; | ||
435 | |||
436 | ieee80211_tx_status(wl->hw, skb); | ||
437 | wl->tx_frames[i] = NULL; | 431 | wl->tx_frames[i] = NULL; |
432 | ieee80211_tx_status(wl->hw, skb); | ||
438 | } | 433 | } |
439 | } | 434 | } |
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.h b/drivers/net/wireless/wl12xx/wl1271_tx.h index 17e405a09caa..3b8b7ac253fd 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.h +++ b/drivers/net/wireless/wl12xx/wl1271_tx.h | |||
@@ -26,7 +26,7 @@ | |||
26 | #define __WL1271_TX_H__ | 26 | #define __WL1271_TX_H__ |
27 | 27 | ||
28 | #define TX_HW_BLOCK_SPARE 2 | 28 | #define TX_HW_BLOCK_SPARE 2 |
29 | #define TX_HW_BLOCK_SHIFT_DIV 8 | 29 | #define TX_HW_BLOCK_SIZE 252 |
30 | 30 | ||
31 | #define TX_HW_MGMT_PKT_LIFETIME_TU 2000 | 31 | #define TX_HW_MGMT_PKT_LIFETIME_TU 2000 |
32 | /* The chipset reference driver states, that the "aid" value 1 | 32 | /* The chipset reference driver states, that the "aid" value 1 |
@@ -125,9 +125,6 @@ struct wl1271_tx_hw_res_if { | |||
125 | 125 | ||
126 | static inline int wl1271_tx_get_queue(int queue) | 126 | static inline int wl1271_tx_get_queue(int queue) |
127 | { | 127 | { |
128 | /* FIXME: use best effort until WMM is enabled */ | ||
129 | return CONF_TX_AC_BE; | ||
130 | |||
131 | switch (queue) { | 128 | switch (queue) { |
132 | case 0: | 129 | case 0: |
133 | return CONF_TX_AC_VO; | 130 | return CONF_TX_AC_VO; |
@@ -160,7 +157,9 @@ static inline int wl1271_tx_ac_to_tid(int ac) | |||
160 | } | 157 | } |
161 | 158 | ||
162 | void wl1271_tx_work(struct work_struct *work); | 159 | void wl1271_tx_work(struct work_struct *work); |
163 | void wl1271_tx_complete(struct wl1271 *wl, u32 count); | 160 | void wl1271_tx_complete(struct wl1271 *wl); |
164 | void wl1271_tx_flush(struct wl1271 *wl); | 161 | void wl1271_tx_flush(struct wl1271 *wl); |
162 | u8 wl1271_rate_to_idx(struct wl1271 *wl, int rate); | ||
163 | u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set); | ||
165 | 164 | ||
166 | #endif | 165 | #endif |
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index 7b9621de239f..65dd502eab0d 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c | |||
@@ -1834,32 +1834,32 @@ out: | |||
1834 | } | 1834 | } |
1835 | 1835 | ||
1836 | static const iw_handler wl3501_handler[] = { | 1836 | static const iw_handler wl3501_handler[] = { |
1837 | [SIOCGIWNAME - SIOCIWFIRST] = wl3501_get_name, | 1837 | IW_HANDLER(SIOCGIWNAME, wl3501_get_name), |
1838 | [SIOCSIWFREQ - SIOCIWFIRST] = wl3501_set_freq, | 1838 | IW_HANDLER(SIOCSIWFREQ, wl3501_set_freq), |
1839 | [SIOCGIWFREQ - SIOCIWFIRST] = wl3501_get_freq, | 1839 | IW_HANDLER(SIOCGIWFREQ, wl3501_get_freq), |
1840 | [SIOCSIWMODE - SIOCIWFIRST] = wl3501_set_mode, | 1840 | IW_HANDLER(SIOCSIWMODE, wl3501_set_mode), |
1841 | [SIOCGIWMODE - SIOCIWFIRST] = wl3501_get_mode, | 1841 | IW_HANDLER(SIOCGIWMODE, wl3501_get_mode), |
1842 | [SIOCGIWSENS - SIOCIWFIRST] = wl3501_get_sens, | 1842 | IW_HANDLER(SIOCGIWSENS, wl3501_get_sens), |
1843 | [SIOCGIWRANGE - SIOCIWFIRST] = wl3501_get_range, | 1843 | IW_HANDLER(SIOCGIWRANGE, wl3501_get_range), |
1844 | [SIOCSIWSPY - SIOCIWFIRST] = iw_handler_set_spy, | 1844 | IW_HANDLER(SIOCSIWSPY, iw_handler_set_spy), |
1845 | [SIOCGIWSPY - SIOCIWFIRST] = iw_handler_get_spy, | 1845 | IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy), |
1846 | [SIOCSIWTHRSPY - SIOCIWFIRST] = iw_handler_set_thrspy, | 1846 | IW_HANDLER(SIOCSIWTHRSPY, iw_handler_set_thrspy), |
1847 | [SIOCGIWTHRSPY - SIOCIWFIRST] = iw_handler_get_thrspy, | 1847 | IW_HANDLER(SIOCGIWTHRSPY, iw_handler_get_thrspy), |
1848 | [SIOCSIWAP - SIOCIWFIRST] = wl3501_set_wap, | 1848 | IW_HANDLER(SIOCSIWAP, wl3501_set_wap), |
1849 | [SIOCGIWAP - SIOCIWFIRST] = wl3501_get_wap, | 1849 | IW_HANDLER(SIOCGIWAP, wl3501_get_wap), |
1850 | [SIOCSIWSCAN - SIOCIWFIRST] = wl3501_set_scan, | 1850 | IW_HANDLER(SIOCSIWSCAN, wl3501_set_scan), |
1851 | [SIOCGIWSCAN - SIOCIWFIRST] = wl3501_get_scan, | 1851 | IW_HANDLER(SIOCGIWSCAN, wl3501_get_scan), |
1852 | [SIOCSIWESSID - SIOCIWFIRST] = wl3501_set_essid, | 1852 | IW_HANDLER(SIOCSIWESSID, wl3501_set_essid), |
1853 | [SIOCGIWESSID - SIOCIWFIRST] = wl3501_get_essid, | 1853 | IW_HANDLER(SIOCGIWESSID, wl3501_get_essid), |
1854 | [SIOCSIWNICKN - SIOCIWFIRST] = wl3501_set_nick, | 1854 | IW_HANDLER(SIOCSIWNICKN, wl3501_set_nick), |
1855 | [SIOCGIWNICKN - SIOCIWFIRST] = wl3501_get_nick, | 1855 | IW_HANDLER(SIOCGIWNICKN, wl3501_get_nick), |
1856 | [SIOCGIWRATE - SIOCIWFIRST] = wl3501_get_rate, | 1856 | IW_HANDLER(SIOCGIWRATE, wl3501_get_rate), |
1857 | [SIOCGIWRTS - SIOCIWFIRST] = wl3501_get_rts_threshold, | 1857 | IW_HANDLER(SIOCGIWRTS, wl3501_get_rts_threshold), |
1858 | [SIOCGIWFRAG - SIOCIWFIRST] = wl3501_get_frag_threshold, | 1858 | IW_HANDLER(SIOCGIWFRAG, wl3501_get_frag_threshold), |
1859 | [SIOCGIWTXPOW - SIOCIWFIRST] = wl3501_get_txpow, | 1859 | IW_HANDLER(SIOCGIWTXPOW, wl3501_get_txpow), |
1860 | [SIOCGIWRETRY - SIOCIWFIRST] = wl3501_get_retry, | 1860 | IW_HANDLER(SIOCGIWRETRY, wl3501_get_retry), |
1861 | [SIOCGIWENCODE - SIOCIWFIRST] = wl3501_get_encode, | 1861 | IW_HANDLER(SIOCGIWENCODE, wl3501_get_encode), |
1862 | [SIOCGIWPOWER - SIOCIWFIRST] = wl3501_get_power, | 1862 | IW_HANDLER(SIOCGIWPOWER, wl3501_get_power), |
1863 | }; | 1863 | }; |
1864 | 1864 | ||
1865 | static const struct iw_handler_def wl3501_handler_def = { | 1865 | static const struct iw_handler_def wl3501_handler_def = { |
diff --git a/drivers/ssb/driver_chipcommon.c b/drivers/ssb/driver_chipcommon.c index 9681536163ca..59c3c0fdbecd 100644 --- a/drivers/ssb/driver_chipcommon.c +++ b/drivers/ssb/driver_chipcommon.c | |||
@@ -370,6 +370,7 @@ u32 ssb_chipco_gpio_control(struct ssb_chipcommon *cc, u32 mask, u32 value) | |||
370 | { | 370 | { |
371 | return chipco_write32_masked(cc, SSB_CHIPCO_GPIOCTL, mask, value); | 371 | return chipco_write32_masked(cc, SSB_CHIPCO_GPIOCTL, mask, value); |
372 | } | 372 | } |
373 | EXPORT_SYMBOL(ssb_chipco_gpio_control); | ||
373 | 374 | ||
374 | u32 ssb_chipco_gpio_intmask(struct ssb_chipcommon *cc, u32 mask, u32 value) | 375 | u32 ssb_chipco_gpio_intmask(struct ssb_chipcommon *cc, u32 mask, u32 value) |
375 | { | 376 | { |
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 19984958ab7b..e9e03b02cb08 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h | |||
@@ -1324,7 +1324,6 @@ enum ieee80211_back_actioncode { | |||
1324 | enum ieee80211_back_parties { | 1324 | enum ieee80211_back_parties { |
1325 | WLAN_BACK_RECIPIENT = 0, | 1325 | WLAN_BACK_RECIPIENT = 0, |
1326 | WLAN_BACK_INITIATOR = 1, | 1326 | WLAN_BACK_INITIATOR = 1, |
1327 | WLAN_BACK_TIMER = 2, | ||
1328 | }; | 1327 | }; |
1329 | 1328 | ||
1330 | /* SA Query action */ | 1329 | /* SA Query action */ |
diff --git a/include/linux/mmc/sdio.h b/include/linux/mmc/sdio.h index 47ba464f5170..118f0295a575 100644 --- a/include/linux/mmc/sdio.h +++ b/include/linux/mmc/sdio.h | |||
@@ -94,6 +94,8 @@ | |||
94 | 94 | ||
95 | #define SDIO_BUS_WIDTH_1BIT 0x00 | 95 | #define SDIO_BUS_WIDTH_1BIT 0x00 |
96 | #define SDIO_BUS_WIDTH_4BIT 0x02 | 96 | #define SDIO_BUS_WIDTH_4BIT 0x02 |
97 | #define SDIO_BUS_ECSI 0x20 /* Enable continuous SPI interrupt */ | ||
98 | #define SDIO_BUS_SCSI 0x40 /* Support continuous SPI interrupt */ | ||
97 | 99 | ||
98 | #define SDIO_BUS_CD_DISABLE 0x80 /* disable pull-up on DAT3 (pin 1) */ | 100 | #define SDIO_BUS_CD_DISABLE 0x80 /* disable pull-up on DAT3 (pin 1) */ |
99 | 101 | ||
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 28ba20fda3e2..2ea3edeee7aa 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h | |||
@@ -323,6 +323,12 @@ | |||
323 | * the TX command and %NL80211_ATTR_FRAME includes the contents of the | 323 | * the TX command and %NL80211_ATTR_FRAME includes the contents of the |
324 | * frame. %NL80211_ATTR_ACK flag is included if the recipient acknowledged | 324 | * frame. %NL80211_ATTR_ACK flag is included if the recipient acknowledged |
325 | * the frame. | 325 | * the frame. |
326 | * @NL80211_CMD_SET_CQM: Connection quality monitor configuration. This command | ||
327 | * is used to configure connection quality monitoring notification trigger | ||
328 | * levels. | ||
329 | * @NL80211_CMD_NOTIFY_CQM: Connection quality monitor notification. This | ||
330 | * command is used as an event to indicate the that a trigger level was | ||
331 | * reached. | ||
326 | * | 332 | * |
327 | * @NL80211_CMD_MAX: highest used command number | 333 | * @NL80211_CMD_MAX: highest used command number |
328 | * @__NL80211_CMD_AFTER_LAST: internal use | 334 | * @__NL80211_CMD_AFTER_LAST: internal use |
@@ -419,6 +425,9 @@ enum nl80211_commands { | |||
419 | NL80211_CMD_SET_POWER_SAVE, | 425 | NL80211_CMD_SET_POWER_SAVE, |
420 | NL80211_CMD_GET_POWER_SAVE, | 426 | NL80211_CMD_GET_POWER_SAVE, |
421 | 427 | ||
428 | NL80211_CMD_SET_CQM, | ||
429 | NL80211_CMD_NOTIFY_CQM, | ||
430 | |||
422 | /* add new commands above here */ | 431 | /* add new commands above here */ |
423 | 432 | ||
424 | /* used to define NL80211_CMD_MAX below */ | 433 | /* used to define NL80211_CMD_MAX below */ |
@@ -691,6 +700,15 @@ enum nl80211_commands { | |||
691 | * @NL80211_ATTR_ACK: Flag attribute indicating that the frame was | 700 | * @NL80211_ATTR_ACK: Flag attribute indicating that the frame was |
692 | * acknowledged by the recipient. | 701 | * acknowledged by the recipient. |
693 | * | 702 | * |
703 | * @NL80211_ATTR_CQM: connection quality monitor configuration in a | ||
704 | * nested attribute with %NL80211_ATTR_CQM_* sub-attributes. | ||
705 | * | ||
706 | * @NL80211_ATTR_LOCAL_STATE_CHANGE: Flag attribute to indicate that a command | ||
707 | * is requesting a local authentication/association state change without | ||
708 | * invoking actual management frame exchange. This can be used with | ||
709 | * NL80211_CMD_AUTHENTICATE, NL80211_CMD_DEAUTHENTICATE, | ||
710 | * NL80211_CMD_DISASSOCIATE. | ||
711 | * | ||
694 | * @NL80211_ATTR_MAX: highest attribute number currently defined | 712 | * @NL80211_ATTR_MAX: highest attribute number currently defined |
695 | * @__NL80211_ATTR_AFTER_LAST: internal use | 713 | * @__NL80211_ATTR_AFTER_LAST: internal use |
696 | */ | 714 | */ |
@@ -842,6 +860,10 @@ enum nl80211_attrs { | |||
842 | 860 | ||
843 | NL80211_ATTR_PS_STATE, | 861 | NL80211_ATTR_PS_STATE, |
844 | 862 | ||
863 | NL80211_ATTR_CQM, | ||
864 | |||
865 | NL80211_ATTR_LOCAL_STATE_CHANGE, | ||
866 | |||
845 | /* add attributes here, update the policy in nl80211.c */ | 867 | /* add attributes here, update the policy in nl80211.c */ |
846 | 868 | ||
847 | __NL80211_ATTR_AFTER_LAST, | 869 | __NL80211_ATTR_AFTER_LAST, |
@@ -1583,4 +1605,40 @@ enum nl80211_ps_state { | |||
1583 | NL80211_PS_ENABLED, | 1605 | NL80211_PS_ENABLED, |
1584 | }; | 1606 | }; |
1585 | 1607 | ||
1608 | /** | ||
1609 | * enum nl80211_attr_cqm - connection quality monitor attributes | ||
1610 | * @__NL80211_ATTR_CQM_INVALID: invalid | ||
1611 | * @NL80211_ATTR_CQM_RSSI_THOLD: RSSI threshold in dBm. This value specifies | ||
1612 | * the threshold for the RSSI level at which an event will be sent. Zero | ||
1613 | * to disable. | ||
1614 | * @NL80211_ATTR_CQM_RSSI_HYST: RSSI hysteresis in dBm. This value specifies | ||
1615 | * the minimum amount the RSSI level must change after an event before a | ||
1616 | * new event may be issued (to reduce effects of RSSI oscillation). | ||
1617 | * @NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT: RSSI threshold event | ||
1618 | * @__NL80211_ATTR_CQM_AFTER_LAST: internal | ||
1619 | * @NL80211_ATTR_CQM_MAX: highest key attribute | ||
1620 | */ | ||
1621 | enum nl80211_attr_cqm { | ||
1622 | __NL80211_ATTR_CQM_INVALID, | ||
1623 | NL80211_ATTR_CQM_RSSI_THOLD, | ||
1624 | NL80211_ATTR_CQM_RSSI_HYST, | ||
1625 | NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT, | ||
1626 | |||
1627 | /* keep last */ | ||
1628 | __NL80211_ATTR_CQM_AFTER_LAST, | ||
1629 | NL80211_ATTR_CQM_MAX = __NL80211_ATTR_CQM_AFTER_LAST - 1 | ||
1630 | }; | ||
1631 | |||
1632 | /** | ||
1633 | * enum nl80211_cqm_rssi_threshold_event - RSSI threshold event | ||
1634 | * @NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW - The RSSI level is lower than the | ||
1635 | * configured threshold | ||
1636 | * @NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH - The RSSI is higher than the | ||
1637 | * configured threshold | ||
1638 | */ | ||
1639 | enum nl80211_cqm_rssi_threshold_event { | ||
1640 | NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW, | ||
1641 | NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH, | ||
1642 | }; | ||
1643 | |||
1586 | #endif /* __LINUX_NL80211_H */ | 1644 | #endif /* __LINUX_NL80211_H */ |
diff --git a/include/linux/wireless.h b/include/linux/wireless.h index 5b4c6c772a9b..e6827eedf18b 100644 --- a/include/linux/wireless.h +++ b/include/linux/wireless.h | |||
@@ -346,6 +346,8 @@ | |||
346 | #define SIOCIWFIRST 0x8B00 | 346 | #define SIOCIWFIRST 0x8B00 |
347 | #define SIOCIWLAST SIOCIWLASTPRIV /* 0x8BFF */ | 347 | #define SIOCIWLAST SIOCIWLASTPRIV /* 0x8BFF */ |
348 | #define IW_IOCTL_IDX(cmd) ((cmd) - SIOCIWFIRST) | 348 | #define IW_IOCTL_IDX(cmd) ((cmd) - SIOCIWFIRST) |
349 | #define IW_HANDLER(id, func) \ | ||
350 | [IW_IOCTL_IDX(id)] = func | ||
349 | 351 | ||
350 | /* Odd : get (world access), even : set (root access) */ | 352 | /* Odd : get (world access), even : set (root access) */ |
351 | #define IW_IS_SET(cmd) (!((cmd) & 0x1)) | 353 | #define IW_IS_SET(cmd) (!((cmd) & 0x1)) |
@@ -648,7 +650,7 @@ | |||
648 | * 32 bit bitmasks. Note : 32 bits = 0x20 = 2^5. */ | 650 | * 32 bit bitmasks. Note : 32 bits = 0x20 = 2^5. */ |
649 | #define IW_EVENT_CAPA_BASE(cmd) ((cmd >= SIOCIWFIRSTPRIV) ? \ | 651 | #define IW_EVENT_CAPA_BASE(cmd) ((cmd >= SIOCIWFIRSTPRIV) ? \ |
650 | (cmd - SIOCIWFIRSTPRIV + 0x60) : \ | 652 | (cmd - SIOCIWFIRSTPRIV + 0x60) : \ |
651 | (cmd - SIOCSIWCOMMIT)) | 653 | (cmd - SIOCIWFIRST)) |
652 | #define IW_EVENT_CAPA_INDEX(cmd) (IW_EVENT_CAPA_BASE(cmd) >> 5) | 654 | #define IW_EVENT_CAPA_INDEX(cmd) (IW_EVENT_CAPA_BASE(cmd) >> 5) |
653 | #define IW_EVENT_CAPA_MASK(cmd) (1 << (IW_EVENT_CAPA_BASE(cmd) & 0x1F)) | 655 | #define IW_EVENT_CAPA_MASK(cmd) (1 << (IW_EVENT_CAPA_BASE(cmd) & 0x1F)) |
654 | /* Event capability constants - event autogenerated by the kernel | 656 | /* Event capability constants - event autogenerated by the kernel |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 3d134a1fb96b..37cebd3aa0f7 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -704,6 +704,10 @@ struct cfg80211_crypto_settings { | |||
704 | * @key_len: length of WEP key for shared key authentication | 704 | * @key_len: length of WEP key for shared key authentication |
705 | * @key_idx: index of WEP key for shared key authentication | 705 | * @key_idx: index of WEP key for shared key authentication |
706 | * @key: WEP key for shared key authentication | 706 | * @key: WEP key for shared key authentication |
707 | * @local_state_change: This is a request for a local state only, i.e., no | ||
708 | * Authentication frame is to be transmitted and authentication state is | ||
709 | * to be changed without having to wait for a response from the peer STA | ||
710 | * (AP). | ||
707 | */ | 711 | */ |
708 | struct cfg80211_auth_request { | 712 | struct cfg80211_auth_request { |
709 | struct cfg80211_bss *bss; | 713 | struct cfg80211_bss *bss; |
@@ -712,6 +716,7 @@ struct cfg80211_auth_request { | |||
712 | enum nl80211_auth_type auth_type; | 716 | enum nl80211_auth_type auth_type; |
713 | const u8 *key; | 717 | const u8 *key; |
714 | u8 key_len, key_idx; | 718 | u8 key_len, key_idx; |
719 | bool local_state_change; | ||
715 | }; | 720 | }; |
716 | 721 | ||
717 | /** | 722 | /** |
@@ -744,12 +749,15 @@ struct cfg80211_assoc_request { | |||
744 | * @ie: Extra IEs to add to Deauthentication frame or %NULL | 749 | * @ie: Extra IEs to add to Deauthentication frame or %NULL |
745 | * @ie_len: Length of ie buffer in octets | 750 | * @ie_len: Length of ie buffer in octets |
746 | * @reason_code: The reason code for the deauthentication | 751 | * @reason_code: The reason code for the deauthentication |
752 | * @local_state_change: This is a request for a local state only, i.e., no | ||
753 | * Deauthentication frame is to be transmitted. | ||
747 | */ | 754 | */ |
748 | struct cfg80211_deauth_request { | 755 | struct cfg80211_deauth_request { |
749 | struct cfg80211_bss *bss; | 756 | struct cfg80211_bss *bss; |
750 | const u8 *ie; | 757 | const u8 *ie; |
751 | size_t ie_len; | 758 | size_t ie_len; |
752 | u16 reason_code; | 759 | u16 reason_code; |
760 | bool local_state_change; | ||
753 | }; | 761 | }; |
754 | 762 | ||
755 | /** | 763 | /** |
@@ -762,12 +770,15 @@ struct cfg80211_deauth_request { | |||
762 | * @ie: Extra IEs to add to Disassociation frame or %NULL | 770 | * @ie: Extra IEs to add to Disassociation frame or %NULL |
763 | * @ie_len: Length of ie buffer in octets | 771 | * @ie_len: Length of ie buffer in octets |
764 | * @reason_code: The reason code for the disassociation | 772 | * @reason_code: The reason code for the disassociation |
773 | * @local_state_change: This is a request for a local state only, i.e., no | ||
774 | * Disassociation frame is to be transmitted. | ||
765 | */ | 775 | */ |
766 | struct cfg80211_disassoc_request { | 776 | struct cfg80211_disassoc_request { |
767 | struct cfg80211_bss *bss; | 777 | struct cfg80211_bss *bss; |
768 | const u8 *ie; | 778 | const u8 *ie; |
769 | size_t ie_len; | 779 | size_t ie_len; |
770 | u16 reason_code; | 780 | u16 reason_code; |
781 | bool local_state_change; | ||
771 | }; | 782 | }; |
772 | 783 | ||
773 | /** | 784 | /** |
@@ -1007,6 +1018,7 @@ struct cfg80211_pmksa { | |||
1007 | * RSN IE. It allows for faster roaming between WPA2 BSSIDs. | 1018 | * RSN IE. It allows for faster roaming between WPA2 BSSIDs. |
1008 | * @del_pmksa: Delete a cached PMKID. | 1019 | * @del_pmksa: Delete a cached PMKID. |
1009 | * @flush_pmksa: Flush all cached PMKIDs. | 1020 | * @flush_pmksa: Flush all cached PMKIDs. |
1021 | * @set_cqm_rssi_config: Configure connection quality monitor RSSI threshold. | ||
1010 | * | 1022 | * |
1011 | */ | 1023 | */ |
1012 | struct cfg80211_ops { | 1024 | struct cfg80211_ops { |
@@ -1152,6 +1164,10 @@ struct cfg80211_ops { | |||
1152 | 1164 | ||
1153 | int (*set_power_mgmt)(struct wiphy *wiphy, struct net_device *dev, | 1165 | int (*set_power_mgmt)(struct wiphy *wiphy, struct net_device *dev, |
1154 | bool enabled, int timeout); | 1166 | bool enabled, int timeout); |
1167 | |||
1168 | int (*set_cqm_rssi_config)(struct wiphy *wiphy, | ||
1169 | struct net_device *dev, | ||
1170 | s32 rssi_thold, u32 rssi_hyst); | ||
1155 | }; | 1171 | }; |
1156 | 1172 | ||
1157 | /* | 1173 | /* |
@@ -2337,4 +2353,18 @@ bool cfg80211_rx_action(struct net_device *dev, int freq, const u8 *buf, | |||
2337 | void cfg80211_action_tx_status(struct net_device *dev, u64 cookie, | 2353 | void cfg80211_action_tx_status(struct net_device *dev, u64 cookie, |
2338 | const u8 *buf, size_t len, bool ack, gfp_t gfp); | 2354 | const u8 *buf, size_t len, bool ack, gfp_t gfp); |
2339 | 2355 | ||
2356 | |||
2357 | /** | ||
2358 | * cfg80211_cqm_rssi_notify - connection quality monitoring rssi event | ||
2359 | * @dev: network device | ||
2360 | * @rssi_event: the triggered RSSI event | ||
2361 | * @gfp: context flags | ||
2362 | * | ||
2363 | * This function is called when a configured connection quality monitoring | ||
2364 | * rssi threshold reached event occurs. | ||
2365 | */ | ||
2366 | void cfg80211_cqm_rssi_notify(struct net_device *dev, | ||
2367 | enum nl80211_cqm_rssi_threshold_event rssi_event, | ||
2368 | gfp_t gfp); | ||
2369 | |||
2340 | #endif /* __NET_CFG80211_H */ | 2370 | #endif /* __NET_CFG80211_H */ |
diff --git a/include/net/iw_handler.h b/include/net/iw_handler.h index b2b98f3fa265..3afdb21cc31d 100644 --- a/include/net/iw_handler.h +++ b/include/net/iw_handler.h | |||
@@ -323,7 +323,7 @@ typedef int (*iw_handler)(struct net_device *dev, struct iw_request_info *info, | |||
323 | struct iw_handler_def { | 323 | struct iw_handler_def { |
324 | 324 | ||
325 | /* Array of handlers for standard ioctls | 325 | /* Array of handlers for standard ioctls |
326 | * We will call dev->wireless_handlers->standard[ioctl - SIOCSIWCOMMIT] | 326 | * We will call dev->wireless_handlers->standard[ioctl - SIOCIWFIRST] |
327 | */ | 327 | */ |
328 | const iw_handler * standard; | 328 | const iw_handler * standard; |
329 | /* Number of handlers defined (more precisely, index of the | 329 | /* Number of handlers defined (more precisely, index of the |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 45d7d44d7cbe..dcf3c5f23c96 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -144,6 +144,7 @@ struct ieee80211_low_level_stats { | |||
144 | * new beacon (beaconing modes) | 144 | * new beacon (beaconing modes) |
145 | * @BSS_CHANGED_BEACON_ENABLED: Beaconing should be | 145 | * @BSS_CHANGED_BEACON_ENABLED: Beaconing should be |
146 | * enabled/disabled (beaconing modes) | 146 | * enabled/disabled (beaconing modes) |
147 | * @BSS_CHANGED_CQM: Connection quality monitor config changed | ||
147 | */ | 148 | */ |
148 | enum ieee80211_bss_change { | 149 | enum ieee80211_bss_change { |
149 | BSS_CHANGED_ASSOC = 1<<0, | 150 | BSS_CHANGED_ASSOC = 1<<0, |
@@ -156,6 +157,7 @@ enum ieee80211_bss_change { | |||
156 | BSS_CHANGED_BSSID = 1<<7, | 157 | BSS_CHANGED_BSSID = 1<<7, |
157 | BSS_CHANGED_BEACON = 1<<8, | 158 | BSS_CHANGED_BEACON = 1<<8, |
158 | BSS_CHANGED_BEACON_ENABLED = 1<<9, | 159 | BSS_CHANGED_BEACON_ENABLED = 1<<9, |
160 | BSS_CHANGED_CQM = 1<<10, | ||
159 | }; | 161 | }; |
160 | 162 | ||
161 | /** | 163 | /** |
@@ -185,6 +187,9 @@ enum ieee80211_bss_change { | |||
185 | * @enable_beacon: whether beaconing should be enabled or not | 187 | * @enable_beacon: whether beaconing should be enabled or not |
186 | * @ht_operation_mode: HT operation mode (like in &struct ieee80211_ht_info). | 188 | * @ht_operation_mode: HT operation mode (like in &struct ieee80211_ht_info). |
187 | * This field is only valid when the channel type is one of the HT types. | 189 | * This field is only valid when the channel type is one of the HT types. |
190 | * @cqm_rssi_thold: Connection quality monitor RSSI threshold, a zero value | ||
191 | * implies disabled | ||
192 | * @cqm_rssi_hyst: Connection quality monitor RSSI hysteresis | ||
188 | */ | 193 | */ |
189 | struct ieee80211_bss_conf { | 194 | struct ieee80211_bss_conf { |
190 | const u8 *bssid; | 195 | const u8 *bssid; |
@@ -202,6 +207,8 @@ struct ieee80211_bss_conf { | |||
202 | u64 timestamp; | 207 | u64 timestamp; |
203 | u32 basic_rates; | 208 | u32 basic_rates; |
204 | u16 ht_operation_mode; | 209 | u16 ht_operation_mode; |
210 | s32 cqm_rssi_thold; | ||
211 | u32 cqm_rssi_hyst; | ||
205 | }; | 212 | }; |
206 | 213 | ||
207 | /** | 214 | /** |
@@ -543,7 +550,7 @@ enum mac80211_rx_flags { | |||
543 | * @signal: signal strength when receiving this frame, either in dBm, in dB or | 550 | * @signal: signal strength when receiving this frame, either in dBm, in dB or |
544 | * unspecified depending on the hardware capabilities flags | 551 | * unspecified depending on the hardware capabilities flags |
545 | * @IEEE80211_HW_SIGNAL_* | 552 | * @IEEE80211_HW_SIGNAL_* |
546 | * @noise: noise when receiving this frame, in dBm. | 553 | * @noise: noise when receiving this frame, in dBm (DEPRECATED). |
547 | * @antenna: antenna used | 554 | * @antenna: antenna used |
548 | * @rate_idx: index of data rate into band's supported rates or MCS index if | 555 | * @rate_idx: index of data rate into band's supported rates or MCS index if |
549 | * HT rates are use (RX_FLAG_HT) | 556 | * HT rates are use (RX_FLAG_HT) |
@@ -554,7 +561,7 @@ struct ieee80211_rx_status { | |||
554 | enum ieee80211_band band; | 561 | enum ieee80211_band band; |
555 | int freq; | 562 | int freq; |
556 | int signal; | 563 | int signal; |
557 | int noise; | 564 | int noise __deprecated; |
558 | int antenna; | 565 | int antenna; |
559 | int rate_idx; | 566 | int rate_idx; |
560 | int flag; | 567 | int flag; |
@@ -580,11 +587,15 @@ struct ieee80211_rx_status { | |||
580 | * may turn the device off as much as possible. Typically, this flag will | 587 | * may turn the device off as much as possible. Typically, this flag will |
581 | * be set when an interface is set UP but not associated or scanning, but | 588 | * be set when an interface is set UP but not associated or scanning, but |
582 | * it can also be unset in that case when monitor interfaces are active. | 589 | * it can also be unset in that case when monitor interfaces are active. |
590 | * @IEEE80211_CONF_QOS: Enable 802.11e QoS also know as WMM (Wireless | ||
591 | * Multimedia). On some drivers (iwlwifi is one of know) we have | ||
592 | * to enable/disable QoS explicitly. | ||
583 | */ | 593 | */ |
584 | enum ieee80211_conf_flags { | 594 | enum ieee80211_conf_flags { |
585 | IEEE80211_CONF_MONITOR = (1<<0), | 595 | IEEE80211_CONF_MONITOR = (1<<0), |
586 | IEEE80211_CONF_PS = (1<<1), | 596 | IEEE80211_CONF_PS = (1<<1), |
587 | IEEE80211_CONF_IDLE = (1<<2), | 597 | IEEE80211_CONF_IDLE = (1<<2), |
598 | IEEE80211_CONF_QOS = (1<<3), | ||
588 | }; | 599 | }; |
589 | 600 | ||
590 | 601 | ||
@@ -609,6 +620,7 @@ enum ieee80211_conf_changed { | |||
609 | IEEE80211_CONF_CHANGE_CHANNEL = BIT(6), | 620 | IEEE80211_CONF_CHANGE_CHANNEL = BIT(6), |
610 | IEEE80211_CONF_CHANGE_RETRY_LIMITS = BIT(7), | 621 | IEEE80211_CONF_CHANGE_RETRY_LIMITS = BIT(7), |
611 | IEEE80211_CONF_CHANGE_IDLE = BIT(8), | 622 | IEEE80211_CONF_CHANGE_IDLE = BIT(8), |
623 | IEEE80211_CONF_CHANGE_QOS = BIT(9), | ||
612 | }; | 624 | }; |
613 | 625 | ||
614 | /** | 626 | /** |
@@ -954,6 +966,17 @@ enum ieee80211_tkip_key_type { | |||
954 | * Hardware can provide ack status reports of Tx frames to | 966 | * Hardware can provide ack status reports of Tx frames to |
955 | * the stack. | 967 | * the stack. |
956 | * | 968 | * |
969 | * @IEEE80211_HW_CONNECTION_MONITOR: | ||
970 | * The hardware performs its own connection monitoring, including | ||
971 | * periodic keep-alives to the AP and probing the AP on beacon loss. | ||
972 | * When this flag is set, signaling beacon-loss will cause an immediate | ||
973 | * change to disassociated state. | ||
974 | * | ||
975 | * @IEEE80211_HW_SUPPORTS_CQM_RSSI: | ||
976 | * Hardware can do connection quality monitoring - i.e. it can monitor | ||
977 | * connection quality related parameters, such as the RSSI level and | ||
978 | * provide notifications if configured trigger levels are reached. | ||
979 | * | ||
957 | */ | 980 | */ |
958 | enum ieee80211_hw_flags { | 981 | enum ieee80211_hw_flags { |
959 | IEEE80211_HW_HAS_RATE_CONTROL = 1<<0, | 982 | IEEE80211_HW_HAS_RATE_CONTROL = 1<<0, |
@@ -975,6 +998,8 @@ enum ieee80211_hw_flags { | |||
975 | IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS = 1<<16, | 998 | IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS = 1<<16, |
976 | IEEE80211_HW_SUPPORTS_UAPSD = 1<<17, | 999 | IEEE80211_HW_SUPPORTS_UAPSD = 1<<17, |
977 | IEEE80211_HW_REPORTS_TX_ACK_STATUS = 1<<18, | 1000 | IEEE80211_HW_REPORTS_TX_ACK_STATUS = 1<<18, |
1001 | IEEE80211_HW_CONNECTION_MONITOR = 1<<19, | ||
1002 | IEEE80211_HW_SUPPORTS_CQM_RSSI = 1<<20, | ||
978 | }; | 1003 | }; |
979 | 1004 | ||
980 | /** | 1005 | /** |
@@ -1802,7 +1827,10 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw); | |||
1802 | * ieee80211_rx - receive frame | 1827 | * ieee80211_rx - receive frame |
1803 | * | 1828 | * |
1804 | * Use this function to hand received frames to mac80211. The receive | 1829 | * Use this function to hand received frames to mac80211. The receive |
1805 | * buffer in @skb must start with an IEEE 802.11 header. | 1830 | * buffer in @skb must start with an IEEE 802.11 header. In case of a |
1831 | * paged @skb is used, the driver is recommended to put the ieee80211 | ||
1832 | * header of the frame on the linear part of the @skb to avoid memory | ||
1833 | * allocation and/or memcpy by the stack. | ||
1806 | * | 1834 | * |
1807 | * This function may not be called in IRQ context. Calls to this function | 1835 | * This function may not be called in IRQ context. Calls to this function |
1808 | * for a single hardware must be synchronized against each other. Calls to | 1836 | * for a single hardware must be synchronized against each other. Calls to |
@@ -2364,12 +2392,42 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw, | |||
2364 | * | 2392 | * |
2365 | * @vif: &struct ieee80211_vif pointer from the add_interface callback. | 2393 | * @vif: &struct ieee80211_vif pointer from the add_interface callback. |
2366 | * | 2394 | * |
2367 | * When beacon filtering is enabled with IEEE80211_HW_BEACON_FILTERING and | 2395 | * When beacon filtering is enabled with %IEEE80211_HW_BEACON_FILTERING and |
2368 | * IEEE80211_CONF_PS is set, the driver needs to inform whenever the | 2396 | * %IEEE80211_CONF_PS is set, the driver needs to inform whenever the |
2369 | * hardware is not receiving beacons with this function. | 2397 | * hardware is not receiving beacons with this function. |
2370 | */ | 2398 | */ |
2371 | void ieee80211_beacon_loss(struct ieee80211_vif *vif); | 2399 | void ieee80211_beacon_loss(struct ieee80211_vif *vif); |
2372 | 2400 | ||
2401 | /** | ||
2402 | * ieee80211_connection_loss - inform hardware has lost connection to the AP | ||
2403 | * | ||
2404 | * @vif: &struct ieee80211_vif pointer from the add_interface callback. | ||
2405 | * | ||
2406 | * When beacon filtering is enabled with %IEEE80211_HW_BEACON_FILTERING, and | ||
2407 | * %IEEE80211_CONF_PS and %IEEE80211_HW_CONNECTION_MONITOR are set, the driver | ||
2408 | * needs to inform if the connection to the AP has been lost. | ||
2409 | * | ||
2410 | * This function will cause immediate change to disassociated state, | ||
2411 | * without connection recovery attempts. | ||
2412 | */ | ||
2413 | void ieee80211_connection_loss(struct ieee80211_vif *vif); | ||
2414 | |||
2415 | /** | ||
2416 | * ieee80211_cqm_rssi_notify - inform a configured connection quality monitoring | ||
2417 | * rssi threshold triggered | ||
2418 | * | ||
2419 | * @vif: &struct ieee80211_vif pointer from the add_interface callback. | ||
2420 | * @rssi_event: the RSSI trigger event type | ||
2421 | * @gfp: context flags | ||
2422 | * | ||
2423 | * When the %IEEE80211_HW_SUPPORTS_CQM_RSSI is set, and a connection quality | ||
2424 | * monitoring is configured with an rssi threshold, the driver will inform | ||
2425 | * whenever the rssi level reaches the threshold. | ||
2426 | */ | ||
2427 | void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif, | ||
2428 | enum nl80211_cqm_rssi_threshold_event rssi_event, | ||
2429 | gfp_t gfp); | ||
2430 | |||
2373 | /* Rate control API */ | 2431 | /* Rate control API */ |
2374 | 2432 | ||
2375 | /** | 2433 | /** |
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index a952b7f8c648..334c359da5e8 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig | |||
@@ -15,8 +15,12 @@ comment "CFG80211 needs to be enabled for MAC80211" | |||
15 | 15 | ||
16 | if MAC80211 != n | 16 | if MAC80211 != n |
17 | 17 | ||
18 | config MAC80211_HAS_RC | ||
19 | def_bool n | ||
20 | |||
18 | config MAC80211_RC_PID | 21 | config MAC80211_RC_PID |
19 | bool "PID controller based rate control algorithm" if EMBEDDED | 22 | bool "PID controller based rate control algorithm" if EMBEDDED |
23 | select MAC80211_HAS_RC | ||
20 | ---help--- | 24 | ---help--- |
21 | This option enables a TX rate control algorithm for | 25 | This option enables a TX rate control algorithm for |
22 | mac80211 that uses a PID controller to select the TX | 26 | mac80211 that uses a PID controller to select the TX |
@@ -24,12 +28,14 @@ config MAC80211_RC_PID | |||
24 | 28 | ||
25 | config MAC80211_RC_MINSTREL | 29 | config MAC80211_RC_MINSTREL |
26 | bool "Minstrel" if EMBEDDED | 30 | bool "Minstrel" if EMBEDDED |
31 | select MAC80211_HAS_RC | ||
27 | default y | 32 | default y |
28 | ---help--- | 33 | ---help--- |
29 | This option enables the 'minstrel' TX rate control algorithm | 34 | This option enables the 'minstrel' TX rate control algorithm |
30 | 35 | ||
31 | choice | 36 | choice |
32 | prompt "Default rate control algorithm" | 37 | prompt "Default rate control algorithm" |
38 | depends on MAC80211_HAS_RC | ||
33 | default MAC80211_RC_DEFAULT_MINSTREL | 39 | default MAC80211_RC_DEFAULT_MINSTREL |
34 | ---help--- | 40 | ---help--- |
35 | This option selects the default rate control algorithm | 41 | This option selects the default rate control algorithm |
@@ -62,6 +68,9 @@ config MAC80211_RC_DEFAULT | |||
62 | 68 | ||
63 | endif | 69 | endif |
64 | 70 | ||
71 | comment "Some wireless drivers require a rate control algorithm" | ||
72 | depends on MAC80211_HAS_RC=n | ||
73 | |||
65 | config MAC80211_MESH | 74 | config MAC80211_MESH |
66 | bool "Enable mac80211 mesh networking (pre-802.11s) support" | 75 | bool "Enable mac80211 mesh networking (pre-802.11s) support" |
67 | depends on MAC80211 && EXPERIMENTAL | 76 | depends on MAC80211 && EXPERIMENTAL |
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index a978e666ed6f..53233ab50f65 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c | |||
@@ -22,19 +22,20 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | |||
22 | u16 initiator, u16 reason) | 22 | u16 initiator, u16 reason) |
23 | { | 23 | { |
24 | struct ieee80211_local *local = sta->local; | 24 | struct ieee80211_local *local = sta->local; |
25 | struct tid_ampdu_rx *tid_rx; | ||
25 | int i; | 26 | int i; |
26 | 27 | ||
27 | /* check if TID is in operational state */ | ||
28 | spin_lock_bh(&sta->lock); | 28 | spin_lock_bh(&sta->lock); |
29 | if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL) { | 29 | |
30 | /* check if TID is in operational state */ | ||
31 | if (!sta->ampdu_mlme.tid_active_rx[tid]) { | ||
30 | spin_unlock_bh(&sta->lock); | 32 | spin_unlock_bh(&sta->lock); |
31 | return; | 33 | return; |
32 | } | 34 | } |
33 | 35 | ||
34 | sta->ampdu_mlme.tid_state_rx[tid] = | 36 | sta->ampdu_mlme.tid_active_rx[tid] = false; |
35 | HT_AGG_STATE_REQ_STOP_BA_MSK | | 37 | |
36 | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); | 38 | tid_rx = sta->ampdu_mlme.tid_rx[tid]; |
37 | spin_unlock_bh(&sta->lock); | ||
38 | 39 | ||
39 | #ifdef CONFIG_MAC80211_HT_DEBUG | 40 | #ifdef CONFIG_MAC80211_HT_DEBUG |
40 | printk(KERN_DEBUG "Rx BA session stop requested for %pM tid %u\n", | 41 | printk(KERN_DEBUG "Rx BA session stop requested for %pM tid %u\n", |
@@ -46,61 +47,35 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | |||
46 | printk(KERN_DEBUG "HW problem - can not stop rx " | 47 | printk(KERN_DEBUG "HW problem - can not stop rx " |
47 | "aggregation for tid %d\n", tid); | 48 | "aggregation for tid %d\n", tid); |
48 | 49 | ||
49 | /* shutdown timer has not expired */ | ||
50 | if (initiator != WLAN_BACK_TIMER) | ||
51 | del_timer_sync(&sta->ampdu_mlme.tid_rx[tid]->session_timer); | ||
52 | |||
53 | /* check if this is a self generated aggregation halt */ | 50 | /* check if this is a self generated aggregation halt */ |
54 | if (initiator == WLAN_BACK_RECIPIENT || initiator == WLAN_BACK_TIMER) | 51 | if (initiator == WLAN_BACK_RECIPIENT) |
55 | ieee80211_send_delba(sta->sdata, sta->sta.addr, | 52 | ieee80211_send_delba(sta->sdata, sta->sta.addr, |
56 | tid, 0, reason); | 53 | tid, 0, reason); |
57 | 54 | ||
58 | /* free the reordering buffer */ | 55 | /* free the reordering buffer */ |
59 | for (i = 0; i < sta->ampdu_mlme.tid_rx[tid]->buf_size; i++) { | 56 | for (i = 0; i < tid_rx->buf_size; i++) { |
60 | if (sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]) { | 57 | if (tid_rx->reorder_buf[i]) { |
61 | /* release the reordered frames */ | 58 | /* release the reordered frames */ |
62 | dev_kfree_skb(sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]); | 59 | dev_kfree_skb(tid_rx->reorder_buf[i]); |
63 | sta->ampdu_mlme.tid_rx[tid]->stored_mpdu_num--; | 60 | tid_rx->stored_mpdu_num--; |
64 | sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i] = NULL; | 61 | tid_rx->reorder_buf[i] = NULL; |
65 | } | 62 | } |
66 | } | 63 | } |
67 | 64 | ||
68 | spin_lock_bh(&sta->lock); | ||
69 | /* free resources */ | 65 | /* free resources */ |
70 | kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_buf); | 66 | kfree(tid_rx->reorder_buf); |
71 | kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_time); | 67 | kfree(tid_rx->reorder_time); |
68 | sta->ampdu_mlme.tid_rx[tid] = NULL; | ||
72 | 69 | ||
73 | if (!sta->ampdu_mlme.tid_rx[tid]->shutdown) { | ||
74 | kfree(sta->ampdu_mlme.tid_rx[tid]); | ||
75 | sta->ampdu_mlme.tid_rx[tid] = NULL; | ||
76 | } | ||
77 | |||
78 | sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_IDLE; | ||
79 | spin_unlock_bh(&sta->lock); | 70 | spin_unlock_bh(&sta->lock); |
80 | } | ||
81 | |||
82 | void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, | ||
83 | u16 initiator, u16 reason) | ||
84 | { | ||
85 | struct sta_info *sta; | ||
86 | |||
87 | rcu_read_lock(); | ||
88 | |||
89 | sta = sta_info_get(sdata, ra); | ||
90 | if (!sta) { | ||
91 | rcu_read_unlock(); | ||
92 | return; | ||
93 | } | ||
94 | |||
95 | __ieee80211_stop_rx_ba_session(sta, tid, initiator, reason); | ||
96 | 71 | ||
97 | rcu_read_unlock(); | 72 | del_timer_sync(&tid_rx->session_timer); |
73 | kfree(tid_rx); | ||
98 | } | 74 | } |
99 | 75 | ||
100 | /* | 76 | /* |
101 | * After accepting the AddBA Request we activated a timer, | 77 | * After accepting the AddBA Request we activated a timer, |
102 | * resetting it after each frame that arrives from the originator. | 78 | * resetting it after each frame that arrives from the originator. |
103 | * if this timer expires ieee80211_sta_stop_rx_ba_session will be executed. | ||
104 | */ | 79 | */ |
105 | static void sta_rx_agg_session_timer_expired(unsigned long data) | 80 | static void sta_rx_agg_session_timer_expired(unsigned long data) |
106 | { | 81 | { |
@@ -116,9 +91,8 @@ static void sta_rx_agg_session_timer_expired(unsigned long data) | |||
116 | #ifdef CONFIG_MAC80211_HT_DEBUG | 91 | #ifdef CONFIG_MAC80211_HT_DEBUG |
117 | printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); | 92 | printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); |
118 | #endif | 93 | #endif |
119 | ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->sta.addr, | 94 | __ieee80211_stop_rx_ba_session(sta, *ptid, WLAN_BACK_RECIPIENT, |
120 | (u16)*ptid, WLAN_BACK_TIMER, | 95 | WLAN_REASON_QSTA_TIMEOUT); |
121 | WLAN_REASON_QSTA_TIMEOUT); | ||
122 | } | 96 | } |
123 | 97 | ||
124 | static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, | 98 | static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, |
@@ -193,7 +167,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
193 | 167 | ||
194 | status = WLAN_STATUS_REQUEST_DECLINED; | 168 | status = WLAN_STATUS_REQUEST_DECLINED; |
195 | 169 | ||
196 | if (test_sta_flags(sta, WLAN_STA_SUSPEND)) { | 170 | if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) { |
197 | #ifdef CONFIG_MAC80211_HT_DEBUG | 171 | #ifdef CONFIG_MAC80211_HT_DEBUG |
198 | printk(KERN_DEBUG "Suspend in progress. " | 172 | printk(KERN_DEBUG "Suspend in progress. " |
199 | "Denying ADDBA request\n"); | 173 | "Denying ADDBA request\n"); |
@@ -231,7 +205,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
231 | /* examine state machine */ | 205 | /* examine state machine */ |
232 | spin_lock_bh(&sta->lock); | 206 | spin_lock_bh(&sta->lock); |
233 | 207 | ||
234 | if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_IDLE) { | 208 | if (sta->ampdu_mlme.tid_active_rx[tid]) { |
235 | #ifdef CONFIG_MAC80211_HT_DEBUG | 209 | #ifdef CONFIG_MAC80211_HT_DEBUG |
236 | if (net_ratelimit()) | 210 | if (net_ratelimit()) |
237 | printk(KERN_DEBUG "unexpected AddBA Req from " | 211 | printk(KERN_DEBUG "unexpected AddBA Req from " |
@@ -293,7 +267,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
293 | } | 267 | } |
294 | 268 | ||
295 | /* change state and send addba resp */ | 269 | /* change state and send addba resp */ |
296 | sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_OPERATIONAL; | 270 | sta->ampdu_mlme.tid_active_rx[tid] = true; |
297 | tid_agg_rx->dialog_token = dialog_token; | 271 | tid_agg_rx->dialog_token = dialog_token; |
298 | tid_agg_rx->ssn = start_seq_num; | 272 | tid_agg_rx->ssn = start_seq_num; |
299 | tid_agg_rx->head_seq_num = start_seq_num; | 273 | tid_agg_rx->head_seq_num = start_seq_num; |
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 5538e1b4a697..32d2148b5b98 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -245,7 +245,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid) | |||
245 | return -EINVAL; | 245 | return -EINVAL; |
246 | } | 246 | } |
247 | 247 | ||
248 | if (test_sta_flags(sta, WLAN_STA_SUSPEND)) { | 248 | if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) { |
249 | #ifdef CONFIG_MAC80211_HT_DEBUG | 249 | #ifdef CONFIG_MAC80211_HT_DEBUG |
250 | printk(KERN_DEBUG "Suspend in progress. " | 250 | printk(KERN_DEBUG "Suspend in progress. " |
251 | "Denying BA session request\n"); | 251 | "Denying BA session request\n"); |
@@ -414,7 +414,7 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local, | |||
414 | struct sta_info *sta, u16 tid) | 414 | struct sta_info *sta, u16 tid) |
415 | { | 415 | { |
416 | #ifdef CONFIG_MAC80211_HT_DEBUG | 416 | #ifdef CONFIG_MAC80211_HT_DEBUG |
417 | printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid); | 417 | printk(KERN_DEBUG "Aggregation is on for tid %d\n", tid); |
418 | #endif | 418 | #endif |
419 | 419 | ||
420 | spin_lock(&local->ampdu_lock); | 420 | spin_lock(&local->ampdu_lock); |
@@ -674,7 +674,7 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
674 | del_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); | 674 | del_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); |
675 | 675 | ||
676 | #ifdef CONFIG_MAC80211_HT_DEBUG | 676 | #ifdef CONFIG_MAC80211_HT_DEBUG |
677 | printk(KERN_DEBUG "switched off addBA timer for tid %d \n", tid); | 677 | printk(KERN_DEBUG "switched off addBA timer for tid %d\n", tid); |
678 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 678 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
679 | 679 | ||
680 | if (le16_to_cpu(mgmt->u.action.u.addba_resp.status) | 680 | if (le16_to_cpu(mgmt->u.action.u.addba_resp.status) |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index b7116ef84a3b..4edd73cbf052 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -1136,6 +1136,10 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy, | |||
1136 | return -EINVAL; | 1136 | return -EINVAL; |
1137 | } | 1137 | } |
1138 | 1138 | ||
1139 | /* enable WMM or activate new settings */ | ||
1140 | local->hw.conf.flags |= IEEE80211_CONF_QOS; | ||
1141 | drv_config(local, IEEE80211_CONF_CHANGE_QOS); | ||
1142 | |||
1139 | return 0; | 1143 | return 0; |
1140 | } | 1144 | } |
1141 | 1145 | ||
@@ -1402,6 +1406,35 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, | |||
1402 | return 0; | 1406 | return 0; |
1403 | } | 1407 | } |
1404 | 1408 | ||
1409 | static int ieee80211_set_cqm_rssi_config(struct wiphy *wiphy, | ||
1410 | struct net_device *dev, | ||
1411 | s32 rssi_thold, u32 rssi_hyst) | ||
1412 | { | ||
1413 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1414 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1415 | struct ieee80211_vif *vif = &sdata->vif; | ||
1416 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | ||
1417 | |||
1418 | if (rssi_thold == bss_conf->cqm_rssi_thold && | ||
1419 | rssi_hyst == bss_conf->cqm_rssi_hyst) | ||
1420 | return 0; | ||
1421 | |||
1422 | bss_conf->cqm_rssi_thold = rssi_thold; | ||
1423 | bss_conf->cqm_rssi_hyst = rssi_hyst; | ||
1424 | |||
1425 | if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI)) { | ||
1426 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | ||
1427 | return -EOPNOTSUPP; | ||
1428 | return 0; | ||
1429 | } | ||
1430 | |||
1431 | /* tell the driver upon association, unless already associated */ | ||
1432 | if (sdata->u.mgd.associated) | ||
1433 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_CQM); | ||
1434 | |||
1435 | return 0; | ||
1436 | } | ||
1437 | |||
1405 | static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, | 1438 | static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, |
1406 | struct net_device *dev, | 1439 | struct net_device *dev, |
1407 | const u8 *addr, | 1440 | const u8 *addr, |
@@ -1506,4 +1539,5 @@ struct cfg80211_ops mac80211_config_ops = { | |||
1506 | .remain_on_channel = ieee80211_remain_on_channel, | 1539 | .remain_on_channel = ieee80211_remain_on_channel, |
1507 | .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel, | 1540 | .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel, |
1508 | .action = ieee80211_action, | 1541 | .action = ieee80211_action, |
1542 | .set_cqm_rssi_config = ieee80211_set_cqm_rssi_config, | ||
1509 | }; | 1543 | }; |
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index b4ddb2f83914..623e6644b80c 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -99,6 +99,14 @@ static ssize_t ieee80211_if_fmt_##name( \ | |||
99 | return scnprintf(buf, buflen, "%pM\n", sdata->field); \ | 99 | return scnprintf(buf, buflen, "%pM\n", sdata->field); \ |
100 | } | 100 | } |
101 | 101 | ||
102 | #define IEEE80211_IF_FMT_DEC_DIV_16(name, field) \ | ||
103 | static ssize_t ieee80211_if_fmt_##name( \ | ||
104 | const struct ieee80211_sub_if_data *sdata, \ | ||
105 | char *buf, int buflen) \ | ||
106 | { \ | ||
107 | return scnprintf(buf, buflen, "%d\n", sdata->field / 16); \ | ||
108 | } | ||
109 | |||
102 | #define __IEEE80211_IF_FILE(name, _write) \ | 110 | #define __IEEE80211_IF_FILE(name, _write) \ |
103 | static ssize_t ieee80211_if_read_##name(struct file *file, \ | 111 | static ssize_t ieee80211_if_read_##name(struct file *file, \ |
104 | char __user *userbuf, \ | 112 | char __user *userbuf, \ |
@@ -139,6 +147,8 @@ IEEE80211_IF_FILE(rc_rateidx_mask_5ghz, rc_rateidx_mask[IEEE80211_BAND_5GHZ], | |||
139 | /* STA attributes */ | 147 | /* STA attributes */ |
140 | IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC); | 148 | IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC); |
141 | IEEE80211_IF_FILE(aid, u.mgd.aid, DEC); | 149 | IEEE80211_IF_FILE(aid, u.mgd.aid, DEC); |
150 | IEEE80211_IF_FILE(last_beacon, u.mgd.last_beacon_signal, DEC); | ||
151 | IEEE80211_IF_FILE(ave_beacon, u.mgd.ave_beacon_signal, DEC_DIV_16); | ||
142 | 152 | ||
143 | static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata, | 153 | static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata, |
144 | enum ieee80211_smps_mode smps_mode) | 154 | enum ieee80211_smps_mode smps_mode) |
@@ -275,6 +285,8 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata) | |||
275 | 285 | ||
276 | DEBUGFS_ADD(bssid); | 286 | DEBUGFS_ADD(bssid); |
277 | DEBUGFS_ADD(aid); | 287 | DEBUGFS_ADD(aid); |
288 | DEBUGFS_ADD(last_beacon); | ||
289 | DEBUGFS_ADD(ave_beacon); | ||
278 | DEBUGFS_ADD_MODE(smps, 0600); | 290 | DEBUGFS_ADD_MODE(smps, 0600); |
279 | } | 291 | } |
280 | 292 | ||
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index d92800bb2d2f..740ff6c5b92c 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -57,7 +57,6 @@ STA_FILE(tx_filtered, tx_filtered_count, LU); | |||
57 | STA_FILE(tx_retry_failed, tx_retry_failed, LU); | 57 | STA_FILE(tx_retry_failed, tx_retry_failed, LU); |
58 | STA_FILE(tx_retry_count, tx_retry_count, LU); | 58 | STA_FILE(tx_retry_count, tx_retry_count, LU); |
59 | STA_FILE(last_signal, last_signal, D); | 59 | STA_FILE(last_signal, last_signal, D); |
60 | STA_FILE(last_noise, last_noise, D); | ||
61 | STA_FILE(wep_weak_iv_count, wep_weak_iv_count, LU); | 60 | STA_FILE(wep_weak_iv_count, wep_weak_iv_count, LU); |
62 | 61 | ||
63 | static ssize_t sta_flags_read(struct file *file, char __user *userbuf, | 62 | static ssize_t sta_flags_read(struct file *file, char __user *userbuf, |
@@ -120,7 +119,7 @@ STA_OPS(last_seq_ctrl); | |||
120 | static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, | 119 | static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, |
121 | size_t count, loff_t *ppos) | 120 | size_t count, loff_t *ppos) |
122 | { | 121 | { |
123 | char buf[64 + STA_TID_NUM * 40], *p = buf; | 122 | char buf[71 + STA_TID_NUM * 40], *p = buf; |
124 | int i; | 123 | int i; |
125 | struct sta_info *sta = file->private_data; | 124 | struct sta_info *sta = file->private_data; |
126 | 125 | ||
@@ -128,16 +127,16 @@ static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, | |||
128 | p += scnprintf(p, sizeof(buf) + buf - p, "next dialog_token: %#02x\n", | 127 | p += scnprintf(p, sizeof(buf) + buf - p, "next dialog_token: %#02x\n", |
129 | sta->ampdu_mlme.dialog_token_allocator + 1); | 128 | sta->ampdu_mlme.dialog_token_allocator + 1); |
130 | p += scnprintf(p, sizeof(buf) + buf - p, | 129 | p += scnprintf(p, sizeof(buf) + buf - p, |
131 | "TID\t\tRX\tDTKN\tSSN\t\tTX\tDTKN\tSSN\tpending\n"); | 130 | "TID\t\tRX active\tDTKN\tSSN\t\tTX\tDTKN\tSSN\tpending\n"); |
132 | for (i = 0; i < STA_TID_NUM; i++) { | 131 | for (i = 0; i < STA_TID_NUM; i++) { |
133 | p += scnprintf(p, sizeof(buf) + buf - p, "%02d", i); | 132 | p += scnprintf(p, sizeof(buf) + buf - p, "%02d", i); |
134 | p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x", | 133 | p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x", |
135 | sta->ampdu_mlme.tid_state_rx[i]); | 134 | sta->ampdu_mlme.tid_active_rx[i]); |
136 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x", | 135 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x", |
137 | sta->ampdu_mlme.tid_state_rx[i] ? | 136 | sta->ampdu_mlme.tid_active_rx[i] ? |
138 | sta->ampdu_mlme.tid_rx[i]->dialog_token : 0); | 137 | sta->ampdu_mlme.tid_rx[i]->dialog_token : 0); |
139 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.3x", | 138 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.3x", |
140 | sta->ampdu_mlme.tid_state_rx[i] ? | 139 | sta->ampdu_mlme.tid_active_rx[i] ? |
141 | sta->ampdu_mlme.tid_rx[i]->ssn : 0); | 140 | sta->ampdu_mlme.tid_rx[i]->ssn : 0); |
142 | 141 | ||
143 | p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x", | 142 | p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x", |
@@ -289,7 +288,6 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta) | |||
289 | DEBUGFS_ADD(tx_retry_failed); | 288 | DEBUGFS_ADD(tx_retry_failed); |
290 | DEBUGFS_ADD(tx_retry_count); | 289 | DEBUGFS_ADD(tx_retry_count); |
291 | DEBUGFS_ADD(last_signal); | 290 | DEBUGFS_ADD(last_signal); |
292 | DEBUGFS_ADD(last_noise); | ||
293 | DEBUGFS_ADD(wep_weak_iv_count); | 291 | DEBUGFS_ADD(wep_weak_iv_count); |
294 | DEBUGFS_ADD(ht_capa); | 292 | DEBUGFS_ADD(ht_capa); |
295 | } | 293 | } |
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index bb677a73b7c9..2ab106a0a491 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -175,8 +175,7 @@ void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, | |||
175 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 175 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
176 | 176 | ||
177 | if (initiator == WLAN_BACK_INITIATOR) | 177 | if (initiator == WLAN_BACK_INITIATOR) |
178 | ieee80211_sta_stop_rx_ba_session(sdata, sta->sta.addr, tid, | 178 | __ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_INITIATOR, 0); |
179 | WLAN_BACK_INITIATOR, 0); | ||
180 | else { /* WLAN_BACK_RECIPIENT */ | 179 | else { /* WLAN_BACK_RECIPIENT */ |
181 | spin_lock_bh(&sta->lock); | 180 | spin_lock_bh(&sta->lock); |
182 | if (sta->ampdu_mlme.tid_state_tx[tid] & HT_ADDBA_REQUESTED_MSK) | 181 | if (sta->ampdu_mlme.tid_state_tx[tid] & HT_ADDBA_REQUESTED_MSK) |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index f3e942486749..01974c2510a8 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -264,17 +264,16 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
264 | sta->sta.supp_rates[band] = supp_rates | | 264 | sta->sta.supp_rates[band] = supp_rates | |
265 | ieee80211_mandatory_rates(local, band); | 265 | ieee80211_mandatory_rates(local, band); |
266 | 266 | ||
267 | if (sta->sta.supp_rates[band] != prev_rates) { | ||
267 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 268 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
268 | if (sta->sta.supp_rates[band] != prev_rates) | ||
269 | printk(KERN_DEBUG "%s: updated supp_rates set " | 269 | printk(KERN_DEBUG "%s: updated supp_rates set " |
270 | "for %pM based on beacon info (0x%llx | " | 270 | "for %pM based on beacon/probe_response " |
271 | "0x%llx -> 0x%llx)\n", | 271 | "(0x%x -> 0x%x)\n", |
272 | sdata->name, | 272 | sdata->name, sta->sta.addr, |
273 | sta->sta.addr, | 273 | prev_rates, sta->sta.supp_rates[band]); |
274 | (unsigned long long) prev_rates, | ||
275 | (unsigned long long) supp_rates, | ||
276 | (unsigned long long) sta->sta.supp_rates[band]); | ||
277 | #endif | 274 | #endif |
275 | rate_control_rate_init(sta); | ||
276 | } | ||
278 | rcu_read_unlock(); | 277 | rcu_read_unlock(); |
279 | } else { | 278 | } else { |
280 | rcu_read_unlock(); | 279 | rcu_read_unlock(); |
@@ -370,6 +369,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
370 | sdata->name, mgmt->bssid); | 369 | sdata->name, mgmt->bssid); |
371 | #endif | 370 | #endif |
372 | ieee80211_sta_join_ibss(sdata, bss); | 371 | ieee80211_sta_join_ibss(sdata, bss); |
372 | supp_rates = ieee80211_sta_get_rates(local, elems, band); | ||
373 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, | 373 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, |
374 | supp_rates, GFP_KERNEL); | 374 | supp_rates, GFP_KERNEL); |
375 | } | 375 | } |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 241533e1bc03..4e73660ebe99 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -317,6 +317,7 @@ enum ieee80211_sta_flags { | |||
317 | IEEE80211_STA_MFP_ENABLED = BIT(6), | 317 | IEEE80211_STA_MFP_ENABLED = BIT(6), |
318 | IEEE80211_STA_UAPSD_ENABLED = BIT(7), | 318 | IEEE80211_STA_UAPSD_ENABLED = BIT(7), |
319 | IEEE80211_STA_NULLFUNC_ACKED = BIT(8), | 319 | IEEE80211_STA_NULLFUNC_ACKED = BIT(8), |
320 | IEEE80211_STA_RESET_SIGNAL_AVE = BIT(9), | ||
320 | }; | 321 | }; |
321 | 322 | ||
322 | struct ieee80211_if_managed { | 323 | struct ieee80211_if_managed { |
@@ -327,7 +328,7 @@ struct ieee80211_if_managed { | |||
327 | struct work_struct work; | 328 | struct work_struct work; |
328 | struct work_struct monitor_work; | 329 | struct work_struct monitor_work; |
329 | struct work_struct chswitch_work; | 330 | struct work_struct chswitch_work; |
330 | struct work_struct beacon_loss_work; | 331 | struct work_struct beacon_connection_loss_work; |
331 | 332 | ||
332 | unsigned long probe_timeout; | 333 | unsigned long probe_timeout; |
333 | int probe_send_count; | 334 | int probe_send_count; |
@@ -359,6 +360,24 @@ struct ieee80211_if_managed { | |||
359 | int wmm_last_param_set; | 360 | int wmm_last_param_set; |
360 | 361 | ||
361 | u8 use_4addr; | 362 | u8 use_4addr; |
363 | |||
364 | /* Signal strength from the last Beacon frame in the current BSS. */ | ||
365 | int last_beacon_signal; | ||
366 | |||
367 | /* | ||
368 | * Weighted average of the signal strength from Beacon frames in the | ||
369 | * current BSS. This is in units of 1/16 of the signal unit to maintain | ||
370 | * accuracy and to speed up calculations, i.e., the value need to be | ||
371 | * divided by 16 to get the actual value. | ||
372 | */ | ||
373 | int ave_beacon_signal; | ||
374 | |||
375 | /* | ||
376 | * Last Beacon frame signal strength average (ave_beacon_signal / 16) | ||
377 | * that triggered a cqm event. 0 indicates that no event has been | ||
378 | * generated for the current association. | ||
379 | */ | ||
380 | int last_cqm_event_signal; | ||
362 | }; | 381 | }; |
363 | 382 | ||
364 | enum ieee80211_ibss_request { | 383 | enum ieee80211_ibss_request { |
@@ -745,6 +764,7 @@ struct ieee80211_local { | |||
745 | int scan_channel_idx; | 764 | int scan_channel_idx; |
746 | int scan_ies_len; | 765 | int scan_ies_len; |
747 | 766 | ||
767 | unsigned long leave_oper_channel_time; | ||
748 | enum mac80211_scan_state next_scan_state; | 768 | enum mac80211_scan_state next_scan_state; |
749 | struct delayed_work scan_work; | 769 | struct delayed_work scan_work; |
750 | struct ieee80211_sub_if_data *scan_sdata; | 770 | struct ieee80211_sub_if_data *scan_sdata; |
@@ -1078,8 +1098,6 @@ int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, | |||
1078 | enum ieee80211_smps_mode smps, const u8 *da, | 1098 | enum ieee80211_smps_mode smps, const u8 *da, |
1079 | const u8 *bssid); | 1099 | const u8 *bssid); |
1080 | 1100 | ||
1081 | void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *da, | ||
1082 | u16 tid, u16 initiator, u16 reason); | ||
1083 | void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | 1101 | void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, |
1084 | u16 initiator, u16 reason); | 1102 | u16 initiator, u16 reason); |
1085 | void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta); | 1103 | void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta); |
@@ -1155,7 +1173,7 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local, | |||
1155 | int powersave); | 1173 | int powersave); |
1156 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, | 1174 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, |
1157 | struct ieee80211_hdr *hdr); | 1175 | struct ieee80211_hdr *hdr); |
1158 | void ieee80211_beacon_loss_work(struct work_struct *work); | 1176 | void ieee80211_beacon_connection_loss_work(struct work_struct *work); |
1159 | 1177 | ||
1160 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, | 1178 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, |
1161 | enum queue_stop_reason reason); | 1179 | enum queue_stop_reason reason); |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 0793d7a8d743..b4ec59a8dc03 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -486,7 +486,7 @@ static int ieee80211_stop(struct net_device *dev) | |||
486 | cancel_work_sync(&sdata->u.mgd.work); | 486 | cancel_work_sync(&sdata->u.mgd.work); |
487 | cancel_work_sync(&sdata->u.mgd.chswitch_work); | 487 | cancel_work_sync(&sdata->u.mgd.chswitch_work); |
488 | cancel_work_sync(&sdata->u.mgd.monitor_work); | 488 | cancel_work_sync(&sdata->u.mgd.monitor_work); |
489 | cancel_work_sync(&sdata->u.mgd.beacon_loss_work); | 489 | cancel_work_sync(&sdata->u.mgd.beacon_connection_loss_work); |
490 | 490 | ||
491 | /* | 491 | /* |
492 | * When we get here, the interface is marked down. | 492 | * When we get here, the interface is marked down. |
@@ -815,6 +815,118 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, | |||
815 | return 0; | 815 | return 0; |
816 | } | 816 | } |
817 | 817 | ||
818 | static void ieee80211_assign_perm_addr(struct ieee80211_local *local, | ||
819 | struct net_device *dev, | ||
820 | enum nl80211_iftype type) | ||
821 | { | ||
822 | struct ieee80211_sub_if_data *sdata; | ||
823 | u64 mask, start, addr, val, inc; | ||
824 | u8 *m; | ||
825 | u8 tmp_addr[ETH_ALEN]; | ||
826 | int i; | ||
827 | |||
828 | /* default ... something at least */ | ||
829 | memcpy(dev->perm_addr, local->hw.wiphy->perm_addr, ETH_ALEN); | ||
830 | |||
831 | if (is_zero_ether_addr(local->hw.wiphy->addr_mask) && | ||
832 | local->hw.wiphy->n_addresses <= 1) | ||
833 | return; | ||
834 | |||
835 | |||
836 | mutex_lock(&local->iflist_mtx); | ||
837 | |||
838 | switch (type) { | ||
839 | case NL80211_IFTYPE_MONITOR: | ||
840 | /* doesn't matter */ | ||
841 | break; | ||
842 | case NL80211_IFTYPE_WDS: | ||
843 | case NL80211_IFTYPE_AP_VLAN: | ||
844 | /* match up with an AP interface */ | ||
845 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
846 | if (sdata->vif.type != NL80211_IFTYPE_AP) | ||
847 | continue; | ||
848 | memcpy(dev->perm_addr, sdata->vif.addr, ETH_ALEN); | ||
849 | break; | ||
850 | } | ||
851 | /* keep default if no AP interface present */ | ||
852 | break; | ||
853 | default: | ||
854 | /* assign a new address if possible -- try n_addresses first */ | ||
855 | for (i = 0; i < local->hw.wiphy->n_addresses; i++) { | ||
856 | bool used = false; | ||
857 | |||
858 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
859 | if (memcmp(local->hw.wiphy->addresses[i].addr, | ||
860 | sdata->vif.addr, ETH_ALEN) == 0) { | ||
861 | used = true; | ||
862 | break; | ||
863 | } | ||
864 | } | ||
865 | |||
866 | if (!used) { | ||
867 | memcpy(dev->perm_addr, | ||
868 | local->hw.wiphy->addresses[i].addr, | ||
869 | ETH_ALEN); | ||
870 | break; | ||
871 | } | ||
872 | } | ||
873 | |||
874 | /* try mask if available */ | ||
875 | if (is_zero_ether_addr(local->hw.wiphy->addr_mask)) | ||
876 | break; | ||
877 | |||
878 | m = local->hw.wiphy->addr_mask; | ||
879 | mask = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) | | ||
880 | ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) | | ||
881 | ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8); | ||
882 | |||
883 | if (__ffs64(mask) + hweight64(mask) != fls64(mask)) { | ||
884 | /* not a contiguous mask ... not handled now! */ | ||
885 | printk(KERN_DEBUG "not contiguous\n"); | ||
886 | break; | ||
887 | } | ||
888 | |||
889 | m = local->hw.wiphy->perm_addr; | ||
890 | start = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) | | ||
891 | ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) | | ||
892 | ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8); | ||
893 | |||
894 | inc = 1ULL<<__ffs64(mask); | ||
895 | val = (start & mask); | ||
896 | addr = (start & ~mask) | (val & mask); | ||
897 | do { | ||
898 | bool used = false; | ||
899 | |||
900 | tmp_addr[5] = addr >> 0*8; | ||
901 | tmp_addr[4] = addr >> 1*8; | ||
902 | tmp_addr[3] = addr >> 2*8; | ||
903 | tmp_addr[2] = addr >> 3*8; | ||
904 | tmp_addr[1] = addr >> 4*8; | ||
905 | tmp_addr[0] = addr >> 5*8; | ||
906 | |||
907 | val += inc; | ||
908 | |||
909 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
910 | if (memcmp(tmp_addr, sdata->vif.addr, | ||
911 | ETH_ALEN) == 0) { | ||
912 | used = true; | ||
913 | break; | ||
914 | } | ||
915 | } | ||
916 | |||
917 | if (!used) { | ||
918 | memcpy(dev->perm_addr, tmp_addr, ETH_ALEN); | ||
919 | break; | ||
920 | } | ||
921 | addr = (start & ~mask) | (val & mask); | ||
922 | } while (addr != start); | ||
923 | |||
924 | break; | ||
925 | } | ||
926 | |||
927 | mutex_unlock(&local->iflist_mtx); | ||
928 | } | ||
929 | |||
818 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, | 930 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, |
819 | struct net_device **new_dev, enum nl80211_iftype type, | 931 | struct net_device **new_dev, enum nl80211_iftype type, |
820 | struct vif_params *params) | 932 | struct vif_params *params) |
@@ -844,8 +956,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
844 | if (ret < 0) | 956 | if (ret < 0) |
845 | goto fail; | 957 | goto fail; |
846 | 958 | ||
847 | memcpy(ndev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN); | 959 | ieee80211_assign_perm_addr(local, ndev, type); |
848 | memcpy(ndev->perm_addr, ndev->dev_addr, ETH_ALEN); | 960 | memcpy(ndev->dev_addr, ndev->perm_addr, ETH_ALEN); |
849 | SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy)); | 961 | SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy)); |
850 | 962 | ||
851 | /* don't use IEEE80211_DEV_TO_SUB_IF because it checks too much */ | 963 | /* don't use IEEE80211_DEV_TO_SUB_IF because it checks too much */ |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index be5f723d643a..461167dfa42c 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -46,6 +46,13 @@ | |||
46 | */ | 46 | */ |
47 | #define IEEE80211_PROBE_WAIT (HZ / 2) | 47 | #define IEEE80211_PROBE_WAIT (HZ / 2) |
48 | 48 | ||
49 | /* | ||
50 | * Weight given to the latest Beacon frame when calculating average signal | ||
51 | * strength for Beacon frames received in the current BSS. This must be | ||
52 | * between 1 and 15. | ||
53 | */ | ||
54 | #define IEEE80211_SIGNAL_AVE_WEIGHT 3 | ||
55 | |||
49 | #define TMR_RUNNING_TIMER 0 | 56 | #define TMR_RUNNING_TIMER 0 |
50 | #define TMR_RUNNING_CHANSW 1 | 57 | #define TMR_RUNNING_CHANSW 1 |
51 | 58 | ||
@@ -203,7 +210,7 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
203 | 210 | ||
204 | static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | 211 | static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, |
205 | const u8 *bssid, u16 stype, u16 reason, | 212 | const u8 *bssid, u16 stype, u16 reason, |
206 | void *cookie) | 213 | void *cookie, bool send_frame) |
207 | { | 214 | { |
208 | struct ieee80211_local *local = sdata->local; | 215 | struct ieee80211_local *local = sdata->local; |
209 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 216 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
@@ -240,7 +247,11 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | |||
240 | cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len); | 247 | cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len); |
241 | if (!(ifmgd->flags & IEEE80211_STA_MFP_ENABLED)) | 248 | if (!(ifmgd->flags & IEEE80211_STA_MFP_ENABLED)) |
242 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 249 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
243 | ieee80211_tx_skb(sdata, skb); | 250 | |
251 | if (send_frame) | ||
252 | ieee80211_tx_skb(sdata, skb); | ||
253 | else | ||
254 | kfree_skb(skb); | ||
244 | } | 255 | } |
245 | 256 | ||
246 | void ieee80211_send_pspoll(struct ieee80211_local *local, | 257 | void ieee80211_send_pspoll(struct ieee80211_local *local, |
@@ -589,6 +600,9 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, | |||
589 | int count; | 600 | int count; |
590 | u8 *pos, uapsd_queues = 0; | 601 | u8 *pos, uapsd_queues = 0; |
591 | 602 | ||
603 | if (!local->ops->conf_tx) | ||
604 | return; | ||
605 | |||
592 | if (local->hw.queues < 4) | 606 | if (local->hw.queues < 4) |
593 | return; | 607 | return; |
594 | 608 | ||
@@ -663,11 +677,15 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, | |||
663 | params.aifs, params.cw_min, params.cw_max, params.txop, | 677 | params.aifs, params.cw_min, params.cw_max, params.txop, |
664 | params.uapsd); | 678 | params.uapsd); |
665 | #endif | 679 | #endif |
666 | if (drv_conf_tx(local, queue, ¶ms) && local->ops->conf_tx) | 680 | if (drv_conf_tx(local, queue, ¶ms)) |
667 | printk(KERN_DEBUG "%s: failed to set TX queue " | 681 | printk(KERN_DEBUG "%s: failed to set TX queue " |
668 | "parameters for queue %d\n", | 682 | "parameters for queue %d\n", |
669 | wiphy_name(local->hw.wiphy), queue); | 683 | wiphy_name(local->hw.wiphy), queue); |
670 | } | 684 | } |
685 | |||
686 | /* enable WMM or activate new settings */ | ||
687 | local->hw.conf.flags |= IEEE80211_CONF_QOS; | ||
688 | drv_config(local, IEEE80211_CONF_CHANGE_QOS); | ||
671 | } | 689 | } |
672 | 690 | ||
673 | static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, | 691 | static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, |
@@ -728,6 +746,8 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
728 | sdata->u.mgd.associated = cbss; | 746 | sdata->u.mgd.associated = cbss; |
729 | memcpy(sdata->u.mgd.bssid, cbss->bssid, ETH_ALEN); | 747 | memcpy(sdata->u.mgd.bssid, cbss->bssid, ETH_ALEN); |
730 | 748 | ||
749 | sdata->u.mgd.flags |= IEEE80211_STA_RESET_SIGNAL_AVE; | ||
750 | |||
731 | /* just to be sure */ | 751 | /* just to be sure */ |
732 | sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL | | 752 | sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL | |
733 | IEEE80211_STA_BEACON_POLL); | 753 | IEEE80211_STA_BEACON_POLL); |
@@ -753,6 +773,11 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
753 | /* And the BSSID changed - we're associated now */ | 773 | /* And the BSSID changed - we're associated now */ |
754 | bss_info_changed |= BSS_CHANGED_BSSID; | 774 | bss_info_changed |= BSS_CHANGED_BSSID; |
755 | 775 | ||
776 | /* Tell the driver to monitor connection quality (if supported) */ | ||
777 | if ((local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI) && | ||
778 | sdata->vif.bss_conf.cqm_rssi_thold) | ||
779 | bss_info_changed |= BSS_CHANGED_CQM; | ||
780 | |||
756 | ieee80211_bss_info_change_notify(sdata, bss_info_changed); | 781 | ieee80211_bss_info_change_notify(sdata, bss_info_changed); |
757 | 782 | ||
758 | mutex_lock(&local->iflist_mtx); | 783 | mutex_lock(&local->iflist_mtx); |
@@ -764,7 +789,8 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
764 | netif_carrier_on(sdata->dev); | 789 | netif_carrier_on(sdata->dev); |
765 | } | 790 | } |
766 | 791 | ||
767 | static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata) | 792 | static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, |
793 | bool remove_sta) | ||
768 | { | 794 | { |
769 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 795 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
770 | struct ieee80211_local *local = sdata->local; | 796 | struct ieee80211_local *local = sdata->local; |
@@ -837,7 +863,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata) | |||
837 | changed |= BSS_CHANGED_BSSID; | 863 | changed |= BSS_CHANGED_BSSID; |
838 | ieee80211_bss_info_change_notify(sdata, changed); | 864 | ieee80211_bss_info_change_notify(sdata, changed); |
839 | 865 | ||
840 | sta_info_destroy_addr(sdata, bssid); | 866 | if (remove_sta) |
867 | sta_info_destroy_addr(sdata, bssid); | ||
841 | } | 868 | } |
842 | 869 | ||
843 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, | 870 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, |
@@ -854,6 +881,9 @@ void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, | |||
854 | if (is_multicast_ether_addr(hdr->addr1)) | 881 | if (is_multicast_ether_addr(hdr->addr1)) |
855 | return; | 882 | return; |
856 | 883 | ||
884 | if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) | ||
885 | return; | ||
886 | |||
857 | mod_timer(&sdata->u.mgd.conn_mon_timer, | 887 | mod_timer(&sdata->u.mgd.conn_mon_timer, |
858 | round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME)); | 888 | round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME)); |
859 | } | 889 | } |
@@ -931,23 +961,68 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, | |||
931 | mutex_unlock(&ifmgd->mtx); | 961 | mutex_unlock(&ifmgd->mtx); |
932 | } | 962 | } |
933 | 963 | ||
934 | void ieee80211_beacon_loss_work(struct work_struct *work) | 964 | static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata) |
965 | { | ||
966 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
967 | struct ieee80211_local *local = sdata->local; | ||
968 | u8 bssid[ETH_ALEN]; | ||
969 | |||
970 | mutex_lock(&ifmgd->mtx); | ||
971 | if (!ifmgd->associated) { | ||
972 | mutex_unlock(&ifmgd->mtx); | ||
973 | return; | ||
974 | } | ||
975 | |||
976 | memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); | ||
977 | |||
978 | printk(KERN_DEBUG "Connection to AP %pM lost.\n", bssid); | ||
979 | |||
980 | ieee80211_set_disassoc(sdata, true); | ||
981 | ieee80211_recalc_idle(local); | ||
982 | mutex_unlock(&ifmgd->mtx); | ||
983 | /* | ||
984 | * must be outside lock due to cfg80211, | ||
985 | * but that's not a problem. | ||
986 | */ | ||
987 | ieee80211_send_deauth_disassoc(sdata, bssid, | ||
988 | IEEE80211_STYPE_DEAUTH, | ||
989 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, | ||
990 | NULL, true); | ||
991 | } | ||
992 | |||
993 | void ieee80211_beacon_connection_loss_work(struct work_struct *work) | ||
935 | { | 994 | { |
936 | struct ieee80211_sub_if_data *sdata = | 995 | struct ieee80211_sub_if_data *sdata = |
937 | container_of(work, struct ieee80211_sub_if_data, | 996 | container_of(work, struct ieee80211_sub_if_data, |
938 | u.mgd.beacon_loss_work); | 997 | u.mgd.beacon_connection_loss_work); |
939 | 998 | ||
940 | ieee80211_mgd_probe_ap(sdata, true); | 999 | if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) |
1000 | __ieee80211_connection_loss(sdata); | ||
1001 | else | ||
1002 | ieee80211_mgd_probe_ap(sdata, true); | ||
941 | } | 1003 | } |
942 | 1004 | ||
943 | void ieee80211_beacon_loss(struct ieee80211_vif *vif) | 1005 | void ieee80211_beacon_loss(struct ieee80211_vif *vif) |
944 | { | 1006 | { |
945 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | 1007 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); |
1008 | struct ieee80211_hw *hw = &sdata->local->hw; | ||
946 | 1009 | ||
947 | ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.beacon_loss_work); | 1010 | WARN_ON(hw->flags & IEEE80211_HW_CONNECTION_MONITOR); |
1011 | ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work); | ||
948 | } | 1012 | } |
949 | EXPORT_SYMBOL(ieee80211_beacon_loss); | 1013 | EXPORT_SYMBOL(ieee80211_beacon_loss); |
950 | 1014 | ||
1015 | void ieee80211_connection_loss(struct ieee80211_vif *vif) | ||
1016 | { | ||
1017 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
1018 | struct ieee80211_hw *hw = &sdata->local->hw; | ||
1019 | |||
1020 | WARN_ON(!(hw->flags & IEEE80211_HW_CONNECTION_MONITOR)); | ||
1021 | ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work); | ||
1022 | } | ||
1023 | EXPORT_SYMBOL(ieee80211_connection_loss); | ||
1024 | |||
1025 | |||
951 | static enum rx_mgmt_action __must_check | 1026 | static enum rx_mgmt_action __must_check |
952 | ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, | 1027 | ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, |
953 | struct ieee80211_mgmt *mgmt, size_t len) | 1028 | struct ieee80211_mgmt *mgmt, size_t len) |
@@ -968,7 +1043,7 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, | |||
968 | printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n", | 1043 | printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n", |
969 | sdata->name, bssid, reason_code); | 1044 | sdata->name, bssid, reason_code); |
970 | 1045 | ||
971 | ieee80211_set_disassoc(sdata); | 1046 | ieee80211_set_disassoc(sdata, true); |
972 | ieee80211_recalc_idle(sdata->local); | 1047 | ieee80211_recalc_idle(sdata->local); |
973 | 1048 | ||
974 | return RX_MGMT_CFG80211_DEAUTH; | 1049 | return RX_MGMT_CFG80211_DEAUTH; |
@@ -998,7 +1073,7 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, | |||
998 | printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n", | 1073 | printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n", |
999 | sdata->name, mgmt->sa, reason_code); | 1074 | sdata->name, mgmt->sa, reason_code); |
1000 | 1075 | ||
1001 | ieee80211_set_disassoc(sdata); | 1076 | ieee80211_set_disassoc(sdata, true); |
1002 | ieee80211_recalc_idle(sdata->local); | 1077 | ieee80211_recalc_idle(sdata->local); |
1003 | return RX_MGMT_CFG80211_DISASSOC; | 1078 | return RX_MGMT_CFG80211_DISASSOC; |
1004 | } | 1079 | } |
@@ -1290,6 +1365,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1290 | struct ieee80211_rx_status *rx_status) | 1365 | struct ieee80211_rx_status *rx_status) |
1291 | { | 1366 | { |
1292 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1367 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1368 | struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; | ||
1293 | size_t baselen; | 1369 | size_t baselen; |
1294 | struct ieee802_11_elems elems; | 1370 | struct ieee802_11_elems elems; |
1295 | struct ieee80211_local *local = sdata->local; | 1371 | struct ieee80211_local *local = sdata->local; |
@@ -1325,6 +1401,41 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1325 | if (memcmp(bssid, mgmt->bssid, ETH_ALEN) != 0) | 1401 | if (memcmp(bssid, mgmt->bssid, ETH_ALEN) != 0) |
1326 | return; | 1402 | return; |
1327 | 1403 | ||
1404 | /* Track average RSSI from the Beacon frames of the current AP */ | ||
1405 | ifmgd->last_beacon_signal = rx_status->signal; | ||
1406 | if (ifmgd->flags & IEEE80211_STA_RESET_SIGNAL_AVE) { | ||
1407 | ifmgd->flags &= ~IEEE80211_STA_RESET_SIGNAL_AVE; | ||
1408 | ifmgd->ave_beacon_signal = rx_status->signal; | ||
1409 | ifmgd->last_cqm_event_signal = 0; | ||
1410 | } else { | ||
1411 | ifmgd->ave_beacon_signal = | ||
1412 | (IEEE80211_SIGNAL_AVE_WEIGHT * rx_status->signal * 16 + | ||
1413 | (16 - IEEE80211_SIGNAL_AVE_WEIGHT) * | ||
1414 | ifmgd->ave_beacon_signal) / 16; | ||
1415 | } | ||
1416 | if (bss_conf->cqm_rssi_thold && | ||
1417 | !(local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI)) { | ||
1418 | int sig = ifmgd->ave_beacon_signal / 16; | ||
1419 | int last_event = ifmgd->last_cqm_event_signal; | ||
1420 | int thold = bss_conf->cqm_rssi_thold; | ||
1421 | int hyst = bss_conf->cqm_rssi_hyst; | ||
1422 | if (sig < thold && | ||
1423 | (last_event == 0 || sig < last_event - hyst)) { | ||
1424 | ifmgd->last_cqm_event_signal = sig; | ||
1425 | ieee80211_cqm_rssi_notify( | ||
1426 | &sdata->vif, | ||
1427 | NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW, | ||
1428 | GFP_KERNEL); | ||
1429 | } else if (sig > thold && | ||
1430 | (last_event == 0 || sig > last_event + hyst)) { | ||
1431 | ifmgd->last_cqm_event_signal = sig; | ||
1432 | ieee80211_cqm_rssi_notify( | ||
1433 | &sdata->vif, | ||
1434 | NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH, | ||
1435 | GFP_KERNEL); | ||
1436 | } | ||
1437 | } | ||
1438 | |||
1328 | if (ifmgd->flags & IEEE80211_STA_BEACON_POLL) { | 1439 | if (ifmgd->flags & IEEE80211_STA_BEACON_POLL) { |
1329 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 1440 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
1330 | if (net_ratelimit()) { | 1441 | if (net_ratelimit()) { |
@@ -1610,7 +1721,7 @@ static void ieee80211_sta_work(struct work_struct *work) | |||
1610 | printk(KERN_DEBUG "No probe response from AP %pM" | 1721 | printk(KERN_DEBUG "No probe response from AP %pM" |
1611 | " after %dms, disconnecting.\n", | 1722 | " after %dms, disconnecting.\n", |
1612 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); | 1723 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); |
1613 | ieee80211_set_disassoc(sdata); | 1724 | ieee80211_set_disassoc(sdata, true); |
1614 | ieee80211_recalc_idle(local); | 1725 | ieee80211_recalc_idle(local); |
1615 | mutex_unlock(&ifmgd->mtx); | 1726 | mutex_unlock(&ifmgd->mtx); |
1616 | /* | 1727 | /* |
@@ -1620,7 +1731,7 @@ static void ieee80211_sta_work(struct work_struct *work) | |||
1620 | ieee80211_send_deauth_disassoc(sdata, bssid, | 1731 | ieee80211_send_deauth_disassoc(sdata, bssid, |
1621 | IEEE80211_STYPE_DEAUTH, | 1732 | IEEE80211_STYPE_DEAUTH, |
1622 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, | 1733 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, |
1623 | NULL); | 1734 | NULL, true); |
1624 | mutex_lock(&ifmgd->mtx); | 1735 | mutex_lock(&ifmgd->mtx); |
1625 | } | 1736 | } |
1626 | } | 1737 | } |
@@ -1637,7 +1748,8 @@ static void ieee80211_sta_bcn_mon_timer(unsigned long data) | |||
1637 | if (local->quiescing) | 1748 | if (local->quiescing) |
1638 | return; | 1749 | return; |
1639 | 1750 | ||
1640 | ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.beacon_loss_work); | 1751 | ieee80211_queue_work(&sdata->local->hw, |
1752 | &sdata->u.mgd.beacon_connection_loss_work); | ||
1641 | } | 1753 | } |
1642 | 1754 | ||
1643 | static void ieee80211_sta_conn_mon_timer(unsigned long data) | 1755 | static void ieee80211_sta_conn_mon_timer(unsigned long data) |
@@ -1689,7 +1801,7 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata) | |||
1689 | */ | 1801 | */ |
1690 | 1802 | ||
1691 | cancel_work_sync(&ifmgd->work); | 1803 | cancel_work_sync(&ifmgd->work); |
1692 | cancel_work_sync(&ifmgd->beacon_loss_work); | 1804 | cancel_work_sync(&ifmgd->beacon_connection_loss_work); |
1693 | if (del_timer_sync(&ifmgd->timer)) | 1805 | if (del_timer_sync(&ifmgd->timer)) |
1694 | set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); | 1806 | set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); |
1695 | 1807 | ||
@@ -1723,7 +1835,8 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) | |||
1723 | INIT_WORK(&ifmgd->work, ieee80211_sta_work); | 1835 | INIT_WORK(&ifmgd->work, ieee80211_sta_work); |
1724 | INIT_WORK(&ifmgd->monitor_work, ieee80211_sta_monitor_work); | 1836 | INIT_WORK(&ifmgd->monitor_work, ieee80211_sta_monitor_work); |
1725 | INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work); | 1837 | INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work); |
1726 | INIT_WORK(&ifmgd->beacon_loss_work, ieee80211_beacon_loss_work); | 1838 | INIT_WORK(&ifmgd->beacon_connection_loss_work, |
1839 | ieee80211_beacon_connection_loss_work); | ||
1727 | setup_timer(&ifmgd->timer, ieee80211_sta_timer, | 1840 | setup_timer(&ifmgd->timer, ieee80211_sta_timer, |
1728 | (unsigned long) sdata); | 1841 | (unsigned long) sdata); |
1729 | setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer, | 1842 | setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer, |
@@ -1802,6 +1915,9 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, | |||
1802 | struct ieee80211_work *wk; | 1915 | struct ieee80211_work *wk; |
1803 | u16 auth_alg; | 1916 | u16 auth_alg; |
1804 | 1917 | ||
1918 | if (req->local_state_change) | ||
1919 | return 0; /* no need to update mac80211 state */ | ||
1920 | |||
1805 | switch (req->auth_type) { | 1921 | switch (req->auth_type) { |
1806 | case NL80211_AUTHTYPE_OPEN_SYSTEM: | 1922 | case NL80211_AUTHTYPE_OPEN_SYSTEM: |
1807 | auth_alg = WLAN_AUTH_OPEN; | 1923 | auth_alg = WLAN_AUTH_OPEN; |
@@ -1910,7 +2026,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
1910 | } | 2026 | } |
1911 | 2027 | ||
1912 | /* Trying to reassociate - clear previous association state */ | 2028 | /* Trying to reassociate - clear previous association state */ |
1913 | ieee80211_set_disassoc(sdata); | 2029 | ieee80211_set_disassoc(sdata, true); |
1914 | } | 2030 | } |
1915 | mutex_unlock(&ifmgd->mtx); | 2031 | mutex_unlock(&ifmgd->mtx); |
1916 | 2032 | ||
@@ -2014,7 +2130,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
2014 | 2130 | ||
2015 | if (ifmgd->associated == req->bss) { | 2131 | if (ifmgd->associated == req->bss) { |
2016 | bssid = req->bss->bssid; | 2132 | bssid = req->bss->bssid; |
2017 | ieee80211_set_disassoc(sdata); | 2133 | ieee80211_set_disassoc(sdata, true); |
2018 | mutex_unlock(&ifmgd->mtx); | 2134 | mutex_unlock(&ifmgd->mtx); |
2019 | } else { | 2135 | } else { |
2020 | bool not_auth_yet = false; | 2136 | bool not_auth_yet = false; |
@@ -2057,9 +2173,9 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
2057 | printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n", | 2173 | printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n", |
2058 | sdata->name, bssid, req->reason_code); | 2174 | sdata->name, bssid, req->reason_code); |
2059 | 2175 | ||
2060 | ieee80211_send_deauth_disassoc(sdata, bssid, | 2176 | ieee80211_send_deauth_disassoc(sdata, bssid, IEEE80211_STYPE_DEAUTH, |
2061 | IEEE80211_STYPE_DEAUTH, req->reason_code, | 2177 | req->reason_code, cookie, |
2062 | cookie); | 2178 | !req->local_state_change); |
2063 | 2179 | ||
2064 | ieee80211_recalc_idle(sdata->local); | 2180 | ieee80211_recalc_idle(sdata->local); |
2065 | 2181 | ||
@@ -2071,6 +2187,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | |||
2071 | void *cookie) | 2187 | void *cookie) |
2072 | { | 2188 | { |
2073 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 2189 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
2190 | u8 bssid[ETH_ALEN]; | ||
2074 | 2191 | ||
2075 | mutex_lock(&ifmgd->mtx); | 2192 | mutex_lock(&ifmgd->mtx); |
2076 | 2193 | ||
@@ -2088,13 +2205,15 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | |||
2088 | printk(KERN_DEBUG "%s: disassociating from %pM by local choice (reason=%d)\n", | 2205 | printk(KERN_DEBUG "%s: disassociating from %pM by local choice (reason=%d)\n", |
2089 | sdata->name, req->bss->bssid, req->reason_code); | 2206 | sdata->name, req->bss->bssid, req->reason_code); |
2090 | 2207 | ||
2091 | ieee80211_set_disassoc(sdata); | 2208 | memcpy(bssid, req->bss->bssid, ETH_ALEN); |
2209 | ieee80211_set_disassoc(sdata, false); | ||
2092 | 2210 | ||
2093 | mutex_unlock(&ifmgd->mtx); | 2211 | mutex_unlock(&ifmgd->mtx); |
2094 | 2212 | ||
2095 | ieee80211_send_deauth_disassoc(sdata, req->bss->bssid, | 2213 | ieee80211_send_deauth_disassoc(sdata, req->bss->bssid, |
2096 | IEEE80211_STYPE_DISASSOC, req->reason_code, | 2214 | IEEE80211_STYPE_DISASSOC, req->reason_code, |
2097 | cookie); | 2215 | cookie, !req->local_state_change); |
2216 | sta_info_destroy_addr(sdata, bssid); | ||
2098 | 2217 | ||
2099 | ieee80211_recalc_idle(sdata->local); | 2218 | ieee80211_recalc_idle(sdata->local); |
2100 | 2219 | ||
@@ -2135,3 +2254,13 @@ int ieee80211_mgd_action(struct ieee80211_sub_if_data *sdata, | |||
2135 | *cookie = (unsigned long) skb; | 2254 | *cookie = (unsigned long) skb; |
2136 | return 0; | 2255 | return 0; |
2137 | } | 2256 | } |
2257 | |||
2258 | void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif, | ||
2259 | enum nl80211_cqm_rssi_threshold_event rssi_event, | ||
2260 | gfp_t gfp) | ||
2261 | { | ||
2262 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
2263 | |||
2264 | cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, gfp); | ||
2265 | } | ||
2266 | EXPORT_SYMBOL(ieee80211_cqm_rssi_notify); | ||
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 0e64484e861c..75202b295a4e 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
@@ -46,7 +46,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) | |||
46 | 46 | ||
47 | if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { | 47 | if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { |
48 | list_for_each_entry_rcu(sta, &local->sta_list, list) { | 48 | list_for_each_entry_rcu(sta, &local->sta_list, list) { |
49 | set_sta_flags(sta, WLAN_STA_SUSPEND); | 49 | set_sta_flags(sta, WLAN_STA_BLOCK_BA); |
50 | ieee80211_sta_tear_down_BA_sessions(sta); | 50 | ieee80211_sta_tear_down_BA_sessions(sta); |
51 | } | 51 | } |
52 | } | 52 | } |
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index 6e5d68b4e427..4926d929fd9f 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c | |||
@@ -541,7 +541,7 @@ minstrel_free(void *priv) | |||
541 | kfree(priv); | 541 | kfree(priv); |
542 | } | 542 | } |
543 | 543 | ||
544 | static struct rate_control_ops mac80211_minstrel = { | 544 | struct rate_control_ops mac80211_minstrel = { |
545 | .name = "minstrel", | 545 | .name = "minstrel", |
546 | .tx_status = minstrel_tx_status, | 546 | .tx_status = minstrel_tx_status, |
547 | .get_rate = minstrel_get_rate, | 547 | .get_rate = minstrel_get_rate, |
diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h index 38bf4168fc3a..0f5a83370aa6 100644 --- a/net/mac80211/rc80211_minstrel.h +++ b/net/mac80211/rc80211_minstrel.h | |||
@@ -80,7 +80,18 @@ struct minstrel_priv { | |||
80 | unsigned int lookaround_rate_mrr; | 80 | unsigned int lookaround_rate_mrr; |
81 | }; | 81 | }; |
82 | 82 | ||
83 | struct minstrel_debugfs_info { | ||
84 | size_t len; | ||
85 | char buf[]; | ||
86 | }; | ||
87 | |||
88 | extern struct rate_control_ops mac80211_minstrel; | ||
83 | void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir); | 89 | void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir); |
84 | void minstrel_remove_sta_debugfs(void *priv, void *priv_sta); | 90 | void minstrel_remove_sta_debugfs(void *priv, void *priv_sta); |
85 | 91 | ||
92 | /* debugfs */ | ||
93 | int minstrel_stats_open(struct inode *inode, struct file *file); | ||
94 | ssize_t minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos); | ||
95 | int minstrel_stats_release(struct inode *inode, struct file *file); | ||
96 | |||
86 | #endif | 97 | #endif |
diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c index a715d9454f64..56d0f24957d9 100644 --- a/net/mac80211/rc80211_minstrel_debugfs.c +++ b/net/mac80211/rc80211_minstrel_debugfs.c | |||
@@ -52,21 +52,15 @@ | |||
52 | #include <net/mac80211.h> | 52 | #include <net/mac80211.h> |
53 | #include "rc80211_minstrel.h" | 53 | #include "rc80211_minstrel.h" |
54 | 54 | ||
55 | struct minstrel_stats_info { | 55 | int |
56 | struct minstrel_sta_info *mi; | ||
57 | char buf[4096]; | ||
58 | size_t len; | ||
59 | }; | ||
60 | |||
61 | static int | ||
62 | minstrel_stats_open(struct inode *inode, struct file *file) | 56 | minstrel_stats_open(struct inode *inode, struct file *file) |
63 | { | 57 | { |
64 | struct minstrel_sta_info *mi = inode->i_private; | 58 | struct minstrel_sta_info *mi = inode->i_private; |
65 | struct minstrel_stats_info *ms; | 59 | struct minstrel_debugfs_info *ms; |
66 | unsigned int i, tp, prob, eprob; | 60 | unsigned int i, tp, prob, eprob; |
67 | char *p; | 61 | char *p; |
68 | 62 | ||
69 | ms = kmalloc(sizeof(*ms), GFP_KERNEL); | 63 | ms = kmalloc(sizeof(*ms) + 4096, GFP_KERNEL); |
70 | if (!ms) | 64 | if (!ms) |
71 | return -ENOMEM; | 65 | return -ENOMEM; |
72 | 66 | ||
@@ -106,36 +100,19 @@ minstrel_stats_open(struct inode *inode, struct file *file) | |||
106 | return 0; | 100 | return 0; |
107 | } | 101 | } |
108 | 102 | ||
109 | static ssize_t | 103 | ssize_t |
110 | minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *o) | 104 | minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos) |
111 | { | 105 | { |
112 | struct minstrel_stats_info *ms; | 106 | struct minstrel_debugfs_info *ms; |
113 | char *src; | ||
114 | 107 | ||
115 | ms = file->private_data; | 108 | ms = file->private_data; |
116 | src = ms->buf; | 109 | return simple_read_from_buffer(buf, len, ppos, ms->buf, ms->len); |
117 | |||
118 | len = min(len, ms->len); | ||
119 | if (len <= *o) | ||
120 | return 0; | ||
121 | |||
122 | src += *o; | ||
123 | len -= *o; | ||
124 | *o += len; | ||
125 | |||
126 | if (copy_to_user(buf, src, len)) | ||
127 | return -EFAULT; | ||
128 | |||
129 | return len; | ||
130 | } | 110 | } |
131 | 111 | ||
132 | static int | 112 | int |
133 | minstrel_stats_release(struct inode *inode, struct file *file) | 113 | minstrel_stats_release(struct inode *inode, struct file *file) |
134 | { | 114 | { |
135 | struct minstrel_stats_info *ms = file->private_data; | 115 | kfree(file->private_data); |
136 | |||
137 | kfree(ms); | ||
138 | |||
139 | return 0; | 116 | return 0; |
140 | } | 117 | } |
141 | 118 | ||
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 13fcd2d17c6b..c0ad7e879a6e 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -38,7 +38,7 @@ static struct sk_buff *remove_monitor_info(struct ieee80211_local *local, | |||
38 | { | 38 | { |
39 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) { | 39 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) { |
40 | if (likely(skb->len > FCS_LEN)) | 40 | if (likely(skb->len > FCS_LEN)) |
41 | skb_trim(skb, skb->len - FCS_LEN); | 41 | __pskb_trim(skb, skb->len - FCS_LEN); |
42 | else { | 42 | else { |
43 | /* driver bug */ | 43 | /* driver bug */ |
44 | WARN_ON(1); | 44 | WARN_ON(1); |
@@ -178,14 +178,6 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
178 | pos++; | 178 | pos++; |
179 | } | 179 | } |
180 | 180 | ||
181 | /* IEEE80211_RADIOTAP_DBM_ANTNOISE */ | ||
182 | if (local->hw.flags & IEEE80211_HW_NOISE_DBM) { | ||
183 | *pos = status->noise; | ||
184 | rthdr->it_present |= | ||
185 | cpu_to_le32(1 << IEEE80211_RADIOTAP_DBM_ANTNOISE); | ||
186 | pos++; | ||
187 | } | ||
188 | |||
189 | /* IEEE80211_RADIOTAP_LOCK_QUALITY is missing */ | 181 | /* IEEE80211_RADIOTAP_LOCK_QUALITY is missing */ |
190 | 182 | ||
191 | /* IEEE80211_RADIOTAP_ANTENNA */ | 183 | /* IEEE80211_RADIOTAP_ANTENNA */ |
@@ -235,6 +227,12 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, | |||
235 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) | 227 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) |
236 | present_fcs_len = FCS_LEN; | 228 | present_fcs_len = FCS_LEN; |
237 | 229 | ||
230 | /* make sure hdr->frame_control is on the linear part */ | ||
231 | if (!pskb_may_pull(origskb, 2)) { | ||
232 | dev_kfree_skb(origskb); | ||
233 | return NULL; | ||
234 | } | ||
235 | |||
238 | if (!local->monitors) { | 236 | if (!local->monitors) { |
239 | if (should_drop_frame(origskb, present_fcs_len)) { | 237 | if (should_drop_frame(origskb, present_fcs_len)) { |
240 | dev_kfree_skb(origskb); | 238 | dev_kfree_skb(origskb); |
@@ -722,14 +720,16 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx, | |||
722 | 720 | ||
723 | tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; | 721 | tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; |
724 | 722 | ||
725 | if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL) | 723 | spin_lock(&sta->lock); |
726 | goto dont_reorder; | 724 | |
725 | if (!sta->ampdu_mlme.tid_active_rx[tid]) | ||
726 | goto dont_reorder_unlock; | ||
727 | 727 | ||
728 | tid_agg_rx = sta->ampdu_mlme.tid_rx[tid]; | 728 | tid_agg_rx = sta->ampdu_mlme.tid_rx[tid]; |
729 | 729 | ||
730 | /* qos null data frames are excluded */ | 730 | /* qos null data frames are excluded */ |
731 | if (unlikely(hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_NULLFUNC))) | 731 | if (unlikely(hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_NULLFUNC))) |
732 | goto dont_reorder; | 732 | goto dont_reorder_unlock; |
733 | 733 | ||
734 | /* new, potentially un-ordered, ampdu frame - process it */ | 734 | /* new, potentially un-ordered, ampdu frame - process it */ |
735 | 735 | ||
@@ -741,15 +741,20 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx, | |||
741 | /* if this mpdu is fragmented - terminate rx aggregation session */ | 741 | /* if this mpdu is fragmented - terminate rx aggregation session */ |
742 | sc = le16_to_cpu(hdr->seq_ctrl); | 742 | sc = le16_to_cpu(hdr->seq_ctrl); |
743 | if (sc & IEEE80211_SCTL_FRAG) { | 743 | if (sc & IEEE80211_SCTL_FRAG) { |
744 | ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->sta.addr, | 744 | spin_unlock(&sta->lock); |
745 | tid, 0, WLAN_REASON_QSTA_REQUIRE_SETUP); | 745 | __ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT, |
746 | WLAN_REASON_QSTA_REQUIRE_SETUP); | ||
746 | dev_kfree_skb(skb); | 747 | dev_kfree_skb(skb); |
747 | return; | 748 | return; |
748 | } | 749 | } |
749 | 750 | ||
750 | if (ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb, frames)) | 751 | if (ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb, frames)) { |
752 | spin_unlock(&sta->lock); | ||
751 | return; | 753 | return; |
754 | } | ||
752 | 755 | ||
756 | dont_reorder_unlock: | ||
757 | spin_unlock(&sta->lock); | ||
753 | dont_reorder: | 758 | dont_reorder: |
754 | __skb_queue_tail(frames, skb); | 759 | __skb_queue_tail(frames, skb); |
755 | } | 760 | } |
@@ -815,7 +820,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
815 | { | 820 | { |
816 | struct sk_buff *skb = rx->skb; | 821 | struct sk_buff *skb = rx->skb; |
817 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 822 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
818 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 823 | struct ieee80211_hdr *hdr; |
819 | int keyidx; | 824 | int keyidx; |
820 | int hdrlen; | 825 | int hdrlen; |
821 | ieee80211_rx_result result = RX_DROP_UNUSABLE; | 826 | ieee80211_rx_result result = RX_DROP_UNUSABLE; |
@@ -856,6 +861,11 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
856 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | 861 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) |
857 | return RX_CONTINUE; | 862 | return RX_CONTINUE; |
858 | 863 | ||
864 | if (skb_linearize(rx->skb)) | ||
865 | return RX_DROP_UNUSABLE; | ||
866 | |||
867 | hdr = (struct ieee80211_hdr *)skb->data; | ||
868 | |||
859 | /* start without a key */ | 869 | /* start without a key */ |
860 | rx->key = NULL; | 870 | rx->key = NULL; |
861 | 871 | ||
@@ -1077,7 +1087,6 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
1077 | sta->rx_fragments++; | 1087 | sta->rx_fragments++; |
1078 | sta->rx_bytes += rx->skb->len; | 1088 | sta->rx_bytes += rx->skb->len; |
1079 | sta->last_signal = status->signal; | 1089 | sta->last_signal = status->signal; |
1080 | sta->last_noise = status->noise; | ||
1081 | 1090 | ||
1082 | /* | 1091 | /* |
1083 | * Change STA power saving mode only at the end of a frame | 1092 | * Change STA power saving mode only at the end of a frame |
@@ -1240,6 +1249,9 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
1240 | } | 1249 | } |
1241 | I802_DEBUG_INC(rx->local->rx_handlers_fragments); | 1250 | I802_DEBUG_INC(rx->local->rx_handlers_fragments); |
1242 | 1251 | ||
1252 | if (skb_linearize(rx->skb)) | ||
1253 | return RX_DROP_UNUSABLE; | ||
1254 | |||
1243 | seq = (sc & IEEE80211_SCTL_SEQ) >> 4; | 1255 | seq = (sc & IEEE80211_SCTL_SEQ) >> 4; |
1244 | 1256 | ||
1245 | if (frag == 0) { | 1257 | if (frag == 0) { |
@@ -1405,21 +1417,24 @@ static int | |||
1405 | ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx) | 1417 | ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx) |
1406 | { | 1418 | { |
1407 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 1419 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
1420 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); | ||
1408 | __le16 fc = hdr->frame_control; | 1421 | __le16 fc = hdr->frame_control; |
1409 | int res; | ||
1410 | 1422 | ||
1411 | res = ieee80211_drop_unencrypted(rx, fc); | 1423 | /* |
1412 | if (unlikely(res)) | 1424 | * Pass through unencrypted frames if the hardware has |
1413 | return res; | 1425 | * decrypted them already. |
1426 | */ | ||
1427 | if (status->flag & RX_FLAG_DECRYPTED) | ||
1428 | return 0; | ||
1414 | 1429 | ||
1415 | if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) { | 1430 | if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) { |
1416 | if (unlikely(ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && | 1431 | if (unlikely(!ieee80211_has_protected(fc) && |
1432 | ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && | ||
1417 | rx->key)) | 1433 | rx->key)) |
1418 | return -EACCES; | 1434 | return -EACCES; |
1419 | /* BIP does not use Protected field, so need to check MMIE */ | 1435 | /* BIP does not use Protected field, so need to check MMIE */ |
1420 | if (unlikely(ieee80211_is_multicast_robust_mgmt_frame(rx->skb) && | 1436 | if (unlikely(ieee80211_is_multicast_robust_mgmt_frame(rx->skb) && |
1421 | ieee80211_get_mmie_keyidx(rx->skb) < 0 && | 1437 | ieee80211_get_mmie_keyidx(rx->skb) < 0)) |
1422 | rx->key)) | ||
1423 | return -EACCES; | 1438 | return -EACCES; |
1424 | /* | 1439 | /* |
1425 | * When using MFP, Action frames are not allowed prior to | 1440 | * When using MFP, Action frames are not allowed prior to |
@@ -1597,6 +1612,9 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) | |||
1597 | skb->dev = dev; | 1612 | skb->dev = dev; |
1598 | __skb_queue_head_init(&frame_list); | 1613 | __skb_queue_head_init(&frame_list); |
1599 | 1614 | ||
1615 | if (skb_linearize(skb)) | ||
1616 | return RX_DROP_UNUSABLE; | ||
1617 | |||
1600 | ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr, | 1618 | ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr, |
1601 | rx->sdata->vif.type, | 1619 | rx->sdata->vif.type, |
1602 | rx->local->hw.extra_tx_headroom); | 1620 | rx->local->hw.extra_tx_headroom); |
@@ -1795,10 +1813,12 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames) | |||
1795 | if (ieee80211_is_back_req(bar->frame_control)) { | 1813 | if (ieee80211_is_back_req(bar->frame_control)) { |
1796 | if (!rx->sta) | 1814 | if (!rx->sta) |
1797 | return RX_DROP_MONITOR; | 1815 | return RX_DROP_MONITOR; |
1816 | spin_lock(&rx->sta->lock); | ||
1798 | tid = le16_to_cpu(bar->control) >> 12; | 1817 | tid = le16_to_cpu(bar->control) >> 12; |
1799 | if (rx->sta->ampdu_mlme.tid_state_rx[tid] | 1818 | if (!rx->sta->ampdu_mlme.tid_active_rx[tid]) { |
1800 | != HT_AGG_STATE_OPERATIONAL) | 1819 | spin_unlock(&rx->sta->lock); |
1801 | return RX_DROP_MONITOR; | 1820 | return RX_DROP_MONITOR; |
1821 | } | ||
1802 | tid_agg_rx = rx->sta->ampdu_mlme.tid_rx[tid]; | 1822 | tid_agg_rx = rx->sta->ampdu_mlme.tid_rx[tid]; |
1803 | 1823 | ||
1804 | start_seq_num = le16_to_cpu(bar->start_seq_num) >> 4; | 1824 | start_seq_num = le16_to_cpu(bar->start_seq_num) >> 4; |
@@ -1812,6 +1832,7 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames) | |||
1812 | ieee80211_release_reorder_frames(hw, tid_agg_rx, start_seq_num, | 1832 | ieee80211_release_reorder_frames(hw, tid_agg_rx, start_seq_num, |
1813 | frames); | 1833 | frames); |
1814 | kfree_skb(skb); | 1834 | kfree_skb(skb); |
1835 | spin_unlock(&rx->sta->lock); | ||
1815 | return RX_QUEUED; | 1836 | return RX_QUEUED; |
1816 | } | 1837 | } |
1817 | 1838 | ||
@@ -2371,29 +2392,42 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2371 | struct ieee80211_local *local = hw_to_local(hw); | 2392 | struct ieee80211_local *local = hw_to_local(hw); |
2372 | struct ieee80211_sub_if_data *sdata; | 2393 | struct ieee80211_sub_if_data *sdata; |
2373 | struct ieee80211_hdr *hdr; | 2394 | struct ieee80211_hdr *hdr; |
2395 | __le16 fc; | ||
2374 | struct ieee80211_rx_data rx; | 2396 | struct ieee80211_rx_data rx; |
2375 | int prepares; | 2397 | int prepares; |
2376 | struct ieee80211_sub_if_data *prev = NULL; | 2398 | struct ieee80211_sub_if_data *prev = NULL; |
2377 | struct sk_buff *skb_new; | 2399 | struct sk_buff *skb_new; |
2378 | struct sta_info *sta, *tmp; | 2400 | struct sta_info *sta, *tmp; |
2379 | bool found_sta = false; | 2401 | bool found_sta = false; |
2402 | int err = 0; | ||
2380 | 2403 | ||
2381 | hdr = (struct ieee80211_hdr *)skb->data; | 2404 | fc = ((struct ieee80211_hdr *)skb->data)->frame_control; |
2382 | memset(&rx, 0, sizeof(rx)); | 2405 | memset(&rx, 0, sizeof(rx)); |
2383 | rx.skb = skb; | 2406 | rx.skb = skb; |
2384 | rx.local = local; | 2407 | rx.local = local; |
2385 | 2408 | ||
2386 | if (ieee80211_is_data(hdr->frame_control) || ieee80211_is_mgmt(hdr->frame_control)) | 2409 | if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc)) |
2387 | local->dot11ReceivedFragmentCount++; | 2410 | local->dot11ReceivedFragmentCount++; |
2388 | 2411 | ||
2389 | if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) || | 2412 | if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) || |
2390 | test_bit(SCAN_OFF_CHANNEL, &local->scanning))) | 2413 | test_bit(SCAN_OFF_CHANNEL, &local->scanning))) |
2391 | rx.flags |= IEEE80211_RX_IN_SCAN; | 2414 | rx.flags |= IEEE80211_RX_IN_SCAN; |
2392 | 2415 | ||
2416 | if (ieee80211_is_mgmt(fc)) | ||
2417 | err = skb_linearize(skb); | ||
2418 | else | ||
2419 | err = !pskb_may_pull(skb, ieee80211_hdrlen(fc)); | ||
2420 | |||
2421 | if (err) { | ||
2422 | dev_kfree_skb(skb); | ||
2423 | return; | ||
2424 | } | ||
2425 | |||
2426 | hdr = (struct ieee80211_hdr *)skb->data; | ||
2393 | ieee80211_parse_qos(&rx); | 2427 | ieee80211_parse_qos(&rx); |
2394 | ieee80211_verify_alignment(&rx); | 2428 | ieee80211_verify_alignment(&rx); |
2395 | 2429 | ||
2396 | if (ieee80211_is_data(hdr->frame_control)) { | 2430 | if (ieee80211_is_data(fc)) { |
2397 | for_each_sta_info(local, hdr->addr2, sta, tmp) { | 2431 | for_each_sta_info(local, hdr->addr2, sta, tmp) { |
2398 | rx.sta = sta; | 2432 | rx.sta = sta; |
2399 | found_sta = true; | 2433 | found_sta = true; |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index b822dce97867..75a85978c3b3 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -14,6 +14,8 @@ | |||
14 | 14 | ||
15 | #include <linux/if_arp.h> | 15 | #include <linux/if_arp.h> |
16 | #include <linux/rtnetlink.h> | 16 | #include <linux/rtnetlink.h> |
17 | #include <linux/pm_qos_params.h> | ||
18 | #include <net/sch_generic.h> | ||
17 | #include <net/mac80211.h> | 19 | #include <net/mac80211.h> |
18 | 20 | ||
19 | #include "ieee80211_i.h" | 21 | #include "ieee80211_i.h" |
@@ -321,6 +323,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) | |||
321 | 323 | ||
322 | ieee80211_offchannel_stop_beaconing(local); | 324 | ieee80211_offchannel_stop_beaconing(local); |
323 | 325 | ||
326 | local->leave_oper_channel_time = 0; | ||
324 | local->next_scan_state = SCAN_DECISION; | 327 | local->next_scan_state = SCAN_DECISION; |
325 | local->scan_channel_idx = 0; | 328 | local->scan_channel_idx = 0; |
326 | 329 | ||
@@ -425,11 +428,28 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
425 | return rc; | 428 | return rc; |
426 | } | 429 | } |
427 | 430 | ||
431 | static unsigned long | ||
432 | ieee80211_scan_get_channel_time(struct ieee80211_channel *chan) | ||
433 | { | ||
434 | /* | ||
435 | * TODO: channel switching also consumes quite some time, | ||
436 | * add that delay as well to get a better estimation | ||
437 | */ | ||
438 | if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) | ||
439 | return IEEE80211_PASSIVE_CHANNEL_TIME; | ||
440 | return IEEE80211_PROBE_DELAY + IEEE80211_CHANNEL_TIME; | ||
441 | } | ||
442 | |||
428 | static int ieee80211_scan_state_decision(struct ieee80211_local *local, | 443 | static int ieee80211_scan_state_decision(struct ieee80211_local *local, |
429 | unsigned long *next_delay) | 444 | unsigned long *next_delay) |
430 | { | 445 | { |
431 | bool associated = false; | 446 | bool associated = false; |
447 | bool tx_empty = true; | ||
448 | bool bad_latency; | ||
449 | bool listen_int_exceeded; | ||
450 | unsigned long min_beacon_int = 0; | ||
432 | struct ieee80211_sub_if_data *sdata; | 451 | struct ieee80211_sub_if_data *sdata; |
452 | struct ieee80211_channel *next_chan; | ||
433 | 453 | ||
434 | /* if no more bands/channels left, complete scan and advance to the idle state */ | 454 | /* if no more bands/channels left, complete scan and advance to the idle state */ |
435 | if (local->scan_channel_idx >= local->scan_req->n_channels) { | 455 | if (local->scan_channel_idx >= local->scan_req->n_channels) { |
@@ -437,7 +457,11 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local, | |||
437 | return 1; | 457 | return 1; |
438 | } | 458 | } |
439 | 459 | ||
440 | /* check if at least one STA interface is associated */ | 460 | /* |
461 | * check if at least one STA interface is associated, | ||
462 | * check if at least one STA interface has pending tx frames | ||
463 | * and grab the lowest used beacon interval | ||
464 | */ | ||
441 | mutex_lock(&local->iflist_mtx); | 465 | mutex_lock(&local->iflist_mtx); |
442 | list_for_each_entry(sdata, &local->interfaces, list) { | 466 | list_for_each_entry(sdata, &local->interfaces, list) { |
443 | if (!ieee80211_sdata_running(sdata)) | 467 | if (!ieee80211_sdata_running(sdata)) |
@@ -446,7 +470,16 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local, | |||
446 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 470 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { |
447 | if (sdata->u.mgd.associated) { | 471 | if (sdata->u.mgd.associated) { |
448 | associated = true; | 472 | associated = true; |
449 | break; | 473 | |
474 | if (sdata->vif.bss_conf.beacon_int < | ||
475 | min_beacon_int || min_beacon_int == 0) | ||
476 | min_beacon_int = | ||
477 | sdata->vif.bss_conf.beacon_int; | ||
478 | |||
479 | if (!qdisc_all_tx_empty(sdata->dev)) { | ||
480 | tx_empty = false; | ||
481 | break; | ||
482 | } | ||
450 | } | 483 | } |
451 | } | 484 | } |
452 | } | 485 | } |
@@ -455,11 +488,34 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local, | |||
455 | if (local->scan_channel) { | 488 | if (local->scan_channel) { |
456 | /* | 489 | /* |
457 | * we're currently scanning a different channel, let's | 490 | * we're currently scanning a different channel, let's |
458 | * switch back to the operating channel now if at least | 491 | * see if we can scan another channel without interfering |
459 | * one interface is associated. Otherwise just scan the | 492 | * with the current traffic situation. |
460 | * next channel | 493 | * |
494 | * Since we don't know if the AP has pending frames for us | ||
495 | * we can only check for our tx queues and use the current | ||
496 | * pm_qos requirements for rx. Hence, if no tx traffic occurs | ||
497 | * at all we will scan as many channels in a row as the pm_qos | ||
498 | * latency allows us to. Additionally we also check for the | ||
499 | * currently negotiated listen interval to prevent losing | ||
500 | * frames unnecessarily. | ||
501 | * | ||
502 | * Otherwise switch back to the operating channel. | ||
461 | */ | 503 | */ |
462 | if (associated) | 504 | next_chan = local->scan_req->channels[local->scan_channel_idx]; |
505 | |||
506 | bad_latency = time_after(jiffies + | ||
507 | ieee80211_scan_get_channel_time(next_chan), | ||
508 | local->leave_oper_channel_time + | ||
509 | usecs_to_jiffies(pm_qos_requirement(PM_QOS_NETWORK_LATENCY))); | ||
510 | |||
511 | listen_int_exceeded = time_after(jiffies + | ||
512 | ieee80211_scan_get_channel_time(next_chan), | ||
513 | local->leave_oper_channel_time + | ||
514 | usecs_to_jiffies(min_beacon_int * 1024) * | ||
515 | local->hw.conf.listen_interval); | ||
516 | |||
517 | if (associated && ( !tx_empty || bad_latency || | ||
518 | listen_int_exceeded)) | ||
463 | local->next_scan_state = SCAN_ENTER_OPER_CHANNEL; | 519 | local->next_scan_state = SCAN_ENTER_OPER_CHANNEL; |
464 | else | 520 | else |
465 | local->next_scan_state = SCAN_SET_CHANNEL; | 521 | local->next_scan_state = SCAN_SET_CHANNEL; |
@@ -491,6 +547,9 @@ static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *loca | |||
491 | else | 547 | else |
492 | *next_delay = HZ / 10; | 548 | *next_delay = HZ / 10; |
493 | 549 | ||
550 | /* remember when we left the operating channel */ | ||
551 | local->leave_oper_channel_time = jiffies; | ||
552 | |||
494 | /* advance to the next channel to be scanned */ | 553 | /* advance to the next channel to be scanned */ |
495 | local->next_scan_state = SCAN_SET_CHANNEL; | 554 | local->next_scan_state = SCAN_SET_CHANNEL; |
496 | } | 555 | } |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index fb12cec4d333..4de987cbda1c 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -250,9 +250,6 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
250 | * enable session_timer's data differentiation. refer to | 250 | * enable session_timer's data differentiation. refer to |
251 | * sta_rx_agg_session_timer_expired for useage */ | 251 | * sta_rx_agg_session_timer_expired for useage */ |
252 | sta->timer_to_tid[i] = i; | 252 | sta->timer_to_tid[i] = i; |
253 | /* rx */ | ||
254 | sta->ampdu_mlme.tid_state_rx[i] = HT_AGG_STATE_IDLE; | ||
255 | sta->ampdu_mlme.tid_rx[i] = NULL; | ||
256 | /* tx */ | 253 | /* tx */ |
257 | sta->ampdu_mlme.tid_state_tx[i] = HT_AGG_STATE_IDLE; | 254 | sta->ampdu_mlme.tid_state_tx[i] = HT_AGG_STATE_IDLE; |
258 | sta->ampdu_mlme.tid_tx[i] = NULL; | 255 | sta->ampdu_mlme.tid_tx[i] = NULL; |
@@ -619,7 +616,7 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
619 | struct ieee80211_sub_if_data *sdata; | 616 | struct ieee80211_sub_if_data *sdata; |
620 | struct sk_buff *skb; | 617 | struct sk_buff *skb; |
621 | unsigned long flags; | 618 | unsigned long flags; |
622 | int ret, i; | 619 | int ret; |
623 | 620 | ||
624 | might_sleep(); | 621 | might_sleep(); |
625 | 622 | ||
@@ -629,6 +626,15 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
629 | local = sta->local; | 626 | local = sta->local; |
630 | sdata = sta->sdata; | 627 | sdata = sta->sdata; |
631 | 628 | ||
629 | /* | ||
630 | * Before removing the station from the driver and | ||
631 | * rate control, it might still start new aggregation | ||
632 | * sessions -- block that to make sure the tear-down | ||
633 | * will be sufficient. | ||
634 | */ | ||
635 | set_sta_flags(sta, WLAN_STA_BLOCK_BA); | ||
636 | ieee80211_sta_tear_down_BA_sessions(sta); | ||
637 | |||
632 | spin_lock_irqsave(&local->sta_lock, flags); | 638 | spin_lock_irqsave(&local->sta_lock, flags); |
633 | ret = sta_info_hash_del(local, sta); | 639 | ret = sta_info_hash_del(local, sta); |
634 | /* this might still be the pending list ... which is fine */ | 640 | /* this might still be the pending list ... which is fine */ |
@@ -645,9 +651,6 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
645 | * may mean it is removed from hardware which requires that | 651 | * may mean it is removed from hardware which requires that |
646 | * the key->sta pointer is still valid, so flush the key todo | 652 | * the key->sta pointer is still valid, so flush the key todo |
647 | * list here. | 653 | * list here. |
648 | * | ||
649 | * ieee80211_key_todo() will synchronize_rcu() so after this | ||
650 | * nothing can reference this sta struct any more. | ||
651 | */ | 654 | */ |
652 | ieee80211_key_todo(); | 655 | ieee80211_key_todo(); |
653 | 656 | ||
@@ -679,11 +682,17 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
679 | sdata = sta->sdata; | 682 | sdata = sta->sdata; |
680 | } | 683 | } |
681 | 684 | ||
685 | /* | ||
686 | * At this point, after we wait for an RCU grace period, | ||
687 | * neither mac80211 nor the driver can reference this | ||
688 | * sta struct any more except by still existing timers | ||
689 | * associated with this station that we clean up below. | ||
690 | */ | ||
691 | synchronize_rcu(); | ||
692 | |||
682 | #ifdef CONFIG_MAC80211_MESH | 693 | #ifdef CONFIG_MAC80211_MESH |
683 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 694 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
684 | mesh_accept_plinks_update(sdata); | 695 | mesh_accept_plinks_update(sdata); |
685 | del_timer(&sta->plink_timer); | ||
686 | } | ||
687 | #endif | 696 | #endif |
688 | 697 | ||
689 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 698 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
@@ -710,50 +719,6 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
710 | while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) | 719 | while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) |
711 | dev_kfree_skb_any(skb); | 720 | dev_kfree_skb_any(skb); |
712 | 721 | ||
713 | for (i = 0; i < STA_TID_NUM; i++) { | ||
714 | struct tid_ampdu_rx *tid_rx; | ||
715 | struct tid_ampdu_tx *tid_tx; | ||
716 | |||
717 | spin_lock_bh(&sta->lock); | ||
718 | tid_rx = sta->ampdu_mlme.tid_rx[i]; | ||
719 | /* Make sure timer won't free the tid_rx struct, see below */ | ||
720 | if (tid_rx) | ||
721 | tid_rx->shutdown = true; | ||
722 | |||
723 | spin_unlock_bh(&sta->lock); | ||
724 | |||
725 | /* | ||
726 | * Outside spinlock - shutdown is true now so that the timer | ||
727 | * won't free tid_rx, we have to do that now. Can't let the | ||
728 | * timer do it because we have to sync the timer outside the | ||
729 | * lock that it takes itself. | ||
730 | */ | ||
731 | if (tid_rx) { | ||
732 | del_timer_sync(&tid_rx->session_timer); | ||
733 | kfree(tid_rx); | ||
734 | } | ||
735 | |||
736 | /* | ||
737 | * No need to do such complications for TX agg sessions, the | ||
738 | * path leading to freeing the tid_tx struct goes via a call | ||
739 | * from the driver, and thus needs to look up the sta struct | ||
740 | * again, which cannot be found when we get here. Hence, we | ||
741 | * just need to delete the timer and free the aggregation | ||
742 | * info; we won't be telling the peer about it then but that | ||
743 | * doesn't matter if we're not talking to it again anyway. | ||
744 | */ | ||
745 | tid_tx = sta->ampdu_mlme.tid_tx[i]; | ||
746 | if (tid_tx) { | ||
747 | del_timer_sync(&tid_tx->addba_resp_timer); | ||
748 | /* | ||
749 | * STA removed while aggregation session being | ||
750 | * started? Bit odd, but purge frames anyway. | ||
751 | */ | ||
752 | skb_queue_purge(&tid_tx->pending); | ||
753 | kfree(tid_tx); | ||
754 | } | ||
755 | } | ||
756 | |||
757 | __sta_info_free(local, sta); | 722 | __sta_info_free(local, sta); |
758 | 723 | ||
759 | return 0; | 724 | return 0; |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 822d84522937..48a5e80957f0 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -35,8 +35,8 @@ | |||
35 | * IEEE80211_TX_CTL_CLEAR_PS_FILT control flag) when the next | 35 | * IEEE80211_TX_CTL_CLEAR_PS_FILT control flag) when the next |
36 | * frame to this station is transmitted. | 36 | * frame to this station is transmitted. |
37 | * @WLAN_STA_MFP: Management frame protection is used with this STA. | 37 | * @WLAN_STA_MFP: Management frame protection is used with this STA. |
38 | * @WLAN_STA_SUSPEND: Set/cleared during a suspend/resume cycle. | 38 | * @WLAN_STA_BLOCK_BA: Used to deny ADDBA requests (both TX and RX) |
39 | * Used to deny ADDBA requests (both TX and RX). | 39 | * during suspend/resume and station removal. |
40 | * @WLAN_STA_PS_DRIVER: driver requires keeping this station in | 40 | * @WLAN_STA_PS_DRIVER: driver requires keeping this station in |
41 | * power-save mode logically to flush frames that might still | 41 | * power-save mode logically to flush frames that might still |
42 | * be in the queues | 42 | * be in the queues |
@@ -57,7 +57,7 @@ enum ieee80211_sta_info_flags { | |||
57 | WLAN_STA_WDS = 1<<7, | 57 | WLAN_STA_WDS = 1<<7, |
58 | WLAN_STA_CLEAR_PS_FILT = 1<<9, | 58 | WLAN_STA_CLEAR_PS_FILT = 1<<9, |
59 | WLAN_STA_MFP = 1<<10, | 59 | WLAN_STA_MFP = 1<<10, |
60 | WLAN_STA_SUSPEND = 1<<11, | 60 | WLAN_STA_BLOCK_BA = 1<<11, |
61 | WLAN_STA_PS_DRIVER = 1<<12, | 61 | WLAN_STA_PS_DRIVER = 1<<12, |
62 | WLAN_STA_PSPOLL = 1<<13, | 62 | WLAN_STA_PSPOLL = 1<<13, |
63 | WLAN_STA_DISASSOC = 1<<14, | 63 | WLAN_STA_DISASSOC = 1<<14, |
@@ -106,7 +106,6 @@ struct tid_ampdu_tx { | |||
106 | * @buf_size: buffer size for incoming A-MPDUs | 106 | * @buf_size: buffer size for incoming A-MPDUs |
107 | * @timeout: reset timer value (in TUs). | 107 | * @timeout: reset timer value (in TUs). |
108 | * @dialog_token: dialog token for aggregation session | 108 | * @dialog_token: dialog token for aggregation session |
109 | * @shutdown: this session is being shut down due to STA removal | ||
110 | */ | 109 | */ |
111 | struct tid_ampdu_rx { | 110 | struct tid_ampdu_rx { |
112 | struct sk_buff **reorder_buf; | 111 | struct sk_buff **reorder_buf; |
@@ -118,7 +117,6 @@ struct tid_ampdu_rx { | |||
118 | u16 buf_size; | 117 | u16 buf_size; |
119 | u16 timeout; | 118 | u16 timeout; |
120 | u8 dialog_token; | 119 | u8 dialog_token; |
121 | bool shutdown; | ||
122 | }; | 120 | }; |
123 | 121 | ||
124 | /** | 122 | /** |
@@ -156,7 +154,7 @@ enum plink_state { | |||
156 | */ | 154 | */ |
157 | struct sta_ampdu_mlme { | 155 | struct sta_ampdu_mlme { |
158 | /* rx */ | 156 | /* rx */ |
159 | u8 tid_state_rx[STA_TID_NUM]; | 157 | bool tid_active_rx[STA_TID_NUM]; |
160 | struct tid_ampdu_rx *tid_rx[STA_TID_NUM]; | 158 | struct tid_ampdu_rx *tid_rx[STA_TID_NUM]; |
161 | /* tx */ | 159 | /* tx */ |
162 | u8 tid_state_tx[STA_TID_NUM]; | 160 | u8 tid_state_tx[STA_TID_NUM]; |
@@ -200,7 +198,6 @@ struct sta_ampdu_mlme { | |||
200 | * @rx_fragments: number of received MPDUs | 198 | * @rx_fragments: number of received MPDUs |
201 | * @rx_dropped: number of dropped MPDUs from this STA | 199 | * @rx_dropped: number of dropped MPDUs from this STA |
202 | * @last_signal: signal of last received frame from this STA | 200 | * @last_signal: signal of last received frame from this STA |
203 | * @last_noise: noise of last received frame from this STA | ||
204 | * @last_seq_ctrl: last received seq/frag number from this STA (per RX queue) | 201 | * @last_seq_ctrl: last received seq/frag number from this STA (per RX queue) |
205 | * @tx_filtered_count: number of frames the hardware filtered for this STA | 202 | * @tx_filtered_count: number of frames the hardware filtered for this STA |
206 | * @tx_retry_failed: number of frames that failed retry | 203 | * @tx_retry_failed: number of frames that failed retry |
@@ -267,7 +264,6 @@ struct sta_info { | |||
267 | unsigned long rx_fragments; | 264 | unsigned long rx_fragments; |
268 | unsigned long rx_dropped; | 265 | unsigned long rx_dropped; |
269 | int last_signal; | 266 | int last_signal; |
270 | int last_noise; | ||
271 | __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES]; | 267 | __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES]; |
272 | 268 | ||
273 | /* Updated from TX status path only, no locking requirements */ | 269 | /* Updated from TX status path only, no locking requirements */ |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 56d5b9a6ec5b..11805a3a626f 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -171,7 +171,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
171 | struct net_device *prev_dev = NULL; | 171 | struct net_device *prev_dev = NULL; |
172 | struct sta_info *sta, *tmp; | 172 | struct sta_info *sta, *tmp; |
173 | int retry_count = -1, i; | 173 | int retry_count = -1, i; |
174 | bool injected; | 174 | bool send_to_cooked; |
175 | 175 | ||
176 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { | 176 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { |
177 | /* the HW cannot have attempted that rate */ | 177 | /* the HW cannot have attempted that rate */ |
@@ -296,11 +296,15 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
296 | /* this was a transmitted frame, but now we want to reuse it */ | 296 | /* this was a transmitted frame, but now we want to reuse it */ |
297 | skb_orphan(skb); | 297 | skb_orphan(skb); |
298 | 298 | ||
299 | /* Need to make a copy before skb->cb gets cleared */ | ||
300 | send_to_cooked = !!(info->flags & IEEE80211_TX_CTL_INJECTED) || | ||
301 | (type != IEEE80211_FTYPE_DATA); | ||
302 | |||
299 | /* | 303 | /* |
300 | * This is a bit racy but we can avoid a lot of work | 304 | * This is a bit racy but we can avoid a lot of work |
301 | * with this test... | 305 | * with this test... |
302 | */ | 306 | */ |
303 | if (!local->monitors && !local->cooked_mntrs) { | 307 | if (!local->monitors && (!send_to_cooked || !local->cooked_mntrs)) { |
304 | dev_kfree_skb(skb); | 308 | dev_kfree_skb(skb); |
305 | return; | 309 | return; |
306 | } | 310 | } |
@@ -345,9 +349,6 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
345 | /* for now report the total retry_count */ | 349 | /* for now report the total retry_count */ |
346 | rthdr->data_retries = retry_count; | 350 | rthdr->data_retries = retry_count; |
347 | 351 | ||
348 | /* Need to make a copy before skb->cb gets cleared */ | ||
349 | injected = !!(info->flags & IEEE80211_TX_CTL_INJECTED); | ||
350 | |||
351 | /* XXX: is this sufficient for BPF? */ | 352 | /* XXX: is this sufficient for BPF? */ |
352 | skb_set_mac_header(skb, 0); | 353 | skb_set_mac_header(skb, 0); |
353 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 354 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
@@ -362,8 +363,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
362 | continue; | 363 | continue; |
363 | 364 | ||
364 | if ((sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) && | 365 | if ((sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) && |
365 | !injected && | 366 | !send_to_cooked) |
366 | (type == IEEE80211_FTYPE_DATA)) | ||
367 | continue; | 367 | continue; |
368 | 368 | ||
369 | if (prev_dev) { | 369 | if (prev_dev) { |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index cfc473e1b050..2cb77267f733 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -513,6 +513,8 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
513 | else if (tx->sta && (key = rcu_dereference(tx->sta->key))) | 513 | else if (tx->sta && (key = rcu_dereference(tx->sta->key))) |
514 | tx->key = key; | 514 | tx->key = key; |
515 | else if (ieee80211_is_mgmt(hdr->frame_control) && | 515 | else if (ieee80211_is_mgmt(hdr->frame_control) && |
516 | is_multicast_ether_addr(hdr->addr1) && | ||
517 | ieee80211_is_robust_mgmt_frame(hdr) && | ||
516 | (key = rcu_dereference(tx->sdata->default_mgmt_key))) | 518 | (key = rcu_dereference(tx->sdata->default_mgmt_key))) |
517 | tx->key = key; | 519 | tx->key = key; |
518 | else if ((key = rcu_dereference(tx->sdata->default_key))) | 520 | else if ((key = rcu_dereference(tx->sdata->default_key))) |
@@ -1142,13 +1144,12 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, | |||
1142 | 1144 | ||
1143 | if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) && | 1145 | if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) && |
1144 | (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION)) { | 1146 | (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION)) { |
1145 | unsigned long flags; | ||
1146 | struct tid_ampdu_tx *tid_tx; | 1147 | struct tid_ampdu_tx *tid_tx; |
1147 | 1148 | ||
1148 | qc = ieee80211_get_qos_ctl(hdr); | 1149 | qc = ieee80211_get_qos_ctl(hdr); |
1149 | tid = *qc & IEEE80211_QOS_CTL_TID_MASK; | 1150 | tid = *qc & IEEE80211_QOS_CTL_TID_MASK; |
1150 | 1151 | ||
1151 | spin_lock_irqsave(&tx->sta->lock, flags); | 1152 | spin_lock(&tx->sta->lock); |
1152 | /* | 1153 | /* |
1153 | * XXX: This spinlock could be fairly expensive, but see the | 1154 | * XXX: This spinlock could be fairly expensive, but see the |
1154 | * comment in agg-tx.c:ieee80211_agg_tx_operational(). | 1155 | * comment in agg-tx.c:ieee80211_agg_tx_operational(). |
@@ -1173,7 +1174,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, | |||
1173 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; | 1174 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; |
1174 | __skb_queue_tail(&tid_tx->pending, skb); | 1175 | __skb_queue_tail(&tid_tx->pending, skb); |
1175 | } | 1176 | } |
1176 | spin_unlock_irqrestore(&tx->sta->lock, flags); | 1177 | spin_unlock(&tx->sta->lock); |
1177 | 1178 | ||
1178 | if (unlikely(queued)) | 1179 | if (unlikely(queued)) |
1179 | return TX_QUEUED; | 1180 | return TX_QUEUED; |
@@ -2011,14 +2012,12 @@ void ieee80211_tx_pending(unsigned long data) | |||
2011 | while (!skb_queue_empty(&local->pending[i])) { | 2012 | while (!skb_queue_empty(&local->pending[i])) { |
2012 | struct sk_buff *skb = __skb_dequeue(&local->pending[i]); | 2013 | struct sk_buff *skb = __skb_dequeue(&local->pending[i]); |
2013 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 2014 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
2014 | struct ieee80211_sub_if_data *sdata; | ||
2015 | 2015 | ||
2016 | if (WARN_ON(!info->control.vif)) { | 2016 | if (WARN_ON(!info->control.vif)) { |
2017 | kfree_skb(skb); | 2017 | kfree_skb(skb); |
2018 | continue; | 2018 | continue; |
2019 | } | 2019 | } |
2020 | 2020 | ||
2021 | sdata = vif_to_sdata(info->control.vif); | ||
2022 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, | 2021 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, |
2023 | flags); | 2022 | flags); |
2024 | 2023 | ||
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 53af57047435..ad9009f717ed 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -796,6 +796,11 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) | |||
796 | 796 | ||
797 | drv_conf_tx(local, queue, &qparam); | 797 | drv_conf_tx(local, queue, &qparam); |
798 | } | 798 | } |
799 | |||
800 | /* after reinitialize QoS TX queues setting to default, | ||
801 | * disable QoS at all */ | ||
802 | local->hw.conf.flags &= ~IEEE80211_CONF_QOS; | ||
803 | drv_config(local, IEEE80211_CONF_CHANGE_QOS); | ||
799 | } | 804 | } |
800 | 805 | ||
801 | void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, | 806 | void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, |
@@ -1135,7 +1140,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1135 | 1140 | ||
1136 | if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { | 1141 | if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { |
1137 | list_for_each_entry_rcu(sta, &local->sta_list, list) { | 1142 | list_for_each_entry_rcu(sta, &local->sta_list, list) { |
1138 | clear_sta_flags(sta, WLAN_STA_SUSPEND); | 1143 | clear_sta_flags(sta, WLAN_STA_BLOCK_BA); |
1139 | } | 1144 | } |
1140 | } | 1145 | } |
1141 | 1146 | ||
diff --git a/net/rfkill/core.c b/net/rfkill/core.c index c218e07e5caf..7ae58b5b5a08 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c | |||
@@ -628,6 +628,49 @@ static ssize_t rfkill_persistent_show(struct device *dev, | |||
628 | return sprintf(buf, "%d\n", rfkill->persistent); | 628 | return sprintf(buf, "%d\n", rfkill->persistent); |
629 | } | 629 | } |
630 | 630 | ||
631 | static ssize_t rfkill_hard_show(struct device *dev, | ||
632 | struct device_attribute *attr, | ||
633 | char *buf) | ||
634 | { | ||
635 | struct rfkill *rfkill = to_rfkill(dev); | ||
636 | |||
637 | return sprintf(buf, "%d\n", (rfkill->state & RFKILL_BLOCK_HW) ? 1 : 0 ); | ||
638 | } | ||
639 | |||
640 | static ssize_t rfkill_soft_show(struct device *dev, | ||
641 | struct device_attribute *attr, | ||
642 | char *buf) | ||
643 | { | ||
644 | struct rfkill *rfkill = to_rfkill(dev); | ||
645 | |||
646 | return sprintf(buf, "%d\n", (rfkill->state & RFKILL_BLOCK_SW) ? 1 : 0 ); | ||
647 | } | ||
648 | |||
649 | static ssize_t rfkill_soft_store(struct device *dev, | ||
650 | struct device_attribute *attr, | ||
651 | const char *buf, size_t count) | ||
652 | { | ||
653 | struct rfkill *rfkill = to_rfkill(dev); | ||
654 | unsigned long state; | ||
655 | int err; | ||
656 | |||
657 | if (!capable(CAP_NET_ADMIN)) | ||
658 | return -EPERM; | ||
659 | |||
660 | err = strict_strtoul(buf, 0, &state); | ||
661 | if (err) | ||
662 | return err; | ||
663 | |||
664 | if (state > 1 ) | ||
665 | return -EINVAL; | ||
666 | |||
667 | mutex_lock(&rfkill_global_mutex); | ||
668 | rfkill_set_block(rfkill, state); | ||
669 | mutex_unlock(&rfkill_global_mutex); | ||
670 | |||
671 | return err ?: count; | ||
672 | } | ||
673 | |||
631 | static u8 user_state_from_blocked(unsigned long state) | 674 | static u8 user_state_from_blocked(unsigned long state) |
632 | { | 675 | { |
633 | if (state & RFKILL_BLOCK_HW) | 676 | if (state & RFKILL_BLOCK_HW) |
@@ -643,14 +686,8 @@ static ssize_t rfkill_state_show(struct device *dev, | |||
643 | char *buf) | 686 | char *buf) |
644 | { | 687 | { |
645 | struct rfkill *rfkill = to_rfkill(dev); | 688 | struct rfkill *rfkill = to_rfkill(dev); |
646 | unsigned long flags; | ||
647 | u32 state; | ||
648 | |||
649 | spin_lock_irqsave(&rfkill->lock, flags); | ||
650 | state = rfkill->state; | ||
651 | spin_unlock_irqrestore(&rfkill->lock, flags); | ||
652 | 689 | ||
653 | return sprintf(buf, "%d\n", user_state_from_blocked(state)); | 690 | return sprintf(buf, "%d\n", user_state_from_blocked(rfkill->state)); |
654 | } | 691 | } |
655 | 692 | ||
656 | static ssize_t rfkill_state_store(struct device *dev, | 693 | static ssize_t rfkill_state_store(struct device *dev, |
@@ -700,6 +737,8 @@ static struct device_attribute rfkill_dev_attrs[] = { | |||
700 | __ATTR(persistent, S_IRUGO, rfkill_persistent_show, NULL), | 737 | __ATTR(persistent, S_IRUGO, rfkill_persistent_show, NULL), |
701 | __ATTR(state, S_IRUGO|S_IWUSR, rfkill_state_show, rfkill_state_store), | 738 | __ATTR(state, S_IRUGO|S_IWUSR, rfkill_state_show, rfkill_state_store), |
702 | __ATTR(claim, S_IRUGO|S_IWUSR, rfkill_claim_show, rfkill_claim_store), | 739 | __ATTR(claim, S_IRUGO|S_IWUSR, rfkill_claim_show, rfkill_claim_store), |
740 | __ATTR(soft, S_IRUGO|S_IWUSR, rfkill_soft_show, rfkill_soft_store), | ||
741 | __ATTR(hard, S_IRUGO, rfkill_hard_show, NULL), | ||
703 | __ATTR_NULL | 742 | __ATTR_NULL |
704 | }; | 743 | }; |
705 | 744 | ||
diff --git a/net/wireless/core.h b/net/wireless/core.h index d52da913145a..b2234b436ead 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -293,13 +293,15 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
293 | const u8 *bssid, | 293 | const u8 *bssid, |
294 | const u8 *ssid, int ssid_len, | 294 | const u8 *ssid, int ssid_len, |
295 | const u8 *ie, int ie_len, | 295 | const u8 *ie, int ie_len, |
296 | const u8 *key, int key_len, int key_idx); | 296 | const u8 *key, int key_len, int key_idx, |
297 | bool local_state_change); | ||
297 | int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | 298 | int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, |
298 | struct net_device *dev, struct ieee80211_channel *chan, | 299 | struct net_device *dev, struct ieee80211_channel *chan, |
299 | enum nl80211_auth_type auth_type, const u8 *bssid, | 300 | enum nl80211_auth_type auth_type, const u8 *bssid, |
300 | const u8 *ssid, int ssid_len, | 301 | const u8 *ssid, int ssid_len, |
301 | const u8 *ie, int ie_len, | 302 | const u8 *ie, int ie_len, |
302 | const u8 *key, int key_len, int key_idx); | 303 | const u8 *key, int key_len, int key_idx, |
304 | bool local_state_change); | ||
303 | int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | 305 | int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, |
304 | struct net_device *dev, | 306 | struct net_device *dev, |
305 | struct ieee80211_channel *chan, | 307 | struct ieee80211_channel *chan, |
@@ -315,13 +317,16 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | |||
315 | struct cfg80211_crypto_settings *crypt); | 317 | struct cfg80211_crypto_settings *crypt); |
316 | int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, | 318 | int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, |
317 | struct net_device *dev, const u8 *bssid, | 319 | struct net_device *dev, const u8 *bssid, |
318 | const u8 *ie, int ie_len, u16 reason); | 320 | const u8 *ie, int ie_len, u16 reason, |
321 | bool local_state_change); | ||
319 | int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, | 322 | int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, |
320 | struct net_device *dev, const u8 *bssid, | 323 | struct net_device *dev, const u8 *bssid, |
321 | const u8 *ie, int ie_len, u16 reason); | 324 | const u8 *ie, int ie_len, u16 reason, |
325 | bool local_state_change); | ||
322 | int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, | 326 | int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, |
323 | struct net_device *dev, const u8 *bssid, | 327 | struct net_device *dev, const u8 *bssid, |
324 | const u8 *ie, int ie_len, u16 reason); | 328 | const u8 *ie, int ie_len, u16 reason, |
329 | bool local_state_change); | ||
325 | void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, | 330 | void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, |
326 | struct net_device *dev); | 331 | struct net_device *dev); |
327 | void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | 332 | void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 62bc8855e123..387dd2a27d2f 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -377,7 +377,8 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
377 | const u8 *bssid, | 377 | const u8 *bssid, |
378 | const u8 *ssid, int ssid_len, | 378 | const u8 *ssid, int ssid_len, |
379 | const u8 *ie, int ie_len, | 379 | const u8 *ie, int ie_len, |
380 | const u8 *key, int key_len, int key_idx) | 380 | const u8 *key, int key_len, int key_idx, |
381 | bool local_state_change) | ||
381 | { | 382 | { |
382 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 383 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
383 | struct cfg80211_auth_request req; | 384 | struct cfg80211_auth_request req; |
@@ -407,6 +408,7 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
407 | 408 | ||
408 | memset(&req, 0, sizeof(req)); | 409 | memset(&req, 0, sizeof(req)); |
409 | 410 | ||
411 | req.local_state_change = local_state_change; | ||
410 | req.ie = ie; | 412 | req.ie = ie; |
411 | req.ie_len = ie_len; | 413 | req.ie_len = ie_len; |
412 | req.auth_type = auth_type; | 414 | req.auth_type = auth_type; |
@@ -433,12 +435,18 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
433 | goto out; | 435 | goto out; |
434 | } | 436 | } |
435 | 437 | ||
436 | wdev->authtry_bsses[slot] = bss; | 438 | if (local_state_change) |
439 | wdev->auth_bsses[slot] = bss; | ||
440 | else | ||
441 | wdev->authtry_bsses[slot] = bss; | ||
437 | cfg80211_hold_bss(bss); | 442 | cfg80211_hold_bss(bss); |
438 | 443 | ||
439 | err = rdev->ops->auth(&rdev->wiphy, dev, &req); | 444 | err = rdev->ops->auth(&rdev->wiphy, dev, &req); |
440 | if (err) { | 445 | if (err) { |
441 | wdev->authtry_bsses[slot] = NULL; | 446 | if (local_state_change) |
447 | wdev->auth_bsses[slot] = NULL; | ||
448 | else | ||
449 | wdev->authtry_bsses[slot] = NULL; | ||
442 | cfg80211_unhold_bss(bss); | 450 | cfg80211_unhold_bss(bss); |
443 | } | 451 | } |
444 | 452 | ||
@@ -453,14 +461,15 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
453 | enum nl80211_auth_type auth_type, const u8 *bssid, | 461 | enum nl80211_auth_type auth_type, const u8 *bssid, |
454 | const u8 *ssid, int ssid_len, | 462 | const u8 *ssid, int ssid_len, |
455 | const u8 *ie, int ie_len, | 463 | const u8 *ie, int ie_len, |
456 | const u8 *key, int key_len, int key_idx) | 464 | const u8 *key, int key_len, int key_idx, |
465 | bool local_state_change) | ||
457 | { | 466 | { |
458 | int err; | 467 | int err; |
459 | 468 | ||
460 | wdev_lock(dev->ieee80211_ptr); | 469 | wdev_lock(dev->ieee80211_ptr); |
461 | err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, | 470 | err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, |
462 | ssid, ssid_len, ie, ie_len, | 471 | ssid, ssid_len, ie, ie_len, |
463 | key, key_len, key_idx); | 472 | key, key_len, key_idx, local_state_change); |
464 | wdev_unlock(dev->ieee80211_ptr); | 473 | wdev_unlock(dev->ieee80211_ptr); |
465 | 474 | ||
466 | return err; | 475 | return err; |
@@ -554,7 +563,8 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | |||
554 | 563 | ||
555 | int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, | 564 | int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, |
556 | struct net_device *dev, const u8 *bssid, | 565 | struct net_device *dev, const u8 *bssid, |
557 | const u8 *ie, int ie_len, u16 reason) | 566 | const u8 *ie, int ie_len, u16 reason, |
567 | bool local_state_change) | ||
558 | { | 568 | { |
559 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 569 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
560 | struct cfg80211_deauth_request req; | 570 | struct cfg80211_deauth_request req; |
@@ -564,6 +574,7 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, | |||
564 | 574 | ||
565 | memset(&req, 0, sizeof(req)); | 575 | memset(&req, 0, sizeof(req)); |
566 | req.reason_code = reason; | 576 | req.reason_code = reason; |
577 | req.local_state_change = local_state_change; | ||
567 | req.ie = ie; | 578 | req.ie = ie; |
568 | req.ie_len = ie_len; | 579 | req.ie_len = ie_len; |
569 | if (wdev->current_bss && | 580 | if (wdev->current_bss && |
@@ -590,13 +601,15 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, | |||
590 | 601 | ||
591 | int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, | 602 | int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, |
592 | struct net_device *dev, const u8 *bssid, | 603 | struct net_device *dev, const u8 *bssid, |
593 | const u8 *ie, int ie_len, u16 reason) | 604 | const u8 *ie, int ie_len, u16 reason, |
605 | bool local_state_change) | ||
594 | { | 606 | { |
595 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 607 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
596 | int err; | 608 | int err; |
597 | 609 | ||
598 | wdev_lock(wdev); | 610 | wdev_lock(wdev); |
599 | err = __cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason); | 611 | err = __cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason, |
612 | local_state_change); | ||
600 | wdev_unlock(wdev); | 613 | wdev_unlock(wdev); |
601 | 614 | ||
602 | return err; | 615 | return err; |
@@ -604,7 +617,8 @@ int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, | |||
604 | 617 | ||
605 | static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, | 618 | static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, |
606 | struct net_device *dev, const u8 *bssid, | 619 | struct net_device *dev, const u8 *bssid, |
607 | const u8 *ie, int ie_len, u16 reason) | 620 | const u8 *ie, int ie_len, u16 reason, |
621 | bool local_state_change) | ||
608 | { | 622 | { |
609 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 623 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
610 | struct cfg80211_disassoc_request req; | 624 | struct cfg80211_disassoc_request req; |
@@ -619,6 +633,7 @@ static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, | |||
619 | 633 | ||
620 | memset(&req, 0, sizeof(req)); | 634 | memset(&req, 0, sizeof(req)); |
621 | req.reason_code = reason; | 635 | req.reason_code = reason; |
636 | req.local_state_change = local_state_change; | ||
622 | req.ie = ie; | 637 | req.ie = ie; |
623 | req.ie_len = ie_len; | 638 | req.ie_len = ie_len; |
624 | if (memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) | 639 | if (memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) |
@@ -631,13 +646,15 @@ static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, | |||
631 | 646 | ||
632 | int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, | 647 | int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, |
633 | struct net_device *dev, const u8 *bssid, | 648 | struct net_device *dev, const u8 *bssid, |
634 | const u8 *ie, int ie_len, u16 reason) | 649 | const u8 *ie, int ie_len, u16 reason, |
650 | bool local_state_change) | ||
635 | { | 651 | { |
636 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 652 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
637 | int err; | 653 | int err; |
638 | 654 | ||
639 | wdev_lock(wdev); | 655 | wdev_lock(wdev); |
640 | err = __cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason); | 656 | err = __cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason, |
657 | local_state_change); | ||
641 | wdev_unlock(wdev); | 658 | wdev_unlock(wdev); |
642 | 659 | ||
643 | return err; | 660 | return err; |
@@ -894,3 +911,16 @@ void cfg80211_action_tx_status(struct net_device *dev, u64 cookie, | |||
894 | nl80211_send_action_tx_status(rdev, dev, cookie, buf, len, ack, gfp); | 911 | nl80211_send_action_tx_status(rdev, dev, cookie, buf, len, ack, gfp); |
895 | } | 912 | } |
896 | EXPORT_SYMBOL(cfg80211_action_tx_status); | 913 | EXPORT_SYMBOL(cfg80211_action_tx_status); |
914 | |||
915 | void cfg80211_cqm_rssi_notify(struct net_device *dev, | ||
916 | enum nl80211_cqm_rssi_threshold_event rssi_event, | ||
917 | gfp_t gfp) | ||
918 | { | ||
919 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
920 | struct wiphy *wiphy = wdev->wiphy; | ||
921 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
922 | |||
923 | /* Indicate roaming trigger event to user space */ | ||
924 | nl80211_send_cqm_rssi_notify(rdev, dev, rssi_event, gfp); | ||
925 | } | ||
926 | EXPORT_SYMBOL(cfg80211_cqm_rssi_notify); | ||
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index e447db04cf76..df5505b3930c 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -149,6 +149,8 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
149 | .len = IEEE80211_MAX_DATA_LEN }, | 149 | .len = IEEE80211_MAX_DATA_LEN }, |
150 | [NL80211_ATTR_FRAME_MATCH] = { .type = NLA_BINARY, }, | 150 | [NL80211_ATTR_FRAME_MATCH] = { .type = NLA_BINARY, }, |
151 | [NL80211_ATTR_PS_STATE] = { .type = NLA_U32 }, | 151 | [NL80211_ATTR_PS_STATE] = { .type = NLA_U32 }, |
152 | [NL80211_ATTR_CQM] = { .type = NLA_NESTED, }, | ||
153 | [NL80211_ATTR_LOCAL_STATE_CHANGE] = { .type = NLA_FLAG }, | ||
152 | }; | 154 | }; |
153 | 155 | ||
154 | /* policy for the attributes */ | 156 | /* policy for the attributes */ |
@@ -2095,7 +2097,8 @@ static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info) | |||
2095 | goto out_rtnl; | 2097 | goto out_rtnl; |
2096 | 2098 | ||
2097 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && | 2099 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && |
2098 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN) { | 2100 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && |
2101 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) { | ||
2099 | err = -EINVAL; | 2102 | err = -EINVAL; |
2100 | goto out; | 2103 | goto out; |
2101 | } | 2104 | } |
@@ -3391,6 +3394,7 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) | |||
3391 | int err, ssid_len, ie_len = 0; | 3394 | int err, ssid_len, ie_len = 0; |
3392 | enum nl80211_auth_type auth_type; | 3395 | enum nl80211_auth_type auth_type; |
3393 | struct key_parse key; | 3396 | struct key_parse key; |
3397 | bool local_state_change; | ||
3394 | 3398 | ||
3395 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) | 3399 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) |
3396 | return -EINVAL; | 3400 | return -EINVAL; |
@@ -3469,9 +3473,12 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) | |||
3469 | goto out; | 3473 | goto out; |
3470 | } | 3474 | } |
3471 | 3475 | ||
3476 | local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; | ||
3477 | |||
3472 | err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, | 3478 | err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, |
3473 | ssid, ssid_len, ie, ie_len, | 3479 | ssid, ssid_len, ie, ie_len, |
3474 | key.p.key, key.p.key_len, key.idx); | 3480 | key.p.key, key.p.key_len, key.idx, |
3481 | local_state_change); | ||
3475 | 3482 | ||
3476 | out: | 3483 | out: |
3477 | cfg80211_unlock_rdev(rdev); | 3484 | cfg80211_unlock_rdev(rdev); |
@@ -3648,6 +3655,7 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info) | |||
3648 | const u8 *ie = NULL, *bssid; | 3655 | const u8 *ie = NULL, *bssid; |
3649 | int err, ie_len = 0; | 3656 | int err, ie_len = 0; |
3650 | u16 reason_code; | 3657 | u16 reason_code; |
3658 | bool local_state_change; | ||
3651 | 3659 | ||
3652 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) | 3660 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) |
3653 | return -EINVAL; | 3661 | return -EINVAL; |
@@ -3693,7 +3701,10 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info) | |||
3693 | ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); | 3701 | ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); |
3694 | } | 3702 | } |
3695 | 3703 | ||
3696 | err = cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code); | 3704 | local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; |
3705 | |||
3706 | err = cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code, | ||
3707 | local_state_change); | ||
3697 | 3708 | ||
3698 | out: | 3709 | out: |
3699 | cfg80211_unlock_rdev(rdev); | 3710 | cfg80211_unlock_rdev(rdev); |
@@ -3710,6 +3721,7 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) | |||
3710 | const u8 *ie = NULL, *bssid; | 3721 | const u8 *ie = NULL, *bssid; |
3711 | int err, ie_len = 0; | 3722 | int err, ie_len = 0; |
3712 | u16 reason_code; | 3723 | u16 reason_code; |
3724 | bool local_state_change; | ||
3713 | 3725 | ||
3714 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) | 3726 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) |
3715 | return -EINVAL; | 3727 | return -EINVAL; |
@@ -3755,7 +3767,10 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) | |||
3755 | ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); | 3767 | ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); |
3756 | } | 3768 | } |
3757 | 3769 | ||
3758 | err = cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code); | 3770 | local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; |
3771 | |||
3772 | err = cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code, | ||
3773 | local_state_change); | ||
3759 | 3774 | ||
3760 | out: | 3775 | out: |
3761 | cfg80211_unlock_rdev(rdev); | 3776 | cfg80211_unlock_rdev(rdev); |
@@ -4778,6 +4793,84 @@ unlock_rtnl: | |||
4778 | return err; | 4793 | return err; |
4779 | } | 4794 | } |
4780 | 4795 | ||
4796 | static struct nla_policy | ||
4797 | nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] __read_mostly = { | ||
4798 | [NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 }, | ||
4799 | [NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U32 }, | ||
4800 | [NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 }, | ||
4801 | }; | ||
4802 | |||
4803 | static int nl80211_set_cqm_rssi(struct genl_info *info, | ||
4804 | s32 threshold, u32 hysteresis) | ||
4805 | { | ||
4806 | struct cfg80211_registered_device *rdev; | ||
4807 | struct wireless_dev *wdev; | ||
4808 | struct net_device *dev; | ||
4809 | int err; | ||
4810 | |||
4811 | if (threshold > 0) | ||
4812 | return -EINVAL; | ||
4813 | |||
4814 | rtnl_lock(); | ||
4815 | |||
4816 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
4817 | if (err) | ||
4818 | goto unlock_rdev; | ||
4819 | |||
4820 | wdev = dev->ieee80211_ptr; | ||
4821 | |||
4822 | if (!rdev->ops->set_cqm_rssi_config) { | ||
4823 | err = -EOPNOTSUPP; | ||
4824 | goto unlock_rdev; | ||
4825 | } | ||
4826 | |||
4827 | if (wdev->iftype != NL80211_IFTYPE_STATION) { | ||
4828 | err = -EOPNOTSUPP; | ||
4829 | goto unlock_rdev; | ||
4830 | } | ||
4831 | |||
4832 | err = rdev->ops->set_cqm_rssi_config(wdev->wiphy, dev, | ||
4833 | threshold, hysteresis); | ||
4834 | |||
4835 | unlock_rdev: | ||
4836 | cfg80211_unlock_rdev(rdev); | ||
4837 | dev_put(dev); | ||
4838 | rtnl_unlock(); | ||
4839 | |||
4840 | return err; | ||
4841 | } | ||
4842 | |||
4843 | static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info) | ||
4844 | { | ||
4845 | struct nlattr *attrs[NL80211_ATTR_CQM_MAX + 1]; | ||
4846 | struct nlattr *cqm; | ||
4847 | int err; | ||
4848 | |||
4849 | cqm = info->attrs[NL80211_ATTR_CQM]; | ||
4850 | if (!cqm) { | ||
4851 | err = -EINVAL; | ||
4852 | goto out; | ||
4853 | } | ||
4854 | |||
4855 | err = nla_parse_nested(attrs, NL80211_ATTR_CQM_MAX, cqm, | ||
4856 | nl80211_attr_cqm_policy); | ||
4857 | if (err) | ||
4858 | goto out; | ||
4859 | |||
4860 | if (attrs[NL80211_ATTR_CQM_RSSI_THOLD] && | ||
4861 | attrs[NL80211_ATTR_CQM_RSSI_HYST]) { | ||
4862 | s32 threshold; | ||
4863 | u32 hysteresis; | ||
4864 | threshold = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_THOLD]); | ||
4865 | hysteresis = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_HYST]); | ||
4866 | err = nl80211_set_cqm_rssi(info, threshold, hysteresis); | ||
4867 | } else | ||
4868 | err = -EINVAL; | ||
4869 | |||
4870 | out: | ||
4871 | return err; | ||
4872 | } | ||
4873 | |||
4781 | static struct genl_ops nl80211_ops[] = { | 4874 | static struct genl_ops nl80211_ops[] = { |
4782 | { | 4875 | { |
4783 | .cmd = NL80211_CMD_GET_WIPHY, | 4876 | .cmd = NL80211_CMD_GET_WIPHY, |
@@ -5082,6 +5175,12 @@ static struct genl_ops nl80211_ops[] = { | |||
5082 | .policy = nl80211_policy, | 5175 | .policy = nl80211_policy, |
5083 | /* can be retrieved by unprivileged users */ | 5176 | /* can be retrieved by unprivileged users */ |
5084 | }, | 5177 | }, |
5178 | { | ||
5179 | .cmd = NL80211_CMD_SET_CQM, | ||
5180 | .doit = nl80211_set_cqm, | ||
5181 | .policy = nl80211_policy, | ||
5182 | .flags = GENL_ADMIN_PERM, | ||
5183 | }, | ||
5085 | }; | 5184 | }; |
5086 | 5185 | ||
5087 | static struct genl_multicast_group nl80211_mlme_mcgrp = { | 5186 | static struct genl_multicast_group nl80211_mlme_mcgrp = { |
@@ -5832,6 +5931,52 @@ void nl80211_send_action_tx_status(struct cfg80211_registered_device *rdev, | |||
5832 | nlmsg_free(msg); | 5931 | nlmsg_free(msg); |
5833 | } | 5932 | } |
5834 | 5933 | ||
5934 | void | ||
5935 | nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev, | ||
5936 | struct net_device *netdev, | ||
5937 | enum nl80211_cqm_rssi_threshold_event rssi_event, | ||
5938 | gfp_t gfp) | ||
5939 | { | ||
5940 | struct sk_buff *msg; | ||
5941 | struct nlattr *pinfoattr; | ||
5942 | void *hdr; | ||
5943 | |||
5944 | msg = nlmsg_new(NLMSG_GOODSIZE, gfp); | ||
5945 | if (!msg) | ||
5946 | return; | ||
5947 | |||
5948 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NOTIFY_CQM); | ||
5949 | if (!hdr) { | ||
5950 | nlmsg_free(msg); | ||
5951 | return; | ||
5952 | } | ||
5953 | |||
5954 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); | ||
5955 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); | ||
5956 | |||
5957 | pinfoattr = nla_nest_start(msg, NL80211_ATTR_CQM); | ||
5958 | if (!pinfoattr) | ||
5959 | goto nla_put_failure; | ||
5960 | |||
5961 | NLA_PUT_U32(msg, NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT, | ||
5962 | rssi_event); | ||
5963 | |||
5964 | nla_nest_end(msg, pinfoattr); | ||
5965 | |||
5966 | if (genlmsg_end(msg, hdr) < 0) { | ||
5967 | nlmsg_free(msg); | ||
5968 | return; | ||
5969 | } | ||
5970 | |||
5971 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | ||
5972 | nl80211_mlme_mcgrp.id, gfp); | ||
5973 | return; | ||
5974 | |||
5975 | nla_put_failure: | ||
5976 | genlmsg_cancel(msg, hdr); | ||
5977 | nlmsg_free(msg); | ||
5978 | } | ||
5979 | |||
5835 | static int nl80211_netlink_notify(struct notifier_block * nb, | 5980 | static int nl80211_netlink_notify(struct notifier_block * nb, |
5836 | unsigned long state, | 5981 | unsigned long state, |
5837 | void *_notify) | 5982 | void *_notify) |
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index 4ca511102c6c..2ad7fbc7d9f1 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h | |||
@@ -82,4 +82,10 @@ void nl80211_send_action_tx_status(struct cfg80211_registered_device *rdev, | |||
82 | const u8 *buf, size_t len, bool ack, | 82 | const u8 *buf, size_t len, bool ack, |
83 | gfp_t gfp); | 83 | gfp_t gfp); |
84 | 84 | ||
85 | void | ||
86 | nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev, | ||
87 | struct net_device *netdev, | ||
88 | enum nl80211_cqm_rssi_threshold_event rssi_event, | ||
89 | gfp_t gfp); | ||
90 | |||
85 | #endif /* __NET_WIRELESS_NL80211_H */ | 91 | #endif /* __NET_WIRELESS_NL80211_H */ |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 81fcafc60150..496348c48506 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -2355,10 +2355,10 @@ static void print_regdomain(const struct ieee80211_regdomain *rd) | |||
2355 | rdev->country_ie_alpha2[1]); | 2355 | rdev->country_ie_alpha2[1]); |
2356 | } else | 2356 | } else |
2357 | printk(KERN_INFO "cfg80211: Current regulatory " | 2357 | printk(KERN_INFO "cfg80211: Current regulatory " |
2358 | "domain intersected: \n"); | 2358 | "domain intersected:\n"); |
2359 | } else | 2359 | } else |
2360 | printk(KERN_INFO "cfg80211: Current regulatory " | 2360 | printk(KERN_INFO "cfg80211: Current regulatory " |
2361 | "domain intersected: \n"); | 2361 | "domain intersected:\n"); |
2362 | } else if (is_world_regdom(rd->alpha2)) | 2362 | } else if (is_world_regdom(rd->alpha2)) |
2363 | printk(KERN_INFO "cfg80211: World regulatory " | 2363 | printk(KERN_INFO "cfg80211: World regulatory " |
2364 | "domain updated:\n"); | 2364 | "domain updated:\n"); |
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 17fde0da1b08..17465777eb47 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
@@ -170,7 +170,7 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev) | |||
170 | params->ssid, params->ssid_len, | 170 | params->ssid, params->ssid_len, |
171 | NULL, 0, | 171 | NULL, 0, |
172 | params->key, params->key_len, | 172 | params->key, params->key_len, |
173 | params->key_idx); | 173 | params->key_idx, false); |
174 | case CFG80211_CONN_ASSOCIATE_NEXT: | 174 | case CFG80211_CONN_ASSOCIATE_NEXT: |
175 | BUG_ON(!rdev->ops->assoc); | 175 | BUG_ON(!rdev->ops->assoc); |
176 | wdev->conn->state = CFG80211_CONN_ASSOCIATING; | 176 | wdev->conn->state = CFG80211_CONN_ASSOCIATING; |
@@ -185,12 +185,13 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev) | |||
185 | if (err) | 185 | if (err) |
186 | __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, | 186 | __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, |
187 | NULL, 0, | 187 | NULL, 0, |
188 | WLAN_REASON_DEAUTH_LEAVING); | 188 | WLAN_REASON_DEAUTH_LEAVING, |
189 | false); | ||
189 | return err; | 190 | return err; |
190 | case CFG80211_CONN_DEAUTH_ASSOC_FAIL: | 191 | case CFG80211_CONN_DEAUTH_ASSOC_FAIL: |
191 | __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, | 192 | __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, |
192 | NULL, 0, | 193 | NULL, 0, |
193 | WLAN_REASON_DEAUTH_LEAVING); | 194 | WLAN_REASON_DEAUTH_LEAVING, false); |
194 | /* return an error so that we call __cfg80211_connect_result() */ | 195 | /* return an error so that we call __cfg80211_connect_result() */ |
195 | return -EINVAL; | 196 | return -EINVAL; |
196 | default: | 197 | default: |
@@ -675,7 +676,8 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, | |||
675 | continue; | 676 | continue; |
676 | bssid = wdev->auth_bsses[i]->pub.bssid; | 677 | bssid = wdev->auth_bsses[i]->pub.bssid; |
677 | ret = __cfg80211_mlme_deauth(rdev, dev, bssid, NULL, 0, | 678 | ret = __cfg80211_mlme_deauth(rdev, dev, bssid, NULL, 0, |
678 | WLAN_REASON_DEAUTH_LEAVING); | 679 | WLAN_REASON_DEAUTH_LEAVING, |
680 | false); | ||
679 | WARN(ret, "deauth failed: %d\n", ret); | 681 | WARN(ret, "deauth failed: %d\n", ret); |
680 | } | 682 | } |
681 | } | 683 | } |
@@ -934,7 +936,7 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev, | |||
934 | /* wdev->conn->params.bssid must be set if > SCANNING */ | 936 | /* wdev->conn->params.bssid must be set if > SCANNING */ |
935 | err = __cfg80211_mlme_deauth(rdev, dev, | 937 | err = __cfg80211_mlme_deauth(rdev, dev, |
936 | wdev->conn->params.bssid, | 938 | wdev->conn->params.bssid, |
937 | NULL, 0, reason); | 939 | NULL, 0, reason, false); |
938 | if (err) | 940 | if (err) |
939 | return err; | 941 | return err; |
940 | } else { | 942 | } else { |
@@ -990,7 +992,8 @@ void cfg80211_sme_disassoc(struct net_device *dev, int idx) | |||
990 | 992 | ||
991 | memcpy(bssid, wdev->auth_bsses[idx]->pub.bssid, ETH_ALEN); | 993 | memcpy(bssid, wdev->auth_bsses[idx]->pub.bssid, ETH_ALEN); |
992 | if (__cfg80211_mlme_deauth(rdev, dev, bssid, | 994 | if (__cfg80211_mlme_deauth(rdev, dev, bssid, |
993 | NULL, 0, WLAN_REASON_DEAUTH_LEAVING)) { | 995 | NULL, 0, WLAN_REASON_DEAUTH_LEAVING, |
996 | false)) { | ||
994 | /* whatever -- assume gone anyway */ | 997 | /* whatever -- assume gone anyway */ |
995 | cfg80211_unhold_bss(wdev->auth_bsses[idx]); | 998 | cfg80211_unhold_bss(wdev->auth_bsses[idx]); |
996 | cfg80211_put_bss(&wdev->auth_bsses[idx]->pub); | 999 | cfg80211_put_bss(&wdev->auth_bsses[idx]->pub); |
diff --git a/net/wireless/util.c b/net/wireless/util.c index be2ab8c59e3a..7acb81b9675d 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -330,11 +330,18 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, | |||
330 | if (iftype == NL80211_IFTYPE_MESH_POINT) { | 330 | if (iftype == NL80211_IFTYPE_MESH_POINT) { |
331 | struct ieee80211s_hdr *meshdr = | 331 | struct ieee80211s_hdr *meshdr = |
332 | (struct ieee80211s_hdr *) (skb->data + hdrlen); | 332 | (struct ieee80211s_hdr *) (skb->data + hdrlen); |
333 | hdrlen += ieee80211_get_mesh_hdrlen(meshdr); | 333 | /* make sure meshdr->flags is on the linear part */ |
334 | if (!pskb_may_pull(skb, hdrlen + 1)) | ||
335 | return -1; | ||
334 | if (meshdr->flags & MESH_FLAGS_AE_A5_A6) { | 336 | if (meshdr->flags & MESH_FLAGS_AE_A5_A6) { |
335 | memcpy(dst, meshdr->eaddr1, ETH_ALEN); | 337 | skb_copy_bits(skb, hdrlen + |
336 | memcpy(src, meshdr->eaddr2, ETH_ALEN); | 338 | offsetof(struct ieee80211s_hdr, eaddr1), |
339 | dst, ETH_ALEN); | ||
340 | skb_copy_bits(skb, hdrlen + | ||
341 | offsetof(struct ieee80211s_hdr, eaddr2), | ||
342 | src, ETH_ALEN); | ||
337 | } | 343 | } |
344 | hdrlen += ieee80211_get_mesh_hdrlen(meshdr); | ||
338 | } | 345 | } |
339 | break; | 346 | break; |
340 | case cpu_to_le16(IEEE80211_FCTL_FROMDS): | 347 | case cpu_to_le16(IEEE80211_FCTL_FROMDS): |
@@ -346,9 +353,14 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, | |||
346 | if (iftype == NL80211_IFTYPE_MESH_POINT) { | 353 | if (iftype == NL80211_IFTYPE_MESH_POINT) { |
347 | struct ieee80211s_hdr *meshdr = | 354 | struct ieee80211s_hdr *meshdr = |
348 | (struct ieee80211s_hdr *) (skb->data + hdrlen); | 355 | (struct ieee80211s_hdr *) (skb->data + hdrlen); |
349 | hdrlen += ieee80211_get_mesh_hdrlen(meshdr); | 356 | /* make sure meshdr->flags is on the linear part */ |
357 | if (!pskb_may_pull(skb, hdrlen + 1)) | ||
358 | return -1; | ||
350 | if (meshdr->flags & MESH_FLAGS_AE_A4) | 359 | if (meshdr->flags & MESH_FLAGS_AE_A4) |
351 | memcpy(src, meshdr->eaddr1, ETH_ALEN); | 360 | skb_copy_bits(skb, hdrlen + |
361 | offsetof(struct ieee80211s_hdr, eaddr1), | ||
362 | src, ETH_ALEN); | ||
363 | hdrlen += ieee80211_get_mesh_hdrlen(meshdr); | ||
352 | } | 364 | } |
353 | break; | 365 | break; |
354 | case cpu_to_le16(0): | 366 | case cpu_to_le16(0): |
@@ -357,7 +369,7 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, | |||
357 | break; | 369 | break; |
358 | } | 370 | } |
359 | 371 | ||
360 | if (unlikely(skb->len - hdrlen < 8)) | 372 | if (!pskb_may_pull(skb, hdrlen + 8)) |
361 | return -1; | 373 | return -1; |
362 | 374 | ||
363 | payload = skb->data + hdrlen; | 375 | payload = skb->data + hdrlen; |
diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c index 5e1656bdf23b..bfcbeee23f9c 100644 --- a/net/wireless/wext-core.c +++ b/net/wireless/wext-core.c | |||
@@ -28,226 +28,226 @@ typedef int (*wext_ioctl_func)(struct net_device *, struct iwreq *, | |||
28 | * know about. | 28 | * know about. |
29 | */ | 29 | */ |
30 | static const struct iw_ioctl_description standard_ioctl[] = { | 30 | static const struct iw_ioctl_description standard_ioctl[] = { |
31 | [SIOCSIWCOMMIT - SIOCIWFIRST] = { | 31 | [IW_IOCTL_IDX(SIOCSIWCOMMIT)] = { |
32 | .header_type = IW_HEADER_TYPE_NULL, | 32 | .header_type = IW_HEADER_TYPE_NULL, |
33 | }, | 33 | }, |
34 | [SIOCGIWNAME - SIOCIWFIRST] = { | 34 | [IW_IOCTL_IDX(SIOCGIWNAME)] = { |
35 | .header_type = IW_HEADER_TYPE_CHAR, | 35 | .header_type = IW_HEADER_TYPE_CHAR, |
36 | .flags = IW_DESCR_FLAG_DUMP, | 36 | .flags = IW_DESCR_FLAG_DUMP, |
37 | }, | 37 | }, |
38 | [SIOCSIWNWID - SIOCIWFIRST] = { | 38 | [IW_IOCTL_IDX(SIOCSIWNWID)] = { |
39 | .header_type = IW_HEADER_TYPE_PARAM, | 39 | .header_type = IW_HEADER_TYPE_PARAM, |
40 | .flags = IW_DESCR_FLAG_EVENT, | 40 | .flags = IW_DESCR_FLAG_EVENT, |
41 | }, | 41 | }, |
42 | [SIOCGIWNWID - SIOCIWFIRST] = { | 42 | [IW_IOCTL_IDX(SIOCGIWNWID)] = { |
43 | .header_type = IW_HEADER_TYPE_PARAM, | 43 | .header_type = IW_HEADER_TYPE_PARAM, |
44 | .flags = IW_DESCR_FLAG_DUMP, | 44 | .flags = IW_DESCR_FLAG_DUMP, |
45 | }, | 45 | }, |
46 | [SIOCSIWFREQ - SIOCIWFIRST] = { | 46 | [IW_IOCTL_IDX(SIOCSIWFREQ)] = { |
47 | .header_type = IW_HEADER_TYPE_FREQ, | 47 | .header_type = IW_HEADER_TYPE_FREQ, |
48 | .flags = IW_DESCR_FLAG_EVENT, | 48 | .flags = IW_DESCR_FLAG_EVENT, |
49 | }, | 49 | }, |
50 | [SIOCGIWFREQ - SIOCIWFIRST] = { | 50 | [IW_IOCTL_IDX(SIOCGIWFREQ)] = { |
51 | .header_type = IW_HEADER_TYPE_FREQ, | 51 | .header_type = IW_HEADER_TYPE_FREQ, |
52 | .flags = IW_DESCR_FLAG_DUMP, | 52 | .flags = IW_DESCR_FLAG_DUMP, |
53 | }, | 53 | }, |
54 | [SIOCSIWMODE - SIOCIWFIRST] = { | 54 | [IW_IOCTL_IDX(SIOCSIWMODE)] = { |
55 | .header_type = IW_HEADER_TYPE_UINT, | 55 | .header_type = IW_HEADER_TYPE_UINT, |
56 | .flags = IW_DESCR_FLAG_EVENT, | 56 | .flags = IW_DESCR_FLAG_EVENT, |
57 | }, | 57 | }, |
58 | [SIOCGIWMODE - SIOCIWFIRST] = { | 58 | [IW_IOCTL_IDX(SIOCGIWMODE)] = { |
59 | .header_type = IW_HEADER_TYPE_UINT, | 59 | .header_type = IW_HEADER_TYPE_UINT, |
60 | .flags = IW_DESCR_FLAG_DUMP, | 60 | .flags = IW_DESCR_FLAG_DUMP, |
61 | }, | 61 | }, |
62 | [SIOCSIWSENS - SIOCIWFIRST] = { | 62 | [IW_IOCTL_IDX(SIOCSIWSENS)] = { |
63 | .header_type = IW_HEADER_TYPE_PARAM, | 63 | .header_type = IW_HEADER_TYPE_PARAM, |
64 | }, | 64 | }, |
65 | [SIOCGIWSENS - SIOCIWFIRST] = { | 65 | [IW_IOCTL_IDX(SIOCGIWSENS)] = { |
66 | .header_type = IW_HEADER_TYPE_PARAM, | 66 | .header_type = IW_HEADER_TYPE_PARAM, |
67 | }, | 67 | }, |
68 | [SIOCSIWRANGE - SIOCIWFIRST] = { | 68 | [IW_IOCTL_IDX(SIOCSIWRANGE)] = { |
69 | .header_type = IW_HEADER_TYPE_NULL, | 69 | .header_type = IW_HEADER_TYPE_NULL, |
70 | }, | 70 | }, |
71 | [SIOCGIWRANGE - SIOCIWFIRST] = { | 71 | [IW_IOCTL_IDX(SIOCGIWRANGE)] = { |
72 | .header_type = IW_HEADER_TYPE_POINT, | 72 | .header_type = IW_HEADER_TYPE_POINT, |
73 | .token_size = 1, | 73 | .token_size = 1, |
74 | .max_tokens = sizeof(struct iw_range), | 74 | .max_tokens = sizeof(struct iw_range), |
75 | .flags = IW_DESCR_FLAG_DUMP, | 75 | .flags = IW_DESCR_FLAG_DUMP, |
76 | }, | 76 | }, |
77 | [SIOCSIWPRIV - SIOCIWFIRST] = { | 77 | [IW_IOCTL_IDX(SIOCSIWPRIV)] = { |
78 | .header_type = IW_HEADER_TYPE_NULL, | 78 | .header_type = IW_HEADER_TYPE_NULL, |
79 | }, | 79 | }, |
80 | [SIOCGIWPRIV - SIOCIWFIRST] = { /* (handled directly by us) */ | 80 | [IW_IOCTL_IDX(SIOCGIWPRIV)] = { /* (handled directly by us) */ |
81 | .header_type = IW_HEADER_TYPE_POINT, | 81 | .header_type = IW_HEADER_TYPE_POINT, |
82 | .token_size = sizeof(struct iw_priv_args), | 82 | .token_size = sizeof(struct iw_priv_args), |
83 | .max_tokens = 16, | 83 | .max_tokens = 16, |
84 | .flags = IW_DESCR_FLAG_NOMAX, | 84 | .flags = IW_DESCR_FLAG_NOMAX, |
85 | }, | 85 | }, |
86 | [SIOCSIWSTATS - SIOCIWFIRST] = { | 86 | [IW_IOCTL_IDX(SIOCSIWSTATS)] = { |
87 | .header_type = IW_HEADER_TYPE_NULL, | 87 | .header_type = IW_HEADER_TYPE_NULL, |
88 | }, | 88 | }, |
89 | [SIOCGIWSTATS - SIOCIWFIRST] = { /* (handled directly by us) */ | 89 | [IW_IOCTL_IDX(SIOCGIWSTATS)] = { /* (handled directly by us) */ |
90 | .header_type = IW_HEADER_TYPE_POINT, | 90 | .header_type = IW_HEADER_TYPE_POINT, |
91 | .token_size = 1, | 91 | .token_size = 1, |
92 | .max_tokens = sizeof(struct iw_statistics), | 92 | .max_tokens = sizeof(struct iw_statistics), |
93 | .flags = IW_DESCR_FLAG_DUMP, | 93 | .flags = IW_DESCR_FLAG_DUMP, |
94 | }, | 94 | }, |
95 | [SIOCSIWSPY - SIOCIWFIRST] = { | 95 | [IW_IOCTL_IDX(SIOCSIWSPY)] = { |
96 | .header_type = IW_HEADER_TYPE_POINT, | 96 | .header_type = IW_HEADER_TYPE_POINT, |
97 | .token_size = sizeof(struct sockaddr), | 97 | .token_size = sizeof(struct sockaddr), |
98 | .max_tokens = IW_MAX_SPY, | 98 | .max_tokens = IW_MAX_SPY, |
99 | }, | 99 | }, |
100 | [SIOCGIWSPY - SIOCIWFIRST] = { | 100 | [IW_IOCTL_IDX(SIOCGIWSPY)] = { |
101 | .header_type = IW_HEADER_TYPE_POINT, | 101 | .header_type = IW_HEADER_TYPE_POINT, |
102 | .token_size = sizeof(struct sockaddr) + | 102 | .token_size = sizeof(struct sockaddr) + |
103 | sizeof(struct iw_quality), | 103 | sizeof(struct iw_quality), |
104 | .max_tokens = IW_MAX_SPY, | 104 | .max_tokens = IW_MAX_SPY, |
105 | }, | 105 | }, |
106 | [SIOCSIWTHRSPY - SIOCIWFIRST] = { | 106 | [IW_IOCTL_IDX(SIOCSIWTHRSPY)] = { |
107 | .header_type = IW_HEADER_TYPE_POINT, | 107 | .header_type = IW_HEADER_TYPE_POINT, |
108 | .token_size = sizeof(struct iw_thrspy), | 108 | .token_size = sizeof(struct iw_thrspy), |
109 | .min_tokens = 1, | 109 | .min_tokens = 1, |
110 | .max_tokens = 1, | 110 | .max_tokens = 1, |
111 | }, | 111 | }, |
112 | [SIOCGIWTHRSPY - SIOCIWFIRST] = { | 112 | [IW_IOCTL_IDX(SIOCGIWTHRSPY)] = { |
113 | .header_type = IW_HEADER_TYPE_POINT, | 113 | .header_type = IW_HEADER_TYPE_POINT, |
114 | .token_size = sizeof(struct iw_thrspy), | 114 | .token_size = sizeof(struct iw_thrspy), |
115 | .min_tokens = 1, | 115 | .min_tokens = 1, |
116 | .max_tokens = 1, | 116 | .max_tokens = 1, |
117 | }, | 117 | }, |
118 | [SIOCSIWAP - SIOCIWFIRST] = { | 118 | [IW_IOCTL_IDX(SIOCSIWAP)] = { |
119 | .header_type = IW_HEADER_TYPE_ADDR, | 119 | .header_type = IW_HEADER_TYPE_ADDR, |
120 | }, | 120 | }, |
121 | [SIOCGIWAP - SIOCIWFIRST] = { | 121 | [IW_IOCTL_IDX(SIOCGIWAP)] = { |
122 | .header_type = IW_HEADER_TYPE_ADDR, | 122 | .header_type = IW_HEADER_TYPE_ADDR, |
123 | .flags = IW_DESCR_FLAG_DUMP, | 123 | .flags = IW_DESCR_FLAG_DUMP, |
124 | }, | 124 | }, |
125 | [SIOCSIWMLME - SIOCIWFIRST] = { | 125 | [IW_IOCTL_IDX(SIOCSIWMLME)] = { |
126 | .header_type = IW_HEADER_TYPE_POINT, | 126 | .header_type = IW_HEADER_TYPE_POINT, |
127 | .token_size = 1, | 127 | .token_size = 1, |
128 | .min_tokens = sizeof(struct iw_mlme), | 128 | .min_tokens = sizeof(struct iw_mlme), |
129 | .max_tokens = sizeof(struct iw_mlme), | 129 | .max_tokens = sizeof(struct iw_mlme), |
130 | }, | 130 | }, |
131 | [SIOCGIWAPLIST - SIOCIWFIRST] = { | 131 | [IW_IOCTL_IDX(SIOCGIWAPLIST)] = { |
132 | .header_type = IW_HEADER_TYPE_POINT, | 132 | .header_type = IW_HEADER_TYPE_POINT, |
133 | .token_size = sizeof(struct sockaddr) + | 133 | .token_size = sizeof(struct sockaddr) + |
134 | sizeof(struct iw_quality), | 134 | sizeof(struct iw_quality), |
135 | .max_tokens = IW_MAX_AP, | 135 | .max_tokens = IW_MAX_AP, |
136 | .flags = IW_DESCR_FLAG_NOMAX, | 136 | .flags = IW_DESCR_FLAG_NOMAX, |
137 | }, | 137 | }, |
138 | [SIOCSIWSCAN - SIOCIWFIRST] = { | 138 | [IW_IOCTL_IDX(SIOCSIWSCAN)] = { |
139 | .header_type = IW_HEADER_TYPE_POINT, | 139 | .header_type = IW_HEADER_TYPE_POINT, |
140 | .token_size = 1, | 140 | .token_size = 1, |
141 | .min_tokens = 0, | 141 | .min_tokens = 0, |
142 | .max_tokens = sizeof(struct iw_scan_req), | 142 | .max_tokens = sizeof(struct iw_scan_req), |
143 | }, | 143 | }, |
144 | [SIOCGIWSCAN - SIOCIWFIRST] = { | 144 | [IW_IOCTL_IDX(SIOCGIWSCAN)] = { |
145 | .header_type = IW_HEADER_TYPE_POINT, | 145 | .header_type = IW_HEADER_TYPE_POINT, |
146 | .token_size = 1, | 146 | .token_size = 1, |
147 | .max_tokens = IW_SCAN_MAX_DATA, | 147 | .max_tokens = IW_SCAN_MAX_DATA, |
148 | .flags = IW_DESCR_FLAG_NOMAX, | 148 | .flags = IW_DESCR_FLAG_NOMAX, |
149 | }, | 149 | }, |
150 | [SIOCSIWESSID - SIOCIWFIRST] = { | 150 | [IW_IOCTL_IDX(SIOCSIWESSID)] = { |
151 | .header_type = IW_HEADER_TYPE_POINT, | 151 | .header_type = IW_HEADER_TYPE_POINT, |
152 | .token_size = 1, | 152 | .token_size = 1, |
153 | .max_tokens = IW_ESSID_MAX_SIZE, | 153 | .max_tokens = IW_ESSID_MAX_SIZE, |
154 | .flags = IW_DESCR_FLAG_EVENT, | 154 | .flags = IW_DESCR_FLAG_EVENT, |
155 | }, | 155 | }, |
156 | [SIOCGIWESSID - SIOCIWFIRST] = { | 156 | [IW_IOCTL_IDX(SIOCGIWESSID)] = { |
157 | .header_type = IW_HEADER_TYPE_POINT, | 157 | .header_type = IW_HEADER_TYPE_POINT, |
158 | .token_size = 1, | 158 | .token_size = 1, |
159 | .max_tokens = IW_ESSID_MAX_SIZE, | 159 | .max_tokens = IW_ESSID_MAX_SIZE, |
160 | .flags = IW_DESCR_FLAG_DUMP, | 160 | .flags = IW_DESCR_FLAG_DUMP, |
161 | }, | 161 | }, |
162 | [SIOCSIWNICKN - SIOCIWFIRST] = { | 162 | [IW_IOCTL_IDX(SIOCSIWNICKN)] = { |
163 | .header_type = IW_HEADER_TYPE_POINT, | 163 | .header_type = IW_HEADER_TYPE_POINT, |
164 | .token_size = 1, | 164 | .token_size = 1, |
165 | .max_tokens = IW_ESSID_MAX_SIZE, | 165 | .max_tokens = IW_ESSID_MAX_SIZE, |
166 | }, | 166 | }, |
167 | [SIOCGIWNICKN - SIOCIWFIRST] = { | 167 | [IW_IOCTL_IDX(SIOCGIWNICKN)] = { |
168 | .header_type = IW_HEADER_TYPE_POINT, | 168 | .header_type = IW_HEADER_TYPE_POINT, |
169 | .token_size = 1, | 169 | .token_size = 1, |
170 | .max_tokens = IW_ESSID_MAX_SIZE, | 170 | .max_tokens = IW_ESSID_MAX_SIZE, |
171 | }, | 171 | }, |
172 | [SIOCSIWRATE - SIOCIWFIRST] = { | 172 | [IW_IOCTL_IDX(SIOCSIWRATE)] = { |
173 | .header_type = IW_HEADER_TYPE_PARAM, | 173 | .header_type = IW_HEADER_TYPE_PARAM, |
174 | }, | 174 | }, |
175 | [SIOCGIWRATE - SIOCIWFIRST] = { | 175 | [IW_IOCTL_IDX(SIOCGIWRATE)] = { |
176 | .header_type = IW_HEADER_TYPE_PARAM, | 176 | .header_type = IW_HEADER_TYPE_PARAM, |
177 | }, | 177 | }, |
178 | [SIOCSIWRTS - SIOCIWFIRST] = { | 178 | [IW_IOCTL_IDX(SIOCSIWRTS)] = { |
179 | .header_type = IW_HEADER_TYPE_PARAM, | 179 | .header_type = IW_HEADER_TYPE_PARAM, |
180 | }, | 180 | }, |
181 | [SIOCGIWRTS - SIOCIWFIRST] = { | 181 | [IW_IOCTL_IDX(SIOCGIWRTS)] = { |
182 | .header_type = IW_HEADER_TYPE_PARAM, | 182 | .header_type = IW_HEADER_TYPE_PARAM, |
183 | }, | 183 | }, |
184 | [SIOCSIWFRAG - SIOCIWFIRST] = { | 184 | [IW_IOCTL_IDX(SIOCSIWFRAG)] = { |
185 | .header_type = IW_HEADER_TYPE_PARAM, | 185 | .header_type = IW_HEADER_TYPE_PARAM, |
186 | }, | 186 | }, |
187 | [SIOCGIWFRAG - SIOCIWFIRST] = { | 187 | [IW_IOCTL_IDX(SIOCGIWFRAG)] = { |
188 | .header_type = IW_HEADER_TYPE_PARAM, | 188 | .header_type = IW_HEADER_TYPE_PARAM, |
189 | }, | 189 | }, |
190 | [SIOCSIWTXPOW - SIOCIWFIRST] = { | 190 | [IW_IOCTL_IDX(SIOCSIWTXPOW)] = { |
191 | .header_type = IW_HEADER_TYPE_PARAM, | 191 | .header_type = IW_HEADER_TYPE_PARAM, |
192 | }, | 192 | }, |
193 | [SIOCGIWTXPOW - SIOCIWFIRST] = { | 193 | [IW_IOCTL_IDX(SIOCGIWTXPOW)] = { |
194 | .header_type = IW_HEADER_TYPE_PARAM, | 194 | .header_type = IW_HEADER_TYPE_PARAM, |
195 | }, | 195 | }, |
196 | [SIOCSIWRETRY - SIOCIWFIRST] = { | 196 | [IW_IOCTL_IDX(SIOCSIWRETRY)] = { |
197 | .header_type = IW_HEADER_TYPE_PARAM, | 197 | .header_type = IW_HEADER_TYPE_PARAM, |
198 | }, | 198 | }, |
199 | [SIOCGIWRETRY - SIOCIWFIRST] = { | 199 | [IW_IOCTL_IDX(SIOCGIWRETRY)] = { |
200 | .header_type = IW_HEADER_TYPE_PARAM, | 200 | .header_type = IW_HEADER_TYPE_PARAM, |
201 | }, | 201 | }, |
202 | [SIOCSIWENCODE - SIOCIWFIRST] = { | 202 | [IW_IOCTL_IDX(SIOCSIWENCODE)] = { |
203 | .header_type = IW_HEADER_TYPE_POINT, | 203 | .header_type = IW_HEADER_TYPE_POINT, |
204 | .token_size = 1, | 204 | .token_size = 1, |
205 | .max_tokens = IW_ENCODING_TOKEN_MAX, | 205 | .max_tokens = IW_ENCODING_TOKEN_MAX, |
206 | .flags = IW_DESCR_FLAG_EVENT | IW_DESCR_FLAG_RESTRICT, | 206 | .flags = IW_DESCR_FLAG_EVENT | IW_DESCR_FLAG_RESTRICT, |
207 | }, | 207 | }, |
208 | [SIOCGIWENCODE - SIOCIWFIRST] = { | 208 | [IW_IOCTL_IDX(SIOCGIWENCODE)] = { |
209 | .header_type = IW_HEADER_TYPE_POINT, | 209 | .header_type = IW_HEADER_TYPE_POINT, |
210 | .token_size = 1, | 210 | .token_size = 1, |
211 | .max_tokens = IW_ENCODING_TOKEN_MAX, | 211 | .max_tokens = IW_ENCODING_TOKEN_MAX, |
212 | .flags = IW_DESCR_FLAG_DUMP | IW_DESCR_FLAG_RESTRICT, | 212 | .flags = IW_DESCR_FLAG_DUMP | IW_DESCR_FLAG_RESTRICT, |
213 | }, | 213 | }, |
214 | [SIOCSIWPOWER - SIOCIWFIRST] = { | 214 | [IW_IOCTL_IDX(SIOCSIWPOWER)] = { |
215 | .header_type = IW_HEADER_TYPE_PARAM, | 215 | .header_type = IW_HEADER_TYPE_PARAM, |
216 | }, | 216 | }, |
217 | [SIOCGIWPOWER - SIOCIWFIRST] = { | 217 | [IW_IOCTL_IDX(SIOCGIWPOWER)] = { |
218 | .header_type = IW_HEADER_TYPE_PARAM, | 218 | .header_type = IW_HEADER_TYPE_PARAM, |
219 | }, | 219 | }, |
220 | [SIOCSIWGENIE - SIOCIWFIRST] = { | 220 | [IW_IOCTL_IDX(SIOCSIWGENIE)] = { |
221 | .header_type = IW_HEADER_TYPE_POINT, | 221 | .header_type = IW_HEADER_TYPE_POINT, |
222 | .token_size = 1, | 222 | .token_size = 1, |
223 | .max_tokens = IW_GENERIC_IE_MAX, | 223 | .max_tokens = IW_GENERIC_IE_MAX, |
224 | }, | 224 | }, |
225 | [SIOCGIWGENIE - SIOCIWFIRST] = { | 225 | [IW_IOCTL_IDX(SIOCGIWGENIE)] = { |
226 | .header_type = IW_HEADER_TYPE_POINT, | 226 | .header_type = IW_HEADER_TYPE_POINT, |
227 | .token_size = 1, | 227 | .token_size = 1, |
228 | .max_tokens = IW_GENERIC_IE_MAX, | 228 | .max_tokens = IW_GENERIC_IE_MAX, |
229 | }, | 229 | }, |
230 | [SIOCSIWAUTH - SIOCIWFIRST] = { | 230 | [IW_IOCTL_IDX(SIOCSIWAUTH)] = { |
231 | .header_type = IW_HEADER_TYPE_PARAM, | 231 | .header_type = IW_HEADER_TYPE_PARAM, |
232 | }, | 232 | }, |
233 | [SIOCGIWAUTH - SIOCIWFIRST] = { | 233 | [IW_IOCTL_IDX(SIOCGIWAUTH)] = { |
234 | .header_type = IW_HEADER_TYPE_PARAM, | 234 | .header_type = IW_HEADER_TYPE_PARAM, |
235 | }, | 235 | }, |
236 | [SIOCSIWENCODEEXT - SIOCIWFIRST] = { | 236 | [IW_IOCTL_IDX(SIOCSIWENCODEEXT)] = { |
237 | .header_type = IW_HEADER_TYPE_POINT, | 237 | .header_type = IW_HEADER_TYPE_POINT, |
238 | .token_size = 1, | 238 | .token_size = 1, |
239 | .min_tokens = sizeof(struct iw_encode_ext), | 239 | .min_tokens = sizeof(struct iw_encode_ext), |
240 | .max_tokens = sizeof(struct iw_encode_ext) + | 240 | .max_tokens = sizeof(struct iw_encode_ext) + |
241 | IW_ENCODING_TOKEN_MAX, | 241 | IW_ENCODING_TOKEN_MAX, |
242 | }, | 242 | }, |
243 | [SIOCGIWENCODEEXT - SIOCIWFIRST] = { | 243 | [IW_IOCTL_IDX(SIOCGIWENCODEEXT)] = { |
244 | .header_type = IW_HEADER_TYPE_POINT, | 244 | .header_type = IW_HEADER_TYPE_POINT, |
245 | .token_size = 1, | 245 | .token_size = 1, |
246 | .min_tokens = sizeof(struct iw_encode_ext), | 246 | .min_tokens = sizeof(struct iw_encode_ext), |
247 | .max_tokens = sizeof(struct iw_encode_ext) + | 247 | .max_tokens = sizeof(struct iw_encode_ext) + |
248 | IW_ENCODING_TOKEN_MAX, | 248 | IW_ENCODING_TOKEN_MAX, |
249 | }, | 249 | }, |
250 | [SIOCSIWPMKSA - SIOCIWFIRST] = { | 250 | [IW_IOCTL_IDX(SIOCSIWPMKSA)] = { |
251 | .header_type = IW_HEADER_TYPE_POINT, | 251 | .header_type = IW_HEADER_TYPE_POINT, |
252 | .token_size = 1, | 252 | .token_size = 1, |
253 | .min_tokens = sizeof(struct iw_pmksa), | 253 | .min_tokens = sizeof(struct iw_pmksa), |
@@ -261,44 +261,44 @@ static const unsigned standard_ioctl_num = ARRAY_SIZE(standard_ioctl); | |||
261 | * we know about. | 261 | * we know about. |
262 | */ | 262 | */ |
263 | static const struct iw_ioctl_description standard_event[] = { | 263 | static const struct iw_ioctl_description standard_event[] = { |
264 | [IWEVTXDROP - IWEVFIRST] = { | 264 | [IW_EVENT_IDX(IWEVTXDROP)] = { |
265 | .header_type = IW_HEADER_TYPE_ADDR, | 265 | .header_type = IW_HEADER_TYPE_ADDR, |
266 | }, | 266 | }, |
267 | [IWEVQUAL - IWEVFIRST] = { | 267 | [IW_EVENT_IDX(IWEVQUAL)] = { |
268 | .header_type = IW_HEADER_TYPE_QUAL, | 268 | .header_type = IW_HEADER_TYPE_QUAL, |
269 | }, | 269 | }, |
270 | [IWEVCUSTOM - IWEVFIRST] = { | 270 | [IW_EVENT_IDX(IWEVCUSTOM)] = { |
271 | .header_type = IW_HEADER_TYPE_POINT, | 271 | .header_type = IW_HEADER_TYPE_POINT, |
272 | .token_size = 1, | 272 | .token_size = 1, |
273 | .max_tokens = IW_CUSTOM_MAX, | 273 | .max_tokens = IW_CUSTOM_MAX, |
274 | }, | 274 | }, |
275 | [IWEVREGISTERED - IWEVFIRST] = { | 275 | [IW_EVENT_IDX(IWEVREGISTERED)] = { |
276 | .header_type = IW_HEADER_TYPE_ADDR, | 276 | .header_type = IW_HEADER_TYPE_ADDR, |
277 | }, | 277 | }, |
278 | [IWEVEXPIRED - IWEVFIRST] = { | 278 | [IW_EVENT_IDX(IWEVEXPIRED)] = { |
279 | .header_type = IW_HEADER_TYPE_ADDR, | 279 | .header_type = IW_HEADER_TYPE_ADDR, |
280 | }, | 280 | }, |
281 | [IWEVGENIE - IWEVFIRST] = { | 281 | [IW_EVENT_IDX(IWEVGENIE)] = { |
282 | .header_type = IW_HEADER_TYPE_POINT, | 282 | .header_type = IW_HEADER_TYPE_POINT, |
283 | .token_size = 1, | 283 | .token_size = 1, |
284 | .max_tokens = IW_GENERIC_IE_MAX, | 284 | .max_tokens = IW_GENERIC_IE_MAX, |
285 | }, | 285 | }, |
286 | [IWEVMICHAELMICFAILURE - IWEVFIRST] = { | 286 | [IW_EVENT_IDX(IWEVMICHAELMICFAILURE)] = { |
287 | .header_type = IW_HEADER_TYPE_POINT, | 287 | .header_type = IW_HEADER_TYPE_POINT, |
288 | .token_size = 1, | 288 | .token_size = 1, |
289 | .max_tokens = sizeof(struct iw_michaelmicfailure), | 289 | .max_tokens = sizeof(struct iw_michaelmicfailure), |
290 | }, | 290 | }, |
291 | [IWEVASSOCREQIE - IWEVFIRST] = { | 291 | [IW_EVENT_IDX(IWEVASSOCREQIE)] = { |
292 | .header_type = IW_HEADER_TYPE_POINT, | 292 | .header_type = IW_HEADER_TYPE_POINT, |
293 | .token_size = 1, | 293 | .token_size = 1, |
294 | .max_tokens = IW_GENERIC_IE_MAX, | 294 | .max_tokens = IW_GENERIC_IE_MAX, |
295 | }, | 295 | }, |
296 | [IWEVASSOCRESPIE - IWEVFIRST] = { | 296 | [IW_EVENT_IDX(IWEVASSOCRESPIE)] = { |
297 | .header_type = IW_HEADER_TYPE_POINT, | 297 | .header_type = IW_HEADER_TYPE_POINT, |
298 | .token_size = 1, | 298 | .token_size = 1, |
299 | .max_tokens = IW_GENERIC_IE_MAX, | 299 | .max_tokens = IW_GENERIC_IE_MAX, |
300 | }, | 300 | }, |
301 | [IWEVPMKIDCAND - IWEVFIRST] = { | 301 | [IW_EVENT_IDX(IWEVPMKIDCAND)] = { |
302 | .header_type = IW_HEADER_TYPE_POINT, | 302 | .header_type = IW_HEADER_TYPE_POINT, |
303 | .token_size = 1, | 303 | .token_size = 1, |
304 | .max_tokens = sizeof(struct iw_pmkid_cand), | 304 | .max_tokens = sizeof(struct iw_pmkid_cand), |
@@ -449,11 +449,11 @@ void wireless_send_event(struct net_device * dev, | |||
449 | 449 | ||
450 | /* Get the description of the Event */ | 450 | /* Get the description of the Event */ |
451 | if (cmd <= SIOCIWLAST) { | 451 | if (cmd <= SIOCIWLAST) { |
452 | cmd_index = cmd - SIOCIWFIRST; | 452 | cmd_index = IW_IOCTL_IDX(cmd); |
453 | if (cmd_index < standard_ioctl_num) | 453 | if (cmd_index < standard_ioctl_num) |
454 | descr = &(standard_ioctl[cmd_index]); | 454 | descr = &(standard_ioctl[cmd_index]); |
455 | } else { | 455 | } else { |
456 | cmd_index = cmd - IWEVFIRST; | 456 | cmd_index = IW_EVENT_IDX(cmd); |
457 | if (cmd_index < standard_event_num) | 457 | if (cmd_index < standard_event_num) |
458 | descr = &(standard_event[cmd_index]); | 458 | descr = &(standard_event[cmd_index]); |
459 | } | 459 | } |
@@ -662,7 +662,7 @@ static iw_handler get_handler(struct net_device *dev, unsigned int cmd) | |||
662 | return NULL; | 662 | return NULL; |
663 | 663 | ||
664 | /* Try as a standard command */ | 664 | /* Try as a standard command */ |
665 | index = cmd - SIOCIWFIRST; | 665 | index = IW_IOCTL_IDX(cmd); |
666 | if (index < handlers->num_standard) | 666 | if (index < handlers->num_standard) |
667 | return handlers->standard[index]; | 667 | return handlers->standard[index]; |
668 | 668 | ||
@@ -954,9 +954,9 @@ static int ioctl_standard_call(struct net_device * dev, | |||
954 | int ret = -EINVAL; | 954 | int ret = -EINVAL; |
955 | 955 | ||
956 | /* Get the description of the IOCTL */ | 956 | /* Get the description of the IOCTL */ |
957 | if ((cmd - SIOCIWFIRST) >= standard_ioctl_num) | 957 | if (IW_IOCTL_IDX(cmd) >= standard_ioctl_num) |
958 | return -EOPNOTSUPP; | 958 | return -EOPNOTSUPP; |
959 | descr = &(standard_ioctl[cmd - SIOCIWFIRST]); | 959 | descr = &(standard_ioctl[IW_IOCTL_IDX(cmd)]); |
960 | 960 | ||
961 | /* Check if we have a pointer to user space data or not */ | 961 | /* Check if we have a pointer to user space data or not */ |
962 | if (descr->header_type != IW_HEADER_TYPE_POINT) { | 962 | if (descr->header_type != IW_HEADER_TYPE_POINT) { |
@@ -1012,7 +1012,7 @@ static int compat_standard_call(struct net_device *dev, | |||
1012 | struct iw_point iwp; | 1012 | struct iw_point iwp; |
1013 | int err; | 1013 | int err; |
1014 | 1014 | ||
1015 | descr = standard_ioctl + (cmd - SIOCIWFIRST); | 1015 | descr = standard_ioctl + IW_IOCTL_IDX(cmd); |
1016 | 1016 | ||
1017 | if (descr->header_type != IW_HEADER_TYPE_POINT) | 1017 | if (descr->header_type != IW_HEADER_TYPE_POINT) |
1018 | return ioctl_standard_call(dev, iwr, cmd, info, handler); | 1018 | return ioctl_standard_call(dev, iwr, cmd, info, handler); |