LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [GIT PULL] FireWire update
@ 2007-11-07  1:20 Stefan Richter
  0 siblings, 0 replies; 9+ messages in thread
From: Stefan Richter @ 2007-11-07  1:20 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Andrew Morton, linux-kernel, linux1394-devel

Linus, please pull from the for-linus branch at

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

to receive the following fix for a regression since 2.6.24-rc1.
(Or apply from this e-mail.)

 drivers/firewire/fw-sbp2.c |   11 +++++++----
 1 files changed, 7 insertions(+), 4 deletions(-)

Stefan Richter (1):
      firewire: fw-sbp2: fix refcounting


Full log and diff:

commit 7c45d1913f0a1d597eb4bc3b2c962bc2967da9ea
Author: Stefan Richter <stefanr@s5r6.in-berlin.de>
Date:   Wed Nov 7 01:11:56 2007 +0100

    firewire: fw-sbp2: fix refcounting
    
    Since patch "fw-sbp2: use an own workqueue (fix system responsiveness)"
    increased parallelism between fw-sbp2 and fw-core, it was possible that
    fw-sbp2 didn't release the SCSI device when the FireWire device was
    disconnected.
    
    This happened if sbp2_update() ran during sbp2_login(), because a bus
    reset occurred during sbp2_login().  The sbp2_login() work would [try
    to] reschedule itself because it failed due to the bus reset, and it
    would _not_ drop its reference on the target.  However, sbp2_update()
    would schedule sbp2_login() too before sbp2_login() rescheduled itself
    and hence sbp2_update() would take an additional reference.  And then
    we would have one reference too many.
    
    The fix is to _always_ drop the reference when leaving the sbp2_login()
    work.  If the sbp2_login() work reschedules itself, it takes a
    reference, but only if it wasn't already rescheduled by sbp2_update().
    
    Ditto in the sbp2_reconnect() work.
    
    The resulting code is actually simpler than before:  We _always_ take
    a reference when successfully scheduling work.  And we _always_ drop
    a reference when leaving a workqueue job.  No exceptions.
    
    Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>

diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c
index 5596df6..624ff3e 100644
--- a/drivers/firewire/fw-sbp2.c
+++ b/drivers/firewire/fw-sbp2.c
@@ -650,13 +650,14 @@ static void sbp2_login(struct work_struct *work)
 	if (sbp2_send_management_orb(lu, node_id, generation,
 				SBP2_LOGIN_REQUEST, lu->lun, &response) < 0) {
 		if (lu->retries++ < 5) {
-			queue_delayed_work(sbp2_wq, &lu->work,
-					   DIV_ROUND_UP(HZ, 5));
+			if (queue_delayed_work(sbp2_wq, &lu->work,
+					       DIV_ROUND_UP(HZ, 5)))
+				kref_get(&lu->tgt->kref);
 		} else {
 			fw_error("failed to login to %s LUN %04x\n",
 				 unit->device.bus_id, lu->lun);
-			kref_put(&lu->tgt->kref, sbp2_release_target);
 		}
+		kref_put(&lu->tgt->kref, sbp2_release_target);
 		return;
 	}
 
@@ -914,7 +915,9 @@ static void sbp2_reconnect(struct work_struct *work)
 			lu->retries = 0;
 			PREPARE_DELAYED_WORK(&lu->work, sbp2_login);
 		}
-		queue_delayed_work(sbp2_wq, &lu->work, DIV_ROUND_UP(HZ, 5));
+		if (queue_delayed_work(sbp2_wq, &lu->work, DIV_ROUND_UP(HZ, 5)))
+			kref_get(&lu->tgt->kref);
+		kref_put(&lu->tgt->kref, sbp2_release_target);
 		return;
 	}
 

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


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

* [git pull] FireWire update
@ 2011-07-11 13:42 Stefan Richter
  0 siblings, 0 replies; 9+ messages in thread
From: Stefan Richter @ 2011-07-11 13:42 UTC (permalink / raw)
  To: Linus Torvalds, Andrew Morton; +Cc: linux-kernel, linux1394-devel

Linus, please pull from the movieboard branch at

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

to receive the following quirks workaround for the IEEE 1394 (FireWire)
subsystem.  This is a hopefully temporary bandaid for a comparably rare
piece of hardware.

