lkundrak / rpms / kernel

Forked from rpms/kernel 4 years ago
Clone
Jesse Keating 7a32965
linux1394-2.6.git tree vs. linus v2.6.29-rc3-git1 on 20090130 by jarod
Jesse Keating 7a32965
Jesse Keating 7a32965
---
Jesse Keating 7a32965
 firewire-git/drivers/firewire/fw-card.c        |   68 -
Jesse Keating 7a32965
 firewire-git/drivers/firewire/fw-cdev.c        | 1014 +++++++++++++++++--------
Jesse Keating 7a32965
 firewire-git/drivers/firewire/fw-device.c      |   43 -
Jesse Keating 7a32965
 firewire-git/drivers/firewire/fw-device.h      |    7 
Jesse Keating 7a32965
 firewire-git/drivers/firewire/fw-iso.c         |  225 ++++-
Jesse Keating 7a32965
 firewire-git/drivers/firewire/fw-ohci.c        |  236 ++---
Jesse Keating 7a32965
 firewire-git/drivers/firewire/fw-sbp2.c        |   57 -
Jesse Keating 7a32965
 firewire-git/drivers/firewire/fw-topology.c    |   28 
Jesse Keating 7a32965
 firewire-git/drivers/firewire/fw-topology.h    |   19 
Jesse Keating 7a32965
 firewire-git/drivers/firewire/fw-transaction.c |  151 +--
Jesse Keating 7a32965
 firewire-git/drivers/firewire/fw-transaction.h |  125 ---
Jesse Keating 7a32965
 include/linux/firewire-cdev.h                  |  170 +++-
Jesse Keating 7a32965
 12 files changed, 1359 insertions(+), 784 deletions(-)
Jesse Keating 7a32965
Jesse Keating 7a32965
diff -Naurp linux-2.6-git/drivers/firewire/fw-card.c firewire-git/drivers/firewire/fw-card.c
Jesse Keating 7a32965
--- linux-2.6-git/drivers/firewire/fw-card.c	2009-01-30 13:39:02.989651512 -0500
Jesse Keating 7a32965
+++ firewire-git/drivers/firewire/fw-card.c	2009-01-30 13:35:51.859771884 -0500
Jesse Keating 7a32965
@@ -63,8 +63,7 @@ static int descriptor_count;
Jesse Keating 7a32965
 #define BIB_CMC			((1) << 30)
Jesse Keating 7a32965
 #define BIB_IMC			((1) << 31)
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static u32 *
Jesse Keating 7a32965
-generate_config_rom(struct fw_card *card, size_t *config_rom_length)
Jesse Keating 7a32965
+static u32 *generate_config_rom(struct fw_card *card, size_t *config_rom_length)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_descriptor *desc;
Jesse Keating 7a32965
 	static u32 config_rom[256];
