diff options
-rw-r--r-- | drivers/firewire/core-card.c | 42 |
1 files changed, 29 insertions, 13 deletions
diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index e4864e894e4f..ed635ae2b5d3 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c @@ -57,6 +57,9 @@ static LIST_HEAD(card_list); static LIST_HEAD(descriptor_list); static int descriptor_count; +/* ROM header, bus info block, root dir header, capabilities = 7 quadlets */ +static size_t config_rom_length = 1 + 4 + 1 + 1; + #define BIB_CRC(v) ((v) << 0) #define BIB_CRC_LENGTH(v) ((v) << 16) #define BIB_INFO_LENGTH(v) ((v) << 24) @@ -72,7 +75,7 @@ static int descriptor_count; #define BIB_CMC ((1) << 30) #define BIB_IMC ((1) << 31) -static u32 *generate_config_rom(struct fw_card *card, size_t *config_rom_length) +static u32 *generate_config_rom(struct fw_card *card) { struct fw_descriptor *desc; static u32 config_rom[256]; @@ -131,7 +134,7 @@ static u32 *generate_config_rom(struct fw_card *card, size_t *config_rom_length) for (i = 0; i < j; i += length + 1) length = fw_compute_block_crc(config_rom + i); - *config_rom_length = j; + WARN_ON(j != config_rom_length); return config_rom; } @@ -140,17 +143,24 @@ static void update_config_roms(void) { struct fw_card *card; u32 *config_rom; - size_t length; list_for_each_entry (card, &card_list, link) { - config_rom = generate_config_rom(card, &length); - card->driver->set_config_rom(card, config_rom, length); + config_rom = generate_config_rom(card); + card->driver->set_config_rom(card, config_rom, + config_rom_length); } } +static size_t required_space(struct fw_descriptor *desc) +{ + /* descriptor + entry into root dir + optional immediate entry */ + return desc->length + 1 + (desc->immediate > 0 ? 1 : 0); +} + int fw_core_add_descriptor(struct fw_descriptor *desc) { size_t i; + int ret; /* * Check descriptor is valid; the length of all blocks in the @@ -166,15 +176,21 @@ int fw_core_add_descriptor(struct fw_descriptor *desc) mutex_lock(&card_mutex); - list_add_tail(&desc->link, &descriptor_list); - descriptor_count++; - if (desc->immediate > 0) + if (config_rom_length + required_space(desc) > 256) { + ret = -EBUSY; + } else { + list_add_tail(&desc->link, &descriptor_list); + config_rom_length += required_space(desc); descriptor_count++; - update_config_roms(); + if (desc->immediate > 0) + descriptor_count++; + update_config_roms(); + ret = 0; + } mutex_unlock(&card_mutex); - return 0; + return ret; } EXPORT_SYMBOL(fw_core_add_descriptor); @@ -183,6 +199,7 @@ void fw_core_remove_descriptor(struct fw_descriptor *desc) mutex_lock(&card_mutex); list_del(&desc->link); + config_rom_length -= required_space(desc); descriptor_count--; if (desc->immediate > 0) descriptor_count--; @@ -436,7 +453,6 @@ int fw_card_add(struct fw_card *card, u32 max_receive, u32 link_speed, u64 guid) { u32 *config_rom; - size_t length; int ret; card->max_receive = max_receive; @@ -445,8 +461,8 @@ int fw_card_add(struct fw_card *card, mutex_lock(&card_mutex); - config_rom = generate_config_rom(card, &length); - ret = card->driver->enable(card, config_rom, length); + config_rom = generate_config_rom(card); + ret = card->driver->enable(card, config_rom, config_rom_length); if (ret == 0) list_add_tail(&card->link, &card_list); |