Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 87cfb955 authored by Jens Taprogge's avatar Jens Taprogge Committed by Greg Kroah-Hartman
Browse files

Staging: ipack/devices/ipoctal: Split interrupt service routine.



Split the IRQ service routing in TX part and RX part.

Signed-off-by: default avatarJens Taprogge <jens.taprogge@taprogge.org>
Signed-off-by: default avatarSamuel Iglesias Gonsalvez <siglesias@igalia.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 4e4732ac
Loading
Loading
Loading
Loading
+97 −91
Original line number Diff line number Diff line
@@ -163,52 +163,11 @@ static int ipoctal_get_icount(struct tty_struct *tty,
	return 0;
}

static int ipoctal_irq_handler(void *arg)
static void ipoctal_irq_rx(struct ipoctal_channel *channel,
			   struct tty_struct *tty, u8 sr)
{
	unsigned int ichannel;
	unsigned char isr;
	unsigned char sr;
	unsigned char value;
	unsigned char flag;
	struct tty_struct *tty;
	struct ipoctal *ipoctal = (struct ipoctal *) arg;
	struct ipoctal_channel *channel;

	/* Check all channels */
	for (ichannel = 0; ichannel < NR_CHANNELS; ichannel++) {
		channel = &ipoctal->channel[ichannel];
		/* If there is no client, skip the check */
		if (!atomic_read(&channel->open))
			continue;

		tty = tty_port_tty_get(&channel->tty_port);
		if (!tty)
			continue;

		/*
		 * The HW is organized in pair of channels.
		 * See which register we need to read from
		 */
		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 ((ipoctal->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);
			ipoctal->write = 1;
			wake_up_interruptible(&channel->queue);
		}

		/* RX data */
		if ((isr && channel->isr_rx_rdy_mask) && (sr & SR_RX_READY)) {
			value = ioread8(&channel->regs->r.rhr);
			flag = TTY_NORMAL;
	unsigned char value = ioread8(&channel->regs->r.rhr);
	unsigned char flag = TTY_NORMAL;

	/* Error: count statistics */
	if (sr & SR_ERROR) {
@@ -236,13 +195,14 @@ static int ipoctal_irq_handler(void *arg)
	tty_insert_flip_char(tty, value, flag);
}

		/* TX of each character */
		if ((isr & channel->isr_tx_rdy_mask) && (sr & SR_TX_READY)) {
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;
				continue;
		return;
	}

	value = channel->tty_port.xmit_buf[*pointer_write];
@@ -256,16 +216,62 @@ static int ipoctal_irq_handler(void *arg)
	if ((channel->nb_bytes == 0) &&
	    (waitqueue_active(&channel->queue))) {

				if (ipoctal->board_id != IPACK1_DEVICE_ID_SBS_OCTAL_485) {
					ipoctal->write = 1;
		if (channel->board_id != IPACK1_DEVICE_ID_SBS_OCTAL_485) {
			*channel->board_write = 1;
			wake_up_interruptible(&channel->queue);
		}
	}
}

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;
	/* The HW is organized in pair of channels.  See which register we need
	 * to read from */
	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);
		*channel->board_write = 1;
		wake_up_interruptible(&channel->queue);
	}

	/* RX data */
	if ((isr & channel->isr_rx_rdy_mask) && (sr & SR_RX_READY))
		ipoctal_irq_rx(channel, tty, sr);

	/* TX of each character */
	if ((isr & channel->isr_tx_rdy_mask) && (sr & SR_TX_READY))
		ipoctal_irq_tx(channel);

	tty_flip_buffer_push(tty);
	tty_kref_put(tty);
}

static int 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]);

	return IRQ_HANDLED;
}