firewire: core: add tracepoints event for asynchronous inbound response
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>
Mon, 29 Apr 2024 04:32:16 +0000 (13:32 +0900)
committerTakashi Sakamoto <o-takashi@sakamocchi.jp>
Mon, 6 May 2024 02:06:05 +0000 (11:06 +0900)
In the transaction of IEEE 1394, the node to receive the asynchronous
request transfers any response packet to the requester except for the
unified transaction.

This commit adds an event for the inbound packet. Note that the code to
decode the packet header is moved, against the note about the sanity
check.

The following example is for asynchronous lock response with
compare_and_swap code.

async_response_inbound: \
  transaction=0xffff955fc6a07a10 generation=5 scode=2 status=1 \
  timestamp=0x0089 dst_id=0xffc1 tlabel=54 tcode=11 src_id=0xffc0 \
  rcode=0 header={0xffc1d9b0,0xffc00000,0x0,0x40002} data={0x50800080}

Link: https://lore.kernel.org/r/20240429043218.609398-4-o-takashi@sakamocchi.jp
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
drivers/firewire/core-transaction.c
include/trace/events/firewire.h

index c9318024386f8c96ae608db90cbcc88dcc904044..56510d305564ccc0e659c20190f6fd3c92d91006 100644 (file)
@@ -1011,32 +1011,10 @@ void fw_core_handle_response(struct fw_card *card, struct fw_packet *p)
        source = async_header_get_source(p->header);
        rcode = async_header_get_rcode(p->header);
 
-       spin_lock_irqsave(&card->lock, flags);
-       list_for_each_entry(iter, &card->transaction_list, link) {
-               if (iter->node_id == source && iter->tlabel == tlabel) {
-                       if (!try_cancel_split_timeout(iter)) {
-                               spin_unlock_irqrestore(&card->lock, flags);
-                               goto timed_out;
-                       }
-                       list_del_init(&iter->link);
-                       card->tlabel_mask &= ~(1ULL << iter->tlabel);
-                       t = iter;
-                       break;
-               }
-       }
-       spin_unlock_irqrestore(&card->lock, flags);
-
-       if (!t) {
- timed_out:
-               fw_notice(card, "unsolicited response (source %x, tlabel %x)\n",
-                         source, tlabel);
-               return;
-       }
-
-       /*
-        * FIXME: sanity check packet, is length correct, does tcodes
-        * and addresses match.
-        */
+       // FIXME: sanity check packet, is length correct, does tcodes
+       // and addresses match to the transaction request queried later.
+       //
+       // For the tracepoints event, let us decode the header here against the concern.
 
        switch (tcode) {
        case TCODE_READ_QUADLET_RESPONSE:
@@ -1062,6 +1040,31 @@ void fw_core_handle_response(struct fw_card *card, struct fw_packet *p)
                break;
        }
 
