diff options
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/Kconfig | 4 | ||||
-rw-r--r-- | drivers/char/drm/drm_sysfs.c | 2 | ||||
-rw-r--r-- | drivers/char/hw_random/Kconfig | 9 | ||||
-rw-r--r-- | drivers/char/hw_random/Makefile | 1 | ||||
-rw-r--r-- | drivers/char/hw_random/virtio-rng.c | 155 | ||||
-rw-r--r-- | drivers/char/ip2/Makefile | 4 | ||||
-rw-r--r-- | drivers/char/ip2/ip2main.c | 23 | ||||
-rw-r--r-- | drivers/char/pcmcia/ipwireless/hardware.c | 20 | ||||
-rw-r--r-- | drivers/char/vt.c | 15 |
9 files changed, 190 insertions, 43 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 595a925c62a9..d307bf26af58 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -118,8 +118,8 @@ config COMPUTONE order to become a dial-in server. If you have a card like that, say Y here and read <file:Documentation/computone.txt>. - To compile this driver as modules, choose M here: the - modules will be called ip2 and ip2main. + To compile this driver as module, choose M here: the + module will be called ip2. config ROCKETPORT tristate "Comtrol RocketPort support" diff --git a/drivers/char/drm/drm_sysfs.c b/drivers/char/drm/drm_sysfs.c index 9a32169e88fb..af211a0ef179 100644 --- a/drivers/char/drm/drm_sysfs.c +++ b/drivers/char/drm/drm_sysfs.c @@ -34,8 +34,6 @@ static int drm_sysfs_suspend(struct device *dev, pm_message_t state) struct drm_minor *drm_minor = to_drm_minor(dev); struct drm_device *drm_dev = drm_minor->dev; - printk(KERN_ERR "%s\n", __func__); - if (drm_dev->driver->suspend) return drm_dev->driver->suspend(drm_dev, state); diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index 8d6c2089d2a8..efd0b4db7c8e 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -112,3 +112,12 @@ config HW_RANDOM_PASEMI If unsure, say Y. +config HW_RANDOM_VIRTIO + tristate "VirtIO Random Number Generator support" + depends on HW_RANDOM && VIRTIO + ---help--- + This driver provides kernel-side support for the virtual Random Number + Generator hardware. + + To compile this driver as a module, choose M here: the + module will be called virtio-rng. If unsure, say N. diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile index c8b7300e2fb1..b4940ddbb35f 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile @@ -11,3 +11,4 @@ obj-$(CONFIG_HW_RANDOM_VIA) += via-rng.o obj-$(CONFIG_HW_RANDOM_IXP4XX) += ixp4xx-rng.o obj-$(CONFIG_HW_RANDOM_OMAP) += omap-rng.o obj-$(CONFIG_HW_RANDOM_PASEMI) += pasemi-rng.o +obj-$(CONFIG_HW_RANDOM_VIRTIO) += virtio-rng.o diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c new file mode 100644 index 000000000000..d0e563e4fc39 --- /dev/null +++ b/drivers/char/hw_random/virtio-rng.c @@ -0,0 +1,155 @@ +/* + * Randomness driver for virtio + * Copyright (C) 2007, 2008 Rusty Russell IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <linux/err.h> +#include <linux/hw_random.h> +#include <linux/scatterlist.h> +#include <linux/spinlock.h> +#include <linux/virtio.h> +#include <linux/virtio_rng.h> + +/* The host will fill any buffer we give it with sweet, sweet randomness. We + * give it 64 bytes at a time, and the hwrng framework takes it 4 bytes at a + * time. */ +#define RANDOM_DATA_SIZE 64 + +static struct virtqueue *vq; +static u32 *random_data; +static unsigned int data_left; +static DECLARE_COMPLETION(have_data); + +static void random_recv_done(struct virtqueue *vq) +{ + int len; + + /* We never get spurious callbacks. */ + if (!vq->vq_ops->get_buf(vq, &len)) + BUG(); + + data_left = len / sizeof(random_data[0]); + complete(&have_data); +} + +static void register_buffer(void) +{ + struct scatterlist sg; + + sg_init_one(&sg, random_data, RANDOM_DATA_SIZE); + /* There should always be room for one buffer. */ + if (vq->vq_ops->add_buf(vq, &sg, 0, 1, random_data) != 0) + BUG(); + vq->vq_ops->kick(vq); +} + +/* At least we don't udelay() in a loop like some other drivers. */ +static int virtio_data_present(struct hwrng *rng, int wait) +{ + if (data_left) + return 1; + + if (!wait) + return 0; + + wait_for_completion(&have_data); + return 1; +} + +/* virtio_data_present() must have succeeded before this is called. */ +static int virtio_data_read(struct hwrng *rng, u32 *data) +{ + BUG_ON(!data_left); + + *data = random_data[--data_left]; + + if (!data_left) { + init_completion(&have_data); + register_buffer(); + } + return sizeof(*data); +} + +static struct hwrng virtio_hwrng = { + .name = "virtio", + .data_present = virtio_data_present, + .data_read = virtio_data_read, +}; + +static int virtrng_probe(struct virtio_device *vdev) +{ + int err; + + /* We expect a single virtqueue. */ + vq = vdev->config->find_vq(vdev, 0, random_recv_done); + if (IS_ERR(vq)) + return PTR_ERR(vq); + + err = hwrng_register(&virtio_hwrng); + if (err) { + vdev->config->del_vq(vq); + return err; + } + + register_buffer(); + return 0; +} + +static void virtrng_remove(struct virtio_device *vdev) +{ + vdev->config->reset(vdev); + hwrng_unregister(&virtio_hwrng); + vdev->config->del_vq(vq); +} + +static struct virtio_device_id id_table[] = { + { VIRTIO_ID_RNG, VIRTIO_DEV_ANY_ID }, + { 0 }, +}; + +static struct virtio_driver virtio_rng = { + .driver.name = KBUILD_MODNAME, + .driver.owner = THIS_MODULE, + .id_table = id_table, + .probe = virtrng_probe, + .remove = __devexit_p(virtrng_remove), +}; + +static int __init init(void) +{ + int err; + + random_data = kmalloc(RANDOM_DATA_SIZE, GFP_KERNEL); + if (!random_data) + return -ENOMEM; + + err = register_virtio_driver(&virtio_rng); + if (err) + kfree(random_data); + return err; +} + +static void __exit fini(void) +{ + kfree(random_data); + unregister_virtio_driver(&virtio_rng); +} +module_init(init); +module_exit(fini); + +MODULE_DEVICE_TABLE(virtio, id_table); +MODULE_DESCRIPTION("Virtio random number driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/char/ip2/Makefile b/drivers/char/ip2/Makefile index 6bfe2543ddc2..939618f62fe1 100644 --- a/drivers/char/ip2/Makefile +++ b/drivers/char/ip2/Makefile @@ -2,7 +2,7 @@ # Makefile for the Computone IntelliPort Plus Driver # -obj-$(CONFIG_COMPUTONE) += ip2.o ip2main.o +obj-$(CONFIG_COMPUTONE) += ip2.o -ip2-objs := ip2base.o +ip2-objs := ip2base.o ip2main.o diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c index 70957acaa960..c12cf8fc4be0 100644 --- a/drivers/char/ip2/ip2main.c +++ b/drivers/char/ip2/ip2main.c @@ -346,27 +346,6 @@ have_requested_irq( char irq ) } /******************************************************************************/ -/* Function: init_module() */ -/* Parameters: None */ -/* Returns: Success (0) */ -/* */ -/* Description: */ -/* This is a required entry point for an installable module. It simply calls */ -/* the driver initialisation function and returns what it returns. */ -/******************************************************************************/ -#ifdef MODULE -static int __init -ip2_init_module(void) -{ -#ifdef IP2DEBUG_INIT - printk (KERN_DEBUG "Loading module ...\n" ); -#endif - return 0; -} -module_init(ip2_init_module); -#endif /* MODULE */ - -/******************************************************************************/ /* Function: cleanup_module() */ /* Parameters: None */ /* Returns: Nothing */ @@ -779,8 +758,6 @@ out: return err; } -EXPORT_SYMBOL(ip2_loadmain); - /******************************************************************************/ /* Function: ip2_init_board() */ /* Parameters: Index of board in configuration structure */ diff --git a/drivers/char/pcmcia/ipwireless/hardware.c b/drivers/char/pcmcia/ipwireless/hardware.c index fa9d3c945f31..ba6340ae98af 100644 --- a/drivers/char/pcmcia/ipwireless/hardware.c +++ b/drivers/char/pcmcia/ipwireless/hardware.c @@ -251,10 +251,11 @@ struct ipw_hardware { int init_loops; struct timer_list setup_timer; + /* Flag if hw is ready to send next packet */ int tx_ready; - struct list_head tx_queue[NL_NUM_OF_PRIORITIES]; - /* True if any packets are queued for transmission */ + /* Count of pending packets to be sent */ int tx_queued; + struct list_head tx_queue[NL_NUM_OF_PRIORITIES]; int rx_bytes_queued; struct list_head rx_queue; @@ -404,6 +405,8 @@ static int do_send_fragment(struct ipw_hardware *hw, const unsigned char *data, spin_lock_irqsave(&hw->spinlock, flags); + hw->tx_ready = 0; + if (hw->hw_version == HW_VERSION_1) { outw((unsigned short) length, hw->base_port + IODWR); @@ -492,6 +495,7 @@ static int do_send_packet(struct ipw_hardware *hw, struct ipw_tx_packet *packet) spin_lock_irqsave(&hw->spinlock, flags); list_add(&packet->queue, &hw->tx_queue[0]); + hw->tx_queued++; spin_unlock_irqrestore(&hw->spinlock, flags); } else { if (packet->packet_callback) @@ -949,12 +953,10 @@ static int send_pending_packet(struct ipw_hardware *hw, int priority_limit) unsigned long flags; spin_lock_irqsave(&hw->spinlock, flags); - if (hw->tx_queued && hw->tx_ready != 0) { + if (hw->tx_queued && hw->tx_ready) { int priority; struct ipw_tx_packet *packet = NULL; - hw->tx_ready--; - /* Pick a packet */ for (priority = 0; priority < priority_limit; priority++) { if (!list_empty(&hw->tx_queue[priority])) { @@ -963,6 +965,7 @@ static int send_pending_packet(struct ipw_hardware *hw, int priority_limit) struct ipw_tx_packet, queue); + hw->tx_queued--; list_del(&packet->queue); break; @@ -973,6 +976,7 @@ static int send_pending_packet(struct ipw_hardware *hw, int priority_limit) spin_unlock_irqrestore(&hw->spinlock, flags); return 0; } + spin_unlock_irqrestore(&hw->spinlock, flags); /* Send */ @@ -1063,7 +1067,7 @@ static irqreturn_t ipwireless_handle_v1_interrupt(int irq, if (irqn & IR_TXINTR) { ack |= IR_TXINTR; spin_lock_irqsave(&hw->spinlock, flags); - hw->tx_ready++; + hw->tx_ready = 1; spin_unlock_irqrestore(&hw->spinlock, flags); } /* Received data */ @@ -1170,7 +1174,7 @@ static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq, if (memrxdone & MEMRX_RX_DONE) { writew(0, &hw->memory_info_regs->memreg_rx_done); spin_lock_irqsave(&hw->spinlock, flags); - hw->tx_ready++; + hw->tx_ready = 1; spin_unlock_irqrestore(&hw->spinlock, flags); tx = 1; } @@ -1234,7 +1238,7 @@ static void send_packet(struct ipw_hardware *hw, int priority, spin_lock_irqsave(&hw->spinlock, flags); list_add_tail(&packet->queue, &hw->tx_queue[priority]); - hw->tx_queued = 1; + hw->tx_queued++; spin_unlock_irqrestore(&hw->spinlock, flags); flush_packets_to_hw(hw); diff --git a/drivers/char/vt.c b/drivers/char/vt.c index fa1ffbf2c621..935f1c207a1f 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -434,7 +434,7 @@ static void update_attr(struct vc_data *vc) vc->vc_blink, vc->vc_underline, vc->vc_reverse ^ vc->vc_decscnm, vc->vc_italic); vc->vc_video_erase_char = (build_attr(vc, vc->vc_color, 1, vc->vc_blink, 0, vc->vc_decscnm, 0) << 8) | ' '; - vc->vc_scrl_erase_char = (build_attr(vc, vc->vc_def_color, 1, false, false, false, false) << 8) | ' '; + vc->vc_scrl_erase_char = (build_attr(vc, vc->vc_def_color, 1, false, false, vc->vc_decscnm, false) << 8) | ' '; } /* Note: inverting the screen twice should revert to the original state */ @@ -909,7 +909,7 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines) if (vc->vc_tty) { struct winsize ws, *cws = &vc->vc_tty->winsize; - unsigned long flags; + struct pid *pgrp = NULL; memset(&ws, 0, sizeof(ws)); ws.ws_row = vc->vc_rows; @@ -917,11 +917,14 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines) ws.ws_ypixel = vc->vc_scan_lines; mutex_lock(&vc->vc_tty->termios_mutex); - spin_lock_irqsave(&vc->vc_tty->ctrl_lock, flags); - if ((ws.ws_row != cws->ws_row || ws.ws_col != cws->ws_col) && - vc->vc_tty->pgrp) + spin_lock_irq(&vc->vc_tty->ctrl_lock); + if ((ws.ws_row != cws->ws_row || ws.ws_col != cws->ws_col)) + pgrp = get_pid(vc->vc_tty->pgrp); + spin_unlock_irq(&vc->vc_tty->ctrl_lock); + if (pgrp) { kill_pgrp(vc->vc_tty->pgrp, SIGWINCH, 1); - spin_unlock_irqrestore(&vc->vc_tty->ctrl_lock, flags); + put_pid(pgrp); + } *cws = ws; mutex_unlock(&vc->vc_tty->termios_mutex); } |