Commit 8e85973e authored by Stefan Richter's avatar Stefan Richter

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: default avatarStefan Richter <stefanr@s5r6.in-berlin.de>
parent e21fcf79
...@@ -38,6 +38,18 @@ ...@@ -38,6 +38,18 @@
#include "core.h" #include "core.h"
static int __compute_block_crc(__be32 *block)
{
int length;
u16 crc;
length = (be32_to_cpu(block[0]) >> 16) & 0xff;
crc = crc_itu_t(0, (u8 *)&block[1], length * 4);
*block |= cpu_to_be32(crc);
return length;
}
int fw_compute_block_crc(u32 *block) int fw_compute_block_crc(u32 *block)
{ {
__be32 be32_block[256]; __be32 be32_block[256];
...@@ -72,11 +84,11 @@ static int descriptor_count; ...@@ -72,11 +84,11 @@ static int descriptor_count;
#define BIB_CMC ((1) << 30) #define BIB_CMC ((1) << 30)
#define BIB_IMC ((1) << 31) #define BIB_IMC ((1) << 31)
static u32 *generate_config_rom(struct fw_card *card, size_t *config_rom_length) static __be32 *generate_config_rom(struct fw_card *card, size_t *rom_length)
{ {
struct fw_descriptor *desc; struct fw_descriptor *desc;
static u32 config_rom[256]; static __be32 config_rom[256];
int i, j, length; int i, j, k, length;
/* /*
* Initialize contents of config rom buffer. On the OHCI * Initialize contents of config rom buffer. On the OHCI
...@@ -87,40 +99,39 @@ static u32 *generate_config_rom(struct fw_card *card, size_t *config_rom_length) ...@@ -87,40 +99,39 @@ static u32 *generate_config_rom(struct fw_card *card, size_t *config_rom_length)
* the version stored in the OHCI registers. * the version stored in the OHCI registers.
*/ */
memset(config_rom, 0, sizeof(config_rom)); config_rom[0] = cpu_to_be32(
config_rom[0] = BIB_CRC_LENGTH(4) | BIB_INFO_LENGTH(4) | BIB_CRC(0); BIB_CRC_LENGTH(4) | BIB_INFO_LENGTH(4) | BIB_CRC(0));
config_rom[1] = 0x31333934; config_rom[1] = cpu_to_be32(0x31333934);
config_rom[2] = cpu_to_be32(
config_rom[2] =
BIB_LINK_SPEED(card->link_speed) | BIB_LINK_SPEED(card->link_speed) |
BIB_GENERATION(card->config_rom_generation++ % 14 + 2) | BIB_GENERATION(card->config_rom_generation++ % 14 + 2) |
BIB_MAX_ROM(2) | BIB_MAX_ROM(2) |
BIB_MAX_RECEIVE(card->max_receive) | BIB_MAX_RECEIVE(card->max_receive) |
BIB_BMC | BIB_ISC | BIB_CMC | BIB_IMC; BIB_BMC | BIB_ISC | BIB_CMC | BIB_IMC);
config_rom[3] = card->guid >> 32; config_rom[3] = cpu_to_be32(card->guid >> 32);
config_rom[4] = card->guid; config_rom[4] = cpu_to_be32(card->guid);
/* Generate root directory. */ /* Generate root directory. */
i = 5; config_rom[6] = cpu_to_be32(0x0c0083c0); /* node capabilities */
config_rom[i++] = 0; i = 7;
config_rom[i++] = 0x0c0083c0; /* node capabilities */ j = 7 + descriptor_count;
j = i + descriptor_count;
/* Generate root directory entries for descriptors. */ /* Generate root directory entries for descriptors. */
list_for_each_entry (desc, &descriptor_list, link) { list_for_each_entry (desc, &descriptor_list, link) {
if (desc->immediate > 0) if (desc->immediate > 0)
config_rom[i++] = desc->immediate; config_rom[i++] = cpu_to_be32(desc->immediate);
config_rom[i] = desc->key | (j - i); config_rom[i] = cpu_to_be32(desc->key | (j - i));
i++; i++;
j += desc->length; j += desc->length;
} }
/* Update root directory length. */ /* Update root directory length. */
config_rom[5] = (i - 5 - 1) << 16; config_rom[5] = cpu_to_be32((i - 5 - 1) << 16);
/* End of root directory, now copy in descriptors. */ /* End of root directory, now copy in descriptors. */
list_for_each_entry (desc, &descriptor_list, link) { list_for_each_entry (desc, &descriptor_list, link) {
memcpy(&config_rom[i], desc->data, desc->length * 4); for (k = 0; k < desc->length; k++)
config_rom[i + k] = cpu_to_be32(desc->data[k]);
i += desc->length; i += desc->length;
} }
...@@ -129,9 +140,9 @@ static u32 *generate_config_rom(struct fw_card *card, size_t *config_rom_length) ...@@ -129,9 +140,9 @@ static u32 *generate_config_rom(struct fw_card *card, size_t *config_rom_length)
* the bus info block, which is always the case for this * the bus info block, which is always the case for this
* implementation. */ * implementation. */
for (i = 0; i < j; i += length + 1) for (i = 0; i < j; i += length + 1)
length = fw_compute_block_crc(config_rom + i); length = __compute_block_crc(config_rom + i);
*config_rom_length = j; *rom_length = j;
return config_rom; return config_rom;
} }
...@@ -139,7 +150,7 @@ static u32 *generate_config_rom(struct fw_card *card, size_t *config_rom_length) ...@@ -139,7 +150,7 @@ static u32 *generate_config_rom(struct fw_card *card, size_t *config_rom_length)
static void update_config_roms(void) static void update_config_roms(void)
{ {
struct fw_card *card; struct fw_card *card;
u32 *config_rom; __be32 *config_rom;
size_t length; size_t length;
list_for_each_entry (card, &card_list, link) { list_for_each_entry (card, &card_list, link) {
...@@ -432,7 +443,7 @@ EXPORT_SYMBOL(fw_card_initialize); ...@@ -432,7 +443,7 @@ EXPORT_SYMBOL(fw_card_initialize);
int fw_card_add(struct fw_card *card, int fw_card_add(struct fw_card *card,
u32 max_receive, u32 link_speed, u64 guid) u32 max_receive, u32 link_speed, u64 guid)
{ {
u32 *config_rom; __be32 *config_rom;
size_t length; size_t length;
int ret; int ret;
...@@ -462,7 +473,8 @@ EXPORT_SYMBOL(fw_card_add); ...@@ -462,7 +473,8 @@ EXPORT_SYMBOL(fw_card_add);
* shutdown still need to be provided by the card driver. * shutdown still need to be provided by the card driver.
*/ */
static int dummy_enable(struct fw_card *card, u32 *config_rom, size_t length) static int dummy_enable(struct fw_card *card,
const __be32 *config_rom, size_t length)
{ {
BUG(); BUG();
return -1; return -1;
...@@ -475,7 +487,7 @@ static int dummy_update_phy_reg(struct fw_card *card, int address, ...@@ -475,7 +487,7 @@ static int dummy_update_phy_reg(struct fw_card *card, int address,
} }
static int dummy_set_config_rom(struct fw_card *card, static int dummy_set_config_rom(struct fw_card *card,
u32 *config_rom, size_t length) const __be32 *config_rom, size_t length)
{ {
/* /*
* We take the card out of card_list before setting the dummy * We take the card out of card_list before setting the dummy
......
...@@ -40,7 +40,8 @@ struct fw_card_driver { ...@@ -40,7 +40,8 @@ struct fw_card_driver {
* enable the PHY or set the link_on bit and initiate a bus * enable the PHY or set the link_on bit and initiate a bus
* reset. * reset.
*/ */
int (*enable)(struct fw_card *card, u32 *config_rom, size_t length); int (*enable)(struct fw_card *card,
const __be32 *config_rom, size_t length);
int (*update_phy_reg)(struct fw_card *card, int address, int (*update_phy_reg)(struct fw_card *card, int address,
int clear_bits, int set_bits); int clear_bits, int set_bits);
...@@ -48,10 +49,10 @@ struct fw_card_driver { ...@@ -48,10 +49,10 @@ struct fw_card_driver {
/* /*
* Update the config rom for an enabled card. This function * Update the config rom for an enabled card. This function
* should change the config rom that is presented on the bus * should change the config rom that is presented on the bus
* an initiate a bus reset. * and initiate a bus reset.
*/ */
int (*set_config_rom)(struct fw_card *card, int (*set_config_rom)(struct fw_card *card,
u32 *config_rom, size_t length); const __be32 *config_rom, size_t length);
void (*send_request)(struct fw_card *card, struct fw_packet *packet); void (*send_request)(struct fw_card *card, struct fw_packet *packet);
void (*send_response)(struct fw_card *card, struct fw_packet *packet); void (*send_response)(struct fw_card *card, struct fw_packet *packet);
......
...@@ -205,7 +205,7 @@ struct fw_ohci { ...@@ -205,7 +205,7 @@ struct fw_ohci {
dma_addr_t config_rom_bus; dma_addr_t config_rom_bus;
__be32 *next_config_rom; __be32 *next_config_rom;
dma_addr_t next_config_rom_bus; dma_addr_t next_config_rom_bus;
u32 next_header; __be32 next_header;
struct ar_context ar_request_ctx; struct ar_context ar_request_ctx;
struct ar_context ar_response_ctx; struct ar_context ar_response_ctx;
...@@ -1355,8 +1355,9 @@ static void bus_reset_tasklet(unsigned long data) ...@@ -1355,8 +1355,9 @@ static void bus_reset_tasklet(unsigned long data)
*/ */
reg_write(ohci, OHCI1394_BusOptions, reg_write(ohci, OHCI1394_BusOptions,
be32_to_cpu(ohci->config_rom[2])); be32_to_cpu(ohci->config_rom[2]));
ohci->config_rom[0] = cpu_to_be32(ohci->next_header); ohci->config_rom[0] = ohci->next_header;
reg_write(ohci, OHCI1394_ConfigROMhdr, ohci->next_header); reg_write(ohci, OHCI1394_ConfigROMhdr,
be32_to_cpu(ohci->next_header));
} }
#ifdef CONFIG_FIREWIRE_OHCI_REMOTE_DMA #ifdef CONFIG_FIREWIRE_OHCI_REMOTE_DMA
...@@ -1464,7 +1465,17 @@ static int software_reset(struct fw_ohci *ohci) ...@@ -1464,7 +1465,17 @@ static int software_reset(struct fw_ohci *ohci)
return -EBUSY; return -EBUSY;
} }
static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length) static void copy_config_rom(__be32 *dest, const __be32 *src, size_t length)
{
size_t size = length * 4;
memcpy(dest, src, size);
if (size < CONFIG_ROM_SIZE)
memset(&dest[length], 0, CONFIG_ROM_SIZE - size);
}
static int ohci_enable(struct fw_card *card,
const __be32 *config_rom, size_t length)
{ {
struct fw_ohci *ohci = fw_ohci(card); struct fw_ohci *ohci = fw_ohci(card);
struct pci_dev *dev = to_pci_dev(card->device); struct pci_dev *dev = to_pci_dev(card->device);
...@@ -1565,8 +1576,7 @@ static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length) ...@@ -1565,8 +1576,7 @@ static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length)
if (ohci->next_config_rom == NULL) if (ohci->next_config_rom == NULL)
return -ENOMEM; return -ENOMEM;
memset(ohci->next_config_rom, 0, CONFIG_ROM_SIZE); copy_config_rom(ohci->next_config_rom, config_rom, length);
fw_memcpy_to_be32(ohci->next_config_rom, config_rom, length * 4);
} else { } else {
/* /*
* In the suspend case, config_rom is NULL, which * In the suspend case, config_rom is NULL, which
...@@ -1576,7 +1586,7 @@ static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length) ...@@ -1576,7 +1586,7 @@ static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length)
ohci->next_config_rom_bus = ohci->config_rom_bus; ohci->next_config_rom_bus = ohci->config_rom_bus;
} }
ohci->next_header = be32_to_cpu(ohci->next_config_rom[0]); ohci->next_header = ohci->next_config_rom[0];
ohci->next_config_rom[0] = 0; ohci->next_config_rom[0] = 0;
reg_write(ohci, OHCI1394_ConfigROMhdr, 0); reg_write(ohci, OHCI1394_ConfigROMhdr, 0);
reg_write(ohci, OHCI1394_BusOptions, reg_write(ohci, OHCI1394_BusOptions,
...@@ -1610,7 +1620,7 @@ static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length) ...@@ -1610,7 +1620,7 @@ static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length)
} }
static int ohci_set_config_rom(struct fw_card *card, static int ohci_set_config_rom(struct fw_card *card,
u32 *config_rom, size_t length) const __be32 *config_rom, size_t length)
{ {
struct fw_ohci *ohci; struct fw_ohci *ohci;
unsigned long flags; unsigned long flags;
...@@ -1659,9 +1669,7 @@ static int ohci_set_config_rom(struct fw_card *card, ...@@ -1659,9 +1669,7 @@ static int ohci_set_config_rom(struct fw_card *card,
ohci->next_config_rom = next_config_rom; ohci->next_config_rom = next_config_rom;
ohci->next_config_rom_bus = next_config_rom_bus; ohci->next_config_rom_bus = next_config_rom_bus;
memset(ohci->next_config_rom, 0, CONFIG_ROM_SIZE); copy_config_rom(ohci->next_config_rom, config_rom, length);
fw_memcpy_to_be32(ohci->next_config_rom, config_rom,
length * 4);
ohci->next_header = config_rom[0]; ohci->next_header = config_rom[0];
ohci->next_config_rom[0] = 0; ohci->next_config_rom[0] = 0;
......
...@@ -20,20 +20,6 @@ ...@@ -20,20 +20,6 @@
#define fw_notify(s, args...) printk(KERN_NOTICE KBUILD_MODNAME ": " s, ## args) #define fw_notify(s, args...) printk(KERN_NOTICE KBUILD_MODNAME ": " s, ## args)
#define fw_error(s, args...) printk(KERN_ERR 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 #define CSR_REGISTER_BASE 0xfffff0000000ULL
/* register offsets are relative to CSR_REGISTER_BASE */ /* register offsets are relative to CSR_REGISTER_BASE */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment