rpms/kernel/devel kernel.spec, 1.450, 1.451 linux-2.6-firewire-git-pending.patch, 1.5, 1.6

Jarod Wilson (jwilson) fedora-extras-commits at redhat.com
Mon Feb 25 22:33:37 UTC 2008


Author: jwilson

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

Modified Files:
	kernel.spec linux-2.6-firewire-git-pending.patch 
Log Message:
* Mon Feb 25 2008 Jarod Wilson <jwilson at redhat.com>
- firewire: fix crashes in workqueue jobs
- firewire: endian fixes



Index: kernel.spec
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/kernel.spec,v
retrieving revision 1.450
retrieving revision 1.451
diff -u -r1.450 -r1.451
--- kernel.spec	25 Feb 2008 05:35:20 -0000	1.450
+++ kernel.spec	25 Feb 2008 22:32:56 -0000	1.451
@@ -1737,6 +1737,10 @@
 %kernel_variant_files -a /%{image_install_path}/xen*-%{KVERREL} -e /etc/ld.so.conf.d/kernelcap-%{KVERREL}.conf %{with_xen} xen
 
 %changelog
+* Mon Feb 25 2008 Jarod Wilson <jwilson at redhat.com>
+- firewire: fix crashes in workqueue jobs
+- firewire: endian fixes
+
 * Mon Feb 25 2008 Dave Jones <davej at redhat.com>
 - 2.6.25-rc3
 

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

Index: linux-2.6-firewire-git-pending.patch
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/linux-2.6-firewire-git-pending.patch,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- linux-2.6-firewire-git-pending.patch	21 Feb 2008 04:40:21 -0000	1.5
+++ linux-2.6-firewire-git-pending.patch	25 Feb 2008 22:32:56 -0000	1.6
@@ -3,3 +3,830 @@
 # tree, which we think we're going to want...
 #
 