Thanks.

Stefan Richter (1):
      firewire: ohci: do not bind to Pinnacle cards, avert panic

 drivers/firewire/ohci.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)


commit 7f7e37115a8b6724f26d0637a04e1d35e3c59717
Author: Stefan Richter <stefanr@s5r6.in-berlin.de>
Date:   Sun Jul 10 00:23:03 2011 +0200

    firewire: ohci: do not bind to Pinnacle cards, avert panic
    
    When firewire-ohci is bound to a Pinnacle MovieBoard, eventually a
    "Register access failure" is logged and an interrupt storm or a kernel
    panic happens.  https://bugzilla.kernel.org/show_bug.cgi?id=36622
    
    Until this is sorted out (if that is going to succeed at all), let's
    just prevent firewire-ohci from touching these devices.
    
    Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
    Cc: <stable@kernel.org>

diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index 438e6c8..ebb8973 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -264,6 +264,7 @@ static char ohci_driver_name[] = KBUILD_MODNAME;
 #define PCI_DEVICE_ID_AGERE_FW643      0x5901
 #define PCI_DEVICE_ID_JMICRON_JMB38X_FW        0x2380
 #define PCI_DEVICE_ID_TI_TSB12LV22     0x8009
+#define PCI_VENDOR_ID_PINNACLE_SYSTEMS 0x11bd
 
 #define QUIRK_CYCLE_TIMER              1
 #define QUIRK_RESET_PACKET             2
