rpms/kernel/devel kernel-2.6.spec, 1.3061, 1.3062 linux-2.6-firewire.patch, 1.5, 1.6

fedora-cvs-commits at redhat.com fedora-cvs-commits at redhat.com
Thu Apr 12 21:26:03 UTC 2007


Author: krh

Update of /cvs/dist/rpms/kernel/devel
In directory cvs.devel.redhat.com:/tmp/cvs-serv4114

Modified Files:
	kernel-2.6.spec linux-2.6-firewire.patch 
Log Message:
* Thu Apr 12 2007 Kristian Høgsberg <krh at redhat.com>
- Add a few more firewire bug fixes, incorporate last couple of
  changes to userspace interface.



Index: kernel-2.6.spec
===================================================================
RCS file: /cvs/dist/rpms/kernel/devel/kernel-2.6.spec,v
retrieving revision 1.3061
retrieving revision 1.3062
diff -u -r1.3061 -r1.3062
--- kernel-2.6.spec	12 Apr 2007 19:34:51 -0000	1.3061
+++ kernel-2.6.spec	12 Apr 2007 21:26:01 -0000	1.3062
@@ -572,11 +572,6 @@
 # a0ab4547b23c09541bc47a294a1397b3b0415bfe in the linux1394 git tree.
 Patch5000: linux-2.6-firewire.patch
 
-# These two are going upstream and will get folded into patch 5000,
-# this is just to get some testing ASAP.
-Patch5001: linux-2.6-firewire-context-run.patch
-Patch5002: linux-2.6-firewire-check-condition.patch
- 
 #
 # 10000 to 20000 is for stuff that has to come last due to the
 # amount of drivers they touch. But only these should go here.
@@ -1284,8 +1279,6 @@
 
 # Pull in the new firewire stack
 %patch5000 -p1
-%patch5001 -p1
-%patch5002 -p1
 
 #
 # final stuff
@@ -2263,6 +2256,10 @@
 #  - tux.
 
 %changelog
+* Thu Apr 12 2007 Kristian Høgsberg <krh at redhat.com>
+- Add a few more firewire bug fixes, incorporate last couple of
+  changes to userspace interface.
+
 * Thu Apr 12 2007 Dave Jones <davej at redhat.com>
 - 2.6.21-rc6-git5
 

linux-2.6-firewire.patch:
 Makefile                  |    1 
 firewire/Kconfig          |   60 +
 firewire/Makefile         |   10 
 firewire/fw-card.c        |  542 +++++++++++++
 firewire/fw-device-cdev.c |  974 +++++++++++++++++++++++
 firewire/fw-device-cdev.h |  260 ++++++
 firewire/fw-device.c      |  780 ++++++++++++++++++
 firewire/fw-device.h      |  149 +++
 firewire/fw-iso.c         |  163 +++
 firewire/fw-ohci.c        | 1890 ++++++++++++++++++++++++++++++++++++++++++++++
 firewire/fw-ohci.h        |  153 +++
 firewire/fw-sbp2.c        | 1165 ++++++++++++++++++++++++++++
 firewire/fw-topology.c    |  519 ++++++++++++
 firewire/fw-topology.h    |   94 ++
 firewire/fw-transaction.c |  889 +++++++++++++++++++++
 firewire/fw-transaction.h |  505 ++++++++++++
 ieee1394/Kconfig          |    2 
 17 files changed, 8156 insertions(+)

Index: linux-2.6-firewire.patch
===================================================================
RCS file: /cvs/dist/rpms/kernel/devel/linux-2.6-firewire.patch,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- linux-2.6-firewire.patch	23 Mar 2007 19:43:59 -0000	1.5
+++ linux-2.6-firewire.patch	12 Apr 2007 21:26:01 -0000	1.6
@@ -94,10 +94,10 @@
 +obj-$(CONFIG_FIREWIRE_SBP2) += fw-sbp2.o
 diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c
 new file mode 100644
-index 0000000..d929eb6
+index 0000000..3eb0655
 --- /dev/null
 +++ b/drivers/firewire/fw-card.c
-@@ -0,0 +1,536 @@
+@@ -0,0 +1,542 @@
 +/*						-*- c-basic-offset: 8 -*-
 + *
 + * fw-card.c - card level functions
@@ -260,7 +260,7 @@
 +		i += (desc->data[i] >> 16) + 1;
 +
 +	if (i != desc->length)
-+		return -1;
++		return -EINVAL;
 +
 +	down_write(&fw_bus_type.subsys.rwsem);
 +
@@ -495,9 +495,9 @@
 +	card->link_speed = link_speed;
 +	card->guid = guid;
 +
-+	/* FIXME: add #define's for phy registers. */
 +	/* Activate link_on bit and contender bit in our self ID packets.*/
