firewire: ohci: properly clear posted write errors
authorClemens Ladisch <[email protected]>
Tue, 30 Nov 2010 07:24:32 +0000 (08:24 +0100)
committerStefan Richter <[email protected]>
Mon, 13 Dec 2010 19:39:14 +0000 (20:39 +0100)
To remove the error information from the controller's queue and to allow
more posted writes, the driver has to read the failed posted write
address before clearing the postedWriteErr interrupt bit.

Signed-off-by: Clemens Ladisch <[email protected]>
(Stefan R:) The spec is somewhat fuzzy about the actual requirements.
To err on the safe side, let's do these two read accesses.

Signed-off-by: Stefan Richter <[email protected]>
drivers/firewire/ohci.c

index 276324d741dfb8cf6e4fbbd027ae44c6f0ff70e0..0031ec6e1f00b98a2188cad9a1b302b86297003f 100644 (file)
@@ -1790,8 +1790,12 @@ static irqreturn_t irq_handler(int irq, void *data)
        if (!event || !~event)
                return IRQ_NONE;
 
-       /* busReset must not be cleared yet, see OHCI 1.1 clause 7.2.3.2 */
-       reg_write(ohci, OHCI1394_IntEventClear, event & ~OHCI1394_busReset);
+       /*
+        * busReset and postedWriteErr must not be cleared yet
+        * (OHCI 1.1 clauses 7.2.3.2 and 13.2.8.1)
+        */
+       reg_write(ohci, OHCI1394_IntEventClear,
+                 event & ~(OHCI1394_busReset | OHCI1394_postedWriteErr));
        log_irqs(event);
 
        if (event & OHCI1394_selfIDComplete)
@@ -1831,8 +1835,13 @@ static irqreturn_t irq_handler(int irq, void *data)
                fw_error("Register access failure - "
                         "please notify [email protected]\n");
 
-       if (unlikely(event & OHCI1394_postedWriteErr))
+       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 (unlikely(event & OHCI1394_cycleTooLong)) {
                if (printk_ratelimit())