/* * This file containes (modified) header definitions from the iwlwifi * driver, the LinuxKPI skbuff.h and our tracing code. */ /* * USAGE: * - do your normal startup but make sure no interface is created. * You could do this by commenting out the wlans_iwlwifi0="wlan0" * (or similar) in rc.conf prior to booting. * NB: if you normally attach to iwm(4) please do that and then * flip the driver at this point. Whatever is easier to trigger * the problem will be good. * - kldload if_iwlwifi # if needed * - Re-add the wlans_iwlwifi0="wlan0" lines to rc.conf. * - run this script: * dtrace -C -s iwlwifi-cmds2.d -o /var/tmp/YYYYMMDD-SS-iwlwifi.dout & * - service netif start wlan0 * - once the problem happens please timely fg the dtrace process * (e.g., `jobs` && fg %). * - Interrupt the dtrace process by ^c (possibly needed twice). * * NOTE: IMORTANT: the output file MAY contain personal data! * Do not share publicly! If you share personaly please keep * this in mind. * If reporting please send dmesg -a and possibly wpa_supplicant * logs along. * * Also note: if the problem does not happen quickly the logfile * is likely going to grow quickly. You can always stop and * restart the dtrace process to shrink it. */ /* * XXX-BZ we should figure out how to allow the preprocessor to do * all this including for us wihtout getting into the endless #include * battle or making dtrace barf. In the mean time we adjust (unneeded) * fields to a simple type. Also would require a src tree. */ /* fw/api/cmdhdr.h: */ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* * Copyright (C) 2005-2014 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ /* iwl-trans.h: */ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* * Copyright (C) 2005-2014, 2018-2022 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ #define IWL_MAX_CMD_TBS_PER_TFD 2 struct iwl_host_cmd { const void *data[IWL_MAX_CMD_TBS_PER_TFD]; void *resp_pkt; void *_page; uint32_t _rx_page_order; uint32_t flags; uint32_t id; uint16_t len[IWL_MAX_CMD_TBS_PER_TFD]; uint8_t dataflags[IWL_MAX_CMD_TBS_PER_TFD]; }; struct iwl_cmd_header_wide { uint8_t cmd; uint8_t group_id; uint16_t sequence; uint16_t length; uint8_t reserved; uint8_t version; }; struct iwl_cmd_header { /** * @cmd: Command ID: REPLY_RXON, etc. */ uint8_t cmd; /** * @group_id: group ID, for commands with groups */ uint8_t group_id; /** * @sequence: * Sequence number for the command. * * The driver sets up the sequence number to values of its choosing. * uCode does not use this value, but passes it back to the driver * when sending the response to each driver-originated command, so * the driver can match the response to the command. Since the values * don't get used by uCode, the driver may set up an arbitrary format. * * There is one exception: uCode sets bit 15 when it originates * the response/notification, i.e. when the response/notification * is not a direct response to a command sent by the driver. For * example, uCode issues REPLY_RX when it sends a received frame * to the driver; it is not a direct response to any driver command. * * The Linux driver uses the following format: * * 0:7 tfd index - position within TX queue * 8:12 TX queue id * 13:14 reserved * 15 unsolicited RX or uCode-originated notification */ uint16_t sequence; }; struct iwl_rx_packet { /* * The first 4 bytes of the RX frame header contain both the RX frame * size and some flags. * Bit fields: * 31: flag flush RB request * 30: flag ignore TC (terminal counter) request * 29: flag fast IRQ request * 28-27: Reserved * 26: RADA enabled * 25: Offload enabled * 24: RPF enabled * 23: RSS enabled * 22: Checksum enabled * 21-16: RX queue * 15-14: Reserved * 13-00: RX frame size */ uint32_t len_n_flags; struct iwl_cmd_header hdr; #if 0 uint8_t data[]; #endif }; /* include/linux/skbuff.h and the remainder of this file: */ /*- * Copyright (c) 2020-2022 The FreeBSD Foundation * Copyright (c) 2021-2022 Bjoern A. Zeeb * * This software was developed by Björn Zeeb under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ struct sk_buff { /* XXX TODO */ /* struct sk_buff_head */ struct sk_buff *next; struct sk_buff *prev; int list; /* XXX TYPE */ uint32_t _alloc_len; /* Length of alloc data-buf. XXX-BZ give up for truesize? */ uint32_t len; /* ? */ uint32_t data_len; /* ? If we have frags? */ uint32_t truesize; /* The total size of all buffers, incl. frags. */ uint16_t mac_len; /* Link-layer header length. */ uint16_t csum; uint16_t l3hdroff; /* network header offset from *head */ uint16_t l4hdroff; /* transport header offset from *head */ uint32_t priority; uint16_t qmap; /* queue mapping */ uint16_t _spareu16_0; int pkt_type; /* "Scratch" area for layers to store metadata. */ /* ??? I see sizeof() operations so probably an array. */ /* Does alignment still match? */ uint8_t cb[64]; void *dev; void *sk; /* XXX net/sock.h? */ int csum_offset, csum_start, ip_summed, protocol; uint8_t *head; /* Head of buffer. */ uint8_t *data; /* Head of data. */ uint8_t *tail; /* End of data. */ uint8_t *end; /* End of buffer. */ void *shinfo; /* FreeBSD specific bandaid (see linuxkpi_kfree_skb). */ void *m; /* ... */ }; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #pragma D option quiet #pragma D option switchrate=2 #pragma D option bufsize=4M fbt:*:lkpi_80211_mo_*:* { printf("%-20u %-15s %-15s %-15s %-15s\n\n", walltimestamp, probeprov, probemod, probefunc, probename); /* stack(); */ } fbt:*:lkpi_80211_mo_tx:entry { printf("%-20u %-15s %-15s %-15s %-15s\n\n", walltimestamp, probeprov, probemod, probefunc, probename); skb = (struct sk_buff *)arg2; if (skb != NULL) { printf("\thw %p txctrl %p skb %p { _alloc_len %u len %u data_len %u truesize %u }\n", arg0, arg1, skb, skb->_alloc_len, skb->len, skb->data_len, skb->truesize); printf("\n\tskb->cb[]:\n"); tracemem(skb->cb, 64, 64); if (skb->len > 0) { printf("\n\tskb->cb[]:\n"); tracemem(skb->data, 4096, skb->len); } } else { printf("\thw %p txctrl %p skb %p\n", arg0, arg1, skb); } /* stack(); */ printf("\n"); } fbt:*:linuxkpi_*:* { printf("%-20u %-15s %-15s %-15s %-15s\n\n", walltimestamp, probeprov, probemod, probefunc, probename); /* stack(); */ } fbt:*:lkpi_*:* { printf("%-20u %-15s %-15s %-15s %-15s\n\n", walltimestamp, probeprov, probemod, probefunc, probename); /* stack(); */ } fbt:if_iwlwifi:iwl_pcie_rx_handle:* { printf("%-20u %-15s %-15s %-15s %-15s\n\n", walltimestamp, probeprov, probemod, probefunc, probename); /* stack(); */ } fbt:*:iwl_mvm_nic_restart:* { printf("%-20u %-15s %-15s %-15s %-15s\n\n", walltimestamp, probeprov, probemod, probefunc, probename); /* stack(); */ } fbt:if_iwlwifi:*:* { printf("%-20u %-15s %-15s %-15s %-15s\n\n", walltimestamp, probeprov, probemod, probefunc, probename); /* stack(); */ } fbt:kernel:*80211*:* { printf("%-20u %-15s %-15s %-15s %-15s\n\n", walltimestamp, probeprov, probemod, probefunc, probename); /* stack(); */ } iwlwifi:trace:dev_rx: { printf("%-20u %-15s %-15s %-15s %-15s\n\n", walltimestamp, probeprov, probemod, probefunc, probename); printf("\tdev %p trans %p pkt %p len %u\n", arg0, arg1, arg2, arg3); if (arg3 > 0) { pkt = (struct iwl_rx_packet *)arg2; printf("\tstruct iwl_rx_packet %p len_n_flags %#010x hdr { cmd %#x group_id %u sequence %#x } data ...\n", pkt, pkt->len_n_flags, pkt->hdr.cmd, pkt->hdr.group_id, pkt->hdr.sequence); } /* stack(); */ printf("\n"); } iwlwifi:trace:dev_rx_data: { printf("%-20u %-15s %-15s %-15s %-15s\n\n", walltimestamp, probeprov, probemod, probefunc, probename); printf("\tdev %p trans %p pkt %p len %u\n", arg0, arg1, arg2, arg3); if (arg3 > 0) { pkt = (struct iwl_rx_packet *)arg2; dlen = pkt->len_n_flags & ((1<<14)-1); printf("\tstruct iwl_rx_packet %p len_n_flags %#010x (dlen %u) hdr { cmd %#x group_id %u sequence %#x } data ...\n", pkt, pkt->len_n_flags, dlen, pkt->hdr.cmd, pkt->hdr.group_id, pkt->hdr.sequence); if (dlen > 0) { data = (uint8_t *)(pkt + 1); tracemem(data, 4096, dlen); } } /* stack(); */ printf("\n"); } iwlwifi:trace:dev_hcmd: { total_size = (int)arg2; printf("%-20u %-15s %-15s %-15s %-15s total_len %u\n\n", walltimestamp, probeprov, probemod, probefunc, probename, total_size); hdr_wide = (struct iwl_cmd_header_wide *)NULL; if (total_size >= sizeof(struct iwl_cmd_header_wide)) { hdr_wide = (struct iwl_cmd_header_wide *)arg3; printf("\tcmd %#x group_id %u sequence %#x length %u version %u\n", hdr_wide->cmd, hdr_wide->group_id, hdr_wide->sequence, hdr_wide->length, hdr_wide->version); if (hdr_wide->cmd == 0xc) stack(); } hcmd = (struct iwl_host_cmd *)NULL; if ((total_size - sizeof(struct iwl_cmd_header_wide)) > 0) { hcmd = (struct iwl_host_cmd *)arg1; printf("\thcmd resp_pkt %p _page %p _rx_page_order %#x flags %#x id %#x dataflags[%#x, %#x] len [%#x, %#x]\n", hcmd->resp_pkt, hcmd->_page, hcmd->_rx_page_order, hcmd->flags, hcmd->id, hcmd->dataflags[0], hcmd->dataflags[1], hcmd->len[0], hcmd->len[1]); } /* Now print hexdumps. */ if (hdr_wide != NULL) { printf("\n\tiwl_cmd_header_wide:\n"); tracemem(hdr_wide, 4096, sizeof(struct iwl_cmd_header_wide)); } if (hcmd != NULL) { printf("\n\tiwl_host_cmd:\n"); tracemem(hcmd, 65536, sizeof(struct iwl_host_cmd)); printf("\n\tiwl_host_cmd->data[0]:\n"); if (hcmd->len[0] > 0) tracemem(hcmd->data[0], 65536, hcmd->len[0]); printf("\n\tiwl_host_cmd->data[1]:\n"); if (hcmd->len[1] > 0) tracemem(hcmd->data[1], 65536, hcmd->len[1]); } /* stack(); */ printf("\n"); }