-+	if (card->driver->update_phy_reg(card, 4, 0, 0x80 | 0x40) < 0)
++	if (card->driver->update_phy_reg(card, 4, 0,
++					 PHY_LINK_ACTIVE | PHY_CONTENDER) < 0)
 +		return -EIO;
 +
 +	/* The subsystem grabs a reference when the card is added and
@@ -583,7 +583,8 @@
 +void
 +fw_core_remove_card(struct fw_card *card)
 +{
-+	card->driver->update_phy_reg(card, 4, 0x80 | 0x40, 0);
++	card->driver->update_phy_reg(card, 4,
++				     PHY_LINK_ACTIVE | PHY_CONTENDER, 0);
 +	fw_core_initiate_bus_reset(card, 1);
 +
 +	down_write(&fw_bus_type.subsys.rwsem);
@@ -631,15 +632,20 @@
 +int
 +fw_core_initiate_bus_reset(struct fw_card *card, int short_reset)
 +{
-+	return card->driver->update_phy_reg(card, short_reset ? 5 : 1, 0, 0x40);
++	int reg = short_reset ? 5 : 1;
++	/* The following values happen to be the same bit. However be
++	 * explicit for clarity. */
++	int bit = short_reset ? PHY_BUS_SHORT_RESET : PHY_BUS_RESET;
++
++	return card->driver->update_phy_reg(card, reg, 0, bit);
 +}
 +EXPORT_SYMBOL(fw_core_initiate_bus_reset);
 diff --git a/drivers/firewire/fw-device-cdev.c b/drivers/firewire/fw-device-cdev.c
 new file mode 100644
-index 0000000..f9f2688
+index 0000000..fab6dfb
 --- /dev/null
 +++ b/drivers/firewire/fw-device-cdev.c
-@@ -0,0 +1,879 @@
+@@ -0,0 +1,974 @@
 +/*						-*- c-basic-offset: 8 -*-
 + *
 + * fw-device-cdev.c - Char device for device raw access
@@ -678,16 +684,16 @@
 +#include "fw-device.h"
 +#include "fw-device-cdev.h"
 +
-+/*
-+ * todo
-+ *
-+ * - bus resets sends a new packet with new generation and node id
-+ *
-+ */
-+
 +/* dequeue_event() just kfree()'s the event, so the event has to be
 + * the first field in the struct. */
 +
++struct client;
++struct client_resource {
++	struct list_head link;
++	void (*release)(struct client *client, struct client_resource *r);
++	u32 handle;
++};
++
 +struct event {
 +	struct { void *data; size_t size; } v[2];
 +	struct list_head link;
@@ -702,7 +708,7 @@
 +	struct event event;
 +	struct fw_transaction transaction;
 +	struct client *client;
-+	struct list_head link;
++	struct client_resource resource;
 +	struct fw_cdev_event_response response;
 +};
 +
@@ -715,12 +721,11 @@
 +	u32 version;
 +	struct fw_device *device;
 +	spinlock_t lock;
-+	struct list_head handler_list;
-+	struct list_head request_list;
-+	struct list_head transaction_list;
-+	u32 request_serial;
++	u32 resource_handle;
++	struct list_head resource_list;
 +	struct list_head event_list;
 +	wait_queue_head_t wait;
++	u64 bus_reset_closure;
 +
 +	struct fw_iso_context *iso_context;
 +	struct fw_iso_buffer buffer;
@@ -757,9 +762,7 @@
 +
 +	client->device = fw_device_get(device);
 +	INIT_LIST_HEAD(&client->event_list);
-+	INIT_LIST_HEAD(&client->handler_list);
-+	INIT_LIST_HEAD(&client->request_list);
-+	INIT_LIST_HEAD(&client->transaction_list);
++	INIT_LIST_HEAD(&client->resource_list);
 +	spin_lock_init(&client->lock);
 +	init_waitqueue_head(&client->wait);
 +
@@ -841,12 +844,13 @@
 +
 +static void
 +fill_bus_reset_event(struct fw_cdev_event_bus_reset *event,
-+		     struct fw_device *device)
++		     struct client *client)
 +{
-+	struct fw_card *card = device->card;
++	struct fw_card *card = client->device->card;
 +
++	event->closure	     = client->bus_reset_closure;
 +	event->type          = FW_CDEV_EVENT_BUS_RESET;
-+	event->node_id       = device->node_id;
++	event->node_id       = client->device->node_id;
 +	event->local_node_id = card->local_node->node_id;
 +	event->bm_node_id    = 0; /* FIXME: We don't track the BM. */
 +	event->irm_node_id   = card->irm_node->node_id;
@@ -874,7 +878,6 @@
 +queue_bus_reset_event(struct client *client)
 +{
 +	struct bus_reset *bus_reset;
-+	struct fw_device *device = client->device;
 +
 +	bus_reset = kzalloc(sizeof *bus_reset, GFP_ATOMIC);
 +	if (bus_reset == NULL) {
@@ -882,7 +885,7 @@
 +		return;
 +	}
 +
-+	fill_bus_reset_event(&bus_reset->reset, device);
++	fill_bus_reset_event(&bus_reset->reset, client);
 +
 +	queue_event(client, &bus_reset->event,
 +		    &bus_reset->reset, sizeof bus_reset->reset, NULL, 0);
@@ -925,10 +928,11 @@
 +	}
 +	get_info.rom_length = client->device->config_rom_length * 4;
 +
++	client->bus_reset_closure = get_info.bus_reset_closure;
 +	if (get_info.bus_reset != 0) {
 +		void __user *uptr = u64_to_uptr(get_info.bus_reset);
 +
-+		fill_bus_reset_event(&bus_reset, client->device);
++		fill_bus_reset_event(&bus_reset, client);
 +		if (copy_to_user(uptr, &bus_reset, sizeof bus_reset))
 +			return -EFAULT;
 +	}
@@ -942,6 +946,53 @@
 +}
 +
 +static void
