|
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