diff options
Diffstat (limited to 'drivers/ieee1394')
-rw-r--r-- | drivers/ieee1394/csr1212.c | 45 | ||||
-rw-r--r-- | drivers/ieee1394/csr1212.h | 7 | ||||
-rw-r--r-- | drivers/ieee1394/nodemgr.c | 20 |
3 files changed, 19 insertions, 53 deletions
diff --git a/drivers/ieee1394/csr1212.c b/drivers/ieee1394/csr1212.c index 5e38a68b8af2..a6dfeb0b3372 100644 --- a/drivers/ieee1394/csr1212.c +++ b/drivers/ieee1394/csr1212.c | |||
@@ -1077,15 +1077,10 @@ static int csr1212_parse_bus_info_block(struct csr1212_csr *csr) | |||
1077 | int i; | 1077 | int i; |
1078 | int ret; | 1078 | int ret; |
1079 | 1079 | ||
1080 | /* IEEE 1212 says that the entire bus info block should be readable in | ||
1081 | * a single transaction regardless of the max_rom value. | ||
1082 | * Unfortunately, many IEEE 1394 devices do not abide by that, so the | ||
1083 | * bus info block will be read 1 quadlet at a time. The rest of the | ||
1084 | * ConfigROM will be read according to the max_rom field. */ | ||
1085 | for (i = 0; i < csr->bus_info_len; i += sizeof(u32)) { | 1080 | for (i = 0; i < csr->bus_info_len; i += sizeof(u32)) { |
1086 | ret = csr->ops->bus_read(csr, CSR1212_CONFIG_ROM_SPACE_BASE + i, | 1081 | ret = csr->ops->bus_read(csr, CSR1212_CONFIG_ROM_SPACE_BASE + i, |
1087 | sizeof(u32), &csr->cache_head->data[bytes_to_quads(i)], | 1082 | &csr->cache_head->data[bytes_to_quads(i)], |
1088 | csr->private); | 1083 | csr->private); |
1089 | if (ret != CSR1212_SUCCESS) | 1084 | if (ret != CSR1212_SUCCESS) |
1090 | return ret; | 1085 | return ret; |
1091 | 1086 | ||
@@ -1104,8 +1099,8 @@ static int csr1212_parse_bus_info_block(struct csr1212_csr *csr) | |||
1104 | * a time. */ | 1099 | * a time. */ |
1105 | for (i = csr->bus_info_len; i <= csr->crc_len; i += sizeof(u32)) { | 1100 | for (i = csr->bus_info_len; i <= csr->crc_len; i += sizeof(u32)) { |
1106 | ret = csr->ops->bus_read(csr, CSR1212_CONFIG_ROM_SPACE_BASE + i, | 1101 | ret = csr->ops->bus_read(csr, CSR1212_CONFIG_ROM_SPACE_BASE + i, |
1107 | sizeof(u32), &csr->cache_head->data[bytes_to_quads(i)], | 1102 | &csr->cache_head->data[bytes_to_quads(i)], |
1108 | csr->private); | 1103 | csr->private); |
1109 | if (ret != CSR1212_SUCCESS) | 1104 | if (ret != CSR1212_SUCCESS) |
1110 | return ret; | 1105 | return ret; |
1111 | } | 1106 | } |
@@ -1289,7 +1284,7 @@ csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv) | |||
1289 | 1284 | ||
1290 | if (csr->ops->bus_read(csr, | 1285 | if (csr->ops->bus_read(csr, |
1291 | CSR1212_REGISTER_SPACE_BASE + kv->offset, | 1286 | CSR1212_REGISTER_SPACE_BASE + kv->offset, |
1292 | sizeof(u32), &q, csr->private)) | 1287 | &q, csr->private)) |
1293 | return -EIO; | 1288 | return -EIO; |
1294 | 1289 | ||
1295 | kv->value.leaf.len = be32_to_cpu(q) >> 16; | 1290 | kv->value.leaf.len = be32_to_cpu(q) >> 16; |
@@ -1372,17 +1367,8 @@ csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv) | |||
1372 | addr = (CSR1212_CSR_ARCH_REG_SPACE_BASE + cache->offset + | 1367 | addr = (CSR1212_CSR_ARCH_REG_SPACE_BASE + cache->offset + |
1373 | cr->offset_end) & ~(csr->max_rom - 1); | 1368 | cr->offset_end) & ~(csr->max_rom - 1); |
1374 | 1369 | ||
1375 | if (csr->ops->bus_read(csr, addr, csr->max_rom, cache_ptr, | 1370 | if (csr->ops->bus_read(csr, addr, cache_ptr, csr->private)) |
1376 | csr->private)) { | 1371 | return -EIO; |
1377 | if (csr->max_rom == 4) | ||
1378 | /* We've got problems! */ | ||
1379 | return -EIO; | ||
1380 | |||
1381 | /* Apperently the max_rom value was a lie, set it to | ||
1382 | * do quadlet reads and try again. */ | ||
1383 | csr->max_rom = 4; | ||
1384 | continue; | ||
1385 | } | ||
1386 | 1372 | ||
1387 | cr->offset_end += csr->max_rom - (cr->offset_end & | 1373 | cr->offset_end += csr->max_rom - (cr->offset_end & |
1388 | (csr->max_rom - 1)); | 1374 | (csr->max_rom - 1)); |
@@ -1433,7 +1419,6 @@ csr1212_get_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv) | |||
1433 | 1419 | ||
1434 | int csr1212_parse_csr(struct csr1212_csr *csr) | 1420 | int csr1212_parse_csr(struct csr1212_csr *csr) |
1435 | { | 1421 | { |
1436 | static const int mr_map[] = { 4, 64, 1024, 0 }; | ||
1437 | struct csr1212_dentry *dentry; | 1422 | struct csr1212_dentry *dentry; |
1438 | int ret; | 1423 | int ret; |
1439 | 1424 | ||
@@ -1443,15 +1428,13 @@ int csr1212_parse_csr(struct csr1212_csr *csr) | |||
1443 | if (ret != CSR1212_SUCCESS) | 1428 | if (ret != CSR1212_SUCCESS) |
1444 | return ret; | 1429 | return ret; |
1445 | 1430 | ||
1446 | if (!csr->ops->get_max_rom) { | 1431 | /* |
1447 | csr->max_rom = mr_map[0]; /* default value */ | 1432 | * There has been a buggy firmware with bus_info_block.max_rom > 0 |
1448 | } else { | 1433 | * spotted which actually only supported quadlet read requests to the |
1449 | int i = csr->ops->get_max_rom(csr->bus_info_data, | 1434 | * config ROM. Therefore read everything quadlet by quadlet regardless |
1450 | csr->private); | 1435 | * of what the bus info block says. |
1451 | if (i & ~0x3) | 1436 | */ |
1452 | return -EINVAL; | 1437 | csr->max_rom = 4; |
1453 | csr->max_rom = mr_map[i]; | ||
1454 | } | ||
1455 | 1438 | ||
1456 | csr->cache_head->layout_head = csr->root_kv; | 1439 | csr->cache_head->layout_head = csr->root_kv; |
1457 | csr->cache_head->layout_tail = csr->root_kv; | 1440 | csr->cache_head->layout_tail = csr->root_kv; |
diff --git a/drivers/ieee1394/csr1212.h b/drivers/ieee1394/csr1212.h index 043039fc63ec..aced168f1be2 100644 --- a/drivers/ieee1394/csr1212.h +++ b/drivers/ieee1394/csr1212.h | |||
@@ -200,7 +200,7 @@ struct csr1212_bus_ops { | |||
200 | * entries located in the Units Space. Must return 0 on success | 200 | * entries located in the Units Space. Must return 0 on success |
201 | * anything else indicates an error. */ | 201 | * anything else indicates an error. */ |
202 | int (*bus_read) (struct csr1212_csr *csr, u64 addr, | 202 | int (*bus_read) (struct csr1212_csr *csr, u64 addr, |
203 | u16 length, void *buffer, void *private); | 203 | void *buffer, void *private); |
204 | 204 | ||
205 | /* This function is used by csr1212 to allocate a region in units space | 205 | /* This function is used by csr1212 to allocate a region in units space |
206 | * in the event that Config ROM entries don't all fit in the predefined | 206 | * in the event that Config ROM entries don't all fit in the predefined |
@@ -211,11 +211,6 @@ struct csr1212_bus_ops { | |||
211 | /* This function is used by csr1212 to release a region in units space | 211 | /* This function is used by csr1212 to release a region in units space |
212 | * that is no longer needed. */ | 212 | * that is no longer needed. */ |
213 | void (*release_addr) (u64 addr, void *private); | 213 | void (*release_addr) (u64 addr, void *private); |
214 | |||
215 | /* This function is used by csr1212 to determine the max read request | ||
216 | * supported by a remote node when reading the ConfigROM space. Must | ||
217 | * return 0, 1, or 2 per IEEE 1212. */ | ||
218 | int (*get_max_rom) (u32 *bus_info, void *private); | ||
219 | }; | 214 | }; |
220 | 215 | ||
221 | 216 | ||
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 | ||
88 | static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length, | 88 | static 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 | |||
120 | static 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 | |||
129 | static struct csr1212_bus_ops nodemgr_csr_ops = { | 118 | static 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 | ||