]> rtime.felk.cvut.cz Git - linux-imx.git/blobdiff - drivers/firewire/ohci.c
firewire: ohci: copy_iso_headers(): make comment match the code
[linux-imx.git] / drivers / firewire / ohci.c
index 57cd3a406edf3930954a2c18938ab8e4796ffa16..74ff1a8f4fcb446ee96c8b210d779ed66024a261 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/string.h>
 #include <linux/time.h>
 #include <linux/vmalloc.h>
+#include <linux/workqueue.h>
 
 #include <asm/byteorder.h>
 #include <asm/page.h>
@@ -125,6 +126,7 @@ struct context {
        struct fw_ohci *ohci;
        u32 regs;
        int total_allocation;
+       u32 current_bus;
        bool running;
        bool flushing;
 
@@ -226,7 +228,7 @@ struct fw_ohci {
 
        __le32    *self_id_cpu;
        dma_addr_t self_id_bus;
-       struct tasklet_struct bus_reset_tasklet;
+       struct work_struct bus_reset_work;
 
        u32 self_id_buffer[512];
 };
@@ -263,6 +265,8 @@ static char ohci_driver_name[] = KBUILD_MODNAME;
 #define PCI_DEVICE_ID_AGERE_FW643      0x5901
 #define PCI_DEVICE_ID_JMICRON_JMB38X_FW        0x2380
 #define PCI_DEVICE_ID_TI_TSB12LV22     0x8009
+#define PCI_DEVICE_ID_TI_TSB12LV26     0x8020
+#define PCI_DEVICE_ID_TI_TSB82AA2      0x8025
 #define PCI_VENDOR_ID_PINNACLE_SYSTEMS 0x11bd
 
 #define QUIRK_CYCLE_TIMER              1
@@ -270,6 +274,7 @@ static char ohci_driver_name[] = KBUILD_MODNAME;
 #define QUIRK_BE_HEADERS               4
 #define QUIRK_NO_1394A                 8
 #define QUIRK_NO_MSI                   16
+#define QUIRK_TI_SLLZ059               32
 
 /* In case of multiple matches in ohci_quirks[], only the first one is used. */
 static const struct {
@@ -290,12 +295,21 @@ static const struct {
        {PCI_VENDOR_ID_NEC, PCI_ANY_ID, PCI_ANY_ID,
                QUIRK_CYCLE_TIMER},
 
+       {PCI_VENDOR_ID_O2, PCI_ANY_ID, PCI_ANY_ID,
+               QUIRK_NO_MSI},
+
        {PCI_VENDOR_ID_RICOH, PCI_ANY_ID, PCI_ANY_ID,
                QUIRK_CYCLE_TIMER},
 
        {PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV22, PCI_ANY_ID,
                QUIRK_CYCLE_TIMER | QUIRK_RESET_PACKET | QUIRK_NO_1394A},
 
+       {PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV26, PCI_ANY_ID,
+               QUIRK_RESET_PACKET | QUIRK_TI_SLLZ059},
+
+       {PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB82AA2, PCI_ANY_ID,
+               QUIRK_RESET_PACKET | QUIRK_TI_SLLZ059},
+
        {PCI_VENDOR_ID_TI, PCI_ANY_ID, PCI_ANY_ID,
                QUIRK_RESET_PACKET},
 
@@ -312,6 +326,7 @@ MODULE_PARM_DESC(quirks, "Chip quirks (default = 0"
        ", AR/selfID endianess = "      __stringify(QUIRK_BE_HEADERS)
        ", no 1394a enhancements = "    __stringify(QUIRK_NO_1394A)
        ", disable MSI = "              __stringify(QUIRK_NO_MSI)
+       ", TI SLLZ059 erratum = "       __stringify(QUIRK_TI_SLLZ059)
        ")");
 
 #define OHCI_PARAM_DEBUG_AT_AR         1
@@ -319,8 +334,6 @@ MODULE_PARM_DESC(quirks, "Chip quirks (default = 0"
 #define OHCI_PARAM_DEBUG_IRQS          4
 #define OHCI_PARAM_DEBUG_BUSRESETS     8 /* only effective before chip init */
 
-#ifdef CONFIG_FIREWIRE_OHCI_DEBUG
-
 static int param_debug;
 module_param_named(debug, param_debug, int, 0644);
 MODULE_PARM_DESC(debug, "Verbose logging (default = 0"
@@ -330,7 +343,7 @@ MODULE_PARM_DESC(debug, "Verbose logging (default = 0"
        ", busReset events = "  __stringify(OHCI_PARAM_DEBUG_BUSRESETS)
        ", or a combination, or all = -1)");
 
-static void log_irqs(u32 evt)
+static void log_irqs(struct fw_ohci *ohci, u32 evt)
 {
        if (likely(!(param_debug &
                        (OHCI_PARAM_DEBUG_IRQS | OHCI_PARAM_DEBUG_BUSRESETS))))
@@ -340,7 +353,8 @@ static void log_irqs(u32 evt)
            !(evt & OHCI1394_busReset))
                return;
 
-       fw_notify("IRQ %08x%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", evt,
+       dev_notice(ohci->card.device,
+           "IRQ %08x%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", evt,
            evt & OHCI1394_selfIDComplete       ? " selfID"             : "",
            evt & OHCI1394_RQPkt                ? " AR_req"             : "",
            evt & OHCI1394_RSPkt                ? " AR_resp"            : "",
@@ -379,24 +393,29 @@ static char _p(u32 *s, int shift)
        return port[*s >> shift & 3];
 }
 
-static void log_selfids(int node_id, int generation, int self_id_count, u32 *s)
+static void log_selfids(struct fw_ohci *ohci, int generation, int self_id_count)
 {
+       u32 *s;
+
        if (likely(!(param_debug & OHCI_PARAM_DEBUG_SELFIDS)))
                return;
 
-       fw_notify("%d selfIDs, generation %d, local node ID %04x\n",
-                 self_id_count, generation, node_id);
+       dev_notice(ohci->card.device,
+                  "%d selfIDs, generation %d, local node ID %04x\n",
+                  self_id_count, generation, ohci->node_id);
 
-       for (; self_id_count--; ++s)
+       for (s = ohci->self_id_buffer; self_id_count--; ++s)
                if ((*s & 1 << 23) == 0)
-                       fw_notify("selfID 0: %08x, phy %d [%c%c%c] "
+                       dev_notice(ohci->card.device,
+                           "selfID 0: %08x, phy %d [%c%c%c] "
                            "%s gc=%d %s %s%s%s\n",
                            *s, *s >> 24 & 63, _p(s, 6), _p(s, 4), _p(s, 2),
                            speed[*s >> 14 & 3], *s >> 16 & 63,
                            power[*s >> 8 & 7], *s >> 22 & 1 ? "L" : "",
                            *s >> 11 & 1 ? "c" : "", *s & 2 ? "i" : "");
                else
-                       fw_notify("selfID n: %08x, phy %d [%c%c%c%c%c%c%c%c]\n",
+                       dev_notice(ohci->card.device,
+                           "selfID n: %08x, phy %d [%c%c%c%c%c%c%c%c]\n",
                            *s, *s >> 24 & 63,
                            _p(s, 16), _p(s, 14), _p(s, 12), _p(s, 10),
                            _p(s,  8), _p(s,  6), _p(s,  4), _p(s,  2));
@@ -432,7 +451,8 @@ static const char *tcodes[] = {
        [0xe] = "link internal",        [0xf] = "-reserved-",
 };
 
-static void log_ar_at_event(char dir, int speed, u32 *header, int evt)
+static void log_ar_at_event(struct fw_ohci *ohci,
+                           char dir, int speed, u32 *header, int evt)
 {
        int tcode = header[0] >> 4 & 0xf;
        char specific[12];
@@ -444,8 +464,9 @@ static void log_ar_at_event(char dir, int speed, u32 *header, int evt)
                        evt = 0x1f;
 
        if (evt == OHCI1394_evt_bus_reset) {
-               fw_notify("A%c evt_bus_reset, generation %d\n",
-                   dir, (header[2] >> 16) & 0xff);
+               dev_notice(ohci->card.device,
+                          "A%c evt_bus_reset, generation %d\n",
+                          dir, (header[2] >> 16) & 0xff);
                return;
        }
 
@@ -464,39 +485,35 @@ static void log_ar_at_event(char dir, int speed, u32 *header, int evt)
 
        switch (tcode) {
        case 0xa:
-               fw_notify("A%c %s, %s\n", dir, evts[evt], tcodes[tcode]);
+               dev_notice(ohci->card.device,
+                          "A%c %s, %s\n",
+                          dir, evts[evt], tcodes[tcode]);
                break;
        case 0xe:
-               fw_notify("A%c %s, PHY %08x %08x\n",
-                         dir, evts[evt], header[1], header[2]);
+               dev_notice(ohci->card.device,
+                          "A%c %s, PHY %08x %08x\n",
+                          dir, evts[evt], header[1], header[2]);
                break;
        case 0x0: case 0x1: case 0x4: case 0x5: case 0x9:
-               fw_notify("A%c spd %x tl %02x, "
-                   "%04x -> %04x, %s, "
-                   "%s, %04x%08x%s\n",
-                   dir, speed, header[0] >> 10 & 0x3f,
-                   header[1] >> 16, header[0] >> 16, evts[evt],
-                   tcodes[tcode], header[1] & 0xffff, header[2], specific);
+               dev_notice(ohci->card.device,
+                          "A%c spd %x tl %02x, "
+                          "%04x -> %04x, %s, "
+                          "%s, %04x%08x%s\n",
+                          dir, speed, header[0] >> 10 & 0x3f,
+                          header[1] >> 16, header[0] >> 16, evts[evt],
+                          tcodes[tcode], header[1] & 0xffff, header[2], specific);
                break;
        default:
-               fw_notify("A%c spd %x tl %02x, "
-                   "%04x -> %04x, %s, "
-                   "%s%s\n",
-                   dir, speed, header[0] >> 10 & 0x3f,
-                   header[1] >> 16, header[0] >> 16, evts[evt],
-                   tcodes[tcode], specific);
+               dev_notice(ohci->card.device,
+                          "A%c spd %x tl %02x, "
+                          "%04x -> %04x, %s, "
+                          "%s%s\n",
+                          dir, speed, header[0] >> 10 & 0x3f,
+                          header[1] >> 16, header[0] >> 16, evts[evt],
+                          tcodes[tcode], specific);
        }
 }
 
-#else
-
-#define param_debug 0
-static inline void log_irqs(u32 evt) {}
-static inline void log_selfids(int node_id, int generation, int self_id_count, u32 *s) {}
-static inline void log_ar_at_event(char dir, int speed, u32 *header, int evt) {}
-
-#endif /* CONFIG_FIREWIRE_OHCI_DEBUG */
-
 static inline void reg_write(const struct fw_ohci *ohci, int offset, u32 data)
 {
        writel(data, ohci->registers + offset);
@@ -540,7 +557,7 @@ static int read_phy_reg(struct fw_ohci *ohci, int addr)
                if (i >= 3)
                        msleep(1);
        }
-       fw_error("failed to read phy reg\n");
+       dev_err(ohci->card.device, "failed to read phy reg\n");
 
        return -EBUSY;
 }
@@ -562,7 +579,7 @@ static int write_phy_reg(const struct fw_ohci *ohci, int addr, u32 val)
                if (i >= 3)
                        msleep(1);
        }
-       fw_error("failed to write phy reg\n");
+       dev_err(ohci->card.device, "failed to write phy reg\n");
 
        return -EBUSY;
 }
@@ -661,11 +678,14 @@ static void ar_context_release(struct ar_context *ctx)
 
 static void ar_context_abort(struct ar_context *ctx, const char *error_msg)
 {
-       if (reg_read(ctx->ohci, CONTROL_CLEAR(ctx->regs)) & CONTEXT_RUN) {
-               reg_write(ctx->ohci, CONTROL_CLEAR(ctx->regs), CONTEXT_RUN);
-               flush_writes(ctx->ohci);
+       struct fw_ohci *ohci = ctx->ohci;
+
+       if (reg_read(ohci, CONTROL_CLEAR(ctx->regs)) & CONTEXT_RUN) {
+               reg_write(ohci, CONTROL_CLEAR(ctx->regs), CONTEXT_RUN);
+               flush_writes(ohci);
 
-               fw_error("AR error: %s; DMA stopped\n", error_msg);
+               dev_err(ohci->card.device, "AR error: %s; DMA stopped\n",
+                       error_msg);
        }
        /* FIXME: restart? */
 }
@@ -835,7 +855,7 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer)
        p.timestamp  = status & 0xffff;
        p.generation = ohci->request_generation;
 
-       log_ar_at_event('R', p.speed, p.header, evt);
+       log_ar_at_event(ohci, 'R', p.speed, p.header, evt);
 
        /*
         * Several controllers, notably from NEC and VIA, forget to
@@ -856,7 +876,7 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer)
         *
         * Alas some chips sometimes emit bus reset packets with a
         * wrong generation.  We set the correct generation for these
-        * at a slightly incorrect time (in bus_reset_tasklet).
+        * at a slightly incorrect time (in bus_reset_work).
         */
        if (evt == OHCI1394_evt_bus_reset) {
                if (!(ohci->quirks & QUIRK_RESET_PACKET))
@@ -1043,6 +1063,7 @@ static void context_tasklet(unsigned long data)
                address = le32_to_cpu(last->branch_address);
                z = address & 0xf;
                address &= ~0xf;
+               ctx->current_bus = address;
 
                /* If the branch address points to a buffer outside of the
                 * current buffer, advance to the next buffer. */
@@ -1206,21 +1227,22 @@ static void context_append(struct context *ctx,
 
 static void context_stop(struct context *ctx)
 {
+       struct fw_ohci *ohci = ctx->ohci;
        u32 reg;
        int i;
 
-       reg_write(ctx->ohci, CONTROL_CLEAR(ctx->regs), CONTEXT_RUN);
+       reg_write(ohci, CONTROL_CLEAR(ctx->regs), CONTEXT_RUN);
        ctx->running = false;
 
        for (i = 0; i < 1000; i++) {
-               reg = reg_read(ctx->ohci, CONTROL_SET(ctx->regs));
+               reg = reg_read(ohci, CONTROL_SET(ctx->regs));
                if ((reg & CONTEXT_ACTIVE) == 0)
                        return;
 
                if (i)
                        udelay(10);
        }
-       fw_error("Error: DMA context still active (0x%08x)\n", reg);
+       dev_err(ohci->card.device, "DMA context still active (0x%08x)\n", reg);
 }
 
 struct driver_data {
@@ -1400,7 +1422,7 @@ static int handle_at_packet(struct context *context,
        evt = le16_to_cpu(last->transfer_status) & 0x1f;
        packet->timestamp = le16_to_cpu(last->res_count);
 
-       log_ar_at_event('T', packet->speed, packet->header, evt);
+       log_ar_at_event(ohci, 'T', packet->speed, packet->header, evt);
 
        switch (evt) {
        case OHCI1394_evt_timeout:
@@ -1529,7 +1551,7 @@ static void handle_local_lock(struct fw_ohci *ohci,
                        goto out;
                }
 
-       fw_error("swap not done (CSR lock timeout)\n");
+       dev_err(ohci->card.device, "swap not done (CSR lock timeout)\n");
        fw_fill_response(&response, packet->header, RCODE_BUSY, NULL, 0);
 
  out:
@@ -1603,15 +1625,10 @@ static void detect_dead_context(struct fw_ohci *ohci,
        u32 ctl;
 
        ctl = reg_read(ohci, CONTROL_SET(regs));
-       if (ctl & CONTEXT_DEAD) {
-#ifdef CONFIG_FIREWIRE_OHCI_DEBUG
-               fw_error("DMA context %s has stopped, error code: %s\n",
-                        name, evts[ctl & 0x1f]);
-#else
-               fw_error("DMA context %s has stopped, error code: %#x\n",
-                        name, ctl & 0x1f);
-#endif
-       }
+       if (ctl & CONTEXT_DEAD)
+               dev_err(ohci->card.device,
+                       "DMA context %s has stopped, error code: %s\n",
+                       name, evts[ctl & 0x1f]);
 }
 
 static void handle_dead_contexts(struct fw_ohci *ohci)
@@ -1710,9 +1727,95 @@ static u32 update_bus_time(struct fw_ohci *ohci)
        return ohci->bus_time | cycle_time_seconds;
 }
 
-static void bus_reset_tasklet(unsigned long data)
+static int get_status_for_port(struct fw_ohci *ohci, int port_index)
+{
+       int reg;
+
+       mutex_lock(&ohci->phy_reg_mutex);
+       reg = write_phy_reg(ohci, 7, port_index);
+       if (reg >= 0)
+               reg = read_phy_reg(ohci, 8);
+       mutex_unlock(&ohci->phy_reg_mutex);
+       if (reg < 0)
+               return reg;
+
+       switch (reg & 0x0f) {
+       case 0x06:
+               return 2;       /* is child node (connected to parent node) */
+       case 0x0e:
+               return 3;       /* is parent node (connected to child node) */
+       }
+       return 1;               /* not connected */
+}
+
+static int get_self_id_pos(struct fw_ohci *ohci, u32 self_id,
+       int self_id_count)
+{
+       int i;
+       u32 entry;
+
+       for (i = 0; i < self_id_count; i++) {
+               entry = ohci->self_id_buffer[i];
+               if ((self_id & 0xff000000) == (entry & 0xff000000))
+                       return -1;
+               if ((self_id & 0xff000000) < (entry & 0xff000000))
+                       return i;
+       }
+       return i;
+}
+
+/*
+ * TI TSB82AA2B and TSB12LV26 do not receive the selfID of a locally
+ * attached TSB41BA3D phy; see http://www.ti.com/litv/pdf/sllz059.
+ * Construct the selfID from phy register contents.
+ * FIXME:  How to determine the selfID.i flag?
+ */
+static int find_and_insert_self_id(struct fw_ohci *ohci, int self_id_count)
+{
+       int reg, i, pos, status;
+       /* link active 1, speed 3, bridge 0, contender 1, more packets 0 */
+       u32 self_id = 0x8040c800;
+
+       reg = reg_read(ohci, OHCI1394_NodeID);
+       if (!(reg & OHCI1394_NodeID_idValid)) {
+               dev_notice(ohci->card.device,
+                          "node ID not valid, new bus reset in progress\n");
+               return -EBUSY;
+       }
+       self_id |= ((reg & 0x3f) << 24); /* phy ID */
+
+       reg = ohci_read_phy_reg(&ohci->card, 4);
+       if (reg < 0)
+               return reg;
+       self_id |= ((reg & 0x07) << 8); /* power class */
+
+       reg = ohci_read_phy_reg(&ohci->card, 1);
+       if (reg < 0)
+               return reg;
+       self_id |= ((reg & 0x3f) << 16); /* gap count */
+
+       for (i = 0; i < 3; i++) {
+               status = get_status_for_port(ohci, i);
+               if (status < 0)
+                       return status;
+               self_id |= ((status & 0x3) << (6 - (i * 2)));
+       }
+
+       pos = get_self_id_pos(ohci, self_id, self_id_count);
+       if (pos >= 0) {
+               memmove(&(ohci->self_id_buffer[pos+1]),
+                       &(ohci->self_id_buffer[pos]),
+                       (self_id_count - pos) * sizeof(*ohci->self_id_buffer));
+               ohci->self_id_buffer[pos] = self_id;
+               self_id_count++;
+       }
+       return self_id_count;
+}
+
+static void bus_reset_work(struct work_struct *work)
 {
-       struct fw_ohci *ohci = (struct fw_ohci *)data;
+       struct fw_ohci *ohci =
+               container_of(work, struct fw_ohci, bus_reset_work);
        int self_id_count, i, j, reg;
        int generation, new_generation;
        unsigned long flags;
@@ -1722,11 +1825,12 @@ static void bus_reset_tasklet(unsigned long data)
 
        reg = reg_read(ohci, OHCI1394_NodeID);
        if (!(reg & OHCI1394_NodeID_idValid)) {
-               fw_notify("node ID not valid, new bus reset in progress\n");
+               dev_notice(ohci->card.device,
+                          "node ID not valid, new bus reset in progress\n");
                return;
        }
        if ((reg & OHCI1394_NodeID_nodeNumber) == 63) {
-               fw_notify("malconfigured bus\n");
+               dev_notice(ohci->card.device, "malconfigured bus\n");
                return;
        }
        ohci->node_id = reg & (OHCI1394_NodeID_busNumber |
@@ -1740,7 +1844,7 @@ static void bus_reset_tasklet(unsigned long data)
 
        reg = reg_read(ohci, OHCI1394_SelfIDCount);
        if (reg & OHCI1394_SelfIDCount_selfIDError) {
-               fw_notify("inconsistent self IDs\n");
+               dev_notice(ohci->card.device, "inconsistent self IDs\n");
                return;
        }
        /*
@@ -1750,21 +1854,53 @@ static void bus_reset_tasklet(unsigned long data)
         * bit extra to get the actual number of self IDs.
         */
        self_id_count = (reg >> 3) & 0xff;
-       if (self_id_count == 0 || self_id_count > 252) {
-               fw_notify("inconsistent self IDs\n");
+
+       if (self_id_count > 252) {
+               dev_notice(ohci->card.device, "inconsistent self IDs\n");
                return;
        }
+
        generation = (cond_le32_to_cpu(ohci->self_id_cpu[0]) >> 16) & 0xff;
        rmb();
 
        for (i = 1, j = 0; j < self_id_count; i += 2, j++) {
                if (ohci->self_id_cpu[i] != ~ohci->self_id_cpu[i + 1]) {
-                       fw_notify("inconsistent self IDs\n");
-                       return;
+                       /*
+                        * If the invalid data looks like a cycle start packet,
+                        * it's likely to be the result of the cycle master
+                        * having a wrong gap count.  In this case, the self IDs
+                        * so far are valid and should be processed so that the
+                        * bus manager can then correct the gap count.
+                        */
+                       if (cond_le32_to_cpu(ohci->self_id_cpu[i])
+                                                       == 0xffff008f) {
+                               dev_notice(ohci->card.device,
+                                          "ignoring spurious self IDs\n");
+                               self_id_count = j;
+                               break;
+                       } else {
+                               dev_notice(ohci->card.device,
+                                          "inconsistent self IDs\n");
+                               return;
+                       }
                }
                ohci->self_id_buffer[j] =
                                cond_le32_to_cpu(ohci->self_id_cpu[i]);
        }
+
+       if (ohci->quirks & QUIRK_TI_SLLZ059) {
+               self_id_count = find_and_insert_self_id(ohci, self_id_count);
+               if (self_id_count < 0) {
+                       dev_notice(ohci->card.device,
+                                  "could not construct local self ID\n");
+                       return;
+               }
+       }
+
+       if (self_id_count == 0) {
+               dev_notice(ohci->card.device, "inconsistent self IDs\n");
+               return;
+       }
        rmb();
 
        /*
@@ -1783,8 +1919,8 @@ static void bus_reset_tasklet(unsigned long data)
 
        new_generation = (reg_read(ohci, OHCI1394_SelfIDCount) >> 16) & 0xff;
        if (new_generation != generation) {
-               fw_notify("recursive bus reset detected, "
-                         "discarding self ids\n");
+               dev_notice(ohci->card.device,
+                          "new bus reset, discarding self ids\n");
                return;
        }
 
@@ -1855,8 +1991,7 @@ static void bus_reset_tasklet(unsigned long data)
                dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
                                  free_rom, free_rom_bus);
 
-       log_selfids(ohci->node_id, generation,
-                   self_id_count, ohci->self_id_buffer);
+       log_selfids(ohci, generation, self_id_count);
 
        fw_core_handle_bus_reset(&ohci->card, ohci->node_id, generation,
                                 self_id_count, ohci->self_id_buffer,
@@ -1881,10 +2016,10 @@ static irqreturn_t irq_handler(int irq, void *data)
         */
        reg_write(ohci, OHCI1394_IntEventClear,
                  event & ~(OHCI1394_busReset | OHCI1394_postedWriteErr));
-       log_irqs(event);
+       log_irqs(ohci, event);
 
        if (event & OHCI1394_selfIDComplete)
-               tasklet_schedule(&ohci->bus_reset_tasklet);
+               queue_work(fw_workqueue, &ohci->bus_reset_work);
 
        if (event & OHCI1394_RQPkt)
                tasklet_schedule(&ohci->ar_request_ctx.tasklet);
@@ -1923,20 +2058,21 @@ static irqreturn_t irq_handler(int irq, void *data)
        }
 
        if (unlikely(event & OHCI1394_regAccessFail))
-               fw_error("Register access failure - "
-                        "please notify linux1394-devel@lists.sf.net\n");
+               dev_err(ohci->card.device, "register access failure\n");
 
        if (unlikely(event & OHCI1394_postedWriteErr)) {
                reg_read(ohci, OHCI1394_PostedWriteAddressHi);
                reg_read(ohci, OHCI1394_PostedWriteAddressLo);
                reg_write(ohci, OHCI1394_IntEventClear,
                          OHCI1394_postedWriteErr);
-               fw_error("PCI posted write error\n");
+               if (printk_ratelimit())
+                       dev_err(ohci->card.device, "PCI posted write error\n");
        }
 
        if (unlikely(event & OHCI1394_cycleTooLong)) {
                if (printk_ratelimit())
-                       fw_notify("isochronous cycle too long\n");
+                       dev_notice(ohci->card.device,
+                                  "isochronous cycle too long\n");
                reg_write(ohci, OHCI1394_LinkControlSet,
                          OHCI1394_LinkControl_cycleMaster);
        }
@@ -1949,7 +2085,8 @@ static irqreturn_t irq_handler(int irq, void *data)
                 * them at least two cycles later.  (FIXME?)
                 */
                if (printk_ratelimit())
-                       fw_notify("isochronous cycle inconsistent\n");
+                       dev_notice(ohci->card.device,
+                                  "isochronous cycle inconsistent\n");
        }
 
        if (unlikely(event & OHCI1394_unrecoverableError))
@@ -2045,6 +2182,28 @@ static int configure_1394a_enhancements(struct fw_ohci *ohci)
        return 0;
 }
 
+static int probe_tsb41ba3d(struct fw_ohci *ohci)
+{
+       /* TI vendor ID = 0x080028, TSB41BA3D product ID = 0x833005 (sic) */
+       static const u8 id[] = { 0x08, 0x00, 0x28, 0x83, 0x30, 0x05, };
+       int reg, i;
+
+       reg = read_phy_reg(ohci, 2);
+       if (reg < 0)
+               return reg;
+       if ((reg & PHY_EXTENDED_REGISTERS) != PHY_EXTENDED_REGISTERS)
+               return 0;
+
+       for (i = ARRAY_SIZE(id) - 1; i >= 0; i--) {
+               reg = read_paged_phy_reg(ohci, 1, i + 10);
+               if (reg < 0)
+                       return reg;
+               if (reg != id[i])
+                       return 0;
+       }
+       return 1;
+}
+
 static int ohci_enable(struct fw_card *card,
                       const __be32 *config_rom, size_t length)
 {
@@ -2054,7 +2213,7 @@ static int ohci_enable(struct fw_card *card,
        int i, ret;
 
        if (software_reset(ohci)) {
-               fw_error("Failed to reset ohci card.\n");
+               dev_err(card->device, "failed to reset ohci card\n");
                return -EBUSY;
        }
 
@@ -2078,10 +2237,20 @@ static int ohci_enable(struct fw_card *card,
        }
 
        if (!lps) {
-               fw_error("Failed to set Link Power Status\n");
+               dev_err(card->device, "failed to set Link Power Status\n");
                return -EIO;
        }
 
+       if (ohci->quirks & QUIRK_TI_SLLZ059) {
+               ret = probe_tsb41ba3d(ohci);
+               if (ret < 0)
+                       return ret;
+               if (ret)
+                       dev_notice(card->device, "local TSB41BA3D phy\n");
+               else
+                       ohci->quirks &= ~QUIRK_TI_SLLZ059;
+       }
+
        reg_write(ohci, OHCI1394_HCControlClear,
                  OHCI1394_HCControl_noByteSwapData);
 
@@ -2177,7 +2346,8 @@ static int ohci_enable(struct fw_card *card,
        if (request_irq(dev->irq, irq_handler,
                        pci_dev_msi_enabled(dev) ? 0 : IRQF_SHARED,
                        ohci_driver_name, ohci)) {
-               fw_error("Failed to allocate interrupt %d.\n", dev->irq);
+               dev_err(card->device, "failed to allocate interrupt %d\n",
+                       dev->irq);
                pci_disable_msi(dev);
 
                if (config_rom) {
@@ -2257,7 +2427,7 @@ static int ohci_set_config_rom(struct fw_card *card,
         * then set up the real values for the two registers.
         *
         * We use ohci->lock to avoid racing with the code that sets
-        * ohci->next_config_rom to NULL (see bus_reset_tasklet).
+        * ohci->next_config_rom to NULL (see bus_reset_work).
         */
 
        next_config_rom =
@@ -2342,7 +2512,7 @@ static int ohci_cancel_packet(struct fw_card *card, struct fw_packet *packet)
                dma_unmap_single(ohci->card.device, packet->payload_bus,
                                 packet->payload_length, DMA_TO_DEVICE);
 
-       log_ar_at_event('T', packet->speed, packet->header, 0x20);
+       log_ar_at_event(ohci, 'T', packet->speed, packet->header, 0x20);
        driver_data->packet = NULL;
        packet->ack = RCODE_CANCELLED;
        packet->callback(packet, &ohci->card, packet->ack);
@@ -2515,10 +2685,9 @@ static void copy_iso_headers(struct iso_context *ctx, void *p)
                return;
 
        /*
-        * The iso header is byteswapped to little endian by
-        * the controller, but the remaining header quadlets
-        * are big endian.  We want to present all the headers
-        * as big endian, so we have to swap the first quadlet.
+        * The two iso header quadlets are byteswapped to little
+        * endian by the controller, but we want to present them
+        * as big endian for consistency with the bus endianness.
         */
        if (ctx->base.header_size > 0)
                *(u32 *) (ctx->header + i) = __swab32(*(u32 *) (p + 4));
@@ -2536,6 +2705,7 @@ static int handle_ir_packet_per_buffer(struct context *context,
        struct iso_context *ctx =
                container_of(context, struct iso_context, context);
        struct descriptor *pd;
+       u32 buffer_dma;
        __le32 *ir_header;
        void *p;
 
@@ -2546,6 +2716,16 @@ static int handle_ir_packet_per_buffer(struct context *context,
                /* Descriptor(s) not done yet, stop iteration */
                return 0;
 
+       while (!(d->control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS))) {
+               d++;
+               buffer_dma = le32_to_cpu(d->data_address);
+               dma_sync_single_range_for_cpu(context->ohci->card.device,
+                                             buffer_dma & PAGE_MASK,
+                                             buffer_dma & ~PAGE_MASK,
+                                             le16_to_cpu(d->req_count),
+                                             DMA_FROM_DEVICE);
+       }
+
        p = last + 1;
        copy_iso_headers(ctx, p);
 
@@ -2568,21 +2748,65 @@ static int handle_ir_buffer_fill(struct context *context,
 {
        struct iso_context *ctx =
                container_of(context, struct iso_context, context);
+       u32 buffer_dma;
 
-       if (!last->transfer_status)
+       if (last->res_count != 0)
                /* Descriptor(s) not done yet, stop iteration */
                return 0;
 
+       buffer_dma = le32_to_cpu(last->data_address);
+       dma_sync_single_range_for_cpu(context->ohci->card.device,
+                                     buffer_dma & PAGE_MASK,
+                                     buffer_dma & ~PAGE_MASK,
+                                     le16_to_cpu(last->req_count),
+                                     DMA_FROM_DEVICE);
+
        if (le16_to_cpu(last->control) & DESCRIPTOR_IRQ_ALWAYS)
                ctx->base.callback.mc(&ctx->base,
                                      le32_to_cpu(last->data_address) +
-                                     le16_to_cpu(last->req_count) -
-                                     le16_to_cpu(last->res_count),
+                                     le16_to_cpu(last->req_count),
                                      ctx->base.callback_data);
 
        return 1;
 }
 
+static inline void sync_it_packet_for_cpu(struct context *context,
+                                         struct descriptor *pd)
+{
+       __le16 control;
+       u32 buffer_dma;
+
+       /* only packets beginning with OUTPUT_MORE* have data buffers */
+       if (pd->control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS))
+               return;
+
+       /* skip over the OUTPUT_MORE_IMMEDIATE descriptor */
+       pd += 2;
+
+       /*
+        * If the packet has a header, the first OUTPUT_MORE/LAST descriptor's
+        * data buffer is in the context program's coherent page and must not
+        * be synced.
+        */
+       if ((le32_to_cpu(pd->data_address) & PAGE_MASK) ==
+           (context->current_bus          & PAGE_MASK)) {
+               if (pd->control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS))
+                       return;
+               pd++;
+       }
+
+       do {
+               buffer_dma = le32_to_cpu(pd->data_address);
+               dma_sync_single_range_for_cpu(context->ohci->card.device,
+                                             buffer_dma & PAGE_MASK,
+                                             buffer_dma & ~PAGE_MASK,
+                                             le16_to_cpu(pd->req_count),
+                                             DMA_TO_DEVICE);
+               control = pd->control;
+               pd++;
+       } while (!(control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS)));
+}
+
 static int handle_it_packet(struct context *context,
                            struct descriptor *d,
                            struct descriptor *last)
@@ -2599,6 +2823,8 @@ static int handle_it_packet(struct context *context,
                /* Descriptor(s) not done yet, stop iteration */
                return 0;
 
+       sync_it_packet_for_cpu(context, d);
+
        i = ctx->header_length;
        if (i + 4 < PAGE_SIZE) {
                /* Present this value as big-endian to match the receive code */
@@ -2968,6 +3194,10 @@ static int queue_iso_transmit(struct iso_context *ctx,
                page_bus = page_private(buffer->pages[page]);
                pd[i].data_address = cpu_to_le32(page_bus + offset);
 
+               dma_sync_single_range_for_device(ctx->context.ohci->card.device,
+                                                page_bus, offset, length,
+                                                DMA_TO_DEVICE);
+
                payload_index += length;
        }
 
@@ -2992,6 +3222,7 @@ static int queue_iso_packet_per_buffer(struct iso_context *ctx,
                                       struct fw_iso_buffer *buffer,
                                       unsigned long payload)
 {
+       struct device *device = ctx->context.ohci->card.device;
        struct descriptor *d, *pd;
        dma_addr_t d_bus, page_bus;
        u32 z, header_z, rest;
@@ -3046,6 +3277,10 @@ static int queue_iso_packet_per_buffer(struct iso_context *ctx,
                        page_bus = page_private(buffer->pages[page]);
                        pd->data_address = cpu_to_le32(page_bus + offset);
 
+                       dma_sync_single_range_for_device(device, page_bus,
+                                                        offset, length,
+                                                        DMA_FROM_DEVICE);
+
                        offset = (offset + length) & ~PAGE_MASK;
                        rest -= length;
                        if (offset == 0)
@@ -3105,6 +3340,10 @@ static int queue_iso_buffer_fill(struct iso_context *ctx,
                page_bus = page_private(buffer->pages[page]);
                d->data_address = cpu_to_le32(page_bus + offset);
 
+               dma_sync_single_range_for_device(ctx->context.ohci->card.device,
+                                                page_bus, offset, length,
+                                                DMA_FROM_DEVICE);
+
                rest -= length;
                offset = 0;
                page++;
@@ -3225,7 +3464,7 @@ static int __devinit pci_probe(struct pci_dev *dev,
 
        err = pci_enable_device(dev);
        if (err) {
-               fw_error("Failed to enable OHCI hardware\n");
+               dev_err(&dev->dev, "failed to enable OHCI hardware\n");
                goto fail_free;
        }
 
@@ -3236,18 +3475,17 @@ static int __devinit pci_probe(struct pci_dev *dev,
        spin_lock_init(&ohci->lock);
        mutex_init(&ohci->phy_reg_mutex);
 
-       tasklet_init(&ohci->bus_reset_tasklet,
-                    bus_reset_tasklet, (unsigned long)ohci);
+       INIT_WORK(&ohci->bus_reset_work, bus_reset_work);
 
        err = pci_request_region(dev, 0, ohci_driver_name);
        if (err) {
-               fw_error("MMIO resource unavailable\n");
+               dev_err(&dev->dev, "MMIO resource unavailable\n");
                goto fail_disable;
        }
 
        ohci->registers = pci_iomap(dev, 0, OHCI1394_REGISTER_SIZE);
        if (ohci->registers == NULL) {
-               fw_error("Failed to remap registers\n");
+               dev_err(&dev->dev, "failed to remap registers\n");
                err = -ENXIO;
                goto fail_iomem;
        }
@@ -3336,9 +3574,10 @@ static int __devinit pci_probe(struct pci_dev *dev,
                goto fail_contexts;
 
        version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff;
-       fw_notify("Added fw-ohci device %s, OHCI v%x.%x, "
+       dev_notice(&dev->dev,
+                 "added OHCI v%x.%x device as card %d, "
                  "%d IR + %d IT contexts, quirks 0x%x\n",
-                 dev_name(&dev->dev), version >> 16, version & 0xff,
+                 version >> 16, version & 0xff, ohci->card.index,
                  ohci->n_ir, ohci->n_it, ohci->quirks);
 
        return 0;
@@ -3367,7 +3606,7 @@ static int __devinit pci_probe(struct pci_dev *dev,
        pmac_ohci_off(dev);
  fail:
        if (err == -ENOMEM)
-               fw_error("Out of memory\n");
+               dev_err(&dev->dev, "out of memory\n");
 
        return err;
 }
@@ -3379,6 +3618,7 @@ static void pci_remove(struct pci_dev *dev)
        ohci = pci_get_drvdata(dev);
        reg_write(ohci, OHCI1394_IntMaskClear, ~0);
        flush_writes(ohci);
+       cancel_work_sync(&ohci->bus_reset_work);
        fw_core_remove_card(&ohci->card);
 
        /*
@@ -3410,7 +3650,7 @@ static void pci_remove(struct pci_dev *dev)
        kfree(ohci);
        pmac_ohci_off(dev);
 
-       fw_notify("Removed fw-ohci device.\n");
+       dev_notice(&dev->dev, "removed fw-ohci device\n");
 }
 
 #ifdef CONFIG_PM
@@ -3424,12 +3664,12 @@ static int pci_suspend(struct pci_dev *dev, pm_message_t state)
        pci_disable_msi(dev);
        err = pci_save_state(dev);
        if (err) {
-               fw_error("pci_save_state failed\n");
+               dev_err(&dev->dev, "pci_save_state failed\n");
                return err;
        }
        err = pci_set_power_state(dev, pci_choose_state(dev, state));
        if (err)
-               fw_error("pci_set_power_state failed with %d\n", err);
+               dev_err(&dev->dev, "pci_set_power_state failed with %d\n", err);
        pmac_ohci_off(dev);
 
        return 0;
@@ -3445,7 +3685,7 @@ static int pci_resume(struct pci_dev *dev)
        pci_restore_state(dev);
        err = pci_enable_device(dev);
        if (err) {
-               fw_error("pci_enable_device failed\n");
+               dev_err(&dev->dev, "pci_enable_device failed\n");
                return err;
        }