From 8e85973efc87dfae8508f1a3440fd44612897458 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Thu, 8 Oct 2009 00:41:59 +0200 Subject: firewire: optimize config ROM creation The config ROM image of the local node was created in CPU byte order, then a temporary big endian copy was created to compute the CRC, and finally the card driver created its own big endian copy. We now generate it in big endian byte order in the first place to avoid one byte order conversion and the temporary on-stack copy of the ROM image (1000 bytes stack usage in process context). Furthermore, two 1000 bytes memset()s are replaced by one 1000 bytes - ROM length sized memset. The trivial fw_memcpy_{from,to}_be32() helpers are now superfluous and removed. The newly added __compute_block_crc() function will be folded into fw_compute_block_crc() in a subsequent change. Signed-off-by: Stefan Richter --- include/linux/firewire.h | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'include') diff --git a/include/linux/firewire.h b/include/linux/firewire.h index 7e1d4dec83e7..53b9217de86c 100644 --- a/include/linux/firewire.h +++ b/include/linux/firewire.h @@ -20,20 +20,6 @@ #define fw_notify(s, args...) printk(KERN_NOTICE KBUILD_MODNAME ": " s, ## args) #define fw_error(s, args...) printk(KERN_ERR KBUILD_MODNAME ": " s, ## args) -static inline void fw_memcpy_from_be32(void *_dst, void *_src, size_t size) -{ - u32 *dst = _dst; - __be32 *src = _src; - int i; - - for (i = 0; i < size / 4; i++) - dst[i] = be32_to_cpu(src[i]); -} - -static inline void fw_memcpy_to_be32(void *_dst, void *_src, size_t size) -{ - fw_memcpy_from_be32(_dst, _src, size); -} #define CSR_REGISTER_BASE 0xfffff0000000ULL /* register offsets are relative to CSR_REGISTER_BASE */ -- cgit v1.2.3-58-ga151 From cb7c96da3651111efbe088fa12f9bed61836ea93 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Thu, 8 Oct 2009 00:42:53 +0200 Subject: firewire: core: optimize Topology Map creation The Topology Map of the local node was created in CPU byte order, then a temporary big endian copy was created to compute the CRC, and when a read request to the Topology Map arrived it had to be converted to big endian byte order again. We now generate it in big endian byte order in the first place. This also rids us of 1000 bytes stack usage in tasklet context. Signed-off-by: Stefan Richter --- drivers/firewire/core-card.c | 17 ++--------------- drivers/firewire/core-topology.c | 17 ++++++++++------- drivers/firewire/core-transaction.c | 9 ++------- drivers/firewire/core.h | 2 +- include/linux/firewire.h | 2 +- 5 files changed, 16 insertions(+), 31 deletions(-) (limited to 'include') diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index f58130789990..7083bcc1b9c7 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c @@ -38,7 +38,7 @@ #include "core.h" -static int __compute_block_crc(__be32 *block) +int fw_compute_block_crc(__be32 *block) { int length; u16 crc; @@ -50,19 +50,6 @@ static int __compute_block_crc(__be32 *block) return length; } -int fw_compute_block_crc(u32 *block) -{ - __be32 be32_block[256]; - int i, length; - - length = (*block >> 16) & 0xff; - for (i = 0; i < length; i++) - be32_block[i] = cpu_to_be32(block[i + 1]); - *block |= crc_itu_t(0, (u8 *) be32_block, length * 4); - - return length; -} - static DEFINE_MUTEX(card_mutex); static LIST_HEAD(card_list); @@ -141,7 +128,7 @@ static size_t generate_config_rom(struct fw_card *card, __be32 *config_rom) * the bus info block, which is always the case for this * implementation. */ for (i = 0; i < j; i += length + 1) - length = __compute_block_crc(config_rom + i); + length = fw_compute_block_crc(config_rom + i); return j; } diff --git a/drivers/firewire/core-topology.c b/drivers/firewire/core-topology.c index fddf2b358936..9a5f38c80b0e 100644 --- a/drivers/firewire/core-topology.c +++ b/drivers/firewire/core-topology.c @@ -28,9 +28,9 @@ #include #include #include -#include #include +#include #include #include "core.h" @@ -510,13 +510,16 @@ static void update_tree(struct fw_card *card, struct fw_node *root) static void update_topology_map(struct fw_card *card, u32 *self_ids, int self_id_count) { - int node_count; + int node_count = (card->root_node->node_id & 0x3f) + 1; + __be32 *map = card->topology_map; + + *map++ = cpu_to_be32((self_id_count + 2) << 16); + *map++ = cpu_to_be32(be32_to_cpu(card->topology_map[1]) + 1); + *map++ = cpu_to_be32((node_count << 16) | self_id_count); + + while (self_id_count--) + *map++ = cpu_to_be32p(self_ids++); - card->topology_map[1]++; - node_count = (card->root_node->node_id & 0x3f) + 1; - card->topology_map[2] = (node_count << 16) | self_id_count; - card->topology_map[0] = (self_id_count + 2) << 16; - memcpy(&card->topology_map[3], self_ids, self_id_count * 4); fw_compute_block_crc(card->topology_map); } diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index da628c72a462..203e6428bada 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -810,8 +810,7 @@ static void handle_topology_map(struct fw_card *card, struct fw_request *request int speed, unsigned long long offset, void *payload, size_t length, void *callback_data) { - int i, start, end; - __be32 *map; + int start; if (!TCODE_IS_READ_REQUEST(tcode)) { fw_send_response(card, request, RCODE_TYPE_ERROR); @@ -824,11 +823,7 @@ static void handle_topology_map(struct fw_card *card, struct fw_request *request } start = (offset - topology_map_region.start) / 4; - end = start + length / 4; - map = payload; - - for (i = 0; i < length / 4; i++) - map[i] = cpu_to_be32(card->topology_map[start + i]); + memcpy(payload, &card->topology_map[start], length); fw_send_response(card, request, RCODE_COMPLETE); } diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h index 7adca7cb9f55..ed3b1a765c00 100644 --- a/drivers/firewire/core.h +++ b/drivers/firewire/core.h @@ -94,7 +94,7 @@ int fw_card_add(struct fw_card *card, u32 max_receive, u32 link_speed, u64 guid); void fw_core_remove_card(struct fw_card *card); int fw_core_initiate_bus_reset(struct fw_card *card, int short_reset); -int fw_compute_block_crc(u32 *block); +int fw_compute_block_crc(__be32 *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) diff --git a/include/linux/firewire.h b/include/linux/firewire.h index 53b9217de86c..211a5d7d87b3 100644 --- a/include/linux/firewire.h +++ b/include/linux/firewire.h @@ -117,7 +117,7 @@ struct fw_card { bool broadcast_channel_allocated; u32 broadcast_channel; - u32 topology_map[(CSR_TOPOLOGY_MAP_END - CSR_TOPOLOGY_MAP) / 4]; + __be32 topology_map[(CSR_TOPOLOGY_MAP_END - CSR_TOPOLOGY_MAP) / 4]; }; struct fw_attribute_group { -- cgit v1.2.3-58-ga151 From 19593ffdb6daa6ba691d247a2400cece12687c52 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Wed, 14 Oct 2009 20:40:10 +0200 Subject: firewire: ohci: 0 may be a valid DMA address I was told that there are obscure architectures with non-coherent DMA which may DMA-map to bus address 0. We shall not use 0 as a magic number of uninitialized bus address variables. The packet->payload_length > 0 test cannot be used either (except in at_context_queue_packet) because local requests are not DMA-mapped regardless of payload_length. Hence add a state flag to struct fw_packet. Signed-off-by: Stefan Richter --- drivers/firewire/core-transaction.c | 4 ++-- drivers/firewire/ohci.c | 9 +++++---- include/linux/firewire.h | 1 + 3 files changed, 8 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index 66789c3cc561..842739df23e2 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -226,7 +226,7 @@ static void fw_fill_request(struct fw_packet *packet, int tcode, int tlabel, packet->speed = speed; packet->generation = generation; packet->ack = 0; - packet->payload_bus = 0; + packet->payload_mapped = false; } /** @@ -601,7 +601,7 @@ void fw_fill_response(struct fw_packet *response, u32 *request_header, WARN(1, KERN_ERR "wrong tcode %d", tcode); } - response->payload_bus = 0; + response->payload_mapped = false; } EXPORT_SYMBOL(fw_fill_response); diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 418415564791..a71477541dc7 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -995,7 +995,8 @@ static int at_context_queue_packet(struct context *ctx, packet->ack = RCODE_SEND_ERROR; return -1; } - packet->payload_bus = payload_bus; + packet->payload_bus = payload_bus; + packet->payload_mapped = true; d[2].req_count = cpu_to_le16(packet->payload_length); d[2].data_address = cpu_to_le32(payload_bus); @@ -1023,7 +1024,7 @@ static int at_context_queue_packet(struct context *ctx, */ if (ohci->generation != packet->generation || reg_read(ohci, OHCI1394_IntEventSet) & OHCI1394_busReset) { - if (packet->payload_length > 0) + if (packet->payload_mapped) dma_unmap_single(ohci->card.device, payload_bus, packet->payload_length, DMA_TO_DEVICE); packet->ack = RCODE_GENERATION; @@ -1059,7 +1060,7 @@ static int handle_at_packet(struct context *context, /* This packet was cancelled, just continue. */ return 1; - if (packet->payload_bus) + if (packet->payload_mapped) dma_unmap_single(ohci->card.device, packet->payload_bus, packet->payload_length, DMA_TO_DEVICE); @@ -1723,7 +1724,7 @@ static int ohci_cancel_packet(struct fw_card *card, struct fw_packet *packet) if (packet->ack != 0) goto out; - if (packet->payload_bus) + if (packet->payload_mapped) dma_unmap_single(ohci->card.device, packet->payload_bus, packet->payload_length, DMA_TO_DEVICE); diff --git a/include/linux/firewire.h b/include/linux/firewire.h index 211a5d7d87b3..9416a461b696 100644 --- a/include/linux/firewire.h +++ b/include/linux/firewire.h @@ -267,6 +267,7 @@ struct fw_packet { void *payload; size_t payload_length; dma_addr_t payload_bus; + bool payload_mapped; u32 timestamp; /* -- cgit v1.2.3-58-ga151