@@ -3190,6 +3191,11 @@ static int __devinit pci_probe(struct pci_dev *dev,
        int i, err;
        size_t size;
 
+       if (dev->vendor == PCI_VENDOR_ID_PINNACLE_SYSTEMS) {
+               dev_err(&dev->dev, "Pinnacle MovieBoard is not yet supported\n");
+               return -ENOSYS;
+       }
+
        ohci = kzalloc(sizeof(*ohci), GFP_KERNEL);
        if (ohci == NULL) {
                err = -ENOMEM;

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

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

* [GIT PULL] firewire update
@ 2008-06-27 19:05 Stefan Richter
  0 siblings, 0 replies; 9+ messages in thread
From: Stefan Richter @ 2008-06-27 19:05 UTC (permalink / raw)
  To: Linus Torvalds, Andrew Morton; +Cc: linux-kernel, linux1394-devel

Linus, please pull from the for-linus branch at

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

to receive the following one-liner.

Richard Sharpe (1):
      firewire: fw-sbp2: fix parsing of logical unit directories

 drivers/firewire/fw-sbp2.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)


commit 0e3e2eabf4fbc0162e1f1eb4fd90cb3e9513a554
Author: Richard Sharpe <realrichardsharpe@gmail.com>
Date:   Tue Jun 24 19:11:13 2008 -0700

    firewire: fw-sbp2: fix parsing of logical unit directories
    
    There is a small off-by-one bug in firewire-sbp2. This causes problems
    when a device exports multiple LUN Directories. I found it when trying
    to talk to a SONY DVD Jukebox.
    
    Signed-off-by: Richard Sharpe <realrichardsharpe@gmail.com>
    Acked-by: Kristian Høgsberg <krh@redhat.com>
    Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de> (op. order, changelog)

diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c
index b2458bb..227d2e0 100644
--- a/drivers/firewire/fw-sbp2.c
+++ b/drivers/firewire/fw-sbp2.c
@@ -1051,7 +1051,8 @@ static int sbp2_scan_unit_dir(struct sbp2_target *tgt, u32 *directory,
 			break;
 
 		case SBP2_CSR_LOGICAL_UNIT_DIRECTORY:
-			if (sbp2_scan_logical_unit_dir(tgt, ci.p + value) < 0)
+			/* Adjust for the increment in the iterator */
+			if (sbp2_scan_logical_unit_dir(tgt, ci.p - 1 + value) < 0)
 				return -ENOMEM;
 			break;
 		}
-- 
Stefan Richter
-=====-==--- -==- ==-==
http://arcgraph.de/sr/


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

* Re: [GIT PULL] FireWire update
  2008-03-27 20:37           ` Stefan Richter
@ 2008-03-31  8:46             ` Stefan Richter
  0 siblings, 0 replies; 9+ messages in thread
From: Stefan Richter @ 2008-03-31  8:46 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Andrew Morton, linux-kernel, linux1394-devel

I wrote:
> Linus, please pull from the for-linus branch at
> 
>     git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6.git for-linus
> 
> to receive the following update for the firewire subsystem.
> 
>  drivers/firewire/fw-ohci.c |    9 +++++----
>  1 files changed, 5 insertions(+), 4 deletions(-)
> 
> Jarod Wilson (1):
>       firewire: fw-ohci: plug dma memory leak in AR handler

Ping.

This stops firewire-ohci from feeding random arguments to 
dma_free_coherent().
-- 
Stefan Richter
-=====-==--- --== =====
http://arcgraph.de/sr/

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

* [GIT PULL] FireWire update
  2008-03-20 17:28         ` [GIT PULL] FireWire update Stefan Richter
@ 2008-03-27 20:37           ` Stefan Richter
  2008-03-31  8:46             ` Stefan Richter
  0 siblings, 1 reply; 9+ messages in thread
From: Stefan Richter @ 2008-03-27 20:37 UTC (permalink / raw)
  To: Linus Torvalds, Andrew Morton; +Cc: linux-kernel, linux1394-devel

Linus, please pull from the for-linus branch at

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

to receive the following update for the firewire subsystem.

 drivers/firewire/fw-ohci.c |    9 +++++----
 1 files changed, 5 insertions(+), 4 deletions(-)

Jarod Wilson (1):
      firewire: fw-ohci: plug dma memory leak in AR handler


commit 6b84236d37ef602d1e4f52b27162c20394e83359
Author: Jarod Wilson <jwilson@redhat.com>
Date:   Tue Mar 25 16:47:16 2008 -0400

    firewire: fw-ohci: plug dma memory leak in AR handler
    
    There's an ugly little memory leak in firewire-ohci's
    ar_context_tasklet(), where we're not freeing up some of the memory we
    use for each ar_buffer, due to a moving pointer. The problem has been
    there for a while, but didn't get noticed until after converting the AR
    routines over to use coherent DMA and I started running into I/O stall-
    outs with the following message output repeatedly to the console:
    
    PCI-DMA: Out of IOMMU space for 53248 bytes at device 0000:04:09.0
    
    Plugging this leak is definitely necessary, but unfortunately, isn't the
    entire answer to my problem, it only increases the amount of I/O that I
    can do before hitting the problem. Still working on tracking down the
    root cause..
    
    Signed-off-by: Jarod Wilson <jwilson@redhat.com>
    Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>

diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c
index 996d61f..ca6d51e 100644
--- a/drivers/firewire/fw-ohci.c
+++ b/drivers/firewire/fw-ohci.c
@@ -401,7 +401,8 @@ static void ar_context_tasklet(unsigned long data)
 
 	if (d->res_count == 0) {
 		size_t size, rest, offset;
-		dma_addr_t buffer_bus;
+		dma_addr_t start_bus;
+		void *start;
 
 		/*
 		 * This descriptor is finished and we may have a
@@ -410,9 +411,9 @@ static void ar_context_tasklet(unsigned long data)
 		 */
 
 		offset = offsetof(struct ar_buffer, data);
-		buffer_bus = le32_to_cpu(ab->descriptor.data_address) - offset;
+		start = buffer = ab;
+		start_bus = le32_to_cpu(ab->descriptor.data_address) - offset;
 
-		buffer = ab;
 		ab = ab->next;
 		d = &ab->descriptor;
 		size = buffer + PAGE_SIZE - ctx->pointer;
@@ -427,7 +428,7 @@ static void ar_context_tasklet(unsigned long data)
 			buffer = handle_ar_packet(ctx, buffer);
 
 		dma_free_coherent(ohci->card.device, PAGE_SIZE,
-				  buffer, buffer_bus);
+				  start, start_bus);
 		ar_context_add_page(ctx);
 	} else {
 		buffer = ctx->pointer;

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


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

* [GIT PULL] FireWire update
  2008-03-14 18:07       ` Stefan Richter
@ 2008-03-20 17:28         ` Stefan Richter
  2008-03-27 20:37           ` Stefan Richter
  0 siblings, 1 reply; 9+ messages in thread
From: Stefan Richter @ 2008-03-20 17:28 UTC (permalink / raw)
  To: Linus Torvalds, Andrew Morton; +Cc: linux-kernel, linux1394-devel

Linus, please pull from the for-linus branch at

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

to receive the following update for the firewire subsystem.

 drivers/firewire/fw-transaction.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

Stefan Richter (1):
      firewire: fix panic in handle_at_packet


commit 10a4c735515a5afc317abe4d697a4c95f6d9d764
Author: Stefan Richter <stefanr@s5r6.in-berlin.de>
Date:   Sun Mar 16 00:56:41 2008 +0100

    firewire: fix panic in handle_at_packet
    
    This fixes a use-after-free bug in the handling of split transactions.
    The AT DMA handler of the request was occasionally executed after the
    AR DMA handler of the response.  The AT DMA handler then accessed an
    already freed packet.
    
    Reported by Johannes Berg.
    http://bugzilla.kernel.org/show_bug.cgi?id=9617
    
    Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
    Tested-by: Johannes Berg <johannes@sipsolutions.net>
    Signed-off-by: Jarod Wilson <jwilson@redhat.com>

diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c
index 99529e5..e6f1bda 100644
--- a/drivers/firewire/fw-transaction.c
+++ b/drivers/firewire/fw-transaction.c
@@ -736,6 +736,12 @@ fw_core_handle_response(struct fw_card *card, struct fw_packet *p)
 		break;
 	}
 
