All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/8] firewire: cdev ABI updates
@ 2010-06-20 20:49 Stefan Richter
  2010-06-20 20:50 ` [PATCH 1/8] firewire: remove an unused function argument Stefan Richter
                   ` (8 more replies)
  0 siblings, 9 replies; 10+ messages in thread
From: Stefan Richter @ 2010-06-20 20:49 UTC (permalink / raw)
  To: linux1394-devel; +Cc: linux-kernel

Following as replies:  Proposed updates to the <linux/firewire-cdev.h>
ABI and to its backing implementation.  These updates are required for
target-type userspace drivers and in order to be able to use more than
one audio device with FFADO.

Some of the patches have already been seen on linux1394-devel but not
yet on linux-kernel.

Corresponding patches to libraw1394 will be posted to linux1394-devel
right after the kernel patch postings.

Clemens Ladisch (1):
      firewire: cdev: fix race in iso context creation

Jay Fenlason (2):
      firewire: cdev: fix responses to nodes at different card
      firewire: expose extended tcode of incoming lock requests to (userspace) drivers

Stefan Richter (5):
      firewire: remove an unused function argument
      firewire: cdev: count references of cards during inbound transactions
      firewire: cdev: freeze FW_CDEV_VERSION due to libraw1394 bug
      firewire: cdev: fix ABI for FCP and address range mapping, add fw_cdev_event_request2
      firewire: cdev: extend fw_cdev_event_iso_interrupt documentation

 drivers/firewire/core-cdev.c            |   81 ++++++++++++++++-----
 drivers/firewire/core-transaction.c     |   18 +++--
 drivers/firewire/net.c                  |    4 +-
 drivers/firewire/sbp2.c                 |    3 +-
 drivers/media/dvb/firewire/firedtv-fw.c |    4 +-
 include/linux/firewire-cdev.h           |  117 +++++++++++++++++++++++++++---
 include/linux/firewire.h                |    2 +-
 7 files changed, 183 insertions(+), 46 deletions(-)
-- 
Stefan Richter
-=====-==-=- -==- =-=--
http://arcgraph.de/sr/


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/8] firewire: remove an unused function argument
  2010-06-20 20:49 [PATCH 0/8] firewire: cdev ABI updates Stefan Richter
@ 2010-06-20 20:50 ` Stefan Richter
  2010-06-20 20:51 ` [PATCH 2/8] firewire: cdev: fix race in iso context creation Stefan Richter
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Stefan Richter @ 2010-06-20 20:50 UTC (permalink / raw)
  To: linux1394-devel; +Cc: linux-kernel

void (*fw_address_callback_t)(..., int speed, ...) is the speed that a
remote node chose to transmit a request to us.  In case of split
transactions, firewire-core will transmit the response at that speed.

Upper layer drivers on the other hand (firewire-net, -sbp2, firedtv, and
userspace drivers) cannot do anything useful with that speed datum,
except log it for debug purposes.  But data that is merely potentially
(not even actually) used for debug purposes does not belong into the API.

Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
---
 drivers/firewire/core-cdev.c            |    3 +--
 drivers/firewire/core-transaction.c     |   14 +++++++-------
 drivers/firewire/net.c                  |    4 ++--
 drivers/firewire/sbp2.c                 |    3 +--
 drivers/media/dvb/firewire/firedtv-fw.c |    4 ++--
 include/linux/firewire.h                |    2 +-
 6 files changed, 14 insertions(+), 16 deletions(-)