++add_client_resource(struct client *client, struct client_resource *resource)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&client->lock, flags);
++	list_add_tail(&resource->link, &client->resource_list);
++	resource->handle = client->resource_handle++;
++	spin_unlock_irqrestore(&client->lock, flags);
++}
++
++static int
++release_client_resource(struct client *client, u32 handle,
++			struct client_resource **resource)
++{
++	struct client_resource *r;
++	unsigned long flags;
++
++	spin_lock_irqsave(&client->lock, flags);
++	list_for_each_entry(r, &client->resource_list, link) {
++		if (r->handle == handle) {
++			list_del(&r->link);
++			break;
++		}
++	}
++	spin_unlock_irqrestore(&client->lock, flags);
++
++	if (&r->link == &client->resource_list)
++		return -EINVAL;
++
++	if (resource)
++		*resource = r;
++	else
++		r->release(client, r);
++
++	return 0;
++}
++
++static void
++release_transaction(struct client *client, struct client_resource *resource)
++{
++	struct response *response =
++		container_of(resource, struct response, resource);
++
++	fw_cancel_transaction(client->device->card, &response->transaction);
++}
++
++static void
 +complete_transaction(struct fw_card *card, int rcode,
 +		     void *payload, size_t length, void *data)
 +{
@@ -956,7 +1007,7 @@
 +		       response->response.length);
 +
 +	spin_lock_irqsave(&client->lock, flags);
-+	list_del(&response->link);
++	list_del(&response->resource.link);
 +	spin_unlock_irqrestore(&client->lock, flags);
 +
 +	response->response.type   = FW_CDEV_EVENT_RESPONSE;
@@ -971,7 +1022,6 @@
 +	struct fw_device *device = client->device;
 +	struct fw_cdev_send_request request;
 +	struct response *response;
-+	unsigned long flags;
 +
 +	if (copy_from_user(&request, arg, sizeof request))
 +		return -EFAULT;
@@ -995,9 +1045,8 @@
 +		return -EFAULT;
 +	}
 +
-+	spin_lock_irqsave(&client->lock, flags);
-+	list_add_tail(&response->link, &client->transaction_list);
-+	spin_unlock_irqrestore(&client->lock, flags);
++	response->resource.release = release_transaction;
++	add_client_resource(client, &response->resource);
 +
 +	fw_send_request(device->card, &response->transaction,
 +			request.tcode & 0x1f,
@@ -1018,15 +1067,14 @@
 +	struct fw_address_handler handler;
 +	__u64 closure;
 +	struct client *client;
-+	struct list_head link;
++	struct client_resource resource;
 +};
 +
 +struct request {
 +	struct fw_request *request;
 +	void *data;
 +	size_t length;
-+	u32 serial;
-+	struct list_head link;
++	struct client_resource resource;
 +};
 +
 +struct request_event {
@@ -1035,6 +1083,17 @@
 +};
 +
 +static void
++release_request(struct client *client, struct client_resource *resource)
++{
++	struct request *request =
++		container_of(resource, struct request, resource);
++
++	fw_send_response(client->device->card, request->request,
++			 RCODE_CONFLICT_ERROR);
++	kfree(request);
++}
++
++static void
 +handle_request(struct fw_card *card, struct fw_request *r,
 +	       int tcode, int destination, int source,
 +	       int generation, int speed,
@@ -1044,7 +1103,6 @@
 +	struct address_handler *handler = callback_data;
 +	struct request *request;
 +	struct request_event *e;
-+	unsigned long flags;
 +	struct client *client = handler->client;
 +
 +	request = kmalloc(sizeof *request, GFP_ATOMIC);
@@ -1060,27 +1118,35 @@
 +	request->data    = payload;
 +	request->length  = length;
 +
-+	spin_lock_irqsave(&client->lock, flags);
-+	request->serial = client->request_serial++;
-+	list_add_tail(&request->link, &client->request_list);
-+	spin_unlock_irqrestore(&client->lock, flags);
++	request->resource.release = release_request;
++	add_client_resource(client, &request->resource);
 +
 +	e->request.type    = FW_CDEV_EVENT_REQUEST;
 +	e->request.tcode   = tcode;
 +	e->request.offset  = offset;
 +	e->request.length  = length;
-+	e->request.serial  = request->serial;
++	e->request.handle  = request->resource.handle;
 +	e->request.closure = handler->closure;
 +
 +	queue_event(client, &e->event,
 +		    &e->request, sizeof e->request, payload, length);
 +}
 +
++static void
++release_address_handler(struct client *client,
++			struct client_resource *resource)
++{
++	struct address_handler *handler =
++		container_of(resource, struct address_handler, resource);
++
++	fw_core_remove_address_handler(&handler->handler);
++	kfree(handler);
++}
++
 +static int ioctl_allocate(struct client *client, void __user *arg)
 +{
 +	struct fw_cdev_allocate request;
 +	struct address_handler *handler;
-+	unsigned long flags;
 +	struct fw_address_region region;
 +
 +	if (copy_from_user(&request, arg, sizeof request))
@@ -1103,9 +1169,12 @@
 +		return -EBUSY;
 +	}
 +
