rpms/kernel/devel linux-2.6-firewire-config-rom-read-fixup.patch, 1.1, 1.2

Jarod Wilson (jwilson) fedora-extras-commits at redhat.com
Thu Jan 24 22:09:00 UTC 2008


Author: jwilson

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

Modified Files:
	linux-2.6-firewire-config-rom-read-fixup.patch 
Log Message:
Updated firewire config rom read fixup patch

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

Index: linux-2.6-firewire-config-rom-read-fixup.patch
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/linux-2.6-firewire-config-rom-read-fixup.patch,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- linux-2.6-firewire-config-rom-read-fixup.patch	23 Jan 2008 20:08:21 -0000	1.1
+++ linux-2.6-firewire-config-rom-read-fixup.patch	24 Jan 2008 22:08:25 -0000	1.2
@@ -1,48 +1,159 @@
-diff -Naurp linux-2.6.23.noarch/drivers/firewire.old/fw-device.c linux-2.6.23.noarch/drivers/firewire/fw-device.c
---- linux-2.6.23.noarch/drivers/firewire.old/fw-device.c	2008-01-23 14:35:53.000000000 -0500
-+++ linux-2.6.23.noarch/drivers/firewire/fw-device.c	2008-01-23 14:48:55.000000000 -0500
-@@ -404,6 +404,10 @@ static int read_rom(struct fw_device *de
+diff -Naurp linux-2.6.23.noarch/drivers/firewire.orig/fw-cdev.c linux-2.6.23.noarch/drivers/firewire/fw-cdev.c
+--- linux-2.6.23.noarch/drivers/firewire.orig/fw-cdev.c	2008-01-24 14:36:40.000000000 -0500
++++ linux-2.6.23.noarch/drivers/firewire/fw-cdev.c	2008-01-24 14:39:36.000000000 -0500
+@@ -206,12 +206,13 @@ fill_bus_reset_event(struct fw_cdev_even
+ 
+ 	event->closure	     = client->bus_reset_closure;
+ 	event->type          = FW_CDEV_EVENT_BUS_RESET;
++	event->generation    = client->device->generation;
++	smp_rmb();           /* node_id must not be older than generation */
+ 	event->node_id       = client->device->node_id;
+ 	event->local_node_id = card->local_node->node_id;
+ 	event->bm_node_id    = 0; /* FIXME: We don't track the BM. */
+ 	event->irm_node_id   = card->irm_node->node_id;
+ 	event->root_node_id  = card->root_node->node_id;
+-	event->generation    = card->generation;
+ }
+ 
+ static void
+diff -Naurp linux-2.6.23.noarch/drivers/firewire.orig/fw-device.c linux-2.6.23.noarch/drivers/firewire/fw-device.c
+--- linux-2.6.23.noarch/drivers/firewire.orig/fw-device.c	2008-01-24 14:36:40.000000000 -0500
++++ linux-2.6.23.noarch/drivers/firewire/fw-device.c	2008-01-24 14:44:38.000000000 -0500
+@@ -182,9 +182,13 @@ static void fw_device_release(struct dev
+ 
+ int fw_device_enable_phys_dma(struct fw_device *device)
+ {
++	int generation = device->generation;
++
++	/* device->node_id, accessed below, must not be older than generation */
++	smp_rmb();
+ 	return device->card->driver->enable_phys_dma(device->card,
+ 						     device->node_id,
+-						     device->generation);
++						     generation);
+ }
+ EXPORT_SYMBOL(fw_device_enable_phys_dma);
+ 
+@@ -384,17 +388,21 @@ 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;
+ 
++	/* device->node_id, accessed below, must not be older than generation */
++	smp_rmb();
++
+ 	init_completion(&callback_data.done);
+ 
+ 	offset = 0xfffff0000400ULL + index * 4;
+ 	fw_send_request(device->card, &t, TCODE_READ_QUADLET_REQUEST,
+-			device->node_id, device->generation, device->max_speed,
++			device->node_id, generation, device->max_speed,
+ 			offset, NULL, 4, complete_transaction, &callback_data);
+ 
+ 	wait_for_completion(&callback_data.done);
+@@ -404,7 +412,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 device's config ROM.
++ * 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)
++static int read_bus_info_block(struct fw_device *device, int generation)
  {
  	static u32 rom[256];
-@@ -801,6 +805,7 @@ void fw_node_event(struct fw_card *card,
+ 	u32 stack[16], sp, key;
+@@ -414,7 +429,7 @@ static int read_bus_info_block(struct fw
+ 
+ 	/* First read the bus info block. */
+ 	for (i = 0; i < 5; i++) {
+-		if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE)
++		if (read_rom(device, generation, i, &rom[i]) != RCODE_COMPLETE)
+ 			return -1;
+ 		/*
+ 		 * As per IEEE1212 7.2, during power-up, devices can
+@@ -449,7 +464,8 @@ static int read_bus_info_block(struct fw
+ 			device->max_speed = device->card->link_speed;
+ 
+ 		while (device->max_speed > SCODE_100) {
+-			if (read_rom(device, 0, &dummy) == RCODE_COMPLETE)
++			if (read_rom(device, generation, 0, &dummy) ==
++			    RCODE_COMPLETE)
+ 				break;
+ 			device->max_speed--;
+ 		}
+@@ -482,7 +498,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++;
+@@ -501,7 +517,8 @@ static int read_bus_info_block(struct fw
+ 		 * it references another block, and push it in that case.
+ 		 */
+ 		while (i < end) {
+-			if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE)
++			if (read_rom(device, generation, i, &rom[i]) !=
++			    RCODE_COMPLETE)
+ 				return -1;
+ 			if ((key >> 30) == 3 && (rom[i] >> 30) > 1 &&
+ 			    sp < ARRAY_SIZE(stack))
+@@ -648,7 +665,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);
+@@ -801,6 +818,7 @@ void fw_node_event(struct fw_card *card,
  
  		device = node->data;
  		device->node_id = node->node_id;
-+		smp_wmb();
++		smp_wmb();  /* update node_id before generation */
  		device->generation = card->generation;
  		if (atomic_read(&device->state) == FW_DEVICE_RUNNING) {
  			PREPARE_DELAYED_WORK(&device->work, fw_device_update);
-diff -Naurp linux-2.6.23.noarch/drivers/firewire.old/fw-ohci.c linux-2.6.23.noarch/drivers/firewire/fw-ohci.c
---- linux-2.6.23.noarch/drivers/firewire.old/fw-ohci.c	2008-01-23 14:36:14.000000000 -0500
-+++ linux-2.6.23.noarch/drivers/firewire/fw-ohci.c	2008-01-23 14:48:55.000000000 -0500
-@@ -1023,14 +1023,14 @@ static void bus_reset_tasklet(unsigned l
- 
- 	self_id_count = (reg_read(ohci, OHCI1394_SelfIDCount) >> 3) & 0x3ff;
- 	generation = (le32_to_cpu(ohci->self_id_cpu[0]) >> 16) & 0xff;
--	rmb();
-+	smp_rmb();
+diff -Naurp linux-2.6.23.noarch/drivers/firewire.orig/fw-device.h linux-2.6.23.noarch/drivers/firewire/fw-device.h
+--- linux-2.6.23.noarch/drivers/firewire.orig/fw-device.h	2008-01-24 14:36:40.000000000 -0500
++++ linux-2.6.23.noarch/drivers/firewire/fw-device.h	2008-01-24 14:39:36.000000000 -0500
+@@ -35,6 +35,18 @@ struct fw_attribute_group {
+ 	struct attribute *attrs[11];
+ };
  
- 	for (i = 1, j = 0; j < self_id_count; i += 2, j++) {
- 		if (ohci->self_id_cpu[i] != ~ohci->self_id_cpu[i + 1])
- 			fw_error("inconsistent self IDs\n");
- 		ohci->self_id_buffer[j] = le32_to_cpu(ohci->self_id_cpu[i]);
- 	}
--	rmb();
-+	smp_rmb();
- 
- 	/*
- 	 * Check the consistency of the self IDs we just read.  The
-diff -Naurp linux-2.6.23.noarch/drivers/firewire.old/fw-sbp2.c linux-2.6.23.noarch/drivers/firewire/fw-sbp2.c
---- linux-2.6.23.noarch/drivers/firewire.old/fw-sbp2.c	2008-01-23 14:36:14.000000000 -0500
-+++ linux-2.6.23.noarch/drivers/firewire/fw-sbp2.c	2008-01-23 14:48:55.000000000 -0500
++/*
++ * Note, fw_device.generation always has to be read before fw_device.node_id.
++ * Use SMP memory barriers to ensure this.  Otherwise requests will be sent
++ * to an outdated node_id if the generation was updated in the meantime due
++ * to a bus reset.
++ *
++ * Likewise, fw-core will take care to update .node_id before .generation so
++ * that whenever fw_device.generation is current WRT the actual bus generation,
++ * fw_device.node_id is guaranteed to be current too.
++ *
++ * The same applies to fw_device.card->node_id vs. fw_device.generation.
++ */
+ struct fw_device {
+ 	atomic_t state;
+ 	struct fw_node *node;
+diff -Naurp linux-2.6.23.noarch/drivers/firewire.orig/fw-sbp2.c linux-2.6.23.noarch/drivers/firewire/fw-sbp2.c
+--- linux-2.6.23.noarch/drivers/firewire.orig/fw-sbp2.c	2008-01-24 14:36:58.000000000 -0500
++++ linux-2.6.23.noarch/drivers/firewire/fw-sbp2.c	2008-01-24 14:39:36.000000000 -0500
 @@ -678,9 +678,10 @@ static void sbp2_login(struct work_struc
  	struct sbp2_login_response response;
  	int generation, node_id, local_node_id;
@@ -51,7 +162,7 @@
 -	node_id       = device->node->node_id;
 -	local_node_id = device->card->local_node->node_id;
 +	generation    = device->generation;
-+	smp_rmb();
++	smp_rmb();    /* node_id must not be older than generation */
 +	node_id       = device->node_id;
 +	local_node_id = device->card->node_id;
  
@@ -65,32 +176,24 @@
 -	node_id       = device->node->node_id;
 -	local_node_id = device->card->local_node->node_id;
 +	generation    = device->generation;
-+	smp_rmb();
++	smp_rmb();    /* node_id must not be older than generation */
 +	node_id       = device->node_id;
 +	local_node_id = device->card->node_id;
  
  	if (sbp2_send_management_orb(lu, node_id, generation,
  				     SBP2_RECONNECT_REQUEST,
-diff -Naurp linux-2.6.23.noarch/drivers/firewire.old/fw-topology.c linux-2.6.23.noarch/drivers/firewire/fw-topology.c
---- linux-2.6.23.noarch/drivers/firewire.old/fw-topology.c	2008-01-23 14:35:53.000000000 -0500
-+++ linux-2.6.23.noarch/drivers/firewire/fw-topology.c	2008-01-23 14:48:55.000000000 -0500
-@@ -518,6 +518,7 @@ fw_core_handle_bus_reset(struct fw_card 
+diff -Naurp linux-2.6.23.noarch/drivers/firewire.orig/fw-topology.c linux-2.6.23.noarch/drivers/firewire/fw-topology.c
+--- linux-2.6.23.noarch/drivers/firewire.orig/fw-topology.c	2008-01-24 14:36:40.000000000 -0500
++++ linux-2.6.23.noarch/drivers/firewire/fw-topology.c	2008-01-24 14:39:36.000000000 -0500
+@@ -518,6 +518,11 @@ fw_core_handle_bus_reset(struct fw_card 
  		card->bm_retries = 0;
  
  	card->node_id = node_id;
++	/*
++	 * Update node_id before generation to prevent anybody from using
++	 * a stale node_id together with a current generation.
++	 */
 +	smp_wmb();
  	card->generation = generation;
  	card->reset_jiffies = jiffies;
  	schedule_delayed_work(&card->work, 0);
-diff -Naurp linux-2.6.23.noarch/drivers/firewire.old/fw-transaction.c linux-2.6.23.noarch/drivers/firewire/fw-transaction.c
---- linux-2.6.23.noarch/drivers/firewire.old/fw-transaction.c	2008-01-23 14:36:14.000000000 -0500
-+++ linux-2.6.23.noarch/drivers/firewire/fw-transaction.c	2008-01-23 14:48:55.000000000 -0500
-@@ -153,7 +153,7 @@ fw_fill_request(struct fw_packet *packet
- 	int ext_tcode;
- 
- 	if (tcode > 0x10) {
--		ext_tcode = tcode - 0x10;
-+		ext_tcode = tcode & ~0x10;
- 		tcode = TCODE_LOCK_REQUEST;
- 	} else
- 		ext_tcode = 0;




More information about the fedora-extras-commits mailing list