staging: Add framebuffer driver for XGI chipsets
[safe/jmp/linux-2.6] / drivers / firewire / core-card.c
index 543fcca..9dcb304 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
-#include <linux/timer.h>
 #include <linux/workqueue.h>
 
 #include <asm/atomic.h>
 
 #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;
 }
@@ -57,10 +55,14 @@ static LIST_HEAD(card_list);
 static LIST_HEAD(descriptor_list);
 static int descriptor_count;
 
+static __be32 tmp_config_rom[256];
+/* 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)
-
+#define BIB_BUS_NAME           0x31333934 /* "1394" */
 #define BIB_LINK_SPEED(v)      ((v) <<  0)
 #define BIB_GENERATION(v)      ((v) <<  4)
 #define BIB_MAX_ROM(v)         ((v) <<  8)
@@ -70,13 +72,13 @@ static int descriptor_count;
 #define BIB_BMC                        ((1) << 28)
 #define BIB_ISC                        ((1) << 29)
 #define BIB_CMC                        ((1) << 30)
-#define BIB_IMC                        ((1) << 31)
+#define BIB_IRMC               ((1) << 31)
+#define NODE_CAPABILITIES      0x0c0083c0 /* per IEEE 1394 clause 8.3.2.6.5.2 */
 
-static u32 *generate_config_rom(struct fw_card *card, size_t *config_rom_length)
+static void 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
@@ -87,40 +89,39 @@ static u32 *generate_config_rom(struct fw_card *card, size_t *config_rom_length)
         * 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(BIB_BUS_NAME);
+       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_IRMC);
+       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(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;
        }
 
@@ -131,26 +132,30 @@ 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;
-
-       return config_rom;
+       WARN_ON(j != config_rom_length);
 }
 
 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);
+               generate_config_rom(card, tmp_config_rom);
+               card->driver->set_config_rom(card, tmp_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 +171,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 +194,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--;
@@ -196,8 +208,8 @@ static void allocate_broadcast_channel(struct fw_card *card, int generation)
 {
        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,
@@ -211,11 +223,8 @@ static const char gap_count_table[] = {
 
 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);
 }
 
@@ -230,7 +239,6 @@ static void fw_card_bm_work(struct work_struct *work)
        bool do_reset = false;
        bool root_device_is_running;
        bool root_device_is_cmc;
-       __be32 lock_data[2];
 
        spin_lock_irqsave(&card->lock, flags);
 
@@ -273,22 +281,23 @@ static void fw_card_bm_work(struct work_struct *work)
                        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)
@@ -398,13 +407,6 @@ static void fw_card_bm_work(struct work_struct *work)
        fw_card_put(card);
 }
 
-static void flush_timer_callback(unsigned long data)
-{
-       struct fw_card *card = (struct fw_card *)data;
-
-       fw_flush_transactions(card);
-}
-
 void fw_card_initialize(struct fw_card *card,
                        const struct fw_card_driver *driver,
                        struct device *device)
@@ -423,8 +425,6 @@ void fw_card_initialize(struct fw_card *card,
        init_completion(&card->done);
        INIT_LIST_HEAD(&card->transaction_list);
        spin_lock_init(&card->lock);
-       setup_timer(&card->flush_timer,
-                   flush_timer_callback, (unsigned long)card);
 
        card->local_node = NULL;
 
@@ -435,8 +435,6 @@ 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->max_receive = max_receive;
@@ -444,16 +442,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);
 
-       ret = card->driver->enable(card, config_rom, length);
-       if (ret < 0) {
-               mutex_lock(&card_mutex);
-               list_del(&card->link);
-               mutex_unlock(&card_mutex);
-       }
+       generate_config_rom(card, tmp_config_rom);
+       ret = card->driver->enable(card, tmp_config_rom, config_rom_length);
+       if (ret == 0)
+               list_add_tail(&card->link, &card_list);
+
+       mutex_unlock(&card_mutex);
 
        return ret;
 }
@@ -468,7 +463,8 @@ EXPORT_SYMBOL(fw_card_add);
  * 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;
@@ -481,7 +477,7 @@ static int dummy_update_phy_reg(struct fw_card *card, int address,
 }
 
 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
@@ -553,7 +549,6 @@ void fw_core_remove_card(struct fw_card *card)
        wait_for_completion(&card->done);
 
        WARN_ON(!list_empty(&card->transaction_list));
-       del_timer_sync(&card->flush_timer);
 }
 EXPORT_SYMBOL(fw_core_remove_card);