Index: b/drivers/firewire/core-cdev.c
===================================================================
--- a/drivers/firewire/core-cdev.c
+++ b/drivers/firewire/core-cdev.c
@@ -633,8 +633,7 @@ static void release_request(struct clien
 
 static void handle_request(struct fw_card *card, struct fw_request *request,
 			   int tcode, int destination, int source,
-			   int generation, int speed,
-			   unsigned long long offset,
+			   int generation, unsigned long long offset,
 			   void *payload, size_t length, void *callback_data)
 {
 	struct address_handler_resource *handler = callback_data;
Index: b/drivers/firewire/core-transaction.c
===================================================================
--- a/drivers/firewire/core-transaction.c
+++ b/drivers/firewire/core-transaction.c
@@ -802,7 +802,7 @@ static void handle_exclusive_region_requ
 	else
 		handler->address_callback(card, request,
 					  tcode, destination, source,
-					  p->generation, p->speed, offset,
+					  p->generation, offset,
 					  request->data, request->length,
 					  handler->callback_data);
 }
@@ -840,8 +840,8 @@ static void handle_fcp_region_request(st
 		if (is_enclosing_handler(handler, offset, request->length))
 			handler->address_callback(card, NULL, tcode,
 						  destination, source,
-						  p->generation, p->speed,
-						  offset, request->data,
+						  p->generation, offset,
+						  request->data,
 						  request->length,
 						  handler->callback_data);
 	}
@@ -951,8 +951,8 @@ static const struct fw_address_region to
 
 static void handle_topology_map(struct fw_card *card, struct fw_request *request,
 		int tcode, int destination, int source, int generation,
-		int speed, unsigned long long offset,
-		void *payload, size_t length, void *callback_data)
+		unsigned long long offset, void *payload, size_t length,
+		void *callback_data)
 {
 	int start;
 
@@ -996,8 +996,8 @@ static void update_split_timeout(struct 
 
 static void handle_registers(struct fw_card *card, struct fw_request *request,
 		int tcode, int destination, int source, int generation,
-		int speed, unsigned long long offset,
-		void *payload, size_t length, void *callback_data)
+		unsigned long long offset, void *payload, size_t length,
+		void *callback_data)
 {
 	int reg = offset & ~CSR_REGISTER_BASE;
 	__be32 *data = payload;
Index: b/drivers/firewire/net.c
===================================================================
--- a/drivers/firewire/net.c
+++ b/drivers/firewire/net.c
@@ -806,8 +806,8 @@ static int fwnet_incoming_packet(struct 
 
 static void fwnet_receive_packet(struct fw_card *card, struct fw_request *r,
 		int tcode, int destination, int source, int generation,
-		int speed, unsigned long long offset, void *payload,
-		size_t length, void *callback_data)
+		unsigned long long offset, void *payload, size_t length,
+		void *callback_data)
 {
 	struct fwnet_device *dev = callback_data;
 	int rcode;
Index: b/drivers/firewire/sbp2.c
===================================================================
--- a/drivers/firewire/sbp2.c
+++ b/drivers/firewire/sbp2.c
@@ -410,8 +410,7 @@ static void free_orb(struct kref *kref)
 
 static void sbp2_status_write(struct fw_card *card, struct fw_request *request,
 			      int tcode, int destination, int source,
-			      int generation, int speed,
-			      unsigned long long offset,
+			      int generation, unsigned long long offset,
 			      void *payload, size_t length, void *callback_data)
 {
 	struct sbp2_logical_unit *lu = callback_data;
Index: b/drivers/media/dvb/firewire/firedtv-fw.c
===================================================================
--- a/drivers/media/dvb/firewire/firedtv-fw.c
+++ b/drivers/media/dvb/firewire/firedtv-fw.c
@@ -194,8 +194,8 @@ static const struct firedtv_backend back
 
 static void handle_fcp(struct fw_card *card, struct fw_request *request,
 		       int tcode, int destination, int source, int generation,
-		       int speed, unsigned long long offset,
-		       void *payload, size_t length, void *callback_data)
+		       unsigned long long offset, void *payload, size_t length,
+		       void *callback_data)
 {
 	struct firedtv *f, *fdtv = NULL;
 	struct fw_device *device;
Index: b/include/linux/firewire.h
===================================================================
--- a/include/linux/firewire.h
+++ b/include/linux/firewire.h
@@ -265,7 +265,7 @@ typedef void (*fw_transaction_callback_t
 typedef void (*fw_address_callback_t)(struct fw_card *card,
 				      struct fw_request *request,
 				      int tcode, int destination, int source,
-				      int generation, int speed,
+				      int generation,
 				      unsigned long long offset,
 				      void *data, size_t length,
 				      void *callback_data);

-- 
Stefan Richter
-=====-==-=- -==- =-=--
http://arcgraph.de/sr/


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 2/8] firewire: cdev: fix race in iso context creation
  2010-06-20 20:49 [PATCH 0/8] firewire: cdev ABI updates Stefan Richter
  2010-06-20 20:50 ` [PATCH 1/8] firewire: remove an unused function argument Stefan Richter
@ 2010-06-20 20:51 ` Stefan Richter
  2010-06-20 20:51 ` [PATCH 3/8] firewire: cdev: fix responses to nodes at different card Stefan Richter
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Stefan Richter @ 2010-06-20 20:51 UTC (permalink / raw)
  To: linux1394-devel; +Cc: linux-kernel

Date: Mon, 14 Jun 2010 11:46:25 +0200
From: Clemens Ladisch <clemens@ladisch.de>

Protect the client's iso context pointer against a race that can happen
when more than one creation call is executed at the same time.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
---
 drivers/firewire/core-cdev.c |   13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

Index: b/drivers/firewire/core-cdev.c
===================================================================
--- a/drivers/firewire/core-cdev.c
+++ b/drivers/firewire/core-cdev.c
@@ -865,10 +865,6 @@ static int ioctl_create_iso_context(stru
 	struct fw_cdev_create_iso_context *a = &arg->create_iso_context;
 	struct fw_iso_context *context;
 
-	/* We only support one context at this time. */
-	if (client->iso_context != NULL)
-		return -EBUSY;
-
 	if (a->channel > 63)
 		return -EINVAL;
 
@@ -893,10 +889,17 @@ static int ioctl_create_iso_context(stru
 	if (IS_ERR(context))
 		return PTR_ERR(context);
 
+	/* We only support one context at this time. */
+	spin_lock_irq(&client->lock);
+	if (client->iso_context != NULL) {
+		spin_unlock_irq(&client->lock);
+		fw_iso_context_destroy(context);
+		return -EBUSY;
+	}
 	client->iso_closure = a->closure;
 	client->iso_context = context;
+	spin_unlock_irq(&client->lock);
 
-	/* We only support one context at this time. */
 	a->handle = 0;
 
 	return 0;

-- 
Stefan Richter
-=====-==-=- -==- =-=--
http://arcgraph.de/sr/


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 3/8] firewire: cdev: fix responses to nodes at different card
  2010-06-20 20:49 [PATCH 0/8] firewire: cdev ABI updates Stefan Richter
  2010-06-20 20:50 ` [PATCH 1/8] firewire: remove an unused function argument Stefan Richter
  2010-06-20 20:51 ` [PATCH 2/8] firewire: cdev: fix race in iso context creation Stefan Richter
@ 2010-06-20 20:51 ` Stefan Richter
  2010-06-20 20:52 ` [PATCH 4/8] firewire: cdev: count references of cards during inbound transactions Stefan Richter
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Stefan Richter @ 2010-06-20 20:51 UTC (permalink / raw)
  To: linux1394-devel; +Cc: linux-kernel

Date: Tue, 18 May 2010 14:02:45 -0400
From: Jay Fenlason <fenlason@redhat.com>

My box has two firewire cards in it: card0 and card1.
My application opens /dev/fw0 (card 0) and allocates an address space.
The core makes the address space available on both cards.
Along comes the remote device, which sends a READ_QUADLET_REQUEST to
card1.  The request gets passed up to my application, which calls
ioctl_send_response().

ioctl_send_response() then calls fw_send_response() with card0,
because that's the card it's bound to.
Card0's driver drops the response, because it isn't part of
a transaction that it has outstanding.

So in core-cdev: handle_request(), we need to stash the
card of the inbound request in the struct inbound_transaction_resource and
use that card to send the response to.

The hard part will be refcounting the card correctly
so it can't get deallocated while we hold a pointer to it.

Here's a trivial patch, which does not do the card refcounting, but at
least demonstrates what the problem is.

Note that we can't depend on the fact that the core-cdev:client
structure holds a card open, because in this case the card it holds
open is not the card the request came in on.

..and there's no way for the core to tell cdev "this card is gone,
kill any inbound transactions on it", while cdev holds the transaction
open until userspace issues a SEND_RESPONSE ioctl, which may be a very,
very long time.  But when it does, it calls fw_send_response(), which
will dereference the card...

So how unhappy are we about userspace potentially holding a fw_card
open forever?

Signed-off-by: Jay Fenlason <fenlason@redhat.com>

Reference counting to be addressed in a separate change.

Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de> (whitespace)
---
 drivers/firewire/core-cdev.c |    7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

Index: b/drivers/firewire/core-cdev.c
===================================================================
--- a/drivers/firewire/core-cdev.c
+++ b/drivers/firewire/core-cdev.c
@@ -107,6 +107,7 @@ struct outbound_transaction_resource {
 
 struct inbound_transaction_resource {
 	struct client_resource resource;
+	struct fw_card *card;
 	struct fw_request *request;
 	void *data;
 	size_t length;
@@ -626,8 +627,7 @@ static void release_request(struct clien
 	if (is_fcp_request(r->request))
 		kfree(r->data);
 	else
-		fw_send_response(client->device->card, r->request,
-				 RCODE_CONFLICT_ERROR);
+		fw_send_response(r->card, r->request, RCODE_CONFLICT_ERROR);
 	kfree(r);
 }
 
@@ -647,6 +647,7 @@ static void handle_request(struct fw_car
 	if (r == NULL || e == NULL)
 		goto failed;
 
+	r->card    = card;
 	r->request = request;
 	r->data    = payload;
 	r->length  = length;
@@ -766,7 +767,7 @@ static int ioctl_send_response(struct cl
 		kfree(r->request);
 		goto out;
 	}
-	fw_send_response(client->device->card, r->request, a->rcode);
+	fw_send_response(r->card, r->request, a->rcode);
  out:
 	kfree(r);
 

-- 
Stefan Richter
-=====-==-=- -==- =-=--
http://arcgraph.de/sr/


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 4/8] firewire: cdev: count references of cards during inbound transactions
  2010-06-20 20:49 [PATCH 0/8] firewire: cdev ABI updates Stefan Richter
                   ` (2 preceding siblings ...)
  2010-06-20 20:51 ` [PATCH 3/8] firewire: cdev: fix responses to nodes at different card Stefan Richter
@ 2010-06-20 20:52 ` Stefan Richter
  2010-06-20 20:52 ` [PATCH 5/8] firewire: cdev: freeze FW_CDEV_VERSION due to libraw1394 bug Stefan Richter
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Stefan Richter @ 2010-06-20 20:52 UTC (permalink / raw)
  To: linux1394-devel; +Cc: linux-kernel

If a request comes in to an address range managed by a userspace driver
i.e. <linux/firewire-cdev.h> client, the card instance of request and
response may differ from the card instance of the client device.
Therefore we need to take a reference of the card until the response was
sent.

I thought about putting the reference counting into core-transaction.c,
but the various high-level drivers besides cdev clients (firewire-net,
firewire-sbp2, firedtv) use the card pointer in their fw_address_handler
address_callback method only to look up devices of which they already
hold the necessary references.  So this seems to be a specific
firewire-cdev issue which is better addressed locally.

We do not need the reference
  - in case of FCP_REQUEST or FCP_RESPONSE requests because then the
    firewire-core will send the split transaction response for us
    already in the context of the request handler,
  - if it is the same card as the client device's because we hold a
    card reference indirectly via teh client->device reference.
To keep things simple, we take the reference nevertheless.

Jay Fenlason wrote:
> there's no way for the core to tell cdev "this card is gone,
> kill any inbound transactions on it", while cdev holds the transaction
> open until userspace issues a SEND_RESPONSE ioctl, which may be a very,
> very long time.  But when it does, it calls fw_send_response(), which
> will dereference the card...
> 
> So how unhappy are we about userspace potentially holding a fw_card
> open forever?

While termination of inbound transcations at card removal could be
implemented, it is IMO not worth the effort.  Currently, the effect of
holding a reference of a card that has been removed is to block the
process that called the pci_remove of the card.  This is
  - either a user process ran by root.  Root can find and kill processes
    that have /dev/fw* open, if desired.
  - a kernel thread (which one?) in case of hot removal of a PCCard or
    ExpressCard.
The latter case could be a problem indeed.  firewire-core's card
shutdown and card release should probably be improved not to block in
shutdown, just to defer freeing of memory until release.

This is not a new problem though; the same already always happens with
the client->device->card without the need of inbound transactions or
other special conditions involved, other than the client not closing the
file.

Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
---
 drivers/firewire/core-cdev.c |    8 ++++++++
 1 file changed, 8 insertions(+)

Index: b/drivers/firewire/core-cdev.c
===================================================================
--- a/drivers/firewire/core-cdev.c
+++ b/drivers/firewire/core-cdev.c
@@ -628,6 +628,8 @@ static void release_request(struct clien
 		kfree(r->data);
 	else
 		fw_send_response(r->card, r->request, RCODE_CONFLICT_ERROR);
+
+	fw_card_put(r->card);
 	kfree(r);
 }
 
@@ -642,6 +644,9 @@ static void handle_request(struct fw_car
 	void *fcp_frame = NULL;
 	int ret;
 
+	/* card may be different from handler->client->device->card */
+	fw_card_get(card);
+
 	r = kmalloc(sizeof(*r), GFP_ATOMIC);
 	e = kmalloc(sizeof(*e), GFP_ATOMIC);
 	if (r == NULL || e == NULL)
@@ -687,6 +692,8 @@ static void handle_request(struct fw_car
 
 	if (!is_fcp_request(request))
 		fw_send_response(card, request, RCODE_CONFLICT_ERROR);
+
+	fw_card_put(card);
 }
 
 static void release_address_handler(struct client *client,
@@ -769,6 +776,7 @@ static int ioctl_send_response(struct cl
 	}
 	fw_send_response(r->card, r->request, a->rcode);
  out:
+	fw_card_put(r->card);
 	kfree(r);
 
 	return ret;

-- 
Stefan Richter
-=====-==-=- -==- =-=--
http://arcgraph.de/sr/


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 5/8] firewire: cdev: freeze FW_CDEV_VERSION due to libraw1394 bug
  2010-06-20 20:49 [PATCH 0/8] firewire: cdev ABI updates Stefan Richter
                   ` (3 preceding siblings ...)
  2010-06-20 20:52 ` [PATCH 4/8] firewire: cdev: count references of cards during inbound transactions Stefan Richter
@ 2010-06-20 20:52 ` Stefan Richter
  2010-06-20 20:53 ` [PATCH 6/8] firewire: expose extended tcode of incoming lock requests to (userspace) drivers Stefan Richter
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Stefan Richter @ 2010-06-20 20:52 UTC (permalink / raw)
  To: linux1394-devel; +Cc: linux-kernel

libraw1394 v2.0.0...v2.0.5 takes FW_CDEV_VERSION from an externally
installed header file and uses it to declare its own implementation
level in FW_CDEV_IOC_GET_INFO.  This is wrong; it should set the real
version for which it was actually written.

If we add features to the kernel ABI that require the kernel to check
a client's implementation level, we can not trust the client version if
it was set from FW_CDEV_VERSION.

Hence freeze FW_CDEV_VERSION at the current value (no damage has been
done yet), clearly document FW_CDEV_VERSION as a dummy version and what
clients are expected to do with fw_cdev_get_info.version, and use a new
defined constant (which is not placed into the exported header file) as
kernel implementation level.

Note, in order to check in client program source code which features are
present in an externally installed linux/firewire-cdev.h, use
preprocessor directives like
  #ifdef FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE
or
  #ifdef FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED
instead of a check of FW_CDEV_VERSION.

Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
---
 drivers/firewire/core-cdev.c  |    7 ++++++-
 include/linux/firewire-cdev.h |   22 ++++++++++++++++------
 2 files changed, 22 insertions(+), 7 deletions(-)

Index: b/drivers/firewire/core-cdev.c
===================================================================
--- a/drivers/firewire/core-cdev.c
+++ b/drivers/firewire/core-cdev.c
@@ -47,6 +47,11 @@
 
 #include "core.h"
 
+/*
+ * ABI version history is documented in linux/firewire-cdev.h.
+ */
+#define FW_CDEV_KERNEL_VERSION 3
+
 struct client {
 	u32 version;
 	struct fw_device *device;
@@ -396,7 +401,7 @@ static int ioctl_get_info(struct client 
 	unsigned long ret = 0;
 
 	client->version = a->version;
-	a->version = FW_CDEV_VERSION;
+	a->version = FW_CDEV_KERNEL_VERSION;
 	a->card = client->device->card->index;
 
 	down_read(&fw_device_rwsem);
Index: b/include/linux/firewire-cdev.h
===================================================================
--- a/include/linux/firewire-cdev.h
+++ b/include/linux/firewire-cdev.h
@@ -224,7 +224,7 @@ union fw_cdev_event {
 	struct fw_cdev_event_response		response;
 	struct fw_cdev_event_request		request;
 	struct fw_cdev_event_iso_interrupt	iso_interrupt;
-	struct fw_cdev_event_iso_resource	iso_resource;
+	struct fw_cdev_event_iso_resource	iso_resource; /* added in 2.6.30 */
 };
 
 /* available since kernel version 2.6.22 */
@@ -257,22 +257,32 @@ union fw_cdev_event {
 #define FW_CDEV_IOC_GET_CYCLE_TIMER2   _IOWR('#', 0x14, struct fw_cdev_get_cycle_timer2)
 
 /*
- * FW_CDEV_VERSION History
+ * ABI version history
  *  1  (2.6.22)  - initial version
+ *     (2.6.24)  - added %FW_CDEV_IOC_GET_CYCLE_TIMER
  *  2  (2.6.30)  - changed &fw_cdev_event_iso_interrupt.header if
  *                 &fw_cdev_create_iso_context.header_size is 8 or more
+ *               - added %FW_CDEV_IOC_*_ISO_RESOURCE*,
+ *                 %FW_CDEV_IOC_GET_SPEED, %FW_CDEV_IOC_SEND_BROADCAST_REQUEST,
+ *                 %FW_CDEV_IOC_SEND_STREAM_PACKET
  *     (2.6.32)  - added time stamp to xmit &fw_cdev_event_iso_interrupt
  *     (2.6.33)  - IR has always packet-per-buffer semantics now, not one of
  *                 dual-buffer or packet-per-buffer depending on hardware
  *  3  (2.6.34)  - made &fw_cdev_get_cycle_timer reliable
+ *               - added %FW_CDEV_IOC_GET_CYCLE_TIMER2
  */
-#define FW_CDEV_VERSION 3
+#define FW_CDEV_VERSION 3 /* Meaningless; don't use this macro. */
 
 /**
  * struct fw_cdev_get_info - General purpose information ioctl
- * @version:	The version field is just a running serial number.
- *		We never break backwards compatibility, but may add more
- *		structs and ioctls in later revisions.
+ * @version:	The version field is just a running serial number.  Both an
+ *		input parameter (ABI version implemented by the client) and
+ *		output parameter (ABI version implemented by the kernel).
+ *		A client must not fill in an %FW_CDEV_VERSION defined from an
+ *		included kernel header file but the actual version for which
+ *		the client was implemented.  This is necessary for forward
+ *		compatibility.  We never break backwards compatibility, but
+ *		may add more structs, events, and ioctls in later revisions.
  * @rom_length:	If @rom is non-zero, at most rom_length bytes of configuration
  *		ROM will be copied into that user space address.  In either
  *		case, @rom_length is updated with the actual length of the

-- 
Stefan Richter
-=====-==-=- -==- =-=--
http://arcgraph.de/sr/


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 6/8] firewire: expose extended tcode of incoming lock requests to (userspace) drivers
  2010-06-20 20:49 [PATCH 0/8] firewire: cdev ABI updates Stefan Richter
                   ` (4 preceding siblings ...)
  2010-06-20 20:52 ` [PATCH 5/8] firewire: cdev: freeze FW_CDEV_VERSION due to libraw1394 bug Stefan Richter
@ 2010-06-20 20:53 ` Stefan Richter
  2010-06-20 20:53 ` [PATCH 7/8] firewire: cdev: fix ABI for FCP and address range mapping, add fw_cdev_event_request2 Stefan Richter
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Stefan Richter @ 2010-06-20 20:53 UTC (permalink / raw)
  To: linux1394-devel; +Cc: linux-kernel

Date: Tue, 18 May 2010 10:57:33 -0400
From: Jay Fenlason <fenlason@redhat.com>

When a remote device does a LOCK_REQUEST, the core does not pass
the extended tcode to userspace.  This patch makes it use the
juju-specific tcodes listed in firewire-constants.h for incoming
requests.

Signed-off-by: Jay Fenlason <fenlason@redhat.com>

This matches how tcode in the API for outbound requests is treated.
Affects kernelspace and userspace drivers alike, but at the moment there
are no kernespace drivers that receive lock requests.

Split out from a combo patch, slightly reordered, changelog reworded.

Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
---
 drivers/firewire/core-transaction.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

Index: b/drivers/firewire/core-transaction.c
===================================================================
--- a/drivers/firewire/core-transaction.c
+++ b/drivers/firewire/core-transaction.c
@@ -780,9 +780,11 @@ static void handle_exclusive_region_requ
 	unsigned long flags;
 	int tcode, destination, source;
 
-	tcode       = HEADER_GET_TCODE(p->header[0]);
 	destination = HEADER_GET_DESTINATION(p->header[0]);
 	source      = HEADER_GET_SOURCE(p->header[1]);
+	tcode       = HEADER_GET_TCODE(p->header[0]);
+	if (tcode == TCODE_LOCK_REQUEST)
+		tcode = 0x10 + HEADER_GET_EXTENDED_TCODE(p->header[3]);
 
 	spin_lock_irqsave(&address_handler_lock, flags);
 	handler = lookup_enclosing_address_handler(&address_handler_list,

-- 
Stefan Richter
-=====-==-=- -==- =-=--
http://arcgraph.de/sr/


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 7/8] firewire: cdev: fix ABI for FCP and address range mapping, add fw_cdev_event_request2
  2010-06-20 20:49 [PATCH 0/8] firewire: cdev ABI updates Stefan Richter
                   ` (5 preceding siblings ...)
  2010-06-20 20:53 ` [PATCH 6/8] firewire: expose extended tcode of incoming lock requests to (userspace) drivers Stefan Richter
@ 2010-06-20 20:53 ` Stefan Richter
  2010-06-20 20:54 ` [PATCH 8/8] firewire: cdev: extend fw_cdev_event_iso_interrupt documentation Stefan Richter
  2010-06-20 21:48 ` [PATCH 0/8] firewire: cdev ABI updates Stefan Richter
  8 siblings, 0 replies; 10+ messages in thread
From: Stefan Richter @ 2010-06-20 20:53 UTC (permalink / raw)
  To: linux1394-devel; +Cc: linux-kernel

The problem:

A target-like userspace driver, e.g. AV/C target or SBP-2/3 target,
needs to be able to act as responder and requester.  In the latter role,
it needs to send requests to nods from which it received requests.  This
is currently impossible because fw_cdev_event_request lacks information
about sender node ID.
Reported-by: Jay Fenlason <fenlason@redhat.com>

Libffado + libraw1394 + firewire-core is currently unable to drive two
or more audio devices on the same bus.
Reported-by: Arnold Krille <arnold@arnoldarts.de>

This is because libffado requires destination node ID of FCP requests
and sender node ID of FCP responses to match.  It even prohibits
libffado from working with a bus on which libraw1394 opens a /dev/fw* as
default ioctl device that does not correspond with the audio device.
This is because libraw1394 does not receive the sender node ID from the
kernel.

Moreover, fw_cdev_event_request makes it impossible to tell unicast and
broadcast write requests apart.

The fix:

Add a replacement of struct fw_cdev_event_request request, boringly
called struct fw_cdev_event_request2.  The new event will be sent to a
userspace client instead of the old one if the client claims
compatibility with <linux/firewire-cdev.h> ABI version 4 or later.

libraw1394 needs to be extended to make use of the new event, in order
to properly support libffado and other FCP or address range mapping
users who require correct sender node IDs.

Further notes:

While we are at it, change back the range of possible values of
fw_cdev_event_request.tcode to 0x0...0xb like in ABI version <= 3.
The preceding change "firewire: expose extended tcode of incoming lock
requests to (userspace) drivers" expanded it to 0x0...0x17 which could
catch sloppily coded clients by surprise.  The extended range of codes
is only used in the new fw_cdev_event_request2.tcode.

Jay and I also suggested an alternative approach to fix the ABI for
incoming requests:  Add an FW_CDEV_IOC_GET_REQUEST_INFO ioctl which can
be called after reception of an fw_cdev_event_request, before issuing of
the closing FW_CDEV_IOC_SEND_RESPONSE ioctl.  The new ioctl would reveal
the vital information about a request that fw_cdev_event_request lacks.
Jay showed an implementation of this approach.

The former event approach adds 27 LOC of rather trivial code to
core-cdev.c, the ioctl approach 34 LOC, some of which is nontrivial.
The ioctl approach would certainly also add more LOC to userspace
programs which require the expanded information on inbound requests.
This approach is probably only on the lighter-weight side in case of
clients that want to be compatible with kernels that lack the new
capability, like libraw1394.  However, the code to be added to such
libraw1394-like clients in case of the event approach is a straight-
forward additional switch () case in its event handler.

Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
---
 drivers/firewire/core-cdev.c  |   45 ++++++++++++++++----
 include/linux/firewire-cdev.h |   76 +++++++++++++++++++++++++++++++++-
 2 files changed, 110 insertions(+), 11 deletions(-)

Index: b/drivers/firewire/core-cdev.c
===================================================================
--- a/drivers/firewire/core-cdev.c
+++ b/drivers/firewire/core-cdev.c
@@ -50,7 +50,8 @@
 /*
  * ABI version history is documented in linux/firewire-cdev.h.
  */
-#define FW_CDEV_KERNEL_VERSION 3
+#define FW_CDEV_KERNEL_VERSION		4
+#define FW_CDEV_VERSION_EVENT_REQUEST2	4
 
 struct client {
 	u32 version;
@@ -177,7 +178,10 @@ struct outbound_transaction_event {
 
 struct inbound_transaction_event {
 	struct event event;
-	struct fw_cdev_event_request request;
+	union {
+		struct fw_cdev_event_request request;
+		struct fw_cdev_event_request2 request2;
+	} req;
 };
 
 struct iso_interrupt_event {
@@ -646,6 +650,7 @@ static void handle_request(struct fw_car
 	struct address_handler_resource *handler = callback_data;
 	struct inbound_transaction_resource *r;
 	struct inbound_transaction_event *e;
+	size_t event_size0;
 	void *fcp_frame = NULL;
 	int ret;
 
@@ -679,15 +684,37 @@ static void handle_request(struct fw_car
 	if (ret < 0)
 		goto failed;
 
-	e->request.type    = FW_CDEV_EVENT_REQUEST;
-	e->request.tcode   = tcode;
-	e->request.offset  = offset;
-	e->request.length  = length;
-	e->request.handle  = r->resource.handle;
-	e->request.closure = handler->closure;
+	if (handler->client->version < FW_CDEV_VERSION_EVENT_REQUEST2) {
+		struct fw_cdev_event_request *req = &e->req.request;
+
+		if (tcode & 0x10)
+			tcode = TCODE_LOCK_REQUEST;
+
+		req->type	= FW_CDEV_EVENT_REQUEST;
+		req->tcode	= tcode;
+		req->offset	= offset;
+		req->length	= length;
+		req->handle	= r->resource.handle;
+		req->closure	= handler->closure;
+		event_size0	= sizeof(*req);
+	} else {
+		struct fw_cdev_event_request2 *req = &e->req.request2;
+
+		req->type	= FW_CDEV_EVENT_REQUEST2;
+		req->tcode	= tcode;
+		req->offset	= offset;
+		req->source_node_id = source;
+		req->destination_node_id = destination;
+		req->card	= card->index;
+		req->generation	= generation;
+		req->length	= length;
+		req->handle	= r->resource.handle;
+		req->closure	= handler->closure;
+		event_size0	= sizeof(*req);
+	}
 
 	queue_event(handler->client, &e->event,
-		    &e->request, sizeof(e->request), r->data, length);
+		    &e->req, event_size0, r->data, length);
 	return;
 
  failed:
Index: b/include/linux/firewire-cdev.h
===================================================================
--- a/include/linux/firewire-cdev.h
+++ b/include/linux/firewire-cdev.h
@@ -37,6 +37,9 @@
 #define FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED	0x04
 #define FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED	0x05
 
+/* available since kernel version 2.6.36 */
+#define FW_CDEV_EVENT_REQUEST2			0x06
+
 /**
  * struct fw_cdev_event_common - Common part of all fw_cdev_event_ types
  * @closure:	For arbitrary use by userspace
@@ -103,11 +106,46 @@ struct fw_cdev_event_response {
 };
 
 /**
- * struct fw_cdev_event_request - Sent on incoming request to an address region
+ * struct fw_cdev_event_request - Old version of &fw_cdev_event_request2
  * @closure:	See &fw_cdev_event_common; set by %FW_CDEV_IOC_ALLOCATE ioctl
  * @type:	See &fw_cdev_event_common; always %FW_CDEV_EVENT_REQUEST
+ * @tcode:	See &fw_cdev_event_request2
+ * @offset:	See &fw_cdev_event_request2
+ * @handle:	See &fw_cdev_event_request2
+ * @length:	See &fw_cdev_event_request2
+ * @data:	See &fw_cdev_event_request2
+ *
+ * This event is sent instead of &fw_cdev_event_request2 if the kernel or
+ * the client implements ABI version <= 3.
+ *
+ * Unlike &fw_cdev_event_request2, the sender identity cannot be established,
+ * broadcast write requests cannot be distinguished from unicast writes, and
+ * @tcode of lock requests is %TCODE_LOCK_REQUEST.
+ *
+ * Requests to the FCP_REQUEST or FCP_RESPONSE register are responded to as
+ * with &fw_cdev_event_request2, except in kernel 2.6.32 and older which send
+ * the response packet of the client's %FW_CDEV_IOC_SEND_RESPONSE ioctl.
+ */
+struct fw_cdev_event_request {
+	__u64 closure;
+	__u32 type;
+	__u32 tcode;
+	__u64 offset;
+	__u32 handle;
+	__u32 length;
+	__u32 data[0];
+};
+
+/**
+ * struct fw_cdev_event_request2 - Sent on incoming request to an address region
+ * @closure:	See &fw_cdev_event_common; set by %FW_CDEV_IOC_ALLOCATE ioctl
+ * @type:	See &fw_cdev_event_common; always %FW_CDEV_EVENT_REQUEST2
  * @tcode:	Transaction code of the incoming request
  * @offset:	The offset into the 48-bit per-node address space
+ * @source_node_id: Sender node ID
+ * @destination_node_id: Destination node ID
+ * @card:	The index of the card from which the request came
+ * @generation:	Bus generation in which the request is valid
  * @handle:	Reference to the kernel-side pending request
  * @length:	Data length, i.e. the request's payload size in bytes
  * @data:	Incoming data, if any
@@ -120,12 +158,42 @@ struct fw_cdev_event_response {
  *
  * The payload data for requests carrying data (write and lock requests)
  * follows immediately and can be accessed through the @data field.
+ *
+ * Unlike &fw_cdev_event_request, @tcode of lock requests is one of the
+ * firewire-core specific %TCODE_LOCK_MASK_SWAP...%TCODE_LOCK_VENDOR_DEPENDENT,
+ * i.e. encodes the extended transaction code.
+ *
+ * @card may differ from &fw_cdev_get_info.card because requests are received
+ * from all cards of the Linux host.  @source_node_id, @destination_node_id, and
+ * @generation pertain to that card.  Destination node ID and bus generation may
+ * therefore differ from the corresponding fields of the last
+ * &fw_cdev_event_bus_reset.
+ *
+ * @destination_node_id may also differ from the current node ID because of a
+ * non-local bus ID part or in case of a broadcast write request.  Note, a
+ * client must call an %FW_CDEV_IOC_SEND_RESPONSE ioctl even in case of a
+ * broadcast write request; the kernel will then release the kernel-side pending
+ * request but will not actually send a response packet.
+ *
+ * In case of a write request to FCP_REQUEST or FCP_RESPONSE, the kernel already
+ * sent a write response immediately after the request was received; in this
+ * case the client must still call an %FW_CDEV_IOC_SEND_RESPONSE ioctl to
+ * release the kernel-side pending request, though another response won't be
+ * sent.
+ *
+ * If the client subsequently needs to initiate requests to the sender node of
+ * an &fw_cdev_event_request2, it needs to use a device file with matching
+ * card index, node ID, and generation for outbound requests.
  */
-struct fw_cdev_event_request {
+struct fw_cdev_event_request2 {
 	__u64 closure;
 	__u32 type;
 	__u32 tcode;
 	__u64 offset;
+	__u32 source_node_id;
+	__u32 destination_node_id;
+	__u32 card;
+	__u32 generation;
 	__u32 handle;
 	__u32 length;
 	__u32 data[0];
@@ -205,6 +273,7 @@ struct fw_cdev_event_iso_resource {
  * @bus_reset:     Valid if @common.type == %FW_CDEV_EVENT_BUS_RESET
  * @response:      Valid if @common.type == %FW_CDEV_EVENT_RESPONSE
  * @request:       Valid if @common.type == %FW_CDEV_EVENT_REQUEST
+ * @request2:      Valid if @common.type == %FW_CDEV_EVENT_REQUEST2
  * @iso_interrupt: Valid if @common.type == %FW_CDEV_EVENT_ISO_INTERRUPT
  * @iso_resource:  Valid if @common.type ==
  *				%FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED or
@@ -223,6 +292,7 @@ union fw_cdev_event {
 	struct fw_cdev_event_bus_reset		bus_reset;
 	struct fw_cdev_event_response		response;
 	struct fw_cdev_event_request		request;
+	struct fw_cdev_event_request2		request2;     /* added in 2.6.36 */
 	struct fw_cdev_event_iso_interrupt	iso_interrupt;
 	struct fw_cdev_event_iso_resource	iso_resource; /* added in 2.6.30 */
 };
@@ -268,8 +338,10 @@ union fw_cdev_event {
  *     (2.6.32)  - added time stamp to xmit &fw_cdev_event_iso_interrupt
  *     (2.6.33)  - IR has always packet-per-buffer semantics now, not one of
  *                 dual-buffer or packet-per-buffer depending on hardware
+ *               - shared use and auto-response for FCP registers
  *  3  (2.6.34)  - made &fw_cdev_get_cycle_timer reliable
  *               - added %FW_CDEV_IOC_GET_CYCLE_TIMER2
+ *  4  (2.6.36)  - added %FW_CDEV_EVENT_REQUEST2
  */
 #define FW_CDEV_VERSION 3 /* Meaningless; don't use this macro. */
 

-- 
Stefan Richter
-=====-==-=- -==- =-=--
http://arcgraph.de/sr/


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 8/8] firewire: cdev: extend fw_cdev_event_iso_interrupt documentation
  2010-06-20 20:49 [PATCH 0/8] firewire: cdev ABI updates Stefan Richter
                   ` (6 preceding siblings ...)
  2010-06-20 20:53 ` [PATCH 7/8] firewire: cdev: fix ABI for FCP and address range mapping, add fw_cdev_event_request2 Stefan Richter
@ 2010-06-20 20:54 ` Stefan Richter
  2010-06-20 21:48 ` [PATCH 0/8] firewire: cdev ABI updates Stefan Richter
  8 siblings, 0 replies; 10+ messages in thread
From: Stefan Richter @ 2010-06-20 20:54 UTC (permalink / raw)
  To: linux1394-devel; +Cc: linux-kernel

Add information regarding the 2.6.32 update to the xmit variant of
fw_cdev_event_iso_interrupt.

Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
---
 include/linux/firewire-cdev.h |   19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

Index: b/include/linux/firewire-cdev.h
===================================================================
--- a/include/linux/firewire-cdev.h
+++ b/include/linux/firewire-cdev.h
@@ -209,10 +209,21 @@ struct fw_cdev_event_request2 {
  * @header:	Stripped headers, if any
  *
  * This event is sent when the controller has completed an &fw_cdev_iso_packet
- * with the %FW_CDEV_ISO_INTERRUPT bit set.  In the receive case, the headers
- * stripped of all packets up until and including the interrupt packet are
- * returned in the @header field.  The amount of header data per packet is as
- * specified at iso context creation by &fw_cdev_create_iso_context.header_size.
+ * with the %FW_CDEV_ISO_INTERRUPT bit set.
+ *
+ * Isochronous transmit events:
+ *
+ * In version 1 of the ABI, &header_length is 0.  In version 3 and some
+ * implementations of version 2 of the ABI, &header_length is a multiple of 4
+ * and &header contains timestamps of all packets up until the interrupt packet.
+ * The format of the timestamps is as described below for isochronous reception.
+ *
+ * Isochronous receive events:
+ *
+ * The headers stripped of all packets up until and including the interrupt
+ * packet are returned in the @header field.  The amount of header data per
+ * packet is as specified at iso context creation by
+ * &fw_cdev_create_iso_context.header_size.
  *
  * In version 1 of this ABI, header data consisted of the 1394 isochronous
  * packet header, followed by quadlets from the packet payload if

-- 
Stefan Richter
-=====-==-=- -==- =-=--
http://arcgraph.de/sr/


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/8] firewire: cdev ABI updates
  2010-06-20 20:49 [PATCH 0/8] firewire: cdev ABI updates Stefan Richter
                   ` (7 preceding siblings ...)
  2010-06-20 20:54 ` [PATCH 8/8] firewire: cdev: extend fw_cdev_event_iso_interrupt documentation Stefan Richter
@ 2010-06-20 21:48 ` Stefan Richter
  8 siblings, 0 replies; 10+ messages in thread
From: Stefan Richter @ 2010-06-20 21:48 UTC (permalink / raw)
  To: linux1394-devel; +Cc: linux-kernel

On 20 Jun, Stefan Richter wrote:
> Following as replies:  Proposed updates to the <linux/firewire-cdev.h>
> ABI and to its backing implementation.  These updates are required for
> target-type userspace drivers and in order to be able to use more than
> one audio device with FFADO.
> 
> Some of the patches have already been seen on linux1394-devel but not
> yet on linux-kernel.
> 
> Corresponding patches to libraw1394 will be posted to linux1394-devel
> right after the kernel patch postings.

The patches have been committed to a temporary branch called "testing"
at the firewire drivers development repository:

    git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6.git testing

    gitweb:
    http://git.kernel.org/?p=linux/kernel/git/ieee1394/linux1394-2.6.git;a=shortlog;h=refs/heads/testing

This branch may be rebuild or deleted in case of negative feedback about
the proposed patches.

The patches are also available as quilt series and combo patches in my
backports to a few stable kernel series at

    http://user.in-berlin.de/~s5r6/linux1394/updates/

The corresponding libraw1394 patches are available at the libraw1394
mirror repository, also in a "testing" branch:

    git://git.kernel.org/pub/scm/libs/ieee1394/libraw1394.git testing

    gitweb:
    http://git.kernel.org/?p=libs/ieee1394/libraw1394.git;a=shortlog;h=refs/heads/testing

Would be good if a FFADO developer with two or more audio devices could
give this a run.
-- 
Stefan Richter
-=====-==-=- -==- =-=--
http://arcgraph.de/sr/


^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2010-06-20 21:49 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-06-20 20:49 [PATCH 0/8] firewire: cdev ABI updates Stefan Richter
2010-06-20 20:50 ` [PATCH 1/8] firewire: remove an unused function argument Stefan Richter
2010-06-20 20:51 ` [PATCH 2/8] firewire: cdev: fix race in iso context creation Stefan Richter
2010-06-20 20:51 ` [PATCH 3/8] firewire: cdev: fix responses to nodes at different card Stefan Richter
2010-06-20 20:52 ` [PATCH 4/8] firewire: cdev: count references of cards during inbound transactions Stefan Richter
2010-06-20 20:52 ` [PATCH 5/8] firewire: cdev: freeze FW_CDEV_VERSION due to libraw1394 bug Stefan Richter
2010-06-20 20:53 ` [PATCH 6/8] firewire: expose extended tcode of incoming lock requests to (userspace) drivers Stefan Richter
2010-06-20 20:53 ` [PATCH 7/8] firewire: cdev: fix ABI for FCP and address range mapping, add fw_cdev_event_request2 Stefan Richter
2010-06-20 20:54 ` [PATCH 8/8] firewire: cdev: extend fw_cdev_event_iso_interrupt documentation Stefan Richter
2010-06-20 21:48 ` [PATCH 0/8] firewire: cdev ABI updates Stefan Richter

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.