From: Ben Collins <bcollins@debian.org>


ChangeSet@1.1534, 2003-12-24 10:17:28-05:00, bcollins@debian.org
  Many files:
  IEEE-1394 Sync with r1088
  
  - Cleanup Kconfig so that ieee1394 core doesn't require PCI.
  
  - Some function renames to make things consistent.
  
  - Fixup ISO API so that packet-per-buffer and irq-interval work
    correctly.
  
  - Get rid of host list and use driver model for handling host ref count
    and host accounting.
  
  - Get rid of packet semaphore.
  
  - Move bus registration into core ieee1394 initialization.
  
  - Get rid of ancient unused data_be (big-endian) flag in packet struct.
  
  - Fix recursive use of bus_for_each_dev() in nodemgr.
  
  - Revert changes to oui.db. This file is verbatim from IEEE, so if any
    changes should be made, register them with the IEEE database and keep
    this one pristine.
  
  - Fix PCILynx so that it checks for errors on calls to copy_from_user().
  
  - Add ARM API handlers to raw1394.
  
  - Cleanup sbp2's packet sending to accomodate for a case where a packet
    was free'd while sbp2 was waiting on it.



 drivers/ieee1394/Kconfig                 |   20 ++--
 drivers/ieee1394/eth1394.c               |   16 +--
 drivers/ieee1394/highlevel.c             |   44 +++++-----
 drivers/ieee1394/highlevel.h             |    5 -
 drivers/ieee1394/hosts.c                 |  104 +++++--------------------
 drivers/ieee1394/hosts.h                 |   22 -----
 drivers/ieee1394/ieee1394_core.c         |  120 +++++++++++++++--------------
 drivers/ieee1394/ieee1394_core.h         |   24 ++---
 drivers/ieee1394/ieee1394_transactions.c |   69 +++++++---------
 drivers/ieee1394/iso.c                   |   16 ++-
 drivers/ieee1394/iso.h                   |   11 ++
 drivers/ieee1394/nodemgr.c               |   88 +++++++++++----------
 drivers/ieee1394/nodemgr.h               |    9 ++
 drivers/ieee1394/ohci1394.c              |   51 +++++++-----
 drivers/ieee1394/oui.db                  |    6 -
 drivers/ieee1394/pcilynx.c               |   30 ++++---
 drivers/ieee1394/raw1394.c               |  126 ++++++++++++++++++++++++++++--
 drivers/ieee1394/raw1394.h               |    5 +
 drivers/ieee1394/sbp2.c                  |  127 +++++++++++--------------------
 19 files changed, 470 insertions(+), 423 deletions(-)

diff -puN drivers/ieee1394/eth1394.c~ieee1394-update drivers/ieee1394/eth1394.c
--- 25/drivers/ieee1394/eth1394.c~ieee1394-update	2003-12-24 10:25:54.000000000 -0800
+++ 25-akpm/drivers/ieee1394/eth1394.c	2003-12-24 10:25:54.000000000 -0800
@@ -89,7 +89,7 @@
 #define TRACE() printk(KERN_ERR "%s:%s[%d] ---- TRACE\n", driver_name, __FUNCTION__, __LINE__)
 
 static char version[] __devinitdata =
