|
32 | 32 | */ |
33 | 33 | static void init_8259A(int auto_eoi); |
34 | 34 |
|
| 35 | +static bool pcat_compat __ro_after_init; |
35 | 36 | static int i8259A_auto_eoi; |
36 | 37 | DEFINE_RAW_SPINLOCK(i8259A_lock); |
37 | 38 |
|
@@ -299,15 +300,32 @@ static void unmask_8259A(void) |
299 | 300 |
|
300 | 301 | static int probe_8259A(void) |
301 | 302 | { |
| 303 | + unsigned char new_val, probe_val = ~(1 << PIC_CASCADE_IR); |
302 | 304 | unsigned long flags; |
303 | | - unsigned char probe_val = ~(1 << PIC_CASCADE_IR); |
304 | | - unsigned char new_val; |
| 305 | + |
| 306 | + /* |
| 307 | + * If MADT has the PCAT_COMPAT flag set, then do not bother probing |
| 308 | + * for the PIC. Some BIOSes leave the PIC uninitialized and probing |
| 309 | + * fails. |
| 310 | + * |
| 311 | + * Right now this causes problems as quite some code depends on |
| 312 | + * nr_legacy_irqs() > 0 or has_legacy_pic() == true. This is silly |
| 313 | + * when the system has an IO/APIC because then PIC is not required |
| 314 | + * at all, except for really old machines where the timer interrupt |
| 315 | + * must be routed through the PIC. So just pretend that the PIC is |
| 316 | + * there and let legacy_pic->init() initialize it for nothing. |
| 317 | + * |
| 318 | + * Alternatively this could just try to initialize the PIC and |
| 319 | + * repeat the probe, but for cases where there is no PIC that's |
| 320 | + * just pointless. |
| 321 | + */ |
| 322 | + if (pcat_compat) |
| 323 | + return nr_legacy_irqs(); |
| 324 | + |
305 | 325 | /* |
306 | | - * Check to see if we have a PIC. |
307 | | - * Mask all except the cascade and read |
308 | | - * back the value we just wrote. If we don't |
309 | | - * have a PIC, we will read 0xff as opposed to the |
310 | | - * value we wrote. |
| 326 | + * Check to see if we have a PIC. Mask all except the cascade and |
| 327 | + * read back the value we just wrote. If we don't have a PIC, we |
| 328 | + * will read 0xff as opposed to the value we wrote. |
311 | 329 | */ |
312 | 330 | raw_spin_lock_irqsave(&i8259A_lock, flags); |
313 | 331 |
|
@@ -429,5 +447,9 @@ static int __init i8259A_init_ops(void) |
429 | 447 |
|
430 | 448 | return 0; |
431 | 449 | } |
432 | | - |
433 | 450 | device_initcall(i8259A_init_ops); |
| 451 | + |
| 452 | +void __init legacy_pic_pcat_compat(void) |
| 453 | +{ |
| 454 | + pcat_compat = true; |
| 455 | +} |
0 commit comments