serial:ifx6x60:Prevent data transfer when IFX6x60 port is shutdown
authorchao bi <chao.bi@intel.com>
Wed, 31 Oct 2012 08:54:07 +0000 (16:54 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 1 Nov 2012 15:50:01 +0000 (08:50 -0700)
This patch is to implement following 2 places to avoid potential error when IFX6x60 port shutdown:
1) Clear Flag IFX_SPI_STATE_IO_AVAILABLE to disable data transfer when Modem port is shutdown;
2) Clear Flag IFX_SPI_STATE_IO_IN_PROGRESS and IFX_SPI_STATE_IO_READY when reopen port.
This is because last port shutdown may happen when SPI/DMA transfer is in progress, if the last
data transfer is not completed(for example due to modem reset), the Flag IFX_SPI_STATE_IO_IN_PROGRESS
will be set forever, so when IFX port is activated again, IFX_SPI_STATE_IO_IN_PROGRESS will prevent
transferring data forever. And if don't clear IFX_SPI_STATE_IO_READY, it may cause one more SPI frame
transferring in spit there is not data need to be transfer.

cc: liu chuansheng <chuansheng.liu@intel.com>
cc: Chen Jun <jun.d.chen@intel.com>
Signed-off-by: channing <chao.bi@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/serial/ifx6x60.c
drivers/tty/serial/ifx6x60.h

index e595c832be203df082c47a401a64ae616fe36da7..fbda37415f01ca4e5fbdf942ced406743cecd34b 100644 (file)
@@ -569,12 +569,19 @@ static int ifx_port_activate(struct tty_port *port, struct tty_struct *tty)
        /* clear any old data; can't do this in 'close' */
        kfifo_reset(&ifx_dev->tx_fifo);
 
+       /* clear any flag which may be set in port shutdown procedure */
+       clear_bit(IFX_SPI_STATE_IO_IN_PROGRESS, &ifx_dev->flags);
+       clear_bit(IFX_SPI_STATE_IO_READY, &ifx_dev->flags);
+
        /* put port data into this tty */
        tty->driver_data = ifx_dev;
 
        /* allows flip string push from int context */
        tty->low_latency = 1;
 
+       /* set flag to allows data transfer */
+       set_bit(IFX_SPI_STATE_IO_AVAILABLE, &ifx_dev->flags);
+
        return 0;
 }
 
@@ -590,6 +597,7 @@ static void ifx_port_shutdown(struct tty_port *port)
        struct ifx_spi_device *ifx_dev =
                container_of(port, struct ifx_spi_device, tty_port);
 
+       clear_bit(IFX_SPI_STATE_IO_AVAILABLE, &ifx_dev->flags);
        mrdy_set_low(ifx_dev);
        clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags);
        tasklet_kill(&ifx_dev->io_work_tasklet);
@@ -745,7 +753,8 @@ static void ifx_spi_io(unsigned long data)
        int retval;
        struct ifx_spi_device *ifx_dev = (struct ifx_spi_device *) data;
 
-       if (!test_and_set_bit(IFX_SPI_STATE_IO_IN_PROGRESS, &ifx_dev->flags)) {
+       if (!test_and_set_bit(IFX_SPI_STATE_IO_IN_PROGRESS, &ifx_dev->flags) &&
+               test_bit(IFX_SPI_STATE_IO_AVAILABLE, &ifx_dev->flags)) {
                if (ifx_dev->gpio.unack_srdy_int_nb > 0)
                        ifx_dev->gpio.unack_srdy_int_nb--;
 
index d8869f5a4632cb7ec1d4165be171424c3b281720..4fbddc297839d6ac5e50346ff3c035fa5498b4db 100644 (file)
@@ -41,6 +41,7 @@
 #define IFX_SPI_STATE_IO_IN_PROGRESS   1
 #define IFX_SPI_STATE_IO_READY         2
 #define IFX_SPI_STATE_TIMER_PENDING    3
+#define IFX_SPI_STATE_IO_AVAILABLE     4
 
 /* flow control bitfields */
 #define IFX_SPI_DCD                    0