Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 16 Jun 2009 21:29:46 +0000 (14:29 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 16 Jun 2009 21:29:46 +0000 (14:29 -0700)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6:
  firewire: core: use more outbound tlabels
  firewire: core: don't update Broadcast_Channel if RFC 2734 conditions aren't met
  firewire: core: prepare for non-core children of card devices
  firewire: core: include linux/uaccess.h instead of asm/uaccess.h
  firewire: add parent-of-unit accessor
  firewire: rename source files
  firewire: reorganize header files
  firewire: clean up includes
  firewire: ohci: access bus_seconds atomically
  firewire: also use vendor ID in root directory for driver matches
  firewire: share device ID table type with ieee1394
  firewire: core: add sysfs attribute for easier udev rules
  firewire: core: check for missing struct update at build time, not run time
  firewire: core: improve check for local node

15 files changed:
drivers/firewire/Makefile
drivers/firewire/core-card.c [moved from drivers/firewire/fw-card.c with 97% similarity]
drivers/firewire/core-cdev.c [moved from drivers/firewire/fw-cdev.c with 99% similarity]
drivers/firewire/core-device.c [moved from drivers/firewire/fw-device.c with 88% similarity]
drivers/firewire/core-iso.c [moved from drivers/firewire/fw-iso.c with 99% similarity]
drivers/firewire/core-topology.c [moved from drivers/firewire/fw-topology.c with 97% similarity]
drivers/firewire/core-transaction.c [moved from drivers/firewire/fw-transaction.c with 97% similarity]
drivers/firewire/core.h [new file with mode: 0644]
drivers/firewire/fw-device.h [deleted file]
drivers/firewire/fw-topology.h [deleted file]
drivers/firewire/fw-transaction.h [deleted file]
drivers/firewire/ohci.c [moved from drivers/firewire/fw-ohci.c with 99% similarity]
drivers/firewire/ohci.h [moved from drivers/firewire/fw-ohci.h with 98% similarity]
drivers/firewire/sbp2.c [moved from drivers/firewire/fw-sbp2.c with 97% similarity]
include/linux/firewire.h [new file with mode: 0644]

index a7c31e9039c14c0912554ed981c1fa390ce7606d..bc3b9bf822bf1e15c661944edae679406e673a0e 100644 (file)
@@ -2,10 +2,10 @@
 # Makefile for the Linux IEEE 1394 implementation
 #
 
-firewire-core-y += fw-card.o fw-topology.o fw-transaction.o fw-iso.o \
-                   fw-device.o fw-cdev.o
-firewire-ohci-y += fw-ohci.o
-firewire-sbp2-y += fw-sbp2.o
+firewire-core-y += core-card.o core-cdev.o core-device.o \
+                   core-iso.o core-topology.o core-transaction.o
+firewire-ohci-y += ohci.o
+firewire-sbp2-y += sbp2.o
 
 obj-$(CONFIG_FIREWIRE) += firewire-core.o
 obj-$(CONFIG_FIREWIRE_OHCI) += firewire-ohci.o
similarity index 97%
rename from drivers/firewire/fw-card.c
rename to drivers/firewire/core-card.c
index 8b8c8c22f0fce384229eab085210a1aea4353cc8..4c1be64fdddd458a93bc8dd9ae0c156f7a5abf89 100644 (file)
  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
+#include <linux/bug.h>
 #include <linux/completion.h>
 #include <linux/crc-itu-t.h>
-#include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/errno.h>
+#include <linux/firewire.h>
+#include <linux/firewire-constants.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
 #include <linux/kref.h>
+#include <linux/list.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/timer.h>
+#include <linux/workqueue.h>
 
-#include "fw-transaction.h"
-#include "fw-topology.h"
-#include "fw-device.h"
+#include <asm/atomic.h>
+#include <asm/byteorder.h>
+
+#include "core.h"
 
 int fw_compute_block_crc(u32 *block)
 {
@@ -181,12 +190,6 @@ void fw_core_remove_descriptor(struct fw_descriptor *desc)
        mutex_unlock(&card_mutex);
 }
 
-static int set_broadcast_channel(struct device *dev, void *data)
-{
-       fw_device_set_broadcast_channel(fw_device(dev), (long)data);
-       return 0;
-}
-
 static void allocate_broadcast_channel(struct fw_card *card, int generation)
 {
        int channel, bandwidth = 0;
@@ -196,7 +199,7 @@ static void allocate_broadcast_channel(struct fw_card *card, int generation)
        if (channel == 31) {
                card->broadcast_channel_allocated = true;
                device_for_each_child(card->device, (void *)(long)generation,
-                                     set_broadcast_channel);
+                                     fw_device_set_broadcast_channel);
        }
 }
 
similarity index 99%
rename from drivers/firewire/fw-cdev.c
rename to drivers/firewire/core-cdev.c
index 7eb6594cc3e5b92e9891773ada1898a4f0831c38..d1d30c615b0f191c7fb33a313e64bfd37b2835d5 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/errno.h>
+#include <linux/firewire.h>
 #include <linux/firewire-cdev.h>
 #include <linux/idr.h>
 #include <linux/jiffies.h>
 #include <linux/preempt.h>
 #include <linux/spinlock.h>
 #include <linux/time.h>
+#include <linux/uaccess.h>
 #include <linux/vmalloc.h>
 #include <linux/wait.h>
 #include <linux/workqueue.h>
 
 #include <asm/system.h>
-#include <asm/uaccess.h>
 
