Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6: (31 commits)
  firewire: fw-sbp2: fix DMA mapping of management ORBs
  firewire: fw-sbp2: fix DMA mapping of command ORBs
  firewire: fw-sbp2: fix DMA mapping of S/G tables
  firewire: fw-sbp2: add a boundary check
  firewire: fw-sbp2: correctly align page tables
  firewire: fw-sbp2: memset wants string.h
  firewire: fw-sbp2: use correct speed in sbp2_agent_reset
  firewire: fw-sbp2: correctly dereference by container_of
  firewire: Document userspace ioctl interface.
  firewire: fw-sbp2: implement nonexclusive login
  firewire: fw-sbp2: let SCSI shutdown commands through before logout
  firewire: fw-sbp2: implement max sectors limit for some old bridges
  firewire: simplify a struct type
  firewire: support S100B...S400B and link slower than PHY
  firewire: optimize gap count with 1394b leaf nodes
  firewire: remove unused macro
  firewire: missing newline in printk
  firewire: fw-sbp2: remove unused struct member
  ieee1394: remove old isochronous ABI
  ieee1394: sbp2: change some module parameters from int to bool
  ...
diff --git a/Documentation/ABI/removed/raw1394_legacy_isochronous b/Documentation/ABI/removed/raw1394_legacy_isochronous
new file mode 100644
index 0000000..1b62962
--- /dev/null
+++ b/Documentation/ABI/removed/raw1394_legacy_isochronous
@@ -0,0 +1,16 @@
+What:		legacy isochronous ABI of raw1394 (1st generation iso ABI)
+Date:		June 2007 (scheduled), removed in kernel v2.6.23
+Contact:	linux1394-devel@lists.sourceforge.net
+Description:
+	The two request types RAW1394_REQ_ISO_SEND, RAW1394_REQ_ISO_LISTEN have
+	been deprecated for quite some time.  They are very inefficient as they
+	come with high interrupt load and several layers of callbacks for each
+	packet.  Because of these deficiencies, the video1394 and dv1394 drivers
+	and the 3rd-generation isochronous ABI in raw1394 (rawiso) were created.
+
+Users:
+	libraw1394 users via the long deprecated API raw1394_iso_write,
+	raw1394_start_iso_write, raw1394_start_iso_rcv, raw1394_stop_iso_rcv
+
+	libdc1394, which optionally uses these old libraw1394 calls
+	alternatively to the more efficient video1394 ABI
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 7d3f205..51b369e 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -49,16 +49,6 @@
 
 ---------------------------
 
-What:	raw1394: requests of type RAW1394_REQ_ISO_SEND, RAW1394_REQ_ISO_LISTEN
-When:	June 2007
-Why:	Deprecated in favour of the more efficient and robust rawiso interface.
-	Affected are applications which use the deprecated part of libraw1394
-	(raw1394_iso_write, raw1394_start_iso_write, raw1394_start_iso_rcv,
-	raw1394_stop_iso_rcv) or bypass	libraw1394.
-Who:	Dan Dennedy <dan@dennedy.org>, Stefan Richter <stefanr@s5r6.in-berlin.de>
-
----------------------------
-
 What:	old NCR53C9x driver
 When:	October 2007
 Why:	Replaced by the much better esp_scsi driver.  Actual low-level
diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c
index 9eb1eda..0aeab32 100644
--- a/drivers/firewire/fw-card.c
+++ b/drivers/firewire/fw-card.c
@@ -336,8 +336,11 @@
 	}
 
  pick_me:
-	/* Now figure out what gap count to set. */
-	if (card->topology_type == FW_TOPOLOGY_A &&
+	/*
+	 * Pick a gap count from 1394a table E-1.  The table doesn't cover
+	 * the typically much larger 1394b beta repeater delays though.
+	 */
+	if (!card->beta_repeaters_present &&
 	    card->root_node->max_hops < ARRAY_SIZE(gap_count_table))
 		gap_count = gap_count_table[card->root_node->max_hops];
 	else
diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c
index dbb7642..7538864 100644
--- a/drivers/firewire/fw-cdev.c
+++ b/drivers/firewire/fw-cdev.c
@@ -397,7 +397,7 @@
 			request->tcode & 0x1f,
 			device->node->node_id,
 			request->generation,
-			device->node->max_speed,
+			device->max_speed,
 			request->offset,
 			response->response.data, request->length,
 			complete_transaction, response);
diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c
index c1ce465..2b65863 100644
--- a/drivers/firewire/fw-device.c
+++ b/drivers/firewire/fw-device.c
@@ -401,8 +401,7 @@
 
 	offset = 0xfffff0000400ULL + index * 4;
 	fw_send_request(device->card, &t, TCODE_READ_QUADLET_REQUEST,
-			device->node_id,
-			device->generation, SCODE_100,
+			device->node_id, device->generation, device->max_speed,
 			offset, NULL, 4, complete_transaction, &callback_data);
 
 	wait_for_completion(&callback_data.done);
@@ -418,6 +417,8 @@
 	u32 stack[16], sp, key;
 	int i, end, length;
 
+	device->max_speed = SCODE_100;
+
 	/* First read the bus info block. */
 	for (i = 0; i < 5; i++) {
 		if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE)
@@ -434,6 +435,33 @@
 			return -1;
 	}
 
+	device->max_speed = device->node->max_speed;
+
+	/*
+	 * Determine the speed of
+	 *   - devices with link speed less than PHY speed,
+	 *   - devices with 1394b PHY (unless only connected to 1394a PHYs),
+	 *   - all devices if there are 1394b repeaters.
+	 * Note, we cannot use the bus info block's link_spd as starting point
+	 * because some buggy firmwares set it lower than necessary and because
+	 * 1394-1995 nodes do not have the field.
+	 */
+	if ((rom[2] & 0x7) < device->max_speed ||
+	    device->max_speed == SCODE_BETA ||
+	    device->card->beta_repeaters_present) {
+		u32 dummy;
+
+		/* for S1600 and S3200 */
+		if (device->max_speed == SCODE_BETA)
+			device->max_speed = device->card->link_speed;
+
+		while (device->max_speed > SCODE_100) {
+			if (read_rom(device, 0, &dummy) == RCODE_COMPLETE)
+				break;
+			device->max_speed--;
+		}
+	}
+
 	/*
 	 * Now parse the config rom.  The config rom is a recursive
 	 * directory structure so we parse it using a stack of
@@ -680,8 +708,10 @@
 		    FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN)
 		fw_device_shutdown(&device->work.work);
 	else
-		fw_notify("created new fw device %s (%d config rom retries)\n",
-			  device->device.bus_id, device->config_rom_retries);
+		fw_notify("created new fw device %s "
+			  "(%d config rom retries, S%d00)\n",
+			  device->device.bus_id, device->config_rom_retries,
+			  1 << device->max_speed);
 
 	/*
 	 * Reschedule the IRM work if we just finished reading the
diff --git a/drivers/firewire/fw-device.h b/drivers/firewire/fw-device.h
index af1723e..d13e6a6 100644
--- a/drivers/firewire/fw-device.h
+++ b/drivers/firewire/fw-device.h
@@ -40,6 +40,7 @@
 	struct fw_node *node;
 	int node_id;
 	int generation;
+	unsigned max_speed;
 	struct fw_card *card;
 	struct device device;
 	struct list_head link;
diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c
index 96c8ac5..41476ab 100644
--- a/drivers/firewire/fw-ohci.c
+++ b/drivers/firewire/fw-ohci.c
@@ -1934,12 +1934,12 @@
 	free_irq(pdev->irq, ohci);
 	err = pci_save_state(pdev);
 	if (err) {
-		fw_error("pci_save_state failed with %d", err);
+		fw_error("pci_save_state failed\n");
 		return err;
 	}
 	err = pci_set_power_state(pdev, pci_choose_state(pdev, state));
 	if (err) {
-		fw_error("pci_set_power_state failed with %d", err);
+		fw_error("pci_set_power_state failed\n");
 		return err;
 	}
 
@@ -1955,7 +1955,7 @@
 	pci_restore_state(pdev);
 	err = pci_enable_device(pdev);
 	if (err) {
-		fw_error("pci_enable_device failed with %d", err);
+		fw_error("pci_enable_device failed\n");
 		return err;
 	}
 
diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c
index a98d391..7c53be0 100644
--- a/drivers/firewire/fw-sbp2.c
+++ b/drivers/firewire/fw-sbp2.c
@@ -30,10 +30,13 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/mod_devicetable.h>
 #include <linux/device.h>
 #include <linux/scatterlist.h>
 #include <linux/dma-mapping.h>
+#include <linux/blkdev.h>
+#include <linux/string.h>
 #include <linux/timer.h>
 
 #include <scsi/scsi.h>
@@ -46,6 +49,18 @@
 #include "fw-topology.h"
 #include "fw-device.h"
 
+/*
+ * So far only bridges from Oxford Semiconductor are known to support
+ * concurrent logins. Depending on firmware, four or two concurrent logins
+ * are possible on OXFW911 and newer Oxsemi bridges.
+ *
+ * Concurrent logins are useful together with cluster filesystems.
+ */
+static int sbp2_param_exclusive_login = 1;
+module_param_named(exclusive_login, sbp2_param_exclusive_login, bool, 0644);
+MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device "
+		 "(default = Y, use N for concurrent initiators)");
+
 /* I don't know why the SCSI stack doesn't define something like this... */
 typedef void (*scsi_done_fn_t)(struct scsi_cmnd *);
 
@@ -154,7 +169,7 @@
 #define MANAGEMENT_ORB_LUN(v)			((v))
 #define MANAGEMENT_ORB_FUNCTION(v)		((v) << 16)
 #define MANAGEMENT_ORB_RECONNECT(v)		((v) << 20)
-#define MANAGEMENT_ORB_EXCLUSIVE		((1) << 28)
+#define MANAGEMENT_ORB_EXCLUSIVE(v)		((v) ? 1 << 28 : 0)
 #define MANAGEMENT_ORB_REQUEST_FORMAT(v)	((v) << 29)
 #define MANAGEMENT_ORB_NOTIFY			((1) << 31)
 
@@ -205,9 +220,8 @@
 	scsi_done_fn_t done;
 	struct fw_unit *unit;
 
-	struct sbp2_pointer page_table[SG_ALL];
+	struct sbp2_pointer page_table[SG_ALL] __attribute__((aligned(8)));
 	dma_addr_t page_table_bus;
-	dma_addr_t request_buffer_bus;
 };
 
 /*
@@ -347,8 +361,7 @@
 	spin_unlock_irqrestore(&device->card->lock, flags);
 
 	fw_send_request(device->card, &orb->t, TCODE_WRITE_BLOCK_REQUEST,
-			node_id, generation,
-			device->node->max_speed, offset,
+			node_id, generation, device->max_speed, offset,
 			&orb->pointer, sizeof(orb->pointer),
 			complete_transaction, orb);
 }
@@ -383,7 +396,7 @@
 complete_management_orb(struct sbp2_orb *base_orb, struct sbp2_status *status)
 {
 	struct sbp2_management_orb *orb =
-	    (struct sbp2_management_orb *)base_orb;
+		container_of(base_orb, struct sbp2_management_orb, base);
 
 	if (status)
 		memcpy(&orb->status, status, sizeof(*status));
@@ -403,21 +416,11 @@
 	if (orb == NULL)
 		return -ENOMEM;
 
-	/*
-	 * The sbp2 device is going to send a block read request to
-	 * read out the request from host memory, so map it for dma.
-	 */
-	orb->base.request_bus =
-		dma_map_single(device->card->device, &orb->request,
-			       sizeof(orb->request), DMA_TO_DEVICE);
-	if (dma_mapping_error(orb->base.request_bus))
-		goto out;
-
 	orb->response_bus =
 		dma_map_single(device->card->device, &orb->response,
 			       sizeof(orb->response), DMA_FROM_DEVICE);
 	if (dma_mapping_error(orb->response_bus))
-		goto out;
+		goto fail_mapping_response;
 
 	orb->request.response.high    = 0;
 	orb->request.response.low     = orb->response_bus;
@@ -432,14 +435,9 @@
 	orb->request.status_fifo.high = sd->address_handler.offset >> 32;
 	orb->request.status_fifo.low  = sd->address_handler.offset;
 
-	/*
-	 * FIXME: Yeah, ok this isn't elegant, we hardwire exclusive
-	 * login and 1 second reconnect time.  The reconnect setting
-	 * is probably fine, but the exclusive login should be an option.
-	 */
 	if (function == SBP2_LOGIN_REQUEST) {
 		orb->request.misc |=
-			MANAGEMENT_ORB_EXCLUSIVE |
+			MANAGEMENT_ORB_EXCLUSIVE(sbp2_param_exclusive_login) |
 			MANAGEMENT_ORB_RECONNECT(0);
 	}
 
@@ -448,6 +446,12 @@
 	init_completion(&orb->done);
 	orb->base.callback = complete_management_orb;
 
+	orb->base.request_bus =
+		dma_map_single(device->card->device, &orb->request,
+			       sizeof(orb->request), DMA_TO_DEVICE);
+	if (dma_mapping_error(orb->base.request_bus))
+		goto fail_mapping_request;
+
 	sbp2_send_orb(&orb->base, unit,
 		      node_id, generation, sd->management_agent_address);
 
@@ -479,9 +483,10 @@
  out:
 	dma_unmap_single(device->card->device, orb->base.request_bus,
 			 sizeof(orb->request), DMA_TO_DEVICE);
+ fail_mapping_request:
 	dma_unmap_single(device->card->device, orb->response_bus,
 			 sizeof(orb->response), DMA_FROM_DEVICE);
-
+ fail_mapping_response:
 	if (response)
 		fw_memcpy_from_be32(response,
 				    orb->response, sizeof(orb->response));
@@ -511,7 +516,7 @@
 		return -ENOMEM;
 
 	fw_send_request(device->card, t, TCODE_WRITE_QUADLET_REQUEST,
-			sd->node_id, sd->generation, SCODE_400,
+			sd->node_id, sd->generation, device->max_speed,
 			sd->command_block_agent_address + SBP2_AGENT_RESET,
 			&zero, sizeof(zero), complete_agent_reset_write, t);
 
@@ -521,17 +526,15 @@
 static void sbp2_reconnect(struct work_struct *work);
 static struct scsi_host_template scsi_driver_template;
 
-static void
-release_sbp2_device(struct kref *kref)
+static void release_sbp2_device(struct kref *kref)
 {
 	struct sbp2_device *sd = container_of(kref, struct sbp2_device, kref);
 	struct Scsi_Host *host =
 		container_of((void *)sd, struct Scsi_Host, hostdata[0]);
 
+	scsi_remove_host(host);
 	sbp2_send_management_orb(sd->unit, sd->node_id, sd->generation,
 				 SBP2_LOGOUT_REQUEST, sd->login_id, NULL);
-
-	scsi_remove_host(host);
 	fw_core_remove_address_handler(&sd->address_handler);
 	fw_notify("removed sbp2 unit %s\n", sd->unit->device.bus_id);
 	put_device(&sd->unit->device);
@@ -833,7 +836,8 @@
 static void
 complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status)
 {
-	struct sbp2_command_orb *orb = (struct sbp2_command_orb *)base_orb;
+	struct sbp2_command_orb *orb =
+		container_of(base_orb, struct sbp2_command_orb, base);
 	struct fw_unit *unit = orb->unit;
 	struct fw_device *device = fw_device(unit->device.parent);
 	struct scatterlist *sg;
@@ -880,12 +884,7 @@
 
 	if (orb->page_table_bus != 0)
 		dma_unmap_single(device->card->device, orb->page_table_bus,
-				 sizeof(orb->page_table_bus), DMA_TO_DEVICE);
-
-	if (orb->request_buffer_bus != 0)
-		dma_unmap_single(device->card->device, orb->request_buffer_bus,
-				 sizeof(orb->request_buffer_bus),
-				 DMA_FROM_DEVICE);
+				 sizeof(orb->page_table), DMA_TO_DEVICE);
 
 	orb->cmd->result = result;
 	orb->done(orb->cmd);
@@ -900,7 +899,6 @@
 	struct fw_device *device = fw_device(unit->device.parent);
 	struct scatterlist *sg;
 	int sg_len, l, i, j, count;
-	size_t size;
 	dma_addr_t sg_addr;
 
 	sg = (struct scatterlist *)orb->cmd->request_buffer;
