#include <linux/module.h>
#include <linux/major.h>
#include <linux/kernel.h>
-#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/sysrq.h>
#include <linux/tty.h>
#define __ALIGNED__ __attribute__((__aligned__(sizeof(long))))
struct hvsi_struct {
- struct work_struct writer;
+ struct delayed_work writer;
struct work_struct handshaker;
wait_queue_head_t emptyq; /* woken when outbuf is emptied */
wait_queue_head_t stateq; /* woken when HVSI state changes */
/* CD went away; no more connection */
pr_debug("hvsi%i: CD dropped\n", hp->index);
hp->mctrl &= TIOCM_CD;
- if (!(hp->tty->flags & CLOCAL))
+ /* If userland hasn't done an open(2) yet, hp->tty is NULL. */
+ if (hp->tty && !(hp->tty->flags & CLOCAL))
*to_hangup = hp->tty;
}
break;
hp->sysrq = 1;
continue;
} else if (hp->sysrq) {
- handle_sysrq(c, NULL, hp->tty);
+ handle_sysrq(c, hp->tty);
hp->sysrq = 0;
continue;
}
* must get all pending data because we only get an irq on empty->non-empty
* transition
*/
-static irqreturn_t hvsi_interrupt(int irq, void *arg, struct pt_regs *regs)
+static irqreturn_t hvsi_interrupt(int irq, void *arg)
{
struct hvsi_struct *hp = (struct hvsi_struct *)arg;
struct tty_struct *flip;
unsigned long end_jiffies = jiffies + HVSI_TIMEOUT;
for (;;) {
- hvsi_interrupt(hp->virq, (void *)hp, NULL); /* get pending data */
+ hvsi_interrupt(hp->virq, (void *)hp); /* get pending data */
if (hp->state == state)
return 0;
return 0;
}
-static void hvsi_handshaker(void *arg)
+static void hvsi_handshaker(struct work_struct *work)
{
- struct hvsi_struct *hp = (struct hvsi_struct *)arg;
+ struct hvsi_struct *hp =
+ container_of(work, struct hvsi_struct, handshaker);
if (hvsi_handshake(hp) >= 0)
return;
}
/* hvsi_write_worker will keep rescheduling itself until outbuf is empty */
-static void hvsi_write_worker(void *arg)
+static void hvsi_write_worker(struct work_struct *work)
{
- struct hvsi_struct *hp = (struct hvsi_struct *)arg;
+ struct hvsi_struct *hp =
+ container_of(work, struct hvsi_struct, writer.work);
unsigned long flags;
#ifdef DEBUG
static long start_j = 0;
start_j = 0;
#endif /* DEBUG */
wake_up_all(&hp->emptyq);
- if (test_bit(TTY_DO_WRITE_WAKEUP, &hp->tty->flags)
- && hp->tty->ldisc.write_wakeup)
- hp->tty->ldisc.write_wakeup(hp->tty);
- wake_up_interruptible(&hp->tty->write_wait);
+ tty_wakeup(hp->tty);
}
out:
}
-static struct tty_operations hvsi_ops = {
+static const struct tty_operations hvsi_ops = {
.open = hvsi_open,
.close = hvsi_close,
.write = hvsi_write,
hvsi_driver->type = TTY_DRIVER_TYPE_SYSTEM;
hvsi_driver->init_termios = tty_std_termios;
hvsi_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL;
+ hvsi_driver->init_termios.c_ispeed = 9600;
+ hvsi_driver->init_termios.c_ospeed = 9600;
hvsi_driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(hvsi_driver, &hvsi_ops);
vty != NULL;
vty = of_find_compatible_node(vty, "serial", "hvterm-protocol")) {
struct hvsi_struct *hp;
- uint32_t *vtermno;
- uint32_t *irq;
+ const uint32_t *vtermno, *irq;
- vtermno = (uint32_t *)get_property(vty, "reg", NULL);
- irq = (uint32_t *)get_property(vty, "interrupts", NULL);
+ vtermno = of_get_property(vty, "reg", NULL);
+ irq = of_get_property(vty, "interrupts", NULL);
if (!vtermno || !irq)
continue;
}
hp = &hvsi_ports[hvsi_count];
- INIT_WORK(&hp->writer, hvsi_write_worker, hp);
- INIT_WORK(&hp->handshaker, hvsi_handshaker, hp);
+ INIT_DELAYED_WORK(&hp->writer, hvsi_write_worker);
+ INIT_WORK(&hp->handshaker, hvsi_handshaker);
init_waitqueue_head(&hp->emptyq);
init_waitqueue_head(&hp->stateq);
spin_lock_init(&hp->lock);
hp->inbuf_end = hp->inbuf;
hp->state = HVSI_CLOSED;
hp->vtermno = *vtermno;
- hp->virq = irq_create_mapping(NULL, irq[0], 0);
+ hp->virq = irq_create_mapping(NULL, irq[0]);
if (hp->virq == NO_IRQ) {
printk(KERN_ERR "%s: couldn't create irq mapping for 0x%x\n",
__FUNCTION__, irq[0]);