* [PATCH 10/11] sdio_uart: Fix the locking on "func" for new code
2009-11-03 14:17 [PATCH 00/11] Sort out sdio_uart - stage two Alan Cox
@ 2009-11-03 14:18 ` Alan Cox
0 siblings, 0 replies; 15+ messages in thread
From: Alan Cox @ 2009-11-03 14:18 UTC (permalink / raw)
To: linux-mmc, linux-kernel, nico
The new dtr_rts function didn't take the port->func lock as it should
so add use of the lock there.
Signed-off-by: Alan Cox <alan@linux.intel.com>
---
drivers/mmc/card/sdio_uart.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c
index ebb5d4b..0a3acfb 100644
--- a/drivers/mmc/card/sdio_uart.c
+++ b/drivers/mmc/card/sdio_uart.c
@@ -565,10 +565,14 @@ static void uart_dtr_rts(struct tty_port *tport, int onoff)
{
struct sdio_uart_port *port =
container_of(tport, struct sdio_uart_port, port);
+ int ret = sdio_uart_claim_func(port);
+ if (ret)
+ return;
if (onoff == 0)
sdio_uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
else
sdio_uart_set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
+ sdio_uart_release_func(port);
}
/**
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 00/11] Series short description
@ 2009-11-18 14:18 Alan Cox
2009-11-18 14:19 ` [PATCH 01/11] tty_port: Move hupcl handling Alan Cox
` (10 more replies)
0 siblings, 11 replies; 15+ messages in thread
From: Alan Cox @ 2009-11-18 14:18 UTC (permalink / raw)
To: greg, linux-kernel
Resend: This patch series reworks the sdio_uart driver into a modern format
and also replaces the circ buffer stuff it uses with a kfifo which makes the
code a good deal easier to follow.
---
Alan Cox (10):
sdio_uart: add modem functionality
sdio_uart: Fix the locking on "func" for new code
sdio_uart: Style fixes
sdio_uart: Use kfifo instead of the messy circ stuff
sdio_uart: Fix termios handling
sdio_uart: Switch to the open/close helpers
sdio_uart: Move the open lock
sdio_uart: refcount the tty objects
sdio_uart: use tty_port
tty_port: Move hupcl handling
Nicolas Pitre (1):
sdio_uart: Fix oops caused by the previous changeset
drivers/char/tty_port.c | 13 +
drivers/mmc/card/sdio_uart.c | 393 ++++++++++++++++++++++++------------------
2 files changed, 235 insertions(+), 171 deletions(-)
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 01/11] tty_port: Move hupcl handling
2009-11-18 14:18 [PATCH 00/11] Series short description Alan Cox
@ 2009-11-18 14:19 ` Alan Cox
2009-11-18 14:19 ` [PATCH 02/11] sdio_uart: use tty_port Alan Cox
` (9 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Alan Cox @ 2009-11-18 14:19 UTC (permalink / raw)
To: greg, linux-kernel
Move the HUCPL handling from the end of close_port_start to the beginning
of close_port_end. What this actually does is change the ordering from
port shutdown
port->dtr_rts
to
port->dtr_rts
port shutdown
Some hardware drops the physical connection on shutdown so we must perform
the port operations before the shutdown.
Signed-off-by: Alan Cox <alan@linux.intel.com>
---
drivers/char/tty_port.c | 13 ++++++++-----
1 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/drivers/char/tty_port.c b/drivers/char/tty_port.c
index 5e2ac57..93a5bf5 100644
--- a/drivers/char/tty_port.c
+++ b/drivers/char/tty_port.c
@@ -360,6 +360,14 @@ int tty_port_close_start(struct tty_port *port,
timeout = 2 * HZ;
schedule_timeout_interruptible(timeout);
}
+ /* Flush the ldisc buffering */
+ tty_ldisc_flush(tty);
+
+ /* Drop DTR/RTS if HUPCL is set. This causes any attached modem to
+ hang up the line */
+ if (tty->termios->c_cflag & HUPCL)
+ tty_port_lower_dtr_rts(port);
+
/* Don't call port->drop for the last reference. Callers will want
to drop the last active reference in ->shutdown() or the tty
shutdown path */
@@ -371,11 +379,6 @@ void tty_port_close_end(struct tty_port *port, struct tty_struct *tty)
{
unsigned long flags;
- tty_ldisc_flush(tty);
-
- if (tty->termios->c_cflag & HUPCL)
- tty_port_lower_dtr_rts(port);
-
spin_lock_irqsave(&port->lock, flags);
tty->closing = 0;
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 02/11] sdio_uart: use tty_port
2009-11-18 14:18 [PATCH 00/11] Series short description Alan Cox
2009-11-18 14:19 ` [PATCH 01/11] tty_port: Move hupcl handling Alan Cox
@ 2009-11-18 14:19 ` Alan Cox
2009-11-18 14:19 ` [PATCH 03/11] sdio_uart: Fix oops caused by the previous changeset Alan Cox
` (8 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Alan Cox @ 2009-11-18 14:19 UTC (permalink / raw)
To: greg, linux-kernel
Add a tty_port object to the sdio uart. For the moment just begin using the
tty field of the port, as this is the critical one to clean up.
Signed-off-by: Alan Cox <alan@linux.intel.com>
---
drivers/mmc/card/sdio_uart.c | 41 +++++++++++++++++++++++------------------
1 files changed, 23 insertions(+), 18 deletions(-)
diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c
index b8e7c5a..c2759db 100644
--- a/drivers/mmc/card/sdio_uart.c
+++ b/drivers/mmc/card/sdio_uart.c
@@ -73,6 +73,7 @@ struct uart_icount {
};
struct sdio_uart_port {
+ struct tty_port port;
struct kref kref;
struct tty_struct *tty;
unsigned int index;
@@ -172,7 +173,7 @@ static void sdio_uart_port_remove(struct sdio_uart_port *port)
port->func = NULL;
mutex_unlock(&port->func_lock);
if (port->opened)
- tty_hangup(port->tty);
+ tty_hangup(port->port.tty);
mutex_unlock(&port->open_lock);
sdio_release_irq(func);
sdio_disable_func(func);
@@ -391,7 +392,7 @@ static void sdio_uart_stop_rx(struct sdio_uart_port *port)
static void sdio_uart_receive_chars(struct sdio_uart_port *port,
unsigned int *status)
{
- struct tty_struct *tty = port->tty;
+ struct tty_struct *tty = port->port.tty;
unsigned int ch, flag;
int max_count = 256;
@@ -446,6 +447,7 @@ static void sdio_uart_transmit_chars(struct sdio_uart_port *port)
{
struct circ_buf *xmit = &port->xmit;
int count;
+ struct tty_struct *tty = port->port.tty;
if (port->x_char) {
sdio_out(port, UART_TX, port->x_char);
@@ -453,7 +455,7 @@ static void sdio_uart_transmit_chars(struct sdio_uart_port *port)
port->x_char = 0;
return;
}
- if (circ_empty(xmit) || port->tty->stopped || port->tty->hw_stopped) {
+ if (circ_empty(xmit) || tty->stopped || tty->hw_stopped) {
sdio_uart_stop_tx(port);
return;
}
@@ -468,7 +470,7 @@ static void sdio_uart_transmit_chars(struct sdio_uart_port *port)
} while (--count > 0);
if (circ_chars_pending(xmit) < WAKEUP_CHARS)
- tty_wakeup(port->tty);
+ tty_wakeup(tty);
if (circ_empty(xmit))
sdio_uart_stop_tx(port);
@@ -477,6 +479,7 @@ static void sdio_uart_transmit_chars(struct sdio_uart_port *port)
static void sdio_uart_check_modem_status(struct sdio_uart_port *port)
{
int status;
+ struct tty_struct *tty = port->port.tty;
status = sdio_in(port, UART_MSR);
@@ -491,17 +494,17 @@ static void sdio_uart_check_modem_status(struct sdio_uart_port *port)
port->icount.dcd++;
if (status & UART_MSR_DCTS) {
port->icount.cts++;
- if (port->tty->termios->c_cflag & CRTSCTS) {
+ if (tty->termios->c_cflag & CRTSCTS) {
int cts = (status & UART_MSR_CTS);
- if (port->tty->hw_stopped) {
+ if (tty->hw_stopped) {
if (cts) {
- port->tty->hw_stopped = 0;
+ tty->hw_stopped = 0;
sdio_uart_start_tx(port);
- tty_wakeup(port->tty);
+ tty_wakeup(tty);
}
} else {
if (!cts) {
- port->tty->hw_stopped = 1;
+ tty->hw_stopped = 1;
sdio_uart_stop_tx(port);
}
}
@@ -546,12 +549,13 @@ static int sdio_uart_startup(struct sdio_uart_port *port)
{
unsigned long page;
int ret;
+ struct tty_struct *tty = port->port.tty;
/*
* Set the TTY IO error marker - we will only clear this
* once we have successfully opened the port.
*/
- set_bit(TTY_IO_ERROR, &port->tty->flags);
+ set_bit(TTY_IO_ERROR, &tty->flags);
/* Initialise and allocate the transmit buffer. */
page = __get_free_page(GFP_KERNEL);
@@ -595,14 +599,14 @@ static int sdio_uart_startup(struct sdio_uart_port *port)
port->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE | UART_IER_UUE;
port->mctrl = TIOCM_OUT2;
- sdio_uart_change_speed(port, port->tty->termios, NULL);
+ sdio_uart_change_speed(port, tty->termios, NULL);
- if (port->tty->termios->c_cflag & CBAUD)
+ if (tty->termios->c_cflag & CBAUD)
sdio_uart_set_mctrl(port, TIOCM_RTS | TIOCM_DTR);
- if (port->tty->termios->c_cflag & CRTSCTS)
+ if (tty->termios->c_cflag & CRTSCTS)
if (!(sdio_uart_get_mctrl(port) & TIOCM_CTS))
- port->tty->hw_stopped = 1;
+ tty->hw_stopped = 1;
clear_bit(TTY_IO_ERROR, &port->tty->flags);
@@ -634,7 +638,7 @@ static void sdio_uart_shutdown(struct sdio_uart_port *port)
/* TODO: wait here for TX FIFO to drain */
/* Turn off DTR and RTS early. */
- if (port->tty->termios->c_cflag & HUPCL)
+ if (port->port.tty->termios->c_cflag & HUPCL)
sdio_uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
/* Disable interrupts from this port */
@@ -684,11 +688,11 @@ static int sdio_uart_open(struct tty_struct *tty, struct file *filp)
if (!port->opened) {
tty->driver_data = port;
- port->tty = tty;
+ port->port.tty = tty;
ret = sdio_uart_startup(port);
if (ret) {
tty->driver_data = NULL;
- port->tty = NULL;
+ port->port.tty = NULL;
mutex_unlock(&port->open_lock);
sdio_uart_port_put(port);
return ret;
@@ -723,7 +727,7 @@ static void sdio_uart_close(struct tty_struct *tty, struct file * filp)
tty->closing = 1;
sdio_uart_shutdown(port);
tty_ldisc_flush(tty);
- port->tty = NULL;
+ port->port.tty = NULL;
tty->driver_data = NULL;
tty->closing = 0;
}
@@ -1068,6 +1072,7 @@ static int sdio_uart_probe(struct sdio_func *func,
port->func = func;
sdio_set_drvdata(func, port);
+ tty_port_init(&port->port);
ret = sdio_uart_add_port(port);
if (ret) {
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 03/11] sdio_uart: Fix oops caused by the previous changeset
2009-11-18 14:18 [PATCH 00/11] Series short description Alan Cox
2009-11-18 14:19 ` [PATCH 01/11] tty_port: Move hupcl handling Alan Cox
2009-11-18 14:19 ` [PATCH 02/11] sdio_uart: use tty_port Alan Cox
@ 2009-11-18 14:19 ` Alan Cox
2009-11-18 14:19 ` [PATCH 04/11] sdio_uart: refcount the tty objects Alan Cox
` (7 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Alan Cox @ 2009-11-18 14:19 UTC (permalink / raw)
To: greg, linux-kernel
From: Nicolas Pitre <nico@fluxnic.net>
Now... testing reveals that the very first patch "sdio_uart: use
tty_port" causes a segmentation fault in sdio_uart_open():
Unable to handle kernel NULL pointer dereference at virtual address 00000084
pgd = dfb44000 [00000084] *pgd=1fb99031, *pte=00000000, *ppte=00000000
Internal error: Oops: 17 [#1] PREEMPT
last sysfs file:
/sys/devices/platform/mvsdio/mmc_host/mmc0/mmc0:f111/uevent
Modules linked in:
CPU: 0 Not tainted (2.6.32-rc5-next-20091102-00001-gb36eae9 #10)
PC is at sdio_uart_open+0x204/0x2cc
[...]
Signed-off-by: Alan Cox <alan@linux.intel.com>
---
drivers/mmc/card/sdio_uart.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c
index c2759db..671fe5e 100644
--- a/drivers/mmc/card/sdio_uart.c
+++ b/drivers/mmc/card/sdio_uart.c
@@ -608,7 +608,7 @@ static int sdio_uart_startup(struct sdio_uart_port *port)
if (!(sdio_uart_get_mctrl(port) & TIOCM_CTS))
tty->hw_stopped = 1;
- clear_bit(TTY_IO_ERROR, &port->tty->flags);
+ clear_bit(TTY_IO_ERROR, &tty->flags);
/* Kick the IRQ handler once while we're still holding the host lock */
sdio_uart_irq(port->func);
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 04/11] sdio_uart: refcount the tty objects
2009-11-18 14:18 [PATCH 00/11] Series short description Alan Cox
` (2 preceding siblings ...)
2009-11-18 14:19 ` [PATCH 03/11] sdio_uart: Fix oops caused by the previous changeset Alan Cox
@ 2009-11-18 14:19 ` Alan Cox
2009-11-18 14:19 ` [PATCH 05/11] sdio_uart: Move the open lock Alan Cox
` (6 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Alan Cox @ 2009-11-18 14:19 UTC (permalink / raw)
To: greg, linux-kernel
The tty can go away underneath us, so we must refcount it. Do the naïve
implementation initially. We will worry about startup shortly.
Signed-off-by: Alan Cox <alan@linux.intel.com>
---
drivers/mmc/card/sdio_uart.c | 59 ++++++++++++++++++++++++++++++------------
1 files changed, 42 insertions(+), 17 deletions(-)
diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c
index 671fe5e..86ad543 100644
--- a/drivers/mmc/card/sdio_uart.c
+++ b/drivers/mmc/card/sdio_uart.c
@@ -172,8 +172,13 @@ static void sdio_uart_port_remove(struct sdio_uart_port *port)
sdio_claim_host(func);
port->func = NULL;
mutex_unlock(&port->func_lock);
- if (port->opened)
- tty_hangup(port->port.tty);
+ if (port->opened) {
+ struct tty_struct *tty = tty_port_tty_get(&port->port);
+ /* tty_hangup is async so is this safe as is ?? */
+ if (tty)
+ tty_hangup(tty);
+ tty_kref_put(tty);
+ }
mutex_unlock(&port->open_lock);
sdio_release_irq(func);
sdio_disable_func(func);
@@ -392,7 +397,7 @@ static void sdio_uart_stop_rx(struct sdio_uart_port *port)
static void sdio_uart_receive_chars(struct sdio_uart_port *port,
unsigned int *status)
{
- struct tty_struct *tty = port->port.tty;
+ struct tty_struct *tty = tty_port_tty_get(&port->port);
unsigned int ch, flag;
int max_count = 256;
@@ -429,25 +434,30 @@ static void sdio_uart_receive_chars(struct sdio_uart_port *port,
}
if ((*status & port->ignore_status_mask & ~UART_LSR_OE) == 0)
- tty_insert_flip_char(tty, ch, flag);
+ if (tty)
+ tty_insert_flip_char(tty, ch, flag);
/*
* Overrun is special. Since it's reported immediately,
* it doesn't affect the current character.
*/
if (*status & ~port->ignore_status_mask & UART_LSR_OE)
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+ if (tty)
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
*status = sdio_in(port, UART_LSR);
} while ((*status & UART_LSR_DR) && (max_count-- > 0));
- tty_flip_buffer_push(tty);
+ if (tty) {
+ tty_flip_buffer_push(tty);
+ tty_kref_put(tty);
+ }
}
static void sdio_uart_transmit_chars(struct sdio_uart_port *port)
{
struct circ_buf *xmit = &port->xmit;
int count;
- struct tty_struct *tty = port->port.tty;
+ struct tty_struct *tty;
if (port->x_char) {
sdio_out(port, UART_TX, port->x_char);
@@ -455,8 +465,12 @@ static void sdio_uart_transmit_chars(struct sdio_uart_port *port)
port->x_char = 0;
return;
}
- if (circ_empty(xmit) || tty->stopped || tty->hw_stopped) {
+
+ tty = tty_port_tty_get(&port->port);
+
+ if (tty == NULL || circ_empty(xmit) || tty->stopped || tty->hw_stopped) {
sdio_uart_stop_tx(port);
+ tty_kref_put(tty);
return;
}
@@ -474,12 +488,13 @@ static void sdio_uart_transmit_chars(struct sdio_uart_port *port)
if (circ_empty(xmit))
sdio_uart_stop_tx(port);
+ tty_kref_put(tty);
}
static void sdio_uart_check_modem_status(struct sdio_uart_port *port)
{
int status;
- struct tty_struct *tty = port->port.tty;
+ struct tty_struct *tty;
status = sdio_in(port, UART_MSR);
@@ -494,7 +509,8 @@ static void sdio_uart_check_modem_status(struct sdio_uart_port *port)
port->icount.dcd++;
if (status & UART_MSR_DCTS) {
port->icount.cts++;
- if (tty->termios->c_cflag & CRTSCTS) {
+ tty = tty_port_tty_get(&port->port);
+ if (tty && (tty->termios->c_cflag & CRTSCTS)) {
int cts = (status & UART_MSR_CTS);
if (tty->hw_stopped) {
if (cts) {
@@ -509,6 +525,7 @@ static void sdio_uart_check_modem_status(struct sdio_uart_port *port)
}
}
}
+ tty_kref_put(tty);
}
}
@@ -548,8 +565,10 @@ static void sdio_uart_irq(struct sdio_func *func)
static int sdio_uart_startup(struct sdio_uart_port *port)
{
unsigned long page;
- int ret;
- struct tty_struct *tty = port->port.tty;
+ int ret = -ENOMEM;
+ struct tty_struct *tty = tty_port_tty_get(&port->port);
+
+ /* FIXME: What if it is NULL ?? */
/*
* Set the TTY IO error marker - we will only clear this
@@ -560,7 +579,7 @@ static int sdio_uart_startup(struct sdio_uart_port *port)
/* Initialise and allocate the transmit buffer. */
page = __get_free_page(GFP_KERNEL);
if (!page)
- return -ENOMEM;
+ goto err0;
port->xmit.buf = (unsigned char *)page;
circ_clear(&port->xmit);
@@ -614,6 +633,7 @@ static int sdio_uart_startup(struct sdio_uart_port *port)
sdio_uart_irq(port->func);
sdio_uart_release_func(port);
+ tty_kref_put(tty);
return 0;
err3:
@@ -622,12 +642,15 @@ err2:
sdio_uart_release_func(port);
err1:
free_page((unsigned long)port->xmit.buf);
+err0:
+ tty_kref_put(tty);
return ret;
}
static void sdio_uart_shutdown(struct sdio_uart_port *port)
{
int ret;
+ struct tty_struct *tty;
ret = sdio_uart_claim_func(port);
if (ret)
@@ -637,9 +660,11 @@ static void sdio_uart_shutdown(struct sdio_uart_port *port)
/* TODO: wait here for TX FIFO to drain */
+ tty = tty_port_tty_get(&port->port);
/* Turn off DTR and RTS early. */
- if (port->port.tty->termios->c_cflag & HUPCL)
+ if (tty && (tty->termios->c_cflag & HUPCL))
sdio_uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
+ tty_kref_put(tty);
/* Disable interrupts from this port */
sdio_release_irq(port->func);
@@ -688,11 +713,11 @@ static int sdio_uart_open(struct tty_struct *tty, struct file *filp)
if (!port->opened) {
tty->driver_data = port;
- port->port.tty = tty;
+ tty_port_tty_set(&port->port, tty);
ret = sdio_uart_startup(port);
if (ret) {
tty->driver_data = NULL;
- port->port.tty = NULL;
+ tty_port_tty_set(&port->port, NULL);
mutex_unlock(&port->open_lock);
sdio_uart_port_put(port);
return ret;
@@ -727,7 +752,7 @@ static void sdio_uart_close(struct tty_struct *tty, struct file * filp)
tty->closing = 1;
sdio_uart_shutdown(port);
tty_ldisc_flush(tty);
- port->port.tty = NULL;
+ tty_port_tty_set(&port->port, NULL);
tty->driver_data = NULL;
tty->closing = 0;
}
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 05/11] sdio_uart: Move the open lock
2009-11-18 14:18 [PATCH 00/11] Series short description Alan Cox
` (3 preceding siblings ...)
2009-11-18 14:19 ` [PATCH 04/11] sdio_uart: refcount the tty objects Alan Cox
@ 2009-11-18 14:19 ` Alan Cox
2009-11-18 14:19 ` [PATCH 06/11] sdio_uart: Switch to the open/close helpers Alan Cox
` (5 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Alan Cox @ 2009-11-18 14:19 UTC (permalink / raw)
To: greg, linux-kernel
When we move to the tty_port logic the port mutex will protect open v close
v hangup. Move to this first in the existing open code so we have a bisection
point.
Signed-off-by: Alan Cox <alan@linux.intel.com>
---
drivers/mmc/card/sdio_uart.c | 20 +++++++++-----------
1 files changed, 9 insertions(+), 11 deletions(-)
diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c
index 86ad543..31f7023 100644
--- a/drivers/mmc/card/sdio_uart.c
+++ b/drivers/mmc/card/sdio_uart.c
@@ -78,7 +78,6 @@ struct sdio_uart_port {
struct tty_struct *tty;
unsigned int index;
unsigned int opened;
- struct mutex open_lock;
struct sdio_func *func;
struct mutex func_lock;
struct task_struct *in_sdio_uart_irq;
@@ -103,7 +102,6 @@ static int sdio_uart_add_port(struct sdio_uart_port *port)
int index, ret = -EBUSY;
kref_init(&port->kref);
- mutex_init(&port->open_lock);
mutex_init(&port->func_lock);
spin_lock_init(&port->write_lock);
@@ -166,7 +164,7 @@ static void sdio_uart_port_remove(struct sdio_uart_port *port)
* give up on that port ASAP.
* Beware: the lock ordering is critical.
*/
- mutex_lock(&port->open_lock);
+ mutex_lock(&port->port.mutex);
mutex_lock(&port->func_lock);
func = port->func;
sdio_claim_host(func);
@@ -179,7 +177,7 @@ static void sdio_uart_port_remove(struct sdio_uart_port *port)
tty_hangup(tty);
tty_kref_put(tty);
}
- mutex_unlock(&port->open_lock);
+ mutex_unlock(&port->port.mutex);
sdio_release_irq(func);
sdio_disable_func(func);
sdio_release_host(func);
@@ -699,14 +697,14 @@ static int sdio_uart_open(struct tty_struct *tty, struct file *filp)
if (!port)
return -ENODEV;
- mutex_lock(&port->open_lock);
+ mutex_lock(&port->port.mutex);
/*
* Make sure not to mess up with a dead port
* which has not been closed yet.
*/
if (tty->driver_data && tty->driver_data != port) {
- mutex_unlock(&port->open_lock);
+ mutex_unlock(&port->port.mutex);
sdio_uart_port_put(port);
return -EBUSY;
}
@@ -718,13 +716,13 @@ static int sdio_uart_open(struct tty_struct *tty, struct file *filp)
if (ret) {
tty->driver_data = NULL;
tty_port_tty_set(&port->port, NULL);
- mutex_unlock(&port->open_lock);
+ mutex_unlock(&port->port.mutex);
sdio_uart_port_put(port);
return ret;
}
}
port->opened++;
- mutex_unlock(&port->open_lock);
+ mutex_unlock(&port->port.mutex);
return 0;
}
@@ -735,7 +733,7 @@ static void sdio_uart_close(struct tty_struct *tty, struct file * filp)
if (!port)
return;
- mutex_lock(&port->open_lock);
+ mutex_lock(&port->port.mutex);
BUG_ON(!port->opened);
/*
@@ -744,7 +742,7 @@ static void sdio_uart_close(struct tty_struct *tty, struct file * filp)
* is larger than port->count.
*/
if (tty->count > port->opened) {
- mutex_unlock(&port->open_lock);
+ mutex_unlock(&port->port.mutex);
return;
}
@@ -756,7 +754,7 @@ static void sdio_uart_close(struct tty_struct *tty, struct file * filp)
tty->driver_data = NULL;
tty->closing = 0;
}
- mutex_unlock(&port->open_lock);
+ mutex_unlock(&port->port.mutex);
sdio_uart_port_put(port);
}
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 06/11] sdio_uart: Switch to the open/close helpers
2009-11-18 14:18 [PATCH 00/11] Series short description Alan Cox
` (4 preceding siblings ...)
2009-11-18 14:19 ` [PATCH 05/11] sdio_uart: Move the open lock Alan Cox
@ 2009-11-18 14:19 ` Alan Cox
2009-11-20 17:35 ` Greg KH
2009-11-18 14:20 ` [PATCH 07/11] sdio_uart: Fix termios handling Alan Cox
` (4 subsequent siblings)
10 siblings, 1 reply; 15+ messages in thread
From: Alan Cox @ 2009-11-18 14:19 UTC (permalink / raw)
To: greg, linux-kernel
Gets us proper tty semantics, removes some code and fixes up a few corner
case races (hangup during open etc)
Signed-off-by: Alan Cox <alan@linux.intel.com>
---
drivers/mmc/card/sdio_uart.c | 201 +++++++++++++++++++++++++-----------------
1 files changed, 119 insertions(+), 82 deletions(-)
diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c
index 31f7023..1be90bc 100644
--- a/drivers/mmc/card/sdio_uart.c
+++ b/drivers/mmc/card/sdio_uart.c
@@ -77,7 +77,6 @@ struct sdio_uart_port {
struct kref kref;
struct tty_struct *tty;
unsigned int index;
- unsigned int opened;
struct sdio_func *func;
struct mutex func_lock;
struct task_struct *in_sdio_uart_irq;
@@ -150,6 +149,7 @@ static void sdio_uart_port_put(struct sdio_uart_port *port)
static void sdio_uart_port_remove(struct sdio_uart_port *port)
{
struct sdio_func *func;
+ struct tty_struct *tty;
BUG_ON(sdio_uart_table[port->index] != port);
@@ -170,11 +170,10 @@ static void sdio_uart_port_remove(struct sdio_uart_port *port)
sdio_claim_host(func);
port->func = NULL;
mutex_unlock(&port->func_lock);
- if (port->opened) {
- struct tty_struct *tty = tty_port_tty_get(&port->port);
- /* tty_hangup is async so is this safe as is ?? */
- if (tty)
- tty_hangup(tty);
+ tty = tty_port_tty_get(&port->port);
+ /* tty_hangup is async so is this safe as is ?? */
+ if (tty) {
+ tty_hangup(tty);
tty_kref_put(tty);
}
mutex_unlock(&port->port.mutex);
@@ -560,13 +559,46 @@ static void sdio_uart_irq(struct sdio_func *func)
port->in_sdio_uart_irq = NULL;
}
-static int sdio_uart_startup(struct sdio_uart_port *port)
+/**
+ * uart_dtr_rts - port helper to set uart signals
+ * @tport: tty port to be updated
+ * @onoff: set to turn on DTR/RTS
+ *
+ * Called by the tty port helpers when the modem signals need to be
+ * adjusted during an open, close and hangup.
+ */
+
+static void uart_dtr_rts(struct tty_port *tport, int onoff)
{
- unsigned long page;
- int ret = -ENOMEM;
- struct tty_struct *tty = tty_port_tty_get(&port->port);
+ struct sdio_uart_port *port =
+ container_of(tport, struct sdio_uart_port, port);
+ if (onoff == 0)
+ sdio_uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
+ else
+ sdio_uart_set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
+}
+
+/**
+ * sdio_uart_activate - start up hardware
+ * @tport: tty port to activate
+ * @tty: tty bound to this port
+ *
+ * Activate a tty port. The port locking guarantees us this will be
+ * run exactly once per set of opens, and if successful will see the
+ * shutdown method run exactly once to match. Start up and shutdown are
+ * protected from each other by the internal locking and will not run
+ * at the same time even during a hangup event.
+ *
+ * If we successfully start up the port we take an extra kref as we
+ * will keep it around until shutdown when the kref is dropped.
+ */
- /* FIXME: What if it is NULL ?? */
+static int sdio_uart_activate(struct tty_port *tport, struct tty_struct *tty)
+{
+ struct sdio_uart_port *port =
+ container_of(tport, struct sdio_uart_port, port);
+ unsigned long page;
+ int ret;
/*
* Set the TTY IO error marker - we will only clear this
@@ -577,7 +609,7 @@ static int sdio_uart_startup(struct sdio_uart_port *port)
/* Initialise and allocate the transmit buffer. */
page = __get_free_page(GFP_KERNEL);
if (!page)
- goto err0;
+ return -ENOMEM;
port->xmit.buf = (unsigned char *)page;
circ_clear(&port->xmit);
@@ -631,7 +663,6 @@ static int sdio_uart_startup(struct sdio_uart_port *port)
sdio_uart_irq(port->func);
sdio_uart_release_func(port);
- tty_kref_put(tty);
return 0;
err3:
@@ -640,15 +671,25 @@ err2:
sdio_uart_release_func(port);
err1:
free_page((unsigned long)port->xmit.buf);
-err0:
- tty_kref_put(tty);
return ret;
}
-static void sdio_uart_shutdown(struct sdio_uart_port *port)
+
+/**
+ * sdio_uart_shutdown - stop hardware
+ * @tport: tty port to shut down
+ *
+ * Deactivate a tty port. The port locking guarantees us this will be
+ * run only if a successful matching activate already ran. The two are
+ * protected from each other by the internal locking and will not run
+ * at the same time even during a hangup event.
+ */
+
+static void sdio_uart_shutdown(struct tty_port *tport)
{
+ struct sdio_uart_port *port =
+ container_of(tport, struct sdio_uart_port, port);
int ret;
- struct tty_struct *tty;
ret = sdio_uart_claim_func(port);
if (ret)
@@ -656,14 +697,6 @@ static void sdio_uart_shutdown(struct sdio_uart_port *port)
sdio_uart_stop_rx(port);
- /* TODO: wait here for TX FIFO to drain */
-
- tty = tty_port_tty_get(&port->port);
- /* Turn off DTR and RTS early. */
- if (tty && (tty->termios->c_cflag & HUPCL))
- sdio_uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
- tty_kref_put(tty);
-
/* Disable interrupts from this port */
sdio_release_irq(port->func);
port->ier = 0;
@@ -688,74 +721,68 @@ skip:
free_page((unsigned long)port->xmit.buf);
}
-static int sdio_uart_open(struct tty_struct *tty, struct file *filp)
+/**
+ * sdio_uart_install - install method
+ * @driver: the driver in use (sdio_uart in our case)
+ * @tty: the tty being bound
+ *
+ * Look up and bind the tty and the driver together. Initialize
+ * any needed private data (in our case the termios)
+ */
+
+static int sdio_uart_install(struct tty_driver *driver, struct tty_struct *tty)
{
- struct sdio_uart_port *port;
- int ret;
+ int idx = tty->index;
+ struct sdio_uart_port *port = sdio_uart_port_get(idx);
+ int ret = tty_init_termios(tty);
+
+ if (ret == 0) {
+ tty_driver_kref_get(driver);
+ tty->count++;
+ /* This is the ref sdio_uart_port get provided */
+ tty->driver_data = port;
+ driver->ttys[idx] = tty;
+ } else
+ sdio_uart_port_put(port);
+ return ret;
+
+}
- port = sdio_uart_port_get(tty->index);
- if (!port)
- return -ENODEV;
+/**
+ * sdio_uart_cleanup - called on the last tty kref drop
+ * @tty: the tty being destroyed
+ *
+ * Called asynchronously when the last reference to the tty is dropped.
+ * We cannot destroy the tty->driver_data port kref until this point
+ */
- mutex_lock(&port->port.mutex);
+static void sdio_uart_cleanup(struct tty_struct *tty)
+{
+ struct sdio_uart_port *port = tty->driver_data;
+ tty->driver_data = NULL; /* Bug trap */
+ sdio_uart_port_put(port);
+}
- /*
- * Make sure not to mess up with a dead port
- * which has not been closed yet.
- */
- if (tty->driver_data && tty->driver_data != port) {
- mutex_unlock(&port->port.mutex);
- sdio_uart_port_put(port);
- return -EBUSY;
- }
+/*
+ * Open/close/hangup is now entirely boilerplate
+ */
- if (!port->opened) {
- tty->driver_data = port;
- tty_port_tty_set(&port->port, tty);
- ret = sdio_uart_startup(port);
- if (ret) {
- tty->driver_data = NULL;
- tty_port_tty_set(&port->port, NULL);
- mutex_unlock(&port->port.mutex);
- sdio_uart_port_put(port);
- return ret;
- }
- }
- port->opened++;
- mutex_unlock(&port->port.mutex);
- return 0;
+static int sdio_uart_open(struct tty_struct *tty, struct file *filp)
+{
+ struct sdio_uart_port *port = tty->driver_data;
+ return tty_port_open(&port->port, tty, filp);
}
static void sdio_uart_close(struct tty_struct *tty, struct file * filp)
{
struct sdio_uart_port *port = tty->driver_data;
+ tty_port_close(&port->port, tty, filp);
+}
- if (!port)
- return;
-
- mutex_lock(&port->port.mutex);
- BUG_ON(!port->opened);
-
- /*
- * This is messy. The tty layer calls us even when open()
- * returned an error. Ignore this close request if tty->count
- * is larger than port->count.
- */
- if (tty->count > port->opened) {
- mutex_unlock(&port->port.mutex);
- return;
- }
-
- if (--port->opened == 0) {
- tty->closing = 1;
- sdio_uart_shutdown(port);
- tty_ldisc_flush(tty);
- tty_port_tty_set(&port->port, NULL);
- tty->driver_data = NULL;
- tty->closing = 0;
- }
- mutex_unlock(&port->port.mutex);
- sdio_uart_port_put(port);
+static void sdio_uart_hangup(struct tty_struct *tty)
+{
+ struct sdio_uart_port *port = tty->driver_data;
+ tty_port_hangup(&port->port);
}
static int sdio_uart_write(struct tty_struct * tty, const unsigned char *buf,
@@ -1021,6 +1048,12 @@ static const struct file_operations sdio_uart_proc_fops = {
.release = single_release,
};
+static const struct tty_port_operations sdio_uart_port_ops = {
+ .dtr_rts = uart_dtr_rts,
+ .shutdown = sdio_uart_shutdown,
+ .activate = sdio_uart_activate,
+};
+
static const struct tty_operations sdio_uart_ops = {
.open = sdio_uart_open,
.close = sdio_uart_close,
@@ -1031,9 +1064,12 @@ static const struct tty_operations sdio_uart_ops = {
.throttle = sdio_uart_throttle,
.unthrottle = sdio_uart_unthrottle,
.set_termios = sdio_uart_set_termios,
+ .hangup = sdio_uart_hangup,
.break_ctl = sdio_uart_break_ctl,
.tiocmget = sdio_uart_tiocmget,
.tiocmset = sdio_uart_tiocmset,
+ .install = sdio_uart_install,
+ .cleanup = sdio_uart_cleanup,
.proc_fops = &sdio_uart_proc_fops,
};
@@ -1096,6 +1132,7 @@ static int sdio_uart_probe(struct sdio_func *func,
port->func = func;
sdio_set_drvdata(func, port);
tty_port_init(&port->port);
+ port->port.ops = &sdio_uart_port_ops;
ret = sdio_uart_add_port(port);
if (ret) {
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 07/11] sdio_uart: Fix termios handling
2009-11-18 14:18 [PATCH 00/11] Series short description Alan Cox
` (5 preceding siblings ...)
2009-11-18 14:19 ` [PATCH 06/11] sdio_uart: Switch to the open/close helpers Alan Cox
@ 2009-11-18 14:20 ` Alan Cox
2009-11-18 14:20 ` [PATCH 08/11] sdio_uart: Use kfifo instead of the messy circ stuff Alan Cox
` (3 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Alan Cox @ 2009-11-18 14:20 UTC (permalink / raw)
To: greg, linux-kernel
Switching between two non standard baud rates fails because of the cflag
test. Do as we did elsewhere and just kill the "optimisation".
Signed-off-by: Alan Cox <alan@linux.intel.com>
---
drivers/mmc/card/sdio_uart.c | 6 ------
1 files changed, 0 insertions(+), 6 deletions(-)
diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c
index 1be90bc..ffa56cb 100644
--- a/drivers/mmc/card/sdio_uart.c
+++ b/drivers/mmc/card/sdio_uart.c
@@ -902,12 +902,6 @@ static void sdio_uart_set_termios(struct tty_struct *tty, struct ktermios *old_t
struct sdio_uart_port *port = tty->driver_data;
unsigned int cflag = tty->termios->c_cflag;
-#define RELEVANT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
- if ((cflag ^ old_termios->c_cflag) == 0 &&
- RELEVANT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0)
- return;
-
if (sdio_uart_claim_func(port) != 0)
return;
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 08/11] sdio_uart: Use kfifo instead of the messy circ stuff
2009-11-18 14:18 [PATCH 00/11] Series short description Alan Cox
` (6 preceding siblings ...)
2009-11-18 14:20 ` [PATCH 07/11] sdio_uart: Fix termios handling Alan Cox
@ 2009-11-18 14:20 ` Alan Cox
2009-11-18 14:20 ` [PATCH 09/11] sdio_uart: Style fixes Alan Cox
` (2 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Alan Cox @ 2009-11-18 14:20 UTC (permalink / raw)
To: greg, linux-kernel
Probably all the tty code should switch to this, especially when the new
lockless kfifo is merged.
Signed-off-by: Alan Cox <alan@linux.intel.com>
---
drivers/mmc/card/sdio_uart.c | 92 +++++++++++++-----------------------------
1 files changed, 29 insertions(+), 63 deletions(-)
diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c
index ffa56cb..4139b24 100644
--- a/drivers/mmc/card/sdio_uart.c
+++ b/drivers/mmc/card/sdio_uart.c
@@ -32,7 +32,7 @@
#include <linux/mutex.h>
#include <linux/seq_file.h>
#include <linux/serial_reg.h>
-#include <linux/circ_buf.h>
+#include <linux/kfifo.h>
#include <linux/gfp.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
@@ -46,18 +46,9 @@
#define UART_NR 8 /* Number of UARTs this driver can handle */
-#define UART_XMIT_SIZE PAGE_SIZE
+#define FIFO_SIZE PAGE_SIZE
#define WAKEUP_CHARS 256
-#define circ_empty(circ) ((circ)->head == (circ)->tail)
-#define circ_clear(circ) ((circ)->head = (circ)->tail = 0)
-
-#define circ_chars_pending(circ) \
- (CIRC_CNT((circ)->head, (circ)->tail, UART_XMIT_SIZE))
-
-#define circ_chars_free(circ) \
- (CIRC_SPACE((circ)->head, (circ)->tail, UART_XMIT_SIZE))
-
struct uart_icount {
__u32 cts;
@@ -81,7 +72,7 @@ struct sdio_uart_port {
struct mutex func_lock;
struct task_struct *in_sdio_uart_irq;
unsigned int regs_offset;
- struct circ_buf xmit;
+ struct kfifo *xmit_fifo;
spinlock_t write_lock;
struct uart_icount icount;
unsigned int uartclk;
@@ -103,6 +94,9 @@ static int sdio_uart_add_port(struct sdio_uart_port *port)
kref_init(&port->kref);
mutex_init(&port->func_lock);
spin_lock_init(&port->write_lock);
+ port->xmit_fifo = kfifo_alloc(FIFO_SIZE, GFP_KERNEL, &port->write_lock);
+ if (port->xmit_fifo == NULL)
+ return -ENOMEM;
spin_lock(&sdio_uart_table_lock);
for (index = 0; index < UART_NR; index++) {
@@ -138,6 +132,7 @@ static void sdio_uart_port_destroy(struct kref *kref)
{
struct sdio_uart_port *port =
container_of(kref, struct sdio_uart_port, kref);
+ kfifo_free(port->xmit_fifo);
kfree(port);
}
@@ -452,9 +447,11 @@ static void sdio_uart_receive_chars(struct sdio_uart_port *port,
static void sdio_uart_transmit_chars(struct sdio_uart_port *port)
{
- struct circ_buf *xmit = &port->xmit;
+ struct kfifo *xmit = port->xmit_fifo;
int count;
struct tty_struct *tty;
+ u8 iobuf[16];
+ int len;
if (port->x_char) {
sdio_out(port, UART_TX, port->x_char);
@@ -465,25 +462,22 @@ static void sdio_uart_transmit_chars(struct sdio_uart_port *port)
tty = tty_port_tty_get(&port->port);
- if (tty == NULL || circ_empty(xmit) || tty->stopped || tty->hw_stopped) {
+ if (tty == NULL || !kfifo_len(xmit) || tty->stopped || tty->hw_stopped) {
sdio_uart_stop_tx(port);
tty_kref_put(tty);
return;
}
- count = 16;
- do {
- sdio_out(port, UART_TX, xmit->buf[xmit->tail]);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+ len = kfifo_get(xmit, iobuf, 16);
+ for (count = 0; count < len; count++) {
+ sdio_out(port, UART_TX, iobuf[count]);
port->icount.tx++;
- if (circ_empty(xmit))
- break;
- } while (--count > 0);
+ }
- if (circ_chars_pending(xmit) < WAKEUP_CHARS)
+ if (len < WAKEUP_CHARS)
tty_wakeup(tty);
- if (circ_empty(xmit))
+ if (len == 0)
sdio_uart_stop_tx(port);
tty_kref_put(tty);
}
@@ -597,7 +591,6 @@ static int sdio_uart_activate(struct tty_port *tport, struct tty_struct *tty)
{
struct sdio_uart_port *port =
container_of(tport, struct sdio_uart_port, port);
- unsigned long page;
int ret;
/*
@@ -606,22 +599,17 @@ static int sdio_uart_activate(struct tty_port *tport, struct tty_struct *tty)
*/
set_bit(TTY_IO_ERROR, &tty->flags);
- /* Initialise and allocate the transmit buffer. */
- page = __get_free_page(GFP_KERNEL);
- if (!page)
- return -ENOMEM;
- port->xmit.buf = (unsigned char *)page;
- circ_clear(&port->xmit);
+ kfifo_reset(port->xmit_fifo);
ret = sdio_uart_claim_func(port);
if (ret)
- goto err1;
+ return ret;
ret = sdio_enable_func(port->func);
if (ret)
- goto err2;
+ goto err1;
ret = sdio_claim_irq(port->func, sdio_uart_irq);
if (ret)
- goto err3;
+ goto err2;
/*
* Clear the FIFO buffers and disable them.
@@ -665,12 +653,10 @@ static int sdio_uart_activate(struct tty_port *tport, struct tty_struct *tty)
sdio_uart_release_func(port);
return 0;
-err3:
- sdio_disable_func(port->func);
err2:
- sdio_uart_release_func(port);
+ sdio_disable_func(port->func);
err1:
- free_page((unsigned long)port->xmit.buf);
+ sdio_uart_release_func(port);
return ret;
}
@@ -689,11 +675,9 @@ static void sdio_uart_shutdown(struct tty_port *tport)
{
struct sdio_uart_port *port =
container_of(tport, struct sdio_uart_port, port);
- int ret;
- ret = sdio_uart_claim_func(port);
- if (ret)
- goto skip;
+ if (sdio_uart_claim_func(port))
+ return;
sdio_uart_stop_rx(port);
@@ -715,10 +699,6 @@ static void sdio_uart_shutdown(struct tty_port *tport)
sdio_disable_func(port->func);
sdio_uart_release_func(port);
-
-skip:
- /* Free the transmit buffer page. */
- free_page((unsigned long)port->xmit.buf);
}
/**
@@ -789,26 +769,12 @@ static int sdio_uart_write(struct tty_struct * tty, const unsigned char *buf,
int count)
{
struct sdio_uart_port *port = tty->driver_data;
- struct circ_buf *circ = &port->xmit;
- int c, ret = 0;
+ int ret;
if (!port->func)
return -ENODEV;
- spin_lock(&port->write_lock);
- while (1) {
- c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);
- if (count < c)
- c = count;
- if (c <= 0)
- break;
- memcpy(circ->buf + circ->head, buf, c);
- circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1);
- buf += c;
- count -= c;
- ret += c;
- }
- spin_unlock(&port->write_lock);
+ ret = kfifo_put(port->xmit_fifo, buf, count);
if ( !(port->ier & UART_IER_THRI)) {
int err = sdio_uart_claim_func(port);
@@ -826,13 +792,13 @@ static int sdio_uart_write(struct tty_struct * tty, const unsigned char *buf,
static int sdio_uart_write_room(struct tty_struct *tty)
{
struct sdio_uart_port *port = tty->driver_data;
- return port ? circ_chars_free(&port->xmit) : 0;
+ return FIFO_SIZE - kfifo_len(port->xmit_fifo);
}
static int sdio_uart_chars_in_buffer(struct tty_struct *tty)
{
struct sdio_uart_port *port = tty->driver_data;
- return port ? circ_chars_pending(&port->xmit) : 0;
+ return kfifo_len(port->xmit_fifo);
}
static void sdio_uart_send_xchar(struct tty_struct *tty, char ch)
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 09/11] sdio_uart: Style fixes
2009-11-18 14:18 [PATCH 00/11] Series short description Alan Cox
` (7 preceding siblings ...)
2009-11-18 14:20 ` [PATCH 08/11] sdio_uart: Use kfifo instead of the messy circ stuff Alan Cox
@ 2009-11-18 14:20 ` Alan Cox
2009-11-18 14:20 ` [PATCH 10/11] sdio_uart: Fix the locking on "func" for new code Alan Cox
2009-11-18 14:21 ` [PATCH 11/11] sdio_uart: add modem functionality Alan Cox
10 siblings, 0 replies; 15+ messages in thread
From: Alan Cox @ 2009-11-18 14:20 UTC (permalink / raw)
To: greg, linux-kernel
Running the current code through checkpatch shows a few bits of noise
mostly but not entirely from before the changes.
Signed-off-by: Alan Cox <alan@linux.intel.com>
---
drivers/mmc/card/sdio_uart.c | 25 +++++++++++++------------
1 files changed, 13 insertions(+), 12 deletions(-)
diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c
index 4139b24..f14338b 100644
--- a/drivers/mmc/card/sdio_uart.c
+++ b/drivers/mmc/card/sdio_uart.c
@@ -462,7 +462,8 @@ static void sdio_uart_transmit_chars(struct sdio_uart_port *port)
tty = tty_port_tty_get(&port->port);
- if (tty == NULL || !kfifo_len(xmit) || tty->stopped || tty->hw_stopped) {
+ if (tty == NULL || !kfifo_len(xmit)
+ || tty->stopped || tty->hw_stopped) {
sdio_uart_stop_tx(port);
tty_kref_put(tty);
return;
@@ -633,7 +634,7 @@ static int sdio_uart_activate(struct tty_port *tport, struct tty_struct *tty)
*/
sdio_out(port, UART_LCR, UART_LCR_WLEN8);
- port->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE | UART_IER_UUE;
+ port->ier = UART_IER_RLSI|UART_IER_RDI|UART_IER_RTOIE|UART_IER_UUE;
port->mctrl = TIOCM_OUT2;
sdio_uart_change_speed(port, tty->termios, NULL);
@@ -660,7 +661,6 @@ err1:
return ret;
}
-
/**
* sdio_uart_shutdown - stop hardware
* @tport: tty port to shut down
@@ -725,7 +725,6 @@ static int sdio_uart_install(struct tty_driver *driver, struct tty_struct *tty)
} else
sdio_uart_port_put(port);
return ret;
-
}
/**
@@ -765,7 +764,7 @@ static void sdio_uart_hangup(struct tty_struct *tty)
tty_port_hangup(&port->port);
}
-static int sdio_uart_write(struct tty_struct * tty, const unsigned char *buf,
+static int sdio_uart_write(struct tty_struct *tty, const unsigned char *buf,
int count)
{
struct sdio_uart_port *port = tty->driver_data;
@@ -776,7 +775,7 @@ static int sdio_uart_write(struct tty_struct * tty, const unsigned char *buf,
ret = kfifo_put(port->xmit_fifo, buf, count);
- if ( !(port->ier & UART_IER_THRI)) {
+ if (!(port->ier & UART_IER_THRI)) {
int err = sdio_uart_claim_func(port);
if (!err) {
sdio_uart_start_tx(port);
@@ -863,7 +862,8 @@ static void sdio_uart_unthrottle(struct tty_struct *tty)
sdio_uart_release_func(port);
}
-static void sdio_uart_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
+static void sdio_uart_set_termios(struct tty_struct *tty,
+ struct ktermios *old_termios)
{
struct sdio_uart_port *port = tty->driver_data;
unsigned int cflag = tty->termios->c_cflag;
@@ -942,7 +942,7 @@ static int sdio_uart_tiocmset(struct tty_struct *tty, struct file *file,
int result;
result = sdio_uart_claim_func(port);
- if(!result) {
+ if (!result) {
sdio_uart_update_mctrl(port, set, clear);
sdio_uart_release_func(port);
}
@@ -960,7 +960,7 @@ static int sdio_uart_proc_show(struct seq_file *m, void *v)
struct sdio_uart_port *port = sdio_uart_port_get(i);
if (port) {
seq_printf(m, "%d: uart:SDIO", i);
- if(capable(CAP_SYS_ADMIN)) {
+ if (capable(CAP_SYS_ADMIN)) {
seq_printf(m, " tx:%d rx:%d",
port->icount.tx, port->icount.rx);
if (port->icount.frame)
@@ -1013,7 +1013,7 @@ static const struct tty_port_operations sdio_uart_port_ops = {
.shutdown = sdio_uart_shutdown,
.activate = sdio_uart_activate,
};
-
+
static const struct tty_operations sdio_uart_ops = {
.open = sdio_uart_open,
.close = sdio_uart_close,
@@ -1066,7 +1066,7 @@ static int sdio_uart_probe(struct sdio_func *func,
}
if (!tpl) {
printk(KERN_WARNING
- "%s: can't find tuple 0x91 subtuple 0 (SUBTPL_SIOREG) for GPS class\n",
+ "%s: can't find tuple 0x91 subtuple 0 (SUBTPL_SIOREG) for GPS class\n",
sdio_func_id(func));
kfree(port);
return -EINVAL;
@@ -1099,7 +1099,8 @@ static int sdio_uart_probe(struct sdio_func *func,
kfree(port);
} else {
struct device *dev;
- dev = tty_register_device(sdio_uart_tty_driver, port->index, &func->dev);
+ dev = tty_register_device(sdio_uart_tty_driver,
+ port->index, &func->dev);
if (IS_ERR(dev)) {
sdio_uart_port_remove(port);
ret = PTR_ERR(dev);
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 10/11] sdio_uart: Fix the locking on "func" for new code
2009-11-18 14:18 [PATCH 00/11] Series short description Alan Cox
` (8 preceding siblings ...)
2009-11-18 14:20 ` [PATCH 09/11] sdio_uart: Style fixes Alan Cox
@ 2009-11-18 14:20 ` Alan Cox
2009-11-18 14:21 ` [PATCH 11/11] sdio_uart: add modem functionality Alan Cox
10 siblings, 0 replies; 15+ messages in thread
From: Alan Cox @ 2009-11-18 14:20 UTC (permalink / raw)
To: greg, linux-kernel
The new dtr_rts function didn't take the port->func lock as it should
so add use of the lock there.
Signed-off-by: Alan Cox <alan@linux.intel.com>
---
drivers/mmc/card/sdio_uart.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c
index f14338b..6d8f019 100644
--- a/drivers/mmc/card/sdio_uart.c
+++ b/drivers/mmc/card/sdio_uart.c
@@ -567,10 +567,14 @@ static void uart_dtr_rts(struct tty_port *tport, int onoff)
{
struct sdio_uart_port *port =
container_of(tport, struct sdio_uart_port, port);
+ int ret = sdio_uart_claim_func(port);
+ if (ret)
+ return;
if (onoff == 0)
sdio_uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
else
sdio_uart_set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
+ sdio_uart_release_func(port);
}
/**
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 11/11] sdio_uart: add modem functionality
2009-11-18 14:18 [PATCH 00/11] Series short description Alan Cox
` (9 preceding siblings ...)
2009-11-18 14:20 ` [PATCH 10/11] sdio_uart: Fix the locking on "func" for new code Alan Cox
@ 2009-11-18 14:21 ` Alan Cox
10 siblings, 0 replies; 15+ messages in thread
From: Alan Cox @ 2009-11-18 14:21 UTC (permalink / raw)
To: greg, linux-kernel
Add the POSIX block for carrier
Linux TIOCMIWAIT functionality is still lacking from the driver.
Signed-off-by: Alan Cox <alan@linux.intel.com>
---
drivers/mmc/card/sdio_uart.c | 33 ++++++++++++++++++++++++++++++++-
1 files changed, 32 insertions(+), 1 deletions(-)
diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c
index 6d8f019..edf2f33 100644
--- a/drivers/mmc/card/sdio_uart.c
+++ b/drivers/mmc/card/sdio_uart.c
@@ -29,6 +29,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/sched.h>
#include <linux/mutex.h>
#include <linux/seq_file.h>
#include <linux/serial_reg.h>
@@ -77,6 +78,7 @@ struct sdio_uart_port {
struct uart_icount icount;
unsigned int uartclk;
unsigned int mctrl;
+ unsigned int rx_mctrl;
unsigned int read_status_mask;
unsigned int ignore_status_mask;
unsigned char x_char;
@@ -215,6 +217,8 @@ static unsigned int sdio_uart_get_mctrl(struct sdio_uart_port *port)
unsigned char status;
unsigned int ret;
+ /* FIXME: What stops this losing the delta bits and breaking
+ sdio_uart_check_modem_status ? */
status = sdio_in(port, UART_MSR);
ret = 0;
@@ -497,8 +501,20 @@ static void sdio_uart_check_modem_status(struct sdio_uart_port *port)
port->icount.rng++;
if (status & UART_MSR_DDSR)
port->icount.dsr++;
- if (status & UART_MSR_DDCD)
+ if (status & UART_MSR_DDCD) {
port->icount.dcd++;
+ /* DCD raise - wake for open */
+ if (status & UART_MSR_DCD)
+ wake_up_interruptible(&port->port.open_wait);
+ else {
+ /* DCD drop - hang up if tty attached */
+ tty = tty_port_tty_get(&port->port);
+ if (tty) {
+ tty_hangup(tty);
+ tty_kref_put(tty);
+ }
+ }
+ }
if (status & UART_MSR_DCTS) {
port->icount.cts++;
tty = tty_port_tty_get(&port->port);
@@ -554,6 +570,20 @@ static void sdio_uart_irq(struct sdio_func *func)
port->in_sdio_uart_irq = NULL;
}
+static int uart_carrier_raised(struct tty_port *tport)
+{
+ struct sdio_uart_port *port =
+ container_of(tport, struct sdio_uart_port, port);
+ unsigned int ret = sdio_uart_claim_func(port);
+ if (ret) /* Missing hardware shoudn't block for carrier */
+ return 1;
+ ret = sdio_uart_get_mctrl(port);
+ sdio_uart_release_func(port);
+ if (ret & TIOCM_CAR)
+ return 1;
+ return 0;
+}
+
/**
* uart_dtr_rts - port helper to set uart signals
* @tport: tty port to be updated
@@ -1014,6 +1044,7 @@ static const struct file_operations sdio_uart_proc_fops = {
static const struct tty_port_operations sdio_uart_port_ops = {
.dtr_rts = uart_dtr_rts,
+ .carrier_raised = uart_carrier_raised,
.shutdown = sdio_uart_shutdown,
.activate = sdio_uart_activate,
};
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH 06/11] sdio_uart: Switch to the open/close helpers
2009-11-18 14:19 ` [PATCH 06/11] sdio_uart: Switch to the open/close helpers Alan Cox
@ 2009-11-20 17:35 ` Greg KH
2009-11-20 19:23 ` Alan Cox
0 siblings, 1 reply; 15+ messages in thread
From: Greg KH @ 2009-11-20 17:35 UTC (permalink / raw)
To: Alan Cox; +Cc: linux-kernel
On Wed, Nov 18, 2009 at 02:19:57PM +0000, Alan Cox wrote:
> Gets us proper tty semantics, removes some code and fixes up a few corner
> case races (hangup during open etc)
>
> Signed-off-by: Alan Cox <alan@linux.intel.com>
Something is wierd here, this patch doesn't apply. And if I do it by
hand and fix up the errors, then patch 7 doesn't apply.
Wierd.
How about I take the first 5 and then you resync and send me the next 6?
thanks,
greg k-h
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 06/11] sdio_uart: Switch to the open/close helpers
2009-11-20 17:35 ` Greg KH
@ 2009-11-20 19:23 ` Alan Cox
0 siblings, 0 replies; 15+ messages in thread
From: Alan Cox @ 2009-11-20 19:23 UTC (permalink / raw)
To: Greg KH; +Cc: Alan Cox, linux-kernel
> Something is wierd here, this patch doesn't apply. And if I do it by
> hand and fix up the errors, then patch 7 doesn't apply.
>
> Wierd.
wEIrd (sorry pet hate)
> How about I take the first 5 and then you resync and send me the next 6?
Works for me.
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2009-11-20 19:21 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-11-18 14:18 [PATCH 00/11] Series short description Alan Cox
2009-11-18 14:19 ` [PATCH 01/11] tty_port: Move hupcl handling Alan Cox
2009-11-18 14:19 ` [PATCH 02/11] sdio_uart: use tty_port Alan Cox
2009-11-18 14:19 ` [PATCH 03/11] sdio_uart: Fix oops caused by the previous changeset Alan Cox
2009-11-18 14:19 ` [PATCH 04/11] sdio_uart: refcount the tty objects Alan Cox
2009-11-18 14:19 ` [PATCH 05/11] sdio_uart: Move the open lock Alan Cox
2009-11-18 14:19 ` [PATCH 06/11] sdio_uart: Switch to the open/close helpers Alan Cox
2009-11-20 17:35 ` Greg KH
2009-11-20 19:23 ` Alan Cox
2009-11-18 14:20 ` [PATCH 07/11] sdio_uart: Fix termios handling Alan Cox
2009-11-18 14:20 ` [PATCH 08/11] sdio_uart: Use kfifo instead of the messy circ stuff Alan Cox
2009-11-18 14:20 ` [PATCH 09/11] sdio_uart: Style fixes Alan Cox
2009-11-18 14:20 ` [PATCH 10/11] sdio_uart: Fix the locking on "func" for new code Alan Cox
2009-11-18 14:21 ` [PATCH 11/11] sdio_uart: add modem functionality Alan Cox
-- strict thread matches above, loose matches on Subject: below --
2009-11-03 14:17 [PATCH 00/11] Sort out sdio_uart - stage two Alan Cox
2009-11-03 14:18 ` [PATCH 10/11] sdio_uart: Fix the locking on "func" for new code Alan Cox
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.