@@ -935,6 +933,11 @@
 		sg_len = sg_dma_len(sg + i);
 		sg_addr = sg_dma_address(sg + i);
 		while (sg_len) {
+			/* FIXME: This won't get us out of the pinch. */
+			if (unlikely(j >= ARRAY_SIZE(orb->page_table))) {
+				fw_error("page table overflow\n");
+				goto fail_page_table;
+			}
 			l = min(sg_len, SBP2_MAX_SG_ELEMENT_LENGTH);
 			orb->page_table[j].low = sg_addr;
 			orb->page_table[j].high = (l << 16);
@@ -944,7 +947,13 @@
 		}
 	}
 
-	size = sizeof(orb->page_table[0]) * j;
+	fw_memcpy_to_be32(orb->page_table, orb->page_table,
+			  sizeof(orb->page_table[0]) * j);
+	orb->page_table_bus =
+		dma_map_single(device->card->device, orb->page_table,
+			       sizeof(orb->page_table), DMA_TO_DEVICE);
+	if (dma_mapping_error(orb->page_table_bus))
+		goto fail_page_table;
 
 	/*
 	 * The data_descriptor pointer is the one case where we need
@@ -953,20 +962,12 @@
 	 * initiator (i.e. us), but data_descriptor can refer to data
 	 * on other nodes so we need to put our ID in descriptor.high.
 	 */
-
-	orb->page_table_bus =
-		dma_map_single(device->card->device, orb->page_table,
-			       size, DMA_TO_DEVICE);
-	if (dma_mapping_error(orb->page_table_bus))
-		goto fail_page_table;
 	orb->request.data_descriptor.high = sd->address_high;
 	orb->request.data_descriptor.low  = orb->page_table_bus;
 	orb->request.misc |=
 		COMMAND_ORB_PAGE_TABLE_PRESENT |
 		COMMAND_ORB_DATA_SIZE(j);
 
-	fw_memcpy_to_be32(orb->page_table, orb->page_table, size);
-
 	return 0;
 
  fail_page_table:
@@ -991,7 +992,7 @@
 	 * transfer direction not handled.
 	 */
 	if (cmd->sc_data_direction == DMA_BIDIRECTIONAL) {
-		fw_error("Cannot handle DMA_BIDIRECTIONAL - rejecting command");
+		fw_error("Can't handle DMA_BIDIRECTIONAL, rejecting command\n");
 		cmd->result = DID_ERROR << 16;
 		done(cmd);
 		return 0;
@@ -1005,11 +1006,6 @@
 
 	/* Initialize rcode to something not RCODE_COMPLETE. */
 	orb->base.rcode = -1;
-	orb->base.request_bus =
-		dma_map_single(device->card->device, &orb->request,
-			       sizeof(orb->request), DMA_TO_DEVICE);
-	if (dma_mapping_error(orb->base.request_bus))
-		goto fail_mapping;
 
 	orb->unit = unit;
 	orb->done = done;
@@ -1024,8 +1020,8 @@
 	 * if we set this to max_speed + 7, we get the right value.
 	 */
 	orb->request.misc =
-		COMMAND_ORB_MAX_PAYLOAD(device->node->max_speed + 7) |
-		COMMAND_ORB_SPEED(device->node->max_speed) |
+		COMMAND_ORB_MAX_PAYLOAD(device->max_speed + 7) |
+		COMMAND_ORB_SPEED(device->max_speed) |
 		COMMAND_ORB_NOTIFY;
 
 	if (cmd->sc_data_direction == DMA_FROM_DEVICE)
@@ -1036,7 +1032,7 @@
 			COMMAND_ORB_DIRECTION(SBP2_DIRECTION_TO_MEDIA);
 
 	if (cmd->use_sg && sbp2_command_orb_map_scatterlist(orb) < 0)
-		goto fail_map_payload;
+		goto fail_mapping;
 
 	fw_memcpy_to_be32(&orb->request, &orb->request, sizeof(orb->request));
 
@@ -1045,15 +1041,17 @@
 	memcpy(orb->request.command_block, cmd->cmnd, COMMAND_SIZE(*cmd->cmnd));
 
 	orb->base.callback = complete_command_orb;
+	orb->base.request_bus =
+		dma_map_single(device->card->device, &orb->request,
+			       sizeof(orb->request), DMA_TO_DEVICE);
+	if (dma_mapping_error(orb->base.request_bus))
+		goto fail_mapping;
 
 	sbp2_send_orb(&orb->base, unit, sd->node_id, sd->generation,
 		      sd->command_block_agent_address + SBP2_ORB_POINTER);
 
 	return 0;
 
- fail_map_payload:
-	dma_unmap_single(device->card->device, orb->base.request_bus,
-			 sizeof(orb->request), DMA_TO_DEVICE);
  fail_mapping:
 	kfree(orb);
  fail_alloc:
@@ -1087,7 +1085,8 @@
 		fw_notify("setting fix_capacity for %s\n", unit->device.bus_id);
 		sdev->fix_capacity = 1;
 	}
-
+	if (sd->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS)
+		blk_queue_max_sectors(sdev->request_queue, 128 * 1024 / 512);
 	return 0;
 }
 
diff --git a/drivers/firewire/fw-topology.c b/drivers/firewire/fw-topology.c
index 7aebb8a..39e5cd1 100644
--- a/drivers/firewire/fw-topology.c
+++ b/drivers/firewire/fw-topology.c
@@ -135,17 +135,17 @@
 	int i;
 
 	for (i = 0; i < node->port_count; i++) {
-		if (node->ports[i].node == NULL)
+		if (node->ports[i] == NULL)
 			continue;
 
-		if (node->ports[i].node->max_hops > max_child_hops)
-			max_child_hops = node->ports[i].node->max_hops;
+		if (node->ports[i]->max_hops > max_child_hops)
+			max_child_hops = node->ports[i]->max_hops;
 
-		if (node->ports[i].node->max_depth > depths[0]) {
+		if (node->ports[i]->max_depth > depths[0]) {
 			depths[1] = depths[0];
-			depths[0] = node->ports[i].node->max_depth;
-		} else if (node->ports[i].node->max_depth > depths[1])
-			depths[1] = node->ports[i].node->max_depth;
+			depths[0] = node->ports[i]->max_depth;
+		} else if (node->ports[i]->max_depth > depths[1])
+			depths[1] = node->ports[i]->max_depth;
 	}
 
 	node->max_depth = depths[0] + 1;
@@ -172,7 +172,8 @@
 	struct list_head stack, *h;
 	u32 *next_sid, *end, q;
 	int i, port_count, child_port_count, phy_id, parent_count, stack_depth;
-	int gap_count, topology_type;
+	int gap_count;
+	bool beta_repeaters_present;
 
 	local_node = NULL;
 	node = NULL;
@@ -182,7 +183,7 @@
 	phy_id = 0;
 	irm_node = NULL;
 	gap_count = SELF_ID_GAP_COUNT(*sid);
-	topology_type = 0;
+	beta_repeaters_present = false;
 
 	while (sid < end) {
 		next_sid = count_ports(sid, &port_count, &child_port_count);
@@ -214,7 +215,7 @@
 
 		node = fw_node_create(q, port_count, card->color);
 		if (node == NULL) {
-			fw_error("Out of memory while building topology.");
+			fw_error("Out of memory while building topology.\n");
 			return NULL;
 		}
 
@@ -224,11 +225,6 @@
 		if (SELF_ID_CONTENDER(q))
 			irm_node = node;
 
-		if (node->phy_speed == SCODE_BETA)
-			topology_type |= FW_TOPOLOGY_B;
-		else
-			topology_type |= FW_TOPOLOGY_A;
-
 		parent_count = 0;
 
 		for (i = 0; i < port_count; i++) {
@@ -249,12 +245,12 @@
 				break;
 
 			case SELFID_PORT_CHILD:
-				node->ports[i].node = child;
+				node->ports[i] = child;
 				/*
 				 * Fix up parent reference for this
 				 * child node.
 				 */
-				child->ports[child->color].node = node;
+				child->ports[child->color] = node;
 				child->color = card->color;
 				child = fw_node(child->link.next);
 				break;
@@ -278,6 +274,10 @@
 		list_add_tail(&node->link, &stack);
 		stack_depth += 1 - child_port_count;
 
+		if (node->phy_speed == SCODE_BETA &&
+		    parent_count + child_port_count > 1)
+			beta_repeaters_present = true;
+
 		/*
 		 * If all PHYs does not report the same gap count
 		 * setting, we fall back to 63 which will force a gap
@@ -295,7 +295,7 @@
 	card->root_node = node;
 	card->irm_node = irm_node;
 	card->gap_count = gap_count;
-	card->topology_type = topology_type;
+	card->beta_repeaters_present = beta_repeaters_present;
 
 	return local_node;
 }
@@ -321,7 +321,7 @@
 		node->color = card->color;
 
 		for (i = 0; i < node->port_count; i++) {
-			child = node->ports[i].node;
+			child = node->ports[i];
 			if (!child)
 				continue;
 			if (child->color == card->color)
@@ -382,11 +382,11 @@
 	struct fw_node *tree;
 	int i;
 
-	tree = node1->ports[port].node;
-	node0->ports[port].node = tree;
+	tree = node1->ports[port];
+	node0->ports[port] = tree;
 	for (i = 0; i < tree->port_count; i++) {
-		if (tree->ports[i].node == node1) {
-			tree->ports[i].node = node0;
+		if (tree->ports[i] == node1) {
+			tree->ports[i] = node0;
 			break;
 		}
 	}
@@ -437,19 +437,17 @@
 			card->irm_node = node0;
 
 		for (i = 0; i < node0->port_count; i++) {
-			if (node0->ports[i].node && node1->ports[i].node) {
+			if (node0->ports[i] && node1->ports[i]) {
 				/*
 				 * This port didn't change, queue the
 				 * connected node for further
 				 * investigation.
 				 */
-				if (node0->ports[i].node->color == card->color)
+				if (node0->ports[i]->color == card->color)
 					continue;
-				list_add_tail(&node0->ports[i].node->link,
-					      &list0);
-				list_add_tail(&node1->ports[i].node->link,
-					      &list1);
-			} else if (node0->ports[i].node) {
+				list_add_tail(&node0->ports[i]->link, &list0);
+				list_add_tail(&node1->ports[i]->link, &list1);
+			} else if (node0->ports[i]) {
 				/*
 				 * The nodes connected here were
 				 * unplugged; unref the lost nodes and
@@ -457,10 +455,10 @@
 				 * them.
 				 */
 
-				for_each_fw_node(card, node0->ports[i].node,
+				for_each_fw_node(card, node0->ports[i],
 						 report_lost_node);
-				node0->ports[i].node = NULL;
-			} else if (node1->ports[i].node) {
+				node0->ports[i] = NULL;
+			} else if (node1->ports[i]) {
 				/*
 				 * One or more node were connected to
 				 * this port. Move the new nodes into
@@ -468,7 +466,7 @@
 				 * callbacks for them.
 				 */
 				move_tree(node0, node1, i);
-				for_each_fw_node(card, node0->ports[i].node,
+				for_each_fw_node(card, node0->ports[i],
 						 report_found_node);
 			}
 		}
diff --git a/drivers/firewire/fw-topology.h b/drivers/firewire/fw-topology.h
index 363b6cb..1b56b4a 100644
--- a/drivers/firewire/fw-topology.h
+++ b/drivers/firewire/fw-topology.h
@@ -20,12 +20,6 @@
 #define __fw_topology_h
 
 enum {
-	FW_TOPOLOGY_A =		0x01,
-	FW_TOPOLOGY_B =		0x02,
-	FW_TOPOLOGY_MIXED =	0x03,
-};
-
-enum {
 	FW_NODE_CREATED =   0x00,
 	FW_NODE_UPDATED =   0x01,
 	FW_NODE_DESTROYED = 0x02,
@@ -33,21 +27,16 @@
 	FW_NODE_LINK_OFF =  0x04,
 };
 
-struct fw_port {
-	struct fw_node *node;
-	unsigned speed : 3; /* S100, S200, ... S3200 */
-};
-
 struct fw_node {
 	u16 node_id;
 	u8 color;
 	u8 port_count;
-	unsigned link_on : 1;
-	unsigned initiated_reset : 1;
-	unsigned b_path : 1;
-	u8 phy_speed : 3; /* As in the self ID packet. */
-	u8 max_speed : 5; /* Minimum of all phy-speeds and port speeds on
-			   * the path from the local node to this node. */
+	u8 link_on : 1;
+	u8 initiated_reset : 1;
+	u8 b_path : 1;
+	u8 phy_speed : 2; /* As in the self ID packet. */
+	u8 max_speed : 2; /* Minimum of all phy-speeds on the path from the
+			   * local node to this node. */
 	u8 max_depth : 4; /* Maximum depth to any leaf node */
 	u8 max_hops : 4;  /* Max hops in this sub tree */
 	atomic_t ref_count;
@@ -58,7 +47,7 @@
 	/* Upper layer specific data. */
 	void *data;
 
-	struct fw_port ports[0];
+	struct fw_node *ports[0];
 };
 
 static inline struct fw_node *
diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h
index acdc3be..5abed19 100644
--- a/drivers/firewire/fw-transaction.h
+++ b/drivers/firewire/fw-transaction.h
@@ -81,7 +81,6 @@
 
 #define fw_notify(s, args...) printk(KERN_NOTICE KBUILD_MODNAME ": " s, ## args)
 #define fw_error(s, args...) printk(KERN_ERR KBUILD_MODNAME ": " s, ## args)
-#define fw_debug(s, args...) printk(KERN_DEBUG KBUILD_MODNAME ": " s, ## args)
 
 static inline void
 fw_memcpy_from_be32(void *_dst, void *_src, size_t size)
@@ -246,7 +245,7 @@
 	struct fw_node *irm_node;
 	int color;
 	int gap_count;
-	int topology_type;
+	bool beta_repeaters_present;
 
 	int index;
 
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
index 2081413..6572211 100644
--- a/drivers/ieee1394/dv1394.c
+++ b/drivers/ieee1394/dv1394.c
@@ -2280,7 +2280,7 @@
 	} while (video);
 
 	if (found_ohci_card)
-		class_device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR,
+		device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR,
 			   IEEE1394_MINOR_BLOCK_DV1394 * 16 + (host->id << 2)));
 }
 
@@ -2295,9 +2295,9 @@
 
 	ohci = (struct ti_ohci *)host->hostdata;
 
-	class_device_create(hpsb_protocol_class, NULL, MKDEV(
-		IEEE1394_MAJOR,	IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)), 
-		NULL, "dv1394-%d", id);
+	device_create(hpsb_protocol_class, NULL, MKDEV(
+		IEEE1394_MAJOR,	IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)),
+		"dv1394-%d", id);
 
 	dv1394_init(ohci, DV1394_NTSC, MODE_RECEIVE);
 	dv1394_init(ohci, DV1394_NTSC, MODE_TRANSMIT);
diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c
index 7c13fb3..93362ee 100644
--- a/drivers/ieee1394/eth1394.c
+++ b/drivers/ieee1394/eth1394.c
@@ -599,9 +599,7 @@
 	}
 
 	SET_MODULE_OWNER(dev);
-
-	/* This used to be &host->device in Linux 2.6.20 and before. */
-	SET_NETDEV_DEV(dev, host->device.parent);
+	SET_NETDEV_DEV(dev, &host->device);
 
 	priv = netdev_priv(dev);
 	INIT_LIST_HEAD(&priv->ip_node_list);
diff --git a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c
index 83a49331..b642546 100644
--- a/drivers/ieee1394/highlevel.c
+++ b/drivers/ieee1394/highlevel.c
@@ -483,37 +483,6 @@
 	return retval;
 }
 
-/**
- * hpsb_listen_channel - enable receving a certain isochronous channel
- *
- * Reception is handled through the @hl's iso_receive op.
- */
-int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
-			unsigned int channel)
-{
-	if (channel > 63) {
-		HPSB_ERR("%s called with invalid channel", __FUNCTION__);
-		return -EINVAL;
-	}
-	if (host->iso_listen_count[channel]++ == 0)
-		return host->driver->devctl(host, ISO_LISTEN_CHANNEL, channel);
-	return 0;
-}
-
-/**
- * hpsb_unlisten_channel - disable receving a certain isochronous channel
- */
-void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
-			   unsigned int channel)
-{
-	if (channel > 63) {
-		HPSB_ERR("%s called with invalid channel", __FUNCTION__);
-		return;
-	}
-	if (--host->iso_listen_count[channel] == 0)
-		host->driver->devctl(host, ISO_UNLISTEN_CHANNEL, channel);
-}
-
 static void init_hpsb_highlevel(struct hpsb_host *host)
 {
 	INIT_LIST_HEAD(&dummy_zero_addr.host_list);
@@ -570,20 +539,6 @@
 	read_unlock_irqrestore(&hl_irqs_lock, flags);
 }
 
