You are not logged in.

#1 2013-09-15 08:23:25

wdirksen
Member
From: New Zealand
Registered: 2012-02-23
Posts: 107

ASMedia PCIe to PCI bridge chipsets kill DVB functionality (SOLVED)

This is not so much a question but a forum placement to help others in future search situations.

This can be very important for anyone who uses PCI DVB DTV cards, not PCIe, and have all their hardware and software working but the DVB cards intermittently but very repeatedly no longer respond.  Actually any type of PCI card which needs decent PCI throughput can be affected here. All PCIe to PCI bridge chipsets are famous for potential bandwidth limiting but in the case of ASMedia, they are known to be outright faulty:

http://www.gossamer-threads.com/lists/l … el/1466185
https://lkml.org/lkml/2012/1/30/432

If you are using VDR, TVHeadend, or MythTV with FFdecsawrapper (open-sasc-ng in the old days) with PCI hardware, and you have an ASMedia chip on the motherboard, such as asm1080 or asm1083, you can patch the kernel to fix this. Below is a patch that works with current 3.10 ARCH and tested with 3.11 ARCH now in testing. The patch is actually a sort of hack because the chips are apparently faulty and the patch changes IRQ polling for the whole IRQ system. I can sometimes notice a bit of weird behaviour here and there in other things but nothing serious. My DTV is however FINALLY rock solid (big sigh):

--- a/kernel/irq/spurious.c	2011-12-11 16:14:48.188377387 +0100
+++ b/kernel/irq/spurious.c	2011-12-11 16:14:48.188377387 +0100
@@ -18,7 +18,7 @@

 static int irqfixup __read_mostly;

-#define POLL_SPURIOUS_IRQ_INTERVAL (HZ/10)
+#define POLL_SPURIOUS_IRQ_INTERVAL (HZ/100)
 static void poll_spurious_irqs(unsigned long dummy);
 static DEFINE_TIMER(poll_spurious_irq_timer, poll_spurious_irqs, 0, 0);
 static int irq_poll_cpu;
@@ -141,14 +141,15 @@ out:
 static void poll_spurious_irqs(unsigned long dummy)
 {
 	struct irq_desc *desc;
-	int i;
+	int i, poll_again;

 	if (atomic_inc_return(&irq_poll_active) != 1)
 		goto out;
 	irq_poll_cpu = smp_processor_id();

+	poll_again = 0; /* Will stay false as long as no polling candidate is found */
 	for_each_irq_desc(i, desc) {
-		unsigned int state;
+		unsigned int state, irq;

 		if (!i)
 			 continue;
@@ -158,15 +159,33 @@ static void poll_spurious_irqs(unsigned
		barrier();
		if (!(state & IRQS_SPURIOUS_DISABLED))
			continue;
-
-		local_irq_disable();
-		try_one_irq(i, desc, true);
-		local_irq_enable();
+		
+		/* We end up here with a disabled spurious interrupt.
+		   desc->irqs_unhandled now tracks the number of times
+		   the interrupt has been polled */
+
+		irq = desc->irq_data.irq;
+		if (desc->irqs_unhandled < 100) { /* 1 second delay with pollfrequency 100 Hz */
+			if (desc->irqs_unhandled == 0)
+				printk("Polling IRQ %d\n", irq);
+			local_irq_disable();
+			try_one_irq(i, desc, true);
+			local_irq_enable();
+			desc->irqs_unhandled++;
+			poll_again = 1;
+		} else {
+			printk("Reenabling IRQ %d\n", irq);
+			irq_enable(desc); /* Reenable the interrupt line */
+			desc->depth--;
+			desc->istate &= (~IRQS_SPURIOUS_DISABLED);
+			desc->irqs_unhandled = 0;
+		}
 	}
+	if (poll_again)
+		mod_timer(&poll_spurious_irq_timer,
+			  jiffies + POLL_SPURIOUS_IRQ_INTERVAL);
 out:
 	atomic_dec(&irq_poll_active);
-	mod_timer(&poll_spurious_irq_timer,
-		  jiffies + POLL_SPURIOUS_IRQ_INTERVAL);
 }

 static inline int bad_action_ret(irqreturn_t action_ret)
@@ -177,11 +196,19 @@ static inline int bad_action_ret(irqretu
 }

 /*
- * If 99,900 of the previous 100,000 interrupts have not been handled
+ * If 9 of the previous 10 interrupts have not been handled
  * then assume that the IRQ is stuck in some manner. Drop a diagnostic
  * and try to turn the IRQ off.
  *
- * (The other 100-of-100,000 interrupts may have been a correctly
+ * Although this may cause early deactivation of a sporadically
+ * malfunctioning IRQ line, the poll system will:
+ * a) Poll it for 100 cycles at a 100 Hz rate
+ * b) Reenable it afterwards
+ *

Last edited by wdirksen (2013-09-15 09:52:54)


Research | Trial | Make Mistakes | Ask questions | Learn | Repeat

Offline

Board footer

Powered by FluxBB