-	"$Rev: 1043 $ Ben Collins <bcollins@debian.org>";
+	"$Rev: 1079 $ Ben Collins <bcollins@debian.org>";
 
 struct fragment_info {
 	struct list_head list;
@@ -220,7 +220,7 @@ static int ether1394_init_bc(struct net_
 
 			priv->iso = hpsb_iso_recv_init(priv->host, 16 * 4096,
 						       16, priv->broadcast_channel,
-						       1, ether1394_iso);
+						       HPSB_ISO_DMA_PACKET_PER_BUFFER, 1, ether1394_iso);
 			if (priv->iso == NULL) {
 				ETH1394_PRINT(KERN_ERR, dev->name,
 					      "failed to change broadcast "
@@ -475,7 +475,7 @@ static void ether1394_add_host (struct h
 	priv->broadcast_channel = host->csr.broadcast_channel & 0x3f;
 
 	priv->iso = hpsb_iso_recv_init(host, 16 * 4096, 16, priv->broadcast_channel,
-				       1, ether1394_iso);
+					HPSB_ISO_DMA_PACKET_PER_BUFFER, 1, ether1394_iso);
 	if (priv->iso == NULL) {
 		priv->bc_state = ETHER1394_BC_CLOSED;
 	}
@@ -1258,7 +1258,7 @@ static inline struct hpsb_packet *ether1
 {
 	struct hpsb_packet *p;
 
-	p = alloc_hpsb_packet(0);
+	p = hpsb_alloc_packet(0);
 	if (p) {
 		p->host = host;
 		p->data = NULL;
@@ -1327,7 +1327,7 @@ static inline void ether1394_free_packet
 	if (packet->tcode != TCODE_STREAM_DATA)
 		hpsb_free_tlabel(packet);
 	packet->data = NULL;
-	free_hpsb_packet(packet);
+	hpsb_free_packet(packet);
 }
 
 static void ether1394_complete_cb(void *__ptask);
@@ -1349,7 +1349,7 @@ static int ether1394_send_packet(struct 
 					       ptask->dest_node,
 					       ptask->addr, ptask->skb->data,
 					       tx_len)) {
-		free_hpsb_packet(packet);
+		hpsb_free_packet(packet);
 		return -1;
 	}
 
@@ -1357,7 +1357,7 @@ static int ether1394_send_packet(struct 
 	hpsb_set_packet_complete_task(ptask->packet, ether1394_complete_cb,
 				      ptask);
 
-	if (!hpsb_send_packet(packet)) {
+	if (hpsb_send_packet(packet) < 0) {
 		ether1394_free_packet(packet);
 		return -1;
 	}
@@ -1599,7 +1599,7 @@ static int ether1394_ethtool_ioctl(struc
 		case ETHTOOL_GDRVINFO: {
 			struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
 			strcpy (info.driver, driver_name);
-			strcpy (info.version, "$Rev: 1043 $");
+			strcpy (info.version, "$Rev: 1079 $");
 			/* FIXME XXX provide sane businfo */
 			strcpy (info.bus_info, "ieee1394");
 			if (copy_to_user (useraddr, &info, sizeof (info)))
diff -puN drivers/ieee1394/highlevel.c~ieee1394-update drivers/ieee1394/highlevel.c
--- 25/drivers/ieee1394/highlevel.c~ieee1394-update	2003-12-24 10:25:54.000000000 -0800
+++ 25-akpm/drivers/ieee1394/highlevel.c	2003-12-24 10:25:54.000000000 -0800
@@ -26,6 +26,7 @@
 #include "hosts.h"
 #include "ieee1394_core.h"
 #include "highlevel.h"
+#include "nodemgr.h"
 
 
 struct hl_host_info {
@@ -227,10 +228,17 @@ struct hpsb_host *hpsb_get_host_bykey(st
 	return host;
 }
 
+static int highlevel_for_each_host_reg(struct hpsb_host *host, void *__data)
+{
+	struct hpsb_highlevel *hl = __data;
+
+	hl->add_host(host);
+
+	return 0;
+}
 
 void hpsb_register_highlevel(struct hpsb_highlevel *hl)
 {
-	struct list_head *lh;
 	unsigned long flags;
 
         INIT_LIST_HEAD(&hl->addr_list);
@@ -242,21 +250,25 @@ void hpsb_register_highlevel(struct hpsb
         list_add_tail(&hl->hl_list, &hl_drivers);
 	write_unlock_irqrestore(&hl_drivers_lock, flags);
 
-	if (hl->add_host) {
-		down(&hpsb_hosts_lock);
-		list_for_each (lh, &hpsb_hosts) {
-			struct hpsb_host *host = list_entry(lh, struct hpsb_host, host_list);
-			hl->add_host(host);
-		}
-		up(&hpsb_hosts_lock);
-	}
+	if (hl->add_host)
+		nodemgr_for_each_host(hl, highlevel_for_each_host_reg);
 
         return;
 }
 
+static int highlevel_for_each_host_unreg(struct hpsb_host *host, void *__data)
+{
+	struct hpsb_highlevel *hl = __data;
+
+	hl->remove_host(host);
+	hpsb_destroy_hostinfo(hl, host);
+
+	return 0;
+}
+
 void hpsb_unregister_highlevel(struct hpsb_highlevel *hl)
 {
-        struct list_head *lh, *next;
+	struct list_head *lh, *next;
         struct hpsb_address_serve *as;
 	unsigned long flags;
 
@@ -272,16 +284,8 @@ void hpsb_unregister_highlevel(struct hp
         list_del(&hl->hl_list);
 	write_unlock_irqrestore(&hl_drivers_lock, flags);
 
-        if (hl->remove_host) {
-		down(&hpsb_hosts_lock);
-		list_for_each(lh, &hpsb_hosts) {
-			struct hpsb_host *host = list_entry(lh, struct hpsb_host, host_list);
-
-			hl->remove_host(host);
-			hpsb_destroy_hostinfo(hl, host);
-		}
-		up(&hpsb_hosts_lock);
-	}
+        if (hl->remove_host)
+		nodemgr_for_each_host(hl, highlevel_for_each_host_unreg);
 }
 
 int hpsb_register_addrspace(struct hpsb_highlevel *hl,
diff -puN drivers/ieee1394/highlevel.h~ieee1394-update drivers/ieee1394/highlevel.h
--- 25/drivers/ieee1394/highlevel.h~ieee1394-update	2003-12-24 10:25:54.000000000 -0800
+++ 25-akpm/drivers/ieee1394/highlevel.h	2003-12-24 10:25:54.000000000 -0800
@@ -92,8 +92,6 @@ struct hpsb_address_ops {
 };
 
 
-void init_hpsb_highlevel(void);
-
 void highlevel_add_host(struct hpsb_host *host);
 void highlevel_remove_host(struct hpsb_host *host);
 void highlevel_host_reset(struct hpsb_host *host);
@@ -180,4 +178,7 @@ int hpsb_set_hostinfo(struct hpsb_highle
 /* Retrieve hpsb_host using a highlevel handle and a key */
 struct hpsb_host *hpsb_get_host_bykey(struct hpsb_highlevel *hl, unsigned long key);
 
+/* Initialize the highlevel system */
+void init_hpsb_highlevel(void);
+
 #endif /* IEEE1394_HIGHLEVEL_H */
diff -puN drivers/ieee1394/hosts.c~ieee1394-update drivers/ieee1394/hosts.c
--- 25/drivers/ieee1394/hosts.c~ieee1394-update	2003-12-24 10:25:54.000000000 -0800
+++ 25-akpm/drivers/ieee1394/hosts.c	2003-12-24 10:25:54.000000000 -0800
@@ -16,14 +16,14 @@
 #include <linux/list.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/pci.h>
 
 #include "ieee1394_types.h"
 #include "hosts.h"
 #include "ieee1394_core.h"
 #include "highlevel.h"
+#include "nodemgr.h"
 
-LIST_HEAD(hpsb_hosts);
-DECLARE_MUTEX(hpsb_hosts_lock);
 
 static int dummy_transmit_packet(struct hpsb_host *h, struct hpsb_packet *p)
 {
@@ -46,54 +46,14 @@ static struct hpsb_host_driver dummy_dri
 	.isoctl =          dummy_isoctl
 };
 
-/**
- * hpsb_ref_host - increase reference count for host controller.
- * @host: the host controller
- *
- * Increase the reference count for the specified host controller.
- * When holding a reference to a host, the memory allocated for the
- * host struct will not be freed and the host is guaranteed to be in a
- * consistent state.  The driver may be unloaded or the controller may
- * be removed (PCMCIA), but the host struct will remain valid.
- */
-
-int hpsb_ref_host(struct hpsb_host *host)
+static int alloc_hostnum_cb(struct hpsb_host *host, void *__data)
 {
-        struct list_head *lh;
-        int retval = 0;
-
-	down(&hpsb_hosts_lock);
-        list_for_each(lh, &hpsb_hosts) {
-                if (host == list_entry(lh, struct hpsb_host, host_list)) {
-			if (try_module_get(host->driver->owner)) {
-				atomic_inc(&host->refcount);
-				retval = 1;
-			}
-			break;
-        	}
-        }
-	up(&hpsb_hosts_lock);
-
-        return retval;
-}
+	int *hostnum = __data;
 
-/**
- * hpsb_unref_host - decrease reference count for host controller.
- * @host: the host controller
- *
- * Decrease the reference count for the specified host controller.
- * When the reference count reaches zero, the memory allocated for the
- * &hpsb_host will be freed.
- */
-
-void hpsb_unref_host(struct hpsb_host *host)
-{
-	module_put(host->driver->owner);
+	if (host->id == *hostnum)
+		return 1;
 
-	down(&hpsb_hosts_lock);
-        if (atomic_dec_and_test(&host->refcount) && host->is_shutdown)
-		device_unregister(&host->device);
-	up(&hpsb_hosts_lock);
+	return 0;
 }
 
 /**
@@ -108,19 +68,16 @@ void hpsb_unref_host(struct hpsb_host *h
  * driver specific parts, enable the controller and make it available
  * to the general subsystem using hpsb_add_host().
  *
- * The &hpsb_host is allocated with an single initial reference
- * belonging to the driver.  Once the driver is done with the struct,
- * for example, when the driver is unloaded, it should release this
- * reference using hpsb_unref_host().
- *
  * Return Value: a pointer to the &hpsb_host if succesful, %NULL if
  * no memory was available.
  */
 
-struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra)
+struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
+				  struct device *dev)
 {
         struct hpsb_host *h;
 	int i;
+	int hostnum = 0;
 
         h = kmalloc(sizeof(struct hpsb_host) + extra, SLAB_KERNEL);
         if (!h) return NULL;
@@ -128,7 +85,6 @@ struct hpsb_host *hpsb_alloc_host(struct
 
 	h->hostdata = h + 1;
         h->driver = drv;
-	atomic_set(&h->refcount, 1);
 
         INIT_LIST_HEAD(&h->pending_packets);
         spin_lock_init(&h->pending_pkt_lock);
@@ -146,53 +102,35 @@ struct hpsb_host *hpsb_alloc_host(struct
         h->topology_map = h->csr.topology_map + 3;
         h->speed_map = (u8 *)(h->csr.speed_map + 2);
 
-	return h;
-}
-
-static int alloc_hostnum(void)
-{
-	int hostnum = 0;
-
 	while (1) {
-		struct list_head *lh;
-		int found = 0;
-
-		list_for_each(lh, &hpsb_hosts) {
-			struct hpsb_host *host = list_entry(lh, struct hpsb_host, host_list);
-
-			if (host->id == hostnum) {
-				found = 1;
-				break;
-			}
+		if (!nodemgr_for_each_host(&hostnum, alloc_hostnum_cb)) {
+			h->id = hostnum;
+			break;
 		}
 
-		if (!found)
-			return hostnum;
-
 		hostnum++;
 	}
 
-	return 0;
+	memcpy(&h->device, &nodemgr_dev_template_host, sizeof(h->device));
+	h->device.parent = dev;
+	snprintf(h->device.bus_id, BUS_ID_SIZE, "fw-host%d", h->id);
+	device_register(&h->device);
+
+	return h;
 }
 
 void hpsb_add_host(struct hpsb_host *host)
 {
-	down(&hpsb_hosts_lock);
-	host->id = alloc_hostnum();
-        list_add_tail(&host->host_list, &hpsb_hosts);
-	up(&hpsb_hosts_lock);
-
         highlevel_add_host(host);
         host->driver->devctl(host, RESET_BUS, LONG_RESET);
 }
 
 void hpsb_remove_host(struct hpsb_host *host)
 {
-	down(&hpsb_hosts_lock);
         host->is_shutdown = 1;
         host->driver = &dummy_driver;
-	list_del(&host->host_list);
-	up(&hpsb_hosts_lock);
 
         highlevel_remove_host(host);
+
+	device_unregister(&host->device);
 }
diff -puN drivers/ieee1394/hosts.h~ieee1394-update drivers/ieee1394/hosts.h
--- 25/drivers/ieee1394/hosts.h~ieee1394-update	2003-12-24 10:25:54.000000000 -0800
+++ 25-akpm/drivers/ieee1394/hosts.h	2003-12-24 10:25:54.000000000 -0800
@@ -29,8 +29,6 @@ struct hpsb_host {
 
         atomic_t generation;
 
-	atomic_t refcount;
-
         struct list_head pending_packets;
         spinlock_t pending_pkt_lock;
 	struct timer_list timeout;
@@ -165,7 +163,7 @@ struct hpsb_host_driver {
          * packet->type == raw) and do byte-swapping as necessary or instruct
          * the hardware to do so.  It can return immediately after the packet
          * was queued for sending.  After sending, hpsb_sent_packet() has to be
-         * called.  Return 0 for failure.
+         * called.  Return 0 on success, negative errno on failure.
          * NOTE: The function must be callable in interrupt context.
          */
         int (*transmit_packet) (struct hpsb_host *host, 
@@ -195,22 +193,8 @@ struct hpsb_host_driver {
 };
 
 
-extern struct list_head hpsb_hosts;
-extern struct semaphore hpsb_hosts_lock;
-
-
-/*
- * In order to prevent hosts from unloading, use hpsb_ref_host().  This prevents
- * the host from going away (e.g. makes module unloading of the driver
- * impossible), but still can not guarantee it (e.g. PC-Card being pulled by the
- * user).  hpsb_ref_host() returns false if host could not be locked.  If it is
- * successful, host is valid as a pointer until hpsb_unref_host() (not just
- * until after remove_host).
- */
-int hpsb_ref_host(struct hpsb_host *host);
-void hpsb_unref_host(struct hpsb_host *host);
-
-struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra);
+struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
+				  struct device *dev);
 void hpsb_add_host(struct hpsb_host *host);
 void hpsb_remove_host(struct hpsb_host *h);
 
diff -puN drivers/ieee1394/ieee1394_core.c~ieee1394-update drivers/ieee1394/ieee1394_core.c
--- 25/drivers/ieee1394/ieee1394_core.c~ieee1394-update	2003-12-24 10:25:54.000000000 -0800
+++ 25-akpm/drivers/ieee1394/ieee1394_core.c	2003-12-24 10:25:54.000000000 -0800
@@ -109,7 +109,7 @@ void hpsb_set_packet_complete_task(struc
 }
 
 /**
- * alloc_hpsb_packet - allocate new packet structure
+ * hpsb_alloc_packet - allocate new packet structure
  * @data_size: size of the data block to be allocated
  *
  * This function allocates, initializes and returns a new &struct hpsb_packet.
@@ -128,7 +128,7 @@ void hpsb_set_packet_complete_task(struc
  * Return value: A pointer to a &struct hpsb_packet or NULL on allocation
  * failure.
  */
-struct hpsb_packet *alloc_hpsb_packet(size_t data_size)
+struct hpsb_packet *hpsb_alloc_packet(size_t data_size)
 {
         struct hpsb_packet *packet = NULL;
         void *data = NULL;
@@ -152,25 +152,23 @@ struct hpsb_packet *alloc_hpsb_packet(si
         }
 
         INIT_LIST_HEAD(&packet->list);
-        sema_init(&packet->state_change, 0);
 	packet->complete_routine = NULL;
 	packet->complete_data = NULL;
         packet->state = hpsb_unused;
         packet->generation = -1;
-        packet->data_be = 1;
 
         return packet;
 }
 
 
 /**
- * free_hpsb_packet - free packet and data associated with it
+ * hpsb_free_packet - free packet and data associated with it
  * @packet: packet to free (is NULL safe)
  *
  * This function will free packet->data, packet->header and finally the packet
  * itself.
  */
-void free_hpsb_packet(struct hpsb_packet *packet)
+void hpsb_free_packet(struct hpsb_packet *packet)
 {
         if (!packet) return;
 
@@ -420,14 +418,12 @@ void hpsb_packet_sent(struct hpsb_host *
 
         if (packet->no_waiter) {
                 /* must not have a tlabel allocated */
-                free_hpsb_packet(packet);
+                hpsb_free_packet(packet);
                 return;
         }
 
         if (ackcode != ACK_PENDING || !packet->expect_response) {
                 packet->state = hpsb_complete;
-                up(&packet->state_change);
-                up(&packet->state_change);
                 run_packet_complete(packet);
                 return;
         }
@@ -439,7 +435,6 @@ void hpsb_packet_sent(struct hpsb_host *
         list_add_tail(&packet->list, &host->pending_packets);
         spin_unlock_irqrestore(&host->pending_pkt_lock, flags);
 
-        up(&packet->state_change);
 	mod_timer(&host->timeout, jiffies + host->timeout_interval);
 }
 
@@ -465,7 +460,7 @@ int hpsb_send_phy_config(struct hpsb_hos
 		return -EINVAL;
 	}
 
-	packet = alloc_hpsb_packet(0);
+	packet = hpsb_alloc_packet(0);
 	if (!packet)
 		return -ENOMEM;
 
@@ -485,16 +480,8 @@ int hpsb_send_phy_config(struct hpsb_hos
 
 	packet->generation = get_hpsb_generation(host);
 
-	if (!hpsb_send_packet(packet)) {
-		retval = -EINVAL;
-		goto fail;
-	}
-
-	down(&packet->state_change);
-	down(&packet->state_change);
-
-fail:
-	free_hpsb_packet(packet);
+	retval = hpsb_send_packet_and_wait(packet);
+	hpsb_free_packet(packet);
 
 	return retval;
 }
@@ -504,23 +491,24 @@ fail:
  * @packet: packet to send
  *
  * The packet is sent through the host specified in the packet->host field.
- * Before sending, the packet's transmit speed is automatically determined using
- * the local speed map when it is an async, non-broadcast packet.
+ * Before sending, the packet's transmit speed is automatically determined
+ * using the local speed map when it is an async, non-broadcast packet.
  *
  * Possibilities for failure are that host is either not initialized, in bus
  * reset, the packet's generation number doesn't match the current generation
  * number or the host reports a transmit error.
  *
- * Return value: False (0) on failure, true (1) otherwise.
+ * Return value: 0 on success, negative errno on failure.
  */
 int hpsb_send_packet(struct hpsb_packet *packet)
 {
         struct hpsb_host *host = packet->host;
 
-        if (host->is_shutdown || host->in_bus_reset
-            || (packet->generation != get_hpsb_generation(host))) {
-                return 0;
-        }
+        if (host->is_shutdown)
+		return -EINVAL;
+	if (host->in_bus_reset ||
+	    (packet->generation != get_hpsb_generation(host)))
+                return -EAGAIN;
 
         packet->state = hpsb_queued;
 
@@ -532,23 +520,13 @@ int hpsb_send_packet(struct hpsb_packet 
                 data = kmalloc(packet->header_size + packet->data_size, GFP_ATOMIC);
                 if (!data) {
                         HPSB_ERR("unable to allocate memory for concatenating header and data");
-                        return 0;
+                        return -ENOMEM;
                 }
 
                 memcpy(data, packet->header, packet->header_size);
 
                 if (packet->data_size)
-                {
-                        if (packet->data_be) {
-                                memcpy(((u8*)data)+packet->header_size, packet->data, packet->data_size);
-                        } else {
-                                int i;
-                                quadlet_t *my_data=(quadlet_t*) ((u8*) data + packet->data_size);
-                                for (i=0; i < packet->data_size/4; i++) {
-                                        my_data[i] = cpu_to_be32(packet->data[i]);
-                                }
-                        }
-                }
+			memcpy(((u8*)data)+packet->header_size, packet->data, packet->data_size);
 
                 dump_packet("send packet local:", packet->header,
                             packet->header_size);
@@ -558,7 +536,7 @@ int hpsb_send_packet(struct hpsb_packet 
 
                 kfree(data);
 
-                return 1;
+                return 0;
         }
 
         if (packet->type == hpsb_async && packet->node_id != ALL_NODES) {
@@ -584,10 +562,33 @@ int hpsb_send_packet(struct hpsb_packet 
         return host->driver->transmit_packet(host, packet);
 }
 
+/* We could just use complete() directly as the packet complete
+ * callback, but this is more typesafe, in the sense that we get a
+ * compiler error if the prototype for complete() changes. */
+
+static void complete_packet(void *data)
+{
+	complete((struct completion *) data);
+}
+
+int hpsb_send_packet_and_wait(struct hpsb_packet *packet)
+{
+	struct completion done;
+	int retval;
+
+	init_completion(&done);
+	hpsb_set_packet_complete_task(packet, complete_packet, &done);
+	retval = hpsb_send_packet(packet);
+	if (retval == 0)
+		wait_for_completion(&done);
+
+	return retval;
+}
+
 static void send_packet_nocare(struct hpsb_packet *packet)
 {
-        if (!hpsb_send_packet(packet)) {
-                free_hpsb_packet(packet);
+        if (hpsb_send_packet(packet) < 0) {
+                hpsb_free_packet(packet);
         }
 }
 
@@ -668,7 +669,6 @@ void handle_packet_response(struct hpsb_
         }
 
         packet->state = hpsb_complete;
-        up(&packet->state_change);
 	run_packet_complete(packet);
 }
 
@@ -680,7 +680,7 @@ static struct hpsb_packet *create_reply_
 
         dsize += (dsize % 4 ? 4 - (dsize % 4) : 0);
 
-        p = alloc_hpsb_packet(dsize);
+        p = hpsb_alloc_packet(dsize);
         if (p == NULL) {
                 /* FIXME - send data_error response */
                 return NULL;
@@ -820,6 +820,8 @@ static void handle_incoming_packet(struc
                 if (rcode >= 0) {
                         fill_async_readblock_resp(packet, rcode, length);
                         send_packet_nocare(packet);
+                } else {
+                        hpsb_free_packet(packet);
                 }
                 break;
 
@@ -874,7 +876,7 @@ static void handle_incoming_packet(struc
                 if (rcode >= 0) {
                         send_packet_nocare(packet);
                 } else {
-                        free_hpsb_packet(packet);
+                        hpsb_free_packet(packet);
                 }
                 break;
         }
@@ -949,7 +951,6 @@ void abort_requests(struct hpsb_host *ho
                 list_del(&packet->list);
                 packet->state = hpsb_complete;
                 packet->ack_code = ACKX_ABORTED;
-                up(&packet->state_change);
 		run_packet_complete(packet);
         }
 }
@@ -987,7 +988,6 @@ void abort_timedouts(unsigned long __opa
                 list_del(&packet->list);
                 packet->state = hpsb_complete;
                 packet->ack_code = ACKX_TIMEOUT;
-                up(&packet->state_change);
 		run_packet_complete(packet);
         }
 }
@@ -1171,19 +1171,22 @@ static int ieee1394_dispatch_open(struct
 
 static int __init ieee1394_init(void)
 {
-	hpsb_packet_cache = kmem_cache_create("hpsb_packet", sizeof(struct hpsb_packet),
-					      0, 0, NULL, NULL);
-
 	devfs_mk_dir("ieee1394");
-
 	if (register_chrdev(IEEE1394_MAJOR, "ieee1394", &ieee1394_chardev_ops)) {
 		HPSB_ERR("unable to register character device major %d!\n", IEEE1394_MAJOR);
-		devfs_remove("ieee1394");
 		return -ENODEV;
 	}
 
+	devfs_mk_dir("ieee1394");
+
+	hpsb_packet_cache = kmem_cache_create("hpsb_packet", sizeof(struct hpsb_packet),
+					      0, 0, NULL, NULL);
+
+	bus_register(&ieee1394_bus_type);
+
 	init_hpsb_highlevel();
 	init_csr();
+
 	if (!disable_nodemgr)
 		init_ieee1394_nodemgr();
 	else
@@ -1198,6 +1201,9 @@ static void __exit ieee1394_cleanup(void
 		cleanup_ieee1394_nodemgr();
 
 	cleanup_csr();
+
+	bus_unregister(&ieee1394_bus_type);
+
 	kmem_cache_destroy(hpsb_packet_cache);
 
 	unregister_chrdev(IEEE1394_MAJOR, "ieee1394");
@@ -1213,16 +1219,15 @@ module_exit(ieee1394_cleanup);
 EXPORT_SYMBOL(hpsb_alloc_host);
 EXPORT_SYMBOL(hpsb_add_host);
 EXPORT_SYMBOL(hpsb_remove_host);
-EXPORT_SYMBOL(hpsb_ref_host);
-EXPORT_SYMBOL(hpsb_unref_host);
 
 /** ieee1394_core.c **/
 EXPORT_SYMBOL(hpsb_speedto_str);
 EXPORT_SYMBOL(hpsb_set_packet_complete_task);
-EXPORT_SYMBOL(alloc_hpsb_packet);
-EXPORT_SYMBOL(free_hpsb_packet);
+EXPORT_SYMBOL(hpsb_alloc_packet);
+EXPORT_SYMBOL(hpsb_free_packet);
 EXPORT_SYMBOL(hpsb_send_phy_config);
 EXPORT_SYMBOL(hpsb_send_packet);
+EXPORT_SYMBOL(hpsb_send_packet_and_wait);
 EXPORT_SYMBOL(hpsb_reset_bus);
 EXPORT_SYMBOL(hpsb_bus_reset);
 EXPORT_SYMBOL(hpsb_selfid_received);
@@ -1282,6 +1287,7 @@ EXPORT_SYMBOL(hpsb_node_lock);
 EXPORT_SYMBOL(hpsb_register_protocol);
 EXPORT_SYMBOL(hpsb_unregister_protocol);
 EXPORT_SYMBOL(ieee1394_bus_type);
+EXPORT_SYMBOL(nodemgr_for_each_host);
 
 /** csr.c **/
 EXPORT_SYMBOL(hpsb_update_config_rom);
diff -puN drivers/ieee1394/ieee1394_core.h~ieee1394-update drivers/ieee1394/ieee1394_core.h
--- 25/drivers/ieee1394/ieee1394_core.h~ieee1394-update	2003-12-24 10:25:54.000000000 -0800
+++ 25-akpm/drivers/ieee1394/ieee1394_core.h	2003-12-24 10:25:54.000000000 -0800
@@ -40,11 +40,6 @@ struct hpsb_packet {
         unsigned expect_response:1;
         unsigned no_waiter:1;
 
-        /* Data big endianness flag - may vary from request to request.  The
-         * header is always in machine byte order.
-         * Not really used currently.  */
-        unsigned data_be:1;
-
         /* Speed to transmit with: 0 = 100Mbps, 1 = 200Mbps, 2 = 400Mbps */
         unsigned speed_code:2;
 
@@ -64,9 +59,6 @@ struct hpsb_packet {
         struct hpsb_host *host;
         unsigned int generation;
 
-        /* Very core internal, don't care. */
-        struct semaphore state_change;
-
 	/* Function (and possible data to pass to it) to call when this
 	 * packet is completed.  */
 	void (*complete_routine)(void *);
@@ -90,8 +82,8 @@ static inline struct hpsb_packet *driver
 void abort_timedouts(unsigned long __opaque);
 void abort_requests(struct hpsb_host *host);
 
-struct hpsb_packet *alloc_hpsb_packet(size_t data_size);
-void free_hpsb_packet(struct hpsb_packet *packet);
+struct hpsb_packet *hpsb_alloc_packet(size_t data_size);
+void hpsb_free_packet(struct hpsb_packet *packet);
 
 
 /*
@@ -108,15 +100,23 @@ static inline unsigned int get_hpsb_gene
 }
 
 /*
- * Send a PHY configuration packet.
+ * Send a PHY configuration packet, return 0 on success, negative
+ * errno on failure.
  */
 int hpsb_send_phy_config(struct hpsb_host *host, int rootid, int gapcnt);
 
 /*
- * Queue packet for transmitting, return 0 for failure.
+ * Queue packet for transmitting, return 0 on success, negative errno
+ * on failure.
  */
 int hpsb_send_packet(struct hpsb_packet *packet);
 
+/*
+ * Queue packet for transmitting, and block until the transaction
+ * completes. Return 0 on success, negative errno on failure.
+ */
+int hpsb_send_packet_and_wait(struct hpsb_packet *packet);
+
 /* Initiate bus reset on the given host.  Returns 1 if bus reset already in
  * progress, 0 otherwise. */
 int hpsb_reset_bus(struct hpsb_host *host, int type);
diff -puN drivers/ieee1394/ieee1394_transactions.c~ieee1394-update drivers/ieee1394/ieee1394_transactions.c
--- 25/drivers/ieee1394/ieee1394_transactions.c~ieee1394-update	2003-12-24 10:25:54.000000000 -0800
+++ 25-akpm/drivers/ieee1394/ieee1394_transactions.c	2003-12-24 10:25:54.000000000 -0800
@@ -263,7 +263,7 @@ struct hpsb_packet *hpsb_make_readpacket
 	if (length == 0)
 		return NULL;
 
-	packet = alloc_hpsb_packet(length + (length % 4 ? 4 - (length % 4) : 0));
+	packet = hpsb_alloc_packet(length + (length % 4 ? 4 - (length % 4) : 0));
 	if (!packet)
 		return NULL;
 
@@ -271,7 +271,7 @@ struct hpsb_packet *hpsb_make_readpacket
 	packet->node_id = node;
 
 	if (hpsb_get_tlabel(packet)) {
-		free_hpsb_packet(packet);
+		hpsb_free_packet(packet);
 		return NULL;
 	}
 
@@ -291,7 +291,7 @@ struct hpsb_packet *hpsb_make_writepacke
 	if (length == 0)
 		return NULL;
 
-	packet = alloc_hpsb_packet(length + (length % 4 ? 4 - (length % 4) : 0));
+	packet = hpsb_alloc_packet(length + (length % 4 ? 4 - (length % 4) : 0));
 	if (!packet)
 		return NULL;
 
@@ -302,7 +302,7 @@ struct hpsb_packet *hpsb_make_writepacke
 	packet->node_id = node;
 
 	if (hpsb_get_tlabel(packet)) {
-		free_hpsb_packet(packet);
+		hpsb_free_packet(packet);
 		return NULL;
 	}
 
@@ -325,7 +325,7 @@ struct hpsb_packet *hpsb_make_streampack
 	if (length == 0)
 		return NULL;
 
-	packet = alloc_hpsb_packet(length + (length % 4 ? 4 - (length % 4) : 0));
+	packet = hpsb_alloc_packet(length + (length % 4 ? 4 - (length % 4) : 0));
 	if (!packet)
 		return NULL;
 
@@ -335,7 +335,7 @@ struct hpsb_packet *hpsb_make_streampack
 	packet->host = host;
     
 	if (hpsb_get_tlabel(packet)) {
-		free_hpsb_packet(packet);
+		hpsb_free_packet(packet);
 		return NULL;
 	}
 
@@ -353,13 +353,13 @@ struct hpsb_packet *hpsb_make_lockpacket
 	struct hpsb_packet *p;
 	u32 length;
 
-	p = alloc_hpsb_packet(8);
+	p = hpsb_alloc_packet(8);
 	if (!p) return NULL;
 
 	p->host = host;
 	p->node_id = node;
 	if (hpsb_get_tlabel(p)) {
-		free_hpsb_packet(p);
+		hpsb_free_packet(p);
 		return NULL;
 	}
 
@@ -390,13 +390,13 @@ struct hpsb_packet *hpsb_make_lock64pack
 	struct hpsb_packet *p;
 	u32 length;
 
-	p = alloc_hpsb_packet(16);
+	p = hpsb_alloc_packet(16);
 	if (!p) return NULL;
 
 	p->host = host;
 	p->node_id = node;
 	if (hpsb_get_tlabel(p)) {
-		free_hpsb_packet(p);
+		hpsb_free_packet(p);
 		return NULL;
 	}
 
@@ -429,7 +429,7 @@ struct hpsb_packet *hpsb_make_phypacket(
 {
         struct hpsb_packet *p; 
 
-        p = alloc_hpsb_packet(0); 
+        p = hpsb_alloc_packet(0); 
         if (!p) return NULL; 
 
         p->host = host; 
@@ -444,7 +444,7 @@ struct hpsb_packet *hpsb_make_isopacket(
 {
 	struct hpsb_packet *p;
 
-	p = alloc_hpsb_packet(length);
+	p = hpsb_alloc_packet(length);
 	if (!p) return NULL;
 
 	p->host = host;
@@ -478,13 +478,10 @@ int hpsb_read(struct hpsb_host *host, no
         }
 
 	packet->generation = generation;
-        if (!hpsb_send_packet(packet)) {
-		retval = -EINVAL;
+        retval = hpsb_send_packet_and_wait(packet);
+	if (retval < 0)
 		goto hpsb_read_fail;
-	}
 
-        down(&packet->state_change);
-        down(&packet->state_change);
         retval = hpsb_packet_success(packet);
 
         if (retval == 0) {
@@ -497,7 +494,7 @@ int hpsb_read(struct hpsb_host *host, no
 
 hpsb_read_fail:
         hpsb_free_tlabel(packet);
-        free_hpsb_packet(packet);
+        hpsb_free_packet(packet);
 
         return retval;
 }
@@ -520,18 +517,15 @@ int hpsb_write(struct hpsb_host *host, n
 		return -ENOMEM;
 
 	packet->generation = generation;
-        if (!hpsb_send_packet(packet)) {
-		retval = -EINVAL;
+        retval = hpsb_send_packet_and_wait(packet);
+	if (retval < 0)
 		goto hpsb_write_fail;
-	}
 
-        down(&packet->state_change);
-        down(&packet->state_change);
         retval = hpsb_packet_success(packet);
 
 hpsb_write_fail:
         hpsb_free_tlabel(packet);
-        free_hpsb_packet(packet);
+        hpsb_free_packet(packet);
 
         return retval;
 }
@@ -550,12 +544,10 @@ int hpsb_lock(struct hpsb_host *host, no
                 return -ENOMEM;
 
 	packet->generation = generation;
-        if (!hpsb_send_packet(packet)) {
-		retval = -EINVAL;
+        retval = hpsb_send_packet_and_wait(packet);
+	if (retval < 0)
 		goto hpsb_lock_fail;
-	}
-        down(&packet->state_change);
-        down(&packet->state_change);
+
         retval = hpsb_packet_success(packet);
 
         if (retval == 0) {
@@ -564,7 +556,7 @@ int hpsb_lock(struct hpsb_host *host, no
 
 hpsb_lock_fail:
         hpsb_free_tlabel(packet);
-        free_hpsb_packet(packet);
+        hpsb_free_packet(packet);
 
         return retval;
 }
@@ -582,12 +574,10 @@ int hpsb_lock64(struct hpsb_host *host, 
 		return -ENOMEM;
 
 	packet->generation = generation;
-	if (!hpsb_send_packet(packet)) {
-		retval = -EINVAL;
+	retval = hpsb_send_packet_and_wait(packet);
+	if (retval < 0)
 		goto hpsb_lock64_fail;
-	}
-	down(&packet->state_change);
-	down(&packet->state_change);
+
 	retval = hpsb_packet_success(packet);
 
 	if (retval == 0)
@@ -595,7 +585,7 @@ int hpsb_lock64(struct hpsb_host *host, 
 
 hpsb_lock64_fail:
 	hpsb_free_tlabel(packet);
-	free_hpsb_packet(packet);
+	hpsb_free_packet(packet);
 
         return retval;
 }
@@ -626,10 +616,9 @@ int hpsb_send_gasp(struct hpsb_host *hos
 
 	packet->no_waiter = 1;
 
-	if (!hpsb_send_packet(packet)) {
-		free_hpsb_packet(packet);
-		retval = -EINVAL;
-	}
+	retval = hpsb_send_packet(packet);
+	if (retval < 0)
+		hpsb_free_packet(packet);
 
 	return retval;
 }
diff -puN drivers/ieee1394/iso.c~ieee1394-update drivers/ieee1394/iso.c
--- 25/drivers/ieee1394/iso.c~ieee1394-update	2003-12-24 10:25:54.000000000 -0800
+++ 25-akpm/drivers/ieee1394/iso.c	2003-12-24 10:25:54.000000000 -0800
@@ -40,6 +40,7 @@ static struct hpsb_iso* hpsb_iso_common_
 					     unsigned int data_buf_size,
 					     unsigned int buf_packets,
 					     int channel,
+					     int dma_mode,
 					     int irq_interval,
 					     void (*callback)(struct hpsb_iso*))
 {
@@ -58,8 +59,13 @@ static struct hpsb_iso* hpsb_iso_common_
 	if (buf_packets < 2)
 		buf_packets = 2;
 
-	if (irq_interval < 1 || irq_interval > buf_packets / 2)
-		irq_interval = buf_packets / 2;
+	if ((dma_mode < HPSB_ISO_DMA_DEFAULT) || (dma_mode > HPSB_ISO_DMA_PACKET_PER_BUFFER))
+		dma_mode=HPSB_ISO_DMA_DEFAULT;
+
+	if (irq_interval == 0)     /* really interrupt for each packet*/
+		irq_interval = 1;
+	else if ((irq_interval < 0) || (irq_interval > buf_packets / 4))
+ 		irq_interval = buf_packets / 4;
 
 	if (channel < -1 || channel >= 64)
 		return NULL;
@@ -83,6 +89,7 @@ static struct hpsb_iso* hpsb_iso_common_
 	init_waitqueue_head(&iso->waitq);
 	iso->channel = channel;
 	iso->irq_interval = irq_interval;
+	iso->dma_mode = dma_mode;
 	dma_region_init(&iso->data_buf);
 	iso->buf_size = round_up_to_page(data_buf_size);
 	iso->buf_packets = buf_packets;
@@ -136,7 +143,7 @@ struct hpsb_iso* hpsb_iso_xmit_init(stru
 {
 	struct hpsb_iso *iso = hpsb_iso_common_init(host, HPSB_ISO_XMIT,
 						    data_buf_size, buf_packets,
-						    channel, irq_interval, callback);
+						    channel, HPSB_ISO_DMA_DEFAULT, irq_interval, callback);
 	if (!iso)
 		return NULL;
 
@@ -158,12 +165,13 @@ struct hpsb_iso* hpsb_iso_recv_init(stru
 				    unsigned int data_buf_size,
 				    unsigned int buf_packets,
 				    int channel,
+				    int dma_mode,
 				    int irq_interval,
 				    void (*callback)(struct hpsb_iso*))
 {
 	struct hpsb_iso *iso = hpsb_iso_common_init(host, HPSB_ISO_RECV,
 						    data_buf_size, buf_packets,
-						    channel, irq_interval, callback);
+						    channel, dma_mode, irq_interval, callback);
 	if (!iso)
 		return NULL;
 
diff -puN drivers/ieee1394/iso.h~ieee1394-update drivers/ieee1394/iso.h
--- 25/drivers/ieee1394/iso.h~ieee1394-update	2003-12-24 10:25:54.000000000 -0800
+++ 25-akpm/drivers/ieee1394/iso.h	2003-12-24 10:25:54.000000000 -0800
@@ -51,6 +51,14 @@ struct hpsb_iso_packet_info {
 
 enum hpsb_iso_type { HPSB_ISO_RECV = 0, HPSB_ISO_XMIT = 1 };
 
+/* The mode of the dma when receiving iso data. Must be supported by chip */
+enum raw1394_iso_dma_recv_mode {
+	HPSB_ISO_DMA_DEFAULT = -1,
+	HPSB_ISO_DMA_OLD_ABI = 0,
+	HPSB_ISO_DMA_BUFFERFILL = 1,
+	HPSB_ISO_DMA_PACKET_PER_BUFFER = 2
+};
+
 struct hpsb_iso {
 	enum hpsb_iso_type type;
 
@@ -68,6 +76,8 @@ struct hpsb_iso {
 
 	int speed; /* IEEE1394_SPEED_100, 200, or 400 */
 	int channel; /* -1 if multichannel */
+	int dma_mode; /* dma receive mode */
+
 
 	/* greatest # of packets between interrupts - controls
 	   the maximum latency of the buffer */
@@ -139,6 +149,7 @@ struct hpsb_iso* hpsb_iso_recv_init(stru
 				    unsigned int data_buf_size,
 				    unsigned int buf_packets,
 				    int channel,
+				    int dma_mode,
 				    int irq_interval,
 				    void (*callback)(struct hpsb_iso*));
 
diff -puN drivers/ieee1394/Kconfig~ieee1394-update drivers/ieee1394/Kconfig
--- 25/drivers/ieee1394/Kconfig~ieee1394-update	2003-12-24 10:25:54.000000000 -0800
+++ 25-akpm/drivers/ieee1394/Kconfig	2003-12-24 10:25:54.000000000 -0800
@@ -1,7 +1,7 @@
 # -*- shell-script -*-
 
 menu "IEEE 1394 (FireWire) support (EXPERIMENTAL)"
-	depends on PCI && EXPERIMENTAL
+	depends on EXPERIMENTAL
 
 config IEEE1394
 	tristate "IEEE 1394 (FireWire) support (EXPERIMENTAL)"
@@ -15,7 +15,7 @@ config IEEE1394
 	  is the core support only, you will also need to select a driver for
 	  your IEEE 1394 adapter.
 
-	  To compile this driver as a module, choose M here: the
+	  To compile this driver as a module, say M here: the
 	  module will be called ieee1394.
 
 comment "Subsystem Options"
@@ -56,13 +56,13 @@ comment "Texas Instruments PCILynx requi
 
 config IEEE1394_PCILYNX
 	tristate "Texas Instruments PCILynx support"
-	depends on IEEE1394 && I2C_ALGOBIT
+	depends on PCI && IEEE1394 && I2C_ALGOBIT
 	help
 	  Say Y here if you have an IEEE-1394 controller with the Texas
 	  Instruments PCILynx chip.  Note: this driver is written for revision
 	  2 of this chip and may not work with revision 0.
 
-	  To compile this driver as a module, choose M here: the
+	  To compile this driver as a module, say M here: the
 	  module will be called pcilynx.
 
 # Non-maintained pcilynx options
@@ -72,7 +72,7 @@ config IEEE1394_PCILYNX
 # fi
 config IEEE1394_OHCI1394
 	tristate "OHCI-1394 support"
-	depends on IEEE1394
+	depends on PCI && IEEE1394
 	help
 	  Enable this driver if you have an IEEE 1394 controller based on the
 	  OHCI-1394 specification. The current driver is only tested with OHCI
@@ -80,7 +80,7 @@ config IEEE1394_OHCI1394
 	  use one of these chipsets.  It should work with any OHCI-1394
 	  compliant card, however.
 
-	  To compile this driver as a module, choose M here: the
+	  To compile this driver as a module, say M here: the
 	  module will be called ohci1394.
 
 comment "Protocol Drivers"
@@ -122,7 +122,7 @@ config IEEE1394_DV1394
 
 	  The user-space API for dv1394 is documented in dv1394.h.
 
-	  To compile this driver as a module, choose M here: the
+	  To compile this driver as a module, say M here: the
 	  module will be called dv1394.
 
 config IEEE1394_RAWIO
@@ -134,7 +134,7 @@ config IEEE1394_RAWIO
 	  direct communication of user programs with the IEEE 1394 bus and
 	  thus with the attached peripherals.
 
-	  To compile this driver as a module, choose M here: the
+	  To compile this driver as a module, say M here: the
 	  module will be called raw1394.
 
 config IEEE1394_CMP
@@ -144,7 +144,7 @@ config IEEE1394_CMP
 	  This option enables the Connection Management Procedures
 	  (IEC61883-1) driver, which implements input and output plugs.
 
-	  To compile this driver as a module, choose M here: the
+	  To compile this driver as a module, say M here: the
 	  module will be called cmp.
 
 config IEEE1394_AMDTP
@@ -157,7 +157,7 @@ config IEEE1394_AMDTP
 
 	  The userspace interface is documented in amdtp.h.
 
-	  To compile this driver as a module, choose M here: the
+	  To compile this driver as a module, say M here: the
 	  module will be called amdtp.
 
 endmenu
diff -puN drivers/ieee1394/nodemgr.c~ieee1394-update drivers/ieee1394/nodemgr.c
--- 25/drivers/ieee1394/nodemgr.c~ieee1394-update	2003-12-24 10:25:54.000000000 -0800
+++ 25-akpm/drivers/ieee1394/nodemgr.c	2003-12-24 10:25:54.000000000 -0800
@@ -516,8 +516,7 @@ static struct device nodemgr_dev_templat
 	.driver_data	= &nodemgr_driverdata_ne,
 };
 
-
-static struct device nodemgr_dev_template_host = {
+struct device nodemgr_dev_template_host = {
 	.bus		= &ieee1394_bus_type,
 	.release	= nodemgr_release_host,
 	.driver		= &nodemgr_driver_host,
@@ -1255,36 +1254,6 @@ void hpsb_unregister_protocol(struct hps
 }
 
 
-/* Searches the list of ud's that match a ne as the parent. If the ud has
- * a driver associated with it, we call that driver's update function
- * with the ud as the argument. */
-static int nodemgr_driver_search_cb(struct device *dev, void *__data)
-{
-	struct node_entry *ne = __data;
-	struct unit_directory *ud;
-
-	if (dev->driver_data == &nodemgr_driverdata_ne ||
-	    dev->driver_data == &nodemgr_driverdata_host)
-		return 0;
-
-	ud = container_of(dev, struct unit_directory, device);
-
-	if (&ne->device != ud->device.parent)
-		return 0;
-
-	if (ud->device.driver) {
-		struct hpsb_protocol_driver *pdrv;
-
-		pdrv = container_of(ud->device.driver,
-				struct hpsb_protocol_driver, driver);
-
-		if (pdrv->update)
-			pdrv->update(ud);
-	}
-
-	return 0;
-}
-
 /*
  * This function updates nodes that were present on the bus before the
  * reset and still are after the reset.  The nodeid and the config rom
@@ -1480,9 +1449,24 @@ static int nodemgr_probe_ne_cb(struct de
 		ne->needs_probe = 0;
 		return 1;
 	} else {
+		struct list_head *lh;
+
 		/* Update unit_dirs with attached drivers */
-		bus_for_each_dev(&ieee1394_bus_type, NULL, ne,
-				 nodemgr_driver_search_cb);
+		list_for_each(lh, &dev->children) {
+			struct unit_directory *ud;
+			
+			ud = container_of(list_to_dev(lh), struct unit_directory, device);
+
+			if (ud->device.driver) {
+				struct hpsb_protocol_driver *pdrv;
+
+				pdrv = container_of(ud->device.driver,
+						    struct hpsb_protocol_driver, driver);
+
+				if (pdrv->update)
+					pdrv->update(ud);
+			}
+		}
 	}
 	return 0;
 }
@@ -1664,7 +1648,6 @@ static int nodemgr_host_thread(void *__h
 	allow_signal(SIGTERM);
 
 	/* Setup our device-model entries */
-	device_register(&host->device);
 	nodemgr_create_host_dev_files(host);
 
 	/* Sit and wait for a signal to probe the nodes on the bus. This
@@ -1753,6 +1736,34 @@ struct node_entry *hpsb_nodeid_get_entry
 	return ne;
 }
 
+struct for_each_host_struct {
+	int (*cb)(struct hpsb_host *, void *);
+	void *data;
+};
+
+static int nodemgr_for_each_host_cb(struct device *dev, void *__data)
+{
+	struct for_each_host_struct *host_data = __data;
+	struct hpsb_host *host;
+
+	if (dev->driver_data != &nodemgr_driverdata_host)
+		return 0;
+
+	host = container_of(dev, struct hpsb_host, device);
+
+	return host_data->cb(host, host_data->data);
+}
+
+int nodemgr_for_each_host(void *__data, int (*cb)(struct hpsb_host *, void *))
+{
+	struct for_each_host_struct host_data;
+
+	host_data.cb = cb;
+	host_data.data = __data;
+
+	return bus_for_each_dev(&ieee1394_bus_type, NULL, &host_data, nodemgr_for_each_host_cb);
+}
+
 /* The following four convenience functions use a struct node_entry
  * for addressing a node on the bus.  They are intended for use by any
  * process context, not just the nodemgr thread, so we need to be a
@@ -1821,11 +1832,6 @@ static void nodemgr_add_host(struct hpsb
 	init_completion(&hi->exited);
         sema_init(&hi->reset_sem, 0);
 
-	memcpy(&host->device, &nodemgr_dev_template_host,
-	       sizeof(host->device));
-	host->device.parent = &host->pdev->dev;
-	snprintf(host->device.bus_id, BUS_ID_SIZE, "fw-host%d", host->id);
-
 	sprintf(hi->daemon_name, "knodemgrd_%d", host->id);
 
 	hi->pid = kernel_thread(nodemgr_host_thread, hi, CLONE_KERNEL);
@@ -1879,7 +1885,6 @@ static struct hpsb_highlevel nodemgr_hig
 
 void init_ieee1394_nodemgr(void)
 {
-	bus_register(&ieee1394_bus_type);
 	driver_register(&nodemgr_driver_host);
 	driver_register(&nodemgr_driver_ne);
 
@@ -1892,5 +1897,4 @@ void cleanup_ieee1394_nodemgr(void)
 
 	driver_unregister(&nodemgr_driver_ne);
 	driver_unregister(&nodemgr_driver_host);
-	bus_unregister(&ieee1394_bus_type);
 }
diff -puN drivers/ieee1394/nodemgr.h~ieee1394-update drivers/ieee1394/nodemgr.h
--- 25/drivers/ieee1394/nodemgr.h~ieee1394-update	2003-12-24 10:25:54.000000000 -0800
+++ 25-akpm/drivers/ieee1394/nodemgr.h	2003-12-24 10:25:54.000000000 -0800
@@ -219,7 +219,16 @@ int hpsb_node_lock(struct node_entry *ne
 		   int extcode, quadlet_t *data, quadlet_t arg);
 
 
+/* Iterate the hosts, calling a given function with supplied data for each
+ * host. */
+int nodemgr_for_each_host(void *__data, int (*cb)(struct hpsb_host *, void *));
+
+
 void init_ieee1394_nodemgr(void);
 void cleanup_ieee1394_nodemgr(void);
 
+
+/* The template for a host device */
+extern struct device nodemgr_dev_template_host;
+
 #endif /* _IEEE1394_NODEMGR_H */
diff -puN drivers/ieee1394/ohci1394.c~ieee1394-update drivers/ieee1394/ohci1394.c
--- 25/drivers/ieee1394/ohci1394.c~ieee1394-update	2003-12-24 10:25:54.000000000 -0800
+++ 25-akpm/drivers/ieee1394/ohci1394.c	2003-12-24 10:25:54.000000000 -0800
@@ -134,7 +134,7 @@
 
 #ifdef OHCI1394_DEBUG
 #define DBGMSG(card, fmt, args...) \
-printk(KERN_INFO "%s_%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args)
+printk(KERN_INFO "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args)
 #else
 #define DBGMSG(card, fmt, args...)
 #endif
@@ -158,10 +158,10 @@ printk(level "%s: " fmt "\n" , OHCI1394_
 
 /* print card specific information */
 #define PRINT(level, card, fmt, args...) \
-printk(level "%s_%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args)
+printk(level "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args)
 
 static char version[] __devinitdata =
-	"$Rev: 1045 $ Ben Collins <bcollins@debian.org>";
+	"$Rev: 1087 $ Ben Collins <bcollins@debian.org>";
 
 /* Module Parameters */
 static int phys_dma = 1;
@@ -845,7 +845,7 @@ static int ohci_transmit(struct hpsb_hos
 		PRINT(KERN_ERR, ohci->id, 
 		      "Transmit packet size %Zd is too big",
 		      packet->data_size);
-		return 0;
+		return -EOVERFLOW;
 	}
 
 	/* Decide whether we have an iso, a request, or a response packet */
@@ -862,7 +862,7 @@ static int ohci_transmit(struct hpsb_hos
 			if (in_interrupt()) {
 				PRINT(KERN_ERR, ohci->id, 
 				      "legacy IT context cannot be initialized during interrupt");
-				return 0;
+				return -EINVAL;
 			}
 
 			if (alloc_dma_trm_ctx(ohci, &ohci->it_legacy_context,
@@ -870,7 +870,7 @@ static int ohci_transmit(struct hpsb_hos
 					      OHCI1394_IsoXmitContextBase) < 0) {
 				PRINT(KERN_ERR, ohci->id, 
 				      "error initializing legacy IT context");
-				return 0;
+				return -ENOMEM;
 			}
 
 			initialize_dma_trm_ctx(&ohci->it_legacy_context);
@@ -890,7 +890,7 @@ static int ohci_transmit(struct hpsb_hos
 
 	spin_unlock_irqrestore(&d->lock,flags);
 
-	return 1;
+	return 0;
 }
 
 static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
@@ -1113,8 +1113,8 @@ struct ohci_iso_recv {
 	struct ohci1394_iso_tasklet task;
 	int task_active;
 
-	enum { BUFFER_FILL_MODE,
-	       PACKET_PER_BUFFER_MODE } dma_mode;
+	enum { BUFFER_FILL_MODE = 0,
+	       PACKET_PER_BUFFER_MODE = 1 } dma_mode;
 
 	/* memory and PCI mapping for the DMA descriptors */
 	struct dma_prog_region prog;
@@ -1175,7 +1175,8 @@ static int ohci_iso_recv_init(struct hps
 	/* use buffer-fill mode, unless irq_interval is 1
 	   (note: multichannel requires buffer-fill) */
 
-	if (iso->irq_interval == 1 && iso->channel != -1) {
+	if (((iso->irq_interval == 1 && iso->dma_mode == HPSB_ISO_DMA_OLD_ABI) ||
+	     iso->dma_mode == HPSB_ISO_DMA_PACKET_PER_BUFFER) && iso->channel != -1) {
 		recv->dma_mode = PACKET_PER_BUFFER_MODE;
 	} else {
 		recv->dma_mode = BUFFER_FILL_MODE;
@@ -1194,8 +1195,11 @@ static int ohci_iso_recv_init(struct hps
 		}
 
 		/* iso->irq_interval is in packets - translate that to blocks */
-		/* (err, sort of... 1 is always the safest value) */
-		recv->block_irq_interval = iso->irq_interval / recv->nblocks;
+		if (iso->irq_interval == 1)
+			recv->block_irq_interval = 1;			
+		else
+			recv->block_irq_interval = iso->irq_interval *
+							((recv->nblocks+1)/iso->buf_packets);
 		if (recv->block_irq_interval*4 > recv->nblocks)
 			recv->block_irq_interval = recv->nblocks/4;
 		if (recv->block_irq_interval < 1)
@@ -1205,6 +1209,10 @@ static int ohci_iso_recv_init(struct hps
 		int max_packet_size;
 
 		recv->nblocks = iso->buf_packets;
+		recv->block_irq_interval = iso->irq_interval;
+		if (recv->block_irq_interval * 4 > iso->buf_packets)
+			recv->block_irq_interval = iso->buf_packets / 4;
+		if (recv->block_irq_interval < 1)
 		recv->block_irq_interval = 1;
 
 		/* choose a buffer stride */
@@ -3271,7 +3279,6 @@ do {						\
 static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
 					const struct pci_device_id *ent)
 {
-	static unsigned int card_id_counter = 0;
 	static int version_printed = 0;
 
 	struct hpsb_host *host;
@@ -3282,15 +3289,14 @@ static int __devinit ohci1394_pci_probe(
 		PRINT_G(KERN_INFO, "%s", version);
 
         if (pci_enable_device(dev))
-		FAIL(-ENXIO, "Failed to enable OHCI hardware %d",
-		        card_id_counter++);
+		FAIL(-ENXIO, "Failed to enable OHCI hardware");
         pci_set_master(dev);
 
-	host = hpsb_alloc_host(&ohci1394_driver, sizeof(struct ti_ohci));
+	host = hpsb_alloc_host(&ohci1394_driver, sizeof(struct ti_ohci), &dev->dev);
 	if (!host) FAIL(-ENOMEM, "Failed to allocate host structure");
 
 	ohci = host->hostdata;
-	ohci->id = card_id_counter++;
+	ohci->id = host->id;
 	ohci->dev = dev;
 	ohci->host = host;
 	ohci->init_state = OHCI_INIT_ALLOC_HOST;
@@ -3462,11 +3468,14 @@ static int __devinit ohci1394_pci_probe(
 static void ohci1394_pci_remove(struct pci_dev *pdev)
 {
 	struct ti_ohci *ohci;
+	struct device *dev;
 
 	ohci = pci_get_drvdata(pdev);
 	if (!ohci)
 		return;
 
+	dev = get_device(&ohci->host->device);
+
 	switch (ohci->init_state) {
 	case OHCI_INIT_DONE:
 		hpsb_remove_host(ohci->host);
@@ -3489,7 +3498,7 @@ static void ohci1394_pci_remove(struct p
 
 		/* Disable IRM Contender */
 		set_phy_reg(ohci, 4, ~0xc0 & get_phy_reg(ohci, 4));
-		
+
 		/* Clear link control register */
 		reg_write(ohci, OHCI1394_LinkControlClear, 0xffffffff);
 
@@ -3521,7 +3530,7 @@ static void ohci1394_pci_remove(struct p
 				    ohci->selfid_buf_cpu,
 				    ohci->selfid_buf_bus);
 		OHCI_DMA_FREE("consistent selfid_buf");
-		
+
 	case OHCI_INIT_HAVE_CONFIG_ROM_BUFFER:
 		pci_free_consistent(ohci->dev, OHCI_CONFIG_ROM_LEN,
 				    ohci->csr_config_rom_cpu,
@@ -3555,8 +3564,10 @@ static void ohci1394_pci_remove(struct p
 
 	case OHCI_INIT_ALLOC_HOST:
 		pci_set_drvdata(ohci->dev, NULL);
-		hpsb_unref_host(ohci->host);
 	}
+
+	if (dev)
+		put_device(dev);
 }
 
 
diff -puN drivers/ieee1394/oui.db~ieee1394-update drivers/ieee1394/oui.db
--- 25/drivers/ieee1394/oui.db~ieee1394-update	2003-12-24 10:25:54.000000000 -0800
+++ 25-akpm/drivers/ieee1394/oui.db	2003-12-24 10:25:54.000000000 -0800
@@ -1612,7 +1612,7 @@
 000658 Helmut Fischer GmbH & Co. KG
 000659 EAL (Apeldoorn) B.V.
 00065A Strix Systems
-00065B Dell Inc.
+00065B Dell Computer Corp.
 00065C Malachite Technologies, Inc.
 00065D Heidelberg Web Systems
 00065E Photuris, Inc.
@@ -3965,7 +3965,7 @@
 00B0C2 Cisco Systems, Inc.
 00B0C7 Tellabs Operations, Inc.
 00B0CE TECHNOLOGY RESCUE
-00B0D0 Dell Inc.
+00B0D0 Dell Computer Corp.
 00B0DB Nextcell, Inc.
 00B0DF Reliable Data Technology, Inc.
 00B0E7 British Federal Ltd.
@@ -4054,7 +4054,7 @@
 00C04C DEPARTMENT OF FOREIGN AFFAIRS
 00C04D MITEC, INC.
 00C04E COMTROL CORPORATION
-00C04F Dell Inc.
+00C04F DELL COMPUTER CORPORATION
 00C050 TOYO DENKI SEIZO K.K.
 00C051 ADVANCED INTEGRATION RESEARCH
 00C052 BURR-BROWN
diff -puN drivers/ieee1394/pcilynx.c~ieee1394-update drivers/ieee1394/pcilynx.c
--- 25/drivers/ieee1394/pcilynx.c~ieee1394-update	2003-12-24 10:25:54.000000000 -0800
+++ 25-akpm/drivers/ieee1394/pcilynx.c	2003-12-24 10:25:54.000000000 -0800
@@ -521,10 +521,6 @@ static void send_next(struct ti_lynx *ly
                 break;
         }                
 
-        if (!packet->data_be) {
-                pcl.buffer[1].control |= PCL_BIGENDIAN;
-        }
-
         put_pcl(lynx, d->pcl, &pcl);
         run_pcl(lynx, d->pcl_start, d->channel);
 }
@@ -540,7 +536,7 @@ static int lynx_transmit(struct hpsb_hos
         if (packet->data_size >= 4096) {
                 PRINT(KERN_ERR, lynx->id, "transmit packet data too big (%Zd)",
                       packet->data_size);
-                return 0;
+                return -EOVERFLOW;
         }
 
         switch (packet->type) {
@@ -554,7 +550,7 @@ static int lynx_transmit(struct hpsb_hos
         default:
                 PRINT(KERN_ERR, lynx->id, "invalid packet type %d",
                       packet->type);
-                return 0;
+                return -EINVAL;
         }
 
         if (packet->tcode == TCODE_WRITEQ
@@ -570,7 +566,7 @@ static int lynx_transmit(struct hpsb_hos
 
         spin_unlock_irqrestore(&d->queue_lock, flags);
 
-        return 1;
+        return 0;
 }
 
 
@@ -1120,7 +1116,7 @@ static ssize_t mem_read(struct file *fil
         retval = copy_to_user(buffer, md->lynx->mem_dma_buffer, count);
         up(&md->lynx->mem_dma_mutex);
 
-        if (retval < 0) return retval;
+	if (retval) return -EFAULT;
         *offset += count;
         return count;
 }
@@ -1141,14 +1137,17 @@ static ssize_t mem_write(struct file *fi
         /* FIXME: dereferencing pointers to PCI mem doesn't work everywhere */
         switch (md->type) {
         case aux:
-                copy_from_user(md->lynx->aux_port+(*offset), buffer, count);
+		if (copy_from_user(md->lynx->aux_port+(*offset), buffer, count))
+			return -EFAULT;
                 break;
         case ram:
-                copy_from_user(md->lynx->local_ram+(*offset), buffer, count);
+		if (copy_from_user(md->lynx->local_ram+(*offset), buffer, count))
+			return -EFAULT;
                 break;
         case rom:
                 /* the ROM may be writeable */
-                copy_from_user(md->lynx->local_rom+(*offset), buffer, count);
+		if (copy_from_user(md->lynx->local_rom+(*offset), buffer, count))
+			return -EFAULT;
                 break;
         }
 
@@ -1443,12 +1442,15 @@ static void iso_rcv_bh(struct ti_lynx *l
 static void remove_card(struct pci_dev *dev)
 {
         struct ti_lynx *lynx;
+	struct device *lynx_dev;
         int i;
 
         lynx = pci_get_drvdata(dev);
         if (!lynx) return;
         pci_set_drvdata(dev, NULL);
 
+	lynx_dev = get_device(&lynx->host->device);
+
         switch (lynx->state) {
         case is_host:
                 reg_write(lynx, PCI_INT_ENABLE, 0);
@@ -1498,7 +1500,9 @@ static void remove_card(struct pci_dev *
         }
 
 	tasklet_kill(&lynx->iso_rcv.tq);
-	hpsb_unref_host(lynx->host);
+
+	if (lynx_dev)
+		put_device(lynx_dev);
 }
 
 
@@ -1535,7 +1539,7 @@ static int __devinit add_card(struct pci
 
         error = -ENOMEM;
 
-	host = hpsb_alloc_host(&lynx_driver, sizeof(struct ti_lynx));
+	host = hpsb_alloc_host(&lynx_driver, sizeof(struct ti_lynx), &dev->dev);
         if (!host) FAIL("failed to allocate control structure memory");
 
         lynx = host->hostdata;
diff -puN drivers/ieee1394/raw1394.c~ieee1394-update drivers/ieee1394/raw1394.c
--- 25/drivers/ieee1394/raw1394.c~ieee1394-update	2003-12-24 10:25:54.000000000 -0800
+++ 25-akpm/drivers/ieee1394/raw1394.c	2003-12-24 10:25:54.000000000 -0800
@@ -128,7 +128,7 @@ static void free_pending_request(struct 
         } else if (req->free_data) {
                 kfree(req->data);
         }
-        free_hpsb_packet(req->packet);
+        hpsb_free_packet(req->packet);
         kfree(req);
 }
 
@@ -558,7 +558,7 @@ static int state_initialized(struct file
                                 lh = lh->next;
                         }
                         hi = list_entry(lh, struct host_info, list);
-                        hpsb_ref_host(hi->host); // XXX Need to handle failure case
+			get_device(&hi->host->device); // XXX Need to handle failure case
                         list_add_tail(&fi->list, &hi->file_info_list);
                         fi->host = hi->host;
                         fi->state = connected;
@@ -782,7 +782,7 @@ static int handle_async_request(struct f
 
 	packet->generation = req->req.generation;
 
-        if (!hpsb_send_packet(packet)) {
+        if (hpsb_send_packet(packet) < 0) {
                 req->req.error = RAW1394_ERROR_SEND_ERROR;
                 req->req.length = 0;
                 hpsb_free_tlabel(packet);
@@ -823,7 +823,7 @@ static int handle_iso_send(struct file_i
 	/* Update the generation of the packet just before sending. */
 	packet->generation = req->req.generation;
 
-        if (!hpsb_send_packet(packet)) {
+        if (hpsb_send_packet(packet) < 0) {
                 req->req.error = RAW1394_ERROR_SEND_ERROR;
                 queue_complete_req(req);
         }
@@ -846,7 +846,7 @@ static int handle_async_send(struct file
                 return sizeof(struct raw1394_request);
         } 
 
-        packet = alloc_hpsb_packet(req->req.length-header_length);
+        packet = hpsb_alloc_packet(req->req.length-header_length);
         req->packet = packet;
         if (!packet) return -ENOMEM;
 
@@ -885,7 +885,7 @@ static int handle_async_send(struct file
         /* Update the generation of the packet just before sending. */
         packet->generation = req->req.generation;
 
-        if (!hpsb_send_packet(packet)) {
+        if (hpsb_send_packet(packet) < 0) {
                 req->req.error = RAW1394_ERROR_SEND_ERROR;
                 queue_complete_req(req);
         }
@@ -1797,6 +1797,106 @@ static int arm_unregister(struct file_in
         return sizeof(struct raw1394_request);
 }
 
+/* Copy data from ARM buffer(s) to user buffer. */
+static int arm_get_buf(struct file_info *fi, struct pending_request *req)
+{
+	struct arm_addr  *arm_addr = NULL;
+	unsigned long flags;
+	unsigned long offset;
+
+	struct list_head *entry;
+
+	DBGMSG("arm_get_buf "
+	       "addr(Offset): %04X %08X length: %u",
+	       (u32) ((req->req.address >> 32) & 0xFFFF),
+	       (u32) (req->req.address & 0xFFFFFFFF),
+	       (u32) req->req.length);
+
+	spin_lock_irqsave(&host_info_lock, flags);
+	entry = fi->addr_list.next;
+	while (entry != &(fi->addr_list)) {
+		arm_addr = list_entry(entry, struct arm_addr, addr_list);
+		if ((arm_addr->start <= req->req.address) &&
+		    (arm_addr->end > req->req.address)) {
+			if (req->req.address + req->req.length <= arm_addr->end) {
+				offset = req->req.address - arm_addr->start;
+
+				DBGMSG("arm_get_buf copy_to_user( %08X, %08X, %u )",
+				       (u32) req->req.recvb,
+				       (u32) (arm_addr->addr_space_buffer+offset),
+				       (u32) req->req.length);
+
+				if (copy_to_user(int2ptr(req->req.recvb), arm_addr->addr_space_buffer+offset, req->req.length)) {
+					spin_unlock_irqrestore(&host_info_lock, flags);
+					return (-EFAULT);
+				}
+
+				spin_unlock_irqrestore(&host_info_lock, flags);
+				free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
+				return sizeof(struct raw1394_request);
+			} else {
+				DBGMSG("arm_get_buf request exceeded mapping");
+				spin_unlock_irqrestore(&host_info_lock, flags);
+				return (-EINVAL);
+			}
+		}
+		entry = entry->next;
+	}
+	spin_unlock_irqrestore(&host_info_lock, flags);
+	return (-EINVAL);
+}
+
+
+/* Copy data from user buffer to ARM buffer(s). */
+static int arm_set_buf(struct file_info *fi, struct pending_request *req)
+{
+	struct arm_addr  *arm_addr = NULL;
+	unsigned long flags;
+	unsigned long offset;
+
+	struct list_head *entry;
+
+	DBGMSG("arm_set_buf "
+	       "addr(Offset): %04X %08X length: %u",
+	       (u32) ((req->req.address >> 32) & 0xFFFF),
+	       (u32) (req->req.address & 0xFFFFFFFF),
+	       (u32) req->req.length);
+
+
+	spin_lock_irqsave(&host_info_lock, flags);
+	entry = fi->addr_list.next;
+	while (entry != &(fi->addr_list)) {
+		arm_addr = list_entry(entry, struct arm_addr, addr_list);
+		if ((arm_addr->start <= req->req.address) &&
+		    (arm_addr->end > req->req.address)) {
+			if (req->req.address + req->req.length <= arm_addr->end) {
+				offset = req->req.address - arm_addr->start;
+
+				DBGMSG("arm_set_buf copy_from_user( %08X, %08X, %u )",
+				       (u32) (arm_addr->addr_space_buffer+offset),
+				       (u32) req->req.sendb,
+				       (u32) req->req.length);
+
+				if (copy_from_user(arm_addr->addr_space_buffer+offset, int2ptr(req->req.sendb), req->req.length)) {
+					spin_unlock_irqrestore(&host_info_lock, flags);
+					return (-EFAULT);
+				}
+
+				spin_unlock_irqrestore(&host_info_lock, flags);
+				free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
+				return sizeof(struct raw1394_request);
+			} else {
+				DBGMSG("arm_set_buf request exceeded mapping");
+				spin_unlock_irqrestore(&host_info_lock, flags);
+				return (-EINVAL);
+			}
+		}
+		entry = entry->next;
+	}
+	spin_unlock_irqrestore(&host_info_lock, flags);
+	return (-EINVAL);
+}
+
 static int reset_notification(struct file_info *fi, struct pending_request *req)
 {
         DBGMSG("reset_notification called - switch %s ",
@@ -1829,9 +1929,8 @@ static int write_phypacket(struct file_i
         spin_unlock_irq(&fi->reqlists_lock);
         packet->generation = req->req.generation;
         retval = hpsb_send_packet(packet);
-        DBGMSG("write_phypacket send_packet called => retval: %d ",
-                retval);
-        if (! retval) {
+        DBGMSG("write_phypacket send_packet called => retval: %d ", retval);
+        if (retval < 0) {
                 req->req.error = RAW1394_ERROR_SEND_ERROR;
                 req->req.length = 0;
                 queue_complete_req(req);
@@ -1912,6 +2011,12 @@ static int state_connected(struct file_i
         case RAW1394_REQ_ARM_UNREGISTER:
                 return arm_unregister(fi, req);
 
+        case RAW1394_REQ_ARM_SET_BUF:
+                return arm_set_buf(fi, req);
+
+        case RAW1394_REQ_ARM_GET_BUF:
+                return arm_get_buf(fi, req);
+
         case RAW1394_REQ_RESET_NOTIFY:
                 return reset_notification(fi, req);
 
@@ -2137,6 +2242,7 @@ static int raw1394_iso_recv_init(struct 
 					    stat.config.data_buf_size,
 					    stat.config.buf_packets,
 					    stat.config.channel,
+ 					    stat.config.dma_mode,
 					    stat.config.irq_interval,
 					    rawiso_activity_cb);
 	if (!fi->iso_handle)
@@ -2489,7 +2595,7 @@ static int raw1394_release(struct inode 
                 list_del(&fi->list);
                 spin_unlock_irq(&host_info_lock);
 
-                hpsb_unref_host(fi->host);
+		put_device(&fi->host->device);
         }
 
         kfree(fi);
diff -puN drivers/ieee1394/raw1394.h~ieee1394-update drivers/ieee1394/raw1394.h
--- 25/drivers/ieee1394/raw1394.h~ieee1394-update	2003-12-24 10:25:54.000000000 -0800
+++ 25-akpm/drivers/ieee1394/raw1394.h	2003-12-24 10:25:54.000000000 -0800
@@ -30,6 +30,8 @@
 
 #define RAW1394_REQ_ARM_REGISTER    300
 #define RAW1394_REQ_ARM_UNREGISTER  301
+#define RAW1394_REQ_ARM_SET_BUF     302
+#define RAW1394_REQ_ARM_GET_BUF     303
 
 #define RAW1394_REQ_RESET_NOTIFY    400
 
@@ -149,6 +151,9 @@ struct raw1394_iso_config {
 	/* xmit only - iso transmission speed */
 	__u8 speed;
 
+	/* The mode of the dma when receiving iso data. Must be supported by chip */
+	__u8 dma_mode;
+
 	/* max. latency of buffer, in packets (-1 if you don't care) */
 	__s32 irq_interval;
 };
diff -puN drivers/ieee1394/sbp2.c~ieee1394-update drivers/ieee1394/sbp2.c
--- 25/drivers/ieee1394/sbp2.c~ieee1394-update	2003-12-24 10:25:54.000000000 -0800
+++ 25-akpm/drivers/ieee1394/sbp2.c	2003-12-24 10:25:54.000000000 -0800
@@ -77,7 +77,7 @@
 #include "sbp2.h"
 
 static char version[] __devinitdata =
-	"$Rev: 1034 $ Ben Collins <bcollins@debian.org>";
+	"$Rev: 1082 $ Ben Collins <bcollins@debian.org>";
 
 /*
  * Module load parameter definitions
@@ -361,38 +361,34 @@ static int sbp2util_down_timeout(atomic_
 static void sbp2_free_packet(struct hpsb_packet *packet)
 {
 	hpsb_free_tlabel(packet);
-	free_hpsb_packet(packet);
+	hpsb_free_packet(packet);
 }
 
-/*
- * This function is called to retrieve a block write packet from our
- * packet pool. This function is used in place of calling
- * alloc_hpsb_packet (which costs us three kmallocs). Instead we just pull
- * out a free request packet and re-initialize values in it. I'm sure this
- * can still stand some more optimization.
+/* This is much like hpsb_node_write(), except it ignores the response
+ * subaction and returns immediately. Can be used from interrupts.
  */
-static struct hpsb_packet *
-sbp2util_allocate_write_packet(struct sbp2scsi_host_info *hi,
-			       struct node_entry *ne, u64 addr,
-			       size_t data_size,
-			       quadlet_t *data)
+int sbp2util_node_write_no_wait(struct node_entry *ne, u64 addr,
+				quadlet_t *buffer, size_t length)
 {
 	struct hpsb_packet *packet;
 
-	packet = hpsb_make_writepacket(hi->host, ne->nodeid,
-				       addr, data, data_size);
-
+	packet = hpsb_make_writepacket(ne->host, ne->nodeid,
+				       addr, buffer, length);
         if (!packet)
-                return NULL;
+                return -ENOMEM;
 
 	hpsb_set_packet_complete_task(packet, (void (*)(void*))sbp2_free_packet,
 				      packet);
 
 	hpsb_node_fill_packet(ne, packet);
 
-	return packet;
-}
+        if (hpsb_send_packet(packet) < 0) {
+		sbp2_free_packet(packet);
+		return -EIO;
+	}
 
+	return 0;
+}
 
 /*
  * This function is called to create a pool of command orbs used for
@@ -1734,35 +1730,26 @@ static int sbp2_max_speed_and_size(struc
  */
 static int sbp2_agent_reset(struct scsi_id_instance_data *scsi_id, int wait) 
 {
-	struct sbp2scsi_host_info *hi = scsi_id->hi;
-	struct hpsb_packet *packet;
 	quadlet_t data;
-	
+	u64 addr;
+	int retval;
+
 	SBP2_DEBUG("sbp2_agent_reset");
 
 	/*
 	 * Ok, let's write to the target's management agent register
 	 */
 	data = ntohl(SBP2_AGENT_RESET_DATA);
-	packet = sbp2util_allocate_write_packet(hi, scsi_id->ne,
-						scsi_id->sbp2_command_block_agent_addr +
-						SBP2_AGENT_RESET_OFFSET,
-						4, &data);
-
-	if (!packet) {
-		SBP2_ERR("sbp2util_allocate_write_packet failed");
-		return(-ENOMEM);
-	}
+	addr = scsi_id->sbp2_command_block_agent_addr + SBP2_AGENT_RESET_OFFSET;
 
-	if (!hpsb_send_packet(packet)) {
-		SBP2_ERR("hpsb_send_packet failed");
-		sbp2_free_packet(packet); 
-		return(-EIO);
-	}
+	if (wait)
+		retval = hpsb_node_write(scsi_id->ne, addr, &data, 4);
+	else
+		retval = sbp2util_node_write_no_wait(scsi_id->ne, addr, &data, 4);
 
-	if (wait) {
-		down(&packet->state_change);
-		down(&packet->state_change);
+	if (retval < 0) {
+		SBP2_ERR("hpsb_node_write failed.\n");
+		return -EIO;
 	}
 
 	/*
@@ -2032,8 +2019,9 @@ static int sbp2_link_orb_command(struct 
 				 struct sbp2_command_info *command)
 {
 	struct sbp2scsi_host_info *hi = scsi_id->hi;
-        struct hpsb_packet *packet;
 	struct sbp2_command_orb *command_orb = &command->command_orb;
+	struct node_entry *ne = scsi_id->ne;
+	u64 addr;
 
 	outstanding_orb_incr;
 	SBP2_ORB_DEBUG("sending command orb %p, total orbs = %x",
@@ -2049,40 +2037,30 @@ static int sbp2_link_orb_command(struct 
 	 * Check to see if there are any previous orbs to use
 	 */
 	if (scsi_id->last_orb == NULL) {
-	
+		quadlet_t data[2];
+
 		/*
 		 * Ok, let's write to the target's management agent register
 		 */
-		if (hpsb_node_entry_valid(scsi_id->ne)) {
-
-			packet = sbp2util_allocate_write_packet(hi, scsi_id->ne,
-								scsi_id->sbp2_command_block_agent_addr +
-								SBP2_ORB_POINTER_OFFSET, 8, NULL);
-		
-			if (!packet) {
-				SBP2_ERR("sbp2util_allocate_write_packet failed");
-				return(-ENOMEM);
-			}
-		
-			packet->data[0] = ORB_SET_NODE_ID(hi->host->node_id);
-			packet->data[1] = command->command_orb_dma;
-			sbp2util_cpu_to_be32_buffer(packet->data, 8);
-		
-			SBP2_ORB_DEBUG("write command agent, command orb %p", command_orb);
+		addr = scsi_id->sbp2_command_block_agent_addr + SBP2_ORB_POINTER_OFFSET;
+		data[0] = ORB_SET_NODE_ID(hi->host->node_id);
+		data[1] = command->command_orb_dma;
+		sbp2util_cpu_to_be32_buffer(data, 8);
 
-			if (!hpsb_send_packet(packet)) {
-				SBP2_ERR("hpsb_send_packet failed");
-				sbp2_free_packet(packet); 
-				return(-EIO);
-			}
+		SBP2_ORB_DEBUG("write command agent, command orb %p", command_orb);
 
-			SBP2_ORB_DEBUG("write command agent complete");
+		if (sbp2util_node_write_no_wait(ne, addr, data, 8) < 0) {
+			SBP2_ERR("sbp2util_node_write_no_wait failed.\n");
+			return -EIO;
 		}
 
+		SBP2_ORB_DEBUG("write command agent complete");
+
 		scsi_id->last_orb = command_orb;
 		scsi_id->last_orb_dma = command->command_orb_dma;
 
 	} else {
+		quadlet_t data;
 
 		/*
 		 * We have an orb already sent (maybe or maybe not
@@ -2102,25 +2080,14 @@ static int sbp2_link_orb_command(struct 
 		/*
 		 * Ring the doorbell
 		 */
-		if (hpsb_node_entry_valid(scsi_id->ne)) {
-			quadlet_t data = cpu_to_be32(command->command_orb_dma);
+		data = cpu_to_be32(command->command_orb_dma);
+		addr = scsi_id->sbp2_command_block_agent_addr + SBP2_DOORBELL_OFFSET;
 
-			packet = sbp2util_allocate_write_packet(hi, scsi_id->ne,
-					scsi_id->sbp2_command_block_agent_addr +
-					SBP2_DOORBELL_OFFSET, 4, &data);
-	
-			if (!packet) {
-				SBP2_ERR("sbp2util_allocate_write_packet failed");
-				return(-ENOMEM);
-			}
+		SBP2_ORB_DEBUG("ring doorbell, command orb %p", command_orb);
 
-			SBP2_ORB_DEBUG("ring doorbell, command orb %p", command_orb);
-
-			if (!hpsb_send_packet(packet)) {
-				SBP2_ERR("hpsb_send_packet failed");
-				sbp2_free_packet(packet);
-				return(-EIO);
-			}
+		if (sbp2util_node_write_no_wait(ne, addr, &data, 4) < 0) {
+			SBP2_ERR("sbp2util_node_write_no_wait failed");
+			return(-EIO);
 		}
 
 		scsi_id->last_orb = command_orb;

_