-#include "fw-device.h"
-#include "fw-topology.h"
-#include "fw-transaction.h"
+#include "core.h"
 
 struct client {
        u32 version;
@@ -739,15 +738,11 @@ static void release_descriptor(struct client *client,
 static int ioctl_add_descriptor(struct client *client, void *buffer)
 {
        struct fw_cdev_add_descriptor *request = buffer;
-       struct fw_card *card = client->device->card;
        struct descriptor_resource *r;
        int ret;
 
        /* Access policy: Allow this ioctl only on local nodes' device files. */
-       spin_lock_irq(&card->lock);
-       ret = client->device->node_id != card->local_node->node_id;
-       spin_unlock_irq(&card->lock);
-       if (ret)
+       if (!client->device->is_local)
                return -ENOSYS;
 
        if (request->length > 256)
similarity index 88%
rename from drivers/firewire/fw-device.c
rename to drivers/firewire/core-device.c
index a47e2129d83d3a5f99aa7165a6600f3bea9b5383..97e656af2d22800e03d7c2302747ed7573ff71a7 100644 (file)
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/errno.h>
+#include <linux/firewire.h>
+#include <linux/firewire-constants.h>
 #include <linux/idr.h>
 #include <linux/jiffies.h>
 #include <linux/kobject.h>
 #include <linux/list.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/rwsem.h>
 #include <linux/semaphore.h>
 #include <linux/string.h>
 #include <linux/workqueue.h>
 
+#include <asm/atomic.h>
+#include <asm/byteorder.h>
 #include <asm/system.h>
 
-#include "fw-device.h"
-#include "fw-topology.h"
-#include "fw-transaction.h"
+#include "core.h"
 
 void fw_csr_iterator_init(struct fw_csr_iterator *ci, u32 * p)
 {
@@ -55,9 +59,10 @@ int fw_csr_iterator_next(struct fw_csr_iterator *ci, int *key, int *value)
 }
 EXPORT_SYMBOL(fw_csr_iterator_next);
 
-static int is_fw_unit(struct device *dev);
+static bool is_fw_unit(struct device *dev);
 
-static int match_unit_directory(u32 * directory, const struct fw_device_id *id)
+static int match_unit_directory(u32 *directory, u32 match_flags,
+                               const struct ieee1394_device_id *id)
 {
        struct fw_csr_iterator ci;
        int key, value, match;
@@ -65,31 +70,42 @@ static int match_unit_directory(u32 * directory, const struct fw_device_id *id)
        match = 0;
        fw_csr_iterator_init(&ci, directory);
        while (fw_csr_iterator_next(&ci, &key, &value)) {
-               if (key == CSR_VENDOR && value == id->vendor)
-                       match |= FW_MATCH_VENDOR;
-               if (key == CSR_MODEL && value == id->model)
-                       match |= FW_MATCH_MODEL;
+               if (key == CSR_VENDOR && value == id->vendor_id)
+                       match |= IEEE1394_MATCH_VENDOR_ID;
+               if (key == CSR_MODEL && value == id->model_id)
+                       match |= IEEE1394_MATCH_MODEL_ID;
                if (key == CSR_SPECIFIER_ID && value == id->specifier_id)
-                       match |= FW_MATCH_SPECIFIER_ID;
+                       match |= IEEE1394_MATCH_SPECIFIER_ID;
                if (key == CSR_VERSION && value == id->version)
-                       match |= FW_MATCH_VERSION;
+                       match |= IEEE1394_MATCH_VERSION;
        }
 
-       return (match & id->match_flags) == id->match_flags;
+       return (match & match_flags) == match_flags;
 }
 
 static int fw_unit_match(struct device *dev, struct device_driver *drv)
 {
        struct fw_unit *unit = fw_unit(dev);
-       struct fw_driver *driver = fw_driver(drv);
-       int i;
+       struct fw_device *device;
+       const struct ieee1394_device_id *id;
 
        /* We only allow binding to fw_units. */
        if (!is_fw_unit(dev))
                return 0;
 
-       for (i = 0; driver->id_table[i].match_flags != 0; i++) {
-               if (match_unit_directory(unit->directory, &driver->id_table[i]))
+       device = fw_parent_device(unit);
+       id = container_of(drv, struct fw_driver, driver)->id_table;
+
+       for (; id->match_flags != 0; id++) {
+               if (match_unit_directory(unit->directory, id->match_flags, id))
+                       return 1;
+
+               /* Also check vendor ID in the root directory. */
+               if ((id->match_flags & IEEE1394_MATCH_VENDOR_ID) &&
+                   match_unit_directory(&device->config_rom[5],
+                               IEEE1394_MATCH_VENDOR_ID, id) &&
+                   match_unit_directory(unit->directory, id->match_flags
+                               & ~IEEE1394_MATCH_VENDOR_ID, id))
                        return 1;
        }
 
@@ -98,7 +114,7 @@ static int fw_unit_match(struct device *dev, struct device_driver *drv)
 
 static int get_modalias(struct fw_unit *unit, char *buffer, size_t buffer_size)
 {
-       struct fw_device *device = fw_device(unit->device.parent);
+       struct fw_device *device = fw_parent_device(unit);
        struct fw_csr_iterator ci;
 
        int key, value;
@@ -292,8 +308,7 @@ static void init_fw_attribute_group(struct device *dev,
                group->attrs[j++] = &attr->attr;
        }
 
-       BUG_ON(j >= ARRAY_SIZE(group->attrs));
-       group->attrs[j++] = NULL;
+       group->attrs[j] = NULL;
        group->groups[0] = &group->group;
        group->groups[1] = NULL;
        group->group.attrs = group->attrs;
@@ -356,9 +371,56 @@ static ssize_t guid_show(struct device *dev,
        return ret;
 }
 
+static int units_sprintf(char *buf, u32 *directory)
+{
+       struct fw_csr_iterator ci;
+       int key, value;
+       int specifier_id = 0;
+       int version = 0;
+
+       fw_csr_iterator_init(&ci, directory);
+       while (fw_csr_iterator_next(&ci, &key, &value)) {
+               switch (key) {
+               case CSR_SPECIFIER_ID:
+                       specifier_id = value;
+                       break;
+               case CSR_VERSION:
+                       version = value;
+                       break;
+               }
+       }
+
+       return sprintf(buf, "0x%06x:0x%06x ", specifier_id, version);
+}
+
+static ssize_t units_show(struct device *dev,
+                         struct device_attribute *attr, char *buf)
+{
+       struct fw_device *device = fw_device(dev);
+       struct fw_csr_iterator ci;
+       int key, value, i = 0;
+
+       down_read(&fw_device_rwsem);
+       fw_csr_iterator_init(&ci, &device->config_rom[5]);
+       while (fw_csr_iterator_next(&ci, &key, &value)) {
+               if (key != (CSR_UNIT | CSR_DIRECTORY))
+                       continue;
+               i += units_sprintf(&buf[i], ci.p + value - 1);
+               if (i >= PAGE_SIZE - (8 + 1 + 8 + 1))
+                       break;
+       }
+       up_read(&fw_device_rwsem);
+
+       if (i)
+               buf[i - 1] = '\n';
+
+       return i;
+}
+
 static struct device_attribute fw_device_attributes[] = {
        __ATTR_RO(config_rom),
        __ATTR_RO(guid),
+       __ATTR_RO(units),
        __ATTR_NULL,
 };
 
@@ -518,7 +580,9 @@ static int read_bus_info_block(struct fw_device *device, int generation)
 
        kfree(old_rom);
        ret = 0;
-       device->cmc = rom[2] >> 30 & 1;
+       device->max_rec = rom[2] >> 12 & 0xf;
+       device->cmc     = rom[2] >> 30 & 1;
+       device->irmc    = rom[2] >> 31 & 1;
  out:
        kfree(rom);
 
@@ -537,7 +601,7 @@ static struct device_type fw_unit_type = {
        .release        = fw_unit_release,
 };
 
-static int is_fw_unit(struct device *dev)
+static bool is_fw_unit(struct device *dev)
 {
        return dev->type == &fw_unit_type;
 }
@@ -570,9 +634,13 @@ static void create_units(struct fw_device *device)
                unit->device.parent = &device->device;
                dev_set_name(&unit->device, "%s.%d", dev_name(&device->device), i++);
 
+               BUILD_BUG_ON(ARRAY_SIZE(unit->attribute_group.attrs) <
+                               ARRAY_SIZE(fw_unit_attributes) +
+                               ARRAY_SIZE(config_rom_attributes));
                init_fw_attribute_group(&unit->device,
                                        fw_unit_attributes,
                                        &unit->attribute_group);
+
                if (device_register(&unit->device) < 0)
                        goto skip_unit;
 
@@ -683,6 +751,11 @@ static struct device_type fw_device_type = {
        .release = fw_device_release,
 };
 
+static bool is_fw_device(struct device *dev)
+{
+       return dev->type == &fw_device_type;
+}
+
 static int update_unit(struct device *dev, void *data)
 {
        struct fw_unit *unit = fw_unit(dev);
@@ -719,6 +792,9 @@ static int lookup_existing_device(struct device *dev, void *data)
        struct fw_card *card = new->card;
        int match = 0;
 
+       if (!is_fw_device(dev))
+               return 0;
+
        down_read(&fw_device_rwsem); /* serialize config_rom access */
        spin_lock_irq(&card->lock);  /* serialize node access */
 
@@ -758,7 +834,7 @@ static int lookup_existing_device(struct device *dev, void *data)
 
 enum { BC_UNKNOWN = 0, BC_UNIMPLEMENTED, BC_IMPLEMENTED, };
 
-void fw_device_set_broadcast_channel(struct fw_device *device, int generation)
+static void set_broadcast_channel(struct fw_device *device, int generation)
 {
        struct fw_card *card = device->card;
        __be32 data;
@@ -767,6 +843,20 @@ void fw_device_set_broadcast_channel(struct fw_device *device, int generation)
        if (!card->broadcast_channel_allocated)
                return;
 
+       /*
+        * The Broadcast_Channel Valid bit is required by nodes which want to
+        * transmit on this channel.  Such transmissions are practically
+        * exclusive to IP over 1394 (RFC 2734).  IP capable nodes are required
+        * to be IRM capable and have a max_rec of 8 or more.  We use this fact
+        * to narrow down to which nodes we send Broadcast_Channel updates.
+        */
+       if (!device->irmc || device->max_rec < 8)
+               return;
+
+       /*
+        * Some 1394-1995 nodes crash if this 1394a-2000 register is written.
+        * Perform a read test first.
+        */
        if (device->bc_implemented == BC_UNKNOWN) {
                rcode = fw_run_transaction(card, TCODE_READ_QUADLET_REQUEST,
                                device->node_id, generation, device->max_speed,
@@ -794,6 +884,14 @@ void fw_device_set_broadcast_channel(struct fw_device *device, int generation)
        }
 }
 
+int fw_device_set_broadcast_channel(struct device *dev, void *gen)
+{
+       if (is_fw_device(dev))
+               set_broadcast_channel(fw_device(dev), (long)gen);
+
+       return 0;
+}
+
 static void fw_device_init(struct work_struct *work)
 {
        struct fw_device *device =
@@ -849,9 +947,13 @@ static void fw_device_init(struct work_struct *work)
        device->device.devt = MKDEV(fw_cdev_major, minor);
        dev_set_name(&device->device, "fw%d", minor);
 
+       BUILD_BUG_ON(ARRAY_SIZE(device->attribute_group.attrs) <
+                       ARRAY_SIZE(fw_device_attributes) +
+                       ARRAY_SIZE(config_rom_attributes));
        init_fw_attribute_group(&device->device,
                                fw_device_attributes,
                                &device->attribute_group);
+
        if (device_add(&device->device)) {
                fw_error("Failed to add device.\n");
                goto error_with_cdev;
@@ -888,7 +990,7 @@ static void fw_device_init(struct work_struct *work)
                                  1 << device->max_speed);
                device->config_rom_retries = 0;
 
-               fw_device_set_broadcast_channel(device, device->generation);
+               set_broadcast_channel(device, device->generation);
        }
 
        /*
@@ -993,6 +1095,9 @@ static void fw_device_refresh(struct work_struct *work)
 
        create_units(device);
 
+       /* Userspace may want to re-read attributes. */
+       kobject_uevent(&device->device.kobj, KOBJ_CHANGE);
+
        if (atomic_cmpxchg(&device->state,
                           FW_DEVICE_INITIALIZING,
                           FW_DEVICE_RUNNING) == FW_DEVICE_GONE)
@@ -1042,6 +1147,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
                device->node = fw_node_get(node);
                device->node_id = node->node_id;
                device->generation = card->generation;
+               device->is_local = node == card->local_node;
                mutex_init(&device->client_list_mutex);
                INIT_LIST_HEAD(&device->client_list);
 
@@ -1075,7 +1181,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
                            FW_DEVICE_INITIALIZING) == FW_DEVICE_RUNNING) {
                        PREPARE_DELAYED_WORK(&device->work, fw_device_refresh);
                        schedule_delayed_work(&device->work,
-                               node == card->local_node ? 0 : INITIAL_DELAY);
+                               device->is_local ? 0 : INITIAL_DELAY);
                }
                break;
 
similarity index 99%
rename from drivers/firewire/fw-iso.c
rename to drivers/firewire/core-iso.c
index 2baf1007253e66a972b357d37b62b1e245d26bcd..28076c892d7e8320d38b9f61c5f78163148b6a01 100644 (file)
 
 #include <linux/dma-mapping.h>
 #include <linux/errno.h>
+#include <linux/firewire.h>
 #include <linux/firewire-constants.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/spinlock.h>
 #include <linux/vmalloc.h>
 
-#include "fw-topology.h"
-#include "fw-transaction.h"
+#include <asm/byteorder.h>
+
+#include "core.h"
 
 /*
  * Isochronous DMA context management
similarity index 97%
rename from drivers/firewire/fw-topology.c
rename to drivers/firewire/core-topology.c
index d0deecc4de938440c99c1c6778ca0917e71491d0..fddf2b358936bd7b223a79bea5b4bd41147291d8 100644 (file)
  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
-#include <linux/module.h>
-#include <linux/wait.h>
+#include <linux/bug.h>
 #include <linux/errno.h>
-#include <asm/bug.h>
+#include <linux/firewire.h>
+#include <linux/firewire-constants.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+
+#include <asm/atomic.h>
 #include <asm/system.h>
-#include "fw-transaction.h"
-#include "fw-topology.h"
+
+#include "core.h"
 
 #define SELF_ID_PHY_ID(q)              (((q) >> 24) & 0x3f)
 #define SELF_ID_EXTENDED(q)            (((q) >> 23) & 0x01)
 
 #define SELF_ID_EXT_SEQUENCE(q)                (((q) >> 20) & 0x07)
 
+#define SELFID_PORT_CHILD      0x3
+#define SELFID_PORT_PARENT     0x2
+#define SELFID_PORT_NCONN      0x1
+#define SELFID_PORT_NONE       0x0
+
 static u32 *count_ports(u32 *sid, int *total_port_count, int *child_port_count)
 {
        u32 q;
similarity index 97%
rename from drivers/firewire/fw-transaction.c
rename to drivers/firewire/core-transaction.c
index 283dac6d327db100853c1768be00f37dbc346b10..479b22f5a1eb7889162643741357fdd6cd8948b4 100644 (file)
  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
+#include <linux/bug.h>
 #include <linux/completion.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/firewire.h>
+#include <linux/firewire-constants.h>
+#include <linux/fs.h>
+#include <linux/init.h>
 #include <linux/idr.h>
+#include <linux/jiffies.h>
 #include <linux/kernel.h>
-#include <linux/kref.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/poll.h>
 #include <linux/list.h>
-#include <linux/kthread.h>
-#include <asm/uaccess.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/types.h>
 
-#include "fw-transaction.h"
-#include "fw-topology.h"
-#include "fw-device.h"
+#include <asm/byteorder.h>
+
+#include "core.h"
 
 #define HEADER_PRI(pri)                        ((pri) << 0)
 #define HEADER_TCODE(tcode)            ((tcode) << 4)
 #define HEADER_DESTINATION_IS_BROADCAST(q) \
        (((q) & HEADER_DESTINATION(0x3f)) == HEADER_DESTINATION(0x3f))
 
+#define PHY_PACKET_CONFIG      0x0
+#define PHY_PACKET_LINK_ON     0x1
+#define PHY_PACKET_SELF_ID     0x2
+
 #define PHY_CONFIG_GAP_COUNT(gap_count)        (((gap_count) << 16) | (1 << 22))
 #define PHY_CONFIG_ROOT_ID(node_id)    ((((node_id) & 0x3f) << 24) | (1 << 23))
 #define PHY_IDENTIFIER(id)             ((id) << 30)
@@ -74,7 +82,7 @@ static int close_transaction(struct fw_transaction *transaction,
        list_for_each_entry(t, &card->transaction_list, link) {
                if (t == transaction) {
                        list_del(&t->link);
-                       card->tlabel_mask &= ~(1 << t->tlabel);
+                       card->tlabel_mask &= ~(1ULL << t->tlabel);
                        break;
                }
        }
@@ -280,14 +288,14 @@ void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode,
        spin_lock_irqsave(&card->lock, flags);
 
        tlabel = card->current_tlabel;
-       if (card->tlabel_mask & (1 << tlabel)) {
+       if (card->tlabel_mask & (1ULL << tlabel)) {
                spin_unlock_irqrestore(&card->lock, flags);
                callback(card, RCODE_SEND_ERROR, NULL, 0, callback_data);
                return;
        }
 
-       card->current_tlabel = (card->current_tlabel + 1) & 0x1f;
-       card->tlabel_mask |= (1 << tlabel);
+       card->current_tlabel = (card->current_tlabel + 1) & 0x3f;
+       card->tlabel_mask |= (1ULL << tlabel);
 
        t->node_id = destination_id;
        t->tlabel = tlabel;
diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h
new file mode 100644 (file)
index 0000000..0a25a7b
--- /dev/null
@@ -0,0 +1,293 @@
+#ifndef _FIREWIRE_CORE_H
+#define _FIREWIRE_CORE_H
+
+#include <linux/dma-mapping.h>
+#include <linux/fs.h>
+#include <linux/list.h>
+#include <linux/idr.h>
+#include <linux/mm_types.h>
+#include <linux/rwsem.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include <asm/atomic.h>
+
+struct device;
+struct fw_card;
+struct fw_device;
+struct fw_iso_buffer;
+struct fw_iso_context;
+struct fw_iso_packet;
+struct fw_node;
+struct fw_packet;
+
+
+/* -card */
+
+/* bitfields within the PHY registers */
+#define PHY_LINK_ACTIVE                0x80
+#define PHY_CONTENDER          0x40
+#define PHY_BUS_RESET          0x40
+#define PHY_BUS_SHORT_RESET    0x40
+
+#define BANDWIDTH_AVAILABLE_INITIAL    4915
+#define BROADCAST_CHANNEL_INITIAL      (1 << 31 | 31)
+#define BROADCAST_CHANNEL_VALID                (1 << 30)
+
+struct fw_card_driver {
+       /*
+        * Enable the given card with the given initial config rom.
+        * This function is expected to activate the card, and either
+        * enable the PHY or set the link_on bit and initiate a bus
+        * reset.
+        */
+       int (*enable)(struct fw_card *card, u32 *config_rom, size_t length);
+
+       int (*update_phy_reg)(struct fw_card *card, int address,
+                             int clear_bits, int set_bits);
+
+       /*
+        * Update the config rom for an enabled card.  This function
+        * should change the config rom that is presented on the bus
+        * an initiate a bus reset.
+        */
+       int (*set_config_rom)(struct fw_card *card,
+                             u32 *config_rom, size_t length);
+
+       void (*send_request)(struct fw_card *card, struct fw_packet *packet);
+       void (*send_response)(struct fw_card *card, struct fw_packet *packet);
+       /* Calling cancel is valid once a packet has been submitted. */
+       int (*cancel_packet)(struct fw_card *card, struct fw_packet *packet);
+
+       /*
+        * Allow the specified node ID to do direct DMA out and in of
+        * host memory.  The card will disable this for all node when
+        * a bus reset happens, so driver need to reenable this after
+        * bus reset.  Returns 0 on success, -ENODEV if the card
+        * doesn't support this, -ESTALE if the generation doesn't
+        * match.
+        */
+       int (*enable_phys_dma)(struct fw_card *card,
+                              int node_id, int generation);
+
+       u64 (*get_bus_time)(struct fw_card *card);
+
+       struct fw_iso_context *
+       (*allocate_iso_context)(struct fw_card *card,
+                               int type, int channel, size_t header_size);
+       void (*free_iso_context)(struct fw_iso_context *ctx);
+
+       int (*start_iso)(struct fw_iso_context *ctx,
+                        s32 cycle, u32 sync, u32 tags);
+
+       int (*queue_iso)(struct fw_iso_context *ctx,
+                        struct fw_iso_packet *packet,
+                        struct fw_iso_buffer *buffer,
+                        unsigned long payload);
+
+       int (*stop_iso)(struct fw_iso_context *ctx);
+};
+
+void fw_card_initialize(struct fw_card *card,
+               const struct fw_card_driver *driver, struct device *device);
+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);
+void fw_schedule_bm_work(struct fw_card *card, unsigned long delay);
+
+struct fw_descriptor {
+       struct list_head link;
+       size_t length;
+       u32 immediate;
+       u32 key;
+       const u32 *data;
+};
+
+int fw_core_add_descriptor(struct fw_descriptor *desc);
+void fw_core_remove_descriptor(struct fw_descriptor *desc);
+
+
+/* -cdev */
+
+extern const struct file_operations fw_device_ops;
+
+void fw_device_cdev_update(struct fw_device *device);
+void fw_device_cdev_remove(struct fw_device *device);
+
+
+/* -device */
+
+extern struct rw_semaphore fw_device_rwsem;
+extern struct idr fw_device_idr;
+extern int fw_cdev_major;
+
+struct fw_device *fw_device_get_by_devt(dev_t devt);
+int fw_device_set_broadcast_channel(struct device *dev, void *gen);
+void fw_node_event(struct fw_card *card, struct fw_node *node, int event);
+
+
+/* -iso */
+
+/*
+ * The iso packet format allows for an immediate header/payload part
+ * stored in 'header' immediately after the packet info plus an
+ * indirect payload part that is pointer to by the 'payload' field.
+ * Applications can use one or the other or both to implement simple
+ * low-bandwidth streaming (e.g. audio) or more advanced
+ * scatter-gather streaming (e.g. assembling video frame automatically).
+ */
+struct fw_iso_packet {
+       u16 payload_length;     /* Length of indirect payload. */
+       u32 interrupt:1;        /* Generate interrupt on this packet */
+       u32 skip:1;             /* Set to not send packet at all. */
+       u32 tag:2;
+       u32 sy:4;
+       u32 header_length:8;    /* Length of immediate header. */
+       u32 header[0];
+};
+
+#define FW_ISO_CONTEXT_TRANSMIT        0
+#define FW_ISO_CONTEXT_RECEIVE 1
+
+#define FW_ISO_CONTEXT_MATCH_TAG0       1
+#define FW_ISO_CONTEXT_MATCH_TAG1       2
+#define FW_ISO_CONTEXT_MATCH_TAG2       4
+#define FW_ISO_CONTEXT_MATCH_TAG3       8
+#define FW_ISO_CONTEXT_MATCH_ALL_TAGS  15
+
+/*
+ * An iso buffer is just a set of pages mapped for DMA in the
+ * specified direction.  Since the pages are to be used for DMA, they
+ * are not mapped into the kernel virtual address space.  We store the
+ * DMA address in the page private. The helper function
+ * fw_iso_buffer_map() will map the pages into a given vma.
+ */
+struct fw_iso_buffer {
+       enum dma_data_direction direction;
+       struct page **pages;
+       int page_count;
+};
+
+typedef void (*fw_iso_callback_t)(struct fw_iso_context *context,
+                                 u32 cycle, size_t header_length,
+                                 void *header, void *data);
+
+struct fw_iso_context {
+       struct fw_card *card;
+       int type;
+       int channel;
+       int speed;
+       size_t header_size;
+       fw_iso_callback_t callback;
+       void *callback_data;
+};
+
+int fw_iso_buffer_init(struct fw_iso_buffer *buffer, struct fw_card *card,
+                      int page_count, enum dma_data_direction direction);
+int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma);
+void fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, struct fw_card *card);
+
+struct fw_iso_context *fw_iso_context_create(struct fw_card *card,
+               int type, int channel, int speed, size_t header_size,
+               fw_iso_callback_t callback, void *callback_data);
+int fw_iso_context_queue(struct fw_iso_context *ctx,
+                        struct fw_iso_packet *packet,
+                        struct fw_iso_buffer *buffer,
+                        unsigned long payload);
+int fw_iso_context_start(struct fw_iso_context *ctx,
+                        int cycle, int sync, int tags);
+int fw_iso_context_stop(struct fw_iso_context *ctx);
+void fw_iso_context_destroy(struct fw_iso_context *ctx);
+
+void fw_iso_resource_manage(struct fw_card *card, int generation,
+               u64 channels_mask, int *channel, int *bandwidth, bool allocate);
+
+
+/* -topology */
+
+enum {
+       FW_NODE_CREATED,
+       FW_NODE_UPDATED,
+       FW_NODE_DESTROYED,
+       FW_NODE_LINK_ON,
+       FW_NODE_LINK_OFF,
+       FW_NODE_INITIATED_RESET,
+};
+
+struct fw_node {
+       u16 node_id;
+       u8 color;
+       u8 port_count;
+       u8 link_on:1;
+       u8 initiated_reset:1;
+       u8 b_path:1;
+       u8 phy_speed:2; /* As in the self ID packet. */
+       u8 max_speed:2; /* Minimum of all phy-speeds on the path from the
+                        * local node to this node. */
+       u8 max_depth:4; /* Maximum depth to any leaf node */
+       u8 max_hops:4;  /* Max hops in this sub tree */
+       atomic_t ref_count;
+
+       /* For serializing node topology into a list. */
+       struct list_head link;
+
+       /* Upper layer specific data. */
+       void *data;
+
+       struct fw_node *ports[0];
+};
+
+static inline struct fw_node *fw_node_get(struct fw_node *node)
+{
+       atomic_inc(&node->ref_count);
+
+       return node;
+}
+
+static inline void fw_node_put(struct fw_node *node)
+{
+       if (atomic_dec_and_test(&node->ref_count))
+               kfree(node);
+}
+
+void fw_core_handle_bus_reset(struct fw_card *card, int node_id,
+                             int generation, int self_id_count, u32 *self_ids);
+void fw_destroy_nodes(struct fw_card *card);
+
+/*
+ * Check whether new_generation is the immediate successor of old_generation.
+ * Take counter roll-over at 255 (as per OHCI) into account.
+ */
+static inline bool is_next_generation(int new_generation, int old_generation)
+{
+       return (new_generation & 0xff) == ((old_generation + 1) & 0xff);
+}
+
+
+/* -transaction */
+
+#define TCODE_IS_READ_REQUEST(tcode)   (((tcode) & ~1) == 4)
+#define TCODE_IS_BLOCK_PACKET(tcode)   (((tcode) &  1) != 0)
+#define TCODE_IS_REQUEST(tcode)                (((tcode) &  2) == 0)
+#define TCODE_IS_RESPONSE(tcode)       (((tcode) &  2) != 0)
+#define TCODE_HAS_REQUEST_DATA(tcode)  (((tcode) & 12) != 4)
+#define TCODE_HAS_RESPONSE_DATA(tcode) (((tcode) & 12) != 0)
+
+#define LOCAL_BUS 0xffc0
+
+void fw_core_handle_request(struct fw_card *card, struct fw_packet *request);
+void fw_core_handle_response(struct fw_card *card, struct fw_packet *packet);
+void fw_fill_response(struct fw_packet *response, u32 *request_header,
+                     int rcode, void *payload, size_t length);
+void fw_flush_transactions(struct fw_card *card);
+void fw_send_phy_config(struct fw_card *card,
+                       int node_id, int generation, int gap_count);
+
+static inline int fw_stream_packet_destination_id(int tag, int channel, int sy)
+{
+       return tag << 14 | channel << 8 | sy;
+}
+
+#endif /* _FIREWIRE_CORE_H */
diff --git a/drivers/firewire/fw-device.h b/drivers/firewire/fw-device.h
deleted file mode 100644 (file)
index 9758893..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * Copyright (C) 2005-2006  Kristian Hoegsberg <krh@bitplanet.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef __fw_device_h
-#define __fw_device_h
-
-#include <linux/device.h>
-#include <linux/fs.h>
-#include <linux/idr.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/mutex.h>
-#include <linux/rwsem.h>
-#include <linux/sysfs.h>
-#include <linux/types.h>
-#include <linux/workqueue.h>
-
-#include <asm/atomic.h>
-
-enum fw_device_state {
-       FW_DEVICE_INITIALIZING,
-       FW_DEVICE_RUNNING,
-       FW_DEVICE_GONE,
-       FW_DEVICE_SHUTDOWN,
-};
-
-struct fw_attribute_group {
-       struct attribute_group *groups[2];
-       struct attribute_group group;
-       struct attribute *attrs[11];
-};
-
-struct fw_node;
-struct fw_card;
-
-/*
- * Note, fw_device.generation always has to be read before fw_device.node_id.
- * Use SMP memory barriers to ensure this.  Otherwise requests will be sent
- * to an outdated node_id if the generation was updated in the meantime due
- * to a bus reset.
- *
- * Likewise, fw-core will take care to update .node_id before .generation so
- * that whenever fw_device.generation is current WRT the actual bus generation,
- * fw_device.node_id is guaranteed to be current too.
- *
- * The same applies to fw_device.card->node_id vs. fw_device.generation.
- *
- * fw_device.config_rom and fw_device.config_rom_length may be accessed during
- * the lifetime of any fw_unit belonging to the fw_device, before device_del()
- * was called on the last fw_unit.  Alternatively, they may be accessed while
- * holding fw_device_rwsem.
- */
-struct fw_device {
-       atomic_t state;
-       struct fw_node *node;
-       int node_id;
-       int generation;
-       unsigned max_speed;
-       struct fw_card *card;
-       struct device device;
-
-       struct mutex client_list_mutex;
-       struct list_head client_list;
-
-       u32 *config_rom;
-       size_t config_rom_length;
-       int config_rom_retries;
-       unsigned cmc:1;
-       unsigned bc_implemented:2;
-
-       struct delayed_work work;
-       struct fw_attribute_group attribute_group;
-};
-
-static inline struct fw_device *fw_device(struct device *dev)
-{
-       return container_of(dev, struct fw_device, device);
-}
-
-static inline int fw_device_is_shutdown(struct fw_device *device)
-{
-       return atomic_read(&device->state) == FW_DEVICE_SHUTDOWN;
-}
-
-static inline struct fw_device *fw_device_get(struct fw_device *device)
-{
-       get_device(&device->device);
-
-       return device;
-}
-
-static inline void fw_device_put(struct fw_device *device)
-{
-       put_device(&device->device);
-}
-
-struct fw_device *fw_device_get_by_devt(dev_t devt);
-int fw_device_enable_phys_dma(struct fw_device *device);
-void fw_device_set_broadcast_channel(struct fw_device *device, int generation);
-
-void fw_device_cdev_update(struct fw_device *device);
-void fw_device_cdev_remove(struct fw_device *device);
-
-extern struct rw_semaphore fw_device_rwsem;
-extern struct idr fw_device_idr;
-extern int fw_cdev_major;
-
-/*
- * fw_unit.directory must not be accessed after device_del(&fw_unit.device).
- */
-struct fw_unit {
-       struct device device;
-       u32 *directory;
-       struct fw_attribute_group attribute_group;
-};
-
-static inline struct fw_unit *fw_unit(struct device *dev)
-{
-       return container_of(dev, struct fw_unit, device);
-}
-
-static inline struct fw_unit *fw_unit_get(struct fw_unit *unit)
-{
-       get_device(&unit->device);
-
-       return unit;
-}
-
-static inline void fw_unit_put(struct fw_unit *unit)
-{
-       put_device(&unit->device);
-}
-
-#define CSR_OFFSET     0x40
-#define CSR_LEAF       0x80
-#define CSR_DIRECTORY  0xc0
-
-#define CSR_DESCRIPTOR         0x01
-#define CSR_VENDOR             0x03
-#define CSR_HARDWARE_VERSION   0x04
-#define CSR_NODE_CAPABILITIES  0x0c
-#define CSR_UNIT               0x11
-#define CSR_SPECIFIER_ID       0x12
-#define CSR_VERSION            0x13
-#define CSR_DEPENDENT_INFO     0x14
-#define CSR_MODEL              0x17
-#define CSR_INSTANCE           0x18
-#define CSR_DIRECTORY_ID       0x20
-
-struct fw_csr_iterator {
-       u32 *p;
-       u32 *end;
-};
-
-void fw_csr_iterator_init(struct fw_csr_iterator *ci, u32 *p);
-int fw_csr_iterator_next(struct fw_csr_iterator *ci,
-                        int *key, int *value);
-
-#define FW_MATCH_VENDOR                0x0001
-#define FW_MATCH_MODEL         0x0002
-#define FW_MATCH_SPECIFIER_ID  0x0004
-#define FW_MATCH_VERSION       0x0008
-
-struct fw_device_id {
-       u32 match_flags;
-       u32 vendor;
-       u32 model;
-       u32 specifier_id;
-       u32 version;
-       void *driver_data;
-};
-
-struct fw_driver {
-       struct device_driver driver;
-       /* Called when the parent device sits through a bus reset. */
-       void (*update) (struct fw_unit *unit);
-       const struct fw_device_id *id_table;
-};
-
-static inline struct fw_driver *fw_driver(struct device_driver *drv)
-{
-       return container_of(drv, struct fw_driver, driver);
-}
-
-extern const struct file_operations fw_device_ops;
-
-#endif /* __fw_device_h */
diff --git a/drivers/firewire/fw-topology.h b/drivers/firewire/fw-topology.h
deleted file mode 100644 (file)
index 3c497bb..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2003-2006 Kristian Hoegsberg <krh@bitplanet.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef __fw_topology_h
-#define __fw_topology_h
-
-#include <linux/list.h>
-#include <linux/slab.h>
-
-#include <asm/atomic.h>
-
-enum {
-       FW_NODE_CREATED,
-       FW_NODE_UPDATED,
-       FW_NODE_DESTROYED,
-       FW_NODE_LINK_ON,
-       FW_NODE_LINK_OFF,
-       FW_NODE_INITIATED_RESET,
-};
-
-struct fw_node {
-       u16 node_id;
-       u8 color;
-       u8 port_count;
-       u8 link_on : 1;
-       u8 initiated_reset : 1;
-       u8 b_path : 1;
-       u8 phy_speed : 2; /* As in the self ID packet. */
-       u8 max_speed : 2; /* Minimum of all phy-speeds on the path from the
-                          * local node to this node. */
-       u8 max_depth : 4; /* Maximum depth to any leaf node */
-       u8 max_hops : 4;  /* Max hops in this sub tree */
-       atomic_t ref_count;
-
-       /* For serializing node topology into a list. */
-       struct list_head link;
-
-       /* Upper layer specific data. */
-       void *data;
-
-       struct fw_node *ports[0];
-};
-
-static inline struct fw_node *fw_node_get(struct fw_node *node)
-{
-       atomic_inc(&node->ref_count);
-
-       return node;
-}
-
-static inline void fw_node_put(struct fw_node *node)
-{
-       if (atomic_dec_and_test(&node->ref_count))
-               kfree(node);
-}
-
-struct fw_card;
-void fw_destroy_nodes(struct fw_card *card);
-
-int fw_compute_block_crc(u32 *block);
-
-#endif /* __fw_topology_h */
diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h
deleted file mode 100644 (file)
index dfa7990..0000000
+++ /dev/null
@@ -1,446 +0,0 @@
-/*
- * Copyright (C) 2003-2006 Kristian Hoegsberg <krh@bitplanet.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef __fw_transaction_h
-#define __fw_transaction_h
-
-#include <linux/completion.h>
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <linux/firewire-constants.h>
-#include <linux/kref.h>
-#include <linux/list.h>
-#include <linux/spinlock_types.h>
-#include <linux/timer.h>
-#include <linux/types.h>
-#include <linux/workqueue.h>
-
-#define TCODE_IS_READ_REQUEST(tcode)   (((tcode) & ~1) == 4)
-#define TCODE_IS_BLOCK_PACKET(tcode)   (((tcode) &  1) != 0)
-#define TCODE_IS_REQUEST(tcode)                (((tcode) &  2) == 0)
-#define TCODE_IS_RESPONSE(tcode)       (((tcode) &  2) != 0)
-#define TCODE_HAS_REQUEST_DATA(tcode)  (((tcode) & 12) != 4)
-#define TCODE_HAS_RESPONSE_DATA(tcode) (((tcode) & 12) != 0)
-
-#define LOCAL_BUS 0xffc0
-
-#define SELFID_PORT_CHILD      0x3
-#define SELFID_PORT_PARENT     0x2
-#define SELFID_PORT_NCONN      0x1
-#define SELFID_PORT_NONE       0x0
-
-#define PHY_PACKET_CONFIG      0x0
-#define PHY_PACKET_LINK_ON     0x1
-#define PHY_PACKET_SELF_ID     0x2
-
-/* Bit fields _within_ the PHY registers. */
-#define PHY_LINK_ACTIVE                0x80
-#define PHY_CONTENDER          0x40
-#define PHY_BUS_RESET          0x40
-#define PHY_BUS_SHORT_RESET    0x40
-
-#define CSR_REGISTER_BASE              0xfffff0000000ULL
-
-/* register offsets relative to CSR_REGISTER_BASE */
-#define CSR_STATE_CLEAR                        0x0
-#define CSR_STATE_SET                  0x4
-#define CSR_NODE_IDS                   0x8
-#define CSR_RESET_START                        0xc
-#define CSR_SPLIT_TIMEOUT_HI           0x18
-#define CSR_SPLIT_TIMEOUT_LO           0x1c
-#define CSR_CYCLE_TIME                 0x200
-#define CSR_BUS_TIME                   0x204
-#define CSR_BUSY_TIMEOUT               0x210
-#define CSR_BUS_MANAGER_ID             0x21c
-#define CSR_BANDWIDTH_AVAILABLE                0x220
-#define CSR_CHANNELS_AVAILABLE         0x224
-#define CSR_CHANNELS_AVAILABLE_HI      0x224
-#define CSR_CHANNELS_AVAILABLE_LO      0x228
-#define CSR_BROADCAST_CHANNEL          0x234
-#define CSR_CONFIG_ROM                 0x400
-#define CSR_CONFIG_ROM_END             0x800
-#define CSR_FCP_COMMAND                        0xB00
-#define CSR_FCP_RESPONSE               0xD00
-#define CSR_FCP_END                    0xF00
-#define CSR_TOPOLOGY_MAP               0x1000
-#define CSR_TOPOLOGY_MAP_END           0x1400
-#define CSR_SPEED_MAP                  0x2000
-#define CSR_SPEED_MAP_END              0x3000
-
-#define BANDWIDTH_AVAILABLE_INITIAL    4915
-#define BROADCAST_CHANNEL_INITIAL      (1 << 31 | 31)
-#define BROADCAST_CHANNEL_VALID                (1 << 30)
-
-#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);
-}
-
-struct fw_card;
-struct fw_packet;
-struct fw_node;
-struct fw_request;
-
-struct fw_descriptor {
-       struct list_head link;
-       size_t length;
-       u32 immediate;
-       u32 key;
-       const u32 *data;
-};
-
-int fw_core_add_descriptor(struct fw_descriptor *desc);
-void fw_core_remove_descriptor(struct fw_descriptor *desc);
-
-typedef void (*fw_packet_callback_t)(struct fw_packet *packet,
-                                    struct fw_card *card, int status);
-
-typedef void (*fw_transaction_callback_t)(struct fw_card *card, int rcode,
-                                         void *data, size_t length,
-                                         void *callback_data);
-
-/*
- * Important note:  The callback must guarantee that either fw_send_response()
- * or kfree() is called on the @request.
- */
-typedef void (*fw_address_callback_t)(struct fw_card *card,
-                                     struct fw_request *request,
-                                     int tcode, int destination, int source,
-                                     int generation, int speed,
-                                     unsigned long long offset,
-                                     void *data, size_t length,
-                                     void *callback_data);
-
-struct fw_packet {
-       int speed;
-       int generation;
-       u32 header[4];
-       size_t header_length;
-       void *payload;
-       size_t payload_length;
-       dma_addr_t payload_bus;
-       u32 timestamp;
-
-       /*
-        * This callback is called when the packet transmission has
-        * completed; for successful transmission, the status code is
-        * the ack received from the destination, otherwise it's a
-        * negative errno: ENOMEM, ESTALE, ETIMEDOUT, ENODEV, EIO.
-        * The callback can be called from tasklet context and thus
-        * must never block.
-        */
-       fw_packet_callback_t callback;
-       int ack;
-       struct list_head link;
-       void *driver_data;
-};
-
-struct fw_transaction {
-       int node_id; /* The generation is implied; it is always the current. */
-       int tlabel;
-       int timestamp;
-       struct list_head link;
-
-       struct fw_packet packet;
-
-       /*
-        * The data passed to the callback is valid only during the
-        * callback.
-        */
-       fw_transaction_callback_t callback;
-       void *callback_data;
-};
-
-struct fw_address_handler {
-       u64 offset;
-       size_t length;
-       fw_address_callback_t address_callback;
-       void *callback_data;
-       struct list_head link;
-};
-
-struct fw_address_region {
-       u64 start;
-       u64 end;
-};
-
-extern const struct fw_address_region fw_high_memory_region;
-
-int fw_core_add_address_handler(struct fw_address_handler *handler,
-                               const struct fw_address_region *region);
-void fw_core_remove_address_handler(struct fw_address_handler *handler);
-void fw_fill_response(struct fw_packet *response, u32 *request_header,
-                     int rcode, void *payload, size_t length);
-void fw_send_response(struct fw_card *card,
-                     struct fw_request *request, int rcode);
-
-extern struct bus_type fw_bus_type;
-
-struct fw_card {
-       const struct fw_card_driver *driver;
-       struct device *device;
-       struct kref kref;
-       struct completion done;
-
-       int node_id;
-       int generation;
-       int current_tlabel, tlabel_mask;
-       struct list_head transaction_list;
-       struct timer_list flush_timer;
-       unsigned long reset_jiffies;
-
-       unsigned long long guid;
-       unsigned max_receive;
-       int link_speed;
-       int config_rom_generation;
-
-       spinlock_t lock; /* Take this lock when handling the lists in
-                         * this struct. */
-       struct fw_node *local_node;
-       struct fw_node *root_node;
-       struct fw_node *irm_node;
-       u8 color; /* must be u8 to match the definition in struct fw_node */
-       int gap_count;
-       bool beta_repeaters_present;
-
-       int index;
-
-       struct list_head link;
-
-       /* Work struct for BM duties. */
-       struct delayed_work work;
-       int bm_retries;
-       int bm_generation;
-
-       bool broadcast_channel_allocated;
-       u32 broadcast_channel;
-       u32 topology_map[(CSR_TOPOLOGY_MAP_END - CSR_TOPOLOGY_MAP) / 4];
-};
-
-static inline struct fw_card *fw_card_get(struct fw_card *card)
-{
-       kref_get(&card->kref);
-
-       return card;
-}
-
-void fw_card_release(struct kref *kref);
-
-static inline void fw_card_put(struct fw_card *card)
-{
-       kref_put(&card->kref, fw_card_release);
-}
-
-extern void fw_schedule_bm_work(struct fw_card *card, unsigned long delay);
-
-/*
- * Check whether new_generation is the immediate successor of old_generation.
- * Take counter roll-over at 255 (as per to OHCI) into account.
- */
-static inline bool is_next_generation(int new_generation, int old_generation)
-{
-       return (new_generation & 0xff) == ((old_generation + 1) & 0xff);
-}
-
-/*
- * The iso packet format allows for an immediate header/payload part
- * stored in 'header' immediately after the packet info plus an
- * indirect payload part that is pointer to by the 'payload' field.
- * Applications can use one or the other or both to implement simple
- * low-bandwidth streaming (e.g. audio) or more advanced
- * scatter-gather streaming (e.g. assembling video frame automatically).
- */
-
-struct fw_iso_packet {
-       u16 payload_length;     /* Length of indirect payload. */
-       u32 interrupt : 1;      /* Generate interrupt on this packet */
-       u32 skip : 1;           /* Set to not send packet at all. */
-       u32 tag : 2;
-       u32 sy : 4;
-       u32 header_length : 8;  /* Length of immediate header. */
-       u32 header[0];
-};
-
-#define FW_ISO_CONTEXT_TRANSMIT        0
-#define FW_ISO_CONTEXT_RECEIVE 1
-
-#define FW_ISO_CONTEXT_MATCH_TAG0       1
-#define FW_ISO_CONTEXT_MATCH_TAG1       2
-#define FW_ISO_CONTEXT_MATCH_TAG2       4
-#define FW_ISO_CONTEXT_MATCH_TAG3       8
-#define FW_ISO_CONTEXT_MATCH_ALL_TAGS  15
-
-struct fw_iso_context;
-
-typedef void (*fw_iso_callback_t)(struct fw_iso_context *context,
-                                 u32 cycle, size_t header_length,
-                                 void *header, void *data);
-
-/*
- * An iso buffer is just a set of pages mapped for DMA in the
- * specified direction.  Since the pages are to be used for DMA, they
- * are not mapped into the kernel virtual address space.  We store the
- * DMA address in the page private. The helper function
- * fw_iso_buffer_map() will map the pages into a given vma.
- */
-
-struct fw_iso_buffer {
-       enum dma_data_direction direction;
-       struct page **pages;
-       int page_count;
-};
-
-struct fw_iso_context {
-       struct fw_card *card;
-       int type;
-       int channel;
-       int speed;
-       size_t header_size;
-       fw_iso_callback_t callback;
-       void *callback_data;
-};
-
-int fw_iso_buffer_init(struct fw_iso_buffer *buffer, struct fw_card *card,
-                      int page_count, enum dma_data_direction direction);
-int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma);
-void fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, struct fw_card *card);
-
-struct fw_iso_context *fw_iso_context_create(struct fw_card *card,
-               int type, int channel, int speed, size_t header_size,
-               fw_iso_callback_t callback, void *callback_data);
-int fw_iso_context_queue(struct fw_iso_context *ctx,
-                        struct fw_iso_packet *packet,
-                        struct fw_iso_buffer *buffer,
-                        unsigned long payload);
-int fw_iso_context_start(struct fw_iso_context *ctx,
-                        int cycle, int sync, int tags);
-int fw_iso_context_stop(struct fw_iso_context *ctx);
-void fw_iso_context_destroy(struct fw_iso_context *ctx);
-
-void fw_iso_resource_manage(struct fw_card *card, int generation,
-               u64 channels_mask, int *channel, int *bandwidth, bool allocate);
-
-struct fw_card_driver {
-       /*
-        * Enable the given card with the given initial config rom.
-        * This function is expected to activate the card, and either
-        * enable the PHY or set the link_on bit and initiate a bus
-        * reset.
-        */
-       int (*enable)(struct fw_card *card, u32 *config_rom, size_t length);
-
-       int (*update_phy_reg)(struct fw_card *card, int address,
-                             int clear_bits, int set_bits);
-
-       /*
-        * Update the config rom for an enabled card.  This function
-        * should change the config rom that is presented on the bus
-        * an initiate a bus reset.
-        */
-       int (*set_config_rom)(struct fw_card *card,
-                             u32 *config_rom, size_t length);
-
-       void (*send_request)(struct fw_card *card, struct fw_packet *packet);
-       void (*send_response)(struct fw_card *card, struct fw_packet *packet);
-       /* Calling cancel is valid once a packet has been submitted. */
-       int (*cancel_packet)(struct fw_card *card, struct fw_packet *packet);
-
-       /*
-        * Allow the specified node ID to do direct DMA out and in of
-        * host memory.  The card will disable this for all node when
-        * a bus reset happens, so driver need to reenable this after
-        * bus reset.  Returns 0 on success, -ENODEV if the card
-        * doesn't support this, -ESTALE if the generation doesn't
-        * match.
-        */
-       int (*enable_phys_dma)(struct fw_card *card,
-                              int node_id, int generation);
-
-       u64 (*get_bus_time)(struct fw_card *card);
-
-       struct fw_iso_context *
-       (*allocate_iso_context)(struct fw_card *card,
-                               int type, int channel, size_t header_size);
-       void (*free_iso_context)(struct fw_iso_context *ctx);
-
-       int (*start_iso)(struct fw_iso_context *ctx,
-                        s32 cycle, u32 sync, u32 tags);
-
-       int (*queue_iso)(struct fw_iso_context *ctx,
-                        struct fw_iso_packet *packet,
-                        struct fw_iso_buffer *buffer,
-                        unsigned long payload);
-
-       int (*stop_iso)(struct fw_iso_context *ctx);
-};
-
-int fw_core_initiate_bus_reset(struct fw_card *card, int short_reset);
-
-void fw_send_request(struct fw_card *card, struct fw_transaction *t,
-               int tcode, int destination_id, int generation, int speed,
-               unsigned long long offset, void *payload, size_t length,
-               fw_transaction_callback_t callback, void *callback_data);
-int fw_cancel_transaction(struct fw_card *card,
-                         struct fw_transaction *transaction);
-void fw_flush_transactions(struct fw_card *card);
-int fw_run_transaction(struct fw_card *card, int tcode, int destination_id,
-                      int generation, int speed, unsigned long long offset,
-                      void *payload, size_t length);
-void fw_send_phy_config(struct fw_card *card,
-                       int node_id, int generation, int gap_count);
-
-static inline int fw_stream_packet_destination_id(int tag, int channel, int sy)
-{
-       return tag << 14 | channel << 8 | sy;
-}
-
-/*
- * Called by the topology code to inform the device code of node
- * activity; found, lost, or updated nodes.
- */
-void fw_node_event(struct fw_card *card, struct fw_node *node, int event);
-
-/* API used by card level drivers */
-
-void fw_card_initialize(struct fw_card *card,
-               const struct fw_card_driver *driver, struct device *device);
-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);
-void fw_core_handle_bus_reset(struct fw_card *card, int node_id,
-               int generation, int self_id_count, u32 *self_ids);
-void fw_core_handle_request(struct fw_card *card, struct fw_packet *request);
-void fw_core_handle_response(struct fw_card *card, struct fw_packet *packet);
-
-extern int fw_irm_set_broadcast_channel_register(struct device *dev,
-                                                void *data);
-
-#endif /* __fw_transaction_h */
similarity index 99%
rename from drivers/firewire/fw-ohci.c
rename to drivers/firewire/ohci.c
index 1180d0be0bb4c0536cd7917cbd68910518f67450..ecddd11b797a366d105763656dd4eda2c2273add 100644 (file)
 
 #include <linux/compiler.h>
 #include <linux/delay.h>
