mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-20 05:31:15 +00:00
tty_port: Add port client functions
Introduce a client (upward direction) operations struct for tty_port clients. Initially supported operations are for receiving data and write wake-up. This will allow for having clients other than an ldisc. Convert the calls to the ldisc to use the client ops as the default operations. Signed-off-by: Rob Herring <robh@kernel.org> Reviewed-By: Sebastian Reichel <sre@kernel.org> Tested-By: Sebastian Reichel <sre@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
a380ed461f
commit
c3485ee0d5
3 changed files with 51 additions and 21 deletions
|
@ -437,7 +437,7 @@ int tty_ldisc_receive_buf(struct tty_ldisc *ld, const unsigned char *p,
|
||||||
EXPORT_SYMBOL_GPL(tty_ldisc_receive_buf);
|
EXPORT_SYMBOL_GPL(tty_ldisc_receive_buf);
|
||||||
|
|
||||||
static int
|
static int
|
||||||
receive_buf(struct tty_ldisc *ld, struct tty_buffer *head, int count)
|
receive_buf(struct tty_port *port, struct tty_buffer *head, int count)
|
||||||
{
|
{
|
||||||
unsigned char *p = char_buf_ptr(head, head->read);
|
unsigned char *p = char_buf_ptr(head, head->read);
|
||||||
char *f = NULL;
|
char *f = NULL;
|
||||||
|
@ -445,7 +445,7 @@ receive_buf(struct tty_ldisc *ld, struct tty_buffer *head, int count)
|
||||||
if (~head->flags & TTYB_NORMAL)
|
if (~head->flags & TTYB_NORMAL)
|
||||||
f = flag_buf_ptr(head, head->read);
|
f = flag_buf_ptr(head, head->read);
|
||||||
|
|
||||||
return tty_ldisc_receive_buf(ld, p, f, count);
|
return port->client_ops->receive_buf(port, p, f, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -465,16 +465,6 @@ static void flush_to_ldisc(struct work_struct *work)
|
||||||
{
|
{
|
||||||
struct tty_port *port = container_of(work, struct tty_port, buf.work);
|
struct tty_port *port = container_of(work, struct tty_port, buf.work);
|
||||||
struct tty_bufhead *buf = &port->buf;
|
struct tty_bufhead *buf = &port->buf;
|
||||||
struct tty_struct *tty;
|
|
||||||
struct tty_ldisc *disc;
|
|
||||||
|
|
||||||
tty = READ_ONCE(port->itty);
|
|
||||||
if (tty == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
disc = tty_ldisc_ref(tty);
|
|
||||||
if (disc == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
mutex_lock(&buf->lock);
|
mutex_lock(&buf->lock);
|
||||||
|
|
||||||
|
@ -504,7 +494,7 @@ static void flush_to_ldisc(struct work_struct *work)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
count = receive_buf(disc, head, count);
|
count = receive_buf(port, head, count);
|
||||||
if (!count)
|
if (!count)
|
||||||
break;
|
break;
|
||||||
head->read += count;
|
head->read += count;
|
||||||
|
@ -512,7 +502,6 @@ static void flush_to_ldisc(struct work_struct *work)
|
||||||
|
|
||||||
mutex_unlock(&buf->lock);
|
mutex_unlock(&buf->lock);
|
||||||
|
|
||||||
tty_ldisc_deref(disc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -17,6 +17,44 @@
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
|
||||||
|
static int tty_port_default_receive_buf(struct tty_port *port,
|
||||||
|
const unsigned char *p,
|
||||||
|
const unsigned char *f, size_t count)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct tty_struct *tty;
|
||||||
|
struct tty_ldisc *disc;
|
||||||
|
|
||||||
|
tty = READ_ONCE(port->itty);
|
||||||
|
if (!tty)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
disc = tty_ldisc_ref(tty);
|
||||||
|
if (!disc)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ret = tty_ldisc_receive_buf(disc, p, (char *)f, count);
|
||||||
|
|
||||||
|
tty_ldisc_deref(disc);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tty_port_default_wakeup(struct tty_port *port)
|
||||||
|
{
|
||||||
|
struct tty_struct *tty = tty_port_tty_get(port);
|
||||||
|
|
||||||
|
if (tty) {
|
||||||
|
tty_wakeup(tty);
|
||||||
|
tty_kref_put(tty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct tty_port_client_operations default_client_ops = {
|
||||||
|
.receive_buf = tty_port_default_receive_buf,
|
||||||
|
.write_wakeup = tty_port_default_wakeup,
|
||||||
|
};
|
||||||
|
|
||||||
void tty_port_init(struct tty_port *port)
|
void tty_port_init(struct tty_port *port)
|
||||||
{
|
{
|
||||||
memset(port, 0, sizeof(*port));
|
memset(port, 0, sizeof(*port));
|
||||||
|
@ -28,6 +66,7 @@ void tty_port_init(struct tty_port *port)
|
||||||
spin_lock_init(&port->lock);
|
spin_lock_init(&port->lock);
|
||||||
port->close_delay = (50 * HZ) / 100;
|
port->close_delay = (50 * HZ) / 100;
|
||||||
port->closing_wait = (3000 * HZ) / 100;
|
port->closing_wait = (3000 * HZ) / 100;
|
||||||
|
port->client_ops = &default_client_ops;
|
||||||
kref_init(&port->kref);
|
kref_init(&port->kref);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(tty_port_init);
|
EXPORT_SYMBOL(tty_port_init);
|
||||||
|
@ -272,12 +311,7 @@ EXPORT_SYMBOL_GPL(tty_port_tty_hangup);
|
||||||
*/
|
*/
|
||||||
void tty_port_tty_wakeup(struct tty_port *port)
|
void tty_port_tty_wakeup(struct tty_port *port)
|
||||||
{
|
{
|
||||||
struct tty_struct *tty = tty_port_tty_get(port);
|
port->client_ops->write_wakeup(port);
|
||||||
|
|
||||||
if (tty) {
|
|
||||||
tty_wakeup(tty);
|
|
||||||
tty_kref_put(tty);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(tty_port_tty_wakeup);
|
EXPORT_SYMBOL_GPL(tty_port_tty_wakeup);
|
||||||
|
|
||||||
|
|
|
@ -217,12 +217,18 @@ struct tty_port_operations {
|
||||||
/* Called on the final put of a port */
|
/* Called on the final put of a port */
|
||||||
void (*destruct)(struct tty_port *port);
|
void (*destruct)(struct tty_port *port);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct tty_port_client_operations {
|
||||||
|
int (*receive_buf)(struct tty_port *port, const unsigned char *, const unsigned char *, size_t);
|
||||||
|
void (*write_wakeup)(struct tty_port *port);
|
||||||
|
};
|
||||||
|
|
||||||
struct tty_port {
|
struct tty_port {
|
||||||
struct tty_bufhead buf; /* Locked internally */
|
struct tty_bufhead buf; /* Locked internally */
|
||||||
struct tty_struct *tty; /* Back pointer */
|
struct tty_struct *tty; /* Back pointer */
|
||||||
struct tty_struct *itty; /* internal back ptr */
|
struct tty_struct *itty; /* internal back ptr */
|
||||||
const struct tty_port_operations *ops; /* Port operations */
|
const struct tty_port_operations *ops; /* Port operations */
|
||||||
|
const struct tty_port_client_operations *client_ops; /* Port client operations */
|
||||||
spinlock_t lock; /* Lock protecting tty field */
|
spinlock_t lock; /* Lock protecting tty field */
|
||||||
int blocked_open; /* Waiting to open */
|
int blocked_open; /* Waiting to open */
|
||||||
int count; /* Usage count */
|
int count; /* Usage count */
|
||||||
|
@ -241,6 +247,7 @@ struct tty_port {
|
||||||
based drain is needed else
|
based drain is needed else
|
||||||
set to size of fifo */
|
set to size of fifo */
|
||||||
struct kref kref; /* Ref counter */
|
struct kref kref; /* Ref counter */
|
||||||
|
void *client_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* tty_port::iflags bits -- use atomic bit ops */
|
/* tty_port::iflags bits -- use atomic bit ops */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue