#include "core.h"
-int fw_compute_block_crc(u32 *block)
+int fw_compute_block_crc(__be32 *block)
{
- __be32 be32_block[256];
- int i, length;
+ int length;
+ u16 crc;
- 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);
+ 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;
}
static LIST_HEAD(descriptor_list);
static int descriptor_count;
+static __be32 tmp_config_rom[256];
+
#define BIB_CRC(v) ((v) << 0)
#define BIB_CRC_LENGTH(v) ((v) << 16)
#define BIB_INFO_LENGTH(v) ((v) << 24)
#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 size_t generate_config_rom(struct fw_card *card, __be32 *config_rom)
{
struct fw_descriptor *desc;
- static u32 config_rom[256];
- int i, j, length;
+ int i, j, k, length;
/*
* Initialize contents of config rom buffer. On the OHCI
* the version stored in the OHCI registers.
*/
- memset(config_rom, 0, sizeof(config_rom));
- config_rom[0] = BIB_CRC_LENGTH(4) | BIB_INFO_LENGTH(4) | BIB_CRC(0);
- config_rom[1] = 0x31333934;
-
- config_rom[2] =
+ config_rom[0] = cpu_to_be32(
+ BIB_CRC_LENGTH(4) | BIB_INFO_LENGTH(4) | BIB_CRC(0));
+ config_rom[1] = cpu_to_be32(0x31333934);
+ config_rom[2] = cpu_to_be32(
BIB_LINK_SPEED(card->link_speed) |
BIB_GENERATION(card->config_rom_generation++ % 14 + 2) |
BIB_MAX_ROM(2) |
BIB_MAX_RECEIVE(card->max_receive) |
- BIB_BMC | BIB_ISC | BIB_CMC | BIB_IMC;
- config_rom[3] = card->guid >> 32;
- config_rom[4] = card->guid;
+ BIB_BMC | BIB_ISC | BIB_CMC | BIB_IMC);
+ config_rom[3] = cpu_to_be32(card->guid >> 32);
+ config_rom[4] = cpu_to_be32(card->guid);
/* Generate root directory. */
- i = 5;
- config_rom[i++] = 0;
- config_rom[i++] = 0x0c0083c0; /* node capabilities */
- j = i + descriptor_count;
+ config_rom[6] = cpu_to_be32(0x0c0083c0); /* node capabilities */
+ i = 7;
+ j = 7 + descriptor_count;
/* Generate root directory entries for descriptors. */
list_for_each_entry (desc, &descriptor_list, link) {
if (desc->immediate > 0)
- config_rom[i++] = desc->immediate;
- config_rom[i] = desc->key | (j - i);
+ config_rom[i++] = cpu_to_be32(desc->immediate);
+ config_rom[i] = cpu_to_be32(desc->key | (j - i));
i++;
j += desc->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. */
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;
}
for (i = 0; i < j; i += length + 1)
length = fw_compute_block_crc(config_rom + i);
- *config_rom_length = j;
-
- return config_rom;
+ return j;
}
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);
+ length = generate_config_rom(card, tmp_config_rom);
+ card->driver->set_config_rom(card, tmp_config_rom, length);
}
}
{
int channel, bandwidth = 0;
- fw_iso_resource_manage(card, generation, 1ULL << 31,
- &channel, &bandwidth, true);
+ fw_iso_resource_manage(card, generation, 1ULL << 31, &channel,
+ &bandwidth, true, card->bm_transaction_data);
if (channel == 31) {
card->broadcast_channel_allocated = true;
device_for_each_child(card->device, (void *)(long)generation,
void fw_schedule_bm_work(struct fw_card *card, unsigned long delay)
{
- int scheduled;
-
fw_card_get(card);
- scheduled = schedule_delayed_work(&card->work, delay);
- if (!scheduled)
+ if (!schedule_delayed_work(&card->work, delay))
fw_card_put(card);
}
bool do_reset = false;
bool root_device_is_running;
bool root_device_is_cmc;
- __be32 lock_data[2];
spin_lock_irqsave(&card->lock, flags);
goto pick_me;
}
- lock_data[0] = cpu_to_be32(0x3f);
- lock_data[1] = cpu_to_be32(local_id);
+ card->bm_transaction_data[0] = cpu_to_be32(0x3f);
+ card->bm_transaction_data[1] = cpu_to_be32(local_id);
spin_unlock_irqrestore(&card->lock, flags);
rcode = fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP,
irm_id, generation, SCODE_100,
CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID,
- lock_data, sizeof(lock_data));
+ card->bm_transaction_data,
+ sizeof(card->bm_transaction_data));
if (rcode == RCODE_GENERATION)
/* Another bus reset, BM work has been rescheduled. */
goto out;
if (rcode == RCODE_COMPLETE &&
- lock_data[0] != cpu_to_be32(0x3f)) {
+ card->bm_transaction_data[0] != cpu_to_be32(0x3f)) {
/* Somebody else is BM. Only act as IRM. */
if (local_id == irm_id)
card->local_node = NULL;
INIT_DELAYED_WORK(&card->work, fw_card_bm_work);
- card->netdev = NULL;
- INIT_LIST_HEAD(&card->peer_list);
}
EXPORT_SYMBOL(fw_card_initialize);
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->guid = guid;
mutex_lock(&card_mutex);
- config_rom = generate_config_rom(card, &length);
- list_add_tail(&card->link, &card_list);
- mutex_unlock(&card_mutex);
- ret = card->driver->enable(card, config_rom, length);
- if (ret < 0) {
- mutex_lock(&card_mutex);
- list_del(&card->link);
- mutex_unlock(&card_mutex);
- }
+ length = generate_config_rom(card, tmp_config_rom);
+ ret = card->driver->enable(card, tmp_config_rom, length);
+ if (ret == 0)
+ list_add_tail(&card->link, &card_list);
+
+ mutex_unlock(&card_mutex);
return ret;
}
/*
- * The next few functions implements a dummy driver that use once a
- * card driver shuts down an fw_card. This allows the driver to
- * cleanly unload, as all IO to the card will be handled by the dummy
- * driver instead of calling into the (possibly) unloaded module. The
- * dummy driver just fails all IO.
+ * The next few functions implement a dummy driver that is used once a card
+ * driver shuts down an fw_card. This allows the driver to cleanly unload,
+ * as all IO to the card will be handled (and failed) by the dummy driver
+ * instead of calling into the module. Only functions for iso context
+ * 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();
return -1;
}
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
return -ENODEV;
}
-static struct fw_card_driver dummy_driver = {
+static const struct fw_card_driver dummy_driver_template = {
.enable = dummy_enable,
.update_phy_reg = dummy_update_phy_reg,
.set_config_rom = dummy_set_config_rom,
void fw_core_remove_card(struct fw_card *card)
{
+ struct fw_card_driver dummy_driver = dummy_driver_template;
+
card->driver->update_phy_reg(card, 4,
PHY_LINK_ACTIVE | PHY_CONTENDER, 0);
fw_core_initiate_bus_reset(card, 1);
list_del_init(&card->link);
mutex_unlock(&card_mutex);
- /* Set up the dummy driver. */
+ /* Switch off most of the card driver interface. */
+ dummy_driver.free_iso_context = card->driver->free_iso_context;
+ dummy_driver.stop_iso = card->driver->stop_iso;
card->driver = &dummy_driver;
fw_destroy_nodes(card);