]> www.infradead.org Git - users/willy/xarray.git/commitdiff
firewire: core: add tests for serialization/deserialization of phy config packet
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>
Thu, 6 Jun 2024 23:51:32 +0000 (08:51 +0900)
committerTakashi Sakamoto <o-takashi@sakamocchi.jp>
Sun, 16 Jun 2024 23:37:03 +0000 (08:37 +0900)
In the protocol of IEEE 1394, phy configuration packet is broadcasted to
the bus to configure all PHYs residing on the bus. It includes two
purposes; selecting root node and optimizing gap count.

This commit adds some helper function to serialize/deserialize the
content of phy configuration packet, as well as some KUnit tests for it.

Link: https://lore.kernel.org/r/20240606235133.231543-2-o-takashi@sakamocchi.jp
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
drivers/firewire/packet-serdes-test.c
drivers/firewire/phy-packet-definitions.h

index c56199e84f91162c45af293615a0b2ceac649e2b..62ba433756ae60f513e84ad2e78c4244914048c7 100644 (file)
@@ -248,6 +248,29 @@ static void deserialize_phy_packet_self_id_extended(u32 quadlet, unsigned int *p
        *has_more_packets = phy_packet_self_id_get_more_packets(quadlet);
 }
 
+static void serialize_phy_packet_phy_config(u32 *quadlet, unsigned int packet_identifier,
+                                           unsigned int root_id, bool has_force_root_node,
+                                           bool has_gap_count_optimization, unsigned int gap_count)
+{
+       phy_packet_set_packet_identifier(quadlet, packet_identifier);
+       phy_packet_phy_config_set_root_id(quadlet, root_id);
+       phy_packet_phy_config_set_force_root_node(quadlet, has_force_root_node);
+       phy_packet_phy_config_set_gap_count_optimization(quadlet, has_gap_count_optimization);
+       phy_packet_phy_config_set_gap_count(quadlet, gap_count);
+}
+
+static void deserialize_phy_packet_phy_config(u32 quadlet, unsigned int *packet_identifier,
+                                             unsigned int *root_id, bool *has_force_root_node,
+                                             bool *has_gap_count_optimization,
+                                             unsigned int *gap_count)
+{
+       *packet_identifier = phy_packet_get_packet_identifier(quadlet);
+       *root_id = phy_packet_phy_config_get_root_id(quadlet);
+       *has_force_root_node = phy_packet_phy_config_get_force_root_node(quadlet);
+       *has_gap_count_optimization = phy_packet_phy_config_get_gap_count_optimization(quadlet);
+       *gap_count = phy_packet_phy_config_get_gap_count(quadlet);
+}
+
 static void test_async_header_write_quadlet_request(struct kunit *test)
 {
        static const u32 expected[ASYNC_HEADER_QUADLET_COUNT] = {
@@ -811,6 +834,60 @@ static void test_phy_packet_self_id_zero_and_one(struct kunit *test)
        KUNIT_EXPECT_MEMEQ(test, quadlets, expected, sizeof(expected));
 }
 
+static void test_phy_packet_phy_config_force_root_node(struct kunit *test)
+{
+       const u32 expected = 0x02800000;
+       u32 quadlet = 0;
+
+       unsigned int packet_identifier;
+       unsigned int root_id;
+       bool has_force_root_node;
+       bool has_gap_count_optimization;
+       unsigned int gap_count;
+
+       deserialize_phy_packet_phy_config(expected, &packet_identifier, &root_id,
+                                         &has_force_root_node, &has_gap_count_optimization,
+                                         &gap_count);
+
+       KUNIT_EXPECT_EQ(test, PHY_PACKET_PACKET_IDENTIFIER_PHY_CONFIG, packet_identifier);
+       KUNIT_EXPECT_EQ(test, 0x02, root_id);
+       KUNIT_EXPECT_TRUE(test, has_force_root_node);
+       KUNIT_EXPECT_FALSE(test, has_gap_count_optimization);
+       KUNIT_EXPECT_EQ(test, 0, gap_count);
+
+       serialize_phy_packet_phy_config(&quadlet, packet_identifier, root_id, has_force_root_node,
+                                       has_gap_count_optimization, gap_count);
+
+       KUNIT_EXPECT_EQ(test, quadlet, expected);
+}
+
+static void test_phy_packet_phy_config_gap_count_optimization(struct kunit *test)
+{
+       const u32 expected = 0x034f0000;
+       u32 quadlet = 0;
+
+       unsigned int packet_identifier;
+       unsigned int root_id;
+       bool has_force_root_node;
+       bool has_gap_count_optimization;
+       unsigned int gap_count;
+
+       deserialize_phy_packet_phy_config(expected, &packet_identifier, &root_id,
+                                         &has_force_root_node, &has_gap_count_optimization,
+                                         &gap_count);
+
+       KUNIT_EXPECT_EQ(test, PHY_PACKET_PACKET_IDENTIFIER_PHY_CONFIG, packet_identifier);
+       KUNIT_EXPECT_EQ(test, 0x03, root_id);
+       KUNIT_EXPECT_FALSE(test, has_force_root_node);
+       KUNIT_EXPECT_TRUE(test, has_gap_count_optimization);
+       KUNIT_EXPECT_EQ(test, 0x0f, gap_count);
+
+       serialize_phy_packet_phy_config(&quadlet, packet_identifier, root_id, has_force_root_node,
+                                       has_gap_count_optimization, gap_count);
+
+       KUNIT_EXPECT_EQ(test, quadlet, expected);
+}
+
 static struct kunit_case packet_serdes_test_cases[] = {
        KUNIT_CASE(test_async_header_write_quadlet_request),
        KUNIT_CASE(test_async_header_write_block_request),
@@ -825,6 +902,8 @@ static struct kunit_case packet_serdes_test_cases[] = {
        KUNIT_CASE(test_phy_packet_self_id_zero_case0),
        KUNIT_CASE(test_phy_packet_self_id_zero_case1),
        KUNIT_CASE(test_phy_packet_self_id_zero_and_one),
+       KUNIT_CASE(test_phy_packet_phy_config_force_root_node),
+       KUNIT_CASE(test_phy_packet_phy_config_gap_count_optimization),
        {}
 };
 
index 8f78494ad371ef9eb8999fcbce6ad0c0b6c7369a..03c7c606759f972ec836c2b6b3d9c131f761a270 100644 (file)
@@ -21,6 +21,61 @@ static inline void phy_packet_set_packet_identifier(u32 *quadlet, unsigned int p
        *quadlet |= (packet_identifier << PACKET_IDENTIFIER_SHIFT) & PACKET_IDENTIFIER_MASK;
 }
 
+#define PHY_PACKET_PACKET_IDENTIFIER_PHY_CONFIG                0
+
+#define PHY_CONFIG_ROOT_ID_MASK                                0x3f000000
+#define PHY_CONFIG_ROOT_ID_SHIFT                       24
+#define PHY_CONFIG_FORCE_ROOT_NODE_MASK                        0x00800000
+#define PHY_CONFIG_FORCE_ROOT_NODE_SHIFT               23
+#define PHY_CONFIG_GAP_COUNT_OPTIMIZATION_MASK         0x00400000
+#define PHY_CONFIG_GAP_COUNT_OPTIMIZATION_SHIFT                22
+#define PHY_CONFIG_GAP_COUNT_MASK                      0x003f0000
+#define PHY_CONFIG_GAP_COUNT_SHIFT                     16
+
+static inline unsigned int phy_packet_phy_config_get_root_id(u32 quadlet)
+{
+       return (quadlet & PHY_CONFIG_ROOT_ID_MASK) >> PHY_CONFIG_ROOT_ID_SHIFT;
+}
+
+static inline void phy_packet_phy_config_set_root_id(u32 *quadlet, unsigned int root_id)
+{
+       *quadlet &= ~PHY_CONFIG_ROOT_ID_MASK;
+       *quadlet |= (root_id << PHY_CONFIG_ROOT_ID_SHIFT) & PHY_CONFIG_ROOT_ID_MASK;
+}
+
+static inline bool phy_packet_phy_config_get_force_root_node(u32 quadlet)
+{
+       return (quadlet & PHY_CONFIG_FORCE_ROOT_NODE_MASK) >> PHY_CONFIG_FORCE_ROOT_NODE_SHIFT;
+}
+
+static inline void phy_packet_phy_config_set_force_root_node(u32 *quadlet, bool has_force_root_node)
+{
+       *quadlet &= ~PHY_CONFIG_FORCE_ROOT_NODE_MASK;
+       *quadlet |= (has_force_root_node << PHY_CONFIG_FORCE_ROOT_NODE_SHIFT) & PHY_CONFIG_FORCE_ROOT_NODE_MASK;
+}
+
+static inline bool phy_packet_phy_config_get_gap_count_optimization(u32 quadlet)
+{
+       return (quadlet & PHY_CONFIG_GAP_COUNT_OPTIMIZATION_MASK) >> PHY_CONFIG_GAP_COUNT_OPTIMIZATION_SHIFT;
+}
+
+static inline void phy_packet_phy_config_set_gap_count_optimization(u32 *quadlet, bool has_gap_count_optimization)
+{
+       *quadlet &= ~PHY_CONFIG_GAP_COUNT_OPTIMIZATION_MASK;
+       *quadlet |= (has_gap_count_optimization << PHY_CONFIG_GAP_COUNT_OPTIMIZATION_SHIFT) & PHY_CONFIG_GAP_COUNT_OPTIMIZATION_MASK;
+}
+
+static inline unsigned int phy_packet_phy_config_get_gap_count(u32 quadlet)
+{
+       return (quadlet & PHY_CONFIG_GAP_COUNT_MASK) >> PHY_CONFIG_GAP_COUNT_SHIFT;
+}
+
+static inline void phy_packet_phy_config_set_gap_count(u32 *quadlet, unsigned int gap_count)
+{
+       *quadlet &= ~PHY_CONFIG_GAP_COUNT_MASK;
+       *quadlet |= (gap_count << PHY_CONFIG_GAP_COUNT_SHIFT) & PHY_CONFIG_GAP_COUNT_MASK;
+}
+
 #define PHY_PACKET_PACKET_IDENTIFIER_SELF_ID           2
 
 #define SELF_ID_PHY_ID_MASK                            0x3f000000