The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [PATCH 0/5] firewire: ohci: add tracepoints event for data of Self-ID DMA
@ 2024-07-02 22:20 Takashi Sakamoto
  2024-07-02 22:20 ` [PATCH 1/5] firewire: ohci: use common macro to interpret be32 data in le32 buffer Takashi Sakamoto
                   ` (5 more replies)
  0 siblings, 6 replies; 8+ messages in thread
From: Takashi Sakamoto @ 2024-07-02 22:20 UTC (permalink / raw)
  To: linux1394-devel; +Cc: linux-kernel

Hi,

In IEEE 1394, Self identification process is the last step at
bus configuration process initiated by reset. In this step, all nodes at
the bus broadcast self-ID packet according to the new topology. In 1394
OHCI, the contents of the self-ID packet stream are transmitted to host
system by DMA. This is Self-ID DMA, and configured by two registers,
signaled by an interrupt, has a format of buffer.

Software handles the interrupt, then parse the contents of self-ID packet
stream to detect all nodes in the bus. Finally it starts any type of
operation in the bus. Both the timing to handle the interrupt and the
data of DMA buffer are important as a first step to use the bus.

This series of patches is to add a tracepoints event to trace the
interrupt and the data of DMA buffer. It would be useful to diagnose
some kind of issue related to the self-ID process; e.g. hardware quirks.
I also expect it useful to investigate the timing issue between hardIRQ
and softIRQ contexts to process the contents of self-ID packets.

Takashi Sakamoto (5):
  firewire: ohci: use common macro to interpret be32 data in le32 buffer
  firewire: ohci: use static function to handle endian issue on PowerPC
    platform
  firewire: ohci: add static inline functions to deserialize for Self-ID
    DMA operation
  firewire: ohci: use inline functions to operate data of self-ID DMA
  firewire: ohci: add tracepoints event for data of Self-ID DMA

 drivers/firewire/.kunitconfig        |  1 +
 drivers/firewire/Kconfig             | 16 ++++++++
 drivers/firewire/Makefile            |  1 +
 drivers/firewire/ohci-serdes-test.c  | 56 ++++++++++++++++++++++++++
 drivers/firewire/ohci.c              | 60 ++++++++++++++++++++--------
 drivers/firewire/ohci.h              | 43 +++++++++++++++++++-
 include/trace/events/firewire_ohci.h | 54 +++++++++++++++++++++++++
 7 files changed, 213 insertions(+), 18 deletions(-)
 create mode 100644 drivers/firewire/ohci-serdes-test.c

-- 
2.43.0


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/5] firewire: ohci: use common macro to interpret be32 data in le32 buffer
  2024-07-02 22:20 [PATCH 0/5] firewire: ohci: add tracepoints event for data of Self-ID DMA Takashi Sakamoto
@ 2024-07-02 22:20 ` Takashi Sakamoto
  2024-07-02 22:20 ` [PATCH 2/5] firewire: ohci: use static function to handle endian issue on PowerPC platform Takashi Sakamoto
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Takashi Sakamoto @ 2024-07-02 22:20 UTC (permalink / raw)
  To: linux1394-devel; +Cc: linux-kernel

The 1394 OHCI driver configures the hardware to transfer the data quadlets
of packet via DMA after converting it to little endian, therefore the data
is typed as __le32. Nevertheless some actual hardware ignores the
configuration. In the case, the data in DMA buffer is aligned to big endian
(__be32).

For the case in big-endian machine, the driver includes the following
interpretation from __le32 to u32 (host-endian = __be32):

    * (__force __u32)(v)

In include/linux/byteorder/generic.h, be32_to_cpu() is available. It is
expanded to the following expression in
'include/uapi/linux/byteorder/big_endian.h':

    * (__force __u32)(__be32)(x)

