aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ieee1394/nodemgr.c
diff options
context:
space:
mode:
authorStefan Richter <stefanr@s5r6.in-berlin.de>2008-12-13 17:12:06 -0500
committerStefan Richter <stefanr@s5r6.in-berlin.de>2009-01-04 17:50:34 -0500
commit0bed1819687b50a769a1fee6d91cb0ef79b011b4 (patch)
treebc5c36dda1f8e8de697ca3bb2b4d170cb77183c6 /drivers/ieee1394/nodemgr.c
parentc1fc58d63d754b82070881c62601551464afa19d (diff)
ieee1394: ignore nonzero Bus_Info_Block.max_rom, fetch config ROM in quadlets
It is already known that buggy firmwares exist which report a bogus link_spd in their config ROM bus info block. We now got the first report of a bogus max_rom too (Freecom FireWire Hard Drive 1TB, http://bugzilla.kernel.org/show_bug.cgi?id=12206). I suspect other OSs only use quadlet reads to fetch the config ROM, otherwise the firmware authors would have noticed their mistake. Hence limit ieee1394's config ROM fetching routine to quadlets as the safe minimum regardless of what the bus info block says. This will potentially slow the bus reset handling by nodemgr somewhat down. But most existing devices support only quadlet reads anyway, hence there will often be no actual difference to before this change. Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/ieee1394/nodemgr.c')
-rw-r--r--drivers/ieee1394/nodemgr.c20
1 files changed, 4 insertions, 16 deletions
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index 79ef5fd928ae..906c5a98d814 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -67,7 +67,7 @@ static int nodemgr_check_speed(struct nodemgr_csr_info *ci, u64 addr,
67 for (i = IEEE1394_SPEED_100; i <= old_speed; i++) { 67 for (i = IEEE1394_SPEED_100; i <= old_speed; i++) {
68 *speed = i; 68 *speed = i;
69 error = hpsb_read(ci->host, ci->nodeid, ci->generation, addr, 69 error = hpsb_read(ci->host, ci->nodeid, ci->generation, addr,
70 &q, sizeof(quadlet_t)); 70 &q, 4);
71 if (error) 71 if (error)
72 break; 72 break;
73 *buffer = q; 73 *buffer = q;
@@ -85,7 +85,7 @@ static int nodemgr_check_speed(struct nodemgr_csr_info *ci, u64 addr,
85 return error; 85 return error;
86} 86}
87 87
88static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length, 88static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr,
89 void *buffer, void *__ci) 89 void *buffer, void *__ci)
90{ 90{
91 struct nodemgr_csr_info *ci = (struct nodemgr_csr_info*)__ci; 91 struct nodemgr_csr_info *ci = (struct nodemgr_csr_info*)__ci;
@@ -93,7 +93,7 @@ static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length,
93 93
94 for (i = 1; ; i++) { 94 for (i = 1; ; i++) {
95 error = hpsb_read(ci->host, ci->nodeid, ci->generation, addr, 95 error = hpsb_read(ci->host, ci->nodeid, ci->generation, addr,
96 buffer, length); 96 buffer, 4);
97 if (!error) { 97 if (!error) {
98 ci->speed_unverified = 0; 98 ci->speed_unverified = 0;
99 break; 99 break;
@@ -104,7 +104,7 @@ static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length,
104 104
105 /* The ieee1394_core guessed the node's speed capability from 105 /* The ieee1394_core guessed the node's speed capability from
106 * the self ID. Check whether a lower speed works. */ 106 * the self ID. Check whether a lower speed works. */
107 if (ci->speed_unverified && length == sizeof(quadlet_t)) { 107 if (ci->speed_unverified) {
108 error = nodemgr_check_speed(ci, addr, buffer); 108 error = nodemgr_check_speed(ci, addr, buffer);
109 if (!error) 109 if (!error)
110 break; 110 break;
@@ -115,20 +115,8 @@ static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length,
115 return error; 115 return error;
116} 116}
117 117
118#define OUI_FREECOM_TECHNOLOGIES_GMBH 0x0001db
119
120static int nodemgr_get_max_rom(quadlet_t *bus_info_data, void *__ci)
121{
122 /* Freecom FireWire Hard Drive firmware bug */
123 if (be32_to_cpu(bus_info_data[3]) >> 8 == OUI_FREECOM_TECHNOLOGIES_GMBH)
124 return 0;
125
126 return (be32_to_cpu(bus_info_data[2]) >> 8) & 0x3;
127}
128
129static struct csr1212_bus_ops nodemgr_csr_ops = { 118static struct csr1212_bus_ops nodemgr_csr_ops = {
130 .bus_read = nodemgr_bus_read, 119 .bus_read = nodemgr_bus_read,
131 .get_max_rom = nodemgr_get_max_rom
132}; 120};
133 121
134 122