rpms/kernel/F-8 config-generic, 1.49, 1.50 kernel.spec, 1.362, 1.363 linux-2.6-firewire-git-pending.patch, 1.1, 1.2 linux-2.6-firewire-git-update.patch, 1.3, 1.4

Jarod Wilson (jwilson) fedora-extras-commits at redhat.com
Tue Mar 4 05:03:54 UTC 2008


Author: jwilson

Update of /cvs/pkgs/rpms/kernel/F-8
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv18709

Modified Files:
	config-generic kernel.spec 
	linux-2.6-firewire-git-pending.patch 
	linux-2.6-firewire-git-update.patch 
Log Message:
* Mon Mar 03 2008 Jarod Wilson <jwilson at redhat.com> 2.6.24.3-17
- firewire-sbp2: permit drives to suspend (#243210)
- firewire: fix suspend/resume on older PowerPC Macs (#312871)
- firewire: restore bus power on resume on older PowerPC Macs
- firewire: support for first-gen Apple UniNorth controller
- firewire: fix crashes in workqueue jobs



Index: config-generic
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/F-8/config-generic,v
retrieving revision 1.49
retrieving revision 1.50
diff -u -r1.49 -r1.50
--- config-generic	21 Feb 2008 19:11:27 -0000	1.49
+++ config-generic	4 Mar 2008 05:03:17 -0000	1.50
@@ -3357,3 +3357,4 @@
 # CONFIG_WRITABLE_DEVMEM is not set
 # CONFIG_WRITABLE_DEVKMEM is not set
 
+# CONFIG_FIREWIRE_OHCI_REMOTE_DMA is not set


Index: kernel.spec
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/F-8/kernel.spec,v
retrieving revision 1.362
retrieving revision 1.363
diff -u -r1.362 -r1.363
--- kernel.spec	3 Mar 2008 23:29:42 -0000	1.362
+++ kernel.spec	4 Mar 2008 05:03:17 -0000	1.363
@@ -700,7 +700,6 @@
 Patch1805: linux-2.6-git-initial-r500-drm.patch
 
 # Updated firewire stack from linux1394 git
-# snap from http://me.in-berlin.de/~s5r6/linux1394/updates/2.6.23/
 Patch1910: linux-2.6-firewire-git-update.patch
 Patch1911: linux-2.6-firewire-git-pending.patch
 # fix thinkpad key events for volume/brightness
@@ -1313,6 +1312,7 @@
 ApplyPatch linux-2.6-dcdbas-autoload.patch
 
 # FireWire updates and fixes
+# snap from http://me.in-berlin.de/~s5r6/linux1394/updates/
 ApplyPatch linux-2.6-firewire-git-update.patch
 ApplyPatch linux-2.6-firewire-git-pending.patch
 
@@ -1918,6 +1918,13 @@
 
 
 %changelog
+* Mon Mar 03 2008 Jarod Wilson <jwilson at redhat.com> 2.6.24.3-17
+- firewire-sbp2: permit drives to suspend (#243210)
+- firewire: fix suspend/resume on older PowerPC Macs (#312871)
+- firewire: restore bus power on resume on older PowerPC Macs
+- firewire: support for first-gen Apple UniNorth controller
+- firewire: fix crashes in workqueue jobs
+
 * Mon Mar 03 2008 Chuck Ebbert <cebbert at redhat.com> 2.6.24.3-16
 - ISDN: don't oops on driver load (#362621)
 

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

Index: linux-2.6-firewire-git-pending.patch
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/F-8/linux-2.6-firewire-git-pending.patch,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- linux-2.6-firewire-git-pending.patch	15 Feb 2008 23:58:52 -0000	1.1
+++ linux-2.6-firewire-git-pending.patch	4 Mar 2008 05:03:18 -0000	1.2
@@ -3,1216 +3,485 @@
 # tree, which we think we're going to want...
 #
 
-If a device is being unplugged while fw-sbp2 had a login or reconnect on
-schedule, it would take about half a minute to shut the fw_unit down:
-
-Jan 27 18:34:54 stein firewire_sbp2: logged in to fw2.0 LUN 0000 (0 retries)
-<unplug>
-Jan 27 18:34:59 stein firewire_sbp2: sbp2_scsi_abort
-Jan 27 18:34:59 stein scsi 25:0:0:0: Device offlined - not ready after error recovery
-Jan 27 18:35:01 stein firewire_sbp2: orb reply timed out, rcode=0x11
-Jan 27 18:35:06 stein firewire_sbp2: orb reply timed out, rcode=0x11
-Jan 27 18:35:12 stein firewire_sbp2: orb reply timed out, rcode=0x11
-Jan 27 18:35:17 stein firewire_sbp2: orb reply timed out, rcode=0x11
-Jan 27 18:35:22 stein firewire_sbp2: orb reply timed out, rcode=0x11
-Jan 27 18:35:27 stein firewire_sbp2: orb reply timed out, rcode=0x11
-Jan 27 18:35:32 stein firewire_sbp2: orb reply timed out, rcode=0x11
-Jan 27 18:35:32 stein firewire_sbp2: failed to login to fw2.0 LUN 0000
-Jan 27 18:35:32 stein firewire_sbp2: released fw2.0
-
-After this patch, typically only a few seconds spent in __scsi_add_device
-remain:
-
-Jan 27 19:05:50 stein firewire_sbp2: logged in to fw2.0 LUN 0000 (0 retries)
-<unplug>
-Jan 27 19:05:56 stein firewire_sbp2: sbp2_scsi_abort
-Jan 27 19:05:56 stein scsi 33:0:0:0: Device offlined - not ready after error recovery
-Jan 27 19:05:56 stein firewire_sbp2: released fw2.0
-
-The benefit of this is negligible on simple setups.  But on buses with
-several devices, we should avoid any unnecessary blockade of fw-sbp2's
-workqueue thread.
+read_bus_info_block() is repeatedly called by workqueue jobs.
+These will step on each others toes eventually if there are multiple
+workqueue threads, and we end up with corrupt config ROM images.
 
 Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
-Signed-off-by: Jarod Wilson <jwilson at redhat.com>
 ---
- drivers/firewire/fw-sbp2.c |   16 +++++++++++-----
- 1 file changed, 11 insertions(+), 5 deletions(-)
-
-Index: linux/drivers/firewire/fw-sbp2.c
-===================================================================
---- linux.orig/drivers/firewire/fw-sbp2.c
-+++ linux/drivers/firewire/fw-sbp2.c
-@@ -499,6 +499,9 @@ sbp2_send_management_orb(struct sbp2_log
- 	unsigned int timeout;
- 	int retval = -ENOMEM;
- 
-+	if (function == SBP2_LOGOUT_REQUEST && fw_device_is_shutdown(device))
-+		return 0;
-+
- 	orb = kzalloc(sizeof(*orb), GFP_ATOMIC);
- 	if (orb == NULL)
- 		return -ENOMEM;
-@@ -619,16 +622,13 @@ 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);
- 
--		if (!fw_device_is_shutdown(device))
--			sbp2_send_management_orb(lu, tgt->node_id,
--					lu->generation, SBP2_LOGOUT_REQUEST,
--					lu->login_id, NULL);
-+		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);
-@@ -673,6 +673,9 @@ static void sbp2_login(struct work_struc
- 	struct sbp2_login_response response;
- 	int generation, node_id, local_node_id;
- 
-+	if (fw_device_is_shutdown(device))
-+		goto out;
-+
- 	generation    = device->generation;
- 	smp_rmb();    /* node_id must not be older than generation */
- 	node_id       = device->node_id;
-@@ -968,6 +971,9 @@ static void sbp2_reconnect(struct work_s
- 	struct fw_device *device = fw_device(unit->device.parent);
- 	int generation, node_id, local_node_id;
- 
-+	if (fw_device_is_shutdown(device))
-+		goto out;
-+
- 	generation    = device->generation;
- 	smp_rmb();    /* node_id must not be older than generation */
- 	node_id       = device->node_id;
-
--- 
-Stefan Richter
--=====-==--- ---= ==-==
-http://arcgraph.de/sr/
-
-
-There is a race between shutdown and creation of devices:  fw-core may
-attempt to add a device with the same name of an already existing
-device.  http://bugzilla.kernel.org/show_bug.cgi?id=9828
-
-Impact of the bug:  Happens rarely (when shutdown of a device coincides
-with creation of another), forces the user to unplug and replug the new
-device to get it working.
-
-The fix is obvious:  Free the minor number *after* instead of *before*
-device_unregister().  This requires to take an additional reference of
-the fw_device as long as the IDR tree points to it.
-
-And while we are at it, we fix an additional race condition:
-fw_device_op_open() took its reference of the fw_device a little bit too
-late, hence was in danger to access an already invalid fw_device.
-
-Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
----
- drivers/firewire/fw-cdev.c   |    8 +++++---
- drivers/firewire/fw-device.c |   20 ++++++++++++++------
- drivers/firewire/fw-device.h |    2 +-
- 3 files changed, 20 insertions(+), 10 deletions(-)
+ drivers/firewire/fw-device.c |   41 +++++++++++++++++++++++------------
+ 1 file changed, 27 insertions(+), 14 deletions(-)
 
 Index: linux/drivers/firewire/fw-device.c
 ===================================================================
 --- linux.orig/drivers/firewire/fw-device.c
 +++ linux/drivers/firewire/fw-device.c
-@@ -610,12 +610,14 @@ static DECLARE_RWSEM(idr_rwsem);
- static DEFINE_IDR(fw_device_idr);
- int fw_cdev_major;
- 
--struct fw_device *fw_device_from_devt(dev_t devt)
-+struct fw_device *fw_device_get_by_devt(dev_t devt)
- {
- 	struct fw_device *device;
- 
- 	down_read(&idr_rwsem);
- 	device = idr_find(&fw_device_idr, MINOR(devt));
-+	if (device)
-+		fw_device_get(device);
- 	up_read(&idr_rwsem);
- 
- 	return device;
-@@ -627,13 +629,14 @@ static void fw_device_shutdown(struct wo
- 		container_of(work, struct fw_device, work.work);
- 	int minor = MINOR(device->device.devt);
- 
--	down_write(&idr_rwsem);
--	idr_remove(&fw_device_idr, minor);
--	up_write(&idr_rwsem);
--
- 	fw_device_cdev_remove(device);
- 	device_for_each_child(&device->device, NULL, shutdown_unit);
- 	device_unregister(&device->device);
-+
-+	down_write(&idr_rwsem);
-+	idr_remove(&fw_device_idr, minor);
-+	up_write(&idr_rwsem);
-+	fw_device_put(device);
+@@ -400,6 +400,9 @@ read_rom(struct fw_device *device, int g
+ 	return callback_data.rcode;
  }
  
- static struct device_type fw_device_type = {
-@@ -682,10 +685,13 @@ static void fw_device_init(struct work_s
- 	}
- 
- 	err = -ENOMEM;
-+
-+	fw_device_get(device);
- 	down_write(&idr_rwsem);
- 	if (idr_pre_get(&fw_device_idr, GFP_KERNEL))
- 		err = idr_get_new(&fw_device_idr, device, &minor);
- 	up_write(&idr_rwsem);
-+
- 	if (err < 0)
- 		goto error;
- 
-@@ -741,7 +747,9 @@ static void fw_device_init(struct work_s
- 	idr_remove(&fw_device_idr, minor);
- 	up_write(&idr_rwsem);
-  error:
--	put_device(&device->device);
-+	fw_device_put(device);		/* fw_device_idr's reference */
++#define READ_BIB_ROM_SIZE	256
++#define READ_BIB_STACK_SIZE	16
 +
-+	put_device(&device->device);	/* our reference */
- }
- 
- static int update_unit(struct device *dev, void *data)
-Index: linux/drivers/firewire/fw-cdev.c
-===================================================================
---- linux.orig/drivers/firewire/fw-cdev.c
-+++ linux/drivers/firewire/fw-cdev.c
-@@ -109,15 +109,17 @@ static int fw_device_op_open(struct inod
- 	struct client *client;
- 	unsigned long flags;
- 
--	device = fw_device_from_devt(inode->i_rdev);
-+	device = fw_device_get_by_devt(inode->i_rdev);
- 	if (device == NULL)
- 		return -ENODEV;
- 
- 	client = kzalloc(sizeof(*client), GFP_KERNEL);
--	if (client == NULL)
-+	if (client == NULL) {
-+		fw_device_put(device);
- 		return -ENOMEM;
-+	}
- 
--	client->device = fw_device_get(device);
-+	client->device = device;
- 	INIT_LIST_HEAD(&client->event_list);
- 	INIT_LIST_HEAD(&client->resource_list);
- 	spin_lock_init(&client->lock);
-Index: linux/drivers/firewire/fw-device.h
-===================================================================
---- linux.orig/drivers/firewire/fw-device.h
-+++ linux/drivers/firewire/fw-device.h
-@@ -77,13 +77,13 @@ fw_device_is_shutdown(struct fw_device *
- }
- 
- struct fw_device *fw_device_get(struct fw_device *device);
-+struct fw_device *fw_device_get_by_devt(dev_t devt);
- void fw_device_put(struct fw_device *device);
- int fw_device_enable_phys_dma(struct fw_device *device);
- 
- void fw_device_cdev_update(struct fw_device *device);
- void fw_device_cdev_remove(struct fw_device *device);
+ /*
+  * 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
+@@ -409,16 +412,23 @@ read_rom(struct fw_device *device, int g
+  */
+ static int read_bus_info_block(struct fw_device *device, int generation)
+ {
+-	static u32 rom[256];
+-	u32 stack[16], sp, key;
+-	int i, end, length;
++	u32 *rom, *stack;
++	u32 sp, key;
++	int i, end, length, ret = -1;
++
++	rom = kmalloc(sizeof(*rom) * READ_BIB_ROM_SIZE +
++		      sizeof(*stack) * READ_BIB_STACK_SIZE, GFP_KERNEL);
++	if (rom == NULL)
++		return -ENOMEM;
++
++	stack = &rom[READ_BIB_ROM_SIZE];
+ 
+ 	device->max_speed = SCODE_100;
+ 
+ 	/* First read the bus info block. */
+ 	for (i = 0; i < 5; i++) {
+ 		if (read_rom(device, generation, i, &rom[i]) != RCODE_COMPLETE)
+-			return -1;
++			goto out;
+ 		/*
+ 		 * As per IEEE1212 7.2, during power-up, devices can
+ 		 * reply with a 0 for the first quadlet of the config
+@@ -428,7 +438,7 @@ static int read_bus_info_block(struct fw
+ 		 * retry mechanism will try again later.
+ 		 */
+ 		if (i == 0 && rom[i] == 0)
+-			return -1;
++			goto out;
+ 	}
  
--struct fw_device *fw_device_from_devt(dev_t devt);
- extern int fw_cdev_major;
+ 	device->max_speed = device->node->max_speed;
+@@ -478,26 +488,26 @@ static int read_bus_info_block(struct fw
+ 		 */
+ 		key = stack[--sp];
+ 		i = key & 0xffffff;
+-		if (i >= ARRAY_SIZE(rom))
++		if (i >= READ_BIB_ROM_SIZE)
+ 			/*
+ 			 * The reference points outside the standard
+ 			 * config rom area, something's fishy.
+ 			 */
+-			return -1;
++			goto out;
+ 
+ 		/* Read header quadlet for the block to get the length. */
+ 		if (read_rom(device, generation, i, &rom[i]) != RCODE_COMPLETE)
+-			return -1;
++			goto out;
+ 		end = i + (rom[i] >> 16) + 1;
+ 		i++;
+-		if (end > ARRAY_SIZE(rom))
++		if (end > READ_BIB_ROM_SIZE)
+ 			/*
+ 			 * This block extends outside standard config
+ 			 * area (and the array we're reading it
+ 			 * into).  That's broken, so ignore this
+ 			 * device.
+ 			 */
+-			return -1;
++			goto out;
+ 
+ 		/*
+ 		 * Now read in the block.  If this is a directory
+@@ -507,9 +517,9 @@ static int read_bus_info_block(struct fw
+ 		while (i < end) {
+ 			if (read_rom(device, generation, i, &rom[i]) !=
+ 			    RCODE_COMPLETE)
+-				return -1;
++				goto out;
+ 			if ((key >> 30) == 3 && (rom[i] >> 30) > 1 &&
+-			    sp < ARRAY_SIZE(stack))
++			    sp < READ_BIB_STACK_SIZE)
+ 				stack[sp++] = i + rom[i];
+ 			i++;
+ 		}
+@@ -519,11 +529,14 @@ static int read_bus_info_block(struct fw
  
- struct fw_unit {
-
--- 
-Stefan Richter
--=====-==--- --=- ---=-
-http://arcgraph.de/sr/
-
-
-This should help to interpret user reports.  E.g. one can look up the
-vendor OUI (first three bytes of the GUID) and thus tell what is what.
-
-Also simplifies the math in the GUID sysfs attribute.
-
-Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
----
- drivers/firewire/fw-device.c |   28 +++++++++++++++++-----------
- 1 file changed, 17 insertions(+), 11 deletions(-)
-
-Index: linux/drivers/firewire/fw-device.c
-===================================================================
---- linux.orig/drivers/firewire/fw-device.c
-+++ linux/drivers/firewire/fw-device.c
-@@ -358,12 +358,9 @@ static ssize_t
- guid_show(struct device *dev, struct device_attribute *attr, char *buf)
- {
- 	struct fw_device *device = fw_device(dev);
--	u64 guid;
+ 	device->config_rom = kmalloc(length * 4, GFP_KERNEL);
+ 	if (device->config_rom == NULL)
+-		return -1;
++		goto out;
+ 	memcpy(device->config_rom, rom, length * 4);
+ 	device->config_rom_length = length;
++	ret = 0;
++ out:
++	kfree(rom);
  
--	guid = ((u64)device->config_rom[3] << 32) | device->config_rom[4];
--
--	return snprintf(buf, PAGE_SIZE, "0x%016llx\n",
--			(unsigned long long)guid);
-+	return snprintf(buf, PAGE_SIZE, "0x%08x%08x\n",
-+			device->config_rom[3], device->config_rom[4]);
+-	return 0;
++	return ret;
  }
  
- static struct device_attribute fw_device_attributes[] = {
-@@ -723,13 +720,22 @@ static void fw_device_init(struct work_s
- 	 */
- 	if (atomic_cmpxchg(&device->state,
- 		    FW_DEVICE_INITIALIZING,
--		    FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN)
-+		    FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN) {
- 		fw_device_shutdown(&device->work.work);
--	else
--		fw_notify("created new fw device %s "
--			  "(%d config rom retries, S%d00)\n",
--			  device->device.bus_id, device->config_rom_retries,
--			  1 << device->max_speed);
-+	} else {
-+		if (device->config_rom_retries)
-+			fw_notify("created device %s: GUID %08x%08x, S%d00, "
-+				  "%d config ROM retries\n",
-+				  device->device.bus_id,
-+				  device->config_rom[3], device->config_rom[4],
-+				  1 << device->max_speed,
-+				  device->config_rom_retries);
-+		else
-+			fw_notify("created device %s: GUID %08x%08x, S%d00\n",
-+				  device->device.bus_id,
-+				  device->config_rom[3], device->config_rom[4],
-+				  1 << device->max_speed);
-+	}
- 
- 	/*
- 	 * Reschedule the IRM work if we just finished reading the
+ static void fw_unit_release(struct device *dev)
 
 -- 
 Stefan Richter
--=====-==--- --=- ---==
+-=====-==--- --== ---=-
 http://arcgraph.de/sr/
 
 
-Several different SBP-2 bridges accept a login early while the IDE
-device is still powering up.  They are therefore unable to respond to
-SCSI INQUIRY immediately, and the SCSI core has to retry the INQUIRY.
-One of these retries is typically successful, and all is well.
+When a device changes its configuration ROM, it announces this with a
+bus reset.  firewire-core has to check which node initiated a bus reset
+and whether any unit directories went away or were added on this node.
 
-But in case of Momobay FX-3A, the INQUIRY retries tend to fail entirely.
-This can usually be avoided by waiting a little while after login before
-letting the SCSI core send the INQUIRY.  The old sbp2 driver handles
-this more gracefully for as yet unknown reasons (perhaps because it
-waits for fetch agent resets to complete, unlike fw-sbp2 which quickly
-proceeds after requesting the agent reset).  Therefore the workaround is
-not as much necessary for sbp2.
-
-Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
----
- drivers/firewire/fw-sbp2.c |   15 +++++++++++++++
- 1 file changed, 15 insertions(+)
-
-Index: linux/drivers/firewire/fw-sbp2.c
-===================================================================
---- linux.orig/drivers/firewire/fw-sbp2.c
-+++ linux/drivers/firewire/fw-sbp2.c
-@@ -32,6 +32,7 @@
- #include <linux/module.h>
- #include <linux/moduleparam.h>
- #include <linux/mod_devicetable.h>
-+#include <linux/delay.h>
- #include <linux/device.h>
- #include <linux/scatterlist.h>
- #include <linux/dma-mapping.h>
-@@ -82,6 +83,9 @@ MODULE_PARM_DESC(exclusive_login, "Exclu
-  *   Avoids access beyond actual disk limits on devices with an off-by-one bug.
-  *   Don't use this with devices which don't have this bug.
-  *
-+ * - delay inquiry
-+ *   Wait extra SBP2_INQUIRY_DELAY seconds after login before SCSI inquiry.
-+ *
-  * - override internal blacklist
-  *   Instead of adding to the built-in blacklist, use only the workarounds
-  *   specified in the module load parameter.
-@@ -91,6 +95,8 @@ MODULE_PARM_DESC(exclusive_login, "Exclu
- #define SBP2_WORKAROUND_INQUIRY_36	0x2
- #define SBP2_WORKAROUND_MODE_SENSE_8	0x4
- #define SBP2_WORKAROUND_FIX_CAPACITY	0x8
-+#define SBP2_WORKAROUND_DELAY_INQUIRY	0x10
-+#define SBP2_INQUIRY_DELAY		12
- #define SBP2_WORKAROUND_OVERRIDE	0x100
- 
- static int sbp2_param_workarounds;
-@@ -100,6 +106,7 @@ MODULE_PARM_DESC(workarounds, "Work arou
- 	", 36 byte inquiry = "    __stringify(SBP2_WORKAROUND_INQUIRY_36)
- 	", skip mode page 8 = "   __stringify(SBP2_WORKAROUND_MODE_SENSE_8)
- 	", fix capacity = "       __stringify(SBP2_WORKAROUND_FIX_CAPACITY)
-+	", delay inquiry = "      __stringify(SBP2_WORKAROUND_DELAY_INQUIRY)
- 	", override internal blacklist = " __stringify(SBP2_WORKAROUND_OVERRIDE)
- 	", or a combination)");
- 
-@@ -303,6 +310,11 @@ static const struct {
- 		.workarounds		= SBP2_WORKAROUND_INQUIRY_36 |
- 					  SBP2_WORKAROUND_MODE_SENSE_8,
- 	},
-+	/* DViCO Momobay FX-3A with TSB42AA9A bridge */ {
-+		.firmware_revision	= 0x002800,
-+		.model			= 0x000000,
-+		.workarounds		= SBP2_WORKAROUND_DELAY_INQUIRY,
-+	},
- 	/* Initio bridges, actually only needed for some older ones */ {
- 		.firmware_revision	= 0x000200,
- 		.model			= ~0,
-@@ -712,6 +724,9 @@ static void sbp2_login(struct work_struc
- 	PREPARE_DELAYED_WORK(&lu->work, sbp2_reconnect);
- 	sbp2_agent_reset(lu);
- 
-+	if (lu->tgt->workarounds & SBP2_WORKAROUND_DELAY_INQUIRY)
-+		ssleep(SBP2_INQUIRY_DELAY);
-+
- 	memset(&eight_bytes_lun, 0, sizeof(eight_bytes_lun));
- 	eight_bytes_lun.scsi_lun[0] = (lu->lun >> 8) & 0xff;
- 	eight_bytes_lun.scsi_lun[1] = lu->lun & 0xff;
-
--- 
-Stefan Richter
--=====-==--- --=- ---==
-http://arcgraph.de/sr/
+Tested with an IOI FWB-IDE01AB which has its link-on bit set if bus
+power is available but does not respond to ROM read requests if self
+power is off.  This implements
+  - recognition of the units if self power is switched on after fw-core
+    gave up the initial attempt to read the config ROM,
+  - shutdown of the units when self power is switched off.
 
-
-Add the same workaround as found in fw-sbp2 for feature parity and
-compatibility of the workarounds module parameter.
+Also tested with a second PC running Linux/ieee1394.  When the eth1394
+driver is inserted and removed on that node, fw-core now notices the
+addition and removal of the IPv4 unit on the ieee1394 node.
 
 Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
 ---
- drivers/ieee1394/sbp2.c |   12 ++++++++++++
- drivers/ieee1394/sbp2.h |    2 ++
- 2 files changed, 14 insertions(+)
-
-Index: linux/drivers/ieee1394/sbp2.c
-===================================================================
---- linux.orig/drivers/ieee1394/sbp2.c
-+++ linux/drivers/ieee1394/sbp2.c
-@@ -183,6 +183,9 @@ MODULE_PARM_DESC(exclusive_login, "Exclu
-  *   Avoids access beyond actual disk limits on devices with an off-by-one bug.
-  *   Don't use this with devices which don't have this bug.
-  *
-+ * - delay inquiry
-+ *   Wait extra SBP2_INQUIRY_DELAY seconds after login before SCSI inquiry.
-+ *
-  * - override internal blacklist
-  *   Instead of adding to the built-in blacklist, use only the workarounds
-  *   specified in the module load parameter.
-@@ -195,6 +198,7 @@ MODULE_PARM_DESC(workarounds, "Work arou
- 	", 36 byte inquiry = "    __stringify(SBP2_WORKAROUND_INQUIRY_36)
- 	", skip mode page 8 = "   __stringify(SBP2_WORKAROUND_MODE_SENSE_8)
- 	", fix capacity = "       __stringify(SBP2_WORKAROUND_FIX_CAPACITY)
-+	", delay inquiry = "      __stringify(SBP2_WORKAROUND_DELAY_INQUIRY)
- 	", override internal blacklist = " __stringify(SBP2_WORKAROUND_OVERRIDE)
- 	", or a combination)");
- 
-@@ -357,6 +361,11 @@ static const struct {
- 		.workarounds		= SBP2_WORKAROUND_INQUIRY_36 |
- 					  SBP2_WORKAROUND_MODE_SENSE_8,
- 	},
-+	/* DViCO Momobay FX-3A with TSB42AA9A bridge */ {
-+		.firmware_revision	= 0x002800,
-+		.model_id		= 0x000000,
-+		.workarounds		= SBP2_WORKAROUND_DELAY_INQUIRY,
-+	},
- 	/* Initio bridges, actually only needed for some older ones */ {
- 		.firmware_revision	= 0x000200,
- 		.model_id		= SBP2_ROM_VALUE_WILDCARD,
-@@ -914,6 +923,9 @@ static int sbp2_start_device(struct sbp2
- 	sbp2_agent_reset(lu, 1);
- 	sbp2_max_speed_and_size(lu);
- 
-+	if (lu->workarounds & SBP2_WORKAROUND_DELAY_INQUIRY)
-+		ssleep(SBP2_INQUIRY_DELAY);
-+
- 	error = scsi_add_device(lu->shost, 0, lu->ud->id, 0);
- 	if (error) {
- 		SBP2_ERR("scsi_add_device failed");
-Index: linux/drivers/ieee1394/sbp2.h
-===================================================================
---- linux.orig/drivers/ieee1394/sbp2.h
-+++ linux/drivers/ieee1394/sbp2.h
-@@ -343,6 +343,8 @@ enum sbp2lu_state_types {
- #define SBP2_WORKAROUND_INQUIRY_36	0x2
- #define SBP2_WORKAROUND_MODE_SENSE_8	0x4
- #define SBP2_WORKAROUND_FIX_CAPACITY	0x8
-+#define SBP2_WORKAROUND_DELAY_INQUIRY	0x10
-+#define SBP2_INQUIRY_DELAY		12
- #define SBP2_WORKAROUND_OVERRIDE	0x100
- 
- #endif /* SBP2_H */
-
--- 
-Stefan Richter
--=====-==--- --=- ---==
-http://arcgraph.de/sr/
-
 
-Like the old sbp2 driver, wait for the write transaction to the
-AGENT_RESET to complete before proceeding (after login, after reconnect,
-or in SCSI error handling).
+Applies after "firewire: replace static ROM cache by allocated cache".
 
-There is one occasion where AGENT_RESET is written to from atomic
-context when getting DEAD status for a command ORB.  There we still
-continue without waiting for the transaction to complete because this
-is more difficult to fix...
+ drivers/firewire/fw-cdev.c     |   18 ++--
+ drivers/firewire/fw-device.c   |  147 ++++++++++++++++++++++++++++++---
+ drivers/firewire/fw-topology.c |    3 
+ drivers/firewire/fw-topology.h |   11 +-
+ 4 files changed, 158 insertions(+), 21 deletions(-)
 
-Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
----
- drivers/firewire/fw-sbp2.c |   39 ++++++++++++++++++++++++++-----------
- 1 file changed, 28 insertions(+), 11 deletions(-)
-
-Index: linux/drivers/firewire/fw-sbp2.c
+Index: linux/drivers/firewire/fw-cdev.c
 ===================================================================
---- linux.orig/drivers/firewire/fw-sbp2.c
-+++ linux/drivers/firewire/fw-sbp2.c
-@@ -603,29 +603,46 @@ sbp2_send_management_orb(struct sbp2_log
- 
- static void
- complete_agent_reset_write(struct fw_card *card, int rcode,
--			   void *payload, size_t length, void *data)
-+			   void *payload, size_t length, void *done)
+--- linux.orig/drivers/firewire/fw-cdev.c
++++ linux/drivers/firewire/fw-cdev.c
+@@ -32,6 +32,7 @@
+ #include <linux/idr.h>
+ #include <linux/compat.h>
+ #include <linux/firewire-cdev.h>
++#include <asm/semaphore.h>
+ #include <asm/system.h>
+ #include <asm/uaccess.h>
+ #include "fw-transaction.h"
+@@ -269,20 +270,25 @@ static int ioctl_get_info(struct client 
  {
--	struct fw_transaction *t = data;
-+	complete(done);
-+}
-+
-+static void sbp2_agent_reset(struct sbp2_logical_unit *lu)
-+{
-+	struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
-+	DECLARE_COMPLETION_ONSTACK(done);
-+	struct fw_transaction t;
-+	static u32 z;
- 
--	kfree(t);
-+	fw_send_request(device->card, &t, TCODE_WRITE_QUADLET_REQUEST,
-+			lu->tgt->node_id, lu->generation, device->max_speed,
-+			lu->command_block_agent_address + SBP2_AGENT_RESET,
-+			&z, sizeof(z), complete_agent_reset_write, &done);
-+	wait_for_completion(&done);
- }
+ 	struct fw_cdev_get_info *get_info = buffer;
+ 	struct fw_cdev_event_bus_reset bus_reset;
++	struct fw_device *device = client->device;
++	unsigned long ret = 0;
+ 
+ 	client->version = get_info->version;
+ 	get_info->version = FW_CDEV_VERSION;
+ 
++	down(&device->device.sem);
+ 	if (get_info->rom != 0) {
+ 		void __user *uptr = u64_to_uptr(get_info->rom);
+ 		size_t want = get_info->rom_length;
+-		size_t have = client->device->config_rom_length * 4;
++		size_t have;
+ 
+-		if (copy_to_user(uptr, client->device->config_rom,
+-				 min(want, have)))
+-			return -EFAULT;
++		have = device->config_rom_length * 4;
++		ret = copy_to_user(uptr, device->config_rom, min(want, have));
+ 	}
+-	get_info->rom_length = client->device->config_rom_length * 4;
++	get_info->rom_length = device->config_rom_length * 4;
++	up(&device->device.sem);
++	if (ret != 0)
++		return -EFAULT;
+ 
+ 	client->bus_reset_closure = get_info->bus_reset_closure;
+ 	if (get_info->bus_reset != 0) {
+@@ -293,7 +299,7 @@ static int ioctl_get_info(struct client 
+ 			return -EFAULT;
+ 	}
  
--static int sbp2_agent_reset(struct sbp2_logical_unit *lu)
-+static void
-+complete_agent_reset_write_no_wait(struct fw_card *card, int rcode,
-+				   void *payload, size_t length, void *data)
-+{
-+	kfree(data);
-+}
-+
-+static void sbp2_agent_reset_no_wait(struct sbp2_logical_unit *lu)
- {
- 	struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
- 	struct fw_transaction *t;
--	static u32 zero;
-+	static u32 z;
- 
--	t = kzalloc(sizeof(*t), GFP_ATOMIC);
-+	t = kmalloc(sizeof(*t), GFP_ATOMIC);
- 	if (t == NULL)
--		return -ENOMEM;
-+		return;
+-	get_info->card = client->device->card->index;
++	get_info->card = device->card->index;
  
- 	fw_send_request(device->card, t, TCODE_WRITE_QUADLET_REQUEST,
- 			lu->tgt->node_id, lu->generation, device->max_speed,
- 			lu->command_block_agent_address + SBP2_AGENT_RESET,
--			&zero, sizeof(zero), complete_agent_reset_write, t);
--
--	return 0;
-+			&z, sizeof(z), complete_agent_reset_write_no_wait, t);
+ 	return 0;
  }
- 
- static void sbp2_release_target(struct kref *kref)
-@@ -1110,7 +1127,7 @@ complete_command_orb(struct sbp2_orb *ba
- 
- 	if (status != NULL) {
- 		if (STATUS_GET_DEAD(*status))
--			sbp2_agent_reset(orb->lu);
-+			sbp2_agent_reset_no_wait(orb->lu);
- 
- 		switch (STATUS_GET_RESPONSE(*status)) {
- 		case SBP2_STATUS_REQUEST_COMPLETE:
-
--- 
-Stefan Richter
--=====-==--- --=- ---==
-http://arcgraph.de/sr/
-
-
-for easier readable logs if more than one SBP-2 device is present.
-
-Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
----
- drivers/firewire/fw-sbp2.c |   66 ++++++++++++++++++-------------------
- 1 file changed, 33 insertions(+), 33 deletions(-)
-
-Index: linux/drivers/firewire/fw-sbp2.c
+Index: linux/drivers/firewire/fw-device.c
 ===================================================================
---- linux.orig/drivers/firewire/fw-sbp2.c
-+++ linux/drivers/firewire/fw-sbp2.c
-@@ -149,6 +149,7 @@ struct sbp2_target {
- 	struct kref kref;
- 	struct fw_unit *unit;
- 	struct list_head lu_list;
-+	const char *bus_id;
- 
- 	u64 management_agent_address;
- 	int directory_id;
-@@ -566,20 +567,20 @@ sbp2_send_management_orb(struct sbp2_log
- 
- 	retval = -EIO;
- 	if (sbp2_cancel_orbs(lu) == 0) {
--		fw_error("orb reply timed out, rcode=0x%02x\n",
--			 orb->base.rcode);
-+		fw_error("%s: orb reply timed out, rcode=0x%02x\n",
-+			 lu->tgt->bus_id, orb->base.rcode);
- 		goto out;
- 	}
- 
- 	if (orb->base.rcode != RCODE_COMPLETE) {
--		fw_error("management write failed, rcode 0x%02x\n",
--			 orb->base.rcode);
-+		fw_error("%s: management write failed, rcode 0x%02x\n",
-+			 lu->tgt->bus_id, orb->base.rcode);
- 		goto out;
- 	}
- 
- 	if (STATUS_GET_RESPONSE(orb->status) != 0 ||
- 	    STATUS_GET_SBP_STATUS(orb->status) != 0) {
--		fw_error("error status: %d:%d\n",
-+		fw_error("%s: error status: %d:%d\n", lu->tgt->bus_id,
- 			 STATUS_GET_RESPONSE(orb->status),
- 			 STATUS_GET_SBP_STATUS(orb->status));
- 		goto out;
-@@ -664,7 +665,7 @@ static void sbp2_release_target(struct k
- 		kfree(lu);
- 	}
- 	scsi_remove_host(shost);
--	fw_notify("released %s\n", tgt->unit->device.bus_id);
-+	fw_notify("released %s\n", tgt->bus_id);
- 
- 	put_device(&tgt->unit->device);
- 	scsi_host_put(shost);
-@@ -693,12 +694,11 @@ static void sbp2_login(struct work_struc
- {
- 	struct sbp2_logical_unit *lu =
- 		container_of(work, struct sbp2_logical_unit, work.work);
--	struct Scsi_Host *shost =
--		container_of((void *)lu->tgt, struct Scsi_Host, hostdata[0]);
-+	struct sbp2_target *tgt = lu->tgt;
-+	struct fw_device *device = fw_device(tgt->unit->device.parent);
-+	struct Scsi_Host *shost;
- 	struct scsi_device *sdev;
- 	struct scsi_lun eight_bytes_lun;
--	struct fw_unit *unit = lu->tgt->unit;
--	struct fw_device *device = fw_device(unit->device.parent);
- 	struct sbp2_login_response response;
- 	int generation, node_id, local_node_id;
- 
-@@ -715,14 +715,14 @@ static void sbp2_login(struct work_struc
- 		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);
-+			fw_error("%s: failed to login to LUN %04x\n",
-+				 tgt->bus_id, lu->lun);
- 		goto out;
- 	}
- 
--	lu->generation        = generation;
--	lu->tgt->node_id      = node_id;
--	lu->tgt->address_high = local_node_id << 16;
-+	lu->generation    = generation;
-+	tgt->node_id	  = node_id;
-+	tgt->address_high = local_node_id << 16;
- 
- 	/* Get command block agent offset and login id. */
- 	lu->command_block_agent_address =
-@@ -730,8 +730,8 @@ static void sbp2_login(struct work_struc
- 		response.command_block_agent.low;
- 	lu->login_id = LOGIN_RESPONSE_GET_LOGIN_ID(response);
- 
--	fw_notify("logged in to %s LUN %04x (%d retries)\n",
--		  unit->device.bus_id, lu->lun, lu->retries);
-+	fw_notify("%s: logged in to LUN %04x (%d retries)\n",
-+		  tgt->bus_id, lu->lun, lu->retries);
- 
- #if 0
- 	/* FIXME: The linux1394 sbp2 does this last step. */
-@@ -747,6 +747,7 @@ static void sbp2_login(struct work_struc
- 	memset(&eight_bytes_lun, 0, sizeof(eight_bytes_lun));
- 	eight_bytes_lun.scsi_lun[0] = (lu->lun >> 8) & 0xff;
- 	eight_bytes_lun.scsi_lun[1] = lu->lun & 0xff;
-+	shost = container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
- 
- 	sdev = __scsi_add_device(shost, 0, 0,
- 				 scsilun_to_int(&eight_bytes_lun), lu);
-@@ -791,7 +792,7 @@ static void sbp2_login(struct work_struc
+--- linux.orig/drivers/firewire/fw-device.c
++++ linux/drivers/firewire/fw-device.c
+@@ -26,6 +26,7 @@
+ #include <linux/delay.h>
+ #include <linux/idr.h>
+ #include <linux/rwsem.h>
++#include <linux/string.h>
+ #include <asm/semaphore.h>
+ #include <asm/system.h>
+ #include <linux/ctype.h>
+@@ -160,9 +161,9 @@ static void fw_device_release(struct dev
+ 	 * Take the card lock so we don't set this to NULL while a
+ 	 * FW_NODE_UPDATED callback is being handled.
  	 */
- 	PREPARE_DELAYED_WORK(&lu->work, sbp2_login);
-  out:
--	sbp2_target_put(lu->tgt);
-+	sbp2_target_put(tgt);
- }
- 
- static int sbp2_add_logical_unit(struct sbp2_target *tgt, int lun_entry)
-@@ -874,7 +875,7 @@ static int sbp2_scan_unit_dir(struct sbp
- 			if (timeout > tgt->mgt_orb_timeout)
- 				fw_notify("%s: config rom contains %ds "
- 					  "management ORB timeout, limiting "
--					  "to %ds\n", tgt->unit->device.bus_id,
-+					  "to %ds\n", tgt->bus_id,
- 					  timeout / 1000,
- 					  tgt->mgt_orb_timeout / 1000);
- 			break;
-@@ -902,7 +903,7 @@ static void sbp2_init_workarounds(struct
- 	if (w)
- 		fw_notify("Please notify linux1394-devel at lists.sourceforge.net "
- 			  "if you need the workarounds parameter for %s\n",
--			  tgt->unit->device.bus_id);
-+			  tgt->bus_id);
- 
- 	if (w & SBP2_WORKAROUND_OVERRIDE)
- 		goto out;
-@@ -924,8 +925,7 @@ static void sbp2_init_workarounds(struct
- 	if (w)
- 		fw_notify("Workarounds for %s: 0x%x "
- 			  "(firmware_revision 0x%06x, model_id 0x%06x)\n",
--			  tgt->unit->device.bus_id,
--			  w, firmware_revision, model);
-+			  tgt->bus_id, w, firmware_revision, model);
- 	tgt->workarounds = w;
- }
- 
-@@ -949,6 +949,7 @@ static int sbp2_probe(struct device *dev
- 	tgt->unit = unit;
- 	kref_init(&tgt->kref);
- 	INIT_LIST_HEAD(&tgt->lu_list);
-+	tgt->bus_id = unit->device.bus_id;
- 
- 	if (fw_device_enable_phys_dma(device) < 0)
- 		goto fail_shost_put;
-@@ -999,8 +1000,8 @@ static void sbp2_reconnect(struct work_s
+-	spin_lock_irqsave(&device->card->lock, flags);
++	spin_lock_irqsave(&card->lock, flags);
+ 	device->node->data = NULL;
+-	spin_unlock_irqrestore(&device->card->lock, flags);
++	spin_unlock_irqrestore(&card->lock, flags);
+ 
+ 	fw_node_put(device->node);
+ 	kfree(device->config_rom);
+@@ -337,10 +338,14 @@ static ssize_t
+ config_rom_show(struct device *dev, struct device_attribute *attr, char *buf)
  {
- 	struct sbp2_logical_unit *lu =
- 		container_of(work, struct sbp2_logical_unit, work.work);
--	struct fw_unit *unit = lu->tgt->unit;
--	struct fw_device *device = fw_device(unit->device.parent);
-+	struct sbp2_target *tgt = lu->tgt;
-+	struct fw_device *device = fw_device(tgt->unit->device.parent);
- 	int generation, node_id, local_node_id;
- 
- 	if (fw_device_is_shutdown(device))
-@@ -1015,8 +1016,7 @@ static void sbp2_reconnect(struct work_s
- 				     SBP2_RECONNECT_REQUEST,
- 				     lu->login_id, NULL) < 0) {
- 		if (lu->retries++ >= 5) {
--			fw_error("failed to reconnect to %s\n",
--				 unit->device.bus_id);
-+			fw_error("%s: failed to reconnect\n", tgt->bus_id);
- 			/* Fall back and try to log in again. */
- 			lu->retries = 0;
- 			PREPARE_DELAYED_WORK(&lu->work, sbp2_login);
-@@ -1025,17 +1025,17 @@ static void sbp2_reconnect(struct work_s
- 		goto out;
- 	}
+ 	struct fw_device *device = fw_device(dev);
++	size_t length;
  
--	lu->generation        = generation;
--	lu->tgt->node_id      = node_id;
--	lu->tgt->address_high = local_node_id << 16;
-+	lu->generation    = generation;
-+	tgt->node_id      = node_id;
-+	tgt->address_high = local_node_id << 16;
- 
--	fw_notify("reconnected to %s LUN %04x (%d retries)\n",
--		  unit->device.bus_id, lu->lun, lu->retries);
-+	fw_notify("%s: reconnected to LUN %04x (%d retries)\n",
-+		  tgt->bus_id, lu->lun, lu->retries);
+-	memcpy(buf, device->config_rom, device->config_rom_length * 4);
++	down(&dev->sem);
++	length = device->config_rom_length * 4;
++	memcpy(buf, device->config_rom, length);
++	up(&dev->sem);
  
- 	sbp2_agent_reset(lu);
- 	sbp2_cancel_orbs(lu);
-  out:
--	sbp2_target_put(lu->tgt);
-+	sbp2_target_put(tgt);
+-	return device->config_rom_length * 4;
++	return length;
  }
  
- static void sbp2_update(struct fw_unit *unit)
-@@ -1377,7 +1377,7 @@ static int sbp2_scsi_abort(struct scsi_c
+ static ssize_t
+@@ -412,7 +417,7 @@ read_rom(struct fw_device *device, int g
+  */
+ static int read_bus_info_block(struct fw_device *device, int generation)
  {
- 	struct sbp2_logical_unit *lu = cmd->device->hostdata;
- 
--	fw_notify("sbp2_scsi_abort\n");
-+	fw_notify("%s: sbp2_scsi_abort\n", lu->tgt->bus_id);
- 	sbp2_agent_reset(lu);
- 	sbp2_cancel_orbs(lu);
+-	u32 *rom, *stack;
++	u32 *rom, *stack, *old_rom, *new_rom;
+ 	u32 sp, key;
+ 	int i, end, length, ret = -1;
+ 
+@@ -527,11 +532,18 @@ static int read_bus_info_block(struct fw
+ 			length = i;
+ 	}
  
-
--- 
-Stefan Richter
--=====-==--- --=- ---==
-http://arcgraph.de/sr/
-
-
-When a reconnect failed but re-login succeeded, __scsi_add_device was
-called again.
-
-Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
----
- drivers/firewire/fw-sbp2.c |    6 ++++++
- 1 file changed, 6 insertions(+)
-
-Index: linux/drivers/firewire/fw-sbp2.c
-===================================================================
---- linux.orig/drivers/firewire/fw-sbp2.c
-+++ linux/drivers/firewire/fw-sbp2.c
-@@ -741,6 +741,12 @@ static void sbp2_login(struct work_struc
- 	PREPARE_DELAYED_WORK(&lu->work, sbp2_reconnect);
- 	sbp2_agent_reset(lu);
- 
-+	/* This was a re-login. */
-+	if (lu->sdev) {
-+		sbp2_cancel_orbs(lu);
-+		goto out;
-+	}
+-	device->config_rom = kmalloc(length * 4, GFP_KERNEL);
+-	if (device->config_rom == NULL)
++	old_rom = device->config_rom;
++	new_rom = kmemdup(rom, length * 4, GFP_KERNEL);
++	if (new_rom == NULL)
+ 		goto out;
+-	memcpy(device->config_rom, rom, length * 4);
 +
- 	if (lu->tgt->workarounds & SBP2_WORKAROUND_DELAY_INQUIRY)
- 		ssleep(SBP2_INQUIRY_DELAY);
- 
-
--- 
-Stefan Richter
--=====-==--- --=- ---==
-http://arcgraph.de/sr/
-
-
-If fw-sbp2 was too late with requesting the reconnect, the target would
-reject this.  In this case, log out before attempting the reconnect.
-Else several firmwares will deny the re-login because they somehow
-didn't invalidate the old login.
-
-Also, don't retry reconnects in this situation.  The retries won't
-succeed either.
-
-These changes improve chances for successful re-login and shorten the
-period during which the logical unit is inaccessible.
-
-Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
----
- drivers/firewire/fw-sbp2.c |   17 +++++++++++++++--
- 1 file changed, 15 insertions(+), 2 deletions(-)
-
-Index: linux/drivers/firewire/fw-sbp2.c
-===================================================================
---- linux.orig/drivers/firewire/fw-sbp2.c
-+++ linux/drivers/firewire/fw-sbp2.c
-@@ -710,6 +710,11 @@ static void sbp2_login(struct work_struc
- 	node_id       = device->node_id;
- 	local_node_id = device->card->node_id;
- 
-+	/* If this is a re-login attempt, log out, or we might be rejected. */
-+	if (lu->sdev)
-+		sbp2_send_management_orb(lu, device->node_id, generation,
-+				SBP2_LOGOUT_REQUEST, lu->login_id, NULL);
-+
- 	if (sbp2_send_management_orb(lu, node_id, generation,
- 				SBP2_LOGIN_REQUEST, lu->lun, &response) < 0) {
- 		if (lu->retries++ < 5)
-@@ -1021,9 +1026,17 @@ static void sbp2_reconnect(struct work_s
- 	if (sbp2_send_management_orb(lu, node_id, generation,
- 				     SBP2_RECONNECT_REQUEST,
- 				     lu->login_id, NULL) < 0) {
--		if (lu->retries++ >= 5) {
-+		/*
-+		 * If reconnect was impossible even though we are in the
-+		 * current generation, fall back and try to log in again.
-+		 *
-+		 * We could check for "Function rejected" status, but
-+		 * looking at the bus generation as simpler and more general.
-+		 */
-+		smp_rmb(); /* get current card generation */
-+		if (generation == device->card->generation ||
-+		    lu->retries++ >= 5) {
- 			fw_error("%s: failed to reconnect\n", tgt->bus_id);
--			/* Fall back and try to log in again. */
- 			lu->retries = 0;
- 			PREPARE_DELAYED_WORK(&lu->work, sbp2_login);
- 		}
-
--- 
-Stefan Richter
--=====-==--- --=- ---==
-http://arcgraph.de/sr/
-
-
-Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
----
- drivers/firewire/fw-sbp2.c |   14 +++++++-------
- 1 file changed, 7 insertions(+), 7 deletions(-)
-
-Index: linux/drivers/firewire/fw-sbp2.c
-===================================================================
---- linux.orig/drivers/firewire/fw-sbp2.c
-+++ linux/drivers/firewire/fw-sbp2.c
-@@ -28,15 +28,15 @@
-  * and many others.
-  */
- 
-+#include <linux/blkdev.h>
-+#include <linux/delay.h>
-+#include <linux/device.h>
-+#include <linux/dma-mapping.h>
- #include <linux/kernel.h>
-+#include <linux/mod_devicetable.h>
- #include <linux/module.h>
- #include <linux/moduleparam.h>
--#include <linux/mod_devicetable.h>
--#include <linux/delay.h>
--#include <linux/device.h>
- #include <linux/scatterlist.h>
--#include <linux/dma-mapping.h>
--#include <linux/blkdev.h>
- #include <linux/string.h>
- #include <linux/stringify.h>
- #include <linux/timer.h>
-@@ -48,9 +48,9 @@
- #include <scsi/scsi_device.h>
- #include <scsi/scsi_host.h>
- 
--#include "fw-transaction.h"
--#include "fw-topology.h"
- #include "fw-device.h"
-+#include "fw-topology.h"
-+#include "fw-transaction.h"
- 
- /*
-  * So far only bridges from Oxford Semiconductor are known to support
-
--- 
-Stefan Richter
--=====-==--- --=- ---==
-http://arcgraph.de/sr/
-
-
-While fw-sbp2 takes the necessary time to reconnect to a logical unit
-after bus reset, the SCSI core keeps sending new commands.  They are all
-immediately completed with host busy status, and application clients or
-filesystems will break quickly.  The SCSI device might even be taken
-offline:  http://bugzilla.kernel.org/show_bug.cgi?id=9734
-
-The only remedy seems to be to block the SCSI device until reconnect.
-Alas the SCSI core has no useful API to block only one logical unit i.e.
-the scsi_device, therefore we block the entire Scsi_Host.  This
-currently corresponds to an SBP-2 target.  In case of targets with
-multiple logical units, we need to satisfy the dependencies between
-logical units by carefully tracking the blocking state of the target and
-its units.  We block all logical units of a target as soon as one of
-them needs to be blocked, and keep them blocked until all of them are
-ready to be unblocked.
-
-Furthermore, as the history of the old sbp2 driver has shown, the
-scsi_block_requests() API is a minefield with high potential of
-deadlocks.  We therefore take extra measures to keep logical units
-unblocked during __scsi_add_device() and during shutdown.
-
-Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
----
- drivers/firewire/fw-sbp2.c |   71 +++++++++++++++++++++++++++++++++++--
- 1 file changed, 69 insertions(+), 2 deletions(-)
-
-Index: linux/drivers/firewire/fw-sbp2.c
-===================================================================
---- linux.orig/drivers/firewire/fw-sbp2.c
-+++ linux/drivers/firewire/fw-sbp2.c
-@@ -41,6 +41,8 @@
- #include <linux/stringify.h>
- #include <linux/timer.h>
- #include <linux/workqueue.h>
-+#include <asm/atomic.h>
-+#include <asm/system.h>
- 
- #include <scsi/scsi.h>
- #include <scsi/scsi_cmnd.h>
-@@ -139,6 +140,7 @@ struct sbp2_logical_unit {
- 	int generation;
- 	int retries;
- 	struct delayed_work work;
-+	atomic_t blocked;
- };
- 
- /*
-@@ -157,6 +159,9 @@ struct sbp2_target {
- 	int address_high;
- 	unsigned int workarounds;
- 	unsigned int mgt_orb_timeout;
++	/* serialize with readers via sysfs or ioctl */
++	down(&device->device.sem);
++	device->config_rom = new_rom;
+ 	device->config_rom_length = length;
++	up(&device->device.sem);
 +
-+	atomic_t dont_block;
-+	atomic_t blocked;
- };
++	kfree(old_rom);
+ 	ret = 0;
+  out:
+ 	kfree(rom);
+@@ -724,7 +736,7 @@ static void fw_device_init(struct work_s
+ 	if (atomic_cmpxchg(&device->state,
+ 		    FW_DEVICE_INITIALIZING,
+ 		    FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN) {
+-		fw_device_shutdown(&device->work.work);
++		fw_device_shutdown(work);
+ 	} else {
+ 		if (device->config_rom_retries)
+ 			fw_notify("created device %s: GUID %08x%08x, S%d00, "
+@@ -738,6 +750,7 @@ static void fw_device_init(struct work_s
+ 				  device->device.bus_id,
+ 				  device->config_rom[3], device->config_rom[4],
+ 				  1 << device->max_speed);
++		device->config_rom_retries = 0;
+ 	}
  
- /*
-@@ -646,6 +651,53 @@ static void sbp2_agent_reset_no_wait(str
- 			&z, sizeof(z), complete_agent_reset_write_no_wait, t);
+ 	/*
+@@ -784,6 +797,104 @@ static void fw_device_update(struct work
+ 	device_for_each_child(&device->device, NULL, update_unit);
  }
  
-+/*
-+ * Blocks lu->tgt if all of the following conditions are met:
-+ *   - Login, INQUIRY, and high-level SCSI setup of all logical units of the
-+ *     target have been successfully finished (indicated by dont_block == 0).
-+ *   - The lu->generation is stale.  sbp2_reconnect will unblock lu later.
-+ */
-+static void sbp2_conditionally_block(struct sbp2_logical_unit *lu)
++enum {
++	REREAD_BIB_ERROR,
++	REREAD_BIB_GONE,
++	REREAD_BIB_UNCHANGED,
++	REREAD_BIB_CHANGED,
++};
++
++/* Reread and compare bus info block and header of root directory */
++static int reread_bus_info_block(struct fw_device *device, int generation)
 +{
-+	struct fw_card *card = fw_device(lu->tgt->unit->device.parent)->card;
++	u32 q;
++	int i;
 +
-+	if (!atomic_read(&lu->tgt->dont_block) &&
-+	    lu->generation != card->generation &&
-+	    atomic_cmpxchg(&lu->blocked, 0, 1) == 0) {
-+
-+		/* raise the block count of the target */
-+		if (atomic_inc_return(&lu->tgt->blocked) == 1) {
-+			scsi_block_requests(lu->sdev->host);
-+			fw_notify("blocked %s\n", lu->tgt->bus_id);
-+		}
++	for (i = 0; i < 6; i++) {
++		if (read_rom(device, generation, i, &q) != RCODE_COMPLETE)
++			return REREAD_BIB_ERROR;
++
++		if (i == 0 && q == 0)
++			return REREAD_BIB_GONE;
++
++		if (i > device->config_rom_length || q != device->config_rom[i])
++			return REREAD_BIB_CHANGED;
 +	}
++
++	return REREAD_BIB_UNCHANGED;
 +}
 +
-+/* Unblocks lu->tgt as soon as all its logical units can be unblocked. */
-+static void sbp2_conditionally_unblock(struct sbp2_logical_unit *lu)
++static void fw_device_refresh(struct work_struct *work)
 +{
-+	if (atomic_cmpxchg(&lu->blocked, 1, 0) == 1) {
++	struct fw_device *device =
++		container_of(work, struct fw_device, work.work);
++	struct fw_card *card = device->card;
++	int node_id = device->node_id;
++
++	switch (reread_bus_info_block(device, device->generation)) {
++	case REREAD_BIB_ERROR:
++		if (device->config_rom_retries < MAX_RETRIES / 2 &&
++		    atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
++			device->config_rom_retries++;
++			schedule_delayed_work(&device->work, RETRY_DELAY / 2);
 +
-+		/* lower the block count of the target */
-+		if (atomic_dec_and_test(&lu->tgt->blocked)) {
-+			scsi_unblock_requests(lu->sdev->host);
-+			fw_notify("unblocked %s\n", lu->tgt->bus_id);
++			return;
 +		}
-+	}
-+}
++		goto give_up;
 +
++	case REREAD_BIB_GONE:
++		goto gone;
 +
-+/* Prevents future blocking of tgt and then unblocks it. */
-+static void sbp2_unblock(struct sbp2_target *tgt)
-+{
-+	struct Scsi_Host *shost =
-+		container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
++	case REREAD_BIB_UNCHANGED:
++		if (atomic_cmpxchg(&device->state,
++			    FW_DEVICE_INITIALIZING,
++			    FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN)
++			goto gone;
 +
-+	atomic_inc(&tgt->dont_block);
-+	smp_wmb();
-+	scsi_unblock_requests(shost);
-+}
++		fw_device_update(work);
++		device->config_rom_retries = 0;
++
++		return;
++	}
 +
- static void sbp2_release_target(struct kref *kref)
- {
- 	struct sbp2_target *tgt = container_of(kref, struct sbp2_target, kref);
-@@ -653,6 +705,12 @@ static void sbp2_release_target(struct k
- 	struct Scsi_Host *shost =
- 		container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
- 
 +	/*
-+	 * Make sure that the target is unblocked and won't be blocked anymore
-+	 * before scsi_remove_device() is called.  Else it will deadlock.
++	 * Something changed.  We keep things simple and don't investigate
++	 * further.  We just destroy all previous units and create new ones.
 +	 */
-+	sbp2_unblock(tgt);
++	device_for_each_child(&device->device, NULL, shutdown_unit);
++
++	if (read_bus_info_block(device, device->generation) < 0) {
++		if (device->config_rom_retries < MAX_RETRIES &&
++		    atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
++			device->config_rom_retries++;
++			schedule_delayed_work(&device->work, RETRY_DELAY);
 +
- 	list_for_each_entry_safe(lu, next, &tgt->lu_list, link) {
- 		if (lu->sdev)
- 			scsi_remove_device(lu->sdev);
-@@ -717,11 +775,14 @@ 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 (lu->retries++ < 5) {
- 			sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
--		else
-+		} else {
- 			fw_error("%s: failed to login to LUN %04x\n",
- 				 tgt->bus_id, lu->lun);
-+			/* Let any waiting I/O fail from now on. */
-+			sbp2_unblock(lu->tgt);
++			return;
 +		}
- 		goto out;
- 	}
- 
-@@ -749,6 +810,7 @@ static void sbp2_login(struct work_struc
- 	/* This was a re-login. */
- 	if (lu->sdev) {
- 		sbp2_cancel_orbs(lu);
-+		sbp2_conditionally_unblock(lu);
- 		goto out;
- 	}
- 
-@@ -786,6 +848,8 @@ static void sbp2_login(struct work_struc
- 		 * Can you believe it?  Everything went well.
- 		 */
- 		lu->sdev = sdev;
-+		smp_wmb();  /* We need lu->sdev when we want to block lu. */
-+		atomic_dec(&lu->tgt->dont_block);
- 		scsi_device_put(sdev);
- 		goto out;
- 	}
-@@ -828,6 +892,7 @@ static int sbp2_add_logical_unit(struct 
- 	lu->sdev = NULL;
- 	lu->lun  = lun_entry & 0xffff;
- 	lu->retries = 0;
-+	atomic_inc(&tgt->dont_block);
- 	INIT_LIST_HEAD(&lu->orb_list);
- 	INIT_DELAYED_WORK(&lu->work, sbp2_login);
- 
-@@ -1053,6 +1118,7 @@ static void sbp2_reconnect(struct work_s
- 
- 	sbp2_agent_reset(lu);
- 	sbp2_cancel_orbs(lu);
-+	sbp2_conditionally_unblock(lu);
-  out:
- 	sbp2_target_put(tgt);
- }
-@@ -1172,6 +1238,7 @@ complete_command_orb(struct sbp2_orb *ba
- 		 * or when sending the write (less likely).
- 		 */
- 		result = DID_BUS_BUSY << 16;
-+		sbp2_conditionally_block(orb->lu);
- 	}
- 
- 	dma_unmap_single(device->card->device, orb->base.request_bus,
-
--- 
-Stefan Richter
--=====-==--- --=- ---==
-http://arcgraph.de/sr/
-
-Since "fw-sbp2: fix I/O errors during reconnect", a Scsi_Host will be
-blocked as soon as a command failed due to bus generation change.  Now
-we also block it when fw-core signalled a bus reset via sbp2_update.
-This will avoid some command failures and retries (but not all because
-commands are injected from tasklet context while sbp2_update runs from
-workqueue thread context).
-
-Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
----
- drivers/firewire/fw-sbp2.c |    1 +
- 1 file changed, 1 insertion(+)
-
-Index: linux/drivers/firewire/fw-sbp2.c
-===================================================================
---- linux.orig/drivers/firewire/fw-sbp2.c
-+++ linux/drivers/firewire/fw-sbp2.c
-@@ -1135,6 +1135,7 @@ static void sbp2_update(struct fw_unit *
- 	 * Iteration over tgt->lu_list is therefore safe here.
- 	 */
- 	list_for_each_entry(lu, &tgt->lu_list, link) {
-+		sbp2_conditionally_block(lu);
- 		lu->retries = 0;
- 		sbp2_queue_work(lu, 0);
- 	}
-
--- 
-Stefan Richter
--=====-==--- --=- --==-
-http://arcgraph.de/sr/
-
-
-fw-sbp2 is unable to reconnect while performing __scsi_add_device
-because there is only a single workqueue thread context available for
-both at the moment.  This should be fixed eventually.
-
-An actual failure of __scsi_add_device is easy to handle, but an
-incomplete execution of __scsi_add_device with an sdev returned would
-remain undetected and leave the SBP-2 target unusable.
-
-Therefore we use a workaround:  If there was a bus reset during
-__scsi_add_device (i.e. during the SCSI probe), we remove the new sdev
-immediately, log out, and attempt login and SCSI probe again.
-
-Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
-Signed-off-by: Jarod Wilson <jwilson at redhat.com>
----
-
-The previous patch "firewire: fw-sbp2: retry login if scsi_device was
-offlined early" should be folded into this one before upstream
-submission.
-
- drivers/firewire/fw-sbp2.c |   43 ++++++++++++++++---------------------
- 1 file changed, 19 insertions(+), 24 deletions(-)
-
-Index: linux/drivers/firewire/fw-sbp2.c
-===================================================================
---- linux.orig/drivers/firewire/fw-sbp2.c
-+++ linux/drivers/firewire/fw-sbp2.c
-@@ -824,36 +824,31 @@ static void sbp2_login(struct work_struc
- 
- 	sdev = __scsi_add_device(shost, 0, 0,
- 				 scsilun_to_int(&eight_bytes_lun), lu);
--	if (IS_ERR(sdev)) {
--		/*
--		 * The most frequent cause for __scsi_add_device() to fail
--		 * is a bus reset while sending the SCSI INQUIRY.  Try again.
--		 */
-+	/*
-+	 * FIXME:  We are unable to perform reconnects while in sbp2_login().
-+	 * Therefore __scsi_add_device() will get into trouble if a bus reset
-+	 * happens in parallel.  It will either fail or leave us with an
-+	 * unusable sdev.  As a workaround we check for this and retry the
-+	 * whole login and SCSI probing.
-+	 */
++		goto give_up;
++	}
 +
-+	if (IS_ERR(sdev))
- 		goto out_logout_login;
- 
--	} else if (sdev->sdev_state == SDEV_OFFLINE) {
--		/*
--		 * FIXME:  We are unable to perform reconnects while in
--		 * sbp2_login().  Therefore __scsi_add_device() will get
--		 * into trouble if a bus reset happens in parallel.
--		 * It will either fail (that's OK, see above) or take sdev
--		 * offline.  Here is a crude workaround for the latter.
--		 */
--		scsi_device_put(sdev);
-+	scsi_device_put(sdev);
-+
-+	smp_rmb(); /* get current card generation */
-+	if (generation != device->card->generation) {
- 		scsi_remove_device(sdev);
- 		goto out_logout_login;
--
--	} else {
--		/*
--		 * Can you believe it?  Everything went well.
--		 */
--		lu->sdev = sdev;
--		smp_wmb();  /* We need lu->sdev when we want to block lu. */
--		atomic_dec(&lu->tgt->dont_block);
--		scsi_device_put(sdev);
--		goto out;
- 	}
- 
-+	/* Everything went well. */
-+	lu->sdev = sdev;
-+	smp_wmb();  /* We need lu->sdev when we want to block lu. */
-+	atomic_dec(&lu->tgt->dont_block);
++	create_units(device);
++
++	if (atomic_cmpxchg(&device->state,
++		    FW_DEVICE_INITIALIZING,
++		    FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN)
++		goto gone;
++
++	fw_notify("refreshed device %s\n", device->device.bus_id);
++	device->config_rom_retries = 0;
 +	goto out;
 +
-  out_logout_login:
- 	smp_rmb(); /* generation may have changed */
- 	generation = device->generation;
++ give_up:
++	fw_notify("giving up on refresh of device %s\n", device->device.bus_id);
++ gone:
++	atomic_set(&device->state, FW_DEVICE_SHUTDOWN);
++	fw_device_shutdown(work);
++ out:
++	if (node_id == card->root_node->node_id)
++		schedule_delayed_work(&card->work, 0);
++}
++
+ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
+ {
+ 	struct fw_device *device;
+@@ -793,7 +904,7 @@ void fw_node_event(struct fw_card *card,
+ 	case FW_NODE_LINK_ON:
+ 		if (!node->link_on)
+ 			break;
+-
++ create:
+ 		device = kzalloc(sizeof(*device), GFP_ATOMIC);
+ 		if (device == NULL)
+ 			break;
+@@ -832,6 +943,22 @@ void fw_node_event(struct fw_card *card,
+ 		schedule_delayed_work(&device->work, INITIAL_DELAY);
+ 		break;
+ 
++	case FW_NODE_INITIATED_RESET:
++		device = node->data;
++		if (device == NULL)
++			goto create;
++
++		device->node_id = node->node_id;
++		smp_wmb();  /* update node_id before generation */
++		device->generation = card->generation;
++		if (atomic_cmpxchg(&device->state,
++			    FW_DEVICE_RUNNING,
++			    FW_DEVICE_INITIALIZING) == FW_DEVICE_RUNNING) {
++			PREPARE_DELAYED_WORK(&device->work, fw_device_refresh);
++			schedule_delayed_work(&device->work, INITIAL_DELAY);
++		}
++		break;
++
+ 	case FW_NODE_UPDATED:
+ 		if (!node->link_on || node->data == NULL)
+ 			break;
+Index: linux/drivers/firewire/fw-topology.c
+===================================================================
+--- linux.orig/drivers/firewire/fw-topology.c
++++ linux/drivers/firewire/fw-topology.c
+@@ -107,6 +107,7 @@ static struct fw_node *fw_node_create(u3
+ 	node->node_id = LOCAL_BUS | SELF_ID_PHY_ID(sid);
+ 	node->link_on = SELF_ID_LINK_ON(sid);
+ 	node->phy_speed = SELF_ID_PHY_SPEED(sid);
++	node->initiated_reset = SELF_ID_PHY_INITIATOR(sid);
+ 	node->port_count = port_count;
+ 
+ 	atomic_set(&node->ref_count, 1);
+@@ -430,6 +431,8 @@ update_tree(struct fw_card *card, struct
+ 			event = FW_NODE_LINK_OFF;
+ 		else if (!node0->link_on && node1->link_on)
+ 			event = FW_NODE_LINK_ON;
++		else if (node1->initiated_reset && node1->link_on)
++			event = FW_NODE_INITIATED_RESET;
+ 		else
+ 			event = FW_NODE_UPDATED;
+ 
+Index: linux/drivers/firewire/fw-topology.h
+===================================================================
+--- linux.orig/drivers/firewire/fw-topology.h
++++ linux/drivers/firewire/fw-topology.h
+@@ -20,11 +20,12 @@
+ #define __fw_topology_h
+ 
+ enum {
+-	FW_NODE_CREATED =   0x00,
+-	FW_NODE_UPDATED =   0x01,
+-	FW_NODE_DESTROYED = 0x02,
+-	FW_NODE_LINK_ON =   0x03,
+-	FW_NODE_LINK_OFF =  0x04,
++	FW_NODE_CREATED,
++	FW_NODE_UPDATED,
++	FW_NODE_DESTROYED,
++	FW_NODE_LINK_ON,
++	FW_NODE_LINK_OFF,
++	FW_NODE_INITIATED_RESET,
+ };
+ 
+ struct fw_node {
 
 -- 
 Stefan Richter
--=====-==--- --=- -=---
+-=====-==--- --== ---==
 http://arcgraph.de/sr/
 
 

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

View full diff with command:
/usr/bin/cvs -f diff  -kk -u -N -r 1.3 -r 1.4 linux-2.6-firewire-git-update.patch
Index: linux-2.6-firewire-git-update.patch
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/F-8/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	15 Feb 2008 23:58:52 -0000	1.3
+++ linux-2.6-firewire-git-update.patch	4 Mar 2008 05:03:18 -0000	1.4
@@ -1,251 +1,3201 @@
-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
+IEEE 1394 updates for Linux 2.6.24 (v659 2008-03-02)
+
+ MAINTAINERS                              |    4 
+ drivers/firewire/fw-card.c               |   99 +--
+ drivers/firewire/fw-cdev.c               |   20 
+ drivers/firewire/fw-device.c             |  107 ++--
+ drivers/firewire/fw-device.h             |   49 +
+ drivers/firewire/fw-ohci.c               |  494 ++++++++++++-------
+ drivers/firewire/fw-sbp2.c               |  588 +++++++++++++++--------
+ drivers/firewire/fw-topology.c           |    7 
+ drivers/firewire/fw-transaction.c        |    6 
+ drivers/firewire/fw-transaction.h        |   12 
+ drivers/ieee1394/dma.c                   |   37 -
+ drivers/ieee1394/dv1394.c                |    3 
+ drivers/ieee1394/ieee1394_transactions.c |   68 --
+ drivers/ieee1394/nodemgr.c               |    6 
+ drivers/ieee1394/ohci1394.c              |  121 ++--
+ drivers/ieee1394/raw1394.c               |    5 
+ drivers/ieee1394/sbp2.c                  |   67 +-
+ drivers/ieee1394/sbp2.h                  |    3 
+ drivers/ieee1394/video1394.c             |    3 
+ lib/Kconfig.debug                        |   11 
+ 20 files changed, 1042 insertions(+), 668 deletions(-)
+
+========================================================================
+Date: Sat, 1 Mar 2008 12:36:42 +0100 (CET)
+From: Stefan Richter <stefanr at s5r6.in-berlin.de>
+Subject: ieee1394: ohci1394: refactor probe, remove, suspend, resume
+
+Clean up shared code and variable names.
+
+Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
+---
+ drivers/ieee1394/ohci1394.c |  113 +++++++++++++++++++-------------------------
+ 1 file changed, 49 insertions(+), 64 deletions(-)
+
+========================================================================
+Date: Sat, 1 Mar 2008 12:36:06 +0100 (CET)
+From: Stefan Richter <stefanr at s5r6.in-berlin.de>
+Subject: ieee1394: ohci1394: switch on bus power after resume on PPC PMac
+
+The platform feature calls in the suspend method switched off cable
+power, but the calls in the resume method did not switch it back on.
+
+Add the necessary feature call to .resume.  Also add the corresponding
+call to .suspend to make .suspend's behavior explicitly the same on all
+PMacs.
+
+Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
+---
+ drivers/ieee1394/ohci1394.c |    8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+========================================================================
+Date: Sat, 1 Mar 2008 12:35:29 +0100 (CET)
+From: Stefan Richter <stefanr at s5r6.in-berlin.de>
+Subject: firewire: fw-ohci: refactor probe, remove, suspend, resume
+
+Clean up shared code and variable names.
+
+Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
+---
+ drivers/firewire/fw-ohci.c |  100 ++++++++++++++++++---------------------------
+ 1 file changed, 42 insertions(+), 58 deletions(-)
+
+========================================================================
+Date: Sat, 1 Mar 2008 12:34:50 +0100 (CET)
+From: Stefan Richter <stefanr at s5r6.in-berlin.de>
+Subject: firewire: fw-ohci: switch on bus power after resume on PPC PMac
+
+The platform feature calls in the suspend method switched off cable
+power, but the calls in the resume method did not switch it back on.
+
+Add the necessary feature call to .resume.  Also add the corresponding
+call to .suspend to make .suspend's behavior explicitly the same on all
+PMacs.
+
+Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
+---
+ drivers/firewire/fw-ohci.c |    8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+========================================================================
+Date: Sat, 1 Mar 2008 12:21:47 +0100 (CET)
+From: Stefan Richter <stefanr at s5r6.in-berlin.de>
+Subject: firewire: fw-ohci: shut up false compiler warning on PPC32
+
+Shut up two "may be used uninitialised in this function" warnings due to
+PPC32's implementation of dma_alloc_coherent().
+
+Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
+---
+ drivers/firewire/fw-ohci.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+========================================================================
+Date: Sat, 1 Mar 2008 02:47:15 +0100 (CET)
+From: Stefan Richter <stefanr at s5r6.in-berlin.de>
+Subject: firewire: fw-ohci: Apple UniNorth 1st generation support
+
+Mostly copied from ohci1394.c.  Necessary for some older Macs, e.g.
+PowerBook G3 Pismo and early PowerBook G4 Titanium.
+
+Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
+---
+ drivers/firewire/fw-ohci.c |   29 +++++++++++++++++++++--------
+ 1 file changed, 21 insertions(+), 8 deletions(-)
+
+========================================================================
+Date: Sat, 1 Mar 2008 02:42:56 +0100 (CET)
+From: Stefan Richter <stefanr at s5r6.in-berlin.de>
+Subject: firewire: fw-ohci: PPC PMac platform code
+
+Copied from ohci1394.c.  This code is necessary to prevent machine check
+exceptions when reloading or resuming the driver.
+
+Tested on a 1st generation PowerBook G4 Titanium, which also needs the
+pci_probe() hunk.
+
+Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
+
+I was able to reproduce the system exception on resume with a 3rd-gen
+Titanium PowerBook G4 667, and this patch does let the system resume
+successfully now.
+
+Not quite clear if there was possibly an updated version coming using
+pci_enable_device() instead of the pair of pmac_call_feature() calls,
+but either way, this is a definite must-have, at least for older ppc
+macs -- my Aluminum PowerBook G4/1.67 suspends and resumes without this
+patch just fine.
+
+Signed-off-by: Jarod Wilson <jwilson at redhat.com>
+Acked-by: Benjamin Herrenschmidt <benh at kernel.crashing.org>
+---
+ drivers/firewire/fw-ohci.c |   50 +++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 50 insertions(+)
+
+========================================================================
+Date: Thu, 28 Feb 2008 20:54:43 +0100 (CET)
+From: Stefan Richter <stefanr at s5r6.in-berlin.de>
+Subject: firewire: fw-ohci: add option for remote debugging
+
+This way firewire-ohci can be used for remote debugging like ohci1394.
+
+Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
+---
+ drivers/firewire/fw-ohci.c |    9 +++++++++
+ lib/Kconfig.debug          |   11 +++++++++++
+ 2 files changed, 20 insertions(+)
+
+========================================================================
+Date: Thu, 28 Feb 2008 20:53:45 +0100 (CET)
+From: Stefan Richter <stefanr at s5r6.in-berlin.de>
+Subject: firewire: fw-sbp2: reduce log noise
+
+The block/unblock logic is now sufficiently tested.
+
+Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
+---
+ drivers/firewire/fw-sbp2.c |    8 ++------
+ 1 file changed, 2 insertions(+), 6 deletions(-)
+
+========================================================================
+Date: Thu, 28 Feb 2008 20:52:43 +0100 (CET)
+From: Stefan Richter <stefanr at s5r6.in-berlin.de>
+Subject: firewire: fw-sbp2: remove unnecessary memset
+
+orb came from kzalloc.
+
+Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
+---
+ drivers/firewire/fw-sbp2.c |    3 ---
+ 1 file changed, 3 deletions(-)
+
+========================================================================
+Date: Thu, 28 Feb 2008 20:52:02 +0100 (CET)
+From: Stefan Richter <stefanr at s5r6.in-berlin.de>
+Subject: firewire: fw-sbp2: simplify some macros
+
+How hard can it be to switch on one bit? :-)
+
+Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
+---
+ drivers/firewire/fw-sbp2.c |   11 ++---------
+ 1 file changed, 2 insertions(+), 9 deletions(-)
+
+========================================================================
[...4685 lines suppressed...]
 +		goto out;
++	} else if (root_device->config_rom[2] & BIB_CMC) {
+ 		/*
+ 		 * FIXME: I suppose we should set the cmstr bit in the
+ 		 * STATE_CLEAR register of this node, as described in
+@@ -332,7 +345,7 @@ fw_card_bm_work(struct work_struct *work
+ 		 * successfully read the config rom, but it's not
+ 		 * cycle master capable.
+ 		 */
+-		new_root_id = card->local_node->node_id;
++		new_root_id = local_node->node_id;
  	}
  
- 	lu->generation        = generation;
-@@ -930,8 +995,8 @@ static void sbp2_reconnect(struct work_s
+  pick_me:
+@@ -341,8 +354,8 @@ fw_card_bm_work(struct work_struct *work
+ 	 * the typically much larger 1394b beta repeater delays though.
+ 	 */
+ 	if (!card->beta_repeaters_present &&
+-	    card->root_node->max_hops < ARRAY_SIZE(gap_count_table))
+-		gap_count = gap_count_table[card->root_node->max_hops];
++	    root_node->max_hops < ARRAY_SIZE(gap_count_table))
++		gap_count = gap_count_table[root_node->max_hops];
+ 	else
+ 		gap_count = 63;
  
- 	sbp2_agent_reset(lu);
- 	sbp2_cancel_orbs(lu);
--
--	kref_put(&lu->tgt->kref, sbp2_release_target);
+@@ -364,6 +377,11 @@ fw_card_bm_work(struct work_struct *work
+ 		fw_send_phy_config(card, new_root_id, generation, gap_count);
+ 		fw_core_initiate_bus_reset(card, 1);
+ 	}
 + out:
-+	sbp2_target_put(lu->tgt);
++	if (root_device)
++		fw_device_put(root_device);
++	fw_node_put(root_node);
++	fw_node_put(local_node);
  }
  
- static void sbp2_update(struct fw_unit *unit)
-@@ -947,8 +1012,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);
- 	}
- }
+ static void
+@@ -380,7 +398,7 @@ fw_card_initialize(struct fw_card *card,
+ {
+ 	static atomic_t index = ATOMIC_INIT(-1);
  
-@@ -1103,9 +1167,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))) {
-@@ -1158,7 +1222,7 @@ static int sbp2_scsi_queuecommand(struct
- 	struct sbp2_logical_unit *lu = cmd->device->hostdata;
- 	struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
- 	struct sbp2_command_orb *orb;
--	unsigned max_payload;
-+	unsigned int max_payload;
- 	int retval = SCSI_MLQUEUE_HOST_BUSY;
+-	kref_init(&card->kref);
++	atomic_set(&card->device_count, 0);
+ 	card->index = atomic_inc_return(&index);
+ 	card->driver = driver;
+ 	card->device = device;
+@@ -410,12 +428,6 @@ fw_card_add(struct fw_card *card,
+ 	card->link_speed = link_speed;
+ 	card->guid = guid;
  
- 	/*
-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;
+-	/*
+-	 * The subsystem grabs a reference when the card is added and
+-	 * drops it when the driver calls fw_core_remove_card.
+-	 */
+-	fw_card_get(card);
+-
+ 	mutex_lock(&card_mutex);
+ 	config_rom = generate_config_rom(card, &length);
+ 	list_add_tail(&card->link, &card_list);
+@@ -511,44 +523,19 @@ fw_core_remove_card(struct fw_card *card
+ 	card->driver = &dummy_driver;
  
- 	card->node_id = node_id;
+ 	fw_destroy_nodes(card);
+-	flush_scheduled_work();
 +	/*
-+	 * Update node_id before generation to prevent anybody from using
-+	 * a stale node_id together with a current generation.
++	 * Wait for all device workqueue jobs to finish.  Otherwise the
++	 * firewire-core module could be unloaded before the jobs ran.
 +	 */
-+	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;
++	while (atomic_read(&card->device_count) > 0)
++		msleep(100);
  
- 	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]);
- 	destination = HEADER_GET_DESTINATION(p->header[0]);
--	source      = HEADER_GET_SOURCE(p->header[0]);
-+	source      = HEADER_GET_SOURCE(p->header[1]);
++	cancel_delayed_work_sync(&card->work);
+ 	fw_flush_transactions(card);
+ 	del_timer_sync(&card->flush_timer);
+-
+-	fw_card_put(card);
+ }
+ EXPORT_SYMBOL(fw_core_remove_card);
  
- 	spin_lock_irqsave(&address_handler_lock, flags);
- 	handler = lookup_enclosing_address_handler(&address_handler_list,
+-struct fw_card *
+-fw_card_get(struct fw_card *card)
+-{
+-	kref_get(&card->kref);
+-
+-	return card;
+-}
+-EXPORT_SYMBOL(fw_card_get);
+-
+-static void
+-release_card(struct kref *kref)
+-{
+-	struct fw_card *card = container_of(kref, struct fw_card, kref);
+-
+-	kfree(card);
+-}
+-
+-/*
+- * An assumption for fw_card_put() is that the card driver allocates
+- * the fw_card struct with kalloc and that it has been shut down
+- * before the last ref is dropped.
+- */
+-void
+-fw_card_put(struct fw_card *card)
+-{
+-	kref_put(&card->kref, release_card);
+-}
+-EXPORT_SYMBOL(fw_card_put);
+-
+ int
+ fw_core_initiate_bus_reset(struct fw_card *card, int short_reset)
+ {
+Index: linux-2.6.24/lib/Kconfig.debug
+===================================================================
+--- linux-2.6.24.orig/lib/Kconfig.debug
++++ linux-2.6.24/lib/Kconfig.debug
+@@ -517,4 +517,15 @@ config FAULT_INJECTION_STACKTRACE_FILTER
+ 	help
+ 	  Provide stacktrace filter for fault-injection capabilities
+ 
++config FIREWIRE_OHCI_REMOTE_DMA
++	bool "Remote debugging via firewire-ohci"
++	depends on FIREWIRE_OHCI
++	help
++	  This option lets you use the FireWire bus for remote debugging.
++	  It enables unfiltered remote DMA in the firewire-ohci driver.
++	  See Documentation/debugging-via-ohci1394.txt in linux-2.6.25 or
++	  later for more information.
++
++	  If unsure, say N.
++
+ source "samples/Kconfig"




More information about the fedora-extras-commits mailing list