This commit replace the ad-hoc endian interpretation with the above.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
 drivers/firewire/ohci.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index df16a8f4ee7f..a2d6d1d1ec2b 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -876,7 +876,7 @@ static void ar_sync_buffers_for_cpu(struct ar_context *ctx,
 
 #if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32)
 #define cond_le32_to_cpu(v) \
-	(ohci->quirks & QUIRK_BE_HEADERS ? (__force __u32)(v) : le32_to_cpu(v))
+	(ohci->quirks & QUIRK_BE_HEADERS ? be32_to_cpu(v) : le32_to_cpu(v))
 #else
 #define cond_le32_to_cpu(v) le32_to_cpu(v)
 #endif
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/5] firewire: ohci: use static function to handle endian issue on PowerPC platform
  2024-07-02 22:20 [PATCH 0/5] firewire: ohci: add tracepoints event for data of Self-ID DMA Takashi Sakamoto
  2024-07-02 22:20 ` [PATCH 1/5] firewire: ohci: use common macro to interpret be32 data in le32 buffer Takashi Sakamoto
@ 2024-07-02 22:20 ` Takashi Sakamoto
  2024-07-02 22:20 ` [PATCH 3/5] firewire: ohci: add static inline functions to deserialize for Self-ID DMA operation Takashi Sakamoto
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Takashi Sakamoto @ 2024-07-02 22:20 UTC (permalink / raw)
  To: linux1394-devel; +Cc: linux-kernel

It is preferable to use static function instead of functional macro in
some points. It checks type of argument, but would be optimized to
embedded code instead of function calls.

This commit obsoletes the functional macro with the static function.
Additionally this commit refactors quirk detection to ease the later work.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
 drivers/firewire/ohci.c | 39 +++++++++++++++++++++++++++------------
 1 file changed, 27 insertions(+), 12 deletions(-)

diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index a2d6d1d1ec2b..5b90ca72fa64 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -875,10 +875,25 @@ static void ar_sync_buffers_for_cpu(struct ar_context *ctx,
 }
 
 #if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32)
-#define cond_le32_to_cpu(v) \
-	(ohci->quirks & QUIRK_BE_HEADERS ? be32_to_cpu(v) : le32_to_cpu(v))
+static u32 cond_le32_to_cpu(__le32 value, bool has_be_header_quirk)
+{
+	return has_be_header_quirk ? be32_to_cpu(value) : le32_to_cpu(value);
+}
+
+static bool has_be_header_quirk(const struct fw_ohci *ohci)
+{
+	return !!(ohci->quirks & QUIRK_BE_HEADERS);
+}
 #else
-#define cond_le32_to_cpu(v) le32_to_cpu(v)
+static u32 cond_le32_to_cpu(__le32 value, bool has_be_header_quirk __maybe_unused)
+{
+	return le32_to_cpu(value);
+}
+
+static bool has_be_header_quirk(const struct fw_ohci *ohci)
+{
+	return false;
+}
 #endif
 
 static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer)
@@ -888,9 +903,9 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer)
 	u32 status, length, tcode;
 	int evt;
 
-	p.header[0] = cond_le32_to_cpu(buffer[0]);
-	p.header[1] = cond_le32_to_cpu(buffer[1]);
-	p.header[2] = cond_le32_to_cpu(buffer[2]);
+	p.header[0] = cond_le32_to_cpu(buffer[0], has_be_header_quirk(ohci));
+	p.header[1] = cond_le32_to_cpu(buffer[1], has_be_header_quirk(ohci));
+	p.header[2] = cond_le32_to_cpu(buffer[2], has_be_header_quirk(ohci));
 
 	tcode = async_header_get_tcode(p.header);
 	switch (tcode) {
@@ -902,7 +917,7 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer)
 		break;
 
 	case TCODE_READ_BLOCK_REQUEST :
-		p.header[3] = cond_le32_to_cpu(buffer[3]);
+		p.header[3] = cond_le32_to_cpu(buffer[3], has_be_header_quirk(ohci));
 		p.header_length = 16;
 		p.payload_length = 0;
 		break;
@@ -911,7 +926,7 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer)
 	case TCODE_READ_BLOCK_RESPONSE:
 	case TCODE_LOCK_REQUEST:
 	case TCODE_LOCK_RESPONSE:
-		p.header[3] = cond_le32_to_cpu(buffer[3]);
+		p.header[3] = cond_le32_to_cpu(buffer[3], has_be_header_quirk(ohci));
 		p.header_length = 16;
 		p.payload_length = async_header_get_data_length(p.header);
 		if (p.payload_length > MAX_ASYNC_PAYLOAD) {
@@ -936,7 +951,7 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer)
 
 	/* FIXME: What to do about evt_* errors? */
 	length = (p.header_length + p.payload_length + 3) / 4;
-	status = cond_le32_to_cpu(buffer[length]);
+	status = cond_le32_to_cpu(buffer[length], has_be_header_quirk(ohci));
 	evt    = (status >> 16) & 0x1f;
 
 	p.ack        = evt - 16;
@@ -2030,12 +2045,12 @@ static void bus_reset_work(struct work_struct *work)
 		return;
 	}
 
-	generation = (cond_le32_to_cpu(ohci->self_id[0]) >> 16) & 0xff;
+	generation = (cond_le32_to_cpu(ohci->self_id[0], has_be_header_quirk(ohci)) >> 16) & 0xff;
 	rmb();
 
 	for (i = 1, j = 0; j < self_id_count; i += 2, j++) {
-		u32 id  = cond_le32_to_cpu(ohci->self_id[i]);
-		u32 id2 = cond_le32_to_cpu(ohci->self_id[i + 1]);
+		u32 id  = cond_le32_to_cpu(ohci->self_id[i], has_be_header_quirk(ohci));
+		u32 id2 = cond_le32_to_cpu(ohci->self_id[i + 1], has_be_header_quirk(ohci));
 
 		if (id != ~id2) {
 			/*
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 3/5] firewire: ohci: add static inline functions to deserialize for Self-ID DMA operation
  2024-07-02 22:20 [PATCH 0/5] firewire: ohci: add tracepoints event for data of Self-ID DMA Takashi Sakamoto
  2024-07-02 22:20 ` [PATCH 1/5] firewire: ohci: use common macro to interpret be32 data in le32 buffer Takashi Sakamoto
  2024-07-02 22:20 ` [PATCH 2/5] firewire: ohci: use static function to handle endian issue on PowerPC platform Takashi Sakamoto
@ 2024-07-02 22:20 ` Takashi Sakamoto
  2024-07-02 22:20 ` [PATCH 4/5] firewire: ohci: use inline functions to operate data of self-ID DMA Takashi Sakamoto
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Takashi Sakamoto @ 2024-07-02 22:20 UTC (permalink / raw)
  To: linux1394-devel; +Cc: linux-kernel

The SelfI-ID is one type of DMAs defined in 1394 OHCI specification. It is
operated by two registers, one interrupt, and has one format of buffer.

This commit adds some static inline functions to deserialize the data in
the buffer and registers. Some KUnit tests are also added to check their
reliability.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
 drivers/firewire/.kunitconfig       |  1 +
 drivers/firewire/Kconfig            | 16 +++++++++
 drivers/firewire/Makefile           |  1 +
 drivers/firewire/ohci-serdes-test.c | 56 +++++++++++++++++++++++++++++
 drivers/firewire/ohci.h             | 42 ++++++++++++++++++++++
 5 files changed, 116 insertions(+)
 create mode 100644 drivers/firewire/ohci-serdes-test.c

diff --git a/drivers/firewire/.kunitconfig b/drivers/firewire/.kunitconfig
index 74259204fcdd..21b7e9eef63d 100644
--- a/drivers/firewire/.kunitconfig
+++ b/drivers/firewire/.kunitconfig
@@ -5,3 +5,4 @@ CONFIG_FIREWIRE_KUNIT_UAPI_TEST=y
 CONFIG_FIREWIRE_KUNIT_DEVICE_ATTRIBUTE_TEST=y
 CONFIG_FIREWIRE_KUNIT_PACKET_SERDES_TEST=y
 CONFIG_FIREWIRE_KUNIT_SELF_ID_SEQUENCE_HELPER_TEST=y
+CONFIG_FIREWIRE_KUNIT_OHCI_SERDES_TEST=y
diff --git a/drivers/firewire/Kconfig b/drivers/firewire/Kconfig
index 95e72e0b592b..905c82e26ce7 100644
--- a/drivers/firewire/Kconfig
+++ b/drivers/firewire/Kconfig
@@ -92,6 +92,22 @@ config FIREWIRE_OHCI
 	  To compile this driver as a module, say M here:  The module will be
 	  called firewire-ohci.
 
+config FIREWIRE_KUNIT_OHCI_SERDES_TEST
+	tristate "KUnit tests for serialization/deserialization of data in buffers/registers" if !KUNIT_ALL_TESTS
+	depends on FIREWIRE && KUNIT
+	default KUNIT_ALL_TESTS
+	help
+	  This builds the KUnit tests to check serialization and deserialization
+	  of data in buffers and registers defined in 1394 OHCI specification.
+
+	  KUnit tests run during boot and output the results to the debug
+	  log in TAP format (https://testanything.org/). Only useful for
+	  kernel devs running KUnit test harness and are not for inclusion
+	  into a production build.
+
+	  For more information on KUnit and unit tests in general, refer
+	  to the KUnit documentation in Documentation/dev-tools/kunit/.
+
 config FIREWIRE_SBP2
 	tristate "Storage devices (SBP-2 protocol)"
 	depends on FIREWIRE && SCSI
diff --git a/drivers/firewire/Makefile b/drivers/firewire/Makefile
index 21b975e0a387..1ff550e93a8c 100644
--- a/drivers/firewire/Makefile
+++ b/drivers/firewire/Makefile
@@ -19,3 +19,4 @@ obj-$(CONFIG_PROVIDE_OHCI1394_DMA_INIT) += init_ohci1394_dma.o
 obj-$(CONFIG_FIREWIRE_KUNIT_UAPI_TEST) += uapi-test.o
 obj-$(CONFIG_FIREWIRE_KUNIT_PACKET_SERDES_TEST) += packet-serdes-test.o
 obj-$(CONFIG_FIREWIRE_KUNIT_SELF_ID_SEQUENCE_HELPER_TEST) += self-id-sequence-helper-test.o
+obj-$(CONFIG_FIREWIRE_KUNIT_OHCI_SERDES_TEST) += ohci-serdes-test.o
diff --git a/drivers/firewire/ohci-serdes-test.c b/drivers/firewire/ohci-serdes-test.c
new file mode 100644
index 000000000000..304a09ff528e
--- /dev/null
+++ b/drivers/firewire/ohci-serdes-test.c
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+//
+// ohci-serdes-test.c - An application of Kunit to check serialization/deserialization of data in
+//			buffers and registers defined in 1394 OHCI specification.
+//
+// Copyright (c) 2024 Takashi Sakamoto
+
+#include <kunit/test.h>
+
+#include "ohci.h"
+
+
+static void test_self_id_count_register_deserialization(struct kunit *test)
+{
+	const u32 expected = 0x803d0594;
+
+	bool is_error = ohci1394_self_id_count_is_error(expected);
+	u8 generation = ohci1394_self_id_count_get_generation(expected);
+	u32 size = ohci1394_self_id_count_get_size(expected);
+
+	KUNIT_EXPECT_TRUE(test, is_error);
+	KUNIT_EXPECT_EQ(test, 0x3d, generation);
+	KUNIT_EXPECT_EQ(test, 0x165, size);
+}
+
+static void test_self_id_receive_buffer_deserialization(struct kunit *test)
+{
+	const u32 buffer[] = {
+		0x0006f38b,
+		0x807fcc56,
+		0x7f8033a9,
+		0x8145cc5e,
+		0x7eba33a1,
+	};
+
+	u8 generation = ohci1394_self_id_receive_q0_get_generation(buffer[0]);
+	u16 timestamp = ohci1394_self_id_receive_q0_get_timestamp(buffer[0]);
+
+	KUNIT_EXPECT_EQ(test, 0x6, generation);
+	KUNIT_EXPECT_EQ(test, 0xf38b, timestamp);
+}
+
+static struct kunit_case ohci_serdes_test_cases[] = {
+	KUNIT_CASE(test_self_id_count_register_deserialization),
+	KUNIT_CASE(test_self_id_receive_buffer_deserialization),
+	{}
+};
+
+static struct kunit_suite ohci_serdes_test_suite = {
+	.name = "firewire-ohci-serdes",
+	.test_cases = ohci_serdes_test_cases,
+};
+kunit_test_suite(ohci_serdes_test_suite);
+
+MODULE_DESCRIPTION("FireWire buffers and registers serialization/deserialization unit test suite");
+MODULE_LICENSE("GPL");
diff --git a/drivers/firewire/ohci.h b/drivers/firewire/ohci.h
index c4d005a9901a..d83fd4731d56 100644
--- a/drivers/firewire/ohci.h
+++ b/drivers/firewire/ohci.h
@@ -156,4 +156,46 @@
 
 #define OHCI1394_phy_tcode		0xe
 
+// Self-ID DMA.
+
+#define OHCI1394_SelfIDCount_selfIDError_MASK		0x80000000
+#define OHCI1394_SelfIDCount_selfIDError_SHIFT		31
+#define OHCI1394_SelfIDCount_selfIDGeneration_MASK	0x00ff0000
+#define OHCI1394_SelfIDCount_selfIDGeneration_SHIFT	16
+#define OHCI1394_SelfIDCount_selfIDSize_MASK		0x000007fc
+#define OHCI1394_SelfIDCount_selfIDSize_SHIFT		2
+
+static inline bool ohci1394_self_id_count_is_error(u32 value)
+{
+	return !!((value & OHCI1394_SelfIDCount_selfIDError_MASK) >> OHCI1394_SelfIDCount_selfIDError_SHIFT);
+}
+
+static inline u8 ohci1394_self_id_count_get_generation(u32 value)
+{
+	return (value & OHCI1394_SelfIDCount_selfIDGeneration_MASK) >> OHCI1394_SelfIDCount_selfIDGeneration_SHIFT;
+}
+
+// In 1394 OHCI specification, the maximum size of self ID stream is 504 quadlets
+// (= 63 devices * 4 self ID packets * 2 quadlets). The selfIDSize field accommodates it and its
+// additional first quadlet, since the field is 9 bits (0x1ff = 511).
+static inline u32 ohci1394_self_id_count_get_size(u32 value)
+{
+	return (value & OHCI1394_SelfIDCount_selfIDSize_MASK) >> OHCI1394_SelfIDCount_selfIDSize_SHIFT;
+}
+
+#define OHCI1394_SELF_ID_RECEIVE_Q0_GENERATION_MASK	0x00ff0000
+#define OHCI1394_SELF_ID_RECEIVE_Q0_GENERATION_SHIFT	16
+#define OHCI1394_SELF_ID_RECEIVE_Q0_TIMESTAMP_MASK	0x0000ffff
+#define OHCI1394_SELF_ID_RECEIVE_Q0_TIMESTAMP_SHIFT	0
+
+static inline u8 ohci1394_self_id_receive_q0_get_generation(u32 quadlet0)
+{
+	return (quadlet0 & OHCI1394_SELF_ID_RECEIVE_Q0_GENERATION_MASK) >> OHCI1394_SELF_ID_RECEIVE_Q0_GENERATION_SHIFT;
+}
+
+static inline u16 ohci1394_self_id_receive_q0_get_timestamp(u32 quadlet0)
+{
+	return (quadlet0 & OHCI1394_SELF_ID_RECEIVE_Q0_TIMESTAMP_MASK) >> OHCI1394_SELF_ID_RECEIVE_Q0_TIMESTAMP_SHIFT;
+}
+
 #endif /* _FIREWIRE_OHCI_H */
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 4/5] firewire: ohci: use inline functions to operate data of self-ID DMA
  2024-07-02 22:20 [PATCH 0/5] firewire: ohci: add tracepoints event for data of Self-ID DMA Takashi Sakamoto
                   ` (2 preceding siblings ...)
  2024-07-02 22:20 ` [PATCH 3/5] firewire: ohci: add static inline functions to deserialize for Self-ID DMA operation Takashi Sakamoto
@ 2024-07-02 22:20 ` Takashi Sakamoto
  2024-07-02 22:20 ` [PATCH 5/5] firewire: ohci: add tracepoints event for data of Self-ID DMA Takashi Sakamoto
  2024-07-03 23:30 ` [PATCH 0/5] " Takashi Sakamoto
  5 siblings, 0 replies; 8+ messages in thread
