[PATCH] intel-rng workarounds

Add a load option to intel-rng to allow skipping the FWH detection,
necessary in case the BIOS has locked read-only the firmware hub space.
Also prevent any attempt to write to firmware space if it cannot be write
enabled (apparently caused hangs on some systems not having an FWH and thus
also not having a respective RNG).

Signed-off-by: Jan Beulich <jbeulich@novell.com>
Signed-off-by: Michael Buesch <mb@bu3sch.de>
Cc: Jeff Garzik <jeff@garzik.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by Jan Beulich and committed by Linus Torvalds 9863be59 f73ca1b7

+30 -2
+30 -2
drivers/char/hw_random/intel-rng.c
··· 143 143 }; 144 144 MODULE_DEVICE_TABLE(pci, pci_tbl); 145 145 146 + static __initdata int no_fwh_detect; 147 + module_param(no_fwh_detect, int, 0); 148 + MODULE_PARM_DESC(no_fwh_detect, "Skip FWH detection:\n" 149 + " positive value - skip if FWH space locked read-only\n" 150 + " negative value - skip always"); 146 151 147 152 static inline u8 hwstatus_get(void __iomem *mem) 148 153 { ··· 245 240 if (!dev) 246 241 goto out; /* Device not found. */ 247 242 243 + if (no_fwh_detect < 0) { 244 + pci_dev_put(dev); 245 + goto fwh_done; 246 + } 247 + 248 248 /* Check for Intel 82802 */ 249 249 if (dev->device < 0x2640) { 250 250 fwh_dec_en1_off = FWH_DEC_EN1_REG_OLD; ··· 261 251 262 252 pci_read_config_byte(dev, fwh_dec_en1_off, &fwh_dec_en1_val); 263 253 pci_read_config_byte(dev, bios_cntl_off, &bios_cntl_val); 254 + 255 + if ((bios_cntl_val & 256 + (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK)) 257 + == BIOS_CNTL_LOCK_ENABLE_MASK) { 258 + static __initdata /*const*/ char warning[] = 259 + KERN_WARNING PFX "Firmware space is locked read-only. If you can't or\n" 260 + KERN_WARNING PFX "don't want to disable this in firmware setup, and if\n" 261 + KERN_WARNING PFX "you are certain that your system has a functional\n" 262 + KERN_WARNING PFX "RNG, try using the 'no_fwh_detect' option.\n"; 263 + 264 + pci_dev_put(dev); 265 + if (no_fwh_detect) 266 + goto fwh_done; 267 + printk(warning); 268 + err = -EBUSY; 269 + goto out; 270 + } 264 271 265 272 mem = ioremap_nocache(INTEL_FWH_ADDR, INTEL_FWH_ADDR_LEN); 266 273 if (mem == NULL) { ··· 307 280 pci_write_config_byte(dev, 308 281 fwh_dec_en1_off, 309 282 fwh_dec_en1_val | FWH_F8_EN_MASK); 310 - if (!(bios_cntl_val & 311 - (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK))) 283 + if (!(bios_cntl_val & BIOS_CNTL_WRITE_ENABLE_MASK)) 312 284 pci_write_config_byte(dev, 313 285 bios_cntl_off, 314 286 bios_cntl_val | BIOS_CNTL_WRITE_ENABLE_MASK); ··· 340 314 err = -ENODEV; 341 315 goto out; 342 316 } 317 + 318 + fwh_done: 343 319 344 320 err = -ENOMEM; 345 321 mem = ioremap(INTEL_RNG_ADDR, INTEL_RNG_ADDR_LEN);