mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* A general question on SMP-safe driver code.
@ 2004-12-24 22:58 Jim Nelson
  2004-12-24 23:28 ` Linus Torvalds
  2004-12-25 12:23 ` Alan Cox
  0 siblings, 2 replies; 3+ messages in thread
From: Jim Nelson @ 2004-12-24 22:58 UTC (permalink / raw)
  To: linux-kernel

Looking at a few older drivers, I'm trying to figure out the best ways to handle 
some locking.  Using drivers/char/esp.c as an example (since it's the one I'm 
trying to grok right now), here is one example:

static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
{
	struct esp_struct *info = (struct esp_struct *)tty->driver_data;
	unsigned long orig_jiffies, char_time;
	unsigned long flags;

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

	orig_jiffies = jiffies;
	char_time = ((info->timeout - HZ / 50) / 1024) / 5;

	if (!char_time)
		char_time = 1;

	save_flags(flags); cli();
	serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND);
	serial_out(info, UART_ESI_CMD1, ESI_GET_TX_AVAIL);

	while ((serial_in(info, UART_ESI_STAT1) != 0x03) ||
		(serial_in(info, UART_ESI_STAT2) != 0xff)) {
		msleep_interruptible(jiffies_to_msecs(char_time));

		if (signal_pending(current))
			break;

		if (timeout && time_after(jiffies, orig_jiffies + timeout))
			break;

		serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND);
		serial_out(info, UART_ESI_CMD1, ESI_GET_TX_AVAIL);
	}
	
	restore_flags(flags);
	set_current_state(TASK_RUNNING);
}

Now, it seems like the cli()/sti() pair is to prevent other code from interrupting 
the whole sequence.  It looks like the only things actually need interrupts 
disabled (from a command sequencing perspective) is the serial_out pairs, but you 
want to keep other parts of the driver from sending other commands to the board.

So, would:

	down_interruptible(&info->sem);
	spin_lock_irq(&info->esp_lock);
	serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND);
	serial_out(info, UART_ESI_CMD1, ESI_GET_TX_AVAIL);
	spin_unlock_irq(&info->esp_lock);

	while ((serial_in(info, UART_ESI_STAT1) != 0x03) ||
		(serial_in(info, UART_ESI_STAT2) != 0xff)) {
		msleep_interruptible(jiffies_to_msecs(char_time));

		if (signal_pending(current))
			break;

		if (timeout && time_after(jiffies, orig_jiffies + timeout))
			break;

		spin_lock_irq(&info->esp_lock);
		serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND);
		serial_out(info, UART_ESI_CMD1, ESI_GET_TX_AVAIL);
		spin_unlock_irq(&info->esp_lock);
	up(&info->esp_sem);

work if all other areas of the driver that send commands to the board also try for 
the semaphore?

Is there an easier way of doing this?

Jim

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2004-12-25 13:29 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-12-24 22:58 A general question on SMP-safe driver code Jim Nelson
2004-12-24 23:28 ` Linus Torvalds
2004-12-25 12:23 ` Alan Cox

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

Powered by JetHome