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.

firewire: core: use helper functions for self ID sequence

This commit replaces the existing implementation with the helper
functions for self ID sequence.

Link: https://lore.kernel.org/r/20240605235155.116468-6-o-takashi@sakamocchi.jp
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>

+69 -120
+69 -120
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 25 26 #define SELF_ID_PHY_ID(q) (((q) >> 24) & 0x3f) 26 - #define SELF_ID_EXTENDED(q) (((q) >> 23) & 0x01) 27 27 #define SELF_ID_LINK_ON(q) (((q) >> 22) & 0x01) 28 28 #define SELF_ID_GAP_COUNT(q) (((q) >> 16) & 0x3f) 29 29 #define SELF_ID_PHY_SPEED(q) (((q) >> 14) & 0x03) 30 30 #define SELF_ID_CONTENDER(q) (((q) >> 11) & 0x01) 31 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 const u32 *count_ports(const u32 *sid, int *total_port_count, int *child_port_count) 42 - { 43 - u32 q; 44 - int port_type, shift, seq; 45 - 46 - shift = 6; 47 - q = *sid; 48 - seq = 0; 49 - 50 - while (1) { 51 - port_type = (q >> shift) & 0x03; 52 - switch (port_type) { 53 - case SELFID_PORT_CHILD: 54 - (*child_port_count)++; 55 - fallthrough; 56 - case SELFID_PORT_PARENT: 57 - case SELFID_PORT_NCONN: 58 - (*total_port_count)++; 59 - fallthrough; 60 - case SELFID_PORT_NONE: 61 - break; 62 - } 63 - 64 - shift -= 2; 65 - if (shift == 0) { 66 - if (!SELF_ID_MORE_PACKETS(q)) 67 - return sid + 1; 68 - 69 - shift = 16; 70 - sid++; 71 - q = *sid; 72 - 73 - /* 74 - * Check that the extra packets actually are 75 - * extended self ID packets and that the 76 - * sequence numbers in the extended self ID 77 - * packets increase as expected. 78 - */ 79 - 80 - if (!SELF_ID_EXTENDED(q) || 81 - seq != SELF_ID_EXT_SEQUENCE(q)) 82 - return NULL; 83 - 84 - seq++; 85 - } 86 - } 87 - } 88 - 89 - static int get_port_type(const u32 *sid, int port_index) 90 - { 91 - int index, shift; 92 - 93 - index = (port_index + 5) / 8; 94 - shift = 16 - ((port_index + 5) & 7) * 2; 95 - return (sid[index] >> shift) & 0x03; 96 - } 97 32 98 33 static struct fw_node *fw_node_create(u32 sid, int port_count, int color) 99 34 { ··· 103 168 */ 104 169 static struct fw_node *build_tree(struct fw_card *card, const u32 *sid, int self_id_count) 105 170 { 171 + struct self_id_sequence_enumerator enumerator = { 172 + .cursor = sid, 173 + .quadlet_count = self_id_count, 174 + }; 106 175 struct fw_node *node, *child, *local_node, *irm_node; 107 176 struct list_head stack; 108 - const u32 *end; 109 177 int phy_id, stack_depth; 110 178 int gap_count; 111 179 bool beta_repeaters_present; ··· 117 179 node = NULL; 118 180 INIT_LIST_HEAD(&stack); 119 181 stack_depth = 0; 120 - end = sid + self_id_count; 121 182 phy_id = 0; 122 183 irm_node = NULL; 123 184 gap_count = SELF_ID_GAP_COUNT(*sid); 124 185 beta_repeaters_present = false; 125 186 126 - while (sid < end) { 127 - int port_count = 0; 128 - int child_port_count = 0; 129 - int parent_count = 0; 130 - const u32 *next_sid; 131 - u32 q; 187 + while (enumerator.quadlet_count > 0) { 188 + unsigned int child_port_count = 0; 189 + unsigned int total_port_count = 0; 190 + unsigned int parent_count = 0; 191 + unsigned int quadlet_count; 192 + const u32 *self_id_sequence; 193 + unsigned int port_capacity; 194 + enum phy_packet_self_id_port_status port_status; 195 + unsigned int port_index; 132 196 struct list_head *h; 133 197 int i; 134 198 135 - next_sid = count_ports(sid, &port_count, &child_port_count); 136 - if (next_sid == NULL) { 137 - fw_err(card, "inconsistent extended self IDs\n"); 138 - return NULL; 199 + self_id_sequence = self_id_sequence_enumerator_next(&enumerator, &quadlet_count); 200 + if (IS_ERR(self_id_sequence)) { 201 + if (PTR_ERR(self_id_sequence) != -ENODATA) { 202 + fw_err(card, "inconsistent extended self IDs: %ld\n", 203 + PTR_ERR(self_id_sequence)); 204 + return NULL; 205 + } 206 + break; 139 207 } 140 208 141 - q = *sid; 142 - if (phy_id != SELF_ID_PHY_ID(q)) { 209 + port_capacity = self_id_sequence_get_port_capacity(quadlet_count); 210 + for (port_index = 0; port_index < port_capacity; ++port_index) { 211 + port_status = self_id_sequence_get_port_status(self_id_sequence, quadlet_count, 212 + port_index); 213 + switch (port_status) { 214 + case PHY_PACKET_SELF_ID_PORT_STATUS_CHILD: 215 + ++child_port_count; 216 + fallthrough; 217 + case PHY_PACKET_SELF_ID_PORT_STATUS_PARENT: 218 + case PHY_PACKET_SELF_ID_PORT_STATUS_NCONN: 219 + ++total_port_count; 220 + fallthrough; 221 + case PHY_PACKET_SELF_ID_PORT_STATUS_NONE: 222 + default: 223 + break; 224 + } 225 + } 226 + 227 + if (phy_id != SELF_ID_PHY_ID(self_id_sequence[0])) { 143 228 fw_err(card, "PHY ID mismatch in self ID: %d != %d\n", 144 - phy_id, SELF_ID_PHY_ID(q)); 229 + phy_id, SELF_ID_PHY_ID(self_id_sequence[0])); 145 230 return NULL; 146 231 } 147 232 ··· 185 224 */ 186 225 child = fw_node(h); 187 226 188 - node = fw_node_create(q, port_count, card->color); 227 + node = fw_node_create(self_id_sequence[0], total_port_count, card->color); 189 228 if (node == NULL) { 190 229 fw_err(card, "out of memory while building topology\n"); 191 230 return NULL; ··· 194 233 if (phy_id == (card->node_id & 0x3f)) 195 234 local_node = node; 196 235 197 - if (SELF_ID_CONTENDER(q)) 236 + if (SELF_ID_CONTENDER(self_id_sequence[0])) 198 237 irm_node = node; 199 238 200 - parent_count = 0; 201 - 202 - for (i = 0; i < port_count; i++) { 203 - switch (get_port_type(sid, i)) { 204 - case SELFID_PORT_PARENT: 205 - /* 206 - * Who's your daddy? We dont know the 207 - * parent node at this time, so we 208 - * temporarily abuse node->color for 209 - * remembering the entry in the 210 - * node->ports array where the parent 211 - * node should be. Later, when we 212 - * handle the parent node, we fix up 213 - * the reference. 214 - */ 215 - parent_count++; 239 + for (port_index = 0; port_index < total_port_count; ++port_index) { 240 + port_status = self_id_sequence_get_port_status(self_id_sequence, quadlet_count, 241 + port_index); 242 + switch (port_status) { 243 + case PHY_PACKET_SELF_ID_PORT_STATUS_PARENT: 244 + // Who's your daddy? We dont know the parent node at this time, so 245 + // we temporarily abuse node->color for remembering the entry in 246 + // the node->ports array where the parent node should be. Later, 247 + // when we handle the parent node, we fix up the reference. 248 + ++parent_count; 216 249 node->color = i; 217 250 break; 218 251 219 - case SELFID_PORT_CHILD: 220 - node->ports[i] = child; 221 - /* 222 - * Fix up parent reference for this 223 - * child node. 224 - */ 252 + case PHY_PACKET_SELF_ID_PORT_STATUS_CHILD: 253 + node->ports[port_index] = child; 254 + // Fix up parent reference for this child node. 225 255 child->ports[child->color] = node; 226 256 child->color = card->color; 227 257 child = fw_node(child->link.next); 228 258 break; 259 + case PHY_PACKET_SELF_ID_PORT_STATUS_NCONN: 260 + case PHY_PACKET_SELF_ID_PORT_STATUS_NONE: 261 + default: 262 + break; 229 263 } 230 264 } 231 265 232 - /* 233 - * Check that the node reports exactly one parent 234 - * port, except for the root, which of course should 235 - * have no parents. 236 - */ 237 - if ((next_sid == end && parent_count != 0) || 238 - (next_sid < end && parent_count != 1)) { 266 + // Check that the node reports exactly one parent port, except for the root, which 267 + // of course should have no parents. 268 + if ((enumerator.quadlet_count == 0 && parent_count != 0) || 269 + (enumerator.quadlet_count > 0 && parent_count != 1)) { 239 270 fw_err(card, "parent port inconsistency for node %d: " 240 271 "parent_count=%d\n", phy_id, parent_count); 241 272 return NULL; ··· 238 285 list_add_tail(&node->link, &stack); 239 286 stack_depth += 1 - child_port_count; 240 287 241 - if (node->phy_speed == SCODE_BETA && 242 - parent_count + child_port_count > 1) 288 + if (node->phy_speed == SCODE_BETA && parent_count + child_port_count > 1) 243 289 beta_repeaters_present = true; 244 290 245 - /* 246 - * If PHYs report different gap counts, set an invalid count 247 - * which will force a gap count reconfiguration and a reset. 248 - */ 249 - if (SELF_ID_GAP_COUNT(q) != gap_count) 291 + // If PHYs report different gap counts, set an invalid count which will force a gap 292 + // count reconfiguration and a reset. 293 + if (SELF_ID_GAP_COUNT(self_id_sequence[0]) != gap_count) 250 294 gap_count = 0; 251 295 252 296 update_hop_count(node); 253 297 254 - sid = next_sid; 255 298 phy_id++; 256 299 } 257 300