diff --git a/tracing/plugins/ath6kl.py b/tracing/plugins/ath6kl.py
new file mode 100644
index 0000000..228c736
--- /dev/null
+++ b/tracing/plugins/ath6kl.py
@@ -0,0 +1,251 @@
+#
+# Copyright (c) 2012 Qualcomm Atheros, Inc.
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+# To install the plugin:
+#
+# cp ath6kl.py ~/.trace-cmd/plugins/
+#
+# When making changes to the plugin use -V to see all python errors/warnings:
+#
+# trace-cmd report -V trace.dat
+
+import tracecmd
+import struct
+import binascii
+
+def hexdump(buf, prefix=None):
+    s = binascii.b2a_hex(buf)
+    s_len = len(s)
+    result = ""
+
+    if prefix == None:
+        prefix = ""
+
+    for i in range(s_len / 2):
+        if i % 16 == 0:
+            result = result + ("%s%04x: " % (prefix, i))
+
+        result = result + (s[2*i] + s[2*i+1] + " ")
+
+        if (i + 1) % 16 == 0:
+            result = result + "\n"
+
+    # FIXME: if len(s) % 16 == 0 there's an extra \n in the end
+
+    return result
+
+def wmi_event_bssinfo(pevent, trace_seq, event, buf):
+    hdr = struct.unpack("<HBB6BH", buf[0:12])
+    channel = hdr[0]
+    frame_type = hdr[1]
+    snr = hdr[2]
+    bssid = hdr[3]
+    ie_mask = hdr[4]
+
+    trace_seq.puts("\t\t\tWMI_BSSINFO_EVENTID channel %d frame_type 0x%x snr %d ie_mask 0x%x\n" %
+                   (channel, frame_type, snr, ie_mask))
+
+wmi_event_handlers = [
+    [0x1004, wmi_event_bssinfo ],
+    ]
+
+def wmi_cmd_set_bss_filter_handler(pevent, trace_seq, event, buf):
+    hdr = struct.unpack("<BBHI", buf[0:8])
+    bss_filter = hdr[0]
+    ie_mask = hdr[3]
+
+    trace_seq.puts("\t\t\tWMI_SET_BSS_FILTER_CMDID bss_filter 0x%x ie_mask 0x%08x\n" %
+                   (bss_filter, ie_mask))
+
+def wmi_cmd_set_probed_ssid_handler(pevent, trace_seq, event, buf):
+    hdr = struct.unpack("<BBB", buf[0:3])
+    entry_index = hdr[0]
+    flag = hdr[1]
+    ssid_len = hdr[2]
+
+    # fmt = "<" + ssid_len + "s"
+    # hdr = struct.unpack(fmt, buf[3:3 + ssid_len])
+
+    trace_seq.puts("\t\t\tWMI_SET_PROBED_SSID_CMDID entry_index 0x%x flag 0x%08x ssid_len %d\n" %
+                   (entry_index, flag, ssid_len))
+
+    # FIXME: print SSID
+    # for c in hdr[0]:
+    #     print ascii(c)
+
+wmi_cmd_handlers = [
+    [9, wmi_cmd_set_bss_filter_handler ],
+    [10, wmi_cmd_set_probed_ssid_handler ],
+    ]
+
+WMI_CMD_HDR_IF_ID_MASK = 0xf
+
+def ath6kl_wmi_cmd_handler(pevent, trace_seq, event):
+    buf_len = long(event['buf_len'])
+    buf = event['buf'].data
+
+    hdr = struct.unpack("<HHH", buf[0:6])
+    cmd_id = hdr[0]
+    if_idx = hdr[1] & WMI_CMD_HDR_IF_ID_MASK
+
+    trace_seq.puts("id 0x%x len %d if_idx %d\n" % (cmd_id, buf_len, if_idx))
+                   
+    for (wmi_id, handler) in wmi_cmd_handlers:
+        if wmi_id == cmd_id:
+            handler(pevent, trace_seq, event, buf[6:])
+            break
+
+def ath6kl_wmi_event_handler(pevent, trace_seq, event):
+    buf_len = long(event['buf_len'])
+    buf = event['buf'].data
+
+    hdr = struct.unpack("<HHH", buf[0:6])
+    cmd_id = hdr[0]
+    if_idx = hdr[1] & WMI_CMD_HDR_IF_ID_MASK
+
+    trace_seq.puts("id 0x%x len %d if_idx %d\n" % (cmd_id, buf_len, if_idx))
+                   
+    for (wmi_id, handler) in wmi_event_handlers:
+        if wmi_id == cmd_id:
+            handler(pevent, trace_seq, event, buf[6:])
+            break
+
+def ath6kl_htc_tx_handler(pevent, trace_seq, event):
+    buf_len = long(event['buf_len'])
+    buf = event['buf'].data
+
+    hdr = struct.unpack("<BBHBB", buf[0:6])
+    endpoint = hdr[0]
+    flags = hdr[1]
+    payload_len = hdr[2]
+    ctrl0 = hdr[3]
+    ctrl1 = hdr[4]
+
+    seqno = ctrl1
+
+    trace_seq.puts("seqno %d endpoint %d payload_len %d flags 0x%x\n" %
+                   (seqno, endpoint, payload_len, flags))
+
+    if flags != 0:
+        trace_seq.puts("\t\t\t\t\t\t")
+
+    if flags & 0x1:
+        trace_seq.puts(" NEED_CREDIT_UPDATE")
+
+    if flags & 0x2:
+        trace_seq.puts(" SEND_BUNDLE")
+
+    if flags & 0x4:
+        trace_seq.puts(" FIXUP_NETBUF")
+
+    if flags != 0:
+        trace_seq.puts("\n")
+
+def ath6kl_htc_rx_handler(pevent, trace_seq, event):
+    buf_len = long(event['buf_len'])
+    buf = event['buf'].data
+
+    hdr = struct.unpack("<BBHBB", buf[0:6])
+    endpoint = hdr[0]
+    flags = hdr[1]
+    payload_len = hdr[2]
+    ctrl0 = hdr[3]
+    ctrl1 = hdr[4]
+
+    seqno = ctrl1
+    bundle_count = (flags & 0xf0) >> 4
+
+    trace_seq.puts("seqno %d endpoint %d payload_len %d flags 0x%x bundle_count %d\n" %
+                   (seqno, endpoint, payload_len, flags, bundle_count))
+
+    if (flags & 0xf) != 0:
+        trace_seq.puts("\t\t\t\t\t\t")
+
+    if flags & 0x1:
+        trace_seq.puts(" UNUSED")
+
+    if flags & 0x2:
+        trace_seq.puts(" TRAILER")
+
+    if (flags & 0xf) != 0:
+        trace_seq.puts("\n")
+
+def ath6kl_sdio_handler(pevent, trace_seq, event):
+    tx = long(event['tx'])
+    addr = event['addr']
+    flags = event['flags']
+
+    buf_len = long(event['buf_len'])
+    buf = event['buf'].data
+
+    if tx == 1:
+        direction = "tx"
+    else:
+        direction = "rx"
+
+    trace_seq.puts("%s addr 0x%x flags 0x%x buf_len %d\n" %
+                   (direction, addr, flags, buf_len))
+    trace_seq.puts("%s\n" % hexdump(buf))
+
+def ath6kl_sdio_scat_handler(pevent, trace_seq, event):
+    tx = long(event['tx'])
+    addr = long(event['addr'])
+    flags = long(event['flags'])
+    entries = long(event['entries'])
+    total_len = long(event['total_len'])
+
+    len_array_data = event['len_array'].data
+    data = event['data'].data
+
+    if tx == 1:
+        direction = "tx"
+    else:
+        direction = "rx"
+
+    trace_seq.puts("%s addr 0x%x flags 0x%x entries %d total_len %d\n" %
+                   (direction, addr, flags, entries, total_len))
+
+    offset = 0
+
+    len_array = struct.unpack("<%dI" % entries, len_array_data[0:8])
+
+    for i in range(entries):
+        length = len_array[i]
+        start = offset
+        end = start + length
+
+        trace_seq.puts("%s\n" % hexdump(data[start:end]))
+
+        offset = offset + length
+
+def register(pevent):
+    pevent.register_event_handler("ath6kl", "ath6kl_wmi_cmd",
+                                  lambda *args:
+                                      ath6kl_wmi_cmd_handler(pevent, *args))
+    pevent.register_event_handler("ath6kl", "ath6kl_wmi_event",
+                                  lambda *args:
+                                      ath6kl_wmi_event_handler(pevent, *args))
+    pevent.register_event_handler("ath6kl", "ath6kl_htc_tx",
+                                  lambda *args:
+                                      ath6kl_htc_tx_handler(pevent, *args))
+    pevent.register_event_handler("ath6kl", "ath6kl_htc_rx",
+                                  lambda *args:
+                                      ath6kl_htc_rx_handler(pevent, *args))
+    pevent.register_event_handler("ath6kl", "ath6kl_sdio",
+                                  lambda *args:
+                                      ath6kl_sdio_handler(pevent, *args))
+    pevent.register_event_handler("ath6kl", "ath6kl_sdio_scat",
+                                  lambda *args:
+                                      ath6kl_sdio_scat_handler(pevent, *args))