-void highlevel_iso_receive(struct hpsb_host *host, void *data, size_t length)
-{
-	unsigned long flags;
-	struct hpsb_highlevel *hl;
-	int channel = (((quadlet_t *)data)[0] >> 8) & 0x3f;
-
-	read_lock_irqsave(&hl_irqs_lock, flags);
-	list_for_each_entry(hl, &hl_irqs, irq_list) {
-		if (hl->iso_receive)
-			hl->iso_receive(host, channel, data, length);
-	}
-	read_unlock_irqrestore(&hl_irqs_lock, flags);
-}
-
 void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction,
 			   void *data, size_t length)
 {
diff --git a/drivers/ieee1394/highlevel.h b/drivers/ieee1394/highlevel.h
index 63474f7..eb9fe32 100644
--- a/drivers/ieee1394/highlevel.h
+++ b/drivers/ieee1394/highlevel.h
@@ -26,9 +26,7 @@
 struct hpsb_highlevel {
 	const char *name;
 
-	/* Any of the following pointers can legally be NULL, except for
-	 * iso_receive which can only be NULL when you don't request
-	 * channels. */
+	/* Any of the following pointers can legally be NULL. */
 
 	/* New host initialized.  Will also be called during
 	 * hpsb_register_highlevel for all hosts already installed. */
@@ -43,13 +41,6 @@
 	 * You can not expect to be able to do stock hpsb_reads. */
 	void (*host_reset)(struct hpsb_host *host);
 
-	/* An isochronous packet was received.  Channel contains the channel
-	 * number for your convenience, it is also contained in the included
-	 * packet header (first quadlet, CRCs are missing).  You may get called
-	 * for channel/host combinations you did not request. */
-	void (*iso_receive)(struct hpsb_host *host, int channel,
-			    quadlet_t *data, size_t length);
-
 	/* A write request was received on either the FCP_COMMAND (direction =
 	 * 0) or the FCP_RESPONSE (direction = 1) register.  The cts arg
 	 * contains the cts field (first byte of data). */
@@ -109,7 +100,6 @@
 int highlevel_lock64(struct hpsb_host *host, int nodeid, octlet_t *store,
 		     u64 addr, octlet_t data, octlet_t arg, int ext_tcode,
 		     u16 flags);
-void highlevel_iso_receive(struct hpsb_host *host, void *data, size_t length);
 void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction,
 			   void *data, size_t length);
 
@@ -125,10 +115,6 @@
 			    struct hpsb_address_ops *ops, u64 start, u64 end);
 int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
 			      u64 start);
-int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
-			unsigned int channel);
-void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
-			   unsigned int channel);
 
 void *hpsb_get_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host);
 void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
diff --git a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c
index bd0755c..8dd09d8 100644
--- a/drivers/ieee1394/hosts.c
+++ b/drivers/ieee1394/hosts.c
@@ -154,15 +154,16 @@
 
 	memcpy(&h->device, &nodemgr_dev_template_host, sizeof(h->device));
 	h->device.parent = dev;
+	set_dev_node(&h->device, dev_to_node(dev));
 	snprintf(h->device.bus_id, BUS_ID_SIZE, "fw-host%d", h->id);
 
-	h->class_dev.dev = &h->device;
-	h->class_dev.class = &hpsb_host_class;
-	snprintf(h->class_dev.class_id, BUS_ID_SIZE, "fw-host%d", h->id);
+	h->host_dev.parent = &h->device;
+	h->host_dev.class = &hpsb_host_class;
+	snprintf(h->host_dev.bus_id, BUS_ID_SIZE, "fw-host%d", h->id);
 
 	if (device_register(&h->device))
 		goto fail;
-	if (class_device_register(&h->class_dev)) {
+	if (device_register(&h->host_dev)) {
 		device_unregister(&h->device);
 		goto fail;
 	}
@@ -202,7 +203,7 @@
 	host->driver = &dummy_driver;
 	highlevel_remove_host(host);
 
-	class_device_unregister(&host->class_dev);
+	device_unregister(&host->host_dev);
 	device_unregister(&host->device);
 }
 
diff --git a/drivers/ieee1394/hosts.h b/drivers/ieee1394/hosts.h
index feb55d0..e4e8aeb 100644
--- a/drivers/ieee1394/hosts.h
+++ b/drivers/ieee1394/hosts.h
@@ -28,8 +28,6 @@
 	struct timer_list timeout;
 	unsigned long timeout_interval;
 
-	unsigned char iso_listen_count[64];
-
 	int node_count;      /* number of identified nodes on this bus */
 	int selfid_count;    /* total number of SelfIDs received */
 	int nodes_active;    /* number of nodes with active link layer */
@@ -57,7 +55,7 @@
 	struct hpsb_host_driver *driver;
 	struct pci_dev *pdev;
 	struct device device;
-	struct class_device class_dev;
+	struct device host_dev;
 
 	struct delayed_work delayed_reset;
 	unsigned config_roms:31;
@@ -99,12 +97,6 @@
 	/* Cancel all outstanding async requests without resetting the bus.
 	 * Return void. */
 	CANCEL_REQUESTS,
-
-	/* Start or stop receiving isochronous channel in arg.  Return void.
-	 * This acts as an optimization hint, hosts are not required not to
-	 * listen on unrequested channels. */
-	ISO_LISTEN_CHANNEL,
-	ISO_UNLISTEN_CHANNEL
 };
 
 enum isoctl_cmd {
diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c
index 8f71b6a..0fc8c6e 100644
--- a/drivers/ieee1394/ieee1394_core.c
+++ b/drivers/ieee1394/ieee1394_core.c
@@ -1028,11 +1028,6 @@
 		handle_incoming_packet(host, tcode, data, size, write_acked);
 		break;
 
-
-	case TCODE_ISO_DATA:
-		highlevel_iso_receive(host, data, size);
-		break;
-
 	case TCODE_CYCLE_START:
 		/* simply ignore this packet if it is passed on */
 		break;
@@ -1316,7 +1311,6 @@
 EXPORT_SYMBOL(hpsb_make_lockpacket);
 EXPORT_SYMBOL(hpsb_make_lock64packet);
 EXPORT_SYMBOL(hpsb_make_phypacket);
-EXPORT_SYMBOL(hpsb_make_isopacket);
 EXPORT_SYMBOL(hpsb_read);
 EXPORT_SYMBOL(hpsb_write);
 EXPORT_SYMBOL(hpsb_packet_success);
@@ -1327,8 +1321,6 @@
 EXPORT_SYMBOL(hpsb_register_addrspace);
 EXPORT_SYMBOL(hpsb_unregister_addrspace);
 EXPORT_SYMBOL(hpsb_allocate_and_register_addrspace);
-EXPORT_SYMBOL(hpsb_listen_channel);
-EXPORT_SYMBOL(hpsb_unlisten_channel);
 EXPORT_SYMBOL(hpsb_get_hostinfo);
 EXPORT_SYMBOL(hpsb_create_hostinfo);
 EXPORT_SYMBOL(hpsb_destroy_hostinfo);
diff --git a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h
index ad52652..21d50f7 100644
--- a/drivers/ieee1394/ieee1394_core.h
+++ b/drivers/ieee1394/ieee1394_core.h
@@ -24,9 +24,8 @@
 
 	nodeid_t node_id;
 
-	/* Async and Iso types should be clear, raw means send-as-is, do not
-	 * CRC!  Byte swapping shall still be done in this case. */
-	enum { hpsb_async, hpsb_iso, hpsb_raw } __attribute__((packed)) type;
+	/* hpsb_raw = send as-is, do not CRC (but still byte-swap it) */
+	enum { hpsb_async, hpsb_raw } __attribute__((packed)) type;
 
 	/* Okay, this is core internal and a no care for hosts.
 	 * queued   = queued for sending
@@ -37,7 +36,7 @@
 		hpsb_unused, hpsb_queued, hpsb_pending, hpsb_complete
 	} __attribute__((packed)) state;
 
-	/* These are core internal. */
+	/* These are core-internal. */
 	signed char tlabel;
 	signed char ack_code;
 	unsigned char tcode;
@@ -62,11 +61,15 @@
 	/* Store jiffies for implementing bus timeouts. */
 	unsigned long sendtime;
 
-	/* Sizes are in bytes. *data can be DMA-mapped. */
+	/* Core-internal.  */
 	size_t allocated_data_size;	/* as allocated */
+
+	/* Sizes are in bytes. To be set by caller of hpsb_alloc_packet. */
 	size_t data_size;		/* as filled in */
 	size_t header_size;		/* as filled in, not counting the CRC */
-	quadlet_t *data;
+
+	/* Buffers */
+	quadlet_t *data;		/* can be DMA-mapped */
 	quadlet_t header[5];
 	quadlet_t embedded_data[0];	/* keep as last member */
 };
diff --git a/drivers/ieee1394/ieee1394_transactions.c b/drivers/ieee1394/ieee1394_transactions.c
index 40078ce..c39c70a 100644
--- a/drivers/ieee1394/ieee1394_transactions.c
+++ b/drivers/ieee1394/ieee1394_transactions.c
@@ -89,18 +89,6 @@
 	packet->expect_response = 1;
 }
 
-static void fill_iso_packet(struct hpsb_packet *packet, int length, int channel,
-			    int tag, int sync)
-{
-	packet->header[0] = (length << 16) | (tag << 14) | (channel << 8)
-	    | (TCODE_ISO_DATA << 4) | sync;
-
-	packet->header_size = 4;
-	packet->data_size = length;
-	packet->type = hpsb_iso;
-	packet->tcode = TCODE_ISO_DATA;
-}
-
 static void fill_phy_packet(struct hpsb_packet *packet, quadlet_t data)
 {
 	packet->header[0] = data;
@@ -491,24 +479,6 @@
 	return p;
 }
 
-struct hpsb_packet *hpsb_make_isopacket(struct hpsb_host *host,
-					int length, int channel,
-					int tag, int sync)
-{
-	struct hpsb_packet *p;
-
-	p = hpsb_alloc_packet(length);
-	if (!p)
-		return NULL;
-
-	p->host = host;
-	fill_iso_packet(p, length, channel, tag, sync);
-
-	p->generation = get_hpsb_generation(host);
-
-	return p;
-}
-
 /*
  * FIXME - these functions should probably read from / write to user space to
  * avoid in kernel buffers for user space callers
diff --git a/drivers/ieee1394/ieee1394_transactions.h b/drivers/ieee1394/ieee1394_transactions.h
index 86b8ee6..d2d5bc3 100644
--- a/drivers/ieee1394/ieee1394_transactions.h
+++ b/drivers/ieee1394/ieee1394_transactions.h
@@ -19,8 +19,6 @@
 					   nodeid_t node, u64 addr, int extcode,
 					   octlet_t *data, octlet_t arg);
 struct hpsb_packet *hpsb_make_phypacket(struct hpsb_host *host, quadlet_t data);
-struct hpsb_packet *hpsb_make_isopacket(struct hpsb_host *host, int length,
-					int channel, int tag, int sync);
 struct hpsb_packet *hpsb_make_writepacket(struct hpsb_host *host,
 					  nodeid_t node, u64 addr,
 					  quadlet_t *buffer, size_t length);
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index 81b3864..c4d3d41 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -19,6 +19,7 @@
 #include <linux/mutex.h>
 #include <linux/freezer.h>
 #include <asm/atomic.h>
+#include <asm/semaphore.h>
 
 #include "csr.h"
 #include "highlevel.h"
@@ -145,8 +146,6 @@
  * but now we are much simpler because of the LDM.
  */
 
-static DEFINE_MUTEX(nodemgr_serialize);
-
 struct host_info {
 	struct hpsb_host *host;
 	struct list_head list;
@@ -154,7 +153,7 @@
 };
 
 static int nodemgr_bus_match(struct device * dev, struct device_driver * drv);
-static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,
+static int nodemgr_uevent(struct device *dev, char **envp, int num_envp,
 			  char *buffer, int buffer_size);
 static void nodemgr_resume_ne(struct node_entry *ne);
 static void nodemgr_remove_ne(struct node_entry *ne);
@@ -165,37 +164,38 @@
 	.match		= nodemgr_bus_match,
 };
 
-static void host_cls_release(struct class_device *class_dev)
+static void host_cls_release(struct device *dev)
 {
-	put_device(&container_of((class_dev), struct hpsb_host, class_dev)->device);
+	put_device(&container_of((dev), struct hpsb_host, host_dev)->device);
 }
 
 struct class hpsb_host_class = {
 	.name		= "ieee1394_host",
-	.release	= host_cls_release,
+	.dev_release	= host_cls_release,
 };
 
-static void ne_cls_release(struct class_device *class_dev)
+static void ne_cls_release(struct device *dev)
 {
-	put_device(&container_of((class_dev), struct node_entry, class_dev)->device);
+	put_device(&container_of((dev), struct node_entry, node_dev)->device);
 }
 
 static struct class nodemgr_ne_class = {
 	.name		= "ieee1394_node",
-	.release	= ne_cls_release,
+	.dev_release	= ne_cls_release,
 };
 
-static void ud_cls_release(struct class_device *class_dev)
+static void ud_cls_release(struct device *dev)
 {
-	put_device(&container_of((class_dev), struct unit_directory, class_dev)->device);
+	put_device(&container_of((dev), struct unit_directory, unit_dev)->device);
 }
 
 /* The name here is only so that unit directory hotplug works with old
- * style hotplug, which only ever did unit directories anyway. */
+ * style hotplug, which only ever did unit directories anyway.
+ */
 static struct class nodemgr_ud_class = {
 	.name		= "ieee1394",
-	.release	= ud_cls_release,
-	.uevent		= nodemgr_uevent,
+	.dev_release	= ud_cls_release,
+	.dev_uevent	= nodemgr_uevent,
 };
 
 static struct hpsb_highlevel nodemgr_highlevel;
