2020#include <asm/byteorder.h>
2121
2222#include "core.h"
23+ #include "phy-packet-definitions.h"
2324#include <trace/events/firewire.h>
2425
2526#define SELF_ID_PHY_ID (q ) (((q) >> 24) & 0x3f)
26- #define SELF_ID_EXTENDED (q ) (((q) >> 23) & 0x01)
2727#define SELF_ID_LINK_ON (q ) (((q) >> 22) & 0x01)
2828#define SELF_ID_GAP_COUNT (q ) (((q) >> 16) & 0x3f)
2929#define SELF_ID_PHY_SPEED (q ) (((q) >> 14) & 0x03)
3030#define SELF_ID_CONTENDER (q ) (((q) >> 11) & 0x01)
3131#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- }
9732
9833static struct fw_node * fw_node_create (u32 sid , int port_count , int color )
9934{
@@ -168,9 +103,12 @@ static inline struct fw_node *fw_node(struct list_head *l)
168103 */
169104static struct fw_node * build_tree (struct fw_card * card , const u32 * sid , int self_id_count )
170105{
106+ struct self_id_sequence_enumerator enumerator = {
107+ .cursor = sid ,
108+ .quadlet_count = self_id_count ,
109+ };
171110 struct fw_node * node , * child , * local_node , * irm_node ;
172111 struct list_head stack ;
173- const u32 * end ;
174112 int phy_id , stack_depth ;
175113 int gap_count ;
176114 bool beta_repeaters_present ;
@@ -179,31 +117,54 @@ static struct fw_node *build_tree(struct fw_card *card, const u32 *sid, int self
179117 node = NULL ;
180118 INIT_LIST_HEAD (& stack );
181119 stack_depth = 0 ;
182- end = sid + self_id_count ;
183120 phy_id = 0 ;
184121 irm_node = NULL ;
185122 gap_count = SELF_ID_GAP_COUNT (* sid );
186123 beta_repeaters_present = false;
187124
188- while (sid < end ) {
189- int port_count = 0 ;
190- int child_port_count = 0 ;
191- int parent_count = 0 ;
192- const u32 * next_sid ;
193- u32 q ;
125+ while (enumerator .quadlet_count > 0 ) {
126+ unsigned int child_port_count = 0 ;
127+ unsigned int total_port_count = 0 ;
128+ unsigned int parent_count = 0 ;
129+ unsigned int quadlet_count ;
130+ const u32 * self_id_sequence ;
131+ unsigned int port_capacity ;
132+ enum phy_packet_self_id_port_status port_status ;
133+ unsigned int port_index ;
194134 struct list_head * h ;
195135 int i ;
196136
197- next_sid = count_ports (sid , & port_count , & child_port_count );
198- if (next_sid == NULL ) {
199- fw_err (card , "inconsistent extended self IDs\n" );
200- return NULL ;
137+ self_id_sequence = self_id_sequence_enumerator_next (& enumerator , & quadlet_count );
138+ if (IS_ERR (self_id_sequence )) {
139+ if (PTR_ERR (self_id_sequence ) != - ENODATA ) {
140+ fw_err (card , "inconsistent extended self IDs: %ld\n" ,
141+ PTR_ERR (self_id_sequence ));
142+ return NULL ;
143+ }
144+ break ;
201145 }
202146
203- q = * sid ;
204- if (phy_id != SELF_ID_PHY_ID (q )) {
147+ port_capacity = self_id_sequence_get_port_capacity (quadlet_count );
148+ for (port_index = 0 ; port_index < port_capacity ; ++ port_index ) {
149+ port_status = self_id_sequence_get_port_status (self_id_sequence , quadlet_count ,
150+ port_index );
151+ switch (port_status ) {
152+ case PHY_PACKET_SELF_ID_PORT_STATUS_CHILD :
153+ ++ child_port_count ;
154+ fallthrough ;
155+ case PHY_PACKET_SELF_ID_PORT_STATUS_PARENT :
156+ case PHY_PACKET_SELF_ID_PORT_STATUS_NCONN :
157+ ++ total_port_count ;
158+ fallthrough ;
159+ case PHY_PACKET_SELF_ID_PORT_STATUS_NONE :
160+ default :
161+ break ;
162+ }
163+ }
164+
165+ if (phy_id != SELF_ID_PHY_ID (self_id_sequence [0 ])) {
205166 fw_err (card , "PHY ID mismatch in self ID: %d != %d\n" ,
206- phy_id , SELF_ID_PHY_ID (q ));
167+ phy_id , SELF_ID_PHY_ID (self_id_sequence [ 0 ] ));
207168 return NULL ;
208169 }
209170
@@ -224,7 +185,7 @@ static struct fw_node *build_tree(struct fw_card *card, const u32 *sid, int self
224185 */
225186 child = fw_node (h );
226187
227- node = fw_node_create (q , port_count , card -> color );
188+ node = fw_node_create (self_id_sequence [ 0 ], total_port_count , card -> color );
228189 if (node == NULL ) {
229190 fw_err (card , "out of memory while building topology\n" );
230191 return NULL ;
@@ -233,48 +194,40 @@ static struct fw_node *build_tree(struct fw_card *card, const u32 *sid, int self
233194 if (phy_id == (card -> node_id & 0x3f ))
234195 local_node = node ;
235196
236- if (SELF_ID_CONTENDER (q ))
197+ if (SELF_ID_CONTENDER (self_id_sequence [ 0 ] ))
237198 irm_node = node ;
238199
239- parent_count = 0 ;
240-
241- for (i = 0 ; i < port_count ; i ++ ) {
242- switch (get_port_type (sid , i )) {
243- case SELFID_PORT_PARENT :
244- /*
245- * Who's your daddy? We dont know the
246- * parent node at this time, so we
247- * temporarily abuse node->color for
248- * remembering the entry in the
249- * node->ports array where the parent
250- * node should be. Later, when we
251- * handle the parent node, we fix up
252- * the reference.
253- */
254- parent_count ++ ;
200+ for (port_index = 0 ; port_index < total_port_count ; ++ port_index ) {
201+ port_status = self_id_sequence_get_port_status (self_id_sequence , quadlet_count ,
202+ port_index );
203+ switch (port_status ) {
204+ case PHY_PACKET_SELF_ID_PORT_STATUS_PARENT :
205+ // Who's your daddy? We dont know the parent node at this time, so
206+ // we temporarily abuse node->color for remembering the entry in
207+ // the node->ports array where the parent node should be. Later,
208+ // when we handle the parent node, we fix up the reference.
209+ ++ parent_count ;
255210 node -> color = i ;
256211 break ;
257212
258- case SELFID_PORT_CHILD :
259- node -> ports [i ] = child ;
260- /*
261- * Fix up parent reference for this
262- * child node.
263- */
213+ case PHY_PACKET_SELF_ID_PORT_STATUS_CHILD :
214+ node -> ports [port_index ] = child ;
215+ // Fix up parent reference for this child node.
264216 child -> ports [child -> color ] = node ;
265217 child -> color = card -> color ;
266218 child = fw_node (child -> link .next );
267219 break ;
220+ case PHY_PACKET_SELF_ID_PORT_STATUS_NCONN :
221+ case PHY_PACKET_SELF_ID_PORT_STATUS_NONE :
222+ default :
223+ break ;
268224 }
269225 }
270226
271- /*
272- * Check that the node reports exactly one parent
273- * port, except for the root, which of course should
274- * have no parents.
275- */
276- if ((next_sid == end && parent_count != 0 ) ||
277- (next_sid < end && parent_count != 1 )) {
227+ // Check that the node reports exactly one parent port, except for the root, which
228+ // of course should have no parents.
229+ if ((enumerator .quadlet_count == 0 && parent_count != 0 ) ||
230+ (enumerator .quadlet_count > 0 && parent_count != 1 )) {
278231 fw_err (card , "parent port inconsistency for node %d: "
279232 "parent_count=%d\n" , phy_id , parent_count );
280233 return NULL ;
@@ -285,20 +238,16 @@ static struct fw_node *build_tree(struct fw_card *card, const u32 *sid, int self
285238 list_add_tail (& node -> link , & stack );
286239 stack_depth += 1 - child_port_count ;
287240
288- if (node -> phy_speed == SCODE_BETA &&
289- parent_count + child_port_count > 1 )
241+ if (node -> phy_speed == SCODE_BETA && parent_count + child_port_count > 1 )
290242 beta_repeaters_present = true;
291243
292- /*
293- * If PHYs report different gap counts, set an invalid count
294- * which will force a gap count reconfiguration and a reset.
295- */
296- if (SELF_ID_GAP_COUNT (q ) != gap_count )
244+ // If PHYs report different gap counts, set an invalid count which will force a gap
245+ // count reconfiguration and a reset.
246+ if (SELF_ID_GAP_COUNT (self_id_sequence [0 ]) != gap_count )
297247 gap_count = 0 ;
298248
299249 update_hop_count (node );
300250
301- sid = next_sid ;
302251 phy_id ++ ;
303252 }
304253
0 commit comments