diff options
author | Steven Whitehouse <swhiteho@redhat.com> | 2006-03-31 15:34:58 -0500 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2006-03-31 15:34:58 -0500 |
commit | 86579dd06deecfa6ac88d5e84e4d63c397cd6f6d (patch) | |
tree | b4475d3ccde53015ad84a06e4e55e64591171b75 /drivers/firmware | |
parent | 7ea9ea832212c4a755650f7c7cc1ff0b63292a41 (diff) | |
parent | a0f067802576d4eb4c65d40b8ee7d6ea3c81dd61 (diff) | |
download | op-kernel-dev-86579dd06deecfa6ac88d5e84e4d63c397cd6f6d.zip op-kernel-dev-86579dd06deecfa6ac88d5e84e4d63c397cd6f6d.tar.gz |
Merge branch 'master'
Diffstat (limited to 'drivers/firmware')
-rw-r--r-- | drivers/firmware/dcdbas.c | 152 | ||||
-rw-r--r-- | drivers/firmware/efivars.c | 28 | ||||
-rw-r--r-- | drivers/firmware/pcdp.c | 19 |
3 files changed, 130 insertions, 69 deletions
diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c index 4652512..339f405 100644 --- a/drivers/firmware/dcdbas.c +++ b/drivers/firmware/dcdbas.c @@ -33,6 +33,7 @@ #include <linux/spinlock.h> #include <linux/string.h> #include <linux/types.h> +#include <linux/mutex.h> #include <asm/io.h> #include <asm/semaphore.h> @@ -48,7 +49,7 @@ static u8 *smi_data_buf; static dma_addr_t smi_data_buf_handle; static unsigned long smi_data_buf_size; static u32 smi_data_buf_phys_addr; -static DECLARE_MUTEX(smi_data_lock); +static DEFINE_MUTEX(smi_data_lock); static unsigned int host_control_action; static unsigned int host_control_smi_type; @@ -139,9 +140,9 @@ static ssize_t smi_data_buf_size_store(struct device *dev, buf_size = simple_strtoul(buf, NULL, 10); /* make sure SMI data buffer is at least buf_size */ - down(&smi_data_lock); + mutex_lock(&smi_data_lock); ret = smi_data_buf_realloc(buf_size); - up(&smi_data_lock); + mutex_unlock(&smi_data_lock); if (ret) return ret; @@ -154,7 +155,7 @@ static ssize_t smi_data_read(struct kobject *kobj, char *buf, loff_t pos, size_t max_read; ssize_t ret; - down(&smi_data_lock); + mutex_lock(&smi_data_lock); if (pos >= smi_data_buf_size) { ret = 0; @@ -165,7 +166,7 @@ static ssize_t smi_data_read(struct kobject *kobj, char *buf, loff_t pos, ret = min(max_read, count); memcpy(buf, smi_data_buf + pos, ret); out: - up(&smi_data_lock); + mutex_unlock(&smi_data_lock); return ret; } @@ -174,7 +175,7 @@ static ssize_t smi_data_write(struct kobject *kobj, char *buf, loff_t pos, { ssize_t ret; - down(&smi_data_lock); + mutex_lock(&smi_data_lock); ret = smi_data_buf_realloc(pos + count); if (ret) @@ -183,7 +184,7 @@ static ssize_t smi_data_write(struct kobject *kobj, char *buf, loff_t pos, memcpy(smi_data_buf + pos, buf, count); ret = count; out: - up(&smi_data_lock); + mutex_unlock(&smi_data_lock); return ret; } @@ -201,9 +202,9 @@ static ssize_t host_control_action_store(struct device *dev, ssize_t ret; /* make sure buffer is available for host control command */ - down(&smi_data_lock); + mutex_lock(&smi_data_lock); ret = smi_data_buf_realloc(sizeof(struct apm_cmd)); - up(&smi_data_lock); + mutex_unlock(&smi_data_lock); if (ret) return ret; @@ -302,7 +303,7 @@ static ssize_t smi_request_store(struct device *dev, unsigned long val = simple_strtoul(buf, NULL, 10); ssize_t ret; - down(&smi_data_lock); + mutex_lock(&smi_data_lock); if (smi_data_buf_size < sizeof(struct smi_cmd)) { ret = -ENODEV; @@ -334,7 +335,7 @@ static ssize_t smi_request_store(struct device *dev, } out: - up(&smi_data_lock); + mutex_unlock(&smi_data_lock); return ret; } @@ -483,26 +484,15 @@ static void dcdbas_host_control(void) static int dcdbas_reboot_notify(struct notifier_block *nb, unsigned long code, void *unused) { - static unsigned int notify_cnt = 0; - switch (code) { case SYS_DOWN: case SYS_HALT: case SYS_POWER_OFF: if (host_control_on_shutdown) { /* firmware is going to perform host control action */ - if (++notify_cnt == 2) { - printk(KERN_WARNING - "Please wait for shutdown " - "action to complete...\n"); - dcdbas_host_control(); - } - /* - * register again and initiate the host control - * action on the second notification to allow - * everyone that registered to be notified - */ - register_reboot_notifier(nb); + printk(KERN_WARNING "Please wait for shutdown " + "action to complete...\n"); + dcdbas_host_control(); } break; } @@ -513,7 +503,7 @@ static int dcdbas_reboot_notify(struct notifier_block *nb, unsigned long code, static struct notifier_block dcdbas_reboot_nb = { .notifier_call = dcdbas_reboot_notify, .next = NULL, - .priority = 0 + .priority = INT_MIN }; static DCDBAS_BIN_ATTR_RW(smi_data); @@ -530,30 +520,27 @@ static DCDBAS_DEV_ATTR_RW(host_control_action); static DCDBAS_DEV_ATTR_RW(host_control_smi_type); static DCDBAS_DEV_ATTR_RW(host_control_on_shutdown); -static struct device_attribute *dcdbas_dev_attrs[] = { - &dev_attr_smi_data_buf_size, - &dev_attr_smi_data_buf_phys_addr, - &dev_attr_smi_request, - &dev_attr_host_control_action, - &dev_attr_host_control_smi_type, - &dev_attr_host_control_on_shutdown, +static struct attribute *dcdbas_dev_attrs[] = { + &dev_attr_smi_data_buf_size.attr, + &dev_attr_smi_data_buf_phys_addr.attr, + &dev_attr_smi_request.attr, + &dev_attr_host_control_action.attr, + &dev_attr_host_control_smi_type.attr, + &dev_attr_host_control_on_shutdown.attr, NULL }; -/** - * dcdbas_init: initialize driver - */ -static int __init dcdbas_init(void) +static struct attribute_group dcdbas_attr_group = { + .attrs = dcdbas_dev_attrs, +}; + +static int __devinit dcdbas_probe(struct platform_device *dev) { - int i; + int i, error; host_control_action = HC_ACTION_NONE; host_control_smi_type = HC_SMITYPE_NONE; - dcdbas_pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0); - if (IS_ERR(dcdbas_pdev)) - return PTR_ERR(dcdbas_pdev); - /* * BIOS SMI calls require buffer addresses be in 32-bit address space. * This is done by setting the DMA mask below. @@ -561,19 +548,79 @@ static int __init dcdbas_init(void) dcdbas_pdev->dev.coherent_dma_mask = DMA_32BIT_MASK; dcdbas_pdev->dev.dma_mask = &dcdbas_pdev->dev.coherent_dma_mask; + error = sysfs_create_group(&dev->dev.kobj, &dcdbas_attr_group); + if (error) + return error; + + for (i = 0; dcdbas_bin_attrs[i]; i++) { + error = sysfs_create_bin_file(&dev->dev.kobj, + dcdbas_bin_attrs[i]); + if (error) { + while (--i >= 0) + sysfs_remove_bin_file(&dev->dev.kobj, + dcdbas_bin_attrs[i]); + sysfs_create_group(&dev->dev.kobj, &dcdbas_attr_group); + return error; + } + } + register_reboot_notifier(&dcdbas_reboot_nb); + dev_info(&dev->dev, "%s (version %s)\n", + DRIVER_DESCRIPTION, DRIVER_VERSION); + + return 0; +} + +static int __devexit dcdbas_remove(struct platform_device *dev) +{ + int i; + + unregister_reboot_notifier(&dcdbas_reboot_nb); for (i = 0; dcdbas_bin_attrs[i]; i++) - sysfs_create_bin_file(&dcdbas_pdev->dev.kobj, - dcdbas_bin_attrs[i]); + sysfs_remove_bin_file(&dev->dev.kobj, dcdbas_bin_attrs[i]); + sysfs_remove_group(&dev->dev.kobj, &dcdbas_attr_group); - for (i = 0; dcdbas_dev_attrs[i]; i++) - device_create_file(&dcdbas_pdev->dev, dcdbas_dev_attrs[i]); + return 0; +} - dev_info(&dcdbas_pdev->dev, "%s (version %s)\n", - DRIVER_DESCRIPTION, DRIVER_VERSION); +static struct platform_driver dcdbas_driver = { + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + }, + .probe = dcdbas_probe, + .remove = __devexit_p(dcdbas_remove), +}; + +/** + * dcdbas_init: initialize driver + */ +static int __init dcdbas_init(void) +{ + int error; + + error = platform_driver_register(&dcdbas_driver); + if (error) + return error; + + dcdbas_pdev = platform_device_alloc(DRIVER_NAME, -1); + if (!dcdbas_pdev) { + error = -ENOMEM; + goto err_unregister_driver; + } + + error = platform_device_add(dcdbas_pdev); + if (error) + goto err_free_device; return 0; + + err_free_device: + platform_device_put(dcdbas_pdev); + err_unregister_driver: + platform_driver_unregister(&dcdbas_driver); + return error; } /** @@ -588,6 +635,15 @@ static void __exit dcdbas_exit(void) unregister_reboot_notifier(&dcdbas_reboot_nb); smi_data_buf_free(); platform_device_unregister(dcdbas_pdev); + platform_driver_unregister(&dcdbas_driver); + + /* + * We have to free the buffer here instead of dcdbas_remove + * because only in module exit function we can be sure that + * all sysfs attributes belonging to this module have been + * released. + */ + smi_data_buf_free(); } module_init(dcdbas_init); diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c index 343379f..9b7e4d5 100644 --- a/drivers/firmware/efivars.c +++ b/drivers/firmware/efivars.c @@ -568,20 +568,20 @@ systab_read(struct subsystem *entry, char *buf) if (!entry || !buf) return -EINVAL; - if (efi.mps) - str += sprintf(str, "MPS=0x%lx\n", __pa(efi.mps)); - if (efi.acpi20) - str += sprintf(str, "ACPI20=0x%lx\n", __pa(efi.acpi20)); - if (efi.acpi) - str += sprintf(str, "ACPI=0x%lx\n", __pa(efi.acpi)); - if (efi.smbios) - str += sprintf(str, "SMBIOS=0x%lx\n", __pa(efi.smbios)); - if (efi.hcdp) - str += sprintf(str, "HCDP=0x%lx\n", __pa(efi.hcdp)); - if (efi.boot_info) - str += sprintf(str, "BOOTINFO=0x%lx\n", __pa(efi.boot_info)); - if (efi.uga) - str += sprintf(str, "UGA=0x%lx\n", __pa(efi.uga)); + if (efi.mps != EFI_INVALID_TABLE_ADDR) + str += sprintf(str, "MPS=0x%lx\n", efi.mps); + if (efi.acpi20 != EFI_INVALID_TABLE_ADDR) + str += sprintf(str, "ACPI20=0x%lx\n", efi.acpi20); + if (efi.acpi != EFI_INVALID_TABLE_ADDR) + str += sprintf(str, "ACPI=0x%lx\n", efi.acpi); + if (efi.smbios != EFI_INVALID_TABLE_ADDR) + str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios); + if (efi.hcdp != EFI_INVALID_TABLE_ADDR) + str += sprintf(str, "HCDP=0x%lx\n", efi.hcdp); + if (efi.boot_info != EFI_INVALID_TABLE_ADDR) + str += sprintf(str, "BOOTINFO=0x%lx\n", efi.boot_info); + if (efi.uga != EFI_INVALID_TABLE_ADDR) + str += sprintf(str, "UGA=0x%lx\n", efi.uga); return str - buf; } diff --git a/drivers/firmware/pcdp.c b/drivers/firmware/pcdp.c index ae1fb45..c37baf9 100644 --- a/drivers/firmware/pcdp.c +++ b/drivers/firmware/pcdp.c @@ -89,19 +89,20 @@ efi_setup_pcdp_console(char *cmdline) struct pcdp_uart *uart; struct pcdp_device *dev, *end; int i, serial = 0; + int rc = -ENODEV; - pcdp = efi.hcdp; - if (!pcdp) + if (efi.hcdp == EFI_INVALID_TABLE_ADDR) return -ENODEV; - printk(KERN_INFO "PCDP: v%d at 0x%lx\n", pcdp->rev, __pa(pcdp)); + pcdp = ioremap(efi.hcdp, 4096); + printk(KERN_INFO "PCDP: v%d at 0x%lx\n", pcdp->rev, efi.hcdp); if (strstr(cmdline, "console=hcdp")) { if (pcdp->rev < 3) serial = 1; } else if (strstr(cmdline, "console=")) { printk(KERN_INFO "Explicit \"console=\"; ignoring PCDP\n"); - return -ENODEV; + goto out; } if (pcdp->rev < 3 && efi_uart_console_only()) @@ -110,7 +111,8 @@ efi_setup_pcdp_console(char *cmdline) for (i = 0, uart = pcdp->uart; i < pcdp->num_uarts; i++, uart++) { if (uart->flags & PCDP_UART_PRIMARY_CONSOLE || serial) { if (uart->type == PCDP_CONSOLE_UART) { - return setup_serial_console(uart); + rc = setup_serial_console(uart); + goto out; } } } @@ -121,10 +123,13 @@ efi_setup_pcdp_console(char *cmdline) dev = (struct pcdp_device *) ((u8 *) dev + dev->length)) { if (dev->flags & PCDP_PRIMARY_CONSOLE) { if (dev->type == PCDP_CONSOLE_VGA) { - return setup_vga_console(dev); + rc = setup_vga_console(dev); + goto out; } } } - return -ENODEV; +out: + iounmap(pcdp); + return rc; } |