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/ --
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, ...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/
--
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 ...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 ...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 ...
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;
} ......
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/
--