@@ -730,11 +730,11 @@
 
 static void nodemgr_remove_uds(struct node_entry *ne)
 {
-	struct class_device *cdev;
+	struct device *dev;
 	struct unit_directory *tmp, *ud;
 
-	/* Iteration over nodemgr_ud_class.children has to be protected by
-	 * nodemgr_ud_class.sem, but class_device_unregister() will eventually
+	/* Iteration over nodemgr_ud_class.devices has to be protected by
+	 * nodemgr_ud_class.sem, but device_unregister() will eventually
 	 * take nodemgr_ud_class.sem too. Therefore pick out one ud at a time,
 	 * release the semaphore, and then unregister the ud. Since this code
 	 * may be called from other contexts besides the knodemgrds, protect the
@@ -744,9 +744,9 @@
 	for (;;) {
 		ud = NULL;
 		down(&nodemgr_ud_class.sem);
-		list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
-			tmp = container_of(cdev, struct unit_directory,
-					   class_dev);
+		list_for_each_entry(dev, &nodemgr_ud_class.devices, node) {
+			tmp = container_of(dev, struct unit_directory,
+					   unit_dev);
 			if (tmp->ne == ne) {
 				ud = tmp;
 				break;
@@ -755,7 +755,7 @@
 		up(&nodemgr_ud_class.sem);
 		if (ud == NULL)
 			break;
-		class_device_unregister(&ud->class_dev);
+		device_unregister(&ud->unit_dev);
 		device_unregister(&ud->device);
 	}
 	mutex_unlock(&nodemgr_serialize_remove_uds);
@@ -772,10 +772,9 @@
 
 	HPSB_DEBUG("Node removed: ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",
 		   NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid);
-
 	nodemgr_remove_uds(ne);
 
-	class_device_unregister(&ne->class_dev);
+	device_unregister(&ne->node_dev);
 	device_unregister(dev);
 
 	put_device(dev);
@@ -783,7 +782,9 @@
 
 static int __nodemgr_remove_host_dev(struct device *dev, void *data)
 {
-	nodemgr_remove_ne(container_of(dev, struct node_entry, device));
+	if (dev->bus == &ieee1394_bus_type)
+		nodemgr_remove_ne(container_of(dev, struct node_entry,
+				  device));
 	return 0;
 }
 
@@ -850,14 +851,14 @@
 	snprintf(ne->device.bus_id, BUS_ID_SIZE, "%016Lx",
 		 (unsigned long long)(ne->guid));
 
-	ne->class_dev.dev = &ne->device;
-	ne->class_dev.class = &nodemgr_ne_class;
-	snprintf(ne->class_dev.class_id, BUS_ID_SIZE, "%016Lx",
-		 (unsigned long long)(ne->guid));
+	ne->node_dev.parent = &ne->device;
+	ne->node_dev.class = &nodemgr_ne_class;
+	snprintf(ne->node_dev.bus_id, BUS_ID_SIZE, "%016Lx",
+		(unsigned long long)(ne->guid));
 
 	if (device_register(&ne->device))
 		goto fail_devreg;
-	if (class_device_register(&ne->class_dev))
+	if (device_register(&ne->node_dev))
 		goto fail_classdevreg;
 	get_device(&ne->device);
 
@@ -885,12 +886,12 @@
 
 static struct node_entry *find_entry_by_guid(u64 guid)
 {
-	struct class_device *cdev;
+	struct device *dev;
 	struct node_entry *ne, *ret_ne = NULL;
 
 	down(&nodemgr_ne_class.sem);
-	list_for_each_entry(cdev, &nodemgr_ne_class.children, node) {
-		ne = container_of(cdev, struct node_entry, class_dev);
+	list_for_each_entry(dev, &nodemgr_ne_class.devices, node) {
+		ne = container_of(dev, struct node_entry, node_dev);
 
 		if (ne->guid == guid) {
 			ret_ne = ne;
@@ -906,12 +907,12 @@
 static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host,
 					       nodeid_t nodeid)
 {
-	struct class_device *cdev;
+	struct device *dev;
 	struct node_entry *ne, *ret_ne = NULL;
 
 	down(&nodemgr_ne_class.sem);
-	list_for_each_entry(cdev, &nodemgr_ne_class.children, node) {
-		ne = container_of(cdev, struct node_entry, class_dev);
+	list_for_each_entry(dev, &nodemgr_ne_class.devices, node) {
+		ne = container_of(dev, struct node_entry, node_dev);
 
 		if (ne->host == host && ne->nodeid == nodeid) {
 			ret_ne = ne;
@@ -935,14 +936,14 @@
 	snprintf(ud->device.bus_id, BUS_ID_SIZE, "%s-%u",
 		 ne->device.bus_id, ud->id);
 
-	ud->class_dev.dev = &ud->device;
-	ud->class_dev.class = &nodemgr_ud_class;
-	snprintf(ud->class_dev.class_id, BUS_ID_SIZE, "%s-%u",
+	ud->unit_dev.parent = &ud->device;
+	ud->unit_dev.class = &nodemgr_ud_class;
+	snprintf(ud->unit_dev.bus_id, BUS_ID_SIZE, "%s-%u",
 		 ne->device.bus_id, ud->id);
 
 	if (device_register(&ud->device))
 		goto fail_devreg;
-	if (class_device_register(&ud->class_dev))
+	if (device_register(&ud->unit_dev))
 		goto fail_classdevreg;
 	get_device(&ud->device);
 
@@ -1159,7 +1160,7 @@
 
 #ifdef CONFIG_HOTPLUG
 
-static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,
+static int nodemgr_uevent(struct device *dev, char **envp, int num_envp,
 			  char *buffer, int buffer_size)
 {
 	struct unit_directory *ud;
@@ -1169,10 +1170,10 @@
 	/* ieee1394:venNmoNspNverN */
 	char buf[8 + 1 + 3 + 8 + 2 + 8 + 2 + 8 + 3 + 8 + 1];
 
-	if (!cdev)
+	if (!dev)
 		return -ENODEV;
 
-	ud = container_of(cdev, struct unit_directory, class_dev);
+	ud = container_of(dev, struct unit_directory, unit_dev);
 
 	if (ud->ne->in_limbo || ud->ignore_driver)
 		return -ENODEV;
@@ -1207,7 +1208,7 @@
 
 #else
 
-static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,
+static int nodemgr_uevent(struct device *dev, char **envp, int num_envp,
 			  char *buffer, int buffer_size)
 {
 	return -ENODEV;
@@ -1378,8 +1379,10 @@
 
 static void nodemgr_suspend_ne(struct node_entry *ne)
 {
-	struct class_device *cdev;
+	struct device *dev;
 	struct unit_directory *ud;
+	struct device_driver *drv;
+	int error;
 
 	HPSB_DEBUG("Node suspended: ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",
 		   NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid);
@@ -1388,15 +1391,24 @@
 	WARN_ON(device_create_file(&ne->device, &dev_attr_ne_in_limbo));
 
 	down(&nodemgr_ud_class.sem);
-	list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
-		ud = container_of(cdev, struct unit_directory, class_dev);
+	list_for_each_entry(dev, &nodemgr_ud_class.devices, node) {
+		ud = container_of(dev, struct unit_directory, unit_dev);
 		if (ud->ne != ne)
 			continue;
 
-		if (ud->device.driver &&
-		    (!ud->device.driver->suspend ||
-		      ud->device.driver->suspend(&ud->device, PMSG_SUSPEND)))
+		drv = get_driver(ud->device.driver);
+		if (!drv)
+			continue;
+
+		error = 1; /* release if suspend is not implemented */
+		if (drv->suspend) {
+			down(&ud->device.sem);
+			error = drv->suspend(&ud->device, PMSG_SUSPEND);
+			up(&ud->device.sem);
+		}
+		if (error)
 			device_release_driver(&ud->device);
+		put_driver(drv);
 	}
 	up(&nodemgr_ud_class.sem);
 }
@@ -1404,20 +1416,29 @@
 
 static void nodemgr_resume_ne(struct node_entry *ne)
 {
-	struct class_device *cdev;
+	struct device *dev;
 	struct unit_directory *ud;
+	struct device_driver *drv;
 
 	ne->in_limbo = 0;
 	device_remove_file(&ne->device, &dev_attr_ne_in_limbo);
 
 	down(&nodemgr_ud_class.sem);
-	list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
-		ud = container_of(cdev, struct unit_directory, class_dev);
+	list_for_each_entry(dev, &nodemgr_ud_class.devices, node) {
+		ud = container_of(dev, struct unit_directory, unit_dev);
 		if (ud->ne != ne)
 			continue;
 
-		if (ud->device.driver && ud->device.driver->resume)
-			ud->device.driver->resume(&ud->device);
+		drv = get_driver(ud->device.driver);
+		if (!drv)
+			continue;
+
+		if (drv->resume) {
+			down(&ud->device.sem);
+			drv->resume(&ud->device);
+			up(&ud->device.sem);
+		}
+		put_driver(drv);
 	}
 	up(&nodemgr_ud_class.sem);
 
@@ -1428,23 +1449,32 @@
 
 static void nodemgr_update_pdrv(struct node_entry *ne)
 {
+	struct device *dev;
 	struct unit_directory *ud;
+	struct device_driver *drv;
 	struct hpsb_protocol_driver *pdrv;
-	struct class_device *cdev;
+	int error;
 
 	down(&nodemgr_ud_class.sem);
-	list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
-		ud = container_of(cdev, struct unit_directory, class_dev);
+	list_for_each_entry(dev, &nodemgr_ud_class.devices, node) {
+		ud = container_of(dev, struct unit_directory, unit_dev);
 		if (ud->ne != ne)
 			continue;
 
-		if (ud->device.driver) {
-			pdrv = container_of(ud->device.driver,
-					    struct hpsb_protocol_driver,
-					    driver);
-			if (pdrv->update && pdrv->update(ud))
-				device_release_driver(&ud->device);
+		drv = get_driver(ud->device.driver);
+		if (!drv)
+			continue;
+
+		error = 0;
+		pdrv = container_of(drv, struct hpsb_protocol_driver, driver);
+		if (pdrv->update) {
+			down(&ud->device.sem);
+			error = pdrv->update(ud);
+			up(&ud->device.sem);
 		}
+		if (error)
+			device_release_driver(&ud->device);
+		put_driver(drv);
 	}
 	up(&nodemgr_ud_class.sem);
 }
@@ -1509,7 +1539,7 @@
 static void nodemgr_node_probe(struct host_info *hi, int generation)
 {
 	struct hpsb_host *host = hi->host;
-	struct class_device *cdev;
+	struct device *dev;
 	struct node_entry *ne;
 
 	/* Do some processing of the nodes we've probed. This pulls them
@@ -1522,13 +1552,13 @@
 	 * improvement...) */
 
 	down(&nodemgr_ne_class.sem);
-	list_for_each_entry(cdev, &nodemgr_ne_class.children, node) {
-		ne = container_of(cdev, struct node_entry, class_dev);
+	list_for_each_entry(dev, &nodemgr_ne_class.devices, node) {
+		ne = container_of(dev, struct node_entry, node_dev);
 		if (!ne->needs_probe)
 			nodemgr_probe_ne(hi, ne, generation);
 	}
-	list_for_each_entry(cdev, &nodemgr_ne_class.children, node) {
-		ne = container_of(cdev, struct node_entry, class_dev);
+	list_for_each_entry(dev, &nodemgr_ne_class.devices, node) {
+		ne = container_of(dev, struct node_entry, node_dev);
 		if (ne->needs_probe)
 			nodemgr_probe_ne(hi, ne, generation);
 	}
@@ -1686,18 +1716,12 @@
 		if (kthread_should_stop())
 			goto exit;
 
-		if (mutex_lock_interruptible(&nodemgr_serialize)) {
-			if (try_to_freeze())
-				continue;
-			goto exit;
-		}
-
 		/* Pause for 1/4 second in 1/16 second intervals,
 		 * to make sure things settle down. */
 		g = get_hpsb_generation(host);
 		for (i = 0; i < 4 ; i++) {
 			if (msleep_interruptible(63) || kthread_should_stop())
-				goto unlock_exit;
+				goto exit;
 
 			/* Now get the generation in which the node ID's we collect
 			 * are valid.  During the bus scan we will use this generation
@@ -1715,7 +1739,6 @@
 		if (!nodemgr_check_irm_capability(host, reset_cycles) ||
 		    !nodemgr_do_irm_duties(host, reset_cycles)) {
 			reset_cycles++;
-			mutex_unlock(&nodemgr_serialize);
 			continue;
 		}
 		reset_cycles = 0;
@@ -1732,11 +1755,7 @@
 
 		/* Update some of our sysfs symlinks */
 		nodemgr_update_host_dev_links(host);
-
-		mutex_unlock(&nodemgr_serialize);
 	}
-unlock_exit:
-	mutex_unlock(&nodemgr_serialize);
 exit:
 	HPSB_VERBOSE("NodeMgr: Exiting thread");
 	return 0;
@@ -1756,13 +1775,13 @@
  */
 int nodemgr_for_each_host(void *data, int (*cb)(struct hpsb_host *, void *))
 {
-	struct class_device *cdev;
+	struct device *dev;
 	struct hpsb_host *host;
 	int error = 0;
 
 	down(&hpsb_host_class.sem);
-	list_for_each_entry(cdev, &hpsb_host_class.children, node) {
-		host = container_of(cdev, struct hpsb_host, class_dev);
+	list_for_each_entry(dev, &hpsb_host_class.devices, node) {
+		host = container_of(dev, struct hpsb_host, host_dev);
 
 		if ((error = cb(host, data)))
 			break;
diff --git a/drivers/ieee1394/nodemgr.h b/drivers/ieee1394/nodemgr.h
index 4530b29..919e92e 100644
--- a/drivers/ieee1394/nodemgr.h
+++ b/drivers/ieee1394/nodemgr.h
@@ -84,7 +84,7 @@
 	int length;		/* Number of quadlets */
 
 	struct device device;
-	struct class_device class_dev;
+	struct device unit_dev;
 
 	struct csr1212_keyval *ud_kv;
 	u32 lun;		/* logical unit number immediate value */
@@ -107,7 +107,7 @@
 	u32 capabilities;
 
 	struct device device;
-	struct class_device class_dev;
+	struct device node_dev;
 
 	/* Means this node is not attached anymore */
 	int in_limbo;
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
index 5dadfd2..5667c81 100644
--- a/drivers/ieee1394/ohci1394.c
+++ b/drivers/ieee1394/ohci1394.c
@@ -138,19 +138,6 @@
 #define DBGMSG(fmt, args...) do {} while (0)
 #endif
 
-#ifdef CONFIG_IEEE1394_OHCI_DMA_DEBUG
-#define OHCI_DMA_ALLOC(fmt, args...) \
-	HPSB_ERR("%s(%s)alloc(%d): "fmt, OHCI1394_DRIVER_NAME, __FUNCTION__, \
-		++global_outstanding_dmas, ## args)
-#define OHCI_DMA_FREE(fmt, args...) \
-	HPSB_ERR("%s(%s)free(%d): "fmt, OHCI1394_DRIVER_NAME, __FUNCTION__, \
-		--global_outstanding_dmas, ## args)
-static int global_outstanding_dmas = 0;
-#else
-#define OHCI_DMA_ALLOC(fmt, args...) do {} while (0)
-#define OHCI_DMA_FREE(fmt, args...) do {} while (0)
-#endif
-
 /* print general (card independent) information */
 #define PRINT_G(level, fmt, args...) \
 printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args)
@@ -170,7 +157,6 @@
 static int alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
 			     enum context_type type, int ctx, int num_desc,
 			     int buf_size, int split_buf_size, int context_base);
-static void stop_dma_rcv_ctx(struct dma_rcv_ctx *d);
 static void free_dma_rcv_ctx(struct dma_rcv_ctx *d);
 
 static int alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d,
@@ -533,9 +519,6 @@
 	initialize_dma_trm_ctx(&ohci->at_req_context);
 	initialize_dma_trm_ctx(&ohci->at_resp_context);
 	
-	/* Initialize IR Legacy DMA channel mask */
-	ohci->ir_legacy_channels = 0;
-
 	/* Accept AR requests from all nodes */
 	reg_write(ohci, OHCI1394_AsReqFilterHiSet, 0x80000000);
 
@@ -733,7 +716,6 @@
                                 pci_map_single(ohci->dev, packet->data,
                                                packet->data_size,
                                                PCI_DMA_TODEVICE));
-			OHCI_DMA_ALLOC("single, block transmit packet");
 
                         d->prg_cpu[idx]->end.branchAddress = 0;
                         d->prg_cpu[idx]->end.status = 0;
@@ -783,7 +765,6 @@
                 d->prg_cpu[idx]->end.address = cpu_to_le32(
 				pci_map_single(ohci->dev, packet->data,
 				packet->data_size, PCI_DMA_TODEVICE));
-		OHCI_DMA_ALLOC("single, iso transmit packet");
 
                 d->prg_cpu[idx]->end.branchAddress = 0;
                 d->prg_cpu[idx]->end.status = 0;
@@ -884,36 +865,9 @@
 		return -EOVERFLOW;
 	}
 
-	/* Decide whether we have an iso, a request, or a response packet */
 	if (packet->type == hpsb_raw)
 		d = &ohci->at_req_context;
-	else if ((packet->tcode == TCODE_ISO_DATA) && (packet->type == hpsb_iso)) {
-		/* The legacy IT DMA context is initialized on first
-		 * use.  However, the alloc cannot be run from
-		 * interrupt context, so we bail out if that is the
-		 * case. I don't see anyone sending ISO packets from
-		 * interrupt context anyway... */
-
-		if (ohci->it_legacy_context.ohci == NULL) {
-			if (in_interrupt()) {
-				PRINT(KERN_ERR,
-				      "legacy IT context cannot be initialized during interrupt");
-				return -EINVAL;
-			}
-
-			if (alloc_dma_trm_ctx(ohci, &ohci->it_legacy_context,
-					      DMA_CTX_ISO, 0, IT_NUM_DESC,
-					      OHCI1394_IsoXmitContextBase) < 0) {
-				PRINT(KERN_ERR,
-				      "error initializing legacy IT context");
-				return -ENOMEM;
-			}
-
-			initialize_dma_trm_ctx(&ohci->it_legacy_context);
-		}
-
-		d = &ohci->it_legacy_context;
-	} else if ((packet->tcode & 0x02) && (packet->tcode != TCODE_ISO_DATA))
+	else if ((packet->tcode & 0x02) && (packet->tcode != TCODE_ISO_DATA))
 		d = &ohci->at_resp_context;
 	else
 		d = &ohci->at_req_context;
@@ -932,9 +886,7 @@
 static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
 {
 	struct ti_ohci *ohci = host->hostdata;
-	int retval = 0;
-	unsigned long flags;
-	int phy_reg;
+	int retval = 0, phy_reg;
 
 	switch (cmd) {
 	case RESET_BUS:
@@ -1027,117 +979,6 @@
 		dma_trm_reset(&ohci->at_resp_context);
 		break;
 
-	case ISO_LISTEN_CHANNEL:
-        {
-		u64 mask;
-		struct dma_rcv_ctx *d = &ohci->ir_legacy_context;
-		int ir_legacy_active;
-
-		if (arg<0 || arg>63) {
-			PRINT(KERN_ERR,
-			      "%s: IS0 listen channel %d is out of range",
-			      __FUNCTION__, arg);
-			return -EFAULT;
-		}
-
-		mask = (u64)0x1<<arg;
-
-                spin_lock_irqsave(&ohci->IR_channel_lock, flags);
-
-		if (ohci->ISO_channel_usage & mask) {
-			PRINT(KERN_ERR,
-			      "%s: IS0 listen channel %d is already used",
-			      __FUNCTION__, arg);
-			spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
-			return -EFAULT;
-		}
-
-		ir_legacy_active = ohci->ir_legacy_channels;
-
-		ohci->ISO_channel_usage |= mask;
-		ohci->ir_legacy_channels |= mask;
-
-                spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
-
-		if (!ir_legacy_active) {
-			if (ohci1394_register_iso_tasklet(ohci,
-					  &ohci->ir_legacy_tasklet) < 0) {
-				PRINT(KERN_ERR, "No IR DMA context available");
-				return -EBUSY;
-			}
-
-			/* the IR context can be assigned to any DMA context
-			 * by ohci1394_register_iso_tasklet */
-			d->ctx = ohci->ir_legacy_tasklet.context;
-			d->ctrlSet = OHCI1394_IsoRcvContextControlSet +
-				32*d->ctx;
-			d->ctrlClear = OHCI1394_IsoRcvContextControlClear +
-				32*d->ctx;
-			d->cmdPtr = OHCI1394_IsoRcvCommandPtr + 32*d->ctx;
-			d->ctxtMatch = OHCI1394_IsoRcvContextMatch + 32*d->ctx;
-
-			initialize_dma_rcv_ctx(&ohci->ir_legacy_context, 1);
-
-			if (printk_ratelimit())
-				DBGMSG("IR legacy activated");
-		}
-
-                spin_lock_irqsave(&ohci->IR_channel_lock, flags);
-
-		if (arg>31)
-			reg_write(ohci, OHCI1394_IRMultiChanMaskHiSet,
-				  1<<(arg-32));
-		else
-			reg_write(ohci, OHCI1394_IRMultiChanMaskLoSet,
-				  1<<arg);
-
-                spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
-                DBGMSG("Listening enabled on channel %d", arg);
-                break;
-        }
-	case ISO_UNLISTEN_CHANNEL:
-        {
-		u64 mask;
-
-		if (arg<0 || arg>63) {
-			PRINT(KERN_ERR,
-			      "%s: IS0 unlisten channel %d is out of range",
-			      __FUNCTION__, arg);
-			return -EFAULT;
-		}
-
-		mask = (u64)0x1<<arg;
-
-                spin_lock_irqsave(&ohci->IR_channel_lock, flags);
-
-		if (!(ohci->ISO_channel_usage & mask)) {
-			PRINT(KERN_ERR,
-			      "%s: IS0 unlisten channel %d is not used",
-			      __FUNCTION__, arg);
-			spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
-			return -EFAULT;
-		}
-
-		ohci->ISO_channel_usage &= ~mask;
-		ohci->ir_legacy_channels &= ~mask;
-
-		if (arg>31)
-			reg_write(ohci, OHCI1394_IRMultiChanMaskHiClear,
-				  1<<(arg-32));
-		else
-			reg_write(ohci, OHCI1394_IRMultiChanMaskLoClear,
-				  1<<arg);
-
-                spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
-                DBGMSG("Listening disabled on channel %d", arg);
-
-		if (ohci->ir_legacy_channels == 0) {
-			stop_dma_rcv_ctx(&ohci->ir_legacy_context);
-			DBGMSG("ISO legacy receive context stopped");
-		}
-
-                break;
-        }
 	default:
 		PRINT_G(KERN_ERR, "ohci_devctl cmd %d not implemented yet",
 			cmd);
@@ -2869,12 +2710,10 @@
 		list_del_init(&packet->driver_list);
 		hpsb_packet_sent(ohci->host, packet, ack);
 
-		if (datasize) {
+		if (datasize)
 			pci_unmap_single(ohci->dev,
 					 cpu_to_le32(d->prg_cpu[d->sent_ind]->end.address),
 					 datasize, PCI_DMA_TODEVICE);
-			OHCI_DMA_FREE("single Xmit data packet");
-		}
 
 		d->sent_ind = (d->sent_ind+1)%d->num_desc;
 		d->free_prgs++;
@@ -2885,22 +2724,6 @@
 	spin_unlock_irqrestore(&d->lock, flags);
 }
 
-static void stop_dma_rcv_ctx(struct dma_rcv_ctx *d)
-{
-	if (d->ctrlClear) {
-		ohci1394_stop_context(d->ohci, d->ctrlClear, NULL);
-
-		if (d->type == DMA_CTX_ISO) {
-			/* disable interrupts */
-			reg_write(d->ohci, OHCI1394_IsoRecvIntMaskClear, 1 << d->ctx);
-			ohci1394_unregister_iso_tasklet(d->ohci, &d->ohci->ir_legacy_tasklet);
-		} else {
-			tasklet_kill(&d->task);
-		}
-	}
-}
-
-
 static void free_dma_rcv_ctx(struct dma_rcv_ctx *d)
 {
 	int i;
@@ -2913,23 +2736,19 @@
 
 	if (d->buf_cpu) {
 		for (i=0; i<d->num_desc; i++)
-			if (d->buf_cpu[i] && d->buf_bus[i]) {
+			if (d->buf_cpu[i] && d->buf_bus[i])
 				pci_free_consistent(
 					ohci->dev, d->buf_size,
 					d->buf_cpu[i], d->buf_bus[i]);
-				OHCI_DMA_FREE("consistent dma_rcv buf[%d]", i);
-			}
 		kfree(d->buf_cpu);
 		kfree(d->buf_bus);
 	}
 	if (d->prg_cpu) {
 		for (i=0; i<d->num_desc; i++)
-			if (d->prg_cpu[i] && d->prg_bus[i]) {
-				pci_pool_free(d->prg_pool, d->prg_cpu[i], d->prg_bus[i]);
-				OHCI_DMA_FREE("consistent dma_rcv prg[%d]", i);
-			}
+			if (d->prg_cpu[i] && d->prg_bus[i])
+				pci_pool_free(d->prg_pool, d->prg_cpu[i],
+					      d->prg_bus[i]);
 		pci_pool_destroy(d->prg_pool);
-		OHCI_DMA_FREE("dma_rcv prg pool");
 		kfree(d->prg_cpu);
 		kfree(d->prg_bus);
 	}
@@ -2998,13 +2817,10 @@
 	}
 	num_allocs++;
 
-	OHCI_DMA_ALLOC("dma_rcv prg pool");
-
 	for (i=0; i<d->num_desc; i++) {
 		d->buf_cpu[i] = pci_alloc_consistent(ohci->dev,
 						     d->buf_size,
 						     d->buf_bus+i);
-		OHCI_DMA_ALLOC("consistent dma_rcv buf[%d]", i);
 
 		if (d->buf_cpu[i] != NULL) {
 			memset(d->buf_cpu[i], 0, d->buf_size);
@@ -3016,7 +2832,6 @@
 		}
 
 		d->prg_cpu[i] = pci_pool_alloc(d->prg_pool, GFP_KERNEL, d->prg_bus+i);
-		OHCI_DMA_ALLOC("pool dma_rcv prg[%d]", i);
 
                 if (d->prg_cpu[i] != NULL) {
                         memset(d->prg_cpu[i], 0, sizeof(struct dma_cmd));
@@ -3030,18 +2845,11 @@
 
         spin_lock_init(&d->lock);
 
-	if (type == DMA_CTX_ISO) {
-		ohci1394_init_iso_tasklet(&ohci->ir_legacy_tasklet,
-					  OHCI_ISO_MULTICHANNEL_RECEIVE,
-					  dma_rcv_tasklet, (unsigned long) d);
-	} else {
-		d->ctrlSet = context_base + OHCI1394_ContextControlSet;
-		d->ctrlClear = context_base + OHCI1394_ContextControlClear;
-		d->cmdPtr = context_base + OHCI1394_ContextCommandPtr;
+	d->ctrlSet = context_base + OHCI1394_ContextControlSet;
+	d->ctrlClear = context_base + OHCI1394_ContextControlClear;
+	d->cmdPtr = context_base + OHCI1394_ContextCommandPtr;
 
-		tasklet_init (&d->task, dma_rcv_tasklet, (unsigned long) d);
-	}
-
+	tasklet_init(&d->task, dma_rcv_tasklet, (unsigned long) d);
 	return 0;
 }
 
@@ -3057,12 +2865,10 @@
 
 	if (d->prg_cpu) {
 		for (i=0; i<d->num_desc; i++)
-			if (d->prg_cpu[i] && d->prg_bus[i]) {
-				pci_pool_free(d->prg_pool, d->prg_cpu[i], d->prg_bus[i]);
-				OHCI_DMA_FREE("pool dma_trm prg[%d]", i);
-			}
+			if (d->prg_cpu[i] && d->prg_bus[i])
+				pci_pool_free(d->prg_pool, d->prg_cpu[i],
+					      d->prg_bus[i]);
 		pci_pool_destroy(d->prg_pool);
-		OHCI_DMA_FREE("dma_trm prg pool");
 		kfree(d->prg_cpu);
 		kfree(d->prg_bus);
 	}
@@ -3108,11 +2914,8 @@
 	}
 	num_allocs++;
 
-	OHCI_DMA_ALLOC("dma_rcv prg pool");
-
 	for (i = 0; i < d->num_desc; i++) {
 		d->prg_cpu[i] = pci_pool_alloc(d->prg_pool, GFP_KERNEL, d->prg_bus+i);
-		OHCI_DMA_ALLOC("pool dma_trm prg[%d]", i);
 
                 if (d->prg_cpu[i] != NULL) {
                         memset(d->prg_cpu[i], 0, sizeof(struct at_dma_prg));
@@ -3127,28 +2930,10 @@
         spin_lock_init(&d->lock);
 
 	/* initialize tasklet */
-	if (type == DMA_CTX_ISO) {
-		ohci1394_init_iso_tasklet(&ohci->it_legacy_tasklet, OHCI_ISO_TRANSMIT,
-					  dma_trm_tasklet, (unsigned long) d);
-		if (ohci1394_register_iso_tasklet(ohci,
-						  &ohci->it_legacy_tasklet) < 0) {
-			PRINT(KERN_ERR, "No IT DMA context available");
-			free_dma_trm_ctx(d);
-			return -EBUSY;
-		}
-
-		/* IT can be assigned to any context by register_iso_tasklet */
-		d->ctx = ohci->it_legacy_tasklet.context;
-		d->ctrlSet = OHCI1394_IsoXmitContextControlSet + 16 * d->ctx;
-		d->ctrlClear = OHCI1394_IsoXmitContextControlClear + 16 * d->ctx;
-		d->cmdPtr = OHCI1394_IsoXmitCommandPtr + 16 * d->ctx;
-	} else {
-		d->ctrlSet = context_base + OHCI1394_ContextControlSet;
-		d->ctrlClear = context_base + OHCI1394_ContextControlClear;
-		d->cmdPtr = context_base + OHCI1394_ContextCommandPtr;
-		tasklet_init (&d->task, dma_trm_tasklet, (unsigned long)d);
-	}
-
+	d->ctrlSet = context_base + OHCI1394_ContextControlSet;
+	d->ctrlClear = context_base + OHCI1394_ContextControlClear;
+	d->cmdPtr = context_base + OHCI1394_ContextCommandPtr;
+	tasklet_init(&d->task, dma_trm_tasklet, (unsigned long)d);
 	return 0;
 }
 
@@ -3294,7 +3079,6 @@
 	ohci->csr_config_rom_cpu =
 		pci_alloc_consistent(ohci->dev, OHCI_CONFIG_ROM_LEN,
 				     &ohci->csr_config_rom_bus);
-	OHCI_DMA_ALLOC("consistent csr_config_rom");
 	if (ohci->csr_config_rom_cpu == NULL)
 		FAIL(-ENOMEM, "Failed to allocate buffer config rom");
 	ohci->init_state = OHCI_INIT_HAVE_CONFIG_ROM_BUFFER;
@@ -3303,8 +3087,6 @@
 	ohci->selfid_buf_cpu =
 		pci_alloc_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE,
                       &ohci->selfid_buf_bus);
-	OHCI_DMA_ALLOC("consistent selfid_buf");
-
 	if (ohci->selfid_buf_cpu == NULL)
 		FAIL(-ENOMEM, "Failed to allocate DMA buffer for self-id packets");
 	ohci->init_state = OHCI_INIT_HAVE_SELFID_BUFFER;
@@ -3377,20 +3159,6 @@
 	ohci->ISO_channel_usage = 0;
         spin_lock_init(&ohci->IR_channel_lock);
 
-	/* Allocate the IR DMA context right here so we don't have
-	 * to do it in interrupt path - note that this doesn't
-	 * waste much memory and avoids the jugglery required to
-	 * allocate it in IRQ path. */
-	if (alloc_dma_rcv_ctx(ohci, &ohci->ir_legacy_context,
-			      DMA_CTX_ISO, 0, IR_NUM_DESC,
-			      IR_BUF_SIZE, IR_SPLIT_BUF_SIZE,
-			      OHCI1394_IsoRcvContextBase) < 0) {
-		FAIL(-ENOMEM, "Cannot allocate IR Legacy DMA context");
-	}
-
-	/* We hopefully don't have to pre-allocate IT DMA like we did
-	 * for IR DMA above. Allocate it on-demand and mark inactive. */
-	ohci->it_legacy_context.ohci = NULL;
 	spin_lock_init(&ohci->event_lock);
 
 	/*
@@ -3483,20 +3251,16 @@
 		free_dma_rcv_ctx(&ohci->ar_resp_context);
 		free_dma_trm_ctx(&ohci->at_req_context);
 		free_dma_trm_ctx(&ohci->at_resp_context);
-		free_dma_rcv_ctx(&ohci->ir_legacy_context);
-		free_dma_trm_ctx(&ohci->it_legacy_context);
 
 	case OHCI_INIT_HAVE_SELFID_BUFFER:
 		pci_free_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE,
 				    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,
 				    ohci->csr_config_rom_bus);
-		OHCI_DMA_FREE("consistent csr_config_rom");
 
 	case OHCI_INIT_HAVE_IOMAPPING:
 		iounmap(ohci->registers);
diff --git a/drivers/ieee1394/ohci1394.h b/drivers/ieee1394/ohci1394.h
index f1ad539..4320bf01 100644
--- a/drivers/ieee1394/ohci1394.h
+++ b/drivers/ieee1394/ohci1394.h
@@ -190,23 +190,10 @@
 	unsigned long ir_multichannel_used; /* ditto */
         spinlock_t IR_channel_lock;
 
-	/* iso receive (legacy API) */
-	u64 ir_legacy_channels; /* note: this differs from ISO_channel_usage;
-				   it only accounts for channels listened to
-				   by the legacy API, so that we can know when
-				   it is safe to free the legacy API context */
-
-	struct dma_rcv_ctx ir_legacy_context;
-	struct ohci1394_iso_tasklet ir_legacy_tasklet;
-
         /* iso transmit */
 	int nb_iso_xmit_ctx;
 	unsigned long it_ctx_usage; /* use test_and_set_bit() for atomicity */
 
-	/* iso transmit (legacy API) */
-	struct dma_trm_ctx it_legacy_context;
-	struct ohci1394_iso_tasklet it_legacy_tasklet;
-
         u64 ISO_channel_usage;
 
         /* IEEE-1394 part follows */
@@ -221,7 +208,6 @@
 
 	/* Tasklets for iso receive and transmit, used by video1394
 	 * and dv1394 */
-
 	struct list_head iso_tasklet_list;
 	spinlock_t iso_tasklet_list_lock;
 
diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c
index 0742bef..d1a5bcd 100644
--- a/drivers/ieee1394/pcilynx.c
+++ b/drivers/ieee1394/pcilynx.c
@@ -477,7 +477,11 @@
         struct lynx_send_data *d;
         struct hpsb_packet *packet;
 
+#if 0 /* has been removed from ieee1394 core */
         d = (what == hpsb_iso ? &lynx->iso_send : &lynx->async);
+#else
+	d = &lynx->async;
+#endif
         if (!list_empty(&d->pcl_queue)) {
                 PRINT(KERN_ERR, lynx->id, "trying to queue a new packet in nonempty fifo");
                 BUG();
@@ -511,9 +515,11 @@
         case hpsb_async:
                 pcl.buffer[0].control |= PCL_CMD_XMT;
                 break;
+#if 0 /* has been removed from ieee1394 core */
         case hpsb_iso:
                 pcl.buffer[0].control |= PCL_CMD_XMT | PCL_ISOMODE;
                 break;
+#endif
         case hpsb_raw:
                 pcl.buffer[0].control |= PCL_CMD_UNFXMT;
                 break;
@@ -542,9 +548,11 @@
         case hpsb_raw:
                 d = &lynx->async;
                 break;
+#if 0 /* has been removed from ieee1394 core */
         case hpsb_iso:
                 d = &lynx->iso_send;
                 break;
+#endif
         default:
                 PRINT(KERN_ERR, lynx->id, "invalid packet type %d",
                       packet->type);
@@ -797,7 +805,7 @@
 		}
 
                 break;
-
+#if 0 /* has been removed from ieee1394 core */
         case ISO_LISTEN_CHANNEL:
                 spin_lock_irqsave(&lynx->iso_rcv.lock, flags);
 
@@ -819,7 +827,7 @@
 
                 spin_unlock_irqrestore(&lynx->iso_rcv.lock, flags);
                 break;
-
+#endif
         default:
                 PRINT(KERN_ERR, lynx->id, "unknown devctl command %d", cmd);
                 retval = -1;
@@ -1009,11 +1017,11 @@
                                 pci_unmap_single(lynx->dev, lynx->iso_send.data_dma,
                                                  packet->data_size, PCI_DMA_TODEVICE);
                         }
-
+#if 0 /* has been removed from ieee1394 core */
                         if (!list_empty(&lynx->iso_send.queue)) {
                                 send_next(lynx, hpsb_iso);
                         }
-
+#endif
                         spin_unlock(&lynx->iso_send.queue_lock);
 
                         if (pcl.pcl_status & DMA_CHAN_STAT_PKTCMPL) {
diff --git a/drivers/ieee1394/raw1394-private.h b/drivers/ieee1394/raw1394-private.h
index 50daabf..a06aaad 100644
--- a/drivers/ieee1394/raw1394-private.h
+++ b/drivers/ieee1394/raw1394-private.h
@@ -36,11 +36,6 @@
 
         u8 __user *fcp_buffer;
 
-	/* old ISO API */
-        u64 listen_channels;
-        quadlet_t __user *iso_buffer;
-        size_t iso_buffer_length;
-
         u8 notification; /* (busreset-notification) RAW1394_NOTIFY_OFF/ON */
 
 	/* new rawiso API */
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
index f1d05ee..336e5ff 100644
--- a/drivers/ieee1394/raw1394.c
+++ b/drivers/ieee1394/raw1394.c
@@ -98,21 +98,6 @@
 
 static void queue_complete_cb(struct pending_request *req);
 
-#include <asm/current.h>
-static void print_old_iso_deprecation(void)
-{
-	static pid_t p;
-
-	if (p == current->pid)
-		return;
-	p = current->pid;
-	printk(KERN_WARNING "raw1394: WARNING - Program \"%s\" uses unsupported"
-	       " isochronous request types which will be removed in a next"
-	       " kernel release\n", current->comm);
-	printk(KERN_WARNING "raw1394: Update your software to use libraw1394's"
-	       " newer interface\n");
-}
-
 static struct pending_request *__alloc_pending_request(gfp_t flags)
 {
 	struct pending_request *req;
@@ -297,67 +282,6 @@
 	spin_unlock_irqrestore(&host_info_lock, flags);
 }
 
-static void iso_receive(struct hpsb_host *host, int channel, quadlet_t * data,
-			size_t length)
-{
-	unsigned long flags;
-	struct host_info *hi;
-	struct file_info *fi;
-	struct pending_request *req, *req_next;
-	struct iso_block_store *ibs = NULL;
-	LIST_HEAD(reqs);
-
-	if ((atomic_read(&iso_buffer_size) + length) > iso_buffer_max) {
-		HPSB_INFO("dropped iso packet");
-		return;
-	}
-
-	spin_lock_irqsave(&host_info_lock, flags);
-	hi = find_host_info(host);
-
-	if (hi != NULL) {
-		list_for_each_entry(fi, &hi->file_info_list, list) {
-			if (!(fi->listen_channels & (1ULL << channel)))
-				continue;
-
-			req = __alloc_pending_request(GFP_ATOMIC);
-			if (!req)
-				break;
-
-			if (!ibs) {
-				ibs = kmalloc(sizeof(*ibs) + length,
-					      GFP_ATOMIC);
-				if (!ibs) {
-					kfree(req);
-					break;
-				}
-
-				atomic_add(length, &iso_buffer_size);
-				atomic_set(&ibs->refcount, 0);
-				ibs->data_size = length;
-				memcpy(ibs->data, data, length);
-			}
-
-			atomic_inc(&ibs->refcount);
-
-			req->file_info = fi;
-			req->ibs = ibs;
-			req->data = ibs->data;
-			req->req.type = RAW1394_REQ_ISO_RECEIVE;
-			req->req.generation = get_hpsb_generation(host);
-			req->req.misc = 0;
-			req->req.recvb = ptr2int(fi->iso_buffer);
-			req->req.length = min(length, fi->iso_buffer_length);
-
-			list_add_tail(&req->list, &reqs);
-		}
-	}
-	spin_unlock_irqrestore(&host_info_lock, flags);
-
-	list_for_each_entry_safe(req, req_next, &reqs, list)
-	    queue_complete_req(req);
-}
-
 static void fcp_request(struct hpsb_host *host, int nodeid, int direction,
 			int cts, u8 * data, size_t length)
 {
@@ -434,7 +358,11 @@
 
 	__u64 sendb;
 	__u64 recvb;
-} __attribute__((packed));
+}
+#if defined(CONFIG_X86_64) || defined(CONFIG_IA64)
+__attribute__((packed))
+#endif
+;
 
 static const char __user *raw1394_compat_write(const char __user *buf)
 {
@@ -459,7 +387,7 @@
 static int
 raw1394_compat_read(const char __user *buf, struct raw1394_request *r)
 {
-	struct compat_raw1394_req __user *cr = (typeof(cr)) r;
+	struct compat_raw1394_req __user *cr = (typeof(cr)) buf;
 	if (!access_ok(VERIFY_WRITE, cr, sizeof(struct compat_raw1394_req)) ||
 	    P(type) ||
 	    P(error) ||
@@ -587,7 +515,7 @@
 
 	req->req.length = 0;
 	queue_complete_req(req);
-	return sizeof(struct raw1394_request);
+	return 0;
 }
 
 static int state_initialized(struct file_info *fi, struct pending_request *req)
@@ -601,7 +529,7 @@
 		req->req.generation = atomic_read(&internal_generation);
 		req->req.length = 0;
 		queue_complete_req(req);
-		return sizeof(struct raw1394_request);
+		return 0;
 	}
 
 	switch (req->req.type) {
@@ -673,44 +601,7 @@
 	}
 
 	queue_complete_req(req);
-	return sizeof(struct raw1394_request);
-}
-
-static void handle_iso_listen(struct file_info *fi, struct pending_request *req)
-{
-	int channel = req->req.misc;
-
-	if ((channel > 63) || (channel < -64)) {
-		req->req.error = RAW1394_ERROR_INVALID_ARG;
-	} else if (channel >= 0) {
-		/* allocate channel req.misc */
-		if (fi->listen_channels & (1ULL << channel)) {
-			req->req.error = RAW1394_ERROR_ALREADY;
-		} else {
-			if (hpsb_listen_channel
-			    (&raw1394_highlevel, fi->host, channel)) {
-				req->req.error = RAW1394_ERROR_ALREADY;
-			} else {
-				fi->listen_channels |= 1ULL << channel;
-				fi->iso_buffer = int2ptr(req->req.recvb);
-				fi->iso_buffer_length = req->req.length;
-			}
-		}
-	} else {
-		/* deallocate channel (one's complement neg) req.misc */
-		channel = ~channel;
-
-		if (fi->listen_channels & (1ULL << channel)) {
-			hpsb_unlisten_channel(&raw1394_highlevel, fi->host,
-					      channel);
-			fi->listen_channels &= ~(1ULL << channel);
-		} else {
-			req->req.error = RAW1394_ERROR_INVALID_ARG;
-		}
-	}
-
-	req->req.length = 0;
-	queue_complete_req(req);
+	return 0;
 }
 
 static void handle_fcp_listen(struct file_info *fi, struct pending_request *req)
@@ -865,7 +756,7 @@
 	if (req->req.error) {
 		req->req.length = 0;
 		queue_complete_req(req);
-		return sizeof(struct raw1394_request);
+		return 0;
 	}
 
 	hpsb_set_packet_complete_task(packet,
@@ -883,51 +774,7 @@
 		hpsb_free_tlabel(packet);
 		queue_complete_req(req);
 	}
-	return sizeof(struct raw1394_request);
-}
-
-static int handle_iso_send(struct file_info *fi, struct pending_request *req,
-			   int channel)
-{
-	unsigned long flags;
-	struct hpsb_packet *packet;
-
-	packet = hpsb_make_isopacket(fi->host, req->req.length, channel & 0x3f,
-				     (req->req.misc >> 16) & 0x3,
-				     req->req.misc & 0xf);
-	if (!packet)
-		return -ENOMEM;
-
-	packet->speed_code = req->req.address & 0x3;
-
-	req->packet = packet;
-
-	if (copy_from_user(packet->data, int2ptr(req->req.sendb),
-			   req->req.length)) {
-		req->req.error = RAW1394_ERROR_MEMFAULT;
-		req->req.length = 0;
-		queue_complete_req(req);
-		return sizeof(struct raw1394_request);
-	}
-
-	req->req.length = 0;
-	hpsb_set_packet_complete_task(packet,
-				      (void (*)(void *))queue_complete_req,
-				      req);
-
-	spin_lock_irqsave(&fi->reqlists_lock, flags);
-	list_add_tail(&req->list, &fi->req_pending);
-	spin_unlock_irqrestore(&fi->reqlists_lock, flags);
-
-	/* Update the generation of the packet just before sending. */
-	packet->generation = req->req.generation;
-
-	if (hpsb_send_packet(packet) < 0) {
-		req->req.error = RAW1394_ERROR_SEND_ERROR;
-		queue_complete_req(req);
-	}
-
-	return sizeof(struct raw1394_request);
+	return 0;
 }
 
 static int handle_async_send(struct file_info *fi, struct pending_request *req)
@@ -943,7 +790,7 @@
 		req->req.error = RAW1394_ERROR_INVALID_ARG;
 		req->req.length = 0;
 		queue_complete_req(req);
-		return sizeof(struct raw1394_request);
+		return 0;
 	}
 
 	data_size = req->req.length - header_length;
@@ -957,7 +804,7 @@
 		req->req.error = RAW1394_ERROR_MEMFAULT;
 		req->req.length = 0;
 		queue_complete_req(req);
-		return sizeof(struct raw1394_request);
+		return 0;
 	}
 
 	if (copy_from_user
@@ -966,7 +813,7 @@
 		req->req.error = RAW1394_ERROR_MEMFAULT;
 		req->req.length = 0;
 		queue_complete_req(req);
-		return sizeof(struct raw1394_request);
+		return 0;
 	}
 
 	packet->type = hpsb_async;
@@ -994,7 +841,7 @@
 		queue_complete_req(req);
 	}
 
-	return sizeof(struct raw1394_request);
+	return 0;
 }
 
 static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer,
@@ -1869,7 +1716,7 @@
 		spin_lock_irqsave(&host_info_lock, flags);
 		list_add_tail(&addr->addr_list, &fi->addr_list);
 		spin_unlock_irqrestore(&host_info_lock, flags);
-		return sizeof(struct raw1394_request);
+		return 0;
 	}
 	retval =
 	    hpsb_register_addrspace(&raw1394_highlevel, fi->host, &arm_ops,
@@ -1887,7 +1734,7 @@
 		return (-EALREADY);
 	}
 	free_pending_request(req);	/* immediate success or fail */
-	return sizeof(struct raw1394_request);
+	return 0;
 }
 
 static int arm_unregister(struct file_info *fi, struct pending_request *req)
@@ -1955,7 +1802,7 @@
 		vfree(addr->addr_space_buffer);
 		kfree(addr);
 		free_pending_request(req);	/* immediate success or fail */
-		return sizeof(struct raw1394_request);
+		return 0;
 	}
 	retval =
 	    hpsb_unregister_addrspace(&raw1394_highlevel, fi->host,
@@ -1971,7 +1818,7 @@
 	vfree(addr->addr_space_buffer);
 	kfree(addr);
 	free_pending_request(req);	/* immediate success or fail */
-	return sizeof(struct raw1394_request);
+	return 0;
 }
 
 /* Copy data from ARM buffer(s) to user buffer. */