From: Takashi Sakamoto @ 2024-07-02 22:20 UTC (permalink / raw)
  To: linux1394-devel; +Cc: linux-kernel

The code of 1394 OHCI driver includes hard-coded magic number to operate
data of Self-ID DMA.

This commit replaces them with the inline functions added/tested in the
former commit.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
 drivers/firewire/ohci.c | 12 +++++++-----
 drivers/firewire/ohci.h |  1 -
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index 5b90ca72fa64..c95f26c74e2b 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -2003,7 +2003,7 @@ static void bus_reset_work(struct work_struct *work)
 	struct fw_ohci *ohci =
 		container_of(work, struct fw_ohci, bus_reset_work);
 	int self_id_count, generation, new_generation, i, j;
-	u32 reg;
+	u32 reg, quadlet;
 	void *free_rom = NULL;
 	dma_addr_t free_rom_bus = 0;
 	bool is_new_root;
@@ -2028,7 +2028,7 @@ static void bus_reset_work(struct work_struct *work)
 	ohci->is_root = is_new_root;
 
 	reg = reg_read(ohci, OHCI1394_SelfIDCount);
-	if (reg & OHCI1394_SelfIDCount_selfIDError) {
+	if (ohci1394_self_id_count_is_error(reg)) {
 		ohci_notice(ohci, "self ID receive error\n");
 		return;
 	}
@@ -2038,14 +2038,15 @@ static void bus_reset_work(struct work_struct *work)
 	 * the inverted quadlets and a header quadlet, we shift one
 	 * bit extra to get the actual number of self IDs.
 	 */
-	self_id_count = (reg >> 3) & 0xff;
+	self_id_count = ohci1394_self_id_count_get_size(reg) >> 1;
 
 	if (self_id_count > 252) {
 		ohci_notice(ohci, "bad selfIDSize (%08x)\n", reg);
 		return;
 	}
 
-	generation = (cond_le32_to_cpu(ohci->self_id[0], has_be_header_quirk(ohci)) >> 16) & 0xff;
+	quadlet = cond_le32_to_cpu(ohci->self_id[0], has_be_header_quirk(ohci));
+	generation = ohci1394_self_id_receive_q0_get_generation(quadlet);
 	rmb();
 
 	for (i = 1, j = 0; j < self_id_count; i += 2, j++) {
@@ -2102,7 +2103,8 @@ static void bus_reset_work(struct work_struct *work)
 	 * of self IDs.
 	 */
 
-	new_generation = (reg_read(ohci, OHCI1394_SelfIDCount) >> 16) & 0xff;
+	reg = reg_read(ohci, OHCI1394_SelfIDCount);
+	new_generation = ohci1394_self_id_count_get_generation(reg);
 	if (new_generation != generation) {
 		ohci_notice(ohci, "new bus reset, discarding self ids\n");
 		return;
diff --git a/drivers/firewire/ohci.h b/drivers/firewire/ohci.h
index d83fd4731d56..71c2ed84cafb 100644
--- a/drivers/firewire/ohci.h
+++ b/drivers/firewire/ohci.h
@@ -31,7 +31,6 @@
 #define  OHCI1394_HCControl_softReset		0x00010000
 #define OHCI1394_SelfIDBuffer                 0x064
 #define OHCI1394_SelfIDCount                  0x068
-#define  OHCI1394_SelfIDCount_selfIDError	0x80000000
 #define OHCI1394_IRMultiChanMaskHiSet         0x070
 #define OHCI1394_IRMultiChanMaskHiClear       0x074
 #define OHCI1394_IRMultiChanMaskLoSet         0x078
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 5/5] firewire: ohci: add tracepoints event for data of Self-ID DMA
  2024-07-02 22:20 [PATCH 0/5] firewire: ohci: add tracepoints event for data of Self-ID DMA Takashi Sakamoto
                   ` (3 preceding siblings ...)
  2024-07-02 22:20 ` [PATCH 4/5] firewire: ohci: use inline functions to operate data of self-ID DMA Takashi Sakamoto
@ 2024-07-02 22:20 ` Takashi Sakamoto
  2024-07-04  0:07   ` Takashi Sakamoto
  2024-07-03 23:30 ` [PATCH 0/5] " Takashi Sakamoto
  5 siblings, 1 reply; 8+ messages in thread
From: Takashi Sakamoto @ 2024-07-02 22:20 UTC (permalink / raw)
  To: linux1394-devel; +Cc: linux-kernel

In 1394 OHCI, the SelfIDComplete event occurs when the hardware has
finished transmitting all of the self ID packets received during the bus
initialization process to the host memory by DMA.

This commit adds a tracepoints event for this event to trace the timing
and packet data of Self-ID DMA. It is the part of following tracepoints
events helpful to debug some events at bus reset; e.g. the issue addressed
at a commit d0b06dc48fb1 ("firewire: core: use long bus reset on gap count
error")[1]:

* firewire_ohci:irqs
* firewire_ohci:self_id_complete
* firewire:bus_reset_handle
* firewire:self_id_sequence

They would be also helpful in the problem about invocation timing of
hardIRQ/softIRQ contexts. We can often see this kind of problem with -rt
kernel[2].

[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d0b06dc48fb1
[2] https://lore.kernel.org/linux-rt-users/YAwPoaUZ1gTD5y+k@hmbx/

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
 drivers/firewire/ohci.c              | 11 +++++-
 include/trace/events/firewire_ohci.h | 54 ++++++++++++++++++++++++++++
 2 files changed, 64 insertions(+), 1 deletion(-)

diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index c95f26c74e2b..f8d880574c19 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -45,6 +45,8 @@
 
 #include <trace/events/firewire.h>
 
+static u32 cond_le32_to_cpu(__le32 value, bool has_be_header_quirk);
+
 #define CREATE_TRACE_POINTS
 #include <trace/events/firewire_ohci.h>
 
@@ -2208,8 +2210,15 @@ static irqreturn_t irq_handler(int irq, void *data)
 	if (event & OHCI1394_busReset)
 		reg_write(ohci, OHCI1394_IntMaskClear, OHCI1394_busReset);
 
-	if (event & OHCI1394_selfIDComplete)
+	if (event & OHCI1394_selfIDComplete) {
+		if (trace_self_id_complete_enabled()) {
+			u32 reg = reg_read(ohci, OHCI1394_SelfIDCount);
+
+			trace_self_id_complete(ohci->card.index, reg, ohci->self_id,
+					       has_be_header_quirk(ohci));
+		}
 		queue_work(selfid_workqueue, &ohci->bus_reset_work);
+	}
 
 	if (event & OHCI1394_RQPkt)
 		tasklet_schedule(&ohci->ar_request_ctx.tasklet);
diff --git a/include/trace/events/firewire_ohci.h b/include/trace/events/firewire_ohci.h
index 483aeeb033af..4f9a7f2577f3 100644
--- a/include/trace/events/firewire_ohci.h
+++ b/include/trace/events/firewire_ohci.h
@@ -9,6 +9,8 @@
 
 #include <linux/tracepoint.h>
 
+// Some macros and helper functions are defined in 'drivers/firewire/ohci.c'.
+
 TRACE_EVENT(irqs,
 	TP_PROTO(unsigned int card_index, u32 events),
 	TP_ARGS(card_index, events),
@@ -42,6 +44,58 @@ TRACE_EVENT(irqs,
 	)
 );
 
+#define QUADLET_SIZE	4
+
+#define SELF_ID_COUNT_IS_ERROR(reg)	\
+	(!!(((reg) & OHCI1394_SelfIDCount_selfIDError_MASK) >> OHCI1394_SelfIDCount_selfIDError_SHIFT))
+
+#define SELF_ID_COUNT_GET_GENERATION(reg)	\
+	(((reg) & OHCI1394_SelfIDCount_selfIDGeneration_MASK) >> OHCI1394_SelfIDCount_selfIDGeneration_SHIFT)
+
+#define SELF_ID_RECEIVE_Q0_GET_GENERATION(quadlet)	\
+	(((quadlet) & OHCI1394_SELF_ID_RECEIVE_Q0_GENERATION_MASK) >> OHCI1394_SELF_ID_RECEIVE_Q0_GENERATION_SHIFT)
+
+#define SELF_ID_RECEIVE_Q0_GET_TIMESTAMP(quadlet)	\
+	(((quadlet) & OHCI1394_SELF_ID_RECEIVE_Q0_TIMESTAMP_MASK) >> OHCI1394_SELF_ID_RECEIVE_Q0_TIMESTAMP_SHIFT)
+
+TRACE_EVENT(self_id_complete,
+	TP_PROTO(unsigned int card_index, u32 reg, const __le32 *self_id_receive, bool has_be_header_quirk),
+	TP_ARGS(card_index, reg, self_id_receive, has_be_header_quirk),
+	TP_STRUCT__entry(
+		__field(u8, card_index)
+		__field(u32, reg)
+		__dynamic_array(u32, self_id_receive, ohci1394_self_id_count_get_size(reg))
+	),
+	TP_fast_assign(
+		__entry->card_index = card_index;
+		__entry->reg = reg;
+		{
+			u32 *ptr = __get_dynamic_array(self_id_receive);
+			int i;
+
+			for (i = 0; i < __get_dynamic_array_len(self_id_receive) / QUADLET_SIZE; ++i)
+				ptr[i] = cond_le32_to_cpu(self_id_receive[i], has_be_header_quirk);
+		}
+	),
+	TP_printk(
+		"card_index=%u is_error=%s generation_at_bus_reset=%u generation_at_completion=%u timestamp=0x%04x packet_data=%s",
+		__entry->card_index,
+		SELF_ID_COUNT_IS_ERROR(__entry->reg) ? "true" : "false",
+		SELF_ID_COUNT_GET_GENERATION(__entry->reg),
+		SELF_ID_RECEIVE_Q0_GET_GENERATION(((const u32 *)__get_dynamic_array(self_id_receive))[0]),
+		SELF_ID_RECEIVE_Q0_GET_TIMESTAMP(((const u32 *)__get_dynamic_array(self_id_receive))[0]),
+		__print_array(((const u32 *)__get_dynamic_array(self_id_receive)) + 1,
+			      (__get_dynamic_array_len(self_id_receive) / QUADLET_SIZE) - 1, QUADLET_SIZE)
+	)
+);
+
+#undef SELF_ID_COUNT_IS_ERROR
+#undef SELF_ID_COUNT_GET_GENERATION
+#undef SELF_ID_RECEIVE_Q0_GET_GENERATION
+#undef SELF_ID_RECEIVE_Q0_GET_TIMESTAMP
+
+#undef QUADLET_SIZE
+
 #endif // _FIREWIRE_OHCI_TRACE_EVENT_H
 
 #include <trace/define_trace.h>
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 0/5] firewire: ohci: add tracepoints event for data of Self-ID DMA
  2024-07-02 22:20 [PATCH 0/5] firewire: ohci: add tracepoints event for data of Self-ID DMA Takashi Sakamoto
                   ` (4 preceding siblings ...)
  2024-07-02 22:20 ` [PATCH 5/5] firewire: ohci: add tracepoints event for data of Self-ID DMA Takashi Sakamoto
@ 2024-07-03 23:30 ` Takashi Sakamoto
  5 siblings, 0 replies; 8+ messages in thread
From: Takashi Sakamoto @ 2024-07-03 23:30 UTC (permalink / raw)
  To: linux1394-devel; +Cc: linux-kernel

On Wed, Jul 03, 2024 at 07:20:29AM +0900, Takashi Sakamoto wrote:
> Hi,
> 
> In IEEE 1394, Self identification process is the last step at
> bus configuration process initiated by reset. In this step, all nodes at
> the bus broadcast self-ID packet according to the new topology. In 1394
> OHCI, the contents of the self-ID packet stream are transmitted to host
> system by DMA. This is Self-ID DMA, and configured by two registers,
> signaled by an interrupt, has a format of buffer.
> 
> Software handles the interrupt, then parse the contents of self-ID packet
> stream to detect all nodes in the bus. Finally it starts any type of
> operation in the bus. Both the timing to handle the interrupt and the
> data of DMA buffer are important as a first step to use the bus.
> 
> This series of patches is to add a tracepoints event to trace the
> interrupt and the data of DMA buffer. It would be useful to diagnose
> some kind of issue related to the self-ID process; e.g. hardware quirks.
> I also expect it useful to investigate the timing issue between hardIRQ
> and softIRQ contexts to process the contents of self-ID packets.
> 
> Takashi Sakamoto (5):
>   firewire: ohci: use common macro to interpret be32 data in le32 buffer
>   firewire: ohci: use static function to handle endian issue on PowerPC
>     platform
>   firewire: ohci: add static inline functions to deserialize for Self-ID
>     DMA operation
>   firewire: ohci: use inline functions to operate data of self-ID DMA
>   firewire: ohci: add tracepoints event for data of Self-ID DMA
> 
>  drivers/firewire/.kunitconfig        |  1 +
>  drivers/firewire/Kconfig             | 16 ++++++++
>  drivers/firewire/Makefile            |  1 +
>  drivers/firewire/ohci-serdes-test.c  | 56 ++++++++++++++++++++++++++
>  drivers/firewire/ohci.c              | 60 ++++++++++++++++++++--------
>  drivers/firewire/ohci.h              | 43 +++++++++++++++++++-
>  include/trace/events/firewire_ohci.h | 54 +++++++++++++++++++++++++
>  7 files changed, 213 insertions(+), 18 deletions(-)
>  create mode 100644 drivers/firewire/ohci-serdes-test.c

Applied to for-next branch.


Regards

Takashi Sakamoto

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 5/5] firewire: ohci: add tracepoints event for data of Self-ID DMA
  2024-07-02 22:20 ` [PATCH 5/5] firewire: ohci: add tracepoints event for data of Self-ID DMA Takashi Sakamoto
@ 2024-07-04  0:07   ` Takashi Sakamoto
  0 siblings, 0 replies; 8+ messages in thread
From: Takashi Sakamoto @ 2024-07-04  0:07 UTC (permalink / raw)
  To: linux1394-devel; +Cc: linux-kernel

Hi,

On Wed, Jul 03, 2024 at 07:20:34AM +0900, Takashi Sakamoto wrote:
> In 1394 OHCI, the SelfIDComplete event occurs when the hardware has
> finished transmitting all of the self ID packets received during the bus
> initialization process to the host memory by DMA.
> 
> This commit adds a tracepoints event for this event to trace the timing
> and packet data of Self-ID DMA. It is the part of following tracepoints
> events helpful to debug some events at bus reset; e.g. the issue addressed
> at a commit d0b06dc48fb1 ("firewire: core: use long bus reset on gap count
> error")[1]:
> 
> * firewire_ohci:irqs
> * firewire_ohci:self_id_complete
> * firewire:bus_reset_handle
> * firewire:self_id_sequence
> 
> They would be also helpful in the problem about invocation timing of
> hardIRQ/softIRQ contexts. We can often see this kind of problem with -rt
> kernel[2].

Oops, I misunderstood. The handling of Self-ID DMA buffer is in hardIRQ
and process (workqueue) contexts, thus the above issue is not the
invocation timing of hardIRQ/softIRQ contexts. Let me correct it at the
applied commit comment.

> [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d0b06dc48fb1
> [2] https://lore.kernel.org/linux-rt-users/YAwPoaUZ1gTD5y+k@hmbx/
> 
> Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
> ---
>  drivers/firewire/ohci.c              | 11 +++++-
>  include/trace/events/firewire_ohci.h | 54 ++++++++++++++++++++++++++++
>  2 files changed, 64 insertions(+), 1 deletion(-)


Regards

Takashi Sakamoto

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2024-07-04  0:07 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-07-02 22:20 [PATCH 0/5] firewire: ohci: add tracepoints event for data of Self-ID DMA Takashi Sakamoto
2024-07-02 22:20 ` [PATCH 1/5] firewire: ohci: use common macro to interpret be32 data in le32 buffer Takashi Sakamoto
2024-07-02 22:20 ` [PATCH 2/5] firewire: ohci: use static function to handle endian issue on PowerPC platform Takashi Sakamoto
2024-07-02 22:20 ` [PATCH 3/5] firewire: ohci: add static inline functions to deserialize for Self-ID DMA operation Takashi Sakamoto
2024-07-02 22:20 ` [PATCH 4/5] firewire: ohci: use inline functions to operate data of self-ID DMA Takashi Sakamoto
2024-07-02 22:20 ` [PATCH 5/5] firewire: ohci: add tracepoints event for data of Self-ID DMA Takashi Sakamoto
2024-07-04  0:07   ` Takashi Sakamoto
2024-07-03 23:30 ` [PATCH 0/5] " Takashi Sakamoto

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox