4 * GUID collection and management
6 * Copyright (C) 2000 Andreas E. Bombe
8 * This code is licensed under the GPL. See the file COPYING in the root
9 * directory of the kernel sources for details.
12 #include <linux/kernel.h>
13 #include <linux/list.h>
14 #include <linux/slab.h>
15 #include <asm/byteorder.h>
16 #include <asm/atomic.h>
18 #include "ieee1394_types.h"
21 #include "ieee1394_transactions.h"
22 #include "highlevel.h"
26 static atomic_t outstanding_requests
;
28 static LIST_HEAD(guid_list
);
29 rwlock_t guid_lock
= RW_LOCK_UNLOCKED
;
32 struct list_head list
;
37 struct hpsb_host
*host
;
44 struct hpsb_packet
*pkt
;
49 static struct guid_entry
*create_guid_entry(void)
51 struct guid_entry
*ge
;
54 ge
= kmalloc(sizeof(struct guid_entry
), SLAB_ATOMIC
);
57 INIT_LIST_HEAD(&ge
->list
);
58 atomic_set(&ge
->refcount
, 0);
62 atomic_set(&ge
->generation
, -1);
64 write_lock_irqsave(&guid_lock
, flags
);
65 list_add_tail(&ge
->list
, &guid_list
);
66 write_unlock_irqrestore(&guid_lock
, flags
);
71 static struct guid_entry
*find_entry(u64 guid
)
74 struct guid_entry
*ge
;
77 while (lh
!= &guid_list
) {
78 ge
= list_entry(lh
, struct guid_entry
, list
);
79 if (ge
->guid
== guid
) return ge
;
86 static void associate_guid(struct hpsb_host
*host
, nodeid_t nodeid
, u64 guid
)
88 struct guid_entry
*ge
;
91 HPSB_DEBUG("node %d on host 0x%p has GUID 0x%08x%08x",
92 nodeid
& NODE_MASK
, host
, (unsigned int)(guid
>> 32),
93 (unsigned int)(guid
& 0xffffffff));
95 read_lock_irqsave(&guid_lock
, flags
);
96 ge
= find_entry(guid
);
97 read_unlock_irqrestore(&guid_lock
, flags
);
99 if (!ge
) ge
= create_guid_entry();
103 ge
->node_id
= nodeid
;
106 atomic_set(&ge
->generation
, get_hpsb_generation());
109 static void pkt_complete(struct guid_req
*req
)
111 struct hpsb_packet
*pkt
= req
->pkt
;
112 int rcode
= (pkt
->header
[1] >> 12) & 0xf;
114 if (pkt
->ack_code
== ACK_PENDING
&& rcode
== RCODE_COMPLETE
) {
115 if (*(char *)pkt
->data
> 1) {
116 associate_guid(pkt
->host
, pkt
->node_id
,
117 ((u64
)be32_to_cpu(pkt
->data
[3]) << 32)
118 | be32_to_cpu(pkt
->data
[4]));
120 HPSB_DEBUG("minimal ROM on node %d",
121 pkt
->node_id
& NODE_MASK
);
124 HPSB_DEBUG("guid transaction error: ack %d, rcode %d",
125 pkt
->ack_code
, rcode
);
128 free_tlabel(pkt
->host
, pkt
->node_id
, pkt
->tlabel
);
129 free_hpsb_packet(pkt
);
132 if (atomic_dec_and_test(&outstanding_requests
)) {
133 /* FIXME: free unreferenced and inactive GUID entries. */
138 static void host_reset(struct hpsb_host
*host
)
140 struct guid_req
*greq
;
141 struct hpsb_packet
*pkt
;
142 struct selfid
*sid
= (struct selfid
*)host
->topology_map
;
143 int nodecount
= host
->node_count
;
144 nodeid_t nodeid
= LOCAL_BUS
;
146 for (; nodecount
; nodecount
--, nodeid
++, sid
++) {
147 while (sid
->extended
) sid
++;
148 if (!sid
->link_active
) continue;
149 if (nodeid
== host
->node_id
) continue;
151 greq
= kmalloc(sizeof(struct guid_req
), SLAB_ATOMIC
);
153 HPSB_ERR("out of memory in GUID processing");
157 pkt
= hpsb_make_readbpacket(host
, nodeid
,
158 CSR_REGISTER_BASE
+ CSR_CONFIG_ROM
,
162 HPSB_ERR("out of memory in GUID processing");
166 greq
->tq
.next
= NULL
;
168 greq
->tq
.routine
= (void (*)(void*))pkt_complete
;
169 greq
->tq
.data
= greq
;
172 queue_task(&greq
->tq
, &pkt
->complete_tq
);
174 if (!hpsb_send_packet(pkt
)) {
175 free_tlabel(pkt
->host
, pkt
->node_id
, pkt
->tlabel
);
176 free_hpsb_packet(pkt
);
178 HPSB_NOTICE("failed to send packet in GUID processing");
181 HPSB_INFO("GUID request sent to node %d", nodeid
& NODE_MASK
);
182 atomic_inc(&outstanding_requests
);
187 struct guid_entry
*hpsb_guid_get_handle(u64 guid
)
190 struct guid_entry
*ge
;
192 read_lock_irqsave(&guid_lock
, flags
);
193 ge
= find_entry(guid
);
194 if (ge
) atomic_inc(&ge
->refcount
);
195 read_unlock_irqrestore(&guid_lock
, flags
);
200 struct hpsb_host
*hpsb_guid_localhost(struct guid_entry
*ge
)
202 if (atomic_read(&ge
->generation
) != get_hpsb_generation()) return NULL
;
203 if (ge
->node_id
== ge
->host
->node_id
) return ge
->host
;
207 int hpsb_guid_fill_packet(struct guid_entry
*ge
, struct hpsb_packet
*pkt
)
209 if (atomic_read(&ge
->generation
) != get_hpsb_generation()) return 0;
211 pkt
->host
= ge
->host
;
212 pkt
->node_id
= ge
->node_id
;
213 pkt
->generation
= atomic_read(&ge
->generation
);
218 static struct hpsb_highlevel_ops guid_ops
= {
219 host_reset
: host_reset
,
222 void init_ieee1394_guid(void)
224 atomic_set(&outstanding_requests
, 0);
226 if (!hpsb_register_highlevel("GUID manager", &guid_ops
)) {
227 HPSB_ERR("out of memory during ieee1394 initialization");