| From 100ceb66d5c40cc0c7018e06a9474302470be73c Mon Sep 17 00:00:00 2001 |
| From: Stefan Richter <stefanr@s5r6.in-berlin.de> |
| Date: Tue, 3 Nov 2015 01:46:21 +0100 |
| Subject: firewire: ohci: fix JMicron JMB38x IT context discovery |
| |
| From: Stefan Richter <stefanr@s5r6.in-berlin.de> |
| |
| commit 100ceb66d5c40cc0c7018e06a9474302470be73c upstream. |
| |
| Reported by Clifford and Craig for JMicron OHCI-1394 + SDHCI combo |
| controllers: Often or even most of the time, the controller is |
| initialized with the message "added OHCI v1.10 device as card 0, 4 IR + |
| 0 IT contexts, quirks 0x10". With 0 isochronous transmit DMA contexts |
| (IT contexts), applications like audio output are impossible. |
| |
| However, OHCI-1394 demands that at least 4 IT contexts are implemented |
| by the link layer controller, and indeed JMicron JMB38x do implement |
| four of them. Only their IsoXmitIntMask register is unreliable at early |
| access. |
| |
| With my own JMB381 single function controller I found: |
| - I can reproduce the problem with a lower probability than Craig's. |
| - If I put a loop around the section which clears and reads |
| IsoXmitIntMask, then either the first or the second attempt will |
| return the correct initial mask of 0x0000000f. I never encountered |
| a case of needing more than a second attempt. |
| - Consequently, if I put a dummy reg_read(...IsoXmitIntMaskSet) |
| before the first write, the subsequent read will return the correct |
| result. |
| - If I merely ignore a wrong read result and force the known real |
| result, later isochronous transmit DMA usage works just fine. |
| |
| So let's just fix this chip bug up by the latter method. Tested with |
| JMB381 on kernel 3.13 and 4.3. |
| |
| Since OHCI-1394 generally requires 4 IT contexts at a minium, this |
| workaround is simply applied whenever the initial read of IsoXmitIntMask |
| returns 0, regardless whether it's a JMicron chip or not. I never heard |
| of this issue together with any other chip though. |
| |
| I am not 100% sure that this fix works on the OHCI-1394 part of JMB380 |
| and JMB388 combo controllers exactly the same as on the JMB381 single- |
| function controller, but so far I haven't had a chance to let an owner |
| of a combo chip run a patched kernel. |
| |
| Strangely enough, IsoRecvIntMask is always reported correctly, even |
| though it is probed right before IsoXmitIntMask. |
| |
| Reported-by: Clifford Dunn |
| Reported-by: Craig Moore <craig.moore@qenos.com> |
| Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/firewire/ohci.c | 5 +++++ |
| 1 file changed, 5 insertions(+) |
| |
| --- a/drivers/firewire/ohci.c |
| +++ b/drivers/firewire/ohci.c |
| @@ -3670,6 +3670,11 @@ static int pci_probe(struct pci_dev *dev |
| |
| reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, ~0); |
| ohci->it_context_support = reg_read(ohci, OHCI1394_IsoXmitIntMaskSet); |
| + /* JMicron JMB38x often shows 0 at first read, just ignore it */ |
| + if (!ohci->it_context_support) { |
| + ohci_notice(ohci, "overriding IsoXmitIntMask\n"); |
| + ohci->it_context_support = 0xf; |
| + } |
| reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, ~0); |
| ohci->it_context_mask = ohci->it_context_support; |
| ohci->n_it = hweight32(ohci->it_context_mask); |