From 928ec5f148e729076e9202e7c78babede628a50c Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 6 Sep 2009 18:49:17 +0200 Subject: firewire: ohci: fix Self ID Count register mask (safeguard against buffer overflow) The selfIDSize field of Self ID Count is 9 bits wide, and we are only interested in the high 8 bits. Fix the mask accordingly. The previously too large mask didn't do damage though because the next few bits in the register are reserved and therefore zero with presently existing hardware. Also, check for the maximum possible self ID count of 252 (according to OHCI 1.1 clause 11.2 and IEEE 1394a-2000 clause 4.3.4.1, i.e. up to four self IDs of up to 63 nodes, even though IEEE 1394 up to edition 2008 defines only up to three self IDs per node). More than 252 self IDs would only happen if the self ID receive DMA unit malfunctioned, which would likely be caught by other self ID buffer checks. However, check it early to be sure. More than 253 quadlets would overflow the Topology Map CSR. Reported-By: PaX Team Signed-off-by: Stefan Richter --- drivers/firewire/ohci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/firewire') diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 76b321bb73f..5d524254499 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -1279,8 +1279,8 @@ static void bus_reset_tasklet(unsigned long data) * the inverted quadlets and a header quadlet, we shift one * bit extra to get the actual number of self IDs. */ - self_id_count = (reg >> 3) & 0x3ff; - if (self_id_count == 0) { + self_id_count = (reg >> 3) & 0xff; + if (self_id_count == 0 || self_id_count > 252) { fw_notify("inconsistent self IDs\n"); return; } -- cgit v1.2.3-18-g5258 From 18668ff9a3232d5f942a2f7abc1ad67d2760dcdf Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 6 Sep 2009 18:49:48 +0200 Subject: firewire: core: header file cleanup fw_card_get, fw_card_put, fw_card_release are currently not exported for use outside the firewire-core. Move their definitions/ declarations from the subsystem header file to the core header file. Signed-off-by: Stefan Richter --- drivers/firewire/core.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers/firewire') diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h index 6052816be35..7ff6e758515 100644 --- a/drivers/firewire/core.h +++ b/drivers/firewire/core.h @@ -96,6 +96,20 @@ int fw_core_initiate_bus_reset(struct fw_card *card, int short_reset); int fw_compute_block_crc(u32 *block); void fw_schedule_bm_work(struct fw_card *card, unsigned long delay); +static inline struct fw_card *fw_card_get(struct fw_card *card) +{ + kref_get(&card->kref); + + return card; +} + +void fw_card_release(struct kref *kref); + +static inline void fw_card_put(struct fw_card *card) +{ + kref_put(&card->kref, fw_card_release); +} + /* -cdev */ -- cgit v1.2.3-18-g5258 From b171e204b32b69e241af994d6e9be559e33535c1 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 6 Sep 2009 18:50:29 +0200 Subject: firewire: core: fix race with parallel PCI device probe The config ROM buffer received from generate_config_rom is a globally shared static buffer. Extend the card_mutex protection in fw_add_card until after the config ROM was copied into the card driver's buffer. Otherwise, parallelized card driver probes may end up with ROM contents that were meant for a different card. firewire-ohci's card->driver->enable hook is safe to be called within the card_mutex. Furthermore, it is safe to reorder card_list update versus card enable, which simplifies the code a little. Signed-off-by: Stefan Richter --- drivers/firewire/core-card.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers/firewire') diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index f74edae5cb4..e4864e894e4 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c @@ -444,16 +444,13 @@ int fw_card_add(struct fw_card *card, card->guid = guid; mutex_lock(&card_mutex); - config_rom = generate_config_rom(card, &length); - list_add_tail(&card->link, &card_list); - mutex_unlock(&card_mutex); + config_rom = generate_config_rom(card, &length); ret = card->driver->enable(card, config_rom, length); - if (ret < 0) { - mutex_lock(&card_mutex); - list_del(&card->link); - mutex_unlock(&card_mutex); - } + if (ret == 0) + list_add_tail(&card->link, &card_list); + + mutex_unlock(&card_mutex); return ret; } -- cgit v1.2.3-18-g5258 From 85cb9b68640cf467a99d4b6d518f1293222dbc9e Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Tue, 8 Sep 2009 01:13:53 +0200 Subject: firewire: core: fix topology map response handler This register is 1 kBytes large. Adjust topology_map.length to prevent registration of other response handlers in this region and to make sure that we respond to requests to the upper half of the register. Signed-off-by: Stefan Richter --- drivers/firewire/core-transaction.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/firewire') diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index 479b22f5a1e..da628c72a46 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -834,7 +834,7 @@ static void handle_topology_map(struct fw_card *card, struct fw_request *request } static struct fw_address_handler topology_map = { - .length = 0x200, + .length = 0x400, .address_callback = handle_topology_map, }; -- cgit v1.2.3-18-g5258 From 094614fc14966bc6a6259ade55f051fe17f36122 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 6 Sep 2009 18:51:27 +0200 Subject: firewire: sbp2: fix status reception Per SBP-2 clause 5.3, a target shall store 8...32 bytes of status information. Trailing zeros after the first 8 bytes don't need to be stored, they are implicit. Fix the status write handler to clear all unwritten status data. Signed-off-by: Stefan Richter --- drivers/firewire/sbp2.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers/firewire') diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c index e5df822a813..8f83bffb43e 100644 --- a/drivers/firewire/sbp2.c +++ b/drivers/firewire/sbp2.c @@ -425,19 +425,20 @@ static void sbp2_status_write(struct fw_card *card, struct fw_request *request, struct sbp2_logical_unit *lu = callback_data; struct sbp2_orb *orb; struct sbp2_status status; - size_t header_size; unsigned long flags; if (tcode != TCODE_WRITE_BLOCK_REQUEST || - length == 0 || length > sizeof(status)) { + length < 8 || length > sizeof(status)) { fw_send_response(card, request, RCODE_TYPE_ERROR); return; } - header_size = min(length, 2 * sizeof(u32)); - fw_memcpy_from_be32(&status, payload, header_size); - if (length > header_size) - memcpy(status.data, payload + 8, length - header_size); + status.status = be32_to_cpup(payload); + status.orb_low = be32_to_cpup(payload + 4); + memset(status.data, 0, sizeof(status.data)); + if (length > 8) + memcpy(status.data, payload + 8, length - 8); + if (STATUS_GET_SOURCE(status) == 2 || STATUS_GET_SOURCE(status) == 3) { fw_notify("non-orb related status write, not handled\n"); fw_send_response(card, request, RCODE_COMPLETE); -- cgit v1.2.3-18-g5258 From 3c5f80357c3fb3170e39e5d0ae87ddd6652f36ac Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 6 Sep 2009 19:33:50 +0200 Subject: firewire: sbp2: remove a workaround for Momobay FX-3A The inquiry delay does more harm than good in tests on a recent kernel. Signed-off-by: Stefan Richter --- drivers/firewire/sbp2.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/firewire') diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c index 8f83bffb43e..50f0176de61 100644 --- a/drivers/firewire/sbp2.c +++ b/drivers/firewire/sbp2.c @@ -354,8 +354,7 @@ static const struct { /* DViCO Momobay FX-3A with TSB42AA9A bridge */ { .firmware_revision = 0x002800, .model = 0x000000, - .workarounds = SBP2_WORKAROUND_DELAY_INQUIRY | - SBP2_WORKAROUND_POWER_CONDITION, + .workarounds = SBP2_WORKAROUND_POWER_CONDITION, }, /* Initio bridges, actually only needed for some older ones */ { .firmware_revision = 0x000200, -- cgit v1.2.3-18-g5258