-+	spin_lock_irqsave(&client->lock, flags);
-+	list_add_tail(&handler->link, &client->handler_list);
-+	spin_unlock_irqrestore(&client->lock, flags);
++	handler->resource.release = release_address_handler;
++	add_client_resource(client, &handler->resource);
++	request.handle = handler->resource.handle;
++
++	if (copy_to_user(arg, &request, sizeof request))
++		return -EFAULT;
 +
 +	return 0;
 +}
@@ -1113,57 +1182,30 @@
 +static int ioctl_deallocate(struct client *client, void __user *arg)
 +{
 +	struct fw_cdev_deallocate request;
-+	struct address_handler *handler;
-+	unsigned long flags;
 +
 +	if (copy_from_user(&request, arg, sizeof request))
 +		return -EFAULT;
 +
-+	spin_lock_irqsave(&client->lock, flags);
-+	list_for_each_entry(handler, &client->handler_list, link) {
-+		if (handler->handler.offset == request.offset) {
-+			list_del(&handler->link);
-+			break;
-+		}
-+	}
-+	spin_unlock_irqrestore(&client->lock, flags);
-+
-+	if (&handler->link == &client->handler_list)
-+		return -EINVAL;
-+
-+	fw_core_remove_address_handler(&handler->handler);
-+
-+	return 0;
++	return release_client_resource(client, request.handle, NULL);
 +}
 +
 +static int ioctl_send_response(struct client *client, void __user *arg)
 +{
 +	struct fw_cdev_send_response request;
++	struct client_resource *resource;
 +	struct request *r;
-+	unsigned long flags;
 +
 +	if (copy_from_user(&request, arg, sizeof request))
 +		return -EFAULT;
-+
-+	spin_lock_irqsave(&client->lock, flags);
-+	list_for_each_entry(r, &client->request_list, link) {
-+		if (r->serial == request.serial) {
-+			list_del(&r->link);
-+			break;
-+		}
-+	}
-+	spin_unlock_irqrestore(&client->lock, flags);
-+
-+	if (&r->link == &client->request_list)
++	if (release_client_resource(client, request.handle, &resource) < 0)
 +		return -EINVAL;
-+
++	r = container_of(resource, struct request, resource);
 +	if (request.length < r->length)
 +		r->length = request.length;
 +	if (copy_from_user(r->data, u64_to_uptr(request.data), r->length))
 +		return -EFAULT;
 +
 +	fw_send_response(client->device->card, r->request, request.rcode);
-+
 +	kfree(r);
 +
 +	return 0;
@@ -1182,6 +1224,76 @@
 +	return fw_core_initiate_bus_reset(client->device->card, short_reset);
 +}
 +
++struct descriptor {
++	struct fw_descriptor d;
++	struct client_resource resource;
++	u32 data[0];
++};
++
++static void release_descriptor(struct client *client,
++			       struct client_resource *resource)
++{
++	struct descriptor *descriptor =
++		container_of(resource, struct descriptor, resource);
++
++	fw_core_remove_descriptor(&descriptor->d);
++	kfree(descriptor);
++}
++
++static int ioctl_add_descriptor(struct client *client, void __user *arg)
++{
++	struct fw_cdev_add_descriptor request;
++	struct descriptor *descriptor;
++	int retval;
++
++	if (copy_from_user(&request, arg, sizeof request))
++		return -EFAULT;
++
++	if (request.length > 256)
++		return -EINVAL;
++
++	descriptor =
++		kmalloc(sizeof *descriptor + request.length * 4, GFP_KERNEL);
++	if (descriptor == NULL)
++		return -ENOMEM;
++
++	if (copy_from_user(descriptor->data,
++			   u64_to_uptr(request.data), request.length * 4)) {
++		kfree(descriptor);
++		return -EFAULT;
++	}
++
++	descriptor->d.length = request.length;
++	descriptor->d.immediate = request.immediate;
++	descriptor->d.key = request.key;
++	descriptor->d.data = descriptor->data;
++
++	retval = fw_core_add_descriptor(&descriptor->d);
++	if (retval < 0) {
++		kfree(descriptor);
++		return retval;
++	}
++
++	descriptor->resource.release = release_descriptor;
++	add_client_resource(client, &descriptor->resource);
++	request.handle = descriptor->resource.handle;
++
++	if (copy_to_user(arg, &request, sizeof request))
++		return -EFAULT;
++
++	return 0;
++}
++
++static int ioctl_remove_descriptor(struct client *client, void __user *arg)
++{
++	struct fw_cdev_remove_descriptor request;
++
++	if (copy_from_user(&request, arg, sizeof request))
++		return -EFAULT;
++
++	return release_client_resource(client, request.handle, NULL);
++}
++
 +static void
 +iso_callback(struct fw_iso_context *context, u32 cycle,
 +	     size_t header_length, void *header, void *data)
@@ -1247,7 +1359,7 @@
 +	struct fw_cdev_queue_iso request;
 +	struct fw_cdev_iso_packet __user *p, *end, *next;
 +	struct fw_iso_context *ctx = client->iso_context;
