Re: [PATCH 4/5] atmel_serial: Split the interrupt handler
On Wed, 19 Dec 2007 12:40:08 +0100 Haavard Skinnemoen <[EMAIL PROTECTED]> wrote: > Btw, the funny thing is that, looking at my shell history, I think I > actually did the right thing when committing your patches: > > git commit -s --author 'Remy Bohmer <[EMAIL PROTECTED]>' > git commit -s --author 'Chip Coldwell <[EMAIL PROTECTED]>' > > But for some reason only your names stuck, not your e-mail addresses... It just happened again. Seems like if git-rebase hits a conflict, and I just do "git-rebase --continue" after resolving it (and updating the index), the original author's name is used, but not his e-mail address. Looks like a bug in git-rebase...? Haavard -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 4/5] atmel_serial: Split the interrupt handler
On Tue, 18 Dec 2007 13:19:39 -0500 (EST) Chip Coldwell <[EMAIL PROTECTED]> wrote: > > On Tue, 18 Dec 2007 18:06:14 +0100 > > Haavard Skinnemoen <[EMAIL PROTECTED]> wrote: > > > > > From: Remy Bohmer <[EMAIL PROTECTED]> > > > > Heh. That's obviously wrong. Wonder what happened there? > > > > Looks like Chip's address got mangled too. > > You can find me at <[EMAIL PROTECTED]> or <[EMAIL PROTECTED]> these > days, although <[EMAIL PROTECTED]> still works for the time > being. Thanks. I'll update the broken commits. Btw, the funny thing is that, looking at my shell history, I think I actually did the right thing when committing your patches: git commit -s --author 'Remy Bohmer <[EMAIL PROTECTED]>' git commit -s --author 'Chip Coldwell <[EMAIL PROTECTED]>' But for some reason only your names stuck, not your e-mail addresses... Haavard -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 4/5] atmel_serial: Split the interrupt handler
On Wed, 19 Dec 2007 00:15:24 +0100 Jiri Slaby <[EMAIL PROTECTED]> wrote: > On 12/18/2007 06:06 PM, Haavard Skinnemoen wrote: > > port = _ports[pdev->id]; > > atmel_init_port(port, pdev); > > > > + data = kmalloc(ATMEL_SERIAL_RINGSIZE, GFP_KERNEL); > > + if (!data) > > { > clk_disable(atmel_port->clk); > clk_put(atmel_port->clk); Indeed, thanks. Hmm...the existing error path gets this wrong too. It's actually a bit risky to disable the clock here since we might end up losing the console. I wonder what we're really supposed to do if the console is initialized successfully, but the corresponding device fails to probe...? > > @@ -1022,6 +1144,7 @@ static int __devexit atmel_serial_remove(struct > > platform_device *pdev) > > > > if (port) { > > ret = uart_remove_one_port(_uart, port); > > Don't you need tasklet_kill() here (or somewhere)? Absolutely. Thanks again. > > + kfree(atmel_port->rx_ring.buf); > > kfree(port); Hmm...this actually looks like a bug too. "port" is allocated statically, so it shouldn't be freed. I wonder if anyone ever use this driver as a module? Haavard -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 4/5] atmel_serial: Split the interrupt handler
On Wed, 19 Dec 2007 00:15:24 +0100 Jiri Slaby [EMAIL PROTECTED] wrote: On 12/18/2007 06:06 PM, Haavard Skinnemoen wrote: port = atmel_ports[pdev-id]; atmel_init_port(port, pdev); + data = kmalloc(ATMEL_SERIAL_RINGSIZE, GFP_KERNEL); + if (!data) { clk_disable(atmel_port-clk); clk_put(atmel_port-clk); Indeed, thanks. Hmm...the existing error path gets this wrong too. It's actually a bit risky to disable the clock here since we might end up losing the console. I wonder what we're really supposed to do if the console is initialized successfully, but the corresponding device fails to probe...? @@ -1022,6 +1144,7 @@ static int __devexit atmel_serial_remove(struct platform_device *pdev) if (port) { ret = uart_remove_one_port(atmel_uart, port); Don't you need tasklet_kill() here (or somewhere)? Absolutely. Thanks again. + kfree(atmel_port-rx_ring.buf); kfree(port); Hmm...this actually looks like a bug too. port is allocated statically, so it shouldn't be freed. I wonder if anyone ever use this driver as a module? Haavard -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 4/5] atmel_serial: Split the interrupt handler
On Tue, 18 Dec 2007 13:19:39 -0500 (EST) Chip Coldwell [EMAIL PROTECTED] wrote: On Tue, 18 Dec 2007 18:06:14 +0100 Haavard Skinnemoen [EMAIL PROTECTED] wrote: From: Remy Bohmer [EMAIL PROTECTED] Heh. That's obviously wrong. Wonder what happened there? Looks like Chip's address got mangled too. You can find me at [EMAIL PROTECTED] or [EMAIL PROTECTED] these days, although [EMAIL PROTECTED] still works for the time being. Thanks. I'll update the broken commits. Btw, the funny thing is that, looking at my shell history, I think I actually did the right thing when committing your patches: git commit -s --author 'Remy Bohmer [EMAIL PROTECTED]' git commit -s --author 'Chip Coldwell [EMAIL PROTECTED]' But for some reason only your names stuck, not your e-mail addresses... Haavard -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 4/5] atmel_serial: Split the interrupt handler
On Wed, 19 Dec 2007 12:40:08 +0100 Haavard Skinnemoen [EMAIL PROTECTED] wrote: Btw, the funny thing is that, looking at my shell history, I think I actually did the right thing when committing your patches: git commit -s --author 'Remy Bohmer [EMAIL PROTECTED]' git commit -s --author 'Chip Coldwell [EMAIL PROTECTED]' But for some reason only your names stuck, not your e-mail addresses... It just happened again. Seems like if git-rebase hits a conflict, and I just do git-rebase --continue after resolving it (and updating the index), the original author's name is used, but not his e-mail address. Looks like a bug in git-rebase...? Haavard -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 4/5] atmel_serial: Split the interrupt handler
On 12/18/2007 06:06 PM, Haavard Skinnemoen wrote: > From: Remy Bohmer <[EMAIL PROTECTED]> > > This patch splits up the interrupt handler of the serial port > into a interrupt top-half and a tasklet. [...] > [EMAIL PROTECTED]: misc cleanups and simplifications] > Signed-off-by: Remy Bohmer <[EMAIL PROTECTED]> > Signed-off-by: Haavard Skinnemoen <[EMAIL PROTECTED]> > --- > drivers/serial/atmel_serial.c | 215 > - > 1 files changed, 169 insertions(+), 46 deletions(-) > > diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c > index a6b3828..990d3ab 100644 > --- a/drivers/serial/atmel_serial.c > +++ b/drivers/serial/atmel_serial.c [...] > @@ -994,11 +1108,19 @@ static int atmel_serial_resume(struct platform_device > *pdev) > static int __devinit atmel_serial_probe(struct platform_device *pdev) > { > struct atmel_uart_port *port; > + void *data; > int ret; > > + BUILD_BUG_ON(!is_power_of_2(ATMEL_SERIAL_RINGSIZE)); > + > port = _ports[pdev->id]; > atmel_init_port(port, pdev); > > + data = kmalloc(ATMEL_SERIAL_RINGSIZE, GFP_KERNEL); > + if (!data) { clk_disable(atmel_port->clk); clk_put(atmel_port->clk); > + return -ENOMEM; } > + port->rx_ring.buf = data; > + > ret = uart_add_one_port(_uart, >uart); > if (!ret) { > device_init_wakeup(>dev, 1); > @@ -1022,6 +1144,7 @@ static int __devexit atmel_serial_remove(struct > platform_device *pdev) > > if (port) { > ret = uart_remove_one_port(_uart, port); Don't you need tasklet_kill() here (or somewhere)? > + kfree(atmel_port->rx_ring.buf); > kfree(port); > } > -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 4/5] atmel_serial: Split the interrupt handler
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On Tue, 18 Dec 2007, Haavard Skinnemoen wrote: > On Tue, 18 Dec 2007 18:06:14 +0100 > Haavard Skinnemoen <[EMAIL PROTECTED]> wrote: > > > From: Remy Bohmer <[EMAIL PROTECTED]> > > Heh. That's obviously wrong. Wonder what happened there? > > Looks like Chip's address got mangled too. You can find me at <[EMAIL PROTECTED]> or <[EMAIL PROTECTED]> these days, although <[EMAIL PROTECTED]> still works for the time being. Chip - -- Charles M. "Chip" Coldwell Senior Software Engineer Red Hat, Inc 978-392-2426 GPG ID: 852E052F GPG FPR: 77E5 2B51 4907 F08A 7E92 DE80 AFA9 9A8F 852E 052F -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.7 (GNU/Linux) iD8DBQFHaA87r6maj4UuBS8RApaiAKCDFvC/WtA/s0pysvMIZIsTlAcN7wCffRoa JwA3E6Kt16pU9yi1dx1lCWk= =M528 -END PGP SIGNATURE- -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 4/5] atmel_serial: Split the interrupt handler
On Tue, 18 Dec 2007 18:06:14 +0100 Haavard Skinnemoen <[EMAIL PROTECTED]> wrote: > From: Remy Bohmer <[EMAIL PROTECTED]> Heh. That's obviously wrong. Wonder what happened there? Looks like Chip's address got mangled too. Haavard -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 4/5] atmel_serial: Split the interrupt handler
From: Remy Bohmer <[EMAIL PROTECTED]> This patch splits up the interrupt handler of the serial port into a interrupt top-half and a tasklet. The goal is to get the interrupt top-half as short as possible to minimize latencies on interrupts. But the old code also does some calls in the interrupt handler that are not allowed on preempt-RT in IRQF_NODELAY context. This handler is executed in this context because of the interrupt sharing with the timer interrupt. The timer interrupt on Preempt-RT runs in IRQF_NODELAY context. The tasklet takes care of handling control status changes, pushing incoming characters to the tty layer, handling break and other errors. The Transmit path was IRQF_NODELAY safe by itself, and is not adapted. The read path for DMA(PDC) is also not adapted, because that code does not run in IRQF_NODELAY context due to irq-sharing. The DBGU which is shared with the timer-irq does not work with DMA, so therefor this is no problem. Reading the complete receive queue is still done in the top-half because we never want to miss any incoming character. [EMAIL PROTECTED]: misc cleanups and simplifications] Signed-off-by: Remy Bohmer <[EMAIL PROTECTED]> Signed-off-by: Haavard Skinnemoen <[EMAIL PROTECTED]> --- drivers/serial/atmel_serial.c | 215 - 1 files changed, 169 insertions(+), 46 deletions(-) diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c index a6b3828..990d3ab 100644 --- a/drivers/serial/atmel_serial.c +++ b/drivers/serial/atmel_serial.c @@ -111,6 +111,13 @@ static int (*atmel_open_hook) (struct uart_port *); static void (*atmel_close_hook) (struct uart_port *); +struct atmel_uart_char { + u16 status; + u16 ch; +}; + +#define ATMEL_SERIAL_RINGSIZE 1024 + /* * We wrap our port structure around the generic uart_port. */ @@ -119,6 +126,12 @@ struct atmel_uart_port { struct clk *clk; /* uart clock */ unsigned short suspended; /* is port suspended? */ int break_active; /* break being received */ + + struct tasklet_struct tasklet; + unsigned intirq_pending; + unsigned intirq_status; + + struct circ_buf rx_ring; }; static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART]; @@ -248,22 +261,42 @@ static void atmel_break_ctl(struct uart_port *port, int break_state) } /* + * Stores the incoming character in the ring buffer + */ +static void +atmel_buffer_rx_char(struct uart_port *port, unsigned int status, +unsigned int ch) +{ + struct atmel_uart_port *atmel_port = (struct atmel_uart_port *)port; + struct circ_buf *ring = _port->rx_ring; + struct atmel_uart_char *c; + + if (!CIRC_SPACE(ring->head, ring->tail, ATMEL_SERIAL_RINGSIZE)) + /* Buffer overflow, ignore char */ + return; + + c = &((struct atmel_uart_char *)ring->buf)[ring->head]; + c->status = status; + c->ch = ch; + + /* Make sure the character is stored before we update head. */ + smp_wmb(); + + ring->head = (ring->head + 1) & (ATMEL_SERIAL_RINGSIZE - 1); +} + +/* * Characters received (called from interrupt handler) */ static void atmel_rx_chars(struct uart_port *port) { struct atmel_uart_port *atmel_port = (struct atmel_uart_port *)port; - struct tty_struct *tty = port->info->tty; - unsigned int status, ch, flg; + unsigned int status, ch; status = UART_GET_CSR(port); while (status & ATMEL_US_RXRDY) { ch = UART_GET_CHAR(port); - port->icount.rx++; - - flg = TTY_NORMAL; - /* * note that the error handling code is * out of the main execution path @@ -271,17 +304,14 @@ static void atmel_rx_chars(struct uart_port *port) if (unlikely(status & (ATMEL_US_PARE | ATMEL_US_FRAME | ATMEL_US_OVRE | ATMEL_US_RXBRK) || atmel_port->break_active)) { + /* clear error */ UART_PUT_CR(port, ATMEL_US_RSTSTA); + if (status & ATMEL_US_RXBRK && !atmel_port->break_active) { - /* ignore side-effect */ - status &= ~(ATMEL_US_PARE | ATMEL_US_FRAME); - port->icount.brk++; atmel_port->break_active = 1; UART_PUT_IER(port, ATMEL_US_RXBRK); - if (uart_handle_break(port)) - goto ignore_char; } else { /* * This is either the end-of-break @@ -294,33 +324,13
[PATCH 4/5] atmel_serial: Split the interrupt handler
From: Remy Bohmer [EMAIL PROTECTED] This patch splits up the interrupt handler of the serial port into a interrupt top-half and a tasklet. The goal is to get the interrupt top-half as short as possible to minimize latencies on interrupts. But the old code also does some calls in the interrupt handler that are not allowed on preempt-RT in IRQF_NODELAY context. This handler is executed in this context because of the interrupt sharing with the timer interrupt. The timer interrupt on Preempt-RT runs in IRQF_NODELAY context. The tasklet takes care of handling control status changes, pushing incoming characters to the tty layer, handling break and other errors. The Transmit path was IRQF_NODELAY safe by itself, and is not adapted. The read path for DMA(PDC) is also not adapted, because that code does not run in IRQF_NODELAY context due to irq-sharing. The DBGU which is shared with the timer-irq does not work with DMA, so therefor this is no problem. Reading the complete receive queue is still done in the top-half because we never want to miss any incoming character. [EMAIL PROTECTED]: misc cleanups and simplifications] Signed-off-by: Remy Bohmer [EMAIL PROTECTED] Signed-off-by: Haavard Skinnemoen [EMAIL PROTECTED] --- drivers/serial/atmel_serial.c | 215 - 1 files changed, 169 insertions(+), 46 deletions(-) diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c index a6b3828..990d3ab 100644 --- a/drivers/serial/atmel_serial.c +++ b/drivers/serial/atmel_serial.c @@ -111,6 +111,13 @@ static int (*atmel_open_hook) (struct uart_port *); static void (*atmel_close_hook) (struct uart_port *); +struct atmel_uart_char { + u16 status; + u16 ch; +}; + +#define ATMEL_SERIAL_RINGSIZE 1024 + /* * We wrap our port structure around the generic uart_port. */ @@ -119,6 +126,12 @@ struct atmel_uart_port { struct clk *clk; /* uart clock */ unsigned short suspended; /* is port suspended? */ int break_active; /* break being received */ + + struct tasklet_struct tasklet; + unsigned intirq_pending; + unsigned intirq_status; + + struct circ_buf rx_ring; }; static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART]; @@ -248,22 +261,42 @@ static void atmel_break_ctl(struct uart_port *port, int break_state) } /* + * Stores the incoming character in the ring buffer + */ +static void +atmel_buffer_rx_char(struct uart_port *port, unsigned int status, +unsigned int ch) +{ + struct atmel_uart_port *atmel_port = (struct atmel_uart_port *)port; + struct circ_buf *ring = atmel_port-rx_ring; + struct atmel_uart_char *c; + + if (!CIRC_SPACE(ring-head, ring-tail, ATMEL_SERIAL_RINGSIZE)) + /* Buffer overflow, ignore char */ + return; + + c = ((struct atmel_uart_char *)ring-buf)[ring-head]; + c-status = status; + c-ch = ch; + + /* Make sure the character is stored before we update head. */ + smp_wmb(); + + ring-head = (ring-head + 1) (ATMEL_SERIAL_RINGSIZE - 1); +} + +/* * Characters received (called from interrupt handler) */ static void atmel_rx_chars(struct uart_port *port) { struct atmel_uart_port *atmel_port = (struct atmel_uart_port *)port; - struct tty_struct *tty = port-info-tty; - unsigned int status, ch, flg; + unsigned int status, ch; status = UART_GET_CSR(port); while (status ATMEL_US_RXRDY) { ch = UART_GET_CHAR(port); - port-icount.rx++; - - flg = TTY_NORMAL; - /* * note that the error handling code is * out of the main execution path @@ -271,17 +304,14 @@ static void atmel_rx_chars(struct uart_port *port) if (unlikely(status (ATMEL_US_PARE | ATMEL_US_FRAME | ATMEL_US_OVRE | ATMEL_US_RXBRK) || atmel_port-break_active)) { + /* clear error */ UART_PUT_CR(port, ATMEL_US_RSTSTA); + if (status ATMEL_US_RXBRK !atmel_port-break_active) { - /* ignore side-effect */ - status = ~(ATMEL_US_PARE | ATMEL_US_FRAME); - port-icount.brk++; atmel_port-break_active = 1; UART_PUT_IER(port, ATMEL_US_RXBRK); - if (uart_handle_break(port)) - goto ignore_char; } else { /* * This is either the end-of-break @@ -294,33 +324,13 @@ static void
Re: [PATCH 4/5] atmel_serial: Split the interrupt handler
On Tue, 18 Dec 2007 18:06:14 +0100 Haavard Skinnemoen [EMAIL PROTECTED] wrote: From: Remy Bohmer [EMAIL PROTECTED] Heh. That's obviously wrong. Wonder what happened there? Looks like Chip's address got mangled too. Haavard -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 4/5] atmel_serial: Split the interrupt handler
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On Tue, 18 Dec 2007, Haavard Skinnemoen wrote: On Tue, 18 Dec 2007 18:06:14 +0100 Haavard Skinnemoen [EMAIL PROTECTED] wrote: From: Remy Bohmer [EMAIL PROTECTED] Heh. That's obviously wrong. Wonder what happened there? Looks like Chip's address got mangled too. You can find me at [EMAIL PROTECTED] or [EMAIL PROTECTED] these days, although [EMAIL PROTECTED] still works for the time being. Chip - -- Charles M. Chip Coldwell Senior Software Engineer Red Hat, Inc 978-392-2426 GPG ID: 852E052F GPG FPR: 77E5 2B51 4907 F08A 7E92 DE80 AFA9 9A8F 852E 052F -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.7 (GNU/Linux) iD8DBQFHaA87r6maj4UuBS8RApaiAKCDFvC/WtA/s0pysvMIZIsTlAcN7wCffRoa JwA3E6Kt16pU9yi1dx1lCWk= =M528 -END PGP SIGNATURE- -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 4/5] atmel_serial: Split the interrupt handler
On 12/18/2007 06:06 PM, Haavard Skinnemoen wrote: From: Remy Bohmer [EMAIL PROTECTED] This patch splits up the interrupt handler of the serial port into a interrupt top-half and a tasklet. [...] [EMAIL PROTECTED]: misc cleanups and simplifications] Signed-off-by: Remy Bohmer [EMAIL PROTECTED] Signed-off-by: Haavard Skinnemoen [EMAIL PROTECTED] --- drivers/serial/atmel_serial.c | 215 - 1 files changed, 169 insertions(+), 46 deletions(-) diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c index a6b3828..990d3ab 100644 --- a/drivers/serial/atmel_serial.c +++ b/drivers/serial/atmel_serial.c [...] @@ -994,11 +1108,19 @@ static int atmel_serial_resume(struct platform_device *pdev) static int __devinit atmel_serial_probe(struct platform_device *pdev) { struct atmel_uart_port *port; + void *data; int ret; + BUILD_BUG_ON(!is_power_of_2(ATMEL_SERIAL_RINGSIZE)); + port = atmel_ports[pdev-id]; atmel_init_port(port, pdev); + data = kmalloc(ATMEL_SERIAL_RINGSIZE, GFP_KERNEL); + if (!data) { clk_disable(atmel_port-clk); clk_put(atmel_port-clk); + return -ENOMEM; } + port-rx_ring.buf = data; + ret = uart_add_one_port(atmel_uart, port-uart); if (!ret) { device_init_wakeup(pdev-dev, 1); @@ -1022,6 +1144,7 @@ static int __devexit atmel_serial_remove(struct platform_device *pdev) if (port) { ret = uart_remove_one_port(atmel_uart, port); Don't you need tasklet_kill() here (or somewhere)? + kfree(atmel_port-rx_ring.buf); kfree(port); } -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/