mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Stefan Richter <stefanr@s5r6.in-berlin.de>
To: Jarod Wilson <jwilson@redhat.com>
Cc: "Kristian Høgsberg" <krh@redhat.com>,
	"Nick Piggin" <nickpiggin@yahoo.com.au>,
	linux1394-devel@lists.sourceforge.net,
	linux-kernel@vger.kernel.org
Subject: [PATCH 4/4 update] firewire: fw-core: react on bus resets while the config ROM is being fetched
Date: Fri, 25 Jan 2008 17:53:49 +0100 (CET)	[thread overview]
Message-ID: <tkrat.34be174a07a7f85e@s5r6.in-berlin.de> (raw)
In-Reply-To: <4798E664.2040405@redhat.com>

read_rom() obtained a fresh new fw_device.generation for each read
transaction.  Hence it was able to continue reading in the middle of the
ROM even if a bus reset happened.  However the device may have modified
the ROM during the reset.  We would end up with a corrupt fetched ROM
image then.

Although all of this is quite unlikely, it is not impossible.
Therefore we now restart reading the ROM if the bus generation changed.

Note, the memory barrier in read_rom() is still necessary according to
tests by Jarod Wilson, despite of the ->generation access being moved up
in the call chain.

Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
---

First posted on 2007-11-01.  Update:  Barrier stays.

 drivers/firewire/fw-device.c |   25 +++++++++++++++++--------
 1 file changed, 17 insertions(+), 8 deletions(-)

Index: linux-2.6.24/drivers/firewire/fw-device.c
===================================================================
--- linux-2.6.24.orig/drivers/firewire/fw-device.c
+++ linux-2.6.24/drivers/firewire/fw-device.c
@@ -389,12 +389,12 @@ complete_transaction(struct fw_card *car
 	complete(&callback_data->done);
 }
 
-static int read_rom(struct fw_device *device, int index, u32 * data)
+static int
+read_rom(struct fw_device *device, int generation, int index, u32 *data)
 {
 	struct read_quadlet_callback_data callback_data;
 	struct fw_transaction t;
 	u64 offset;
-	int generation = device->generation;
 
 	/* device->node_id, accessed below, must not be older than generation */
 	smp_rmb();
@@ -413,7 +413,14 @@ static int read_rom(struct fw_device *de
 	return callback_data.rcode;
 }
 
-static int read_bus_info_block(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
+ * generation changes under us, read_bus_info_block will fail and get retried.
+ * It's better to start all over in this case because the node from which we
+ * are reading the ROM may have changed the ROM during the reset.
+ */
+static int read_bus_info_block(struct fw_device *device, int generation)
 {
 	static u32 rom[256];
 	u32 stack[16], sp, key;
@@ -423,7 +430,7 @@ static int read_bus_info_block(struct fw
 
 	/* First read the bus info block. */
 	for (i = 0; i < 5; i++) {
-		if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE)
+		if (read_rom(device, generation, i, &rom[i]) != RCODE_COMPLETE)
 			return -1;
 		/*
 		 * As per IEEE1212 7.2, during power-up, devices can
@@ -458,7 +465,8 @@ static int read_bus_info_block(struct fw
 			device->max_speed = device->card->link_speed;
 
 		while (device->max_speed > SCODE_100) {
-			if (read_rom(device, 0, &dummy) == RCODE_COMPLETE)
+			if (read_rom(device, generation, 0, &dummy) ==
+			    RCODE_COMPLETE)
 				break;
 			device->max_speed--;
 		}
@@ -491,7 +499,7 @@ static int read_bus_info_block(struct fw
 			return -1;
 
 		/* Read header quadlet for the block to get the length. */
-		if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE)
+		if (read_rom(device, generation, i, &rom[i]) != RCODE_COMPLETE)
 			return -1;
 		end = i + (rom[i] >> 16) + 1;
 		i++;
@@ -510,7 +518,8 @@ static int read_bus_info_block(struct fw
 		 * it references another block, and push it in that case.
 		 */
 		while (i < end) {
-			if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE)
+			if (read_rom(device, generation, i, &rom[i]) !=
+			    RCODE_COMPLETE)
 				return -1;
 			if ((key >> 30) == 3 && (rom[i] >> 30) > 1 &&
 			    sp < ARRAY_SIZE(stack))
@@ -657,7 +666,7 @@ static void fw_device_init(struct work_s
 	 * device.
 	 */
 
-	if (read_bus_info_block(device) < 0) {
+	if (read_bus_info_block(device, device->generation) < 0) {
 		if (device->config_rom_retries < MAX_RETRIES) {
 			device->config_rom_retries++;
 			schedule_delayed_work(&device->work, RETRY_DELAY);

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


  reply	other threads:[~2008-01-25 16:54 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-11-01  1:49 [PATCH] firewire: fw-core: enforce write order when updating fw_device.generation Stefan Richter
2007-11-01  1:50 ` [PATCH] firewire: fw-core: react on bus resets while the config ROM is being fetched Stefan Richter
2007-11-01  1:51   ` [PATCH] firewire: fw-sbp2: enforce read order of device generation and node ID Stefan Richter
2007-11-01  3:53 ` [PATCH] firewire: fw-core: enforce write order when updating fw_device.generation Nick Piggin
2007-11-01  9:51   ` dealing with barriers (was Re: [PATCH] firewire: fw-core: enforce write order when updating fw_device.generation) Stefan Richter
2007-11-01 11:32     ` Nick Piggin
2008-01-24  0:52     ` [PATCH 0/4] firewire: order of memory accesses (bus generation vs. node ID) Stefan Richter
2008-01-24  0:53       ` [PATCH 1/4] firewire: fw-sbp2: use device generation, not card generation Stefan Richter
2008-01-24 16:04         ` Jarod Wilson
2008-01-24  0:53       ` [PATCH 2/4] firewire: fw-cdev: " Stefan Richter
2008-01-24 16:05         ` Jarod Wilson
2008-01-24  0:54       ` [PATCH 3/4] firewire: enforce access order between generation and node ID Stefan Richter
2008-01-24  4:55         ` Nick Piggin
2008-01-24 16:06         ` Jarod Wilson
2008-01-25 16:35           ` Stefan Richter
2008-01-25 17:57             ` Stefan Richter
     [not found]               ` <59ad55d30801251024j6ff43953tb86aaa52fdea5ec9@mail.gmail.com>
2008-01-25 22:25                 ` Stefan Richter
2008-01-24  0:55       ` [PATCH 4/4] firewire: fw-core: react on bus resets while the config ROM is being fetched Stefan Richter
2008-01-24 16:11         ` Jarod Wilson
2008-01-24 19:26           ` Jarod Wilson
2008-01-25 16:53             ` Stefan Richter [this message]
2008-01-25 17:16               ` [PATCH 4/4 update] " Jarod Wilson
2008-01-25 17:21                 ` Stefan Richter

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=tkrat.34be174a07a7f85e@s5r6.in-berlin.de \
    --to=stefanr@s5r6.in-berlin.de \
    --cc=jwilson@redhat.com \
    --cc=krh@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux1394-devel@lists.sourceforge.net \
    --cc=nickpiggin@yahoo.com.au \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

Powered by JetHome