Skip to content

Commit 24b7f8e

Browse files
committed
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/[email protected] Signed-off-by: Takashi Sakamoto <[email protected]>
1 parent e404cac commit 24b7f8e

File tree

1 file changed

+69
-120
lines changed

1 file changed

+69
-120
lines changed

drivers/firewire/core-topology.c

Lines changed: 69 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -20,80 +20,15 @@
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

9833
static 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
*/
169104
static 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

Comments
 (0)