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