+	/*
+	 * The response handler may be executed while the request handler
+	 * is still pending.  Cancel the request handler.
+	 */
+	card->driver->cancel_packet(card, &t->packet);
+
 	t->callback(card, rcode, data, data_length, t->callback_data);
 }
 EXPORT_SYMBOL(fw_core_handle_response);


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


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

* Re: [GIT PULL] FireWire update
       [not found] ` <59ad55d30712110818u2717b329j80778ec7cc290988@mail.gmail.com>
@ 2007-12-11 17:40   ` Stefan Richter
  0 siblings, 0 replies; 9+ messages in thread
From: Stefan Richter @ 2007-12-11 17:40 UTC (permalink / raw)
  To: Kristian Høgsberg
  Cc: Linus Torvalds, Andrew Morton, linux1394-devel, linux-kernel

Kristian Høgsberg wrote:
> On Dec 10, 2007 4:25 PM, Stefan Richter <stefanr@s5r6.in-berlin.de> wrote:
>> This considerably enhances compatibility of the new firewire-ohci driver
...
> And I worked with Jarod on this so I'll add a
> 
> Signed-off-by: Kristian Høgsberg <krh@redhat.com>

The commit already went public; nevertheless I much appreciate the
sign-off and your work on the OHCI 1.0 issue.  Thanks.
-- 
Stefan Richter
-=====-=-=== ==-- -=-==
http://arcgraph.de/sr/

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

