Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'firewire-updates-6.11' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394

Pull firewire updates from Takashi Sakamoto:
"There are many lines of changes for FireWire subsystem, but there is
practically no functional change.

Most of the changes are for code refactoring, some KUnit tests to
added helper functions, and new tracepoints events for both the core
functions and 1394 OHCI driver.

The tracepoints events now cover the verbose logging enabled by debug
parameter of firewire-ohci kernel module. The parameter would be
removed in any future timing, thus it is now deprecated"

* tag 'firewire-updates-6.11' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394: (32 commits)
firewire: core: move copy_port_status() helper function to TP_fast_assign() block
Revert "firewire: ohci: use common macro to interpret be32 data in le32 buffer"
firewire: ohci: add tracepoints event for data of Self-ID DMA
firewire: ohci: use inline functions to operate data of self-ID DMA
firewire: ohci: add static inline functions to deserialize for Self-ID DMA operation
firewire: ohci: use static function to handle endian issue on PowerPC platform
firewire: ohci: use common macro to interpret be32 data in le32 buffer
firewire: core: Fix spelling mistakes in tracepoint messages
firewire: ohci: add tracepoints event for hardIRQ event
firewire: ohci: add support for Linux kernel tracepoints
firewire: core: add tracepoints events for completions of packets in isochronous context
firewire: core: add tracepoints events for queueing packets of isochronous context
firewire: core: add tracepoints events for flushing completions of isochronous context
firewire: core: add tracepoints events for flushing of isochronous context
firewire: core: add tracepoints events for starting/stopping of isochronous context
firewire: core: add tracepoints events for setting channels of multichannel context
firewire: core: add tracepoints events for allocation/deallocation of isochronous context
firewire: core: undefine macros after use in tracepoints events
firewire: core: record card index in tracepoints event for self ID sequence
firewire: core: use inline helper functions to serialize phy config packet
...