+#include <linux/device.h>
 #include <linux/dma-mapping.h>
+#include <linux/firewire.h>
+#include <linux/firewire-constants.h>
 #include <linux/gfp.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/io.h>
 #include <linux/kernel.h>
+#include <linux/list.h>
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/pci.h>
 #include <linux/spinlock.h>
+#include <linux/string.h>
 
+#include <asm/atomic.h>
+#include <asm/byteorder.h>
 #include <asm/page.h>
 #include <asm/system.h>
 
@@ -38,8 +46,8 @@
 #include <asm/pmac_feature.h>
 #endif
 
-#include "fw-ohci.h"
-#include "fw-transaction.h"
+#include "core.h"
+#include "ohci.h"
 
 #define DESCRIPTOR_OUTPUT_MORE         0
 #define DESCRIPTOR_OUTPUT_LAST         (1 << 12)
@@ -178,7 +186,7 @@ struct fw_ohci {
        int node_id;
        int generation;
        int request_generation; /* for timestamping incoming requests */
-       u32 bus_seconds;
+       atomic_t bus_seconds;
 
        bool use_dualbuffer;
        bool old_uninorth;
@@ -231,7 +239,6 @@ static inline struct fw_ohci *fw_ohci(struct fw_card *card)
 #define OHCI1394_MAX_AT_RESP_RETRIES   0x2
 #define OHCI1394_MAX_PHYS_RESP_RETRIES 0x8
 
-#define FW_OHCI_MAJOR                  240
 #define OHCI1394_REGISTER_SIZE         0x800
 #define OHCI_LOOP_COUNT                        500
 #define OHCI1394_PCI_HCI_Control       0x40
@@ -1434,7 +1441,7 @@ static irqreturn_t irq_handler(int irq, void *data)
        if (event & OHCI1394_cycle64Seconds) {
                cycle_time = reg_read(ohci, OHCI1394_IsochronousCycleTimer);
                if ((cycle_time & 0x80000000) == 0)
-                       ohci->bus_seconds++;
+                       atomic_inc(&ohci->bus_seconds);
        }
 
        return IRQ_HANDLED;
@@ -1770,7 +1777,7 @@ static u64 ohci_get_bus_time(struct fw_card *card)
        u64 bus_time;
 
        cycle_time = reg_read(ohci, OHCI1394_IsochronousCycleTimer);
-       bus_time = ((u64) ohci->bus_seconds << 32) | cycle_time;
+       bus_time = ((u64)atomic_read(&ohci->bus_seconds) << 32) | cycle_time;
 
        return bus_time;
 }