-+	unsigned long payload, payload_end, header_length;
++	unsigned long payload, buffer_end, header_length;
 +	int count;
 +	struct {
 +		struct fw_iso_packet packet;
@@ -1268,11 +1380,11 @@
 +	 * and the request.data pointer is ignored.*/
 +
 +	payload = (unsigned long)request.data - client->vm_start;
-+	payload_end = payload + (client->buffer.page_count << PAGE_SHIFT);
++	buffer_end = client->buffer.page_count << PAGE_SHIFT;
 +	if (request.data == 0 || client->buffer.pages == NULL ||
-+	    payload >= payload_end) {
++	    payload >= buffer_end) {
 +		payload = 0;
-+		payload_end = 0;
++		buffer_end = 0;
 +	}
 +
 +	if (!access_ok(VERIFY_READ, request.packets, request.size))
@@ -1309,7 +1421,7 @@
 +		if (u.packet.skip && ctx->type == FW_ISO_CONTEXT_TRANSMIT &&
 +		    u.packet.header_length + u.packet.payload_length > 0)
 +			return -EINVAL;
-+		if (payload + u.packet.payload_length > payload_end)
++		if (payload + u.packet.payload_length > buffer_end)
 +			return -EINVAL;
 +
 +		if (fw_iso_context_queue(ctx, &u.packet,
@@ -1371,6 +1483,10 @@
 +		return ioctl_send_response(client, arg);
 +	case FW_CDEV_IOC_INITIATE_BUS_RESET:
 +		return ioctl_initiate_bus_reset(client, arg);
++	case FW_CDEV_IOC_ADD_DESCRIPTOR:
++		return ioctl_add_descriptor(client, arg);
++	case FW_CDEV_IOC_REMOVE_DESCRIPTOR:
++		return ioctl_remove_descriptor(client, arg);
 +	case FW_CDEV_IOC_CREATE_ISO_CONTEXT:
 +		return ioctl_create_iso_context(client, arg);
 +	case FW_CDEV_IOC_QUEUE_ISO:
@@ -1447,10 +1563,8 @@
 +static int fw_device_op_release(struct inode *inode, struct file *file)
 +{
 +	struct client *client = file->private_data;
-+	struct address_handler *h, *next_h;
-+	struct request *r, *next_r;
 +	struct event *e, *next_e;
-+	struct response *t, *next_t;
++	struct client_resource *r, *next_r;
 +	unsigned long flags;
 +
 +	if (client->buffer.pages)
@@ -1459,21 +1573,8 @@
 +	if (client->iso_context)
 +		fw_iso_context_destroy(client->iso_context);
 +
-+	list_for_each_entry_safe(h, next_h, &client->handler_list, link) {
-+		fw_core_remove_address_handler(&h->handler);
-+		kfree(h);
-+	}
-+
-+	list_for_each_entry_safe(r, next_r, &client->request_list, link) {
-+		fw_send_response(client->device->card, r->request,
-+				 RCODE_CONFLICT_ERROR);
-+		kfree(r);
-+	}
-+
-+	list_for_each_entry_safe(t, next_t, &client->transaction_list, link) {
-+		fw_cancel_transaction(client->device->card, &t->transaction);
-+		kfree(t);
-+	}
++	list_for_each_entry_safe(r, next_r, &client->resource_list, link)
++		r->release(client, r);
 +
 +	/* FIXME: We should wait for the async tasklets to stop
 +	 * running before freeing the memory. */
@@ -1521,10 +1622,10 @@
 +};
 diff --git a/drivers/firewire/fw-device-cdev.h b/drivers/firewire/fw-device-cdev.h
 new file mode 100644
-index 0000000..10b8322
+index 0000000..a6340bf
 --- /dev/null
 +++ b/drivers/firewire/fw-device-cdev.h
-@@ -0,0 +1,226 @@
+@@ -0,0 +1,260 @@
 +/*						-*- c-basic-offset: 8 -*-
 + *
 + * fw-device-cdev.h -- Char device interface.
@@ -1601,7 +1702,13 @@
 + * event.  It's a 64-bit type so that it's a fixed size type big
 + * enough to hold a pointer on all platforms. */
 +
++struct fw_cdev_event_common {
++	__u64 closure;
++	__u32 type;
++};
++
 +struct fw_cdev_event_bus_reset {
++	__u64 closure;
 +	__u32 type;
 +	__u32 node_id;
 +	__u32 local_node_id;
@@ -1612,41 +1719,52 @@
 +};
 +
 +struct fw_cdev_event_response {
++	__u64 closure;
 +	__u32 type;
 +	__u32 rcode;
-+	__u64 closure;
 +	__u32 length;
 +	__u32 data[0];
 +};
 +
 +struct fw_cdev_event_request {
++	__u64 closure;
 +	__u32 type;
 +	__u32 tcode;
 +	__u64 offset;
-+	__u64 closure;
-+	__u32 serial;
++	__u32 handle;
 +	__u32 length;
 +	__u32 data[0];
 +};
 +
 +struct fw_cdev_event_iso_interrupt {
++	__u64 closure;
 +	__u32 type;
 +	__u32 cycle;
-+	__u64 closure;
 +	__u32 header_length;	/* Length in bytes of following headers. */
 +	__u32 header[0];
 +};
 +
++union fw_cdev_event {
++	struct fw_cdev_event_common common;
++	struct fw_cdev_event_bus_reset bus_reset;
++	struct fw_cdev_event_response response;
++	struct fw_cdev_event_request request;
++	struct fw_cdev_event_iso_interrupt iso_interrupt;
++};
++
 +#define FW_CDEV_IOC_GET_INFO		_IO('#', 0x00)
 +#define FW_CDEV_IOC_SEND_REQUEST	_IO('#', 0x01)
 +#define FW_CDEV_IOC_ALLOCATE		_IO('#', 0x02)
 +#define FW_CDEV_IOC_DEALLOCATE		_IO('#', 0x03)
 +#define FW_CDEV_IOC_SEND_RESPONSE	_IO('#', 0x04)
 +#define FW_CDEV_IOC_INITIATE_BUS_RESET	_IO('#', 0x05)
-+#define FW_CDEV_IOC_CREATE_ISO_CONTEXT	_IO('#', 0x06)
-+#define FW_CDEV_IOC_QUEUE_ISO		_IO('#', 0x07)
-+#define FW_CDEV_IOC_START_ISO		_IO('#', 0x08)
-+#define FW_CDEV_IOC_STOP_ISO		_IO('#', 0x09)
++#define FW_CDEV_IOC_ADD_DESCRIPTOR	_IO('#', 0x06)
++#define FW_CDEV_IOC_REMOVE_DESCRIPTOR	_IO('#', 0x07)
++
++#define FW_CDEV_IOC_CREATE_ISO_CONTEXT	_IO('#', 0x08)
++#define FW_CDEV_IOC_QUEUE_ISO		_IO('#', 0x09)
++#define FW_CDEV_IOC_START_ISO		_IO('#', 0x0a)
++#define FW_CDEV_IOC_STOP_ISO		_IO('#', 0x0b)
 +
 +/* FW_CDEV_VERSION History
 + *
@@ -1672,8 +1790,12 @@
 +	__u64 rom;
 +
 +	/* If non-zero, a fw_cdev_event_bus_reset struct will be
-+	 * copied here with the current state of the bus. */
++	 * copied here with the current state of the bus.  This does
++	 * not cause a bus reset to happen.  The value of closure in
++	 * this and sub-sequent bus reset events is set to
++	 * bus_reset_closure. */
 +	__u64 bus_reset;
++	__u64 bus_reset_closure;
 +
 +	/* The index of the card this devices belongs to. */
 +	__u32 card;
@@ -1692,17 +1814,18 @@
 +	__u32 rcode;
 +	__u32 length;
 +	__u64 data;
-+	__u32 serial;
++	__u32 handle;
 +};
 +
 +struct fw_cdev_allocate {
 +	__u64 offset;
 +	__u64 closure;
 +	__u32 length;
++	__u32 handle;
 +};
 +
 +struct fw_cdev_deallocate {
-+	__u64 offset;
++	__u32 handle;
 +};
 +
 +#define FW_CDEV_LONG_RESET	0
@@ -1712,6 +1835,18 @@
 +	__u32 type;
 +};
 +
++struct fw_cdev_add_descriptor {
++	__u32 immediate;
++	__u32 key;
++	__u64 data;
++	__u32 length;
++	__u32 handle;
++};
++
++struct fw_cdev_remove_descriptor {
++	__u32 handle;
++};
++
 +#define FW_CDEV_ISO_CONTEXT_TRANSMIT	0
 +#define FW_CDEV_ISO_CONTEXT_RECEIVE	1
 +
@@ -1739,9 +1874,9 @@
 +};
 +
 +struct fw_cdev_queue_iso {
-+	__u32 size;
 +	__u64 packets;
 +	__u64 data;
++	__u32 size;
 +};
 +
 +struct fw_cdev_start_iso {
@@ -1753,10 +1888,10 @@
 +#endif /* __fw_cdev_h */
 diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c
 new file mode 100644
-index 0000000..2bf86aa
+index 0000000..7197657
 --- /dev/null
 +++ b/drivers/firewire/fw-device.c
-@@ -0,0 +1,795 @@
+@@ -0,0 +1,780 @@
 +/*						-*- c-basic-offset: 8 -*-
 + *
 + * fw-device.c - Device probing and sysfs code.
@@ -2048,32 +2183,29 @@
 +};
 +
 +static void
-+remove_config_rom_attributes(struct device *dev)
-+{
-+	int i;
-+
-+	for (i = 0; i < ARRAY_SIZE(config_rom_attributes); i++)
-+		device_remove_file(dev, &config_rom_attributes[i].attr);
-+}
-+
-+static int
-+add_config_rom_attributes(struct device *dev)
++init_fw_attribute_group(struct device *dev,
++			struct device_attribute *attrs,
++			struct fw_attribute_group *group)
 +{
 +	struct device_attribute *attr;
-+	int i, err = 0;
++	int i, j;
++
++	for (j = 0; attrs[j].attr.name != NULL; j++)
++		group->attrs[j] = &attrs[j].attr;
 +
 +	for (i = 0; i < ARRAY_SIZE(config_rom_attributes); i++) {
 +		attr = &config_rom_attributes[i].attr;
 +		if (attr->show(dev, attr, NULL) < 0)
 +			continue;
-+		err = device_create_file(dev, attr);
-+		if (err < 0) {
-+			remove_config_rom_attributes(dev);
-+			break;
-+		}
++		group->attrs[j++] = &attr->attr;
 +	}
 +
-+	return err;
++	BUG_ON(j >= ARRAY_SIZE(group->attrs));
++	group->attrs[j++] = NULL;
++	group->groups[0] = &group->group;
++	group->groups[1] = NULL;
++	group->group.attrs = group->attrs;
++	dev->groups = group->groups;
 +}
 +
 +static ssize_t
@@ -2256,7 +2388,6 @@
 +}
 +
 +static struct device_type fw_unit_type = {
-+	.attrs		= fw_unit_attributes,
 +	.uevent		= fw_unit_uevent,
 +	.release	= fw_unit_release,
 +};
@@ -2293,16 +2424,14 @@
 +		snprintf(unit->device.bus_id, sizeof unit->device.bus_id,
 +			 "%s.%d", device->device.bus_id, i++);
 +
++		init_fw_attribute_group(&unit->device,
++					fw_unit_attributes,
++					&unit->attribute_group);
 +		if (device_register(&unit->device) < 0)
 +			goto skip_unit;
 +
-+		if (add_config_rom_attributes(&unit->device) < 0)
-+			goto skip_unregister;
-+
 +		continue;
 +
-+	skip_unregister:
-+		device_unregister(&unit->device);
 +	skip_unit:
 +		kfree(unit);
 +	}
@@ -2310,9 +2439,6 @@
 +
 +static int shutdown_unit(struct device *device, void *data)
 +{
-+	struct fw_unit *unit = fw_unit(device);
-+
-+	remove_config_rom_attributes(&unit->device);
 +	device_unregister(device);
 +
 +	return 0;
@@ -2342,15 +2468,12 @@
 +	idr_remove(&fw_device_idr, minor);
 +	up_write(&fw_bus_type.subsys.rwsem);
 +
-+	remove_config_rom_attributes(&device->device);
-+
 +	fw_device_cdev_remove(device);
 +	device_for_each_child(&device->device, NULL, shutdown_unit);
 +	device_unregister(&device->device);
 +}
 +
 +static struct device_type fw_device_type = {
-+	.attrs		= fw_device_attributes,
 +	.release	= fw_device_release,
 +};
 +
@@ -2363,8 +2486,8 @@
 + * aggressive than that, since it scales pretty well; if 10 devices
 + * are plugged in, they're all getting read within one second. */
 +
-+#define MAX_RETRIES	5
-+#define RETRY_DELAY	(2 * HZ)
++#define MAX_RETRIES	10
++#define RETRY_DELAY	(3 * HZ)
 +#define INITIAL_DELAY	(HZ / 2)
 +
 +static void fw_device_init(struct work_struct *work)
@@ -2406,15 +2529,14 @@
 +	snprintf(device->device.bus_id, sizeof device->device.bus_id,
 +		 "fw%d", minor);
 +
++	init_fw_attribute_group(&device->device,
++				fw_device_attributes,
++				&device->attribute_group);
 +	if (device_add(&device->device)) {
 +		fw_error("Failed to add device.\n");
 +		goto error_with_cdev;
 +	}
 +
-+	err = add_config_rom_attributes(&device->device);
-+	if (err < 0)
-+		goto error_with_register;
-+
 +	create_units(device);
 +
 +	/* Transition the device to running state.  If it got pulled
@@ -2441,8 +2563,6 @@
 +
 +	return;
 +
-+ error_with_register:
-+	device_unregister(&device->device);
 + error_with_cdev:
 +	down_write(&fw_bus_type.subsys.rwsem);
 +	idr_remove(&fw_device_idr, minor);
@@ -2554,10 +2674,10 @@
 +}
 diff --git a/drivers/firewire/fw-device.h b/drivers/firewire/fw-device.h
 new file mode 100644
-index 0000000..ce47ab9
+index 0000000..c167d59
 --- /dev/null
 +++ b/drivers/firewire/fw-device.h
-@@ -0,0 +1,141 @@
+@@ -0,0 +1,149 @@
 +/*						-*- c-basic-offset: 8 -*-
 + *
 + * fw-device.h - Device probing and sysfs code.
@@ -2592,6 +2712,12 @@
 +	FW_DEVICE_SHUTDOWN,
 +};
 +
++struct fw_attribute_group {
++	struct attribute_group *groups[2];
++	struct attribute_group group;
++	struct attribute *attrs[11];
++};
++
 +struct fw_device {
 +	atomic_t state;
 +	struct fw_node *node;
@@ -2605,6 +2731,7 @@
 +	size_t config_rom_length;
 +	int config_rom_retries;
 +	struct delayed_work work;
++	struct fw_attribute_group attribute_group;
 +};
 +
 +static inline struct fw_device *
@@ -2632,6 +2759,7 @@
 +struct fw_unit {
 +	struct device device;
 +	u32 *directory;
++	struct fw_attribute_group attribute_group;
 +};
 +
 +static inline struct fw_unit *
@@ -2870,10 +2998,10 @@
 +EXPORT_SYMBOL(fw_iso_context_stop);
 diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c
 new file mode 100644
-index 0000000..abb9dc1
+index 0000000..b941239
 --- /dev/null
 +++ b/drivers/firewire/fw-ohci.c
-@@ -0,0 +1,1885 @@
+@@ -0,0 +1,1890 @@
 +/*						-*- c-basic-offset: 8 -*-
 + *
 + * fw-ohci.c - Driver for OHCI 1394 boards
@@ -3504,6 +3632,7 @@
 +
 +	driver_data = (struct driver_data *) &d[3];
 +	driver_data->packet = packet;
++	packet->driver_data = driver_data;
 +	
 +	if (packet->payload_length > 0) {
 +		payload_bus =
@@ -4237,28 +4366,32 @@
 +{
 +	struct iso_context *ctx = container_of(base, struct iso_context, base);
 +	struct fw_ohci *ohci = ctx->context.ohci;
-+	u32 cycle_match = 0;
++	u32 control, match;
 +	int index;
 +
 +	if (ctx->base.type == FW_ISO_CONTEXT_TRANSMIT) {
 +		index = ctx - ohci->it_context_list;
-+		if (cycle > 0)
-+			cycle_match = IT_CONTEXT_CYCLE_MATCH_ENABLE |
++		match = 0;
++		if (cycle >= 0)
++			match = IT_CONTEXT_CYCLE_MATCH_ENABLE |
 +				(cycle & 0x7fff) << 16;
 +
 +		reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 1 << index);
 +		reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1 << index);
-+		context_run(&ctx->context, cycle_match);
++		context_run(&ctx->context, match);
 +	} else {
 +		index = ctx - ohci->ir_context_list;
++		control = IR_CONTEXT_DUAL_BUFFER_MODE | IR_CONTEXT_ISOCH_HEADER;
++		match = (tags << 28) | (sync << 8) | ctx->base.channel;
++		if (cycle >= 0) {
++			match |= (cycle & 0x07fff) << 12;
++			control |= IR_CONTEXT_CYCLE_MATCH_ENABLE;
++		}
 +
 +		reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 1 << index);
 +		reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 1 << index);
-+		reg_write(ohci, context_match(ctx->context.regs),
-+			  (tags << 28) | (sync << 8) | ctx->base.channel);
-+		context_run(&ctx->context,
-+			    IR_CONTEXT_DUAL_BUFFER_MODE |
-+			    IR_CONTEXT_ISOCH_HEADER);
++		reg_write(ohci, context_match(ctx->context.regs), match);
++		context_run(&ctx->context, control);
 +	}
 +
 +	return 0;
@@ -6091,10 +6224,10 @@
 +module_exit(sbp2_cleanup);
 diff --git a/drivers/firewire/fw-topology.c b/drivers/firewire/fw-topology.c
 new file mode 100644
-index 0000000..7923463
+index 0000000..bc8a348
 --- /dev/null
 +++ b/drivers/firewire/fw-topology.c
-@@ -0,0 +1,518 @@
+@@ -0,0 +1,519 @@
 +/*						-*- c-basic-offset: 8 -*-
 + *
 + * fw-topology.c - Incremental bus scan, based on bus topology
@@ -6263,7 +6396,7 @@
 +static struct fw_node *build_tree(struct fw_card *card,
 +				  u32 *sid, int self_id_count)
 +{
-+	struct fw_node *node, *child, *local_node;
++	struct fw_node *node, *child, *local_node, *irm_node;
 +	struct list_head stack, *h;
 +	u32 *next_sid, *end, q;
 +	int i, port_count, child_port_count, phy_id, parent_count, stack_depth;
@@ -6275,7 +6408,7 @@
 +	stack_depth = 0;
 +	end = sid + self_id_count;
 +	phy_id = 0;
-+	card->irm_node = NULL;
++	irm_node = NULL;
 +	gap_count = self_id_gap_count(*sid);
 +	topology_type = 0;
 +
@@ -6315,7 +6448,7 @@
 +			local_node = node;
 +
 +		if (self_id_contender(q))
-+			card->irm_node = node;
++			irm_node = node;
 +
 +		if (node->phy_speed == SCODE_BETA)
 +			topology_type |= FW_TOPOLOGY_B;
@@ -6379,6 +6512,7 @@
 +	}
 +
 +	card->root_node = node;
++	card->irm_node = irm_node;
 +	card->gap_count = gap_count;
 +	card->topology_type = topology_type;
 +
@@ -7610,10 +7744,10 @@
 +module_exit(fw_core_cleanup);
 diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h
 new file mode 100644
-index 0000000..6621497
+index 0000000..6352734
 --- /dev/null
 +++ b/drivers/firewire/fw-transaction.h
-@@ -0,0 +1,499 @@
+@@ -0,0 +1,505 @@
 +/*						-*- c-basic-offset: 8 -*-
 + *
 + * fw-transaction.h - Header for IEEE1394 transaction logic
@@ -7723,6 +7857,12 @@
 +#define PHY_PACKET_LINK_ON	0x1
 +#define PHY_PACKET_SELF_ID	0x2
 +
++/* Bit fields _within_ the PHY registers. */
++#define PHY_LINK_ACTIVE		0x80
++#define PHY_CONTENDER		0x40
++#define PHY_BUS_RESET		0x40
++#define PHY_BUS_SHORT_RESET	0x40
++
 +#define CSR_REGISTER_BASE		0xfffff0000000ULL
 +
 +/* register offsets relative to CSR_REGISTER_BASE */




More information about the fedora-cvs-commits mailing list