serial: imx: Fix the reporting of interrupts

On a imx system with ttymxc0, ttymxc1 and ttymxc4 registered we see the
following output from 'cat /proc/interrupts':

$ cat /proc/interrupts
           CPU0
...
 58:         39       GIC  58  2020000.serial
 67:        115       GIC  67  21f8000.i2c

The only uart irq that appears is ttymxc0, which is the console.

As ttymxc1 and ttymxc4 will only have their irq registered at imx_startup(),
they are not shown right after probe.

Transmitting to ttymxc1 and ttymxc4 will cause their irqs to be registered, but
the output shows:

$ echo "111111" > /dev/ttymxc1
$ echo "444444" > /dev/ttymxc4
$ cat /proc/interrupts
           CPU0
...
 58:        150       GIC  58  2020000.serial
 59:          1       GIC  59
 62:          1       GIC  62
 67:        115       GIC  67  21f8000.i2c

,which misses printing the associated device address.

In order to fix this, register all the irqs inside the probe function via
devm_request_irq(), which will correctly report the serial interrupts associated
with their correspondent serial device and also helps simplyfing the code by
avoiding the calls to free_irq().

$ echo "111111" > /dev/ttymxc1
$ echo "444444" > /dev/ttymxc4
$ cat /proc/interrupts

	   CPU0
....
 58:        202       GIC  58  2020000.serial
 59:          1       GIC  59  21e8000.serial
 62:          1       GIC  62  21f4000.serial
 67:        115       GIC  67  21f8000.i2c

Signed-off-by: Fabio Estevam <fabio.estevam@freescale.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Fabio Estevam 2014-10-27 14:49:37 -02:00 committed by Greg Kroah-Hartman
parent fe655de171
commit c0d1c6b0f0
1 changed files with 30 additions and 48 deletions

View File

@ -1109,37 +1109,6 @@ static int imx_startup(struct uart_port *port)
while (!(readl(sport->port.membase + UCR2) & UCR2_SRST) && (--i > 0))
udelay(1);
/*
* Allocate the IRQ(s) i.MX1 has three interrupts whereas later
* chips only have one interrupt.
*/
if (sport->txirq > 0) {
retval = request_irq(sport->rxirq, imx_rxint, 0,
dev_name(port->dev), sport);
if (retval)
goto error_out1;
retval = request_irq(sport->txirq, imx_txint, 0,
dev_name(port->dev), sport);
if (retval)
goto error_out2;
/* do not use RTS IRQ on IrDA */
if (!USE_IRDA(sport)) {
retval = request_irq(sport->rtsirq, imx_rtsint, 0,
dev_name(port->dev), sport);
if (retval)
goto error_out3;
}
} else {
retval = request_irq(sport->port.irq, imx_int, 0,
dev_name(port->dev), sport);
if (retval) {
free_irq(sport->port.irq, sport);
goto error_out1;
}
}
spin_lock_irqsave(&sport->port.lock, flags);
/*
* Finally, clear and enable interrupts
@ -1202,12 +1171,6 @@ static int imx_startup(struct uart_port *port)
return 0;
error_out3:
if (sport->txirq)
free_irq(sport->txirq, sport);
error_out2:
if (sport->rxirq)
free_irq(sport->rxirq, sport);
error_out1:
return retval;
}
@ -1254,17 +1217,6 @@ static void imx_shutdown(struct uart_port *port)
*/
del_timer_sync(&sport->timer);
/*
* Free the interrupts
*/
if (sport->txirq > 0) {
if (!USE_IRDA(sport))
free_irq(sport->rtsirq, sport);
free_irq(sport->txirq, sport);
free_irq(sport->rxirq, sport);
} else
free_irq(sport->port.irq, sport);
/*
* Disable all interrupts, port and break condition.
*/
@ -1929,6 +1881,36 @@ static int serial_imx_probe(struct platform_device *pdev)
sport->port.uartclk = clk_get_rate(sport->clk_per);
/*
* Allocate the IRQ(s) i.MX1 has three interrupts whereas later
* chips only have one interrupt.
*/
if (sport->txirq > 0) {
ret = devm_request_irq(&pdev->dev, sport->rxirq, imx_rxint, 0,
dev_name(&pdev->dev), sport);
if (ret)
return ret;
ret = devm_request_irq(&pdev->dev, sport->txirq, imx_txint, 0,
dev_name(&pdev->dev), sport);
if (ret)
return ret;
/* do not use RTS IRQ on IrDA */
if (!USE_IRDA(sport)) {
ret = devm_request_irq(&pdev->dev, sport->rtsirq,
imx_rtsint, 0,
dev_name(&pdev->dev), sport);
if (ret)
return ret;
}
} else {
ret = devm_request_irq(&pdev->dev, sport->port.irq, imx_int, 0,
dev_name(&pdev->dev), sport);
if (ret)
return ret;
}
imx_ports[sport->port.line] = sport;
platform_set_drvdata(pdev, sport);