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

Commit 978e595f authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds
Browse files

tty/serial: lay the foundations for the next set of reworks



- Stop drivers calling their own flush method indirectly, it obfuscates code
  and it will change soon anyway

- A few more lock_kernel paths temporarily needed in some driver internal
  waiting code

- Remove private put_char method that does a write call for one char - we
  have that anyway

- Most but not yet all of the termios copy under lock fixing (some has other
  dependencies to follow)

- Note a few locking bugs in drivers found in the process

- Kill remaining [ab]users of TIOCG/SSOFTCAR in the driver, these must go to
  fix the termios locking

Signed-off-by: default avatarAlan Cox <alan@redhat.com>
Cc: Jiri Slaby <jirislaby@gmail.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent ac0e4b7d
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -1505,8 +1505,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
		rs_wait_until_sent(tty, info->timeout);
	}
	shutdown(info);
	if (tty->driver->flush_buffer)
		tty->driver->flush_buffer(tty);
	rs_flush_buffer(tty);
		
	tty_ldisc_flush(tty);
	tty->closing = 0;
@@ -1539,6 +1538,8 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
		return; /* Just in case.... */

	orig_jiffies = jiffies;

	lock_kernel();
	/*
	 * Set the check interval to be 1/5 of the estimated time to
	 * send a single character, and make it at least 1.  The check
@@ -1579,6 +1580,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
			break;
	}
	__set_current_state(TASK_RUNNING);
	unlock_kernel();
#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
	printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
#endif
+40 −36
Original line number Diff line number Diff line
@@ -2522,6 +2522,7 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout)
		return;		/* Just in case.... */

	orig_jiffies = jiffies;
	lock_kernel();
	/*
	 * Set the check interval to be 1/5 of the estimated time to
	 * send a single character, and make it at least 1.  The check
@@ -2573,11 +2574,47 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout)
	}
	/* Run one more char cycle */
	msleep_interruptible(jiffies_to_msecs(char_time * 5));
	unlock_kernel();
#ifdef CY_DEBUG_WAIT_UNTIL_SENT
	printk(KERN_DEBUG "Clean (jiff=%lu)...done\n", jiffies);
#endif
}

static void cy_flush_buffer(struct tty_struct *tty)
{
	struct cyclades_port *info = tty->driver_data;
	struct cyclades_card *card;
	int channel, retval;
	unsigned long flags;

#ifdef CY_DEBUG_IO
	printk(KERN_DEBUG "cyc:cy_flush_buffer ttyC%d\n", info->line);
#endif

	if (serial_paranoia_check(info, tty->name, "cy_flush_buffer"))
		return;

	card = info->card;
	channel = info->line - card->first_line;

	spin_lock_irqsave(&card->card_lock, flags);
	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
	spin_unlock_irqrestore(&card->card_lock, flags);

	if (IS_CYC_Z(*card)) {	/* If it is a Z card, flush the on-board
					   buffers as well */
		spin_lock_irqsave(&card->card_lock, flags);
		retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_TX, 0L);
		if (retval != 0) {
			printk(KERN_ERR "cyc: flush_buffer retval on ttyC%d "
				"was %x\n", info->line, retval);
		}
		spin_unlock_irqrestore(&card->card_lock, flags);
	}
	tty_wakeup(tty);
}				/* cy_flush_buffer */


/*
 * This routine is called when a particular tty device is closed.
 */
@@ -2689,8 +2726,7 @@ static void cy_close(struct tty_struct *tty, struct file *filp)

	spin_unlock_irqrestore(&card->card_lock, flags);
	shutdown(info);
	if (tty->driver->flush_buffer)
		tty->driver->flush_buffer(tty);
	cy_flush_buffer(tty);
	tty_ldisc_flush(tty);
	spin_lock_irqsave(&card->card_lock, flags);

@@ -2881,6 +2917,7 @@ static int cy_chars_in_buffer(struct tty_struct *tty)
		int char_count;
		__u32 tx_put, tx_get, tx_bufsize;

		lock_kernel();
		firm_id = card->base_addr + ID_ADDRESS;
		zfw_ctrl = card->base_addr +
			(readl(&firm_id->zfwctrl_addr) & 0xfffff);
@@ -2898,6 +2935,7 @@ static int cy_chars_in_buffer(struct tty_struct *tty)
		printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n",
			info->line, info->xmit_cnt + char_count);