* [GIT PULL] FireWire update
@ 2007-12-10 21:25 Stefan Richter
       [not found] ` <59ad55d30712110818u2717b329j80778ec7cc290988@mail.gmail.com>
  0 siblings, 1 reply; 9+ messages in thread
From: Stefan Richter @ 2007-12-10 21:25 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Andrew Morton, linux-kernel, linux1394-devel

Linus, please pull from the for-linus branch at

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

to receive the following FireWire subsystem update.

This considerably enhances compatibility of the new firewire-ohci driver
with a number of controllers.  It shrinks the list of chips with trouble
with isochronous reception to VIA VT6306 and some variants of VT6307.

The patch is somewhat big for this late -rc phase, and it has so far only
surfaced in 2.6.24-rc4-mm1 and in recent Fedora test kernels.  But the
author and I did a lot of tests with as much previously working chips as
we could get our hands on (some more than listed below) to make sure that
there is no regression.  

 drivers/firewire/fw-ohci.c |  175 +++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 155 insertions(+), 20 deletions(-)

Jarod Wilson (1):
      firewire: OHCI 1.0 Isochronous Receive support


Full log and diff:

commit a186b4a6b22fdc96a1ed63da483d267b5d00839e
Author: Jarod Wilson <jwilson@redhat.com>
Date:   Mon Dec 3 13:43:12 2007 -0500

    firewire: OHCI 1.0 Isochronous Receive support
    
    Third rendition of FireWire OHCI 1.0 Isochronous Receive support, using a
    zer-copy method similar to OHCI 1.1 which puts the IR data payload directly
    into the userspace buffer. The zero-copy implementation eliminates the
    video artifacts, audio popping, and buffer underrun problems seen with
    version 1 of this patch, as well as fixing a regression in OHCI 1.1 support
    introduced by version 2 of this patch.
    
    Successfully tested in OHCI 1.1 mode on the following chipsets:
    
    - NEC uPD72847 (rev 01), OHCI 1.1 (PCI)
    - Ti XIO2200(A) (rev 01), OHCI 1.1 (PCIe)
    - Ti TSB41AB2 (rev 01), OHCI 1.1 (PCI on SB Audigy)
    - Apple UniNorth 2 (rev 81), OHCI 1.1 (PowerBook G4 onboard)
    
    Successfully tested in OHCI 1.0 mode on the following chipsets:
    
    - Agere FW323 (rev 06), OHCI 1.0 (Mac Mini onboard)
    - Agere FW323 (rev 06), OHCI 1.0 (PCI)
    - Via VT6306 (rev 46), OHCI 1.0 (PCI)
    - NEC OrangeLink (rev 01), OHCI 1.0 (PCI)
    - NEC uPD72847 (rev 01), OHCI 1.1 (PCI)
    - Ti XIO2200(A) (rev 01), OHCI 1.1 (PCIe)
    
    The bulk of testing was done in an x86_64 system, but was also successfully
    sanity-tested on other systems, including a PPC(32) PowerBook G4 and an i686
    EPIA M10k. Crude benchmarking (watching top during capture) puts the cpu
    utilization during capture on the EPIA's 1GHz Via C3 processor around 13%,
    which is down from 30% with the v1 code.
    
    Some implementation details:
    
    To maintain the same userspace API as dual-buffer mode, we set up two
    descriptors for every incoming packet. The first is an INPUT_MORE descriptor,
    pointing to a buffer large enough to hold just the packet's iso headers,
    immediately followed by an INPUT_LAST descriptor, pointing to a chunk of the
    userspace buffer big enough for the packet's data payload. With this setup,
    each incoming packet fills in these two descriptors in a manner that very
    closely emulates dual-buffer receive, to the point where the bulk of the
    handle_ir_* code is now identical between the two (and probably primed for
    some restructuring to share code between them).
    
    The only caveat I have at the moment is that neither of my OHCI 1.0 Via
    VT6307-based FireWire controllers work particularly well with this code
    for reasons I have yet to figure out.
    
    Signed-off-by: Jarod Wilson <jwilson@redhat.com>
    Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>

diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c
index c9b9081..436a855 100644
--- a/drivers/firewire/fw-ohci.c
+++ b/drivers/firewire/fw-ohci.c
@@ -437,6 +437,21 @@ static void ar_context_run(struct ar_context *ctx)
 	flush_writes(ctx->ohci);
 }
 
+static struct descriptor *
+find_branch_descriptor(struct descriptor *d, int z)
+{
+	int b, key;
+
+	b   = (le16_to_cpu(d->control) & DESCRIPTOR_BRANCH_ALWAYS) >> 2;
+	key = (le16_to_cpu(d->control) & DESCRIPTOR_KEY_IMMEDIATE) >> 8;
+
+	/* figure out which descriptor the branch address goes in */
+	if (z == 2 && (b == 3 || key == 2))
+		return d;
+	else
+		return d + z - 1;
+}
+
 static void context_tasklet(unsigned long data)
 {
 	struct context *ctx = (struct context *) data;
@@ -455,7 +470,7 @@ static void context_tasklet(unsigned long data)
 		address = le32_to_cpu(last->branch_address);
 		z = address & 0xf;
 		d = ctx->buffer + (address - ctx->buffer_bus) / sizeof(*d);
-		last = (z == 2) ? d : d + z - 1;
+		last = find_branch_descriptor(d, z);
 
 		if (!ctx->callback(ctx, d, last))
 			break;
@@ -566,7 +581,7 @@ static void context_append(struct context *ctx,
 
 	ctx->head_descriptor = d + z + extra;
 	ctx->prev_descriptor->branch_address = cpu_to_le32(d_bus | z);
-	ctx->prev_descriptor = z == 2 ? d : d + z - 1;
+	ctx->prev_descriptor = find_branch_descriptor(d, z);
 
 	dma_sync_single_for_device(ctx->ohci->card.device, ctx->buffer_bus,
 				   ctx->buffer_size, DMA_TO_DEVICE);
@@ -655,7 +670,7 @@ at_context_queue_packet(struct context *ctx, struct fw_packet *packet)
 	driver_data = (struct driver_data *) &d[3];
 	driver_data->packet = packet;
 	packet->driver_data = driver_data;
-	
+
 	if (packet->payload_length > 0) {
 		payload_bus =
 			dma_map_single(ohci->card.device, packet->payload,
@@ -903,7 +918,7 @@ at_context_transmit(struct context *ctx, struct fw_packet *packet)
 
 	if (retval < 0)
 		packet->callback(packet, &ctx->ohci->card, packet->ack);
-	
+
 }
 
 static void bus_reset_tasklet(unsigned long data)
@@ -1431,6 +1446,57 @@ static int handle_ir_dualbuffer_packet(struct context *context,
 	return 1;
 }
 
+static int handle_ir_packet_per_buffer(struct context *context,
+				       struct descriptor *d,
+				       struct descriptor *last)
+{
+	struct iso_context *ctx =
+		container_of(context, struct iso_context, context);
+	struct descriptor *pd = d + 1;
+	__le32 *ir_header;
+	size_t header_length;
+	void *p, *end;
+	int i, z;
+
+	if (pd->res_count == pd->req_count)
+		/* Descriptor(s) not done yet, stop iteration */
+		return 0;
+
+	header_length = le16_to_cpu(d->req_count);
+
+	i   = ctx->header_length;
+	z   = le32_to_cpu(pd->branch_address) & 0xf;
+	p   = d + z;
+	end = p + header_length;
+
+	while (p < end && i + ctx->base.header_size <= PAGE_SIZE) {
+		/*
+		 * The iso header is byteswapped to little endian by
+		 * the controller, but the remaining header quadlets
+		 * are big endian.  We want to present all the headers
+		 * as big endian, so we have to swap the first quadlet.
+		 */
+		*(u32 *) (ctx->header + i) = __swab32(*(u32 *) (p + 4));
+		memcpy(ctx->header + i + 4, p + 8, ctx->base.header_size - 4);
+		i += ctx->base.header_size;
+		p += ctx->base.header_size + 4;
+	}
+
+	ctx->header_length = i;
+
+	if (le16_to_cpu(pd->control) & DESCRIPTOR_IRQ_ALWAYS) {
+		ir_header = (__le32 *) (d + z);
+		ctx->base.callback(&ctx->base,
+				   le32_to_cpu(ir_header[0]) & 0xffff,
+				   ctx->header_length, ctx->header,
+				   ctx->base.callback_data);
+		ctx->header_length = 0;
+	}
+
+
+	return 1;
+}
+
 static int handle_it_packet(struct context *context,
 			    struct descriptor *d,
 			    struct descriptor *last)
@@ -1466,14 +1532,12 @@ ohci_allocate_iso_context(struct fw_card *card, int type, size_t header_size)
 	} else {
 		mask = &ohci->ir_context_mask;
 		list = ohci->ir_context_list;
-		callback = handle_ir_dualbuffer_packet;
+		if (ohci->version >= OHCI_VERSION_1_1)
+			callback = handle_ir_dualbuffer_packet;
+		else
+			callback = handle_ir_packet_per_buffer;
 	}
 
-	/* FIXME: We need a fallback for pre 1.1 OHCI. */
-	if (callback == handle_ir_dualbuffer_packet &&
-	    ohci->version < OHCI_VERSION_1_1)
-		return ERR_PTR(-ENOSYS);
-
 	spin_lock_irqsave(&ohci->lock, flags);
 	index = ffs(*mask) - 1;
 	if (index >= 0)
@@ -1532,7 +1596,9 @@ static int ohci_start_iso(struct fw_iso_context *base,
 		context_run(&ctx->context, match);
 	} else {
 		index = ctx - ohci->ir_context_list;
-		control = IR_CONTEXT_DUAL_BUFFER_MODE | IR_CONTEXT_ISOCH_HEADER;
+		control = IR_CONTEXT_ISOCH_HEADER;
+		if (ohci->version >= OHCI_VERSION_1_1)
+			control |= IR_CONTEXT_DUAL_BUFFER_MODE;
 		match = (tags << 28) | (sync << 8) | ctx->base.channel;
 		if (cycle >= 0) {
 			match |= (cycle & 0x07fff) << 12;
@@ -1738,7 +1804,6 @@ ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base,
 	offset   = payload & ~PAGE_MASK;
 	rest     = p->payload_length;
 
-	/* FIXME: OHCI 1.0 doesn't support dual buffer receive */
 	/* FIXME: make packet-per-buffer/dual-buffer a context option */
 	while (rest > 0) {
 		d = context_get_descriptors(&ctx->context,
@@ -1777,6 +1842,81 @@ ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base,
 }
 
 static int
+ohci_queue_iso_receive_packet_per_buffer(struct fw_iso_context *base,
+					 struct fw_iso_packet *packet,
+					 struct fw_iso_buffer *buffer,
+					 unsigned long payload)
+{
+	struct iso_context *ctx = container_of(base, struct iso_context, base);
+	struct descriptor *d = NULL, *pd = NULL;
+	struct fw_iso_packet *p;
+	dma_addr_t d_bus, page_bus;
+	u32 z, header_z, rest;
+	int i, page, offset, packet_count, header_size;
+
+	if (packet->skip) {
+		d = context_get_descriptors(&ctx->context, 1, &d_bus);
+		if (d == NULL)
+			return -ENOMEM;
+
+		d->control = cpu_to_le16(DESCRIPTOR_STATUS |
+					 DESCRIPTOR_INPUT_LAST |
+					 DESCRIPTOR_BRANCH_ALWAYS |
+					 DESCRIPTOR_WAIT);
+		context_append(&ctx->context, d, 1, 0);
+	}
+
+	/* one descriptor for header, one for payload */
+	/* FIXME: handle cases where we need multiple desc. for payload */
+	z = 2;
+	p = packet;
+
+	/*
+	 * The OHCI controller puts the status word in the
+	 * buffer too, so we need 4 extra bytes per packet.
+	 */
+	packet_count = p->header_length / ctx->base.header_size;
+	header_size  = packet_count * (ctx->base.header_size + 4);
+
+	/* Get header size in number of descriptors. */
+	header_z = DIV_ROUND_UP(header_size, sizeof(*d));
+	page     = payload >> PAGE_SHIFT;
+	offset   = payload & ~PAGE_MASK;
+	rest     = p->payload_length;
+
+	for (i = 0; i < packet_count; i++) {
+		/* d points to the header descriptor */
+		d = context_get_descriptors(&ctx->context,
+					    z + header_z, &d_bus);
+		if (d == NULL)
+			return -ENOMEM;
+
+		d->control      = cpu_to_le16(DESCRIPTOR_INPUT_MORE);
+		d->req_count    = cpu_to_le16(header_size);
+		d->res_count    = d->req_count;
+		d->data_address = cpu_to_le32(d_bus + (z * sizeof(*d)));
+
+		/* pd points to the payload descriptor */
+		pd = d + 1;
+		pd->control = cpu_to_le16(DESCRIPTOR_STATUS |
+					  DESCRIPTOR_INPUT_LAST |
+					  DESCRIPTOR_BRANCH_ALWAYS);
+		if (p->interrupt)
+			pd->control |= cpu_to_le16(DESCRIPTOR_IRQ_ALWAYS);
+
+		pd->req_count = cpu_to_le16(rest);
+		pd->res_count = pd->req_count;
+
+		page_bus = page_private(buffer->pages[page]);
+		pd->data_address = cpu_to_le32(page_bus + offset);
+
+		context_append(&ctx->context, d, z, header_z);
+	}
+
+	return 0;
+}
+
+static int
 ohci_queue_iso(struct fw_iso_context *base,
 	       struct fw_iso_packet *packet,
 	       struct fw_iso_buffer *buffer,
@@ -1790,8 +1930,9 @@ ohci_queue_iso(struct fw_iso_context *base,
 		return ohci_queue_iso_receive_dualbuffer(base, packet,
 							 buffer, payload);
 	else
-		/* FIXME: Implement fallback for OHCI 1.0 controllers. */
-		return -ENOSYS;
+		return ohci_queue_iso_receive_packet_per_buffer(base, packet,
+								buffer,
+								payload);
 }
 
 static const struct fw_card_driver ohci_driver = {
@@ -1911,12 +2052,6 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
 	ohci->version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff;
 	fw_notify("Added fw-ohci device %s, OHCI version %x.%x\n",
 		  dev->dev.bus_id, ohci->version >> 16, ohci->version & 0xff);
-	if (ohci->version < OHCI_VERSION_1_1) {
-		fw_notify("    Isochronous I/O is not yet implemented for "
-			  "OHCI 1.0 chips.\n");
-		fw_notify("    Cameras, audio devices etc. won't work on "
-			  "this controller with this driver version.\n");
-	}
 	return 0;
 
  fail_self_id:

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


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

* [GIT PULL] FireWire update
@ 2007-11-04 13:41 Stefan Richter
  0 siblings, 0 replies; 9+ messages in thread
From: Stefan Richter @ 2007-11-04 13:41 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Andrew Morton, linux-kernel, linux1394-devel

Linus, please pull from the for-linus branch at

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

to receive the following IEEE 1394 subsystem update.
This fixes "2.6.24-rc1-54866.. fails to boot: kernel BUG at
include/linux/scatterlist.h:49!", bug# 9296.

 drivers/ieee1394/dma.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

Jens Axboe (1):
      ieee1394: iso and async streams: s/g list fix


Full log and diff:

commit 9e66269d40229cd9823024120910a43af57a9d72
Author: Jens Axboe <jens.axboe@oracle.com>
Date:   Sun Nov 4 09:44:56 2007 +0100

    ieee1394: iso and async streams: s/g list fix
    
    Torsten Kaiser wrote:
    > Looking that calltrace upwards, it seems replacing the
    > memset(dma->sglist,...) with sg_init_table(...) would fix the BUG_ON()
    > as that inits the SG_MAGIC.
    
    Tested-by: Torsten Kaiser <just.for.lkml@googlemail.com>
    Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>

diff --git a/drivers/ieee1394/dma.c b/drivers/ieee1394/dma.c
index f5f4983..7c4eb39 100644
--- a/drivers/ieee1394/dma.c
+++ b/drivers/ieee1394/dma.c
@@ -103,8 +103,7 @@ int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes,
 		goto err;
 	}
 
-	/* just to be safe - this will become unnecessary once sglist->address goes away */
-	memset(dma->sglist, 0, dma->n_pages * sizeof(*dma->sglist));
+	sg_init_table(dma->sglist, dma->n_pages);
 
 	/* fill scatter/gather list with pages */
 	for (i = 0; i < dma->n_pages; i++) {

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


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

end of thread, other threads:[~2011-07-11 13:43 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-11-07  1:20 [GIT PULL] FireWire update Stefan Richter
  -- strict thread matches above, loose matches on Subject: below --
2011-07-11 13:42 [git pull] " Stefan Richter
2008-06-27 19:05 [GIT PULL] firewire update Stefan Richter
2008-01-30 22:53 [GIT PULL] FireWire updates post 2.6.24 Stefan Richter
2008-02-02 13:05 ` [GIT PULL] IEEE 1394 regression fix Stefan Richter
2008-02-25 17:58   ` [GIT PULL] FireWire updates Stefan Richter
2008-03-02 12:47     ` Stefan Richter
2008-03-14 18:07       ` Stefan Richter
2008-03-20 17:28         ` [GIT PULL] FireWire update Stefan Richter
2008-03-27 20:37           ` Stefan Richter
2008-03-31  8:46             ` Stefan Richter
2007-12-10 21:25 Stefan Richter
     [not found] ` <59ad55d30712110818u2717b329j80778ec7cc290988@mail.gmail.com>
2007-12-11 17:40   ` Stefan Richter
2007-11-04 13:41 Stefan Richter

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).