+1867 -222
+2
drivers/firewire/.kunitconfig
··· 4 4 CONFIG_FIREWIRE_KUNIT_UAPI_TEST=y 5 5 CONFIG_FIREWIRE_KUNIT_DEVICE_ATTRIBUTE_TEST=y 6 6 CONFIG_FIREWIRE_KUNIT_PACKET_SERDES_TEST=y 7 + CONFIG_FIREWIRE_KUNIT_SELF_ID_SEQUENCE_HELPER_TEST=y 8 + CONFIG_FIREWIRE_KUNIT_OHCI_SERDES_TEST=y
+31
drivers/firewire/Kconfig
··· 66 66 For more information on KUnit and unit tests in general, refer 67 67 to the KUnit documentation in Documentation/dev-tools/kunit/. 68 68 69 + config FIREWIRE_KUNIT_SELF_ID_SEQUENCE_HELPER_TEST 70 + tristate "KUnit tests for helpers of self ID sequence" if !KUNIT_ALL_TESTS 71 + depends on FIREWIRE && KUNIT 72 + default KUNIT_ALL_TESTS 73 + help 74 + This builds the KUnit tests for helpers of self ID sequence. 75 + 76 + KUnit tests run during boot and output the results to the debug 77 + log in TAP format (https://testanything.org/). Only useful for 78 + kernel devs running KUnit test harness and are not for inclusion 79 + into a production build. 80 + 81 + For more information on KUnit and unit tests in general, refer 82 + to the KUnit documentation in Documentation/dev-tools/kunit/. 83 + 69 84 config FIREWIRE_OHCI 70 85 tristate "OHCI-1394 controllers" 71 86 depends on PCI && FIREWIRE && MMU ··· 91 76 92 77 To compile this driver as a module, say M here: The module will be 93 78 called firewire-ohci. 79 + 80 + config FIREWIRE_KUNIT_OHCI_SERDES_TEST 81 + tristate "KUnit tests for serialization/deserialization of data in buffers/registers" if !KUNIT_ALL_TESTS 82 + depends on FIREWIRE && KUNIT 83 + default KUNIT_ALL_TESTS 84 + help 85 + This builds the KUnit tests to check serialization and deserialization 86 + of data in buffers and registers defined in 1394 OHCI specification. 87 + 88 + KUnit tests run during boot and output the results to the debug 89 + log in TAP format (https://testanything.org/). Only useful for 90 + kernel devs running KUnit test harness and are not for inclusion 91 + into a production build. 92 + 93 + For more information on KUnit and unit tests in general, refer 94 + to the KUnit documentation in Documentation/dev-tools/kunit/. 94 95 95 96 config FIREWIRE_SBP2 96 97 tristate "Storage devices (SBP-2 protocol)"
+2
drivers/firewire/Makefile
··· 18 18 19 19 obj-$(CONFIG_FIREWIRE_KUNIT_UAPI_TEST) += uapi-test.o 20 20 obj-$(CONFIG_FIREWIRE_KUNIT_PACKET_SERDES_TEST) += packet-serdes-test.o 21 + obj-$(CONFIG_FIREWIRE_KUNIT_SELF_ID_SEQUENCE_HELPER_TEST) += self-id-sequence-helper-test.o 22 + obj-$(CONFIG_FIREWIRE_KUNIT_OHCI_SERDES_TEST) += ohci-serdes-test.o
+32
drivers/firewire/core-iso.c
··· 22 22 23 23 #include "core.h" 24 24 25 + #include <trace/events/firewire.h> 26 + 25 27 /* 26 28 * Isochronous DMA context management 27 29 */ ··· 150 148 ctx->callback.sc = callback; 151 149 ctx->callback_data = callback_data; 152 150 151 + trace_isoc_outbound_allocate(ctx, channel, speed); 152 + trace_isoc_inbound_single_allocate(ctx, channel, header_size); 153 + trace_isoc_inbound_multiple_allocate(ctx); 154 + 153 155 return ctx; 154 156 } 155 157 EXPORT_SYMBOL(fw_iso_context_create); 156 158 157 159 void fw_iso_context_destroy(struct fw_iso_context *ctx) 158 160 { 161 + trace_isoc_outbound_destroy(ctx); 162 + trace_isoc_inbound_single_destroy(ctx); 163 + trace_isoc_inbound_multiple_destroy(ctx); 164 + 159 165 ctx->card->driver->free_iso_context(ctx); 160 166 } 161 167 EXPORT_SYMBOL(fw_iso_context_destroy); ··· 171 161 int fw_iso_context_start(struct fw_iso_context *ctx, 172 162 int cycle, int sync, int tags) 173 163 { 164 + trace_isoc_outbound_start(ctx, cycle); 165 + trace_isoc_inbound_single_start(ctx, cycle, sync, tags); 166 + trace_isoc_inbound_multiple_start(ctx, cycle, sync, tags); 167 + 174 168 return ctx->card->driver->start_iso(ctx, cycle, sync, tags); 175 169 } 176 170 EXPORT_SYMBOL(fw_iso_context_start); 177 171 178 172 int fw_iso_context_set_channels(struct fw_iso_context *ctx, u64 *channels) 179 173 { 174 + trace_isoc_inbound_multiple_channels(ctx, *channels); 175 + 180 176 return ctx->card->driver->set_iso_channels(ctx, channels); 181 177 } 182 178 ··· 191 175 struct fw_iso_buffer *buffer, 192 176 unsigned long payload) 193 177 { 178 + trace_isoc_outbound_queue(ctx, payload, packet); 179 + trace_isoc_inbound_single_queue(ctx, payload, packet); 180 + trace_isoc_inbound_multiple_queue(ctx, payload, packet); 181 + 194 182 return ctx->card->driver->queue_iso(ctx, packet, buffer, payload); 195 183 } 196 184 EXPORT_SYMBOL(fw_iso_context_queue); 197 185 198 186 void fw_iso_context_queue_flush(struct fw_iso_context *ctx) 199 187 { 188 + trace_isoc_outbound_flush(ctx); 189 + trace_isoc_inbound_single_flush(ctx); 190 + trace_isoc_inbound_multiple_flush(ctx); 191 + 200 192 ctx->card->driver->flush_queue_iso(ctx); 201 193 } 202 194 EXPORT_SYMBOL(fw_iso_context_queue_flush); 203 195 204 196 int fw_iso_context_flush_completions(struct fw_iso_context *ctx) 205 197 { 198 + trace_isoc_outbound_flush_completions(ctx); 199 + trace_isoc_inbound_single_flush_completions(ctx); 200 + trace_isoc_inbound_multiple_flush_completions(ctx); 201 + 206 202 return ctx->card->driver->flush_iso_completions(ctx); 207 203 } 208 204 EXPORT_SYMBOL(fw_iso_context_flush_completions); 209 205 210 206 int fw_iso_context_stop(struct fw_iso_context *ctx) 211 207 { 208 + trace_isoc_outbound_stop(ctx); 209 + trace_isoc_inbound_single_stop(ctx); 210 + trace_isoc_inbound_multiple_stop(ctx); 211 + 212 212 return ctx->card->driver->stop_iso(ctx); 213 213 } 214 214 EXPORT_SYMBOL(fw_iso_context_stop);
+84 -135
drivers/firewire/core-topology.c
··· 20 20 #include <asm/byteorder.h> 21 21 22 22 #include "core.h" 23 + #include "phy-packet-definitions.h" 23 24 #include <trace/events/firewire.h> 24 - 25 - #define SELF_ID_PHY_ID(q) (((q) >> 24) & 0x3f) 26 - #define SELF_ID_EXTENDED(q) (((q) >> 23) & 0x01) 27 - #define SELF_ID_LINK_ON(q) (((q) >> 22) & 0x01) 28 - #define SELF_ID_GAP_COUNT(q) (((q) >> 16) & 0x3f) 29 - #define SELF_ID_PHY_SPEED(q) (((q) >> 14) & 0x03) 30 - #define SELF_ID_CONTENDER(q) (((q) >> 11) & 0x01) 31 - #define SELF_ID_PHY_INITIATOR(q) (((q) >> 1) & 0x01) 32 - #define SELF_ID_MORE_PACKETS(q) (((q) >> 0) & 0x01) 33 - 34 - #define SELF_ID_EXT_SEQUENCE(q) (((q) >> 20) & 0x07) 35 - 36 - #define SELFID_PORT_CHILD 0x3 37 - #define SELFID_PORT_PARENT 0x2 38 - #define SELFID_PORT_NCONN 0x1 39 - #define SELFID_PORT_NONE 0x0 40 - 41 - static u32 *count_ports(u32 *sid, int *total_port_count, int *child_port_count) 42 - { 43 - u32 q; 44 - int port_type, shift, seq; 45 - 46 - *total_port_count = 0; 47 - *child_port_count = 0; 48 - 49 - shift = 6; 50 - q = *sid; 51 - seq = 0; 52 - 53 - while (1) { 54 - port_type = (q >> shift) & 0x03; 55 - switch (port_type) { 56 - case SELFID_PORT_CHILD: 57 - (*child_port_count)++; 58 - fallthrough; 59 - case SELFID_PORT_PARENT: 60 - case SELFID_PORT_NCONN: 61 - (*total_port_count)++; 62 - fallthrough; 63 - case SELFID_PORT_NONE: 64 - break; 65 - } 66 - 67 - shift -= 2; 68 - if (shift == 0) { 69 - if (!SELF_ID_MORE_PACKETS(q)) 70 - return sid + 1; 71 - 72 - shift = 16; 73 - sid++; 74 - q = *sid; 75 - 76 - /* 77 - * Check that the extra packets actually are 78 - * extended self ID packets and that the 79 - * sequence numbers in the extended self ID 80 - * packets increase as expected. 81 - */ 82 - 83 - if (!SELF_ID_EXTENDED(q) || 84 - seq != SELF_ID_EXT_SEQUENCE(q)) 85 - return NULL; 86 - 87 - seq++; 88 - } 89 - } 90 - } 91 - 92 - static int get_port_type(u32 *sid, int port_index) 93 - { 94 - int index, shift; 95 - 96 - index = (port_index + 5) / 8; 97 - shift = 16 - ((port_index + 5) & 7) * 2; 98 - return (sid[index] >> shift) & 0x03; 99 - } 100 25 101 26 static struct fw_node *fw_node_create(u32 sid, int port_count, int color) 102 27 { ··· 32 107 return NULL; 33 108 34 109 node->color = color; 35 - node->node_id = LOCAL_BUS | SELF_ID_PHY_ID(sid); 36 - node->link_on = SELF_ID_LINK_ON(sid); 37 - node->phy_speed = SELF_ID_PHY_SPEED(sid); 38 - node->initiated_reset = SELF_ID_PHY_INITIATOR(sid); 110 + node->node_id = LOCAL_BUS | phy_packet_self_id_get_phy_id(sid); 111 + node->link_on = phy_packet_self_id_zero_get_link_active(sid); 112 + // NOTE: Only two bits, thus only for SCODE_100, SCODE_200, SCODE_400, and SCODE_BETA. 113 + node->phy_speed = phy_packet_self_id_zero_get_scode(sid); 114 + node->initiated_reset = phy_packet_self_id_zero_get_initiated_reset(sid); 39 115 node->port_count = port_count; 40 116 41 117 refcount_set(&node->ref_count, 1); ··· 95 169 * internally consistent. On success this function returns the 96 170 * fw_node corresponding to the local card otherwise NULL. 97 171 */ 98 - static struct fw_node *build_tree(struct fw_card *card, 99 - u32 *sid, int self_id_count) 172 + static struct fw_node *build_tree(struct fw_card *card, const u32 *sid, int self_id_count, 173 + unsigned int generation) 100 174 { 175 + struct self_id_sequence_enumerator enumerator = { 176 + .cursor = sid, 177 + .quadlet_count = self_id_count, 178 + }; 101 179 struct fw_node *node, *child, *local_node, *irm_node; 102 - struct list_head stack, *h; 103 - u32 *next_sid, *end, q; 104 - int i, port_count, child_port_count, phy_id, parent_count, stack_depth; 180 + struct list_head stack; 181 + int phy_id, stack_depth; 105 182 int gap_count; 106 183 bool beta_repeaters_present; 107 184 ··· 112 183 node = NULL; 113 184 INIT_LIST_HEAD(&stack); 114 185 stack_depth = 0; 115 - end = sid + self_id_count; 116 186 phy_id = 0; 117 187 irm_node = NULL; 118 - gap_count = SELF_ID_GAP_COUNT(*sid); 188 + gap_count = phy_packet_self_id_zero_get_gap_count(*sid); 119 189 beta_repeaters_present = false; 120 190 121 - while (sid < end) { 122 - next_sid = count_ports(sid, &port_count, &child_port_count); 191 + while (enumerator.quadlet_count > 0) { 192 + unsigned int child_port_count = 0; 193 + unsigned int total_port_count = 0; 194 + unsigned int parent_count = 0; 195 + unsigned int quadlet_count; 196 + const u32 *self_id_sequence; 197 + unsigned int port_capacity; 198 + enum phy_packet_self_id_port_status port_status; 199 + unsigned int port_index; 200 + struct list_head *h; 201 + int i; 123 202 124 - if (next_sid == NULL) { 125 - fw_err(card, "inconsistent extended self IDs\n"); 126 - return NULL; 203 + self_id_sequence = self_id_sequence_enumerator_next(&enumerator, &quadlet_count); 204 + if (IS_ERR(self_id_sequence)) { 205 + if (PTR_ERR(self_id_sequence) != -ENODATA) { 206 + fw_err(card, "inconsistent extended self IDs: %ld\n", 207 + PTR_ERR(self_id_sequence)); 208 + return NULL; 209 + } 210 + break; 127 211 } 128 212 129 - q = *sid; 130 - if (phy_id != SELF_ID_PHY_ID(q)) { 213 + port_capacity = self_id_sequence_get_port_capacity(quadlet_count); 214 + trace_self_id_sequence(card->index, self_id_sequence, quadlet_count, generation); 215 + 216 + for (port_index = 0; port_index < port_capacity; ++port_index) { 217 + port_status = self_id_sequence_get_port_status(self_id_sequence, quadlet_count, 218 + port_index); 219 + switch (port_status) { 220 + case PHY_PACKET_SELF_ID_PORT_STATUS_CHILD: 221 + ++child_port_count; 222 + fallthrough; 223 + case PHY_PACKET_SELF_ID_PORT_STATUS_PARENT: 224 + case PHY_PACKET_SELF_ID_PORT_STATUS_NCONN: 225 + ++total_port_count; 226 + fallthrough; 227 + case PHY_PACKET_SELF_ID_PORT_STATUS_NONE: 228 + default: 229 + break; 230 + } 231 + } 232 + 233 + if (phy_id != phy_packet_self_id_get_phy_id(self_id_sequence[0])) { 131 234 fw_err(card, "PHY ID mismatch in self ID: %d != %d\n", 132 - phy_id, SELF_ID_PHY_ID(q)); 235 + phy_id, phy_packet_self_id_get_phy_id(self_id_sequence[0])); 133 236 return NULL; 134 237 } 135 238 ··· 182 221 */ 183 222 child = fw_node(h); 184 223 185 - node = fw_node_create(q, port_count, card->color); 224 + node = fw_node_create(self_id_sequence[0], total_port_count, card->color); 186 225 if (node == NULL) { 187 226 fw_err(card, "out of memory while building topology\n"); 188 227 return NULL; ··· 191 230 if (phy_id == (card->node_id & 0x3f)) 192 231 local_node = node; 193 232 194 - if (SELF_ID_CONTENDER(q)) 233 + if (phy_packet_self_id_zero_get_contender(self_id_sequence[0])) 195 234 irm_node = node; 196 235 197 - parent_count = 0; 198 - 199 - for (i = 0; i < port_count; i++) { 200 - switch (get_port_type(sid, i)) { 201 - case SELFID_PORT_PARENT: 202 - /* 203 - * Who's your daddy? We dont know the 204 - * parent node at this time, so we 205 - * temporarily abuse node->color for 206 - * remembering the entry in the 207 - * node->ports array where the parent 208 - * node should be. Later, when we 209 - * handle the parent node, we fix up 210 - * the reference. 211 - */ 212 - parent_count++; 236 + for (port_index = 0; port_index < total_port_count; ++port_index) { 237 + port_status = self_id_sequence_get_port_status(self_id_sequence, quadlet_count, 238 + port_index); 239 + switch (port_status) { 240 + case PHY_PACKET_SELF_ID_PORT_STATUS_PARENT: 241 + // Who's your daddy? We dont know the parent node at this time, so 242 + // we temporarily abuse node->color for remembering the entry in 243 + // the node->ports array where the parent node should be. Later, 244 + // when we handle the parent node, we fix up the reference. 245 + ++parent_count; 213 246 node->color = i; 214 247 break; 215 248 216 - case SELFID_PORT_CHILD: 217 - node->ports[i] = child; 218 - /* 219 - * Fix up parent reference for this 220 - * child node. 221 - */ 249 + case PHY_PACKET_SELF_ID_PORT_STATUS_CHILD: 250 + node->ports[port_index] = child; 251 + // Fix up parent reference for this child node. 222 252 child->ports[child->color] = node; 223 253 child->color = card->color; 224 254 child = fw_node(child->link.next); 225 255 break; 256 + case PHY_PACKET_SELF_ID_PORT_STATUS_NCONN: 257 + case PHY_PACKET_SELF_ID_PORT_STATUS_NONE: 258 + default: 259 + break; 226 260 } 227 261 } 228 262 229 - /* 230 - * Check that the node reports exactly one parent 231 - * port, except for the root, which of course should 232 - * have no parents. 233 - */ 234 - if ((next_sid == end && parent_count != 0) || 235 - (next_sid < end && parent_count != 1)) { 263 + // Check that the node reports exactly one parent port, except for the root, which 264 + // of course should have no parents. 265 + if ((enumerator.quadlet_count == 0 && parent_count != 0) || 266 + (enumerator.quadlet_count > 0 && parent_count != 1)) { 236 267 fw_err(card, "parent port inconsistency for node %d: " 237 268 "parent_count=%d\n", phy_id, parent_count); 238 269 return NULL; ··· 235 282 list_add_tail(&node->link, &stack); 236 283 stack_depth += 1 - child_port_count; 237 284 238 - if (node->phy_speed == SCODE_BETA && 239 - parent_count + child_port_count > 1) 285 + if (node->phy_speed == SCODE_BETA && parent_count + child_port_count > 1) 240 286 beta_repeaters_present = true; 241 287 242 - /* 243 - * If PHYs report different gap counts, set an invalid count 244 - * which will force a gap count reconfiguration and a reset. 245 - */ 246 - if (SELF_ID_GAP_COUNT(q) != gap_count) 288 + // If PHYs report different gap counts, set an invalid count which will force a gap 289 + // count reconfiguration and a reset. 290 + if (phy_packet_self_id_zero_get_gap_count(self_id_sequence[0]) != gap_count) 247 291 gap_count = 0; 248 292 249 293 update_hop_count(node); 250 294 251 - sid = next_sid; 252 295 phy_id++; 253 296 } 254 297 ··· 485 536 card->bm_abdicate = bm_abdicate; 486 537 fw_schedule_bm_work(card, 0); 487 538 488 - local_node = build_tree(card, self_ids, self_id_count); 539 + local_node = build_tree(card, self_ids, self_id_count, generation); 489 540 490 541 update_topology_map(card, self_ids, self_id_count); 491 542
+11
drivers/firewire/core-trace.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-or-later 2 2 // Copyright (c) 2024 Takashi Sakamoto 3 3 4 + #include <linux/types.h> 5 + #include <linux/err.h> 6 + #include "packet-header-definitions.h" 7 + #include "phy-packet-definitions.h" 8 + 4 9 #define CREATE_TRACE_POINTS 5 10 #include <trace/events/firewire.h> 11 + 12 + #ifdef TRACEPOINTS_ENABLED 13 + EXPORT_TRACEPOINT_SYMBOL_GPL(isoc_inbound_single_completions); 14 + EXPORT_TRACEPOINT_SYMBOL_GPL(isoc_inbound_multiple_completions); 15 + EXPORT_TRACEPOINT_SYMBOL_GPL(isoc_outbound_completions); 16 + #endif
+11 -13
drivers/firewire/core-transaction.c
··· 29 29 #include <asm/byteorder.h> 30 30 31 31 #include "core.h" 32 - #include <trace/events/firewire.h> 33 32 #include "packet-header-definitions.h" 33 + #include "phy-packet-definitions.h" 34 + #include <trace/events/firewire.h> 34 35 35 36 #define HEADER_DESTINATION_IS_BROADCAST(header) \ 36 37 ((async_header_get_destination(header) & 0x3f) == 0x3f) 37 - 38 - #define PHY_PACKET_CONFIG 0x0 39 - #define PHY_PACKET_LINK_ON 0x1 40 - #define PHY_PACKET_SELF_ID 0x2 41 - 42 - #define PHY_CONFIG_GAP_COUNT(gap_count) (((gap_count) << 16) | (1 << 22)) 43 - #define PHY_CONFIG_ROOT_ID(node_id) ((((node_id) & 0x3f) << 24) | (1 << 23)) 44 - #define PHY_IDENTIFIER(id) ((id) << 30) 45 38 46 39 /* returns 0 if the split timeout handler is already running */ 47 40 static int try_cancel_split_timeout(struct fw_transaction *t) ··· 474 481 int node_id, int generation, int gap_count) 475 482 { 476 483 long timeout = DIV_ROUND_UP(HZ, 10); 477 - u32 data = PHY_IDENTIFIER(PHY_PACKET_CONFIG); 484 + u32 data = 0; 478 485 479 - if (node_id != FW_PHY_CONFIG_NO_NODE_ID) 480 - data |= PHY_CONFIG_ROOT_ID(node_id); 486 + phy_packet_set_packet_identifier(&data, PHY_PACKET_PACKET_IDENTIFIER_PHY_CONFIG); 487 + 488 + if (node_id != FW_PHY_CONFIG_NO_NODE_ID) { 489 + phy_packet_phy_config_set_root_id(&data, node_id); 490 + phy_packet_phy_config_set_force_root_node(&data, true); 491 + } 481 492 482 493 if (gap_count == FW_PHY_CONFIG_CURRENT_GAP_COUNT) { 483 494 gap_count = card->driver->read_phy_reg(card, 1); ··· 492 495 if (gap_count == 63) 493 496 return; 494 497 } 495 - data |= PHY_CONFIG_GAP_COUNT(gap_count); 498 + phy_packet_phy_config_set_gap_count(&data, gap_count); 499 + phy_packet_phy_config_set_gap_count_optimization(&data, true); 496 500 497 501 mutex_lock(&phy_config_mutex); 498 502
+56
drivers/firewire/ohci-serdes-test.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + // 3 + // ohci-serdes-test.c - An application of Kunit to check serialization/deserialization of data in 4 + // buffers and registers defined in 1394 OHCI specification. 5 + // 6 + // Copyright (c) 2024 Takashi Sakamoto 7 + 8 + #include <kunit/test.h> 9 + 10 + #include "ohci.h" 11 + 12 + 13 + static void test_self_id_count_register_deserialization(struct kunit *test) 14 + { 15 + const u32 expected = 0x803d0594; 16 + 17 + bool is_error = ohci1394_self_id_count_is_error(expected); 18 + u8 generation = ohci1394_self_id_count_get_generation(expected); 19 + u32 size = ohci1394_self_id_count_get_size(expected); 20 + 21 + KUNIT_EXPECT_TRUE(test, is_error); 22 + KUNIT_EXPECT_EQ(test, 0x3d, generation); 23 + KUNIT_EXPECT_EQ(test, 0x165, size); 24 + } 25 + 26 + static void test_self_id_receive_buffer_deserialization(struct kunit *test) 27 + { 28 + const u32 buffer[] = { 29 + 0x0006f38b, 30 + 0x807fcc56, 31 + 0x7f8033a9, 32 + 0x8145cc5e, 33 + 0x7eba33a1, 34 + }; 35 + 36 + u8 generation = ohci1394_self_id_receive_q0_get_generation(buffer[0]); 37 + u16 timestamp = ohci1394_self_id_receive_q0_get_timestamp(buffer[0]); 38 + 39 + KUNIT_EXPECT_EQ(test, 0x6, generation); 40 + KUNIT_EXPECT_EQ(test, 0xf38b, timestamp); 41 + } 42 + 43 + static struct kunit_case ohci_serdes_test_cases[] = { 44 + KUNIT_CASE(test_self_id_count_register_deserialization), 45 + KUNIT_CASE(test_self_id_receive_buffer_deserialization), 46 + {} 47 + }; 48 + 49 + static struct kunit_suite ohci_serdes_test_suite = { 50 + .name = "firewire-ohci-serdes", 51 + .test_cases = ohci_serdes_test_cases, 52 + }; 53 + kunit_test_suite(ohci_serdes_test_suite); 54 + 55 + MODULE_DESCRIPTION("FireWire buffers and registers serialization/deserialization unit test suite"); 56 + MODULE_LICENSE("GPL");
+165 -72
drivers/firewire/ohci.c
··· 41 41 #include "core.h" 42 42 #include "ohci.h" 43 43 #include "packet-header-definitions.h" 44 + #include "phy-packet-definitions.h" 45 + 46 + #include <trace/events/firewire.h> 47 + 48 + static u32 cond_le32_to_cpu(__le32 value, bool has_be_header_quirk); 49 + 50 + #define CREATE_TRACE_POINTS 51 + #include <trace/events/firewire_ohci.h> 44 52 45 53 #define ohci_info(ohci, f, args...) dev_info(ohci->card.device, f, ##args) 46 54 #define ohci_notice(ohci, f, args...) dev_notice(ohci->card.device, f, ##args) ··· 445 437 ? " ?" : ""); 446 438 } 447 439 448 - static const char *speed[] = { 449 - [0] = "S100", [1] = "S200", [2] = "S400", [3] = "beta", 450 - }; 451 - static const char *power[] = { 452 - [0] = "+0W", [1] = "+15W", [2] = "+30W", [3] = "+45W", 453 - [4] = "-3W", [5] = " ?W", [6] = "-3..-6W", [7] = "-3..-10W", 454 - }; 455 - static const char port[] = { '.', '-', 'p', 'c', }; 456 - 457 - static char _p(u32 *s, int shift) 458 - { 459 - return port[*s >> shift & 3]; 460 - } 461 - 462 440 static void log_selfids(struct fw_ohci *ohci, int generation, int self_id_count) 463 441 { 464 - u32 *s; 442 + static const char *const speed[] = { 443 + [0] = "S100", [1] = "S200", [2] = "S400", [3] = "beta", 444 + }; 445 + static const char *const power[] = { 446 + [0] = "+0W", [1] = "+15W", [2] = "+30W", [3] = "+45W", 447 + [4] = "-3W", [5] = " ?W", [6] = "-3..-6W", [7] = "-3..-10W", 448 + }; 449 + static const char port[] = { 450 + [PHY_PACKET_SELF_ID_PORT_STATUS_NONE] = '.', 451 + [PHY_PACKET_SELF_ID_PORT_STATUS_NCONN] = '-', 452 + [PHY_PACKET_SELF_ID_PORT_STATUS_PARENT] = 'p', 453 + [PHY_PACKET_SELF_ID_PORT_STATUS_CHILD] = 'c', 454 + }; 455 + struct self_id_sequence_enumerator enumerator = { 456 + .cursor = ohci->self_id_buffer, 457 + .quadlet_count = self_id_count, 458 + }; 465 459 466 460 if (likely(!(param_debug & OHCI_PARAM_DEBUG_SELFIDS))) 467 461 return; ··· 471 461 ohci_notice(ohci, "%d selfIDs, generation %d, local node ID %04x\n", 472 462 self_id_count, generation, ohci->node_id); 473 463 474 - for (s = ohci->self_id_buffer; self_id_count--; ++s) 475 - if ((*s & 1 << 23) == 0) 476 - ohci_notice(ohci, 477 - "selfID 0: %08x, phy %d [%c%c%c] %s gc=%d %s %s%s%s\n", 478 - *s, *s >> 24 & 63, _p(s, 6), _p(s, 4), _p(s, 2), 479 - speed[*s >> 14 & 3], *s >> 16 & 63, 480 - power[*s >> 8 & 7], *s >> 22 & 1 ? "L" : "", 481 - *s >> 11 & 1 ? "c" : "", *s & 2 ? "i" : ""); 482 - else 464 + while (enumerator.quadlet_count > 0) { 465 + unsigned int quadlet_count; 466 + unsigned int port_index; 467 + const u32 *s; 468 + int i; 469 + 470 + s = self_id_sequence_enumerator_next(&enumerator, &quadlet_count); 471 + if (IS_ERR(s)) 472 + break; 473 + 474 + ohci_notice(ohci, 475 + "selfID 0: %08x, phy %d [%c%c%c] %s gc=%d %s %s%s%s\n", 476 + *s, 477 + phy_packet_self_id_get_phy_id(*s), 478 + port[self_id_sequence_get_port_status(s, quadlet_count, 0)], 479 + port[self_id_sequence_get_port_status(s, quadlet_count, 1)], 480 + port[self_id_sequence_get_port_status(s, quadlet_count, 2)], 481 + speed[*s >> 14 & 3], *s >> 16 & 63, 482 + power[*s >> 8 & 7], *s >> 22 & 1 ? "L" : "", 483 + *s >> 11 & 1 ? "c" : "", *s & 2 ? "i" : ""); 484 + 485 + port_index = 3; 486 + for (i = 1; i < quadlet_count; ++i) { 483 487 ohci_notice(ohci, 484 488 "selfID n: %08x, phy %d [%c%c%c%c%c%c%c%c]\n", 485 - *s, *s >> 24 & 63, 486 - _p(s, 16), _p(s, 14), _p(s, 12), _p(s, 10), 487 - _p(s, 8), _p(s, 6), _p(s, 4), _p(s, 2)); 489 + s[i], 490 + phy_packet_self_id_get_phy_id(s[i]), 491 + port[self_id_sequence_get_port_status(s, quadlet_count, port_index)], 492 + port[self_id_sequence_get_port_status(s, quadlet_count, port_index + 1)], 493 + port[self_id_sequence_get_port_status(s, quadlet_count, port_index + 2)], 494 + port[self_id_sequence_get_port_status(s, quadlet_count, port_index + 3)], 495 + port[self_id_sequence_get_port_status(s, quadlet_count, port_index + 4)], 496 + port[self_id_sequence_get_port_status(s, quadlet_count, port_index + 5)], 497 + port[self_id_sequence_get_port_status(s, quadlet_count, port_index + 6)], 498 + port[self_id_sequence_get_port_status(s, quadlet_count, port_index + 7)] 499 + ); 500 + 501 + port_index += 8; 502 + } 503 + } 488 504 } 489 505 490 506 static const char *evts[] = { ··· 877 841 } 878 842 879 843 #if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32) 880 - #define cond_le32_to_cpu(v) \ 881 - (ohci->quirks & QUIRK_BE_HEADERS ? (__force __u32)(v) : le32_to_cpu(v)) 844 + static u32 cond_le32_to_cpu(__le32 value, bool has_be_header_quirk) 845 + { 846 + return has_be_header_quirk ? (__force __u32)value : le32_to_cpu(value); 847 + } 848 + 849 + static bool has_be_header_quirk(const struct fw_ohci *ohci) 850 + { 851 + return !!(ohci->quirks & QUIRK_BE_HEADERS); 852 + } 882 853 #else 883 - #define cond_le32_to_cpu(v) le32_to_cpu(v) 854 + static u32 cond_le32_to_cpu(__le32 value, bool has_be_header_quirk __maybe_unused) 855 + { 856 + return le32_to_cpu(value); 857 + } 858 + 859 + static bool has_be_header_quirk(const struct fw_ohci *ohci) 860 + { 861 + return false; 862 + } 884 863 #endif 885 864 886 865 static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer) ··· 905 854 u32 status, length, tcode; 906 855 int evt; 907 856 908 - p.header[0] = cond_le32_to_cpu(buffer[0]); 909 - p.header[1] = cond_le32_to_cpu(buffer[1]); 910 - p.header[2] = cond_le32_to_cpu(buffer[2]); 857 + p.header[0] = cond_le32_to_cpu(buffer[0], has_be_header_quirk(ohci)); 858 + p.header[1] = cond_le32_to_cpu(buffer[1], has_be_header_quirk(ohci)); 859 + p.header[2] = cond_le32_to_cpu(buffer[2], has_be_header_quirk(ohci)); 911 860 912 861 tcode = async_header_get_tcode(p.header); 913 862 switch (tcode) { ··· 919 868 break; 920 869 921 870 case TCODE_READ_BLOCK_REQUEST : 922 - p.header[3] = cond_le32_to_cpu(buffer[3]); 871 + p.header[3] = cond_le32_to_cpu(buffer[3], has_be_header_quirk(ohci)); 923 872 p.header_length = 16; 924 873 p.payload_length = 0; 925 874 break; ··· 928 877 case TCODE_READ_BLOCK_RESPONSE: 929 878 case TCODE_LOCK_REQUEST: 930 879 case TCODE_LOCK_RESPONSE: 931 - p.header[3] = cond_le32_to_cpu(buffer[3]); 880 + p.header[3] = cond_le32_to_cpu(buffer[3], has_be_header_quirk(ohci)); 932 881 p.header_length = 16; 933 882 p.payload_length = async_header_get_data_length(p.header); 934 883 if (p.payload_length > MAX_ASYNC_PAYLOAD) { ··· 953 902 954 903 /* FIXME: What to do about evt_* errors? */ 955 904 length = (p.header_length + p.payload_length + 3) / 4; 956 - status = cond_le32_to_cpu(buffer[length]); 905 + status = cond_le32_to_cpu(buffer[length], has_be_header_quirk(ohci)); 957 906 evt = (status >> 16) & 0x1f; 958 907 959 908 p.ack = evt - 16; ··· 1868 1817 return ohci->bus_time | cycle_time_seconds; 1869 1818 } 1870 1819 1871 - static int get_status_for_port(struct fw_ohci *ohci, int port_index) 1820 + static int get_status_for_port(struct fw_ohci *ohci, int port_index, 1821 + enum phy_packet_self_id_port_status *status) 1872 1822 { 1873 1823 int reg; 1874 1824 ··· 1883 1831 1884 1832 switch (reg & 0x0f) { 1885 1833 case 0x06: 1886 - return 2; /* is child node (connected to parent node) */ 1834 + // is child node (connected to parent node) 1835 + *status = PHY_PACKET_SELF_ID_PORT_STATUS_PARENT; 1836 + break; 1887 1837 case 0x0e: 1888 - return 3; /* is parent node (connected to child node) */ 1838 + // is parent node (connected to child node) 1839 + *status = PHY_PACKET_SELF_ID_PORT_STATUS_CHILD; 1840 + break; 1841 + default: 1842 + // not connected 1843 + *status = PHY_PACKET_SELF_ID_PORT_STATUS_NCONN; 1844 + break; 1889 1845 } 1890 - return 1; /* not connected */ 1846 + 1847 + return 0; 1891 1848 } 1892 1849 1893 1850 static int get_self_id_pos(struct fw_ohci *ohci, u32 self_id, 1894 1851 int self_id_count) 1895 1852 { 1853 + unsigned int left_phy_id = phy_packet_self_id_get_phy_id(self_id); 1896 1854 int i; 1897 - u32 entry; 1898 1855 1899 1856 for (i = 0; i < self_id_count; i++) { 1900 - entry = ohci->self_id_buffer[i]; 1901 - if ((self_id & 0xff000000) == (entry & 0xff000000)) 1857 + u32 entry = ohci->self_id_buffer[i]; 1858 + unsigned int right_phy_id = phy_packet_self_id_get_phy_id(entry); 1859 + 1860 + if (left_phy_id == right_phy_id) 1902 1861 return -1; 1903 - if ((self_id & 0xff000000) < (entry & 0xff000000)) 1862 + if (left_phy_id < right_phy_id) 1904 1863 return i; 1905 1864 } 1906 1865 return i; 1907 1866 } 1908 1867 1909 - static int initiated_reset(struct fw_ohci *ohci) 1868 + static bool initiated_reset(struct fw_ohci *ohci) 1910 1869 { 1911 1870 int reg; 1912 - int ret = 0; 1871 + int ret = false; 1913 1872 1914 1873 mutex_lock(&ohci->phy_reg_mutex); 1915 1874 reg = write_phy_reg(ohci, 7, 0xe0); /* Select page 7 */ ··· 1933 1870 if (reg >= 0) { 1934 1871 if ((reg & 0x08) == 0x08) { 1935 1872 /* bit 3 indicates "initiated reset" */ 1936 - ret = 0x2; 1873 + ret = true; 1937 1874 } 1938 1875 } 1939 1876 } ··· 1949 1886 */ 1950 1887 static int find_and_insert_self_id(struct fw_ohci *ohci, int self_id_count) 1951 1888 { 1952 - int reg, i, pos, status; 1953 - /* link active 1, speed 3, bridge 0, contender 1, more packets 0 */ 1954 - u32 self_id = 0x8040c800; 1889 + int reg, i, pos; 1890 + u32 self_id = 0; 1891 + 1892 + // link active 1, speed 3, bridge 0, contender 1, more packets 0. 1893 + phy_packet_set_packet_identifier(&self_id, PHY_PACKET_PACKET_IDENTIFIER_SELF_ID); 1894 + phy_packet_self_id_zero_set_link_active(&self_id, true); 1895 + phy_packet_self_id_zero_set_scode(&self_id, SCODE_800); 1896 + phy_packet_self_id_zero_set_contender(&self_id, true); 1955 1897 1956 1898 reg = reg_read(ohci, OHCI1394_NodeID); 1957 1899 if (!(reg & OHCI1394_NodeID_idValid)) { ··· 1964 1896 "node ID not valid, new bus reset in progress\n"); 1965 1897 return -EBUSY; 1966 1898 } 1967 - self_id |= ((reg & 0x3f) << 24); /* phy ID */ 1899 + phy_packet_self_id_set_phy_id(&self_id, reg & 0x3f); 1968 1900 1969 1901 reg = ohci_read_phy_reg(&ohci->card, 4); 1970 1902 if (reg < 0) 1971 1903 return reg; 1972 - self_id |= ((reg & 0x07) << 8); /* power class */ 1904 + phy_packet_self_id_zero_set_power_class(&self_id, reg & 0x07); 1973 1905 1974 1906 reg = ohci_read_phy_reg(&ohci->card, 1); 1975 1907 if (reg < 0) 1976 1908 return reg; 1977 - self_id |= ((reg & 0x3f) << 16); /* gap count */ 1909 + phy_packet_self_id_zero_set_gap_count(&self_id, reg & 0x3f); 1978 1910 1979 1911 for (i = 0; i < 3; i++) { 1980 - status = get_status_for_port(ohci, i); 1981 - if (status < 0) 1982 - return status; 1983 - self_id |= ((status & 0x3) << (6 - (i * 2))); 1912 + enum phy_packet_self_id_port_status status; 1913 + int err; 1914 + 1915 + err = get_status_for_port(ohci, i, &status); 1916 + if (err < 0) 1917 + return err; 1918 + 1919 + self_id_sequence_set_port_status(&self_id, 1, i, status); 1984 1920 } 1985 1921 1986 - self_id |= initiated_reset(ohci); 1922 + phy_packet_self_id_zero_set_initiated_reset(&self_id, initiated_reset(ohci)); 1987 1923 1988 1924 pos = get_self_id_pos(ohci, self_id, self_id_count); 1989 1925 if (pos >= 0) { ··· 2005 1933 struct fw_ohci *ohci = 2006 1934 container_of(work, struct fw_ohci, bus_reset_work); 2007 1935 int self_id_count, generation, new_generation, i, j; 2008 - u32 reg; 1936 + u32 reg, quadlet; 2009 1937 void *free_rom = NULL; 2010 1938 dma_addr_t free_rom_bus = 0; 2011 1939 bool is_new_root; ··· 2030 1958 ohci->is_root = is_new_root; 2031 1959 2032 1960 reg = reg_read(ohci, OHCI1394_SelfIDCount); 2033 - if (reg & OHCI1394_SelfIDCount_selfIDError) { 1961 + if (ohci1394_self_id_count_is_error(reg)) { 2034 1962 ohci_notice(ohci, "self ID receive error\n"); 2035 1963 return; 2036 1964 } ··· 2040 1968 * the inverted quadlets and a header quadlet, we shift one 2041 1969 * bit extra to get the actual number of self IDs. 2042 1970 */ 2043 - self_id_count = (reg >> 3) & 0xff; 1971 + self_id_count = ohci1394_self_id_count_get_size(reg) >> 1; 2044 1972 2045 1973 if (self_id_count > 252) { 2046 1974 ohci_notice(ohci, "bad selfIDSize (%08x)\n", reg); 2047 1975 return; 2048 1976 } 2049 1977 2050 - generation = (cond_le32_to_cpu(ohci->self_id[0]) >> 16) & 0xff; 1978 + quadlet = cond_le32_to_cpu(ohci->self_id[0], has_be_header_quirk(ohci)); 1979 + generation = ohci1394_self_id_receive_q0_get_generation(quadlet); 2051 1980 rmb(); 2052 1981 2053 1982 for (i = 1, j = 0; j < self_id_count; i += 2, j++) { 2054 - u32 id = cond_le32_to_cpu(ohci->self_id[i]); 2055 - u32 id2 = cond_le32_to_cpu(ohci->self_id[i + 1]); 1983 + u32 id = cond_le32_to_cpu(ohci->self_id[i], has_be_header_quirk(ohci)); 1984 + u32 id2 = cond_le32_to_cpu(ohci->self_id[i + 1], has_be_header_quirk(ohci)); 2056 1985 2057 1986 if (id != ~id2) { 2058 1987 /* ··· 2105 2032 * of self IDs. 2106 2033 */ 2107 2034 2108 - new_generation = (reg_read(ohci, OHCI1394_SelfIDCount) >> 16) & 0xff; 2035 + reg = reg_read(ohci, OHCI1394_SelfIDCount); 2036 + new_generation = ohci1394_self_id_count_get_generation(reg); 2109 2037 if (new_generation != generation) { 2110 2038 ohci_notice(ohci, "new bus reset, discarding self ids\n"); 2111 2039 return; ··· 2204 2130 */ 2205 2131 reg_write(ohci, OHCI1394_IntEventClear, 2206 2132 event & ~(OHCI1394_busReset | OHCI1394_postedWriteErr)); 2133 + trace_irqs(ohci->card.index, event); 2207 2134 log_irqs(ohci, event); 2208 2135 // The flag is masked again at bus_reset_work() scheduled by selfID event. 2209 2136 if (event & OHCI1394_busReset) 2210 2137 reg_write(ohci, OHCI1394_IntMaskClear, OHCI1394_busReset); 2211 2138 2212 - if (event & OHCI1394_selfIDComplete) 2139 + if (event & OHCI1394_selfIDComplete) { 2140 + if (trace_self_id_complete_enabled()) { 2141 + u32 reg = reg_read(ohci, OHCI1394_SelfIDCount); 2142 + 2143 + trace_self_id_complete(ohci->card.index, reg, ohci->self_id, 2144 + has_be_header_quirk(ohci)); 2145 + } 2213 2146 queue_work(selfid_workqueue, &ohci->bus_reset_work); 2147 + } 2214 2148 2215 2149 if (event & OHCI1394_RQPkt) 2216 2150 tasklet_schedule(&ohci->ar_request_ctx.tasklet); ··· 2863 2781 } 2864 2782 } 2865 2783 2866 - static void flush_iso_completions(struct iso_context *ctx) 2784 + static void flush_iso_completions(struct iso_context *ctx, enum fw_iso_context_completions_cause cause) 2867 2785 { 2786 + trace_isoc_inbound_single_completions(&ctx->base, ctx->last_timestamp, cause, ctx->header, 2787 + ctx->header_length); 2788 + trace_isoc_outbound_completions(&ctx->base, ctx->last_timestamp, cause, ctx->header, 2789 + ctx->header_length); 2790 + 2868 2791 ctx->base.callback.sc(&ctx->base, ctx->last_timestamp, 2869 2792 ctx->header_length, ctx->header, 2870 2793 ctx->base.callback_data); ··· 2883 2796 if (ctx->header_length + ctx->base.header_size > PAGE_SIZE) { 2884 2797 if (ctx->base.drop_overflow_headers) 2885 2798 return; 2886 - flush_iso_completions(ctx); 2799 + flush_iso_completions(ctx, FW_ISO_CONTEXT_COMPLETIONS_CAUSE_HEADER_OVERFLOW); 2887 2800 } 2888 2801 2889 2802 ctx_hdr = ctx->header + ctx->header_length; ··· 2932 2845 copy_iso_headers(ctx, (u32 *) (last + 1)); 2933 2846 2934 2847 if (last->control & cpu_to_le16(DESCRIPTOR_IRQ_ALWAYS)) 2935 - flush_iso_completions(ctx); 2848 + flush_iso_completions(ctx, FW_ISO_CONTEXT_COMPLETIONS_CAUSE_IRQ); 2936 2849 2937 2850 return 1; 2938 2851 } ··· 2967 2880 completed, DMA_FROM_DEVICE); 2968 2881 2969 2882 if (last->control & cpu_to_le16(DESCRIPTOR_IRQ_ALWAYS)) { 2883 + trace_isoc_inbound_multiple_completions(&ctx->base, completed, 2884 + FW_ISO_CONTEXT_COMPLETIONS_CAUSE_IRQ); 2885 + 2970 2886 ctx->base.callback.mc(&ctx->base, 2971 2887 buffer_dma + completed, 2972 2888 ctx->base.callback_data); ··· 2985 2895 ctx->mc_buffer_bus & PAGE_MASK, 2986 2896 ctx->mc_buffer_bus & ~PAGE_MASK, 2987 2897 ctx->mc_completed, DMA_FROM_DEVICE); 2898 + 2899 + trace_isoc_inbound_multiple_completions(&ctx->base, ctx->mc_completed, 2900 + FW_ISO_CONTEXT_COMPLETIONS_CAUSE_FLUSH); 2988 2901 2989 2902 ctx->base.callback.mc(&ctx->base, 2990 2903 ctx->mc_buffer_bus + ctx->mc_completed, ··· 3053 2960 if (ctx->header_length + 4 > PAGE_SIZE) { 3054 2961 if (ctx->base.drop_overflow_headers) 3055 2962 return 1; 3056 - flush_iso_completions(ctx); 2963 + flush_iso_completions(ctx, FW_ISO_CONTEXT_COMPLETIONS_CAUSE_HEADER_OVERFLOW); 3057 2964 } 3058 2965 3059 2966 ctx_hdr = ctx->header + ctx->header_length; ··· 3064 2971 ctx->header_length += 4; 3065 2972 3066 2973 if (last->control & cpu_to_le16(DESCRIPTOR_IRQ_ALWAYS)) 3067 - flush_iso_completions(ctx); 2974 + flush_iso_completions(ctx, FW_ISO_CONTEXT_COMPLETIONS_CAUSE_IRQ); 3068 2975 3069 2976 return 1; 3070 2977 } ··· 3629 3536 case FW_ISO_CONTEXT_TRANSMIT: 3630 3537 case FW_ISO_CONTEXT_RECEIVE: 3631 3538 if (ctx->header_length != 0) 3632 - flush_iso_completions(ctx); 3539 + flush_iso_completions(ctx, FW_ISO_CONTEXT_COMPLETIONS_CAUSE_FLUSH); 3633 3540 break; 3634 3541 case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL: 3635 3542 if (ctx->mc_completed != 0)
+42 -1
drivers/firewire/ohci.h
··· 31 31 #define OHCI1394_HCControl_softReset 0x00010000 32 32 #define OHCI1394_SelfIDBuffer 0x064 33 33 #define OHCI1394_SelfIDCount 0x068 34 - #define OHCI1394_SelfIDCount_selfIDError 0x80000000 35 34 #define OHCI1394_IRMultiChanMaskHiSet 0x070 36 35 #define OHCI1394_IRMultiChanMaskHiClear 0x074 37 36 #define OHCI1394_IRMultiChanMaskLoSet 0x078 ··· 154 155 #define OHCI1394_evt_flushed 0xf 155 156 156 157 #define OHCI1394_phy_tcode 0xe 158 + 159 + // Self-ID DMA. 160 + 161 + #define OHCI1394_SelfIDCount_selfIDError_MASK 0x80000000 162 + #define OHCI1394_SelfIDCount_selfIDError_SHIFT 31 163 + #define OHCI1394_SelfIDCount_selfIDGeneration_MASK 0x00ff0000 164 + #define OHCI1394_SelfIDCount_selfIDGeneration_SHIFT 16 165 + #define OHCI1394_SelfIDCount_selfIDSize_MASK 0x000007fc 166 + #define OHCI1394_SelfIDCount_selfIDSize_SHIFT 2 167 + 168 + static inline bool ohci1394_self_id_count_is_error(u32 value) 169 + { 170 + return !!((value & OHCI1394_SelfIDCount_selfIDError_MASK) >> OHCI1394_SelfIDCount_selfIDError_SHIFT); 171 + } 172 + 173 + static inline u8 ohci1394_self_id_count_get_generation(u32 value) 174 + { 175 + return (value & OHCI1394_SelfIDCount_selfIDGeneration_MASK) >> OHCI1394_SelfIDCount_selfIDGeneration_SHIFT; 176 + } 177 + 178 + // In 1394 OHCI specification, the maximum size of self ID stream is 504 quadlets 179 + // (= 63 devices * 4 self ID packets * 2 quadlets). The selfIDSize field accommodates it and its 180 + // additional first quadlet, since the field is 9 bits (0x1ff = 511). 181 + static inline u32 ohci1394_self_id_count_get_size(u32 value) 182 + { 183 + return (value & OHCI1394_SelfIDCount_selfIDSize_MASK) >> OHCI1394_SelfIDCount_selfIDSize_SHIFT; 184 + } 185 + 186 + #define OHCI1394_SELF_ID_RECEIVE_Q0_GENERATION_MASK 0x00ff0000 187 + #define OHCI1394_SELF_ID_RECEIVE_Q0_GENERATION_SHIFT 16 188 + #define OHCI1394_SELF_ID_RECEIVE_Q0_TIMESTAMP_MASK 0x0000ffff 189 + #define OHCI1394_SELF_ID_RECEIVE_Q0_TIMESTAMP_SHIFT 0 190 + 191 + static inline u8 ohci1394_self_id_receive_q0_get_generation(u32 quadlet0) 192 + { 193 + return (quadlet0 & OHCI1394_SELF_ID_RECEIVE_Q0_GENERATION_MASK) >> OHCI1394_SELF_ID_RECEIVE_Q0_GENERATION_SHIFT; 194 + } 195 + 196 + static inline u16 ohci1394_self_id_receive_q0_get_timestamp(u32 quadlet0) 197 + { 198 + return (quadlet0 & OHCI1394_SELF_ID_RECEIVE_Q0_TIMESTAMP_MASK) >> OHCI1394_SELF_ID_RECEIVE_Q0_TIMESTAMP_SHIFT; 199 + } 157 200 158 201 #endif /* _FIREWIRE_OHCI_H */
+2
drivers/firewire/packet-header-definitions.h
··· 7 7 #ifndef _FIREWIRE_PACKET_HEADER_DEFINITIONS_H 8 8 #define _FIREWIRE_PACKET_HEADER_DEFINITIONS_H 9 9 10 + #include <linux/types.h> 11 + 10 12 #define ASYNC_HEADER_QUADLET_COUNT 4 11 13 12 14 #define ASYNC_HEADER_Q0_DESTINATION_SHIFT 16
+334
drivers/firewire/packet-serdes-test.c
··· 10 10 #include <linux/firewire-constants.h> 11 11 12 12 #include "packet-header-definitions.h" 13 + #include "phy-packet-definitions.h" 13 14 14 15 static void serialize_async_header_common(u32 header[ASYNC_HEADER_QUADLET_COUNT], 15 16 unsigned int dst_id, unsigned int tlabel, ··· 186 185 *channel = isoc_header_get_channel(header); 187 186 *tcode = isoc_header_get_tcode(header); 188 187 *sy = isoc_header_get_sy(header); 188 + } 189 + 190 + static void serialize_phy_packet_self_id_zero(u32 *quadlet, unsigned int packet_identifier, 191 + unsigned int phy_id, bool extended, 192 + bool link_is_active, unsigned int gap_count, 193 + unsigned int scode, bool is_contender, 194 + unsigned int power_class, bool is_initiated_reset, 195 + bool has_more_packets) 196 + { 197 + phy_packet_set_packet_identifier(quadlet, packet_identifier); 198 + phy_packet_self_id_set_phy_id(quadlet, phy_id); 199 + phy_packet_self_id_set_extended(quadlet, extended); 200 + phy_packet_self_id_zero_set_link_active(quadlet, link_is_active); 201 + phy_packet_self_id_zero_set_gap_count(quadlet, gap_count); 202 + phy_packet_self_id_zero_set_scode(quadlet, scode); 203 + phy_packet_self_id_zero_set_contender(quadlet, is_contender); 204 + phy_packet_self_id_zero_set_power_class(quadlet, power_class); 205 + phy_packet_self_id_zero_set_initiated_reset(quadlet, is_initiated_reset); 206 + phy_packet_self_id_set_more_packets(quadlet, has_more_packets); 207 + } 208 + 209 + static void deserialize_phy_packet_self_id_zero(u32 quadlet, unsigned int *packet_identifier, 210 + unsigned int *phy_id, bool *extended, 211 + bool *link_is_active, unsigned int *gap_count, 212 + unsigned int *scode, bool *is_contender, 213 + unsigned int *power_class, 214 + bool *is_initiated_reset, bool *has_more_packets) 215 + { 216 + *packet_identifier = phy_packet_get_packet_identifier(quadlet); 217 + *phy_id = phy_packet_self_id_get_phy_id(quadlet); 218 + *extended = phy_packet_self_id_get_extended(quadlet); 219 + *link_is_active = phy_packet_self_id_zero_get_link_active(quadlet); 220 + *gap_count = phy_packet_self_id_zero_get_gap_count(quadlet); 221 + *scode = phy_packet_self_id_zero_get_scode(quadlet); 222 + *is_contender = phy_packet_self_id_zero_get_contender(quadlet); 223 + *power_class = phy_packet_self_id_zero_get_power_class(quadlet); 224 + *is_initiated_reset = phy_packet_self_id_zero_get_initiated_reset(quadlet); 225 + *has_more_packets = phy_packet_self_id_get_more_packets(quadlet); 226 + } 227 + 228 + static void serialize_phy_packet_self_id_extended(u32 *quadlet, unsigned int packet_identifier, 229 + unsigned int phy_id, bool extended, 230 + unsigned int sequence, bool has_more_packets) 231 + { 232 + phy_packet_set_packet_identifier(quadlet, packet_identifier); 233 + phy_packet_self_id_set_phy_id(quadlet, phy_id); 234 + phy_packet_self_id_set_extended(quadlet, extended); 235 + phy_packet_self_id_extended_set_sequence(quadlet, sequence); 236 + phy_packet_self_id_set_more_packets(quadlet, has_more_packets); 237 + } 238 + 239 + static void deserialize_phy_packet_self_id_extended(u32 quadlet, unsigned int *packet_identifier, 240 + unsigned int *phy_id, bool *extended, 241 + unsigned int *sequence, bool *has_more_packets) 242 + { 243 + *packet_identifier = phy_packet_get_packet_identifier(quadlet); 244 + *phy_id = phy_packet_self_id_get_phy_id(quadlet); 245 + *extended = phy_packet_self_id_get_extended(quadlet); 246 + *sequence = phy_packet_self_id_extended_get_sequence(quadlet); 247 + *has_more_packets = phy_packet_self_id_get_more_packets(quadlet); 248 + } 249 + 250 + static void serialize_phy_packet_phy_config(u32 *quadlet, unsigned int packet_identifier, 251 + unsigned int root_id, bool has_force_root_node, 252 + bool has_gap_count_optimization, unsigned int gap_count) 253 + { 254 + phy_packet_set_packet_identifier(quadlet, packet_identifier); 255 + phy_packet_phy_config_set_root_id(quadlet, root_id); 256 + phy_packet_phy_config_set_force_root_node(quadlet, has_force_root_node); 257 + phy_packet_phy_config_set_gap_count_optimization(quadlet, has_gap_count_optimization); 258 + phy_packet_phy_config_set_gap_count(quadlet, gap_count); 259 + } 260 + 261 + static void deserialize_phy_packet_phy_config(u32 quadlet, unsigned int *packet_identifier, 262 + unsigned int *root_id, bool *has_force_root_node, 263 + bool *has_gap_count_optimization, 264 + unsigned int *gap_count) 265 + { 266 + *packet_identifier = phy_packet_get_packet_identifier(quadlet); 267 + *root_id = phy_packet_phy_config_get_root_id(quadlet); 268 + *has_force_root_node = phy_packet_phy_config_get_force_root_node(quadlet); 269 + *has_gap_count_optimization = phy_packet_phy_config_get_gap_count_optimization(quadlet); 270 + *gap_count = phy_packet_phy_config_get_gap_count(quadlet); 189 271 } 190 272 191 273 static void test_async_header_write_quadlet_request(struct kunit *test) ··· 643 559 KUNIT_EXPECT_EQ(test, header, expected); 644 560 } 645 561 562 + static void test_phy_packet_self_id_zero_case0(struct kunit *test) 563 + { 564 + // TSB41AB1/2 with 1 port. 565 + const u32 expected[] = {0x80458c80}; 566 + u32 quadlets[] = {0}; 567 + 568 + unsigned int packet_identifier; 569 + unsigned int phy_id; 570 + bool extended; 571 + bool link_is_active; 572 + unsigned int gap_count; 573 + unsigned int scode; 574 + bool is_contender; 575 + unsigned int power_class; 576 + enum phy_packet_self_id_port_status port_status[3]; 577 + bool is_initiated_reset; 578 + bool has_more_packets; 579 + unsigned int port_index; 580 + 581 + deserialize_phy_packet_self_id_zero(expected[0], &packet_identifier, &phy_id, &extended, 582 + &link_is_active, &gap_count, &scode, &is_contender, 583 + &power_class, &is_initiated_reset, &has_more_packets); 584 + 585 + KUNIT_EXPECT_EQ(test, PHY_PACKET_PACKET_IDENTIFIER_SELF_ID, packet_identifier); 586 + KUNIT_EXPECT_EQ(test, 0, phy_id); 587 + KUNIT_EXPECT_FALSE(test, extended); 588 + KUNIT_EXPECT_TRUE(test, link_is_active); 589 + KUNIT_EXPECT_EQ(test, 0x05, gap_count); 590 + KUNIT_EXPECT_EQ(test, SCODE_400, scode); 591 + KUNIT_EXPECT_TRUE(test, is_contender); 592 + KUNIT_EXPECT_EQ(test, 0x4, power_class); 593 + KUNIT_EXPECT_FALSE(test, is_initiated_reset); 594 + KUNIT_EXPECT_FALSE(test, has_more_packets); 595 + 596 + serialize_phy_packet_self_id_zero(quadlets, packet_identifier, phy_id, extended, 597 + link_is_active, gap_count, scode, is_contender, 598 + power_class, is_initiated_reset, has_more_packets); 599 + 600 + for (port_index = 0; port_index < ARRAY_SIZE(port_status); ++port_index) { 601 + port_status[port_index] = 602 + self_id_sequence_get_port_status(expected, ARRAY_SIZE(expected), port_index); 603 + } 604 + 605 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_PARENT, port_status[0]); 606 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_NONE, port_status[1]); 607 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_NONE, port_status[2]); 608 + 609 + for (port_index = 0; port_index < ARRAY_SIZE(port_status); ++port_index) { 610 + self_id_sequence_set_port_status(quadlets, ARRAY_SIZE(quadlets), port_index, 611 + port_status[port_index]); 612 + } 613 + 614 + KUNIT_EXPECT_MEMEQ(test, quadlets, expected, sizeof(expected)); 615 + } 616 + 617 + static void test_phy_packet_self_id_zero_case1(struct kunit *test) 618 + { 619 + // XIO2213 and TSB81BA3E with 3 ports. 620 + const u32 expected[] = {0x817fcc5e}; 621 + u32 quadlets[] = {0}; 622 + 623 + unsigned int packet_identifier; 624 + unsigned int phy_id; 625 + bool extended; 626 + bool link_is_active; 627 + unsigned int gap_count; 628 + unsigned int scode; 629 + bool is_contender; 630 + unsigned int power_class; 631 + enum phy_packet_self_id_port_status port_status[3]; 632 + bool is_initiated_reset; 633 + bool has_more_packets; 634 + unsigned int port_index; 635 + 636 + deserialize_phy_packet_self_id_zero(expected[0], &packet_identifier, &phy_id, &extended, 637 + &link_is_active, &gap_count, &scode, &is_contender, 638 + &power_class, &is_initiated_reset, &has_more_packets); 639 + 640 + KUNIT_EXPECT_EQ(test, PHY_PACKET_PACKET_IDENTIFIER_SELF_ID, packet_identifier); 641 + KUNIT_EXPECT_EQ(test, 1, phy_id); 642 + KUNIT_EXPECT_FALSE(test, extended); 643 + KUNIT_EXPECT_TRUE(test, link_is_active); 644 + KUNIT_EXPECT_EQ(test, 0x3f, gap_count); 645 + KUNIT_EXPECT_EQ(test, SCODE_800, scode); 646 + KUNIT_EXPECT_TRUE(test, is_contender); 647 + KUNIT_EXPECT_EQ(test, 0x4, power_class); 648 + KUNIT_EXPECT_TRUE(test, is_initiated_reset); 649 + KUNIT_EXPECT_FALSE(test, has_more_packets); 650 + 651 + serialize_phy_packet_self_id_zero(quadlets, packet_identifier, phy_id, extended, 652 + link_is_active, gap_count, scode, is_contender, 653 + power_class, is_initiated_reset, has_more_packets); 654 + 655 + for (port_index = 0; port_index < ARRAY_SIZE(port_status); ++port_index) { 656 + port_status[port_index] = 657 + self_id_sequence_get_port_status(expected, ARRAY_SIZE(expected), port_index); 658 + } 659 + 660 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_NCONN, port_status[0]); 661 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_NCONN, port_status[1]); 662 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_CHILD, port_status[2]); 663 + 664 + for (port_index = 0; port_index < ARRAY_SIZE(port_status); ++port_index) { 665 + self_id_sequence_set_port_status(quadlets, ARRAY_SIZE(quadlets), port_index, 666 + port_status[port_index]); 667 + } 668 + 669 + KUNIT_EXPECT_MEMEQ(test, quadlets, expected, sizeof(expected)); 670 + } 671 + 672 + static void test_phy_packet_self_id_zero_and_one(struct kunit *test) 673 + { 674 + // TSB41LV06A with 6 ports. 675 + const u32 expected[] = { 676 + 0x803f8459, 677 + 0x80815000, 678 + }; 679 + u32 quadlets[] = {0, 0}; 680 + 681 + unsigned int packet_identifier; 682 + unsigned int phy_id; 683 + bool extended; 684 + bool link_is_active; 685 + unsigned int gap_count; 686 + unsigned int scode; 687 + bool is_contender; 688 + unsigned int power_class; 689 + enum phy_packet_self_id_port_status port_status[11]; 690 + bool is_initiated_reset; 691 + bool has_more_packets; 692 + 693 + unsigned int sequence; 694 + unsigned int port_index; 695 + 696 + deserialize_phy_packet_self_id_zero(expected[0], &packet_identifier, &phy_id, &extended, 697 + &link_is_active, &gap_count, &scode, &is_contender, 698 + &power_class, &is_initiated_reset, &has_more_packets); 699 + 700 + KUNIT_EXPECT_EQ(test, PHY_PACKET_PACKET_IDENTIFIER_SELF_ID, packet_identifier); 701 + KUNIT_EXPECT_EQ(test, 0, phy_id); 702 + KUNIT_EXPECT_FALSE(test, extended); 703 + KUNIT_EXPECT_FALSE(test, link_is_active); 704 + KUNIT_EXPECT_EQ(test, 0x3f, gap_count); 705 + KUNIT_EXPECT_EQ(test, SCODE_400, scode); 706 + KUNIT_EXPECT_FALSE(test, is_contender); 707 + KUNIT_EXPECT_EQ(test, 0x4, power_class); 708 + KUNIT_EXPECT_FALSE(test, is_initiated_reset); 709 + KUNIT_EXPECT_TRUE(test, has_more_packets); 710 + 711 + serialize_phy_packet_self_id_zero(quadlets, packet_identifier, phy_id, extended, 712 + link_is_active, gap_count, scode, is_contender, 713 + power_class, is_initiated_reset, has_more_packets); 714 + 715 + deserialize_phy_packet_self_id_extended(expected[1], &packet_identifier, &phy_id, &extended, 716 + &sequence, &has_more_packets); 717 + 718 + KUNIT_EXPECT_EQ(test, PHY_PACKET_PACKET_IDENTIFIER_SELF_ID, packet_identifier); 719 + KUNIT_EXPECT_EQ(test, 0, phy_id); 720 + KUNIT_EXPECT_TRUE(test, extended); 721 + KUNIT_EXPECT_EQ(test, 0, sequence); 722 + KUNIT_EXPECT_FALSE(test, has_more_packets); 723 + 724 + serialize_phy_packet_self_id_extended(&quadlets[1], packet_identifier, phy_id, extended, 725 + sequence, has_more_packets); 726 + 727 + 728 + for (port_index = 0; port_index < ARRAY_SIZE(port_status); ++port_index) { 729 + port_status[port_index] = 730 + self_id_sequence_get_port_status(expected, ARRAY_SIZE(expected), port_index); 731 + } 732 + 733 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_NCONN, port_status[0]); 734 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_NCONN, port_status[1]); 735 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_PARENT, port_status[2]); 736 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_NCONN, port_status[3]); 737 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_NCONN, port_status[4]); 738 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_NCONN, port_status[5]); 739 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_NONE, port_status[6]); 740 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_NONE, port_status[7]); 741 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_NONE, port_status[8]); 742 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_NONE, port_status[9]); 743 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_NONE, port_status[10]); 744 + 745 + for (port_index = 0; port_index < ARRAY_SIZE(port_status); ++port_index) { 746 + self_id_sequence_set_port_status(quadlets, ARRAY_SIZE(quadlets), port_index, 747 + port_status[port_index]); 748 + } 749 + 750 + KUNIT_EXPECT_MEMEQ(test, quadlets, expected, sizeof(expected)); 751 + } 752 + 753 + static void test_phy_packet_phy_config_force_root_node(struct kunit *test) 754 + { 755 + const u32 expected = 0x02800000; 756 + u32 quadlet = 0; 757 + 758 + unsigned int packet_identifier; 759 + unsigned int root_id; 760 + bool has_force_root_node; 761 + bool has_gap_count_optimization; 762 + unsigned int gap_count; 763 + 764 + deserialize_phy_packet_phy_config(expected, &packet_identifier, &root_id, 765 + &has_force_root_node, &has_gap_count_optimization, 766 + &gap_count); 767 + 768 + KUNIT_EXPECT_EQ(test, PHY_PACKET_PACKET_IDENTIFIER_PHY_CONFIG, packet_identifier); 769 + KUNIT_EXPECT_EQ(test, 0x02, root_id); 770 + KUNIT_EXPECT_TRUE(test, has_force_root_node); 771 + KUNIT_EXPECT_FALSE(test, has_gap_count_optimization); 772 + KUNIT_EXPECT_EQ(test, 0, gap_count); 773 + 774 + serialize_phy_packet_phy_config(&quadlet, packet_identifier, root_id, has_force_root_node, 775 + has_gap_count_optimization, gap_count); 776 + 777 + KUNIT_EXPECT_EQ(test, quadlet, expected); 778 + } 779 + 780 + static void test_phy_packet_phy_config_gap_count_optimization(struct kunit *test) 781 + { 782 + const u32 expected = 0x034f0000; 783 + u32 quadlet = 0; 784 + 785 + unsigned int packet_identifier; 786 + unsigned int root_id; 787 + bool has_force_root_node; 788 + bool has_gap_count_optimization; 789 + unsigned int gap_count; 790 + 791 + deserialize_phy_packet_phy_config(expected, &packet_identifier, &root_id, 792 + &has_force_root_node, &has_gap_count_optimization, 793 + &gap_count); 794 + 795 + KUNIT_EXPECT_EQ(test, PHY_PACKET_PACKET_IDENTIFIER_PHY_CONFIG, packet_identifier); 796 + KUNIT_EXPECT_EQ(test, 0x03, root_id); 797 + KUNIT_EXPECT_FALSE(test, has_force_root_node); 798 + KUNIT_EXPECT_TRUE(test, has_gap_count_optimization); 799 + KUNIT_EXPECT_EQ(test, 0x0f, gap_count); 800 + 801 + serialize_phy_packet_phy_config(&quadlet, packet_identifier, root_id, has_force_root_node, 802 + has_gap_count_optimization, gap_count); 803 + 804 + KUNIT_EXPECT_EQ(test, quadlet, expected); 805 + } 806 + 646 807 static struct kunit_case packet_serdes_test_cases[] = { 647 808 KUNIT_CASE(test_async_header_write_quadlet_request), 648 809 KUNIT_CASE(test_async_header_write_block_request), ··· 899 570 KUNIT_CASE(test_async_header_lock_request), 900 571 KUNIT_CASE(test_async_header_lock_response), 901 572 KUNIT_CASE(test_isoc_header), 573 + KUNIT_CASE(test_phy_packet_self_id_zero_case0), 574 + KUNIT_CASE(test_phy_packet_self_id_zero_case1), 575 + KUNIT_CASE(test_phy_packet_self_id_zero_and_one), 576 + KUNIT_CASE(test_phy_packet_phy_config_force_root_node), 577 + KUNIT_CASE(test_phy_packet_phy_config_gap_count_optimization), 902 578 {} 903 579 }; 904 580
+302
drivers/firewire/phy-packet-definitions.h
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + // 3 + // phy-packet-definitions.h - The definitions of phy packet for IEEE 1394. 4 + // 5 + // Copyright (c) 2024 Takashi Sakamoto 6 + 7 + #ifndef _FIREWIRE_PHY_PACKET_DEFINITIONS_H 8 + #define _FIREWIRE_PHY_PACKET_DEFINITIONS_H 9 + 10 + #define PACKET_IDENTIFIER_MASK 0xc0000000 11 + #define PACKET_IDENTIFIER_SHIFT 30 12 + 13 + static inline unsigned int phy_packet_get_packet_identifier(u32 quadlet) 14 + { 15 + return (quadlet & PACKET_IDENTIFIER_MASK) >> PACKET_IDENTIFIER_SHIFT; 16 + } 17 + 18 + static inline void phy_packet_set_packet_identifier(u32 *quadlet, unsigned int packet_identifier) 19 + { 20 + *quadlet &= ~PACKET_IDENTIFIER_MASK; 21 + *quadlet |= (packet_identifier << PACKET_IDENTIFIER_SHIFT) & PACKET_IDENTIFIER_MASK; 22 + } 23 + 24 + #define PHY_PACKET_PACKET_IDENTIFIER_PHY_CONFIG 0 25 + 26 + #define PHY_CONFIG_ROOT_ID_MASK 0x3f000000 27 + #define PHY_CONFIG_ROOT_ID_SHIFT 24 28 + #define PHY_CONFIG_FORCE_ROOT_NODE_MASK 0x00800000 29 + #define PHY_CONFIG_FORCE_ROOT_NODE_SHIFT 23 30 + #define PHY_CONFIG_GAP_COUNT_OPTIMIZATION_MASK 0x00400000 31 + #define PHY_CONFIG_GAP_COUNT_OPTIMIZATION_SHIFT 22 32 + #define PHY_CONFIG_GAP_COUNT_MASK 0x003f0000 33 + #define PHY_CONFIG_GAP_COUNT_SHIFT 16 34 + 35 + static inline unsigned int phy_packet_phy_config_get_root_id(u32 quadlet) 36 + { 37 + return (quadlet & PHY_CONFIG_ROOT_ID_MASK) >> PHY_CONFIG_ROOT_ID_SHIFT; 38 + } 39 + 40 + static inline void phy_packet_phy_config_set_root_id(u32 *quadlet, unsigned int root_id) 41 + { 42 + *quadlet &= ~PHY_CONFIG_ROOT_ID_MASK; 43 + *quadlet |= (root_id << PHY_CONFIG_ROOT_ID_SHIFT) & PHY_CONFIG_ROOT_ID_MASK; 44 + } 45 + 46 + static inline bool phy_packet_phy_config_get_force_root_node(u32 quadlet) 47 + { 48 + return (quadlet & PHY_CONFIG_FORCE_ROOT_NODE_MASK) >> PHY_CONFIG_FORCE_ROOT_NODE_SHIFT; 49 + } 50 + 51 + static inline void phy_packet_phy_config_set_force_root_node(u32 *quadlet, bool has_force_root_node) 52 + { 53 + *quadlet &= ~PHY_CONFIG_FORCE_ROOT_NODE_MASK; 54 + *quadlet |= (has_force_root_node << PHY_CONFIG_FORCE_ROOT_NODE_SHIFT) & PHY_CONFIG_FORCE_ROOT_NODE_MASK; 55 + } 56 + 57 + static inline bool phy_packet_phy_config_get_gap_count_optimization(u32 quadlet) 58 + { 59 + return (quadlet & PHY_CONFIG_GAP_COUNT_OPTIMIZATION_MASK) >> PHY_CONFIG_GAP_COUNT_OPTIMIZATION_SHIFT; 60 + } 61 + 62 + static inline void phy_packet_phy_config_set_gap_count_optimization(u32 *quadlet, bool has_gap_count_optimization) 63 + { 64 + *quadlet &= ~PHY_CONFIG_GAP_COUNT_OPTIMIZATION_MASK; 65 + *quadlet |= (has_gap_count_optimization << PHY_CONFIG_GAP_COUNT_OPTIMIZATION_SHIFT) & PHY_CONFIG_GAP_COUNT_OPTIMIZATION_MASK; 66 + } 67 + 68 + static inline unsigned int phy_packet_phy_config_get_gap_count(u32 quadlet) 69 + { 70 + return (quadlet & PHY_CONFIG_GAP_COUNT_MASK) >> PHY_CONFIG_GAP_COUNT_SHIFT; 71 + } 72 + 73 + static inline void phy_packet_phy_config_set_gap_count(u32 *quadlet, unsigned int gap_count) 74 + { 75 + *quadlet &= ~PHY_CONFIG_GAP_COUNT_MASK; 76 + *quadlet |= (gap_count << PHY_CONFIG_GAP_COUNT_SHIFT) & PHY_CONFIG_GAP_COUNT_MASK; 77 + } 78 + 79 + #define PHY_PACKET_PACKET_IDENTIFIER_SELF_ID 2 80 + 81 + #define SELF_ID_PHY_ID_MASK 0x3f000000 82 + #define SELF_ID_PHY_ID_SHIFT 24 83 + #define SELF_ID_EXTENDED_MASK 0x00800000 84 + #define SELF_ID_EXTENDED_SHIFT 23 85 + #define SELF_ID_MORE_PACKETS_MASK 0x00000001 86 + #define SELF_ID_MORE_PACKETS_SHIFT 0 87 + 88 + #define SELF_ID_ZERO_LINK_ACTIVE_MASK 0x00400000 89 + #define SELF_ID_ZERO_LINK_ACTIVE_SHIFT 22 90 + #define SELF_ID_ZERO_GAP_COUNT_MASK 0x003f0000 91 + #define SELF_ID_ZERO_GAP_COUNT_SHIFT 16 92 + #define SELF_ID_ZERO_SCODE_MASK 0x0000c000 93 + #define SELF_ID_ZERO_SCODE_SHIFT 14 94 + #define SELF_ID_ZERO_CONTENDER_MASK 0x00000800 95 + #define SELF_ID_ZERO_CONTENDER_SHIFT 11 96 + #define SELF_ID_ZERO_POWER_CLASS_MASK 0x00000700 97 + #define SELF_ID_ZERO_POWER_CLASS_SHIFT 8 98 + #define SELF_ID_ZERO_INITIATED_RESET_MASK 0x00000002 99 + #define SELF_ID_ZERO_INITIATED_RESET_SHIFT 1 100 + 101 + #define SELF_ID_EXTENDED_SEQUENCE_MASK 0x00700000 102 + #define SELF_ID_EXTENDED_SEQUENCE_SHIFT 20 103 + 104 + #define SELF_ID_PORT_STATUS_MASK 0x3 105 + 106 + #define SELF_ID_SEQUENCE_MAXIMUM_QUADLET_COUNT 4 107 + 108 + static inline unsigned int phy_packet_self_id_get_phy_id(u32 quadlet) 109 + { 110 + return (quadlet & SELF_ID_PHY_ID_MASK) >> SELF_ID_PHY_ID_SHIFT; 111 + } 112 + 113 + static inline void phy_packet_self_id_set_phy_id(u32 *quadlet, unsigned int phy_id) 114 + { 115 + *quadlet &= ~SELF_ID_PHY_ID_MASK; 116 + *quadlet |= (phy_id << SELF_ID_PHY_ID_SHIFT) & SELF_ID_PHY_ID_MASK; 117 + } 118 + 119 + static inline bool phy_packet_self_id_get_extended(u32 quadlet) 120 + { 121 + return (quadlet & SELF_ID_EXTENDED_MASK) >> SELF_ID_EXTENDED_SHIFT; 122 + } 123 + 124 + static inline void phy_packet_self_id_set_extended(u32 *quadlet, bool extended) 125 + { 126 + *quadlet &= ~SELF_ID_EXTENDED_MASK; 127 + *quadlet |= (extended << SELF_ID_EXTENDED_SHIFT) & SELF_ID_EXTENDED_MASK; 128 + } 129 + 130 + static inline bool phy_packet_self_id_zero_get_link_active(u32 quadlet) 131 + { 132 + return (quadlet & SELF_ID_ZERO_LINK_ACTIVE_MASK) >> SELF_ID_ZERO_LINK_ACTIVE_SHIFT; 133 + } 134 + 135 + static inline void phy_packet_self_id_zero_set_link_active(u32 *quadlet, bool is_active) 136 + { 137 + *quadlet &= ~SELF_ID_ZERO_LINK_ACTIVE_MASK; 138 + *quadlet |= (is_active << SELF_ID_ZERO_LINK_ACTIVE_SHIFT) & SELF_ID_ZERO_LINK_ACTIVE_MASK; 139 + } 140 + 141 + static inline unsigned int phy_packet_self_id_zero_get_gap_count(u32 quadlet) 142 + { 143 + return (quadlet & SELF_ID_ZERO_GAP_COUNT_MASK) >> SELF_ID_ZERO_GAP_COUNT_SHIFT; 144 + } 145 + 146 + static inline void phy_packet_self_id_zero_set_gap_count(u32 *quadlet, unsigned int gap_count) 147 + { 148 + *quadlet &= ~SELF_ID_ZERO_GAP_COUNT_MASK; 149 + *quadlet |= (gap_count << SELF_ID_ZERO_GAP_COUNT_SHIFT) & SELF_ID_ZERO_GAP_COUNT_MASK; 150 + } 151 + 152 + static inline unsigned int phy_packet_self_id_zero_get_scode(u32 quadlet) 153 + { 154 + return (quadlet & SELF_ID_ZERO_SCODE_MASK) >> SELF_ID_ZERO_SCODE_SHIFT; 155 + } 156 + 157 + static inline void phy_packet_self_id_zero_set_scode(u32 *quadlet, unsigned int speed) 158 + { 159 + *quadlet &= ~SELF_ID_ZERO_SCODE_MASK; 160 + *quadlet |= (speed << SELF_ID_ZERO_SCODE_SHIFT) & SELF_ID_ZERO_SCODE_MASK; 161 + } 162 + 163 + static inline bool phy_packet_self_id_zero_get_contender(u32 quadlet) 164 + { 165 + return (quadlet & SELF_ID_ZERO_CONTENDER_MASK) >> SELF_ID_ZERO_CONTENDER_SHIFT; 166 + } 167 + 168 + static inline void phy_packet_self_id_zero_set_contender(u32 *quadlet, bool is_contender) 169 + { 170 + *quadlet &= ~SELF_ID_ZERO_CONTENDER_MASK; 171 + *quadlet |= (is_contender << SELF_ID_ZERO_CONTENDER_SHIFT) & SELF_ID_ZERO_CONTENDER_MASK; 172 + } 173 + 174 + static inline unsigned int phy_packet_self_id_zero_get_power_class(u32 quadlet) 175 + { 176 + return (quadlet & SELF_ID_ZERO_POWER_CLASS_MASK) >> SELF_ID_ZERO_POWER_CLASS_SHIFT; 177 + } 178 + 179 + static inline void phy_packet_self_id_zero_set_power_class(u32 *quadlet, unsigned int power_class) 180 + { 181 + *quadlet &= ~SELF_ID_ZERO_POWER_CLASS_MASK; 182 + *quadlet |= (power_class << SELF_ID_ZERO_POWER_CLASS_SHIFT) & SELF_ID_ZERO_POWER_CLASS_MASK; 183 + } 184 + 185 + static inline bool phy_packet_self_id_zero_get_initiated_reset(u32 quadlet) 186 + { 187 + return (quadlet & SELF_ID_ZERO_INITIATED_RESET_MASK) >> SELF_ID_ZERO_INITIATED_RESET_SHIFT; 188 + } 189 + 190 + static inline void phy_packet_self_id_zero_set_initiated_reset(u32 *quadlet, bool is_initiated_reset) 191 + { 192 + *quadlet &= ~SELF_ID_ZERO_INITIATED_RESET_MASK; 193 + *quadlet |= (is_initiated_reset << SELF_ID_ZERO_INITIATED_RESET_SHIFT) & SELF_ID_ZERO_INITIATED_RESET_MASK; 194 + } 195 + 196 + static inline bool phy_packet_self_id_get_more_packets(u32 quadlet) 197 + { 198 + return (quadlet & SELF_ID_MORE_PACKETS_MASK) >> SELF_ID_MORE_PACKETS_SHIFT; 199 + } 200 + 201 + static inline void phy_packet_self_id_set_more_packets(u32 *quadlet, bool is_more_packets) 202 + { 203 + *quadlet &= ~SELF_ID_MORE_PACKETS_MASK; 204 + *quadlet |= (is_more_packets << SELF_ID_MORE_PACKETS_SHIFT) & SELF_ID_MORE_PACKETS_MASK; 205 + } 206 + 207 + static inline unsigned int phy_packet_self_id_extended_get_sequence(u32 quadlet) 208 + { 209 + return (quadlet & SELF_ID_EXTENDED_SEQUENCE_MASK) >> SELF_ID_EXTENDED_SEQUENCE_SHIFT; 210 + } 211 + 212 + static inline void phy_packet_self_id_extended_set_sequence(u32 *quadlet, unsigned int sequence) 213 + { 214 + *quadlet &= ~SELF_ID_EXTENDED_SEQUENCE_MASK; 215 + *quadlet |= (sequence << SELF_ID_EXTENDED_SHIFT) & SELF_ID_EXTENDED_SEQUENCE_MASK; 216 + } 217 + 218 + struct self_id_sequence_enumerator { 219 + const u32 *cursor; 220 + unsigned int quadlet_count; 221 + }; 222 + 223 + static inline const u32 *self_id_sequence_enumerator_next( 224 + struct self_id_sequence_enumerator *enumerator, unsigned int *quadlet_count) 225 + { 226 + const u32 *self_id_sequence, *cursor; 227 + u32 quadlet; 228 + unsigned int count; 229 + unsigned int sequence; 230 + 231 + if (enumerator->cursor == NULL || enumerator->quadlet_count == 0) 232 + return ERR_PTR(-ENODATA); 233 + cursor = enumerator->cursor; 234 + count = 1; 235 + 236 + quadlet = *cursor; 237 + sequence = 0; 238 + while (phy_packet_self_id_get_more_packets(quadlet)) { 239 + if (count >= enumerator->quadlet_count || 240 + count >= SELF_ID_SEQUENCE_MAXIMUM_QUADLET_COUNT) 241 + return ERR_PTR(-EPROTO); 242 + ++cursor; 243 + ++count; 244 + quadlet = *cursor; 245 + 246 + if (!phy_packet_self_id_get_extended(quadlet) || 247 + sequence != phy_packet_self_id_extended_get_sequence(quadlet)) 248 + return ERR_PTR(-EPROTO); 249 + ++sequence; 250 + } 251 + 252 + *quadlet_count = count; 253 + self_id_sequence = enumerator->cursor; 254 + 255 + enumerator->cursor += count; 256 + enumerator->quadlet_count -= count; 257 + 258 + return self_id_sequence; 259 + } 260 + 261 + enum phy_packet_self_id_port_status { 262 + PHY_PACKET_SELF_ID_PORT_STATUS_NONE = 0, 263 + PHY_PACKET_SELF_ID_PORT_STATUS_NCONN = 1, 264 + PHY_PACKET_SELF_ID_PORT_STATUS_PARENT = 2, 265 + PHY_PACKET_SELF_ID_PORT_STATUS_CHILD = 3, 266 + }; 267 + 268 + static inline unsigned int self_id_sequence_get_port_capacity(unsigned int quadlet_count) 269 + { 270 + return quadlet_count * 8 - 5; 271 + } 272 + 273 + static inline enum phy_packet_self_id_port_status self_id_sequence_get_port_status( 274 + const u32 *self_id_sequence, unsigned int quadlet_count, unsigned int port_index) 275 + { 276 + unsigned int index, shift; 277 + 278 + index = (port_index + 5) / 8; 279 + shift = 16 - ((port_index + 5) % 8) * 2; 280 + 281 + if (index < quadlet_count && index < SELF_ID_SEQUENCE_MAXIMUM_QUADLET_COUNT) 282 + return (self_id_sequence[index] >> shift) & SELF_ID_PORT_STATUS_MASK; 283 + 284 + return PHY_PACKET_SELF_ID_PORT_STATUS_NONE; 285 + } 286 + 287 + static inline void self_id_sequence_set_port_status(u32 *self_id_sequence, unsigned int quadlet_count, 288 + unsigned int port_index, 289 + enum phy_packet_self_id_port_status status) 290 + { 291 + unsigned int index, shift; 292 + 293 + index = (port_index + 5) / 8; 294 + shift = 16 - ((port_index + 5) % 8) * 2; 295 + 296 + if (index < quadlet_count) { 297 + self_id_sequence[index] &= ~(SELF_ID_PORT_STATUS_MASK << shift); 298 + self_id_sequence[index] |= status << shift; 299 + } 300 + } 301 + 302 + #endif // _FIREWIRE_PHY_PACKET_DEFINITIONS_H
+152
drivers/firewire/self-id-sequence-helper-test.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + // 3 + // self-id-sequence-helper-test.c - An application of Kunit to test helpers of self ID sequence. 4 + // 5 + // Copyright (c) 2024 Takashi Sakamoto 6 + 7 + #include <kunit/test.h> 8 + 9 + #include "phy-packet-definitions.h" 10 + 11 + static void test_self_id_sequence_enumerator_valid(struct kunit *test) 12 + { 13 + static const u32 valid_sequences[] = { 14 + 0x00000000, 15 + 0x00000001, 0x00800000, 16 + 0x00000001, 0x00800001, 0x00900000, 17 + 0x00000000, 18 + }; 19 + struct self_id_sequence_enumerator enumerator; 20 + const u32 *entry; 21 + unsigned int quadlet_count; 22 + 23 + enumerator.cursor = valid_sequences; 24 + enumerator.quadlet_count = ARRAY_SIZE(valid_sequences); 25 + 26 + entry = self_id_sequence_enumerator_next(&enumerator, &quadlet_count); 27 + KUNIT_EXPECT_PTR_EQ(test, entry, &valid_sequences[0]); 28 + KUNIT_EXPECT_EQ(test, quadlet_count, 1); 29 + KUNIT_EXPECT_EQ(test, enumerator.quadlet_count, 6); 30 + 31 + entry = self_id_sequence_enumerator_next(&enumerator, &quadlet_count); 32 + KUNIT_EXPECT_PTR_EQ(test, entry, &valid_sequences[1]); 33 + KUNIT_EXPECT_EQ(test, quadlet_count, 2); 34 + KUNIT_EXPECT_EQ(test, enumerator.quadlet_count, 4); 35 + 36 + entry = self_id_sequence_enumerator_next(&enumerator, &quadlet_count); 37 + KUNIT_EXPECT_PTR_EQ(test, entry, &valid_sequences[3]); 38 + KUNIT_EXPECT_EQ(test, quadlet_count, 3); 39 + KUNIT_EXPECT_EQ(test, enumerator.quadlet_count, 1); 40 + 41 + entry = self_id_sequence_enumerator_next(&enumerator, &quadlet_count); 42 + KUNIT_EXPECT_PTR_EQ(test, entry, &valid_sequences[6]); 43 + KUNIT_EXPECT_EQ(test, quadlet_count, 1); 44 + KUNIT_EXPECT_EQ(test, enumerator.quadlet_count, 0); 45 + 46 + entry = self_id_sequence_enumerator_next(&enumerator, &quadlet_count); 47 + KUNIT_EXPECT_EQ(test, PTR_ERR(entry), -ENODATA); 48 + } 49 + 50 + static void test_self_id_sequence_enumerator_invalid(struct kunit *test) 51 + { 52 + static const u32 invalid_sequences[] = { 53 + 0x00000001, 54 + }; 55 + struct self_id_sequence_enumerator enumerator; 56 + const u32 *entry; 57 + unsigned int count; 58 + 59 + enumerator.cursor = invalid_sequences; 60 + enumerator.quadlet_count = ARRAY_SIZE(invalid_sequences); 61 + 62 + entry = self_id_sequence_enumerator_next(&enumerator, &count); 63 + KUNIT_EXPECT_EQ(test, PTR_ERR(entry), -EPROTO); 64 + } 65 + 66 + static void test_self_id_sequence_get_port_status(struct kunit *test) 67 + { 68 + static const u32 expected[] = { 69 + 0x000000e5, 70 + 0x00839e79, 71 + 0x0091e79d, 72 + 0x00a279e4, 73 + }; 74 + u32 quadlets [] = { 75 + 0x00000001, 76 + 0x00800001, 77 + 0x00900001, 78 + 0x00a00000, 79 + }; 80 + enum phy_packet_self_id_port_status port_status[28]; 81 + unsigned int port_capacity; 82 + unsigned int port_index; 83 + 84 + KUNIT_ASSERT_EQ(test, ARRAY_SIZE(expected), ARRAY_SIZE(quadlets)); 85 + 86 + // With an extra port. 87 + port_capacity = self_id_sequence_get_port_capacity(ARRAY_SIZE(expected)) + 1; 88 + KUNIT_ASSERT_EQ(test, port_capacity, ARRAY_SIZE(port_status)); 89 + 90 + for (port_index = 0; port_index < port_capacity; ++port_index) { 91 + port_status[port_index] = 92 + self_id_sequence_get_port_status(expected, ARRAY_SIZE(expected), port_index); 93 + self_id_sequence_set_port_status(quadlets, ARRAY_SIZE(quadlets), port_index, 94 + port_status[port_index]); 95 + } 96 + 97 + // Self ID zero. 98 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_CHILD, port_status[0]); 99 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_PARENT, port_status[1]); 100 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_NCONN, port_status[2]); 101 + 102 + // Self ID one. 103 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_CHILD, port_status[3]); 104 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_PARENT, port_status[4]); 105 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_NCONN, port_status[5]); 106 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_CHILD, port_status[6]); 107 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_PARENT, port_status[7]); 108 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_NCONN, port_status[8]); 109 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_CHILD, port_status[9]); 110 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_PARENT, port_status[10]); 111 + 112 + // Self ID two. 113 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_NCONN, port_status[11]); 114 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_CHILD, port_status[12]); 115 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_PARENT, port_status[13]); 116 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_NCONN, port_status[14]); 117 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_CHILD, port_status[15]); 118 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_PARENT, port_status[16]); 119 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_NCONN, port_status[17]); 120 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_CHILD, port_status[18]); 121 + 122 + // Self ID three. 123 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_PARENT, port_status[19]); 124 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_NCONN, port_status[20]); 125 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_CHILD, port_status[21]); 126 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_PARENT, port_status[22]); 127 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_NCONN, port_status[23]); 128 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_CHILD, port_status[24]); 129 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_PARENT, port_status[25]); 130 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_NCONN, port_status[26]); 131 + 132 + // Our of order. 133 + KUNIT_EXPECT_EQ(test, PHY_PACKET_SELF_ID_PORT_STATUS_NONE, port_status[27]); 134 + 135 + KUNIT_EXPECT_MEMEQ(test, quadlets, expected, sizeof(expected)); 136 + } 137 + 138 + static struct kunit_case self_id_sequence_helper_test_cases[] = { 139 + KUNIT_CASE(test_self_id_sequence_enumerator_valid), 140 + KUNIT_CASE(test_self_id_sequence_enumerator_invalid), 141 + KUNIT_CASE(test_self_id_sequence_get_port_status), 142 + {} 143 + }; 144 + 145 + static struct kunit_suite self_id_sequence_helper_test_suite = { 146 + .name = "self-id-sequence-helper", 147 + .test_cases = self_id_sequence_helper_test_cases, 148 + }; 149 + kunit_test_suite(self_id_sequence_helper_test_suite); 150 + 151 + MODULE_DESCRIPTION("Unit test suite for helpers of self ID sequence"); 152 + MODULE_LICENSE("GPL");
+540 -1
include/trace/events/firewire.h
··· 1 1 // SPDX-License-Identifier: GPL-2.0-or-later 2 2 // Copyright (c) 2024 Takashi Sakamoto 3 3 4 + #undef TRACE_SYSTEM 4 5 #define TRACE_SYSTEM firewire 5 6 6 7 #if !defined(_FIREWIRE_TRACE_EVENT_H) || defined(TRACE_HEADER_MULTI_READ) ··· 12 11 13 12 #include <linux/firewire-constants.h> 14 13 15 - #include "../../../drivers/firewire/packet-header-definitions.h" 14 + // Some macros are defined in 'drivers/firewire/packet-header-definitions.h'. 16 15 17 16 // The content of TP_printk field is preprocessed, then put to the module binary. 18 17 #define ASYNC_HEADER_GET_DESTINATION(header) \ ··· 364 363 __entry->bm_abdicate ? "true" : "false", 365 364 __print_array(__get_dynamic_array(self_ids), 366 365 __get_dynamic_array_len(self_ids) / QUADLET_SIZE, QUADLET_SIZE) 366 + ) 367 + ); 368 + 369 + // Some macros are defined in 'drivers/firewire/phy-packet-definitions.h'. 370 + 371 + // The content of TP_printk field is preprocessed, then put to the module binary. 372 + 373 + #define PHY_PACKET_SELF_ID_GET_PHY_ID(quads) \ 374 + ((((const u32 *)quads)[0] & SELF_ID_PHY_ID_MASK) >> SELF_ID_PHY_ID_SHIFT) 375 + 376 + #define PHY_PACKET_SELF_ID_GET_LINK_ACTIVE(quads) \ 377 + ((((const u32 *)quads)[0] & SELF_ID_ZERO_LINK_ACTIVE_MASK) >> SELF_ID_ZERO_LINK_ACTIVE_SHIFT) 378 + 379 + #define PHY_PACKET_SELF_ID_GET_GAP_COUNT(quads) \ 380 + ((((const u32 *)quads)[0] & SELF_ID_ZERO_GAP_COUNT_MASK) >> SELF_ID_ZERO_GAP_COUNT_SHIFT) 381 + 382 + #define PHY_PACKET_SELF_ID_GET_SCODE(quads) \ 383 + ((((const u32 *)quads)[0] & SELF_ID_ZERO_SCODE_MASK) >> SELF_ID_ZERO_SCODE_SHIFT) 384 + 385 + #define PHY_PACKET_SELF_ID_GET_CONTENDER(quads) \ 386 + ((((const u32 *)quads)[0] & SELF_ID_ZERO_CONTENDER_MASK) >> SELF_ID_ZERO_CONTENDER_SHIFT) 387 + 388 + #define PHY_PACKET_SELF_ID_GET_POWER_CLASS(quads) \ 389 + ((((const u32 *)quads)[0] & SELF_ID_ZERO_POWER_CLASS_MASK) >> SELF_ID_ZERO_POWER_CLASS_SHIFT) 390 + 391 + #define PHY_PACKET_SELF_ID_GET_INITIATED_RESET(quads) \ 392 + ((((const u32 *)quads)[0] & SELF_ID_ZERO_INITIATED_RESET_MASK) >> SELF_ID_ZERO_INITIATED_RESET_SHIFT) 393 + 394 + TRACE_EVENT(self_id_sequence, 395 + TP_PROTO(unsigned int card_index, const u32 *self_id_sequence, unsigned int quadlet_count, unsigned int generation), 396 + TP_ARGS(card_index, self_id_sequence, quadlet_count, generation), 397 + TP_STRUCT__entry( 398 + __field(u8, card_index) 399 + __field(u8, generation) 400 + __dynamic_array(u8, port_status, self_id_sequence_get_port_capacity(quadlet_count)) 401 + __dynamic_array(u32, self_id_sequence, quadlet_count) 402 + ), 403 + TP_fast_assign( 404 + __entry->card_index = card_index; 405 + __entry->generation = generation; 406 + { 407 + u8 *port_status = __get_dynamic_array(port_status); 408 + unsigned int port_index; 409 + 410 + for (port_index = 0; port_index < __get_dynamic_array_len(port_status); ++port_index) { 411 + port_status[port_index] = 412 + self_id_sequence_get_port_status(self_id_sequence, 413 + quadlet_count, port_index); 414 + } 415 + } 416 + memcpy(__get_dynamic_array(self_id_sequence), self_id_sequence, 417 + __get_dynamic_array_len(self_id_sequence)); 418 + ), 419 + TP_printk( 420 + "card_index=%u generation=%u phy_id=0x%02x link_active=%s gap_count=%u scode=%u contender=%s power_class=%u initiated_reset=%s port_status=%s self_id_sequence=%s", 421 + __entry->card_index, 422 + __entry->generation, 423 + PHY_PACKET_SELF_ID_GET_PHY_ID(__get_dynamic_array(self_id_sequence)), 424 + PHY_PACKET_SELF_ID_GET_LINK_ACTIVE(__get_dynamic_array(self_id_sequence)) ? "true" : "false", 425 + PHY_PACKET_SELF_ID_GET_GAP_COUNT(__get_dynamic_array(self_id_sequence)), 426 + PHY_PACKET_SELF_ID_GET_SCODE(__get_dynamic_array(self_id_sequence)), 427 + PHY_PACKET_SELF_ID_GET_CONTENDER(__get_dynamic_array(self_id_sequence)) ? "true" : "false", 428 + PHY_PACKET_SELF_ID_GET_POWER_CLASS(__get_dynamic_array(self_id_sequence)), 429 + PHY_PACKET_SELF_ID_GET_INITIATED_RESET(__get_dynamic_array(self_id_sequence)) ? "true" : "false", 430 + __print_array(__get_dynamic_array(port_status), __get_dynamic_array_len(port_status), 1), 431 + __print_array(__get_dynamic_array(self_id_sequence), 432 + __get_dynamic_array_len(self_id_sequence) / QUADLET_SIZE, QUADLET_SIZE) 433 + ) 434 + ); 435 + 436 + #undef PHY_PACKET_SELF_ID_GET_PHY_ID 437 + #undef PHY_PACKET_SELF_ID_GET_LINK_ACTIVE 438 + #undef PHY_PACKET_SELF_ID_GET_GAP_COUNT 439 + #undef PHY_PACKET_SELF_ID_GET_SCODE 440 + #undef PHY_PACKET_SELF_ID_GET_CONTENDER 441 + #undef PHY_PACKET_SELF_ID_GET_POWER_CLASS 442 + #undef PHY_PACKET_SELF_ID_GET_INITIATED_RESET 443 + 444 + TRACE_EVENT_CONDITION(isoc_outbound_allocate, 445 + TP_PROTO(const struct fw_iso_context *ctx, unsigned int channel, unsigned int scode), 446 + TP_ARGS(ctx, channel, scode), 447 + TP_CONDITION(ctx->type == FW_ISO_CONTEXT_TRANSMIT), 448 + TP_STRUCT__entry( 449 + __field(u64, context) 450 + __field(u8, card_index) 451 + __field(u8, channel) 452 + __field(u8, scode) 453 + ), 454 + TP_fast_assign( 455 + __entry->context = (uintptr_t)ctx; 456 + __entry->card_index = ctx->card->index; 457 + __entry->channel = channel; 458 + __entry->scode = scode; 459 + ), 460 + TP_printk( 461 + "context=0x%llx card_index=%u channel=%u scode=%u", 462 + __entry->context, 463 + __entry->card_index, 464 + __entry->channel, 465 + __entry->scode 466 + ) 467 + ); 468 + 469 + TRACE_EVENT_CONDITION(isoc_inbound_single_allocate, 470 + TP_PROTO(const struct fw_iso_context *ctx, unsigned int channel, unsigned int header_size), 471 + TP_ARGS(ctx, channel, header_size), 472 + TP_CONDITION(ctx->type == FW_ISO_CONTEXT_RECEIVE), 473 + TP_STRUCT__entry( 474 + __field(u64, context) 475 + __field(u8, card_index) 476 + __field(u8, channel) 477 + __field(u8, header_size) 478 + ), 479 + TP_fast_assign( 480 + __entry->context = (uintptr_t)ctx; 481 + __entry->card_index = ctx->card->index; 482 + __entry->channel = channel; 483 + __entry->header_size = header_size; 484 + ), 485 + TP_printk( 486 + "context=0x%llx card_index=%u channel=%u header_size=%u", 487 + __entry->context, 488 + __entry->card_index, 489 + __entry->channel, 490 + __entry->header_size 491 + ) 492 + ); 493 + 494 + TRACE_EVENT_CONDITION(isoc_inbound_multiple_allocate, 495 + TP_PROTO(const struct fw_iso_context *ctx), 496 + TP_ARGS(ctx), 497 + TP_CONDITION(ctx->type == FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL), 498 + TP_STRUCT__entry( 499 + __field(u64, context) 500 + __field(u8, card_index) 501 + ), 502 + TP_fast_assign( 503 + __entry->context = (uintptr_t)ctx; 504 + __entry->card_index = ctx->card->index; 505 + ), 506 + TP_printk( 507 + "context=0x%llx card_index=%u", 508 + __entry->context, 509 + __entry->card_index 510 + ) 511 + ); 512 + 513 + DECLARE_EVENT_CLASS(isoc_destroy_template, 514 + TP_PROTO(const struct fw_iso_context *ctx), 515 + TP_ARGS(ctx), 516 + TP_STRUCT__entry( 517 + __field(u64, context) 518 + __field(u8, card_index) 519 + ), 520 + TP_fast_assign( 521 + __entry->context = (uintptr_t)ctx; 522 + __entry->card_index = ctx->card->index; 523 + ), 524 + TP_printk( 525 + "context=0x%llx card_index=%u", 526 + __entry->context, 527 + __entry->card_index 528 + ) 529 + ) 530 + 531 + DEFINE_EVENT_CONDITION(isoc_destroy_template, isoc_outbound_destroy, 532 + TP_PROTO(const struct fw_iso_context *ctx), 533 + TP_ARGS(ctx), 534 + TP_CONDITION(ctx->type == FW_ISO_CONTEXT_TRANSMIT) 535 + ); 536 + 537 + DEFINE_EVENT_CONDITION(isoc_destroy_template, isoc_inbound_single_destroy, 538 + TP_PROTO(const struct fw_iso_context *ctx), 539 + TP_ARGS(ctx), 540 + TP_CONDITION(ctx->type == FW_ISO_CONTEXT_RECEIVE) 541 + ); 542 + 543 + DEFINE_EVENT_CONDITION(isoc_destroy_template, isoc_inbound_multiple_destroy, 544 + TP_PROTO(const struct fw_iso_context *ctx), 545 + TP_ARGS(ctx), 546 + TP_CONDITION(ctx->type == FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL) 547 + ); 548 + 549 + TRACE_EVENT(isoc_inbound_multiple_channels, 550 + TP_PROTO(const struct fw_iso_context *ctx, u64 channels), 551 + TP_ARGS(ctx, channels), 552 + TP_STRUCT__entry( 553 + __field(u64, context) 554 + __field(u8, card_index) 555 + __field(u64, channels) 556 + ), 557 + TP_fast_assign( 558 + __entry->context = (uintptr_t)ctx; 559 + __entry->card_index = ctx->card->index; 560 + __entry->channels = channels; 561 + ), 562 + TP_printk( 563 + "context=0x%llx card_index=%u channels=0x%016llx", 564 + __entry->context, 565 + __entry->card_index, 566 + __entry->channels 567 + ) 568 + ); 569 + 570 + TRACE_EVENT_CONDITION(isoc_outbound_start, 571 + TP_PROTO(const struct fw_iso_context *ctx, int cycle_match), 572 + TP_ARGS(ctx, cycle_match), 573 + TP_CONDITION(ctx->type == FW_ISO_CONTEXT_TRANSMIT), 574 + TP_STRUCT__entry( 575 + __field(u64, context) 576 + __field(u8, card_index) 577 + __field(bool, cycle_match) 578 + __field(u16, cycle) 579 + ), 580 + TP_fast_assign( 581 + __entry->context = (uintptr_t)ctx; 582 + __entry->card_index = ctx->card->index; 583 + __entry->cycle_match = cycle_match < 0 ? false : true; 584 + __entry->cycle = __entry->cycle_match ? (u16)cycle_match : 0; 585 + ), 586 + TP_printk( 587 + "context=0x%llx card_index=%u cycle_match=%s cycle=0x%04x", 588 + __entry->context, 589 + __entry->card_index, 590 + __entry->cycle_match ? "true" : "false", 591 + __entry->cycle 592 + ) 593 + ); 594 + 595 + DECLARE_EVENT_CLASS(isoc_inbound_start_template, 596 + TP_PROTO(const struct fw_iso_context *ctx, int cycle_match, unsigned int sync, unsigned int tags), 597 + TP_ARGS(ctx, cycle_match, sync, tags), 598 + TP_STRUCT__entry( 599 + __field(u64, context) 600 + __field(u8, card_index) 601 + __field(bool, cycle_match) 602 + __field(u16, cycle) 603 + __field(u8, sync) 604 + __field(u8, tags) 605 + ), 606 + TP_fast_assign( 607 + __entry->context = (uintptr_t)ctx; 608 + __entry->card_index = ctx->card->index; 609 + __entry->cycle_match = cycle_match < 0 ? false : true; 610 + __entry->cycle = __entry->cycle_match ? (u16)cycle_match : 0; 611 + __entry->sync = sync; 612 + __entry->tags = tags; 613 + ), 614 + TP_printk( 615 + "context=0x%llx card_index=%u cycle_match=%s cycle=0x%04x sync=%u tags=%s", 616 + __entry->context, 617 + __entry->card_index, 618 + __entry->cycle_match ? "true" : "false", 619 + __entry->cycle, 620 + __entry->sync, 621 + __print_flags(__entry->tags, "|", 622 + { FW_ISO_CONTEXT_MATCH_TAG0, "0" }, 623 + { FW_ISO_CONTEXT_MATCH_TAG1, "1" }, 624 + { FW_ISO_CONTEXT_MATCH_TAG2, "2" }, 625 + { FW_ISO_CONTEXT_MATCH_TAG3, "3" } 626 + ) 627 + ) 628 + ); 629 + 630 + DEFINE_EVENT_CONDITION(isoc_inbound_start_template, isoc_inbound_single_start, 631 + TP_PROTO(const struct fw_iso_context *ctx, int cycle_match, unsigned int sync, unsigned int tags), 632 + TP_ARGS(ctx, cycle_match, sync, tags), 633 + TP_CONDITION(ctx->type == FW_ISO_CONTEXT_RECEIVE) 634 + ); 635 + 636 + DEFINE_EVENT_CONDITION(isoc_inbound_start_template, isoc_inbound_multiple_start, 637 + TP_PROTO(const struct fw_iso_context *ctx, int cycle_match, unsigned int sync, unsigned int tags), 638 + TP_ARGS(ctx, cycle_match, sync, tags), 639 + TP_CONDITION(ctx->type == FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL) 640 + ); 641 + 642 + DECLARE_EVENT_CLASS(isoc_stop_template, 643 + TP_PROTO(const struct fw_iso_context *ctx), 644 + TP_ARGS(ctx), 645 + TP_STRUCT__entry( 646 + __field(u64, context) 647 + __field(u8, card_index) 648 + ), 649 + TP_fast_assign( 650 + __entry->context = (uintptr_t)ctx; 651 + __entry->card_index = ctx->card->index; 652 + ), 653 + TP_printk( 654 + "context=0x%llx card_index=%u", 655 + __entry->context, 656 + __entry->card_index 657 + ) 658 + ) 659 + 660 + DEFINE_EVENT_CONDITION(isoc_stop_template, isoc_outbound_stop, 661 + TP_PROTO(const struct fw_iso_context *ctx), 662 + TP_ARGS(ctx), 663 + TP_CONDITION(ctx->type == FW_ISO_CONTEXT_TRANSMIT) 664 + ); 665 + 666 + DEFINE_EVENT_CONDITION(isoc_stop_template, isoc_inbound_single_stop, 667 + TP_PROTO(const struct fw_iso_context *ctx), 668 + TP_ARGS(ctx), 669 + TP_CONDITION(ctx->type == FW_ISO_CONTEXT_RECEIVE) 670 + ); 671 + 672 + DEFINE_EVENT_CONDITION(isoc_stop_template, isoc_inbound_multiple_stop, 673 + TP_PROTO(const struct fw_iso_context *ctx), 674 + TP_ARGS(ctx), 675 + TP_CONDITION(ctx->type == FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL) 676 + ); 677 + 678 + DECLARE_EVENT_CLASS(isoc_flush_template, 679 + TP_PROTO(const struct fw_iso_context *ctx), 680 + TP_ARGS(ctx), 681 + TP_STRUCT__entry( 682 + __field(u64, context) 683 + __field(u8, card_index) 684 + ), 685 + TP_fast_assign( 686 + __entry->context = (uintptr_t)ctx; 687 + __entry->card_index = ctx->card->index; 688 + ), 689 + TP_printk( 690 + "context=0x%llx card_index=%u", 691 + __entry->context, 692 + __entry->card_index 693 + ) 694 + ); 695 + 696 + DEFINE_EVENT_CONDITION(isoc_flush_template, isoc_outbound_flush, 697 + TP_PROTO(const struct fw_iso_context *ctx), 698 + TP_ARGS(ctx), 699 + TP_CONDITION(ctx->type == FW_ISO_CONTEXT_TRANSMIT) 700 + ); 701 + 702 + DEFINE_EVENT_CONDITION(isoc_flush_template, isoc_inbound_single_flush, 703 + TP_PROTO(const struct fw_iso_context *ctx), 704 + TP_ARGS(ctx), 705 + TP_CONDITION(ctx->type == FW_ISO_CONTEXT_RECEIVE) 706 + ); 707 + 708 + DEFINE_EVENT_CONDITION(isoc_flush_template, isoc_inbound_multiple_flush, 709 + TP_PROTO(const struct fw_iso_context *ctx), 710 + TP_ARGS(ctx), 711 + TP_CONDITION(ctx->type == FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL) 712 + ); 713 + 714 + DECLARE_EVENT_CLASS(isoc_flush_completions_template, 715 + TP_PROTO(const struct fw_iso_context *ctx), 716 + TP_ARGS(ctx), 717 + TP_STRUCT__entry( 718 + __field(u64, context) 719 + __field(u8, card_index) 720 + ), 721 + TP_fast_assign( 722 + __entry->context = (uintptr_t)ctx; 723 + __entry->card_index = ctx->card->index; 724 + ), 725 + TP_printk( 726 + "context=0x%llx card_index=%u", 727 + __entry->context, 728 + __entry->card_index 729 + ) 730 + ); 731 + 732 + DEFINE_EVENT_CONDITION(isoc_flush_completions_template, isoc_outbound_flush_completions, 733 + TP_PROTO(const struct fw_iso_context *ctx), 734 + TP_ARGS(ctx), 735 + TP_CONDITION(ctx->type == FW_ISO_CONTEXT_TRANSMIT) 736 + ); 737 + 738 + DEFINE_EVENT_CONDITION(isoc_flush_completions_template, isoc_inbound_single_flush_completions, 739 + TP_PROTO(const struct fw_iso_context *ctx), 740 + TP_ARGS(ctx), 741 + TP_CONDITION(ctx->type == FW_ISO_CONTEXT_RECEIVE) 742 + ); 743 + 744 + DEFINE_EVENT_CONDITION(isoc_flush_completions_template, isoc_inbound_multiple_flush_completions, 745 + TP_PROTO(const struct fw_iso_context *ctx), 746 + TP_ARGS(ctx), 747 + TP_CONDITION(ctx->type == FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL) 748 + ); 749 + 750 + #define TP_STRUCT__entry_iso_packet(ctx, buffer_offset, packet) \ 751 + TP_STRUCT__entry( \ 752 + __field(u64, context) \ 753 + __field(u8, card_index) \ 754 + __field(u32, buffer_offset) \ 755 + __field(bool, interrupt) \ 756 + __field(bool, skip) \ 757 + __field(u8, sy) \ 758 + __field(u8, tag) \ 759 + __dynamic_array(u32, header, packet->header_length / QUADLET_SIZE) \ 760 + ) 761 + 762 + #define TP_fast_assign_iso_packet(ctx, buffer_offset, packet) \ 763 + TP_fast_assign( \ 764 + __entry->context = (uintptr_t)ctx; \ 765 + __entry->card_index = ctx->card->index; \ 766 + __entry->buffer_offset = buffer_offset; \ 767 + __entry->interrupt = packet->interrupt; \ 768 + __entry->skip = packet->skip; \ 769 + __entry->sy = packet->sy; \ 770 + __entry->tag = packet->tag; \ 771 + memcpy(__get_dynamic_array(header), packet->header, \ 772 + __get_dynamic_array_len(header)); \ 773 + ) 774 + 775 + TRACE_EVENT_CONDITION(isoc_outbound_queue, 776 + TP_PROTO(const struct fw_iso_context *ctx, unsigned long buffer_offset, const struct fw_iso_packet *packet), 777 + TP_ARGS(ctx, buffer_offset, packet), 778 + TP_CONDITION(ctx->type == FW_ISO_CONTEXT_TRANSMIT), 779 + TP_STRUCT__entry_iso_packet(ctx, buffer_offset, packet), 780 + TP_fast_assign_iso_packet(ctx, buffer_offset, packet), 781 + TP_printk( 782 + "context=0x%llx card_index=%u buffer_offset=0x%x interrupt=%s skip=%s sy=%d tag=%u header=%s", 783 + __entry->context, 784 + __entry->card_index, 785 + __entry->buffer_offset, 786 + __entry->interrupt ? "true" : "false", 787 + __entry->skip ? "true" : "false", 788 + __entry->sy, 789 + __entry->tag, 790 + __print_array(__get_dynamic_array(header), 791 + __get_dynamic_array_len(header) / QUADLET_SIZE, QUADLET_SIZE) 792 + ) 793 + ); 794 + 795 + TRACE_EVENT_CONDITION(isoc_inbound_single_queue, 796 + TP_PROTO(const struct fw_iso_context *ctx, unsigned long buffer_offset, const struct fw_iso_packet *packet), 797 + TP_ARGS(ctx, buffer_offset, packet), 798 + TP_CONDITION(ctx->type == FW_ISO_CONTEXT_RECEIVE), 799 + TP_STRUCT__entry_iso_packet(ctx, buffer_offset, packet), 800 + TP_fast_assign_iso_packet(ctx, buffer_offset, packet), 801 + TP_printk( 802 + "context=0x%llx card_index=%u buffer_offset=0x%x interrupt=%s skip=%s", 803 + __entry->context, 804 + __entry->card_index, 805 + __entry->buffer_offset, 806 + __entry->interrupt ? "true" : "false", 807 + __entry->skip ? "true" : "false" 808 + ) 809 + ); 810 + 811 + TRACE_EVENT_CONDITION(isoc_inbound_multiple_queue, 812 + TP_PROTO(const struct fw_iso_context *ctx, unsigned long buffer_offset, const struct fw_iso_packet *packet), 813 + TP_ARGS(ctx, buffer_offset, packet), 814 + TP_CONDITION(ctx->type == FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL), 815 + TP_STRUCT__entry_iso_packet(ctx, buffer_offset, packet), 816 + TP_fast_assign_iso_packet(ctx, buffer_offset, packet), 817 + TP_printk( 818 + "context=0x%llx card_index=%u buffer_offset=0x%x interrupt=%s", 819 + __entry->context, 820 + __entry->card_index, 821 + __entry->buffer_offset, 822 + __entry->interrupt ? "true" : "false" 823 + ) 824 + ); 825 + 826 + #undef TP_STRUCT__entry_iso_packet 827 + #undef TP_fast_assign_iso_packet 828 + 829 + #ifndef show_cause 830 + enum fw_iso_context_completions_cause { 831 + FW_ISO_CONTEXT_COMPLETIONS_CAUSE_FLUSH = 0, 832 + FW_ISO_CONTEXT_COMPLETIONS_CAUSE_IRQ, 833 + FW_ISO_CONTEXT_COMPLETIONS_CAUSE_HEADER_OVERFLOW, 834 + }; 835 + #define show_cause(cause) \ 836 + __print_symbolic(cause, \ 837 + { FW_ISO_CONTEXT_COMPLETIONS_CAUSE_FLUSH, "FLUSH" }, \ 838 + { FW_ISO_CONTEXT_COMPLETIONS_CAUSE_IRQ, "IRQ" }, \ 839 + { FW_ISO_CONTEXT_COMPLETIONS_CAUSE_HEADER_OVERFLOW, "HEADER_OVERFLOW" } \ 840 + ) 841 + #endif 842 + 843 + DECLARE_EVENT_CLASS(isoc_single_completions_template, 844 + TP_PROTO(const struct fw_iso_context *ctx, u16 timestamp, enum fw_iso_context_completions_cause cause, const u32 *header, unsigned int header_length), 845 + TP_ARGS(ctx, timestamp, cause, header, header_length), 846 + TP_STRUCT__entry( 847 + __field(u64, context) 848 + __field(u8, card_index) 849 + __field(u16, timestamp) 850 + __field(u8, cause) 851 + __dynamic_array(u32, header, header_length / QUADLET_SIZE) 852 + ), 853 + TP_fast_assign( 854 + __entry->context = (uintptr_t)ctx; 855 + __entry->card_index = ctx->card->index; 856 + __entry->timestamp = timestamp; 857 + __entry->cause = cause; 858 + memcpy(__get_dynamic_array(header), header, __get_dynamic_array_len(header)); 859 + ), 860 + TP_printk( 861 + "context=0x%llx card_index=%u timestamp=0x%04x cause=%s header=%s", 862 + __entry->context, 863 + __entry->card_index, 864 + __entry->timestamp, 865 + show_cause(__entry->cause), 866 + __print_array(__get_dynamic_array(header), 867 + __get_dynamic_array_len(header) / QUADLET_SIZE, QUADLET_SIZE) 868 + ) 869 + ) 870 + 871 + DEFINE_EVENT_CONDITION(isoc_single_completions_template, isoc_outbound_completions, 872 + TP_PROTO(const struct fw_iso_context *ctx, u16 timestamp, enum fw_iso_context_completions_cause cause, const u32 *header, unsigned int header_length), 873 + TP_ARGS(ctx, timestamp, cause, header, header_length), 874 + TP_CONDITION(ctx->type == FW_ISO_CONTEXT_TRANSMIT) 875 + ); 876 + 877 + DEFINE_EVENT_CONDITION(isoc_single_completions_template, isoc_inbound_single_completions, 878 + TP_PROTO(const struct fw_iso_context *ctx, u16 timestamp, enum fw_iso_context_completions_cause cause, const u32 *header, unsigned int header_length), 879 + TP_ARGS(ctx, timestamp, cause, header, header_length), 880 + TP_CONDITION(ctx->type == FW_ISO_CONTEXT_RECEIVE) 881 + ); 882 + 883 + TRACE_EVENT(isoc_inbound_multiple_completions, 884 + TP_PROTO(const struct fw_iso_context *ctx, unsigned int completed, enum fw_iso_context_completions_cause cause), 885 + TP_ARGS(ctx, completed, cause), 886 + TP_STRUCT__entry( 887 + __field(u64, context) 888 + __field(u8, card_index) 889 + __field(u16, completed) 890 + __field(u8, cause) 891 + ), 892 + TP_fast_assign( 893 + __entry->context = (uintptr_t)ctx; 894 + __entry->card_index = ctx->card->index; 895 + __entry->completed = completed; 896 + __entry->cause = cause; 897 + ), 898 + TP_printk( 899 + "context=0x%llx card_index=%u completed=%u cause=%s", 900 + __entry->context, 901 + __entry->card_index, 902 + __entry->completed, 903 + show_cause(__entry->cause) 367 904 ) 368 905 ); 369 906
+101
include/trace/events/firewire_ohci.h
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + // Copyright (c) 2024 Takashi Sakamoto 3 + 4 + #undef TRACE_SYSTEM 5 + #define TRACE_SYSTEM firewire_ohci 6 + 7 + #if !defined(_FIREWIRE_OHCI_TRACE_EVENT_H) || defined(TRACE_HEADER_MULTI_READ) 8 + #define _FIREWIRE_OHCI_TRACE_EVENT_H 9 + 10 + #include <linux/tracepoint.h> 11 + 12 + // Some macros and helper functions are defined in 'drivers/firewire/ohci.c'. 13 + 14 + TRACE_EVENT(irqs, 15 + TP_PROTO(unsigned int card_index, u32 events), 16 + TP_ARGS(card_index, events), 17 + TP_STRUCT__entry( 18 + __field(u8, card_index) 19 + __field(u32, events) 20 + ), 21 + TP_fast_assign( 22 + __entry->card_index = card_index; 23 + __entry->events = events; 24 + ), 25 + TP_printk( 26 + "card_index=%u events=%s", 27 + __entry->card_index, 28 + __print_flags(__entry->events, "|", 29 + { OHCI1394_selfIDComplete, "selfIDComplete" }, 30 + { OHCI1394_RQPkt, "RQPkt" }, 31 + { OHCI1394_RSPkt, "RSPkt" }, 32 + { OHCI1394_reqTxComplete, "reqTxComplete" }, 33 + { OHCI1394_respTxComplete, "respTxComplete" }, 34 + { OHCI1394_isochRx, "isochRx" }, 35 + { OHCI1394_isochTx, "isochTx" }, 36 + { OHCI1394_postedWriteErr, "postedWriteErr" }, 37 + { OHCI1394_cycleTooLong, "cycleTooLong" }, 38 + { OHCI1394_cycle64Seconds, "cycle64Seconds" }, 39 + { OHCI1394_cycleInconsistent, "cycleInconsistent" }, 40 + { OHCI1394_regAccessFail, "regAccessFail" }, 41 + { OHCI1394_unrecoverableError, "unrecoverableError" }, 42 + { OHCI1394_busReset, "busReset" } 43 + ) 44 + ) 45 + ); 46 + 47 + #define QUADLET_SIZE 4 48 + 49 + #define SELF_ID_COUNT_IS_ERROR(reg) \ 50 + (!!(((reg) & OHCI1394_SelfIDCount_selfIDError_MASK) >> OHCI1394_SelfIDCount_selfIDError_SHIFT)) 51 + 52 + #define SELF_ID_COUNT_GET_GENERATION(reg) \ 53 + (((reg) & OHCI1394_SelfIDCount_selfIDGeneration_MASK) >> OHCI1394_SelfIDCount_selfIDGeneration_SHIFT) 54 + 55 + #define SELF_ID_RECEIVE_Q0_GET_GENERATION(quadlet) \ 56 + (((quadlet) & OHCI1394_SELF_ID_RECEIVE_Q0_GENERATION_MASK) >> OHCI1394_SELF_ID_RECEIVE_Q0_GENERATION_SHIFT) 57 + 58 + #define SELF_ID_RECEIVE_Q0_GET_TIMESTAMP(quadlet) \ 59 + (((quadlet) & OHCI1394_SELF_ID_RECEIVE_Q0_TIMESTAMP_MASK) >> OHCI1394_SELF_ID_RECEIVE_Q0_TIMESTAMP_SHIFT) 60 + 61 + TRACE_EVENT(self_id_complete, 62 + TP_PROTO(unsigned int card_index, u32 reg, const __le32 *self_id_receive, bool has_be_header_quirk), 63 + TP_ARGS(card_index, reg, self_id_receive, has_be_header_quirk), 64 + TP_STRUCT__entry( 65 + __field(u8, card_index) 66 + __field(u32, reg) 67 + __dynamic_array(u32, self_id_receive, ohci1394_self_id_count_get_size(reg)) 68 + ), 69 + TP_fast_assign( 70 + __entry->card_index = card_index; 71 + __entry->reg = reg; 72 + { 73 + u32 *ptr = __get_dynamic_array(self_id_receive); 74 + int i; 75 + 76 + for (i = 0; i < __get_dynamic_array_len(self_id_receive) / QUADLET_SIZE; ++i) 77 + ptr[i] = cond_le32_to_cpu(self_id_receive[i], has_be_header_quirk); 78 + } 79 + ), 80 + TP_printk( 81 + "card_index=%u is_error=%s generation_at_bus_reset=%u generation_at_completion=%u timestamp=0x%04x packet_data=%s", 82 + __entry->card_index, 83 + SELF_ID_COUNT_IS_ERROR(__entry->reg) ? "true" : "false", 84 + SELF_ID_COUNT_GET_GENERATION(__entry->reg), 85 + SELF_ID_RECEIVE_Q0_GET_GENERATION(((const u32 *)__get_dynamic_array(self_id_receive))[0]), 86 + SELF_ID_RECEIVE_Q0_GET_TIMESTAMP(((const u32 *)__get_dynamic_array(self_id_receive))[0]), 87 + __print_array(((const u32 *)__get_dynamic_array(self_id_receive)) + 1, 88 + (__get_dynamic_array_len(self_id_receive) / QUADLET_SIZE) - 1, QUADLET_SIZE) 89 + ) 90 + ); 91 + 92 + #undef SELF_ID_COUNT_IS_ERROR 93 + #undef SELF_ID_COUNT_GET_GENERATION 94 + #undef SELF_ID_RECEIVE_Q0_GET_GENERATION 95 + #undef SELF_ID_RECEIVE_Q0_GET_TIMESTAMP 96 + 97 + #undef QUADLET_SIZE 98 + 99 + #endif // _FIREWIRE_OHCI_TRACE_EVENT_H 100 + 101 + #include <trace/define_trace.h>