public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [GIT PULL] FireWire fixes
@ 2007-08-02 18:52 Stefan Richter
  0 siblings, 0 replies; 21+ messages in thread
From: Stefan Richter @ 2007-08-02 18:52 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-kernel, linux1394-devel, Kristian Høgsberg

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 fixes for the new and old 1394 subsystems:

Stefan Richter (5):
      ieee1394: revert "sbp2: enforce 32bit DMA mapping"
      ieee1394: sbp2: more correct Kconfig dependencies
      firewire: fw-sbp2: set correct maximum payload (fixes CardBus adapters)
      firewire: fw-ohci: dma_free_coherent needs IRQs enabled
      firewire: fw-core: make two variables static


Stat, log, and combined diff:

 drivers/firewire/fw-ohci.c        |   20 +++++++++++++-------
 drivers/firewire/fw-sbp2.c        |    5 ++++-
 drivers/firewire/fw-transaction.c |    4 ++--
 drivers/firewire/fw-transaction.h |    2 +-
 drivers/ieee1394/Kconfig          |    2 +-
 drivers/ieee1394/sbp2.c           |    5 -----
 6 files changed, 21 insertions(+), 17 deletions(-)


commit ae57988f68acdc9fbee649765148f15eb7a1b991
Author: Stefan Richter <stefanr@s5r6.in-berlin.de>
Date:   Thu Aug 2 20:34:17 2007 +0200

    firewire: fw-core: make two variables static
    
    Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>

commit 4eaff7d63052d781732de9eff4d2287c8e00348f
Author: Stefan Richter <stefanr@s5r6.in-berlin.de>
Date:   Wed Jul 25 19:18:08 2007 +0200

    firewire: fw-ohci: dma_free_coherent needs IRQs enabled
    
    Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>

commit 25659f7183376c6b37661da6141d5eaa21479061
Author: Stefan Richter <stefanr@s5r6.in-berlin.de>
Date:   Sat Jul 21 22:43:05 2007 +0200

    firewire: fw-sbp2: set correct maximum payload (fixes CardBus adapters)
    
    As far as I know, all CardBus FireWire 400 adapters have a maximum
    payload of 1024 bytes which is less than the speed-dependent limit of
    2048 bytes.  Fw-sbp2 has to take the host adapter's limit into account.
    
    This apparently fixes Juju's incompatibility with my CardBus cards, a
    NEC based card and a VIA based card.
    
    Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
    Acked-by: Kristian Høgsberg <krh@redhat.com>

commit e4f8cac5e07528f7e0bc21d3682c16c9de993ecb
Author: Stefan Richter <stefanr@s5r6.in-berlin.de>
Date:   Sat Jul 21 17:51:22 2007 +0200

    ieee1394: sbp2: more correct Kconfig dependencies
    
    Make the option SBP2_PHYS_DMA available on all architectures where it
    compiles.  This includes x86-64 where I runtime-tested it successfully.
    
    Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>

commit a9c2f18800753c82c45fc13b27bdc148849bdbb2
Author: Stefan Richter <stefanr@s5r6.in-berlin.de>
Date:   Wed Aug 1 20:30:36 2007 +0200

    ieee1394: revert "sbp2: enforce 32bit DMA mapping"
    
    Revert commit 0555659d63c285ceb7ead3115532e1b71b0f27a7 from 2.6.22-rc1.
    The dma_set_mask call somehow failed on a PowerMac G5, PPC64:
    http://lkml.org/lkml/2007/8/1/344
    
    Should there ever occur a DMA mapping beyond the physical DMA range, a
    proper SBP-2 firmware will report transport errors.  So let's leave it
    at that.
    
    Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
    Tested-by: Olaf Hering <olh@suse.de>

diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c
index db70375..7e427b4 100644
--- a/drivers/firewire/fw-ohci.c
+++ b/drivers/firewire/fw-ohci.c
@@ -907,6 +907,8 @@ static void bus_reset_tasklet(unsigned long data)
 	int self_id_count, i, j, reg;
 	int generation, new_generation;
 	unsigned long flags;
+	void *free_rom = NULL;
+	dma_addr_t free_rom_bus = 0;
 
 	reg = reg_read(ohci, OHCI1394_NodeID);
 	if (!(reg & OHCI1394_NodeID_idValid)) {
@@ -970,8 +972,8 @@ static void bus_reset_tasklet(unsigned long data)
 	 */
 
 	if (ohci->next_config_rom != NULL) {
-		dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
-				  ohci->config_rom, ohci->config_rom_bus);
+		free_rom     = ohci->config_rom;
+		free_rom_bus = ohci->config_rom_bus;
 		ohci->config_rom      = ohci->next_config_rom;
 		ohci->config_rom_bus  = ohci->next_config_rom_bus;
 		ohci->next_config_rom = NULL;
@@ -990,6 +992,10 @@ static void bus_reset_tasklet(unsigned long data)
 
 	spin_unlock_irqrestore(&ohci->lock, flags);
 
+	if (free_rom)
+		dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
+				  free_rom, free_rom_bus);
+
 	fw_core_handle_bus_reset(&ohci->card, ohci->node_id, generation,
 				 self_id_count, ohci->self_id_buffer);
 }
@@ -1186,7 +1192,7 @@ ohci_set_config_rom(struct fw_card *card, u32 *config_rom, size_t length)
 {
 	struct fw_ohci *ohci;
 	unsigned long flags;
-	int retval = 0;
+	int retval = -EBUSY;
 	__be32 *next_config_rom;
 	dma_addr_t next_config_rom_bus;
 
@@ -1240,10 +1246,7 @@ ohci_set_config_rom(struct fw_card *card, u32 *config_rom, size_t length)
 
 		reg_write(ohci, OHCI1394_ConfigROMmap,
 			  ohci->next_config_rom_bus);
-	} else {
-		dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
-				  next_config_rom, next_config_rom_bus);
-		retval = -EBUSY;
+		retval = 0;
 	}
 
 	spin_unlock_irqrestore(&ohci->lock, flags);
@@ -1257,6 +1260,9 @@ ohci_set_config_rom(struct fw_card *card, u32 *config_rom, size_t length)
 	 */
 	if (retval == 0)
 		fw_core_initiate_bus_reset(&ohci->card, 1);
+	else
+		dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
+				  next_config_rom, next_config_rom_bus);
 
 	return retval;
 }
diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c
index 3e4a369..ba816ef 100644
--- a/drivers/firewire/fw-sbp2.c
+++ b/drivers/firewire/fw-sbp2.c
@@ -984,6 +984,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
 	struct fw_unit *unit = sd->unit;
 	struct fw_device *device = fw_device(unit->device.parent);
 	struct sbp2_command_orb *orb;
+	unsigned max_payload;
 
 	/*
 	 * Bidirectional commands are not yet implemented, and unknown
@@ -1017,8 +1018,10 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
 	 * specifies the max payload size as 2 ^ (max_payload + 2), so
 	 * if we set this to max_speed + 7, we get the right value.
 	 */
+	max_payload = min(device->max_speed + 7,
+			  device->card->max_receive - 1);
 	orb->request.misc =
-		COMMAND_ORB_MAX_PAYLOAD(device->max_speed + 7) |
+		COMMAND_ORB_MAX_PAYLOAD(max_payload) |
 		COMMAND_ORB_SPEED(device->max_speed) |
 		COMMAND_ORB_NOTIFY;
 
diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c
index 3ce8e2f..3e1cb12 100644
--- a/drivers/firewire/fw-transaction.c
+++ b/drivers/firewire/fw-transaction.c
@@ -734,7 +734,7 @@ fw_core_handle_response(struct fw_card *card, struct fw_packet *p)
 }
 EXPORT_SYMBOL(fw_core_handle_response);
 
-const struct fw_address_region topology_map_region =
+static const struct fw_address_region topology_map_region =
 	{ .start = 0xfffff0001000ull, .end = 0xfffff0001400ull, };
 
 static void
@@ -772,7 +772,7 @@ static struct fw_address_handler topology_map = {
 	.address_callback	= handle_topology_map,
 };
 
-const struct fw_address_region registers_region =
+static const struct fw_address_region registers_region =
 	{ .start = 0xfffff0000000ull, .end = 0xfffff0000400ull, };
 
 static void
diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h
index 5ceaccd..fa7967b 100644
--- a/drivers/firewire/fw-transaction.h
+++ b/drivers/firewire/fw-transaction.h
@@ -231,7 +231,7 @@ struct fw_card {
 	unsigned long reset_jiffies;
 
 	unsigned long long guid;
-	int max_receive;
+	unsigned max_receive;
 	int link_speed;
 	int config_rom_generation;
 
diff --git a/drivers/ieee1394/Kconfig b/drivers/ieee1394/Kconfig
index 8012b3b..545663e 100644
--- a/drivers/ieee1394/Kconfig
+++ b/drivers/ieee1394/Kconfig
@@ -97,7 +97,7 @@ config IEEE1394_SBP2
 
 config IEEE1394_SBP2_PHYS_DMA
 	bool "Enable replacement for physical DMA in SBP2"
-	depends on IEEE1394 && IEEE1394_SBP2 && EXPERIMENTAL && (X86_32 || PPC_32)
+	depends on IEEE1394_SBP2 && VIRT_TO_BUS && EXPERIMENTAL
 	help
 	  This builds sbp2 for use with non-OHCI host adapters which do not
 	  support physical DMA or for when ohci1394 is run with phys_dma=0.
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index e882cb9..47dbe8f 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -773,11 +773,6 @@ static struct sbp2_lu *sbp2_alloc_device(struct unit_directory *ud)
 			SBP2_ERR("failed to register lower 4GB address range");
 			goto failed_alloc;
 		}
-#else
-		if (dma_set_mask(hi->host->device.parent, DMA_32BIT_MASK)) {
-			SBP2_ERR("failed to set 4GB DMA mask");
-			goto failed_alloc;
-		}
 #endif
 	}
 


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


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

* [GIT PULL] FireWire fixes
@ 2007-08-25 16:24 Stefan Richter
  0 siblings, 0 replies; 21+ messages in thread
From: Stefan Richter @ 2007-08-25 16:24 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Andrew Morton, linux-kernel, linux1394-devel,
	Kristian Høgsberg

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 fixes for the new and old 1394 subsystems:

Kristian Høgsberg (1):
      firewire: Add ref-counting for sbp2 orbs (fix command abortion)

Stefan Richter (2):
      ieee1394: sbp2: fix sbp2_remove_device for error cases
      firewire: fix unloading of fw-ohci while devices are attached


 drivers/firewire/fw-card.c |    6 +++-
 drivers/firewire/fw-sbp2.c |   49 +++++++++++++++++++++++++++++------
 drivers/ieee1394/sbp2.c    |   14 +++++-----
 3 files changed, 51 insertions(+), 18 deletions(-)


commit e57d2011a6276d55a87f26653a0395f302ce0d51
Author: Kristian Høgsberg <krh@redhat.com>
Date:   Fri Aug 24 18:59:58 2007 -0400

    firewire: Add ref-counting for sbp2 orbs (fix command abortion)
    
    This handles the case where we get the status write before getting the
    complete_transaction callback ("status write for unknown orb").  In
    this case, we just assume that the initial orb pointer transaction
    succeeded and finish the orb.  To prevent the transaction callback
    from touching freed memory, we ref-count the orb structures.
    
    Signed-off-by: Kristian Høgsberg <krh@redhat.com>
    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 ba816ef..238730f 100644
