lkml.org 
[lkml]   [2012]   [Apr]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[ 33/59] xhci: Fix register save/restore order.
    3.0-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Sarah Sharp <sarah.a.sharp@linux.intel.com>

    commit c7713e736526d8c9f6f87716fb90562a8ffaff2c upstream.

    The xHCI 1.0 spec errata released on June 13, 2011, changes the ordering
    that the xHCI registers are saved and restored in. It moves the
    interrupt pending (IMAN) and interrupt control (IMOD) registers to be
    saved and restored last. I believe that's because the host controller
    may attempt to fetch the event ring table when interrupts are
    re-enabled. Therefore we need to restore the event ring registers
    before we re-enable interrupts.

    This should be backported to kernels as old as 2.6.37, that contain the
    commit 5535b1d5f8885695c6ded783c692e3c0d0eda8ca "USB: xHCI: PCI power
    management implementation"

    Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
    Tested-by: Elric Fu <elricfu1@gmail.com>
    Cc: Andiry Xu <andiry.xu@amd.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    drivers/usb/host/xhci.c | 8 ++++----
    1 file changed, 4 insertions(+), 4 deletions(-)

    --- a/drivers/usb/host/xhci.c
    +++ b/drivers/usb/host/xhci.c
    @@ -610,11 +610,11 @@ static void xhci_save_registers(struct x
    xhci->s3.dev_nt = xhci_readl(xhci, &xhci->op_regs->dev_notification);
    xhci->s3.dcbaa_ptr = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr);
    xhci->s3.config_reg = xhci_readl(xhci, &xhci->op_regs->config_reg);
    - xhci->s3.irq_pending = xhci_readl(xhci, &xhci->ir_set->irq_pending);
    - xhci->s3.irq_control = xhci_readl(xhci, &xhci->ir_set->irq_control);
    xhci->s3.erst_size = xhci_readl(xhci, &xhci->ir_set->erst_size);
    xhci->s3.erst_base = xhci_read_64(xhci, &xhci->ir_set->erst_base);
    xhci->s3.erst_dequeue = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
    + xhci->s3.irq_pending = xhci_readl(xhci, &xhci->ir_set->irq_pending);
    + xhci->s3.irq_control = xhci_readl(xhci, &xhci->ir_set->irq_control);
    }

    static void xhci_restore_registers(struct xhci_hcd *xhci)
    @@ -623,11 +623,11 @@ static void xhci_restore_registers(struc
    xhci_writel(xhci, xhci->s3.dev_nt, &xhci->op_regs->dev_notification);
    xhci_write_64(xhci, xhci->s3.dcbaa_ptr, &xhci->op_regs->dcbaa_ptr);
    xhci_writel(xhci, xhci->s3.config_reg, &xhci->op_regs->config_reg);
    - xhci_writel(xhci, xhci->s3.irq_pending, &xhci->ir_set->irq_pending);
    - xhci_writel(xhci, xhci->s3.irq_control, &xhci->ir_set->irq_control);
    xhci_writel(xhci, xhci->s3.erst_size, &xhci->ir_set->erst_size);
    xhci_write_64(xhci, xhci->s3.erst_base, &xhci->ir_set->erst_base);
    xhci_write_64(xhci, xhci->s3.erst_dequeue, &xhci->ir_set->erst_dequeue);
    + xhci_writel(xhci, xhci->s3.irq_pending, &xhci->ir_set->irq_pending);
    + xhci_writel(xhci, xhci->s3.irq_control, &xhci->ir_set->irq_control);
    }

    static void xhci_set_cmd_ring_deq(struct xhci_hcd *xhci)



    \
     
     \ /
      Last update: 2012-04-19 23:15    [W:4.032 / U:0.088 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site