+       spin_lock_irqsave(&card->lock, flags);
+       list_for_each_entry(iter, &card->transaction_list, link) {
+               if (iter->node_id == source && iter->tlabel == tlabel) {
+                       if (!try_cancel_split_timeout(iter)) {
+                               spin_unlock_irqrestore(&card->lock, flags);
+                               goto timed_out;
+                       }
+                       list_del_init(&iter->link);
+                       card->tlabel_mask &= ~(1ULL << iter->tlabel);
+                       t = iter;
+                       break;
+               }
+       }
+       spin_unlock_irqrestore(&card->lock, flags);
+
+       trace_async_response_inbound((uintptr_t)t, p->generation, p->speed, p->ack, p->timestamp,
+                                    p->header, data, data_length / 4);
+
+       if (!t) {
+ timed_out:
+               fw_notice(card, "unsolicited response (source %x, tlabel %x)\n",
+                         source, tlabel);
+               return;
+       }
+
        /*
         * The response handler may be executed while the request handler
         * is still pending.  Cancel the request handler.
index 063695874cfb11eb99ca99ee9bd650cd90852817..2d5f6b196a2200a25d502932960b248423e1a12c 100644 (file)
@@ -30,6 +30,9 @@
        ((((unsigned long long)((header)[1] & ASYNC_HEADER_Q1_OFFSET_HIGH_MASK)) >> ASYNC_HEADER_Q1_OFFSET_HIGH_SHIFT) << 32)| \
        (header)[2]
 
+#define ASYNC_HEADER_GET_RCODE(header) \
+       (((header)[1] & ASYNC_HEADER_Q1_RCODE_MASK) >> ASYNC_HEADER_Q1_RCODE_SHIFT)
+
 #define QUADLET_SIZE   4
 
 DECLARE_EVENT_CLASS(async_outbound_initiate_template,
@@ -94,6 +97,47 @@ DECLARE_EVENT_CLASS(async_outbound_complete_template,
        )
 );
 
+// The value of status is one of ack codes and rcodes specific to Linux FireWire subsystem.
+DECLARE_EVENT_CLASS(async_inbound_template,
+       TP_PROTO(u64 transaction, unsigned int generation, unsigned int scode, unsigned int status, unsigned int timestamp, const u32 *header, const u32 *data, unsigned int data_count),
+       TP_ARGS(transaction, generation, scode, status, timestamp, header, data, data_count),
+       TP_STRUCT__entry(
+               __field(u64, transaction)
+               __field(u8, generation)
+               __field(u8, scode)
+               __field(u8, status)
+               __field(u8, timestamp)
+               __array(u32, header, ASYNC_HEADER_QUADLET_COUNT)
+               __dynamic_array(u32, data, data_count)
+       ),
+       TP_fast_assign(
+               __entry->transaction = transaction;
+               __entry->generation = generation;
+               __entry->scode = scode;
+               __entry->status = status;
+               __entry->timestamp = timestamp;
+               memcpy(__entry->header, header, QUADLET_SIZE * ASYNC_HEADER_QUADLET_COUNT);
+               memcpy(__get_dynamic_array(data), data, __get_dynamic_array_len(data));
+       ),
+       // This format is for the response subaction.
+       TP_printk(
+               "transaction=0x%llx generation=%u scode=%u status=%u timestamp=0x%04x dst_id=0x%04x tlabel=%u tcode=%u src_id=0x%04x rcode=%u header=%s data=%s",
+               __entry->transaction,
+               __entry->generation,
+               __entry->scode,
+               __entry->status,
+               __entry->timestamp,
+               ASYNC_HEADER_GET_DESTINATION(__entry->header),
+               ASYNC_HEADER_GET_TLABEL(__entry->header),
+               ASYNC_HEADER_GET_TCODE(__entry->header),
+               ASYNC_HEADER_GET_SOURCE(__entry->header),
+               ASYNC_HEADER_GET_RCODE(__entry->header),
+               __print_array(__entry->header, ASYNC_HEADER_QUADLET_COUNT, QUADLET_SIZE),
+               __print_array(__get_dynamic_array(data),
+                             __get_dynamic_array_len(data) / QUADLET_SIZE, QUADLET_SIZE)
+       )
+);
+
 DEFINE_EVENT(async_outbound_initiate_template, async_request_outbound_initiate,
        TP_PROTO(u64 transaction, unsigned int generation, unsigned int scode, const u32 *header, const u32 *data, unsigned int data_count),
        TP_ARGS(transaction, generation, scode, header, data, data_count)
@@ -104,11 +148,17 @@ DEFINE_EVENT(async_outbound_complete_template, async_request_outbound_complete,
        TP_ARGS(transaction, generation, scode, status, timestamp)
 );
 
+DEFINE_EVENT(async_inbound_template, async_response_inbound,
+       TP_PROTO(u64 transaction, unsigned int generation, unsigned int scode, unsigned int status, unsigned int timestamp, const u32 *header, const u32 *data, unsigned int data_count),
+       TP_ARGS(transaction, generation, scode, status, timestamp, header, data, data_count)
+);
+
 #undef ASYNC_HEADER_GET_DESTINATION
 #undef ASYNC_HEADER_GET_TLABEL
 #undef ASYNC_HEADER_GET_TCODE
 #undef ASYNC_HEADER_GET_SOURCE
 #undef ASYNC_HEADER_GET_OFFSET
+#undef ASYNC_HEADER_GET_RCODE
 #undef QUADLET_SIZE
 
 #endif // _FIREWIRE_TRACE_EVENT_H