[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 }; 144 MODULE_DEVICE_TABLE(pci, pci_tbl); 145 146 147 static inline u8 hwstatus_get(void __iomem *mem) 148 { ··· 245 if (!dev) 246 goto out; /* Device not found. */ 247 248 /* Check for Intel 82802 */ 249 if (dev->device < 0x2640) { 250 fwh_dec_en1_off = FWH_DEC_EN1_REG_OLD; ··· 261 262 pci_read_config_byte(dev, fwh_dec_en1_off, &fwh_dec_en1_val); 263 pci_read_config_byte(dev, bios_cntl_off, &bios_cntl_val); 264 265 mem = ioremap_nocache(INTEL_FWH_ADDR, INTEL_FWH_ADDR_LEN); 266 if (mem == NULL) { ··· 307 pci_write_config_byte(dev, 308 fwh_dec_en1_off, 309 fwh_dec_en1_val | FWH_F8_EN_MASK); 310 - if (!(bios_cntl_val & 311 - (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK))) 312 pci_write_config_byte(dev, 313 bios_cntl_off, 314 bios_cntl_val | BIOS_CNTL_WRITE_ENABLE_MASK); ··· 340 err = -ENODEV; 341 goto out; 342 } 343 344 err = -ENOMEM; 345 mem = ioremap(INTEL_RNG_ADDR, INTEL_RNG_ADDR_LEN);
··· 143 }; 144 MODULE_DEVICE_TABLE(pci, pci_tbl); 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"); 151 152 static inline u8 hwstatus_get(void __iomem *mem) 153 { ··· 240 if (!dev) 241 goto out; /* Device not found. */ 242 243 + if (no_fwh_detect < 0) { 244 + pci_dev_put(dev); 245 + goto fwh_done; 246 + } 247 + 248 /* Check for Intel 82802 */ 249 if (dev->device < 0x2640) { 250 fwh_dec_en1_off = FWH_DEC_EN1_REG_OLD; ··· 251 252 pci_read_config_byte(dev, fwh_dec_en1_off, &fwh_dec_en1_val); 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 + } 271 272 mem = ioremap_nocache(INTEL_FWH_ADDR, INTEL_FWH_ADDR_LEN); 273 if (mem == NULL) { ··· 280 pci_write_config_byte(dev, 281 fwh_dec_en1_off, 282 fwh_dec_en1_val | FWH_F8_EN_MASK); 283 + if (!(bios_cntl_val & BIOS_CNTL_WRITE_ENABLE_MASK)) 284 pci_write_config_byte(dev, 285 bios_cntl_off, 286 bios_cntl_val | BIOS_CNTL_WRITE_ENABLE_MASK); ··· 314 err = -ENODEV; 315 goto out; 316 } 317 + 318 + fwh_done: 319 320 err = -ENOMEM; 321 mem = ioremap(INTEL_RNG_ADDR, INTEL_RNG_ADDR_LEN);