@@ -2013,7 +1860,7 @@
 				 * queue no response, and therefore nobody
 				 * will free it. */
 				free_pending_request(req);
-				return sizeof(struct raw1394_request);
+				return 0;
 			} else {
 				DBGMSG("arm_get_buf request exceeded mapping");
 				spin_unlock_irqrestore(&host_info_lock, flags);
@@ -2065,7 +1912,7 @@
 				 * queue no response, and therefore nobody
 				 * will free it. */
 				free_pending_request(req);
-				return sizeof(struct raw1394_request);
+				return 0;
 			} else {
 				DBGMSG("arm_set_buf request exceeded mapping");
 				spin_unlock_irqrestore(&host_info_lock, flags);
@@ -2086,7 +1933,7 @@
 	    (req->req.misc == RAW1394_NOTIFY_ON)) {
 		fi->notification = (u8) req->req.misc;
 		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);
+		return 0;
 	}
 	/* error EINVAL (22) invalid argument */
 	return (-EINVAL);
@@ -2119,12 +1966,12 @@
 		req->req.length = 0;
 		queue_complete_req(req);
 	}
-	return sizeof(struct raw1394_request);
+	return 0;
 }
 
 static int get_config_rom(struct file_info *fi, struct pending_request *req)
 {
-	int ret = sizeof(struct raw1394_request);
+	int ret = 0;
 	quadlet_t *data = kmalloc(req->req.length, GFP_KERNEL);
 	int status;
 
@@ -2154,7 +2001,7 @@
 
 static int update_config_rom(struct file_info *fi, struct pending_request *req)
 {
-	int ret = sizeof(struct raw1394_request);
+	int ret = 0;
 	quadlet_t *data = kmalloc(req->req.length, GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
@@ -2221,7 +2068,7 @@
 
 			hpsb_update_config_rom_image(fi->host);
 			free_pending_request(req);
-			return sizeof(struct raw1394_request);
+			return 0;
 		}
 	}
 
@@ -2286,7 +2133,7 @@
 		/* we have to free the request, because we queue no response,
 		 * and therefore nobody will free it */
 		free_pending_request(req);
-		return sizeof(struct raw1394_request);
+		return 0;
 	} else {
 		for (dentry =
 		     fi->csr1212_dirs[dr]->value.directory.dentries_head;
@@ -2311,11 +2158,7 @@
 
 	case RAW1394_REQ_ECHO:
 		queue_complete_req(req);
-		return sizeof(struct raw1394_request);
-
-	case RAW1394_REQ_ISO_SEND:
-		print_old_iso_deprecation();
-		return handle_iso_send(fi, req, node);
+		return 0;
 
 	case RAW1394_REQ_ARM_REGISTER:
 		return arm_register(fi, req);
@@ -2332,27 +2175,30 @@
 	case RAW1394_REQ_RESET_NOTIFY:
 		return reset_notification(fi, req);
 
+	case RAW1394_REQ_ISO_SEND:
 	case RAW1394_REQ_ISO_LISTEN:
-		print_old_iso_deprecation();
-		handle_iso_listen(fi, req);
-		return sizeof(struct raw1394_request);
+		printk(KERN_DEBUG "raw1394: old iso ABI has been removed\n");
+		req->req.error = RAW1394_ERROR_COMPAT;
+		req->req.misc = RAW1394_KERNELAPI_VERSION;
+		queue_complete_req(req);
+		return 0;
 
 	case RAW1394_REQ_FCP_LISTEN:
 		handle_fcp_listen(fi, req);
-		return sizeof(struct raw1394_request);
+		return 0;
 
 	case RAW1394_REQ_RESET_BUS:
 		if (req->req.misc == RAW1394_LONG_RESET) {
 			DBGMSG("busreset called (type: LONG)");
 			hpsb_reset_bus(fi->host, LONG_RESET);
 			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);
+			return 0;
 		}
 		if (req->req.misc == RAW1394_SHORT_RESET) {
 			DBGMSG("busreset called (type: SHORT)");
 			hpsb_reset_bus(fi->host, SHORT_RESET);
 			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);
+			return 0;
 		}
 		/* error EINVAL (22) invalid argument */
 		return (-EINVAL);
