* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <linux/config.h>
#include <linux/console.h>
#include <linux/cpumask.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/delay.h>
+#include <linux/freezer.h>
#include <asm/uaccess.h>
struct tty_struct *tty;
unsigned int count;
int do_wakeup;
- char outbuf[N_OUTBUF] __ALIGNED__;
+ char *outbuf;
+ int outbuf_size;
int n_outbuf;
uint32_t vtermno;
struct hv_ops *ops;
* NOTE: This API isn't used if the console adapter doesn't support interrupts.
* In this case the console is poll driven.
*/
-static irqreturn_t hvc_handle_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
+static irqreturn_t hvc_handle_interrupt(int irq, void *dev_instance)
{
/* if hvc_poll request a repoll, then kick the hvcd thread */
if (hvc_poll(dev_instance))
struct kobject *kobjp;
/* Auto increments kobject reference if found. */
- if (!(hp = hvc_get_by_index(tty->index))) {
- printk(KERN_WARNING "hvc_console: tty open failed, no vty associated with tty.\n");
+ if (!(hp = hvc_get_by_index(tty->index)))
return -ENODEV;
- }
spin_lock_irqsave(&hp->lock, flags);
/* Check and then increment for fast path open. */
spin_unlock_irqrestore(&hp->lock, flags);
/* check error, fallback to non-irq */
if (irq != NO_IRQ)
- rc = request_irq(irq, hvc_handle_interrupt, SA_INTERRUPT, "hvc_console", hp);
+ rc = request_irq(irq, hvc_handle_interrupt, IRQF_DISABLED, "hvc_console", hp);
/*
* If the request_irq() fails and we return an error. The tty layer
if (hp->n_outbuf > 0)
hvc_push(hp);
- while (count > 0 && (rsize = N_OUTBUF - hp->n_outbuf) > 0) {
+ while (count > 0 && (rsize = hp->outbuf_size - hp->n_outbuf) > 0) {
if (rsize > count)
rsize = count;
memcpy(hp->outbuf + hp->n_outbuf, buf, rsize);
if (!hp)
return -1;
- return N_OUTBUF - hp->n_outbuf;
+ return hp->outbuf_size - hp->n_outbuf;
}
static int hvc_chars_in_buffer(struct tty_struct *tty)
#define HVC_POLL_READ 0x00000001
#define HVC_POLL_WRITE 0x00000002
-#define HVC_POLL_QUICK 0x00000004
static int hvc_poll(struct hvc_struct *hp)
{
/* Push pending writes */
if (hp->n_outbuf > 0)
hvc_push(hp);
+
/* Reschedule us if still some write pending */
if (hp->n_outbuf > 0)
poll_mask |= HVC_POLL_WRITE;
sysrq_pressed = 1;
continue;
} else if (sysrq_pressed) {
- handle_sysrq(buf[i], NULL, tty);
+ handle_sysrq(buf[i], tty);
sysrq_pressed = 0;
continue;
}
do {
poll_mask = 0;
hvc_kicked = 0;
+ try_to_freeze();
wmb();
if (cpus_empty(cpus_in_xmon)) {
spin_lock(&hvc_structs_lock);
poll_mask |= HVC_POLL_READ;
if (hvc_kicked)
continue;
- if (poll_mask & HVC_POLL_QUICK) {
+ if (poll_mask & HVC_POLL_WRITE) {
yield();
continue;
}
return 0;
}
-static struct tty_operations hvc_ops = {
+static const struct tty_operations hvc_ops = {
.open = hvc_open,
.close = hvc_close,
.write = hvc_write,
};
struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq,
- struct hv_ops *ops)
+ struct hv_ops *ops, int outbuf_size)
{
struct hvc_struct *hp;
int i;
- hp = kmalloc(sizeof(*hp), GFP_KERNEL);
+ hp = kmalloc(ALIGN(sizeof(*hp), sizeof(long)) + outbuf_size,
+ GFP_KERNEL);
if (!hp)
return ERR_PTR(-ENOMEM);
hp->vtermno = vtermno;
hp->irq = irq;
hp->ops = ops;
+ hp->outbuf_size = outbuf_size;
+ hp->outbuf = &((char *)hp)[ALIGN(sizeof(*hp), sizeof(long))];
kobject_init(&hp->kobj);
hp->kobj.ktype = &hvc_kobj_type;
return -ENOMEM;
drv->owner = THIS_MODULE;
- drv->devfs_name = "hvc/";
drv->driver_name = "hvc";
drv->name = "hvc";
drv->major = HVC_MAJOR;