mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 0/6] DVB: firedtv: simplifications and a portability fix
@ 2009-11-18 19:00 Stefan Richter
  2009-11-18 19:00 ` [PATCH 1/6] firedtv: shrink buffer pointer table Stefan Richter
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: Stefan Richter @ 2009-11-18 19:00 UTC (permalink / raw)
  To: linux-media; +Cc: linux1394-devel, linux-kernel

The following three patches are applicable after "firedtv: port to new
firewire core" from 2009-11-08:

[PATCH 1/6] firedtv: shrink buffer pointer table
[PATCH 2/6] firedtv: packet requeuing is likely to succeed
[PATCH 3/6] firedtv: remove an unnecessary function argument

The rest of this patch set additionally requires the latest firedtv as
of 2.6.32-rc7:

[PATCH 4/6] firedtv: do not DMA-map stack addresses
[PATCH 5/6] firedtv: remove check for interrupting signal
[PATCH 6/6] firedtv: reduce memset()s

 drivers/media/dvb/firewire/firedtv-1394.c |   13
 drivers/media/dvb/firewire/firedtv-avc.c  |  520 +++++++++++-----------
 drivers/media/dvb/firewire/firedtv-dvb.c  |    1
 drivers/media/dvb/firewire/firedtv-fw.c   |   39 -
 drivers/media/dvb/firewire/firedtv.h      |    8
 5 files changed, 306 insertions(+), 275 deletions(-)
-- 
Stefan Richter
-=====-==--= =-== =--=-
http://arcgraph.de/sr/


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

* [PATCH 1/6] firedtv: shrink buffer pointer table
  2009-11-18 19:00 [PATCH 0/6] DVB: firedtv: simplifications and a portability fix Stefan Richter
@ 2009-11-18 19:00 ` Stefan Richter
  2009-11-18 19:01 ` [PATCH 2/6] firedtv: packet requeuing is likely to succeed Stefan Richter
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Stefan Richter @ 2009-11-18 19:00 UTC (permalink / raw)
  To: linux-media; +Cc: linux1394-devel, linux-kernel

Cache only addresses of whole pages, not of each buffer chunk.  Besides,
page addresses can be obtained by page_address() instead of kmap() since
they were allocated in lowmem.

Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
---
 drivers/media/dvb/firewire/firedtv-fw.c |   19 ++++++++-----------
 1 file changed, 8 insertions(+), 11 deletions(-)

Index: linux-2.6.32-rc7/drivers/media/dvb/firewire/firedtv-fw.c
===================================================================
--- linux-2.6.32-rc7.orig/drivers/media/dvb/firewire/firedtv-fw.c
+++ linux-2.6.32-rc7/drivers/media/dvb/firewire/firedtv-fw.c
@@ -6,9 +6,9 @@
 #include <linux/errno.h>
 #include <linux/firewire.h>
 #include <linux/firewire-constants.h>
-#include <linux/highmem.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
+#include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
@@ -73,7 +73,7 @@ struct firedtv_receive_context {
 	struct fw_iso_buffer buffer;
 	int interrupt_packet;
 	int current_packet;
-	char *packets[N_PACKETS];
+	char *pages[N_PAGES];
 };
 
 static int queue_iso(struct firedtv_receive_context *ctx, int index)
@@ -100,7 +100,7 @@ static void handle_iso(struct fw_iso_con
 	struct firedtv *fdtv = data;
 	struct firedtv_receive_context *ctx = fdtv->backend_data;
 	__be32 *h, *h_end;
-	int i = ctx->current_packet, length, err;
+	int length, err, i = ctx->current_packet;
 	char *p, *p_end;
 
 	for (h = header, h_end = h + header_length / 4; h < h_end; h++) {
@@ -110,7 +110,8 @@ static void handle_iso(struct fw_iso_con
 			length = MAX_PACKET_SIZE;
 		}
 
-		p = ctx->packets[i];
+		p = ctx->pages[i / PACKETS_PER_PAGE]
+				+ (i % PACKETS_PER_PAGE) * MAX_PACKET_SIZE;
 		p_end = p + length;
 
 		for (p += CIP_HEADER_SIZE + MPEG2_TS_HEADER_SIZE; p < p_end;
@@ -130,8 +131,7 @@ static int start_iso(struct firedtv *fdt
 {
 	struct firedtv_receive_context *ctx;
 	struct fw_device *device = device_of(fdtv);
-	char *p;
-	int i, j, k, err;
+	int i, err;
 
 	ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
 	if (!ctx)
@@ -153,11 +153,8 @@ static int start_iso(struct firedtv *fdt
 	ctx->interrupt_packet = 1;
 	ctx->current_packet = 0;
 
-	for (i = 0, k = 0; k < N_PAGES; k++) {
-		p = kmap(ctx->buffer.pages[k]);
-		for (j = 0; j < PACKETS_PER_PAGE && i < N_PACKETS; j++, i++)
-			ctx->packets[i] = p + j * MAX_PACKET_SIZE;
-	}
+	for (i = 0; i < N_PAGES; i++)
+		ctx->pages[i] = page_address(ctx->buffer.pages[i]);
 
 	for (i = 0; i < N_PACKETS; i++) {
 		err = queue_iso(ctx, i);

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


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

* [PATCH 2/6] firedtv: packet requeuing is likely to succeed
  2009-11-18 19:00 [PATCH 0/6] DVB: firedtv: simplifications and a portability fix Stefan Richter
  2009-11-18 19:00 ` [PATCH 1/6] firedtv: shrink buffer pointer table Stefan Richter
@ 2009-11-18 19:01 ` Stefan Richter
  2009-11-18 19:01 ` [PATCH 3/6] firedtv: remove an unnecessary function argument Stefan Richter
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Stefan Richter @ 2009-11-18 19:01 UTC (permalink / raw)
  To: linux-media; +Cc: linux1394-devel, linux-kernel

Packet DMA buffers are queued either initially all at once (then, a
queueing failure will cause firedtv to release the DMA context as a
whole) or subsequently one by one as they recycled after use (then a
failure is extremely unlikely).  Therefore we can be a little less
cautious when counting at which packet buffer to set the interrupt flag.

Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
---
 drivers/media/dvb/firewire/firedtv-fw.c |   13 ++++---------
 1 file changed, 4 insertions(+), 9 deletions(-)

