rpms/kernel/devel linux-2.6-firewire-use-device-orb-timeout.patch, NONE, 1.1 kernel.spec, 1.386, 1.387 linux-2.6-firewire-git-update.patch, 1.3, 1.4 linux-2.6-firewire-config-rom-read-fixup.patch, 1.2, NONE

Jarod Wilson (jwilson) fedora-extras-commits at redhat.com
Fri Jan 25 18:08:26 UTC 2008


Author: jwilson

Update of /cvs/pkgs/rpms/kernel/devel
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv6701

Modified Files:
	kernel.spec linux-2.6-firewire-git-update.patch 
Added Files:
	linux-2.6-firewire-use-device-orb-timeout.patch 
Removed Files:
	linux-2.6-firewire-config-rom-read-fixup.patch 
Log Message:
* Fri Jan 25 2008 Jarod Wilson <jwilson at redhat.com>
- Try login to firewire-sbp2 devices using device-provided timeout


linux-2.6-firewire-use-device-orb-timeout.patch:

--- NEW FILE linux-2.6-firewire-use-device-orb-timeout.patch ---
diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c
index 6a5f0bb..64dd060 100644
--- a/drivers/firewire/fw-sbp2.c
+++ b/drivers/firewire/fw-sbp2.c
@@ -148,15 +148,20 @@ struct sbp2_target {
 
 	unsigned workarounds;
 	struct list_head lu_list;
+
+	unsigned int mgt_orb_timeout;
+	unsigned int orb_size;
 };
 
 /*
  * Per section 7.4.8 of the SBP-2 spec, a mgt_ORB_timeout value can be
- * provided in the config rom.  A high timeout value really only matters
- * on initial login, where we'll just use 20s rather than hassling with
- * reading the config rom, since it really wouldn't buy us much.
+ * provided in the config rom. Most devices do provide a value, which
+ * we'll use for login management orbs, but with some sane limits.
  */
-#define SBP2_LOGIN_ORB_TIMEOUT		20000	/* Timeout in ms */
+#define SBP2_MIN_LOGIN_ORB_TIMEOUT	5000	/* Timeout in ms */
+#define SBP2_MAX_LOGIN_ORB_TIMEOUT	40000	/* Timeout in ms */
+#define MIN(x, y)			((x) < (y) ? (x) : (y))
+#define MAX(x, y)			((x) > (y) ? (x) : (y))
 #define SBP2_ORB_TIMEOUT		2000	/* Timeout in ms */
 #define SBP2_ORB_NULL			0x80000000
 #define SBP2_MAX_SG_ELEMENT_LENGTH	0xf000
