blob: b368958dc06c8f27d5c26b0691cbceeb87b8b260 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * IEEE 1394 for Linux
3 *
4 * Core support: hpsb_packet management, packet handling and forwarding to
5 * highlevel or lowlevel code
6 *
7 * Copyright (C) 1999, 2000 Andreas E. Bombe
8 * 2002 Manfred Weihs <weihs@ict.tuwien.ac.at>
9 *
10 * This code is licensed under the GPL. See the file COPYING in the root
11 * directory of the kernel sources for details.
12 *
13 *
14 * Contributions:
15 *
16 * Manfred Weihs <weihs@ict.tuwien.ac.at>
17 * loopback functionality in hpsb_send_packet
18 * allow highlevel drivers to disable automatic response generation
19 * and to generate responses themselves (deferred)
20 *
21 */
22
Linus Torvalds1da177e2005-04-16 15:20:36 -070023#include <linux/kernel.h>
24#include <linux/list.h>
25#include <linux/string.h>
26#include <linux/init.h>
27#include <linux/slab.h>
28#include <linux/interrupt.h>
29#include <linux/module.h>
30#include <linux/moduleparam.h>
31#include <linux/bitops.h>
32#include <linux/kdev_t.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/suspend.h>
Ben Collinsf6542402006-06-12 18:15:50 -040034#include <linux/kthread.h>
Pieter Palmers3dc5ea92007-02-03 17:44:39 +010035#include <linux/preempt.h>
36#include <linux/time.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070037
Pieter Palmers3dc5ea92007-02-03 17:44:39 +010038#include <asm/system.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070039#include <asm/byteorder.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070040
41#include "ieee1394_types.h"
42#include "ieee1394.h"
43#include "hosts.h"
44#include "ieee1394_core.h"
45#include "highlevel.h"
46#include "ieee1394_transactions.h"
47#include "csr.h"
48#include "nodemgr.h"
49#include "dma.h"
50#include "iso.h"
51#include "config_roms.h"
52
53/*
54 * Disable the nodemgr detection and config rom reading functionality.
55 */
Ben Collins1934b8b2005-07-09 20:01:23 -040056static int disable_nodemgr;
Linus Torvalds1da177e2005-04-16 15:20:36 -070057module_param(disable_nodemgr, int, 0444);
58MODULE_PARM_DESC(disable_nodemgr, "Disable nodemgr functionality.");
59
60/* Disable Isochronous Resource Manager functionality */
61int hpsb_disable_irm = 0;
Stefan Richter23e93f12006-03-28 20:03:34 -050062module_param_named(disable_irm, hpsb_disable_irm, bool, 0444);
Linus Torvalds1da177e2005-04-16 15:20:36 -070063MODULE_PARM_DESC(disable_irm,
64 "Disable Isochronous Resource Manager functionality.");
65
66/* We are GPL, so treat us special */
67MODULE_LICENSE("GPL");
68
69/* Some globals used */
70const char *hpsb_speedto_str[] = { "S100", "S200", "S400", "S800", "S1600", "S3200" };
gregkh@suse.de7e25ab92005-03-23 09:53:36 -080071struct class *hpsb_protocol_class;
Linus Torvalds1da177e2005-04-16 15:20:36 -070072
73#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
Jody McIntyredb2fd662005-09-30 11:59:09 -070074static void dump_packet(const char *text, quadlet_t *data, int size, int speed)
Linus Torvalds1da177e2005-04-16 15:20:36 -070075{
76 int i;
77
78 size /= 4;
79 size = (size > 4 ? 4 : size);
80
81 printk(KERN_DEBUG "ieee1394: %s", text);
Jody McIntyredb2fd662005-09-30 11:59:09 -070082 if (speed > -1 && speed < 6)
83 printk(" at %s", hpsb_speedto_str[speed]);
84 printk(":");
Linus Torvalds1da177e2005-04-16 15:20:36 -070085 for (i = 0; i < size; i++)
86 printk(" %08x", data[i]);
87 printk("\n");
88}
89#else
Stefan Richter611aa192006-08-02 18:44:00 +020090#define dump_packet(a,b,c,d) do {} while (0)
Linus Torvalds1da177e2005-04-16 15:20:36 -070091#endif
92
93static void abort_requests(struct hpsb_host *host);
94static void queue_packet_complete(struct hpsb_packet *packet);
95
96
97/**
Stefan Richterafd65462007-03-05 03:06:23 +010098 * hpsb_set_packet_complete_task - set task that runs when a packet completes
Linus Torvalds1da177e2005-04-16 15:20:36 -070099 * @packet: the packet whose completion we want the task added to
100 * @routine: function to call
101 * @data: data (if any) to pass to the above function
Stefan Richterafd65462007-03-05 03:06:23 +0100102 *
103 * Set the task that runs when a packet completes. You cannot call this more
104 * than once on a single packet before it is sent.
Stefan Richter7542e0e2007-03-25 22:22:40 +0200105 *
106 * Typically, the complete @routine is responsible to call hpsb_free_packet().
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107 */
108void hpsb_set_packet_complete_task(struct hpsb_packet *packet,
109 void (*routine)(void *), void *data)
110{
111 WARN_ON(packet->complete_routine != NULL);
112 packet->complete_routine = routine;
113 packet->complete_data = data;
114 return;
115}
116
117/**
118 * hpsb_alloc_packet - allocate new packet structure
Stefan Richter7542e0e2007-03-25 22:22:40 +0200119 * @data_size: size of the data block to be allocated, in bytes
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120 *
121 * This function allocates, initializes and returns a new &struct hpsb_packet.
Stefan Richter7542e0e2007-03-25 22:22:40 +0200122 * It can be used in interrupt context. A header block is always included and
123 * initialized with zeros. Its size is big enough to contain all possible 1394
124 * headers. The data block is only allocated if @data_size is not zero.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125 *
126 * For packets for which responses will be received the @data_size has to be big
127 * enough to contain the response's data block since no further allocation
128 * occurs at response matching time.
129 *
130 * The packet's generation value will be set to the current generation number
131 * for ease of use. Remember to overwrite it with your own recorded generation
132 * number if you can not be sure that your code will not race with a bus reset.
133 *
134 * Return value: A pointer to a &struct hpsb_packet or NULL on allocation
135 * failure.
136 */
137struct hpsb_packet *hpsb_alloc_packet(size_t data_size)
138{
Stefan Richter7542e0e2007-03-25 22:22:40 +0200139 struct hpsb_packet *packet;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140
141 data_size = ((data_size + 3) & ~3);
142
Stefan Richter7542e0e2007-03-25 22:22:40 +0200143 packet = kzalloc(sizeof(*packet) + data_size, GFP_ATOMIC);
144 if (!packet)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145 return NULL;
146
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147 packet->state = hpsb_unused;
148 packet->generation = -1;
149 INIT_LIST_HEAD(&packet->driver_list);
Stefan Richter7542e0e2007-03-25 22:22:40 +0200150 INIT_LIST_HEAD(&packet->queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151 atomic_set(&packet->refcnt, 1);
152
153 if (data_size) {
Stefan Richter7542e0e2007-03-25 22:22:40 +0200154 packet->data = packet->embedded_data;
155 packet->allocated_data_size = data_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157 return packet;
158}
159
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160/**
161 * hpsb_free_packet - free packet and data associated with it
162 * @packet: packet to free (is NULL safe)
163 *
Stefan Richter7542e0e2007-03-25 22:22:40 +0200164 * Frees @packet->data only if it was allocated through hpsb_alloc_packet().
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165 */
166void hpsb_free_packet(struct hpsb_packet *packet)
167{
168 if (packet && atomic_dec_and_test(&packet->refcnt)) {
Stefan Richter7542e0e2007-03-25 22:22:40 +0200169 BUG_ON(!list_empty(&packet->driver_list) ||
170 !list_empty(&packet->queue));
171 kfree(packet);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172 }
173}
174
Stefan Richterafd65462007-03-05 03:06:23 +0100175/**
176 * hpsb_reset_bus - initiate bus reset on the given host
177 * @host: host controller whose bus to reset
178 * @type: one of enum reset_types
179 *
180 * Returns 1 if bus reset already in progress, 0 otherwise.
181 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182int hpsb_reset_bus(struct hpsb_host *host, int type)
183{
Stefan Richter741854e2005-12-01 18:52:03 -0500184 if (!host->in_bus_reset) {
185 host->driver->devctl(host, RESET_BUS, type);
186 return 0;
187 } else {
188 return 1;
189 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190}
191
Pieter Palmers3dc5ea92007-02-03 17:44:39 +0100192/**
193 * hpsb_read_cycle_timer - read cycle timer register and system time
194 * @host: host whose isochronous cycle timer register is read
195 * @cycle_timer: address of bitfield to return the register contents
196 * @local_time: address to return the system time
197 *
198 * The format of * @cycle_timer, is described in OHCI 1.1 clause 5.13. This
199 * format is also read from non-OHCI controllers. * @local_time contains the
200 * system time in microseconds since the Epoch, read at the moment when the
201 * cycle timer was read.
202 *
203 * Return value: 0 for success or error number otherwise.
204 */
205int hpsb_read_cycle_timer(struct hpsb_host *host, u32 *cycle_timer,
206 u64 *local_time)
207{
208 int ctr;
209 struct timeval tv;
210 unsigned long flags;
211
212 if (!host || !cycle_timer || !local_time)
213 return -EINVAL;
214
215 preempt_disable();
216 local_irq_save(flags);
217
218 ctr = host->driver->devctl(host, GET_CYCLE_COUNTER, 0);
219 if (ctr)
220 do_gettimeofday(&tv);
221
222 local_irq_restore(flags);
223 preempt_enable();
224
225 if (!ctr)
226 return -EIO;
227 *cycle_timer = ctr;
228 *local_time = tv.tv_sec * 1000000ULL + tv.tv_usec;
229 return 0;
230}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231
Stefan Richterafd65462007-03-05 03:06:23 +0100232/**
233 * hpsb_bus_reset - notify a bus reset to the core
234 *
235 * For host driver module usage. Safe to use in interrupt context, although
236 * quite complex; so you may want to run it in the bottom rather than top half.
237 *
238 * Returns 1 if bus reset already in progress, 0 otherwise.
239 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240int hpsb_bus_reset(struct hpsb_host *host)
241{
Stefan Richter741854e2005-12-01 18:52:03 -0500242 if (host->in_bus_reset) {
243 HPSB_NOTICE("%s called while bus reset already in progress",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244 __FUNCTION__);
Stefan Richter741854e2005-12-01 18:52:03 -0500245 return 1;
246 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247
Stefan Richter741854e2005-12-01 18:52:03 -0500248 abort_requests(host);
249 host->in_bus_reset = 1;
250 host->irm_id = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 host->is_irm = 0;
Stefan Richter741854e2005-12-01 18:52:03 -0500252 host->busmgr_id = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253 host->is_busmgr = 0;
254 host->is_cycmst = 0;
Stefan Richter741854e2005-12-01 18:52:03 -0500255 host->node_count = 0;
256 host->selfid_count = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257
Stefan Richter741854e2005-12-01 18:52:03 -0500258 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259}
260
261
262/*
263 * Verify num_of_selfids SelfIDs and return number of nodes. Return zero in
264 * case verification failed.
265 */
266static int check_selfids(struct hpsb_host *host)
267{
Stefan Richter741854e2005-12-01 18:52:03 -0500268 int nodeid = -1;
269 int rest_of_selfids = host->selfid_count;
270 struct selfid *sid = (struct selfid *)host->topology_map;
271 struct ext_selfid *esid;
272 int esid_seq = 23;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273
274 host->nodes_active = 0;
275
Stefan Richter741854e2005-12-01 18:52:03 -0500276 while (rest_of_selfids--) {
277 if (!sid->extended) {
278 nodeid++;
279 esid_seq = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280
Stefan Richter741854e2005-12-01 18:52:03 -0500281 if (sid->phy_id != nodeid) {
282 HPSB_INFO("SelfIDs failed monotony check with "
283 "%d", sid->phy_id);
284 return 0;
285 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286
287 if (sid->link_active) {
288 host->nodes_active++;
289 if (sid->contender)
290 host->irm_id = LOCAL_BUS | sid->phy_id;
291 }
Stefan Richter741854e2005-12-01 18:52:03 -0500292 } else {
293 esid = (struct ext_selfid *)sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294
Stefan Richter741854e2005-12-01 18:52:03 -0500295 if ((esid->phy_id != nodeid)
296 || (esid->seq_nr != esid_seq)) {
297 HPSB_INFO("SelfIDs failed monotony check with "
298 "%d/%d", esid->phy_id, esid->seq_nr);
299 return 0;
300 }
301 esid_seq++;
302 }
303 sid++;
304 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305
Stefan Richter741854e2005-12-01 18:52:03 -0500306 esid = (struct ext_selfid *)(sid - 1);
307 while (esid->extended) {
308 if ((esid->porta == SELFID_PORT_PARENT) ||
Stefan Richterd7758462005-12-01 18:51:56 -0500309 (esid->portb == SELFID_PORT_PARENT) ||
310 (esid->portc == SELFID_PORT_PARENT) ||
311 (esid->portd == SELFID_PORT_PARENT) ||
312 (esid->porte == SELFID_PORT_PARENT) ||
313 (esid->portf == SELFID_PORT_PARENT) ||
314 (esid->portg == SELFID_PORT_PARENT) ||
315 (esid->porth == SELFID_PORT_PARENT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316 HPSB_INFO("SelfIDs failed root check on "
317 "extended SelfID");
318 return 0;
Stefan Richter741854e2005-12-01 18:52:03 -0500319 }
320 esid--;
321 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322
Stefan Richter741854e2005-12-01 18:52:03 -0500323 sid = (struct selfid *)esid;
Stefan Richterd7758462005-12-01 18:51:56 -0500324 if ((sid->port0 == SELFID_PORT_PARENT) ||
325 (sid->port1 == SELFID_PORT_PARENT) ||
326 (sid->port2 == SELFID_PORT_PARENT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327 HPSB_INFO("SelfIDs failed root check");
328 return 0;
Stefan Richter741854e2005-12-01 18:52:03 -0500329 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330
331 host->node_count = nodeid + 1;
Stefan Richter741854e2005-12-01 18:52:03 -0500332 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333}
334
335static void build_speed_map(struct hpsb_host *host, int nodecount)
336{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 u8 cldcnt[nodecount];
Stefan Richter741854e2005-12-01 18:52:03 -0500338 u8 *map = host->speed_map;
Ben Collins647dcb52006-06-12 18:12:37 -0400339 u8 *speedcap = host->speed;
Stefan Richter741854e2005-12-01 18:52:03 -0500340 struct selfid *sid;
341 struct ext_selfid *esid;
342 int i, j, n;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343
Stefan Richter741854e2005-12-01 18:52:03 -0500344 for (i = 0; i < (nodecount * 64); i += 64) {
345 for (j = 0; j < nodecount; j++) {
346 map[i+j] = IEEE1394_SPEED_MAX;
347 }
348 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349
Stefan Richter741854e2005-12-01 18:52:03 -0500350 for (i = 0; i < nodecount; i++) {
351 cldcnt[i] = 0;
352 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353
Stefan Richter741854e2005-12-01 18:52:03 -0500354 /* find direct children count and speed */
355 for (sid = (struct selfid *)&host->topology_map[host->selfid_count-1],
356 n = nodecount - 1;
357 (void *)sid >= (void *)host->topology_map; sid--) {
358 if (sid->extended) {
359 esid = (struct ext_selfid *)sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360
Stefan Richterd7758462005-12-01 18:51:56 -0500361 if (esid->porta == SELFID_PORT_CHILD) cldcnt[n]++;
362 if (esid->portb == SELFID_PORT_CHILD) cldcnt[n]++;
363 if (esid->portc == SELFID_PORT_CHILD) cldcnt[n]++;
364 if (esid->portd == SELFID_PORT_CHILD) cldcnt[n]++;
365 if (esid->porte == SELFID_PORT_CHILD) cldcnt[n]++;
366 if (esid->portf == SELFID_PORT_CHILD) cldcnt[n]++;
367 if (esid->portg == SELFID_PORT_CHILD) cldcnt[n]++;
368 if (esid->porth == SELFID_PORT_CHILD) cldcnt[n]++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369 } else {
Stefan Richterd7758462005-12-01 18:51:56 -0500370 if (sid->port0 == SELFID_PORT_CHILD) cldcnt[n]++;
371 if (sid->port1 == SELFID_PORT_CHILD) cldcnt[n]++;
372 if (sid->port2 == SELFID_PORT_CHILD) cldcnt[n]++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373
Stefan Richter741854e2005-12-01 18:52:03 -0500374 speedcap[n] = sid->speed;
375 n--;
376 }
377 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378
Stefan Richter741854e2005-12-01 18:52:03 -0500379 /* set self mapping */
380 for (i = 0; i < nodecount; i++) {
381 map[64*i + i] = speedcap[i];
382 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383
Stefan Richter741854e2005-12-01 18:52:03 -0500384 /* fix up direct children count to total children count;
385 * also fix up speedcaps for sibling and parent communication */
386 for (i = 1; i < nodecount; i++) {
387 for (j = cldcnt[i], n = i - 1; j > 0; j--) {
388 cldcnt[i] += cldcnt[n];
389 speedcap[n] = min(speedcap[n], speedcap[i]);
390 n -= cldcnt[n] + 1;
391 }
392 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393
Stefan Richter741854e2005-12-01 18:52:03 -0500394 for (n = 0; n < nodecount; n++) {
395 for (i = n - cldcnt[n]; i <= n; i++) {
396 for (j = 0; j < (n - cldcnt[n]); j++) {
397 map[j*64 + i] = map[i*64 + j] =
398 min(map[i*64 + j], speedcap[n]);
399 }
400 for (j = n + 1; j < nodecount; j++) {
401 map[j*64 + i] = map[i*64 + j] =
402 min(map[i*64 + j], speedcap[n]);
403 }
404 }
405 }
Ben Collins647dcb52006-06-12 18:12:37 -0400406
Stefan Richter433a87d2006-07-03 12:02:27 -0400407#if SELFID_SPEED_UNKNOWN != IEEE1394_SPEED_MAX
Ben Collins647dcb52006-06-12 18:12:37 -0400408 /* assume maximum speed for 1394b PHYs, nodemgr will correct it */
409 for (n = 0; n < nodecount; n++)
Stefan Richter433a87d2006-07-03 12:02:27 -0400410 if (speedcap[n] == SELFID_SPEED_UNKNOWN)
Ben Collins647dcb52006-06-12 18:12:37 -0400411 speedcap[n] = IEEE1394_SPEED_MAX;
Stefan Richter433a87d2006-07-03 12:02:27 -0400412#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413}
414
415
Stefan Richterafd65462007-03-05 03:06:23 +0100416/**
417 * hpsb_selfid_received - hand over received selfid packet to the core
418 *
419 * For host driver module usage. Safe to use in interrupt context.
420 *
421 * The host driver should have done a successful complement check (second
422 * quadlet is complement of first) beforehand.
423 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424void hpsb_selfid_received(struct hpsb_host *host, quadlet_t sid)
425{
Stefan Richter741854e2005-12-01 18:52:03 -0500426 if (host->in_bus_reset) {
427 HPSB_VERBOSE("Including SelfID 0x%x", sid);
428 host->topology_map[host->selfid_count++] = sid;
429 } else {
430 HPSB_NOTICE("Spurious SelfID packet (0x%08x) received from bus %d",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 sid, NODEID_TO_BUS(host->node_id));
Stefan Richter741854e2005-12-01 18:52:03 -0500432 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433}
434
Stefan Richterafd65462007-03-05 03:06:23 +0100435/**
436 * hpsb_selfid_complete - notify completion of SelfID stage to the core
437 *
438 * For host driver module usage. Safe to use in interrupt context, although
439 * quite complex; so you may want to run it in the bottom rather than top half.
440 *
441 * Notify completion of SelfID stage to the core and report new physical ID
442 * and whether host is root now.
443 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot)
445{
446 if (!host->in_bus_reset)
447 HPSB_NOTICE("SelfID completion called outside of bus reset!");
448
Stefan Richter741854e2005-12-01 18:52:03 -0500449 host->node_id = LOCAL_BUS | phyid;
450 host->is_root = isroot;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451
Stefan Richter741854e2005-12-01 18:52:03 -0500452 if (!check_selfids(host)) {
453 if (host->reset_retries++ < 20) {
454 /* selfid stage did not complete without error */
455 HPSB_NOTICE("Error in SelfID stage, resetting");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456 host->in_bus_reset = 0;
457 /* this should work from ohci1394 now... */
Stefan Richter741854e2005-12-01 18:52:03 -0500458 hpsb_reset_bus(host, LONG_RESET);
459 return;
460 } else {
461 HPSB_NOTICE("Stopping out-of-control reset loop");
462 HPSB_NOTICE("Warning - topology map and speed map will not be valid");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463 host->reset_retries = 0;
Stefan Richter741854e2005-12-01 18:52:03 -0500464 }
465 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466 host->reset_retries = 0;
Stefan Richter741854e2005-12-01 18:52:03 -0500467 build_speed_map(host, host->node_count);
468 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469
470 HPSB_VERBOSE("selfid_complete called with successful SelfID stage "
471 "... irm_id: 0x%X node_id: 0x%X",host->irm_id,host->node_id);
472
Stefan Richter741854e2005-12-01 18:52:03 -0500473 /* irm_id is kept up to date by check_selfids() */
474 if (host->irm_id == host->node_id) {
475 host->is_irm = 1;
476 } else {
477 host->is_busmgr = 0;
478 host->is_irm = 0;
479 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480
Stefan Richter741854e2005-12-01 18:52:03 -0500481 if (isroot) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482 host->driver->devctl(host, ACT_CYCLE_MASTER, 1);
483 host->is_cycmst = 1;
484 }
485 atomic_inc(&host->generation);
486 host->in_bus_reset = 0;
Stefan Richter741854e2005-12-01 18:52:03 -0500487 highlevel_host_reset(host);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488}
489
Stefan Richter7542e0e2007-03-25 22:22:40 +0200490static spinlock_t pending_packets_lock = SPIN_LOCK_UNLOCKED;
491
Stefan Richterafd65462007-03-05 03:06:23 +0100492/**
493 * hpsb_packet_sent - notify core of sending a packet
494 *
495 * For host driver module usage. Safe to call from within a transmit packet
496 * routine.
497 *
498 * Notify core of sending a packet. Ackcode is the ack code returned for async
499 * transmits or ACKX_SEND_ERROR if the transmission failed completely; ACKX_NONE
500 * for other cases (internal errors that don't justify a panic).
501 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet,
Stefan Richter741854e2005-12-01 18:52:03 -0500503 int ackcode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504{
505 unsigned long flags;
506
Stefan Richter7542e0e2007-03-25 22:22:40 +0200507 spin_lock_irqsave(&pending_packets_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508
509 packet->ack_code = ackcode;
510
511 if (packet->no_waiter || packet->state == hpsb_complete) {
512 /* if packet->no_waiter, must not have a tlabel allocated */
Stefan Richter7542e0e2007-03-25 22:22:40 +0200513 spin_unlock_irqrestore(&pending_packets_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514 hpsb_free_packet(packet);
515 return;
516 }
517
518 atomic_dec(&packet->refcnt); /* drop HC's reference */
Stefan Richter7542e0e2007-03-25 22:22:40 +0200519 /* here the packet must be on the host->pending_packets queue */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520
521 if (ackcode != ACK_PENDING || !packet->expect_response) {
522 packet->state = hpsb_complete;
Stefan Richter7542e0e2007-03-25 22:22:40 +0200523 list_del_init(&packet->queue);
524 spin_unlock_irqrestore(&pending_packets_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 queue_packet_complete(packet);
526 return;
527 }
528
529 packet->state = hpsb_pending;
530 packet->sendtime = jiffies;
531
Stefan Richter7542e0e2007-03-25 22:22:40 +0200532 spin_unlock_irqrestore(&pending_packets_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533
534 mod_timer(&host->timeout, jiffies + host->timeout_interval);
535}
536
537/**
538 * hpsb_send_phy_config - transmit a PHY configuration packet on the bus
539 * @host: host that PHY config packet gets sent through
540 * @rootid: root whose force_root bit should get set (-1 = don't set force_root)
541 * @gapcnt: gap count value to set (-1 = don't set gap count)
542 *
Stefan Richterafd65462007-03-05 03:06:23 +0100543 * This function sends a PHY config packet on the bus through the specified
544 * host.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545 *
Stefan Richterafd65462007-03-05 03:06:23 +0100546 * Return value: 0 for success or negative error number otherwise.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547 */
548int hpsb_send_phy_config(struct hpsb_host *host, int rootid, int gapcnt)
549{
550 struct hpsb_packet *packet;
Stefan Richter546513f2005-12-01 18:52:01 -0500551 quadlet_t d = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552 int retval = 0;
553
554 if (rootid >= ALL_NODES || rootid < -1 || gapcnt > 0x3f || gapcnt < -1 ||
555 (rootid == -1 && gapcnt == -1)) {
556 HPSB_DEBUG("Invalid Parameter: rootid = %d gapcnt = %d",
557 rootid, gapcnt);
558 return -EINVAL;
559 }
560
Stefan Richter546513f2005-12-01 18:52:01 -0500561 if (rootid != -1)
562 d |= PHYPACKET_PHYCONFIG_R | rootid << PHYPACKET_PORT_SHIFT;
563 if (gapcnt != -1)
564 d |= PHYPACKET_PHYCONFIG_T | gapcnt << PHYPACKET_GAPCOUNT_SHIFT;
565
566 packet = hpsb_make_phypacket(host, d);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567 if (!packet)
568 return -ENOMEM;
569
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 packet->generation = get_hpsb_generation(host);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571 retval = hpsb_send_packet_and_wait(packet);
572 hpsb_free_packet(packet);
573
574 return retval;
575}
576
577/**
578 * hpsb_send_packet - transmit a packet on the bus
579 * @packet: packet to send
580 *
581 * The packet is sent through the host specified in the packet->host field.
582 * Before sending, the packet's transmit speed is automatically determined
583 * using the local speed map when it is an async, non-broadcast packet.
584 *
585 * Possibilities for failure are that host is either not initialized, in bus
586 * reset, the packet's generation number doesn't match the current generation
587 * number or the host reports a transmit error.
588 *
589 * Return value: 0 on success, negative errno on failure.
590 */
591int hpsb_send_packet(struct hpsb_packet *packet)
592{
593 struct hpsb_host *host = packet->host;
594
Stefan Richter741854e2005-12-01 18:52:03 -0500595 if (host->is_shutdown)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596 return -EINVAL;
597 if (host->in_bus_reset ||
598 (packet->generation != get_hpsb_generation(host)))
Stefan Richter741854e2005-12-01 18:52:03 -0500599 return -EAGAIN;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600
Stefan Richter741854e2005-12-01 18:52:03 -0500601 packet->state = hpsb_queued;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602
603 /* This just seems silly to me */
604 WARN_ON(packet->no_waiter && packet->expect_response);
605
606 if (!packet->no_waiter || packet->expect_response) {
Stefan Richter7542e0e2007-03-25 22:22:40 +0200607 unsigned long flags;
608
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609 atomic_inc(&packet->refcnt);
Ben Collins1934b8b2005-07-09 20:01:23 -0400610 /* Set the initial "sendtime" to 10 seconds from now, to
611 prevent premature expiry. If a packet takes more than
612 10 seconds to hit the wire, we have bigger problems :) */
Jody McIntyre6262d062005-05-16 21:54:05 -0700613 packet->sendtime = jiffies + 10 * HZ;
Stefan Richter7542e0e2007-03-25 22:22:40 +0200614 spin_lock_irqsave(&pending_packets_lock, flags);
615 list_add_tail(&packet->queue, &host->pending_packets);
616 spin_unlock_irqrestore(&pending_packets_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617 }
618
Stefan Richter741854e2005-12-01 18:52:03 -0500619 if (packet->node_id == host->node_id) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620 /* it is a local request, so handle it locally */
621
Stefan Richter741854e2005-12-01 18:52:03 -0500622 quadlet_t *data;
623 size_t size = packet->data_size + packet->header_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624
Stefan Richter741854e2005-12-01 18:52:03 -0500625 data = kmalloc(size, GFP_ATOMIC);
626 if (!data) {
627 HPSB_ERR("unable to allocate memory for concatenating header and data");
628 return -ENOMEM;
629 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630
Stefan Richter741854e2005-12-01 18:52:03 -0500631 memcpy(data, packet->header, packet->header_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632
Stefan Richter741854e2005-12-01 18:52:03 -0500633 if (packet->data_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634 memcpy(((u8*)data) + packet->header_size, packet->data, packet->data_size);
635
Stefan Richter741854e2005-12-01 18:52:03 -0500636 dump_packet("send packet local", packet->header, packet->header_size, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637
Stefan Richter741854e2005-12-01 18:52:03 -0500638 hpsb_packet_sent(host, packet, packet->expect_response ? ACK_PENDING : ACK_COMPLETE);
639 hpsb_packet_received(host, data, size, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640
Stefan Richter741854e2005-12-01 18:52:03 -0500641 kfree(data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642
Stefan Richter741854e2005-12-01 18:52:03 -0500643 return 0;
644 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645
Ben Collins647dcb52006-06-12 18:12:37 -0400646 if (packet->type == hpsb_async &&
647 NODEID_TO_NODE(packet->node_id) != ALL_NODES)
Stefan Richter741854e2005-12-01 18:52:03 -0500648 packet->speed_code =
Ben Collins647dcb52006-06-12 18:12:37 -0400649 host->speed[NODEID_TO_NODE(packet->node_id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650
Stefan Richter741854e2005-12-01 18:52:03 -0500651 dump_packet("send packet", packet->header, packet->header_size, packet->speed_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652
Stefan Richter741854e2005-12-01 18:52:03 -0500653 return host->driver->transmit_packet(host, packet);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654}
655
656/* We could just use complete() directly as the packet complete
657 * callback, but this is more typesafe, in the sense that we get a
658 * compiler error if the prototype for complete() changes. */
659
660static void complete_packet(void *data)
661{
662 complete((struct completion *) data);
663}
664
Stefan Richterafd65462007-03-05 03:06:23 +0100665/**
666 * hpsb_send_packet_and_wait - enqueue packet, block until transaction completes
667 * @packet: packet to send
668 *
669 * Return value: 0 on success, negative errno on failure.
670 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671int hpsb_send_packet_and_wait(struct hpsb_packet *packet)
672{
673 struct completion done;
674 int retval;
675
676 init_completion(&done);
677 hpsb_set_packet_complete_task(packet, complete_packet, &done);
678 retval = hpsb_send_packet(packet);
679 if (retval == 0)
680 wait_for_completion(&done);
681
682 return retval;
683}
684
685static void send_packet_nocare(struct hpsb_packet *packet)
686{
Stefan Richter741854e2005-12-01 18:52:03 -0500687 if (hpsb_send_packet(packet) < 0) {
688 hpsb_free_packet(packet);
689 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690}
691
Stefan Richter7542e0e2007-03-25 22:22:40 +0200692static size_t packet_size_to_data_size(size_t packet_size, size_t header_size,
693 size_t buffer_size, int tcode)
694{
695 size_t ret = packet_size <= header_size ? 0 : packet_size - header_size;
696
697 if (unlikely(ret > buffer_size))
698 ret = buffer_size;
699
700 if (unlikely(ret + header_size != packet_size))
Randy Dunlap504945c2007-04-03 13:00:47 -0700701 HPSB_ERR("unexpected packet size %zd (tcode %d), bug?",
Stefan Richter7542e0e2007-03-25 22:22:40 +0200702 packet_size, tcode);
703 return ret;
704}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705
706static void handle_packet_response(struct hpsb_host *host, int tcode,
707 quadlet_t *data, size_t size)
708{
Stefan Richter7542e0e2007-03-25 22:22:40 +0200709 struct hpsb_packet *packet;
710 int tlabel = (data[0] >> 10) & 0x3f;
711 size_t header_size;
Stefan Richter741854e2005-12-01 18:52:03 -0500712 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713
Stefan Richter7542e0e2007-03-25 22:22:40 +0200714 spin_lock_irqsave(&pending_packets_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715
Stefan Richter7542e0e2007-03-25 22:22:40 +0200716 list_for_each_entry(packet, &host->pending_packets, queue)
717 if (packet->tlabel == tlabel &&
718 packet->node_id == (data[1] >> 16))
719 goto found;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720
Stefan Richter7542e0e2007-03-25 22:22:40 +0200721 spin_unlock_irqrestore(&pending_packets_lock, flags);
722 HPSB_DEBUG("unsolicited response packet received - %s",
723 "no tlabel match");
724 dump_packet("contents", data, 16, -1);
725 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726
Stefan Richter7542e0e2007-03-25 22:22:40 +0200727found:
Stefan Richter741854e2005-12-01 18:52:03 -0500728 switch (packet->tcode) {
729 case TCODE_WRITEQ:
730 case TCODE_WRITEB:
Stefan Richter7542e0e2007-03-25 22:22:40 +0200731 if (unlikely(tcode != TCODE_WRITE_RESPONSE))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732 break;
Stefan Richter7542e0e2007-03-25 22:22:40 +0200733 header_size = 12;
734 size = 0;
735 goto dequeue;
736
Stefan Richter741854e2005-12-01 18:52:03 -0500737 case TCODE_READQ:
Stefan Richter7542e0e2007-03-25 22:22:40 +0200738 if (unlikely(tcode != TCODE_READQ_RESPONSE))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 break;
Stefan Richter7542e0e2007-03-25 22:22:40 +0200740 header_size = 16;
741 size = 0;
742 goto dequeue;
743
Stefan Richter741854e2005-12-01 18:52:03 -0500744 case TCODE_READB:
Stefan Richter7542e0e2007-03-25 22:22:40 +0200745 if (unlikely(tcode != TCODE_READB_RESPONSE))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746 break;
Stefan Richter7542e0e2007-03-25 22:22:40 +0200747 header_size = 16;
748 size = packet_size_to_data_size(size, header_size,
749 packet->allocated_data_size,
750 tcode);
751 goto dequeue;
752
Stefan Richter741854e2005-12-01 18:52:03 -0500753 case TCODE_LOCK_REQUEST:
Stefan Richter7542e0e2007-03-25 22:22:40 +0200754 if (unlikely(tcode != TCODE_LOCK_RESPONSE))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755 break;
Stefan Richter7542e0e2007-03-25 22:22:40 +0200756 header_size = 16;
757 size = packet_size_to_data_size(min(size, (size_t)(16 + 8)),
758 header_size,
759 packet->allocated_data_size,
760 tcode);
761 goto dequeue;
Stefan Richter741854e2005-12-01 18:52:03 -0500762 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763
Stefan Richter7542e0e2007-03-25 22:22:40 +0200764 spin_unlock_irqrestore(&pending_packets_lock, flags);
765 HPSB_DEBUG("unsolicited response packet received - %s",
766 "tcode mismatch");
767 dump_packet("contents", data, 16, -1);
768 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769
Stefan Richter7542e0e2007-03-25 22:22:40 +0200770dequeue:
771 list_del_init(&packet->queue);
772 spin_unlock_irqrestore(&pending_packets_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773
774 if (packet->state == hpsb_queued) {
775 packet->sendtime = jiffies;
776 packet->ack_code = ACK_PENDING;
777 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778 packet->state = hpsb_complete;
Stefan Richter7542e0e2007-03-25 22:22:40 +0200779
780 memcpy(packet->header, data, header_size);
781 if (size)
782 memcpy(packet->data, data + 4, size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783
784 queue_packet_complete(packet);
785}
786
787
788static struct hpsb_packet *create_reply_packet(struct hpsb_host *host,
789 quadlet_t *data, size_t dsize)
790{
Stefan Richter741854e2005-12-01 18:52:03 -0500791 struct hpsb_packet *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792
Stefan Richter741854e2005-12-01 18:52:03 -0500793 p = hpsb_alloc_packet(dsize);
794 if (unlikely(p == NULL)) {
795 /* FIXME - send data_error response */
Stefan Richter7542e0e2007-03-25 22:22:40 +0200796 HPSB_ERR("out of memory, cannot send response packet");
Stefan Richter741854e2005-12-01 18:52:03 -0500797 return NULL;
798 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799
Stefan Richter741854e2005-12-01 18:52:03 -0500800 p->type = hpsb_async;
801 p->state = hpsb_unused;
802 p->host = host;
803 p->node_id = data[1] >> 16;
804 p->tlabel = (data[0] >> 10) & 0x3f;
805 p->no_waiter = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806
807 p->generation = get_hpsb_generation(host);
808
809 if (dsize % 4)
810 p->data[dsize / 4] = 0;
811
Stefan Richter741854e2005-12-01 18:52:03 -0500812 return p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813}
814
815#define PREP_ASYNC_HEAD_RCODE(tc) \
816 packet->tcode = tc; \
817 packet->header[0] = (packet->node_id << 16) | (packet->tlabel << 10) \
818 | (1 << 8) | (tc << 4); \
819 packet->header[1] = (packet->host->node_id << 16) | (rcode << 12); \
820 packet->header[2] = 0
821
822static void fill_async_readquad_resp(struct hpsb_packet *packet, int rcode,
Stefan Richter741854e2005-12-01 18:52:03 -0500823 quadlet_t data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824{
825 PREP_ASYNC_HEAD_RCODE(TCODE_READQ_RESPONSE);
826 packet->header[3] = data;
827 packet->header_size = 16;
828 packet->data_size = 0;
829}
830
831static void fill_async_readblock_resp(struct hpsb_packet *packet, int rcode,
Stefan Richter741854e2005-12-01 18:52:03 -0500832 int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833{
834 if (rcode != RCODE_COMPLETE)
835 length = 0;
836
837 PREP_ASYNC_HEAD_RCODE(TCODE_READB_RESPONSE);
838 packet->header[3] = length << 16;
839 packet->header_size = 16;
840 packet->data_size = length + (length % 4 ? 4 - (length % 4) : 0);
841}
842
843static void fill_async_write_resp(struct hpsb_packet *packet, int rcode)
844{
845 PREP_ASYNC_HEAD_RCODE(TCODE_WRITE_RESPONSE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846 packet->header_size = 12;
847 packet->data_size = 0;
848}
849
850static void fill_async_lock_resp(struct hpsb_packet *packet, int rcode, int extcode,
Stefan Richter741854e2005-12-01 18:52:03 -0500851 int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852{
853 if (rcode != RCODE_COMPLETE)
854 length = 0;
855
856 PREP_ASYNC_HEAD_RCODE(TCODE_LOCK_RESPONSE);
857 packet->header[3] = (length << 16) | extcode;
858 packet->header_size = 16;
859 packet->data_size = length;
860}
861
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862static void handle_incoming_packet(struct hpsb_host *host, int tcode,
Stefan Richterd4c60082007-03-18 00:55:15 +0100863 quadlet_t *data, size_t size,
864 int write_acked)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865{
Stefan Richter741854e2005-12-01 18:52:03 -0500866 struct hpsb_packet *packet;
867 int length, rcode, extcode;
868 quadlet_t buffer;
869 nodeid_t source = data[1] >> 16;
870 nodeid_t dest = data[0] >> 16;
871 u16 flags = (u16) data[0];
872 u64 addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873
Stefan Richterd4c60082007-03-18 00:55:15 +0100874 /* FIXME?
875 * Out-of-bounds lengths are left for highlevel_read|write to cap. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876
Stefan Richter741854e2005-12-01 18:52:03 -0500877 switch (tcode) {
878 case TCODE_WRITEQ:
879 addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
Stefan Richterd4c60082007-03-18 00:55:15 +0100880 rcode = highlevel_write(host, source, dest, data + 3,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881 addr, 4, flags);
Stefan Richterd4c60082007-03-18 00:55:15 +0100882 goto handle_write_request;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883
Stefan Richter741854e2005-12-01 18:52:03 -0500884 case TCODE_WRITEB:
885 addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
Stefan Richterd4c60082007-03-18 00:55:15 +0100886 rcode = highlevel_write(host, source, dest, data + 4,
887 addr, data[3] >> 16, flags);
888handle_write_request:
889 if (rcode < 0 || write_acked ||
890 NODEID_TO_NODE(data[0] >> 16) == NODE_MASK)
891 return;
892 /* not a broadcast write, reply */
893 packet = create_reply_packet(host, data, 0);
894 if (packet) {
Stefan Richter741854e2005-12-01 18:52:03 -0500895 fill_async_write_resp(packet, rcode);
896 send_packet_nocare(packet);
897 }
Stefan Richterd4c60082007-03-18 00:55:15 +0100898 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899
Stefan Richter741854e2005-12-01 18:52:03 -0500900 case TCODE_READQ:
901 addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
902 rcode = highlevel_read(host, source, &buffer, addr, 4, flags);
Stefan Richterd4c60082007-03-18 00:55:15 +0100903 if (rcode < 0)
904 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905
Stefan Richterd4c60082007-03-18 00:55:15 +0100906 packet = create_reply_packet(host, data, 0);
907 if (packet) {
Stefan Richter741854e2005-12-01 18:52:03 -0500908 fill_async_readquad_resp(packet, rcode, buffer);
909 send_packet_nocare(packet);
910 }
Stefan Richterd4c60082007-03-18 00:55:15 +0100911 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912
Stefan Richter741854e2005-12-01 18:52:03 -0500913 case TCODE_READB:
914 length = data[3] >> 16;
Stefan Richterd4c60082007-03-18 00:55:15 +0100915 packet = create_reply_packet(host, data, length);
916 if (!packet)
917 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918
Stefan Richter741854e2005-12-01 18:52:03 -0500919 addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
920 rcode = highlevel_read(host, source, packet->data, addr,
921 length, flags);
Stefan Richterd4c60082007-03-18 00:55:15 +0100922 if (rcode < 0) {
Stefan Richter741854e2005-12-01 18:52:03 -0500923 hpsb_free_packet(packet);
Stefan Richterd4c60082007-03-18 00:55:15 +0100924 return;
Stefan Richter741854e2005-12-01 18:52:03 -0500925 }
Stefan Richterd4c60082007-03-18 00:55:15 +0100926 fill_async_readblock_resp(packet, rcode, length);
927 send_packet_nocare(packet);
928 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929
Stefan Richter741854e2005-12-01 18:52:03 -0500930 case TCODE_LOCK_REQUEST:
931 length = data[3] >> 16;
932 extcode = data[3] & 0xffff;
933 addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934
Stefan Richterd4c60082007-03-18 00:55:15 +0100935 packet = create_reply_packet(host, data, 8);
936 if (!packet)
937 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938
Stefan Richterd4c60082007-03-18 00:55:15 +0100939 if (extcode == 0 || extcode >= 7) {
Stefan Richter741854e2005-12-01 18:52:03 -0500940 /* let switch default handle error */
941 length = 0;
942 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943
Stefan Richter741854e2005-12-01 18:52:03 -0500944 switch (length) {
945 case 4:
946 rcode = highlevel_lock(host, source, packet->data, addr,
Stefan Richterd4c60082007-03-18 00:55:15 +0100947 data[4], 0, extcode, flags);
Stefan Richter741854e2005-12-01 18:52:03 -0500948 fill_async_lock_resp(packet, rcode, extcode, 4);
949 break;
950 case 8:
Stefan Richterd4c60082007-03-18 00:55:15 +0100951 if (extcode != EXTCODE_FETCH_ADD &&
952 extcode != EXTCODE_LITTLE_ADD) {
Stefan Richter741854e2005-12-01 18:52:03 -0500953 rcode = highlevel_lock(host, source,
954 packet->data, addr,
955 data[5], data[4],
956 extcode, flags);
957 fill_async_lock_resp(packet, rcode, extcode, 4);
958 } else {
959 rcode = highlevel_lock64(host, source,
960 (octlet_t *)packet->data, addr,
961 *(octlet_t *)(data + 4), 0ULL,
962 extcode, flags);
963 fill_async_lock_resp(packet, rcode, extcode, 8);
964 }
965 break;
966 case 16:
967 rcode = highlevel_lock64(host, source,
968 (octlet_t *)packet->data, addr,
969 *(octlet_t *)(data + 6),
970 *(octlet_t *)(data + 4),
971 extcode, flags);
972 fill_async_lock_resp(packet, rcode, extcode, 8);
973 break;
974 default:
975 rcode = RCODE_TYPE_ERROR;
Stefan Richterd4c60082007-03-18 00:55:15 +0100976 fill_async_lock_resp(packet, rcode, extcode, 0);
Stefan Richter741854e2005-12-01 18:52:03 -0500977 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978
Stefan Richterd4c60082007-03-18 00:55:15 +0100979 if (rcode < 0)
Stefan Richter741854e2005-12-01 18:52:03 -0500980 hpsb_free_packet(packet);
Stefan Richterd4c60082007-03-18 00:55:15 +0100981 else
982 send_packet_nocare(packet);
983 return;
Stefan Richter741854e2005-12-01 18:52:03 -0500984 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986
Stefan Richterafd65462007-03-05 03:06:23 +0100987/**
988 * hpsb_packet_received - hand over received packet to the core
989 *
990 * For host driver module usage.
991 *
992 * The contents of data are expected to be the full packet but with the CRCs
993 * left out (data block follows header immediately), with the header (i.e. the
994 * first four quadlets) in machine byte order and the data block in big endian.
995 * *@data can be safely overwritten after this call.
996 *
997 * If the packet is a write request, @write_acked is to be set to true if it was
998 * ack_complete'd already, false otherwise. This argument is ignored for any
999 * other packet type.
1000 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size,
Stefan Richter741854e2005-12-01 18:52:03 -05001002 int write_acked)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003{
Stefan Richter741854e2005-12-01 18:52:03 -05001004 int tcode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005
Stefan Richter7542e0e2007-03-25 22:22:40 +02001006 if (unlikely(host->in_bus_reset)) {
1007 HPSB_DEBUG("received packet during reset; ignoring");
Stefan Richter741854e2005-12-01 18:52:03 -05001008 return;
1009 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010
Stefan Richter741854e2005-12-01 18:52:03 -05001011 dump_packet("received packet", data, size, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012
Stefan Richter741854e2005-12-01 18:52:03 -05001013 tcode = (data[0] >> 4) & 0xf;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014
Stefan Richter741854e2005-12-01 18:52:03 -05001015 switch (tcode) {
1016 case TCODE_WRITE_RESPONSE:
1017 case TCODE_READQ_RESPONSE:
1018 case TCODE_READB_RESPONSE:
1019 case TCODE_LOCK_RESPONSE:
1020 handle_packet_response(host, tcode, data, size);
1021 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022
Stefan Richter741854e2005-12-01 18:52:03 -05001023 case TCODE_WRITEQ:
1024 case TCODE_WRITEB:
1025 case TCODE_READQ:
1026 case TCODE_READB:
1027 case TCODE_LOCK_REQUEST:
1028 handle_incoming_packet(host, tcode, data, size, write_acked);
1029 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030
1031
Stefan Richter741854e2005-12-01 18:52:03 -05001032 case TCODE_ISO_DATA:
1033 highlevel_iso_receive(host, data, size);
1034 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035
Stefan Richter741854e2005-12-01 18:52:03 -05001036 case TCODE_CYCLE_START:
1037 /* simply ignore this packet if it is passed on */
1038 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039
Stefan Richter741854e2005-12-01 18:52:03 -05001040 default:
Stefan Richter7542e0e2007-03-25 22:22:40 +02001041 HPSB_DEBUG("received packet with bogus transaction code %d",
1042 tcode);
Stefan Richter741854e2005-12-01 18:52:03 -05001043 break;
1044 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045}
1046
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047static void abort_requests(struct hpsb_host *host)
1048{
Stefan Richter7542e0e2007-03-25 22:22:40 +02001049 struct hpsb_packet *packet, *p;
1050 struct list_head tmp;
1051 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052
1053 host->driver->devctl(host, CANCEL_REQUESTS, 0);
1054
Stefan Richter7542e0e2007-03-25 22:22:40 +02001055 INIT_LIST_HEAD(&tmp);
1056 spin_lock_irqsave(&pending_packets_lock, flags);
1057 list_splice_init(&host->pending_packets, &tmp);
1058 spin_unlock_irqrestore(&pending_packets_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059
Stefan Richter7542e0e2007-03-25 22:22:40 +02001060 list_for_each_entry_safe(packet, p, &tmp, queue) {
1061 list_del_init(&packet->queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 packet->state = hpsb_complete;
1063 packet->ack_code = ACKX_ABORTED;
1064 queue_packet_complete(packet);
1065 }
1066}
1067
1068void abort_timedouts(unsigned long __opaque)
1069{
1070 struct hpsb_host *host = (struct hpsb_host *)__opaque;
Stefan Richter7542e0e2007-03-25 22:22:40 +02001071 struct hpsb_packet *packet, *p;
1072 struct list_head tmp;
1073 unsigned long flags, expire, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074
1075 spin_lock_irqsave(&host->csr.lock, flags);
1076 expire = host->csr.expire;
1077 spin_unlock_irqrestore(&host->csr.lock, flags);
1078
Stefan Richter7542e0e2007-03-25 22:22:40 +02001079 j = jiffies;
1080 INIT_LIST_HEAD(&tmp);
1081 spin_lock_irqsave(&pending_packets_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082
Stefan Richter7542e0e2007-03-25 22:22:40 +02001083 list_for_each_entry_safe(packet, p, &host->pending_packets, queue) {
1084 if (time_before(packet->sendtime + expire, j))
1085 list_move_tail(&packet->queue, &tmp);
1086 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087 /* Since packets are added to the tail, the oldest
1088 * ones are first, always. When we get to one that
1089 * isn't timed out, the rest aren't either. */
1090 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091 }
Stefan Richter7542e0e2007-03-25 22:22:40 +02001092 if (!list_empty(&host->pending_packets))
1093 mod_timer(&host->timeout, j + host->timeout_interval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094
Stefan Richter7542e0e2007-03-25 22:22:40 +02001095 spin_unlock_irqrestore(&pending_packets_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096
Stefan Richter7542e0e2007-03-25 22:22:40 +02001097 list_for_each_entry_safe(packet, p, &tmp, queue) {
1098 list_del_init(&packet->queue);
1099 packet->state = hpsb_complete;
1100 packet->ack_code = ACKX_TIMEOUT;
1101 queue_packet_complete(packet);
1102 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103}
1104
Ben Collinsf6542402006-06-12 18:15:50 -04001105static struct task_struct *khpsbpkt_thread;
Stefan Richter7542e0e2007-03-25 22:22:40 +02001106static LIST_HEAD(hpsbpkt_queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107
1108static void queue_packet_complete(struct hpsb_packet *packet)
1109{
Stefan Richter7542e0e2007-03-25 22:22:40 +02001110 unsigned long flags;
1111
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112 if (packet->no_waiter) {
1113 hpsb_free_packet(packet);
1114 return;
1115 }
1116 if (packet->complete_routine != NULL) {
Stefan Richter7542e0e2007-03-25 22:22:40 +02001117 spin_lock_irqsave(&pending_packets_lock, flags);
1118 list_add_tail(&packet->queue, &hpsbpkt_queue);
1119 spin_unlock_irqrestore(&pending_packets_lock, flags);
Ben Collinsf6542402006-06-12 18:15:50 -04001120 wake_up_process(khpsbpkt_thread);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 }
1122 return;
1123}
1124
Stefan Richter7542e0e2007-03-25 22:22:40 +02001125/*
1126 * Kernel thread which handles packets that are completed. This way the
1127 * packet's "complete" function is asynchronously run in process context.
1128 * Only packets which have a "complete" function may be sent here.
1129 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130static int hpsbpkt_thread(void *__hi)
1131{
Stefan Richter7542e0e2007-03-25 22:22:40 +02001132 struct hpsb_packet *packet, *p;
1133 struct list_head tmp;
1134 int may_schedule;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135
Dave Jones8c1d2862006-01-06 00:18:38 -08001136 current->flags |= PF_NOFREEZE;
1137
Ben Collinsf6542402006-06-12 18:15:50 -04001138 while (!kthread_should_stop()) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139
Stefan Richter7542e0e2007-03-25 22:22:40 +02001140 INIT_LIST_HEAD(&tmp);
1141 spin_lock_irq(&pending_packets_lock);
1142 list_splice_init(&hpsbpkt_queue, &tmp);
1143 spin_unlock_irq(&pending_packets_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144
Stefan Richter7542e0e2007-03-25 22:22:40 +02001145 list_for_each_entry_safe(packet, p, &tmp, queue) {
1146 list_del_init(&packet->queue);
1147 packet->complete_routine(packet->complete_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149
Ben Collinsf6542402006-06-12 18:15:50 -04001150 set_current_state(TASK_INTERRUPTIBLE);
Stefan Richter7542e0e2007-03-25 22:22:40 +02001151 spin_lock_irq(&pending_packets_lock);
1152 may_schedule = list_empty(&hpsbpkt_queue);
1153 spin_unlock_irq(&pending_packets_lock);
1154 if (may_schedule)
Ben Collinsf6542402006-06-12 18:15:50 -04001155 schedule();
1156 __set_current_state(TASK_RUNNING);
1157 }
1158 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159}
1160
1161static int __init ieee1394_init(void)
1162{
1163 int i, ret;
1164
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165 /* non-fatal error */
1166 if (hpsb_init_config_roms()) {
1167 HPSB_ERR("Failed to initialize some config rom entries.\n");
1168 HPSB_ERR("Some features may not be available\n");
1169 }
1170
Ben Collinsf6542402006-06-12 18:15:50 -04001171 khpsbpkt_thread = kthread_run(hpsbpkt_thread, NULL, "khpsbpkt");
1172 if (IS_ERR(khpsbpkt_thread)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173 HPSB_ERR("Failed to start hpsbpkt thread!\n");
Ben Collinsf6542402006-06-12 18:15:50 -04001174 ret = PTR_ERR(khpsbpkt_thread);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175 goto exit_cleanup_config_roms;
1176 }
1177
1178 if (register_chrdev_region(IEEE1394_CORE_DEV, 256, "ieee1394")) {
1179 HPSB_ERR("unable to register character device major %d!\n", IEEE1394_MAJOR);
1180 ret = -ENODEV;
1181 goto exit_release_kernel_thread;
1182 }
1183
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 ret = bus_register(&ieee1394_bus_type);
1185 if (ret < 0) {
1186 HPSB_INFO("bus register failed");
Stefan Richtera8748442006-03-28 19:55:41 -05001187 goto release_chrdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 }
1189
1190 for (i = 0; fw_bus_attrs[i]; i++) {
1191 ret = bus_create_file(&ieee1394_bus_type, fw_bus_attrs[i]);
1192 if (ret < 0) {
1193 while (i >= 0) {
1194 bus_remove_file(&ieee1394_bus_type,
1195 fw_bus_attrs[i--]);
1196 }
1197 bus_unregister(&ieee1394_bus_type);
Stefan Richtera8748442006-03-28 19:55:41 -05001198 goto release_chrdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199 }
1200 }
1201
1202 ret = class_register(&hpsb_host_class);
1203 if (ret < 0)
1204 goto release_all_bus;
1205
gregkh@suse.de7e25ab92005-03-23 09:53:36 -08001206 hpsb_protocol_class = class_create(THIS_MODULE, "ieee1394_protocol");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207 if (IS_ERR(hpsb_protocol_class)) {
1208 ret = PTR_ERR(hpsb_protocol_class);
1209 goto release_class_host;
1210 }
1211
1212 ret = init_csr();
1213 if (ret) {
1214 HPSB_INFO("init csr failed");
1215 ret = -ENOMEM;
1216 goto release_class_protocol;
1217 }
1218
1219 if (disable_nodemgr) {
1220 HPSB_INFO("nodemgr and IRM functionality disabled");
1221 /* We shouldn't contend for IRM with nodemgr disabled, since
1222 nodemgr implements functionality required of ieee1394a-2000
1223 IRMs */
1224 hpsb_disable_irm = 1;
Stefan Richter741854e2005-12-01 18:52:03 -05001225
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226 return 0;
1227 }
1228
1229 if (hpsb_disable_irm) {
1230 HPSB_INFO("IRM functionality disabled");
1231 }
1232
1233 ret = init_ieee1394_nodemgr();
1234 if (ret < 0) {
1235 HPSB_INFO("init nodemgr failed");
1236 goto cleanup_csr;
1237 }
1238
1239 return 0;
1240
1241cleanup_csr:
1242 cleanup_csr();
1243release_class_protocol:
gregkh@suse.de7e25ab92005-03-23 09:53:36 -08001244 class_destroy(hpsb_protocol_class);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245release_class_host:
1246 class_unregister(&hpsb_host_class);
1247release_all_bus:
1248 for (i = 0; fw_bus_attrs[i]; i++)
1249 bus_remove_file(&ieee1394_bus_type, fw_bus_attrs[i]);
1250 bus_unregister(&ieee1394_bus_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251release_chrdev:
1252 unregister_chrdev_region(IEEE1394_CORE_DEV, 256);
1253exit_release_kernel_thread:
Ben Collinsf6542402006-06-12 18:15:50 -04001254 kthread_stop(khpsbpkt_thread);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255exit_cleanup_config_roms:
1256 hpsb_cleanup_config_roms();
1257 return ret;
1258}
1259
1260static void __exit ieee1394_cleanup(void)
1261{
1262 int i;
1263
1264 if (!disable_nodemgr)
1265 cleanup_ieee1394_nodemgr();
1266
1267 cleanup_csr();
1268
gregkh@suse.de7e25ab92005-03-23 09:53:36 -08001269 class_destroy(hpsb_protocol_class);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270 class_unregister(&hpsb_host_class);
1271 for (i = 0; fw_bus_attrs[i]; i++)
1272 bus_remove_file(&ieee1394_bus_type, fw_bus_attrs[i]);
1273 bus_unregister(&ieee1394_bus_type);
1274
Ben Collinsf6542402006-06-12 18:15:50 -04001275 kthread_stop(khpsbpkt_thread);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276
1277 hpsb_cleanup_config_roms();
1278
1279 unregister_chrdev_region(IEEE1394_CORE_DEV, 256);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280}
1281
Andi Kleen8df40832006-07-27 21:54:00 +02001282fs_initcall(ieee1394_init); /* same as ohci1394 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283module_exit(ieee1394_cleanup);
1284
1285/* Exported symbols */
1286
1287/** hosts.c **/
1288EXPORT_SYMBOL(hpsb_alloc_host);
1289EXPORT_SYMBOL(hpsb_add_host);
Stefan Richter33601772007-01-07 21:49:27 +01001290EXPORT_SYMBOL(hpsb_resume_host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291EXPORT_SYMBOL(hpsb_remove_host);
1292EXPORT_SYMBOL(hpsb_update_config_rom_image);
1293
1294/** ieee1394_core.c **/
1295EXPORT_SYMBOL(hpsb_speedto_str);
1296EXPORT_SYMBOL(hpsb_protocol_class);
1297EXPORT_SYMBOL(hpsb_set_packet_complete_task);
1298EXPORT_SYMBOL(hpsb_alloc_packet);
1299EXPORT_SYMBOL(hpsb_free_packet);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300EXPORT_SYMBOL(hpsb_send_packet);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301EXPORT_SYMBOL(hpsb_reset_bus);
Pieter Palmers3dc5ea92007-02-03 17:44:39 +01001302EXPORT_SYMBOL(hpsb_read_cycle_timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303EXPORT_SYMBOL(hpsb_bus_reset);
1304EXPORT_SYMBOL(hpsb_selfid_received);
1305EXPORT_SYMBOL(hpsb_selfid_complete);
1306EXPORT_SYMBOL(hpsb_packet_sent);
1307EXPORT_SYMBOL(hpsb_packet_received);
1308EXPORT_SYMBOL_GPL(hpsb_disable_irm);
1309
1310/** ieee1394_transactions.c **/
1311EXPORT_SYMBOL(hpsb_get_tlabel);
1312EXPORT_SYMBOL(hpsb_free_tlabel);
1313EXPORT_SYMBOL(hpsb_make_readpacket);
1314EXPORT_SYMBOL(hpsb_make_writepacket);
1315EXPORT_SYMBOL(hpsb_make_streampacket);
1316EXPORT_SYMBOL(hpsb_make_lockpacket);
1317EXPORT_SYMBOL(hpsb_make_lock64packet);
1318EXPORT_SYMBOL(hpsb_make_phypacket);
1319EXPORT_SYMBOL(hpsb_make_isopacket);
1320EXPORT_SYMBOL(hpsb_read);
1321EXPORT_SYMBOL(hpsb_write);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322EXPORT_SYMBOL(hpsb_packet_success);
1323
1324/** highlevel.c **/
1325EXPORT_SYMBOL(hpsb_register_highlevel);
1326EXPORT_SYMBOL(hpsb_unregister_highlevel);
1327EXPORT_SYMBOL(hpsb_register_addrspace);
1328EXPORT_SYMBOL(hpsb_unregister_addrspace);
1329EXPORT_SYMBOL(hpsb_allocate_and_register_addrspace);
1330EXPORT_SYMBOL(hpsb_listen_channel);
1331EXPORT_SYMBOL(hpsb_unlisten_channel);
1332EXPORT_SYMBOL(hpsb_get_hostinfo);
1333EXPORT_SYMBOL(hpsb_create_hostinfo);
1334EXPORT_SYMBOL(hpsb_destroy_hostinfo);
1335EXPORT_SYMBOL(hpsb_set_hostinfo_key);
1336EXPORT_SYMBOL(hpsb_get_hostinfo_bykey);
1337EXPORT_SYMBOL(hpsb_set_hostinfo);
Ben Collins1934b8b2005-07-09 20:01:23 -04001338EXPORT_SYMBOL(highlevel_host_reset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339
1340/** nodemgr.c **/
1341EXPORT_SYMBOL(hpsb_node_fill_packet);
1342EXPORT_SYMBOL(hpsb_node_write);
Ben Collinsed30c262006-11-23 13:59:48 -05001343EXPORT_SYMBOL(__hpsb_register_protocol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344EXPORT_SYMBOL(hpsb_unregister_protocol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345
1346/** csr.c **/
1347EXPORT_SYMBOL(hpsb_update_config_rom);
1348
1349/** dma.c **/
1350EXPORT_SYMBOL(dma_prog_region_init);
1351EXPORT_SYMBOL(dma_prog_region_alloc);
1352EXPORT_SYMBOL(dma_prog_region_free);
1353EXPORT_SYMBOL(dma_region_init);
1354EXPORT_SYMBOL(dma_region_alloc);
1355EXPORT_SYMBOL(dma_region_free);
1356EXPORT_SYMBOL(dma_region_sync_for_cpu);
1357EXPORT_SYMBOL(dma_region_sync_for_device);
1358EXPORT_SYMBOL(dma_region_mmap);
1359EXPORT_SYMBOL(dma_region_offset_to_bus);
1360
1361/** iso.c **/
1362EXPORT_SYMBOL(hpsb_iso_xmit_init);
1363EXPORT_SYMBOL(hpsb_iso_recv_init);
1364EXPORT_SYMBOL(hpsb_iso_xmit_start);
1365EXPORT_SYMBOL(hpsb_iso_recv_start);
1366EXPORT_SYMBOL(hpsb_iso_recv_listen_channel);
1367EXPORT_SYMBOL(hpsb_iso_recv_unlisten_channel);
1368EXPORT_SYMBOL(hpsb_iso_recv_set_channel_mask);
1369EXPORT_SYMBOL(hpsb_iso_stop);
1370EXPORT_SYMBOL(hpsb_iso_shutdown);
1371EXPORT_SYMBOL(hpsb_iso_xmit_queue_packet);
1372EXPORT_SYMBOL(hpsb_iso_xmit_sync);
1373EXPORT_SYMBOL(hpsb_iso_recv_release_packets);
1374EXPORT_SYMBOL(hpsb_iso_n_ready);
1375EXPORT_SYMBOL(hpsb_iso_packet_sent);
1376EXPORT_SYMBOL(hpsb_iso_packet_received);
1377EXPORT_SYMBOL(hpsb_iso_wake);
1378EXPORT_SYMBOL(hpsb_iso_recv_flush);
1379
1380/** csr1212.c **/
Ben Collins1934b8b2005-07-09 20:01:23 -04001381EXPORT_SYMBOL(csr1212_attach_keyval_to_directory);
1382EXPORT_SYMBOL(csr1212_detach_keyval_from_directory);
Stefan Richterc1a37f22007-03-14 00:20:53 +01001383EXPORT_SYMBOL(csr1212_get_keyval);
1384EXPORT_SYMBOL(csr1212_new_directory);
Ben Collins1934b8b2005-07-09 20:01:23 -04001385EXPORT_SYMBOL(csr1212_parse_keyval);
Stefan Richterc1a37f22007-03-14 00:20:53 +01001386EXPORT_SYMBOL(csr1212_read);
1387EXPORT_SYMBOL(csr1212_release_keyval);