Index: linux-2.6.32-rc7/drivers/media/dvb/firewire/firedtv-fw.c
===================================================================
--- linux-2.6.32-rc7.orig/drivers/media/dvb/firewire/firedtv-fw.c
+++ linux-2.6.32-rc7/drivers/media/dvb/firewire/firedtv-fw.c
@@ -79,19 +79,14 @@ struct firedtv_receive_context {
 static int queue_iso(struct firedtv_receive_context *ctx, int index)
 {
 	struct fw_iso_packet p;
-	int err;
 
 	p.payload_length = MAX_PACKET_SIZE;
-	p.interrupt = !(ctx->interrupt_packet & (IRQ_INTERVAL - 1));
+	p.interrupt = !(++ctx->interrupt_packet & (IRQ_INTERVAL - 1));
 	p.skip = 0;
 	p.header_length = ISO_HEADER_SIZE;
 
-	err = fw_iso_context_queue(ctx->context, &p, &ctx->buffer,
-				   index * MAX_PACKET_SIZE);
-	if (!err)
-		ctx->interrupt_packet++;
-
-	return err;
+	return fw_iso_context_queue(ctx->context, &p, &ctx->buffer,
+				    index * MAX_PACKET_SIZE);
 }
 
 static void handle_iso(struct fw_iso_context *context, u32 cycle,
@@ -150,7 +145,7 @@ static int start_iso(struct firedtv *fdt
 	if (err)
 		goto fail_context_destroy;
 
-	ctx->interrupt_packet = 1;
+	ctx->interrupt_packet = 0;
 	ctx->current_packet = 0;
 
 	for (i = 0; i < N_PAGES; i++)

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


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

* [PATCH 3/6] firedtv: remove an unnecessary function argument
  2009-11-18 19:00 [PATCH 0/6] DVB: firedtv: simplifications and a portability fix Stefan Richter
  2009-11-18 19:00 ` [PATCH 1/6] firedtv: shrink buffer pointer table Stefan Richter
  2009-11-18 19:01 ` [PATCH 2/6] firedtv: packet requeuing is likely to succeed Stefan Richter
@ 2009-11-18 19:01 ` Stefan Richter
  2009-11-18 19:02 ` [PATCH 4/6] firedtv: do not DMA-map stack addresses Stefan Richter
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Stefan Richter @ 2009-11-18 19:01 UTC (permalink / raw)
  To: linux-media; +Cc: linux1394-devel, linux-kernel

All read transactions initiated by firedtv are only quadlet-sized, hence
the backend->read call can be simplified a little.

Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
---
 drivers/media/dvb/firewire/firedtv-1394.c |    4 ++--
 drivers/media/dvb/firewire/firedtv-avc.c  |    8 ++++----
 drivers/media/dvb/firewire/firedtv-fw.c   |    5 ++---
 drivers/media/dvb/firewire/firedtv.h      |    2 +-
 4 files changed, 9 insertions(+), 10 deletions(-)

Index: linux-2.6.32-rc7/drivers/media/dvb/firewire/firedtv-1394.c
===================================================================
--- linux-2.6.32-rc7.orig/drivers/media/dvb/firewire/firedtv-1394.c
+++ linux-2.6.32-rc7/drivers/media/dvb/firewire/firedtv-1394.c
@@ -101,9 +101,9 @@ static int node_lock(struct firedtv *fdt
 	return ret;
 }
 
-static int node_read(struct firedtv *fdtv, u64 addr, void *data, size_t len)
+static int node_read(struct firedtv *fdtv, u64 addr, void *data)
 {
-	return hpsb_node_read(node_of(fdtv), addr, data, len);
+	return hpsb_node_read(node_of(fdtv), addr, data, 4);
 }
 
 static int node_write(struct firedtv *fdtv, u64 addr, void *data, size_t len)
Index: linux-2.6.32-rc7/drivers/media/dvb/firewire/firedtv-avc.c
===================================================================
--- linux-2.6.32-rc7.orig/drivers/media/dvb/firewire/firedtv-avc.c
+++ linux-2.6.32-rc7/drivers/media/dvb/firewire/firedtv-avc.c
@@ -1236,14 +1236,14 @@ int avc_ca_get_mmi(struct firedtv *fdtv,
 
 #define CMP_OUTPUT_PLUG_CONTROL_REG_0	0xfffff0000904ULL
 
-static int cmp_read(struct firedtv *fdtv, void *buf, u64 addr, size_t len)
+static int cmp_read(struct firedtv *fdtv, u64 addr, __be32 *data)
 {
 	int ret;
 
 	if (mutex_lock_interruptible(&fdtv->avc_mutex))
 		return -EINTR;
 
-	ret = fdtv->backend->read(fdtv, addr, buf, len);
+	ret = fdtv->backend->read(fdtv, addr, data);
 	if (ret < 0)
 		dev_err(fdtv->device, "CMP: read I/O error\n");
 
@@ -1293,7 +1293,7 @@ int cmp_establish_pp_connection(struct f
 	int attempts = 0;
 	int ret;
 
-	ret = cmp_read(fdtv, opcr, opcr_address, 4);
+	ret = cmp_read(fdtv, opcr_address, opcr);
 	if (ret < 0)
 		return ret;
 
@@ -1357,7 +1357,7 @@ void cmp_break_pp_connection(struct fire
 	u64 opcr_address = CMP_OUTPUT_PLUG_CONTROL_REG_0 + (plug << 2);
 	int attempts = 0;
 
-	if (cmp_read(fdtv, opcr, opcr_address, 4) < 0)
+	if (cmp_read(fdtv, opcr_address, opcr) < 0)
 		return;
 
 repeat:
Index: linux-2.6.32-rc7/drivers/media/dvb/firewire/firedtv-fw.c
===================================================================
--- linux-2.6.32-rc7.orig/drivers/media/dvb/firewire/firedtv-fw.c
+++ linux-2.6.32-rc7/drivers/media/dvb/firewire/firedtv-fw.c
@@ -46,10 +46,9 @@ static int node_lock(struct firedtv *fdt
 	return node_req(fdtv, addr, data, 8, TCODE_LOCK_COMPARE_SWAP);
 }
 
-static int node_read(struct firedtv *fdtv, u64 addr, void *data, size_t len)
+static int node_read(struct firedtv *fdtv, u64 addr, void *data)
 {
-	return node_req(fdtv, addr, data, len, len == 4 ?
-			TCODE_READ_QUADLET_REQUEST : TCODE_READ_BLOCK_REQUEST);
+	return node_req(fdtv, addr, data, 4, TCODE_READ_QUADLET_REQUEST);
 }
 
 static int node_write(struct firedtv *fdtv, u64 addr, void *data, size_t len)
Index: linux-2.6.32-rc7/drivers/media/dvb/firewire/firedtv.h
===================================================================
--- linux-2.6.32-rc7.orig/drivers/media/dvb/firewire/firedtv.h
+++ linux-2.6.32-rc7/drivers/media/dvb/firewire/firedtv.h
@@ -74,7 +74,7 @@ struct firedtv;
 
 struct firedtv_backend {
 	int (*lock)(struct firedtv *fdtv, u64 addr, __be32 data[]);
-	int (*read)(struct firedtv *fdtv, u64 addr, void *data, size_t len);
+	int (*read)(struct firedtv *fdtv, u64 addr, void *data);
 	int (*write)(struct firedtv *fdtv, u64 addr, void *data, size_t len);
 	int (*start_iso)(struct firedtv *fdtv);
 	void (*stop_iso)(struct firedtv *fdtv);

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


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

* [PATCH 4/6] firedtv: do not DMA-map stack addresses
  2009-11-18 19:00 [PATCH 0/6] DVB: firedtv: simplifications and a portability fix Stefan Richter
                   ` (2 preceding siblings ...)
  2009-11-18 19:01 ` [PATCH 3/6] firedtv: remove an unnecessary function argument Stefan Richter
@ 2009-11-18 19:02 ` Stefan Richter
  2009-11-18 19:03 ` [PATCH 5/6] firedtv: remove check for interrupting signal Stefan Richter
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Stefan Richter @ 2009-11-18 19:02 UTC (permalink / raw)
  To: linux-media; +Cc: linux1394-devel, linux-kernel

This is a portability fix and reduces stack usage.

The DMA mapping API cannot map on-stack addresses, as explained in
Documentation/DMA-mapping.txt.  Convert the two cases of on-stack packet
payload buffers in firedtv (payload of write requests in avc_write and
of lock requests in cmp_lock) to slab-allocated memory.

We use the 512 bytes sized FCP frame buffer in struct firedtv for this
purpose.  Previously it held only incoming FCP responses, now it holds
pending FCP requests and is then overwriten by an FCP response from the
tuner subunit.  Ditto for CMP lock requests and responses.  Accesses to
the payload buffer are serialized by fdtv->avc_mutex.

As a welcome side effect, stack usage of the AV/C transaction functions
is reduced by 512 bytes.

Alas, avc_register_remote_control() is a special case:  It previously
did not wait for a response.  To fit better in with the other FCP
transactions, let it wait for an interim response.

Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
---
 drivers/media/dvb/firewire/firedtv-1394.c |    9 +
 drivers/media/dvb/firewire/firedtv-avc.c  |  437 +++++++++++++---------
 drivers/media/dvb/firewire/firedtv-dvb.c  |    1 -
 drivers/media/dvb/firewire/firedtv-fw.c   |    2 
 drivers/media/dvb/firewire/firedtv.h      |    6 
 5 files changed, 264 insertions(+), 191 deletions(-)

Index: linux-2.6.32-rc7/drivers/media/dvb/firewire/firedtv-1394.c
===================================================================
--- linux-2.6.32-rc7.orig/drivers/media/dvb/firewire/firedtv-1394.c
+++ linux-2.6.32-rc7/drivers/media/dvb/firewire/firedtv-1394.c
@@ -90,13 +90,14 @@ static inline struct node_entry *node_of
 	return container_of(fdtv->device, struct unit_directory, device)->ne;
 }
 
-static int node_lock(struct firedtv *fdtv, u64 addr, __be32 data[])
+static int node_lock(struct firedtv *fdtv, u64 addr, void *data)
 {
+	quadlet_t *d = data;
 	int ret;
 
-	ret = hpsb_node_lock(node_of(fdtv), addr, EXTCODE_COMPARE_SWAP,
-		(__force quadlet_t *)&data[1], (__force quadlet_t)data[0]);
-	data[0] = data[1];
+	ret = hpsb_node_lock(node_of(fdtv), addr,
+			     EXTCODE_COMPARE_SWAP, &d[1], d[0]);
+	d[0] = d[1];
 
 	return ret;
 }
Index: linux-2.6.32-rc7/drivers/media/dvb/firewire/firedtv-avc.c
===================================================================
--- linux-2.6.32-rc7.orig/drivers/media/dvb/firewire/firedtv-avc.c
+++ linux-2.6.32-rc7/drivers/media/dvb/firewire/firedtv-avc.c
@@ -74,7 +74,6 @@
 #define EN50221_TAG_CA_INFO		0x9f8031
 
 struct avc_command_frame {
-	int length;
 	u8 ctype;
 	u8 subunit;
 	u8 opcode;
@@ -82,7 +81,6 @@ struct avc_command_frame {
 };
 
 struct avc_response_frame {
-	int length;
 	u8 response;
 	u8 subunit;
 	u8 opcode;
@@ -202,78 +200,65 @@ static void debug_pmt(char *msg, int len
 		       16, 1, msg, length, false);
 }
 
-static int __avc_write(struct firedtv *fdtv,
-		const struct avc_command_frame *c, struct avc_response_frame *r)
+static int avc_write(struct firedtv *fdtv)
 {
 	int err, retry;
 
-	if (r)
-		fdtv->avc_reply_received = false;
+	fdtv->avc_reply_received = false;
 
 	for (retry = 0; retry < 6; retry++) {
 		if (unlikely(avc_debug))
-			debug_fcp(&c->ctype, c->length);
+			debug_fcp(fdtv->avc_data, fdtv->avc_data_length);
 
 		err = fdtv->backend->write(fdtv, FCP_COMMAND_REGISTER,
-					   (void *)&c->ctype, c->length);
+				fdtv->avc_data, fdtv->avc_data_length);
 		if (err) {
-			fdtv->avc_reply_received = true;
 			dev_err(fdtv->device, "FCP command write failed\n");
+
 			return err;
 		}
 
-		if (!r)
-			return 0;
-
 		/*
 		 * AV/C specs say that answers should be sent within 150 ms.
 		 * Time out after 200 ms.
 		 */
 		if (wait_event_timeout(fdtv->avc_wait,
 				       fdtv->avc_reply_received,
-				       msecs_to_jiffies(200)) != 0) {
-			r->length = fdtv->response_length;
-			memcpy(&r->response, fdtv->response, r->length);
-
+				       msecs_to_jiffies(200)) != 0)
 			return 0;
-		}
 	}
 	dev_err(fdtv->device, "FCP response timed out\n");
+
 	return -ETIMEDOUT;
 }
 
-static int avc_write(struct firedtv *fdtv,
-		const struct avc_command_frame *c, struct avc_response_frame *r)
+static bool is_register_rc(struct avc_response_frame *r)
 {
-	int ret;
-
-	if (mutex_lock_interruptible(&fdtv->avc_mutex))
-		return -EINTR;
-
-	ret = __avc_write(fdtv, c, r);
-
-	mutex_unlock(&fdtv->avc_mutex);
-	return ret;
+	return r->opcode     == AVC_OPCODE_VENDOR &&
+	       r->operand[0] == SFE_VENDOR_DE_COMPANYID_0 &&
+	       r->operand[1] == SFE_VENDOR_DE_COMPANYID_1 &&
+	       r->operand[2] == SFE_VENDOR_DE_COMPANYID_2 &&
+	       r->operand[3] == SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL;
 }
 
 int avc_recv(struct firedtv *fdtv, void *data, size_t length)
 {
-	struct avc_response_frame *r =
-			data - offsetof(struct avc_response_frame, response);
+	struct avc_response_frame *r = data;
 
 	if (unlikely(avc_debug))
 		debug_fcp(data, length);
 
-	if (length >= 8 &&
-	    r->operand[0] == SFE_VENDOR_DE_COMPANYID_0 &&
-	    r->operand[1] == SFE_VENDOR_DE_COMPANYID_1 &&
-	    r->operand[2] == SFE_VENDOR_DE_COMPANYID_2 &&
-	    r->operand[3] == SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL) {
-		if (r->response == AVC_RESPONSE_CHANGED) {
-			fdtv_handle_rc(fdtv,
-			    r->operand[4] << 8 | r->operand[5]);
+	if (length >= 8 && is_register_rc(r)) {
+		switch (r->response) {
+		case AVC_RESPONSE_CHANGED:
+			fdtv_handle_rc(fdtv, r->operand[4] << 8 | r->operand[5]);
 			schedule_work(&fdtv->remote_ctrl_work);
-		} else if (r->response != AVC_RESPONSE_INTERIM) {
+			break;
+		case AVC_RESPONSE_INTERIM:
+			if (is_register_rc((void *)fdtv->avc_data))
+				goto wake;
+			break;
+		default:
 			dev_info(fdtv->device,
 				 "remote control result = %d\n", r->response);
 		}
@@ -285,9 +270,9 @@ int avc_recv(struct firedtv *fdtv, void 
 		return -EIO;
 	}
 
-	memcpy(fdtv->response, data, length);
-	fdtv->response_length = length;
-
+	memcpy(fdtv->avc_data, data, length);
+	fdtv->avc_data_length = length;
+wake:
 	fdtv->avc_reply_received = true;
 	wake_up(&fdtv->avc_wait);
 
@@ -319,9 +304,10 @@ static int add_pid_filter(struct firedtv
  * (not supported by the AVC standard)
  */
 static void avc_tuner_tuneqpsk(struct firedtv *fdtv,
-			       struct dvb_frontend_parameters *params,
-			       struct avc_command_frame *c)
+			       struct dvb_frontend_parameters *params)
 {
+	struct avc_command_frame *c = (void *)fdtv->avc_data;
+
 	c->opcode = AVC_OPCODE_VENDOR;
 
 	c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
@@ -370,16 +356,17 @@ static void avc_tuner_tuneqpsk(struct fi
 		c->operand[13] = 0x1;
 		c->operand[14] = 0xff;
 		c->operand[15] = 0xff;
-		c->length = 20;
+		fdtv->avc_data_length = 20;
 	} else {
-		c->length = 16;
+		fdtv->avc_data_length = 16;
 	}
 }
 
 static void avc_tuner_dsd_dvb_c(struct firedtv *fdtv,
-				struct dvb_frontend_parameters *params,
-				struct avc_command_frame *c)
+				struct dvb_frontend_parameters *params)
 {
+	struct avc_command_frame *c = (void *)fdtv->avc_data;
+
 	c->opcode = AVC_OPCODE_DSD;
 
 	c->operand[0] = 0;    /* source plug */
@@ -441,14 +428,15 @@ static void avc_tuner_dsd_dvb_c(struct f
 	c->operand[21] = 0x00;
 
 	/* Add PIDs to filter */
-	c->length = ALIGN(22 + add_pid_filter(fdtv, &c->operand[22]) + 3, 4);
+	fdtv->avc_data_length =
+		ALIGN(22 + add_pid_filter(fdtv, &c->operand[22]) + 3, 4);
 }
 
 static void avc_tuner_dsd_dvb_t(struct firedtv *fdtv,
-				struct dvb_frontend_parameters *params,
-				struct avc_command_frame *c)
+				struct dvb_frontend_parameters *params)
 {
 	struct dvb_ofdm_parameters *ofdm = &params->u.ofdm;
+	struct avc_command_frame *c = (void *)fdtv->avc_data;
 
 	c->opcode = AVC_OPCODE_DSD;
 
@@ -544,15 +532,18 @@ static void avc_tuner_dsd_dvb_t(struct f
 	c->operand[16] = 0x00; /* network_ID[1] */
 
 	/* Add PIDs to filter */
-	c->length = ALIGN(17 + add_pid_filter(fdtv, &c->operand[17]) + 3, 4);
+	fdtv->avc_data_length =
+		ALIGN(17 + add_pid_filter(fdtv, &c->operand[17]) + 3, 4);
 }
 
 int avc_tuner_dsd(struct firedtv *fdtv,
 		  struct dvb_frontend_parameters *params)
 {
-	char buffer[sizeof(struct avc_command_frame)];
-	struct avc_command_frame *c = (void *)buffer;
-	struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
+	struct avc_command_frame *c = (void *)fdtv->avc_data;
+	int ret;
+
+	if (mutex_lock_interruptible(&fdtv->avc_mutex))
+		return -EINTR;
 
 	memset(c, 0, sizeof(*c));
 
@@ -561,36 +552,41 @@ int avc_tuner_dsd(struct firedtv *fdtv,
 
 	switch (fdtv->type) {
 	case FIREDTV_DVB_S:
-	case FIREDTV_DVB_S2: avc_tuner_tuneqpsk(fdtv, params, c); break;
-	case FIREDTV_DVB_C: avc_tuner_dsd_dvb_c(fdtv, params, c); break;
-	case FIREDTV_DVB_T: avc_tuner_dsd_dvb_t(fdtv, params, c); break;
+	case FIREDTV_DVB_S2: avc_tuner_tuneqpsk(fdtv, params); break;
+	case FIREDTV_DVB_C: avc_tuner_dsd_dvb_c(fdtv, params); break;
+	case FIREDTV_DVB_T: avc_tuner_dsd_dvb_t(fdtv, params); break;
 	default:
 		BUG();
 	}
-
-	if (avc_write(fdtv, c, r) < 0)
-		return -EIO;
-
-	msleep(500);
+	ret = avc_write(fdtv);
 #if 0
-	/* FIXME: */
-	/* u8 *status was an out-parameter of avc_tuner_dsd, unused by caller */
+	/*
+	 * FIXME:
+	 * u8 *status was an out-parameter of avc_tuner_dsd, unused by caller.
+	 * Check for AVC_RESPONSE_ACCEPTED here instead?
+	 */
 	if (status)
 		*status = r->operand[2];
 #endif
-	return 0;
+	mutex_unlock(&fdtv->avc_mutex);
+
+	if (ret == 0)
+		msleep(500);
+
+	return ret;
 }
 
 int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[])
 {
-	char buffer[sizeof(struct avc_command_frame)];
-	struct avc_command_frame *c = (void *)buffer;
-	struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
-	int pos, k;
+	struct avc_command_frame *c = (void *)fdtv->avc_data;
+	int ret, pos, k;
 
 	if (pidc > 16 && pidc != 0xff)
 		return -EINVAL;
 
+	if (mutex_lock_interruptible(&fdtv->avc_mutex))
+		return -EINTR;
+
 	memset(c, 0, sizeof(*c));
 
 	c->ctype   = AVC_CTYPE_CONTROL;
@@ -615,21 +611,26 @@ int avc_tuner_set_pids(struct firedtv *f
 			c->operand[pos++] = 0x00; /* filter_length */
 		}
 
-	c->length = ALIGN(3 + pos, 4);
+	fdtv->avc_data_length = ALIGN(3 + pos, 4);
+	ret = avc_write(fdtv);
 
-	if (avc_write(fdtv, c, r) < 0)
-		return -EIO;
+	/* FIXME: check response code? */
 
-	msleep(50);
-	return 0;
+	mutex_unlock(&fdtv->avc_mutex);
+
+	if (ret == 0)
+		msleep(50);
+
+	return ret;
 }
 
 int avc_tuner_get_ts(struct firedtv *fdtv)
 {
-	char buffer[sizeof(struct avc_command_frame)];
-	struct avc_command_frame *c = (void *)buffer;
-	struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
-	int sl;
+	struct avc_command_frame *c = (void *)fdtv->avc_data;
+	int ret, sl;
+
+	if (mutex_lock_interruptible(&fdtv->avc_mutex))
+		return -EINTR;
 
 	memset(c, 0, sizeof(*c));
 
@@ -650,20 +651,27 @@ int avc_tuner_get_ts(struct firedtv *fdt
 	c->operand[8] = 0x00;	/* valid_flags [1] */
 	c->operand[7 + sl] = 0x00; /* nr_of_dsit_sel_specs (always 0) */
 
-	c->length = fdtv->type == FIREDTV_DVB_T ? 24 : 28;
+	fdtv->avc_data_length = fdtv->type == FIREDTV_DVB_T ? 24 : 28;
+	ret = avc_write(fdtv);
 
-	if (avc_write(fdtv, c, r) < 0)
-		return -EIO;
+	/* FIXME: check response code? */
 
-	msleep(250);
-	return 0;
+	mutex_unlock(&fdtv->avc_mutex);
+
+	if (ret == 0)
+		msleep(250);
+
+	return ret;
 }
 
 int avc_identify_subunit(struct firedtv *fdtv)
 {
-	char buffer[sizeof(struct avc_command_frame)];
-	struct avc_command_frame *c = (void *)buffer;
-	struct avc_response_frame *r = (void *)buffer;
+	struct avc_command_frame *c = (void *)fdtv->avc_data;
+	struct avc_response_frame *r = (void *)fdtv->avc_data;
+	int ret;
+
+	if (mutex_lock_interruptible(&fdtv->avc_mutex))
+		return -EINTR;
 
 	memset(c, 0, sizeof(*c));
 
@@ -679,28 +687,33 @@ int avc_identify_subunit(struct firedtv 
 	c->operand[5] = 0x00; /* offset highbyte */
 	c->operand[6] = 0x0d; /* offset lowbyte  */
 
-	c->length = 12;
-
-	if (avc_write(fdtv, c, r) < 0)
-		return -EIO;
+	fdtv->avc_data_length = 12;
+	ret = avc_write(fdtv);
+	if (ret < 0)
+		goto out;
 
 	if ((r->response != AVC_RESPONSE_STABLE &&
 	     r->response != AVC_RESPONSE_ACCEPTED) ||
 	    (r->operand[3] << 8) + r->operand[4] != 8) {
 		dev_err(fdtv->device, "cannot read subunit identifier\n");
-		return -EINVAL;
+		ret = -EINVAL;
 	}
-	return 0;
+out:
+	mutex_unlock(&fdtv->avc_mutex);
+
+	return ret;
 }
 
 #define SIZEOF_ANTENNA_INPUT_INFO 22
 
 int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat)
 {
-	char buffer[sizeof(struct avc_command_frame)];
-	struct avc_command_frame *c = (void *)buffer;
-	struct avc_response_frame *r = (void *)buffer;
-	int length;
+	struct avc_command_frame *c = (void *)fdtv->avc_data;
+	struct avc_response_frame *r = (void *)fdtv->avc_data;
+	int length, ret;
+
+	if (mutex_lock_interruptible(&fdtv->avc_mutex))
+		return -EINTR;
 
 	memset(c, 0, sizeof(*c));
 
@@ -716,21 +729,23 @@ int avc_tuner_status(struct firedtv *fdt
 	c->operand[5] = 0x00;
 	c->operand[6] = 0x00;
 
-	c->length = 12;
-
-	if (avc_write(fdtv, c, r) < 0)
-		return -EIO;
+	fdtv->avc_data_length = 12;
+	ret = avc_write(fdtv);
+	if (ret < 0)
+		goto out;
 
 	if (r->response != AVC_RESPONSE_STABLE &&
 	    r->response != AVC_RESPONSE_ACCEPTED) {
 		dev_err(fdtv->device, "cannot read tuner status\n");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out;
 	}
 
 	length = r->operand[9];
 	if (r->operand[1] != 0x10 || length != SIZEOF_ANTENNA_INPUT_INFO) {
 		dev_err(fdtv->device, "got invalid tuner status\n");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out;
 	}
 
 	stat->active_system		= r->operand[10];
@@ -766,18 +781,22 @@ int avc_tuner_status(struct firedtv *fdt
 	stat->ca_dvb_flag		= r->operand[31] >> 3 & 1;
 	stat->ca_error_flag		= r->operand[31] >> 2 & 1;
 	stat->ca_initialization_status	= r->operand[31] >> 1 & 1;
+out:
+	mutex_unlock(&fdtv->avc_mutex);
 
-	return 0;
+	return ret;
 }
 
 int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst,
 		    char conttone, char nrdiseq,
 		    struct dvb_diseqc_master_cmd *diseqcmd)
 {
-	char buffer[sizeof(struct avc_command_frame)];
-	struct avc_command_frame *c = (void *)buffer;
-	struct avc_response_frame *r = (void *)buffer;
-	int i, j, k;
+	struct avc_command_frame *c = (void *)fdtv->avc_data;
+	struct avc_response_frame *r = (void *)fdtv->avc_data;
+	int i, j, k, ret;
+
+	if (mutex_lock_interruptible(&fdtv->avc_mutex))
+		return -EINTR;
 
 	memset(c, 0, sizeof(*c));
 
@@ -805,23 +824,28 @@ int avc_lnb_control(struct firedtv *fdtv
 	c->operand[i++] = burst;
 	c->operand[i++] = conttone;
 
-	c->length = ALIGN(3 + i, 4);
-
-	if (avc_write(fdtv, c, r) < 0)
-		return -EIO;
+	fdtv->avc_data_length = ALIGN(3 + i, 4);
+	ret = avc_write(fdtv);
+	if (ret < 0)
+		goto out;
 
 	if (r->response != AVC_RESPONSE_ACCEPTED) {
 		dev_err(fdtv->device, "LNB control failed\n");
-		return -EINVAL;
+		ret = -EINVAL;
 	}
+out:
+	mutex_unlock(&fdtv->avc_mutex);
 
-	return 0;
+	return ret;
 }
 
 int avc_register_remote_control(struct firedtv *fdtv)
 {
-	char buffer[sizeof(struct avc_command_frame)];
-	struct avc_command_frame *c = (void *)buffer;
+	struct avc_command_frame *c = (void *)fdtv->avc_data;
+	int ret;
+
+	if (mutex_lock_interruptible(&fdtv->avc_mutex))
+		return -EINTR;
 
 	memset(c, 0, sizeof(*c));
 
@@ -834,9 +858,14 @@ int avc_register_remote_control(struct f
 	c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
 	c->operand[3] = SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL;
 
-	c->length = 8;
+	fdtv->avc_data_length = 8;
+	ret = avc_write(fdtv);
 
-	return avc_write(fdtv, c, NULL);
+	/* FIXME: check response code? */
+
+	mutex_unlock(&fdtv->avc_mutex);
+
+	return ret;
 }
 
 void avc_remote_ctrl_work(struct work_struct *work)
@@ -851,9 +880,11 @@ void avc_remote_ctrl_work(struct work_st
 #if 0 /* FIXME: unused */
 int avc_tuner_host2ca(struct firedtv *fdtv)
 {
-	char buffer[sizeof(struct avc_command_frame)];
-	struct avc_command_frame *c = (void *)buffer;
-	struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
+	struct avc_command_frame *c = (void *)fdtv->avc_data;
+	int ret;
+
+	if (mutex_lock_interruptible(&fdtv->avc_mutex))
+		return -EINTR;
 
 	memset(c, 0, sizeof(*c));
 
@@ -870,12 +901,14 @@ int avc_tuner_host2ca(struct firedtv *fd
 	c->operand[6] = 0; /* more/last */
 	c->operand[7] = 0; /* length */
 
-	c->length = 12;
+	fdtv->avc_data_length = 12;
+	ret = avc_write(fdtv);
 
-	if (avc_write(fdtv, c, r) < 0)
-		return -EIO;
+	/* FIXME: check response code? */
 
-	return 0;
+	mutex_unlock(&fdtv->avc_mutex);
+
+	return ret;
 }
 #endif
 
@@ -906,10 +939,12 @@ static int get_ca_object_length(struct a
 
 int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
 {
-	char buffer[sizeof(struct avc_command_frame)];
-	struct avc_command_frame *c = (void *)buffer;
-	struct avc_response_frame *r = (void *)buffer;
-	int pos;
+	struct avc_command_frame *c = (void *)fdtv->avc_data;
+	struct avc_response_frame *r = (void *)fdtv->avc_data;
+	int pos, ret;
+
+	if (mutex_lock_interruptible(&fdtv->avc_mutex))
+		return -EINTR;
 
 	memset(c, 0, sizeof(*c));
 
@@ -924,10 +959,10 @@ int avc_ca_app_info(struct firedtv *fdtv
 	c->operand[4] = 0; /* slot */
 	c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
 
-	c->length = 12;
-
-	if (avc_write(fdtv, c, r) < 0)
-		return -EIO;
+	fdtv->avc_data_length = 12;
+	ret = avc_write(fdtv);
+	if (ret < 0)
+		goto out;
 
 	/* FIXME: check response code and validate response data */
 
@@ -939,16 +974,20 @@ int avc_ca_app_info(struct firedtv *fdtv
 	app_info[4] = 0x01;
 	memcpy(&app_info[5], &r->operand[pos], 5 + r->operand[pos + 4]);
 	*len = app_info[3] + 4;
+out:
+	mutex_unlock(&fdtv->avc_mutex);
 
-	return 0;
+	return ret;
 }
 
 int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
 {
-	char buffer[sizeof(struct avc_command_frame)];
-	struct avc_command_frame *c = (void *)buffer;
-	struct avc_response_frame *r = (void *)buffer;
-	int pos;
+	struct avc_command_frame *c = (void *)fdtv->avc_data;
+	struct avc_response_frame *r = (void *)fdtv->avc_data;
+	int pos, ret;
+
+	if (mutex_lock_interruptible(&fdtv->avc_mutex))
+		return -EINTR;
 
 	memset(c, 0, sizeof(*c));
 
@@ -963,10 +1002,12 @@ int avc_ca_info(struct firedtv *fdtv, ch
 	c->operand[4] = 0; /* slot */
 	c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
 
-	c->length = 12;
+	fdtv->avc_data_length = 12;
+	ret = avc_write(fdtv);
+	if (ret < 0)
+		goto out;
 
-	if (avc_write(fdtv, c, r) < 0)
-		return -EIO;
+	/* FIXME: check response code and validate response data */
 
 	pos = get_ca_object_pos(r);
 	app_info[0] = (EN50221_TAG_CA_INFO >> 16) & 0xff;
@@ -976,15 +1017,19 @@ int avc_ca_info(struct firedtv *fdtv, ch
 	app_info[4] = r->operand[pos + 0];
 	app_info[5] = r->operand[pos + 1];
 	*len = app_info[3] + 4;
+out:
+	mutex_unlock(&fdtv->avc_mutex);
 
-	return 0;
+	return ret;
 }
 
 int avc_ca_reset(struct firedtv *fdtv)
 {
-	char buffer[sizeof(struct avc_command_frame)];
-	struct avc_command_frame *c = (void *)buffer;
-	struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
+	struct avc_command_frame *c = (void *)fdtv->avc_data;
+	int ret;
+
+	if (mutex_lock_interruptible(&fdtv->avc_mutex))
+		return -EINTR;
 
 	memset(c, 0, sizeof(*c));
 
@@ -1002,19 +1047,20 @@ int avc_ca_reset(struct firedtv *fdtv)
 	c->operand[7] = 1; /* length */
 	c->operand[8] = 0; /* force hardware reset */
 
-	c->length = 12;
+	fdtv->avc_data_length = 12;
+	ret = avc_write(fdtv);
 
-	if (avc_write(fdtv, c, r) < 0)
-		return -EIO;
+	/* FIXME: check response code? */
 
-	return 0;
+	mutex_unlock(&fdtv->avc_mutex);
+
+	return ret;
 }
 
 int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)
 {
-	char buffer[sizeof(struct avc_command_frame)];
-	struct avc_command_frame *c = (void *)buffer;
-	struct avc_response_frame *r = (void *)buffer;
+	struct avc_command_frame *c = (void *)fdtv->avc_data;
+	struct avc_response_frame *r = (void *)fdtv->avc_data;
 	int list_management;
 	int program_info_length;
 	int pmt_cmd_id;
@@ -1022,10 +1068,14 @@ int avc_ca_pmt(struct firedtv *fdtv, cha
 	int write_pos;
 	int es_info_length;
 	int crc32_csum;
+	int ret;
 
 	if (unlikely(avc_debug & AVC_DEBUG_APPLICATION_PMT))
 		debug_pmt(msg, length);
 
+	if (mutex_lock_interruptible(&fdtv->avc_mutex))
+		return -EINTR;
+
 	memset(c, 0, sizeof(*c));
 
 	c->ctype   = AVC_CTYPE_CONTROL;
@@ -1124,25 +1174,30 @@ int avc_ca_pmt(struct firedtv *fdtv, cha
 	c->operand[write_pos - 2] = (crc32_csum >>  8) & 0xff;
 	c->operand[write_pos - 1] = (crc32_csum >>  0) & 0xff;
 
-	c->length = ALIGN(3 + write_pos, 4);
-
-	if (avc_write(fdtv, c, r) < 0)
-		return -EIO;
+	fdtv->avc_data_length = ALIGN(3 + write_pos, 4);
+	ret = avc_write(fdtv);
+	if (ret < 0)
+		goto out;
 
 	if (r->response != AVC_RESPONSE_ACCEPTED) {
 		dev_err(fdtv->device,
 			"CA PMT failed with response 0x%x\n", r->response);
-		return -EFAULT;
+		ret = -EFAULT;
 	}
+out:
+	mutex_unlock(&fdtv->avc_mutex);
 
-	return 0;
+	return ret;
 }
 
 int avc_ca_get_time_date(struct firedtv *fdtv, int *interval)
 {
-	char buffer[sizeof(struct avc_command_frame)];
-	struct avc_command_frame *c = (void *)buffer;
-	struct avc_response_frame *r = (void *)buffer;
+	struct avc_command_frame *c = (void *)fdtv->avc_data;
+	struct avc_response_frame *r = (void *)fdtv->avc_data;
+	int ret;
+
+	if (mutex_lock_interruptible(&fdtv->avc_mutex))
+		return -EINTR;
 
 	memset(c, 0, sizeof(*c));
 
@@ -1159,23 +1214,27 @@ int avc_ca_get_time_date(struct firedtv 
 	c->operand[6] = 0; /* more/last */
 	c->operand[7] = 0; /* length */
 
-	c->length = 12;
-
-	if (avc_write(fdtv, c, r) < 0)
-		return -EIO;
+	fdtv->avc_data_length = 12;
+	ret = avc_write(fdtv);
+	if (ret < 0)
+		goto out;
 
 	/* FIXME: check response code and validate response data */
 
 	*interval = r->operand[get_ca_object_pos(r)];
+out:
+	mutex_unlock(&fdtv->avc_mutex);
 
-	return 0;
+	return ret;
 }
 
 int avc_ca_enter_menu(struct firedtv *fdtv)
 {
-	char buffer[sizeof(struct avc_command_frame)];
-	struct avc_command_frame *c = (void *)buffer;
-	struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
+	struct avc_command_frame *c = (void *)fdtv->avc_data;
+	int ret;
+
+	if (mutex_lock_interruptible(&fdtv->avc_mutex))
+		return -EINTR;
 
 	memset(c, 0, sizeof(*c));
 
@@ -1192,19 +1251,24 @@ int avc_ca_enter_menu(struct firedtv *fd
 	c->operand[6] = 0; /* more/last */
 	c->operand[7] = 0; /* length */
 
-	c->length = 12;
+	fdtv->avc_data_length = 12;
+	ret = avc_write(fdtv);
 
-	if (avc_write(fdtv, c, r) < 0)
-		return -EIO;
+	/* FIXME: check response code? */
 
-	return 0;
+	mutex_unlock(&fdtv->avc_mutex);
+
+	return ret;
 }
 
 int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len)
 {
-	char buffer[sizeof(struct avc_command_frame)];
-	struct avc_command_frame *c = (void *)buffer;
-	struct avc_response_frame *r = (void *)buffer;
+	struct avc_command_frame *c = (void *)fdtv->avc_data;
+	struct avc_response_frame *r = (void *)fdtv->avc_data;
+	int ret;
+
+	if (mutex_lock_interruptible(&fdtv->avc_mutex))
+		return -EINTR;
 
 	memset(c, 0, sizeof(*c));
 
@@ -1221,17 +1285,19 @@ int avc_ca_get_mmi(struct firedtv *fdtv,
 	c->operand[6] = 0; /* more/last */
 	c->operand[7] = 0; /* length */
 
-	c->length = 12;
-
-	if (avc_write(fdtv, c, r) < 0)
-		return -EIO;
+	fdtv->avc_data_length = 12;
+	ret = avc_write(fdtv);
+	if (ret < 0)
+		goto out;
 
 	/* FIXME: check response code and validate response data */
 
 	*len = get_ca_object_length(r);
 	memcpy(mmi_object, &r->operand[get_ca_object_pos(r)], *len);
+out:
+	mutex_unlock(&fdtv->avc_mutex);
 
-	return 0;
+	return ret;
 }
 
 #define CMP_OUTPUT_PLUG_CONTROL_REG_0	0xfffff0000904ULL
@@ -1248,6 +1314,7 @@ static int cmp_read(struct firedtv *fdtv
 		dev_err(fdtv->device, "CMP: read I/O error\n");
 
 	mutex_unlock(&fdtv->avc_mutex);
+
 	return ret;
 }
 
@@ -1258,11 +1325,17 @@ static int cmp_lock(struct firedtv *fdtv
 	if (mutex_lock_interruptible(&fdtv->avc_mutex))
 		return -EINTR;
 
-	ret = fdtv->backend->lock(fdtv, addr, data);
+	/* data[] is stack-allocated and should not be DMA-mapped. */
+	memcpy(fdtv->avc_data, data, 8);
+
+	ret = fdtv->backend->lock(fdtv, addr, fdtv->avc_data);
 	if (ret < 0)
 		dev_err(fdtv->device, "CMP: lock I/O error\n");
+	else
+		memcpy(data, fdtv->avc_data, 8);
 
 	mutex_unlock(&fdtv->avc_mutex);
+
 	return ret;
 }
 
Index: linux-2.6.32-rc7/drivers/media/dvb/firewire/firedtv-dvb.c
===================================================================
--- linux-2.6.32-rc7.orig/drivers/media/dvb/firewire/firedtv-dvb.c
+++ linux-2.6.32-rc7/drivers/media/dvb/firewire/firedtv-dvb.c
@@ -277,7 +277,6 @@ struct firedtv *fdtv_alloc(struct device
 
 	mutex_init(&fdtv->avc_mutex);
 	init_waitqueue_head(&fdtv->avc_wait);
-	fdtv->avc_reply_received = true;
 	mutex_init(&fdtv->demux_mutex);
 	INIT_WORK(&fdtv->remote_ctrl_work, avc_remote_ctrl_work);
 
Index: linux-2.6.32-rc7/drivers/media/dvb/firewire/firedtv-fw.c
===================================================================
--- linux-2.6.32-rc7.orig/drivers/media/dvb/firewire/firedtv-fw.c
+++ linux-2.6.32-rc7/drivers/media/dvb/firewire/firedtv-fw.c
@@ -41,7 +41,7 @@ static int node_req(struct firedtv *fdtv
 	return rcode != RCODE_COMPLETE ? -EIO : 0;
 }
 
-static int node_lock(struct firedtv *fdtv, u64 addr, __be32 data[])
+static int node_lock(struct firedtv *fdtv, u64 addr, void *data)
 {
 	return node_req(fdtv, addr, data, 8, TCODE_LOCK_COMPARE_SWAP);
 }
Index: linux-2.6.32-rc7/drivers/media/dvb/firewire/firedtv.h
===================================================================
--- linux-2.6.32-rc7.orig/drivers/media/dvb/firewire/firedtv.h
+++ linux-2.6.32-rc7/drivers/media/dvb/firewire/firedtv.h
@@ -73,7 +73,7 @@ struct input_dev;
 struct firedtv;
 
 struct firedtv_backend {
-	int (*lock)(struct firedtv *fdtv, u64 addr, __be32 data[]);
+	int (*lock)(struct firedtv *fdtv, u64 addr, void *data);
 	int (*read)(struct firedtv *fdtv, u64 addr, void *data);
 	int (*write)(struct firedtv *fdtv, u64 addr, void *data, size_t len);
 	int (*start_iso)(struct firedtv *fdtv);
@@ -114,8 +114,8 @@ struct firedtv {
 	unsigned long		channel_active;
 	u16			channel_pid[16];
 
-	size_t			response_length;
-	u8			response[512];
+	int			avc_data_length;
+	u8			avc_data[512];
 };
 
 /* firedtv-1394.c */

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


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

* [PATCH 5/6] firedtv: remove check for interrupting signal
  2009-11-18 19:00 [PATCH 0/6] DVB: firedtv: simplifications and a portability fix Stefan Richter
                   ` (3 preceding siblings ...)
  2009-11-18 19:02 ` [PATCH 4/6] firedtv: do not DMA-map stack addresses Stefan Richter
@ 2009-11-18 19:03 ` Stefan Richter
  2009-11-18 19:03 ` [PATCH 6/6] firedtv: reduce memset()s Stefan Richter
  2009-11-21  0:26 ` [PATCH 0/6] DVB: firedtv: simplifications and a portability fix Stefan Richter
  6 siblings, 0 replies; 8+ messages in thread
From: Stefan Richter @ 2009-11-18 19:03 UTC (permalink / raw)
  To: linux-media; +Cc: linux1394-devel, linux-kernel

FCP transactions as well as CMP transactions were serialized with
mutex_lock_interruptible.  It is extremely unlikly though that a signal
will arrive while a concurrent process holds the mutex.  And even if one
does, the duration of a transaction is reasonably short (1.2 seconds if
all retries time out, usually much shorter).

Hence simplify the code to plain mutex_lock.

Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
---
 drivers/media/dvb/firewire/firedtv-avc.c |   51 ++++++++---------------
 1 file changed, 17 insertions(+), 34 deletions(-)

Index: linux-2.6.32-rc7/drivers/media/dvb/firewire/firedtv-avc.c
===================================================================
--- linux-2.6.32-rc7.orig/drivers/media/dvb/firewire/firedtv-avc.c
+++ linux-2.6.32-rc7/drivers/media/dvb/firewire/firedtv-avc.c
@@ -542,8 +542,7 @@ int avc_tuner_dsd(struct firedtv *fdtv,
 	struct avc_command_frame *c = (void *)fdtv->avc_data;
 	int ret;
 
-	if (mutex_lock_interruptible(&fdtv->avc_mutex))
-		return -EINTR;
+	mutex_lock(&fdtv->avc_mutex);
 
 	memset(c, 0, sizeof(*c));
 
@@ -584,8 +583,7 @@ int avc_tuner_set_pids(struct firedtv *f
 	if (pidc > 16 && pidc != 0xff)
 		return -EINVAL;
 
-	if (mutex_lock_interruptible(&fdtv->avc_mutex))
-		return -EINTR;
+	mutex_lock(&fdtv->avc_mutex);
 
 	memset(c, 0, sizeof(*c));
 
@@ -629,8 +627,7 @@ int avc_tuner_get_ts(struct firedtv *fdt
 	struct avc_command_frame *c = (void *)fdtv->avc_data;
 	int ret, sl;
 
-	if (mutex_lock_interruptible(&fdtv->avc_mutex))
-		return -EINTR;
+	mutex_lock(&fdtv->avc_mutex);
 
 	memset(c, 0, sizeof(*c));
 
@@ -670,8 +667,7 @@ int avc_identify_subunit(struct firedtv 
 	struct avc_response_frame *r = (void *)fdtv->avc_data;
 	int ret;
 
-	if (mutex_lock_interruptible(&fdtv->avc_mutex))
-		return -EINTR;
+	mutex_lock(&fdtv->avc_mutex);
 
 	memset(c, 0, sizeof(*c));
 
@@ -712,8 +708,7 @@ int avc_tuner_status(struct firedtv *fdt
 	struct avc_response_frame *r = (void *)fdtv->avc_data;
 	int length, ret;
 
-	if (mutex_lock_interruptible(&fdtv->avc_mutex))
-		return -EINTR;
+	mutex_lock(&fdtv->avc_mutex);
 
 	memset(c, 0, sizeof(*c));
 
@@ -795,8 +790,7 @@ int avc_lnb_control(struct firedtv *fdtv
 	struct avc_response_frame *r = (void *)fdtv->avc_data;
 	int i, j, k, ret;
 
-	if (mutex_lock_interruptible(&fdtv->avc_mutex))
-		return -EINTR;
+	mutex_lock(&fdtv->avc_mutex);
 
 	memset(c, 0, sizeof(*c));
 
@@ -844,8 +838,7 @@ int avc_register_remote_control(struct f
 	struct avc_command_frame *c = (void *)fdtv->avc_data;
 	int ret;
 
-	if (mutex_lock_interruptible(&fdtv->avc_mutex))
-		return -EINTR;
+	mutex_lock(&fdtv->avc_mutex);
 
 	memset(c, 0, sizeof(*c));
 
@@ -883,8 +876,7 @@ int avc_tuner_host2ca(struct firedtv *fd
 	struct avc_command_frame *c = (void *)fdtv->avc_data;
 	int ret;
 
-	if (mutex_lock_interruptible(&fdtv->avc_mutex))
-		return -EINTR;
+	mutex_lock(&fdtv->avc_mutex);
 
 	memset(c, 0, sizeof(*c));
 
@@ -943,8 +935,7 @@ int avc_ca_app_info(struct firedtv *fdtv
 	struct avc_response_frame *r = (void *)fdtv->avc_data;
 	int pos, ret;
 
-	if (mutex_lock_interruptible(&fdtv->avc_mutex))
-		return -EINTR;
+	mutex_lock(&fdtv->avc_mutex);
 
 	memset(c, 0, sizeof(*c));
 
@@ -986,8 +977,7 @@ int avc_ca_info(struct firedtv *fdtv, ch
 	struct avc_response_frame *r = (void *)fdtv->avc_data;
 	int pos, ret;
 
-	if (mutex_lock_interruptible(&fdtv->avc_mutex))
-		return -EINTR;
+	mutex_lock(&fdtv->avc_mutex);
 
 	memset(c, 0, sizeof(*c));
 
@@ -1028,8 +1018,7 @@ int avc_ca_reset(struct firedtv *fdtv)
 	struct avc_command_frame *c = (void *)fdtv->avc_data;
 	int ret;
 
-	if (mutex_lock_interruptible(&fdtv->avc_mutex))
-		return -EINTR;
+	mutex_lock(&fdtv->avc_mutex);
 
 	memset(c, 0, sizeof(*c));
 
@@ -1073,8 +1062,7 @@ int avc_ca_pmt(struct firedtv *fdtv, cha
 	if (unlikely(avc_debug & AVC_DEBUG_APPLICATION_PMT))
 		debug_pmt(msg, length);
 
-	if (mutex_lock_interruptible(&fdtv->avc_mutex))
-		return -EINTR;
+	mutex_lock(&fdtv->avc_mutex);
 
 	memset(c, 0, sizeof(*c));
 
@@ -1196,8 +1184,7 @@ int avc_ca_get_time_date(struct firedtv 
 	struct avc_response_frame *r = (void *)fdtv->avc_data;
 	int ret;
 
-	if (mutex_lock_interruptible(&fdtv->avc_mutex))
-		return -EINTR;
+	mutex_lock(&fdtv->avc_mutex);
 
 	memset(c, 0, sizeof(*c));
 
@@ -1233,8 +1220,7 @@ int avc_ca_enter_menu(struct firedtv *fd
 	struct avc_command_frame *c = (void *)fdtv->avc_data;
 	int ret;
 
-	if (mutex_lock_interruptible(&fdtv->avc_mutex))
-		return -EINTR;
+	mutex_lock(&fdtv->avc_mutex);
 
 	memset(c, 0, sizeof(*c));
 
@@ -1267,8 +1253,7 @@ int avc_ca_get_mmi(struct firedtv *fdtv,
 	struct avc_response_frame *r = (void *)fdtv->avc_data;
 	int ret;
 
-	if (mutex_lock_interruptible(&fdtv->avc_mutex))
-		return -EINTR;
+	mutex_lock(&fdtv->avc_mutex);
 
 	memset(c, 0, sizeof(*c));
 
@@ -1306,8 +1291,7 @@ static int cmp_read(struct firedtv *fdtv
 {
 	int ret;
 
-	if (mutex_lock_interruptible(&fdtv->avc_mutex))
-		return -EINTR;
+	mutex_lock(&fdtv->avc_mutex);
 
 	ret = fdtv->backend->read(fdtv, addr, data);
 	if (ret < 0)
@@ -1322,8 +1306,7 @@ static int cmp_lock(struct firedtv *fdtv
 {
 	int ret;
 
-	if (mutex_lock_interruptible(&fdtv->avc_mutex))
-		return -EINTR;
+	mutex_lock(&fdtv->avc_mutex);
 
 	/* data[] is stack-allocated and should not be DMA-mapped. */
 	memcpy(fdtv->avc_data, data, 8);

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


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

* [PATCH 6/6] firedtv: reduce memset()s
  2009-11-18 19:00 [PATCH 0/6] DVB: firedtv: simplifications and a portability fix Stefan Richter
                   ` (4 preceding siblings ...)
  2009-11-18 19:03 ` [PATCH 5/6] firedtv: remove check for interrupting signal Stefan Richter
@ 2009-11-18 19:03 ` Stefan Richter
  2009-11-21  0:26 ` [PATCH 0/6] DVB: firedtv: simplifications and a portability fix Stefan Richter
  6 siblings, 0 replies; 8+ messages in thread
From: Stefan Richter @ 2009-11-18 19:03 UTC (permalink / raw)
  To: linux-media; +Cc: linux1394-devel, linux-kernel

Before each FCP transdaction, the entire 512 bytes of the FCP frame were
cleared, then values filled in.

Clear only the bytes between filled-in bytes and end of the
  - request frame, or
  - response frame if data from a larger response will be needed, or
  - whole frame if data from a variable length response will be taken.

Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
---
 drivers/media/dvb/firewire/firedtv-avc.c |  146 ++++++++++-------------
 1 file changed, 65 insertions(+), 81 deletions(-)

Index: linux-2.6.32-rc7/drivers/media/dvb/firewire/firedtv-avc.c
===================================================================
--- linux-2.6.32-rc7.orig/drivers/media/dvb/firewire/firedtv-avc.c
+++ linux-2.6.32-rc7/drivers/media/dvb/firewire/firedtv-avc.c
@@ -87,6 +87,21 @@ struct avc_response_frame {
 	u8 operand[509];
 };
 
+#define LAST_OPERAND (509 - 1)
+
+static inline void clear_operands(struct avc_command_frame *c, int from, int to)
+{
+	memset(&c->operand[from], 0, to - from + 1);
+}
+
+static void pad_operands(struct avc_command_frame *c, int from)
+{
+	int to = ALIGN(from, 4);
+
+	if (from <= to && to <= LAST_OPERAND)
+		clear_operands(c, from, to);
+}
+
 #define AVC_DEBUG_READ_DESCRIPTOR              0x0001
 #define AVC_DEBUG_DSIT                         0x0002
 #define AVC_DEBUG_DSD                          0x0004
@@ -303,8 +318,8 @@ static int add_pid_filter(struct firedtv
  * tuning command for setting the relative LNB frequency
  * (not supported by the AVC standard)
  */
-static void avc_tuner_tuneqpsk(struct firedtv *fdtv,
-			       struct dvb_frontend_parameters *params)
+static int avc_tuner_tuneqpsk(struct firedtv *fdtv,
+			      struct dvb_frontend_parameters *params)
 {
 	struct avc_command_frame *c = (void *)fdtv->avc_data;
 
@@ -356,14 +371,15 @@ static void avc_tuner_tuneqpsk(struct fi
 		c->operand[13] = 0x1;
 		c->operand[14] = 0xff;
 		c->operand[15] = 0xff;
-		fdtv->avc_data_length = 20;
+
+		return 16;
 	} else {
-		fdtv->avc_data_length = 16;
+		return 13;
 	}
 }
 
-static void avc_tuner_dsd_dvb_c(struct firedtv *fdtv,
-				struct dvb_frontend_parameters *params)
+static int avc_tuner_dsd_dvb_c(struct firedtv *fdtv,
+			       struct dvb_frontend_parameters *params)
 {
 	struct avc_command_frame *c = (void *)fdtv->avc_data;
 
@@ -427,13 +443,11 @@ static void avc_tuner_dsd_dvb_c(struct f
 	c->operand[20] = 0x00;
 	c->operand[21] = 0x00;
 
-	/* Add PIDs to filter */
-	fdtv->avc_data_length =
-		ALIGN(22 + add_pid_filter(fdtv, &c->operand[22]) + 3, 4);
+	return 22 + add_pid_filter(fdtv, &c->operand[22]);
 }
 
-static void avc_tuner_dsd_dvb_t(struct firedtv *fdtv,
-				struct dvb_frontend_parameters *params)
+static int avc_tuner_dsd_dvb_t(struct firedtv *fdtv,
+			       struct dvb_frontend_parameters *params)
 {
 	struct dvb_ofdm_parameters *ofdm = &params->u.ofdm;
 	struct avc_command_frame *c = (void *)fdtv->avc_data;
@@ -531,32 +545,31 @@ static void avc_tuner_dsd_dvb_t(struct f
 	c->operand[15] = 0x00; /* network_ID[0] */
 	c->operand[16] = 0x00; /* network_ID[1] */
 
-	/* Add PIDs to filter */
-	fdtv->avc_data_length =
-		ALIGN(17 + add_pid_filter(fdtv, &c->operand[17]) + 3, 4);
+	return 17 + add_pid_filter(fdtv, &c->operand[17]);
 }
 
 int avc_tuner_dsd(struct firedtv *fdtv,
 		  struct dvb_frontend_parameters *params)
 {
 	struct avc_command_frame *c = (void *)fdtv->avc_data;
-	int ret;
+	int pos, ret;
 
 	mutex_lock(&fdtv->avc_mutex);
 
-	memset(c, 0, sizeof(*c));
-
 	c->ctype   = AVC_CTYPE_CONTROL;
 	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
 
 	switch (fdtv->type) {
 	case FIREDTV_DVB_S:
-	case FIREDTV_DVB_S2: avc_tuner_tuneqpsk(fdtv, params); break;
-	case FIREDTV_DVB_C: avc_tuner_dsd_dvb_c(fdtv, params); break;
-	case FIREDTV_DVB_T: avc_tuner_dsd_dvb_t(fdtv, params); break;
+	case FIREDTV_DVB_S2: pos = avc_tuner_tuneqpsk(fdtv, params); break;
+	case FIREDTV_DVB_C: pos = avc_tuner_dsd_dvb_c(fdtv, params); break;
+	case FIREDTV_DVB_T: pos = avc_tuner_dsd_dvb_t(fdtv, params); break;
 	default:
 		BUG();
 	}
+	pad_operands(c, pos);
+
+	fdtv->avc_data_length = ALIGN(3 + pos, 4);
 	ret = avc_write(fdtv);
 #if 0
 	/*
@@ -585,8 +598,6 @@ int avc_tuner_set_pids(struct firedtv *f
 
 	mutex_lock(&fdtv->avc_mutex);
 
-	memset(c, 0, sizeof(*c));
-
 	c->ctype   = AVC_CTYPE_CONTROL;
 	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
 	c->opcode  = AVC_OPCODE_DSD;
@@ -608,6 +619,7 @@ int avc_tuner_set_pids(struct firedtv *f
 			c->operand[pos++] = 0x00; /* tableID */
 			c->operand[pos++] = 0x00; /* filter_length */
 		}
+	pad_operands(c, pos);
 
 	fdtv->avc_data_length = ALIGN(3 + pos, 4);
 	ret = avc_write(fdtv);
@@ -629,8 +641,6 @@ int avc_tuner_get_ts(struct firedtv *fdt
 
 	mutex_lock(&fdtv->avc_mutex);
 
-	memset(c, 0, sizeof(*c));
-
 	c->ctype   = AVC_CTYPE_CONTROL;
 	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
 	c->opcode  = AVC_OPCODE_DSIT;
@@ -644,9 +654,12 @@ int avc_tuner_get_ts(struct firedtv *fdt
 	c->operand[4] = 0x00;	/* antenna number */
 	c->operand[5] = 0x0; 	/* system_specific_search_flags */
 	c->operand[6] = sl;	/* system_specific_multiplex selection_length */
-	c->operand[7] = 0x00;	/* valid_flags [0] */
-	c->operand[8] = 0x00;	/* valid_flags [1] */
-	c->operand[7 + sl] = 0x00; /* nr_of_dsit_sel_specs (always 0) */
+	/*
+	 * operand[7]: valid_flags[0]
+	 * operand[8]: valid_flags[1]
+	 * operand[7 + sl]: nr_of_dsit_sel_specs (always 0)
+	 */
+	clear_operands(c, 7, 24);
 
 	fdtv->avc_data_length = fdtv->type == FIREDTV_DVB_T ? 24 : 28;
 	ret = avc_write(fdtv);
@@ -669,8 +682,6 @@ int avc_identify_subunit(struct firedtv 
 
 	mutex_lock(&fdtv->avc_mutex);
 
-	memset(c, 0, sizeof(*c));
-
 	c->ctype   = AVC_CTYPE_CONTROL;
 	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
 	c->opcode  = AVC_OPCODE_READ_DESCRIPTOR;
@@ -682,6 +693,7 @@ int avc_identify_subunit(struct firedtv 
 	c->operand[4] = 0x08; /* length lowbyte  */
 	c->operand[5] = 0x00; /* offset highbyte */
 	c->operand[6] = 0x0d; /* offset lowbyte  */
+	clear_operands(c, 7, 8); /* padding */
 
 	fdtv->avc_data_length = 12;
 	ret = avc_write(fdtv);
@@ -710,19 +722,18 @@ int avc_tuner_status(struct firedtv *fdt
 
 	mutex_lock(&fdtv->avc_mutex);
 
-	memset(c, 0, sizeof(*c));
-
 	c->ctype   = AVC_CTYPE_CONTROL;
 	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
 	c->opcode  = AVC_OPCODE_READ_DESCRIPTOR;
 
 	c->operand[0] = DESCRIPTOR_TUNER_STATUS;
 	c->operand[1] = 0xff;	/* read_result_status */
-	c->operand[2] = 0x00;	/* reserved */
-	c->operand[3] = 0;	/* SIZEOF_ANTENNA_INPUT_INFO >> 8; */
-	c->operand[4] = 0;	/* SIZEOF_ANTENNA_INPUT_INFO & 0xff; */
-	c->operand[5] = 0x00;
-	c->operand[6] = 0x00;
+	/*
+	 * operand[2]: reserved
+	 * operand[3]: SIZEOF_ANTENNA_INPUT_INFO >> 8
+	 * operand[4]: SIZEOF_ANTENNA_INPUT_INFO & 0xff
+	 */
+	clear_operands(c, 2, 31);
 
 	fdtv->avc_data_length = 12;
 	ret = avc_write(fdtv);
@@ -788,12 +799,10 @@ int avc_lnb_control(struct firedtv *fdtv
 {
 	struct avc_command_frame *c = (void *)fdtv->avc_data;
 	struct avc_response_frame *r = (void *)fdtv->avc_data;
-	int i, j, k, ret;
+	int pos, j, k, ret;
 
 	mutex_lock(&fdtv->avc_mutex);
 
-	memset(c, 0, sizeof(*c));
-
 	c->ctype   = AVC_CTYPE_CONTROL;
 	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
 	c->opcode  = AVC_OPCODE_VENDOR;
@@ -802,23 +811,21 @@ int avc_lnb_control(struct firedtv *fdtv
 	c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
 	c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
 	c->operand[3] = SFE_VENDOR_OPCODE_LNB_CONTROL;
-
 	c->operand[4] = voltage;
 	c->operand[5] = nrdiseq;
 
-	i = 6;
-
+	pos = 6;
 	for (j = 0; j < nrdiseq; j++) {
-		c->operand[i++] = diseqcmd[j].msg_len;
+		c->operand[pos++] = diseqcmd[j].msg_len;
 
 		for (k = 0; k < diseqcmd[j].msg_len; k++)
-			c->operand[i++] = diseqcmd[j].msg[k];
+			c->operand[pos++] = diseqcmd[j].msg[k];
 	}
+	c->operand[pos++] = burst;
+	c->operand[pos++] = conttone;
+	pad_operands(c, pos);
 
-	c->operand[i++] = burst;
-	c->operand[i++] = conttone;
-
-	fdtv->avc_data_length = ALIGN(3 + i, 4);
+	fdtv->avc_data_length = ALIGN(3 + pos, 4);
 	ret = avc_write(fdtv);
 	if (ret < 0)
 		goto out;
@@ -840,8 +847,6 @@ int avc_register_remote_control(struct f
 
 	mutex_lock(&fdtv->avc_mutex);
 
-	memset(c, 0, sizeof(*c));
-
 	c->ctype   = AVC_CTYPE_NOTIFY;
 	c->subunit = AVC_SUBUNIT_TYPE_UNIT | 7;
 	c->opcode  = AVC_OPCODE_VENDOR;
@@ -850,6 +855,7 @@ int avc_register_remote_control(struct f
 	c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
 	c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
 	c->operand[3] = SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL;
+	c->operand[4] = 0; /* padding */
 
 	fdtv->avc_data_length = 8;
 	ret = avc_write(fdtv);
@@ -878,8 +884,6 @@ int avc_tuner_host2ca(struct firedtv *fd
 
 	mutex_lock(&fdtv->avc_mutex);
 
-	memset(c, 0, sizeof(*c));
-
 	c->ctype   = AVC_CTYPE_CONTROL;
 	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
 	c->opcode  = AVC_OPCODE_VENDOR;
@@ -890,8 +894,7 @@ int avc_tuner_host2ca(struct firedtv *fd
 	c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
 	c->operand[4] = 0; /* slot */
 	c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
-	c->operand[6] = 0; /* more/last */
-	c->operand[7] = 0; /* length */
+	clear_operands(c, 6, 8);
 
 	fdtv->avc_data_length = 12;
 	ret = avc_write(fdtv);
@@ -937,8 +940,6 @@ int avc_ca_app_info(struct firedtv *fdtv
 
 	mutex_lock(&fdtv->avc_mutex);
 
-	memset(c, 0, sizeof(*c));
-
 	c->ctype   = AVC_CTYPE_STATUS;
 	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
 	c->opcode  = AVC_OPCODE_VENDOR;
@@ -949,6 +950,7 @@ int avc_ca_app_info(struct firedtv *fdtv
 	c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
 	c->operand[4] = 0; /* slot */
 	c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
+	clear_operands(c, 6, LAST_OPERAND);
 
 	fdtv->avc_data_length = 12;
 	ret = avc_write(fdtv);
@@ -979,8 +981,6 @@ int avc_ca_info(struct firedtv *fdtv, ch
 
 	mutex_lock(&fdtv->avc_mutex);
 
-	memset(c, 0, sizeof(*c));
-
 	c->ctype   = AVC_CTYPE_STATUS;
 	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
 	c->opcode  = AVC_OPCODE_VENDOR;
@@ -991,6 +991,7 @@ int avc_ca_info(struct firedtv *fdtv, ch
 	c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
 	c->operand[4] = 0; /* slot */
 	c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
+	clear_operands(c, 6, LAST_OPERAND);
 
 	fdtv->avc_data_length = 12;
 	ret = avc_write(fdtv);
@@ -1020,8 +1021,6 @@ int avc_ca_reset(struct firedtv *fdtv)
 
 	mutex_lock(&fdtv->avc_mutex);
 
-	memset(c, 0, sizeof(*c));
-
 	c->ctype   = AVC_CTYPE_CONTROL;
 	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
 	c->opcode  = AVC_OPCODE_VENDOR;
@@ -1064,8 +1063,6 @@ int avc_ca_pmt(struct firedtv *fdtv, cha
 
 	mutex_lock(&fdtv->avc_mutex);
 
-	memset(c, 0, sizeof(*c));
-
 	c->ctype   = AVC_CTYPE_CONTROL;
 	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
 	c->opcode  = AVC_OPCODE_VENDOR;
@@ -1096,7 +1093,7 @@ int avc_ca_pmt(struct firedtv *fdtv, cha
 
 	c->operand[12] = 0x02; /* Table id=2 */
 	c->operand[13] = 0x80; /* Section syntax + length */
-	/* c->operand[14] = XXXprogram_info_length + 12; */
+
 	c->operand[15] = msg[1]; /* Program number */
 	c->operand[16] = msg[2];
 	c->operand[17] = 0x01; /* Version number=0 + current/next=1 */
@@ -1144,12 +1141,7 @@ int avc_ca_pmt(struct firedtv *fdtv, cha
 			write_pos += es_info_length;
 		}
 	}
-
-	/* CRC */
-	c->operand[write_pos++] = 0x00;
-	c->operand[write_pos++] = 0x00;
-	c->operand[write_pos++] = 0x00;
-	c->operand[write_pos++] = 0x00;
+	write_pos += 4; /* CRC */
 
 	c->operand[7] = 0x82;
 	c->operand[8] = (write_pos - 10) >> 8;
@@ -1161,6 +1153,7 @@ int avc_ca_pmt(struct firedtv *fdtv, cha
 	c->operand[write_pos - 3] = (crc32_csum >> 16) & 0xff;
 	c->operand[write_pos - 2] = (crc32_csum >>  8) & 0xff;
 	c->operand[write_pos - 1] = (crc32_csum >>  0) & 0xff;
+	pad_operands(c, write_pos);
 
 	fdtv->avc_data_length = ALIGN(3 + write_pos, 4);
 	ret = avc_write(fdtv);
@@ -1186,8 +1179,6 @@ int avc_ca_get_time_date(struct firedtv 
 
 	mutex_lock(&fdtv->avc_mutex);
 
-	memset(c, 0, sizeof(*c));
-
 	c->ctype   = AVC_CTYPE_STATUS;
 	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
 	c->opcode  = AVC_OPCODE_VENDOR;
@@ -1198,8 +1189,7 @@ int avc_ca_get_time_date(struct firedtv 
 	c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
 	c->operand[4] = 0; /* slot */
 	c->operand[5] = SFE_VENDOR_TAG_CA_DATE_TIME; /* ca tag */
-	c->operand[6] = 0; /* more/last */
-	c->operand[7] = 0; /* length */
+	clear_operands(c, 6, LAST_OPERAND);
 
 	fdtv->avc_data_length = 12;
 	ret = avc_write(fdtv);
@@ -1222,8 +1212,6 @@ int avc_ca_enter_menu(struct firedtv *fd
 
 	mutex_lock(&fdtv->avc_mutex);
 
-	memset(c, 0, sizeof(*c));
-
 	c->ctype   = AVC_CTYPE_STATUS;
 	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
 	c->opcode  = AVC_OPCODE_VENDOR;
@@ -1234,8 +1222,7 @@ int avc_ca_enter_menu(struct firedtv *fd
 	c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
 	c->operand[4] = 0; /* slot */
 	c->operand[5] = SFE_VENDOR_TAG_CA_ENTER_MENU;
-	c->operand[6] = 0; /* more/last */
-	c->operand[7] = 0; /* length */
+	clear_operands(c, 6, 8);
 
 	fdtv->avc_data_length = 12;
 	ret = avc_write(fdtv);
@@ -1255,8 +1242,6 @@ int avc_ca_get_mmi(struct firedtv *fdtv,
 
 	mutex_lock(&fdtv->avc_mutex);
 
-	memset(c, 0, sizeof(*c));
-
 	c->ctype   = AVC_CTYPE_STATUS;
 	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
 	c->opcode  = AVC_OPCODE_VENDOR;
@@ -1267,8 +1252,7 @@ int avc_ca_get_mmi(struct firedtv *fdtv,
 	c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
 	c->operand[4] = 0; /* slot */
 	c->operand[5] = SFE_VENDOR_TAG_CA_MMI;
-	c->operand[6] = 0; /* more/last */
-	c->operand[7] = 0; /* length */
+	clear_operands(c, 6, LAST_OPERAND);
 
 	fdtv->avc_data_length = 12;
 	ret = avc_write(fdtv);

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


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

* Re: [PATCH 0/6] DVB: firedtv: simplifications and a portability fix
  2009-11-18 19:00 [PATCH 0/6] DVB: firedtv: simplifications and a portability fix Stefan Richter
                   ` (5 preceding siblings ...)
  2009-11-18 19:03 ` [PATCH 6/6] firedtv: reduce memset()s Stefan Richter
@ 2009-11-21  0:26 ` Stefan Richter
  6 siblings, 0 replies; 8+ messages in thread
From: Stefan Richter @ 2009-11-21  0:26 UTC (permalink / raw)
  To: linux-media, Mauro Carvalho Chehab; +Cc: linux1394-devel, linux-kernel

On 18 Nov, Stefan Richter wrote:
> The following three patches are applicable after "firedtv: port to new
> firewire core" from 2009-11-08:
...
> The rest of this patch set additionally requires the latest firedtv as
> of 2.6.32-rc7:
...

I updated the "firedtv" branch at

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

now (based on v2.6.31 but having a merge from v2.6.32-rc8 in it due to
above mentioned requirement).

Mauro, please harvest the posted 4 + 6 patches from the mailing list, or
pull or cherry-pick them from linux1394-2.6.git firedtv.  Thanks.

Stefan Richter (11):
      firedtv: move remote control workqueue handling into rc source file
      firedtv: reform lock transaction backend call
      firedtv: add missing include, rename a constant
      firedtv: port to new firewire core
      firedtv: shrink buffer pointer table
      firedtv: packet requeuing is likely to succeed
      firedtv: remove an unnecessary function argument
      Merge tag 'v2.6.32-rc8' into firedtv
      firedtv: do not DMA-map stack addresses
      firedtv: remove check for interrupting signal
      firedtv: reduce memset()s

 drivers/media/dvb/firewire/Kconfig        |    7 +-
 drivers/media/dvb/firewire/Makefile       |    1 +
 drivers/media/dvb/firewire/firedtv-1394.c |   42 +-
 drivers/media/dvb/firewire/firedtv-avc.c  |  566 +++++++++++----------
 drivers/media/dvb/firewire/firedtv-dvb.c  |   16 +-
 drivers/media/dvb/firewire/firedtv-fw.c   |  376 ++++++++++++++
 drivers/media/dvb/firewire/firedtv-rc.c   |    2 +
 drivers/media/dvb/firewire/firedtv.h      |   23 +-
 8 files changed, 746 insertions(+), 287 deletions(-)
-- 
Stefan Richter
-=====-==--= =-== =-=-=
http://arcgraph.de/sr/


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

end of thread, other threads:[~2009-11-21  0:28 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-11-18 19:00 [PATCH 0/6] DVB: firedtv: simplifications and a portability fix Stefan Richter
2009-11-18 19:00 ` [PATCH 1/6] firedtv: shrink buffer pointer table Stefan Richter
2009-11-18 19:01 ` [PATCH 2/6] firedtv: packet requeuing is likely to succeed Stefan Richter
2009-11-18 19:01 ` [PATCH 3/6] firedtv: remove an unnecessary function argument Stefan Richter
2009-11-18 19:02 ` [PATCH 4/6] firedtv: do not DMA-map stack addresses Stefan Richter
2009-11-18 19:03 ` [PATCH 5/6] firedtv: remove check for interrupting signal Stefan Richter
2009-11-18 19:03 ` [PATCH 6/6] firedtv: reduce memset()s Stefan Richter
2009-11-21  0:26 ` [PATCH 0/6] DVB: firedtv: simplifications and a portability fix Stefan Richter

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®