@@ -165,6 +170,7 @@ struct sbp2_target {
 #define SBP2_DIRECTION_FROM_MEDIA	0x1
 
 /* Unit directory keys */
+#define SBP2_CSR_UNIT_CHARACTERISTICS	0x3a
 #define SBP2_CSR_FIRMWARE_REVISION	0x3c
 #define SBP2_CSR_LOGICAL_UNIT_NUMBER	0x14
 #define SBP2_CSR_LOGICAL_UNIT_DIRECTORY	0xd4
@@ -494,7 +500,7 @@ sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id,
 {
 	struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
 	struct sbp2_management_orb *orb;
-	unsigned int timeout;
+	unsigned int rom_timeout, timeout;
 	int retval = -ENOMEM;
 
 	orb = kzalloc(sizeof(*orb), GFP_ATOMIC);
@@ -526,7 +532,13 @@ sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id,
 		orb->request.misc |=
 			MANAGEMENT_ORB_RECONNECT(2) |
 			MANAGEMENT_ORB_EXCLUSIVE(sbp2_param_exclusive_login);
-		timeout = SBP2_LOGIN_ORB_TIMEOUT;
+		rom_timeout = lu->tgt->mgt_orb_timeout * 500; /* in ms */
+		timeout = MIN(SBP2_MAX_LOGIN_ORB_TIMEOUT,
+			      MAX(rom_timeout, SBP2_MIN_LOGIN_ORB_TIMEOUT));
+		if (rom_timeout != timeout)
+			fw_notify("Device config rom gave us a %ds timeout, "
+				  "overriding to %ds\n",
+				  rom_timeout / 1000, timeout / 1000);
 	} else {
 		timeout = SBP2_ORB_TIMEOUT;
 	}


Index: kernel.spec
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/kernel.spec,v
retrieving revision 1.386
retrieving revision 1.387
diff -u -r1.386 -r1.387
--- kernel.spec	25 Jan 2008 17:39:39 -0000	1.386
+++ kernel.spec	25 Jan 2008 18:07:30 -0000	1.387
@@ -656,7 +656,7 @@
 
 # linux1394 git patches
 Patch2200: linux-2.6-firewire-git-update.patch
-Patch2201: linux-2.6-firewire-config-rom-read-fixup.patch
+Patch2201: linux-2.6-firewire-use-device-orb-timeout.patch
 
 # make USB EHCI driver respect "nousb" parameter
 Patch2300: linux-2.6-usb-ehci-hcd-respect-nousb.patch
@@ -1188,7 +1188,7 @@
 
 # linux1394 git patches
 ApplyPatch linux-2.6-firewire-git-update.patch
-ApplyPatch linux-2.6-firewire-config-rom-read-fixup.patch
+ApplyPatch linux-2.6-firewire-use-device-orb-timeout.patch
 
 # usb video
 ApplyPatch linux-2.6-uvcvideo.patch
@@ -1761,6 +1761,9 @@
 %kernel_variant_files -a /%{image_install_path}/xen*-%{KVERREL} -e /etc/ld.so.conf.d/kernelcap-%{KVERREL}.conf %{with_xen} xen
 
 %changelog
+* Fri Jan 25 2008 Jarod Wilson <jwilson at redhat.com>
+- Try login to firewire-sbp2 devices using device-provided timeout
+
 * Fri Jan 25 2008 Chuck Ebbert <cebbert at redhat.com>
 - Bump revision.
 

linux-2.6-firewire-git-update.patch:

Index: linux-2.6-firewire-git-update.patch
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/linux-2.6-firewire-git-update.patch,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- linux-2.6-firewire-git-update.patch	23 Jan 2008 20:08:21 -0000	1.3
+++ linux-2.6-firewire-git-update.patch	25 Jan 2008 18:07:30 -0000	1.4
@@ -1,954 +1,160 @@
-IEEE 1394 updates for Linux 2.6.24-rc8 (v603 2008-01-19)
-
- MAINTAINERS                              |    4 
- drivers/firewire/fw-ohci.c               |  386 ++++++++++++++---------
- drivers/firewire/fw-sbp2.c               |  100 +++--
- drivers/firewire/fw-transaction.c        |    2 
- drivers/ieee1394/dma.c                   |   37 --
- drivers/ieee1394/ieee1394_transactions.c |   68 ----
- drivers/ieee1394/ohci1394.c              |   12 
- drivers/ieee1394/raw1394.c               |    4 
- drivers/ieee1394/sbp2.c                  |   52 +--
- drivers/ieee1394/sbp2.h                  |    1 
- 10 files changed, 350 insertions(+), 316 deletions(-)
-
-========================================================================
-Date: Sat, 19 Jan 2008 13:15:05 +0100 (CET)
-From: Jarod Wilson <jwilson at redhat.com>
-Subject: firewire: fw-sbp2: increase login orb reply timeout, fix "failed to login"
-
-Increase (and rename) the management orb reply timeout value
-to 20s to match that of the old firewire stack. 2s simply didn't
-give many devices enough time to spin up and reply.
-
-Signed-off-by: Jarod Wilson <jwilson at redhat.com>
-
-Fixes inability to recognize some devices.
-Failure mode was "orb reply timed out"/"failed to login".
-
-Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de> (style, comments, changelog)
----
- drivers/firewire/fw-sbp2.c |   16 +++++++++++++---
- 1 file changed, 13 insertions(+), 3 deletions(-)
-
-========================================================================
-Date: Sat, 12 Jan 2008 12:32:44 +0100 (CET)
-From: Stefan Richter <stefanr at s5r6.in-berlin.de>
-Subject: firewire vs. ieee1394: clarify MAINTAINERS
-
-Maintainers like to receive less mail, and submitters like to have to Cc
-less recipients.
-
-Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
----
- MAINTAINERS |    4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-========================================================================
-Date: Sun, 06 Jan 2008 17:21:41 -0500
-From: David Moore <dcm at MIT.EDU>
-Subject: firewire: fw-ohci: Dynamically allocate buffers for DMA descriptors
-
-Previously, the fw-ohci driver used fixed-length buffers for storing
-descriptors for isochronous receive DMA programs.  If an application
-(such as libdc1394) generated a DMA program that was too large, fw-ohci
-would reach the limit of its fixed-sized buffer and return an error to
-userspace.
-
-This patch replaces the fixed-length ring-buffer with a linked-list of
-page-sized buffers.  Additional buffers can be dynamically allocated and
-appended to the list when necessary.  For a particular context, buffers
-are kept around after use and reused as necessary, so there is no
-allocation taking place after the DMA program is generated for the first
-time.
-
-In addition, the buffers it uses are coherent for DMA so there is no
-syncing required before and after writes.  This syncing wasn't properly
-done in the previous version of the code.
-
--
-
-This is the fourth version of my patch that replaces a fixed-length
-buffer for DMA descriptors with a dynamically allocated linked-list of
-buffers.
-
-As we discovered with the last attempt, new context programs are
-sometimes queued from interrupt context, making it unacceptable to call
-tasklet_disable() from context_get_descriptors().
-
-This version of the patch uses ohci->lock for all locking needs instead
-of tasklet_disable/enable.  There is a new requirement that
-context_get_descriptors() be called while holding ohci->lock.  It was
-already held for the AT context, so adding the requirement for the iso
-context did not seem particularly onerous.  In addition, this has the
-side benefit of allowing iso queue to be safely called from concurrent
-user-space threads, which previously was not safe.
-
-Signed-off-by: David Moore <dcm at acm.org>
-Signed-off-by: Kristian Høgsberg <krh at redhat.com>
-Signed-off-by: Jarod Wilson <jwilson at redhat.com>
-
--
-
-Fixes the following issues:
-  - Isochronous reception stopped prematurely if an application used a
-    larger buffer.  (Reproduced with coriander.)
-  - Isochronous reception stopped after one or a few frames on VT630x
-    in OHCI 1.0 mode.  (Fixes reception in coriander, but dvgrab still
-    doesn't work with these chips.)
-
-Patch update: struct member alignment, whitespace nits
-
-Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
----
- drivers/firewire/fw-ohci.c |  232 ++++++++++++++++++++++++-------------
- 1 file changed, 154 insertions(+), 78 deletions(-)
-
-========================================================================
-Date: Sat, 22 Dec 2007 22:14:52 +0100 (CET)
-From: Stefan Richter <stefanr at s5r6.in-berlin.de>
-Subject: firewire: fw-ohci: CycleTooLong interrupt management
-
-The firewire-ohci driver so far lacked the ability to resume cycle
-master duty after that condition happened, as added to ohci1394 in Linux
-2.6.18 by commit 57fdb58fa5a140bdd52cf4c4ffc30df73676f0a5.  This ports
-this patch to fw-ohci.
-
-The "cycle too long" condition has been seen in practice
-  - with IIDC cameras if a mode with packets too large for a speed is
-    chosen,
-  - sporadically when capturing DV on a VIA VT6306 card with ohci1394/
-    ieee1394/ raw1394/ dvgrab 2.
-    https://bugzilla.redhat.com/show_bug.cgi?id=415841#c7
-(This does not fix Fedora bug 415841.)
-
-Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
----
- drivers/firewire/fw-ohci.c |   11 +++++++++--
- 1 file changed, 9 insertions(+), 2 deletions(-)
-
-========================================================================
-Date: Fri, 21 Dec 2007 23:02:15 +0530
-From: Rabin Vincent <rabin at rab.in>
-Subject: firewire: Fix extraction of source node id
-
-Fix extraction of the source node id from the packet header.
-
-Signed-off-by: Rabin Vincent <rabin at rab.in>
-Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
----
- drivers/firewire/fw-transaction.c |    2 +-
- 1 files changed, 1 insertions(+), 1 deletions(-)
-
-========================================================================
-Date: Wed, 19 Dec 2007 15:26:38 -0500
-From: David Moore <dcm at MIT.EDU>
-Subject: firewire: fw-ohci: Bug fixes for packet-per-buffer support
-
-This patch corrects a number of bugs in the current OHCI 1.0
-packet-per-buffer support:
-
-1. Correctly deal with payloads that cross a page boundary.  The
-previous version would not split the descriptor at such a boundary,
-potentially corrupting unrelated memory.
-
-2. Allow user-space to specify multiple packets per struct
-fw_cdev_iso_packet in the same way that dual-buffer allows.  This is
-signaled by header_length being a multiple of header_size.  This
-multiple determines the number of packets.  The payload size allocated
-per packet is determined by dividing the total payload size by the
-number of packets.
-
-3. Make sync support work properly for packet-per-buffer.
-
-I have tested this patch with libdc1394 by forcing my OHCI 1.1
-controller to use the packet-per-buffer support instead of dual-buffer.
-
-I would greatly appreciate testing by those who have a DV devices and
-other types of iso streamers to make sure I didn't cause any
-regressions.
-
-Stefan, with this patch, I'm hoping that libdc1394 will work with all
-your OHCI 1.0 controllers now.
-
-The one bit of future work that remains for packet-per-buffer support is
-the automatic compaction of short payloads that I discussed with
-Kristian.
-
-Signed-off-by: David Moore <dcm at acm.org>
-Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
----
- drivers/firewire/fw-ohci.c |   99 ++++++++++++++++++-------------------
- 1 file changed, 49 insertions(+), 50 deletions(-)
-
-========================================================================
-Date: Wed, 19 Dec 2007 03:09:18 -0500
-From: David Moore <dcm at MIT.EDU>
-Subject: firewire: fw-ohci: Fix for dualbuffer three-or-more buffers
-
-This patch fixes the problem where different OHCI 1.1 controllers behave
-differently when a received iso packet straddles three or more buffers
-when using the dual-buffer receive mode.  Two changes are made in order
-to handle this situation:
-
-1. The packet sync DMA descriptor is given a non-zero header length and
-non-zero payload length.  This is because zero-payload descriptors are
-not discussed in the OHCI 1.1 specs and their behavior is thus
-undefined.  Instead we use a header size just large enough for a single
-header and a payload length of 4 bytes for this first descriptor.
-
-2. As we process received packets in the context's tasklet, read the
-packet length out of the headers.  Keep track of the running total of
-the packet length as "excess_bytes", so we can ignore any descriptors
-where no packet starts or ends.  These descriptors may not have had
-their first_res_count or second_res_count fields updated by the
-controller so we cannot rely on those values.
-
-The main drawback of this patch is that the excess_bytes value might get
-"out of sync" with the packet descriptors if something strange happens
-to the DMA program.  I'm not if such a thing could ever happen, but I
-appreciate any suggestions in making it more robust.
-
-Also, the packet-per-buffer support may need a similar fix to deal with
-issue 1, but I haven't done any work on that yet.
-
-Stefan, I'm hoping that with this patch, all your OHCI 1.1 controllers
-will work properly with an unmodified version of libdc1394.
-
-Signed-off-by: David Moore <dcm at acm.org>
-Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
----
- drivers/firewire/fw-ohci.c |   44 ++++++++++++++++++++-----------------
- 1 file changed, 24 insertions(+), 20 deletions(-)
-
-========================================================================
-Date: Sun, 16 Dec 2007 17:32:11 +0100 (CET)
-From: Stefan Richter <stefanr at s5r6.in-berlin.de>
-Subject: firewire: fw-sbp2: remove unused misleading macro
-
-SBP2_MAX_SECTORS is nowhere used in fw-sbp2.
-It merely got copied over from sbp2 where it played a role in the past.
-
-Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
----
- drivers/firewire/fw-sbp2.c |    2 --
- 1 file changed, 2 deletions(-)
-
-========================================================================
-Date: Wed, 7 Nov 2007 17:39:00 -0500
-From: Jay Fenlason <fenlason at redhat.com>
-Subject: firewire: fw-sbp2: quiet logout errors on device removal
-
-This suppresses both reply timed out and management write failed
-errors on LOGOUT requests.
-
-Signed-off-by: Jay Fenlason <fenlason at redhat.com>
-Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
----
- fw-sbp2.c |   20 ++++++++++++++++----
- 1 file changed, 16 insertions(+), 4 deletions(-)
-
-========================================================================
-Date: Tue, 15 Jan 2008 21:10:50 +0100 (CET)
-From: Stefan Richter <stefanr at s5r6.in-berlin.de>
-Subject: firewire: fw-sbp2: prepare for s/g chaining
-
-Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
----
- drivers/firewire/fw-sbp2.c |    6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
-========================================================================
-Date: Wed, 7 Nov 2007 01:12:51 +0100 (CET)
-From: Stefan Richter <stefanr at s5r6.in-berlin.de>
-Subject: firewire: fw-sbp2: refactor workq and kref handling
-
-This somewhat reduces the size of firewire-sbp2.ko.
-
-Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
----
- drivers/firewire/fw-sbp2.c |   56 +++++++++++++++++++------------------
- 1 file changed, 30 insertions(+), 26 deletions(-)
-
-========================================================================
-Date: Sun, 16 Dec 2007 20:53:13 +0100 (CET)
-From: Stefan Richter <stefanr at s5r6.in-berlin.de>
-Subject: ieee1394: ohci1394: don't schedule IT tasklets on IR events
-
-Bug noted by Pieter Palmers:  Isochronous transmit tasklets were
-scheduled on isochronous receive events, in addition to the proper
-isochronous receive tasklets.
-
-http://marc.info/?l=linux1394-devel&m=119783196222802
-
-Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
----
- drivers/ieee1394/ohci1394.c |   12 ++++++++----
- 1 file changed, 8 insertions(+), 4 deletions(-)
-
-========================================================================
-Date: Sun, 16 Dec 2007 17:31:26 +0100 (CET)
-From: Stefan Richter <stefanr at s5r6.in-berlin.de>
-Subject: ieee1394: sbp2: raise default transfer size limit
-
-This patch speeds up sbp2 a little bit --- but more importantly, it
-brings the behavior of sbp2 and fw-sbp2 closer to each other.  Like
-fw-sbp2, sbp2 now does not limit the size of single transfers to 255
-sectors anymore, unless told so by a blacklist flag or by module load
-parameters.
-
-Only very old bridge chips have been known to need the 255 sectors
-limit, and we have got one such chip in our hardwired blacklist.  There
-certainly is a danger that more bridges need that limit; but I prefer to
-have this issue present in both fw-sbp2 and sbp2 rather than just one of
-them.
-
-An OXUF922 with 400GB 7200RPM disk on an S400 controller is sped up by
-this patch from 22.9 to 23.5 MB/s according to hdparm.  The same effect
-could be achieved before by setting a higher max_sectors module
-parameter.  On buses which use 1394b beta mode, sbp2 and fw-sbp2 will
-now achieve virtually the same bandwidth.  Fw-sbp2 only remains faster
-on 1394a buses due to fw-core's gap count optimization.
-
-Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
----
- drivers/ieee1394/sbp2.c |   26 +++++++++++++++-----------
- drivers/ieee1394/sbp2.h |    1 -
- 2 files changed, 15 insertions(+), 12 deletions(-)
-
-========================================================================
-Date: Sat, 15 Dec 2007 14:11:41 +0100 (CET)
-From: Stefan Richter <stefanr at s5r6.in-berlin.de>
-Subject: ieee1394: remove unused code
-
-The code has been in "#if 0 - #endif" since Linux 2.6.12.
-
-Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
----
- drivers/ieee1394/ieee1394_transactions.c |   68 -----------------------
- 1 file changed, 68 deletions(-)
-
-========================================================================
-Date: Sat, 15 Dec 2007 14:04:42 +0100 (CET)
-From: Stefan Richter <stefanr at s5r6.in-berlin.de>
-Subject: ieee1394: small cleanup after "nopage"
-
-Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
----
- drivers/ieee1394/dma.c |   16 ++++------------
- 1 file changed, 4 insertions(+), 12 deletions(-)
-
-========================================================================
-Date: Wed, 05 Dec 2007 18:15:53 +1100
-From: Nick Piggin <npiggin at suse.de>
-Subject: ieee1394: nopage
-
-Convert ieee1394 from nopage to fault.
-Remove redundant vma range checks (correct resource range check is retained).
-
-Signed-off-by: Nick Piggin <npiggin at suse.de>
-Signed-off-by: Andrew Morton <akpm at linux-foundation.org>
-Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
----
- drivers/ieee1394/dma.c |   39 +++++++++++++++++----------------------
- 1 file changed, 17 insertions(+), 22 deletions(-)
-
-========================================================================
-Date: Mon, 19 Nov 2007 17:48:10 -0800
-From: Joe Perches <joe at perches.com>
-Subject: ieee1394: Add missing "space"
-
-Signed-off-by: Joe Perches <joe at perches.com>
-Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
----
- drivers/ieee1394/raw1394.c |    4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-========================================================================
-Date: Sun, 4 Nov 2007 14:59:24 +0100 (CET)
-From: Stefan Richter <stefanr at s5r6.in-berlin.de>
-Subject: ieee1394: sbp2: s/g list access cosmetics
-
-Replace sg->length by sg_dma_len(sg).  Rename a variable for shorter
-line lengths and eliminate some superfluous local variables.
-
-Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
----
- drivers/ieee1394/sbp2.c |   26 ++++++++++++--------------
- 1 file changed, 12 insertions(+), 14 deletions(-)
-
-========================================================================
-Date: Tue, 15 Jan 2008 21:11:28 +0100 (CET)
-From: Stefan Richter <stefanr at s5r6.in-berlin.de>
-Subject: ieee1394: sbp2: prepare for s/g chaining
-
-Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
----
- drivers/ieee1394/sbp2.c |    2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-========================================================================
-Index: linux/drivers/ieee1394/sbp2.c
-===================================================================
---- linux.orig/drivers/ieee1394/sbp2.c
-+++ linux/drivers/ieee1394/sbp2.c
-@@ -51,6 +51,7 @@
-  * Grep for inline FIXME comments below.
-  */
- 
-+#include <linux/blkdev.h>
- #include <linux/compiler.h>
- #include <linux/delay.h>
- #include <linux/device.h>
-@@ -127,17 +128,21 @@ MODULE_PARM_DESC(serialize_io, "Serializ
- 		 "(default = Y, faster but buggy = N)");
- 
- /*
-- * Bump up max_sectors if you'd like to support very large sized
-- * transfers. Please note that some older sbp2 bridge chips are broken for
-- * transfers greater or equal to 128KB.  Default is a value of 255
-- * sectors, or just under 128KB (at 512 byte sector size). I can note that
-- * the Oxsemi sbp2 chipsets have no problems supporting very large
-- * transfer sizes.
-+ * Adjust max_sectors if you'd like to influence how many sectors each SCSI
-+ * command can transfer at most. Please note that some older SBP-2 bridge
-+ * chips are broken for transfers greater or equal to 128KB, therefore
-+ * max_sectors used to be a safe 255 sectors for many years. We now have a
-+ * default of 0 here which means that we let the SCSI stack choose a limit.
-+ *
-+ * The SBP2_WORKAROUND_128K_MAX_TRANS flag, if set either in the workarounds
-+ * module parameter or in the sbp2_workarounds_table[], will override the
-+ * value of max_sectors. We should use sbp2_workarounds_table[] to cover any
-+ * bridge chip which becomes known to need the 255 sectors limit.
-  */
--static int sbp2_max_sectors = SBP2_MAX_SECTORS;
-+static int sbp2_max_sectors;
- module_param_named(max_sectors, sbp2_max_sectors, int, 0444);
- MODULE_PARM_DESC(max_sectors, "Change max sectors per I/O supported "
--		 "(default = " __stringify(SBP2_MAX_SECTORS) ")");
-+		 "(default = 0 = use SCSI stack's default)");
- 
- /*
-  * Exclusive login to sbp2 device? In most cases, the sbp2 driver should
-@@ -1451,7 +1456,7 @@ static void sbp2_prep_command_orb_sg(str
- 				     struct sbp2_fwhost_info *hi,
- 				     struct sbp2_command_info *cmd,
- 				     unsigned int scsi_use_sg,
--				     struct scatterlist *sgpnt,
-+				     struct scatterlist *sg,
- 				     u32 orb_direction,
- 				     enum dma_data_direction dma_dir)
- {
-@@ -1461,12 +1466,12 @@ static void sbp2_prep_command_orb_sg(str
- 
- 	/* special case if only one element (and less than 64KB in size) */
- 	if ((scsi_use_sg == 1) &&
--	    (sgpnt[0].length <= SBP2_MAX_SG_ELEMENT_LENGTH)) {
-+	    (sg_dma_len(sg) <= SBP2_MAX_SG_ELEMENT_LENGTH)) {
- 
--		cmd->dma_size = sgpnt[0].length;
-+		cmd->dma_size = sg_dma_len(sg);
- 		cmd->dma_type = CMD_DMA_PAGE;
- 		cmd->cmd_dma = dma_map_page(hi->host->device.parent,
--					    sg_page(&sgpnt[0]), sgpnt[0].offset,
-+					    sg_page(sg), sg->offset,
- 					    cmd->dma_size, cmd->dma_dir);
- 
- 		orb->data_descriptor_lo = cmd->cmd_dma;
-@@ -1477,11 +1482,11 @@ static void sbp2_prep_command_orb_sg(str
- 						&cmd->scatter_gather_element[0];
- 		u32 sg_count, sg_len;
- 		dma_addr_t sg_addr;
--		int i, count = dma_map_sg(hi->host->device.parent, sgpnt,
-+		int i, count = dma_map_sg(hi->host->device.parent, sg,
- 					  scsi_use_sg, dma_dir);
- 
- 		cmd->dma_size = scsi_use_sg;
--		cmd->sge_buffer = sgpnt;
-+		cmd->sge_buffer = sg;
- 
- 		/* use page tables (s/g) */
- 		orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1);
-@@ -1489,9 +1494,9 @@ static void sbp2_prep_command_orb_sg(str
- 
- 		/* loop through and fill out our SBP-2 page tables
- 		 * (and split up anything too large) */
--		for (i = 0, sg_count = 0 ; i < count; i++, sgpnt++) {
--			sg_len = sg_dma_len(sgpnt);
--			sg_addr = sg_dma_address(sgpnt);
-+		for (i = 0, sg_count = 0; i < count; i++, sg = sg_next(sg)) {
-+			sg_len = sg_dma_len(sg);
-+			sg_addr = sg_dma_address(sg);
- 			while (sg_len) {
- 				sg_element[sg_count].segment_base_lo = sg_addr;
- 				if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) {
-@@ -1521,11 +1526,10 @@ static void sbp2_create_command_orb(stru
- 				    unchar *scsi_cmd,
- 				    unsigned int scsi_use_sg,
- 				    unsigned int scsi_request_bufflen,
--				    void *scsi_request_buffer,
-+				    struct scatterlist *sg,
- 				    enum dma_data_direction dma_dir)
- {
- 	struct sbp2_fwhost_info *hi = lu->hi;
--	struct scatterlist *sgpnt = (struct scatterlist *)scsi_request_buffer;
- 	struct sbp2_command_orb *orb = &cmd->command_orb;
- 	u32 orb_direction;
- 
-@@ -1560,7 +1564,7 @@ static void sbp2_create_command_orb(stru
- 		orb->data_descriptor_lo = 0x0;
- 		orb->misc |= ORB_SET_DIRECTION(1);
- 	} else
--		sbp2_prep_command_orb_sg(orb, hi, cmd, scsi_use_sg, sgpnt,
-+		sbp2_prep_command_orb_sg(orb, hi, cmd, scsi_use_sg, sg,
- 					 orb_direction, dma_dir);
- 
- 	sbp2util_cpu_to_be32_buffer(orb, sizeof(*orb));
-@@ -1650,7 +1654,6 @@ static int sbp2_send_command(struct sbp2
- 			     void (*done)(struct scsi_cmnd *))
- {
- 	unchar *scsi_cmd = (unchar *)SCpnt->cmnd;
--	unsigned int request_bufflen = scsi_bufflen(SCpnt);
- 	struct sbp2_command_info *cmd;
- 
- 	cmd = sbp2util_allocate_command_orb(lu, SCpnt, done);
-@@ -1658,7 +1661,7 @@ static int sbp2_send_command(struct sbp2
- 		return -EIO;
- 
- 	sbp2_create_command_orb(lu, cmd, scsi_cmd, scsi_sg_count(SCpnt),
--				request_bufflen, scsi_sglist(SCpnt),
-+				scsi_bufflen(SCpnt), scsi_sglist(SCpnt),
- 				SCpnt->sc_data_direction);
- 	sbp2_link_orb_command(lu, cmd);
- 
-@@ -1981,6 +1984,8 @@ static int sbp2scsi_slave_configure(stru
- 		sdev->skip_ms_page_8 = 1;
- 	if (lu->workarounds & SBP2_WORKAROUND_FIX_CAPACITY)
- 		sdev->fix_capacity = 1;
-+	if (lu->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS)
-+		blk_queue_max_sectors(sdev->request_queue, 128 * 1024 / 512);
- 	return 0;
+diff -Naurp linux-2.6-git/drivers/firewire/fw-cdev.c firewire-git/drivers/firewire/fw-cdev.c
+--- linux-2.6-git/drivers/firewire/fw-cdev.c	2008-01-01 22:50:33.000000000 -0500
++++ firewire-git/drivers/firewire/fw-cdev.c	2008-01-25 12:41:22.000000000 -0500
+@@ -206,12 +206,13 @@ fill_bus_reset_event(struct fw_cdev_even
+ 
+ 	event->closure	     = client->bus_reset_closure;
+ 	event->type          = FW_CDEV_EVENT_BUS_RESET;
++	event->generation    = client->device->generation;
++	smp_rmb();           /* node_id must not be older than generation */
+ 	event->node_id       = client->device->node_id;
+ 	event->local_node_id = card->local_node->node_id;
+ 	event->bm_node_id    = 0; /* FIXME: We don't track the BM. */
+ 	event->irm_node_id   = card->irm_node->node_id;
+ 	event->root_node_id  = card->root_node->node_id;
+-	event->generation    = card->generation;
  }
  
-@@ -2087,9 +2092,6 @@ static int sbp2_module_init(void)
- 		sbp2_shost_template.cmd_per_lun = 1;
- 	}
- 
--	if (sbp2_default_workarounds & SBP2_WORKAROUND_128K_MAX_TRANS &&
--	    (sbp2_max_sectors * 512) > (128 * 1024))
--		sbp2_max_sectors = 128 * 1024 / 512;
- 	sbp2_shost_template.max_sectors = sbp2_max_sectors;
- 
- 	hpsb_register_highlevel(&sbp2_highlevel);
-Index: linux/drivers/ieee1394/raw1394.c
-===================================================================
---- linux.orig/drivers/ieee1394/raw1394.c
-+++ linux/drivers/ieee1394/raw1394.c
-@@ -858,7 +858,7 @@ static int arm_read(struct hpsb_host *ho
- 	int found = 0, size = 0, rcode = -1;
- 	struct arm_request_response *arm_req_resp = NULL;
- 
--	DBGMSG("arm_read  called by node: %X"
-+	DBGMSG("arm_read  called by node: %X "
- 	       "addr: %4.4x %8.8x length: %Zu", nodeid,
- 	       (u16) ((addr >> 32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF),
- 	       length);
-@@ -1012,7 +1012,7 @@ static int arm_write(struct hpsb_host *h
- 	int found = 0, size = 0, rcode = -1, length_conflict = 0;
- 	struct arm_request_response *arm_req_resp = NULL;
- 
--	DBGMSG("arm_write called by node: %X"
-+	DBGMSG("arm_write called by node: %X "
- 	       "addr: %4.4x %8.8x length: %Zu", nodeid,
- 	       (u16) ((addr >> 32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF),
- 	       length);
-Index: linux/drivers/ieee1394/dma.c
-===================================================================
---- linux.orig/drivers/ieee1394/dma.c
-+++ linux/drivers/ieee1394/dma.c
-@@ -231,37 +231,24 @@ void dma_region_sync_for_device(struct d
- 
- #ifdef CONFIG_MMU
+ static void
+diff -Naurp linux-2.6-git/drivers/firewire/fw-device.c firewire-git/drivers/firewire/fw-device.c
+--- linux-2.6-git/drivers/firewire/fw-device.c	2008-01-01 22:50:33.000000000 -0500
++++ firewire-git/drivers/firewire/fw-device.c	2008-01-25 12:41:22.000000000 -0500
+@@ -182,9 +182,14 @@ static void fw_device_release(struct dev
  
--/* nopage() handler for mmap access */
--
--static struct page *dma_region_pagefault(struct vm_area_struct *area,
--					 unsigned long address, int *type)
-+static int dma_region_pagefault(struct vm_area_struct *vma,
-+				struct vm_fault *vmf)
+ int fw_device_enable_phys_dma(struct fw_device *device)
  {
--	unsigned long offset;
--	unsigned long kernel_virt_addr;
--	struct page *ret = NOPAGE_SIGBUS;
--
--	struct dma_region *dma = (struct dma_region *)area->vm_private_data;
-+	struct dma_region *dma = (struct dma_region *)vma->vm_private_data;
- 
- 	if (!dma->kvirt)
--		goto out;
-+		return VM_FAULT_SIGBUS;
- 
--	if ((address < (unsigned long)area->vm_start) ||
--	    (address >
--	     (unsigned long)area->vm_start + (dma->n_pages << PAGE_SHIFT)))
--		goto out;
--
--	if (type)
--		*type = VM_FAULT_MINOR;
--	offset = address - area->vm_start;
--	kernel_virt_addr = (unsigned long)dma->kvirt + offset;
--	ret = vmalloc_to_page((void *)kernel_virt_addr);
--	get_page(ret);
--      out:
--	return ret;
-+	if (vmf->pgoff >= dma->n_pages)
-+		return VM_FAULT_SIGBUS;
++	int generation = device->generation;
 +
-+	vmf->page = vmalloc_to_page(dma->kvirt + (vmf->pgoff << PAGE_SHIFT));
-+	get_page(vmf->page);
-+	return 0;
++	/* device->node_id, accessed below, must not be older than generation */
++	smp_rmb();
++
+ 	return device->card->driver->enable_phys_dma(device->card,
+ 						     device->node_id,
+-						     device->generation);
++						     generation);
  }
+ EXPORT_SYMBOL(fw_device_enable_phys_dma);
  
- static struct vm_operations_struct dma_region_vm_ops = {
--	.nopage = dma_region_pagefault,
-+	.fault = dma_region_pagefault,
- };
- 
- /**
-@@ -275,7 +262,7 @@ int dma_region_mmap(struct dma_region *d
- 	if (!dma->kvirt)
- 		return -EINVAL;
- 
--	/* must be page-aligned */
-+	/* must be page-aligned (XXX: comment is wrong, we could allow pgoff) */
- 	if (vma->vm_pgoff != 0)
- 		return -EINVAL;
- 
-Index: linux/drivers/ieee1394/ieee1394_transactions.c
-===================================================================
---- linux.orig/drivers/ieee1394/ieee1394_transactions.c
-+++ linux/drivers/ieee1394/ieee1394_transactions.c
-@@ -570,71 +570,3 @@ int hpsb_write(struct hpsb_host *host, n
- 
- 	return retval;
+@@ -384,17 +389,21 @@ complete_transaction(struct fw_card *car
+ 	complete(&callback_data->done);
  }
--
--#if 0
--
--int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
--	      u64 addr, int extcode, quadlet_t * data, quadlet_t arg)
--{
--	struct hpsb_packet *packet;
--	int retval = 0;
--
--	BUG_ON(in_interrupt());	// We can't be called in an interrupt, yet
--
--	packet = hpsb_make_lockpacket(host, node, addr, extcode, data, arg);
--	if (!packet)
--		return -ENOMEM;
--
--	packet->generation = generation;
--	retval = hpsb_send_packet_and_wait(packet);
--	if (retval < 0)
--		goto hpsb_lock_fail;
--
--	retval = hpsb_packet_success(packet);
--
--	if (retval == 0) {
--		*data = packet->data[0];
--	}
--
--      hpsb_lock_fail:
--	hpsb_free_tlabel(packet);
--	hpsb_free_packet(packet);
--
--	return retval;
--}
--
--int hpsb_send_gasp(struct hpsb_host *host, int channel, unsigned int generation,
--		   quadlet_t * buffer, size_t length, u32 specifier_id,
--		   unsigned int version)
--{
--	struct hpsb_packet *packet;
--	int retval = 0;
--	u16 specifier_id_hi = (specifier_id & 0x00ffff00) >> 8;
--	u8 specifier_id_lo = specifier_id & 0xff;
--
--	HPSB_VERBOSE("Send GASP: channel = %d, length = %Zd", channel, length);
--
--	length += 8;
--
--	packet = hpsb_make_streampacket(host, NULL, length, channel, 3, 0);
--	if (!packet)
--		return -ENOMEM;
--
--	packet->data[0] = cpu_to_be32((host->node_id << 16) | specifier_id_hi);
--	packet->data[1] =
--	    cpu_to_be32((specifier_id_lo << 24) | (version & 0x00ffffff));
--
--	memcpy(&(packet->data[2]), buffer, length - 8);
--
--	packet->generation = generation;
--
--	packet->no_waiter = 1;
--
--	retval = hpsb_send_packet(packet);
--	if (retval < 0)
--		hpsb_free_packet(packet);
--
--	return retval;
--}
--
--#endif				/*  0  */
-Index: linux/drivers/ieee1394/sbp2.h
-===================================================================
---- linux.orig/drivers/ieee1394/sbp2.h
-+++ linux/drivers/ieee1394/sbp2.h
-@@ -222,7 +222,6 @@ struct sbp2_status_block {
-  */
- 
- #define SBP2_MAX_SG_ELEMENT_LENGTH		0xf000
--#define SBP2_MAX_SECTORS			255
- /* There is no real limitation of the queue depth (i.e. length of the linked
-  * list of command ORBs) at the target. The chosen depth is merely an
-  * implementation detail of the sbp2 driver. */
-Index: linux/drivers/ieee1394/ohci1394.c
-===================================================================
---- linux.orig/drivers/ieee1394/ohci1394.c
-+++ linux/drivers/ieee1394/ohci1394.c
-@@ -2126,10 +2126,14 @@ static void ohci_schedule_iso_tasklets(s
- 	list_for_each_entry(t, &ohci->iso_tasklet_list, link) {
- 		mask = 1 << t->context;
- 
--		if (t->type == OHCI_ISO_TRANSMIT && tx_event & mask)
--			tasklet_schedule(&t->tasklet);
--		else if (rx_event & mask)
--			tasklet_schedule(&t->tasklet);
-+		if (t->type == OHCI_ISO_TRANSMIT) {
-+			if (tx_event & mask)
-+				tasklet_schedule(&t->tasklet);
-+		} else {
-+			/* OHCI_ISO_RECEIVE or OHCI_ISO_MULTICHANNEL_RECEIVE */
-+			if (rx_event & mask)
-+				tasklet_schedule(&t->tasklet);
-+		}
- 	}
  
- 	spin_unlock_irqrestore(&ohci->iso_tasklet_list_lock, flags);
-Index: linux/drivers/firewire/fw-sbp2.c
-===================================================================
---- linux.orig/drivers/firewire/fw-sbp2.c
-+++ linux/drivers/firewire/fw-sbp2.c
-@@ -150,11 +150,16 @@ struct sbp2_target {
- 	struct list_head lu_list;
- };
+-static int read_rom(struct fw_device *device, int index, u32 * data)
++static int
++read_rom(struct fw_device *device, int generation, int index, u32 *data)
+ {
+ 	struct read_quadlet_callback_data callback_data;
+ 	struct fw_transaction t;
+ 	u64 offset;
+ 
++	/* device->node_id, accessed below, must not be older than generation */
++	smp_rmb();
++
+ 	init_completion(&callback_data.done);
+ 
+ 	offset = 0xfffff0000400ULL + index * 4;
+ 	fw_send_request(device->card, &t, TCODE_READ_QUADLET_REQUEST,
+-			device->node_id, device->generation, device->max_speed,
++			device->node_id, generation, device->max_speed,
+ 			offset, NULL, 4, complete_transaction, &callback_data);
+ 
+ 	wait_for_completion(&callback_data.done);
+@@ -404,7 +413,14 @@ static int read_rom(struct fw_device *de
+ 	return callback_data.rcode;
+ }
  
--#define SBP2_MAX_SG_ELEMENT_LENGTH	0xf000
--#define SBP2_MAX_SECTORS		255	/* Max sectors supported */
+-static int read_bus_info_block(struct fw_device *device)
 +/*
-+ * Per section 7.4.8 of the SBP-2 spec, a mgt_ORB_timeout value can be
-+ * provided in the config rom.  A high timeout value really only matters
-+ * on initial login, where we'll just use 20s rather than hassling with
-+ * reading the config rom, since it really wouldn't buy us much.
++ * Read the bus info block, perform a speed probe, and read all of the rest of
++ * the config ROM.  We do all this with a cached bus generation.  If the bus
++ * generation changes under us, read_bus_info_block will fail and get retried.
++ * It's better to start all over in this case because the node from which we
++ * are reading the ROM may have changed the ROM during the reset.
 + */
-+#define SBP2_LOGIN_ORB_TIMEOUT		20000	/* Timeout in ms */
- #define SBP2_ORB_TIMEOUT		2000	/* Timeout in ms */
--
- #define SBP2_ORB_NULL			0x80000000
-+#define SBP2_MAX_SG_ELEMENT_LENGTH	0xf000
- 
- #define SBP2_DIRECTION_TO_MEDIA		0x0
- #define SBP2_DIRECTION_FROM_MEDIA	0x1
-@@ -489,6 +494,7 @@ sbp2_send_management_orb(struct sbp2_log
++static int read_bus_info_block(struct fw_device *device, int generation)
  {
- 	struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
- 	struct sbp2_management_orb *orb;
-+	unsigned int timeout;
- 	int retval = -ENOMEM;
- 
- 	orb = kzalloc(sizeof(*orb), GFP_ATOMIC);
-@@ -519,6 +525,9 @@ sbp2_send_management_orb(struct sbp2_log
- 		orb->request.misc |=
- 			MANAGEMENT_ORB_EXCLUSIVE(sbp2_param_exclusive_login) |
- 			MANAGEMENT_ORB_RECONNECT(0);
-+		timeout = SBP2_LOGIN_ORB_TIMEOUT;
-+	} else {
-+		timeout = SBP2_ORB_TIMEOUT;
- 	}
- 
- 	fw_memcpy_to_be32(&orb->request, &orb->request, sizeof(orb->request));
-@@ -535,19 +544,30 @@ sbp2_send_management_orb(struct sbp2_log
- 	sbp2_send_orb(&orb->base, lu, node_id, generation,
- 		      lu->tgt->management_agent_address);
- 
--	wait_for_completion_timeout(&orb->done,
--				    msecs_to_jiffies(SBP2_ORB_TIMEOUT));
-+	wait_for_completion_timeout(&orb->done, msecs_to_jiffies(timeout));
- 
- 	retval = -EIO;
- 	if (sbp2_cancel_orbs(lu) == 0) {
--		fw_error("orb reply timed out, rcode=0x%02x\n",
--			 orb->base.rcode);
-+		/*
-+		 * Logout requests frequently get sent to devices that aren't
-+		 * there any more, resulting in extraneous error messages in
-+		 * the logs.  Unfortunately, this means logout requests that
-+		 * actually fail don't get logged.
-+		 */
-+		if (function != SBP2_LOGOUT_REQUEST)
-+			fw_error("orb reply timed out, rcode=0x%02x\n",
-+				 orb->base.rcode);
- 		goto out;
- 	}
- 
- 	if (orb->base.rcode != RCODE_COMPLETE) {
--		fw_error("management write failed, rcode 0x%02x\n",
--			 orb->base.rcode);
-+		/*
-+		 * On device removal from the bus, sometimes the logout
-+		 * request times out, sometimes it just fails.
-+		 */
-+		if (function != SBP2_LOGOUT_REQUEST)
-+			fw_error("management write failed, rcode 0x%02x\n",
-+				 orb->base.rcode);
- 		goto out;
- 	}
+ 	static u32 rom[256];
+ 	u32 stack[16], sp, key;
+@@ -414,7 +430,7 @@ static int read_bus_info_block(struct fw
+ 
+ 	/* First read the bus info block. */
+ 	for (i = 0; i < 5; i++) {
+-		if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE)
++		if (read_rom(device, generation, i, &rom[i]) != RCODE_COMPLETE)
+ 			return -1;
+ 		/*
+ 		 * As per IEEE1212 7.2, during power-up, devices can
+@@ -449,7 +465,8 @@ static int read_bus_info_block(struct fw
+ 			device->max_speed = device->card->link_speed;
+ 
+ 		while (device->max_speed > SCODE_100) {
+-			if (read_rom(device, 0, &dummy) == RCODE_COMPLETE)
++			if (read_rom(device, generation, 0, &dummy) ==
++			    RCODE_COMPLETE)
+ 				break;
+ 			device->max_speed--;
+ 		}
+@@ -482,7 +499,7 @@ static int read_bus_info_block(struct fw
+ 			return -1;
  
-@@ -628,6 +648,21 @@ static void sbp2_release_target(struct k
+ 		/* Read header quadlet for the block to get the length. */
+-		if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE)
++		if (read_rom(device, generation, i, &rom[i]) != RCODE_COMPLETE)
+ 			return -1;
+ 		end = i + (rom[i] >> 16) + 1;
+ 		i++;
+@@ -501,7 +518,8 @@ static int read_bus_info_block(struct fw
+ 		 * it references another block, and push it in that case.
+ 		 */
+ 		while (i < end) {
+-			if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE)
++			if (read_rom(device, generation, i, &rom[i]) !=
++			    RCODE_COMPLETE)
+ 				return -1;
+ 			if ((key >> 30) == 3 && (rom[i] >> 30) > 1 &&
+ 			    sp < ARRAY_SIZE(stack))
+@@ -648,7 +666,7 @@ static void fw_device_init(struct work_s
+ 	 * device.
+ 	 */
  
- static struct workqueue_struct *sbp2_wq;
+-	if (read_bus_info_block(device) < 0) {
++	if (read_bus_info_block(device, device->generation) < 0) {
+ 		if (device->config_rom_retries < MAX_RETRIES) {
+ 			device->config_rom_retries++;
+ 			schedule_delayed_work(&device->work, RETRY_DELAY);
+@@ -801,6 +819,7 @@ void fw_node_event(struct fw_card *card,
+ 
+ 		device = node->data;
+ 		device->node_id = node->node_id;
++		smp_wmb();  /* update node_id before generation */
+ 		device->generation = card->generation;
+ 		if (atomic_read(&device->state) == FW_DEVICE_RUNNING) {
+ 			PREPARE_DELAYED_WORK(&device->work, fw_device_update);
+diff -Naurp linux-2.6-git/drivers/firewire/fw-device.h firewire-git/drivers/firewire/fw-device.h
+--- linux-2.6-git/drivers/firewire/fw-device.h	2008-01-01 22:50:33.000000000 -0500
++++ firewire-git/drivers/firewire/fw-device.h	2008-01-25 12:41:22.000000000 -0500
+@@ -35,6 +35,18 @@ struct fw_attribute_group {
+ 	struct attribute *attrs[11];
+ };
  
 +/*
-+ * Always get the target's kref when scheduling work on one its units.
-+ * Each workqueue job is responsible to call sbp2_target_put() upon return.
++ * Note, fw_device.generation always has to be read before fw_device.node_id.
++ * Use SMP memory barriers to ensure this.  Otherwise requests will be sent
++ * to an outdated node_id if the generation was updated in the meantime due
++ * to a bus reset.
++ *
++ * Likewise, fw-core will take care to update .node_id before .generation so
++ * that whenever fw_device.generation is current WRT the actual bus generation,
++ * fw_device.node_id is guaranteed to be current too.
++ *
++ * The same applies to fw_device.card->node_id vs. fw_device.generation.
 + */
-+static void sbp2_queue_work(struct sbp2_logical_unit *lu, unsigned long delay)
-+{
-+	if (queue_delayed_work(sbp2_wq, &lu->work, delay))
-+		kref_get(&lu->tgt->kref);
-+}
-+
-+static void sbp2_target_put(struct sbp2_target *tgt)
-+{
-+	kref_put(&tgt->kref, sbp2_release_target);
-+}
-+
- static void sbp2_reconnect(struct work_struct *work);
- 
- static void sbp2_login(struct work_struct *work)
-@@ -649,16 +684,12 @@ static void sbp2_login(struct work_struc
- 
- 	if (sbp2_send_management_orb(lu, node_id, generation,
- 				SBP2_LOGIN_REQUEST, lu->lun, &response) < 0) {
--		if (lu->retries++ < 5) {
--			if (queue_delayed_work(sbp2_wq, &lu->work,
--					       DIV_ROUND_UP(HZ, 5)))
--				kref_get(&lu->tgt->kref);
--		} else {
-+		if (lu->retries++ < 5)
-+			sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
-+		else
- 			fw_error("failed to login to %s LUN %04x\n",
- 				 unit->device.bus_id, lu->lun);
--		}
--		kref_put(&lu->tgt->kref, sbp2_release_target);
--		return;
-+		goto out;
- 	}
- 
- 	lu->generation        = generation;
-@@ -700,7 +731,8 @@ static void sbp2_login(struct work_struc
- 		lu->sdev = sdev;
- 		scsi_device_put(sdev);
- 	}
--	kref_put(&lu->tgt->kref, sbp2_release_target);
-+ out:
-+	sbp2_target_put(lu->tgt);
- }
- 
- static int sbp2_add_logical_unit(struct sbp2_target *tgt, int lun_entry)
-@@ -865,18 +897,13 @@ static int sbp2_probe(struct device *dev
- 
- 	get_device(&unit->device);
- 
--	/*
--	 * We schedule work to do the login so we can easily
--	 * reschedule retries. Always get the ref before scheduling
--	 * work.
--	 */
-+	/* Do the login in a workqueue so we can easily reschedule retries. */
- 	list_for_each_entry(lu, &tgt->lu_list, link)
--		if (queue_delayed_work(sbp2_wq, &lu->work, 0))
--			kref_get(&tgt->kref);
-+		sbp2_queue_work(lu, 0);
- 	return 0;
- 
-  fail_tgt_put:
--	kref_put(&tgt->kref, sbp2_release_target);
-+	sbp2_target_put(tgt);
- 	return -ENOMEM;
- 
-  fail_shost_put:
-@@ -889,7 +916,7 @@ static int sbp2_remove(struct device *de
- 	struct fw_unit *unit = fw_unit(dev);
- 	struct sbp2_target *tgt = unit->device.driver_data;
- 
--	kref_put(&tgt->kref, sbp2_release_target);
-+	sbp2_target_put(tgt);
- 	return 0;
- }
- 
-@@ -915,10 +942,8 @@ static void sbp2_reconnect(struct work_s
- 			lu->retries = 0;
- 			PREPARE_DELAYED_WORK(&lu->work, sbp2_login);
- 		}
--		if (queue_delayed_work(sbp2_wq, &lu->work, DIV_ROUND_UP(HZ, 5)))
--			kref_get(&lu->tgt->kref);
--		kref_put(&lu->tgt->kref, sbp2_release_target);
--		return;
-+		sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
-+		goto out;
- 	}
- 
- 	lu->generation        = generation;
-@@ -930,8 +955,8 @@ static void sbp2_reconnect(struct work_s
- 
- 	sbp2_agent_reset(lu);
- 	sbp2_cancel_orbs(lu);
--
--	kref_put(&lu->tgt->kref, sbp2_release_target);
-+ out:
-+	sbp2_target_put(lu->tgt);
- }
- 
- static void sbp2_update(struct fw_unit *unit)
-@@ -947,8 +972,7 @@ static void sbp2_update(struct fw_unit *
- 	 */
- 	list_for_each_entry(lu, &tgt->lu_list, link) {
- 		lu->retries = 0;
--		if (queue_delayed_work(sbp2_wq, &lu->work, 0))
--			kref_get(&tgt->kref);
-+		sbp2_queue_work(lu, 0);
- 	}
- }
- 
-@@ -1103,9 +1127,9 @@ sbp2_map_scatterlist(struct sbp2_command
- 	 * elements larger than 65535 bytes, some IOMMUs may merge sg elements
- 	 * during DMA mapping, and Linux currently doesn't prevent this.
- 	 */
--	for (i = 0, j = 0; i < count; i++) {
--		sg_len = sg_dma_len(sg + i);
--		sg_addr = sg_dma_address(sg + i);
-+	for (i = 0, j = 0; i < count; i++, sg = sg_next(sg)) {
-+		sg_len = sg_dma_len(sg);
-+		sg_addr = sg_dma_address(sg);
- 		while (sg_len) {
- 			/* FIXME: This won't get us out of the pinch. */
- 			if (unlikely(j >= ARRAY_SIZE(orb->page_table))) {
-Index: linux/drivers/firewire/fw-ohci.c
-===================================================================
---- linux.orig/drivers/firewire/fw-ohci.c
-+++ linux/drivers/firewire/fw-ohci.c
+ struct fw_device {
+ 	atomic_t state;
+ 	struct fw_node *node;
+diff -Naurp linux-2.6-git/drivers/firewire/fw-ohci.c firewire-git/drivers/firewire/fw-ohci.c
+--- linux-2.6-git/drivers/firewire/fw-ohci.c	2008-01-01 22:50:33.000000000 -0500
++++ firewire-git/drivers/firewire/fw-ohci.c	2008-01-23 16:01:36.000000000 -0500
 @@ -98,17 +98,48 @@ struct context;
  typedef int (*descriptor_callback_t)(struct context *ctx,
  				     struct descriptor *d,
@@ -1582,10 +788,265 @@
  		     OHCI1394_AsRspTrContextControlSet, handle_at_packet);
  
  	reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, ~0);
-Index: linux/drivers/firewire/fw-transaction.c
-===================================================================
---- linux.orig/drivers/firewire/fw-transaction.c
-+++ linux/drivers/firewire/fw-transaction.c
+diff -Naurp linux-2.6-git/drivers/firewire/fw-sbp2.c firewire-git/drivers/firewire/fw-sbp2.c
+--- linux-2.6-git/drivers/firewire/fw-sbp2.c	2008-01-01 22:50:33.000000000 -0500
++++ firewire-git/drivers/firewire/fw-sbp2.c	2008-01-25 12:42:11.000000000 -0500
+@@ -150,11 +150,16 @@ struct sbp2_target {
+ 	struct list_head lu_list;
+ };
+ 
+-#define SBP2_MAX_SG_ELEMENT_LENGTH	0xf000
+-#define SBP2_MAX_SECTORS		255	/* Max sectors supported */
++/*
++ * Per section 7.4.8 of the SBP-2 spec, a mgt_ORB_timeout value can be
++ * provided in the config rom.  A high timeout value really only matters
++ * on initial login, where we'll just use 20s rather than hassling with
++ * reading the config rom, since it really wouldn't buy us much.
++ */
++#define SBP2_LOGIN_ORB_TIMEOUT		20000	/* Timeout in ms */
+ #define SBP2_ORB_TIMEOUT		2000	/* Timeout in ms */
+-
+ #define SBP2_ORB_NULL			0x80000000
++#define SBP2_MAX_SG_ELEMENT_LENGTH	0xf000
+ 
+ #define SBP2_DIRECTION_TO_MEDIA		0x0
+ #define SBP2_DIRECTION_FROM_MEDIA	0x1
+@@ -489,6 +494,7 @@ sbp2_send_management_orb(struct sbp2_log
+ {
+ 	struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
+ 	struct sbp2_management_orb *orb;
++	unsigned int timeout;
+ 	int retval = -ENOMEM;
+ 
+ 	orb = kzalloc(sizeof(*orb), GFP_ATOMIC);
+@@ -516,9 +522,13 @@ sbp2_send_management_orb(struct sbp2_log
+ 	orb->request.status_fifo.low  = lu->address_handler.offset;
+ 
+ 	if (function == SBP2_LOGIN_REQUEST) {
++		/* Ask for 2^2 == 4 seconds reconnect grace period */
+ 		orb->request.misc |=
+-			MANAGEMENT_ORB_EXCLUSIVE(sbp2_param_exclusive_login) |
+-			MANAGEMENT_ORB_RECONNECT(0);
++			MANAGEMENT_ORB_RECONNECT(2) |
++			MANAGEMENT_ORB_EXCLUSIVE(sbp2_param_exclusive_login);
++		timeout = SBP2_LOGIN_ORB_TIMEOUT;
++	} else {
++		timeout = SBP2_ORB_TIMEOUT;
+ 	}
+ 
+ 	fw_memcpy_to_be32(&orb->request, &orb->request, sizeof(orb->request));
+@@ -535,8 +545,7 @@ sbp2_send_management_orb(struct sbp2_log
+ 	sbp2_send_orb(&orb->base, lu, node_id, generation,
+ 		      lu->tgt->management_agent_address);
+ 
+-	wait_for_completion_timeout(&orb->done,
+-				    msecs_to_jiffies(SBP2_ORB_TIMEOUT));
++	wait_for_completion_timeout(&orb->done, msecs_to_jiffies(timeout));
+ 
+ 	retval = -EIO;
+ 	if (sbp2_cancel_orbs(lu) == 0) {
+@@ -608,13 +617,17 @@ static void sbp2_release_target(struct k
+ 	struct sbp2_logical_unit *lu, *next;
+ 	struct Scsi_Host *shost =
+ 		container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
++	struct fw_device *device = fw_device(tgt->unit->device.parent);
+ 
+ 	list_for_each_entry_safe(lu, next, &tgt->lu_list, link) {
+ 		if (lu->sdev)
+ 			scsi_remove_device(lu->sdev);
+ 
+-		sbp2_send_management_orb(lu, tgt->node_id, lu->generation,
+-				SBP2_LOGOUT_REQUEST, lu->login_id, NULL);
++		if (!fw_device_is_shutdown(device))
++			sbp2_send_management_orb(lu, tgt->node_id,
++					lu->generation, SBP2_LOGOUT_REQUEST,
++					lu->login_id, NULL);
++
+ 		fw_core_remove_address_handler(&lu->address_handler);
+ 		list_del(&lu->link);
+ 		kfree(lu);
+@@ -628,6 +641,21 @@ static void sbp2_release_target(struct k
+ 
+ static struct workqueue_struct *sbp2_wq;
+ 
++/*
++ * Always get the target's kref when scheduling work on one its units.
++ * Each workqueue job is responsible to call sbp2_target_put() upon return.
++ */
++static void sbp2_queue_work(struct sbp2_logical_unit *lu, unsigned long delay)
++{
++	if (queue_delayed_work(sbp2_wq, &lu->work, delay))
++		kref_get(&lu->tgt->kref);
++}
++
++static void sbp2_target_put(struct sbp2_target *tgt)
++{
++	kref_put(&tgt->kref, sbp2_release_target);
++}
++
+ static void sbp2_reconnect(struct work_struct *work);
+ 
+ static void sbp2_login(struct work_struct *work)
+@@ -643,22 +671,19 @@ static void sbp2_login(struct work_struc
+ 	struct sbp2_login_response response;
+ 	int generation, node_id, local_node_id;
+ 
+-	generation    = device->card->generation;
+-	node_id       = device->node->node_id;
+-	local_node_id = device->card->local_node->node_id;
++	generation    = device->generation;
++	smp_rmb();    /* node_id must not be older than generation */
++	node_id       = device->node_id;
++	local_node_id = device->card->node_id;
+ 
+ 	if (sbp2_send_management_orb(lu, node_id, generation,
+ 				SBP2_LOGIN_REQUEST, lu->lun, &response) < 0) {
+-		if (lu->retries++ < 5) {
+-			if (queue_delayed_work(sbp2_wq, &lu->work,
+-					       DIV_ROUND_UP(HZ, 5)))
+-				kref_get(&lu->tgt->kref);
+-		} else {
++		if (lu->retries++ < 5)
++			sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
++		else
+ 			fw_error("failed to login to %s LUN %04x\n",
+ 				 unit->device.bus_id, lu->lun);
+-		}
+-		kref_put(&lu->tgt->kref, sbp2_release_target);
+-		return;
++		goto out;
+ 	}
+ 
+ 	lu->generation        = generation;
+@@ -700,7 +725,8 @@ static void sbp2_login(struct work_struc
+ 		lu->sdev = sdev;
+ 		scsi_device_put(sdev);
+ 	}
+-	kref_put(&lu->tgt->kref, sbp2_release_target);
++ out:
++	sbp2_target_put(lu->tgt);
+ }
+ 
+ static int sbp2_add_logical_unit(struct sbp2_target *tgt, int lun_entry)
+@@ -865,18 +891,13 @@ static int sbp2_probe(struct device *dev
+ 
+ 	get_device(&unit->device);
+ 
+-	/*
+-	 * We schedule work to do the login so we can easily
+-	 * reschedule retries. Always get the ref before scheduling
+-	 * work.
+-	 */
++	/* Do the login in a workqueue so we can easily reschedule retries. */
+ 	list_for_each_entry(lu, &tgt->lu_list, link)
+-		if (queue_delayed_work(sbp2_wq, &lu->work, 0))
+-			kref_get(&tgt->kref);
++		sbp2_queue_work(lu, 0);
+ 	return 0;
+ 
+  fail_tgt_put:
+-	kref_put(&tgt->kref, sbp2_release_target);
++	sbp2_target_put(tgt);
+ 	return -ENOMEM;
+ 
+  fail_shost_put:
+@@ -889,7 +910,7 @@ static int sbp2_remove(struct device *de
+ 	struct fw_unit *unit = fw_unit(dev);
+ 	struct sbp2_target *tgt = unit->device.driver_data;
+ 
+-	kref_put(&tgt->kref, sbp2_release_target);
++	sbp2_target_put(tgt);
+ 	return 0;
+ }
+ 
+@@ -901,9 +922,10 @@ static void sbp2_reconnect(struct work_s
+ 	struct fw_device *device = fw_device(unit->device.parent);
+ 	int generation, node_id, local_node_id;
+ 
+-	generation    = device->card->generation;
+-	node_id       = device->node->node_id;
+-	local_node_id = device->card->local_node->node_id;
++	generation    = device->generation;
++	smp_rmb();    /* node_id must not be older than generation */
++	node_id       = device->node_id;
++	local_node_id = device->card->node_id;
+ 
+ 	if (sbp2_send_management_orb(lu, node_id, generation,
+ 				     SBP2_RECONNECT_REQUEST,
+@@ -915,10 +937,8 @@ static void sbp2_reconnect(struct work_s
+ 			lu->retries = 0;
+ 			PREPARE_DELAYED_WORK(&lu->work, sbp2_login);
+ 		}
+-		if (queue_delayed_work(sbp2_wq, &lu->work, DIV_ROUND_UP(HZ, 5)))
+-			kref_get(&lu->tgt->kref);
+-		kref_put(&lu->tgt->kref, sbp2_release_target);
+-		return;
++		sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
++		goto out;
+ 	}
+ 
+ 	lu->generation        = generation;
+@@ -930,8 +950,8 @@ static void sbp2_reconnect(struct work_s
+ 
+ 	sbp2_agent_reset(lu);
+ 	sbp2_cancel_orbs(lu);
+-
+-	kref_put(&lu->tgt->kref, sbp2_release_target);
++ out:
++	sbp2_target_put(lu->tgt);
+ }
+ 
+ static void sbp2_update(struct fw_unit *unit)
+@@ -947,8 +967,7 @@ static void sbp2_update(struct fw_unit *
+ 	 */
+ 	list_for_each_entry(lu, &tgt->lu_list, link) {
+ 		lu->retries = 0;
+-		if (queue_delayed_work(sbp2_wq, &lu->work, 0))
+-			kref_get(&tgt->kref);
++		sbp2_queue_work(lu, 0);
+ 	}
+ }
+ 
+@@ -1103,9 +1122,9 @@ sbp2_map_scatterlist(struct sbp2_command
+ 	 * elements larger than 65535 bytes, some IOMMUs may merge sg elements
+ 	 * during DMA mapping, and Linux currently doesn't prevent this.
+ 	 */
+-	for (i = 0, j = 0; i < count; i++) {
+-		sg_len = sg_dma_len(sg + i);
+-		sg_addr = sg_dma_address(sg + i);
++	for (i = 0, j = 0; i < count; i++, sg = sg_next(sg)) {
++		sg_len = sg_dma_len(sg);
++		sg_addr = sg_dma_address(sg);
+ 		while (sg_len) {
+ 			/* FIXME: This won't get us out of the pinch. */
+ 			if (unlikely(j >= ARRAY_SIZE(orb->page_table))) {
+diff -Naurp linux-2.6-git/drivers/firewire/fw-topology.c firewire-git/drivers/firewire/fw-topology.c
+--- linux-2.6-git/drivers/firewire/fw-topology.c	2008-01-01 22:50:33.000000000 -0500
++++ firewire-git/drivers/firewire/fw-topology.c	2008-01-25 12:41:22.000000000 -0500
+@@ -518,6 +518,11 @@ fw_core_handle_bus_reset(struct fw_card 
+ 		card->bm_retries = 0;
+ 
+ 	card->node_id = node_id;
++	/*
++	 * Update node_id before generation to prevent anybody from using
++	 * a stale node_id together with a current generation.
++	 */
++	smp_wmb();
+ 	card->generation = generation;
+ 	card->reset_jiffies = jiffies;
+ 	schedule_delayed_work(&card->work, 0);
+diff -Naurp linux-2.6-git/drivers/firewire/fw-transaction.c firewire-git/drivers/firewire/fw-transaction.c
+--- linux-2.6-git/drivers/firewire/fw-transaction.c	2008-01-01 22:50:33.000000000 -0500
++++ firewire-git/drivers/firewire/fw-transaction.c	2008-01-25 12:41:24.000000000 -0500
+@@ -153,7 +153,7 @@ fw_fill_request(struct fw_packet *packet
+ 	int ext_tcode;
+ 
+ 	if (tcode > 0x10) {
+-		ext_tcode = tcode - 0x10;
++		ext_tcode = tcode & ~0x10;
+ 		tcode = TCODE_LOCK_REQUEST;
+ 	} else
+ 		ext_tcode = 0;
 @@ -650,7 +650,7 @@ fw_core_handle_request(struct fw_card *c
  		 HEADER_GET_OFFSET_HIGH(p->header[1]) << 32) | p->header[2];
  	tcode       = HEADER_GET_TCODE(p->header[0]);
@@ -1595,25 +1056,3 @@
  
  	spin_lock_irqsave(&address_handler_lock, flags);
  	handler = lookup_enclosing_address_handler(&address_handler_list,
-Index: linux/MAINTAINERS
-===================================================================
---- linux.orig/MAINTAINERS
-+++ linux/MAINTAINERS
-@@ -1571,7 +1571,7 @@ P:	Alexander Viro
- M:	viro at zeniv.linux.org.uk
- S:	Maintained
- 
--FIREWIRE SUBSYSTEM
-+FIREWIRE SUBSYSTEM (drivers/firewire, <linux/firewire*.h>)
- P:	Kristian Hoegsberg, Stefan Richter
- M:	krh at redhat.com, stefanr at s5r6.in-berlin.de
- L:	linux1394-devel at lists.sourceforge.net
-@@ -1891,7 +1891,7 @@ L:	linux-ide at vger.kernel.org
- L:	linux-scsi at vger.kernel.org
- S:	Orphan
- 
--IEEE 1394 SUBSYSTEM
-+IEEE 1394 SUBSYSTEM (drivers/ieee1394)
- P:	Ben Collins
- M:	ben.collins at ubuntu.com
- P:	Stefan Richter


--- linux-2.6-firewire-config-rom-read-fixup.patch DELETED ---




More information about the fedora-extras-commits mailing list