fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / char / hw_random / intel-rng.c
index 8efbc9c..f22e78e 100644 (file)
@@ -143,6 +143,11 @@ static const struct pci_device_id pci_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci, pci_tbl);
 
+static __initdata int no_fwh_detect;
+module_param(no_fwh_detect, int, 0);
+MODULE_PARM_DESC(no_fwh_detect, "Skip FWH detection:\n"
+                                " positive value - skip if FWH space locked read-only\n"
+                                " negative value - skip always");
 
 static inline u8 hwstatus_get(void __iomem *mem)
 {
@@ -240,6 +245,11 @@ static int __init mod_init(void)
        if (!dev)
                goto out; /* Device not found. */
 
+       if (no_fwh_detect < 0) {
+               pci_dev_put(dev);
+               goto fwh_done;
+       }
+
        /* Check for Intel 82802 */
        if (dev->device < 0x2640) {
                fwh_dec_en1_off = FWH_DEC_EN1_REG_OLD;
@@ -252,6 +262,23 @@ static int __init mod_init(void)
        pci_read_config_byte(dev, fwh_dec_en1_off, &fwh_dec_en1_val);
        pci_read_config_byte(dev, bios_cntl_off, &bios_cntl_val);
 
+       if ((bios_cntl_val &
+            (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK))
+           == BIOS_CNTL_LOCK_ENABLE_MASK) {
+               static __initdata /*const*/ char warning[] =
+                       KERN_WARNING PFX "Firmware space is locked read-only. If you can't or\n"
+                       KERN_WARNING PFX "don't want to disable this in firmware setup, and if\n"
+                       KERN_WARNING PFX "you are certain that your system has a functional\n"
+                       KERN_WARNING PFX "RNG, try using the 'no_fwh_detect' option.\n";
+
+               pci_dev_put(dev);
+               if (no_fwh_detect)
+                       goto fwh_done;
+               printk(warning);
+               err = -EBUSY;
+               goto out;
+       }
+
        mem = ioremap_nocache(INTEL_FWH_ADDR, INTEL_FWH_ADDR_LEN);
        if (mem == NULL) {
                pci_dev_put(dev);
@@ -280,8 +307,7 @@ static int __init mod_init(void)
                pci_write_config_byte(dev,
                                      fwh_dec_en1_off,
                                      fwh_dec_en1_val | FWH_F8_EN_MASK);
-       if (!(bios_cntl_val &
-             (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK)))
+       if (!(bios_cntl_val & BIOS_CNTL_WRITE_ENABLE_MASK))
                pci_write_config_byte(dev,
                                      bios_cntl_off,
                                      bios_cntl_val | BIOS_CNTL_WRITE_ENABLE_MASK);
@@ -315,6 +341,8 @@ static int __init mod_init(void)
                goto out;
        }
 
+fwh_done:
+
        err = -ENOMEM;
        mem = ioremap(INTEL_RNG_ADDR, INTEL_RNG_ADDR_LEN);
        if (!mem)
@@ -350,7 +378,7 @@ static void __exit mod_exit(void)
        iounmap(mem);
 }
 
-subsys_initcall(mod_init);
+module_init(mod_init);
 module_exit(mod_exit);
 
 MODULE_DESCRIPTION("H/W RNG driver for Intel chipsets");