diff options
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/Kconfig | 4 | ||||
-rw-r--r-- | drivers/char/agp/amd64-agp.c | 10 | ||||
-rw-r--r-- | drivers/char/agp/backend.c | 13 | ||||
-rw-r--r-- | drivers/char/agp/hp-agp.c | 6 | ||||
-rw-r--r-- | drivers/char/agp/intel-agp.c | 6 | ||||
-rw-r--r-- | drivers/char/agp/uninorth-agp.c | 77 | ||||
-rw-r--r-- | drivers/char/efirtc.c | 1 | ||||
-rw-r--r-- | drivers/char/hvc_console.c | 1 | ||||
-rw-r--r-- | drivers/char/hvc_iucv.c | 2 | ||||
-rw-r--r-- | drivers/char/hw_random/core.c | 5 | ||||
-rw-r--r-- | drivers/char/hw_random/virtio-rng.c | 6 | ||||
-rw-r--r-- | drivers/char/ipmi/ipmi_kcs_sm.c | 2 | ||||
-rw-r--r-- | drivers/char/ipmi/ipmi_si_intf.c | 118 | ||||
-rw-r--r-- | drivers/char/keyboard.c | 10 | ||||
-rw-r--r-- | drivers/char/lp.c | 115 | ||||
-rw-r--r-- | drivers/char/mem.c | 161 | ||||
-rw-r--r-- | drivers/char/misc.c | 26 | ||||
-rw-r--r-- | drivers/char/nozomi.c | 50 | ||||
-rw-r--r-- | drivers/char/nvram.c | 14 | ||||
-rw-r--r-- | drivers/char/nwflash.c | 1 | ||||
-rw-r--r-- | drivers/char/random.c | 10 | ||||
-rw-r--r-- | drivers/char/sonypi.c | 60 | ||||
-rw-r--r-- | drivers/char/sysrq.c | 2 | ||||
-rw-r--r-- | drivers/char/toshiba.c | 12 | ||||
-rw-r--r-- | drivers/char/tty_io.c | 4 | ||||
-rw-r--r-- | drivers/char/vt.c | 50 |
26 files changed, 467 insertions, 299 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 6f31c9472100..e023682be2c4 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -502,7 +502,7 @@ config BRIQ_PANEL config BFIN_OTP tristate "Blackfin On-Chip OTP Memory Support" - depends on BLACKFIN && (BF52x || BF54x) + depends on BLACKFIN && (BF51x || BF52x || BF54x) default y help If you say Y here, you will get support for a character device @@ -669,7 +669,7 @@ config VIRTIO_CONSOLE config HVCS tristate "IBM Hypervisor Virtual Console Server support" - depends on PPC_PSERIES + depends on PPC_PSERIES && HVC_CONSOLE help Partitionable IBM Power5 ppc64 machines allow hosting of firmware virtual consoles from one Linux partition by diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 2fb2e6cc322a..1afb8968a342 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c @@ -728,6 +728,10 @@ int __init agp_amd64_init(void) if (agp_off) return -EINVAL; + + if (gart_iommu_aperture) + return agp_bridges_found ? 0 : -ENODEV; + err = pci_register_driver(&agp_amd64_pci_driver); if (err < 0) return err; @@ -766,17 +770,15 @@ int __init agp_amd64_init(void) static void __exit agp_amd64_cleanup(void) { + if (gart_iommu_aperture) + return; if (aperture_resource) release_resource(aperture_resource); pci_unregister_driver(&agp_amd64_pci_driver); } -/* On AMD64 the PCI driver needs to initialize this driver early - for the IOMMU, so it has to be called via a backdoor. */ -#ifndef CONFIG_GART_IOMMU module_init(agp_amd64_init); module_exit(agp_amd64_cleanup); -#endif MODULE_AUTHOR("Dave Jones <davej@redhat.com>, Andi Kleen"); module_param(agp_try_unsupported, bool, 0); diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c index a56ca080e108..c3ab46da51a3 100644 --- a/drivers/char/agp/backend.c +++ b/drivers/char/agp/backend.c @@ -285,18 +285,22 @@ int agp_add_bridge(struct agp_bridge_data *bridge) { int error; - if (agp_off) - return -ENODEV; + if (agp_off) { + error = -ENODEV; + goto err_put_bridge; + } if (!bridge->dev) { printk (KERN_DEBUG PFX "Erk, registering with no pci_dev!\n"); - return -EINVAL; + error = -EINVAL; + goto err_put_bridge; } /* Grab reference on the chipset driver. */ if (!try_module_get(bridge->driver->owner)) { dev_info(&bridge->dev->dev, "can't lock chipset driver\n"); - return -EINVAL; + error = -EINVAL; + goto err_put_bridge; } error = agp_backend_initialize(bridge); @@ -326,6 +330,7 @@ frontend_err: agp_backend_cleanup(bridge); err_out: module_put(bridge->driver->owner); +err_put_bridge: agp_put_bridge(bridge); return error; } diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c index 9047b2714653..58752b70efea 100644 --- a/drivers/char/agp/hp-agp.c +++ b/drivers/char/agp/hp-agp.c @@ -488,9 +488,8 @@ zx1_gart_probe (acpi_handle obj, u32 depth, void *context, void **ret) handle = obj; do { status = acpi_get_object_info(handle, &info); - if (ACPI_SUCCESS(status)) { + if (ACPI_SUCCESS(status) && (info->valid & ACPI_VALID_HID)) { /* TBD check _CID also */ - info->hardware_id.string[sizeof(info->hardware_id.length)-1] = '\0'; match = (strcmp(info->hardware_id.string, "HWP0001") == 0); kfree(info); if (match) { @@ -509,6 +508,9 @@ zx1_gart_probe (acpi_handle obj, u32 depth, void *context, void **ret) handle = parent; } while (ACPI_SUCCESS(status)); + if (ACPI_FAILURE(status)) + return AE_OK; /* found no enclosing IOC */ + if (hp_zx1_setup(sba_hpa + HP_ZX1_IOC_OFFSET, lba_hpa)) return AE_OK; diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 30c36ac2cd00..3999a5f25f38 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -2460,10 +2460,14 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, &bridge->mode); } - if (bridge->driver->mask_memory == intel_i965_mask_memory) + if (bridge->driver->mask_memory == intel_i965_mask_memory) { if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(36))) dev_err(&intel_private.pcidev->dev, "set gfx device dma mask 36bit failed!\n"); + else + pci_set_consistent_dma_mask(intel_private.pcidev, + DMA_BIT_MASK(36)); + } pci_set_drvdata(pdev, bridge); return agp_add_bridge(bridge); diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c index 703959eba45a..d89da4ac061f 100644 --- a/drivers/char/agp/uninorth-agp.c +++ b/drivers/char/agp/uninorth-agp.c @@ -144,16 +144,13 @@ static int uninorth_configure(void) return 0; } -static int uninorth_insert_memory(struct agp_memory *mem, off_t pg_start, - int type) +static int uninorth_insert_memory(struct agp_memory *mem, off_t pg_start, int type) { - int i, j, num_entries; + int i, num_entries; void *temp; + u32 *gp; int mask_type; - temp = agp_bridge->current_size; - num_entries = A_SIZE_32(temp)->num_entries; - if (type != mem->type) return -EINVAL; @@ -163,49 +160,12 @@ static int uninorth_insert_memory(struct agp_memory *mem, off_t pg_start, return -EINVAL; } - if ((pg_start + mem->page_count) > num_entries) - return -EINVAL; - - j = pg_start; - - while (j < (pg_start + mem->page_count)) { - if (agp_bridge->gatt_table[j]) - return -EBUSY; - j++; - } - - for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { - agp_bridge->gatt_table[j] = - cpu_to_le32((page_to_phys(mem->pages[i]) & 0xFFFFF000UL) | 0x1UL); - flush_dcache_range((unsigned long)__va(page_to_phys(mem->pages[i])), - (unsigned long)__va(page_to_phys(mem->pages[i]))+0x1000); - } - (void)in_le32((volatile u32*)&agp_bridge->gatt_table[pg_start]); - mb(); - - uninorth_tlbflush(mem); - return 0; -} - -static int u3_insert_memory(struct agp_memory *mem, off_t pg_start, int type) -{ - int i, num_entries; - void *temp; - u32 *gp; - int mask_type; + if (mem->page_count == 0) + return 0; temp = agp_bridge->current_size; num_entries = A_SIZE_32(temp)->num_entries; - if (type != mem->type) - return -EINVAL; - - mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type); - if (mask_type != 0) { - /* We know nothing of memory types */ - return -EINVAL; - } - if ((pg_start + mem->page_count) > num_entries) return -EINVAL; @@ -213,14 +173,18 @@ static int u3_insert_memory(struct agp_memory *mem, off_t pg_start, int type) for (i = 0; i < mem->page_count; ++i) { if (gp[i]) { dev_info(&agp_bridge->dev->dev, - "u3_insert_memory: entry 0x%x occupied (%x)\n", + "uninorth_insert_memory: entry 0x%x occupied (%x)\n", i, gp[i]); return -EBUSY; } } for (i = 0; i < mem->page_count; i++) { - gp[i] = (page_to_phys(mem->pages[i]) >> PAGE_SHIFT) | 0x80000000UL; + if (is_u3) + gp[i] = (page_to_phys(mem->pages[i]) >> PAGE_SHIFT) | 0x80000000UL; + else + gp[i] = cpu_to_le32((page_to_phys(mem->pages[i]) & 0xFFFFF000UL) | + 0x1UL); flush_dcache_range((unsigned long)__va(page_to_phys(mem->pages[i])), (unsigned long)__va(page_to_phys(mem->pages[i]))+0x1000); } @@ -230,14 +194,23 @@ static int u3_insert_memory(struct agp_memory *mem, off_t pg_start, int type) return 0; } -int u3_remove_memory(struct agp_memory *mem, off_t pg_start, int type) +int uninorth_remove_memory(struct agp_memory *mem, off_t pg_start, int type) { size_t i; u32 *gp; + int mask_type; + + if (type != mem->type) + return -EINVAL; - if (type != 0 || mem->type != 0) + mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type); + if (mask_type != 0) { /* We know nothing of memory types */ return -EINVAL; + } + + if (mem->page_count == 0) + return 0; gp = (u32 *) &agp_bridge->gatt_table[pg_start]; for (i = 0; i < mem->page_count; ++i) @@ -536,7 +509,7 @@ const struct agp_bridge_driver uninorth_agp_driver = { .create_gatt_table = uninorth_create_gatt_table, .free_gatt_table = uninorth_free_gatt_table, .insert_memory = uninorth_insert_memory, - .remove_memory = agp_generic_remove_memory, + .remove_memory = uninorth_remove_memory, .alloc_by_type = agp_generic_alloc_by_type, .free_by_type = agp_generic_free_by_type, .agp_alloc_page = agp_generic_alloc_page, @@ -562,8 +535,8 @@ const struct agp_bridge_driver u3_agp_driver = { .agp_enable = uninorth_agp_enable, .create_gatt_table = uninorth_create_gatt_table, .free_gatt_table = uninorth_free_gatt_table, - .insert_memory = u3_insert_memory, - .remove_memory = u3_remove_memory, + .insert_memory = uninorth_insert_memory, + .remove_memory = uninorth_remove_memory, .alloc_by_type = agp_generic_alloc_by_type, .free_by_type = agp_generic_free_by_type, .agp_alloc_page = agp_generic_alloc_page, diff --git a/drivers/char/efirtc.c b/drivers/char/efirtc.c index 26a47dc88f61..53c524e7b829 100644 --- a/drivers/char/efirtc.c +++ b/drivers/char/efirtc.c @@ -285,6 +285,7 @@ static const struct file_operations efi_rtc_fops = { .unlocked_ioctl = efi_rtc_ioctl, .open = efi_rtc_open, .release = efi_rtc_close, + .llseek = no_llseek, }; static struct miscdevice efi_rtc_dev= { diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index a632f25f144a..416d3423150d 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c @@ -832,6 +832,7 @@ int hvc_remove(struct hvc_struct *hp) tty_hangup(tty); return 0; } +EXPORT_SYMBOL_GPL(hvc_remove); /* Driver initialization: called as soon as someone uses hvc_alloc(). */ static int hvc_init(void) diff --git a/drivers/char/hvc_iucv.c b/drivers/char/hvc_iucv.c index b8a5d654d3d0..fe62bd0e17b7 100644 --- a/drivers/char/hvc_iucv.c +++ b/drivers/char/hvc_iucv.c @@ -931,7 +931,7 @@ static struct hv_ops hvc_iucv_ops = { }; /* Suspend / resume device operations */ -static struct dev_pm_ops hvc_iucv_pm_ops = { +static const struct dev_pm_ops hvc_iucv_pm_ops = { .freeze = hvc_iucv_pm_freeze, .thaw = hvc_iucv_pm_restore_thaw, .restore = hvc_iucv_pm_restore_thaw, diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index e989f67bb61f..3d9c61e5acbf 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c @@ -158,10 +158,11 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf, goto out; } } -out_unlock: - mutex_unlock(&rng_mutex); out: return ret ? : err; +out_unlock: + mutex_unlock(&rng_mutex); + goto out; } diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c index bdaef8e94021..64fe0a793efd 100644 --- a/drivers/char/hw_random/virtio-rng.c +++ b/drivers/char/hw_random/virtio-rng.c @@ -114,7 +114,7 @@ static struct virtio_device_id id_table[] = { { 0 }, }; -static struct virtio_driver virtio_rng = { +static struct virtio_driver virtio_rng_driver = { .driver.name = KBUILD_MODNAME, .driver.owner = THIS_MODULE, .id_table = id_table, @@ -124,12 +124,12 @@ static struct virtio_driver virtio_rng = { static int __init init(void) { - return register_virtio_driver(&virtio_rng); + return register_virtio_driver(&virtio_rng_driver); } static void __exit fini(void) { - unregister_virtio_driver(&virtio_rng); + unregister_virtio_driver(&virtio_rng_driver); } module_init(init); module_exit(fini); diff --git a/drivers/char/ipmi/ipmi_kcs_sm.c b/drivers/char/ipmi/ipmi_kcs_sm.c index 80704875794c..cf82fedae099 100644 --- a/drivers/char/ipmi/ipmi_kcs_sm.c +++ b/drivers/char/ipmi/ipmi_kcs_sm.c @@ -370,7 +370,7 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time) return SI_SM_IDLE; case KCS_START_OP: - if (state != KCS_IDLE) { + if (state != KCS_IDLE_STATE) { start_error_recovery(kcs, "State machine not idle at start"); break; diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index d2e698096ace..176f1751237f 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -64,6 +64,7 @@ #include <linux/dmi.h> #include <linux/string.h> #include <linux/ctype.h> +#include <linux/pnp.h> #ifdef CONFIG_PPC_OF #include <linux/of_device.h> @@ -1919,7 +1920,7 @@ struct SPMITable { s8 spmi_id[1]; /* A '\0' terminated array starts here. */ }; -static __devinit int try_init_acpi(struct SPMITable *spmi) +static __devinit int try_init_spmi(struct SPMITable *spmi) { struct smi_info *info; u8 addr_space; @@ -1940,7 +1941,7 @@ static __devinit int try_init_acpi(struct SPMITable *spmi) return -ENOMEM; } - info->addr_source = "ACPI"; + info->addr_source = "SPMI"; /* Figure out the interface type. */ switch (spmi->InterfaceType) { @@ -2002,7 +2003,7 @@ static __devinit int try_init_acpi(struct SPMITable *spmi) return 0; } -static __devinit void acpi_find_bmc(void) +static __devinit void spmi_find_bmc(void) { acpi_status status; struct SPMITable *spmi; @@ -2020,9 +2021,106 @@ static __devinit void acpi_find_bmc(void) if (status != AE_OK) return; - try_init_acpi(spmi); + try_init_spmi(spmi); } } + +static int __devinit ipmi_pnp_probe(struct pnp_dev *dev, + const struct pnp_device_id *dev_id) +{ + struct acpi_device *acpi_dev; + struct smi_info *info; + acpi_handle handle; + acpi_status status; + unsigned long long tmp; + + acpi_dev = pnp_acpi_device(dev); + if (!acpi_dev) + return -ENODEV; + + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + info->addr_source = "ACPI"; + + handle = acpi_dev->handle; + + /* _IFT tells us the interface type: KCS, BT, etc */ + status = acpi_evaluate_integer(handle, "_IFT", NULL, &tmp); + if (ACPI_FAILURE(status)) + goto err_free; + + switch (tmp) { + case 1: + info->si_type = SI_KCS; + break; + case 2: + info->si_type = SI_SMIC; + break; + case 3: + info->si_type = SI_BT; + break; + default: + dev_info(&dev->dev, "unknown interface type %lld\n", tmp); + goto err_free; + } + + if (pnp_port_valid(dev, 0)) { + info->io_setup = port_setup; + info->io.addr_type = IPMI_IO_ADDR_SPACE; + info->io.addr_data = pnp_port_start(dev, 0); + } else if (pnp_mem_valid(dev, 0)) { + info->io_setup = mem_setup; + info->io.addr_type = IPMI_MEM_ADDR_SPACE; + info->io.addr_data = pnp_mem_start(dev, 0); + } else { + dev_err(&dev->dev, "no I/O or memory address\n"); + goto err_free; + } + + info->io.regspacing = DEFAULT_REGSPACING; + info->io.regsize = DEFAULT_REGSPACING; + info->io.regshift = 0; + + /* If _GPE exists, use it; otherwise use standard interrupts */ + status = acpi_evaluate_integer(handle, "_GPE", NULL, &tmp); + if (ACPI_SUCCESS(status)) { + info->irq = tmp; + info->irq_setup = acpi_gpe_irq_setup; + } else if (pnp_irq_valid(dev, 0)) { + info->irq = pnp_irq(dev, 0); + info->irq_setup = std_irq_setup; + } + + info->dev = &acpi_dev->dev; + pnp_set_drvdata(dev, info); + + return try_smi_init(info); + +err_free: + kfree(info); + return -EINVAL; +} + +static void __devexit ipmi_pnp_remove(struct pnp_dev *dev) +{ + struct smi_info *info = pnp_get_drvdata(dev); + + cleanup_one_si(info); +} + +static const struct pnp_device_id pnp_dev_table[] = { + {"IPI0001", 0}, + {"", 0}, +}; + +static struct pnp_driver ipmi_pnp_driver = { + .name = DEVICE_NAME, + .probe = ipmi_pnp_probe, + .remove = __devexit_p(ipmi_pnp_remove), + .id_table = pnp_dev_table, +}; #endif #ifdef CONFIG_DMI @@ -2202,7 +2300,6 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev, int rv; int class_type = pdev->class & PCI_ERMC_CLASSCODE_TYPE_MASK; struct smi_info *info; - int first_reg_offset = 0; info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) @@ -2241,9 +2338,6 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev, info->addr_source_cleanup = ipmi_pci_cleanup; info->addr_source_data = pdev; - if (pdev->subsystem_vendor == PCI_HP_VENDOR_ID) - first_reg_offset = 1; - if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) { info->io_setup = port_setup; info->io.addr_type = IPMI_IO_ADDR_SPACE; @@ -3108,7 +3202,10 @@ static __devinit int init_ipmi_si(void) #endif #ifdef CONFIG_ACPI - acpi_find_bmc(); + spmi_find_bmc(); +#endif +#ifdef CONFIG_ACPI + pnp_register_driver(&ipmi_pnp_driver); #endif #ifdef CONFIG_PCI @@ -3233,6 +3330,9 @@ static __exit void cleanup_ipmi_si(void) #ifdef CONFIG_PCI pci_unregister_driver(&ipmi_pci_driver); #endif +#ifdef CONFIG_ACPI + pnp_unregister_driver(&ipmi_pnp_driver); +#endif #ifdef CONFIG_PPC_OF of_unregister_platform_driver(&ipmi_of_platform_driver); diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 5619007e7e05..f706b1dffdb3 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -233,7 +233,8 @@ int setkeycode(unsigned int scancode, unsigned int keycode) } /* - * Making beeps and bells. + * Making beeps and bells. Note that we prefer beeps to bells, but when + * shutting the sound off we do both. */ static int kd_sound_helper(struct input_handle *handle, void *data) @@ -242,9 +243,12 @@ static int kd_sound_helper(struct input_handle *handle, void *data) struct input_dev *dev = handle->dev; if (test_bit(EV_SND, dev->evbit)) { - if (test_bit(SND_TONE, dev->sndbit)) + if (test_bit(SND_TONE, dev->sndbit)) { input_inject_event(handle, EV_SND, SND_TONE, *hz); - if (test_bit(SND_BELL, handle->dev->sndbit)) + if (*hz) + return 0; + } + if (test_bit(SND_BELL, dev->sndbit)) input_inject_event(handle, EV_SND, SND_BELL, *hz ? 1 : 0); } diff --git a/drivers/char/lp.c b/drivers/char/lp.c index e444c2dba160..938a3a273886 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c @@ -127,6 +127,7 @@ #include <linux/wait.h> #include <linux/jiffies.h> #include <linux/smp_lock.h> +#include <linux/compat.h> #include <linux/parport.h> #undef LP_STATS @@ -571,13 +572,11 @@ static int lp_release(struct inode * inode, struct file * file) return 0; } -static int lp_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static int lp_do_ioctl(unsigned int minor, unsigned int cmd, + unsigned long arg, void __user *argp) { - unsigned int minor = iminor(inode); int status; int retval = 0; - void __user *argp = (void __user *)arg; #ifdef LP_DEBUG printk(KERN_DEBUG "lp%d ioctl, cmd: 0x%x, arg: 0x%lx\n", minor, cmd, arg); @@ -587,9 +586,6 @@ static int lp_ioctl(struct inode *inode, struct file *file, if ((LP_F(minor) & LP_EXIST) == 0) return -ENODEV; switch ( cmd ) { - struct timeval par_timeout; - long to_jiffies; - case LPTIME: LP_TIME(minor) = arg * HZ/100; break; @@ -652,34 +648,101 @@ static int lp_ioctl(struct inode *inode, struct file *file, return -EFAULT; break; - case LPSETTIMEOUT: - if (copy_from_user (&par_timeout, argp, - sizeof (struct timeval))) { - return -EFAULT; - } - /* Convert to jiffies, place in lp_table */ - if ((par_timeout.tv_sec < 0) || - (par_timeout.tv_usec < 0)) { - return -EINVAL; - } - to_jiffies = DIV_ROUND_UP(par_timeout.tv_usec, 1000000/HZ); - to_jiffies += par_timeout.tv_sec * (long) HZ; - if (to_jiffies <= 0) { - return -EINVAL; - } - lp_table[minor].timeout = to_jiffies; - break; - default: retval = -EINVAL; } return retval; } +static int lp_set_timeout(unsigned int minor, struct timeval *par_timeout) +{ + long to_jiffies; + + /* Convert to jiffies, place in lp_table */ + if ((par_timeout->tv_sec < 0) || + (par_timeout->tv_usec < 0)) { + return -EINVAL; + } + to_jiffies = DIV_ROUND_UP(par_timeout->tv_usec, 1000000/HZ); + to_jiffies += par_timeout->tv_sec * (long) HZ; + if (to_jiffies <= 0) { + return -EINVAL; + } + lp_table[minor].timeout = to_jiffies; + return 0; +} + +static long lp_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + unsigned int minor; + struct timeval par_timeout; + int ret; + + minor = iminor(file->f_path.dentry->d_inode); + lock_kernel(); + switch (cmd) { + case LPSETTIMEOUT: + if (copy_from_user(&par_timeout, (void __user *)arg, + sizeof (struct timeval))) { + ret = -EFAULT; + break; + } + ret = lp_set_timeout(minor, &par_timeout); + break; + default: + ret = lp_do_ioctl(minor, cmd, arg, (void __user *)arg); + break; + } + unlock_kernel(); + + return ret; +} + +#ifdef CONFIG_COMPAT +static long lp_compat_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + unsigned int minor; + struct timeval par_timeout; + struct compat_timeval __user *tc; + int ret; + + minor = iminor(file->f_path.dentry->d_inode); + lock_kernel(); + switch (cmd) { + case LPSETTIMEOUT: + tc = compat_ptr(arg); + if (get_user(par_timeout.tv_sec, &tc->tv_sec) || + get_user(par_timeout.tv_usec, &tc->tv_usec)) { + ret = -EFAULT; + break; + } + ret = lp_set_timeout(minor, &par_timeout); + break; +#ifdef LP_STATS + case LPGETSTATS: + /* FIXME: add an implementation if you set LP_STATS */ + ret = -EINVAL; + break; +#endif + default: + ret = lp_do_ioctl(minor, cmd, arg, compat_ptr(arg)); + break; + } + unlock_kernel(); + + return ret; +} +#endif + static const struct file_operations lp_fops = { .owner = THIS_MODULE, .write = lp_write, - .ioctl = lp_ioctl, + .unlocked_ioctl = lp_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = lp_compat_ioctl, +#endif .open = lp_open, .release = lp_release, #ifdef CONFIG_PARPORT_1284 diff --git a/drivers/char/mem.c b/drivers/char/mem.c index fba76fb55abf..be832b6f8279 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -34,6 +34,16 @@ # include <linux/efi.h> #endif +static inline unsigned long size_inside_page(unsigned long start, + unsigned long size) +{ + unsigned long sz; + + sz = PAGE_SIZE - (start & (PAGE_SIZE - 1)); + + return min(sz, size); +} + /* * Architectures vary in how they handle caching for addresses * outside of main memory. @@ -126,9 +136,7 @@ static ssize_t read_mem(struct file * file, char __user * buf, #ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED /* we don't have page 0 mapped on sparc and m68k.. */ if (p < PAGE_SIZE) { - sz = PAGE_SIZE - p; - if (sz > count) - sz = count; + sz = size_inside_page(p, count); if (sz > 0) { if (clear_user(buf, sz)) return -EFAULT; @@ -141,15 +149,9 @@ static ssize_t read_mem(struct file * file, char __user * buf, #endif while (count > 0) { - /* - * Handle first page in case it's not aligned - */ - if (-p & (PAGE_SIZE - 1)) - sz = -p & (PAGE_SIZE - 1); - else - sz = PAGE_SIZE; + unsigned long remaining; - sz = min_t(unsigned long, sz, count); + sz = size_inside_page(p, count); if (!range_is_allowed(p >> PAGE_SHIFT, count)) return -EPERM; @@ -163,12 +165,10 @@ static ssize_t read_mem(struct file * file, char __user * buf, if (!ptr) return -EFAULT; - if (copy_to_user(buf, ptr, sz)) { - unxlate_dev_mem_ptr(p, ptr); - return -EFAULT; - } - + remaining = copy_to_user(buf, ptr, sz); unxlate_dev_mem_ptr(p, ptr); + if (remaining) + return -EFAULT; buf += sz; p += sz; @@ -196,9 +196,7 @@ static ssize_t write_mem(struct file * file, const char __user * buf, #ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED /* we don't have page 0 mapped on sparc and m68k.. */ if (p < PAGE_SIZE) { - unsigned long sz = PAGE_SIZE - p; - if (sz > count) - sz = count; + sz = size_inside_page(p, count); /* Hmm. Do something? */ buf += sz; p += sz; @@ -208,15 +206,7 @@ static ssize_t write_mem(struct file * file, const char __user * buf, #endif while (count > 0) { - /* - * Handle first page in case it's not aligned - */ - if (-p & (PAGE_SIZE - 1)) - sz = -p & (PAGE_SIZE - 1); - else - sz = PAGE_SIZE; - - sz = min_t(unsigned long, sz, count); + sz = size_inside_page(p, count); if (!range_is_allowed(p >> PAGE_SHIFT, sz)) return -EPERM; @@ -234,16 +224,14 @@ static ssize_t write_mem(struct file * file, const char __user * buf, } copied = copy_from_user(ptr, buf, sz); + unxlate_dev_mem_ptr(p, ptr); if (copied) { written += sz - copied; - unxlate_dev_mem_ptr(p, ptr); if (written) break; return -EFAULT; } - unxlate_dev_mem_ptr(p, ptr); - buf += sz; p += sz; count -= sz; @@ -417,27 +405,18 @@ static ssize_t read_kmem(struct file *file, char __user *buf, #ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED /* we don't have page 0 mapped on sparc and m68k.. */ if (p < PAGE_SIZE && low_count > 0) { - size_t tmp = PAGE_SIZE - p; - if (tmp > low_count) tmp = low_count; - if (clear_user(buf, tmp)) + sz = size_inside_page(p, low_count); + if (clear_user(buf, sz)) return -EFAULT; - buf += tmp; - p += tmp; - read += tmp; - low_count -= tmp; - count -= tmp; + buf += sz; + p += sz; + read += sz; + low_count -= sz; + count -= sz; } #endif while (low_count > 0) { - /* - * Handle first page in case it's not aligned - */ - if (-p & (PAGE_SIZE - 1)) - sz = -p & (PAGE_SIZE - 1); - else - sz = PAGE_SIZE; - - sz = min_t(unsigned long, sz, low_count); + sz = size_inside_page(p, low_count); /* * On ia64 if a page has been mapped somewhere as @@ -461,21 +440,18 @@ static ssize_t read_kmem(struct file *file, char __user *buf, if (!kbuf) return -ENOMEM; while (count > 0) { - int len = count; - - if (len > PAGE_SIZE) - len = PAGE_SIZE; - len = vread(kbuf, (char *)p, len); - if (!len) + sz = size_inside_page(p, count); + sz = vread(kbuf, (char *)p, sz); + if (!sz) break; - if (copy_to_user(buf, kbuf, len)) { + if (copy_to_user(buf, kbuf, sz)) { free_page((unsigned long)kbuf); return -EFAULT; } - count -= len; - buf += len; - read += len; - p += len; + count -= sz; + buf += sz; + read += sz; + p += sz; } free_page((unsigned long)kbuf); } @@ -485,7 +461,7 @@ static ssize_t read_kmem(struct file *file, char __user *buf, static inline ssize_t -do_write_kmem(void *p, unsigned long realp, const char __user * buf, +do_write_kmem(unsigned long p, const char __user *buf, size_t count, loff_t *ppos) { ssize_t written, sz; @@ -494,14 +470,11 @@ do_write_kmem(void *p, unsigned long realp, const char __user * buf, written = 0; #ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED /* we don't have page 0 mapped on sparc and m68k.. */ - if (realp < PAGE_SIZE) { - unsigned long sz = PAGE_SIZE - realp; - if (sz > count) - sz = count; + if (p < PAGE_SIZE) { + sz = size_inside_page(p, count); /* Hmm. Do something? */ buf += sz; p += sz; - realp += sz; count -= sz; written += sz; } @@ -509,22 +482,15 @@ do_write_kmem(void *p, unsigned long realp, const char __user * buf, while (count > 0) { char *ptr; - /* - * Handle first page in case it's not aligned - */ - if (-realp & (PAGE_SIZE - 1)) - sz = -realp & (PAGE_SIZE - 1); - else - sz = PAGE_SIZE; - sz = min_t(unsigned long, sz, count); + sz = size_inside_page(p, count); /* * On ia64 if a page has been mapped somewhere as * uncached, then it must also be accessed uncached * by the kernel or data corruption may occur */ - ptr = xlate_dev_kmem_ptr(p); + ptr = xlate_dev_kmem_ptr((char *)p); copied = copy_from_user(ptr, buf, sz); if (copied) { @@ -535,7 +501,6 @@ do_write_kmem(void *p, unsigned long realp, const char __user * buf, } buf += sz; p += sz; - realp += sz; count -= sz; written += sz; } @@ -554,19 +519,14 @@ static ssize_t write_kmem(struct file * file, const char __user * buf, unsigned long p = *ppos; ssize_t wrote = 0; ssize_t virtr = 0; - ssize_t written; char * kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */ if (p < (unsigned long) high_memory) { - - wrote = count; - if (count > (unsigned long) high_memory - p) - wrote = (unsigned long) high_memory - p; - - written = do_write_kmem((void*)p, p, buf, wrote, ppos); - if (written != wrote) - return written; - wrote = written; + unsigned long to_write = min_t(unsigned long, count, + (unsigned long)high_memory - p); + wrote = do_write_kmem(p, buf, to_write, ppos); + if (wrote != to_write) + return wrote; p += wrote; buf += wrote; count -= wrote; @@ -577,24 +537,21 @@ static ssize_t write_kmem(struct file * file, const char __user * buf, if (!kbuf) return wrote ? wrote : -ENOMEM; while (count > 0) { - int len = count; - - if (len > PAGE_SIZE) - len = PAGE_SIZE; - if (len) { - written = copy_from_user(kbuf, buf, len); - if (written) { - if (wrote + virtr) - break; - free_page((unsigned long)kbuf); - return -EFAULT; - } + unsigned long sz = size_inside_page(p, count); + unsigned long n; + + n = copy_from_user(kbuf, buf, sz); + if (n) { + if (wrote + virtr) + break; + free_page((unsigned long)kbuf); + return -EFAULT; } - len = vwrite(kbuf, (char *)p, len); - count -= len; - buf += len; - virtr += len; - p += len; + sz = vwrite(kbuf, (char *)p, sz); + count -= sz; + buf += sz; + virtr += sz; + p += sz; } free_page((unsigned long)kbuf); } diff --git a/drivers/char/misc.c b/drivers/char/misc.c index 96f1cd086dd2..94a136e96c06 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c @@ -60,9 +60,7 @@ static DEFINE_MUTEX(misc_mtx); * Assigned numbers, used for dynamic minors */ #define DYNAMIC_MINORS 64 /* like dynamic majors */ -static unsigned char misc_minors[DYNAMIC_MINORS / 8]; - -extern int pmu_device_init(void); +static DECLARE_BITMAP(misc_minors, DYNAMIC_MINORS); #ifdef CONFIG_PROC_FS static void *misc_seq_start(struct seq_file *seq, loff_t *pos) @@ -198,24 +196,23 @@ int misc_register(struct miscdevice * misc) } if (misc->minor == MISC_DYNAMIC_MINOR) { - int i = DYNAMIC_MINORS; - while (--i >= 0) - if ( (misc_minors[i>>3] & (1 << (i&7))) == 0) - break; - if (i<0) { + int i = find_first_zero_bit(misc_minors, DYNAMIC_MINORS); + if (i >= DYNAMIC_MINORS) { mutex_unlock(&misc_mtx); return -EBUSY; } - misc->minor = i; + misc->minor = DYNAMIC_MINORS - i - 1; + set_bit(i, misc_minors); } - if (misc->minor < DYNAMIC_MINORS) - misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7); dev = MKDEV(MISC_MAJOR, misc->minor); misc->this_device = device_create(misc_class, misc->parent, dev, misc, "%s", misc->name); if (IS_ERR(misc->this_device)) { + int i = DYNAMIC_MINORS - misc->minor - 1; + if (i < DYNAMIC_MINORS && i >= 0) + clear_bit(i, misc_minors); err = PTR_ERR(misc->this_device); goto out; } @@ -242,7 +239,7 @@ int misc_register(struct miscdevice * misc) int misc_deregister(struct miscdevice *misc) { - int i = misc->minor; + int i = DYNAMIC_MINORS - misc->minor - 1; if (list_empty(&misc->list)) return -EINVAL; @@ -250,9 +247,8 @@ int misc_deregister(struct miscdevice *misc) mutex_lock(&misc_mtx); list_del(&misc->list); device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor)); - if (i < DYNAMIC_MINORS && i>0) { - misc_minors[i>>3] &= ~(1 << (misc->minor & 7)); - } + if (i < DYNAMIC_MINORS && i >= 0) + clear_bit(i, misc_minors); mutex_unlock(&misc_mtx); return 0; } diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c index d3400b20444f..2ad7d37afbd0 100644 --- a/drivers/char/nozomi.c +++ b/drivers/char/nozomi.c @@ -358,7 +358,7 @@ struct port { u8 update_flow_control; struct ctrl_ul ctrl_ul; struct ctrl_dl ctrl_dl; - struct kfifo *fifo_ul; + struct kfifo fifo_ul; void __iomem *dl_addr[2]; u32 dl_size[2]; u8 toggle_dl; @@ -685,8 +685,6 @@ static int nozomi_read_config_table(struct nozomi *dc) dump_table(dc); for (i = PORT_MDM; i < MAX_PORT; i++) { - dc->port[i].fifo_ul = - kfifo_alloc(FIFO_BUFFER_SIZE_UL, GFP_ATOMIC, NULL); memset(&dc->port[i].ctrl_dl, 0, sizeof(struct ctrl_dl)); memset(&dc->port[i].ctrl_ul, 0, sizeof(struct ctrl_ul)); } @@ -798,7 +796,7 @@ static int send_data(enum port_type index, struct nozomi *dc) struct tty_struct *tty = tty_port_tty_get(&port->port); /* Get data from tty and place in buf for now */ - size = __kfifo_get(port->fifo_ul, dc->send_buf, + size = kfifo_out(&port->fifo_ul, dc->send_buf, ul_size < SEND_BUF_MAX ? ul_size : SEND_BUF_MAX); if (size == 0) { @@ -988,11 +986,11 @@ static int receive_flow_control(struct nozomi *dc) } else if (old_ctrl.CTS == 0 && ctrl_dl.CTS == 1) { - if (__kfifo_len(dc->port[port].fifo_ul)) { + if (kfifo_len(&dc->port[port].fifo_ul)) { DBG1("Enable interrupt (0x%04X) on port: %d", enable_ier, port); DBG1("Data in buffer [%d], enable transmit! ", - __kfifo_len(dc->port[port].fifo_ul)); + kfifo_len(&dc->port[port].fifo_ul)); enable_transmit_ul(port, dc); } else { DBG1("No data in buffer..."); @@ -1433,6 +1431,16 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev, goto err_free_sbuf; } + for (i = PORT_MDM; i < MAX_PORT; i++) { + if (kfifo_alloc(&dc->port[i].fifo_ul, + FIFO_BUFFER_SIZE_UL, GFP_ATOMIC)) { + dev_err(&pdev->dev, + "Could not allocate kfifo buffer\n"); + ret = -ENOMEM; + goto err_free_kfifo; + } + } + spin_lock_init(&dc->spin_mutex); nozomi_setup_private_data(dc); @@ -1445,7 +1453,7 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev, NOZOMI_NAME, dc); if (unlikely(ret)) { dev_err(&pdev->dev, "can't request irq %d\n", pdev->irq); - goto err_free_sbuf; + goto err_free_kfifo; } DBG1("base_addr: %p", dc->base_addr); @@ -1464,13 +1472,28 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev, dc->state = NOZOMI_STATE_ENABLED; for (i = 0; i < MAX_PORT; i++) { + struct device *tty_dev; + mutex_init(&dc->port[i].tty_sem); tty_port_init(&dc->port[i].port); - tty_register_device(ntty_driver, dc->index_start + i, + tty_dev = tty_register_device(ntty_driver, dc->index_start + i, &pdev->dev); + + if (IS_ERR(tty_dev)) { + ret = PTR_ERR(tty_dev); + dev_err(&pdev->dev, "Could not allocate tty?\n"); + goto err_free_tty; + } } + return 0; +err_free_tty: + for (i = dc->index_start; i < dc->index_start + MAX_PORT; ++i) + tty_unregister_device(ntty_driver, i); +err_free_kfifo: + for (i = 0; i < MAX_PORT; i++) + kfifo_free(&dc->port[i].fifo_ul); err_free_sbuf: kfree(dc->send_buf); iounmap(dc->base_addr); @@ -1536,8 +1559,7 @@ static void __devexit nozomi_card_exit(struct pci_dev *pdev) free_irq(pdev->irq, dc); for (i = 0; i < MAX_PORT; i++) - if (dc->port[i].fifo_ul) - kfifo_free(dc->port[i].fifo_ul); + kfifo_free(&dc->port[i].fifo_ul); kfree(dc->send_buf); @@ -1629,10 +1651,10 @@ static void ntty_close(struct tty_struct *tty, struct file *file) dc->open_ttys--; port->count--; - tty_port_tty_set(port, NULL); if (port->count == 0) { DBG1("close: %d", nport->token_dl); + tty_port_tty_set(port, NULL); spin_lock_irqsave(&dc->spin_mutex, flags); dc->last_ier &= ~(nport->token_dl); writew(dc->last_ier, dc->reg_ier); @@ -1673,7 +1695,7 @@ static int ntty_write(struct tty_struct *tty, const unsigned char *buffer, goto exit; } - rval = __kfifo_put(port->fifo_ul, (unsigned char *)buffer, count); + rval = kfifo_in(&port->fifo_ul, (unsigned char *)buffer, count); /* notify card */ if (unlikely(dc == NULL)) { @@ -1721,7 +1743,7 @@ static int ntty_write_room(struct tty_struct *tty) if (!port->port.count) goto exit; - room = port->fifo_ul->size - __kfifo_len(port->fifo_ul); + room = port->fifo_ul.size - kfifo_len(&port->fifo_ul); exit: mutex_unlock(&port->tty_sem); @@ -1878,7 +1900,7 @@ static s32 ntty_chars_in_buffer(struct tty_struct *tty) goto exit_in_buffer; } - rval = __kfifo_len(port->fifo_ul); + rval = kfifo_len(&port->fifo_ul); exit_in_buffer: return rval; diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c index 4008e2ce73c1..fdbcc9fd6d31 100644 --- a/drivers/char/nvram.c +++ b/drivers/char/nvram.c @@ -264,10 +264,16 @@ static ssize_t nvram_write(struct file *file, const char __user *buf, unsigned char contents[NVRAM_BYTES]; unsigned i = *ppos; unsigned char *tmp; - int len; - len = (NVRAM_BYTES - i) < count ? (NVRAM_BYTES - i) : count; - if (copy_from_user(contents, buf, len)) + if (i >= NVRAM_BYTES) + return 0; /* Past EOF */ + + if (count > NVRAM_BYTES - i) + count = NVRAM_BYTES - i; + if (count > NVRAM_BYTES) + return -EFAULT; /* Can't happen, but prove it to gcc */ + + if (copy_from_user(contents, buf, count)) return -EFAULT; spin_lock_irq(&rtc_lock); @@ -275,7 +281,7 @@ static ssize_t nvram_write(struct file *file, const char __user *buf, if (!__nvram_check_checksum()) goto checksum_err; - for (tmp = contents; count-- > 0 && i < NVRAM_BYTES; ++i, ++tmp) + for (tmp = contents; count--; ++i, ++tmp) __nvram_write_byte(*tmp, i); __nvram_set_checksum(); diff --git a/drivers/char/nwflash.c b/drivers/char/nwflash.c index 8c7df5ba088f..f80810901db6 100644 --- a/drivers/char/nwflash.c +++ b/drivers/char/nwflash.c @@ -27,6 +27,7 @@ #include <linux/init.h> #include <linux/smp_lock.h> #include <linux/mutex.h> +#include <linux/jiffies.h> #include <asm/hardware/dec21285.h> #include <asm/io.h> diff --git a/drivers/char/random.c b/drivers/char/random.c index dcd08635cf1b..8258982b49ec 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1245,12 +1245,8 @@ static int proc_do_uuid(ctl_table *table, int write, if (uuid[8] == 0) generate_random_uuid(uuid); - sprintf(buf, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-" - "%02x%02x%02x%02x%02x%02x", - uuid[0], uuid[1], uuid[2], uuid[3], - uuid[4], uuid[5], uuid[6], uuid[7], - uuid[8], uuid[9], uuid[10], uuid[11], - uuid[12], uuid[13], uuid[14], uuid[15]); + sprintf(buf, "%pU", uuid); + fake_table.data = buf; fake_table.maxlen = sizeof(buf); @@ -1310,7 +1306,7 @@ ctl_table random_table[] = { /******************************************************************** * - * Random funtions for networking + * Random functions for networking * ********************************************************************/ diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index 8c262aaf7c26..bba727c3807e 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c @@ -50,7 +50,6 @@ #include <linux/err.h> #include <linux/kfifo.h> #include <linux/platform_device.h> -#include <linux/smp_lock.h> #include <asm/uaccess.h> #include <asm/io.h> @@ -487,7 +486,7 @@ static struct sonypi_device { int camera_power; int bluetooth_power; struct mutex lock; - struct kfifo *fifo; + struct kfifo fifo; spinlock_t fifo_lock; wait_queue_head_t fifo_proc_list; struct fasync_struct *fifo_async; @@ -496,7 +495,7 @@ static struct sonypi_device { struct input_dev *input_jog_dev; struct input_dev *input_key_dev; struct work_struct input_work; - struct kfifo *input_fifo; + struct kfifo input_fifo; spinlock_t input_fifo_lock; } sonypi_device; @@ -777,8 +776,9 @@ static void input_keyrelease(struct work_struct *work) { struct sonypi_keypress kp; - while (kfifo_get(sonypi_device.input_fifo, (unsigned char *)&kp, - sizeof(kp)) == sizeof(kp)) { + while (kfifo_out_locked(&sonypi_device.input_fifo, (unsigned char *)&kp, + sizeof(kp), &sonypi_device.input_fifo_lock) + == sizeof(kp)) { msleep(10); input_report_key(kp.dev, kp.key, 0); input_sync(kp.dev); @@ -827,8 +827,9 @@ static void sonypi_report_input_event(u8 event) if (kp.dev) { input_report_key(kp.dev, kp.key, 1); input_sync(kp.dev); - kfifo_put(sonypi_device.input_fifo, - (unsigned char *)&kp, sizeof(kp)); + kfifo_in_locked(&sonypi_device.input_fifo, + (unsigned char *)&kp, sizeof(kp), + &sonypi_device.input_fifo_lock); schedule_work(&sonypi_device.input_work); } } @@ -880,7 +881,8 @@ found: acpi_bus_generate_proc_event(sonypi_acpi_device, 1, event); #endif - kfifo_put(sonypi_device.fifo, (unsigned char *)&event, sizeof(event)); + kfifo_in_locked(&sonypi_device.fifo, (unsigned char *)&event, + sizeof(event), &sonypi_device.fifo_lock); kill_fasync(&sonypi_device.fifo_async, SIGIO, POLL_IN); wake_up_interruptible(&sonypi_device.fifo_proc_list); @@ -902,14 +904,13 @@ static int sonypi_misc_release(struct inode *inode, struct file *file) static int sonypi_misc_open(struct inode *inode, struct file *file) { - lock_kernel(); mutex_lock(&sonypi_device.lock); /* Flush input queue on first open */ if (!sonypi_device.open_count) - kfifo_reset(sonypi_device.fifo); + kfifo_reset(&sonypi_device.fifo); sonypi_device.open_count++; mutex_unlock(&sonypi_device.lock); - unlock_kernel(); + return 0; } @@ -919,17 +920,18 @@ static ssize_t sonypi_misc_read(struct file *file, char __user *buf, ssize_t ret; unsigned char c; - if ((kfifo_len(sonypi_device.fifo) == 0) && + if ((kfifo_len(&sonypi_device.fifo) == 0) && (file->f_flags & O_NONBLOCK)) return -EAGAIN; ret = wait_event_interruptible(sonypi_device.fifo_proc_list, - kfifo_len(sonypi_device.fifo) != 0); + kfifo_len(&sonypi_device.fifo) != 0); if (ret) return ret; while (ret < count && - (kfifo_get(sonypi_device.fifo, &c, sizeof(c)) == sizeof(c))) { + (kfifo_out_locked(&sonypi_device.fifo, &c, sizeof(c), + &sonypi_device.fifo_lock) == sizeof(c))) { if (put_user(c, buf++)) return -EFAULT; ret++; @@ -946,15 +948,15 @@ static ssize_t sonypi_misc_read(struct file *file, char __user *buf, static unsigned int sonypi_misc_poll(struct file *file, poll_table *wait) { poll_wait(file, &sonypi_device.fifo_proc_list, wait); - if (kfifo_len(sonypi_device.fifo)) + if (kfifo_len(&sonypi_device.fifo)) return POLLIN | POLLRDNORM; return 0; } -static int sonypi_misc_ioctl(struct inode *ip, struct file *fp, +static long sonypi_misc_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) { - int ret = 0; + long ret = 0; void __user *argp = (void __user *)arg; u8 val8; u16 val16; @@ -1070,7 +1072,8 @@ static const struct file_operations sonypi_misc_fops = { .open = sonypi_misc_open, .release = sonypi_misc_release, .fasync = sonypi_misc_fasync, - .ioctl = sonypi_misc_ioctl, + .unlocked_ioctl = sonypi_misc_ioctl, + .llseek = no_llseek, }; static struct miscdevice sonypi_misc_device = { @@ -1313,11 +1316,10 @@ static int __devinit sonypi_probe(struct platform_device *dev) "http://www.linux.it/~malattia/wiki/index.php/Sony_drivers\n"); spin_lock_init(&sonypi_device.fifo_lock); - sonypi_device.fifo = kfifo_alloc(SONYPI_BUF_SIZE, GFP_KERNEL, - &sonypi_device.fifo_lock); - if (IS_ERR(sonypi_device.fifo)) { + error = kfifo_alloc(&sonypi_device.fifo, SONYPI_BUF_SIZE, GFP_KERNEL); + if (error) { printk(KERN_ERR "sonypi: kfifo_alloc failed\n"); - return PTR_ERR(sonypi_device.fifo); + return error; } init_waitqueue_head(&sonypi_device.fifo_proc_list); @@ -1393,12 +1395,10 @@ static int __devinit sonypi_probe(struct platform_device *dev) } spin_lock_init(&sonypi_device.input_fifo_lock); - sonypi_device.input_fifo = - kfifo_alloc(SONYPI_BUF_SIZE, GFP_KERNEL, - &sonypi_device.input_fifo_lock); - if (IS_ERR(sonypi_device.input_fifo)) { + error = kfifo_alloc(&sonypi_device.input_fifo, SONYPI_BUF_SIZE, + GFP_KERNEL); + if (error) { printk(KERN_ERR "sonypi: kfifo_alloc failed\n"); - error = PTR_ERR(sonypi_device.input_fifo); goto err_inpdev_unregister; } @@ -1423,7 +1423,7 @@ static int __devinit sonypi_probe(struct platform_device *dev) pci_disable_device(pcidev); err_put_pcidev: pci_dev_put(pcidev); - kfifo_free(sonypi_device.fifo); + kfifo_free(&sonypi_device.fifo); return error; } @@ -1438,7 +1438,7 @@ static int __devexit sonypi_remove(struct platform_device *dev) if (useinput) { input_unregister_device(sonypi_device.input_key_dev); input_unregister_device(sonypi_device.input_jog_dev); - kfifo_free(sonypi_device.input_fifo); + kfifo_free(&sonypi_device.input_fifo); } misc_deregister(&sonypi_misc_device); @@ -1451,7 +1451,7 @@ static int __devexit sonypi_remove(struct platform_device *dev) pci_dev_put(sonypi_device.dev); } - kfifo_free(sonypi_device.fifo); + kfifo_free(&sonypi_device.fifo); return 0; } diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index 44203ff599da..1ae2de7d8b4f 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c @@ -339,7 +339,7 @@ static struct sysrq_key_op sysrq_term_op = { static void moom_callback(struct work_struct *ignored) { - out_of_memory(node_zonelist(0, GFP_KERNEL), GFP_KERNEL, 0); + out_of_memory(node_zonelist(0, GFP_KERNEL), GFP_KERNEL, 0, NULL); } static DECLARE_WORK(moom_work, moom_callback); diff --git a/drivers/char/toshiba.c b/drivers/char/toshiba.c index 663cd15d7c78..f8bc79f6de34 100644 --- a/drivers/char/toshiba.c +++ b/drivers/char/toshiba.c @@ -68,7 +68,7 @@ #include <linux/stat.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> - +#include <linux/smp_lock.h> #include <linux/toshiba.h> #define TOSH_MINOR_DEV 181 @@ -88,13 +88,13 @@ static int tosh_date; static int tosh_sci; static int tosh_fan; -static int tosh_ioctl(struct inode *, struct file *, unsigned int, +static long tosh_ioctl(struct file *, unsigned int, unsigned long); static const struct file_operations tosh_fops = { .owner = THIS_MODULE, - .ioctl = tosh_ioctl, + .unlocked_ioctl = tosh_ioctl, }; static struct miscdevice tosh_device = { @@ -252,8 +252,7 @@ int tosh_smm(SMMRegisters *regs) EXPORT_SYMBOL(tosh_smm); -static int tosh_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, - unsigned long arg) +static long tosh_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) { SMMRegisters regs; SMMRegisters __user *argp = (SMMRegisters __user *)arg; @@ -275,13 +274,16 @@ static int tosh_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, return -EINVAL; /* do we need to emulate the fan ? */ + lock_kernel(); if (tosh_fan==1) { if (((ax==0xf300) || (ax==0xf400)) && (bx==0x0004)) { err = tosh_emulate_fan(®s); + unlock_kernel(); break; } } err = tosh_smm(®s); + unlock_kernel(); break; default: return -EINVAL; diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 684f0e0b175e..c6f3b48be9dd 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -516,7 +516,6 @@ static void do_tty_hangup(struct work_struct *work) /* inuse_filps is protected by the single kernel lock */ lock_kernel(); check_tty_count(tty, "do_tty_hangup"); - unlock_kernel(); file_list_lock(); /* This breaks for file handles being sent over AF_UNIX sockets ? */ @@ -531,7 +530,6 @@ static void do_tty_hangup(struct work_struct *work) } file_list_unlock(); - lock_kernel(); tty_ldisc_hangup(tty); read_lock(&tasklist_lock); @@ -1953,8 +1951,8 @@ static int tty_fasync(int fd, struct file *filp, int on) pid = task_pid(current); type = PIDTYPE_PID; } - spin_unlock_irqrestore(&tty->ctrl_lock, flags); retval = __f_setown(filp, pid, type, 0); + spin_unlock_irqrestore(&tty->ctrl_lock, flags); if (retval) goto out; } else { diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 1e3d728dbf7e..50faa1fb0f06 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -164,6 +164,9 @@ module_param(default_utf8, int, S_IRUGO | S_IWUSR); int global_cursor_default = -1; module_param(global_cursor_default, int, S_IRUGO | S_IWUSR); +static int cur_default = CUR_DEFAULT; +module_param(cur_default, int, S_IRUGO | S_IWUSR); + /* * ignore_poke: don't unblank the screen when things are typed. This is * mainly for the privacy of braille terminal users. @@ -184,12 +187,10 @@ static DECLARE_WORK(console_work, console_callback); * fg_console is the current virtual console, * last_console is the last used one, * want_console is the console we want to switch to, - * kmsg_redirect is the console for kernel messages, */ int fg_console; int last_console; int want_console = -1; -int kmsg_redirect; /* * For each existing display, we have a pointer to console currently visible @@ -1638,7 +1639,7 @@ static void reset_terminal(struct vc_data *vc, int do_clear) /* do not do set_leds here because this causes an endless tasklet loop when the keyboard hasn't been initialized yet */ - vc->vc_cursor_type = CUR_DEFAULT; + vc->vc_cursor_type = cur_default; vc->vc_complement_mask = vc->vc_s_complement_mask; default_attr(vc); @@ -1840,7 +1841,7 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) if (vc->vc_par[0]) vc->vc_cursor_type = vc->vc_par[0] | (vc->vc_par[1] << 8) | (vc->vc_par[2] << 16); else - vc->vc_cursor_type = CUR_DEFAULT; + vc->vc_cursor_type = cur_default; return; } break; @@ -2434,6 +2435,37 @@ struct tty_driver *console_driver; #ifdef CONFIG_VT_CONSOLE +/** + * vt_kmsg_redirect() - Sets/gets the kernel message console + * @new: The new virtual terminal number or -1 if the console should stay + * unchanged + * + * By default, the kernel messages are always printed on the current virtual + * console. However, the user may modify that default with the + * TIOCL_SETKMSGREDIRECT ioctl call. + * + * This function sets the kernel message console to be @new. It returns the old + * virtual console number. The virtual terminal number 0 (both as parameter and + * return value) means no redirection (i.e. always printed on the currently + * active console). + * + * The parameter -1 means that only the current console is returned, but the + * value is not modified. You may use the macro vt_get_kmsg_redirect() in that + * case to make the code more understandable. + * + * When the kernel is compiled without CONFIG_VT_CONSOLE, this function ignores + * the parameter and always returns 0. + */ +int vt_kmsg_redirect(int new) +{ + static int kmsg_con; + + if (new != -1) + return xchg(&kmsg_con, new); + else + return kmsg_con; +} + /* * Console on virtual terminal * @@ -2448,6 +2480,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count) const ushort *start; ushort cnt = 0; ushort myx; + int kmsg_console; /* console busy or not yet initialized */ if (!printable) @@ -2455,8 +2488,9 @@ static void vt_console_print(struct console *co, const char *b, unsigned count) if (!spin_trylock(&printing_lock)) return; - if (kmsg_redirect && vc_cons_allocated(kmsg_redirect - 1)) - vc = vc_cons[kmsg_redirect - 1].d; + kmsg_console = vt_get_kmsg_redirect(); + if (kmsg_console && vc_cons_allocated(kmsg_console - 1)) + vc = vc_cons[kmsg_console - 1].d; /* read `x' only after setting currcons properly (otherwise the `x' macro will read the x of the foreground console). */ @@ -2613,7 +2647,7 @@ int tioclinux(struct tty_struct *tty, unsigned long arg) ret = set_vesa_blanking(p); break; case TIOCL_GETKMSGREDIRECT: - data = kmsg_redirect; + data = vt_get_kmsg_redirect(); ret = __put_user(data, p); break; case TIOCL_SETKMSGREDIRECT: @@ -2623,7 +2657,7 @@ int tioclinux(struct tty_struct *tty, unsigned long arg) if (get_user(data, p+1)) ret = -EFAULT; else - kmsg_redirect = data; + vt_kmsg_redirect(data); } break; case TIOCL_GETFGCONSOLE: |