From cc83f833c77c1d233e3843af18c1abf8d561d1fa Mon Sep 17 00:00:00 2001 From: Alberto Garcia Date: Mon, 10 Dec 2012 11:49:57 +0100 Subject: ipack/devices/ipoctal: Fix race condition during Tx In order to transmit data, the driver enables Tx and sleeps until *board_write is set to 1 by the interrupt handler. It can happen, though, that the data is sent even before the process is asleep. In this case *board_write must be set to 1 anyway, otherwise we will be waiting for a condition that will never be true. Signed-off-by: Alberto Garcia Signed-off-by: Samuel Iglesias Gonsalvez Signed-off-by: Greg Kroah-Hartman --- drivers/ipack/devices/ipoctal.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers/ipack/devices/ipoctal.c') diff --git a/drivers/ipack/devices/ipoctal.c b/drivers/ipack/devices/ipoctal.c index 576d53d92677..e66135da63ce 100644 --- a/drivers/ipack/devices/ipoctal.c +++ b/drivers/ipack/devices/ipoctal.c @@ -195,13 +195,10 @@ static void ipoctal_irq_tx(struct ipoctal_channel *channel) *pointer_write = *pointer_write % PAGE_SIZE; channel->nb_bytes--; - if ((channel->nb_bytes == 0) && - (waitqueue_active(&channel->queue))) { - - if (channel->board_id != IPACK1_DEVICE_ID_SBS_OCTAL_485) { - *channel->board_write = 1; - wake_up_interruptible(&channel->queue); - } + if (channel->nb_bytes == 0 && + channel->board_id != IPACK1_DEVICE_ID_SBS_OCTAL_485) { + *channel->board_write = 1; + wake_up_interruptible(&channel->queue); } } -- cgit v1.2.3-59-g8ed1b From 69a6b9b1b6aec645d2efa23db2c15ed287e672dd Mon Sep 17 00:00:00 2001 From: Alberto Garcia Date: Mon, 10 Dec 2012 11:49:58 +0100 Subject: ipack/devices/ipoctal: don't check if nb_bytes is < 0 It is an unsigned int so that check is pointless. Signed-off-by: Alberto Garcia Signed-off-by: Samuel Iglesias Gonsalvez Signed-off-by: Greg Kroah-Hartman --- drivers/ipack/devices/ipoctal.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/ipack/devices/ipoctal.c') diff --git a/drivers/ipack/devices/ipoctal.c b/drivers/ipack/devices/ipoctal.c index e66135da63ce..a33a849765c6 100644 --- a/drivers/ipack/devices/ipoctal.c +++ b/drivers/ipack/devices/ipoctal.c @@ -183,10 +183,8 @@ static void ipoctal_irq_tx(struct ipoctal_channel *channel) unsigned char value; unsigned int *pointer_write = &channel->pointer_write; - if (channel->nb_bytes <= 0) { - channel->nb_bytes = 0; + if (channel->nb_bytes == 0) return; - } value = channel->tty_port.xmit_buf[*pointer_write]; iowrite8(value, &channel->regs->w.thr); -- cgit v1.2.3-59-g8ed1b From 7e5730d7c22267e406454b5cff0c40e4ebf9a0da Mon Sep 17 00:00:00 2001 From: Samuel Iglesias Gonsalvez Date: Mon, 10 Dec 2012 11:49:59 +0100 Subject: ipack/devices/ipoctal: fix kernel bug when using pppd Trying to setup the pppd server to use ipoctal's serial ports, it says the ports are busy the first time. If the operation is repeated, a kernel bug due to a dereference of a NULL pointer appears. Removing the one-access-only setup from the driver, removes this kernel bug. Signed-off-by: Samuel Iglesias Gonsalvez Signed-off-by: Greg Kroah-Hartman --- drivers/ipack/devices/ipoctal.c | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) (limited to 'drivers/ipack/devices/ipoctal.c') diff --git a/drivers/ipack/devices/ipoctal.c b/drivers/ipack/devices/ipoctal.c index a33a849765c6..8d0a86631908 100644 --- a/drivers/ipack/devices/ipoctal.c +++ b/drivers/ipack/devices/ipoctal.c @@ -38,7 +38,6 @@ struct ipoctal_channel { spinlock_t lock; unsigned int pointer_read; unsigned int pointer_write; - atomic_t open; struct tty_port tty_port; union scc2698_channel __iomem *regs; union scc2698_block __iomem *block_regs; @@ -70,22 +69,12 @@ static int ipoctal_port_activate(struct tty_port *port, struct tty_struct *tty) static int ipoctal_open(struct tty_struct *tty, struct file *file) { - int res; struct ipoctal_channel *channel; channel = dev_get_drvdata(tty->dev); - - if (atomic_read(&channel->open)) - return -EBUSY; - tty->driver_data = channel; - res = tty_port_open(&channel->tty_port, tty, file); - if (res) - return res; - - atomic_inc(&channel->open); - return 0; + return tty_port_open(&channel->tty_port, tty, file); } static void ipoctal_reset_stats(struct ipoctal_stats *stats) @@ -111,9 +100,7 @@ static void ipoctal_close(struct tty_struct *tty, struct file *filp) struct ipoctal_channel *channel = tty->driver_data; tty_port_close(&channel->tty_port, tty, filp); - - if (atomic_dec_and_test(&channel->open)) - ipoctal_free_channel(channel); + ipoctal_free_channel(channel); } static int ipoctal_get_icount(struct tty_struct *tty, @@ -205,10 +192,6 @@ static void ipoctal_irq_channel(struct ipoctal_channel *channel) u8 isr, sr; struct tty_struct *tty; - /* If there is no client, skip the check */ - if (!atomic_read(&channel->open)) - return; - tty = tty_port_tty_get(&channel->tty_port); if (!tty) return; -- cgit v1.2.3-59-g8ed1b From a1da13a67afa45cf996ae9325030dd86c26573fc Mon Sep 17 00:00:00 2001 From: Samuel Iglesias Gonsalvez Date: Mon, 10 Dec 2012 11:50:00 +0100 Subject: ipack/devices/ipoctal: remove wait_queue and atomic_t board_write Don't block the TTY client when sending characters. Signed-off-by: Samuel Iglesias Gonsalvez Signed-off-by: Greg Kroah-Hartman --- drivers/ipack/devices/ipoctal.c | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) (limited to 'drivers/ipack/devices/ipoctal.c') diff --git a/drivers/ipack/devices/ipoctal.c b/drivers/ipack/devices/ipoctal.c index 8d0a86631908..18f9cf1ffe2b 100644 --- a/drivers/ipack/devices/ipoctal.c +++ b/drivers/ipack/devices/ipoctal.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include "ipoctal.h" @@ -42,7 +41,6 @@ struct ipoctal_channel { union scc2698_channel __iomem *regs; union scc2698_block __iomem *block_regs; unsigned int board_id; - unsigned char *board_write; u8 isr_rx_rdy_mask; u8 isr_tx_rdy_mask; }; @@ -51,7 +49,6 @@ struct ipoctal { struct ipack_device *dev; unsigned int board_id; struct ipoctal_channel channel[NR_CHANNELS]; - unsigned char write; struct tty_driver *tty_drv; u8 __iomem *mem8_space; u8 __iomem *int_space; @@ -181,10 +178,8 @@ static void ipoctal_irq_tx(struct ipoctal_channel *channel) channel->nb_bytes--; if (channel->nb_bytes == 0 && - channel->board_id != IPACK1_DEVICE_ID_SBS_OCTAL_485) { - *channel->board_write = 1; - wake_up_interruptible(&channel->queue); - } + channel->board_id != IPACK1_DEVICE_ID_SBS_OCTAL_485) + iowrite8(CR_DISABLE_TX, &channel->regs->w.cr); } static void ipoctal_irq_channel(struct ipoctal_channel *channel) @@ -207,8 +202,7 @@ static void ipoctal_irq_channel(struct ipoctal_channel *channel) iowrite8(CR_DISABLE_TX, &channel->regs->w.cr); iowrite8(CR_CMD_NEGATE_RTSN, &channel->regs->w.cr); iowrite8(CR_ENABLE_RX, &channel->regs->w.cr); - *channel->board_write = 1; - wake_up_interruptible(&channel->queue); + iowrite8(CR_DISABLE_TX, &channel->regs->w.cr); } /* RX data */ @@ -302,7 +296,6 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, struct ipoctal_channel *channel = &ipoctal->channel[i]; channel->regs = chan_regs + i; channel->block_regs = block_regs + (i >> 1); - channel->board_write = &ipoctal->write; channel->board_id = ipoctal->board_id; if (i & 1) { channel->isr_tx_rdy_mask = ISR_TxRDY_B; @@ -385,8 +378,6 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, ipoctal_reset_stats(&channel->stats); channel->nb_bytes = 0; - init_waitqueue_head(&channel->queue); - spin_lock_init(&channel->lock); channel->pointer_read = 0; channel->pointer_write = 0; @@ -450,10 +441,6 @@ static int ipoctal_write_tty(struct tty_struct *tty, * operations */ iowrite8(CR_ENABLE_TX, &channel->regs->w.cr); - wait_event_interruptible(channel->queue, *channel->board_write); - iowrite8(CR_DISABLE_TX, &channel->regs->w.cr); - - *channel->board_write = 0; return char_copied; } -- cgit v1.2.3-59-g8ed1b From b5071f2cd89bfd88cc3c3a820cbb9e7d7d9b5c92 Mon Sep 17 00:00:00 2001 From: Samuel Iglesias Gonsalvez Date: Mon, 10 Dec 2012 11:50:01 +0100 Subject: ipack/devices/ipoctal: setup TTY_NORMAL flag for each character. In case of several characters present in RxFIFO, they will have the flag of the previous one, no matter if the actual character was received properly or not. This patch fixes this bug. Signed-off-by: Samuel Iglesias Gonsalvez Signed-off-by: Greg Kroah-Hartman --- drivers/ipack/devices/ipoctal.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/ipack/devices/ipoctal.c') diff --git a/drivers/ipack/devices/ipoctal.c b/drivers/ipack/devices/ipoctal.c index 18f9cf1ffe2b..850f10506a79 100644 --- a/drivers/ipack/devices/ipoctal.c +++ b/drivers/ipack/devices/ipoctal.c @@ -121,11 +121,12 @@ static void ipoctal_irq_rx(struct ipoctal_channel *channel, struct tty_struct *tty, u8 sr) { unsigned char value; - unsigned char flag = TTY_NORMAL; + unsigned char flag; u8 isr; do { value = ioread8(&channel->regs->r.rhr); + flag = TTY_NORMAL; /* Error: count statistics */ if (sr & SR_ERROR) { iowrite8(CR_CMD_RESET_ERR_STATUS, &channel->regs->w.cr); -- cgit v1.2.3-59-g8ed1b From 9d01b6f064c130028be8beb729ada7c39021b582 Mon Sep 17 00:00:00 2001 From: Samuel Iglesias Gonsalvez Date: Mon, 10 Dec 2012 11:50:02 +0100 Subject: ipack/devices/ipoctal: rework disable TX when the TX buffer is empty Depending of the device, it disables the TX mode in different places when there is no more data to transmit. This patch reorder them and disable the TX mode in the same place. Signed-off-by: Samuel Iglesias Gonsalvez Signed-off-by: Greg Kroah-Hartman --- drivers/ipack/devices/ipoctal.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) (limited to 'drivers/ipack/devices/ipoctal.c') diff --git a/drivers/ipack/devices/ipoctal.c b/drivers/ipack/devices/ipoctal.c index 850f10506a79..f2875f0f14d4 100644 --- a/drivers/ipack/devices/ipoctal.c +++ b/drivers/ipack/devices/ipoctal.c @@ -177,10 +177,6 @@ static void ipoctal_irq_tx(struct ipoctal_channel *channel) (*pointer_write)++; *pointer_write = *pointer_write % PAGE_SIZE; channel->nb_bytes--; - - if (channel->nb_bytes == 0 && - channel->board_id != IPACK1_DEVICE_ID_SBS_OCTAL_485) - iowrite8(CR_DISABLE_TX, &channel->regs->w.cr); } static void ipoctal_irq_channel(struct ipoctal_channel *channel) @@ -196,14 +192,14 @@ static void ipoctal_irq_channel(struct ipoctal_channel *channel) isr = ioread8(&channel->block_regs->r.isr); sr = ioread8(&channel->regs->r.sr); - /* In case of RS-485, change from TX to RX when finishing TX. - * Half-duplex. */ - if ((channel->board_id == IPACK1_DEVICE_ID_SBS_OCTAL_485) && - (sr & SR_TX_EMPTY) && (channel->nb_bytes == 0)) { - iowrite8(CR_DISABLE_TX, &channel->regs->w.cr); - iowrite8(CR_CMD_NEGATE_RTSN, &channel->regs->w.cr); - iowrite8(CR_ENABLE_RX, &channel->regs->w.cr); + if ((sr & SR_TX_EMPTY) && (channel->nb_bytes == 0)) { iowrite8(CR_DISABLE_TX, &channel->regs->w.cr); + /* In case of RS-485, change from TX to RX when finishing TX. + * Half-duplex. */ + if (channel->board_id == IPACK1_DEVICE_ID_SBS_OCTAL_485) { + iowrite8(CR_CMD_NEGATE_RTSN, &channel->regs->w.cr); + iowrite8(CR_ENABLE_RX, &channel->regs->w.cr); + } } /* RX data */ -- cgit v1.2.3-59-g8ed1b From a3882b7814fb3a5b7ea211e421451b1c4685f8f9 Mon Sep 17 00:00:00 2001 From: Samuel Iglesias Gonsalvez Date: Mon, 10 Dec 2012 11:50:03 +0100 Subject: ipack/devices/ipoctal: avoid re-enable RX two times. RX is enabled when the tty port is open, so no need to do it in initialization time: it can allow the device to receive characters but no TTY client is listening to them. It produced an infinite number of IRQ as RxFIFO is not read to clear that IRQ in the device, so it is still pending. Signed-off-by: Samuel Iglesias Gonsalvez Signed-off-by: Greg Kroah-Hartman --- drivers/ipack/devices/ipoctal.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/ipack/devices/ipoctal.c') diff --git a/drivers/ipack/devices/ipoctal.c b/drivers/ipack/devices/ipoctal.c index f2875f0f14d4..09e3a8e63e22 100644 --- a/drivers/ipack/devices/ipoctal.c +++ b/drivers/ipack/devices/ipoctal.c @@ -60,6 +60,10 @@ static int ipoctal_port_activate(struct tty_port *port, struct tty_struct *tty) channel = dev_get_drvdata(tty->dev); + /* + * Enable RX. TX will be enabled when + * there is something to send + */ iowrite8(CR_ENABLE_RX, &channel->regs->w.cr); return 0; } @@ -385,12 +389,6 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, continue; } dev_set_drvdata(tty_dev, channel); - - /* - * Enable again the RX. TX will be enabled when - * there is something to send - */ - iowrite8(CR_ENABLE_RX, &channel->regs->w.cr); } return 0; -- cgit v1.2.3-59-g8ed1b From 21d27ed4616c9a7f2886c4159b4c409f73f96e76 Mon Sep 17 00:00:00 2001 From: Samuel Iglesias Gonsalvez Date: Mon, 10 Dec 2012 11:50:04 +0100 Subject: ipack/devices/ipoctal: ack IRQ before processing it Due to the IRQ processing, we can generate another IRQ that can come before we end the previous one, so we lost it. E.g. when transmitting a character. To allow the processing in SMP machines, we ack the IRQ at the beginning of the IRQ handler. Signed-off-by: Samuel Iglesias Gonsalvez Signed-off-by: Greg Kroah-Hartman --- drivers/ipack/devices/ipoctal.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/ipack/devices/ipoctal.c') diff --git a/drivers/ipack/devices/ipoctal.c b/drivers/ipack/devices/ipoctal.c index 09e3a8e63e22..9cd5572457ff 100644 --- a/drivers/ipack/devices/ipoctal.c +++ b/drivers/ipack/devices/ipoctal.c @@ -223,14 +223,14 @@ static irqreturn_t ipoctal_irq_handler(void *arg) unsigned int i; struct ipoctal *ipoctal = (struct ipoctal *) arg; - /* Check all channels */ - for (i = 0; i < NR_CHANNELS; i++) - ipoctal_irq_channel(&ipoctal->channel[i]); - /* Clear the IPack device interrupt */ readw(ipoctal->int_space + ACK_INT_REQ0); readw(ipoctal->int_space + ACK_INT_REQ1); + /* Check all channels */ + for (i = 0; i < NR_CHANNELS; i++) + ipoctal_irq_channel(&ipoctal->channel[i]); + return IRQ_HANDLED; } -- cgit v1.2.3-59-g8ed1b From e7e664fd688a4a882ce571575ad721203f0cd584 Mon Sep 17 00:00:00 2001 From: Samuel Iglesias Gonsalvez Date: Mon, 10 Dec 2012 11:50:05 +0100 Subject: ipack/devices/ipoctal: protect the channel data processing with a spinlock We protect important data such as TX buffer pointer, nb_bytes counter and status registers of the device, from accessing several times at the same time. Signed-off-by: Samuel Iglesias Gonsalvez Signed-off-by: Greg Kroah-Hartman --- drivers/ipack/devices/ipoctal.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/ipack/devices/ipoctal.c') diff --git a/drivers/ipack/devices/ipoctal.c b/drivers/ipack/devices/ipoctal.c index 9cd5572457ff..5ce2c4c5bb32 100644 --- a/drivers/ipack/devices/ipoctal.c +++ b/drivers/ipack/devices/ipoctal.c @@ -191,6 +191,8 @@ static void ipoctal_irq_channel(struct ipoctal_channel *channel) tty = tty_port_tty_get(&channel->tty_port); if (!tty) return; + + spin_lock(&channel->lock); /* The HW is organized in pair of channels. See which register we need * to read from */ isr = ioread8(&channel->block_regs->r.isr); @@ -216,6 +218,7 @@ static void ipoctal_irq_channel(struct ipoctal_channel *channel) tty_flip_buffer_push(tty); tty_kref_put(tty); + spin_unlock(&channel->lock); } static irqreturn_t ipoctal_irq_handler(void *arg) -- cgit v1.2.3-59-g8ed1b From b06073f963b7b00a628e58e87d02028e2c9e430d Mon Sep 17 00:00:00 2001 From: Samuel Iglesias Gonsalvez Date: Mon, 10 Dec 2012 11:50:06 +0100 Subject: ipack/devices/ipoctal: remove redundant tty_flip_buffer_push() The function is already called in ipoctal_irq_rx() Signed-off-by: Samuel Iglesias Gonsalvez Signed-off-by: Greg Kroah-Hartman --- drivers/ipack/devices/ipoctal.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/ipack/devices/ipoctal.c') diff --git a/drivers/ipack/devices/ipoctal.c b/drivers/ipack/devices/ipoctal.c index 5ce2c4c5bb32..34fcfce0cdd9 100644 --- a/drivers/ipack/devices/ipoctal.c +++ b/drivers/ipack/devices/ipoctal.c @@ -216,7 +216,6 @@ static void ipoctal_irq_channel(struct ipoctal_channel *channel) if ((isr & channel->isr_tx_rdy_mask) && (sr & SR_TX_READY)) ipoctal_irq_tx(channel); - tty_flip_buffer_push(tty); tty_kref_put(tty); spin_unlock(&channel->lock); } -- cgit v1.2.3-59-g8ed1b From b0d17fbdacb32f9f4b9ee1ad2b8f42f6a480d842 Mon Sep 17 00:00:00 2001 From: Samuel Iglesias Gonsalvez Date: Mon, 10 Dec 2012 11:50:07 +0100 Subject: ipack/devices/ipoctal: add rx_enable flag Thus, we don't enable RX when a termios setup has been called, as it could be disabled previously. As the control registers (Rx, Tx flags specifically) cannot be read from the device, we keep this info in rx_enable. Signed-off-by: Samuel Iglesias Gonsalvez Signed-off-by: Greg Kroah-Hartman --- drivers/ipack/devices/ipoctal.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/ipack/devices/ipoctal.c') diff --git a/drivers/ipack/devices/ipoctal.c b/drivers/ipack/devices/ipoctal.c index 34fcfce0cdd9..8666d2d05eef 100644 --- a/drivers/ipack/devices/ipoctal.c +++ b/drivers/ipack/devices/ipoctal.c @@ -43,6 +43,7 @@ struct ipoctal_channel { unsigned int board_id; u8 isr_rx_rdy_mask; u8 isr_tx_rdy_mask; + unsigned int rx_enable; }; struct ipoctal { @@ -65,6 +66,7 @@ static int ipoctal_port_activate(struct tty_port *port, struct tty_struct *tty) * there is something to send */ iowrite8(CR_ENABLE_RX, &channel->regs->w.cr); + channel->rx_enable = 1; return 0; } @@ -309,6 +311,7 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, } iowrite8(CR_DISABLE_RX | CR_DISABLE_TX, &channel->regs->w.cr); + channel->rx_enable = 0; iowrite8(CR_CMD_RESET_RX, &channel->regs->w.cr); iowrite8(CR_CMD_RESET_TX, &channel->regs->w.cr); iowrite8(MR1_CHRL_8_BITS | MR1_ERROR_CHAR | MR1_RxINT_RxRDY, @@ -430,6 +433,7 @@ static int ipoctal_write_tty(struct tty_struct *tty, /* As the IP-OCTAL 485 only supports half duplex, do it manually */ if (channel->board_id == IPACK1_DEVICE_ID_SBS_OCTAL_485) { iowrite8(CR_DISABLE_RX, &channel->regs->w.cr); + channel->rx_enable = 0; iowrite8(CR_CMD_ASSERT_RTSN, &channel->regs->w.cr); } @@ -589,8 +593,9 @@ static void ipoctal_set_termios(struct tty_struct *tty, iowrite8(mr2, &channel->regs->w.mr); iowrite8(csr, &channel->regs->w.csr); - /* Enable again the RX */ - iowrite8(CR_ENABLE_RX, &channel->regs->w.cr); + /* Enable again the RX, if it was before */ + if (channel->rx_enable) + iowrite8(CR_ENABLE_RX, &channel->regs->w.cr); } static void ipoctal_hangup(struct tty_struct *tty) @@ -610,6 +615,7 @@ static void ipoctal_hangup(struct tty_struct *tty) tty_port_hangup(&channel->tty_port); iowrite8(CR_DISABLE_RX | CR_DISABLE_TX, &channel->regs->w.cr); + channel->rx_enable = 0; iowrite8(CR_CMD_RESET_RX, &channel->regs->w.cr); iowrite8(CR_CMD_RESET_TX, &channel->regs->w.cr); iowrite8(CR_CMD_RESET_ERR_STATUS, &channel->regs->w.cr); -- cgit v1.2.3-59-g8ed1b From e0f8d323f34dee3f47388dc3d87e7c428b077a0d Mon Sep 17 00:00:00 2001 From: Samuel Iglesias Gonsalvez Date: Mon, 10 Dec 2012 11:50:08 +0100 Subject: ipack/devices/ipoctal: added shutdown callback Added shutdown callback to disable RX and TX when there is no other client accesing the device. Signed-off-by: Samuel Iglesias Gonsalvez Signed-off-by: Greg Kroah-Hartman --- drivers/ipack/devices/ipoctal.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'drivers/ipack/devices/ipoctal.c') diff --git a/drivers/ipack/devices/ipoctal.c b/drivers/ipack/devices/ipoctal.c index 8666d2d05eef..0b3c4b8fe830 100644 --- a/drivers/ipack/devices/ipoctal.c +++ b/drivers/ipack/devices/ipoctal.c @@ -625,6 +625,22 @@ static void ipoctal_hangup(struct tty_struct *tty) wake_up_interruptible(&channel->tty_port.open_wait); } +static void ipoctal_shutdown(struct tty_struct *tty) +{ + struct ipoctal_channel *channel = tty->driver_data; + + if (channel == NULL) + return; + + iowrite8(CR_DISABLE_RX | CR_DISABLE_TX, &channel->regs->w.cr); + channel->rx_enable = 0; + iowrite8(CR_CMD_RESET_RX, &channel->regs->w.cr); + iowrite8(CR_CMD_RESET_TX, &channel->regs->w.cr); + iowrite8(CR_CMD_RESET_ERR_STATUS, &channel->regs->w.cr); + iowrite8(CR_CMD_RESET_MR, &channel->regs->w.cr); + clear_bit(ASYNCB_INITIALIZED, &channel->tty_port.flags); +} + static const struct tty_operations ipoctal_fops = { .ioctl = NULL, .open = ipoctal_open, @@ -635,6 +651,7 @@ static const struct tty_operations ipoctal_fops = { .chars_in_buffer = ipoctal_chars_in_buffer, .get_icount = ipoctal_get_icount, .hangup = ipoctal_hangup, + .shutdown = ipoctal_shutdown, }; static int ipoctal_probe(struct ipack_device *dev) -- cgit v1.2.3-59-g8ed1b From 2910fe2a7d0dc0d01944110e462045441ba0856f Mon Sep 17 00:00:00 2001 From: Samuel Iglesias Gonsalvez Date: Fri, 18 Jan 2013 08:57:21 +0100 Subject: ipack/devices/ipoctal: add missing rx_enable = 1 There was a bug in the code when managing a GE IP-OCTAL-485 board. The RX would be enabled but we have a wrong state in the rx_enable flag. Then, if the user changes the terminal settings, RX would not be enabled again. Signed-off-by: Samuel Iglesias Gonsalvez Signed-off-by: Greg Kroah-Hartman --- drivers/ipack/devices/ipoctal.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/ipack/devices/ipoctal.c') diff --git a/drivers/ipack/devices/ipoctal.c b/drivers/ipack/devices/ipoctal.c index 0b3c4b8fe830..93cbf9dda1fe 100644 --- a/drivers/ipack/devices/ipoctal.c +++ b/drivers/ipack/devices/ipoctal.c @@ -207,6 +207,7 @@ static void ipoctal_irq_channel(struct ipoctal_channel *channel) if (channel->board_id == IPACK1_DEVICE_ID_SBS_OCTAL_485) { iowrite8(CR_CMD_NEGATE_RTSN, &channel->regs->w.cr); iowrite8(CR_ENABLE_RX, &channel->regs->w.cr); + channel->rx_enable = 1; } } -- cgit v1.2.3-59-g8ed1b From fc8d713ecd01acb312afed8c560130ea7284c6db Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 21 Jan 2013 14:02:53 +0100 Subject: drivers/ipack/devices/ipoctal.c: adjust duplicate test Delete successive tests to the same location. The code tested the result of a previous allocation, that itself was already tested. It is changed to test the result of the most recent allocation. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @s exists@ local idexpression y; expression x,e; @@ *if ( \(x == NULL\|IS_ERR(x)\|y != 0\) ) { ... when forall return ...; } ... when != \(y = e\|y += e\|y -= e\|y |= e\|y &= e\|y++\|y--\|&y\) when != \(XT_GETPAGE(...,y)\|WMI_CMD_BUF(...)\) *if ( \(x == NULL\|IS_ERR(x)\|y != 0\) ) { ... when forall return ...; } // Signed-off-by: Julia Lawall Cc: Samuel Iglesias Gonsalvez Signed-off-by: Greg Kroah-Hartman --- drivers/ipack/devices/ipoctal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/ipack/devices/ipoctal.c') diff --git a/drivers/ipack/devices/ipoctal.c b/drivers/ipack/devices/ipoctal.c index 93cbf9dda1fe..a2cf0f240929 100644 --- a/drivers/ipack/devices/ipoctal.c +++ b/drivers/ipack/devices/ipoctal.c @@ -289,7 +289,7 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, ipoctal->mem8_space = devm_ioremap_nocache(&ipoctal->dev->dev, region->start, 0x8000); - if (!addr) { + if (!ipoctal->mem8_space) { dev_err(&ipoctal->dev->dev, "Unable to map slot [%d:%d] MEM8 space!\n", bus_nr, slot); -- cgit v1.2.3-59-g8ed1b