aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwmc3200wifi
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2010-03-22 21:15:15 -0400
committerDavid S. Miller <davem@davemloft.net>2010-03-22 21:15:15 -0400
commit33e2bf6aa16061bae1253514e7c32af27d2b4b31 (patch)
tree652d13b4feea9a8f562186e7badae72d2e22fe1f /drivers/net/wireless/iwmc3200wifi
parente880eb6c5c9d98e389ffc0d8947f75d70785361a (diff)
parent819bfecc4fc6b6e5a793f719a45b7146ce423b79 (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/Kconfig9
-rw-r--r--drivers/net/wireless/iwmc3200wifi/Makefile3
-rw-r--r--drivers/net/wireless/iwmc3200wifi/cfg80211.c17
-rw-r--r--drivers/net/wireless/iwmc3200wifi/commands.c14
-rw-r--r--drivers/net/wireless/iwmc3200wifi/commands.h1
-rw-r--r--drivers/net/wireless/iwmc3200wifi/debugfs.c13
-rw-r--r--drivers/net/wireless/iwmc3200wifi/hal.c15
-rw-r--r--drivers/net/wireless/iwmc3200wifi/hal.h5
-rw-r--r--drivers/net/wireless/iwmc3200wifi/iwm.h3
-rw-r--r--drivers/net/wireless/iwmc3200wifi/main.c9
-rw-r--r--drivers/net/wireless/iwmc3200wifi/rx.c76
-rw-r--r--drivers/net/wireless/iwmc3200wifi/trace.c3
-rw-r--r--drivers/net/wireless/iwmc3200wifi/trace.h283
-rw-r--r--drivers/net/wireless/iwmc3200wifi/tx.c8
-rw-r--r--drivers/net/wireless/iwmc3200wifi/umac.h2
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
17config IWM_DEBUG 17config 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
34config 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
3iwmc3200wifi-objs += commands.o cfg80211.o eeprom.o 3iwmc3200wifi-objs += commands.o cfg80211.o eeprom.o
4 4
5iwmc3200wifi-$(CONFIG_IWM_DEBUG) += debugfs.o 5iwmc3200wifi-$(CONFIG_IWM_DEBUG) += debugfs.o
6iwmc3200wifi-$(CONFIG_IWM_TRACING) += trace.o
7
8CFLAGS_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,
263int iwm_cfg80211_inform_bss(struct iwm_priv *iwm) 263int 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
728int iwm_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *netdev, 728static 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
736int iwm_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *netdev, 737static 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
744int iwm_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev) 746static 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
784int iwm_invalidate_mlme_profile(struct iwm_priv *iwm) 784int __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
798int 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);
489int iwm_send_umac_config(struct iwm_priv *iwm, __le32 reset_flags); 489int iwm_send_umac_config(struct iwm_priv *iwm, __le32 reset_flags);
490int iwm_send_mlme_profile(struct iwm_priv *iwm); 490int iwm_send_mlme_profile(struct iwm_priv *iwm);
491int __iwm_invalidate_mlme_profile(struct iwm_priv *iwm);
491int iwm_invalidate_mlme_profile(struct iwm_priv *iwm); 492int iwm_invalidate_mlme_profile(struct iwm_priv *iwm);
492int iwm_send_packet(struct iwm_priv *iwm, struct sk_buff *skb, int pool_id); 493int iwm_send_packet(struct iwm_priv *iwm, struct sk_buff *skb, int pool_id);
493int iwm_set_tx_key(struct iwm_priv *iwm, u8 key_idx); 494int 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
108static int iwm_nonwifi_cmd_init(struct iwm_priv *iwm, 109static 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
207struct iwm_wifi_cmd *iwm_get_pending_wifi_cmd(struct iwm_priv *iwm, u16 seq_num) 208struct 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
220struct iwm_nonwifi_cmd * 221struct iwm_nonwifi_cmd *iwm_get_pending_nonwifi_cmd(struct iwm_priv *iwm,
221iwm_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
135struct iwm_wifi_cmd_buff { 136struct 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,
423static struct iwm_notif *iwm_notif_find(struct iwm_priv *iwm, u32 cmd, 426static 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(&notif->pending); 433 list_del(&notif->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)
342static struct iwm_rx_packet *iwm_rx_packet_get(struct iwm_priv *iwm, u16 id) 342static 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, ...) \
9static 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
20TRACE_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
58TRACE_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
101TRACE_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
154TRACE_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
181TRACE_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
216TRACE_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
250TRACE_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)
450int iwm_xmit_frame(struct sk_buff *skb, struct net_device *netdev) 451int 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