]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob
11c8ce8a3e64a406970375e561b42adb735c318a
[thirdparty/kernel/stable-queue.git] /
1 From 10389536742cefbedecb67a5b2906f155cf3a1c3 Mon Sep 17 00:00:00 2001
2 From: Stefan Richter <stefanr@s5r6.in-berlin.de>
3 Date: Sun, 30 May 2010 19:43:52 +0200
4 Subject: firewire: core: check for 1394a compliant IRM, fix inaccessibility of Sony camcorder
5
6 From: Stefan Richter <stefanr@s5r6.in-berlin.de>
7
8 commit 10389536742cefbedecb67a5b2906f155cf3a1c3 upstream.
9
10 Per IEEE 1394 clause 8.4.2.3, a contender for the IRM role shall check
11 whether the current IRM complies to 1394a-2000 or later. If not force a
12 compliant node (e.g. itself) to become IRM. This was implemented in the
13 older ieee1394 driver but not yet in firewire-core.
14
15 An older Sony camcorder (Sony DCR-TRV25) which implements 1394-1995 IRM
16 but neither 1394a-2000 IRM nor BM was now found to cause an
17 interoperability bug:
18 - Camcorder becomes root node when plugged in, hence gets IRM role.
19 - firewire-core successfully contends for BM role, proceeds to perform
20 gap count optimization and resets the bus.
21 - Sony camcorder ignores presence of a BM (against the spec, this is
22 a firmware bug), performs its idea of gap count optimization and
23 resets the bus.
24 - Preceding two steps are repeated endlessly, bus never settles,
25 regular I/O is practically impossible.
26 http://thread.gmane.org/gmane.linux.kernel.firewire.user/3913
27
28 This is an interoperability regression from the old to the new drivers.
29 Fix it indirectly by adding the 1394a IRM check. The spec suggests
30 three and a half methods to determine 1394a compliance of a remote IRM;
31 we choose the method of testing the Config_ROM.Bus_Info.generation
32 field. This is data that firewire-core should have readily available at
33 this point, i.e. does not require extra I/O.
34
35 Reported-by: Clemens Ladisch <clemens@ladisch.de> (missing 1394a check)
36 Reported-by: H. S. <hs.samix@gmail.com> (issue with Sony DCR-TRV25)
37 Tested-by: H. S. <hs.samix@gmail.com>
38 Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
39 Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
40
41 ---
42 drivers/firewire/core-card.c | 24 +++++++++++++++++++-----
43 1 file changed, 19 insertions(+), 5 deletions(-)
44
45 --- a/drivers/firewire/core-card.c
46 +++ b/drivers/firewire/core-card.c
47 @@ -239,7 +239,7 @@ void fw_schedule_bm_work(struct fw_card
48 static void fw_card_bm_work(struct work_struct *work)
49 {
50 struct fw_card *card = container_of(work, struct fw_card, work.work);
51 - struct fw_device *root_device;
52 + struct fw_device *root_device, *irm_device;
53 struct fw_node *root_node;
54 unsigned long flags;
55 int root_id, new_root_id, irm_id, local_id;
56 @@ -247,6 +247,7 @@ static void fw_card_bm_work(struct work_
57 bool do_reset = false;
58 bool root_device_is_running;
59 bool root_device_is_cmc;
60 + bool irm_is_1394_1995_only;
61
62 spin_lock_irqsave(&card->lock, flags);
63
64 @@ -256,12 +257,18 @@ static void fw_card_bm_work(struct work_
65 }
66
67 generation = card->generation;
68 +
69 root_node = card->root_node;
70 fw_node_get(root_node);
71 root_device = root_node->data;
72 root_device_is_running = root_device &&
73 atomic_read(&root_device->state) == FW_DEVICE_RUNNING;
74 root_device_is_cmc = root_device && root_device->cmc;
75 +
76 + irm_device = card->irm_node->data;
77 + irm_is_1394_1995_only = irm_device && irm_device->config_rom &&
78 + (irm_device->config_rom[2] & 0x000000f0) == 0;
79 +
80 root_id = root_node->node_id;
81 irm_id = card->irm_node->node_id;
82 local_id = card->local_node->node_id;
83 @@ -284,8 +291,15 @@ static void fw_card_bm_work(struct work_
84
85 if (!card->irm_node->link_on) {
86 new_root_id = local_id;
87 - fw_notify("IRM has link off, making local node (%02x) root.\n",
88 - new_root_id);
89 + fw_notify("%s, making local node (%02x) root.\n",
90 + "IRM has link off", new_root_id);
91 + goto pick_me;
92 + }
93 +
94 + if (irm_is_1394_1995_only) {
95 + new_root_id = local_id;
96 + fw_notify("%s, making local node (%02x) root.\n",
97 + "IRM is not 1394a compliant", new_root_id);
98 goto pick_me;
99 }
100
101 @@ -324,8 +338,8 @@ static void fw_card_bm_work(struct work_
102 * root, and thus, IRM.
103 */
104 new_root_id = local_id;
105 - fw_notify("BM lock failed, making local node (%02x) root.\n",
106 - new_root_id);
107 + fw_notify("%s, making local node (%02x) root.\n",
108 + "BM lock failed", new_root_id);
109 goto pick_me;
110 }
111 } else if (card->bm_generation != generation) {