#endif
		unlock_kernel();
		return info->xmit_cnt + char_count;
	}
#endif				/* Z_EXT_CHARS_IN_BUFFER */
@@ -4271,40 +4309,6 @@ static void cy_start(struct tty_struct *tty)
	}
}				/* cy_start */

static void cy_flush_buffer(struct tty_struct *tty)
{
	struct cyclades_port *info = tty->driver_data;
	struct cyclades_card *card;
	int channel, retval;
	unsigned long flags;

#ifdef CY_DEBUG_IO
	printk(KERN_DEBUG "cyc:cy_flush_buffer ttyC%d\n", info->line);
#endif

	if (serial_paranoia_check(info, tty->name, "cy_flush_buffer"))
		return;

	card = info->card;
	channel = info->line - card->first_line;

	spin_lock_irqsave(&card->card_lock, flags);
	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
	spin_unlock_irqrestore(&card->card_lock, flags);

	if (IS_CYC_Z(*card)) {	/* If it is a Z card, flush the on-board
					   buffers as well */
		spin_lock_irqsave(&card->card_lock, flags);
		retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_TX, 0L);
		if (retval != 0) {
			printk(KERN_ERR "cyc: flush_buffer retval on ttyC%d "
				"was %x\n", info->line, retval);
		}
		spin_unlock_irqrestore(&card->card_lock, flags);
	}
	tty_wakeup(tty);
}				/* cy_flush_buffer */

/*
 * cy_hangup() --- called by tty_hangup() when a hangup is signaled.
 */
+2 −11
Original line number Diff line number Diff line
@@ -157,7 +157,6 @@ static void epca_error(int, char *);
static void pc_close(struct tty_struct *, struct file *);
static void shutdown(struct channel *);
static void pc_hangup(struct tty_struct *);
static void pc_put_char(struct tty_struct *, unsigned char);
static int pc_write_room(struct tty_struct *);
static int pc_chars_in_buffer(struct tty_struct *);
static void pc_flush_buffer(struct tty_struct *);
@@ -459,8 +458,7 @@ static void pc_close(struct tty_struct *tty, struct file *filp)
			setup_empty_event(tty, ch);
			tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */
		}
		if (tty->driver->flush_buffer)
			tty->driver->flush_buffer(tty);
		pc_flush_buffer(tty);

		tty_ldisc_flush(tty);
		shutdown(ch);
@@ -532,8 +530,7 @@ static void pc_hangup(struct tty_struct *tty)
	if ((ch = verifyChannel(tty)) != NULL) {
		unsigned long flags;

		if (tty->driver->flush_buffer)
			tty->driver->flush_buffer(tty);
		pc_flush_buffer(tty);
		tty_ldisc_flush(tty);
		shutdown(ch);

@@ -645,11 +642,6 @@ static int pc_write(struct tty_struct *tty,
	return amountCopied;
}

static void pc_put_char(struct tty_struct *tty, unsigned char c)
{
	pc_write(tty, &c, 1);
}

static int pc_write_room(struct tty_struct *tty)
{
	int remain;
@@ -1035,7 +1027,6 @@ static const struct tty_operations pc_ops = {
	.flush_buffer = pc_flush_buffer,
	.chars_in_buffer = pc_chars_in_buffer,
	.flush_chars = pc_flush_chars,
	.put_char = pc_put_char,
	.ioctl = pc_ioctl,
	.set_termios = pc_set_termios,
	.stop = pc_stop,
+1 −2
Original line number Diff line number Diff line
@@ -1994,8 +1994,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
		rs_wait_until_sent(tty, info->timeout);
	}
	shutdown(info);
	if (tty->driver->flush_buffer)
		tty->driver->flush_buffer(tty);
	rs_flush_buffer(tty);
	tty_ldisc_flush(tty);
	tty->closing = 0;
	info->tty = NULL;
+1 −2
Original line number Diff line number Diff line
@@ -586,8 +586,7 @@ void gs_close(struct tty_struct * tty, struct file * filp)

	port->flags &= ~GS_ACTIVE;

	if (tty->driver->flush_buffer)
		tty->driver->flush_buffer(tty);
	gs_flush_buffer(tty);

	tty_ldisc_flush(tty);
	tty->closing = 0;
Loading