[PATCH] firewire: fw-ohci: TSB43AB22/A dualbuffer workaround - Kernel

This is a discussion on [PATCH] firewire: fw-ohci: TSB43AB22/A dualbuffer workaround - Kernel ; Isochronous reception in dualbuffer is reportedly broken with TI TSB43AB22A on x86-64. Descriptor addresses above 2G have been determined as the trigger: https://bugzilla.redhat.com/show_bug.cgi?id=435550 Two fixes are possible: - pci_set_consistent_dma_mask(pdev, DMA_31BIT_MASK); at least when IR descriptors are allocated, or - simply ...

+ Reply to Thread
Results 1 to 3 of 3

Thread: [PATCH] firewire: fw-ohci: TSB43AB22/A dualbuffer workaround

  1. [PATCH] firewire: fw-ohci: TSB43AB22/A dualbuffer workaround

    Isochronous reception in dualbuffer is reportedly broken with
    TI TSB43AB22A on x86-64. Descriptor addresses above 2G have been
    determined as the trigger:
    https://bugzilla.redhat.com/show_bug.cgi?id=435550

    Two fixes are possible:
    - pci_set_consistent_dma_mask(pdev, DMA_31BIT_MASK);
    at least when IR descriptors are allocated, or
    - simply don't use dualbuffer.
    This fix implements the latter workaround.

    But we keep using dualbuffer on x86-32 which won't give us highmen (and
    thus physical addresses outside the 31bit range) in coherent DMA memory
    allocations. Right now we could for example also whitelist PPC32, but
    DMA mapping implementation details are expected to change there.

    Signed-off-by: Stefan Richter
    ---
    drivers/firewire/fw-ohci.c | 37 ++++++++++++++++++++++++-------------
    include/linux/pci_ids.h | 1 +
    2 files changed, 25 insertions(+), 13 deletions(-)

    Index: linux/drivers/firewire/fw-ohci.c
    ================================================== =================
    --- linux.orig/drivers/firewire/fw-ohci.c
    +++ linux/drivers/firewire/fw-ohci.c
    @@ -171,7 +171,6 @@ struct iso_context {
    struct fw_ohci {
    struct fw_card card;

    - u32 version;
    __iomem char *registers;
    dma_addr_t self_id_bus;
    __le32 *self_id_cpu;
    @@ -180,6 +179,8 @@ struct fw_ohci {
    int generation;
    int request_generation; /* for timestamping incoming requests */
    u32 bus_seconds;
    +
    + bool use_dualbuffer;
    bool old_uninorth;
    bool bus_reset_packet_quirk;

    @@ -1885,7 +1886,7 @@ ohci_allocate_iso_context(struct fw_card
    } else {
    mask = &ohci->ir_context_mask;
    list = ohci->ir_context_list;
    - if (ohci->version >= OHCI_VERSION_1_1)
    + if (ohci->use_dualbuffer)
    callback = handle_ir_dualbuffer_packet;
    else
    callback = handle_ir_packet_per_buffer;
    @@ -1949,7 +1950,7 @@ static int ohci_start_iso(struct fw_iso_
    } else {
    index = ctx - ohci->ir_context_list;
    control = IR_CONTEXT_ISOCH_HEADER;
    - if (ohci->version >= OHCI_VERSION_1_1)
    + if (ohci->use_dualbuffer)
    control |= IR_CONTEXT_DUAL_BUFFER_MODE;
    match = (tags << 28) | (sync << 8) | ctx->base.channel;
    if (cycle >= 0) {
    @@ -2279,7 +2280,7 @@ ohci_queue_iso(struct fw_iso_context *ba
    spin_lock_irqsave(&ctx->context.ohci->lock, flags);
    if (base->type == FW_ISO_CONTEXT_TRANSMIT)
    retval = ohci_queue_iso_transmit(base, packet, buffer, payload);
    - else if (ctx->context.ohci->version >= OHCI_VERSION_1_1)
    + else if (ctx->context.ohci->use_dualbuffer)
    retval = ohci_queue_iso_receive_dualbuffer(base, packet,
    buffer, payload);
    else
    @@ -2341,7 +2342,7 @@ static int __devinit
    pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
    {
    struct fw_ohci *ohci;
    - u32 bus_options, max_receive, link_speed;
    + u32 bus_options, max_receive, link_speed, version;
    u64 guid;
    int err;
    size_t size;
    @@ -2366,12 +2367,6 @@ pci_probe(struct pci_dev *dev, const str
    pci_write_config_dword(dev, OHCI1394_PCI_HCI_Control, 0);
    pci_set_drvdata(dev, ohci);

    -#if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32)
    - ohci->old_uninorth = dev->vendor == PCI_VENDOR_ID_APPLE &&
    - dev->device == PCI_DEVICE_ID_APPLE_UNI_N_FW;
    -#endif
    - ohci->bus_reset_packet_quirk = dev->vendor == PCI_VENDOR_ID_TI;
    -
    spin_lock_init(&ohci->lock);

    tasklet_init(&ohci->bus_reset_tasklet,
    @@ -2390,6 +2385,23 @@ pci_probe(struct pci_dev *dev, const str
    goto fail_iomem;
    }

    + version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff;
    + ohci->use_dualbuffer = version >= OHCI_VERSION_1_1;
    +
    +/* x86-32 currently doesn't use highmem for dma_alloc_coherent */
    +#if !defined(CONFIG_X86_32)
    + /* dual-buffer mode is broken with descriptor addresses above 2G */
    + if (dev->vendor == PCI_VENDOR_ID_TI &&
    + dev->device == PCI_DEVICE_ID_TI_TSB43AB22)
    + ohci->use_dualbuffer = false;
    +#endif
    +
    +#if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32)
    + ohci->old_uninorth = dev->vendor == PCI_VENDOR_ID_APPLE &&
    + dev->device == PCI_DEVICE_ID_APPLE_UNI_N_FW;
    +#endif
    + ohci->bus_reset_packet_quirk = dev->vendor == PCI_VENDOR_ID_TI;
    +
    ar_context_init(&ohci->ar_request_ctx, ohci,
    OHCI1394_AsReqRcvContextControlSet);

    @@ -2441,9 +2453,8 @@ pci_probe(struct pci_dev *dev, const str
    if (err < 0)
    goto fail_self_id;

    - ohci->version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff;
    fw_notify("Added fw-ohci device %s, OHCI version %x.%x\n",
    - dev->dev.bus_id, ohci->version >> 16, ohci->version & 0xff);
    + dev->dev.bus_id, version >> 16, version & 0xff);
    return 0;

    fail_self_id:
    Index: linux/include/linux/pci_ids.h
    ================================================== =================
    --- linux.orig/include/linux/pci_ids.h
    +++ linux/include/linux/pci_ids.h
    @@ -748,6 +748,7 @@
    #define PCI_VENDOR_ID_TI 0x104c
    #define PCI_DEVICE_ID_TI_TVP4020 0x3d07
    #define PCI_DEVICE_ID_TI_4450 0x8011
    +#define PCI_DEVICE_ID_TI_TSB43AB22 0x8023
    #define PCI_DEVICE_ID_TI_XX21_XX11 0x8031
    #define PCI_DEVICE_ID_TI_XX21_XX11_FM 0x8033
    #define PCI_DEVICE_ID_TI_XX21_XX11_SD 0x8034

    --
    Stefan Richter
    -=====-==--- -=== =-==-
    http://arcgraph.de/sr/

    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  2. Re: [PATCH] firewire: fw-ohci: TSB43AB22/A dualbuffer workaround

    On Tuesday 22 July 2008 12:41:10 pm Stefan Richter wrote:
    > Isochronous reception in dualbuffer is reportedly broken with
    > TI TSB43AB22A on x86-64. Descriptor addresses above 2G have been
    > determined as the trigger:
    > https://bugzilla.redhat.com/show_bug.cgi?id=435550
    >
    > Two fixes are possible:
    > - pci_set_consistent_dma_mask(pdev, DMA_31BIT_MASK);
    > at least when IR descriptors are allocated, or
    > - simply don't use dualbuffer.
    > This fix implements the latter workaround.
    >
    > But we keep using dualbuffer on x86-32 which won't give us highmen (and
    > thus physical addresses outside the 31bit range) in coherent DMA memory
    > allocations. Right now we could for example also whitelist PPC32, but
    > DMA mapping implementation details are expected to change there.
    >
    > Signed-off-by: Stefan Richter


    Still hoping we can get some confirmation of a chipset bug or a fix from TI
    for this controller, but in the interim, this seems to be the most reasonable
    route to go right now.

    Signed-off-by: Jarod Wilson

    --
    Jarod Wilson
    jwilson@redhat.com
    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  3. Re: [PATCH] firewire: fw-ohci: TSB43AB22/A dualbuffer workaround

    Jarod Wilson wrote:
    > Still hoping we can get some confirmation of a chipset bug or a fix from TI
    > for this controller,


    Well, indeed, a chipset/board bug isn't entirely ruled out yet. But
    given that data buffers above 2G don't hurt, only descriptors do, the
    controller is definitely the primary suspect here.
    --
    Stefan Richter
    -=====-==--- -=== =-===
    http://arcgraph.de/sr/
    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

+ Reply to Thread