--- a/drivers/firewire/fw-sbp2.c
+++ b/drivers/firewire/fw-sbp2.c
@@ -159,6 +159,7 @@ struct sbp2_pointer {
 
 struct sbp2_orb {
 	struct fw_transaction t;
+	struct kref kref;
 	dma_addr_t request_bus;
 	int rcode;
 	struct sbp2_pointer pointer;
@@ -280,6 +281,14 @@ static const struct {
 };
 
 static void
+free_orb(struct kref *kref)
+{
+	struct sbp2_orb *orb = container_of(kref, struct sbp2_orb, kref);
+
+	kfree(orb);
+}
+
+static void
 sbp2_status_write(struct fw_card *card, struct fw_request *request,
 		  int tcode, int destination, int source,
 		  int generation, int speed,
@@ -312,8 +321,8 @@ sbp2_status_write(struct fw_card *card, struct fw_request *request,
 	spin_lock_irqsave(&card->lock, flags);
 	list_for_each_entry(orb, &sd->orb_list, link) {
 		if (STATUS_GET_ORB_HIGH(status) == 0 &&
-		    STATUS_GET_ORB_LOW(status) == orb->request_bus &&
-		    orb->rcode == RCODE_COMPLETE) {
+		    STATUS_GET_ORB_LOW(status) == orb->request_bus) {
+			orb->rcode = RCODE_COMPLETE;
 			list_del(&orb->link);
 			break;
 		}
@@ -325,6 +334,8 @@ sbp2_status_write(struct fw_card *card, struct fw_request *request,
 	else
 		fw_error("status write for unknown orb\n");
 
+	kref_put(&orb->kref, free_orb);
+
 	fw_send_response(card, request, RCODE_COMPLETE);
 }
 
@@ -335,13 +346,27 @@ complete_transaction(struct fw_card *card, int rcode,
 	struct sbp2_orb *orb = data;
 	unsigned long flags;
 
-	orb->rcode = rcode;
-	if (rcode != RCODE_COMPLETE) {
-		spin_lock_irqsave(&card->lock, flags);
+	/*
+	 * This is a little tricky.  We can get the status write for
+	 * the orb before we get this callback.  The status write
+	 * handler above will assume the orb pointer transaction was
+	 * successful and set the rcode to RCODE_COMPLETE for the orb.
+	 * So this callback only sets the rcode if it hasn't already
+	 * been set and only does the cleanup if the transaction
+	 * failed and we didn't already get a status write.
+	 */
+	spin_lock_irqsave(&card->lock, flags);
+
+	if (orb->rcode == -1)
+		orb->rcode = rcode;
+	if (orb->rcode != RCODE_COMPLETE) {
 		list_del(&orb->link);
-		spin_unlock_irqrestore(&card->lock, flags);
 		orb->callback(orb, NULL);
 	}
+
+	spin_unlock_irqrestore(&card->lock, flags);
+
+	kref_put(&orb->kref, free_orb);
 }
 
 static void
@@ -360,6 +385,10 @@ sbp2_send_orb(struct sbp2_orb *orb, struct fw_unit *unit,
 	list_add_tail(&orb->link, &sd->orb_list);
 	spin_unlock_irqrestore(&device->card->lock, flags);
 
+	/* Take a ref for the orb list and for the transaction callback. */
+	kref_get(&orb->kref);
+	kref_get(&orb->kref);
+
 	fw_send_request(device->card, &orb->t, TCODE_WRITE_BLOCK_REQUEST,
 			node_id, generation, device->max_speed, offset,
 			&orb->pointer, sizeof(orb->pointer),
@@ -416,6 +445,7 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation,
 	if (orb == NULL)
 		return -ENOMEM;
 
+	kref_init(&orb->base.kref);
 	orb->response_bus =
 		dma_map_single(device->card->device, &orb->response,
 			       sizeof(orb->response), DMA_FROM_DEVICE);
@@ -490,7 +520,7 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation,
 	if (response)
 		fw_memcpy_from_be32(response,
 				    orb->response, sizeof(orb->response));
-	kfree(orb);
+	kref_put(&orb->base.kref, free_orb);
 
 	return retval;
 }
@@ -886,7 +916,6 @@ complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status)
 
 	orb->cmd->result = result;
 	orb->done(orb->cmd);
-	kfree(orb);
 }
 
 static int sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb)
@@ -1005,6 +1034,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
 
 	/* Initialize rcode to something not RCODE_COMPLETE. */
 	orb->base.rcode = -1;
+	kref_init(&orb->base.kref);
 
 	orb->unit = unit;
 	orb->done = done;
@@ -1051,10 +1081,11 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
 	sbp2_send_orb(&orb->base, unit, sd->node_id, sd->generation,
 		      sd->command_block_agent_address + SBP2_ORB_POINTER);
 
+	kref_put(&orb->base.kref, free_orb);
 	return 0;
 
  fail_mapping:
-	kfree(orb);
+	kref_put(&orb->base.kref, free_orb);
  fail_alloc:
 	return SCSI_MLQUEUE_HOST_BUSY;
 }

commit 8a2d9ed3210464d22fccb9834970629c1c36fa36
Author: Stefan Richter <stefanr@s5r6.in-berlin.de>
Date:   Tue Aug 21 01:05:14 2007 +0200

    firewire: fix unloading of fw-ohci while devices are attached
    
    Fix panic in run_timer_softirq right after "modprobe -r firewire-ohci"
    if a FireWire disk was attached and firewire-sbp2 loaded.
    
    Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>

diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c
index 0aeab32..3e97199 100644
--- a/drivers/firewire/fw-card.c
+++ b/drivers/firewire/fw-card.c
@@ -510,9 +510,11 @@ fw_core_remove_card(struct fw_card *card)
 	/* Set up the dummy driver. */
 	card->driver = &dummy_driver;
 
-	fw_flush_transactions(card);
-
 	fw_destroy_nodes(card);
+	flush_scheduled_work();
+
+	fw_flush_transactions(card);
+	del_timer_sync(&card->flush_timer);
 
 	fw_card_put(card);
 }

commit a2ee3f9bbb0ce57102dad8928d54f59acdc4b8f7
Author: Stefan Richter <stefanr@s5r6.in-berlin.de>
Date:   Sat Aug 11 11:51:16 2007 +0200

    ieee1394: sbp2: fix sbp2_remove_device for error cases
    
    Bug found by Olaf Hering <olh@suse.de>:
    sbp2util_remove_command_orb_pool requires a valid lu->hi pointer.
    
    Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>

diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index 47dbe8f..a81ba8f 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -513,9 +513,9 @@ static int sbp2util_create_command_orb_pool(struct sbp2_lu *lu)
 	return 0;
 }
 
-static void sbp2util_remove_command_orb_pool(struct sbp2_lu *lu)
+static void sbp2util_remove_command_orb_pool(struct sbp2_lu *lu,
+					     struct hpsb_host *host)
 {
-	struct hpsb_host *host = lu->hi->host;
 	struct list_head *lh, *next;
 	struct sbp2_command_info *cmd;
 	unsigned long flags;
@@ -922,15 +922,16 @@ static void sbp2_remove_device(struct sbp2_lu *lu)
 
 	if (!lu)
 		return;
-
 	hi = lu->hi;
+	if (!hi)
+		goto no_hi;
 
 	if (lu->shost) {
 		scsi_remove_host(lu->shost);
 		scsi_host_put(lu->shost);
 	}
 	flush_scheduled_work();
-	sbp2util_remove_command_orb_pool(lu);
+	sbp2util_remove_command_orb_pool(lu, hi->host);
 
 	list_del(&lu->lu_list);
 
@@ -971,9 +972,8 @@ static void sbp2_remove_device(struct sbp2_lu *lu)
 
 	lu->ud->device.driver_data = NULL;
 
-	if (hi)
-		module_put(hi->host->driver->owner);
-
+	module_put(hi->host->driver->owner);
+no_hi:
 	kfree(lu);
 }
 

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


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

* [git pull] FireWire fixes
@ 2009-09-05 15:18 Stefan Richter
  0 siblings, 0 replies; 21+ messages in thread
From: Stefan Richter @ 2009-09-05 15:18 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
  - a fix for a post 2.6.30 regression reported at linux1394-devel yesterday,
  - two workarounds for recently found hardware quirks,
  - a fix for an old bug, only recently reported.

Stefan Richter (4):
      firewire: core: fix crash in iso resource management
      firewire: ohci: fix Agere FW643 and multiple cameras
      firewire: ohci: fix Ricoh R5C832, video reception
      firewire: sbp2: fix freeing of unallocated memory

 drivers/firewire/core-iso.c |    4 ++--
 drivers/firewire/ohci.c     |   14 ++++++++++++++
 drivers/firewire/sbp2.c     |    8 ++++----
 3 files changed, 20 insertions(+), 6 deletions(-)

Thanks.


commit baed6b82d9f160184c1c14cdb4accb08f3eb6b87
Author: Stefan Richter <stefanr@s5r6.in-berlin.de>
Date:   Thu Sep 3 23:07:35 2009 +0200

    firewire: sbp2: fix freeing of unallocated memory
    
    If a target writes invalid status (typically status of a command that
    already timed out), firewire-sbp2 attempts to put away an ORB that
    doesn't exist.  https://bugzilla.redhat.com/show_bug.cgi?id=519772
    
    Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>

diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c
index d27cb05..05f0c0c 100644
--- a/drivers/firewire/sbp2.c
+++ b/drivers/firewire/sbp2.c
@@ -456,12 +456,12 @@ static void sbp2_status_write(struct fw_card *card, struct fw_request *request,
 	}
 	spin_unlock_irqrestore(&card->lock, flags);
 
-	if (&orb->link != &lu->orb_list)
+	if (&orb->link != &lu->orb_list) {
 		orb->callback(orb, &status);
-	else
+		kref_put(&orb->kref, free_orb);
+	} else {
 		fw_error("status write for unknown orb\n");
-
-	kref_put(&orb->kref, free_orb);
+	}
 
 	fw_send_response(card, request, RCODE_COMPLETE);
 }

commit 4fe0badd5882c64dc2dcd8893f9b85db63339736
Author: Stefan Richter <stefanr@s5r6.in-berlin.de>
Date:   Fri Aug 28 13:26:03 2009 +0200

    firewire: ohci: fix Ricoh R5C832, video reception
    
    In dual-buffer DMA mode, no video frames are ever received from R5C832
    by libdc1394.  Fallback to packet-per-buffer DMA works reliably.
    http://thread.gmane.org/gmane.linux.kernel.firewire.devel/13393/focus=13476
    
    Reported-by: Jonathan Cameron <jic23@cam.ac.uk>
    Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>

diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index 3486bc4..76b321b 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -2431,6 +2431,11 @@ static int __devinit pci_probe(struct pci_dev *dev,
 	    dev->device == PCI_DEVICE_ID_AGERE_FW643)
 		ohci->use_dualbuffer = false;
 
+	/* dual-buffer mode is broken */
+	if (dev->vendor == PCI_VENDOR_ID_RICOH &&
+	    dev->device == PCI_DEVICE_ID_RICOH_R5C832)
+		ohci->use_dualbuffer = false;
+
 /* x86-32 currently doesn't use highmem for dma_alloc_coherent */
 #if !defined(CONFIG_X86_32)
 	/* dual-buffer mode is broken with descriptor addresses above 2G */

commit fc383796a8cc5df0a0c8633a16dd2e9528a16a63
Author: Stefan Richter <stefanr@s5r6.in-berlin.de>
Date:   Fri Aug 28 13:25:15 2009 +0200

    firewire: ohci: fix Agere FW643 and multiple cameras
    
    An Agere FW643 OHCI 1.1 card works fine for video reception from one
    camera but fails early if receiving from two cameras.  After a short
    while, no IR IRQ events occur and the context control register does not
    react anymore.  This happens regardless whether both IR DMA contexts are
    dual-buffer or one is dual-buffer and the other packet-per-buffer.
    
    This can be worked around by disabling dual buffer DMA mode entirely.
    http://sourceforge.net/mailarchive/message.php?msg_name=4A7C0594.2020208%40gmail.com
    (Reported by Samuel Audet.)
    
    In another report (by Jonathan Cameron), an FW643 works OK with two
    cameras in dual buffer mode.  Whether this is due to different chip
    revisions or different usage patterns (different video formats) is not
    yet clear.  However, as far as the current capabilities of
    firewire-core's isochronous I/O interface are concerned, simply
    switching off dual-buffer on non-working and working FW643s alike is not
    a problem in practice.  We only need to revisit this issue if we are
    going to enhance the interface, e.g. so that applications can explicitly
    choose modes.
    
    Reported-by: Samuel Audet <samuel.audet@gmail.com>
    Reported-by: Jonathan Cameron <jic23@cam.ac.uk>
    Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>

diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index ecddd11..3486bc4 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -34,6 +34,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/pci.h>
+#include <linux/pci_ids.h>
 #include <linux/spinlock.h>
 #include <linux/string.h>
 
@@ -2372,6 +2373,9 @@ static void ohci_pmac_off(struct pci_dev *dev)
 #define ohci_pmac_off(dev)
 #endif /* CONFIG_PPC_PMAC */
 
