diff options
author | David S. Miller <davem@davemloft.net> | 2010-03-22 21:15:15 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-03-22 21:15:15 -0400 |
commit | 33e2bf6aa16061bae1253514e7c32af27d2b4b31 (patch) | |
tree | 652d13b4feea9a8f562186e7badae72d2e22fe1f /drivers/net/wireless/iwmc3200wifi | |
parent | e880eb6c5c9d98e389ffc0d8947f75d70785361a (diff) | |
parent | 819bfecc4fc6b6e5a793f719a45b7146ce423b79 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Conflicts:
Documentation/feature-removal-schedule.txt
drivers/net/wireless/ath/ath5k/phy.c
Diffstat (limited to 'drivers/net/wireless/iwmc3200wifi')
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/Kconfig | 9 | ||||
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/Makefile | 3 | ||||
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/cfg80211.c | 17 | ||||
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/commands.c | 14 | ||||
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/commands.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/debugfs.c | 13 | ||||
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/hal.c | 15 | ||||
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/hal.h | 5 | ||||
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/iwm.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/main.c | 9 | ||||
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/rx.c | 76 | ||||
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/trace.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/trace.h | 283 | ||||
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/tx.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/umac.h | 2 |
15 files changed, 407 insertions, 54 deletions
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 c29c994de0e2..5b75a0ddac1c 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 8456b4dbd146..ce36baf34039 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 |