@@ -2371,7 +2217,7 @@
 		req->req.generation = get_hpsb_generation(fi->host);
 		req->req.length = 0;
 		queue_complete_req(req);
-		return sizeof(struct raw1394_request);
+		return 0;
 	}
 
 	switch (req->req.type) {
@@ -2384,7 +2230,7 @@
 	if (req->req.length == 0) {
 		req->req.error = RAW1394_ERROR_INVALID_ARG;
 		queue_complete_req(req);
-		return sizeof(struct raw1394_request);
+		return 0;
 	}
 
 	return handle_async_request(fi, req, node);
@@ -2395,7 +2241,7 @@
 {
 	struct file_info *fi = (struct file_info *)file->private_data;
 	struct pending_request *req;
-	ssize_t retval = 0;
+	ssize_t retval = -EBADFD;
 
 #ifdef CONFIG_COMPAT
 	if (count == sizeof(struct compat_raw1394_req) &&
@@ -2437,6 +2283,9 @@
 
 	if (retval < 0) {
 		free_pending_request(req);
+	} else {
+		BUG_ON(retval);
+		retval = count;
 	}
 
 	return retval;
@@ -2802,6 +2651,103 @@
 	return -EINVAL;
 }
 
+#ifdef CONFIG_COMPAT
+struct raw1394_iso_packets32 {
+        __u32 n_packets;
+        compat_uptr_t infos;
+} __attribute__((packed));
+
+struct raw1394_cycle_timer32 {
+        __u32 cycle_timer;
+        __u64 local_time;
+}
+#if defined(CONFIG_X86_64) || defined(CONFIG_IA64)
+__attribute__((packed))
+#endif
+;
+
+#define RAW1394_IOC_ISO_RECV_PACKETS32          \
+        _IOW ('#', 0x25, struct raw1394_iso_packets32)
+#define RAW1394_IOC_ISO_XMIT_PACKETS32          \
+        _IOW ('#', 0x27, struct raw1394_iso_packets32)
+#define RAW1394_IOC_GET_CYCLE_TIMER32           \
+        _IOR ('#', 0x30, struct raw1394_cycle_timer32)
+
+static long raw1394_iso_xmit_recv_packets32(struct file *file, unsigned int cmd,
+                                          struct raw1394_iso_packets32 __user *arg)
+{
+	compat_uptr_t infos32;
+	void *infos;
+	long err = -EFAULT;
+	struct raw1394_iso_packets __user *dst = compat_alloc_user_space(sizeof(struct raw1394_iso_packets));
+
+	if (!copy_in_user(&dst->n_packets, &arg->n_packets, sizeof arg->n_packets) &&
+	    !copy_from_user(&infos32, &arg->infos, sizeof infos32)) {
+		infos = compat_ptr(infos32);
+		if (!copy_to_user(&dst->infos, &infos, sizeof infos))
+			err = raw1394_ioctl(NULL, file, cmd, (unsigned long)dst);
+	}
+	return err;
+}
+
+static long raw1394_read_cycle_timer32(struct file_info *fi, void __user * uaddr)
+{
+	struct raw1394_cycle_timer32 ct;
+	int err;
+
+	err = hpsb_read_cycle_timer(fi->host, &ct.cycle_timer, &ct.local_time);
+	if (!err)
+		if (copy_to_user(uaddr, &ct, sizeof(ct)))
+			err = -EFAULT;
+	return err;
+}
+
+static long raw1394_compat_ioctl(struct file *file,
+				 unsigned int cmd, unsigned long arg)
+{
+	struct file_info *fi = file->private_data;
+	void __user *argp = (void __user *)arg;
+	long err;
+
+	lock_kernel();
+	switch (cmd) {
+	/* These requests have same format as long as 'int' has same size. */
+	case RAW1394_IOC_ISO_RECV_INIT:
+	case RAW1394_IOC_ISO_RECV_START:
+	case RAW1394_IOC_ISO_RECV_LISTEN_CHANNEL:
+	case RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL:
+	case RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK:
+	case RAW1394_IOC_ISO_RECV_RELEASE_PACKETS:
+	case RAW1394_IOC_ISO_RECV_FLUSH:
+	case RAW1394_IOC_ISO_XMIT_RECV_STOP:
+	case RAW1394_IOC_ISO_XMIT_INIT:
+	case RAW1394_IOC_ISO_XMIT_START:
+	case RAW1394_IOC_ISO_XMIT_SYNC:
+	case RAW1394_IOC_ISO_GET_STATUS:
+	case RAW1394_IOC_ISO_SHUTDOWN:
+	case RAW1394_IOC_ISO_QUEUE_ACTIVITY:
+		err = raw1394_ioctl(NULL, file, cmd, arg);
+		break;
+	/* These request have different format. */
+	case RAW1394_IOC_ISO_RECV_PACKETS32:
+		err = raw1394_iso_xmit_recv_packets32(file, RAW1394_IOC_ISO_RECV_PACKETS, argp);
+		break;
+	case RAW1394_IOC_ISO_XMIT_PACKETS32:
+		err = raw1394_iso_xmit_recv_packets32(file, RAW1394_IOC_ISO_XMIT_PACKETS, argp);
+		break;
+	case RAW1394_IOC_GET_CYCLE_TIMER32:
+		err = raw1394_read_cycle_timer32(fi, argp);
+		break;
+	default:
+		err = -EINVAL;
+		break;
+	}
+	unlock_kernel();
+
+	return err;
+}
+#endif
+
 static unsigned int raw1394_poll(struct file *file, poll_table * pt)
 {
 	struct file_info *fi = file->private_data;
@@ -2861,14 +2807,7 @@
 	if (fi->iso_state != RAW1394_ISO_INACTIVE)
 		raw1394_iso_shutdown(fi);
 
-	for (i = 0; i < 64; i++) {
-		if (fi->listen_channels & (1ULL << i)) {
-			hpsb_unlisten_channel(&raw1394_highlevel, fi->host, i);
-		}
-	}
-
 	spin_lock_irqsave(&host_info_lock, flags);
-	fi->listen_channels = 0;
 
 	fail = 0;
 	/* set address-entries invalid */
@@ -3030,7 +2969,6 @@
 	.add_host = add_host,
 	.remove_host = remove_host,
 	.host_reset = host_reset,
-	.iso_receive = iso_receive,
 	.fcp_request = fcp_request,
 };
 
@@ -3041,7 +2979,9 @@
 	.write = raw1394_write,
 	.mmap = raw1394_mmap,
 	.ioctl = raw1394_ioctl,
-	// .compat_ioctl = ... someone needs to do this
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = raw1394_compat_ioctl,
+#endif
 	.poll = raw1394_poll,
 	.open = raw1394_open,
 	.release = raw1394_release,
@@ -3054,9 +2994,9 @@
 	hpsb_register_highlevel(&raw1394_highlevel);
 
 	if (IS_ERR
-	    (class_device_create
-	     (hpsb_protocol_class, NULL,
-	      MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16), NULL,
+	    (device_create(
+	      hpsb_protocol_class, NULL,
+	      MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16),
 	      RAW1394_DEVICE_NAME))) {
 		ret = -EFAULT;
 		goto out_unreg;
@@ -3083,9 +3023,9 @@
 	goto out;
 
       out_dev:
-	class_device_destroy(hpsb_protocol_class,
-			     MKDEV(IEEE1394_MAJOR,
-				   IEEE1394_MINOR_BLOCK_RAW1394 * 16));
+	device_destroy(hpsb_protocol_class,
+		       MKDEV(IEEE1394_MAJOR,
+			     IEEE1394_MINOR_BLOCK_RAW1394 * 16));
       out_unreg:
 	hpsb_unregister_highlevel(&raw1394_highlevel);
       out:
@@ -3094,9 +3034,9 @@
 
 static void __exit cleanup_raw1394(void)
 {
-	class_device_destroy(hpsb_protocol_class,
-			     MKDEV(IEEE1394_MAJOR,
-				   IEEE1394_MINOR_BLOCK_RAW1394 * 16));
+	device_destroy(hpsb_protocol_class,
+		       MKDEV(IEEE1394_MAJOR,
+			     IEEE1394_MINOR_BLOCK_RAW1394 * 16));
 	cdev_del(&raw1394_cdev);
 	hpsb_unregister_highlevel(&raw1394_highlevel);
 	hpsb_unregister_protocol(&raw1394_driver);
diff --git a/drivers/ieee1394/raw1394.h b/drivers/ieee1394/raw1394.h
index 7bd22ee..963ac20 100644
--- a/drivers/ieee1394/raw1394.h
+++ b/drivers/ieee1394/raw1394.h
@@ -17,11 +17,11 @@
 #define RAW1394_REQ_ASYNC_WRITE     101
 #define RAW1394_REQ_LOCK            102
 #define RAW1394_REQ_LOCK64          103
-#define RAW1394_REQ_ISO_SEND        104
+#define RAW1394_REQ_ISO_SEND        104 /* removed ABI, now a no-op */
 #define RAW1394_REQ_ASYNC_SEND      105
 #define RAW1394_REQ_ASYNC_STREAM    106
 
-#define RAW1394_REQ_ISO_LISTEN      200
+#define RAW1394_REQ_ISO_LISTEN      200 /* removed ABI, now a no-op */
 #define RAW1394_REQ_FCP_LISTEN      201
 #define RAW1394_REQ_RESET_BUS       202
 #define RAW1394_REQ_GET_ROM         203
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index 3f873cc7..e0c385a 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -118,14 +118,13 @@
 		 "(3 = 800Mb/s, 2 = 400Mb/s, 1 = 200Mb/s, 0 = 100Mb/s)");
 
 /*
- * Set serialize_io to 1 if you'd like only one scsi command sent
- * down to us at a time (debugging). This might be necessary for very
- * badly behaved sbp2 devices.
+ * Set serialize_io to 0 or N to use dynamically appended lists of command ORBs.
+ * This is and always has been buggy in multiple subtle ways. See above TODOs.
  */
 static int sbp2_serialize_io = 1;
-module_param_named(serialize_io, sbp2_serialize_io, int, 0444);
-MODULE_PARM_DESC(serialize_io, "Serialize I/O coming from scsi drivers "
-		 "(default = 1, faster = 0)");
+module_param_named(serialize_io, sbp2_serialize_io, bool, 0444);
+MODULE_PARM_DESC(serialize_io, "Serialize requests coming from SCSI drivers "
+		 "(default = Y, faster but buggy = N)");
 
 /*
  * Bump up max_sectors if you'd like to support very large sized
@@ -154,9 +153,9 @@
  * are possible on OXFW911 and newer Oxsemi bridges.
  */
 static int sbp2_exclusive_login = 1;
-module_param_named(exclusive_login, sbp2_exclusive_login, int, 0644);
+module_param_named(exclusive_login, sbp2_exclusive_login, bool, 0644);
 MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device "
-		 "(default = 1)");
+		 "(default = Y, use N for concurrent initiators)");
 
 /*
  * If any of the following workarounds is required for your device to work,
diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h
index 44402b9..333a4bb 100644
--- a/drivers/ieee1394/sbp2.h
+++ b/drivers/ieee1394/sbp2.h
@@ -67,7 +67,7 @@
 #define ORB_SET_LUN(v)			((v) & 0xffff)
 #define ORB_SET_FUNCTION(v)		(((v) & 0xf) << 16)
 #define ORB_SET_RECONNECT(v)		(((v) & 0xf) << 20)
-#define ORB_SET_EXCLUSIVE(v)		(((v) & 0x1) << 28)
+#define ORB_SET_EXCLUSIVE(v)		((v) ? 1 << 28 : 0)
 #define ORB_SET_LOGIN_RESP_LENGTH(v)	((v) & 0xffff)
 #define ORB_SET_PASSWD_LENGTH(v)	(((v) & 0xffff) << 16)
 
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
index 87ebd08..bd28adf 100644
--- a/drivers/ieee1394/video1394.c
+++ b/drivers/ieee1394/video1394.c
@@ -1340,9 +1340,9 @@
 	hpsb_set_hostinfo_key(&video1394_highlevel, host, ohci->host->id);
 
 	minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id;
-	class_device_create(hpsb_protocol_class, NULL, MKDEV(
-		IEEE1394_MAJOR,	minor), 
-		NULL, "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
+	device_create(hpsb_protocol_class, NULL,
+		      MKDEV(IEEE1394_MAJOR, minor),
+		      "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
 }
 
 
@@ -1351,8 +1351,8 @@
 	struct ti_ohci *ohci = hpsb_get_hostinfo(&video1394_highlevel, host);
 
 	if (ohci)
-		class_device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR,
-			IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id));
+		device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR,
+			       IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id));
 	return;
 }
 
diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h
index efbe1fd..1a45d6f 100644
--- a/include/linux/firewire-cdev.h
+++ b/include/linux/firewire-cdev.h
@@ -30,16 +30,38 @@
 #define FW_CDEV_EVENT_REQUEST		0x02
 #define FW_CDEV_EVENT_ISO_INTERRUPT	0x03
 
-/* The 'closure' fields are for user space to use.  Data passed in the
- * 'closure' field for a request will be returned in the corresponding
- * event.  It's a 64-bit type so that it's a fixed size type big
- * enough to hold a pointer on all platforms. */
-
+/**
+ * struct fw_cdev_event_common - Common part of all fw_cdev_event_ types
+ * @closure:	For arbitrary use by userspace
+ * @type:	Discriminates the fw_cdev_event_ types
+ *
+ * This struct may be used to access generic members of all fw_cdev_event_
+ * types regardless of the specific type.
+ *
+ * Data passed in the @closure field for a request will be returned in the
+ * corresponding event.  It is big enough to hold a pointer on all platforms.
+ * The ioctl used to set @closure depends on the @type of event.
+ */
 struct fw_cdev_event_common {
 	__u64 closure;
 	__u32 type;
 };
 
+/**
+ * struct fw_cdev_event_bus_reset - Sent when a bus reset occurred
+ * @closure:	See &fw_cdev_event_common; set by %FW_CDEV_IOC_GET_INFO ioctl
+ * @type:	See &fw_cdev_event_common; always %FW_CDEV_EVENT_BUS_RESET
+ * @node_id:       New node ID of this node
+ * @local_node_id: Node ID of the local node, i.e. of the controller
+ * @bm_node_id:    Node ID of the bus manager
+ * @irm_node_id:   Node ID of the iso resource manager
+ * @root_node_id:  Node ID of the root node
+ * @generation:    New bus generation
+ *
+ * This event is sent when the bus the device belongs to goes through a bus
+ * reset.  It provides information about the new bus configuration, such as
+ * new node ID for this device, new root ID, and others.
+ */
 struct fw_cdev_event_bus_reset {
 	__u64 closure;
 	__u32 type;
@@ -51,6 +73,20 @@
 	__u32 generation;
 };
 
+/**
+ * struct fw_cdev_event_response - Sent when a response packet was received
+ * @closure:	See &fw_cdev_event_common;
+ *		set by %FW_CDEV_IOC_SEND_REQUEST ioctl
+ * @type:	See &fw_cdev_event_common; always %FW_CDEV_EVENT_RESPONSE
+ * @rcode:	Response code returned by the remote node
+ * @length:	Data length, i.e. the response's payload size in bytes
+ * @data:	Payload data, if any
+ *
+ * This event is sent when the stack receives a response to an outgoing request
+ * sent by %FW_CDEV_IOC_SEND_REQUEST ioctl.  The payload data for responses
+ * carrying data (read and lock responses) follows immediately and can be
+ * accessed through the @data field.
+ */
 struct fw_cdev_event_response {
 	__u64 closure;
 	__u32 type;
@@ -59,6 +95,25 @@
 	__u32 data[0];
 };
 
+/**
+ * struct fw_cdev_event_request - Sent on incoming request to an address region
+ * @closure:	See &fw_cdev_event_common; set by %FW_CDEV_IOC_ALLOCATE ioctl
+ * @type:	See &fw_cdev_event_common; always %FW_CDEV_EVENT_REQUEST
+ * @tcode:	Transaction code of the incoming request
+ * @offset:	The offset into the 48-bit per-node address space
+ * @handle:	Reference to the kernel-side pending request
+ * @length:	Data length, i.e. the request's payload size in bytes
+ * @data:	Incoming data, if any
+ *
+ * This event is sent when the stack receives an incoming request to an address
+ * region registered using the %FW_CDEV_IOC_ALLOCATE ioctl.  The request is
+ * guaranteed to be completely contained in the specified region.  Userspace is
+ * responsible for sending the response by %FW_CDEV_IOC_SEND_RESPONSE ioctl,
+ * using the same @handle.
+ *
+ * The payload data for requests carrying data (write and lock requests)
+ * follows immediately and can be accessed through the @data field.
+ */
 struct fw_cdev_event_request {
 	__u64 closure;
 	__u32 type;
@@ -69,14 +124,39 @@
 	__u32 data[0];
 };
 
+/**
+ * struct fw_cdev_event_iso_interrupt - Sent when an iso packet was completed
+ * @closure:	See &fw_cdev_event_common;
+ *		set by %FW_CDEV_CREATE_ISO_CONTEXT ioctl
+ * @type:	See &fw_cdev_event_common; always %FW_CDEV_EVENT_ISO_INTERRUPT
+ * @cycle:	Cycle counter of the interrupt packet
+ * @header_length: Total length of following headers, in bytes
+ * @header:	Stripped headers, if any
+ *
+ * This event is sent when the controller has completed an &fw_cdev_iso_packet
+ * with the %FW_CDEV_ISO_INTERRUPT bit set.  In the receive case, the headers
+ * stripped of all packets up until and including the interrupt packet are
+ * returned in the @header field.
+ */
 struct fw_cdev_event_iso_interrupt {
 	__u64 closure;
 	__u32 type;
 	__u32 cycle;
-	__u32 header_length;	/* Length in bytes of following headers. */
+	__u32 header_length;
 	__u32 header[0];
 };
 
+/**
+ * union fw_cdev_event - Convenience union of fw_cdev_event_ types
+ * @common:        Valid for all types
+ * @bus_reset:     Valid if @common.type == %FW_CDEV_EVENT_BUS_RESET
+ * @response:      Valid if @common.type == %FW_CDEV_EVENT_RESPONSE
+ * @request:       Valid if @common.type == %FW_CDEV_EVENT_REQUEST
+ * @iso_interrupt: Valid if @common.type == %FW_CDEV_EVENT_ISO_INTERRUPT
+ *
+ * Convenience union for userspace use.  Events could be read(2) into a char
+ * buffer and then cast to this union for further processing.
+ */
 union fw_cdev_event {
 	struct fw_cdev_event_common common;
 	struct fw_cdev_event_bus_reset bus_reset;
@@ -105,35 +185,47 @@
  */
 #define FW_CDEV_VERSION		1
 
+/**
+ * struct fw_cdev_get_info - General purpose information ioctl
+ * @version:	The version field is just a running serial number.
+ *		We never break backwards compatibility, but may add more
+ *		structs and ioctls in later revisions.
+ * @rom_length:	If @rom is non-zero, at most rom_length bytes of configuration
+ *		ROM will be copied into that user space address.  In either
+ *		case, @rom_length is updated with the actual length of the
+ *		configuration ROM.
+ * @rom:	If non-zero, address of a buffer to be filled by a copy of the
+ *		local node's configuration ROM
+ * @bus_reset:	If non-zero, address of a buffer to be filled by a
+ *		&struct fw_cdev_event_bus_reset with the current state
+ *		of the bus.  This does not cause a bus reset to happen.
+ * @bus_reset_closure: Value of &closure in this and subsequent bus reset events
+ * @card:	The index of the card this device belongs to
+ */
 struct fw_cdev_get_info {
-	/* The version field is just a running serial number.  We
-	 * never break backwards compatibility.  Userspace passes in
-	 * the version it expects and the kernel passes back the
-	 * highest version it can provide.  Even if the structs in
-	 * this interface are extended in a later version, the kernel
-	 * will not copy back more data than what was present in the
-	 * interface version userspace expects. */
 	__u32 version;
-
-	/* If non-zero, at most rom_length bytes of config rom will be
-	 * copied into that user space address.  In either case,
-	 * rom_length is updated with the actual length of the config
-	 * rom. */
 	__u32 rom_length;
 	__u64 rom;
-
-	/* If non-zero, a fw_cdev_event_bus_reset struct will be
-	 * copied here with the current state of the bus.  This does
-	 * not cause a bus reset to happen.  The value of closure in
-	 * this and sub-sequent bus reset events is set to
-	 * bus_reset_closure. */
 	__u64 bus_reset;
 	__u64 bus_reset_closure;
-
-	/* The index of the card this devices belongs to. */
 	__u32 card;
 };
 
+/**
+ * struct fw_cdev_send_request - Send an asynchronous request packet
+ * @tcode:	Transaction code of the request
+ * @length:	Length of outgoing payload, in bytes
+ * @offset:	48-bit offset at destination node
+ * @closure:	Passed back to userspace in the response event
+ * @data:	Userspace pointer to payload
+ * @generation:	The bus generation where packet is valid
+ *
+ * Send a request to the device.  This ioctl implements all outgoing requests.
+ * Both quadlet and block request specify the payload as a pointer to the data
+ * in the @data field.  Once the transaction completes, the kernel writes an
+ * &fw_cdev_event_request event back.  The @closure field is passed back to
+ * user space in the response event.
+ */
 struct fw_cdev_send_request {
 	__u32 tcode;
 	__u32 length;
@@ -143,6 +235,19 @@
 	__u32 generation;
 };
 
+/**
+ * struct fw_cdev_send_response - Send an asynchronous response packet
+ * @rcode:	Response code as determined by the userspace handler
+ * @length:	Length of outgoing payload, in bytes
+ * @data:	Userspace pointer to payload
+ * @handle:	The handle from the &fw_cdev_event_request
+ *
+ * Send a response to an incoming request.  By setting up an address range using
+ * the %FW_CDEV_IOC_ALLOCATE ioctl, userspace can listen for incoming requests.  An
+ * incoming request will generate an %FW_CDEV_EVENT_REQUEST, and userspace must
+ * send a reply using this ioctl.  The event has a handle to the kernel-side
+ * pending transaction, which should be used with this ioctl.
+ */
 struct fw_cdev_send_response {
 	__u32 rcode;
 	__u32 length;
@@ -150,6 +255,21 @@
 	__u32 handle;
 };
 
+/**
+ * struct fw_cdev_allocate - Allocate a CSR address range
+ * @offset:	Start offset of the address range
+ * @closure:	To be passed back to userspace in request events
+ * @length:	Length of the address range, in bytes
+ * @handle:	Handle to the allocation, written by the kernel
+ *
+ * Allocate an address range in the 48-bit address space on the local node
+ * (the controller).  This allows userspace to listen for requests with an
+ * offset within that address range.  When the kernel receives a request
+ * within the range, an &fw_cdev_event_request event will be written back.
+ * The @closure field is passed back to userspace in the response event.
+ * The @handle field is an out parameter, returning a handle to the allocated
+ * range to be used for later deallocation of the range.
+ */
 struct fw_cdev_allocate {
 	__u64 offset;
 	__u64 closure;
@@ -157,6 +277,11 @@
 	__u32 handle;
 };
 
+/**
+ * struct fw_cdev_deallocate - Free an address range allocation
+ * @handle:	Handle to the address range, as returned by the kernel when the
+ *		range was allocated
+ */
 struct fw_cdev_deallocate {
 	__u32 handle;
 };
@@ -164,10 +289,41 @@
 #define FW_CDEV_LONG_RESET	0
 #define FW_CDEV_SHORT_RESET	1
 
+/**
+ * struct fw_cdev_initiate_bus_reset - Initiate a bus reset
+ * @type:	%FW_CDEV_SHORT_RESET or %FW_CDEV_LONG_RESET
+ *
+ * Initiate a bus reset for the bus this device is on.  The bus reset can be
+ * either the original (long) bus reset or the arbitrated (short) bus reset
+ * introduced in 1394a-2000.
+ */
 struct fw_cdev_initiate_bus_reset {
-	__u32 type;
+	__u32 type;	/* FW_CDEV_SHORT_RESET or FW_CDEV_LONG_RESET */
 };
 
+/**
+ * struct fw_cdev_add_descriptor - Add contents to the local node's config ROM
+ * @immediate:	If non-zero, immediate key to insert before pointer
+ * @key:	Upper 8 bits of root directory pointer
+ * @data:	Userspace pointer to contents of descriptor block
+ * @length:	Length of descriptor block data, in bytes
+ * @handle:	Handle to the descriptor, written by the kernel
+ *
+ * Add a descriptor block and optionally a preceding immediate key to the local
+ * node's configuration ROM.
+ *
+ * The @key field specifies the upper 8 bits of the descriptor root directory
+ * pointer and the @data and @length fields specify the contents. The @key
+ * should be of the form 0xXX000000. The offset part of the root directory entry
+ * will be filled in by the kernel.
+ *
+ * If not 0, the @immediate field specifies an immediate key which will be
+ * inserted before the root directory pointer.
+ *
+ * If successful, the kernel adds the descriptor and writes back a handle to the
+ * kernel-side object to be used for later removal of the descriptor block and
+ * immediate key.
+ */
 struct fw_cdev_add_descriptor {
 	__u32 immediate;
 	__u32 key;
@@ -176,6 +332,14 @@
 	__u32 handle;
 };
 
+/**
+ * struct fw_cdev_remove_descriptor - Remove contents from the configuration ROM
+ * @handle:	Handle to the descriptor, as returned by the kernel when the
+ *		descriptor was added
+ *
+ * Remove a descriptor block and accompanying immediate key from the local
+ * node's configuration ROM.
+ */
 struct fw_cdev_remove_descriptor {
 	__u32 handle;
 };
@@ -183,12 +347,24 @@
 #define FW_CDEV_ISO_CONTEXT_TRANSMIT	0
 #define FW_CDEV_ISO_CONTEXT_RECEIVE	1
 
-#define FW_CDEV_ISO_CONTEXT_MATCH_TAG0		 1
-#define FW_CDEV_ISO_CONTEXT_MATCH_TAG1		 2
-#define FW_CDEV_ISO_CONTEXT_MATCH_TAG2		 4
-#define FW_CDEV_ISO_CONTEXT_MATCH_TAG3		 8
-#define FW_CDEV_ISO_CONTEXT_MATCH_ALL_TAGS	15
-
+/**
+ * struct fw_cdev_create_iso_context - Create a context for isochronous IO
+ * @type:	%FW_CDEV_ISO_CONTEXT_TRANSMIT or %FW_CDEV_ISO_CONTEXT_RECEIVE
+ * @header_size: Header size to strip for receive contexts
+ * @channel:	Channel to bind to
+ * @speed:	Speed to transmit at
+ * @closure:	To be returned in &fw_cdev_event_iso_interrupt
+ * @handle:	Handle to context, written back by kernel
+ *
+ * Prior to sending or receiving isochronous I/O, a context must be created.
+ * The context records information about the transmit or receive configuration
+ * and typically maps to an underlying hardware resource.  A context is set up
+ * for either sending or receiving.  It is bound to a specific isochronous
+ * channel.
+ *
+ * If a context was successfully created, the kernel writes back a handle to the
+ * context, which must be passed in for subsequent operations on that context.
+ */
 struct fw_cdev_create_iso_context {
 	__u32 type;
 	__u32 header_size;
@@ -201,15 +377,49 @@
 #define FW_CDEV_ISO_PAYLOAD_LENGTH(v)	(v)
 #define FW_CDEV_ISO_INTERRUPT		(1 << 16)
 #define FW_CDEV_ISO_SKIP		(1 << 17)
+#define FW_CDEV_ISO_SYNC		(1 << 17)
 #define FW_CDEV_ISO_TAG(v)		((v) << 18)
 #define FW_CDEV_ISO_SY(v)		((v) << 20)
 #define FW_CDEV_ISO_HEADER_LENGTH(v)	((v) << 24)
 
+/**
+ * struct fw_cdev_iso_packet - Isochronous packet
+ * @control:	Contains the header length (8 uppermost bits), the sy field
+ *		(4 bits), the tag field (2 bits), a sync flag (1 bit),
+ *		a skip flag (1 bit), an interrupt flag (1 bit), and the
+ *		payload length (16 lowermost bits)
+ * @header:	Header and payload
+ *
+ * &struct fw_cdev_iso_packet is used to describe isochronous packet queues.
+ *
+ * Use the FW_CDEV_ISO_ macros to fill in @control.  The sy and tag fields are
+ * specified by IEEE 1394a and IEC 61883.
+ *
+ * FIXME - finish this documentation
+ */
 struct fw_cdev_iso_packet {
 	__u32 control;
 	__u32 header[0];
 };
 
+/**
+ * struct fw_cdev_queue_iso - Queue isochronous packets for I/O
+ * @packets:	Userspace pointer to packet data
+ * @data:	Pointer into mmap()'ed payload buffer
+ * @size:	Size of packet data in bytes
+ * @handle:	Isochronous context handle
+ *
+ * Queue a number of isochronous packets for reception or transmission.
+ * This ioctl takes a pointer to an array of &fw_cdev_iso_packet structs,
+ * which describe how to transmit from or receive into a contiguous region
+ * of a mmap()'ed payload buffer.  As part of the packet descriptors,
+ * a series of headers can be supplied, which will be prepended to the
+ * payload during DMA.
+ *
+ * The kernel may or may not queue all packets, but will write back updated
+ * values of the @packets, @data and @size fields, so the ioctl can be
+ * resubmitted easily.
+ */
 struct fw_cdev_queue_iso {
 	__u64 packets;
 	__u64 data;
@@ -217,6 +427,23 @@
 	__u32 handle;
 };
 
+#define FW_CDEV_ISO_CONTEXT_MATCH_TAG0		 1
+#define FW_CDEV_ISO_CONTEXT_MATCH_TAG1		 2
+#define FW_CDEV_ISO_CONTEXT_MATCH_TAG2		 4
+#define FW_CDEV_ISO_CONTEXT_MATCH_TAG3		 8
+#define FW_CDEV_ISO_CONTEXT_MATCH_ALL_TAGS	15
+
+/**
+ * struct fw_cdev_start_iso - Start an isochronous transmission or reception
+ * @cycle:	Cycle in which to start I/O.  If @cycle is greater than or
+ *		equal to 0, the I/O will start on that cycle.
+ * @sync:	Determines the value to wait for for receive packets that have
+ *		the %FW_CDEV_ISO_SYNC bit set
+ * @tags:	Tag filter bit mask.  Only valid for isochronous reception.
+ *		Determines the tag values for which packets will be accepted.
+ *		Use FW_CDEV_ISO_CONTEXT_MATCH_ macros to set @tags.
+ * @handle:	Isochronous context handle within which to transmit or receive
+ */
 struct fw_cdev_start_iso {
 	__s32 cycle;
 	__u32 sync;
@@ -224,6 +451,10 @@
 	__u32 handle;
 };
 
+/**
+ * struct fw_cdev_stop_iso - Stop an isochronous transmission or reception
+ * @handle:	Handle of isochronous context to stop
+ */
 struct fw_cdev_stop_iso {
 	__u32 handle;
 };