+#define PCI_VENDOR_ID_AGERE		PCI_VENDOR_ID_ATT
+#define PCI_DEVICE_ID_AGERE_FW643	0x5901
+
 static int __devinit pci_probe(struct pci_dev *dev,
 			       const struct pci_device_id *ent)
 {
@@ -2422,6 +2426,11 @@ static int __devinit pci_probe(struct pci_dev *dev,
 	version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff;
 	ohci->use_dualbuffer = version >= OHCI_VERSION_1_1;
 
+	/* dual-buffer mode is broken if more than one IR context is active */
+	if (dev->vendor == PCI_VENDOR_ID_AGERE &&
+	    dev->device == PCI_DEVICE_ID_AGERE_FW643)
+		ohci->use_dualbuffer = false;
+
 /* x86-32 currently doesn't use highmem for dma_alloc_coherent */
 #if !defined(CONFIG_X86_32)
 	/* dual-buffer mode is broken with descriptor addresses above 2G */

commit 1821bc19d54009b6f5e6462dd79074d728080839
Author: Stefan Richter <stefanr@s5r6.in-berlin.de>
Date:   Sat Sep 5 13:23:49 2009 +0200

    firewire: core: fix crash in iso resource management
    
    This fixes a regression due to post 2.6.30 commit "firewire: core: do
    not DMA-map stack addresses" 6fdc03709433ccc2005f0f593ae9d9dd04f7b485.
    
    As David Moore noted, a previously correct sizeof() expression became
    wrong since the commit changed its argument from an array to a pointer.
    This resulted in an oops in ohci_cancel_packet in the shared workqueue
    thread's context when an isochronous resource was to be freed.
    
    Reported-by: Jonathan Cameron <jic23@cam.ac.uk>
    Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>

diff --git a/drivers/firewire/core-iso.c b/drivers/firewire/core-iso.c
index 110e731..1c0b504 100644
--- a/drivers/firewire/core-iso.c
+++ b/drivers/firewire/core-iso.c
@@ -196,7 +196,7 @@ static int manage_bandwidth(struct fw_card *card, int irm_id, int generation,
 		switch (fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP,
 				irm_id, generation, SCODE_100,
 				CSR_REGISTER_BASE + CSR_BANDWIDTH_AVAILABLE,
-				data, sizeof(data))) {
+				data, 8)) {
 		case RCODE_GENERATION:
 			/* A generation change frees all bandwidth. */
 			return allocate ? -EAGAIN : bandwidth;
@@ -233,7 +233,7 @@ static int manage_channel(struct fw_card *card, int irm_id, int generation,
 		data[1] = old ^ c;
 		switch (fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP,
 					   irm_id, generation, SCODE_100,
-					   offset, data, sizeof(data))) {
+					   offset, data, 8)) {
 		case RCODE_GENERATION:
 			/* A generation change frees all channels. */
 			return allocate ? -EAGAIN : i;


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


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

* [git pull] FireWire fixes
@ 2009-11-28  0:50 Stefan Richter
  0 siblings, 0 replies; 21+ messages in thread
From: Stefan Richter @ 2009-11-28  0:50 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 fixes for two bugs which prevented FireWire audio drivers in
userspace (FFADO) to run on the newer firewire kernel stack.

This affects very specific functionality only (necessary for audio out)
and has been extensively tested already, hence I consider this good to
pull even this late.

Jay Fenlason (2):
      firewire: ohci: Make cycleMatch ISO transmission work
      firewire: ohci: pass correct iso xmit timestamps to core

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

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


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

* [git pull] FireWire fixes
  2009-12-31 18:55   ` [git pull] FireWire fixes; new firewire stack is recommended to distributors and users Stefan Richter
@ 2010-01-28 17:05     ` Stefan Richter
  2010-02-15 22:19       ` Stefan Richter
  0 siblings, 1 reply; 21+ messages in thread
From: Stefan Richter @ 2010-01-28 17: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 updates to the FireWire subsystem.
Thanks.

Stefan Richter (4):
      firewire: core: add_descriptor size check
      firewire: cdev: add_descriptor documentation fix
      firewire: core: fix use-after-free regression in FCP handler
      firewire: ohci: fix crashes with TSB43AB23 on 64bit systems

 drivers/firewire/core-card.c  |   41 ++++++++++++++++++--------
 drivers/firewire/core-cdev.c  |   50 +++++++++++++++++++++++---------
 drivers/firewire/ohci.c       |    4 ++-
 include/linux/firewire-cdev.h |    4 ++-
 4 files changed, 70 insertions(+), 29 deletions(-)


commit 7a481436787cbc932af6c407b317ac603969a242
Author: Stefan Richter <stefanr@s5r6.in-berlin.de>
Date:   Tue Jan 26 21:39:07 2010 +0100

    firewire: ohci: fix crashes with TSB43AB23 on 64bit systems
    
    Unsurprisingly, Texas Instruments TSB43AB23 exhibits the same behaviour
    as TSB43AB22/A in dual buffer IR DMA mode:  If descriptors are located
    at physical addresses above the 31 bit address range (2 GB), the
    controller will overwrite random memory.  With luck, this merely
    prevents video reception.  With only a little less luck, the machine
    crashes.
    
    We use the same workaround here as with TSB43AB22/A:  Switch off the
    dual buffer capability flag and use packet-per-buffer IR DMA instead.
    Another possible workaround would be to limit the coherent DMA mask to
    31 bits.
    
    In Linux 2.6.33, this change serves effectively only as documentation
    since dual buffer mode is not used for any controller anymore.  But
    somebody might want to re-enable it in the future to make use of
    features of dual buffer DMA that are not available in packet-per-buffer
    mode.
    
    In Linux 2.6.32 and older, this update is vital for anyone with this
    controller, more than 2 GB RAM, a 64 bit kernel, and FireWire video or
    audio applications.
    
    We have at least four reports:
    http://bugzilla.kernel.org/show_bug.cgi?id=13808
    http://marc.info/?l=linux1394-user&m=126154279004083
    https://bugzilla.redhat.com/show_bug.cgi?id=552142
    http://marc.info/?l=linux1394-user&m=126432246128386
    
    Reported-by: Paul Johnson
    Reported-by: Ronneil Camara
    Reported-by: G Zornetzer
    Reported-by: Mark Thompson
    Cc: stable@kernel.org
    Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>

diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index a61571c..2345d41 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -2420,6 +2420,7 @@ static void ohci_pmac_off(struct pci_dev *dev)
 
 #define PCI_VENDOR_ID_AGERE		PCI_VENDOR_ID_ATT
 #define PCI_DEVICE_ID_AGERE_FW643	0x5901
+#define PCI_DEVICE_ID_TI_TSB43AB23	0x8024
 
 static int __devinit pci_probe(struct pci_dev *dev,
 			       const struct pci_device_id *ent)
@@ -2488,7 +2489,8 @@ static int __devinit pci_probe(struct pci_dev *dev,
 #if !defined(CONFIG_X86_32)
 	/* dual-buffer mode is broken with descriptor addresses above 2G */
 	if (dev->vendor == PCI_VENDOR_ID_TI &&
-	    dev->device == PCI_DEVICE_ID_TI_TSB43AB22)
+	    (dev->device == PCI_DEVICE_ID_TI_TSB43AB22 ||
+	     dev->device == PCI_DEVICE_ID_TI_TSB43AB23))
 		ohci->use_dualbuffer = false;
 #endif
 

commit 281e20323ab72180137824a298ee9e21e6f9acf6
Author: Stefan Richter <stefanr@s5r6.in-berlin.de>
Date:   Sun Jan 24 16:45:03 2010 +0100

    firewire: core: fix use-after-free regression in FCP handler
    
    Commit db5d247a "firewire: fix use of multiple AV/C devices, allow
    multiple FCP listeners" introduced a regression into 2.6.33-rc3:
    The core freed payloads of incoming requests to FCP_Request or
    FCP_Response before a userspace driver accessed them.
    
    We need to copy such payloads for each registered userspace client
    and free the copies according to the lifetime rules of non-FCP client
    request resources.
    
    (This could possibly be optimized by reference counts instead of
    copies.)
    
    The presently only kernelspace driver which listens for FCP requests,
    firedtv, was not affected because it already copies FCP frames into an
    own buffer before returning to firewire-core's FCP handler dispatcher.
    
    Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>

diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c
index e6d6384..4eeaed5 100644
--- a/drivers/firewire/core-cdev.c
+++ b/drivers/firewire/core-cdev.c
@@ -35,6 +35,7 @@
 #include <linux/preempt.h>
 #include <linux/sched.h>
 #include <linux/spinlock.h>
+#include <linux/string.h>
 #include <linux/time.h>
 #include <linux/uaccess.h>
 #include <linux/vmalloc.h>
@@ -595,13 +596,20 @@ static int ioctl_send_request(struct client *client, void *buffer)
 			    client->device->max_speed);
 }
 
+static inline bool is_fcp_request(struct fw_request *request)
+{
+	return request == NULL;
+}
+
 static void release_request(struct client *client,
 			    struct client_resource *resource)
 {
 	struct inbound_transaction_resource *r = container_of(resource,
 			struct inbound_transaction_resource, resource);
 
-	if (r->request)
+	if (is_fcp_request(r->request))
+		kfree(r->data);
+	else
 		fw_send_response(client->device->card, r->request,
 				 RCODE_CONFLICT_ERROR);
 	kfree(r);
@@ -616,6 +624,7 @@ static void handle_request(struct fw_card *card, struct fw_request *request,
 	struct address_handler_resource *handler = callback_data;
 	struct inbound_transaction_resource *r;
 	struct inbound_transaction_event *e;
+	void *fcp_frame = NULL;
 	int ret;
 
 	r = kmalloc(sizeof(*r), GFP_ATOMIC);
@@ -627,6 +636,18 @@ static void handle_request(struct fw_card *card, struct fw_request *request,
 	r->data    = payload;
 	r->length  = length;
 
+	if (is_fcp_request(request)) {
+		/*
+		 * FIXME: Let core-transaction.c manage a
+		 * single reference-counted copy?
+		 */
+		fcp_frame = kmemdup(payload, length, GFP_ATOMIC);
+		if (fcp_frame == NULL)
+			goto failed;
+
+		r->data = fcp_frame;
+	}
+
 	r->resource.release = release_request;
 	ret = add_client_resource(handler->client, &r->resource, GFP_ATOMIC);
 	if (ret < 0)
@@ -640,13 +661,15 @@ static void handle_request(struct fw_card *card, struct fw_request *request,
 	e->request.closure = handler->closure;
 
 	queue_event(handler->client, &e->event,
-		    &e->request, sizeof(e->request), payload, length);
+		    &e->request, sizeof(e->request), r->data, length);
 	return;
 
  failed:
 	kfree(r);
 	kfree(e);
-	if (request)
+	kfree(fcp_frame);
+
+	if (!is_fcp_request(request))
 		fw_send_response(card, request, RCODE_CONFLICT_ERROR);
 }
 
@@ -717,18 +740,17 @@ static int ioctl_send_response(struct client *client, void *buffer)
 
 	r = container_of(resource, struct inbound_transaction_resource,
 			 resource);
-	if (r->request) {
-		if (request->length < r->length)
-			r->length = request->length;
-		if (copy_from_user(r->data, u64_to_uptr(request->data),
-				   r->length)) {
-			ret = -EFAULT;
-			kfree(r->request);
-			goto out;
-		}
-		fw_send_response(client->device->card, r->request,
-				 request->rcode);
+	if (is_fcp_request(r->request))
+		goto out;
+
+	if (request->length < r->length)
+		r->length = request->length;
+	if (copy_from_user(r->data, u64_to_uptr(request->data), r->length)) {
+		ret = -EFAULT;
+		kfree(r->request);
+		goto out;
 	}
+	fw_send_response(client->device->card, r->request, request->rcode);
  out:
 	kfree(r);
 

commit 6d3faf6f431bafb25f4b9926c50a7e5c267738c6
Author: Stefan Richter <stefanr@s5r6.in-berlin.de>
Date:   Sun Jan 24 14:48:00 2010 +0100

    firewire: cdev: add_descriptor documentation fix
    
    struct fw_cdev_add_descriptor.length is in quadlets, not in bytes.
    Also remove any doubts about the endianess of descriptor data.
    
    Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>

diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h
index 1f716d9..520ecf8 100644
--- a/include/linux/firewire-cdev.h
+++ b/include/linux/firewire-cdev.h
@@ -380,7 +380,7 @@ struct fw_cdev_initiate_bus_reset {
  * @immediate:	If non-zero, immediate key to insert before pointer
  * @key:	Upper 8 bits of root directory pointer
  * @data:	Userspace pointer to contents of descriptor block
- * @length:	Length of descriptor block data, in bytes
+ * @length:	Length of descriptor block data, in quadlets
  * @handle:	Handle to the descriptor, written by the kernel
  *
  * Add a descriptor block and optionally a preceding immediate key to the local
@@ -394,6 +394,8 @@ struct fw_cdev_initiate_bus_reset {
  * If not 0, the @immediate field specifies an immediate key which will be
  * inserted before the root directory pointer.
  *
+ * @immediate, @key, and @data array elements are CPU-endian quadlets.
+ *
  * If successful, the kernel adds the descriptor and writes back a handle to the
  * kernel-side object to be used for later removal of the descriptor block and
  * immediate key.

commit e300839da40e99581581c5d053a95a172651fec8
Author: Stefan Richter <stefanr@s5r6.in-berlin.de>
Date:   Sun Jan 24 14:47:02 2010 +0100

    firewire: core: add_descriptor size check
    
    Presently, firewire-core only checks whether descriptors that are to be
    added by userspace drivers to the local node's config ROM do not exceed
    a size of 256 quadlets.  However, the sum of the bare minimum ROM plus
    all descriptors (from firewire-core, from firewire-net, from userspace)
    must not exceed 256 quadlets.
    
    Otherwise, the bounds of a statically allocated buffer will be
    overwritten.  If the kernel survives that, firewire-core will
    subsequently be unable to parse the local node's config ROM.
    
    (Note, userspace drivers can add descriptors only through device files
    of local nodes.  These are usually only accessible by root, unlike
    device files of remote nodes which may be accessible to lesser
    privileged users.)
    
    Therefore add a test which takes the actual present and required ROM
    size into account for all descriptors of kernelspace and userspace
    drivers.
    
    Cc: stable@kernel.org
    Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>

diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c
index 7083bcc..5045156 100644
--- a/drivers/firewire/core-card.c
+++ b/drivers/firewire/core-card.c
@@ -57,6 +57,8 @@ static LIST_HEAD(descriptor_list);
 static int descriptor_count;
 
 static __be32 tmp_config_rom[256];
+/* ROM header, bus info block, root dir header, capabilities = 7 quadlets */
+static size_t config_rom_length = 1 + 4 + 1 + 1;
 
 #define BIB_CRC(v)		((v) <<  0)
 #define BIB_CRC_LENGTH(v)	((v) << 16)
@@ -73,7 +75,7 @@ static __be32 tmp_config_rom[256];
 #define BIB_CMC			((1) << 30)
 #define BIB_IMC			((1) << 31)
 
-static size_t generate_config_rom(struct fw_card *card, __be32 *config_rom)
+static void generate_config_rom(struct fw_card *card, __be32 *config_rom)
 {
 	struct fw_descriptor *desc;
 	int i, j, k, length;
@@ -130,23 +132,30 @@ static size_t generate_config_rom(struct fw_card *card, __be32 *config_rom)
 	for (i = 0; i < j; i += length + 1)
 		length = fw_compute_block_crc(config_rom + i);
 
-	return j;
+	WARN_ON(j != config_rom_length);
 }
 
 static void update_config_roms(void)
 {
 	struct fw_card *card;
-	size_t length;
 
 	list_for_each_entry (card, &card_list, link) {
-		length = generate_config_rom(card, tmp_config_rom);
-		card->driver->set_config_rom(card, tmp_config_rom, length);
+		generate_config_rom(card, tmp_config_rom);
+		card->driver->set_config_rom(card, tmp_config_rom,
+					     config_rom_length);
 	}
 }
 
+static size_t required_space(struct fw_descriptor *desc)
+{
+	/* descriptor + entry into root dir + optional immediate entry */
+	return desc->length + 1 + (desc->immediate > 0 ? 1 : 0);
+}
+
 int fw_core_add_descriptor(struct fw_descriptor *desc)
 {
 	size_t i;
+	int ret;
 
 	/*
 	 * Check descriptor is valid; the length of all blocks in the
@@ -162,15 +171,21 @@ int fw_core_add_descriptor(struct fw_descriptor *desc)
 
 	mutex_lock(&card_mutex);
 
-	list_add_tail(&desc->link, &descriptor_list);
-	descriptor_count++;
-	if (desc->immediate > 0)
+	if (config_rom_length + required_space(desc) > 256) {
+		ret = -EBUSY;
+	} else {
+		list_add_tail(&desc->link, &descriptor_list);
+		config_rom_length += required_space(desc);
 		descriptor_count++;
-	update_config_roms();
+		if (desc->immediate > 0)
+			descriptor_count++;
+		update_config_roms();
+		ret = 0;
+	}
 
 	mutex_unlock(&card_mutex);
 
-	return 0;
+	return ret;
 }
 EXPORT_SYMBOL(fw_core_add_descriptor);
 
@@ -179,6 +194,7 @@ void fw_core_remove_descriptor(struct fw_descriptor *desc)
 	mutex_lock(&card_mutex);
 
 	list_del(&desc->link);
+	config_rom_length -= required_space(desc);
 	descriptor_count--;
 	if (desc->immediate > 0)
 		descriptor_count--;
@@ -428,7 +444,6 @@ EXPORT_SYMBOL(fw_card_initialize);
 int fw_card_add(struct fw_card *card,
 		u32 max_receive, u32 link_speed, u64 guid)
 {
-	size_t length;
 	int ret;
 
 	card->max_receive = max_receive;
@@ -437,8 +452,8 @@ int fw_card_add(struct fw_card *card,
 
 	mutex_lock(&card_mutex);
 
-	length = generate_config_rom(card, tmp_config_rom);
-	ret = card->driver->enable(card, tmp_config_rom, length);
+	generate_config_rom(card, tmp_config_rom);
+	ret = card->driver->enable(card, tmp_config_rom, config_rom_length);
 	if (ret == 0)
 		list_add_tail(&card->link, &card_list);
 
-- 
Stefan Richter
-=====-==-=- ---= ===--
http://arcgraph.de/sr/


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

* [git pull] FireWire fixes
  2010-01-28 17:05     ` [git pull] FireWire fixes Stefan Richter
@ 2010-02-15 22:19       ` Stefan Richter
  0 siblings, 0 replies; 21+ messages in thread
From: Stefan Richter @ 2010-02-15 22:19 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 updates to the FireWire subsystem.
Thanks.

Clemens Ladisch (1):
      firewire: ohci: retransmit isochronous transmit packets on cycle loss

Stefan Richter (1):
      firewire: net: fix panic in fwnet_write_complete

 drivers/firewire/net.c  |   53 ++++++++++++++++++++++++++++----------
 drivers/firewire/ohci.c |   13 ++++++---
 2 files changed, 47 insertions(+), 19 deletions(-)


commit 7f51a100bba517196ac4bdf29408d20ee1c771e8
Author: Clemens Ladisch <clemens@ladisch.de>
Date:   Mon Feb 8 08:30:03 2010 +0100

    firewire: ohci: retransmit isochronous transmit packets on cycle loss
    
    In isochronous transmit DMA descriptors, link the skip address pointer
    back to the descriptor itself.  When a cycle is lost, the controller
    will send the packet in the next cycle, instead of terminating the
    entire DMA program.
    
    There are two reasons for this:
    
    * This behaviour is compatible with the old IEEE1394 stack.  Old
      applications would not expect the DMA program to stop in this case.
    
    * Since the OHCI driver does not report any uncompleted packets, the
      context would stop silently; clients would not have any chance to
      detect and handle this error without a watchdog timer.
    
    Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
    
    Pieter Palmers notes:
    
    "The reason I added this retry behavior to the old stack is because some
    cards now and then fail to send a packet (e.g. the o2micro card in my
    dell laptop).  I couldn't figure out why exactly this happens, my best
    guess is that the card cannot fetch the payload data on time.  This
    happens much more frequently when sending large packets, which leads me
    to suspect that there are some contention issues with the DMA that fills
    the transmit FIFO.
    
    In the old stack it was a pretty critical issue as it resulted in a
    freeze of the userspace application.
    
    The omission of a packet doesn't necessarily have to be an issue.  E.g.
    in IEC61883 streams the DBC field can be used to detect discontinuities
    in the stream.  So as long as the other side doesn't bail when no
    [packet] is present in a cycle, there is not really a problem.
    
    I'm not convinced though that retrying is the proper solution, but it is
    simple and effective for what it had to do.  And I think there are no
    reasons not to do it this way.  Userspace can still detect this by
    checking the cycle the descriptor was sent in."
    
    Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de> (changelog, comment)

diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index 2345d41..43ebf33 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -2101,11 +2101,6 @@ static int ohci_queue_iso_transmit(struct fw_iso_context *base,
 	u32 payload_index, payload_end_index, next_page_index;
 	int page, end_page, i, length, offset;
 
-	/*
-	 * FIXME: Cycle lost behavior should be configurable: lose
-	 * packet, retransmit or terminate..
-	 */
-
 	p = packet;
 	payload_index = payload;
 
@@ -2135,6 +2130,14 @@ static int ohci_queue_iso_transmit(struct fw_iso_context *base,
 	if (!p->skip) {
 		d[0].control   = cpu_to_le16(DESCRIPTOR_KEY_IMMEDIATE);
 		d[0].req_count = cpu_to_le16(8);
+		/*
+		 * Link the skip address to this descriptor itself.  This causes
+		 * a context to skip a cycle whenever lost cycles or FIFO
+		 * overruns occur, without dropping the data.  The application
+		 * should then decide whether this is an error condition or not.
+		 * FIXME:  Make the context's cycle-lost behaviour configurable?
+		 */
+		d[0].branch_address = cpu_to_le32(d_bus | z);
 
 		header = (__le32 *) &d[1];
 		header[0] = cpu_to_le32(IT_HEADER_SY(p->sy) |

commit 110f82d7a2e0ff5a17617a9672f1ccb7e44bc0c6
Author: Stefan Richter <stefanr@s5r6.in-berlin.de>
Date:   Mon Jan 18 22:36:49 2010 +0100

    firewire: net: fix panic in fwnet_write_complete
    
    In the transmit path of firewire-net (IPv4 over 1394), the following
    race condition may occur:
      - The networking soft IRQ inserts a datagram into the 1394 async
        request transmit DMA.
      - The 1394 async transmit completion tasklet runs to finish cleaning
        up (unlink datagram from list of pending ones, release skb and
        outbound 1394 transaction object) --- before the networking soft IRQ
        had a chance to proceed and add the datagram to the list of pending
        datagrams.
    
    This caused a panic in the 1394 async transmit completion tasklet when
    it dereferenced unitialized list heads:
    http://bugzilla.kernel.org/show_bug.cgi?id=15077
    
    The fix is to add checks in the tx soft IRQ and in the tasklet to
    determine which of these two is the last referrer to the transaction
    object.  Then handle the cleanup of the object by the last referrer
    rather than assuming that the tasklet is always the last one.
    
    There is another similar race:  Between said tasklet and fwnet_close,
    i.e. at ifdown.  However, that race is much less likely to occur in
    practice and shall be fixed in a separate update.
    
    Reported-by: Илья Басин <basinilya@gmail.com>
    Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>

diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c
index cbaf420..2d3dc7d 100644
--- a/drivers/firewire/net.c
+++ b/drivers/firewire/net.c
@@ -893,20 +893,31 @@ static void fwnet_receive_broadcast(struct fw_iso_context *context,
 
 static struct kmem_cache *fwnet_packet_task_cache;
 
+static void fwnet_free_ptask(struct fwnet_packet_task *ptask)
+{
+	dev_kfree_skb_any(ptask->skb);
+	kmem_cache_free(fwnet_packet_task_cache, ptask);
+}
+
 static int fwnet_send_packet(struct fwnet_packet_task *ptask);
 
 static void fwnet_transmit_packet_done(struct fwnet_packet_task *ptask)
 {
-	struct fwnet_device *dev;
+	struct fwnet_device *dev = ptask->dev;
 	unsigned long flags;
-
-	dev = ptask->dev;
+	bool free;
 
 	spin_lock_irqsave(&dev->lock, flags);
-	list_del(&ptask->pt_link);
-	spin_unlock_irqrestore(&dev->lock, flags);
 
-	ptask->outstanding_pkts--; /* FIXME access inside lock */
+	ptask->outstanding_pkts--;
+
+	/* Check whether we or the networking TX soft-IRQ is last user. */
+	free = (ptask->outstanding_pkts == 0 && !list_empty(&ptask->pt_link));
+
+	if (ptask->outstanding_pkts == 0)
+		list_del(&ptask->pt_link);
+
+	spin_unlock_irqrestore(&dev->lock, flags);
 
 	if (ptask->outstanding_pkts > 0) {
 		u16 dg_size;
@@ -951,10 +962,10 @@ static void fwnet_transmit_packet_done(struct fwnet_packet_task *ptask)
 			ptask->max_payload = skb->len + RFC2374_FRAG_HDR_SIZE;
 		}
 		fwnet_send_packet(ptask);
-	} else {
-		dev_kfree_skb_any(ptask->skb);
-		kmem_cache_free(fwnet_packet_task_cache, ptask);
 	}
+
+	if (free)
+		fwnet_free_ptask(ptask);
 }
 
 static void fwnet_write_complete(struct fw_card *card, int rcode,
@@ -977,6 +988,7 @@ static int fwnet_send_packet(struct fwnet_packet_task *ptask)
 	unsigned tx_len;
 	struct rfc2734_header *bufhdr;
 	unsigned long flags;
+	bool free;
 
 	dev = ptask->dev;
 	tx_len = ptask->max_payload;
@@ -1022,12 +1034,16 @@ static int fwnet_send_packet(struct fwnet_packet_task *ptask)
 				generation, SCODE_100, 0ULL, ptask->skb->data,
 				tx_len + 8, fwnet_write_complete, ptask);
 
-		/* FIXME race? */
 		spin_lock_irqsave(&dev->lock, flags);
-		list_add_tail(&ptask->pt_link, &dev->broadcasted_list);
+
+		/* If the AT tasklet already ran, we may be last user. */
+		free = (ptask->outstanding_pkts == 0 && list_empty(&ptask->pt_link));
+		if (!free)
+			list_add_tail(&ptask->pt_link, &dev->broadcasted_list);
+
 		spin_unlock_irqrestore(&dev->lock, flags);
 
-		return 0;
+		goto out;
 	}
 
 	fw_send_request(dev->card, &ptask->transaction,
@@ -1035,12 +1051,19 @@ static int fwnet_send_packet(struct fwnet_packet_task *ptask)
 			ptask->generation, ptask->speed, ptask->fifo_addr,
 			ptask->skb->data, tx_len, fwnet_write_complete, ptask);
 
-	/* FIXME race? */
 	spin_lock_irqsave(&dev->lock, flags);
-	list_add_tail(&ptask->pt_link, &dev->sent_list);
+
+	/* If the AT tasklet already ran, we may be last user. */
+	free = (ptask->outstanding_pkts == 0 && list_empty(&ptask->pt_link));
+	if (!free)
+		list_add_tail(&ptask->pt_link, &dev->sent_list);
+
 	spin_unlock_irqrestore(&dev->lock, flags);
 
 	dev->netdev->trans_start = jiffies;
+ out:
+	if (free)
+		fwnet_free_ptask(ptask);
 
 	return 0;
 }
@@ -1298,6 +1321,8 @@ static netdev_tx_t fwnet_tx(struct sk_buff *skb, struct net_device *net)
 	spin_unlock_irqrestore(&dev->lock, flags);
 
 	ptask->max_payload = max_payload;
+	INIT_LIST_HEAD(&ptask->pt_link);
+
 	fwnet_send_packet(ptask);
 
 	return NETDEV_TX_OK;
-- 
Stefan Richter
-=====-==-=- --=- -====
http://arcgraph.de/sr/


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

* [git pull] FireWire fixes
  2010-03-02 18:45 [git pull] FireWire updates post 2.6.33 Stefan Richter
@ 2010-03-26 13:05 ` Stefan Richter
  2010-04-15 15:59   ` [git pull] FireWire fixes and documentation update Stefan Richter
  0 siblings, 1 reply; 21+ messages in thread
From: Stefan Richter @ 2010-03-26 13: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 IEEE 1394/ FireWire subsystem update.

Clemens Ladisch (2):
      firewire: core: fw_iso_resource_manage: fix error handling
      firewire: ohci: add cycle timer quirk for the TI TSB12LV22

Stefan Richter (2):
      firewire: core: fix Model_ID in modalias
      firewire: core: align driver match with modalias

 drivers/firewire/core-device.c |  103 +++++++++++++++------------------------
 drivers/firewire/core-iso.c    |    5 +-
 drivers/firewire/ohci.c        |    4 ++
 3 files changed, 47 insertions(+), 65 deletions(-)

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


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

* [git pull] FireWire fixes
  2010-04-15 15:59   ` [git pull] FireWire fixes and documentation update Stefan Richter
@ 2010-04-22 19:45     ` Stefan Richter
  0 siblings, 0 replies; 21+ messages in thread
From: Stefan Richter @ 2010-04-22 19:45 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 some more IEEE 1394/ FireWire subsystem fixes.
Thanks.

Clemens Ladisch (4):
      firewire: core: fix retries calculation in iso manage_channel()
      firewire: core: fw_iso_resource_manage: return -EBUSY when out of resources
      firewire: ohci: prevent aliasing of locally handled register addresses
      firewire: ohci: wait for local CSR lock access to finish

Stefan Richter (1):
      firewire: cdev: fix cut+paste mistake in disclaimer

 drivers/firewire/core-iso.c        |   14 ++++++++++----
 drivers/firewire/ohci.c            |   23 ++++++++++++++---------
 include/linux/firewire-cdev.h      |    2 +-
 include/linux/firewire-constants.h |    2 +-
 4 files changed, 26 insertions(+), 15 deletions(-)


Full log and diff:

commit e1393667be574807a13bfaf1bb471f5fd1a5287b
Author: Clemens Ladisch <clemens@ladisch.de>
Date:   Mon Apr 12 10:35:44 2010 +0200

    firewire: ohci: wait for local CSR lock access to finish
    
    Add a loop to wait for the controller to finish a locally-initiated CSR
    lock operation.  Google shows some occurrences of the "swap not done
    yet" message which might indicate that some OHCI controllers are not
    fast enough to do the lock/swap in the time needed for one PCI access.
    
    This also correctly handles the case where the lock operation did not
    finish, instead of silently returning an uninitialized value.
    
    Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
    Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
---
 drivers/firewire/ohci.c |   20 +++++++++++++-------
 1 files changed, 13 insertions(+), 7 deletions(-)

diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index 82fb2e7..6e95f8f 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -1158,7 +1158,7 @@ static void handle_local_lock(struct fw_ohci *ohci,
 			      struct fw_packet *packet, u32 csr)
 {
 	struct fw_packet response;
-	int tcode, length, ext_tcode, sel;
+	int tcode, length, ext_tcode, sel, try;
 	__be32 *payload, lock_old;
 	u32 lock_arg, lock_data;
 
@@ -1185,13 +1185,19 @@ static void handle_local_lock(struct fw_ohci *ohci,
 	reg_write(ohci, OHCI1394_CSRCompareData, lock_arg);
 	reg_write(ohci, OHCI1394_CSRControl, sel);
 
-	if (reg_read(ohci, OHCI1394_CSRControl) & 0x80000000)
-		lock_old = cpu_to_be32(reg_read(ohci, OHCI1394_CSRData));
-	else
-		fw_notify("swap not done yet\n");
+	for (try = 0; try < 20; try++)
+		if (reg_read(ohci, OHCI1394_CSRControl) & 0x80000000) {
+			lock_old = cpu_to_be32(reg_read(ohci,
+							OHCI1394_CSRData));
+			fw_fill_response(&response, packet->header,
+					 RCODE_COMPLETE,
+					 &lock_old, sizeof(lock_old));
+			goto out;
+		}
+
+	fw_error("swap not done (CSR lock timeout)\n");
+	fw_fill_response(&response, packet->header, RCODE_BUSY, NULL, 0);
 
-	fw_fill_response(&response, packet->header,
-			 RCODE_COMPLETE, &lock_old, sizeof(lock_old));
  out:
 	fw_core_handle_response(&ohci->card, &response);
 }

commit 2608203daf5f87311c6e5d36e5de5efcb14aab24
Author: Clemens Ladisch <clemens@ladisch.de>
Date:   Mon Apr 12 10:35:30 2010 +0200

    firewire: ohci: prevent aliasing of locally handled register addresses
    
    We must compute the offset from the CSR register base with the
    full 48 address bits to prevent matching with addresses whose
    lower 32 bits happen to be equal with one of the specially
    handled registers.
    
    Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
    Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
---
 drivers/firewire/ohci.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index e33917b..82fb2e7 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -1198,8 +1198,7 @@ static void handle_local_lock(struct fw_ohci *ohci,
 
 static void handle_local_request(struct context *ctx, struct fw_packet *packet)
 {
-	u64 offset;
-	u32 csr;
+	u64 offset, csr;
 
 	if (ctx == &ctx->ohci->at_request_ctx) {
 		packet->ack = ACK_PENDING;

commit d6372b6e7c6142e6cc2108b3b850584cd7ade106
Author: Clemens Ladisch <clemens@ladisch.de>
Date:   Mon Apr 12 10:35:18 2010 +0200

    firewire: core: fw_iso_resource_manage: return -EBUSY when out of resources
    
    Returning -EIO for all errors would not allow clients to determine if
    the resource allocation process itself failed, or if the resources are
    not available.  (The latter information is needed by CMP to synchronize
    restoring of overlayed connections after a bus reset.)
    
    Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
    Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
---
 drivers/firewire/core-iso.c |   10 +++++++---
 1 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/firewire/core-iso.c b/drivers/firewire/core-iso.c
index 34a5137..9198e03 100644
--- a/drivers/firewire/core-iso.c
+++ b/drivers/firewire/core-iso.c
@@ -189,7 +189,7 @@ static int manage_bandwidth(struct fw_card *card, int irm_id, int generation,
 	for (try = 0; try < 5; try++) {
 		new = allocate ? old - bandwidth : old + bandwidth;
 		if (new < 0 || new > BANDWIDTH_AVAILABLE_INITIAL)
-			break;
+			return -EBUSY;
 
 		data[0] = cpu_to_be32(old);
 		data[1] = cpu_to_be32(new);
@@ -217,7 +217,7 @@ static int manage_channel(struct fw_card *card, int irm_id, int generation,
 		u32 channels_mask, u64 offset, bool allocate, __be32 data[2])
 {
 	__be32 c, all, old;
-	int i, retry = 5;
+	int i, ret = -EIO, retry = 5;
 
 	old = all = allocate ? cpu_to_be32(~0) : 0;
 
@@ -225,6 +225,8 @@ static int manage_channel(struct fw_card *card, int irm_id, int generation,
 		if (!(channels_mask & 1 << i))
 			continue;
 
+		ret = -EBUSY;
+
 		c = cpu_to_be32(1 << (31 - i));
 		if ((old & c) != (all & c))
 			continue;
@@ -253,11 +255,13 @@ static int manage_channel(struct fw_card *card, int irm_id, int generation,
 			if (retry) {
 				retry--;
 				i--;
+			} else {
+				ret = -EIO;
 			}
 		}
 	}
 
-	return -EIO;
+	return ret;
 }
 
 static void deallocate_channel(struct fw_card *card, int irm_id,

commit 3a1f0a0e3d871e3d3e08a1429009992151becda8
Author: Clemens Ladisch <clemens@ladisch.de>
Date:   Mon Apr 12 10:35:05 2010 +0200

    firewire: core: fix retries calculation in iso manage_channel()
    
    If there is a permanent error condition when communicating with the IRM,
    after the sixth error, the retry variable will be decremented to -1.
    If, in this case, the bits in channels_mask are not yet exhausted, the
    next channel is retried 2^32 times.
    
    To fix this, check that retry is never decremented beyond zero.
    
    Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
    Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
---
 drivers/firewire/core-iso.c |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/drivers/firewire/core-iso.c b/drivers/firewire/core-iso.c
index 99c20f1..34a5137 100644
--- a/drivers/firewire/core-iso.c
+++ b/drivers/firewire/core-iso.c
@@ -250,8 +250,10 @@ static int manage_channel(struct fw_card *card, int irm_id, int generation,
 
 			/* 1394-1995 IRM, fall through to retry. */
 		default:
-			if (retry--)
+			if (retry) {
+				retry--;
 				i--;
+			}
 		}
 	}
 

commit a2612cb16d4d8447793609cbdd2a2f4f156c0020
Author: Stefan Richter <stefanr@s5r6.in-berlin.de>
Date:   Thu Apr 15 22:16:04 2010 +0200

    firewire: cdev: fix cut+paste mistake in disclaimer
    
    This was supposed to be generic "authors or copyright holders";
    I mistakenly picked up text from a wrong file.
    
    Reported-by: Daniel K. <dk@uw.no>
    Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
---
 include/linux/firewire-cdev.h      |    2 +-
 include/linux/firewire-constants.h |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h
index 81f3b14..68f883b 100644
--- a/include/linux/firewire-cdev.h
+++ b/include/linux/firewire-cdev.h
@@ -17,7 +17,7 @@
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
diff --git a/include/linux/firewire-constants.h b/include/linux/firewire-constants.h
index 9c63f06..9b4bb5f 100644
--- a/include/linux/firewire-constants.h
+++ b/include/linux/firewire-constants.h
@@ -17,7 +17,7 @@
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.

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


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

* [git pull] FireWire fixes
@ 2010-08-29  9:54 Stefan Richter
  0 siblings, 0 replies; 21+ messages in thread
From: Stefan Richter @ 2010-08-29  9:54 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 fixes for
  - three older issues in firewire-sbp2 and -net,
  - a timer misuse added in 2.6.35 in firewire-core,
  - a hardware quirk that obstructed a 2.6.36-rc1 feature in firewire-ohci.
Thanks.

Clemens Ladisch (1):
      firewire: core: do not use del_timer_sync() in interrupt context

Julia Lawall (1):
      ieee1394: Adjust confusing if indentation

Stefan Richter (4):
      firewire: sbp2: fix memory leak in sbp2_cancel_orbs or at send error
      firewire: sbp2: fix stall with "Unsolicited response"
      firewire: net: fix unicast reception RCODE in failure paths
      firewire: ohci: work around VIA and NEC PHY packet reception bug

 drivers/firewire/core-transaction.c |   13 ++++++++++---
 drivers/firewire/net.c              |   28 +++++++++++++++-------------
 drivers/firewire/ohci.c             |   10 +++++++++-
 drivers/firewire/sbp2.c             |   23 +++++++++++++++--------
 drivers/ieee1394/ohci1394.c         |    2 +-
 5 files changed, 50 insertions(+), 26 deletions(-)
-- 
Stefan Richter
-=====-==-=- =--- ===-=
http://arcgraph.de/sr/


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

* [git pull] FireWire fixes
@ 2010-09-17 12:47 Stefan Richter
  2010-09-17 23:06 ` Maxim Levitsky
  0 siblings, 1 reply; 21+ messages in thread
From: Stefan Richter @ 2010-09-17 12:47 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 a hardware quirk entry and a small makefile correction.
Thanks.

Heikki Lindholm (1):
      firewire: ohci: activate cycle timer register quirk on Ricoh chips

Stefan Richter (1):
      firewire: nosy: fix build when CONFIG_FIREWIRE=N

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


Full log and diff:

commit 8702d33aa6e6d753ef99163afe48aba1323374ef
Author: Stefan Richter <stefanr@s5r6.in-berlin.de>
Date:   Wed Sep 15 13:02:44 2010 +0200

    firewire: nosy: fix build when CONFIG_FIREWIRE=N
    
    drivers/firewire/nosy* is a stand-alone driver that does not depend on
    CONFIG_FIREWIRE.  Hence let make descend into drivers/firewire/ also
    if that option is off.
    
    The stand-alone driver drivers/ieee1394/init_ohci1394_dma*  will soon be
    moved into drivers/firewire/ too and will require the same makefile fix.
    
    Side effect:
    As mentioned in https://bugzilla.novell.com/show_bug.cgi?id=586172#c24
    this influences the order in which either firewire-ohci or ohci1394 is
    going to be bound to an OHCI-1394 controller in case of a modular build
    of both drivers if no modprobe blacklist entries are configured.
    However, a user of such a setup cannot expect deterministic behavior
    anyway.  The Kconfig help and the migration guide at
    ieee1394.wiki.kernel.org recommend blacklist entries when a dual
    IEEE 1394 stack build is being used.  (The coexistence period of the two
    stacks is planned to end soon.)
    
    Cc: Michal Marek <mmarek@suse.cz>
    Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>

diff --git a/drivers/Makefile b/drivers/Makefile
index 91874e0..0bbb456 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -50,7 +50,7 @@ obj-$(CONFIG_SPI)		+= spi/
 obj-y				+= net/
 obj-$(CONFIG_ATM)		+= atm/
 obj-$(CONFIG_FUSION)		+= message/
-obj-$(CONFIG_FIREWIRE)		+= firewire/
+obj-y				+= firewire/
 obj-y				+= ieee1394/
 obj-$(CONFIG_UIO)		+= uio/
 obj-y				+= cdrom/

commit 970f4be85ae6ecf97b711a3a2a1d5cecd3ea0534
Author: Heikki Lindholm <holin@iki.fi>
Date:   Mon Sep 6 22:30:45 2010 +0300

    firewire: ohci: activate cycle timer register quirk on Ricoh chips
    
    The Ricoh FireWire controllers appear to have the non-atomic cycle
    timer register access bug, so, activate the driver workaround by
    default.
    
    The behaviour was observed on:
    Ricoh Co Ltd R5C552 IEEE 1394 Controller [1180:0552] and
    Ricoh Co Ltd R5C832 IEEE 1394 Controller [1180:0832] (rev 04).
    
    Signed-off-by: Heikki Lindholm <holin@iki.fi>
    Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>

diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index be29b0b..1b05896 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -263,6 +263,7 @@ static const struct {
 	{PCI_VENDOR_ID_JMICRON,	PCI_DEVICE_ID_JMICRON_JMB38X_FW, QUIRK_NO_MSI},
 	{PCI_VENDOR_ID_NEC,	PCI_ANY_ID,	QUIRK_CYCLE_TIMER},
 	{PCI_VENDOR_ID_VIA,	PCI_ANY_ID,	QUIRK_CYCLE_TIMER},
+	{PCI_VENDOR_ID_RICOH,	PCI_ANY_ID,	QUIRK_CYCLE_TIMER},
 	{PCI_VENDOR_ID_APPLE,	PCI_DEVICE_ID_APPLE_UNI_N_FW, QUIRK_BE_HEADERS},
 };
 

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


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

* Re: [git pull] FireWire fixes
  2010-09-17 12:47 Stefan Richter
@ 2010-09-17 23:06 ` Maxim Levitsky
  2010-09-17 23:41   ` Stefan Richter
  0 siblings, 1 reply; 21+ messages in thread
From: Maxim Levitsky @ 2010-09-17 23:06 UTC (permalink / raw)
  To: Stefan Richter
  Cc: Linus Torvalds, Andrew Morton, linux1394-devel, linux-kernel

On Fri, 2010-09-17 at 14:47 +0200, Stefan Richter 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 a hardware quirk entry and a small makefile correction.
> Thanks.
> 
> Heikki Lindholm (1):
>       firewire: ohci: activate cycle timer register quirk on Ricoh chips
That did it, the strange oops I had with new firewire stack is gone.
(I have the Ricoh chip in the laptop)


However the new stack is still very much unusable:

Running new stack on the laptop + old stack on the desktop gave me about
18-30 Mbit/s speeds varying all the time.
Running both with the new stack results in corrupted packets and sftp
exits immediately.

The problems I so hoped to be fixed in new stack still persist:

Cable disconection/reconnection still results in the link loss till
ifconfig down/up.

Suspend/resume also results in the link loss.

Driver still has panics on some occasions.

Best regards,
Maxim Levitsky




> 
> Stefan Richter (1):
>       firewire: nosy: fix build when CONFIG_FIREWIRE=N
> 
>  drivers/Makefile        |    2 +-
>  drivers/firewire/ohci.c |    1 +
>  2 files changed, 2 insertions(+), 1 deletions(-)
> 
> 
> Full log and diff:
> 
> commit 8702d33aa6e6d753ef99163afe48aba1323374ef
> Author: Stefan Richter <stefanr@s5r6.in-berlin.de>
> Date:   Wed Sep 15 13:02:44 2010 +0200
> 
>     firewire: nosy: fix build when CONFIG_FIREWIRE=N
>     
>     drivers/firewire/nosy* is a stand-alone driver that does not depend on
>     CONFIG_FIREWIRE.  Hence let make descend into drivers/firewire/ also
>     if that option is off.
>     
>     The stand-alone driver drivers/ieee1394/init_ohci1394_dma*  will soon be
>     moved into drivers/firewire/ too and will require the same makefile fix.
>     
>     Side effect:
>     As mentioned in https://bugzilla.novell.com/show_bug.cgi?id=586172#c24
>     this influences the order in which either firewire-ohci or ohci1394 is
>     going to be bound to an OHCI-1394 controller in case of a modular build
>     of both drivers if no modprobe blacklist entries are configured.
>     However, a user of such a setup cannot expect deterministic behavior
>     anyway.  The Kconfig help and the migration guide at
>     ieee1394.wiki.kernel.org recommend blacklist entries when a dual
>     IEEE 1394 stack build is being used.  (The coexistence period of the two
>     stacks is planned to end soon.)
>     
>     Cc: Michal Marek <mmarek@suse.cz>
>     Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
> 
> diff --git a/drivers/Makefile b/drivers/Makefile
> index 91874e0..0bbb456 100644
> --- a/drivers/Makefile
> +++ b/drivers/Makefile
> @@ -50,7 +50,7 @@ obj-$(CONFIG_SPI)		+= spi/
>  obj-y				+= net/
>  obj-$(CONFIG_ATM)		+= atm/
>  obj-$(CONFIG_FUSION)		+= message/
> -obj-$(CONFIG_FIREWIRE)		+= firewire/
> +obj-y				+= firewire/
>  obj-y				+= ieee1394/
>  obj-$(CONFIG_UIO)		+= uio/
>  obj-y				+= cdrom/
> 
> commit 970f4be85ae6ecf97b711a3a2a1d5cecd3ea0534
> Author: Heikki Lindholm <holin@iki.fi>
> Date:   Mon Sep 6 22:30:45 2010 +0300
> 
>     firewire: ohci: activate cycle timer register quirk on Ricoh chips
>     
>     The Ricoh FireWire controllers appear to have the non-atomic cycle
>     timer register access bug, so, activate the driver workaround by
>     default.
>     
>     The behaviour was observed on:
>     Ricoh Co Ltd R5C552 IEEE 1394 Controller [1180:0552] and
>     Ricoh Co Ltd R5C832 IEEE 1394 Controller [1180:0832] (rev 04).
>     
>     Signed-off-by: Heikki Lindholm <holin@iki.fi>
>     Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
> 
> diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
> index be29b0b..1b05896 100644
> --- a/drivers/firewire/ohci.c
> +++ b/drivers/firewire/ohci.c
> @@ -263,6 +263,7 @@ static const struct {
>  	{PCI_VENDOR_ID_JMICRON,	PCI_DEVICE_ID_JMICRON_JMB38X_FW, QUIRK_NO_MSI},
>  	{PCI_VENDOR_ID_NEC,	PCI_ANY_ID,	QUIRK_CYCLE_TIMER},
>  	{PCI_VENDOR_ID_VIA,	PCI_ANY_ID,	QUIRK_CYCLE_TIMER},
> +	{PCI_VENDOR_ID_RICOH,	PCI_ANY_ID,	QUIRK_CYCLE_TIMER},
>  	{PCI_VENDOR_ID_APPLE,	PCI_DEVICE_ID_APPLE_UNI_N_FW, QUIRK_BE_HEADERS},
>  };
>  
> 



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

* Re: [git pull] FireWire fixes
  2010-09-17 23:06 ` Maxim Levitsky
@ 2010-09-17 23:41   ` Stefan Richter
  2010-09-18  0:00     ` Maxim Levitsky
  2010-09-18  0:00     ` Peter Stuge
  0 siblings, 2 replies; 21+ messages in thread
From: Stefan Richter @ 2010-09-17 23:41 UTC (permalink / raw)
  To: Maxim Levitsky
  Cc: Linus Torvalds, Andrew Morton, linux1394-devel, linux-kernel

Maxim Levitsky wrote:
> Running new stack on the laptop + old stack on the desktop gave me about
> 18-30 Mbit/s speeds varying all the time.
> Running both with the new stack results in corrupted packets and sftp
> exits immediately.

firewire-net, the IP over 1394 driver, is still marked as experimental not
because somebody forgot to remove that mark but because we mean it.  But so is
its older counterpart, eth1394.  Both eth1394 and firewire-net are chronically
 underused and undermaintained.

> The problems I so hoped to be fixed in new stack still persist:
> 
> Cable disconection/reconnection still results in the link loss till
> ifconfig down/up.
> 
> Suspend/resume also results in the link loss.

Sounds like something that shouldn't be too hard to fix by anybody who can
spare the time.  Surely a higher-level problem somewhere in firewire-net.

> Driver still has panics on some occasions.

At the moment I suspect that this OTOH might not be a firewire-net problem but
possibly a race in firewire-ohci which is only triggered by workload as
firewire-net imposes it (heavy AT context usage).
-- 
Stefan Richter
-=====-==-=- =--= =--=-
http://arcgraph.de/sr/

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

* Re: [git pull] FireWire fixes
  2010-09-17 23:41   ` Stefan Richter
@ 2010-09-18  0:00     ` Maxim Levitsky
  2010-09-18  0:00     ` Peter Stuge
  1 sibling, 0 replies; 21+ messages in thread
From: Maxim Levitsky @ 2010-09-18  0:00 UTC (permalink / raw)
  To: Stefan Richter
  Cc: Linus Torvalds, Andrew Morton, linux1394-devel, linux-kernel

On Sat, 2010-09-18 at 01:41 +0200, Stefan Richter wrote: 
> Maxim Levitsky wrote:
> > Running new stack on the laptop + old stack on the desktop gave me about
> > 18-30 Mbit/s speeds varying all the time.
> > Running both with the new stack results in corrupted packets and sftp
> > exits immediately.
> 
> firewire-net, the IP over 1394 driver, is still marked as experimental not
> because somebody forgot to remove that mark but because we mean it.  But so is
> its older counterpart, eth1394.  Both eth1394 and firewire-net are chronically
>  underused and undermaintained.
I sure do understand it!
I just did another round of testing and report the results.

Do you have an idea what could cause such low speeds?


> 
> > The problems I so hoped to be fixed in new stack still persist:
> > 
> > Cable disconection/reconnection still results in the link loss till
> > ifconfig down/up.
> > 
> > Suspend/resume also results in the link loss.
> 
> Sounds like something that shouldn't be too hard to fix by anybody who can
> spare the time.  Surely a higher-level problem somewhere in firewire-net.
> 
> > Driver still has panics on some occasions.
> 
> At the moment I suspect that this OTOH might not be a firewire-net problem but
> possibly a race in firewire-ohci which is only triggered by workload as
> firewire-net imposes it (heavy AT context usage).
Thanks for information!

Best regards,
Maxim Levitsky



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

* Re: [git pull] FireWire fixes
  2010-09-17 23:41   ` Stefan Richter
  2010-09-18  0:00     ` Maxim Levitsky
@ 2010-09-18  0:00     ` Peter Stuge
  2010-09-18  0:02       ` Maxim Levitsky
  1 sibling, 1 reply; 21+ messages in thread
From: Peter Stuge @ 2010-09-18  0:00 UTC (permalink / raw)
  To: Stefan Richter
  Cc: Maxim Levitsky, Andrew Morton, linux1394-devel, Linus Torvalds,
	linux-kernel

Stefan Richter wrote:
> > Cable disconection/reconnection still results in the link loss till
> > ifconfig down/up.
> 
> Surely a higher-level problem somewhere in firewire-net.

How to deal with cable glitch? The cable might as well never be
attached again. A timeout? How long? There's a timeout also in SBP-2 IIRC?


//Peter

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

* Re: [git pull] FireWire fixes
  2010-09-18  0:00     ` Peter Stuge
@ 2010-09-18  0:02       ` Maxim Levitsky
  0 siblings, 0 replies; 21+ messages in thread
From: Maxim Levitsky @ 2010-09-18  0:02 UTC (permalink / raw)
  To: Peter Stuge
  Cc: Stefan Richter, Andrew Morton, linux1394-devel, Linus Torvalds,
	linux-kernel

On Sat, 2010-09-18 at 02:00 +0200, Peter Stuge wrote: 
> Stefan Richter wrote:
> > > Cable disconection/reconnection still results in the link loss till
> > > ifconfig down/up.
> > 
> > Surely a higher-level problem somewhere in firewire-net.
> 
> How to deal with cable glitch? The cable might as well never be
> attached again. A timeout? How long? There's a timeout also in SBP-2 IIRC?
Not that.
I mean I expect that if I plug the cable in, I expect the interface to
start working right away, without need of ifconfig up/down as is the
case with ethernet.
(assuming that I did set the IP of the interface beforehand).

Best regards,
Maxim Levitsky


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

* [git pull] FireWire fixes
@ 2010-11-05 20:04 Stefan Richter
  0 siblings, 0 replies; 21+ messages in thread
From: Stefan Richter @ 2010-11-05 20:04 UTC (permalink / raw)
  To: Linus Torvalds, Andrew Morton; +Cc: linux-kernel, linux1394-devel

Linus, please pull from the fixes branch at

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

to receive the following updates.  These address old but severe bugs in
firewire-ohci that caused memory corruption and crashes under workloads
like with firewire-net or forensics applications.

Clemens Ladisch (4):
      firewire: ohci: fix buffer overflow in AR split packet handling
      firewire: ohci: fix race in AR split packet handling
      firewire: ohci: avoid reallocation of AR buffers
      firewire: ohci: fix race when reading count in AR descriptor

 drivers/firewire/ohci.c |   92 ++++++++++++++++++++++++++++++++++-------------
 1 files changed, 67 insertions(+), 25 deletions(-)

Thanks.

Full logs and diff:

commit 693fa7792e9db9f32da9436e633976fbacd04b55
Author: Clemens Ladisch <clemens@ladisch.de>
Date:   Mon Oct 25 11:43:05 2010 +0200

    firewire: ohci: fix race when reading count in AR descriptor
    
    If the controller is storing a split packet and therefore changing
    d->res_count to zero between the two reads by the driver, we end up with
    an end pointer that is not at a packet boundary, and therefore overflow
    the buffer when handling the split packet.
    
    To fix this, read the field once, atomically.  The compiler usually
    merges the two reads anyway, but for correctness, we have to enforce it.
    
    Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
    Tested-by: Maxim Levitsky <maximlevitsky@gmail.com>
    Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>

diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index b5ba666..84eb607 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -740,11 +740,13 @@ static void ar_context_tasklet(unsigned long data)
 	struct ar_buffer *ab;
 	struct descriptor *d;
 	void *buffer, *end;
+	__le16 res_count;
 
 	ab = ctx->current_buffer;
 	d = &ab->descriptor;
 
-	if (d->res_count == 0) {
+	res_count = ACCESS_ONCE(d->res_count);
+	if (res_count == 0) {
 		size_t size, size2, rest, pktsize, size3, offset;
 		dma_addr_t start_bus;
 		void *start;
@@ -812,7 +814,7 @@ static void ar_context_tasklet(unsigned long data)
 	} else {
 		buffer = ctx->pointer;
 		ctx->pointer = end =
-			(void *) ab + PAGE_SIZE - le16_to_cpu(d->res_count);
+			(void *) ab + PAGE_SIZE - le16_to_cpu(res_count);
 
 		while (buffer < end)
 			buffer = handle_ar_packet(ctx, buffer);

commit 837596a61ba8f9bb53bb7aa27d17328ff9b2bcd5
Author: Clemens Ladisch <clemens@ladisch.de>
Date:   Mon Oct 25 11:42:42 2010 +0200

    firewire: ohci: avoid reallocation of AR buffers
    
    Freeing an AR buffer page just to allocate a new page immediately
    afterwards is not only a pointless effort but also dangerous because
    the allocation can fail, which would result in an oops later.
    
    Split ar_context_add_page() into two functions so that we can reuse
    the old page directly.
    
    Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
    Tested-by: Maxim Levitsky <maximlevitsky@gmail.com>
    Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>

diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index 7570b71..b5ba666 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -577,17 +577,11 @@ static int ohci_update_phy_reg(struct fw_card *card, int addr,
 	return ret;
 }
 
-static int ar_context_add_page(struct ar_context *ctx)
+static void ar_context_link_page(struct ar_context *ctx,
+				 struct ar_buffer *ab, dma_addr_t ab_bus)
 {
-	struct device *dev = ctx->ohci->card.device;
-	struct ar_buffer *ab;
-	dma_addr_t uninitialized_var(ab_bus);
 	size_t offset;
 
-	ab = dma_alloc_coherent(dev, PAGE_SIZE, &ab_bus, GFP_ATOMIC);
-	if (ab == NULL)
-		return -ENOMEM;
-
 	ab->next = NULL;
 	memset(&ab->descriptor, 0, sizeof(ab->descriptor));
 	ab->descriptor.control        = cpu_to_le16(DESCRIPTOR_INPUT_MORE |
@@ -606,6 +600,19 @@ static int ar_context_add_page(struct ar_context *ctx)
 
 	reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE);
 	flush_writes(ctx->ohci);
+}
+
+static int ar_context_add_page(struct ar_context *ctx)
+{
+	struct device *dev = ctx->ohci->card.device;
+	struct ar_buffer *ab;
+	dma_addr_t uninitialized_var(ab_bus);
+
+	ab = dma_alloc_coherent(dev, PAGE_SIZE, &ab_bus, GFP_ATOMIC);
+	if (ab == NULL)
+		return -ENOMEM;
+
+	ar_context_link_page(ctx, ab, ab_bus);
 
 	return 0;
 }
@@ -730,7 +737,6 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer)
 static void ar_context_tasklet(unsigned long data)
 {
 	struct ar_context *ctx = (struct ar_context *)data;
-	struct fw_ohci *ohci = ctx->ohci;
 	struct ar_buffer *ab;
 	struct descriptor *d;
 	void *buffer, *end;
@@ -799,9 +805,7 @@ static void ar_context_tasklet(unsigned long data)
 			ctx->current_buffer = ab;
 			ctx->pointer = end;
 
-			dma_free_coherent(ohci->card.device, PAGE_SIZE,
-					  start, start_bus);
-			ar_context_add_page(ctx);
+			ar_context_link_page(ctx, start, start_bus);
 		} else {
 			ctx->pointer = start + PAGE_SIZE;
 		}

commit a1f805e5e73a8fe166b71c6592d3837df0cd5e2e
Author: Clemens Ladisch <clemens@ladisch.de>
Date:   Mon Oct 25 11:42:20 2010 +0200

    firewire: ohci: fix race in AR split packet handling
    
    When handling an AR buffer that has been completely filled, we assumed
    that its descriptor will not be read by the controller and can be
    overwritten.  However, when the last received packet happens to end at
    the end of the buffer, the controller might not yet have moved on to the
    next buffer and might read the branch address later.  If we overwrite
    and free the page before that, the DMA context will either go dead
    because of an invalid Z value, or go off into some random memory.
    
    To fix this, ensure that the descriptor does not get overwritten by
    using only the actual buffer instead of the entire page for reassembling
    the split packet.  Furthermore, to avoid freeing the page too early,
    move on to the next buffer only when some data in it guarantees that the
    controller has moved on.
    
    This should eliminate the remaining firewire-net problems.
    
    Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
    Cc: 2.6.22-2.6.36 <stable@kernel.org>
    Tested-by: Maxim Levitsky <maximlevitsky@gmail.com>
    Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>

diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index 5826ae3..7570b71 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -750,20 +750,19 @@ static void ar_context_tasklet(unsigned long data)
 		 */
 
 		offset = offsetof(struct ar_buffer, data);
-		start = buffer = ab;
+		start = ab;
 		start_bus = le32_to_cpu(ab->descriptor.data_address) - offset;
+		buffer = ab->data;
 
 		ab = ab->next;
 		d = &ab->descriptor;
-		size = buffer + PAGE_SIZE - ctx->pointer;
+		size = start + PAGE_SIZE - ctx->pointer;
 		/* valid buffer data in the next page */
 		rest = le16_to_cpu(d->req_count) - le16_to_cpu(d->res_count);
 		/* what actually fits in this page */
-		size2 = min(rest, (size_t)PAGE_SIZE - size);
+		size2 = min(rest, (size_t)PAGE_SIZE - offset - size);
 		memmove(buffer, ctx->pointer, size);
 		memcpy(buffer + size, ab->data, size2);
-		ctx->current_buffer = ab;
-		ctx->pointer = (void *) ab->data + rest;
 
 		while (size > 0) {
 			void *next = handle_ar_packet(ctx, buffer);
@@ -782,22 +781,30 @@ static void ar_context_tasklet(unsigned long data)
 			size -= pktsize;
 			/* fill up this page again */
 			size3 = min(rest - size2,
-				    (size_t)PAGE_SIZE - size - size2);
+				    (size_t)PAGE_SIZE - offset - size - size2);
 			memcpy(buffer + size + size2,
 			       (void *) ab->data + size2, size3);
 			size2 += size3;
 		}
 
-		/* handle the packets that are fully in the next page */
-		buffer = (void *) ab->data + (buffer - (start + size));
-		end = (void *) ab->data + rest;
+		if (rest > 0) {
+			/* handle the packets that are fully in the next page */
+			buffer = (void *) ab->data +
+					(buffer - (start + offset + size));
+			end = (void *) ab->data + rest;
 
-		while (buffer < end)
-			buffer = handle_ar_packet(ctx, buffer);
+			while (buffer < end)
+				buffer = handle_ar_packet(ctx, buffer);
+
+			ctx->current_buffer = ab;
+			ctx->pointer = end;
 
-		dma_free_coherent(ohci->card.device, PAGE_SIZE,
-				  start, start_bus);
-		ar_context_add_page(ctx);
+			dma_free_coherent(ohci->card.device, PAGE_SIZE,
+					  start, start_bus);
+			ar_context_add_page(ctx);
+		} else {
+			ctx->pointer = start + PAGE_SIZE;
+		}
 	} else {
 		buffer = ctx->pointer;
 		ctx->pointer = end =

commit 85f7ffd5d2b320f73912b15fe8cef34bae297daf
Author: Clemens Ladisch <clemens@ladisch.de>
Date:   Mon Oct 25 11:41:53 2010 +0200

    firewire: ohci: fix buffer overflow in AR split packet handling
    
    When the controller had to split a received asynchronous packet into two
    buffers, the driver tries to reassemble it by copying both parts into
    the first page.  However, if size + rest > PAGE_SIZE, i.e., if the yet
    unhandled packets before the split packet, the split packet itself, and
    any received packets after the split packet are together larger than one
    page, then the memory after the first page would get overwritten.
    
    To fix this, do not try to copy the data of all unhandled packets at
    once, but copy the possibly needed data every time when handling
    a packet.
    
    This gets rid of most of the infamous crashes and data corruptions when
    using firewire-net.
    
    Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
    Cc: 2.6.22-2.6.36 <stable@kernel.org>
    Tested-by: Maxim Levitsky <maximlevitsky@gmail.com>
    Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de> (cast PAGE_SIZE to size_t)

diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index 9dcb17d..5826ae3 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -739,7 +739,7 @@ static void ar_context_tasklet(unsigned long data)
 	d = &ab->descriptor;
 
 	if (d->res_count == 0) {
-		size_t size, rest, offset;
+		size_t size, size2, rest, pktsize, size3, offset;
 		dma_addr_t start_bus;
 		void *start;
 
@@ -756,12 +756,41 @@ static void ar_context_tasklet(unsigned long data)
 		ab = ab->next;
 		d = &ab->descriptor;
 		size = buffer + PAGE_SIZE - ctx->pointer;
+		/* valid buffer data in the next page */
 		rest = le16_to_cpu(d->req_count) - le16_to_cpu(d->res_count);
+		/* what actually fits in this page */
+		size2 = min(rest, (size_t)PAGE_SIZE - size);
 		memmove(buffer, ctx->pointer, size);
-		memcpy(buffer + size, ab->data, rest);
+		memcpy(buffer + size, ab->data, size2);
 		ctx->current_buffer = ab;
 		ctx->pointer = (void *) ab->data + rest;
-		end = buffer + size + rest;
+
+		while (size > 0) {
+			void *next = handle_ar_packet(ctx, buffer);
+			pktsize = next - buffer;
+			if (pktsize >= size) {
+				/*
+				 * We have handled all the data that was
+				 * originally in this page, so we can now
+				 * continue in the next page.
+				 */
+				buffer = next;
+				break;
+			}
+			/* move the next packet to the start of the buffer */
+			memmove(buffer, next, size + size2 - pktsize);
+			size -= pktsize;
+			/* fill up this page again */
+			size3 = min(rest - size2,
+				    (size_t)PAGE_SIZE - size - size2);
+			memcpy(buffer + size + size2,
+			       (void *) ab->data + size2, size3);
+			size2 += size3;
+		}
+
+		/* handle the packets that are fully in the next page */
+		buffer = (void *) ab->data + (buffer - (start + size));
+		end = (void *) ab->data + rest;
 
 		while (buffer < end)
 			buffer = handle_ar_packet(ctx, buffer);




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


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

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

Linus, please pull from the fwnet branch at

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

to receive fixes for some older issues.  These modify the experimental
IPv4-over-1394 firewire-net driver only and have been appropriately
stress-tested.  Thanks to Maxim Levitsky for a lot of help with that.
So the probability and risk of regressions are very low.

Stefan Richter (4):
      firewire: net: count stats.tx_packets and stats.tx_bytes
      firewire: net: fix memory leaks
      firewire: net: replace lists by counters
      firewire: net: throttle TX queue before running out of tlabels

 drivers/firewire/net.c |  160 +++++++++++++++++++++++++++---------------------
 1 files changed, 90 insertions(+), 70 deletions(-)

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

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

* [git pull] FireWire fixes
@ 2011-08-15 14:01 Stefan Richter
  0 siblings, 0 replies; 21+ messages in thread
From: Stefan Richter @ 2011-08-15 14:01 UTC (permalink / raw)
  To: Linus Torvalds, Andrew Morton; +Cc: linux-kernel, linux1394-devel

Linus, please pull from the fixes branch at

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

to receive a small update of the IEEE 1394 (FireWire) subsystem.  This addresses
old but only recently reported bugs.  Thanks.

Stefan Richter (2):
      firewire: cdev: fix 32 bit userland on 64 bit kernel compat corner cases
      firewire: ohci: fix DMA unmapping in an error path

 drivers/firewire/core-cdev.c |   24 +++++++++++++++++++++---
 drivers/firewire/ohci.c      |    9 +++++++--
 2 files changed, 28 insertions(+), 5 deletions(-)


Full log and diff:

commit a01e836087881dd9d824417190994c9b2b0f1dbb
Author: Stefan Richter <stefanr@s5r6.in-berlin.de>
Date:   Thu Aug 11 20:40:42 2011 +0200

    firewire: ohci: fix DMA unmapping in an error path
    
    If request_irq failed, we would pass wrong arguments to
    dma_free_coherent.  https://bugzilla.redhat.com/show_bug.cgi?id=728185
    
    Reported-by: Mads Kiilerich
    Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>

diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index 4f6d72f..ded0c9b 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -2178,8 +2178,13 @@ static int ohci_enable(struct fw_card *card,
 			ohci_driver_name, ohci)) {
 		fw_error("Failed to allocate interrupt %d.\n", dev->irq);
 		pci_disable_msi(dev);
-		dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
-				  ohci->config_rom, ohci->config_rom_bus);
+
+		if (config_rom) {
+			dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
+					  ohci->next_config_rom,
+					  ohci->next_config_rom_bus);
+			ohci->next_config_rom = NULL;
+		}
 		return -EIO;
 	}
 

commit 9c1176b6a28850703ea6e3a0f0c703f6d6c61cd3
Author: Stefan Richter <stefanr@s5r6.in-berlin.de>
Date:   Thu Aug 11 00:06:04 2011 +0200

    firewire: cdev: fix 32 bit userland on 64 bit kernel compat corner cases
    
    Clemens points out that we need to use compat_ptr() in order to safely
    cast from u64 to addresses of a 32-bit usermode client.
    
    Before, our conversion went wrong
      - in practice if the client cast from pointer to integer such that
        sign-extension happened, (libraw1394 and libdc1394 at least were not
        doing that, IOW were not affected)
    or
      - in theory on s390 (which doesn't have FireWire though) and on the
        tile architecture, regardless of what the client does.
    The bug would usually be observed as the initial get_info ioctl failing
    with "Bad address" (EFAULT).
    
    Reported-by: Carl Karsten <carl@personnelware.com>
    Reported-by: Clemens Ladisch <clemens@ladisch.de>
    Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>

diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c
index e6ad3bb..4799393 100644
--- a/drivers/firewire/core-cdev.c
+++ b/drivers/firewire/core-cdev.c
@@ -216,15 +216,33 @@ struct inbound_phy_packet_event {
 	struct fw_cdev_event_phy_packet phy_packet;
 };
 
-static inline void __user *u64_to_uptr(__u64 value)
+#ifdef CONFIG_COMPAT
+static void __user *u64_to_uptr(u64 value)
+{
+	if (is_compat_task())
+		return compat_ptr(value);
+	else
+		return (void __user *)(unsigned long)value;
+}
+
+static u64 uptr_to_u64(void __user *ptr)
+{
+	if (is_compat_task())
+		return ptr_to_compat(ptr);
+	else
+		return (u64)(unsigned long)ptr;
+}
+#else
+static inline void __user *u64_to_uptr(u64 value)
 {
 	return (void __user *)(unsigned long)value;
 }
 
-static inline __u64 uptr_to_u64(void __user *ptr)
+static inline u64 uptr_to_u64(void __user *ptr)
 {
-	return (__u64)(unsigned long)ptr;
+	return (u64)(unsigned long)ptr;
 }
+#endif /* CONFIG_COMPAT */
 
 static int fw_device_op_open(struct inode *inode, struct file *file)
 {

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

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

* [git pull] FireWire fixes
@ 2014-03-08  9:37 Stefan Richter
  0 siblings, 0 replies; 21+ messages in thread
From: Stefan Richter @ 2014-03-08  9:37 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-kernel, linux1394-devel

Linus,

please pull from the tag "firewire-fixes" at

    git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394.git firewire-fixes

to receive the following IEEE 1394 (FireWire) subsystem changes.
These fix a use-after-free regression since v3.4 and an initialization
regression since v3.10.

Stefan Richter (2):
      firewire: net: fix use after free
      firewire: ohci: fix probe failure with Agere/LSI controllers

 drivers/firewire/net.c  |  6 +++---
 drivers/firewire/ohci.c | 15 ++-------------
 2 files changed, 5 insertions(+), 16 deletions(-)

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

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

* [git pull] FireWire fixes
@ 2014-05-30 13:41 Stefan Richter
  0 siblings, 0 replies; 21+ messages in thread
From: Stefan Richter @ 2014-05-30 13:41 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-kernel, linux1394-devel

Linus,

please pull from the tag "firewire-fixes" at

    git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394.git firewire-fixes

to receive a regression fix for the IEEE 1394 subsystem:
Re-enable IRQ-based asynchronous request reception at addresses below 128 TB.

Stefan Richter (1):
      firewire: revert to 4 GB RDMA, fix protocols using Memory Space

 Documentation/debugging-via-ohci1394.txt | 13 ++++++++-----
 drivers/firewire/core.h                  |  4 ++--
 drivers/firewire/ohci.c                  |  2 +-
 3 files changed, 11 insertions(+), 8 deletions(-)

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

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

* [git pull] FireWire fixes
@ 2016-11-05 16:17 Stefan Richter
  0 siblings, 0 replies; 21+ messages in thread
From: Stefan Richter @ 2016-11-05 16:17 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-kernel, linux1394-devel

Linus,

please pull from the tag "firewire-fixes" at

    git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394.git firewire-fixes

to receive the following FireWire (IEEE 1394) subsystem fixes:

  - Add missing input validation to the firewire-net driver.
    Invalid IP-over-1394 encapsulation headers could trigger
    buffer overflows (CVE 2016-8633).

  - IP-over-1394 link fragmentation headers were read and written
    incorrectly, breaking fragmented RX/TX with other OS's stacks.

Stefan Richter (2):
      firewire: net: guard against rx buffer overflows
      firewire: net: fix fragmented datagram_size off-by-one

 drivers/firewire/net.c | 59 ++++++++++++++++++++++++++++--------------
 1 file changed, 39 insertions(+), 20 deletions(-)

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

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

end of thread, other threads:[~2016-11-05 16:17 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-11-28 13:07 [git pull] FireWire fixes Stefan Richter
  -- strict thread matches above, loose matches on Subject: below --
2016-11-05 16:17 Stefan Richter
2014-05-30 13:41 Stefan Richter
2014-03-08  9:37 Stefan Richter
2011-08-15 14:01 Stefan Richter
2010-11-05 20:04 Stefan Richter
2010-09-17 12:47 Stefan Richter
2010-09-17 23:06 ` Maxim Levitsky
2010-09-17 23:41   ` Stefan Richter
2010-09-18  0:00     ` Maxim Levitsky
2010-09-18  0:00     ` Peter Stuge
2010-09-18  0:02       ` Maxim Levitsky
2010-08-29  9:54 Stefan Richter
2010-03-02 18:45 [git pull] FireWire updates post 2.6.33 Stefan Richter
2010-03-26 13:05 ` [git pull] FireWire fixes Stefan Richter
2010-04-15 15:59   ` [git pull] FireWire fixes and documentation update Stefan Richter
2010-04-22 19:45     ` [git pull] FireWire fixes Stefan Richter
2009-12-06 17:56 [git pull] FireWire updates post 2.6.32 Stefan Richter
2009-12-11 20:59 ` [git pull] FireWire fix Stefan Richter
2009-12-31 18:55   ` [git pull] FireWire fixes; new firewire stack is recommended to distributors and users Stefan Richter
2010-01-28 17:05     ` [git pull] FireWire fixes Stefan Richter
2010-02-15 22:19       ` Stefan Richter
2009-11-28  0:50 Stefan Richter
2009-09-05 15:18 Stefan Richter
2007-08-25 16:24 [GIT PULL] " Stefan Richter
2007-08-02 18:52 Stefan Richter

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