similarity index 98%
rename from drivers/firewire/fw-ohci.h
rename to drivers/firewire/ohci.h
index a2fbb6240ca75033e683edafd56b934856d2613b..ba492d85c516260c33339c953296408e23437e16 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __fw_ohci_h
-#define __fw_ohci_h
+#ifndef _FIREWIRE_OHCI_H
+#define _FIREWIRE_OHCI_H
 
 /* OHCI register map */
 
 
 #define OHCI1394_phy_tcode             0xe
 
-#endif /* __fw_ohci_h */
+#endif /* _FIREWIRE_OHCI_H */
similarity index 97%
rename from drivers/firewire/fw-sbp2.c
rename to drivers/firewire/sbp2.c
index a70e66e78c7b8bedfadfc85dc3e434a219aede42..24c45635376a746ba9ae3e69ef53cfa7da1ab514 100644 (file)
 
 #include <linux/blkdev.h>
 #include <linux/bug.h>
+#include <linux/completion.h>
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
+#include <linux/firewire.h>
+#include <linux/firewire-constants.h>
+#include <linux/init.h>
+#include <linux/jiffies.h>
 #include <linux/kernel.h>
+#include <linux/kref.h>
+#include <linux/list.h>
 #include <linux/mod_devicetable.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/scatterlist.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
 #include <linux/string.h>
 #include <linux/stringify.h>
