EHCI handoff failed, propably causing problems

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello all,

I am having problems with interrupts on USB line. When in PIC mode,
after enabling wireless card and making it do someting (which has
separate irq), there are 100000 unhandled interrupts on ehci irq, then
kernel disables it and the wireless doesn't work (neither before nor
after disabling irq line). If I boot with irqpoll, usb and wireless
work like a charm. If I boot with irqfixup, both work too, but it
happens sometimes that those interrupts start hitting again later.
When in APIC mode, when using C2 cpu sleep state (and only then),
right after boot i get 200000 wakeups / sec in powertop, but no
unwanted irqs appear. Wireless card is unaffected (and works). After
playing with apic options, i can delay those wakeups by 5 minutes
(pretty much exactly), but they will come anyway.

The hardware is fujistu-siemens amilo pro v3515 laptop with via
chipset (p4m900) and celeron m cpu, the wireless card is on pci bus.
Testing on kernel version 2.9.29. .

I have noticed "EHCI: BIOS handoff failed" message dmesg, so I went
investigating. What I have found out is that prior to doing any
handoff, both semaphores are marked as taken (set to 1), and moreover
both Os Semaphore SMI Enable and Os Semaphore SMI Bit are set. Under
such circumstances current handoff code does nothing (or rather:
nothing it does has any result), so I made it sanitize the situation
(clear os semaphore and os semaphore smi bit) before doing handoff. It
turned out, that when requesting handoff the os semaphore smi bit is
set (which is correct), but nothing more happens (it doesn't ever get
cleared, nor does bios relinquish its semaphore).

Here is the code snippet I wrote (from drivers/usb/host/pci-quirks.c):

_dump_smi: read EHCI_USBLEGCTLSTS, dump to the console and return its value
_dump_sems: read EHCI_USBLEGSUP, dump to the console and return its value

        switch (cap & 0xff) {
        case 1:         /* BIOS/SMM/... handoff support */
            if ((cap & EHCI_USBLEGSUP_BIOS)) {
                dev_dbg(&pdev->dev, "EHCI: BIOS handoff\n");

                dev_dbg(&pdev->dev, "EHCI: current state:\n");
                _dump_smi(pdev, offset);
                _dump_sems(pdev, offset);

                /* force it to comply with the protocol */

                smi = _dump_smi(pdev, offset);
                if(smi & EHCI_USBLEGCTLSTS_SOO)
                {
                    dev_dbg(&pdev->dev, "EHCI: clearing SMI bit\n");
                    pci_write_config_word(pdev,
                            offset+EHCI_USBLEGCTLSTS+2,
                            0x2000);
                    smi = _dump_smi(pdev, offset);
                }

                cap = _dump_sems(pdev, offset);
                if(cap & EHCI_USBLEGSUP_OS) {
                    dev_dbg(&pdev->dev, "EHCI: putting OS semaphore down\n");
                    pci_write_config_byte(pdev,
                            offset+3,
                            0);
                    cap = _dump_sems(pdev, offset);
                }

                /* now The Proper State should be restored */

                dev_dbg(&pdev->dev, "EHCI: requesting handoff\n");
                pci_write_config_byte(pdev, offset + 3, 1);

                _dump_smi(pdev, offset);
                _dump_sems(pdev, offset);
            }

            /* if boot firmware now owns EHCI, spin till
             * it hands it over.
             */
            msec = 1000;
            while ((cap & EHCI_USBLEGSUP_BIOS) && (msec > 0)) {
                tried_handoff = 1;
                msleep(10);
                msec -= 10;
                pci_read_config_dword(pdev, offset, &cap);
            }

            _dump_sems(pdev, offset);
            _dump_smi(pdev, offset);

            if (cap & EHCI_USBLEGSUP_BIOS) {
                /* well, possibly buggy BIOS... try to shut
                 * it down, and hope nothing goes too wrong
                 */
                dev_warn(&pdev->dev, "EHCI: BIOS handoff failed"
                        " (BIOS bug?) %08x\n", cap);
                pci_write_config_byte(pdev, offset + 2, 0);
            }

and the results are:

pci 0000:00:10.4: EHCI: BIOS handoff
pci 0000:00:10.4: EHCI: current state:
pci 0000:00:10.4: EHCI: SMI enabled: 1, SMI bit: 1, CTLSTS = e00c2000
pci 0000:00:10.4: EHCI: OS semaphore: 1, BIOS semaphore: 1, SUP = 01010001
pci 0000:00:10.4: EHCI: SMI enabled: 1, SMI bit: 1, CTLSTS = e00c2000
pci 0000:00:10.4: EHCI: clearing SMI bit
pci 0000:00:10.4: EHCI: SMI enabled: 1, SMI bit: 0, CTLSTS = c00c2000
pci 0000:00:10.4: EHCI: OS semaphore: 1, BIOS semaphore: 1, SUP = 01010001
pci 0000:00:10.4: EHCI: putting OS semaphore down
pci 0000:00:10.4: EHCI: OS semaphore: 0, BIOS semaphore: 1, SUP = 00010001
pci 0000:00:10.4: EHCI: requesting handoff
pci 0000:00:10.4: EHCI: SMI enabled: 1, SMI bit: 1, CTLSTS = e00c2000
pci 0000:00:10.4: EHCI: OS semaphore: 1, BIOS semaphore: 1, SUP = 01010001
Switched to high resolution mode on CPU 0
pci 0000:00:10.4: EHCI: OS semaphore: 1, BIOS semaphore: 1, SUP = 01010001
pci 0000:00:10.4: EHCI: SMI enabled: 1, SMI bit: 1, CTLSTS = e00c2000
pci 0000:00:10.4: EHCI: BIOS handoff failed (BIOS bug?) 01010001

Where do I go from here? Thanks for your help and please CC me, as I'm
not subscribed to the list.
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux