Re: Re: USB OHCI freezes after few minutes of heavy use. EHCI is OK. noapic or acpi=noirq almost provides workaround

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

 



Thank you Alan for reply :)

> > Systems affected: all Linuxes (any distro 32/64bit:
> > ubuntu,rhel,fedora,suse,mandrake,lunar), all kernel versions up to
> > and including vanilla kernel 3.3 Systems not affected: everything
> > without Linux kernel: FreeBSD 9.0, OpenSolaris 2009.06, Windows XP
> > Pro SP3 32bit. All non affected systems use default generic system
> > provided drivers. No any updates, external drivers or patches were
> > used. Systems tested 'out of the box'. What is different in common
> > Linux APIC implementation that all Linuxes fail and other OSes works
> > perfect with Nvidia OHCI implementation in MCP7x chipset?
> Probably the entire implementation is different between Linux and other
> operating systems.

I think we can narrow down this to APIC handling. There must be some 
generic, tiny incompatibility in Linux when compared to other OS. APIC is 
well known evil on Linux when I search the net for interrupts problem on 
Linux. If we would be able to isolate and fix the issue we could improve 
Linux compatibility as a platform.
I had before nforce2 and nforce430 - ohci worked great. Will try to hammer 
Nvidia again for chipset specs and errata of MCP78.

What I have seen M$ and Solaris (do not know how to check this on FreeBSD) 
use in APIC mode level interrupt handler and Linux uses fasteoi. I have 
rewritten kernel I have to use level interrupt handler and as far I 
remeber it helped a lot. I dropped it because it helped a lot but not 
solved problem fully. See attachement. Here is my comment on nvnews.net 
when I posted it:
http://www.nvnews.net/vbulletin/showthread.php?t=135022&highlight=OHCI&page=2
See post #19

The most important part of this patch is by default kernel uses for all 
APIC ready devices:
 set_irq_chip_and_handler_name(irq, &ioapic_chip,
                                              handle_fasteoi_irq,
                                              "fasteoi");
my patch just changes it to this:
 set_irq_chip_and_handler_name(irq, &ioapic_chip,
                                             handle_level_irq,
                                             "level");

the rest of code just do commandline parsing. Not important.

> Somewhere in the bug report you mentioned that even though the driver
> freezes, the interrupt count keeps going up.  This suggests two
> possibilities: The interrupts aren't getting delivered to ohci-hcd, or
> they are getting delivered but ohci-hcd isn't handling them right.  Do
> you know which is the case?

No. I would be glad to test this if you give me some tips or patches how 
to check this. I can build and use vanilla kernel 3.3.2 and 3.4-rc3 for 
testing. Which one do you prefer to use as debug platform for this 
problem? I can also build other kernel if you have better option.

> > Because for many years nobody was able to make a fix for this how
> > about printing warning when 10de:077b, 10de:077d controllers are
> > detected and APIC is active: "This usb 1.1 controller freezes on
> > Linux when APIC is enabled. Use noapic or acpi=noirq kernel boot
> > parameters to workaround or use PCI/PCIe card with usb ports for usb
> > 1.1 devices"
> I'd prefer to try and solve the problem first.

Me too :) I tried to fix that but I'm not ohci/apic guru and need help 
from someone here.

Thanks again Alan for reply :)
--- linux-2.6.33.3/arch/x86/kernel/apic/io_apic.c	2010-05-01 22:21:21.000000000 +0200
+++ linux-2.6.33.3/arch/x86/kernel/apic/io_apic.c	2010-05-01 22:40:19.000000000 +0200
@@ -73,6 +73,10 @@
  */
 int sis_apic_bug = -1;

+bool noFastEoiHandler = 0;
+#define MAX_LVL_IRQS_NR 24
+int irq_lvl_required[MAX_LVL_IRQS_NR];
+
 static DEFINE_SPINLOCK(ioapic_lock);
 static DEFINE_SPINLOCK(vector_lock);

@@ -124,6 +128,27 @@
 }
 early_param("noapic", parse_noapic);

+static int __init parse_NoFastEoiApic(char *str)
+{
+	/* replace the default fasteoi interrupt handler with level one */
+	noFastEoiHandler = 1;
+	return 0;
+}
+early_param("nofasteoiapic", parse_NoFastEoiApic);
+
+static int __init parse_NoFastEoiApicAt(char *str)
+{
+	/* Reset level int table to default -1 */
+	int i;
+	for(i = 0; i < 24; i++) irq_lvl_required[i] = -1;
+	/* force level handler for irqs instead default fasteoi */
+	get_options(&str, MAX_LVL_IRQS_NR, irq_lvl_required);
+	for(i = 0; i < 24; i++) apic_printk(APIC_VERBOSE, KERN_INFO
+                        "Interrupt table: position %d value %d\n", i, irq_lvl_required[i]);
+	return 0;
+}
+early_param("antifasteoiapic=", parse_NoFastEoiApicAt);
+
 struct irq_pin_list {
 	int apic, pin;
 	struct irq_pin_list *next;
@@ -1324,9 +1349,21 @@
 }
 #endif

-static void ioapic_register_intr(int irq, struct irq_desc *desc, unsigned long trigger)
+int CheckLevelNeeded(int irq)
 {
+/* Looks if level irq is on the list */
+	int i, result = 0;
+	for(i = 0; i < MAX_LVL_IRQS_NR; i++)
+	{
+		if(irq_lvl_required[i] == irq) result = irq;
+		if(irq_lvl_required[i] < 1) result = 0;
+	}
+	apic_printk(APIC_VERBOSE, KERN_INFO, "Interrupt found %d.\n", result);
+	return result;
+}

+static void ioapic_register_intr(int irq, struct irq_desc *desc, unsigned long trigger)
+{
 	if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
 	    trigger == IOAPIC_LEVEL)
 		desc->status |= IRQ_LEVEL;
@@ -1346,10 +1383,21 @@
 	}

 	if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
-	    trigger == IOAPIC_LEVEL)
+	    trigger == IOAPIC_LEVEL) {
+	   if (noFastEoiHandler)
+		set_irq_chip_and_handler_name(irq, &ioapic_chip,
+					      handle_level_irq,
+					      "level");
+	   else if (CheckLevelNeeded(irq)) {
+		set_irq_chip_and_handler_name(irq, &ioapic_chip,
+					      handle_level_irq,
+					      "level");
+			}
+	   else
 		set_irq_chip_and_handler_name(irq, &ioapic_chip,
 					      handle_fasteoi_irq,
 					      "fasteoi");
+		}
 	else
 		set_irq_chip_and_handler_name(irq, &ioapic_chip,
 					      handle_edge_irq, "edge");

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

  Powered by Linux