-#include <linux/timer.h>
 #include <linux/workqueue.h>
+
+#include <asm/byteorder.h>
 #include <asm/system.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
 
-#include "fw-device.h"
-#include "fw-topology.h"
-#include "fw-transaction.h"
-
 /*
  * So far only bridges from Oxford Semiconductor are known to support
  * concurrent logins. Depending on firmware, four or two concurrent logins
@@ -174,6 +180,11 @@ struct sbp2_target {
        int blocked;    /* ditto */
 };
 
+static struct fw_device *target_device(struct sbp2_target *tgt)
+{
+       return fw_parent_device(tgt->unit);
+}
+
 /* Impossible login_id, to detect logout attempt before successful login */
 #define INVALID_LOGIN_ID 0x10000
 
@@ -482,7 +493,7 @@ static void complete_transaction(struct fw_card *card, int rcode,
 static void sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu,
                          int node_id, int generation, u64 offset)
 {
-       struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
+       struct fw_device *device = target_device(lu->tgt);
        unsigned long flags;
 
        orb->pointer.high = 0;
@@ -504,7 +515,7 @@ static void sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu,
 
 static int sbp2_cancel_orbs(struct sbp2_logical_unit *lu)
 {
-       struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
+       struct fw_device *device = target_device(lu->tgt);
        struct sbp2_orb *orb, *next;
        struct list_head list;
        unsigned long flags;
@@ -542,7 +553,7 @@ static int sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id,
                                    int generation, int function,
                                    int lun_or_login_id, void *response)
 {
-       struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
+       struct fw_device *device = target_device(lu->tgt);
        struct sbp2_management_orb *orb;
        unsigned int timeout;
        int retval = -ENOMEM;
@@ -638,7 +649,7 @@ static int sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id,
 
 static void sbp2_agent_reset(struct sbp2_logical_unit *lu)
 {
-       struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
+       struct fw_device *device = target_device(lu->tgt);
        __be32 d = 0;
 
        fw_run_transaction(device->card, TCODE_WRITE_QUADLET_REQUEST,
@@ -655,7 +666,7 @@ static void complete_agent_reset_write_no_wait(struct fw_card *card,
 
 static void sbp2_agent_reset_no_wait(struct sbp2_logical_unit *lu)
 {
-       struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
+       struct fw_device *device = target_device(lu->tgt);
        struct fw_transaction *t;
        static __be32 d;
 
@@ -694,7 +705,7 @@ static inline void sbp2_allow_block(struct sbp2_logical_unit *lu)
 static void sbp2_conditionally_block(struct sbp2_logical_unit *lu)
 {
        struct sbp2_target *tgt = lu->tgt;
-       struct fw_card *card = fw_device(tgt->unit->device.parent)->card;
+       struct fw_card *card = target_device(tgt)->card;
        struct Scsi_Host *shost =
                container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
        unsigned long flags;
@@ -718,7 +729,7 @@ static void sbp2_conditionally_block(struct sbp2_logical_unit *lu)
 static void sbp2_conditionally_unblock(struct sbp2_logical_unit *lu)
 {
        struct sbp2_target *tgt = lu->tgt;
-       struct fw_card *card = fw_device(tgt->unit->device.parent)->card;
+       struct fw_card *card = target_device(tgt)->card;
        struct Scsi_Host *shost =
                container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
        unsigned long flags;
@@ -743,7 +754,7 @@ static void sbp2_conditionally_unblock(struct sbp2_logical_unit *lu)
  */
 static void sbp2_unblock(struct sbp2_target *tgt)
 {
-       struct fw_card *card = fw_device(tgt->unit->device.parent)->card;
+       struct fw_card *card = target_device(tgt)->card;
        struct Scsi_Host *shost =
                container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
        unsigned long flags;
@@ -773,7 +784,7 @@ static void sbp2_release_target(struct kref *kref)
        struct Scsi_Host *shost =
                container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
        struct scsi_device *sdev;
-       struct fw_device *device = fw_device(tgt->unit->device.parent);
+       struct fw_device *device = target_device(tgt);
 
        /* prevent deadlocks */
        sbp2_unblock(tgt);
@@ -846,7 +857,7 @@ static void sbp2_queue_work(struct sbp2_logical_unit *lu, unsigned long delay)
  */
 static void sbp2_set_busy_timeout(struct sbp2_logical_unit *lu)
 {
-       struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
+       struct fw_device *device = target_device(lu->tgt);
        __be32 d = cpu_to_be32(SBP2_CYCLE_LIMIT | SBP2_RETRY_LIMIT);
 
        fw_run_transaction(device->card, TCODE_WRITE_QUADLET_REQUEST,
@@ -862,7 +873,7 @@ static void sbp2_login(struct work_struct *work)
        struct sbp2_logical_unit *lu =
                container_of(work, struct sbp2_logical_unit, work.work);
        struct sbp2_target *tgt = lu->tgt;
-       struct fw_device *device = fw_device(tgt->unit->device.parent);
+       struct fw_device *device = target_device(tgt);
        struct Scsi_Host *shost;
        struct scsi_device *sdev;
        struct sbp2_login_response response;
@@ -1110,7 +1121,7 @@ static struct scsi_host_template scsi_driver_template;
 static int sbp2_probe(struct device *dev)
 {
        struct fw_unit *unit = fw_unit(dev);
-       struct fw_device *device = fw_device(unit->device.parent);
+       struct fw_device *device = fw_parent_device(unit);
        struct sbp2_target *tgt;
        struct sbp2_logical_unit *lu;
        struct Scsi_Host *shost;
@@ -1191,7 +1202,7 @@ static void sbp2_reconnect(struct work_struct *work)
        struct sbp2_logical_unit *lu =
                container_of(work, struct sbp2_logical_unit, work.work);
        struct sbp2_target *tgt = lu->tgt;
-       struct fw_device *device = fw_device(tgt->unit->device.parent);
+       struct fw_device *device = target_device(tgt);
        int generation, node_id, local_node_id;
 
        if (fw_device_is_shutdown(device))
@@ -1243,7 +1254,7 @@ static void sbp2_update(struct fw_unit *unit)
        struct sbp2_target *tgt = dev_get_drvdata(&unit->device);
        struct sbp2_logical_unit *lu;
 
-       fw_device_enable_phys_dma(fw_device(unit->device.parent));
+       fw_device_enable_phys_dma(fw_parent_device(unit));
 
        /*
         * Fw-core serializes sbp2_update() against sbp2_remove().
@@ -1259,9 +1270,10 @@ static void sbp2_update(struct fw_unit *unit)
 #define SBP2_UNIT_SPEC_ID_ENTRY        0x0000609e
 #define SBP2_SW_VERSION_ENTRY  0x00010483
 
-static const struct fw_device_id sbp2_id_table[] = {
+static const struct ieee1394_device_id sbp2_id_table[] = {
        {
-               .match_flags  = FW_MATCH_SPECIFIER_ID | FW_MATCH_VERSION,
+               .match_flags  = IEEE1394_MATCH_SPECIFIER_ID |
+                               IEEE1394_MATCH_VERSION,
                .specifier_id = SBP2_UNIT_SPEC_ID_ENTRY,
                .version      = SBP2_SW_VERSION_ENTRY,
        },
@@ -1335,7 +1347,7 @@ static void complete_command_orb(struct sbp2_orb *base_orb,
 {
        struct sbp2_command_orb *orb =
                container_of(base_orb, struct sbp2_command_orb, base);
-       struct fw_device *device = fw_device(orb->lu->tgt->unit->device.parent);
+       struct fw_device *device = target_device(orb->lu->tgt);
        int result;
 
        if (status != NULL) {
@@ -1442,7 +1454,7 @@ static int sbp2_map_scatterlist(struct sbp2_command_orb *orb,
 static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
 {
        struct sbp2_logical_unit *lu = cmd->device->hostdata;
-       struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
+       struct fw_device *device = target_device(lu->tgt);
        struct sbp2_command_orb *orb;
        int generation, retval = SCSI_MLQUEUE_HOST_BUSY;
 
diff --git a/include/linux/firewire.h b/include/linux/firewire.h
new file mode 100644 (file)
index 0000000..e584b72
--- /dev/null
@@ -0,0 +1,358 @@
+#ifndef _LINUX_FIREWIRE_H
+#define _LINUX_FIREWIRE_H
+
+#include <linux/completion.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/kref.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/sysfs.h>
+#include <linux/timer.h>
+#include <linux/types.h>
+#include <linux/workqueue.h>
+
+#include <asm/atomic.h>
+#include <asm/byteorder.h>
+
+#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 */
+#define CSR_STATE_CLEAR                        0x0
+#define CSR_STATE_SET                  0x4
+#define CSR_NODE_IDS                   0x8
+#define CSR_RESET_START                        0xc
+#define CSR_SPLIT_TIMEOUT_HI           0x18
+#define CSR_SPLIT_TIMEOUT_LO           0x1c
+#define CSR_CYCLE_TIME                 0x200
+#define CSR_BUS_TIME                   0x204
+#define CSR_BUSY_TIMEOUT               0x210
+#define CSR_BUS_MANAGER_ID             0x21c
+#define CSR_BANDWIDTH_AVAILABLE                0x220
+#define CSR_CHANNELS_AVAILABLE         0x224
+#define CSR_CHANNELS_AVAILABLE_HI      0x224
+#define CSR_CHANNELS_AVAILABLE_LO      0x228
+#define CSR_BROADCAST_CHANNEL          0x234
+#define CSR_CONFIG_ROM                 0x400
+#define CSR_CONFIG_ROM_END             0x800
+#define CSR_FCP_COMMAND                        0xB00
+#define CSR_FCP_RESPONSE               0xD00
+#define CSR_FCP_END                    0xF00
+#define CSR_TOPOLOGY_MAP               0x1000
+#define CSR_TOPOLOGY_MAP_END           0x1400
+#define CSR_SPEED_MAP                  0x2000
+#define CSR_SPEED_MAP_END              0x3000
+
+#define CSR_OFFSET             0x40
+#define CSR_LEAF               0x80
+#define CSR_DIRECTORY          0xc0
+
+#define CSR_DESCRIPTOR         0x01
+#define CSR_VENDOR             0x03
+#define CSR_HARDWARE_VERSION   0x04
+#define CSR_NODE_CAPABILITIES  0x0c
+#define CSR_UNIT               0x11
+#define CSR_SPECIFIER_ID       0x12
+#define CSR_VERSION            0x13
+#define CSR_DEPENDENT_INFO     0x14
+#define CSR_MODEL              0x17
+#define CSR_INSTANCE           0x18
+#define CSR_DIRECTORY_ID       0x20
+
+struct fw_csr_iterator {
+       u32 *p;
+       u32 *end;
+};
+
+void fw_csr_iterator_init(struct fw_csr_iterator *ci, u32 *p);
+int fw_csr_iterator_next(struct fw_csr_iterator *ci, int *key, int *value);
+
+extern struct bus_type fw_bus_type;
+
+struct fw_card_driver;
+struct fw_node;
+
+struct fw_card {
+       const struct fw_card_driver *driver;
+       struct device *device;
+       struct kref kref;
+       struct completion done;
+
+       int node_id;
+       int generation;
+       int current_tlabel;
+       u64 tlabel_mask;
+       struct list_head transaction_list;
+       struct timer_list flush_timer;
+       unsigned long reset_jiffies;
+
+       unsigned long long guid;
+       unsigned max_receive;
+       int link_speed;
+       int config_rom_generation;
+
+       spinlock_t lock; /* Take this lock when handling the lists in
+                         * this struct. */
+       struct fw_node *local_node;
+       struct fw_node *root_node;
+       struct fw_node *irm_node;
+       u8 color; /* must be u8 to match the definition in struct fw_node */
+       int gap_count;
+       bool beta_repeaters_present;
+
+       int index;
+
+       struct list_head link;
+
+       /* Work struct for BM duties. */
+       struct delayed_work work;
+       int bm_retries;
+       int bm_generation;
+
+       bool broadcast_channel_allocated;
+       u32 broadcast_channel;
+       u32 topology_map[(CSR_TOPOLOGY_MAP_END - CSR_TOPOLOGY_MAP) / 4];
+};
+
+static inline struct fw_card *fw_card_get(struct fw_card *card)
+{
+       kref_get(&card->kref);
+
+       return card;
+}
+
+void fw_card_release(struct kref *kref);
+
+static inline void fw_card_put(struct fw_card *card)
+{
+       kref_put(&card->kref, fw_card_release);
+}
+
+struct fw_attribute_group {
+       struct attribute_group *groups[2];
+       struct attribute_group group;
+       struct attribute *attrs[12];
+};
+
+enum fw_device_state {
+       FW_DEVICE_INITIALIZING,
+       FW_DEVICE_RUNNING,
+       FW_DEVICE_GONE,
+       FW_DEVICE_SHUTDOWN,
+};
+
+/*
+ * Note, fw_device.generation always has to be read before fw_device.node_id.
+ * Use SMP memory barriers to ensure this.  Otherwise requests will be sent
+ * to an outdated node_id if the generation was updated in the meantime due
+ * to a bus reset.
+ *
+ * Likewise, fw-core will take care to update .node_id before .generation so
+ * that whenever fw_device.generation is current WRT the actual bus generation,
+ * fw_device.node_id is guaranteed to be current too.
+ *
+ * The same applies to fw_device.card->node_id vs. fw_device.generation.
+ *
+ * fw_device.config_rom and fw_device.config_rom_length may be accessed during
+ * the lifetime of any fw_unit belonging to the fw_device, before device_del()
+ * was called on the last fw_unit.  Alternatively, they may be accessed while
+ * holding fw_device_rwsem.
+ */
+struct fw_device {
+       atomic_t state;
+       struct fw_node *node;
+       int node_id;
+       int generation;
+       unsigned max_speed;
+       struct fw_card *card;
+       struct device device;
+
+       struct mutex client_list_mutex;
+       struct list_head client_list;
+
+       u32 *config_rom;
+       size_t config_rom_length;
+       int config_rom_retries;
+       unsigned is_local:1;
+       unsigned max_rec:4;
+       unsigned cmc:1;
+       unsigned irmc:1;
+       unsigned bc_implemented:2;
+
+       struct delayed_work work;
+       struct fw_attribute_group attribute_group;
+};
+
+static inline struct fw_device *fw_device(struct device *dev)
+{
+       return container_of(dev, struct fw_device, device);
+}
+
+static inline int fw_device_is_shutdown(struct fw_device *device)
+{
+       return atomic_read(&device->state) == FW_DEVICE_SHUTDOWN;
+}
+
+static inline struct fw_device *fw_device_get(struct fw_device *device)
+{
+       get_device(&device->device);
+
+       return device;
+}
+
+static inline void fw_device_put(struct fw_device *device)
+{
+       put_device(&device->device);
+}
+
+int fw_device_enable_phys_dma(struct fw_device *device);
+
+/*
+ * fw_unit.directory must not be accessed after device_del(&fw_unit.device).
+ */
+struct fw_unit {
+       struct device device;
+       u32 *directory;
+       struct fw_attribute_group attribute_group;
+};
+
+static inline struct fw_unit *fw_unit(struct device *dev)
+{
+       return container_of(dev, struct fw_unit, device);
+}
+
+static inline struct fw_unit *fw_unit_get(struct fw_unit *unit)
+{
+       get_device(&unit->device);
+
+       return unit;
+}
+
+static inline void fw_unit_put(struct fw_unit *unit)
+{
+       put_device(&unit->device);
+}
+
+static inline struct fw_device *fw_parent_device(struct fw_unit *unit)
+{
+       return fw_device(unit->device.parent);
+}
+
+struct ieee1394_device_id;
+
+struct fw_driver {
+       struct device_driver driver;
+       /* Called when the parent device sits through a bus reset. */
+       void (*update)(struct fw_unit *unit);
+       const struct ieee1394_device_id *id_table;
+};
+
+struct fw_packet;
+struct fw_request;
+
+typedef void (*fw_packet_callback_t)(struct fw_packet *packet,
+                                    struct fw_card *card, int status);
+typedef void (*fw_transaction_callback_t)(struct fw_card *card, int rcode,
+                                         void *data, size_t length,
+                                         void *callback_data);
+/*
+ * Important note:  The callback must guarantee that either fw_send_response()
+ * or kfree() is called on the @request.
+ */
+typedef void (*fw_address_callback_t)(struct fw_card *card,
+                                     struct fw_request *request,
+                                     int tcode, int destination, int source,
+                                     int generation, int speed,
+                                     unsigned long long offset,
+                                     void *data, size_t length,
+                                     void *callback_data);
+
+struct fw_packet {
+       int speed;
+       int generation;
+       u32 header[4];
+       size_t header_length;
+       void *payload;
+       size_t payload_length;
+       dma_addr_t payload_bus;
+       u32 timestamp;
+
+       /*
+        * This callback is called when the packet transmission has
+        * completed; for successful transmission, the status code is
+        * the ack received from the destination, otherwise it's a
+        * negative errno: ENOMEM, ESTALE, ETIMEDOUT, ENODEV, EIO.
+        * The callback can be called from tasklet context and thus
+        * must never block.
+        */
+       fw_packet_callback_t callback;
+       int ack;
+       struct list_head link;
+       void *driver_data;
+};
+
+struct fw_transaction {
+       int node_id; /* The generation is implied; it is always the current. */
+       int tlabel;
+       int timestamp;
+       struct list_head link;
+
+       struct fw_packet packet;
+
+       /*
+        * The data passed to the callback is valid only during the
+        * callback.
+        */
+       fw_transaction_callback_t callback;
+       void *callback_data;
+};
+
+struct fw_address_handler {
+       u64 offset;
+       size_t length;
+       fw_address_callback_t address_callback;
+       void *callback_data;
+       struct list_head link;
+};
+
+struct fw_address_region {
+       u64 start;
+       u64 end;
+};
+
+extern const struct fw_address_region fw_high_memory_region;
+
+int fw_core_add_address_handler(struct fw_address_handler *handler,
+                               const struct fw_address_region *region);
+void fw_core_remove_address_handler(struct fw_address_handler *handler);
+void fw_send_response(struct fw_card *card,
+                     struct fw_request *request, int rcode);
+void fw_send_request(struct fw_card *card, struct fw_transaction *t,
+                    int tcode, int destination_id, int generation, int speed,
+                    unsigned long long offset, void *payload, size_t length,
+                    fw_transaction_callback_t callback, void *callback_data);
+int fw_cancel_transaction(struct fw_card *card,
+                         struct fw_transaction *transaction);
+int fw_run_transaction(struct fw_card *card, int tcode, int destination_id,
+                      int generation, int speed, unsigned long long offset,
+                      void *payload, size_t length);
+
+#endif /* _LINUX_FIREWIRE_H */