+The generation of incoming requests was filled in in wrong byte order on
+machines with big endian CPU.
+
+Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
+Cc: sparclinux at vger.kernel.org
+Cc: linuxppc-dev at ozlabs.org
+---
+
+This patch is a shot in the dark, based on a warning when building with
+C=1 CHECKFLAGS="-D__CHECK_ENDIAN__".  Is it really a fix, or was the
+previous code accidentally correct?
+
+This needs to be tested on different big endian PCs, if possible with
+the Apple Uninorth FireWire controller and other types of controllers.
+One test which involves ohci->request_generation is simply with an SBP-2
+device (harddisk, CD-ROM...).  Does SBP-2 login etc. work?
+
+If possible, also test whether the device remains accessible after
+forcing a bus reset, e.g. by "echo br short > firecontrol".  You need
+the easy to build utility firecontrol and a libraw1394 with "juju"
+backend.  See wiki.linux1394.org for directions.
+
+
+ drivers/firewire/fw-ohci.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+Index: linux/drivers/firewire/fw-ohci.c
+===================================================================
+--- linux.orig/drivers/firewire/fw-ohci.c
++++ linux/drivers/firewire/fw-ohci.c
+@@ -375,7 +375,7 @@ static __le32 *handle_ar_packet(struct a
+ 	 */
+ 
+ 	if (p.ack + 16 == 0x09)
+-		ohci->request_generation = (buffer[2] >> 16) & 0xff;
++		ohci->request_generation = (p.header[2] >> 16) & 0xff;
+ 	else if (ctx == &ohci->ar_request_ctx)
+ 		fw_core_handle_request(&ohci->card, &p);
+ 	else
+
+-- 
+Stefan Richter
+-=====-==--- --=- =-===
+http://arcgraph.de/sr/
+
+
+Kills warnings from 'make C=1 CHECKFLAGS="-D__CHECK_ENDIAN__" modules':
+
+drivers/firewire/fw-transaction.c:771:10: warning: incorrect type in assignment (different base types)
+drivers/firewire/fw-transaction.c:771:10:    expected unsigned int [unsigned] [usertype] <noident>
+drivers/firewire/fw-transaction.c:771:10:    got restricted unsigned int [usertype] <noident>
+drivers/firewire/fw-transaction.h:93:10: warning: incorrect type in assignment (different base types)
+drivers/firewire/fw-transaction.h:93:10:    expected unsigned int [unsigned] [usertype] <noident>
+drivers/firewire/fw-transaction.h:93:10:    got restricted unsigned int [usertype] <noident>
+drivers/firewire/fw-ohci.c:1490:8: warning: restricted degrades to integer
+drivers/firewire/fw-ohci.c:1490:35: warning: restricted degrades to integer
+drivers/firewire/fw-ohci.c:1516:5: warning: cast to restricted type
+
+Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
+Cc: sparclinux at vger.kernel.org
+Cc: linuxppc-dev at ozlabs.org
+---
+ drivers/firewire/fw-ohci.c        |    4 ++--
+ drivers/firewire/fw-transaction.c |    2 +-
+ drivers/firewire/fw-transaction.h |    6 +++---
+ 3 files changed, 6 insertions(+), 6 deletions(-)
+
+Index: linux/drivers/firewire/fw-ohci.c
+===================================================================
+--- linux.orig/drivers/firewire/fw-ohci.c
++++ linux/drivers/firewire/fw-ohci.c
+@@ -1487,7 +1487,7 @@ static int handle_ir_dualbuffer_packet(s
+ 	void *p, *end;
+ 	int i;
+ 
+-	if (db->first_res_count > 0 && db->second_res_count > 0) {
++	if (db->first_res_count != 0 && db->second_res_count != 0) {
+ 		if (ctx->excess_bytes <= le16_to_cpu(db->second_req_count)) {
+ 			/* This descriptor isn't done yet, stop iteration. */
+ 			return 0;
+@@ -1513,7 +1513,7 @@ static int handle_ir_dualbuffer_packet(s
+ 		memcpy(ctx->header + i + 4, p + 8, ctx->base.header_size - 4);
+ 		i += ctx->base.header_size;
+ 		ctx->excess_bytes +=
+-			(le32_to_cpu(*(u32 *)(p + 4)) >> 16) & 0xffff;
++			(le32_to_cpu(*(__le32 *)(p + 4)) >> 16) & 0xffff;
+ 		p += ctx->base.header_size + 4;
+ 	}
+ 	ctx->header_length = i;
+Index: linux/drivers/firewire/fw-transaction.c
+===================================================================
+--- linux.orig/drivers/firewire/fw-transaction.c
++++ linux/drivers/firewire/fw-transaction.c
+@@ -751,7 +751,7 @@ handle_topology_map(struct fw_card *card
+ 		    void *payload, size_t length, void *callback_data)
+ {
+ 	int i, start, end;
+-	u32 *map;
++	__be32 *map;
+ 
+ 	if (!TCODE_IS_READ_REQUEST(tcode)) {
+ 		fw_send_response(card, request, RCODE_TYPE_ERROR);
+Index: linux/drivers/firewire/fw-transaction.h
+===================================================================
+--- linux.orig/drivers/firewire/fw-transaction.h
++++ linux/drivers/firewire/fw-transaction.h
+@@ -85,12 +85,12 @@
+ static inline void
+ fw_memcpy_from_be32(void *_dst, void *_src, size_t size)
+ {
+-	u32 *dst = _dst;
+-	u32 *src = _src;
++	u32    *dst = _dst;
++	__be32 *src = _src;
+ 	int i;
+ 
+ 	for (i = 0; i < size / 4; i++)
+-		dst[i] = cpu_to_be32(src[i]);
++		dst[i] = be32_to_cpu(src[i]);
+ }
+ 
+ static inline void
+
+-- 
+Stefan Richter
+-=====-==--- --=- =-===
+http://arcgraph.de/sr/
+
+
+The bus management workqueue job was in danger to dereference NULL
+pointers.  Also, after having temporarily lifted card->lock, a few node
+pointers and a device pointer may have become invalid.
+
+Add NULL pointer checks and get the necessary references.  Also, move
+card->local_node out of fw_card_bm_work's sight during shutdown of the
+card.
+
+Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
+---
+ drivers/firewire/fw-card.c     |   51 ++++++++++++++++++++++-----------
+ drivers/firewire/fw-topology.c |    1 
+ 2 files changed, 35 insertions(+), 17 deletions(-)
+
+Index: linux/drivers/firewire/fw-card.c
+===================================================================
+--- linux.orig/drivers/firewire/fw-card.c
++++ linux/drivers/firewire/fw-card.c
+@@ -214,17 +214,29 @@ static void
+ fw_card_bm_work(struct work_struct *work)
+ {
+ 	struct fw_card *card = container_of(work, struct fw_card, work.work);
+-	struct fw_device *root;
++	struct fw_device *root_device;
++	struct fw_node *root_node, *local_node;
+ 	struct bm_data bmd;
+ 	unsigned long flags;
+ 	int root_id, new_root_id, irm_id, gap_count, generation, grace;
+ 	int do_reset = 0;
+ 
+ 	spin_lock_irqsave(&card->lock, flags);
++	local_node = card->local_node;
++	root_node  = card->root_node;
++
++	if (local_node == NULL) {
++		spin_unlock_irqrestore(&card->lock, flags);
++		return;
++	}
++	fw_node_get(local_node);
++	fw_node_get(root_node);
+ 
+ 	generation = card->generation;
+-	root = card->root_node->data;
+-	root_id = card->root_node->node_id;
++	root_device = root_node->data;
++	if (root_device)
++		fw_device_get(root_device);
++	root_id = root_node->node_id;
+ 	grace = time_after(jiffies, card->reset_jiffies + DIV_ROUND_UP(HZ, 10));
+ 
+ 	if (card->bm_generation + 1 == generation ||
+@@ -243,14 +255,14 @@ fw_card_bm_work(struct work_struct *work
+ 
+ 		irm_id = card->irm_node->node_id;
+ 		if (!card->irm_node->link_on) {
+-			new_root_id = card->local_node->node_id;
++			new_root_id = local_node->node_id;
+ 			fw_notify("IRM has link off, making local node (%02x) root.\n",
+ 				  new_root_id);
+ 			goto pick_me;
+ 		}
+ 
+ 		bmd.lock.arg = cpu_to_be32(0x3f);
+-		bmd.lock.data = cpu_to_be32(card->local_node->node_id);
++		bmd.lock.data = cpu_to_be32(local_node->node_id);
+ 
+ 		spin_unlock_irqrestore(&card->lock, flags);
+ 
+@@ -267,12 +279,12 @@ fw_card_bm_work(struct work_struct *work
+ 			 * Another bus reset happened. Just return,
+ 			 * the BM work has been rescheduled.
+ 			 */
+-			return;
++			goto out;
+ 		}
+ 
+ 		if (bmd.rcode == RCODE_COMPLETE && bmd.old != 0x3f)
+ 			/* Somebody else is BM, let them do the work. */
+-			return;
++			goto out;
+ 
+ 		spin_lock_irqsave(&card->lock, flags);
+ 		if (bmd.rcode != RCODE_COMPLETE) {
+@@ -282,7 +294,7 @@ fw_card_bm_work(struct work_struct *work
+ 			 * do a bus reset and pick the local node as
+ 			 * root, and thus, IRM.
+ 			 */
+-			new_root_id = card->local_node->node_id;
++			new_root_id = local_node->node_id;
+ 			fw_notify("BM lock failed, making local node (%02x) root.\n",
+ 				  new_root_id);
+ 			goto pick_me;
+@@ -295,7 +307,7 @@ fw_card_bm_work(struct work_struct *work
+ 		 */
+ 		spin_unlock_irqrestore(&card->lock, flags);
+ 		schedule_delayed_work(&card->work, DIV_ROUND_UP(HZ, 10));
+-		return;
++		goto out;
+ 	}
+ 
+ 	/*
+@@ -305,20 +317,20 @@ fw_card_bm_work(struct work_struct *work
+ 	 */
+ 	card->bm_generation = generation;
+ 
+-	if (root == NULL) {
++	if (root_device == NULL) {
+ 		/*
+ 		 * Either link_on is false, or we failed to read the
+ 		 * config rom.  In either case, pick another root.
+ 		 */
+-		new_root_id = card->local_node->node_id;
+-	} else if (atomic_read(&root->state) != FW_DEVICE_RUNNING) {
++		new_root_id = local_node->node_id;
++	} else if (atomic_read(&root_device->state) != FW_DEVICE_RUNNING) {
+ 		/*
+ 		 * If we haven't probed this device yet, bail out now
+ 		 * and let's try again once that's done.
+ 		 */
+ 		spin_unlock_irqrestore(&card->lock, flags);
+-		return;
+-	} else if (root->config_rom[2] & BIB_CMC) {
++		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 +344,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;
+ 	}
+ 
+  pick_me:
+@@ -341,8 +353,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;
+ 
+@@ -364,6 +376,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:
++	if (root_device)
++		fw_device_put(root_device);
++	fw_node_put(root_node);
++	fw_node_put(local_node);
+ }
+ 
+ static void
+Index: linux/drivers/firewire/fw-topology.c
+===================================================================
+--- linux.orig/drivers/firewire/fw-topology.c
++++ linux/drivers/firewire/fw-topology.c
+@@ -383,6 +383,7 @@ void fw_destroy_nodes(struct fw_card *ca
+ 	card->color++;
+ 	if (card->local_node != NULL)
+ 		for_each_fw_node(card, card->local_node, report_lost_node);
++	card->local_node = NULL;
+ 	spin_unlock_irqrestore(&card->lock, flags);
+ }
+ 
+
+-- 
+Stefan Richter
+-=====-==--- --=- ==---
+http://arcgraph.de/sr/
+
+
+"modprobe firewire-ohci; sleep .1; modprobe -r firewire-ohci" used to
+result in crashes like this:
+
+    BUG: unable to handle kernel paging request at ffffffff8807b455
+    IP: [<ffffffff8807b455>]
+    PGD 203067 PUD 207063 PMD 7c170067 PTE 0
+    Oops: 0010 [1] PREEMPT SMP 
+    CPU 0 
+    Modules linked in: i915 drm cpufreq_ondemand acpi_cpufreq freq_table applesmc input_polldev led_class coretemp hwmon eeprom snd_seq_oss snd_seq_midi_event snd_seq snd_seq_device snd_pcm_oss snd_mixer_oss button thermal processor sg snd_hda_intel snd_pcm snd_timer snd snd_page_alloc sky2 i2c_i801 rtc [last unloaded: crc_itu_t]
+    Pid: 9, comm: events/0 Not tainted 2.6.25-rc2 #3
+    RIP: 0010:[<ffffffff8807b455>]  [<ffffffff8807b455>]
+    RSP: 0018:ffff81007dcdde88  EFLAGS: 00010246
+    RAX: ffff81007dc95040 RBX: ffff81007dee5390 RCX: 0000000000005e13
+    RDX: 0000000000008c8b RSI: 0000000000000001 RDI: ffff81007dee5388
+    RBP: ffff81007dc5eb40 R08: 0000000000000002 R09: ffffffff8022d05c
+    R10: ffffffff8023b34c R11: ffffffff8041a353 R12: ffff81007dee5388
+    R13: ffffffff8807b455 R14: ffffffff80593bc0 R15: 0000000000000000
+    FS:  0000000000000000(0000) GS:ffffffff8055a000(0000) knlGS:0000000000000000
+    CS:  0010 DS: 0018 ES: 0018 CR0: 000000008005003b
+    CR2: ffffffff8807b455 CR3: 0000000000201000 CR4: 00000000000006e0
+    DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+    DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
+    Process events/0 (pid: 9, threadinfo ffff81007dcdc000, task ffff81007dc95040)
+    Stack:  ffffffff8023b396 ffffffff88082524 0000000000000000 ffffffff8807d9ae
+    ffff81007dc5eb40 ffff81007dc9dce0 ffff81007dc5eb40 ffff81007dc5eb80
+    ffff81007dc9dce0 ffffffffffffffff ffffffff8023be87 0000000000000000
+    Call Trace:
+    [<ffffffff8023b396>] ? run_workqueue+0xdf/0x1df
+    [<ffffffff8023be87>] ? worker_thread+0xd8/0xe3
+    [<ffffffff8023e917>] ? autoremove_wake_function+0x0/0x2e
+    [<ffffffff8023bdaf>] ? worker_thread+0x0/0xe3
+    [<ffffffff8023e813>] ? kthread+0x47/0x74
+    [<ffffffff804198e0>] ? trace_hardirqs_on_thunk+0x35/0x3a
+    [<ffffffff8020c008>] ? child_rip+0xa/0x12
+    [<ffffffff8020b6e3>] ? restore_args+0x0/0x3d
+    [<ffffffff8023e68a>] ? kthreadd+0x14c/0x171
+    [<ffffffff8023e68a>] ? kthreadd+0x14c/0x171
+    [<ffffffff8023e7cc>] ? kthread+0x0/0x74
+    [<ffffffff8020bffe>] ? child_rip+0x0/0x12
+
+
+    Code:  Bad RIP value.
+    RIP  [<ffffffff8807b455>]
+    RSP <ffff81007dcdde88>
+    CR2: ffffffff8807b455
+    ---[ end trace c7366c6657fe5bed ]---
+
+Note that this crash happened _after_ firewire-core was unloaded.  The
+shared workqueue tried to run firewire-core's device initialization jobs
+or similar jobs.
+
+The fix makes sure that firewire-ohci and hence firewire-core is not
+unloaded before all device shutdown jobs have been completed.  This is
+determined by the count of device initializations minus device releases.
+
+Also skip useless retries in the node initialization job if the node is
+to be shut down.
+
+Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
+---
+ drivers/firewire/fw-card.c        |   10 +++++++++-
+ drivers/firewire/fw-device.c      |   21 ++++++---------------
+ drivers/firewire/fw-device.h      |   16 ++++++++++++++--
+ drivers/firewire/fw-sbp2.c        |    4 ++++
+ drivers/firewire/fw-transaction.h |    2 ++
+ 5 files changed, 35 insertions(+), 18 deletions(-)
+
+Index: linux/drivers/firewire/fw-card.c
+===================================================================
+--- linux.orig/drivers/firewire/fw-card.c
++++ linux/drivers/firewire/fw-card.c
+@@ -18,6 +18,7 @@
+ 
+ #include <linux/module.h>
+ #include <linux/errno.h>
++#include <linux/delay.h>
+ #include <linux/device.h>
+ #include <linux/mutex.h>
+ #include <linux/crc-itu-t.h>
+@@ -398,6 +399,7 @@ fw_card_initialize(struct fw_card *card,
+ 	static atomic_t index = ATOMIC_INIT(-1);
+ 
+ 	kref_init(&card->kref);
++	atomic_set(&card->device_count, 0);
+ 	card->index = atomic_inc_return(&index);
+ 	card->driver = driver;
+ 	card->device = device;
+@@ -528,8 +530,14 @@ fw_core_remove_card(struct fw_card *card
+ 	card->driver = &dummy_driver;
+ 
+ 	fw_destroy_nodes(card);
+-	flush_scheduled_work();
++	/*
++	 * Wait for all device workqueue jobs to finish.  Otherwise the
++	 * firewire-core module could be unloaded before the jobs ran.
++	 */
++	while (atomic_read(&card->device_count) > 0)
++		msleep(100);
+ 
++	cancel_delayed_work_sync(&card->work);
+ 	fw_flush_transactions(card);
+ 	del_timer_sync(&card->flush_timer);
+ 
+Index: linux/drivers/firewire/fw-device.c
+===================================================================
+--- linux.orig/drivers/firewire/fw-device.c
++++ linux/drivers/firewire/fw-device.c
+@@ -150,21 +150,10 @@ struct bus_type fw_bus_type = {
+ };
+ EXPORT_SYMBOL(fw_bus_type);
+ 
+-struct fw_device *fw_device_get(struct fw_device *device)
+-{
+-	get_device(&device->device);
+-
+-	return device;
+-}
+-
+-void fw_device_put(struct fw_device *device)
+-{
+-	put_device(&device->device);
+-}
+-
+ static void fw_device_release(struct device *dev)
+ {
+ 	struct fw_device *device = fw_device(dev);
++	struct fw_card *card = device->card;
+ 	unsigned long flags;
+ 
+ 	/*
+@@ -176,9 +165,9 @@ static void fw_device_release(struct dev
+ 	spin_unlock_irqrestore(&device->card->lock, flags);
+ 
+ 	fw_node_put(device->node);
+-	fw_card_put(device->card);
+ 	kfree(device->config_rom);
+ 	kfree(device);
++	atomic_dec(&card->device_count);
+ }
+ 
+ int fw_device_enable_phys_dma(struct fw_device *device)
+@@ -668,7 +657,8 @@ static void fw_device_init(struct work_s
+ 	 */
+ 
+ 	if (read_bus_info_block(device, device->generation) < 0) {
+-		if (device->config_rom_retries < MAX_RETRIES) {
++		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);
+ 		} else {
+@@ -805,7 +795,8 @@ void fw_node_event(struct fw_card *card,
+ 		 */
+ 		device_initialize(&device->device);
+ 		atomic_set(&device->state, FW_DEVICE_INITIALIZING);
+-		device->card = fw_card_get(card);
++		atomic_inc(&card->device_count);
++		device->card = card;
+ 		device->node = fw_node_get(node);
+ 		device->node_id = node->node_id;
+ 		device->generation = card->generation;
+Index: linux/drivers/firewire/fw-sbp2.c
+===================================================================
+--- linux.orig/drivers/firewire/fw-sbp2.c
++++ linux/drivers/firewire/fw-sbp2.c
+@@ -757,6 +757,7 @@ 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);
+ 
+ 	/* prevent deadlocks */
+ 	sbp2_unblock(tgt);
+@@ -778,6 +779,7 @@ static void sbp2_release_target(struct k
+ 
+ 	put_device(&tgt->unit->device);
+ 	scsi_host_put(shost);
++	fw_device_put(device);
+ }
+ 
+ static struct workqueue_struct *sbp2_wq;
+@@ -1080,6 +1082,8 @@ static int sbp2_probe(struct device *dev
+ 	if (scsi_add_host(shost, &unit->device) < 0)
+ 		goto fail_shost_put;
+ 
++	fw_device_get(device);
++
+ 	/* Initialize to values that won't match anything in our table. */
+ 	firmware_revision = 0xff000000;
+ 	model = 0xff000000;
+Index: linux/drivers/firewire/fw-transaction.h
+===================================================================
+--- linux.orig/drivers/firewire/fw-transaction.h
++++ linux/drivers/firewire/fw-transaction.h
+@@ -26,6 +26,7 @@
+ #include <linux/fs.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/firewire-constants.h>
++#include <asm/atomic.h>
+ 
+ #define TCODE_IS_READ_REQUEST(tcode)	(((tcode) & ~1) == 4)
+ #define TCODE_IS_BLOCK_PACKET(tcode)	(((tcode) &  1) != 0)
+@@ -219,6 +220,7 @@ extern struct bus_type fw_bus_type;
+ struct fw_card {
+ 	const struct fw_card_driver *driver;
+ 	struct device *device;
++	atomic_t device_count;
+ 	struct kref kref;
+ 
+ 	int node_id;
+Index: linux/drivers/firewire/fw-device.h
+===================================================================
+--- linux.orig/drivers/firewire/fw-device.h
++++ linux/drivers/firewire/fw-device.h
+@@ -76,9 +76,21 @@ fw_device_is_shutdown(struct fw_device *
+ 	return atomic_read(&device->state) == FW_DEVICE_SHUTDOWN;
+ }
+ 
+-struct fw_device *fw_device_get(struct fw_device *device);
++static inline struct fw_device *
++fw_device_get(struct fw_device *device)
++{
++	get_device(&device->device);
++
++	return device;
++}
++
++static inline void
++fw_device_put(struct fw_device *device)
++{
++	put_device(&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);
+
+-- 
+Stefan Richter
+-=====-==--- --=- ==---
+http://arcgraph.de/sr/
+
+
+The card->kref became obsolete since patch "firewire: fix crash in
+automatic module unloading" added another counter of card users.
+
+Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
+---
+ drivers/firewire/fw-card.c        |   38 ------------------------------
+ drivers/firewire/fw-ohci.c        |    8 +++---
+ drivers/firewire/fw-transaction.h |    4 ---
+ 3 files changed, 4 insertions(+), 46 deletions(-)
+
+Index: linux/drivers/firewire/fw-card.c
+===================================================================
+--- linux.orig/drivers/firewire/fw-card.c
++++ linux/drivers/firewire/fw-card.c
+@@ -398,7 +398,6 @@ fw_card_initialize(struct fw_card *card,
+ {
+ 	static atomic_t index = ATOMIC_INIT(-1);
+ 
+-	kref_init(&card->kref);
+ 	atomic_set(&card->device_count, 0);
+ 	card->index = atomic_inc_return(&index);
+ 	card->driver = driver;
+@@ -429,12 +428,6 @@ fw_card_add(struct fw_card *card,
+ 	card->link_speed = link_speed;
+ 	card->guid = guid;
+ 
+-	/*
+-	 * 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);
+@@ -540,40 +533,9 @@ fw_core_remove_card(struct fw_card *card
+ 	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);
+ 
+-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/drivers/firewire/fw-ohci.c
+===================================================================
+--- linux.orig/drivers/firewire/fw-ohci.c
++++ linux/drivers/firewire/fw-ohci.c
+@@ -2059,7 +2059,7 @@ pci_probe(struct pci_dev *dev, const str
+ 	err = pci_enable_device(dev);
+ 	if (err) {
+ 		fw_error("Failed to enable OHCI hardware.\n");
+-		goto fail_put_card;
++		goto fail_free;
+ 	}
+ 
+ 	pci_set_master(dev);
+@@ -2151,8 +2151,8 @@ pci_probe(struct pci_dev *dev, const str
+ 	pci_release_region(dev, 0);
+  fail_disable:
+ 	pci_disable_device(dev);
+- fail_put_card:
+-	fw_card_put(&ohci->card);
++ fail_free:
++	kfree(&ohci->card);
+ 
+ 	return err;
+ }
+@@ -2180,7 +2180,7 @@ static void pci_remove(struct pci_dev *d
+ 	pci_iounmap(dev, ohci->registers);
+ 	pci_release_region(dev, 0);
+ 	pci_disable_device(dev);
+-	fw_card_put(&ohci->card);
++	kfree(&ohci->card);
+ 
+ 	fw_notify("Removed fw-ohci device.\n");
+ }
+Index: linux/drivers/firewire/fw-transaction.h
+===================================================================
+--- linux.orig/drivers/firewire/fw-transaction.h
++++ linux/drivers/firewire/fw-transaction.h
+@@ -221,7 +221,6 @@ struct fw_card {
+ 	const struct fw_card_driver *driver;
+ 	struct device *device;
+ 	atomic_t device_count;
+-	struct kref kref;
+ 
+ 	int node_id;
+ 	int generation;
+@@ -263,9 +262,6 @@ struct fw_card {
+ 	int bm_generation;
+ };
+ 
+-struct fw_card *fw_card_get(struct fw_card *card);
+-void fw_card_put(struct fw_card *card);
+-
+ /*
+  * The iso packet format allows for an immediate header/payload part
+  * stored in 'header' immediately after the packet info plus an
+
+-- 
+Stefan Richter
+-=====-==--- --=- ==---
+http://arcgraph.de/sr/
+
+
+The reference count of the unit dropped too low in an error path in
+sbp2_probe.  Fixed by moving the _get further up.
+
+Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
+---
+ drivers/firewire/fw-sbp2.c |    3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+Index: linux/drivers/firewire/fw-sbp2.c
+===================================================================
+--- linux.orig/drivers/firewire/fw-sbp2.c
++++ linux/drivers/firewire/fw-sbp2.c
+@@ -1083,6 +1083,7 @@ static int sbp2_probe(struct device *dev
+ 		goto fail_shost_put;
+ 
+ 	fw_device_get(device);
++	get_device(&unit->device);
+ 
+ 	/* Initialize to values that won't match anything in our table. */
+ 	firmware_revision = 0xff000000;
+@@ -1098,8 +1099,6 @@ static int sbp2_probe(struct device *dev
+ 
+ 	sbp2_init_workarounds(tgt, model, firmware_revision);
+ 
+-	get_device(&unit->device);
+-
+ 	/* Do the login in a workqueue so we can easily reschedule retries. */
+ 	list_for_each_entry(lu, &tgt->lu_list, link)
+ 		sbp2_queue_work(lu, 0);
+
+-- 
+Stefan Richter
+-=====-==--- --=- ==---
+http://arcgraph.de/sr/
+
+
+Add wrappers for getting and putting a unit.
+Remove some line breaks.
+
+Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
+---
+ drivers/firewire/fw-device.h |   27 +++++++++++++++++----------
+ drivers/firewire/fw-sbp2.c   |    4 ++--
+ 2 files changed, 19 insertions(+), 12 deletions(-)
+
+Index: linux/drivers/firewire/fw-device.h
+===================================================================
+--- linux.orig/drivers/firewire/fw-device.h
++++ linux/drivers/firewire/fw-device.h
+@@ -64,28 +64,24 @@ struct fw_device {
+ 	struct fw_attribute_group attribute_group;
+ };
+ 
+-static inline struct fw_device *
+-fw_device(struct device *dev)
++static inline struct fw_device *fw_device(struct device *dev)
+ {
+ 	return container_of(dev, struct fw_device, device);
+ }
+ 
+-static inline int
+-fw_device_is_shutdown(struct fw_device *device)
++static inline int fw_device_is_shutdown(struct fw_device *device)
+ {
+ 	return atomic_read(&device->state) == FW_DEVICE_SHUTDOWN;
+ }
+ 
+-static inline struct fw_device *
+-fw_device_get(struct fw_device *device)
++static inline struct fw_device *fw_device_get(struct fw_device *device)
+ {
+ 	get_device(&device->device);
+ 
+ 	return device;
+ }
+ 
+-static inline void
+-fw_device_put(struct fw_device *device)
++static inline void fw_device_put(struct fw_device *device)
+ {
+ 	put_device(&device->device);
+ }
+@@ -104,12 +100,23 @@ struct fw_unit {
+ 	struct fw_attribute_group attribute_group;
+ };
+ 
+-static inline struct fw_unit *
+-fw_unit(struct device *dev)
++static inline struct fw_unit *fw_unit(struct device *dev)
+ {
+ 	return container_of(dev, struct fw_unit, device);
+ }
+ 
++static inline struct fw_unit *fw_unit_get(struct fw_unit *unit)
++{
++	get_device(&unit->device);
++
++	return unit;
++}
++
++static inline void fw_unit_put(struct fw_unit *unit)
++{
++	put_device(&unit->device);
++}
++
+ #define CSR_OFFSET	0x40
+ #define CSR_LEAF	0x80
+ #define CSR_DIRECTORY	0xc0
+Index: linux/drivers/firewire/fw-sbp2.c
+===================================================================
+--- linux.orig/drivers/firewire/fw-sbp2.c
++++ linux/drivers/firewire/fw-sbp2.c
+@@ -777,7 +777,7 @@ static void sbp2_release_target(struct k
+ 	scsi_remove_host(shost);
+ 	fw_notify("released %s\n", tgt->bus_id);
+ 
+-	put_device(&tgt->unit->device);
++	fw_unit_put(tgt->unit);
+ 	scsi_host_put(shost);
+ 	fw_device_put(device);
+ }
+@@ -1083,7 +1083,7 @@ static int sbp2_probe(struct device *dev
+ 		goto fail_shost_put;
+ 
+ 	fw_device_get(device);
+-	get_device(&unit->device);
++	fw_unit_get(unit);
+ 
+ 	/* Initialize to values that won't match anything in our table. */
+ 	firmware_revision = 0xff000000;
+
+-- 
+Stefan Richter
+-=====-==--- --=- ==---
+http://arcgraph.de/sr/
+
+




More information about the fedora-extras-commits mailing list