Jesse Keating 7a32965
@@ -128,8 +127,7 @@ generate_config_rom(struct fw_card *card
Jesse Keating 7a32965
 	return config_rom;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static void
Jesse Keating 7a32965
-update_config_roms(void)
Jesse Keating 7a32965
+static void update_config_roms(void)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_card *card;
Jesse Keating 7a32965
 	u32 *config_rom;
Jesse Keating 7a32965
@@ -141,8 +139,7 @@ update_config_roms(void)
Jesse Keating 7a32965
 	}
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-int
Jesse Keating 7a32965
-fw_core_add_descriptor(struct fw_descriptor *desc)
Jesse Keating 7a32965
+int fw_core_add_descriptor(struct fw_descriptor *desc)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	size_t i;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
@@ -171,8 +168,7 @@ fw_core_add_descriptor(struct fw_descrip
Jesse Keating 7a32965
 	return 0;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-void
Jesse Keating 7a32965
-fw_core_remove_descriptor(struct fw_descriptor *desc)
Jesse Keating 7a32965
+void fw_core_remove_descriptor(struct fw_descriptor *desc)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	mutex_lock(&card_mutex);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
@@ -189,8 +185,7 @@ static const char gap_count_table[] = {
Jesse Keating 7a32965
 	63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40
Jesse Keating 7a32965
 };
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-void
Jesse Keating 7a32965
-fw_schedule_bm_work(struct fw_card *card, unsigned long delay)
Jesse Keating 7a32965
+void fw_schedule_bm_work(struct fw_card *card, unsigned long delay)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	int scheduled;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
@@ -200,8 +195,7 @@ fw_schedule_bm_work(struct fw_card *card
Jesse Keating 7a32965
 		fw_card_put(card);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static void
Jesse Keating 7a32965
-fw_card_bm_work(struct work_struct *work)
Jesse Keating 7a32965
+static void fw_card_bm_work(struct work_struct *work)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_card *card = container_of(work, struct fw_card, work.work);
Jesse Keating 7a32965
 	struct fw_device *root_device;
Jesse Keating 7a32965
@@ -371,17 +365,16 @@ fw_card_bm_work(struct work_struct *work
Jesse Keating 7a32965
 	fw_card_put(card);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static void
Jesse Keating 7a32965
-flush_timer_callback(unsigned long data)
Jesse Keating 7a32965
+static void flush_timer_callback(unsigned long data)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_card *card = (struct fw_card *)data;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	fw_flush_transactions(card);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-void
Jesse Keating 7a32965
-fw_card_initialize(struct fw_card *card, const struct fw_card_driver *driver,
Jesse Keating 7a32965
-		   struct device *device)
Jesse Keating 7a32965
+void fw_card_initialize(struct fw_card *card,
Jesse Keating 7a32965
+			const struct fw_card_driver *driver,
Jesse Keating 7a32965
+			struct device *device)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	static atomic_t index = ATOMIC_INIT(-1);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
@@ -406,9 +399,8 @@ fw_card_initialize(struct fw_card *card,
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 EXPORT_SYMBOL(fw_card_initialize);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-int
Jesse Keating 7a32965
-fw_card_add(struct fw_card *card,
Jesse Keating 7a32965
-	    u32 max_receive, u32 link_speed, u64 guid)
Jesse Keating 7a32965
+int fw_card_add(struct fw_card *card,
Jesse Keating 7a32965
+		u32 max_receive, u32 link_speed, u64 guid)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	u32 *config_rom;
Jesse Keating 7a32965
 	size_t length;
Jesse Keating 7a32965
@@ -435,23 +427,20 @@ EXPORT_SYMBOL(fw_card_add);
Jesse Keating 7a32965
  * dummy driver just fails all IO.
Jesse Keating 7a32965
  */
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static int
Jesse Keating 7a32965
-dummy_enable(struct fw_card *card, u32 *config_rom, size_t length)
Jesse Keating 7a32965
+static int dummy_enable(struct fw_card *card, u32 *config_rom, size_t length)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	BUG();
Jesse Keating 7a32965
 	return -1;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static int
Jesse Keating 7a32965
-dummy_update_phy_reg(struct fw_card *card, int address,
Jesse Keating 7a32965
-		     int clear_bits, int set_bits)
Jesse Keating 7a32965
+static int dummy_update_phy_reg(struct fw_card *card, int address,
Jesse Keating 7a32965
+				int clear_bits, int set_bits)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	return -ENODEV;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static int
Jesse Keating 7a32965
-dummy_set_config_rom(struct fw_card *card,
Jesse Keating 7a32965
-		     u32 *config_rom, size_t length)
Jesse Keating 7a32965
+static int dummy_set_config_rom(struct fw_card *card,
Jesse Keating 7a32965
+				u32 *config_rom, size_t length)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	/*
Jesse Keating 7a32965
 	 * We take the card out of card_list before setting the dummy
Jesse Keating 7a32965
@@ -461,27 +450,23 @@ dummy_set_config_rom(struct fw_card *car
Jesse Keating 7a32965
 	return -1;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static void
Jesse Keating 7a32965
-dummy_send_request(struct fw_card *card, struct fw_packet *packet)
Jesse Keating 7a32965
+static void dummy_send_request(struct fw_card *card, struct fw_packet *packet)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	packet->callback(packet, card, -ENODEV);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static void
Jesse Keating 7a32965
-dummy_send_response(struct fw_card *card, struct fw_packet *packet)
Jesse Keating 7a32965
+static void dummy_send_response(struct fw_card *card, struct fw_packet *packet)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	packet->callback(packet, card, -ENODEV);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static int
Jesse Keating 7a32965
-dummy_cancel_packet(struct fw_card *card, struct fw_packet *packet)
Jesse Keating 7a32965
+static int dummy_cancel_packet(struct fw_card *card, struct fw_packet *packet)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	return -ENOENT;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static int
Jesse Keating 7a32965
-dummy_enable_phys_dma(struct fw_card *card,
Jesse Keating 7a32965
-		      int node_id, int generation)
Jesse Keating 7a32965
+static int dummy_enable_phys_dma(struct fw_card *card,
Jesse Keating 7a32965
+				 int node_id, int generation)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	return -ENODEV;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
@@ -496,16 +481,14 @@ static struct fw_card_driver dummy_drive
Jesse Keating 7a32965
 	.enable_phys_dma = dummy_enable_phys_dma,
Jesse Keating 7a32965
 };
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-void
Jesse Keating 7a32965
-fw_card_release(struct kref *kref)
Jesse Keating 7a32965
+void fw_card_release(struct kref *kref)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_card *card = container_of(kref, struct fw_card, kref);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	complete(&card->done);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-void
Jesse Keating 7a32965
-fw_core_remove_card(struct fw_card *card)
Jesse Keating 7a32965
+void fw_core_remove_card(struct fw_card *card)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	card->driver->update_phy_reg(card, 4,
Jesse Keating 7a32965
 				     PHY_LINK_ACTIVE | PHY_CONTENDER, 0);
Jesse Keating 7a32965
@@ -529,8 +512,7 @@ fw_core_remove_card(struct fw_card *card
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 EXPORT_SYMBOL(fw_core_remove_card);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-int
Jesse Keating 7a32965
-fw_core_initiate_bus_reset(struct fw_card *card, int short_reset)
Jesse Keating 7a32965
+int fw_core_initiate_bus_reset(struct fw_card *card, int short_reset)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	int reg = short_reset ? 5 : 1;
Jesse Keating 7a32965
 	int bit = short_reset ? PHY_BUS_SHORT_RESET : PHY_BUS_RESET;
Jesse Keating 7a32965
diff -Naurp linux-2.6-git/drivers/firewire/fw-cdev.c firewire-git/drivers/firewire/fw-cdev.c
Jesse Keating 7a32965
--- linux-2.6-git/drivers/firewire/fw-cdev.c	2008-11-04 11:19:19.000000000 -0500
Jesse Keating 7a32965
+++ firewire-git/drivers/firewire/fw-cdev.c	2009-01-30 13:35:51.860646788 -0500
Jesse Keating 7a32965
@@ -18,87 +18,162 @@
Jesse Keating 7a32965
  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Jesse Keating 7a32965
  */
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-#include <linux/module.h>
Jesse Keating 7a32965
-#include <linux/kernel.h>
Jesse Keating 7a32965
-#include <linux/wait.h>
Jesse Keating 7a32965
-#include <linux/errno.h>
Jesse Keating 7a32965
+#include <linux/compat.h>
Jesse Keating 7a32965
+#include <linux/delay.h>
Jesse Keating 7a32965
 #include <linux/device.h>
Jesse Keating 7a32965
-#include <linux/vmalloc.h>
Jesse Keating 7a32965
+#include <linux/errno.h>
Jesse Keating 7a32965
+#include <linux/firewire-cdev.h>
Jesse Keating 7a32965
+#include <linux/idr.h>
Jesse Keating 7a32965
+#include <linux/jiffies.h>
Jesse Keating 7a32965
+#include <linux/kernel.h>
Jesse Keating 7a32965
+#include <linux/kref.h>
Jesse Keating 7a32965
+#include <linux/mm.h>
Jesse Keating 7a32965
+#include <linux/module.h>
Jesse Keating 7a32965
+#include <linux/mutex.h>
Jesse Keating 7a32965
 #include <linux/poll.h>
Jesse Keating 7a32965
 #include <linux/preempt.h>
Jesse Keating 7a32965
+#include <linux/spinlock.h>
Jesse Keating 7a32965
 #include <linux/time.h>
Jesse Keating 7a32965
-#include <linux/delay.h>
Jesse Keating 7a32965
-#include <linux/mm.h>
Jesse Keating 7a32965
-#include <linux/idr.h>
Jesse Keating 7a32965
-#include <linux/compat.h>
Jesse Keating 7a32965
-#include <linux/firewire-cdev.h>
Jesse Keating 7a32965
+#include <linux/vmalloc.h>
Jesse Keating 7a32965
+#include <linux/wait.h>
Jesse Keating 7a32965
+#include <linux/workqueue.h>
Jesse Keating 7a32965
+
Jesse Keating 7a32965
 #include <asm/system.h>
Jesse Keating 7a32965
 #include <asm/uaccess.h>
Jesse Keating 7a32965
-#include "fw-transaction.h"
Jesse Keating 7a32965
-#include "fw-topology.h"
Jesse Keating 7a32965
+
Jesse Keating 7a32965
 #include "fw-device.h"
Jesse Keating 7a32965
+#include "fw-topology.h"
Jesse Keating 7a32965
+#include "fw-transaction.h"
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+struct client {
Jesse Keating 7a32965
+	u32 version;
Jesse Keating 7a32965
+	struct fw_device *device;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	spinlock_t lock;
Jesse Keating 7a32965
+	bool in_shutdown;
Jesse Keating 7a32965
+	struct idr resource_idr;
Jesse Keating 7a32965
+	struct list_head event_list;
Jesse Keating 7a32965
+	wait_queue_head_t wait;
Jesse Keating 7a32965
+	u64 bus_reset_closure;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	struct fw_iso_context *iso_context;
Jesse Keating 7a32965
+	u64 iso_closure;
Jesse Keating 7a32965
+	struct fw_iso_buffer buffer;
Jesse Keating 7a32965
+	unsigned long vm_start;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-struct client;
Jesse Keating 7a32965
-struct client_resource {
Jesse Keating 7a32965
 	struct list_head link;
Jesse Keating 7a32965
-	void (*release)(struct client *client, struct client_resource *r);
Jesse Keating 7a32965
-	u32 handle;
Jesse Keating 7a32965
+	struct kref kref;
Jesse Keating 7a32965
+};
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+static inline void client_get(struct client *client)
Jesse Keating 7a32965
+{
Jesse Keating 7a32965
+	kref_get(&client->kref);
Jesse Keating 7a32965
+}
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+static void client_release(struct kref *kref)
Jesse Keating 7a32965
+{
Jesse Keating 7a32965
+	struct client *client = container_of(kref, struct client, kref);
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	fw_device_put(client->device);
Jesse Keating 7a32965
+	kfree(client);
Jesse Keating 7a32965
+}
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+static void client_put(struct client *client)
Jesse Keating 7a32965
+{
Jesse Keating 7a32965
+	kref_put(&client->kref, client_release);
Jesse Keating 7a32965
+}
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+struct client_resource;
Jesse Keating 7a32965
+typedef void (*client_resource_release_fn_t)(struct client *,
Jesse Keating 7a32965
+					     struct client_resource *);
Jesse Keating 7a32965
+struct client_resource {
Jesse Keating 7a32965
+	client_resource_release_fn_t release;
Jesse Keating 7a32965
+	int handle;
Jesse Keating 7a32965
+};
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+struct address_handler_resource {
Jesse Keating 7a32965
+	struct client_resource resource;
Jesse Keating 7a32965
+	struct fw_address_handler handler;
Jesse Keating 7a32965
+	__u64 closure;
Jesse Keating 7a32965
+	struct client *client;
Jesse Keating 7a32965
+};
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+struct outbound_transaction_resource {
Jesse Keating 7a32965
+	struct client_resource resource;
Jesse Keating 7a32965
+	struct fw_transaction transaction;
Jesse Keating 7a32965
+};
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+struct inbound_transaction_resource {
Jesse Keating 7a32965
+	struct client_resource resource;
Jesse Keating 7a32965
+	struct fw_request *request;
Jesse Keating 7a32965
+	void *data;
Jesse Keating 7a32965
+	size_t length;
Jesse Keating 7a32965
 };
Jesse Keating 7a32965
 
Jesse Keating 7a32965
+struct descriptor_resource {
Jesse Keating 7a32965
+	struct client_resource resource;
Jesse Keating 7a32965
+	struct fw_descriptor descriptor;
Jesse Keating 7a32965
+	u32 data[0];
Jesse Keating 7a32965
+};
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+struct iso_resource {
Jesse Keating 7a32965
+	struct client_resource resource;
Jesse Keating 7a32965
+	struct client *client;
Jesse Keating 7a32965
+	/* Schedule work and access todo only with client->lock held. */
Jesse Keating 7a32965
+	struct delayed_work work;
Jesse Keating 7a32965
+	enum {ISO_RES_ALLOC, ISO_RES_REALLOC, ISO_RES_DEALLOC,
Jesse Keating 7a32965
+	      ISO_RES_ALLOC_ONCE, ISO_RES_DEALLOC_ONCE,} todo;
Jesse Keating 7a32965
+	int generation;
Jesse Keating 7a32965
+	u64 channels;
Jesse Keating 7a32965
+	s32 bandwidth;
Jesse Keating 7a32965
+	struct iso_resource_event *e_alloc, *e_dealloc;
Jesse Keating 7a32965
+};
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+static void schedule_iso_resource(struct iso_resource *);
Jesse Keating 7a32965
+static void release_iso_resource(struct client *, struct client_resource *);
Jesse Keating 7a32965
+
Jesse Keating 7a32965
 /*
Jesse Keating 7a32965
  * dequeue_event() just kfree()'s the event, so the event has to be
Jesse Keating 7a32965
- * the first field in the struct.
Jesse Keating 7a32965
+ * the first field in a struct XYZ_event.
Jesse Keating 7a32965
  */
Jesse Keating 7a32965
-
Jesse Keating 7a32965
 struct event {
Jesse Keating 7a32965
 	struct { void *data; size_t size; } v[2];
Jesse Keating 7a32965
 	struct list_head link;
Jesse Keating 7a32965
 };
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-struct bus_reset {
Jesse Keating 7a32965
+struct bus_reset_event {
Jesse Keating 7a32965
 	struct event event;
Jesse Keating 7a32965
 	struct fw_cdev_event_bus_reset reset;
Jesse Keating 7a32965
 };
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-struct response {
Jesse Keating 7a32965
+struct outbound_transaction_event {
Jesse Keating 7a32965
 	struct event event;
Jesse Keating 7a32965
-	struct fw_transaction transaction;
Jesse Keating 7a32965
 	struct client *client;
Jesse Keating 7a32965
-	struct client_resource resource;
Jesse Keating 7a32965
+	struct outbound_transaction_resource r;
Jesse Keating 7a32965
 	struct fw_cdev_event_response response;
Jesse Keating 7a32965
 };
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-struct iso_interrupt {
Jesse Keating 7a32965
+struct inbound_transaction_event {
Jesse Keating 7a32965
 	struct event event;
Jesse Keating 7a32965
-	struct fw_cdev_event_iso_interrupt interrupt;
Jesse Keating 7a32965
+	struct fw_cdev_event_request request;
Jesse Keating 7a32965
 };
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-struct client {
Jesse Keating 7a32965
-	u32 version;
Jesse Keating 7a32965
-	struct fw_device *device;
Jesse Keating 7a32965
-	spinlock_t lock;
Jesse Keating 7a32965
-	u32 resource_handle;
Jesse Keating 7a32965
-	struct list_head resource_list;
Jesse Keating 7a32965
-	struct list_head event_list;
Jesse Keating 7a32965
-	wait_queue_head_t wait;
Jesse Keating 7a32965
-	u64 bus_reset_closure;
Jesse Keating 7a32965
-
Jesse Keating 7a32965
-	struct fw_iso_context *iso_context;
Jesse Keating 7a32965
-	u64 iso_closure;
Jesse Keating 7a32965
-	struct fw_iso_buffer buffer;
Jesse Keating 7a32965
-	unsigned long vm_start;
Jesse Keating 7a32965
+struct iso_interrupt_event {
Jesse Keating 7a32965
+	struct event event;
Jesse Keating 7a32965
+	struct fw_cdev_event_iso_interrupt interrupt;
Jesse Keating 7a32965
+};
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	struct list_head link;
Jesse Keating 7a32965
+struct iso_resource_event {
Jesse Keating 7a32965
+	struct event event;
Jesse Keating 7a32965
+	struct fw_cdev_event_iso_resource resource;
Jesse Keating 7a32965
 };
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static inline void __user *
Jesse Keating 7a32965
-u64_to_uptr(__u64 value)
Jesse Keating 7a32965
+static inline void __user *u64_to_uptr(__u64 value)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	return (void __user *)(unsigned long)value;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static inline __u64
Jesse Keating 7a32965
-uptr_to_u64(void __user *ptr)
Jesse Keating 7a32965
+static inline __u64 uptr_to_u64(void __user *ptr)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	return (__u64)(unsigned long)ptr;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
@@ -107,7 +182,6 @@ static int fw_device_op_open(struct inod
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_device *device;
Jesse Keating 7a32965
 	struct client *client;
Jesse Keating 7a32965
-	unsigned long flags;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	device = fw_device_get_by_devt(inode->i_rdev);
Jesse Keating 7a32965
 	if (device == NULL)
Jesse Keating 7a32965
@@ -125,16 +199,17 @@ static int fw_device_op_open(struct inod
Jesse Keating 7a32965
 	}
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	client->device = device;
Jesse Keating 7a32965
-	INIT_LIST_HEAD(&client->event_list);
Jesse Keating 7a32965
-	INIT_LIST_HEAD(&client->resource_list);
Jesse Keating 7a32965
 	spin_lock_init(&client->lock);
Jesse Keating 7a32965
+	idr_init(&client->resource_idr);
Jesse Keating 7a32965
+	INIT_LIST_HEAD(&client->event_list);
Jesse Keating 7a32965
 	init_waitqueue_head(&client->wait);
Jesse Keating 7a32965
+	kref_init(&client->kref);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	file->private_data = client;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	spin_lock_irqsave(&device->card->lock, flags);
Jesse Keating 7a32965
+	mutex_lock(&device->client_list_mutex);
Jesse Keating 7a32965
 	list_add_tail(&client->link, &device->client_list);
Jesse Keating 7a32965
-	spin_unlock_irqrestore(&device->card->lock, flags);
Jesse Keating 7a32965
+	mutex_unlock(&device->client_list_mutex);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	return 0;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
@@ -150,68 +225,69 @@ static void queue_event(struct client *c
Jesse Keating 7a32965
 	event->v[1].size = size1;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	spin_lock_irqsave(&client->lock, flags);
Jesse Keating 7a32965
-	list_add_tail(&event->link, &client->event_list);
Jesse Keating 7a32965
+	if (client->in_shutdown)
Jesse Keating 7a32965
+		kfree(event);
Jesse Keating 7a32965
+	else
Jesse Keating 7a32965
+		list_add_tail(&event->link, &client->event_list);
Jesse Keating 7a32965
 	spin_unlock_irqrestore(&client->lock, flags);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	wake_up_interruptible(&client->wait);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static int
Jesse Keating 7a32965
-dequeue_event(struct client *client, char __user *buffer, size_t count)
Jesse Keating 7a32965
+static int dequeue_event(struct client *client,
Jesse Keating 7a32965
+			 char __user *buffer, size_t count)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
-	unsigned long flags;
Jesse Keating 7a32965
 	struct event *event;
Jesse Keating 7a32965
 	size_t size, total;
Jesse Keating 7a32965
-	int i, retval;
Jesse Keating 7a32965
+	int i, ret;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	retval = wait_event_interruptible(client->wait,
Jesse Keating 7a32965
-					  !list_empty(&client->event_list) ||
Jesse Keating 7a32965
-					  fw_device_is_shutdown(client->device));
Jesse Keating 7a32965
-	if (retval < 0)
Jesse Keating 7a32965
-		return retval;
Jesse Keating 7a32965
+	ret = wait_event_interruptible(client->wait,
Jesse Keating 7a32965
+			!list_empty(&client->event_list) ||
Jesse Keating 7a32965
+			fw_device_is_shutdown(client->device));
Jesse Keating 7a32965
+	if (ret < 0)
Jesse Keating 7a32965
+		return ret;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	if (list_empty(&client->event_list) &&
Jesse Keating 7a32965
 		       fw_device_is_shutdown(client->device))
Jesse Keating 7a32965
 		return -ENODEV;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	spin_lock_irqsave(&client->lock, flags);
Jesse Keating 7a32965
-	event = container_of(client->event_list.next, struct event, link);
Jesse Keating 7a32965
+	spin_lock_irq(&client->lock);
Jesse Keating 7a32965
+	event = list_first_entry(&client->event_list, struct event, link);
Jesse Keating 7a32965
 	list_del(&event->link);
Jesse Keating 7a32965
-	spin_unlock_irqrestore(&client->lock, flags);
Jesse Keating 7a32965
+	spin_unlock_irq(&client->lock);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	total = 0;
Jesse Keating 7a32965
 	for (i = 0; i < ARRAY_SIZE(event->v) && total < count; i++) {
Jesse Keating 7a32965
 		size = min(event->v[i].size, count - total);
Jesse Keating 7a32965
 		if (copy_to_user(buffer + total, event->v[i].data, size)) {
Jesse Keating 7a32965
-			retval = -EFAULT;
Jesse Keating 7a32965
+			ret = -EFAULT;
Jesse Keating 7a32965
 			goto out;
Jesse Keating 7a32965
 		}
Jesse Keating 7a32965
 		total += size;
Jesse Keating 7a32965
 	}
Jesse Keating 7a32965
-	retval = total;
Jesse Keating 7a32965
+	ret = total;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
  out:
Jesse Keating 7a32965
 	kfree(event);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	return retval;
Jesse Keating 7a32965
+	return ret;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static ssize_t
Jesse Keating 7a32965
-fw_device_op_read(struct file *file,
Jesse Keating 7a32965
-		  char __user *buffer, size_t count, loff_t *offset)
Jesse Keating 7a32965
+static ssize_t fw_device_op_read(struct file *file, char __user *buffer,
Jesse Keating 7a32965
+				 size_t count, loff_t *offset)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct client *client = file->private_data;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	return dequeue_event(client, buffer, count);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-/* caller must hold card->lock so that node pointers can be dereferenced here */
Jesse Keating 7a32965
-static void
Jesse Keating 7a32965
-fill_bus_reset_event(struct fw_cdev_event_bus_reset *event,
Jesse Keating 7a32965
-		     struct client *client)
Jesse Keating 7a32965
+static void fill_bus_reset_event(struct fw_cdev_event_bus_reset *event,
Jesse Keating 7a32965
+				 struct client *client)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_card *card = client->device->card;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
+	spin_lock_irq(&card->lock);
Jesse Keating 7a32965
+
Jesse Keating 7a32965
 	event->closure	     = client->bus_reset_closure;
Jesse Keating 7a32965
 	event->type          = FW_CDEV_EVENT_BUS_RESET;
Jesse Keating 7a32965
 	event->generation    = client->device->generation;
Jesse Keating 7a32965
@@ -220,39 +296,49 @@ fill_bus_reset_event(struct fw_cdev_even
Jesse Keating 7a32965
 	event->bm_node_id    = 0; /* FIXME: We don't track the BM. */
Jesse Keating 7a32965
 	event->irm_node_id   = card->irm_node->node_id;
Jesse Keating 7a32965
 	event->root_node_id  = card->root_node->node_id;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	spin_unlock_irq(&card->lock);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static void
Jesse Keating 7a32965
-for_each_client(struct fw_device *device,
Jesse Keating 7a32965
-		void (*callback)(struct client *client))
Jesse Keating 7a32965
+static void for_each_client(struct fw_device *device,
Jesse Keating 7a32965
+			    void (*callback)(struct client *client))
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
-	struct fw_card *card = device->card;
Jesse Keating 7a32965
 	struct client *c;
Jesse Keating 7a32965
-	unsigned long flags;
Jesse Keating 7a32965
-
Jesse Keating 7a32965
-	spin_lock_irqsave(&card->lock, flags);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
+	mutex_lock(&device->client_list_mutex);
Jesse Keating 7a32965
 	list_for_each_entry(c, &device->client_list, link)
Jesse Keating 7a32965
 		callback(c);
Jesse Keating 7a32965
+	mutex_unlock(&device->client_list_mutex);
Jesse Keating 7a32965
+}
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+static int schedule_reallocations(int id, void *p, void *data)
Jesse Keating 7a32965
+{
Jesse Keating 7a32965
+	struct client_resource *r = p;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	spin_unlock_irqrestore(&card->lock, flags);
Jesse Keating 7a32965
+	if (r->release == release_iso_resource)
Jesse Keating 7a32965
+		schedule_iso_resource(container_of(r,
Jesse Keating 7a32965
+					struct iso_resource, resource));
Jesse Keating 7a32965
+	return 0;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static void
Jesse Keating 7a32965
-queue_bus_reset_event(struct client *client)
Jesse Keating 7a32965
+static void queue_bus_reset_event(struct client *client)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
-	struct bus_reset *bus_reset;
Jesse Keating 7a32965
+	struct bus_reset_event *e;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	bus_reset = kzalloc(sizeof(*bus_reset), GFP_ATOMIC);
Jesse Keating 7a32965
-	if (bus_reset == NULL) {
Jesse Keating 7a32965
+	e = kzalloc(sizeof(*e), GFP_KERNEL);
Jesse Keating 7a32965
+	if (e == NULL) {
Jesse Keating 7a32965
 		fw_notify("Out of memory when allocating bus reset event\n");
Jesse Keating 7a32965
 		return;
Jesse Keating 7a32965
 	}
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	fill_bus_reset_event(&bus_reset->reset, client);
Jesse Keating 7a32965
+	fill_bus_reset_event(&e->reset, client);
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	queue_event(client, &e->event,
Jesse Keating 7a32965
+		    &e->reset, sizeof(e->reset), NULL, 0);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	queue_event(client, &bus_reset->event,
Jesse Keating 7a32965
-		    &bus_reset->reset, sizeof(bus_reset->reset), NULL, 0);
Jesse Keating 7a32965
+	spin_lock_irq(&client->lock);
Jesse Keating 7a32965
+	idr_for_each(&client->resource_idr, schedule_reallocations, client);
Jesse Keating 7a32965
+	spin_unlock_irq(&client->lock);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 void fw_device_cdev_update(struct fw_device *device)
Jesse Keating 7a32965
@@ -274,11 +360,11 @@ static int ioctl_get_info(struct client 
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_cdev_get_info *get_info = buffer;
Jesse Keating 7a32965
 	struct fw_cdev_event_bus_reset bus_reset;
Jesse Keating 7a32965
-	struct fw_card *card = client->device->card;
Jesse Keating 7a32965
 	unsigned long ret = 0;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	client->version = get_info->version;
Jesse Keating 7a32965
 	get_info->version = FW_CDEV_VERSION;
Jesse Keating 7a32965
+	get_info->card = client->device->card->index;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	down_read(&fw_device_rwsem);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
@@ -300,49 +386,61 @@ static int ioctl_get_info(struct client 
Jesse Keating 7a32965
 	client->bus_reset_closure = get_info->bus_reset_closure;
Jesse Keating 7a32965
 	if (get_info->bus_reset != 0) {
Jesse Keating 7a32965
 		void __user *uptr = u64_to_uptr(get_info->bus_reset);
Jesse Keating 7a32965
-		unsigned long flags;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-		spin_lock_irqsave(&card->lock, flags);
Jesse Keating 7a32965
 		fill_bus_reset_event(&bus_reset, client);
Jesse Keating 7a32965
-		spin_unlock_irqrestore(&card->lock, flags);
Jesse Keating 7a32965
-
Jesse Keating 7a32965
 		if (copy_to_user(uptr, &bus_reset, sizeof(bus_reset)))
Jesse Keating 7a32965
 			return -EFAULT;
Jesse Keating 7a32965
 	}
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	get_info->card = card->index;
Jesse Keating 7a32965
-
Jesse Keating 7a32965
 	return 0;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static void
Jesse Keating 7a32965
-add_client_resource(struct client *client, struct client_resource *resource)
Jesse Keating 7a32965
+static int add_client_resource(struct client *client,
Jesse Keating 7a32965
+			       struct client_resource *resource, gfp_t gfp_mask)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	unsigned long flags;
Jesse Keating 7a32965
+	int ret;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+ retry:
Jesse Keating 7a32965
+	if (idr_pre_get(&client->resource_idr, gfp_mask | __GFP_ZERO) == 0)
Jesse Keating 7a32965
+		return -ENOMEM;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	spin_lock_irqsave(&client->lock, flags);
Jesse Keating 7a32965
-	list_add_tail(&resource->link, &client->resource_list);
Jesse Keating 7a32965
-	resource->handle = client->resource_handle++;
Jesse Keating 7a32965
+	if (client->in_shutdown)
Jesse Keating 7a32965
+		ret = -ECANCELED;
Jesse Keating 7a32965
+	else
Jesse Keating 7a32965
+		ret = idr_get_new(&client->resource_idr, resource,
Jesse Keating 7a32965
+				  &resource->handle);
Jesse Keating 7a32965
+	if (ret >= 0) {
Jesse Keating 7a32965
+		client_get(client);
Jesse Keating 7a32965
+		if (resource->release == release_iso_resource)
Jesse Keating 7a32965
+			schedule_iso_resource(container_of(resource,
Jesse Keating 7a32965
+						struct iso_resource, resource));
Jesse Keating 7a32965
+	}
Jesse Keating 7a32965
 	spin_unlock_irqrestore(&client->lock, flags);
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	if (ret == -EAGAIN)
Jesse Keating 7a32965
+		goto retry;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	return ret < 0 ? ret : 0;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static int
Jesse Keating 7a32965
-release_client_resource(struct client *client, u32 handle,
Jesse Keating 7a32965
-			struct client_resource **resource)
Jesse Keating 7a32965
+static int release_client_resource(struct client *client, u32 handle,
Jesse Keating 7a32965
+				   client_resource_release_fn_t release,
Jesse Keating 7a32965
+				   struct client_resource **resource)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct client_resource *r;
Jesse Keating 7a32965
-	unsigned long flags;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	spin_lock_irqsave(&client->lock, flags);
Jesse Keating 7a32965
-	list_for_each_entry(r, &client->resource_list, link) {
Jesse Keating 7a32965
-		if (r->handle == handle) {
Jesse Keating 7a32965
-			list_del(&r->link);
Jesse Keating 7a32965
-			break;
Jesse Keating 7a32965
-		}
Jesse Keating 7a32965
-	}
Jesse Keating 7a32965
-	spin_unlock_irqrestore(&client->lock, flags);
Jesse Keating 7a32965
+	spin_lock_irq(&client->lock);
Jesse Keating 7a32965
+	if (client->in_shutdown)
Jesse Keating 7a32965
+		r = NULL;
Jesse Keating 7a32965
+	else
Jesse Keating 7a32965
+		r = idr_find(&client->resource_idr, handle);
Jesse Keating 7a32965
+	if (r && r->release == release)
Jesse Keating 7a32965
+		idr_remove(&client->resource_idr, handle);
Jesse Keating 7a32965
+	spin_unlock_irq(&client->lock);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	if (&r->link == &client->resource_list)
Jesse Keating 7a32965
+	if (!(r && r->release == release))
Jesse Keating 7a32965
 		return -EINVAL;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	if (resource)
Jesse Keating 7a32965
@@ -350,203 +448,242 @@ release_client_resource(struct client *c
Jesse Keating 7a32965
 	else
Jesse Keating 7a32965
 		r->release(client, r);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
+	client_put(client);
Jesse Keating 7a32965
+
Jesse Keating 7a32965
 	return 0;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static void
Jesse Keating 7a32965
-release_transaction(struct client *client, struct client_resource *resource)
Jesse Keating 7a32965
+static void release_transaction(struct client *client,
Jesse Keating 7a32965
+				struct client_resource *resource)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
-	struct response *response =
Jesse Keating 7a32965
-		container_of(resource, struct response, resource);
Jesse Keating 7a32965
+	struct outbound_transaction_resource *r = container_of(resource,
Jesse Keating 7a32965
+			struct outbound_transaction_resource, resource);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	fw_cancel_transaction(client->device->card, &response->transaction);
Jesse Keating 7a32965
+	fw_cancel_transaction(client->device->card, &r->transaction);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static void
Jesse Keating 7a32965
-complete_transaction(struct fw_card *card, int rcode,
Jesse Keating 7a32965
-		     void *payload, size_t length, void *data)
Jesse Keating 7a32965
+static void complete_transaction(struct fw_card *card, int rcode,
Jesse Keating 7a32965
+				 void *payload, size_t length, void *data)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
-	struct response *response = data;
Jesse Keating 7a32965
-	struct client *client = response->client;
Jesse Keating 7a32965
+	struct outbound_transaction_event *e = data;
Jesse Keating 7a32965
+	struct fw_cdev_event_response *rsp = &e->response;
Jesse Keating 7a32965
+	struct client *client = e->client;
Jesse Keating 7a32965
 	unsigned long flags;
Jesse Keating 7a32965
-	struct fw_cdev_event_response *r = &response->response;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	if (length < r->length)
Jesse Keating 7a32965
-		r->length = length;
Jesse Keating 7a32965
+	if (length < rsp->length)
Jesse Keating 7a32965
+		rsp->length = length;
Jesse Keating 7a32965
 	if (rcode == RCODE_COMPLETE)
Jesse Keating 7a32965
-		memcpy(r->data, payload, r->length);
Jesse Keating 7a32965
+		memcpy(rsp->data, payload, rsp->length);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	spin_lock_irqsave(&client->lock, flags);
Jesse Keating 7a32965
-	list_del(&response->resource.link);
Jesse Keating 7a32965
+	/*
Jesse Keating 7a32965
+	 * 1. If called while in shutdown, the idr tree must be left untouched.
Jesse Keating 7a32965
+	 *    The idr handle will be removed and the client reference will be
Jesse Keating 7a32965
+	 *    dropped later.
Jesse Keating 7a32965
+	 * 2. If the call chain was release_client_resource ->
Jesse Keating 7a32965
+	 *    release_transaction -> complete_transaction (instead of a normal
Jesse Keating 7a32965
+	 *    conclusion of the transaction), i.e. if this resource was already
Jesse Keating 7a32965
+	 *    unregistered from the idr, the client reference will be dropped
Jesse Keating 7a32965
+	 *    by release_client_resource and we must not drop it here.
Jesse Keating 7a32965
+	 */
Jesse Keating 7a32965
+	if (!client->in_shutdown &&
Jesse Keating 7a32965
+	    idr_find(&client->resource_idr, e->r.resource.handle)) {
Jesse Keating 7a32965
+		idr_remove(&client->resource_idr, e->r.resource.handle);
Jesse Keating 7a32965
+		/* Drop the idr's reference */
Jesse Keating 7a32965
+		client_put(client);
Jesse Keating 7a32965
+	}
Jesse Keating 7a32965
 	spin_unlock_irqrestore(&client->lock, flags);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	r->type   = FW_CDEV_EVENT_RESPONSE;
Jesse Keating 7a32965
-	r->rcode  = rcode;
Jesse Keating 7a32965
+	rsp->type = FW_CDEV_EVENT_RESPONSE;
Jesse Keating 7a32965
+	rsp->rcode = rcode;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	/*
Jesse Keating 7a32965
-	 * In the case that sizeof(*r) doesn't align with the position of the
Jesse Keating 7a32965
+	 * In the case that sizeof(*rsp) doesn't align with the position of the
Jesse Keating 7a32965
 	 * data, and the read is short, preserve an extra copy of the data
Jesse Keating 7a32965
 	 * to stay compatible with a pre-2.6.27 bug.  Since the bug is harmless
Jesse Keating 7a32965
 	 * for short reads and some apps depended on it, this is both safe
Jesse Keating 7a32965
 	 * and prudent for compatibility.
Jesse Keating 7a32965
 	 */
Jesse Keating 7a32965
-	if (r->length <= sizeof(*r) - offsetof(typeof(*r), data))
Jesse Keating 7a32965
-		queue_event(client, &response->event, r, sizeof(*r),
Jesse Keating 7a32965
-			    r->data, r->length);
Jesse Keating 7a32965
+	if (rsp->length <= sizeof(*rsp) - offsetof(typeof(*rsp), data))
Jesse Keating 7a32965
+		queue_event(client, &e->event, rsp, sizeof(*rsp),
Jesse Keating 7a32965
+			    rsp->data, rsp->length);
Jesse Keating 7a32965
 	else
Jesse Keating 7a32965
-		queue_event(client, &response->event, r, sizeof(*r) + r->length,
Jesse Keating 7a32965
+		queue_event(client, &e->event, rsp, sizeof(*rsp) + rsp->length,
Jesse Keating 7a32965
 			    NULL, 0);
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	/* Drop the transaction callback's reference */
Jesse Keating 7a32965
+	client_put(client);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static int ioctl_send_request(struct client *client, void *buffer)
Jesse Keating 7a32965
+static int init_request(struct client *client,
Jesse Keating 7a32965
+			struct fw_cdev_send_request *request,
Jesse Keating 7a32965
+			int destination_id, int speed)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
-	struct fw_device *device = client->device;
Jesse Keating 7a32965
-	struct fw_cdev_send_request *request = buffer;
Jesse Keating 7a32965
-	struct response *response;
Jesse Keating 7a32965
+	struct outbound_transaction_event *e;
Jesse Keating 7a32965
+	int ret;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	/* What is the biggest size we'll accept, really? */
Jesse Keating 7a32965
-	if (request->length > 4096)
Jesse Keating 7a32965
-		return -EINVAL;
Jesse Keating 7a32965
+	if (request->length > 4096 || request->length > 512 << speed)
Jesse Keating 7a32965
+		return -EIO;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	response = kmalloc(sizeof(*response) + request->length, GFP_KERNEL);
Jesse Keating 7a32965
-	if (response == NULL)
Jesse Keating 7a32965
+	e = kmalloc(sizeof(*e) + request->length, GFP_KERNEL);
Jesse Keating 7a32965
+	if (e == NULL)
Jesse Keating 7a32965
 		return -ENOMEM;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	response->client = client;
Jesse Keating 7a32965
-	response->response.length = request->length;
Jesse Keating 7a32965
-	response->response.closure = request->closure;
Jesse Keating 7a32965
+	e->client = client;
Jesse Keating 7a32965
+	e->response.length = request->length;
Jesse Keating 7a32965
+	e->response.closure = request->closure;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	if (request->data &&
Jesse Keating 7a32965
-	    copy_from_user(response->response.data,
Jesse Keating 7a32965
+	    copy_from_user(e->response.data,
Jesse Keating 7a32965
 			   u64_to_uptr(request->data), request->length)) {
Jesse Keating 7a32965
-		kfree(response);
Jesse Keating 7a32965
-		return -EFAULT;
Jesse Keating 7a32965
+		ret = -EFAULT;
Jesse Keating 7a32965
+		goto failed;
Jesse Keating 7a32965
 	}
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	response->resource.release = release_transaction;
Jesse Keating 7a32965
-	add_client_resource(client, &response->resource);
Jesse Keating 7a32965
-
Jesse Keating 7a32965
-	fw_send_request(device->card, &response->transaction,
Jesse Keating 7a32965
-			request->tcode & 0x1f,
Jesse Keating 7a32965
-			device->node->node_id,
Jesse Keating 7a32965
-			request->generation,
Jesse Keating 7a32965
-			device->max_speed,
Jesse Keating 7a32965
-			request->offset,
Jesse Keating 7a32965
-			response->response.data, request->length,
Jesse Keating 7a32965
-			complete_transaction, response);
Jesse Keating 7a32965
+	e->r.resource.release = release_transaction;
Jesse Keating 7a32965
+	ret = add_client_resource(client, &e->r.resource, GFP_KERNEL);
Jesse Keating 7a32965
+	if (ret < 0)
Jesse Keating 7a32965
+		goto failed;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	/* Get a reference for the transaction callback */
Jesse Keating 7a32965
+	client_get(client);
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	fw_send_request(client->device->card, &e->r.transaction,
Jesse Keating 7a32965
+			request->tcode & 0x1f, destination_id,
Jesse Keating 7a32965
+			request->generation, speed, request->offset,
Jesse Keating 7a32965
+			e->response.data, request->length,
Jesse Keating 7a32965
+			complete_transaction, e);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	if (request->data)
Jesse Keating 7a32965
 		return sizeof(request) + request->length;
Jesse Keating 7a32965
 	else
Jesse Keating 7a32965
 		return sizeof(request);
Jesse Keating 7a32965
+ failed:
Jesse Keating 7a32965
+	kfree(e);
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	return ret;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-struct address_handler {
Jesse Keating 7a32965
-	struct fw_address_handler handler;
Jesse Keating 7a32965
-	__u64 closure;
Jesse Keating 7a32965
-	struct client *client;
Jesse Keating 7a32965
-	struct client_resource resource;
Jesse Keating 7a32965
-};
Jesse Keating 7a32965
+static int ioctl_send_request(struct client *client, void *buffer)
Jesse Keating 7a32965
+{
Jesse Keating 7a32965
+	struct fw_cdev_send_request *request = buffer;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-struct request {
Jesse Keating 7a32965
-	struct fw_request *request;
Jesse Keating 7a32965
-	void *data;
Jesse Keating 7a32965
-	size_t length;
Jesse Keating 7a32965
-	struct client_resource resource;
Jesse Keating 7a32965
-};
Jesse Keating 7a32965
+	switch (request->tcode) {
Jesse Keating 7a32965
+	case TCODE_WRITE_QUADLET_REQUEST:
Jesse Keating 7a32965
+	case TCODE_WRITE_BLOCK_REQUEST:
Jesse Keating 7a32965
+	case TCODE_READ_QUADLET_REQUEST:
Jesse Keating 7a32965
+	case TCODE_READ_BLOCK_REQUEST:
Jesse Keating 7a32965
+	case TCODE_LOCK_MASK_SWAP:
Jesse Keating 7a32965
+	case TCODE_LOCK_COMPARE_SWAP:
Jesse Keating 7a32965
+	case TCODE_LOCK_FETCH_ADD:
Jesse Keating 7a32965
+	case TCODE_LOCK_LITTLE_ADD:
Jesse Keating 7a32965
+	case TCODE_LOCK_BOUNDED_ADD:
Jesse Keating 7a32965
+	case TCODE_LOCK_WRAP_ADD:
Jesse Keating 7a32965
+	case TCODE_LOCK_VENDOR_DEPENDENT:
Jesse Keating 7a32965
+		break;
Jesse Keating 7a32965
+	default:
Jesse Keating 7a32965
+		return -EINVAL;
Jesse Keating 7a32965
+	}
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-struct request_event {
Jesse Keating 7a32965
-	struct event event;
Jesse Keating 7a32965
-	struct fw_cdev_event_request request;
Jesse Keating 7a32965
-};
Jesse Keating 7a32965
+	return init_request(client, request, client->device->node->node_id,
Jesse Keating 7a32965
+			    client->device->max_speed);
Jesse Keating 7a32965
+}
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static void
Jesse Keating 7a32965
-release_request(struct client *client, struct client_resource *resource)
Jesse Keating 7a32965
+static void release_request(struct client *client,
Jesse Keating 7a32965
+			    struct client_resource *resource)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
-	struct request *request =
Jesse Keating 7a32965
-		container_of(resource, struct request, resource);
Jesse Keating 7a32965
+	struct inbound_transaction_resource *r = container_of(resource,
Jesse Keating 7a32965
+			struct inbound_transaction_resource, resource);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	fw_send_response(client->device->card, request->request,
Jesse Keating 7a32965
+	fw_send_response(client->device->card, r->request,
Jesse Keating 7a32965
 			 RCODE_CONFLICT_ERROR);
Jesse Keating 7a32965
-	kfree(request);
Jesse Keating 7a32965
+	kfree(r);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static void
Jesse Keating 7a32965
-handle_request(struct fw_card *card, struct fw_request *r,
Jesse Keating 7a32965
-	       int tcode, int destination, int source,
Jesse Keating 7a32965
-	       int generation, int speed,
Jesse Keating 7a32965
-	       unsigned long long offset,
Jesse Keating 7a32965
-	       void *payload, size_t length, void *callback_data)
Jesse Keating 7a32965
-{
Jesse Keating 7a32965
-	struct address_handler *handler = callback_data;
Jesse Keating 7a32965
-	struct request *request;
Jesse Keating 7a32965
-	struct request_event *e;
Jesse Keating 7a32965
-	struct client *client = handler->client;
Jesse Keating 7a32965
+static void handle_request(struct fw_card *card, struct fw_request *request,
Jesse Keating 7a32965
+			   int tcode, int destination, int source,
Jesse Keating 7a32965
+			   int generation, int speed,
Jesse Keating 7a32965
+			   unsigned long long offset,
Jesse Keating 7a32965
+			   void *payload, size_t length, void *callback_data)
Jesse Keating 7a32965
+{
Jesse Keating 7a32965
+	struct address_handler_resource *handler = callback_data;
Jesse Keating 7a32965
+	struct inbound_transaction_resource *r;
Jesse Keating 7a32965
+	struct inbound_transaction_event *e;
Jesse Keating 7a32965
+	int ret;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	request = kmalloc(sizeof(*request), GFP_ATOMIC);
Jesse Keating 7a32965
+	r = kmalloc(sizeof(*r), GFP_ATOMIC);
Jesse Keating 7a32965
 	e = kmalloc(sizeof(*e), GFP_ATOMIC);
Jesse Keating 7a32965
-	if (request == NULL || e == NULL) {
Jesse Keating 7a32965
-		kfree(request);
Jesse Keating 7a32965
-		kfree(e);
Jesse Keating 7a32965
-		fw_send_response(card, r, RCODE_CONFLICT_ERROR);
Jesse Keating 7a32965
-		return;
Jesse Keating 7a32965
-	}
Jesse Keating 7a32965
-
Jesse Keating 7a32965
-	request->request = r;
Jesse Keating 7a32965
-	request->data    = payload;
Jesse Keating 7a32965
-	request->length  = length;
Jesse Keating 7a32965
+	if (r == NULL || e == NULL)
Jesse Keating 7a32965
+		goto failed;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	request->resource.release = release_request;
Jesse Keating 7a32965
-	add_client_resource(client, &request->resource);
Jesse Keating 7a32965
+	r->request = request;
Jesse Keating 7a32965
+	r->data    = payload;
Jesse Keating 7a32965
+	r->length  = length;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	r->resource.release = release_request;
Jesse Keating 7a32965
+	ret = add_client_resource(handler->client, &r->resource, GFP_ATOMIC);
Jesse Keating 7a32965
+	if (ret < 0)
Jesse Keating 7a32965
+		goto failed;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	e->request.type    = FW_CDEV_EVENT_REQUEST;
Jesse Keating 7a32965
 	e->request.tcode   = tcode;
Jesse Keating 7a32965
 	e->request.offset  = offset;
Jesse Keating 7a32965
 	e->request.length  = length;
Jesse Keating 7a32965
-	e->request.handle  = request->resource.handle;
Jesse Keating 7a32965
+	e->request.handle  = r->resource.handle;
Jesse Keating 7a32965
 	e->request.closure = handler->closure;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	queue_event(client, &e->event,
Jesse Keating 7a32965
+	queue_event(handler->client, &e->event,
Jesse Keating 7a32965
 		    &e->request, sizeof(e->request), payload, length);
Jesse Keating 7a32965
+	return;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+ failed:
Jesse Keating 7a32965
+	kfree(r);
Jesse Keating 7a32965
+	kfree(e);
Jesse Keating 7a32965
+	fw_send_response(card, request, RCODE_CONFLICT_ERROR);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static void
Jesse Keating 7a32965
-release_address_handler(struct client *client,
Jesse Keating 7a32965
-			struct client_resource *resource)
Jesse Keating 7a32965
+static void release_address_handler(struct client *client,
Jesse Keating 7a32965
+				    struct client_resource *resource)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
-	struct address_handler *handler =
Jesse Keating 7a32965
-		container_of(resource, struct address_handler, resource);
Jesse Keating 7a32965
+	struct address_handler_resource *r =
Jesse Keating 7a32965
+	    container_of(resource, struct address_handler_resource, resource);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	fw_core_remove_address_handler(&handler->handler);
Jesse Keating 7a32965
-	kfree(handler);
Jesse Keating 7a32965
+	fw_core_remove_address_handler(&r->handler);
Jesse Keating 7a32965
+	kfree(r);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 static int ioctl_allocate(struct client *client, void *buffer)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_cdev_allocate *request = buffer;
Jesse Keating 7a32965
-	struct address_handler *handler;
Jesse Keating 7a32965
+	struct address_handler_resource *r;
Jesse Keating 7a32965
 	struct fw_address_region region;
Jesse Keating 7a32965
+	int ret;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	handler = kmalloc(sizeof(*handler), GFP_KERNEL);
Jesse Keating 7a32965
-	if (handler == NULL)
Jesse Keating 7a32965
+	r = kmalloc(sizeof(*r), GFP_KERNEL);
Jesse Keating 7a32965
+	if (r == NULL)
Jesse Keating 7a32965
 		return -ENOMEM;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	region.start = request->offset;
Jesse Keating 7a32965
 	region.end = request->offset + request->length;
Jesse Keating 7a32965
-	handler->handler.length = request->length;
Jesse Keating 7a32965
-	handler->handler.address_callback = handle_request;
Jesse Keating 7a32965
-	handler->handler.callback_data = handler;
Jesse Keating 7a32965
-	handler->closure = request->closure;
Jesse Keating 7a32965
-	handler->client = client;
Jesse Keating 7a32965
-
Jesse Keating 7a32965
-	if (fw_core_add_address_handler(&handler->handler, &region) < 0) {
Jesse Keating 7a32965
-		kfree(handler);
Jesse Keating 7a32965
-		return -EBUSY;
Jesse Keating 7a32965
+	r->handler.length = request->length;
Jesse Keating 7a32965
+	r->handler.address_callback = handle_request;
Jesse Keating 7a32965
+	r->handler.callback_data = r;
Jesse Keating 7a32965
+	r->closure = request->closure;
Jesse Keating 7a32965
+	r->client = client;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	ret = fw_core_add_address_handler(&r->handler, &region);
Jesse Keating 7a32965
+	if (ret < 0) {
Jesse Keating 7a32965
+		kfree(r);
Jesse Keating 7a32965
+		return ret;
Jesse Keating 7a32965
 	}
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	handler->resource.release = release_address_handler;
Jesse Keating 7a32965
-	add_client_resource(client, &handler->resource);
Jesse Keating 7a32965
-	request->handle = handler->resource.handle;
Jesse Keating 7a32965
+	r->resource.release = release_address_handler;
Jesse Keating 7a32965
+	ret = add_client_resource(client, &r->resource, GFP_KERNEL);
Jesse Keating 7a32965
+	if (ret < 0) {
Jesse Keating 7a32965
+		release_address_handler(client, &r->resource);
Jesse Keating 7a32965
+		return ret;
Jesse Keating 7a32965
+	}
Jesse Keating 7a32965
+	request->handle = r->resource.handle;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	return 0;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
@@ -555,18 +692,22 @@ static int ioctl_deallocate(struct clien
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_cdev_deallocate *request = buffer;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	return release_client_resource(client, request->handle, NULL);
Jesse Keating 7a32965
+	return release_client_resource(client, request->handle,
Jesse Keating 7a32965
+				       release_address_handler, NULL);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 static int ioctl_send_response(struct client *client, void *buffer)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_cdev_send_response *request = buffer;
Jesse Keating 7a32965
 	struct client_resource *resource;
Jesse Keating 7a32965
-	struct request *r;
Jesse Keating 7a32965
+	struct inbound_transaction_resource *r;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	if (release_client_resource(client, request->handle, &resource) < 0)
Jesse Keating 7a32965
+	if (release_client_resource(client, request->handle,
Jesse Keating 7a32965
+				    release_request, &resource) < 0)
Jesse Keating 7a32965
 		return -EINVAL;
Jesse Keating 7a32965
-	r = container_of(resource, struct request, resource);
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	r = container_of(resource, struct inbound_transaction_resource,
Jesse Keating 7a32965
+			 resource);
Jesse Keating 7a32965
 	if (request->length < r->length)
Jesse Keating 7a32965
 		r->length = request->length;
Jesse Keating 7a32965
 	if (copy_from_user(r->data, u64_to_uptr(request->data), r->length))
Jesse Keating 7a32965
@@ -588,85 +729,84 @@ static int ioctl_initiate_bus_reset(stru
Jesse Keating 7a32965
 	return fw_core_initiate_bus_reset(client->device->card, short_reset);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-struct descriptor {
Jesse Keating 7a32965
-	struct fw_descriptor d;
Jesse Keating 7a32965
-	struct client_resource resource;
Jesse Keating 7a32965
-	u32 data[0];
Jesse Keating 7a32965
-};
Jesse Keating 7a32965
-
Jesse Keating 7a32965
 static void release_descriptor(struct client *client,
Jesse Keating 7a32965
 			       struct client_resource *resource)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
-	struct descriptor *descriptor =
Jesse Keating 7a32965
-		container_of(resource, struct descriptor, resource);
Jesse Keating 7a32965
+	struct descriptor_resource *r =
Jesse Keating 7a32965
+		container_of(resource, struct descriptor_resource, resource);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	fw_core_remove_descriptor(&descriptor->d);
Jesse Keating 7a32965
-	kfree(descriptor);
Jesse Keating 7a32965
+	fw_core_remove_descriptor(&r->descriptor);
Jesse Keating 7a32965
+	kfree(r);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 static int ioctl_add_descriptor(struct client *client, void *buffer)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_cdev_add_descriptor *request = buffer;
Jesse Keating 7a32965
-	struct descriptor *descriptor;
Jesse Keating 7a32965
-	int retval;
Jesse Keating 7a32965
+	struct descriptor_resource *r;
Jesse Keating 7a32965
+	int ret;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	if (request->length > 256)
Jesse Keating 7a32965
 		return -EINVAL;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	descriptor =
Jesse Keating 7a32965
-		kmalloc(sizeof(*descriptor) + request->length * 4, GFP_KERNEL);
Jesse Keating 7a32965
-	if (descriptor == NULL)
Jesse Keating 7a32965
+	r = kmalloc(sizeof(*r) + request->length * 4, GFP_KERNEL);
Jesse Keating 7a32965
+	if (r == NULL)
Jesse Keating 7a32965
 		return -ENOMEM;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	if (copy_from_user(descriptor->data,
Jesse Keating 7a32965
+	if (copy_from_user(r->data,
Jesse Keating 7a32965
 			   u64_to_uptr(request->data), request->length * 4)) {
Jesse Keating 7a32965
-		kfree(descriptor);
Jesse Keating 7a32965
-		return -EFAULT;
Jesse Keating 7a32965
+		ret = -EFAULT;
Jesse Keating 7a32965
+		goto failed;
Jesse Keating 7a32965
 	}
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	descriptor->d.length = request->length;
Jesse Keating 7a32965
-	descriptor->d.immediate = request->immediate;
Jesse Keating 7a32965
-	descriptor->d.key = request->key;
Jesse Keating 7a32965
-	descriptor->d.data = descriptor->data;
Jesse Keating 7a32965
-
Jesse Keating 7a32965
-	retval = fw_core_add_descriptor(&descriptor->d);
Jesse Keating 7a32965
-	if (retval < 0) {
Jesse Keating 7a32965
-		kfree(descriptor);
Jesse Keating 7a32965
-		return retval;
Jesse Keating 7a32965
+	r->descriptor.length    = request->length;
Jesse Keating 7a32965
+	r->descriptor.immediate = request->immediate;
Jesse Keating 7a32965
+	r->descriptor.key       = request->key;
Jesse Keating 7a32965
+	r->descriptor.data      = r->data;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	ret = fw_core_add_descriptor(&r->descriptor);
Jesse Keating 7a32965
+	if (ret < 0)
Jesse Keating 7a32965
+		goto failed;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	r->resource.release = release_descriptor;
Jesse Keating 7a32965
+	ret = add_client_resource(client, &r->resource, GFP_KERNEL);
Jesse Keating 7a32965
+	if (ret < 0) {
Jesse Keating 7a32965
+		fw_core_remove_descriptor(&r->descriptor);
Jesse Keating 7a32965
+		goto failed;
Jesse Keating 7a32965
 	}
Jesse Keating 7a32965
-
Jesse Keating 7a32965
-	descriptor->resource.release = release_descriptor;
Jesse Keating 7a32965
-	add_client_resource(client, &descriptor->resource);
Jesse Keating 7a32965
-	request->handle = descriptor->resource.handle;
Jesse Keating 7a32965
+	request->handle = r->resource.handle;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	return 0;
Jesse Keating 7a32965
+ failed:
Jesse Keating 7a32965
+	kfree(r);
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	return ret;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 static int ioctl_remove_descriptor(struct client *client, void *buffer)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_cdev_remove_descriptor *request = buffer;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	return release_client_resource(client, request->handle, NULL);
Jesse Keating 7a32965
+	return release_client_resource(client, request->handle,
Jesse Keating 7a32965
+				       release_descriptor, NULL);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static void
Jesse Keating 7a32965
-iso_callback(struct fw_iso_context *context, u32 cycle,
Jesse Keating 7a32965
-	     size_t header_length, void *header, void *data)
Jesse Keating 7a32965
+static void iso_callback(struct fw_iso_context *context, u32 cycle,
Jesse Keating 7a32965
+			 size_t header_length, void *header, void *data)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct client *client = data;
Jesse Keating 7a32965
-	struct iso_interrupt *irq;
Jesse Keating 7a32965
+	struct iso_interrupt_event *e;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	irq = kzalloc(sizeof(*irq) + header_length, GFP_ATOMIC);
Jesse Keating 7a32965
-	if (irq == NULL)
Jesse Keating 7a32965
+	e = kzalloc(sizeof(*e) + header_length, GFP_ATOMIC);
Jesse Keating 7a32965
+	if (e == NULL)
Jesse Keating 7a32965
 		return;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	irq->interrupt.type      = FW_CDEV_EVENT_ISO_INTERRUPT;
Jesse Keating 7a32965
-	irq->interrupt.closure   = client->iso_closure;
Jesse Keating 7a32965
-	irq->interrupt.cycle     = cycle;
Jesse Keating 7a32965
-	irq->interrupt.header_length = header_length;
Jesse Keating 7a32965
-	memcpy(irq->interrupt.header, header, header_length);
Jesse Keating 7a32965
-	queue_event(client, &irq->event, &irq->interrupt,
Jesse Keating 7a32965
-		    sizeof(irq->interrupt) + header_length, NULL, 0);
Jesse Keating 7a32965
+	e->interrupt.type      = FW_CDEV_EVENT_ISO_INTERRUPT;
Jesse Keating 7a32965
+	e->interrupt.closure   = client->iso_closure;
Jesse Keating 7a32965
+	e->interrupt.cycle     = cycle;
Jesse Keating 7a32965
+	e->interrupt.header_length = header_length;
Jesse Keating 7a32965
+	memcpy(e->interrupt.header, header, header_length);
Jesse Keating 7a32965
+	queue_event(client, &e->event, &e->interrupt,
Jesse Keating 7a32965
+		    sizeof(e->interrupt) + header_length, NULL, 0);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 static int ioctl_create_iso_context(struct client *client, void *buffer)
Jesse Keating 7a32965
@@ -871,6 +1011,237 @@ static int ioctl_get_cycle_timer(struct 
Jesse Keating 7a32965
 	return 0;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
+static void iso_resource_work(struct work_struct *work)
Jesse Keating 7a32965
+{
Jesse Keating 7a32965
+	struct iso_resource_event *e;
Jesse Keating 7a32965
+	struct iso_resource *r =
Jesse Keating 7a32965
+			container_of(work, struct iso_resource, work.work);
Jesse Keating 7a32965
+	struct client *client = r->client;
Jesse Keating 7a32965
+	int generation, channel, bandwidth, todo;
Jesse Keating 7a32965
+	bool skip, free, success;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	spin_lock_irq(&client->lock);
Jesse Keating 7a32965
+	generation = client->device->generation;
Jesse Keating 7a32965
+	todo = r->todo;
Jesse Keating 7a32965
+	/* Allow 1000ms grace period for other reallocations. */
Jesse Keating 7a32965
+	if (todo == ISO_RES_ALLOC &&
Jesse Keating 7a32965
+	    time_is_after_jiffies(client->device->card->reset_jiffies + HZ)) {
Jesse Keating 7a32965
+		if (schedule_delayed_work(&r->work, DIV_ROUND_UP(HZ, 3)))
Jesse Keating 7a32965
+			client_get(client);
Jesse Keating 7a32965
+		skip = true;
Jesse Keating 7a32965
+	} else {
Jesse Keating 7a32965
+		/* We could be called twice within the same generation. */
Jesse Keating 7a32965
+		skip = todo == ISO_RES_REALLOC &&
Jesse Keating 7a32965
+		       r->generation == generation;
Jesse Keating 7a32965
+	}
Jesse Keating 7a32965
+	free = todo == ISO_RES_DEALLOC ||
Jesse Keating 7a32965
+	       todo == ISO_RES_ALLOC_ONCE ||
Jesse Keating 7a32965
+	       todo == ISO_RES_DEALLOC_ONCE;
Jesse Keating 7a32965
+	r->generation = generation;
Jesse Keating 7a32965
+	spin_unlock_irq(&client->lock);
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	if (skip)
Jesse Keating 7a32965
+		goto out;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	bandwidth = r->bandwidth;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	fw_iso_resource_manage(client->device->card, generation,
Jesse Keating 7a32965
+			r->channels, &channel, &bandwidth,
Jesse Keating 7a32965
+			todo == ISO_RES_ALLOC ||
Jesse Keating 7a32965
+			todo == ISO_RES_REALLOC ||
Jesse Keating 7a32965
+			todo == ISO_RES_ALLOC_ONCE);
Jesse Keating 7a32965
+	/*
Jesse Keating 7a32965
+	 * Is this generation outdated already?  As long as this resource sticks
Jesse Keating 7a32965
+	 * in the idr, it will be scheduled again for a newer generation or at
Jesse Keating 7a32965
+	 * shutdown.
Jesse Keating 7a32965
+	 */
Jesse Keating 7a32965
+	if (channel == -EAGAIN &&
Jesse Keating 7a32965
+	    (todo == ISO_RES_ALLOC || todo == ISO_RES_REALLOC))
Jesse Keating 7a32965
+		goto out;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	success = channel >= 0 || bandwidth > 0;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	spin_lock_irq(&client->lock);
Jesse Keating 7a32965
+	/*
Jesse Keating 7a32965
+	 * Transit from allocation to reallocation, except if the client
Jesse Keating 7a32965
+	 * requested deallocation in the meantime.
Jesse Keating 7a32965
+	 */
Jesse Keating 7a32965
+	if (r->todo == ISO_RES_ALLOC)
Jesse Keating 7a32965
+		r->todo = ISO_RES_REALLOC;
Jesse Keating 7a32965
+	/*
Jesse Keating 7a32965
+	 * Allocation or reallocation failure?  Pull this resource out of the
Jesse Keating 7a32965
+	 * idr and prepare for deletion, unless the client is shutting down.
Jesse Keating 7a32965
+	 */
Jesse Keating 7a32965
+	if (r->todo == ISO_RES_REALLOC && !success &&
Jesse Keating 7a32965
+	    !client->in_shutdown &&
Jesse Keating 7a32965
+	    idr_find(&client->resource_idr, r->resource.handle)) {
Jesse Keating 7a32965
+		idr_remove(&client->resource_idr, r->resource.handle);
Jesse Keating 7a32965
+		client_put(client);
Jesse Keating 7a32965
+		free = true;
Jesse Keating 7a32965
+	}
Jesse Keating 7a32965
+	spin_unlock_irq(&client->lock);
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	if (todo == ISO_RES_ALLOC && channel >= 0)
Jesse Keating 7a32965
+		r->channels = 1ULL << channel;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	if (todo == ISO_RES_REALLOC && success)
Jesse Keating 7a32965
+		goto out;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	if (todo == ISO_RES_ALLOC || todo == ISO_RES_ALLOC_ONCE) {
Jesse Keating 7a32965
+		e = r->e_alloc;
Jesse Keating 7a32965
+		r->e_alloc = NULL;
Jesse Keating 7a32965
+	} else {
Jesse Keating 7a32965
+		e = r->e_dealloc;
Jesse Keating 7a32965
+		r->e_dealloc = NULL;
Jesse Keating 7a32965
+	}
Jesse Keating 7a32965
+	e->resource.handle	= r->resource.handle;
Jesse Keating 7a32965
+	e->resource.channel	= channel;
Jesse Keating 7a32965
+	e->resource.bandwidth	= bandwidth;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	queue_event(client, &e->event,
Jesse Keating 7a32965
+		    &e->resource, sizeof(e->resource), NULL, 0);
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	if (free) {
Jesse Keating 7a32965
+		cancel_delayed_work(&r->work);
Jesse Keating 7a32965
+		kfree(r->e_alloc);
Jesse Keating 7a32965
+		kfree(r->e_dealloc);
Jesse Keating 7a32965
+		kfree(r);
Jesse Keating 7a32965
+	}
Jesse Keating 7a32965
+ out:
Jesse Keating 7a32965
+	client_put(client);
Jesse Keating 7a32965
+}
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+static void schedule_iso_resource(struct iso_resource *r)
Jesse Keating 7a32965
+{
Jesse Keating 7a32965
+	client_get(r->client);
Jesse Keating 7a32965
+	if (!schedule_delayed_work(&r->work, 0))
Jesse Keating 7a32965
+		client_put(r->client);
Jesse Keating 7a32965
+}
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+static void release_iso_resource(struct client *client,
Jesse Keating 7a32965
+				 struct client_resource *resource)
Jesse Keating 7a32965
+{
Jesse Keating 7a32965
+	struct iso_resource *r =
Jesse Keating 7a32965
+		container_of(resource, struct iso_resource, resource);
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	spin_lock_irq(&client->lock);
Jesse Keating 7a32965
+	r->todo = ISO_RES_DEALLOC;
Jesse Keating 7a32965
+	schedule_iso_resource(r);
Jesse Keating 7a32965
+	spin_unlock_irq(&client->lock);
Jesse Keating 7a32965
+}
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+static int init_iso_resource(struct client *client,
Jesse Keating 7a32965
+		struct fw_cdev_allocate_iso_resource *request, int todo)
Jesse Keating 7a32965
+{
Jesse Keating 7a32965
+	struct iso_resource_event *e1, *e2;
Jesse Keating 7a32965
+	struct iso_resource *r;
Jesse Keating 7a32965
+	int ret;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	if ((request->channels == 0 && request->bandwidth == 0) ||
Jesse Keating 7a32965
+	    request->bandwidth > BANDWIDTH_AVAILABLE_INITIAL ||
Jesse Keating 7a32965
+	    request->bandwidth < 0)
Jesse Keating 7a32965
+		return -EINVAL;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	r  = kmalloc(sizeof(*r), GFP_KERNEL);
Jesse Keating 7a32965
+	e1 = kmalloc(sizeof(*e1), GFP_KERNEL);
Jesse Keating 7a32965
+	e2 = kmalloc(sizeof(*e2), GFP_KERNEL);
Jesse Keating 7a32965
+	if (r == NULL || e1 == NULL || e2 == NULL) {
Jesse Keating 7a32965
+		ret = -ENOMEM;
Jesse Keating 7a32965
+		goto fail;
Jesse Keating 7a32965
+	}
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	INIT_DELAYED_WORK(&r->work, iso_resource_work);
Jesse Keating 7a32965
+	r->client	= client;
Jesse Keating 7a32965
+	r->todo		= todo;
Jesse Keating 7a32965
+	r->generation	= -1;
Jesse Keating 7a32965
+	r->channels	= request->channels;
Jesse Keating 7a32965
+	r->bandwidth	= request->bandwidth;
Jesse Keating 7a32965
+	r->e_alloc	= e1;
Jesse Keating 7a32965
+	r->e_dealloc	= e2;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	e1->resource.closure	= request->closure;
Jesse Keating 7a32965
+	e1->resource.type	= FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED;
Jesse Keating 7a32965
+	e2->resource.closure	= request->closure;
Jesse Keating 7a32965
+	e2->resource.type	= FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	if (todo == ISO_RES_ALLOC) {
Jesse Keating 7a32965
+		r->resource.release = release_iso_resource;
Jesse Keating 7a32965
+		ret = add_client_resource(client, &r->resource, GFP_KERNEL);
Jesse Keating 7a32965
+		if (ret < 0)
Jesse Keating 7a32965
+			goto fail;
Jesse Keating 7a32965
+	} else {
Jesse Keating 7a32965
+		r->resource.release = NULL;
Jesse Keating 7a32965
+		r->resource.handle = -1;
Jesse Keating 7a32965
+		schedule_iso_resource(r);
Jesse Keating 7a32965
+	}
Jesse Keating 7a32965
+	request->handle = r->resource.handle;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	return 0;
Jesse Keating 7a32965
+ fail:
Jesse Keating 7a32965
+	kfree(r);
Jesse Keating 7a32965
+	kfree(e1);
Jesse Keating 7a32965
+	kfree(e2);
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	return ret;
Jesse Keating 7a32965
+}
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+static int ioctl_allocate_iso_resource(struct client *client, void *buffer)
Jesse Keating 7a32965
+{
Jesse Keating 7a32965
+	struct fw_cdev_allocate_iso_resource *request = buffer;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	return init_iso_resource(client, request, ISO_RES_ALLOC);
Jesse Keating 7a32965
+}
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+static int ioctl_deallocate_iso_resource(struct client *client, void *buffer)
Jesse Keating 7a32965
+{
Jesse Keating 7a32965
+	struct fw_cdev_deallocate *request = buffer;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	return release_client_resource(client, request->handle,
Jesse Keating 7a32965
+				       release_iso_resource, NULL);
Jesse Keating 7a32965
+}
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+static int ioctl_allocate_iso_resource_once(struct client *client, void *buffer)
Jesse Keating 7a32965
+{
Jesse Keating 7a32965
+	struct fw_cdev_allocate_iso_resource *request = buffer;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	return init_iso_resource(client, request, ISO_RES_ALLOC_ONCE);
Jesse Keating 7a32965
+}
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+static int ioctl_deallocate_iso_resource_once(struct client *client, void *buffer)
Jesse Keating 7a32965
+{
Jesse Keating 7a32965
+	struct fw_cdev_allocate_iso_resource *request = buffer;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	return init_iso_resource(client, request, ISO_RES_DEALLOC_ONCE);
Jesse Keating 7a32965
+}
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+static int ioctl_get_speed(struct client *client, void *buffer)
Jesse Keating 7a32965
+{
Jesse Keating 7a32965
+	struct fw_cdev_get_speed *request = buffer;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	request->max_speed = client->device->max_speed;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	return 0;
Jesse Keating 7a32965
+}
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+static int ioctl_send_broadcast_request(struct client *client, void *buffer)
Jesse Keating 7a32965
+{
Jesse Keating 7a32965
+	struct fw_cdev_send_request *request = buffer;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	switch (request->tcode) {
Jesse Keating 7a32965
+	case TCODE_WRITE_QUADLET_REQUEST:
Jesse Keating 7a32965
+	case TCODE_WRITE_BLOCK_REQUEST:
Jesse Keating 7a32965
+		break;
Jesse Keating 7a32965
+	default:
Jesse Keating 7a32965
+		return -EINVAL;
Jesse Keating 7a32965
+	}
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	/* Security policy: Only allow accesses to Units Space. */
Jesse Keating 7a32965
+	if (request->offset < CSR_REGISTER_BASE + CSR_CONFIG_ROM_END)
Jesse Keating 7a32965
+		return -EACCES;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	return init_request(client, request, LOCAL_BUS | 0x3f, SCODE_100);
Jesse Keating 7a32965
+}
Jesse Keating 7a32965
+
Jesse Keating 7a32965
 static int (* const ioctl_handlers[])(struct client *client, void *buffer) = {
Jesse Keating 7a32965
 	ioctl_get_info,
Jesse Keating 7a32965
 	ioctl_send_request,
Jesse Keating 7a32965
@@ -885,13 +1256,19 @@ static int (* const ioctl_handlers[])(st
Jesse Keating 7a32965
 	ioctl_start_iso,
Jesse Keating 7a32965
 	ioctl_stop_iso,
Jesse Keating 7a32965
 	ioctl_get_cycle_timer,
Jesse Keating 7a32965
+	ioctl_allocate_iso_resource,
Jesse Keating 7a32965
+	ioctl_deallocate_iso_resource,
Jesse Keating 7a32965
+	ioctl_allocate_iso_resource_once,
Jesse Keating 7a32965
+	ioctl_deallocate_iso_resource_once,
Jesse Keating 7a32965
+	ioctl_get_speed,
Jesse Keating 7a32965
+	ioctl_send_broadcast_request,
Jesse Keating 7a32965
 };
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static int
Jesse Keating 7a32965
-dispatch_ioctl(struct client *client, unsigned int cmd, void __user *arg)
Jesse Keating 7a32965
+static int dispatch_ioctl(struct client *client,
Jesse Keating 7a32965
+			  unsigned int cmd, void __user *arg)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	char buffer[256];
Jesse Keating 7a32965
-	int retval;
Jesse Keating 7a32965
+	int ret;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	if (_IOC_TYPE(cmd) != '#' ||
Jesse Keating 7a32965
 	    _IOC_NR(cmd) >= ARRAY_SIZE(ioctl_handlers))
Jesse Keating 7a32965
@@ -903,9 +1280,9 @@ dispatch_ioctl(struct client *client, un
Jesse Keating 7a32965
 			return -EFAULT;
Jesse Keating 7a32965
 	}
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	retval = ioctl_handlers[_IOC_NR(cmd)](client, buffer);
Jesse Keating 7a32965
-	if (retval < 0)
Jesse Keating 7a32965
-		return retval;
Jesse Keating 7a32965
+	ret = ioctl_handlers[_IOC_NR(cmd)](client, buffer);
Jesse Keating 7a32965
+	if (ret < 0)
Jesse Keating 7a32965
+		return ret;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	if (_IOC_DIR(cmd) & _IOC_READ) {
Jesse Keating 7a32965
 		if (_IOC_SIZE(cmd) > sizeof(buffer) ||
Jesse Keating 7a32965
@@ -913,12 +1290,11 @@ dispatch_ioctl(struct client *client, un
Jesse Keating 7a32965
 			return -EFAULT;
Jesse Keating 7a32965
 	}
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	return retval;
Jesse Keating 7a32965
+	return ret;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static long
Jesse Keating 7a32965
-fw_device_op_ioctl(struct file *file,
Jesse Keating 7a32965
-		   unsigned int cmd, unsigned long arg)
Jesse Keating 7a32965
+static long fw_device_op_ioctl(struct file *file,
Jesse Keating 7a32965
+			       unsigned int cmd, unsigned long arg)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct client *client = file->private_data;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
@@ -929,9 +1305,8 @@ fw_device_op_ioctl(struct file *file,
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 #ifdef CONFIG_COMPAT
Jesse Keating 7a32965
-static long
Jesse Keating 7a32965
-fw_device_op_compat_ioctl(struct file *file,
Jesse Keating 7a32965
-			  unsigned int cmd, unsigned long arg)
Jesse Keating 7a32965
+static long fw_device_op_compat_ioctl(struct file *file,
Jesse Keating 7a32965
+				      unsigned int cmd, unsigned long arg)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct client *client = file->private_data;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
@@ -947,7 +1322,7 @@ static int fw_device_op_mmap(struct file
Jesse Keating 7a32965
 	struct client *client = file->private_data;
Jesse Keating 7a32965
 	enum dma_data_direction direction;
Jesse Keating 7a32965
 	unsigned long size;
Jesse Keating 7a32965
-	int page_count, retval;
Jesse Keating 7a32965
+	int page_count, ret;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	if (fw_device_is_shutdown(client->device))
Jesse Keating 7a32965
 		return -ENODEV;
Jesse Keating 7a32965
@@ -973,48 +1348,57 @@ static int fw_device_op_mmap(struct file
Jesse Keating 7a32965
 	else
Jesse Keating 7a32965
 		direction = DMA_FROM_DEVICE;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	retval = fw_iso_buffer_init(&client->buffer, client->device->card,
Jesse Keating 7a32965
-				    page_count, direction);
Jesse Keating 7a32965
-	if (retval < 0)
Jesse Keating 7a32965
-		return retval;
Jesse Keating 7a32965
+	ret = fw_iso_buffer_init(&client->buffer, client->device->card,
Jesse Keating 7a32965
+				 page_count, direction);
Jesse Keating 7a32965
+	if (ret < 0)
Jesse Keating 7a32965
+		return ret;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	retval = fw_iso_buffer_map(&client->buffer, vma);
Jesse Keating 7a32965
-	if (retval < 0)
Jesse Keating 7a32965
+	ret = fw_iso_buffer_map(&client->buffer, vma);
Jesse Keating 7a32965
+	if (ret < 0)
Jesse Keating 7a32965
 		fw_iso_buffer_destroy(&client->buffer, client->device->card);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	return retval;
Jesse Keating 7a32965
+	return ret;
Jesse Keating 7a32965
+}
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+static int shutdown_resource(int id, void *p, void *data)
Jesse Keating 7a32965
+{
Jesse Keating 7a32965
+	struct client_resource *r = p;
Jesse Keating 7a32965
+	struct client *client = data;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	r->release(client, r);
Jesse Keating 7a32965
+	client_put(client);
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	return 0;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 static int fw_device_op_release(struct inode *inode, struct file *file)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct client *client = file->private_data;
Jesse Keating 7a32965
 	struct event *e, *next_e;
Jesse Keating 7a32965
-	struct client_resource *r, *next_r;
Jesse Keating 7a32965
-	unsigned long flags;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	if (client->buffer.pages)
Jesse Keating 7a32965
-		fw_iso_buffer_destroy(&client->buffer, client->device->card);
Jesse Keating 7a32965
+	mutex_lock(&client->device->client_list_mutex);
Jesse Keating 7a32965
+	list_del(&client->link);
Jesse Keating 7a32965
+	mutex_unlock(&client->device->client_list_mutex);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	if (client->iso_context)
Jesse Keating 7a32965
 		fw_iso_context_destroy(client->iso_context);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	list_for_each_entry_safe(r, next_r, &client->resource_list, link)
Jesse Keating 7a32965
-		r->release(client, r);
Jesse Keating 7a32965
+	if (client->buffer.pages)
Jesse Keating 7a32965
+		fw_iso_buffer_destroy(&client->buffer, client->device->card);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	/*
Jesse Keating 7a32965
-	 * FIXME: We should wait for the async tasklets to stop
Jesse Keating 7a32965
-	 * running before freeing the memory.
Jesse Keating 7a32965
-	 */
Jesse Keating 7a32965
+	/* Freeze client->resource_idr and client->event_list */
Jesse Keating 7a32965
+	spin_lock_irq(&client->lock);
Jesse Keating 7a32965
+	client->in_shutdown = true;
Jesse Keating 7a32965
+	spin_unlock_irq(&client->lock);
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	idr_for_each(&client->resource_idr, shutdown_resource, client);
Jesse Keating 7a32965
+	idr_remove_all(&client->resource_idr);
Jesse Keating 7a32965
+	idr_destroy(&client->resource_idr);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	list_for_each_entry_safe(e, next_e, &client->event_list, link)
Jesse Keating 7a32965
 		kfree(e);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	spin_lock_irqsave(&client->device->card->lock, flags);
Jesse Keating 7a32965
-	list_del(&client->link);
Jesse Keating 7a32965
-	spin_unlock_irqrestore(&client->device->card->lock, flags);
Jesse Keating 7a32965
-
Jesse Keating 7a32965
-	fw_device_put(client->device);
Jesse Keating 7a32965
-	kfree(client);
Jesse Keating 7a32965
+	client_put(client);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	return 0;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
diff -Naurp linux-2.6-git/drivers/firewire/fw-device.c firewire-git/drivers/firewire/fw-device.c
Jesse Keating 7a32965
--- linux-2.6-git/drivers/firewire/fw-device.c	2009-01-30 13:39:02.989651512 -0500
Jesse Keating 7a32965
+++ firewire-git/drivers/firewire/fw-device.c	2009-01-30 13:35:51.860646788 -0500
Jesse Keating 7a32965
@@ -27,8 +27,10 @@
Jesse Keating 7a32965
 #include <linux/idr.h>
Jesse Keating 7a32965
 #include <linux/jiffies.h>
Jesse Keating 7a32965
 #include <linux/string.h>
Jesse Keating 7a32965
+#include <linux/mutex.h>
Jesse Keating 7a32965
 #include <linux/rwsem.h>
Jesse Keating 7a32965
 #include <linux/semaphore.h>
Jesse Keating 7a32965
+#include <linux/spinlock.h>
Jesse Keating 7a32965
 #include <asm/system.h>
Jesse Keating 7a32965
 #include <linux/ctype.h>
Jesse Keating 7a32965
 #include "fw-transaction.h"
Jesse Keating 7a32965
@@ -132,8 +134,7 @@ static int get_modalias(struct fw_unit *
Jesse Keating 7a32965
 			vendor, model, specifier_id, version);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static int
Jesse Keating 7a32965
-fw_unit_uevent(struct device *dev, struct kobj_uevent_env *env)
Jesse Keating 7a32965
+static int fw_unit_uevent(struct device *dev, struct kobj_uevent_env *env)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_unit *unit = fw_unit(dev);
Jesse Keating 7a32965
 	char modalias[64];
Jesse Keating 7a32965
@@ -191,8 +192,8 @@ struct config_rom_attribute {
Jesse Keating 7a32965
 	u32 key;
Jesse Keating 7a32965
 };
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static ssize_t
Jesse Keating 7a32965
-show_immediate(struct device *dev, struct device_attribute *dattr, char *buf)
Jesse Keating 7a32965
+static ssize_t show_immediate(struct device *dev,
Jesse Keating 7a32965
+			      struct device_attribute *dattr, char *buf)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct config_rom_attribute *attr =
Jesse Keating 7a32965
 		container_of(dattr, struct config_rom_attribute, attr);
Jesse Keating 7a32965
@@ -223,8 +224,8 @@ show_immediate(struct device *dev, struc
Jesse Keating 7a32965
 #define IMMEDIATE_ATTR(name, key)				\
Jesse Keating 7a32965
 	{ __ATTR(name, S_IRUGO, show_immediate, NULL), key }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static ssize_t
Jesse Keating 7a32965
-show_text_leaf(struct device *dev, struct device_attribute *dattr, char *buf)
Jesse Keating 7a32965
+static ssize_t show_text_leaf(struct device *dev,
Jesse Keating 7a32965
+			      struct device_attribute *dattr, char *buf)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct config_rom_attribute *attr =
Jesse Keating 7a32965
 		container_of(dattr, struct config_rom_attribute, attr);
Jesse Keating 7a32965
@@ -293,10 +294,9 @@ static struct config_rom_attribute confi
Jesse Keating 7a32965
 	TEXT_LEAF_ATTR(hardware_version_name, CSR_HARDWARE_VERSION),
Jesse Keating 7a32965
 };
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static void
Jesse Keating 7a32965
-init_fw_attribute_group(struct device *dev,
Jesse Keating 7a32965
-			struct device_attribute *attrs,
Jesse Keating 7a32965
-			struct fw_attribute_group *group)
Jesse Keating 7a32965
+static void init_fw_attribute_group(struct device *dev,
Jesse Keating 7a32965
+				    struct device_attribute *attrs,
Jesse Keating 7a32965
+				    struct fw_attribute_group *group)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct device_attribute *attr;
Jesse Keating 7a32965
 	int i, j;
Jesse Keating 7a32965
@@ -319,9 +319,8 @@ init_fw_attribute_group(struct device *d
Jesse Keating 7a32965
 	dev->groups = group->groups;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static ssize_t
Jesse Keating 7a32965
-modalias_show(struct device *dev,
Jesse Keating 7a32965
-	      struct device_attribute *attr, char *buf)
Jesse Keating 7a32965
+static ssize_t modalias_show(struct device *dev,
Jesse Keating 7a32965
+			     struct device_attribute *attr, char *buf)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_unit *unit = fw_unit(dev);
Jesse Keating 7a32965
 	int length;
Jesse Keating 7a32965
@@ -332,9 +331,8 @@ modalias_show(struct device *dev,
Jesse Keating 7a32965
 	return length + 1;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static ssize_t
Jesse Keating 7a32965
-rom_index_show(struct device *dev,
Jesse Keating 7a32965
-	       struct device_attribute *attr, char *buf)
Jesse Keating 7a32965
+static ssize_t rom_index_show(struct device *dev,
Jesse Keating 7a32965
+			      struct device_attribute *attr, char *buf)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_device *device = fw_device(dev->parent);
Jesse Keating 7a32965
 	struct fw_unit *unit = fw_unit(dev);
Jesse Keating 7a32965
@@ -349,8 +347,8 @@ static struct device_attribute fw_unit_a
Jesse Keating 7a32965
 	__ATTR_NULL,
Jesse Keating 7a32965
 };
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static ssize_t
Jesse Keating 7a32965
-config_rom_show(struct device *dev, struct device_attribute *attr, char *buf)
Jesse Keating 7a32965
+static ssize_t config_rom_show(struct device *dev,
Jesse Keating 7a32965
+			       struct device_attribute *attr, char *buf)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_device *device = fw_device(dev);
Jesse Keating 7a32965
 	size_t length;
Jesse Keating 7a32965
@@ -363,8 +361,8 @@ config_rom_show(struct device *dev, stru
Jesse Keating 7a32965
 	return length;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static ssize_t
Jesse Keating 7a32965
-guid_show(struct device *dev, struct device_attribute *attr, char *buf)
Jesse Keating 7a32965
+static ssize_t guid_show(struct device *dev,
Jesse Keating 7a32965
+			 struct device_attribute *attr, char *buf)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_device *device = fw_device(dev);
Jesse Keating 7a32965
 	int ret;
Jesse Keating 7a32965
@@ -383,8 +381,8 @@ static struct device_attribute fw_device
Jesse Keating 7a32965
 	__ATTR_NULL,
Jesse Keating 7a32965
 };
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static int
Jesse Keating 7a32965
-read_rom(struct fw_device *device, int generation, int index, u32 *data)
Jesse Keating 7a32965
+static int read_rom(struct fw_device *device,
Jesse Keating 7a32965
+		    int generation, int index, u32 *data)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	int rcode;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
@@ -1004,6 +1002,7 @@ void fw_node_event(struct fw_card *card,
Jesse Keating 7a32965
 		device->node = fw_node_get(node);
Jesse Keating 7a32965
 		device->node_id = node->node_id;
Jesse Keating 7a32965
 		device->generation = card->generation;
Jesse Keating 7a32965
+		mutex_init(&device->client_list_mutex);
Jesse Keating 7a32965
 		INIT_LIST_HEAD(&device->client_list);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 		/*
Jesse Keating 7a32965
diff -Naurp linux-2.6-git/drivers/firewire/fw-device.h firewire-git/drivers/firewire/fw-device.h
Jesse Keating 7a32965
--- linux-2.6-git/drivers/firewire/fw-device.h	2009-01-30 13:39:02.989651512 -0500
Jesse Keating 7a32965
+++ firewire-git/drivers/firewire/fw-device.h	2009-01-30 13:35:51.860646788 -0500
Jesse Keating 7a32965
@@ -23,6 +23,7 @@
Jesse Keating 7a32965
 #include <linux/cdev.h>
Jesse Keating 7a32965
 #include <linux/idr.h>
Jesse Keating 7a32965
 #include <linux/rwsem.h>
Jesse Keating 7a32965
+#include <linux/mutex.h>
Jesse Keating 7a32965
 #include <asm/atomic.h>
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 enum fw_device_state {
Jesse Keating 7a32965
@@ -64,7 +65,10 @@ struct fw_device {
Jesse Keating 7a32965
 	bool cmc;
Jesse Keating 7a32965
 	struct fw_card *card;
Jesse Keating 7a32965
 	struct device device;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	struct mutex client_list_mutex;
Jesse Keating 7a32965
 	struct list_head client_list;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
 	u32 *config_rom;
Jesse Keating 7a32965
 	size_t config_rom_length;
Jesse Keating 7a32965
 	int config_rom_retries;
Jesse Keating 7a32965
@@ -176,8 +180,7 @@ struct fw_driver {
Jesse Keating 7a32965
 	const struct fw_device_id *id_table;
Jesse Keating 7a32965
 };
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static inline struct fw_driver *
Jesse Keating 7a32965
-fw_driver(struct device_driver *drv)
Jesse Keating 7a32965
+static inline struct fw_driver *fw_driver(struct device_driver *drv)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	return container_of(drv, struct fw_driver, driver);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
diff -Naurp linux-2.6-git/drivers/firewire/fw-iso.c firewire-git/drivers/firewire/fw-iso.c
Jesse Keating 7a32965
--- linux-2.6-git/drivers/firewire/fw-iso.c	2008-11-04 11:18:33.000000000 -0500
Jesse Keating 7a32965
+++ firewire-git/drivers/firewire/fw-iso.c	2009-01-30 13:35:51.860646788 -0500
Jesse Keating 7a32965
@@ -1,5 +1,7 @@
Jesse Keating 7a32965
 /*
Jesse Keating 7a32965
- * Isochronous IO functionality
Jesse Keating 7a32965
+ * Isochronous I/O functionality:
Jesse Keating 7a32965
+ *   - Isochronous DMA context management
Jesse Keating 7a32965
+ *   - Isochronous bus resource management (channels, bandwidth), client side
Jesse Keating 7a32965
  *
Jesse Keating 7a32965
  * Copyright (C) 2006 Kristian Hoegsberg <krh@bitplanet.net>
Jesse Keating 7a32965
  *
Jesse Keating 7a32965
@@ -18,21 +20,25 @@
Jesse Keating 7a32965
  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Jesse Keating 7a32965
  */
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-#include <linux/kernel.h>
Jesse Keating 7a32965
-#include <linux/module.h>
Jesse Keating 7a32965
 #include <linux/dma-mapping.h>
Jesse Keating 7a32965
-#include <linux/vmalloc.h>
Jesse Keating 7a32965
+#include <linux/errno.h>
Jesse Keating 7a32965
+#include <linux/firewire-constants.h>
Jesse Keating 7a32965
+#include <linux/kernel.h>
Jesse Keating 7a32965
 #include <linux/mm.h>
Jesse Keating 7a32965
+#include <linux/spinlock.h>
Jesse Keating 7a32965
+#include <linux/vmalloc.h>
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-#include "fw-transaction.h"
Jesse Keating 7a32965
 #include "fw-topology.h"
Jesse Keating 7a32965
-#include "fw-device.h"
Jesse Keating 7a32965
+#include "fw-transaction.h"
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-int
Jesse Keating 7a32965
-fw_iso_buffer_init(struct fw_iso_buffer *buffer, struct fw_card *card,
Jesse Keating 7a32965
-		   int page_count, enum dma_data_direction direction)
Jesse Keating 7a32965
+/*
Jesse Keating 7a32965
+ * Isochronous DMA context management
Jesse Keating 7a32965
+ */
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+int fw_iso_buffer_init(struct fw_iso_buffer *buffer, struct fw_card *card,
Jesse Keating 7a32965
+		       int page_count, enum dma_data_direction direction)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
-	int i, j, retval = -ENOMEM;
Jesse Keating 7a32965
+	int i, j;
Jesse Keating 7a32965
 	dma_addr_t address;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	buffer->page_count = page_count;
Jesse Keating 7a32965
@@ -69,19 +75,19 @@ fw_iso_buffer_init(struct fw_iso_buffer 
Jesse Keating 7a32965
 	kfree(buffer->pages);
Jesse Keating 7a32965
  out:
Jesse Keating 7a32965
 	buffer->pages = NULL;
Jesse Keating 7a32965
-	return retval;
Jesse Keating 7a32965
+	return -ENOMEM;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	unsigned long uaddr;
Jesse Keating 7a32965
-	int i, retval;
Jesse Keating 7a32965
+	int i, ret;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	uaddr = vma->vm_start;
Jesse Keating 7a32965
 	for (i = 0; i < buffer->page_count; i++) {
Jesse Keating 7a32965
-		retval = vm_insert_page(vma, uaddr, buffer->pages[i]);
Jesse Keating 7a32965
-		if (retval)
Jesse Keating 7a32965
-			return retval;
Jesse Keating 7a32965
+		ret = vm_insert_page(vma, uaddr, buffer->pages[i]);
Jesse Keating 7a32965
+		if (ret)
Jesse Keating 7a32965
+			return ret;
Jesse Keating 7a32965
 		uaddr += PAGE_SIZE;
Jesse Keating 7a32965
 	}
Jesse Keating 7a32965
 
Jesse Keating 7a32965
@@ -105,14 +111,14 @@ void fw_iso_buffer_destroy(struct fw_iso
Jesse Keating 7a32965
 	buffer->pages = NULL;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-struct fw_iso_context *
Jesse Keating 7a32965
-fw_iso_context_create(struct fw_card *card, int type,
Jesse Keating 7a32965
-		      int channel, int speed, size_t header_size,
Jesse Keating 7a32965
-		      fw_iso_callback_t callback, void *callback_data)
Jesse Keating 7a32965
+struct fw_iso_context *fw_iso_context_create(struct fw_card *card,
Jesse Keating 7a32965
+		int type, int channel, int speed, size_t header_size,
Jesse Keating 7a32965
+		fw_iso_callback_t callback, void *callback_data)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_iso_context *ctx;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	ctx = card->driver->allocate_iso_context(card, type, header_size);
Jesse Keating 7a32965
+	ctx = card->driver->allocate_iso_context(card,
Jesse Keating 7a32965
+						 type, channel, header_size);
Jesse Keating 7a32965
 	if (IS_ERR(ctx))
Jesse Keating 7a32965
 		return ctx;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
@@ -134,25 +140,186 @@ void fw_iso_context_destroy(struct fw_is
Jesse Keating 7a32965
 	card->driver->free_iso_context(ctx);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-int
Jesse Keating 7a32965
-fw_iso_context_start(struct fw_iso_context *ctx, int cycle, int sync, int tags)
Jesse Keating 7a32965
+int fw_iso_context_start(struct fw_iso_context *ctx,
Jesse Keating 7a32965
+			 int cycle, int sync, int tags)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	return ctx->card->driver->start_iso(ctx, cycle, sync, tags);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-int
Jesse Keating 7a32965
-fw_iso_context_queue(struct fw_iso_context *ctx,
Jesse Keating 7a32965
-		     struct fw_iso_packet *packet,
Jesse Keating 7a32965
-		     struct fw_iso_buffer *buffer,
Jesse Keating 7a32965
-		     unsigned long payload)
Jesse Keating 7a32965
+int fw_iso_context_queue(struct fw_iso_context *ctx,
Jesse Keating 7a32965
+			 struct fw_iso_packet *packet,
Jesse Keating 7a32965
+			 struct fw_iso_buffer *buffer,
Jesse Keating 7a32965
+			 unsigned long payload)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_card *card = ctx->card;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	return card->driver->queue_iso(ctx, packet, buffer, payload);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-int
Jesse Keating 7a32965
-fw_iso_context_stop(struct fw_iso_context *ctx)
Jesse Keating 7a32965
+int fw_iso_context_stop(struct fw_iso_context *ctx)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	return ctx->card->driver->stop_iso(ctx);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+/*
Jesse Keating 7a32965
+ * Isochronous bus resource management (channels, bandwidth), client side
Jesse Keating 7a32965
+ */
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+static int manage_bandwidth(struct fw_card *card, int irm_id, int generation,
Jesse Keating 7a32965
+			    int bandwidth, bool allocate)
Jesse Keating 7a32965
+{
Jesse Keating 7a32965
+	__be32 data[2];
Jesse Keating 7a32965
+	int try, new, old = allocate ? BANDWIDTH_AVAILABLE_INITIAL : 0;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	/*
Jesse Keating 7a32965
+	 * On a 1394a IRM with low contention, try < 1 is enough.
Jesse Keating 7a32965
+	 * On a 1394-1995 IRM, we need at least try < 2.
Jesse Keating 7a32965
+	 * Let's just do try < 5.
Jesse Keating 7a32965
+	 */
Jesse Keating 7a32965
+	for (try = 0; try < 5; try++) {
Jesse Keating 7a32965
+		new = allocate ? old - bandwidth : old + bandwidth;
Jesse Keating 7a32965
+		if (new < 0 || new > BANDWIDTH_AVAILABLE_INITIAL)
Jesse Keating 7a32965
+			break;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+		data[0] = cpu_to_be32(old);
Jesse Keating 7a32965
+		data[1] = cpu_to_be32(new);
Jesse Keating 7a32965
+		switch (fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP,
Jesse Keating 7a32965
+				irm_id, generation, SCODE_100,
Jesse Keating 7a32965
+				CSR_REGISTER_BASE + CSR_BANDWIDTH_AVAILABLE,
Jesse Keating 7a32965
+				data, sizeof(data))) {
Jesse Keating 7a32965
+		case RCODE_GENERATION:
Jesse Keating 7a32965
+			/* A generation change frees all bandwidth. */
Jesse Keating 7a32965
+			return allocate ? -EAGAIN : bandwidth;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+		case RCODE_COMPLETE:
Jesse Keating 7a32965
+			if (be32_to_cpup(data) == old)
Jesse Keating 7a32965
+				return bandwidth;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+			old = be32_to_cpup(data);
Jesse Keating 7a32965
+			/* Fall through. */
Jesse Keating 7a32965
+		}
Jesse Keating 7a32965
+	}
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	return -EIO;
Jesse Keating 7a32965
+}
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+static int manage_channel(struct fw_card *card, int irm_id, int generation,
Jesse Keating 7a32965
+			  u32 channels_mask, u64 offset, bool allocate)
Jesse Keating 7a32965
+{
Jesse Keating 7a32965
+	__be32 data[2], c, all, old;
Jesse Keating 7a32965
+	int i, retry = 5;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	old = all = allocate ? cpu_to_be32(~0) : 0;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	for (i = 0; i < 32; i++) {
Jesse Keating 7a32965
+		if (!(channels_mask & 1 << i))
Jesse Keating 7a32965
+			continue;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+		c = cpu_to_be32(1 << (31 - i));
Jesse Keating 7a32965
+		if ((old & c) != (all & c))
Jesse Keating 7a32965
+			continue;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+		data[0] = old;
Jesse Keating 7a32965
+		data[1] = old ^ c;
Jesse Keating 7a32965
+		switch (fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP,
Jesse Keating 7a32965
+					   irm_id, generation, SCODE_100,
Jesse Keating 7a32965
+					   offset, data, sizeof(data))) {
Jesse Keating 7a32965
+		case RCODE_GENERATION:
Jesse Keating 7a32965
+			/* A generation change frees all channels. */
Jesse Keating 7a32965
+			return allocate ? -EAGAIN : i;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+		case RCODE_COMPLETE:
Jesse Keating 7a32965
+			if (data[0] == old)
Jesse Keating 7a32965
+				return i;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+			old = data[0];
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+			/* Is the IRM 1394a-2000 compliant? */
Jesse Keating 7a32965
+			if ((data[0] & c) == (data[1] & c))
Jesse Keating 7a32965
+				continue;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+			/* 1394-1995 IRM, fall through to retry. */
Jesse Keating 7a32965
+		default:
Jesse Keating 7a32965
+			if (retry--)
Jesse Keating 7a32965
+				i--;
Jesse Keating 7a32965
+		}
Jesse Keating 7a32965
+	}
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	return -EIO;
Jesse Keating 7a32965
+}
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+static void deallocate_channel(struct fw_card *card, int irm_id,
Jesse Keating 7a32965
+			       int generation, int channel)
Jesse Keating 7a32965
+{
Jesse Keating 7a32965
+	u32 mask;
Jesse Keating 7a32965
+	u64 offset;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	mask = channel < 32 ? 1 << channel : 1 << (channel - 32);
Jesse Keating 7a32965
+	offset = channel < 32 ? CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI :
Jesse Keating 7a32965
+				CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	manage_channel(card, irm_id, generation, mask, offset, false);
Jesse Keating 7a32965
+}
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+/**
Jesse Keating 7a32965
+ * fw_iso_resource_manage - Allocate or deallocate a channel and/or bandwidth
Jesse Keating 7a32965
+ *
Jesse Keating 7a32965
+ * In parameters: card, generation, channels_mask, bandwidth, allocate
Jesse Keating 7a32965
+ * Out parameters: channel, bandwidth
Jesse Keating 7a32965
+ * This function blocks (sleeps) during communication with the IRM.
Jesse Keating 7a32965
+ *
Jesse Keating 7a32965
+ * Allocates or deallocates at most one channel out of channels_mask.
Jesse Keating 7a32965
+ * channels_mask is a bitfield with MSB for channel 63 and LSB for channel 0.
Jesse Keating 7a32965
+ * (Note, the IRM's CHANNELS_AVAILABLE is a big-endian bitfield with MSB for
Jesse Keating 7a32965
+ * channel 0 and LSB for channel 63.)
Jesse Keating 7a32965
+ * Allocates or deallocates as many bandwidth allocation units as specified.
Jesse Keating 7a32965
+ *
Jesse Keating 7a32965
+ * Returns channel < 0 if no channel was allocated or deallocated.
Jesse Keating 7a32965
+ * Returns bandwidth = 0 if no bandwidth was allocated or deallocated.
Jesse Keating 7a32965
+ *
Jesse Keating 7a32965
+ * If generation is stale, deallocations succeed but allocations fail with
Jesse Keating 7a32965
+ * channel = -EAGAIN.
Jesse Keating 7a32965
+ *
Jesse Keating 7a32965
+ * If channel allocation fails, no bandwidth will be allocated either.
Jesse Keating 7a32965
+ * If bandwidth allocation fails, no channel will be allocated either.
Jesse Keating 7a32965
+ * But deallocations of channel and bandwidth are tried independently
Jesse Keating 7a32965
+ * of each other's success.
Jesse Keating 7a32965
+ */
Jesse Keating 7a32965
+void fw_iso_resource_manage(struct fw_card *card, int generation,
Jesse Keating 7a32965
+			    u64 channels_mask, int *channel, int *bandwidth,
Jesse Keating 7a32965
+			    bool allocate)
Jesse Keating 7a32965
+{
Jesse Keating 7a32965
+	u32 channels_hi = channels_mask;	/* channels 31...0 */
Jesse Keating 7a32965
+	u32 channels_lo = channels_mask >> 32;	/* channels 63...32 */
Jesse Keating 7a32965
+	int irm_id, ret, c = -EINVAL;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	spin_lock_irq(&card->lock);
Jesse Keating 7a32965
+	irm_id = card->irm_node->node_id;
Jesse Keating 7a32965
+	spin_unlock_irq(&card->lock);
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	if (channels_hi)
Jesse Keating 7a32965
+		c = manage_channel(card, irm_id, generation, channels_hi,
Jesse Keating 7a32965
+		    CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI, allocate);
Jesse Keating 7a32965
+	if (channels_lo && c < 0) {
Jesse Keating 7a32965
+		c = manage_channel(card, irm_id, generation, channels_lo,
Jesse Keating 7a32965
+		    CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO, allocate);
Jesse Keating 7a32965
+		if (c >= 0)
Jesse Keating 7a32965
+			c += 32;
Jesse Keating 7a32965
+	}
Jesse Keating 7a32965
+	*channel = c;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	if (allocate && channels_mask != 0 && c < 0)
Jesse Keating 7a32965
+		*bandwidth = 0;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	if (*bandwidth == 0)
Jesse Keating 7a32965
+		return;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	ret = manage_bandwidth(card, irm_id, generation, *bandwidth, allocate);
Jesse Keating 7a32965
+	if (ret < 0)
Jesse Keating 7a32965
+		*bandwidth = 0;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	if (allocate && ret < 0 && c >= 0) {
Jesse Keating 7a32965
+		deallocate_channel(card, irm_id, generation, c);
Jesse Keating 7a32965
+		*channel = ret;
Jesse Keating 7a32965
+	}
Jesse Keating 7a32965
+}
Jesse Keating 7a32965
diff -Naurp linux-2.6-git/drivers/firewire/fw-ohci.c firewire-git/drivers/firewire/fw-ohci.c
Jesse Keating 7a32965
--- linux-2.6-git/drivers/firewire/fw-ohci.c	2009-01-30 13:39:02.990772025 -0500
Jesse Keating 7a32965
+++ firewire-git/drivers/firewire/fw-ohci.c	2009-01-30 13:35:51.861646907 -0500
Jesse Keating 7a32965
@@ -205,6 +205,7 @@ struct fw_ohci {
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	u32 it_context_mask;
Jesse Keating 7a32965
 	struct iso_context *it_context_list;
Jesse Keating 7a32965
+	u64 ir_context_channels;
Jesse Keating 7a32965
 	u32 ir_context_mask;
Jesse Keating 7a32965
 	struct iso_context *ir_context_list;
Jesse Keating 7a32965
 };
Jesse Keating 7a32965
@@ -441,9 +442,8 @@ static inline void flush_writes(const st
Jesse Keating 7a32965
 	reg_read(ohci, OHCI1394_Version);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static int
Jesse Keating 7a32965
-ohci_update_phy_reg(struct fw_card *card, int addr,
Jesse Keating 7a32965
-		    int clear_bits, int set_bits)
Jesse Keating 7a32965
+static int ohci_update_phy_reg(struct fw_card *card, int addr,
Jesse Keating 7a32965
+			       int clear_bits, int set_bits)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_ohci *ohci = fw_ohci(card);
Jesse Keating 7a32965
 	u32 val, old;
Jesse Keating 7a32965
@@ -658,8 +658,8 @@ static void ar_context_tasklet(unsigned 
Jesse Keating 7a32965
 	}
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static int
Jesse Keating 7a32965
-ar_context_init(struct ar_context *ctx, struct fw_ohci *ohci, u32 regs)
Jesse Keating 7a32965
+static int ar_context_init(struct ar_context *ctx,
Jesse Keating 7a32965
+			   struct fw_ohci *ohci, u32 regs)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct ar_buffer ab;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
@@ -690,8 +690,7 @@ static void ar_context_run(struct ar_con
Jesse Keating 7a32965
 	flush_writes(ctx->ohci);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static struct descriptor *
Jesse Keating 7a32965
-find_branch_descriptor(struct descriptor *d, int z)
Jesse Keating 7a32965
+static struct descriptor *find_branch_descriptor(struct descriptor *d, int z)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	int b, key;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
@@ -751,8 +750,7 @@ static void context_tasklet(unsigned lon
Jesse Keating 7a32965
  * Allocate a new buffer and add it to the list of free buffers for this
Jesse Keating 7a32965
  * context.  Must be called with ohci->lock held.
Jesse Keating 7a32965
  */
Jesse Keating 7a32965
-static int
Jesse Keating 7a32965
-context_add_buffer(struct context *ctx)
Jesse Keating 7a32965
+static int context_add_buffer(struct context *ctx)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct descriptor_buffer *desc;
Jesse Keating 7a32965
 	dma_addr_t uninitialized_var(bus_addr);
Jesse Keating 7a32965
@@ -781,9 +779,8 @@ context_add_buffer(struct context *ctx)
Jesse Keating 7a32965
 	return 0;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static int
Jesse Keating 7a32965
-context_init(struct context *ctx, struct fw_ohci *ohci,
Jesse Keating 7a32965
-	     u32 regs, descriptor_callback_t callback)
Jesse Keating 7a32965
+static int context_init(struct context *ctx, struct fw_ohci *ohci,
Jesse Keating 7a32965
+			u32 regs, descriptor_callback_t callback)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	ctx->ohci = ohci;
Jesse Keating 7a32965
 	ctx->regs = regs;
Jesse Keating 7a32965
@@ -814,8 +811,7 @@ context_init(struct context *ctx, struct
Jesse Keating 7a32965
 	return 0;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static void
Jesse Keating 7a32965
-context_release(struct context *ctx)
Jesse Keating 7a32965
+static void context_release(struct context *ctx)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_card *card = &ctx->ohci->card;
Jesse Keating 7a32965
 	struct descriptor_buffer *desc, *tmp;
Jesse Keating 7a32965
@@ -827,8 +823,8 @@ context_release(struct context *ctx)
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 /* Must be called with ohci->lock held */
Jesse Keating 7a32965
-static struct descriptor *
Jesse Keating 7a32965
-context_get_descriptors(struct context *ctx, int z, dma_addr_t *d_bus)
Jesse Keating 7a32965
+static struct descriptor *context_get_descriptors(struct context *ctx,
Jesse Keating 7a32965
+						  int z, dma_addr_t *d_bus)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct descriptor *d = NULL;
Jesse Keating 7a32965
 	struct descriptor_buffer *desc = ctx->buffer_tail;
Jesse Keating 7a32965
@@ -912,8 +908,8 @@ struct driver_data {
Jesse Keating 7a32965
  * Must always be called with the ochi->lock held to ensure proper
Jesse Keating 7a32965
  * generation handling and locking around packet queue manipulation.
Jesse Keating 7a32965
  */
Jesse Keating 7a32965
-static int
Jesse Keating 7a32965
-at_context_queue_packet(struct context *ctx, struct fw_packet *packet)
Jesse Keating 7a32965
+static int at_context_queue_packet(struct context *ctx,
Jesse Keating 7a32965
+				   struct fw_packet *packet)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_ohci *ohci = ctx->ohci;
Jesse Keating 7a32965
 	dma_addr_t d_bus, uninitialized_var(payload_bus);
Jesse Keating 7a32965
@@ -1095,8 +1091,8 @@ static int handle_at_packet(struct conte
Jesse Keating 7a32965
 #define HEADER_GET_DATA_LENGTH(q)	(((q) >> 16) & 0xffff)
Jesse Keating 7a32965
 #define HEADER_GET_EXTENDED_TCODE(q)	(((q) >> 0) & 0xffff)
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static void
Jesse Keating 7a32965
-handle_local_rom(struct fw_ohci *ohci, struct fw_packet *packet, u32 csr)
Jesse Keating 7a32965
+static void handle_local_rom(struct fw_ohci *ohci,
Jesse Keating 7a32965
+			     struct fw_packet *packet, u32 csr)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_packet response;
Jesse Keating 7a32965
 	int tcode, length, i;
Jesse Keating 7a32965
@@ -1122,8 +1118,8 @@ handle_local_rom(struct fw_ohci *ohci, s
Jesse Keating 7a32965
 	fw_core_handle_response(&ohci->card, &response);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static void
Jesse Keating 7a32965
-handle_local_lock(struct fw_ohci *ohci, struct fw_packet *packet, u32 csr)
Jesse Keating 7a32965
+static void handle_local_lock(struct fw_ohci *ohci,
Jesse Keating 7a32965
+			      struct fw_packet *packet, u32 csr)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_packet response;
Jesse Keating 7a32965
 	int tcode, length, ext_tcode, sel;
Jesse Keating 7a32965
@@ -1164,8 +1160,7 @@ handle_local_lock(struct fw_ohci *ohci, 
Jesse Keating 7a32965
 	fw_core_handle_response(&ohci->card, &response);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static void
Jesse Keating 7a32965
-handle_local_request(struct context *ctx, struct fw_packet *packet)
Jesse Keating 7a32965
+static void handle_local_request(struct context *ctx, struct fw_packet *packet)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	u64 offset;
Jesse Keating 7a32965
 	u32 csr;
Jesse Keating 7a32965
@@ -1205,11 +1200,10 @@ handle_local_request(struct context *ctx
Jesse Keating 7a32965
 	}
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static void
Jesse Keating 7a32965
-at_context_transmit(struct context *ctx, struct fw_packet *packet)
Jesse Keating 7a32965
+static void at_context_transmit(struct context *ctx, struct fw_packet *packet)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	unsigned long flags;
Jesse Keating 7a32965
-	int retval;
Jesse Keating 7a32965
+	int ret;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	spin_lock_irqsave(&ctx->ohci->lock, flags);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
@@ -1220,10 +1214,10 @@ at_context_transmit(struct context *ctx,
Jesse Keating 7a32965
 		return;
Jesse Keating 7a32965
 	}
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	retval = at_context_queue_packet(ctx, packet);
Jesse Keating 7a32965
+	ret = at_context_queue_packet(ctx, packet);
Jesse Keating 7a32965
 	spin_unlock_irqrestore(&ctx->ohci->lock, flags);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	if (retval < 0)
Jesse Keating 7a32965
+	if (ret < 0)
Jesse Keating 7a32965
 		packet->callback(packet, &ctx->ohci->card, packet->ack);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
@@ -1590,12 +1584,12 @@ static int ohci_enable(struct fw_card *c
Jesse Keating 7a32965
 	return 0;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static int
Jesse Keating 7a32965
-ohci_set_config_rom(struct fw_card *card, u32 *config_rom, size_t length)
Jesse Keating 7a32965
+static int ohci_set_config_rom(struct fw_card *card,
Jesse Keating 7a32965
+			       u32 *config_rom, size_t length)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_ohci *ohci;
Jesse Keating 7a32965
 	unsigned long flags;
Jesse Keating 7a32965
-	int retval = -EBUSY;
Jesse Keating 7a32965
+	int ret = -EBUSY;
Jesse Keating 7a32965
 	__be32 *next_config_rom;
Jesse Keating 7a32965
 	dma_addr_t uninitialized_var(next_config_rom_bus);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
@@ -1649,7 +1643,7 @@ ohci_set_config_rom(struct fw_card *card
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 		reg_write(ohci, OHCI1394_ConfigROMmap,
Jesse Keating 7a32965
 			  ohci->next_config_rom_bus);
Jesse Keating 7a32965
-		retval = 0;
Jesse Keating 7a32965
+		ret = 0;
Jesse Keating 7a32965
 	}
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	spin_unlock_irqrestore(&ohci->lock, flags);
Jesse Keating 7a32965
@@ -1661,13 +1655,13 @@ ohci_set_config_rom(struct fw_card *card
Jesse Keating 7a32965
 	 * controller could need to access it before the bus reset
Jesse Keating 7a32965
 	 * takes effect.
Jesse Keating 7a32965
 	 */
Jesse Keating 7a32965
-	if (retval == 0)
Jesse Keating 7a32965
+	if (ret == 0)
Jesse Keating 7a32965
 		fw_core_initiate_bus_reset(&ohci->card, 1);
Jesse Keating 7a32965
 	else
Jesse Keating 7a32965
 		dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
Jesse Keating 7a32965
 				  next_config_rom, next_config_rom_bus);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	return retval;
Jesse Keating 7a32965
+	return ret;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 static void ohci_send_request(struct fw_card *card, struct fw_packet *packet)
Jesse Keating 7a32965
@@ -1689,7 +1683,7 @@ static int ohci_cancel_packet(struct fw_
Jesse Keating 7a32965
 	struct fw_ohci *ohci = fw_ohci(card);
Jesse Keating 7a32965
 	struct context *ctx = &ohci->at_request_ctx;
Jesse Keating 7a32965
 	struct driver_data *driver_data = packet->driver_data;
Jesse Keating 7a32965
-	int retval = -ENOENT;
Jesse Keating 7a32965
+	int ret = -ENOENT;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	tasklet_disable(&ctx->tasklet);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
@@ -1704,23 +1698,22 @@ static int ohci_cancel_packet(struct fw_
Jesse Keating 7a32965
 	driver_data->packet = NULL;
Jesse Keating 7a32965
 	packet->ack = RCODE_CANCELLED;
Jesse Keating 7a32965
 	packet->callback(packet, &ohci->card, packet->ack);
Jesse Keating 7a32965
-	retval = 0;
Jesse Keating 7a32965
-
Jesse Keating 7a32965
+	ret = 0;
Jesse Keating 7a32965
  out:
Jesse Keating 7a32965
 	tasklet_enable(&ctx->tasklet);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	return retval;
Jesse Keating 7a32965
+	return ret;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static int
Jesse Keating 7a32965
-ohci_enable_phys_dma(struct fw_card *card, int node_id, int generation)
Jesse Keating 7a32965
+static int ohci_enable_phys_dma(struct fw_card *card,
Jesse Keating 7a32965
+				int node_id, int generation)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 #ifdef CONFIG_FIREWIRE_OHCI_REMOTE_DMA
Jesse Keating 7a32965
 	return 0;
Jesse Keating 7a32965
 #else
Jesse Keating 7a32965
 	struct fw_ohci *ohci = fw_ohci(card);
Jesse Keating 7a32965
 	unsigned long flags;
Jesse Keating 7a32965
-	int n, retval = 0;
Jesse Keating 7a32965
+	int n, ret = 0;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	/*
Jesse Keating 7a32965
 	 * FIXME:  Make sure this bitmask is cleared when we clear the busReset
Jesse Keating 7a32965
@@ -1730,7 +1723,7 @@ ohci_enable_phys_dma(struct fw_card *car
Jesse Keating 7a32965
 	spin_lock_irqsave(&ohci->lock, flags);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	if (ohci->generation != generation) {
Jesse Keating 7a32965
-		retval = -ESTALE;
Jesse Keating 7a32965
+		ret = -ESTALE;
Jesse Keating 7a32965
 		goto out;
Jesse Keating 7a32965
 	}
Jesse Keating 7a32965
 
Jesse Keating 7a32965
@@ -1748,12 +1741,12 @@ ohci_enable_phys_dma(struct fw_card *car
Jesse Keating 7a32965
 	flush_writes(ohci);
Jesse Keating 7a32965
  out:
Jesse Keating 7a32965
 	spin_unlock_irqrestore(&ohci->lock, flags);
Jesse Keating 7a32965
-	return retval;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	return ret;
Jesse Keating 7a32965
 #endif /* CONFIG_FIREWIRE_OHCI_REMOTE_DMA */
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static u64
Jesse Keating 7a32965
-ohci_get_bus_time(struct fw_card *card)
Jesse Keating 7a32965
+static u64 ohci_get_bus_time(struct fw_card *card)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_ohci *ohci = fw_ohci(card);
Jesse Keating 7a32965
 	u32 cycle_time;
Jesse Keating 7a32965
@@ -1765,6 +1758,28 @@ ohci_get_bus_time(struct fw_card *card)
Jesse Keating 7a32965
 	return bus_time;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
+static void copy_iso_headers(struct iso_context *ctx, void *p)
Jesse Keating 7a32965
+{
Jesse Keating 7a32965
+	int i = ctx->header_length;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	if (i + ctx->base.header_size > PAGE_SIZE)
Jesse Keating 7a32965
+		return;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+	/*
Jesse Keating 7a32965
+	 * The iso header is byteswapped to little endian by
Jesse Keating 7a32965
+	 * the controller, but the remaining header quadlets
Jesse Keating 7a32965
+	 * are big endian.  We want to present all the headers
Jesse Keating 7a32965
+	 * as big endian, so we have to swap the first quadlet.
Jesse Keating 7a32965
+	 */
Jesse Keating 7a32965
+	if (ctx->base.header_size > 0)
Jesse Keating 7a32965
+		*(u32 *) (ctx->header + i) = __swab32(*(u32 *) (p + 4));
Jesse Keating 7a32965
+	if (ctx->base.header_size > 4)
Jesse Keating 7a32965
+		*(u32 *) (ctx->header + i + 4) = __swab32(*(u32 *) p);
Jesse Keating 7a32965
+	if (ctx->base.header_size > 8)
Jesse Keating 7a32965
+		memcpy(ctx->header + i + 8, p + 8, ctx->base.header_size - 8);
Jesse Keating 7a32965
+	ctx->header_length += ctx->base.header_size;
Jesse Keating 7a32965
+}
Jesse Keating 7a32965
+
Jesse Keating 7a32965
 static int handle_ir_dualbuffer_packet(struct context *context,
Jesse Keating 7a32965
 				       struct descriptor *d,
Jesse Keating 7a32965
 				       struct descriptor *last)
Jesse Keating 7a32965
@@ -1775,7 +1790,6 @@ static int handle_ir_dualbuffer_packet(s
Jesse Keating 7a32965
 	__le32 *ir_header;
Jesse Keating 7a32965
 	size_t header_length;
Jesse Keating 7a32965
 	void *p, *end;
Jesse Keating 7a32965
-	int i;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	if (db->first_res_count != 0 && db->second_res_count != 0) {
Jesse Keating 7a32965
 		if (ctx->excess_bytes <= le16_to_cpu(db->second_req_count)) {
Jesse Keating 7a32965
@@ -1788,25 +1802,14 @@ static int handle_ir_dualbuffer_packet(s
Jesse Keating 7a32965
 	header_length = le16_to_cpu(db->first_req_count) -
Jesse Keating 7a32965
 		le16_to_cpu(db->first_res_count);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	i = ctx->header_length;
Jesse Keating 7a32965
 	p = db + 1;
Jesse Keating 7a32965
 	end = p + header_length;
Jesse Keating 7a32965
-	while (p < end && i + ctx->base.header_size <= PAGE_SIZE) {
Jesse Keating 7a32965
-		/*
Jesse Keating 7a32965
-		 * The iso header is byteswapped to little endian by
Jesse Keating 7a32965
-		 * the controller, but the remaining header quadlets
Jesse Keating 7a32965
-		 * are big endian.  We want to present all the headers
Jesse Keating 7a32965
-		 * as big endian, so we have to swap the first
Jesse Keating 7a32965
-		 * quadlet.
Jesse Keating 7a32965
-		 */
Jesse Keating 7a32965
-		*(u32 *) (ctx->header + i) = __swab32(*(u32 *) (p + 4));
Jesse Keating 7a32965
-		memcpy(ctx->header + i + 4, p + 8, ctx->base.header_size - 4);
Jesse Keating 7a32965
-		i += ctx->base.header_size;
Jesse Keating 7a32965
+	while (p < end) {
Jesse Keating 7a32965
+		copy_iso_headers(ctx, p);
Jesse Keating 7a32965
 		ctx->excess_bytes +=
Jesse Keating 7a32965
 			(le32_to_cpu(*(__le32 *)(p + 4)) >> 16) & 0xffff;
Jesse Keating 7a32965
-		p += ctx->base.header_size + 4;
Jesse Keating 7a32965
+		p += max(ctx->base.header_size, (size_t)8);
Jesse Keating 7a32965
 	}
Jesse Keating 7a32965
-	ctx->header_length = i;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	ctx->excess_bytes -= le16_to_cpu(db->second_req_count) -
Jesse Keating 7a32965
 		le16_to_cpu(db->second_res_count);
Jesse Keating 7a32965
@@ -1832,7 +1835,6 @@ static int handle_ir_packet_per_buffer(s
Jesse Keating 7a32965
 	struct descriptor *pd;
Jesse Keating 7a32965
 	__le32 *ir_header;
Jesse Keating 7a32965
 	void *p;
Jesse Keating 7a32965
-	int i;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	for (pd = d; pd <= last; pd++) {
Jesse Keating 7a32965
 		if (pd->transfer_status)
Jesse Keating 7a32965
@@ -1842,21 +1844,8 @@ static int handle_ir_packet_per_buffer(s
Jesse Keating 7a32965
 		/* Descriptor(s) not done yet, stop iteration */
Jesse Keating 7a32965
 		return 0;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	i   = ctx->header_length;
Jesse Keating 7a32965
-	p   = last + 1;
Jesse Keating 7a32965
-
Jesse Keating 7a32965
-	if (ctx->base.header_size > 0 &&
Jesse Keating 7a32965
-			i + ctx->base.header_size <= PAGE_SIZE) {
Jesse Keating 7a32965
-		/*
Jesse Keating 7a32965
-		 * The iso header is byteswapped to little endian by
Jesse Keating 7a32965
-		 * the controller, but the remaining header quadlets
Jesse Keating 7a32965
-		 * are big endian.  We want to present all the headers
Jesse Keating 7a32965
-		 * as big endian, so we have to swap the first quadlet.
Jesse Keating 7a32965
-		 */
Jesse Keating 7a32965
-		*(u32 *) (ctx->header + i) = __swab32(*(u32 *) (p + 4));
Jesse Keating 7a32965
-		memcpy(ctx->header + i + 4, p + 8, ctx->base.header_size - 4);
Jesse Keating 7a32965
-		ctx->header_length += ctx->base.header_size;
Jesse Keating 7a32965
-	}
Jesse Keating 7a32965
+	p = last + 1;
Jesse Keating 7a32965
+	copy_iso_headers(ctx, p);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	if (le16_to_cpu(last->control) & DESCRIPTOR_IRQ_ALWAYS) {
Jesse Keating 7a32965
 		ir_header = (__le32 *) p;
Jesse Keating 7a32965
@@ -1888,21 +1877,24 @@ static int handle_it_packet(struct conte
Jesse Keating 7a32965
 	return 1;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static struct fw_iso_context *
Jesse Keating 7a32965
-ohci_allocate_iso_context(struct fw_card *card, int type, size_t header_size)
Jesse Keating 7a32965
+static struct fw_iso_context *ohci_allocate_iso_context(struct fw_card *card,
Jesse Keating 7a32965
+				int type, int channel, size_t header_size)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_ohci *ohci = fw_ohci(card);
Jesse Keating 7a32965
 	struct iso_context *ctx, *list;
Jesse Keating 7a32965
 	descriptor_callback_t callback;
Jesse Keating 7a32965
+	u64 *channels, dont_care = ~0ULL;
Jesse Keating 7a32965
 	u32 *mask, regs;
Jesse Keating 7a32965
 	unsigned long flags;
Jesse Keating 7a32965
-	int index, retval = -ENOMEM;
Jesse Keating 7a32965
+	int index, ret = -ENOMEM;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	if (type == FW_ISO_CONTEXT_TRANSMIT) {
Jesse Keating 7a32965
+		channels = &dont_care;
Jesse Keating 7a32965
 		mask = &ohci->it_context_mask;
Jesse Keating 7a32965
 		list = ohci->it_context_list;
Jesse Keating 7a32965
 		callback = handle_it_packet;
Jesse Keating 7a32965
 	} else {
Jesse Keating 7a32965
+		channels = &ohci->ir_context_channels;
Jesse Keating 7a32965
 		mask = &ohci->ir_context_mask;
Jesse Keating 7a32965
 		list = ohci->ir_context_list;
Jesse Keating 7a32965
 		if (ohci->use_dualbuffer)
Jesse Keating 7a32965
@@ -1912,9 +1904,11 @@ ohci_allocate_iso_context(struct fw_card
Jesse Keating 7a32965
 	}
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	spin_lock_irqsave(&ohci->lock, flags);
Jesse Keating 7a32965
-	index = ffs(*mask) - 1;
Jesse Keating 7a32965
-	if (index >= 0)
Jesse Keating 7a32965
+	index = *channels & 1ULL << channel ? ffs(*mask) - 1 : -1;
Jesse Keating 7a32965
+	if (index >= 0) {
Jesse Keating 7a32965
+		*channels &= ~(1ULL << channel);
Jesse Keating 7a32965
 		*mask &= ~(1 << index);
Jesse Keating 7a32965
+	}
Jesse Keating 7a32965
 	spin_unlock_irqrestore(&ohci->lock, flags);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	if (index < 0)
Jesse Keating 7a32965
@@ -1932,8 +1926,8 @@ ohci_allocate_iso_context(struct fw_card
Jesse Keating 7a32965
 	if (ctx->header == NULL)
Jesse Keating 7a32965
 		goto out;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	retval = context_init(&ctx->context, ohci, regs, callback);
Jesse Keating 7a32965
-	if (retval < 0)
Jesse Keating 7a32965
+	ret = context_init(&ctx->context, ohci, regs, callback);
Jesse Keating 7a32965
+	if (ret < 0)
Jesse Keating 7a32965
 		goto out_with_header;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	return &ctx->base;
Jesse Keating 7a32965
@@ -1945,7 +1939,7 @@ ohci_allocate_iso_context(struct fw_card
Jesse Keating 7a32965
 	*mask |= 1 << index;
Jesse Keating 7a32965
 	spin_unlock_irqrestore(&ohci->lock, flags);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	return ERR_PTR(retval);
Jesse Keating 7a32965
+	return ERR_PTR(ret);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 static int ohci_start_iso(struct fw_iso_context *base,
Jesse Keating 7a32965
@@ -2024,16 +2018,16 @@ static void ohci_free_iso_context(struct
Jesse Keating 7a32965
 	} else {
Jesse Keating 7a32965
 		index = ctx - ohci->ir_context_list;
Jesse Keating 7a32965
 		ohci->ir_context_mask |= 1 << index;
Jesse Keating 7a32965
+		ohci->ir_context_channels |= 1ULL << base->channel;
Jesse Keating 7a32965
 	}
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	spin_unlock_irqrestore(&ohci->lock, flags);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static int
Jesse Keating 7a32965
-ohci_queue_iso_transmit(struct fw_iso_context *base,
Jesse Keating 7a32965
-			struct fw_iso_packet *packet,
Jesse Keating 7a32965
-			struct fw_iso_buffer *buffer,
Jesse Keating 7a32965
-			unsigned long payload)
Jesse Keating 7a32965
+static int ohci_queue_iso_transmit(struct fw_iso_context *base,
Jesse Keating 7a32965
+				   struct fw_iso_packet *packet,
Jesse Keating 7a32965
+				   struct fw_iso_buffer *buffer,
Jesse Keating 7a32965
+				   unsigned long payload)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct iso_context *ctx = container_of(base, struct iso_context, base);
Jesse Keating 7a32965
 	struct descriptor *d, *last, *pd;
Jesse Keating 7a32965
@@ -2128,11 +2122,10 @@ ohci_queue_iso_transmit(struct fw_iso_co
Jesse Keating 7a32965
 	return 0;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static int
Jesse Keating 7a32965
-ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base,
Jesse Keating 7a32965
-				  struct fw_iso_packet *packet,
Jesse Keating 7a32965
-				  struct fw_iso_buffer *buffer,
Jesse Keating 7a32965
-				  unsigned long payload)
Jesse Keating 7a32965
+static int ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base,
Jesse Keating 7a32965
+					     struct fw_iso_packet *packet,
Jesse Keating 7a32965
+					     struct fw_iso_buffer *buffer,
Jesse Keating 7a32965
+					     unsigned long payload)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct iso_context *ctx = container_of(base, struct iso_context, base);
Jesse Keating 7a32965
 	struct db_descriptor *db = NULL;
Jesse Keating 7a32965
@@ -2151,11 +2144,11 @@ ohci_queue_iso_receive_dualbuffer(struct
Jesse Keating 7a32965
 	z = 2;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	/*
Jesse Keating 7a32965
-	 * The OHCI controller puts the status word in the header
Jesse Keating 7a32965
-	 * buffer too, so we need 4 extra bytes per packet.
Jesse Keating 7a32965
+	 * The OHCI controller puts the isochronous header and trailer in the
Jesse Keating 7a32965
+	 * buffer, so we need at least 8 bytes.
Jesse Keating 7a32965
 	 */
Jesse Keating 7a32965
 	packet_count = p->header_length / ctx->base.header_size;
Jesse Keating 7a32965
-	header_size = packet_count * (ctx->base.header_size + 4);
Jesse Keating 7a32965
+	header_size = packet_count * max(ctx->base.header_size, (size_t)8);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	/* Get header size in number of descriptors. */
Jesse Keating 7a32965
 	header_z = DIV_ROUND_UP(header_size, sizeof(*d));
Jesse Keating 7a32965
@@ -2173,7 +2166,8 @@ ohci_queue_iso_receive_dualbuffer(struct
Jesse Keating 7a32965
 		db = (struct db_descriptor *) d;
Jesse Keating 7a32965
 		db->control = cpu_to_le16(DESCRIPTOR_STATUS |
Jesse Keating 7a32965
 					  DESCRIPTOR_BRANCH_ALWAYS);
Jesse Keating 7a32965
-		db->first_size = cpu_to_le16(ctx->base.header_size + 4);
Jesse Keating 7a32965
+		db->first_size =
Jesse Keating 7a32965
+		    cpu_to_le16(max(ctx->base.header_size, (size_t)8));
Jesse Keating 7a32965
 		if (p->skip && rest == p->payload_length) {
Jesse Keating 7a32965
 			db->control |= cpu_to_le16(DESCRIPTOR_WAIT);
Jesse Keating 7a32965
 			db->first_req_count = db->first_size;
Jesse Keating 7a32965
@@ -2208,11 +2202,10 @@ ohci_queue_iso_receive_dualbuffer(struct
Jesse Keating 7a32965
 	return 0;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static int
Jesse Keating 7a32965
-ohci_queue_iso_receive_packet_per_buffer(struct fw_iso_context *base,
Jesse Keating 7a32965
-					 struct fw_iso_packet *packet,
Jesse Keating 7a32965
-					 struct fw_iso_buffer *buffer,
Jesse Keating 7a32965
-					 unsigned long payload)
Jesse Keating 7a32965
+static int ohci_queue_iso_receive_packet_per_buffer(struct fw_iso_context *base,
Jesse Keating 7a32965
+					struct fw_iso_packet *packet,
Jesse Keating 7a32965
+					struct fw_iso_buffer *buffer,
Jesse Keating 7a32965
+					unsigned long payload)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct iso_context *ctx = container_of(base, struct iso_context, base);
Jesse Keating 7a32965
 	struct descriptor *d = NULL, *pd = NULL;
Jesse Keating 7a32965
@@ -2223,11 +2216,11 @@ ohci_queue_iso_receive_packet_per_buffer
Jesse Keating 7a32965
 	int page, offset, packet_count, header_size, payload_per_buffer;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	/*
Jesse Keating 7a32965
-	 * The OHCI controller puts the status word in the
Jesse Keating 7a32965
-	 * buffer too, so we need 4 extra bytes per packet.
Jesse Keating 7a32965
+	 * The OHCI controller puts the isochronous header and trailer in the
Jesse Keating 7a32965
+	 * buffer, so we need at least 8 bytes.
Jesse Keating 7a32965
 	 */
Jesse Keating 7a32965
 	packet_count = p->header_length / ctx->base.header_size;
Jesse Keating 7a32965
-	header_size  = ctx->base.header_size + 4;
Jesse Keating 7a32965
+	header_size  = max(ctx->base.header_size, (size_t)8);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	/* Get header size in number of descriptors. */
Jesse Keating 7a32965
 	header_z = DIV_ROUND_UP(header_size, sizeof(*d));
Jesse Keating 7a32965
@@ -2286,29 +2279,27 @@ ohci_queue_iso_receive_packet_per_buffer
Jesse Keating 7a32965
 	return 0;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static int
Jesse Keating 7a32965
-ohci_queue_iso(struct fw_iso_context *base,
Jesse Keating 7a32965
-	       struct fw_iso_packet *packet,
Jesse Keating 7a32965
-	       struct fw_iso_buffer *buffer,
Jesse Keating 7a32965
-	       unsigned long payload)
Jesse Keating 7a32965
+static int ohci_queue_iso(struct fw_iso_context *base,
Jesse Keating 7a32965
+			  struct fw_iso_packet *packet,
Jesse Keating 7a32965
+			  struct fw_iso_buffer *buffer,
Jesse Keating 7a32965
+			  unsigned long payload)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct iso_context *ctx = container_of(base, struct iso_context, base);
Jesse Keating 7a32965
 	unsigned long flags;
Jesse Keating 7a32965
-	int retval;
Jesse Keating 7a32965
+	int ret;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	spin_lock_irqsave(&ctx->context.ohci->lock, flags);
Jesse Keating 7a32965
 	if (base->type == FW_ISO_CONTEXT_TRANSMIT)
Jesse Keating 7a32965
-		retval = ohci_queue_iso_transmit(base, packet, buffer, payload);
Jesse Keating 7a32965
+		ret = ohci_queue_iso_transmit(base, packet, buffer, payload);
Jesse Keating 7a32965
 	else if (ctx->context.ohci->use_dualbuffer)
Jesse Keating 7a32965
-		retval = ohci_queue_iso_receive_dualbuffer(base, packet,
Jesse Keating 7a32965
-							 buffer, payload);
Jesse Keating 7a32965
+		ret = ohci_queue_iso_receive_dualbuffer(base, packet,
Jesse Keating 7a32965
+							buffer, payload);
Jesse Keating 7a32965
 	else
Jesse Keating 7a32965
-		retval = ohci_queue_iso_receive_packet_per_buffer(base, packet,
Jesse Keating 7a32965
-								buffer,
Jesse Keating 7a32965
-								payload);
Jesse Keating 7a32965
+		ret = ohci_queue_iso_receive_packet_per_buffer(base, packet,
Jesse Keating 7a32965
+							buffer, payload);
Jesse Keating 7a32965
 	spin_unlock_irqrestore(&ctx->context.ohci->lock, flags);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	return retval;
Jesse Keating 7a32965
+	return ret;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 static const struct fw_card_driver ohci_driver = {
Jesse Keating 7a32965
@@ -2357,8 +2348,8 @@ static void ohci_pmac_off(struct pci_dev
Jesse Keating 7a32965
 #define ohci_pmac_off(dev)
Jesse Keating 7a32965
 #endif /* CONFIG_PPC_PMAC */
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static int __devinit
Jesse Keating 7a32965
-pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
Jesse Keating 7a32965
+static int __devinit pci_probe(struct pci_dev *dev,
Jesse Keating 7a32965
+			       const struct pci_device_id *ent)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_ohci *ohci;
Jesse Keating 7a32965
 	u32 bus_options, max_receive, link_speed, version;
Jesse Keating 7a32965
@@ -2440,6 +2431,7 @@ pci_probe(struct pci_dev *dev, const str
Jesse Keating 7a32965
 	ohci->it_context_list = kzalloc(size, GFP_KERNEL);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, ~0);
Jesse Keating 7a32965
+	ohci->ir_context_channels = ~0ULL;
Jesse Keating 7a32965
 	ohci->ir_context_mask = reg_read(ohci, OHCI1394_IsoXmitIntMaskSet);
Jesse Keating 7a32965
 	reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, ~0);
Jesse Keating 7a32965
 	size = sizeof(struct iso_context) * hweight32(ohci->ir_context_mask);
Jesse Keating 7a32965
diff -Naurp linux-2.6-git/drivers/firewire/fw-sbp2.c firewire-git/drivers/firewire/fw-sbp2.c
Jesse Keating 7a32965
--- linux-2.6-git/drivers/firewire/fw-sbp2.c	2009-01-30 13:39:02.991771976 -0500
Jesse Keating 7a32965
+++ firewire-git/drivers/firewire/fw-sbp2.c	2009-01-30 13:35:51.861646907 -0500
Jesse Keating 7a32965
@@ -392,20 +392,18 @@ static const struct {
Jesse Keating 7a32965
 	}
Jesse Keating 7a32965
 };
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static void
Jesse Keating 7a32965
-free_orb(struct kref *kref)
Jesse Keating 7a32965
+static void free_orb(struct kref *kref)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct sbp2_orb *orb = container_of(kref, struct sbp2_orb, kref);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	kfree(orb);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static void
Jesse Keating 7a32965
-sbp2_status_write(struct fw_card *card, struct fw_request *request,
Jesse Keating 7a32965
-		  int tcode, int destination, int source,
Jesse Keating 7a32965
-		  int generation, int speed,
Jesse Keating 7a32965
-		  unsigned long long offset,
Jesse Keating 7a32965
-		  void *payload, size_t length, void *callback_data)
Jesse Keating 7a32965
+static void sbp2_status_write(struct fw_card *card, struct fw_request *request,
Jesse Keating 7a32965
+			      int tcode, int destination, int source,
Jesse Keating 7a32965
+			      int generation, int speed,
Jesse Keating 7a32965
+			      unsigned long long offset,
Jesse Keating 7a32965
+			      void *payload, size_t length, void *callback_data)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct sbp2_logical_unit *lu = callback_data;
Jesse Keating 7a32965
 	struct sbp2_orb *orb;
Jesse Keating 7a32965
@@ -451,9 +449,8 @@ sbp2_status_write(struct fw_card *card, 
Jesse Keating 7a32965
 	fw_send_response(card, request, RCODE_COMPLETE);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static void
Jesse Keating 7a32965
-complete_transaction(struct fw_card *card, int rcode,
Jesse Keating 7a32965
-		     void *payload, size_t length, void *data)
Jesse Keating 7a32965
+static void complete_transaction(struct fw_card *card, int rcode,
Jesse Keating 7a32965
+				 void *payload, size_t length, void *data)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct sbp2_orb *orb = data;
Jesse Keating 7a32965
 	unsigned long flags;
Jesse Keating 7a32965
@@ -482,9 +479,8 @@ complete_transaction(struct fw_card *car
Jesse Keating 7a32965
 	kref_put(&orb->kref, free_orb);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static void
Jesse Keating 7a32965
-sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu,
Jesse Keating 7a32965
-	      int node_id, int generation, u64 offset)
Jesse Keating 7a32965
+static void sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu,
Jesse Keating 7a32965
+			  int node_id, int generation, u64 offset)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
Jesse Keating 7a32965
 	unsigned long flags;
Jesse Keating 7a32965
@@ -531,8 +527,8 @@ static int sbp2_cancel_orbs(struct sbp2_
Jesse Keating 7a32965
 	return retval;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static void
Jesse Keating 7a32965
-complete_management_orb(struct sbp2_orb *base_orb, struct sbp2_status *status)
Jesse Keating 7a32965
+static void complete_management_orb(struct sbp2_orb *base_orb,
Jesse Keating 7a32965
+				    struct sbp2_status *status)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct sbp2_management_orb *orb =
Jesse Keating 7a32965
 		container_of(base_orb, struct sbp2_management_orb, base);
Jesse Keating 7a32965
@@ -542,10 +538,9 @@ complete_management_orb(struct sbp2_orb 
Jesse Keating 7a32965
 	complete(&orb->done);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static int
Jesse Keating 7a32965
-sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id,
Jesse Keating 7a32965
-			 int generation, int function, int lun_or_login_id,
Jesse Keating 7a32965
-			 void *response)
Jesse Keating 7a32965
+static int sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id,
Jesse Keating 7a32965
+				    int generation, int function,
Jesse Keating 7a32965
+				    int lun_or_login_id, void *response)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
Jesse Keating 7a32965
 	struct sbp2_management_orb *orb;
Jesse Keating 7a32965
@@ -652,9 +647,8 @@ static void sbp2_agent_reset(struct sbp2
Jesse Keating 7a32965
 			   &d, sizeof(d));
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static void
Jesse Keating 7a32965
-complete_agent_reset_write_no_wait(struct fw_card *card, int rcode,
Jesse Keating 7a32965
-				   void *payload, size_t length, void *data)
Jesse Keating 7a32965
+static void complete_agent_reset_write_no_wait(struct fw_card *card,
Jesse Keating 7a32965
+		int rcode, void *payload, size_t length, void *data)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	kfree(data);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
@@ -1299,8 +1293,7 @@ static void sbp2_unmap_scatterlist(struc
Jesse Keating 7a32965
 				 sizeof(orb->page_table), DMA_TO_DEVICE);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static unsigned int
Jesse Keating 7a32965
-sbp2_status_to_sense_data(u8 *sbp2_status, u8 *sense_data)
Jesse Keating 7a32965
+static unsigned int sbp2_status_to_sense_data(u8 *sbp2_status, u8 *sense_data)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	int sam_status;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
@@ -1337,8 +1330,8 @@ sbp2_status_to_sense_data(u8 *sbp2_statu
Jesse Keating 7a32965
 	}
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static void
Jesse Keating 7a32965
-complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status)
Jesse Keating 7a32965
+static void complete_command_orb(struct sbp2_orb *base_orb,
Jesse Keating 7a32965
+				 struct sbp2_status *status)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct sbp2_command_orb *orb =
Jesse Keating 7a32965
 		container_of(base_orb, struct sbp2_command_orb, base);
Jesse Keating 7a32965
@@ -1384,9 +1377,8 @@ complete_command_orb(struct sbp2_orb *ba
Jesse Keating 7a32965
 	orb->done(orb->cmd);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static int
Jesse Keating 7a32965
-sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device,
Jesse Keating 7a32965
-		     struct sbp2_logical_unit *lu)
Jesse Keating 7a32965
+static int sbp2_map_scatterlist(struct sbp2_command_orb *orb,
Jesse Keating 7a32965
+		struct fw_device *device, struct sbp2_logical_unit *lu)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct scatterlist *sg = scsi_sglist(orb->cmd);
Jesse Keating 7a32965
 	int i, n;
Jesse Keating 7a32965
@@ -1584,9 +1576,8 @@ static int sbp2_scsi_abort(struct scsi_c
Jesse Keating 7a32965
  * This is the concatenation of target port identifier and logical unit
Jesse Keating 7a32965
  * identifier as per SAM-2...SAM-4 annex A.
Jesse Keating 7a32965
  */
Jesse Keating 7a32965
-static ssize_t
Jesse Keating 7a32965
-sbp2_sysfs_ieee1394_id_show(struct device *dev, struct device_attribute *attr,
Jesse Keating 7a32965
-			    char *buf)
Jesse Keating 7a32965
+static ssize_t sbp2_sysfs_ieee1394_id_show(struct device *dev,
Jesse Keating 7a32965
+			struct device_attribute *attr, char *buf)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct scsi_device *sdev = to_scsi_device(dev);
Jesse Keating 7a32965
 	struct sbp2_logical_unit *lu;
Jesse Keating 7a32965
diff -Naurp linux-2.6-git/drivers/firewire/fw-topology.c firewire-git/drivers/firewire/fw-topology.c
Jesse Keating 7a32965
--- linux-2.6-git/drivers/firewire/fw-topology.c	2009-01-30 13:39:02.991771976 -0500
Jesse Keating 7a32965
+++ firewire-git/drivers/firewire/fw-topology.c	2009-01-30 13:35:51.862647087 -0500
Jesse Keating 7a32965
@@ -314,9 +314,8 @@ typedef void (*fw_node_callback_t)(struc
Jesse Keating 7a32965
 				   struct fw_node * node,
Jesse Keating 7a32965
 				   struct fw_node * parent);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static void
Jesse Keating 7a32965
-for_each_fw_node(struct fw_card *card, struct fw_node *root,
Jesse Keating 7a32965
-		 fw_node_callback_t callback)
Jesse Keating 7a32965
+static void for_each_fw_node(struct fw_card *card, struct fw_node *root,
Jesse Keating 7a32965
+			     fw_node_callback_t callback)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct list_head list;
Jesse Keating 7a32965
 	struct fw_node *node, *next, *child, *parent;
Jesse Keating 7a32965
@@ -349,9 +348,8 @@ for_each_fw_node(struct fw_card *card, s
Jesse Keating 7a32965
 		fw_node_put(node);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static void
Jesse Keating 7a32965
-report_lost_node(struct fw_card *card,
Jesse Keating 7a32965
-		 struct fw_node *node, struct fw_node *parent)
Jesse Keating 7a32965
+static void report_lost_node(struct fw_card *card,
Jesse Keating 7a32965
+			     struct fw_node *node, struct fw_node *parent)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	fw_node_event(card, node, FW_NODE_DESTROYED);
Jesse Keating 7a32965
 	fw_node_put(node);
Jesse Keating 7a32965
@@ -360,9 +358,8 @@ report_lost_node(struct fw_card *card,
Jesse Keating 7a32965
 	card->bm_retries = 0;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static void
Jesse Keating 7a32965
-report_found_node(struct fw_card *card,
Jesse Keating 7a32965
-		  struct fw_node *node, struct fw_node *parent)
Jesse Keating 7a32965
+static void report_found_node(struct fw_card *card,
Jesse Keating 7a32965
+			      struct fw_node *node, struct fw_node *parent)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	int b_path = (node->phy_speed == SCODE_BETA);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
@@ -415,8 +412,7 @@ static void move_tree(struct fw_node *no
Jesse Keating 7a32965
  * found, lost or updated.  Update the nodes in the card topology tree
Jesse Keating 7a32965
  * as we go.
Jesse Keating 7a32965
  */
Jesse Keating 7a32965
-static void
Jesse Keating 7a32965
-update_tree(struct fw_card *card, struct fw_node *root)
Jesse Keating 7a32965
+static void update_tree(struct fw_card *card, struct fw_node *root)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct list_head list0, list1;
Jesse Keating 7a32965
 	struct fw_node *node0, *node1, *next1;
Jesse Keating 7a32965
@@ -497,8 +493,8 @@ update_tree(struct fw_card *card, struct
Jesse Keating 7a32965
 	}
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static void
Jesse Keating 7a32965
-update_topology_map(struct fw_card *card, u32 *self_ids, int self_id_count)
Jesse Keating 7a32965
+static void update_topology_map(struct fw_card *card,
Jesse Keating 7a32965
+				u32 *self_ids, int self_id_count)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	int node_count;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
@@ -510,10 +506,8 @@ update_topology_map(struct fw_card *card
Jesse Keating 7a32965
 	fw_compute_block_crc(card->topology_map);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-void
Jesse Keating 7a32965
-fw_core_handle_bus_reset(struct fw_card *card,
Jesse Keating 7a32965
-			 int node_id, int generation,
Jesse Keating 7a32965
-			 int self_id_count, u32 * self_ids)
Jesse Keating 7a32965
+void fw_core_handle_bus_reset(struct fw_card *card, int node_id, int generation,
Jesse Keating 7a32965
+			      int self_id_count, u32 *self_ids)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_node *local_node;
Jesse Keating 7a32965
 	unsigned long flags;
Jesse Keating 7a32965
diff -Naurp linux-2.6-git/drivers/firewire/fw-topology.h firewire-git/drivers/firewire/fw-topology.h
Jesse Keating 7a32965
--- linux-2.6-git/drivers/firewire/fw-topology.h	2008-11-04 11:18:33.000000000 -0500
Jesse Keating 7a32965
+++ firewire-git/drivers/firewire/fw-topology.h	2009-01-30 13:35:51.862647087 -0500
Jesse Keating 7a32965
@@ -19,6 +19,11 @@
Jesse Keating 7a32965
 #ifndef __fw_topology_h
Jesse Keating 7a32965
 #define __fw_topology_h
Jesse Keating 7a32965
 
Jesse Keating 7a32965
+#include <linux/list.h>
Jesse Keating 7a32965
+#include <linux/slab.h>
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+#include <asm/atomic.h>
Jesse Keating 7a32965
+
Jesse Keating 7a32965
 enum {
Jesse Keating 7a32965
 	FW_NODE_CREATED,
Jesse Keating 7a32965
 	FW_NODE_UPDATED,
Jesse Keating 7a32965
@@ -51,26 +56,22 @@ struct fw_node {
Jesse Keating 7a32965
 	struct fw_node *ports[0];
Jesse Keating 7a32965
 };
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static inline struct fw_node *
Jesse Keating 7a32965
-fw_node_get(struct fw_node *node)
Jesse Keating 7a32965
+static inline struct fw_node *fw_node_get(struct fw_node *node)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	atomic_inc(&node->ref_count);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	return node;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static inline void
Jesse Keating 7a32965
-fw_node_put(struct fw_node *node)
Jesse Keating 7a32965
+static inline void fw_node_put(struct fw_node *node)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	if (atomic_dec_and_test(&node->ref_count))
Jesse Keating 7a32965
 		kfree(node);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-void
Jesse Keating 7a32965
-fw_destroy_nodes(struct fw_card *card);
Jesse Keating 7a32965
-
Jesse Keating 7a32965
-int
Jesse Keating 7a32965
-fw_compute_block_crc(u32 *block);
Jesse Keating 7a32965
+struct fw_card;
Jesse Keating 7a32965
+void fw_destroy_nodes(struct fw_card *card);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
+int fw_compute_block_crc(u32 *block);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 #endif /* __fw_topology_h */
Jesse Keating 7a32965
diff -Naurp linux-2.6-git/drivers/firewire/fw-transaction.c firewire-git/drivers/firewire/fw-transaction.c
Jesse Keating 7a32965
--- linux-2.6-git/drivers/firewire/fw-transaction.c	2009-01-30 13:39:02.991771976 -0500
Jesse Keating 7a32965
+++ firewire-git/drivers/firewire/fw-transaction.c	2009-01-30 13:35:51.862647087 -0500
Jesse Keating 7a32965
@@ -64,10 +64,9 @@
Jesse Keating 7a32965
 #define PHY_CONFIG_ROOT_ID(node_id)	((((node_id) & 0x3f) << 24) | (1 << 23))
Jesse Keating 7a32965
 #define PHY_IDENTIFIER(id)		((id) << 30)
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static int
Jesse Keating 7a32965
-close_transaction(struct fw_transaction *transaction,
Jesse Keating 7a32965
-		  struct fw_card *card, int rcode,
Jesse Keating 7a32965
-		  u32 *payload, size_t length)
Jesse Keating 7a32965
+static int close_transaction(struct fw_transaction *transaction,
Jesse Keating 7a32965
+			     struct fw_card *card, int rcode,
Jesse Keating 7a32965
+			     u32 *payload, size_t length)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_transaction *t;
Jesse Keating 7a32965
 	unsigned long flags;
Jesse Keating 7a32965
@@ -94,9 +93,8 @@ close_transaction(struct fw_transaction 
Jesse Keating 7a32965
  * Only valid for transactions that are potentially pending (ie have
Jesse Keating 7a32965
  * been sent).
Jesse Keating 7a32965
  */
Jesse Keating 7a32965
-int
Jesse Keating 7a32965
-fw_cancel_transaction(struct fw_card *card,
Jesse Keating 7a32965
-		      struct fw_transaction *transaction)
Jesse Keating 7a32965
+int fw_cancel_transaction(struct fw_card *card,
Jesse Keating 7a32965
+			  struct fw_transaction *transaction)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	/*
Jesse Keating 7a32965
 	 * Cancel the packet transmission if it's still queued.  That
Jesse Keating 7a32965
@@ -116,9 +114,8 @@ fw_cancel_transaction(struct fw_card *ca
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 EXPORT_SYMBOL(fw_cancel_transaction);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static void
Jesse Keating 7a32965
-transmit_complete_callback(struct fw_packet *packet,
Jesse Keating 7a32965
-			   struct fw_card *card, int status)
Jesse Keating 7a32965
+static void transmit_complete_callback(struct fw_packet *packet,
Jesse Keating 7a32965
+				       struct fw_card *card, int status)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_transaction *t =
Jesse Keating 7a32965
 	    container_of(packet, struct fw_transaction, packet);
Jesse Keating 7a32965
@@ -151,8 +148,7 @@ transmit_complete_callback(struct fw_pac
Jesse Keating 7a32965
 	}
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static void
Jesse Keating 7a32965
-fw_fill_request(struct fw_packet *packet, int tcode, int tlabel,
Jesse Keating 7a32965
+static void fw_fill_request(struct fw_packet *packet, int tcode, int tlabel,
Jesse Keating 7a32965
 		int destination_id, int source_id, int generation, int speed,
Jesse Keating 7a32965
 		unsigned long long offset, void *payload, size_t length)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
@@ -247,12 +243,10 @@ fw_fill_request(struct fw_packet *packet
Jesse Keating 7a32965
  * @param callback_data pointer to arbitrary data, which will be
Jesse Keating 7a32965
  *   passed to the callback
Jesse Keating 7a32965
  */
Jesse Keating 7a32965
-void
Jesse Keating 7a32965
-fw_send_request(struct fw_card *card, struct fw_transaction *t,
Jesse Keating 7a32965
-		int tcode, int destination_id, int generation, int speed,
Jesse Keating 7a32965
-		unsigned long long offset,
Jesse Keating 7a32965
-		void *payload, size_t length,
Jesse Keating 7a32965
-		fw_transaction_callback_t callback, void *callback_data)
Jesse Keating 7a32965
+void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode,
Jesse Keating 7a32965
+		     int destination_id, int generation, int speed,
Jesse Keating 7a32965
+		     unsigned long long offset, void *payload, size_t length,
Jesse Keating 7a32965
+		     fw_transaction_callback_t callback, void *callback_data)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	unsigned long flags;
Jesse Keating 7a32965
 	int tlabel;
Jesse Keating 7a32965
@@ -322,8 +316,8 @@ static void transaction_callback(struct 
Jesse Keating 7a32965
  * Returns the RCODE.
Jesse Keating 7a32965
  */
Jesse Keating 7a32965
 int fw_run_transaction(struct fw_card *card, int tcode, int destination_id,
Jesse Keating 7a32965
-		int generation, int speed, unsigned long long offset,
Jesse Keating 7a32965
-		void *data, size_t length)
Jesse Keating 7a32965
+		       int generation, int speed, unsigned long long offset,
Jesse Keating 7a32965
+		       void *data, size_t length)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct transaction_callback_data d;
Jesse Keating 7a32965
 	struct fw_transaction t;
Jesse Keating 7a32965
@@ -399,9 +393,8 @@ void fw_flush_transactions(struct fw_car
Jesse Keating 7a32965
 	}
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static struct fw_address_handler *
Jesse Keating 7a32965
-lookup_overlapping_address_handler(struct list_head *list,
Jesse Keating 7a32965
-				   unsigned long long offset, size_t length)
Jesse Keating 7a32965
+static struct fw_address_handler *lookup_overlapping_address_handler(
Jesse Keating 7a32965
+	struct list_head *list, unsigned long long offset, size_t length)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_address_handler *handler;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
@@ -414,9 +407,8 @@ lookup_overlapping_address_handler(struc
Jesse Keating 7a32965
 	return NULL;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static struct fw_address_handler *
Jesse Keating 7a32965
-lookup_enclosing_address_handler(struct list_head *list,
Jesse Keating 7a32965
-				 unsigned long long offset, size_t length)
Jesse Keating 7a32965
+static struct fw_address_handler *lookup_enclosing_address_handler(
Jesse Keating 7a32965
+	struct list_head *list, unsigned long long offset, size_t length)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_address_handler *handler;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
@@ -449,36 +441,44 @@ const struct fw_address_region fw_unit_s
Jesse Keating 7a32965
 #endif  /*  0  */
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 /**
Jesse Keating 7a32965
- * Allocate a range of addresses in the node space of the OHCI
Jesse Keating 7a32965
- * controller.  When a request is received that falls within the
Jesse Keating 7a32965
- * specified address range, the specified callback is invoked.  The
Jesse Keating 7a32965
- * parameters passed to the callback give the details of the
Jesse Keating 7a32965
- * particular request.
Jesse Keating 7a32965
+ * fw_core_add_address_handler - register for incoming requests
Jesse Keating 7a32965
+ * @handler: callback
Jesse Keating 7a32965
+ * @region: region in the IEEE 1212 node space address range
Jesse Keating 7a32965
+ *
Jesse Keating 7a32965
+ * region->start, ->end, and handler->length have to be quadlet-aligned.
Jesse Keating 7a32965
+ *
Jesse Keating 7a32965
+ * When a request is received that falls within the specified address range,
Jesse Keating 7a32965
+ * the specified callback is invoked.  The parameters passed to the callback
Jesse Keating 7a32965
+ * give the details of the particular request.
Jesse Keating 7a32965
  *
Jesse Keating 7a32965
  * Return value:  0 on success, non-zero otherwise.
Jesse Keating 7a32965
  * The start offset of the handler's address region is determined by
Jesse Keating 7a32965
  * fw_core_add_address_handler() and is returned in handler->offset.
Jesse Keating 7a32965
- * The offset is quadlet-aligned.
Jesse Keating 7a32965
  */
Jesse Keating 7a32965
-int
Jesse Keating 7a32965
-fw_core_add_address_handler(struct fw_address_handler *handler,
Jesse Keating 7a32965
-			    const struct fw_address_region *region)
Jesse Keating 7a32965
+int fw_core_add_address_handler(struct fw_address_handler *handler,
Jesse Keating 7a32965
+				const struct fw_address_region *region)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_address_handler *other;
Jesse Keating 7a32965
 	unsigned long flags;
Jesse Keating 7a32965
 	int ret = -EBUSY;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
+	if (region->start & 0xffff000000000003ULL ||
Jesse Keating 7a32965
+	    region->end   & 0xffff000000000003ULL ||
Jesse Keating 7a32965
+	    region->start >= region->end ||
Jesse Keating 7a32965
+	    handler->length & 3 ||
Jesse Keating 7a32965
+	    handler->length == 0)
Jesse Keating 7a32965
+		return -EINVAL;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
 	spin_lock_irqsave(&address_handler_lock, flags);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	handler->offset = roundup(region->start, 4);
Jesse Keating 7a32965
+	handler->offset = region->start;
Jesse Keating 7a32965
 	while (handler->offset + handler->length <= region->end) {
Jesse Keating 7a32965
 		other =
Jesse Keating 7a32965
 		    lookup_overlapping_address_handler(&address_handler_list,
Jesse Keating 7a32965
 						       handler->offset,
Jesse Keating 7a32965
 						       handler->length);
Jesse Keating 7a32965
 		if (other != NULL) {
Jesse Keating 7a32965
-			handler->offset =
Jesse Keating 7a32965
-			    roundup(other->offset + other->length, 4);
Jesse Keating 7a32965
+			handler->offset += other->length;
Jesse Keating 7a32965
 		} else {
Jesse Keating 7a32965
 			list_add_tail(&handler->link, &address_handler_list);
Jesse Keating 7a32965
 			ret = 0;
Jesse Keating 7a32965
@@ -493,12 +493,7 @@ fw_core_add_address_handler(struct fw_ad
Jesse Keating 7a32965
 EXPORT_SYMBOL(fw_core_add_address_handler);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 /**
Jesse Keating 7a32965
- * Deallocate a range of addresses allocated with fw_allocate.  This
Jesse Keating 7a32965
- * will call the associated callback one last time with a the special
Jesse Keating 7a32965
- * tcode TCODE_DEALLOCATE, to let the client destroy the registered
Jesse Keating 7a32965
- * callback data.  For convenience, the callback parameters offset and
Jesse Keating 7a32965
- * length are set to the start and the length respectively for the
Jesse Keating 7a32965
- * deallocated region, payload is set to NULL.
Jesse Keating 7a32965
+ * fw_core_remove_address_handler - unregister an address handler
Jesse Keating 7a32965
  */
Jesse Keating 7a32965
 void fw_core_remove_address_handler(struct fw_address_handler *handler)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
@@ -518,9 +513,8 @@ struct fw_request {
Jesse Keating 7a32965
 	u32 data[0];
Jesse Keating 7a32965
 };
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static void
Jesse Keating 7a32965
-free_response_callback(struct fw_packet *packet,
Jesse Keating 7a32965
-		       struct fw_card *card, int status)
Jesse Keating 7a32965
+static void free_response_callback(struct fw_packet *packet,
Jesse Keating 7a32965
+				   struct fw_card *card, int status)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_request *request;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
@@ -528,9 +522,8 @@ free_response_callback(struct fw_packet 
Jesse Keating 7a32965
 	kfree(request);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-void
Jesse Keating 7a32965
-fw_fill_response(struct fw_packet *response, u32 *request_header,
Jesse Keating 7a32965
-		 int rcode, void *payload, size_t length)
Jesse Keating 7a32965
+void fw_fill_response(struct fw_packet *response, u32 *request_header,
Jesse Keating 7a32965
+		      int rcode, void *payload, size_t length)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	int tcode, tlabel, extended_tcode, source, destination;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
@@ -588,8 +581,7 @@ fw_fill_response(struct fw_packet *respo
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 EXPORT_SYMBOL(fw_fill_response);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static struct fw_request *
Jesse Keating 7a32965
-allocate_request(struct fw_packet *p)
Jesse Keating 7a32965
+static struct fw_request *allocate_request(struct fw_packet *p)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_request *request;
Jesse Keating 7a32965
 	u32 *data, length;
Jesse Keating 7a32965
@@ -649,8 +641,8 @@ allocate_request(struct fw_packet *p)
Jesse Keating 7a32965
 	return request;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-void
Jesse Keating 7a32965
-fw_send_response(struct fw_card *card, struct fw_request *request, int rcode)
Jesse Keating 7a32965
+void fw_send_response(struct fw_card *card,
Jesse Keating 7a32965
+		      struct fw_request *request, int rcode)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	/* unified transaction or broadcast transaction: don't respond */
Jesse Keating 7a32965
 	if (request->ack != ACK_PENDING ||
Jesse Keating 7a32965
@@ -670,8 +662,7 @@ fw_send_response(struct fw_card *card, s
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 EXPORT_SYMBOL(fw_send_response);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-void
Jesse Keating 7a32965
-fw_core_handle_request(struct fw_card *card, struct fw_packet *p)
Jesse Keating 7a32965
+void fw_core_handle_request(struct fw_card *card, struct fw_packet *p)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_address_handler *handler;
Jesse Keating 7a32965
 	struct fw_request *request;
Jesse Keating 7a32965
@@ -719,8 +710,7 @@ fw_core_handle_request(struct fw_card *c
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 EXPORT_SYMBOL(fw_core_handle_request);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-void
Jesse Keating 7a32965
-fw_core_handle_response(struct fw_card *card, struct fw_packet *p)
Jesse Keating 7a32965
+void fw_core_handle_response(struct fw_card *card, struct fw_packet *p)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	struct fw_transaction *t;
Jesse Keating 7a32965
 	unsigned long flags;
Jesse Keating 7a32965
@@ -793,12 +783,10 @@ static const struct fw_address_region to
Jesse Keating 7a32965
 	{ .start = CSR_REGISTER_BASE | CSR_TOPOLOGY_MAP,
Jesse Keating 7a32965
 	  .end   = CSR_REGISTER_BASE | CSR_TOPOLOGY_MAP_END, };
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static void
Jesse Keating 7a32965
-handle_topology_map(struct fw_card *card, struct fw_request *request,
Jesse Keating 7a32965
-		    int tcode, int destination, int source,
Jesse Keating 7a32965
-		    int generation, int speed,
Jesse Keating 7a32965
-		    unsigned long long offset,
Jesse Keating 7a32965
-		    void *payload, size_t length, void *callback_data)
Jesse Keating 7a32965
+static void handle_topology_map(struct fw_card *card, struct fw_request *request,
Jesse Keating 7a32965
+		int tcode, int destination, int source, int generation,
Jesse Keating 7a32965
+		int speed, unsigned long long offset,
Jesse Keating 7a32965
+		void *payload, size_t length, void *callback_data)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	int i, start, end;
Jesse Keating 7a32965
 	__be32 *map;
Jesse Keating 7a32965
@@ -832,12 +820,10 @@ static const struct fw_address_region re
Jesse Keating 7a32965
 	{ .start = CSR_REGISTER_BASE,
Jesse Keating 7a32965
 	  .end   = CSR_REGISTER_BASE | CSR_CONFIG_ROM, };
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static void
Jesse Keating 7a32965
-handle_registers(struct fw_card *card, struct fw_request *request,
Jesse Keating 7a32965
-		 int tcode, int destination, int source,
Jesse Keating 7a32965
-		 int generation, int speed,
Jesse Keating 7a32965
-		 unsigned long long offset,
Jesse Keating 7a32965
-		 void *payload, size_t length, void *callback_data)
Jesse Keating 7a32965
+static void handle_registers(struct fw_card *card, struct fw_request *request,
Jesse Keating 7a32965
+		int tcode, int destination, int source, int generation,
Jesse Keating 7a32965
+		int speed, unsigned long long offset,
Jesse Keating 7a32965
+		void *payload, size_t length, void *callback_data)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	int reg = offset & ~CSR_REGISTER_BASE;
Jesse Keating 7a32965
 	unsigned long long bus_time;
Jesse Keating 7a32965
@@ -939,11 +925,11 @@ static struct fw_descriptor model_id_des
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 static int __init fw_core_init(void)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
-	int retval;
Jesse Keating 7a32965
+	int ret;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	retval = bus_register(&fw_bus_type);
Jesse Keating 7a32965
-	if (retval < 0)
Jesse Keating 7a32965
-		return retval;
Jesse Keating 7a32965
+	ret = bus_register(&fw_bus_type);
Jesse Keating 7a32965
+	if (ret < 0)
Jesse Keating 7a32965
+		return ret;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	fw_cdev_major = register_chrdev(0, "firewire", &fw_device_ops);
Jesse Keating 7a32965
 	if (fw_cdev_major < 0) {
Jesse Keating 7a32965
@@ -951,19 +937,10 @@ static int __init fw_core_init(void)
Jesse Keating 7a32965
 		return fw_cdev_major;
Jesse Keating 7a32965
 	}
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-	retval = fw_core_add_address_handler(&topology_map,
Jesse Keating 7a32965
-					     &topology_map_region);
Jesse Keating 7a32965
-	BUG_ON(retval < 0);
Jesse Keating 7a32965
-
Jesse Keating 7a32965
-	retval = fw_core_add_address_handler(&registers,
Jesse Keating 7a32965
-					     &registers_region);
Jesse Keating 7a32965
-	BUG_ON(retval < 0);
Jesse Keating 7a32965
-
Jesse Keating 7a32965
-	/* Add the vendor textual descriptor. */
Jesse Keating 7a32965
-	retval = fw_core_add_descriptor(&vendor_id_descriptor);
Jesse Keating 7a32965
-	BUG_ON(retval < 0);
Jesse Keating 7a32965
-	retval = fw_core_add_descriptor(&model_id_descriptor);
Jesse Keating 7a32965
-	BUG_ON(retval < 0);
Jesse Keating 7a32965
+	fw_core_add_address_handler(&topology_map, &topology_map_region);
Jesse Keating 7a32965
+	fw_core_add_address_handler(&registers, &registers_region);
Jesse Keating 7a32965
+	fw_core_add_descriptor(&vendor_id_descriptor);
Jesse Keating 7a32965
+	fw_core_add_descriptor(&model_id_descriptor);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	return 0;
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
diff -Naurp linux-2.6-git/drivers/firewire/fw-transaction.h firewire-git/drivers/firewire/fw-transaction.h
Jesse Keating 7a32965
--- linux-2.6-git/drivers/firewire/fw-transaction.h	2009-01-30 13:39:02.992772636 -0500
Jesse Keating 7a32965
+++ firewire-git/drivers/firewire/fw-transaction.h	2009-01-30 13:35:51.862647087 -0500
Jesse Keating 7a32965
@@ -82,14 +82,14 @@
Jesse Keating 7a32965
 #define CSR_SPEED_MAP			0x2000
Jesse Keating 7a32965
 #define CSR_SPEED_MAP_END		0x3000
Jesse Keating 7a32965
 
Jesse Keating 7a32965
+#define BANDWIDTH_AVAILABLE_INITIAL	4915
Jesse Keating 7a32965
 #define BROADCAST_CHANNEL_INITIAL	(1 << 31 | 31)
Jesse Keating 7a32965
 #define BROADCAST_CHANNEL_VALID		(1 << 30)
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 #define fw_notify(s, args...) printk(KERN_NOTICE KBUILD_MODNAME ": " s, ## args)
Jesse Keating 7a32965
 #define fw_error(s, args...) printk(KERN_ERR KBUILD_MODNAME ": " s, ## args)
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static inline void
Jesse Keating 7a32965
-fw_memcpy_from_be32(void *_dst, void *_src, size_t size)
Jesse Keating 7a32965
+static inline void fw_memcpy_from_be32(void *_dst, void *_src, size_t size)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	u32    *dst = _dst;
Jesse Keating 7a32965
 	__be32 *src = _src;
Jesse Keating 7a32965
@@ -99,8 +99,7 @@ fw_memcpy_from_be32(void *_dst, void *_s
Jesse Keating 7a32965
 		dst[i] = be32_to_cpu(src[i]);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static inline void
Jesse Keating 7a32965
-fw_memcpy_to_be32(void *_dst, void *_src, size_t size)
Jesse Keating 7a32965
+static inline void fw_memcpy_to_be32(void *_dst, void *_src, size_t size)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965
 	fw_memcpy_from_be32(_dst, _src, size);
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
@@ -125,8 +124,7 @@ typedef void (*fw_packet_callback_t)(str
Jesse Keating 7a32965
 				     struct fw_card *card, int status);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 typedef void (*fw_transaction_callback_t)(struct fw_card *card, int rcode,
Jesse Keating 7a32965
-					  void *data,
Jesse Keating 7a32965
-					  size_t length,
Jesse Keating 7a32965
+					  void *data, size_t length,
Jesse Keating 7a32965
 					  void *callback_data);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 /*
Jesse Keating 7a32965
@@ -141,12 +139,6 @@ typedef void (*fw_address_callback_t)(st
Jesse Keating 7a32965
 				      void *data, size_t length,
Jesse Keating 7a32965
 				      void *callback_data);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-typedef void (*fw_bus_reset_callback_t)(struct fw_card *handle,
Jesse Keating 7a32965
-					int node_id, int generation,
Jesse Keating 7a32965
-					u32 *self_ids,
Jesse Keating 7a32965
-					int self_id_count,
Jesse Keating 7a32965
-					void *callback_data);
Jesse Keating 7a32965
-
Jesse Keating 7a32965
 struct fw_packet {
Jesse Keating 7a32965
 	int speed;
Jesse Keating 7a32965
 	int generation;
Jesse Keating 7a32965
@@ -187,12 +179,6 @@ struct fw_transaction {
Jesse Keating 7a32965
 	void *callback_data;
Jesse Keating 7a32965
 };
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-static inline struct fw_packet *
Jesse Keating 7a32965
-fw_packet(struct list_head *l)
Jesse Keating 7a32965
-{
Jesse Keating 7a32965
-	return list_entry(l, struct fw_packet, link);
Jesse Keating 7a32965
-}
Jesse Keating 7a32965
-
Jesse Keating 7a32965
 struct fw_address_handler {
Jesse Keating 7a32965
 	u64 offset;
Jesse Keating 7a32965
 	size_t length;
Jesse Keating 7a32965
@@ -201,7 +187,6 @@ struct fw_address_handler {
Jesse Keating 7a32965
 	struct list_head link;
Jesse Keating 7a32965
 };
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-
Jesse Keating 7a32965
 struct fw_address_region {
Jesse Keating 7a32965
 	u64 start;
Jesse Keating 7a32965
 	u64 end;
Jesse Keating 7a32965
@@ -315,10 +300,8 @@ struct fw_iso_packet {
Jesse Keating 7a32965
 struct fw_iso_context;
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 typedef void (*fw_iso_callback_t)(struct fw_iso_context *context,
Jesse Keating 7a32965
-				  u32 cycle,
Jesse Keating 7a32965
-				  size_t header_length,
Jesse Keating 7a32965
-				  void *header,
Jesse Keating 7a32965
-				  void *data);
Jesse Keating 7a32965
+				  u32 cycle, size_t header_length,
Jesse Keating 7a32965
+				  void *header, void *data);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 /*
Jesse Keating 7a32965
  * An iso buffer is just a set of pages mapped for DMA in the
Jesse Keating 7a32965
@@ -344,36 +327,25 @@ struct fw_iso_context {
Jesse Keating 7a32965
 	void *callback_data;
Jesse Keating 7a32965
 };
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-int
Jesse Keating 7a32965
-fw_iso_buffer_init(struct fw_iso_buffer *buffer,
Jesse Keating 7a32965
-		   struct fw_card *card,
Jesse Keating 7a32965
-		   int page_count,
Jesse Keating 7a32965
-		   enum dma_data_direction direction);
Jesse Keating 7a32965
-int
Jesse Keating 7a32965
-fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma);
Jesse Keating 7a32965
-void
Jesse Keating 7a32965
-fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, struct fw_card *card);
Jesse Keating 7a32965
-
Jesse Keating 7a32965
-struct fw_iso_context *
Jesse Keating 7a32965
-fw_iso_context_create(struct fw_card *card, int type,
Jesse Keating 7a32965
-		      int channel, int speed, size_t header_size,
Jesse Keating 7a32965
-		      fw_iso_callback_t callback, void *callback_data);
Jesse Keating 7a32965
-
Jesse Keating 7a32965
-void
Jesse Keating 7a32965
-fw_iso_context_destroy(struct fw_iso_context *ctx);
Jesse Keating 7a32965
-
Jesse Keating 7a32965
-int
Jesse Keating 7a32965
-fw_iso_context_queue(struct fw_iso_context *ctx,
Jesse Keating 7a32965
-		     struct fw_iso_packet *packet,
Jesse Keating 7a32965
-		     struct fw_iso_buffer *buffer,
Jesse Keating 7a32965
-		     unsigned long payload);
Jesse Keating 7a32965
-
Jesse Keating 7a32965
-int
Jesse Keating 7a32965
-fw_iso_context_start(struct fw_iso_context *ctx,
Jesse Keating 7a32965
-		     int cycle, int sync, int tags);
Jesse Keating 7a32965
+int fw_iso_buffer_init(struct fw_iso_buffer *buffer, struct fw_card *card,
Jesse Keating 7a32965
+		       int page_count, enum dma_data_direction direction);
Jesse Keating 7a32965
+int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma);
Jesse Keating 7a32965
+void fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, struct fw_card *card);
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+struct fw_iso_context *fw_iso_context_create(struct fw_card *card,
Jesse Keating 7a32965
+		int type, int channel, int speed, size_t header_size,
Jesse Keating 7a32965
+		fw_iso_callback_t callback, void *callback_data);
Jesse Keating 7a32965
+int fw_iso_context_queue(struct fw_iso_context *ctx,
Jesse Keating 7a32965
+			 struct fw_iso_packet *packet,
Jesse Keating 7a32965
+			 struct fw_iso_buffer *buffer,
Jesse Keating 7a32965
+			 unsigned long payload);
Jesse Keating 7a32965
+int fw_iso_context_start(struct fw_iso_context *ctx,
Jesse Keating 7a32965
+			 int cycle, int sync, int tags);
Jesse Keating 7a32965
+int fw_iso_context_stop(struct fw_iso_context *ctx);
Jesse Keating 7a32965
+void fw_iso_context_destroy(struct fw_iso_context *ctx);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-int
Jesse Keating 7a32965
-fw_iso_context_stop(struct fw_iso_context *ctx);
Jesse Keating 7a32965
+void fw_iso_resource_manage(struct fw_card *card, int generation,
Jesse Keating 7a32965
+		u64 channels_mask, int *channel, int *bandwidth, bool allocate);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 struct fw_card_driver {
Jesse Keating 7a32965
 	/*
Jesse Keating 7a32965
@@ -415,7 +387,7 @@ struct fw_card_driver {
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	struct fw_iso_context *
Jesse Keating 7a32965
 	(*allocate_iso_context)(struct fw_card *card,
Jesse Keating 7a32965
-				int type, size_t header_size);
Jesse Keating 7a32965
+				int type, int channel, size_t header_size);
Jesse Keating 7a32965
 	void (*free_iso_context)(struct fw_iso_context *ctx);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 	int (*start_iso)(struct fw_iso_context *ctx,
Jesse Keating 7a32965
@@ -429,24 +401,18 @@ struct fw_card_driver {
Jesse Keating 7a32965
 	int (*stop_iso)(struct fw_iso_context *ctx);
Jesse Keating 7a32965
 };
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-int
Jesse Keating 7a32965
-fw_core_initiate_bus_reset(struct fw_card *card, int short_reset);
Jesse Keating 7a32965
+int fw_core_initiate_bus_reset(struct fw_card *card, int short_reset);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-void
Jesse Keating 7a32965
-fw_send_request(struct fw_card *card, struct fw_transaction *t,
Jesse Keating 7a32965
+void fw_send_request(struct fw_card *card, struct fw_transaction *t,
Jesse Keating 7a32965
 		int tcode, int destination_id, int generation, int speed,
Jesse Keating 7a32965
 		unsigned long long offset, void *data, size_t length,
Jesse Keating 7a32965
 		fw_transaction_callback_t callback, void *callback_data);
Jesse Keating 7a32965
-
Jesse Keating 7a32965
-int fw_run_transaction(struct fw_card *card, int tcode, int destination_id,
Jesse Keating 7a32965
-		       int generation, int speed, unsigned long long offset,
Jesse Keating 7a32965
-		       void *data, size_t length);
Jesse Keating 7a32965
-
Jesse Keating 7a32965
 int fw_cancel_transaction(struct fw_card *card,
Jesse Keating 7a32965
 			  struct fw_transaction *transaction);
Jesse Keating 7a32965
-
Jesse Keating 7a32965
 void fw_flush_transactions(struct fw_card *card);
Jesse Keating 7a32965
-
Jesse Keating 7a32965
+int fw_run_transaction(struct fw_card *card, int tcode, int destination_id,
Jesse Keating 7a32965
+		       int generation, int speed, unsigned long long offset,
Jesse Keating 7a32965
+		       void *data, size_t length);
Jesse Keating 7a32965
 void fw_send_phy_config(struct fw_card *card,
Jesse Keating 7a32965
 			int node_id, int generation, int gap_count);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
@@ -454,29 +420,18 @@ void fw_send_phy_config(struct fw_card *
Jesse Keating 7a32965
  * Called by the topology code to inform the device code of node
Jesse Keating 7a32965
  * activity; found, lost, or updated nodes.
Jesse Keating 7a32965
  */
Jesse Keating 7a32965
-void
Jesse Keating 7a32965
-fw_node_event(struct fw_card *card, struct fw_node *node, int event);
Jesse Keating 7a32965
+void fw_node_event(struct fw_card *card, struct fw_node *node, int event);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 /* API used by card level drivers */
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-void
Jesse Keating 7a32965
-fw_card_initialize(struct fw_card *card, const struct fw_card_driver *driver,
Jesse Keating 7a32965
-		   struct device *device);
Jesse Keating 7a32965
-int
Jesse Keating 7a32965
-fw_card_add(struct fw_card *card,
Jesse Keating 7a32965
-	    u32 max_receive, u32 link_speed, u64 guid);
Jesse Keating 7a32965
-
Jesse Keating 7a32965
-void
Jesse Keating 7a32965
-fw_core_remove_card(struct fw_card *card);
Jesse Keating 7a32965
-
Jesse Keating 7a32965
-void
Jesse Keating 7a32965
-fw_core_handle_bus_reset(struct fw_card *card,
Jesse Keating 7a32965
-			 int node_id, int generation,
Jesse Keating 7a32965
-			 int self_id_count, u32 *self_ids);
Jesse Keating 7a32965
-void
Jesse Keating 7a32965
-fw_core_handle_request(struct fw_card *card, struct fw_packet *request);
Jesse Keating 7a32965
-
Jesse Keating 7a32965
-void
Jesse Keating 7a32965
-fw_core_handle_response(struct fw_card *card, struct fw_packet *packet);
Jesse Keating 7a32965
+void fw_card_initialize(struct fw_card *card,
Jesse Keating 7a32965
+		const struct fw_card_driver *driver, struct device *device);
Jesse Keating 7a32965
+int fw_card_add(struct fw_card *card,
Jesse Keating 7a32965
+		u32 max_receive, u32 link_speed, u64 guid);
Jesse Keating 7a32965
+void fw_core_remove_card(struct fw_card *card);
Jesse Keating 7a32965
+void fw_core_handle_bus_reset(struct fw_card *card, int node_id,
Jesse Keating 7a32965
+		int generation, int self_id_count, u32 *self_ids);
Jesse Keating 7a32965
+void fw_core_handle_request(struct fw_card *card, struct fw_packet *request);
Jesse Keating 7a32965
+void fw_core_handle_response(struct fw_card *card, struct fw_packet *packet);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 #endif /* __fw_transaction_h */
Jesse Keating 7a32965
--- linux-2.6-git/include/linux/firewire-cdev.h	2008-11-04 11:19:21.000000000 -0500
Jesse Keating 7a32965
+++ firewire-git/include/linux/firewire-cdev.h	2009-01-30 13:35:54.327647015 -0500
Jesse Keating 7a32965
@@ -25,10 +25,12 @@
Jesse Keating 7a32965
 #include <linux/types.h>
Jesse Keating 7a32965
 #include <linux/firewire-constants.h>
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-#define FW_CDEV_EVENT_BUS_RESET		0x00
Jesse Keating 7a32965
-#define FW_CDEV_EVENT_RESPONSE		0x01
Jesse Keating 7a32965
-#define FW_CDEV_EVENT_REQUEST		0x02
Jesse Keating 7a32965
-#define FW_CDEV_EVENT_ISO_INTERRUPT	0x03
Jesse Keating 7a32965
+#define FW_CDEV_EVENT_BUS_RESET			0x00
Jesse Keating 7a32965
+#define FW_CDEV_EVENT_RESPONSE			0x01
Jesse Keating 7a32965
+#define FW_CDEV_EVENT_REQUEST			0x02
Jesse Keating 7a32965
+#define FW_CDEV_EVENT_ISO_INTERRUPT		0x03
Jesse Keating 7a32965
+#define FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED	0x04
Jesse Keating 7a32965
+#define FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED	0x05
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 /**
Jesse Keating 7a32965
  * struct fw_cdev_event_common - Common part of all fw_cdev_event_ types
Jesse Keating 7a32965
@@ -136,7 +138,24 @@ struct fw_cdev_event_request {
Jesse Keating 7a32965
  * This event is sent when the controller has completed an &fw_cdev_iso_packet
Jesse Keating 7a32965
  * with the %FW_CDEV_ISO_INTERRUPT bit set.  In the receive case, the headers
Jesse Keating 7a32965
  * stripped of all packets up until and including the interrupt packet are
Jesse Keating 7a32965
- * returned in the @header field.
Jesse Keating 7a32965
+ * returned in the @header field.  The amount of header data per packet is as
Jesse Keating 7a32965
+ * specified at iso context creation by &fw_cdev_create_iso_context.header_size.
Jesse Keating 7a32965
+ *
Jesse Keating 7a32965
+ * In version 1 of this ABI, header data consisted of the 1394 isochronous
Jesse Keating 7a32965
+ * packet header, followed by quadlets from the packet payload if
Jesse Keating 7a32965
+ * &fw_cdev_create_iso_context.header_size > 4.
Jesse Keating 7a32965
+ *
Jesse Keating 7a32965
+ * In version 2 of this ABI, header data consist of the 1394 isochronous
Jesse Keating 7a32965
+ * packet header, followed by a timestamp quadlet if
Jesse Keating 7a32965
+ * &fw_cdev_create_iso_context.header_size > 4, followed by quadlets from the
Jesse Keating 7a32965
+ * packet payload if &fw_cdev_create_iso_context.header_size > 8.
Jesse Keating 7a32965
+ *
Jesse Keating 7a32965
+ * Behaviour of ver. 1 of this ABI is no longer available since ABI ver. 2.
Jesse Keating 7a32965
+ *
Jesse Keating 7a32965
+ * Format of 1394 iso packet header: 16 bits len, 2 bits tag, 6 bits channel,
Jesse Keating 7a32965
+ * 4 bits tcode, 4 bits sy, in big endian byte order.  Format of timestamp:
Jesse Keating 7a32965
+ * 16 bits invalid, 3 bits cycleSeconds, 13 bits cycleCount, in big endian byte
Jesse Keating 7a32965
+ * order.
Jesse Keating 7a32965
  */
Jesse Keating 7a32965
 struct fw_cdev_event_iso_interrupt {
Jesse Keating 7a32965
 	__u64 closure;
Jesse Keating 7a32965
@@ -147,12 +166,44 @@ struct fw_cdev_event_iso_interrupt {
Jesse Keating 7a32965
 };
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 /**
Jesse Keating 7a32965
+ * struct fw_cdev_event_iso_resource - Iso resources were allocated or freed
Jesse Keating 7a32965
+ * @closure:	See &fw_cdev_event_common;
Jesse Keating 7a32965
+ *		set by %FW_CDEV_IOC_(DE)ALLOCATE_ISO_RESOURCE(_ONCE) ioctl
Jesse Keating 7a32965
+ * @type:	%FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED or
Jesse Keating 7a32965
+ *		%FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED
Jesse Keating 7a32965
+ * @handle:	Reference by which an allocated resource can be deallocated
Jesse Keating 7a32965
+ * @channel:	Isochronous channel which was (de)allocated, if any
Jesse Keating 7a32965
+ * @bandwidth:	Bandwidth allocation units which were (de)allocated, if any
Jesse Keating 7a32965
+ *
Jesse Keating 7a32965
+ * An %FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED event is sent after an isochronous
Jesse Keating 7a32965
+ * resource was allocated at the IRM.  The client has to check @channel and
Jesse Keating 7a32965
+ * @bandwidth for whether the allocation actually succeeded.
Jesse Keating 7a32965
+ *
Jesse Keating 7a32965
+ * An %FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED event is sent after an isochronous
Jesse Keating 7a32965
+ * resource was deallocated at the IRM.  It is also sent when automatic
Jesse Keating 7a32965
+ * reallocation after a bus reset failed.
Jesse Keating 7a32965
+ *
Jesse Keating 7a32965
+ * @channel is <0 if no channel was (de)allocated or if reallocation failed.
Jesse Keating 7a32965
+ * @bandwidth is 0 if no bandwidth was (de)allocated or if reallocation failed.
Jesse Keating 7a32965
+ */
Jesse Keating 7a32965
+struct fw_cdev_event_iso_resource {
Jesse Keating 7a32965
+	__u64 closure;
Jesse Keating 7a32965
+	__u32 type;
Jesse Keating 7a32965
+	__u32 handle;
Jesse Keating 7a32965
+	__s32 channel;
Jesse Keating 7a32965
+	__s32 bandwidth;
Jesse Keating 7a32965
+};
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+/**
Jesse Keating 7a32965
  * union fw_cdev_event - Convenience union of fw_cdev_event_ types
Jesse Keating 7a32965
  * @common:        Valid for all types
Jesse Keating 7a32965
  * @bus_reset:     Valid if @common.type == %FW_CDEV_EVENT_BUS_RESET
Jesse Keating 7a32965
  * @response:      Valid if @common.type == %FW_CDEV_EVENT_RESPONSE
Jesse Keating 7a32965
  * @request:       Valid if @common.type == %FW_CDEV_EVENT_REQUEST
Jesse Keating 7a32965
  * @iso_interrupt: Valid if @common.type == %FW_CDEV_EVENT_ISO_INTERRUPT
Jesse Keating 7a32965
+ * @iso_resource:  Valid if @common.type ==
Jesse Keating 7a32965
+ *				%FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED or
Jesse Keating 7a32965
+ *				%FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED
Jesse Keating 7a32965
  *
Jesse Keating 7a32965
  * Convenience union for userspace use.  Events could be read(2) into an
Jesse Keating 7a32965
  * appropriately aligned char buffer and then cast to this union for further
Jesse Keating 7a32965
@@ -163,13 +214,15 @@ struct fw_cdev_event_iso_interrupt {
Jesse Keating 7a32965
  * not fit will be discarded so that the next read(2) will return a new event.
Jesse Keating 7a32965
  */
Jesse Keating 7a32965
 union fw_cdev_event {
Jesse Keating 7a32965
-	struct fw_cdev_event_common common;
Jesse Keating 7a32965
-	struct fw_cdev_event_bus_reset bus_reset;
Jesse Keating 7a32965
-	struct fw_cdev_event_response response;
Jesse Keating 7a32965
-	struct fw_cdev_event_request request;
Jesse Keating 7a32965
-	struct fw_cdev_event_iso_interrupt iso_interrupt;
Jesse Keating 7a32965
+	struct fw_cdev_event_common		common;
Jesse Keating 7a32965
+	struct fw_cdev_event_bus_reset		bus_reset;
Jesse Keating 7a32965
+	struct fw_cdev_event_response		response;
Jesse Keating 7a32965
+	struct fw_cdev_event_request		request;
Jesse Keating 7a32965
+	struct fw_cdev_event_iso_interrupt	iso_interrupt;
Jesse Keating 7a32965
+	struct fw_cdev_event_iso_resource	iso_resource;
Jesse Keating 7a32965
 };
Jesse Keating 7a32965
 
Jesse Keating 7a32965
+/* available since kernel version 2.6.22 */
Jesse Keating 7a32965
 #define FW_CDEV_IOC_GET_INFO		_IOWR('#', 0x00, struct fw_cdev_get_info)
Jesse Keating 7a32965
 #define FW_CDEV_IOC_SEND_REQUEST	_IOW('#', 0x01, struct fw_cdev_send_request)
Jesse Keating 7a32965
 #define FW_CDEV_IOC_ALLOCATE		_IOWR('#', 0x02, struct fw_cdev_allocate)
Jesse Keating 7a32965
@@ -178,18 +231,29 @@ union fw_cdev_event {
Jesse Keating 7a32965
 #define FW_CDEV_IOC_INITIATE_BUS_RESET	_IOW('#', 0x05, struct fw_cdev_initiate_bus_reset)
Jesse Keating 7a32965
 #define FW_CDEV_IOC_ADD_DESCRIPTOR	_IOWR('#', 0x06, struct fw_cdev_add_descriptor)
Jesse Keating 7a32965
 #define FW_CDEV_IOC_REMOVE_DESCRIPTOR	_IOW('#', 0x07, struct fw_cdev_remove_descriptor)
Jesse Keating 7a32965
-
Jesse Keating 7a32965
 #define FW_CDEV_IOC_CREATE_ISO_CONTEXT	_IOWR('#', 0x08, struct fw_cdev_create_iso_context)
Jesse Keating 7a32965
 #define FW_CDEV_IOC_QUEUE_ISO		_IOWR('#', 0x09, struct fw_cdev_queue_iso)
Jesse Keating 7a32965
 #define FW_CDEV_IOC_START_ISO		_IOW('#', 0x0a, struct fw_cdev_start_iso)
Jesse Keating 7a32965
 #define FW_CDEV_IOC_STOP_ISO		_IOW('#', 0x0b, struct fw_cdev_stop_iso)
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+/* available since kernel version 2.6.24 */
Jesse Keating 7a32965
 #define FW_CDEV_IOC_GET_CYCLE_TIMER	_IOR('#', 0x0c, struct fw_cdev_get_cycle_timer)
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-/* FW_CDEV_VERSION History
Jesse Keating 7a32965
- *
Jesse Keating 7a32965
- * 1	Feb 18, 2007:  Initial version.
Jesse Keating 7a32965
+/* available since kernel version 2.6.30 */
Jesse Keating 7a32965
+#define FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE       _IOWR('#', 0x0d, struct fw_cdev_allocate_iso_resource)
Jesse Keating 7a32965
+#define FW_CDEV_IOC_DEALLOCATE_ISO_RESOURCE      _IOW('#', 0x0e, struct fw_cdev_deallocate)
Jesse Keating 7a32965
+#define FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE_ONCE   _IOW('#', 0x0f, struct fw_cdev_allocate_iso_resource)
Jesse Keating 7a32965
+#define FW_CDEV_IOC_DEALLOCATE_ISO_RESOURCE_ONCE _IOW('#', 0x10, struct fw_cdev_allocate_iso_resource)
Jesse Keating 7a32965
+#define FW_CDEV_IOC_GET_SPEED                    _IOR('#', 0x11, struct fw_cdev_get_speed)
Jesse Keating 7a32965
+#define FW_CDEV_IOC_SEND_BROADCAST_REQUEST       _IOW('#', 0x12, struct fw_cdev_send_request)
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+/*
Jesse Keating 7a32965
+ * FW_CDEV_VERSION History
Jesse Keating 7a32965
+ *  1  (2.6.22)  - initial version
Jesse Keating 7a32965
+ *  2  (2.6.30)  - changed &fw_cdev_event_iso_interrupt.header if
Jesse Keating 7a32965
+ *                 &fw_cdev_create_iso_context.header_size is 8 or more
Jesse Keating 7a32965
  */
Jesse Keating 7a32965
-#define FW_CDEV_VERSION		1
Jesse Keating 7a32965
+#define FW_CDEV_VERSION 2
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 /**
Jesse Keating 7a32965
  * struct fw_cdev_get_info - General purpose information ioctl
Jesse Keating 7a32965
@@ -201,7 +265,7 @@ union fw_cdev_event {
Jesse Keating 7a32965
  *		case, @rom_length is updated with the actual length of the
Jesse Keating 7a32965
  *		configuration ROM.
Jesse Keating 7a32965
  * @rom:	If non-zero, address of a buffer to be filled by a copy of the
Jesse Keating 7a32965
- *		local node's configuration ROM
Jesse Keating 7a32965
+ *		device's configuration ROM
Jesse Keating 7a32965
  * @bus_reset:	If non-zero, address of a buffer to be filled by a
Jesse Keating 7a32965
  *		&struct fw_cdev_event_bus_reset with the current state
Jesse Keating 7a32965
  *		of the bus.  This does not cause a bus reset to happen.
Jesse Keating 7a32965
@@ -229,7 +293,7 @@ struct fw_cdev_get_info {
Jesse Keating 7a32965
  * Send a request to the device.  This ioctl implements all outgoing requests.
Jesse Keating 7a32965
  * Both quadlet and block request specify the payload as a pointer to the data
Jesse Keating 7a32965
  * in the @data field.  Once the transaction completes, the kernel writes an
Jesse Keating 7a32965
- * &fw_cdev_event_request event back.  The @closure field is passed back to
Jesse Keating 7a32965
+ * &fw_cdev_event_response event back.  The @closure field is passed back to
Jesse Keating 7a32965
  * user space in the response event.
Jesse Keating 7a32965
  */
Jesse Keating 7a32965
 struct fw_cdev_send_request {
Jesse Keating 7a32965
@@ -284,9 +348,9 @@ struct fw_cdev_allocate {
Jesse Keating 7a32965
 };
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 /**
Jesse Keating 7a32965
- * struct fw_cdev_deallocate - Free an address range allocation
Jesse Keating 7a32965
- * @handle:	Handle to the address range, as returned by the kernel when the
Jesse Keating 7a32965
- *		range was allocated
Jesse Keating 7a32965
+ * struct fw_cdev_deallocate - Free a CSR address range or isochronous resource
Jesse Keating 7a32965
+ * @handle:	Handle to the address range or iso resource, as returned by the
Jesse Keating 7a32965
+ *		kernel when the range or resource was allocated
Jesse Keating 7a32965
  */
Jesse Keating 7a32965
 struct fw_cdev_deallocate {
Jesse Keating 7a32965
 	__u32 handle;
Jesse Keating 7a32965
@@ -370,6 +434,9 @@ struct fw_cdev_remove_descriptor {
Jesse Keating 7a32965
  *
Jesse Keating 7a32965
  * If a context was successfully created, the kernel writes back a handle to the
Jesse Keating 7a32965
  * context, which must be passed in for subsequent operations on that context.
Jesse Keating 7a32965
+ *
Jesse Keating 7a32965
+ * Note that the effect of a @header_size > 4 depends on
Jesse Keating 7a32965
+ * &fw_cdev_get_info.version, as documented at &fw_cdev_event_iso_interrupt.
Jesse Keating 7a32965
  */
Jesse Keating 7a32965
 struct fw_cdev_create_iso_context {
Jesse Keating 7a32965
 	__u32 type;
Jesse Keating 7a32965
@@ -473,10 +540,73 @@ struct fw_cdev_stop_iso {
Jesse Keating 7a32965
  * The %FW_CDEV_IOC_GET_CYCLE_TIMER ioctl reads the isochronous cycle timer
Jesse Keating 7a32965
  * and also the system clock.  This allows to express the receive time of an
Jesse Keating 7a32965
  * isochronous packet as a system time with microsecond accuracy.
Jesse Keating 7a32965
+ *
Jesse Keating 7a32965
+ * @cycle_timer consists of 7 bits cycleSeconds, 13 bits cycleCount, and
Jesse Keating 7a32965
+ * 12 bits cycleOffset, in host byte order.
Jesse Keating 7a32965
  */
Jesse Keating 7a32965
 struct fw_cdev_get_cycle_timer {
Jesse Keating 7a32965
 	__u64 local_time;
Jesse Keating 7a32965
 	__u32 cycle_timer;
Jesse Keating 7a32965
 };
Jesse Keating 7a32965
 
Jesse Keating 7a32965
+/**
Jesse Keating 7a32965
+ * struct fw_cdev_allocate_iso_resource - (De)allocate a channel or bandwidth
Jesse Keating 7a32965
+ * @closure:	Passed back to userspace in correponding iso resource events
Jesse Keating 7a32965
+ * @channels:	Isochronous channels of which one is to be (de)allocated
Jesse Keating 7a32965
+ * @bandwidth:	Isochronous bandwidth units to be (de)allocated
Jesse Keating 7a32965
+ * @handle:	Handle to the allocation, written by the kernel (only valid in
Jesse Keating 7a32965
+ *		case of %FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE ioctls)
Jesse Keating 7a32965
+ *
Jesse Keating 7a32965
+ * The %FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE ioctl initiates allocation of an
Jesse Keating 7a32965
+ * isochronous channel and/or of isochronous bandwidth at the isochronous
Jesse Keating 7a32965
+ * resource manager (IRM).  Only one of the channels specified in @channels is
Jesse Keating 7a32965
+ * allocated.  An %FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED is sent after
Jesse Keating 7a32965
+ * communication with the IRM, indicating success or failure in the event data.
Jesse Keating 7a32965
+ * The kernel will automatically reallocate the resources after bus resets.
Jesse Keating 7a32965
+ * Should a reallocation fail, an %FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED event
Jesse Keating 7a32965
+ * will be sent.  The kernel will also automatically deallocate the resources
Jesse Keating 7a32965
+ * when the file descriptor is closed.
Jesse Keating 7a32965
+ *
Jesse Keating 7a32965
+ * The %FW_CDEV_IOC_DEALLOCATE_ISO_RESOURCE ioctl can be used to initiate
Jesse Keating 7a32965
+ * deallocation of resources which were allocated as described above.
Jesse Keating 7a32965
+ * An %FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED event concludes this operation.
Jesse Keating 7a32965
+ *
Jesse Keating 7a32965
+ * The %FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE_ONCE ioctl is a variant of allocation
Jesse Keating 7a32965
+ * without automatic re- or deallocation.
Jesse Keating 7a32965
+ * An %FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED event concludes this operation,
Jesse Keating 7a32965
+ * indicating success or failure in its data.
Jesse Keating 7a32965
+ *
Jesse Keating 7a32965
+ * The %FW_CDEV_IOC_DEALLOCATE_ISO_RESOURCE_ONCE ioctl works like
Jesse Keating 7a32965
+ * %FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE_ONCE except that resources are freed
Jesse Keating 7a32965
+ * instead of allocated.
Jesse Keating 7a32965
+ * An %FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED event concludes this operation.
Jesse Keating 7a32965
+ *
Jesse Keating 7a32965
+ * To summarize, %FW_CDEV_IOC_DEALLOCATE_ISO_RESOURCE allocates iso resources
Jesse Keating 7a32965
+ * for the lifetime of the fd or handle.
Jesse Keating 7a32965
+ * In contrast, %FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE_ONCE allocates iso resources
Jesse Keating 7a32965
+ * for the duration of a bus generation.
Jesse Keating 7a32965
+ *
Jesse Keating 7a32965
+ * @channels is a host-endian bitfield with the least significant bit
Jesse Keating 7a32965
+ * representing channel 0 and the most significant bit representing channel 63:
Jesse Keating 7a32965
+ * 1ULL << c for each channel c that is a candidate for (de)allocation.
Jesse Keating 7a32965
+ *
Jesse Keating 7a32965
+ * @bandwidth is expressed in bandwidth allocation units, i.e. the time to send
Jesse Keating 7a32965
+ * one quadlet of data (payload or header data) at speed S1600.
Jesse Keating 7a32965
+ */
Jesse Keating 7a32965
+struct fw_cdev_allocate_iso_resource {
Jesse Keating 7a32965
+	__u64 closure;
Jesse Keating 7a32965
+	__u64 channels;
Jesse Keating 7a32965
+	__u32 bandwidth;
Jesse Keating 7a32965
+	__u32 handle;
Jesse Keating 7a32965
+};
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+/**
Jesse Keating 7a32965
+ * struct fw_cdev_get_speed - Query maximum speed to or from this device
Jesse Keating 7a32965
+ * @max_speed:	Speed code; minimum of the device's link speed, the local node's
Jesse Keating 7a32965
+ *		link speed, and all PHY port speeds between the two links
Jesse Keating 7a32965
+ */
Jesse Keating 7a32965
+struct fw_cdev_get_speed {
Jesse Keating 7a32965
+	__u32 max_speed;
Jesse Keating 7a32965
+};
Jesse Keating 7a32965
+
Jesse Keating 7a32965
 #endif /* _LINUX_FIREWIRE_CDEV_H */