summaryrefslogtreecommitdiffstats
path: root/sys/pci/pci_compat.c
diff options
context:
space:
mode:
authortegge <tegge@FreeBSD.org>1998-04-01 21:07:37 +0000
committertegge <tegge@FreeBSD.org>1998-04-01 21:07:37 +0000
commit028480bfb1299a0a34ad19f20e2cc3f24b402235 (patch)
tree77436497a16e77fa303820d1d60caeb109f2acad /sys/pci/pci_compat.c
parent574d6dcedfc1e96deb88ef6e7f5540eab053fe2d (diff)
downloadFreeBSD-src-028480bfb1299a0a34ad19f20e2cc3f24b402235.zip
FreeBSD-src-028480bfb1299a0a34ad19f20e2cc3f24b402235.tar.gz
Add two workarounds for broken MP tables:
- Attempt to handle PCI devices where the interrupt is an ISA/EISA interrupt according to the mp table. - Attempt to handle multiple IO APIC pins connected to the same PCI or ISA/EISA interrupt source. Print a warning if this happens, since performance is suboptimal. This workaround is only used for PCI devices. With these two workarounds, the -SMP kernel is capable of running on my Asus P/I-P65UP5 motherboard when version 1.4 of the MP table is disabled.
Diffstat (limited to 'sys/pci/pci_compat.c')
-rw-r--r--sys/pci/pci_compat.c48
1 files changed, 46 insertions, 2 deletions
diff --git a/sys/pci/pci_compat.c b/sys/pci/pci_compat.c
index 9041156..8499fcf 100644
--- a/sys/pci/pci_compat.c
+++ b/sys/pci/pci_compat.c
@@ -23,7 +23,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: pci_compat.c,v 1.5 1997/08/21 07:05:48 fsmp Exp $
+ * $Id: pci_compat.c,v 1.6 1997/08/21 08:42:59 fsmp Exp $
*
*/
@@ -164,13 +164,57 @@ int pci_map_mem(pcici_t cfg, u_long reg, vm_offset_t* va, vm_offset_t* pa)
int
pci_map_int(pcici_t cfg, pci_inthand_t *func, void *arg, unsigned *maskptr)
{
+ int error;
+#ifdef APIC_IO
+ int nextpin, muxcnt;
+#endif
if (cfg->intpin != 0) {
int irq = cfg->intline;
void *dev_instance = (void *)-1; /* XXX use cfg->devdata */
void *idesc;
idesc = intr_create(dev_instance, irq, func, arg, maskptr, 0);
- return (intr_connect(idesc) == 0);
+ error = intr_connect(idesc);
+ if (error != 0)
+ return 0;
+#ifdef APIC_IO
+ nextpin = next_apic_pin(irq);
+
+ if (nextpin < 0)
+ return 1;
+
+ /*
+ * Attempt handling of some broken mp tables.
+ *
+ * It's OK to yell (since the mp tables are broken).
+ *
+ * Hanging in the boot is not OK
+ */
+
+ muxcnt = 2;
+ nextpin = next_apic_pin(nextpin);
+ while (muxcnt < 5 && nextpin >= 0) {
+ muxcnt++;
+ nextpin = next_apic_pin(nextpin);
+ }
+ if (muxcnt >= 5) {
+ printf("bogus MP table, more than 4 IO APIC pins connected to the same PCI device or ISA/EISA interrupt\n");
+ return 0;
+ }
+
+ printf("bogus MP table, %d IO APIC pins connected to the same PCI device or ISA/EISA interrupt\n", muxcnt);
+
+ nextpin = next_apic_pin(irq);
+ while (nextpin >= 0) {
+ idesc = intr_create(dev_instance, nextpin, func, arg,
+ maskptr, 0);
+ error = intr_connect(idesc);
+ if (error != 0)
+ return 0;
+ printf("Registered extra interrupt handler for int %d (in addition to int %d)\n", nextpin, irq);
+ nextpin = next_apic_pin(nextpin);
+ }
+#endif
}
return (1);
}
OpenPOWER on IntegriCloud