diff options
62 files changed, 1742 insertions, 2636 deletions
| diff --git a/Documentation/devicetree/bindings/tty/serial/nxp-lpc32xx-hsuart.txt b/Documentation/devicetree/bindings/tty/serial/nxp-lpc32xx-hsuart.txt new file mode 100644 index 000000000000..0d439dfc1aa5 --- /dev/null +++ b/Documentation/devicetree/bindings/tty/serial/nxp-lpc32xx-hsuart.txt @@ -0,0 +1,14 @@ +* NXP LPC32xx SoC High Speed UART + +Required properties: +- compatible: Should be "nxp,lpc3220-hsuart" +- reg: Should contain registers location and length +- interrupts: Should contain interrupt + +Example: + +	uart1: serial@40014000 { +		compatible = "nxp,lpc3220-hsuart"; +		reg = <0x40014000 0x1000>; +		interrupts = <26 0>; +	}; diff --git a/Documentation/devicetree/bindings/tty/serial/of-serial.txt b/Documentation/devicetree/bindings/tty/serial/of-serial.txt index b8b27b0aca10..0847fdeee11a 100644 --- a/Documentation/devicetree/bindings/tty/serial/of-serial.txt +++ b/Documentation/devicetree/bindings/tty/serial/of-serial.txt @@ -9,6 +9,7 @@ Required properties:  	- "ns16750"  	- "ns16850"  	- "nvidia,tegra20-uart" +	- "nxp,lpc3220-uart"  	- "ibm,qpace-nwp-serial"  	- "serial" if the port type is unknown.  - reg : offset and length of the register set for the device. diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c index 45e248c2f43c..87eebfe03c61 100644 --- a/arch/um/drivers/chan_kern.c +++ b/arch/um/drivers/chan_kern.c @@ -150,9 +150,11 @@ void chan_enable_winch(struct chan *chan, struct tty_struct *tty)  static void line_timer_cb(struct work_struct *work)  {  	struct line *line = container_of(work, struct line, task.work); +	struct tty_struct *tty = tty_port_tty_get(&line->port);  	if (!line->throttled) -		chan_interrupt(line, line->tty, line->driver->read_irq); +		chan_interrupt(line, tty, line->driver->read_irq); +	tty_kref_put(tty);  }  int enable_chan(struct line *line) diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index acfd0e0fd0c9..fb6e4ea09921 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -19,9 +19,11 @@ static irqreturn_t line_interrupt(int irq, void *data)  {  	struct chan *chan = data;  	struct line *line = chan->line; +	struct tty_struct *tty = tty_port_tty_get(&line->port);  	if (line) -		chan_interrupt(line, line->tty, irq); +		chan_interrupt(line, tty, irq); +	tty_kref_put(tty);  	return IRQ_HANDLED;  } @@ -333,7 +335,7 @@ static irqreturn_t line_write_interrupt(int irq, void *data)  {  	struct chan *chan = data;  	struct line *line = chan->line; -	struct tty_struct *tty = line->tty; +	struct tty_struct *tty;  	int err;  	/* @@ -352,10 +354,13 @@ static irqreturn_t line_write_interrupt(int irq, void *data)  	}  	spin_unlock(&line->lock); +	tty = tty_port_tty_get(&line->port);  	if (tty == NULL)  		return IRQ_NONE;  	tty_wakeup(tty); +	tty_kref_put(tty); +  	return IRQ_HANDLED;  } @@ -404,12 +409,12 @@ int line_open(struct line *lines, struct tty_struct *tty)  		goto out_unlock;  	err = 0; -	if (line->count++) +	if (line->port.count++)  		goto out_unlock;  	BUG_ON(tty->driver_data);  	tty->driver_data = line; -	line->tty = tty; +	tty_port_tty_set(&line->port, tty);  	err = enable_chan(line);  	if (err) /* line_close() will be called by our caller */ @@ -446,10 +451,10 @@ void line_close(struct tty_struct *tty, struct file * filp)  	mutex_lock(&line->count_lock);  	BUG_ON(!line->valid); -	if (--line->count) +	if (--line->port.count)  		goto out_unlock; -	line->tty = NULL; +	tty_port_tty_set(&line->port, NULL);  	tty->driver_data = NULL;  	if (line->sigio) { @@ -478,7 +483,7 @@ int setup_one_line(struct line *lines, int n, char *init,  	mutex_lock(&line->count_lock); -	if (line->count) { +	if (line->port.count) {  		*error_out = "Device is already open";  		goto out;  	} @@ -610,9 +615,15 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str,  	mutex_lock(&line->count_lock);  	if (!line->valid)  		CONFIG_CHUNK(str, size, n, "none", 1); -	else if (line->tty == NULL) -		CONFIG_CHUNK(str, size, n, line->init_str, 1); -	else n = chan_config_string(line, str, size, error_out); +	else { +		struct tty_struct *tty = tty_port_tty_get(&line->port); +		if (tty == NULL) { +			CONFIG_CHUNK(str, size, n, line->init_str, 1); +		} else { +			n = chan_config_string(line, str, size, error_out); +			tty_kref_put(tty); +		} +	}  	mutex_unlock(&line->count_lock);  	return n; @@ -663,6 +674,7 @@ int register_lines(struct line_driver *line_driver,  	driver->init_termios = tty_std_termios;  	for (i = 0; i < nlines; i++) { +		tty_port_init(&lines[i].port);  		spin_lock_init(&lines[i].lock);  		mutex_init(&lines[i].count_lock);  		lines[i].driver = line_driver; diff --git a/arch/um/drivers/line.h b/arch/um/drivers/line.h index 0a1834719dba..5b3d4fbdec18 100644 --- a/arch/um/drivers/line.h +++ b/arch/um/drivers/line.h @@ -32,9 +32,8 @@ struct line_driver {  };  struct line { -	struct tty_struct *tty; +	struct tty_port port;  	struct mutex count_lock; -	unsigned long count;  	int valid;  	char *init_str; diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c index 6cc4358f68c1..35819e312624 100644 --- a/drivers/tty/amiserial.c +++ b/drivers/tty/amiserial.c @@ -1033,7 +1033,7 @@ static int get_serial_info(struct tty_struct *tty, struct serial_state *state,  	if (!retinfo)  		return -EFAULT;  	memset(&tmp, 0, sizeof(tmp)); -	tty_lock(); +	tty_lock(tty);  	tmp.line = tty->index;  	tmp.port = state->port;  	tmp.flags = state->tport.flags; @@ -1042,7 +1042,7 @@ static int get_serial_info(struct tty_struct *tty, struct serial_state *state,  	tmp.close_delay = state->tport.close_delay;  	tmp.closing_wait = state->tport.closing_wait;  	tmp.custom_divisor = state->custom_divisor; -	tty_unlock(); +	tty_unlock(tty);  	if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))  		return -EFAULT;  	return 0; @@ -1059,12 +1059,12 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state,  	if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))  		return -EFAULT; -	tty_lock(); +	tty_lock(tty);  	change_spd = ((new_serial.flags ^ port->flags) & ASYNC_SPD_MASK) ||  		new_serial.custom_divisor != state->custom_divisor;  	if (new_serial.irq || new_serial.port != state->port ||  			new_serial.xmit_fifo_size != state->xmit_fifo_size) { -		tty_unlock(); +		tty_unlock(tty);  		return -EINVAL;  	} @@ -1074,7 +1074,7 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state,  		    (new_serial.xmit_fifo_size != state->xmit_fifo_size) ||  		    ((new_serial.flags & ~ASYNC_USR_MASK) !=  		     (port->flags & ~ASYNC_USR_MASK))) { -			tty_unlock(); +			tty_unlock(tty);  			return -EPERM;  		}  		port->flags = ((port->flags & ~ASYNC_USR_MASK) | @@ -1084,7 +1084,7 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state,  	}  	if (new_serial.baud_base < 9600) { -		tty_unlock(); +		tty_unlock(tty);  		return -EINVAL;  	} @@ -1116,7 +1116,7 @@ check_and_exit:  		}  	} else  		retval = startup(tty, state); -	tty_unlock(); +	tty_unlock(tty);  	return retval;  } diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c index e61cabdd69df..69e9ca2dd4b3 100644 --- a/drivers/tty/cyclades.c +++ b/drivers/tty/cyclades.c @@ -1599,7 +1599,7 @@ static int cy_open(struct tty_struct *tty, struct file *filp)  	 * If the port is the middle of closing, bail out now  	 */  	if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) { -		wait_event_interruptible_tty(info->port.close_wait, +		wait_event_interruptible_tty(tty, info->port.close_wait,  				!(info->port.flags & ASYNC_CLOSING));  		return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;  	} @@ -3289,6 +3289,7 @@ static unsigned short __devinit cyy_init_card(void __iomem *true_base_addr,  static int __init cy_detect_isa(void)  {  #ifdef CONFIG_ISA +	struct cyclades_card *card;  	unsigned short cy_isa_irq, nboard;  	void __iomem *cy_isa_address;  	unsigned short i, j, cy_isa_nchan; @@ -3349,7 +3350,8 @@ static int __init cy_detect_isa(void)  		}  		/* fill the next cy_card structure available */  		for (j = 0; j < NR_CARDS; j++) { -			if (cy_card[j].base_addr == NULL) +			card = &cy_card[j]; +			if (card->base_addr == NULL)  				break;  		}  		if (j == NR_CARDS) {	/* no more cy_cards available */ @@ -3363,7 +3365,7 @@ static int __init cy_detect_isa(void)  		/* allocate IRQ */  		if (request_irq(cy_isa_irq, cyy_interrupt, -				0, "Cyclom-Y", &cy_card[j])) { +				0, "Cyclom-Y", card)) {  			printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but "  				"could not allocate IRQ#%d.\n",  				(unsigned long)cy_isa_address, cy_isa_irq); @@ -3372,16 +3374,16 @@ static int __init cy_detect_isa(void)  		}  		/* set cy_card */ -		cy_card[j].base_addr = cy_isa_address; -		cy_card[j].ctl_addr.p9050 = NULL; -		cy_card[j].irq = (int)cy_isa_irq; -		cy_card[j].bus_index = 0; -		cy_card[j].first_line = cy_next_channel; -		cy_card[j].num_chips = cy_isa_nchan / CyPORTS_PER_CHIP; -		cy_card[j].nports = cy_isa_nchan; -		if (cy_init_card(&cy_card[j])) { -			cy_card[j].base_addr = NULL; -			free_irq(cy_isa_irq, &cy_card[j]); +		card->base_addr = cy_isa_address; +		card->ctl_addr.p9050 = NULL; +		card->irq = (int)cy_isa_irq; +		card->bus_index = 0; +		card->first_line = cy_next_channel; +		card->num_chips = cy_isa_nchan / CyPORTS_PER_CHIP; +		card->nports = cy_isa_nchan; +		if (cy_init_card(card)) { +			card->base_addr = NULL; +			free_irq(cy_isa_irq, card);  			iounmap(cy_isa_address);  			continue;  		} @@ -3695,6 +3697,7 @@ err:  static int __devinit cy_pci_probe(struct pci_dev *pdev,  		const struct pci_device_id *ent)  { +	struct cyclades_card *card;  	void __iomem *addr0 = NULL, *addr2 = NULL;  	char *card_name = NULL;  	u32 uninitialized_var(mailbox); @@ -3829,7 +3832,8 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,  	}  	/* fill the next cy_card structure available */  	for (card_no = 0; card_no < NR_CARDS; card_no++) { -		if (cy_card[card_no].base_addr == NULL) +		card = &cy_card[card_no]; +		if (card->base_addr == NULL)  			break;  	}  	if (card_no == NR_CARDS) {	/* no more cy_cards available */ @@ -3843,27 +3847,26 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,  			device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) {  		/* allocate IRQ */  		retval = request_irq(irq, cyy_interrupt, -				IRQF_SHARED, "Cyclom-Y", &cy_card[card_no]); +				IRQF_SHARED, "Cyclom-Y", card);  		if (retval) {  			dev_err(&pdev->dev, "could not allocate IRQ\n");  			goto err_unmap;  		} -		cy_card[card_no].num_chips = nchan / CyPORTS_PER_CHIP; +		card->num_chips = nchan / CyPORTS_PER_CHIP;  	} else {  		struct FIRM_ID __iomem *firm_id = addr2 + ID_ADDRESS;  		struct ZFW_CTRL __iomem *zfw_ctrl;  		zfw_ctrl = addr2 + (readl(&firm_id->zfwctrl_addr) & 0xfffff); -		cy_card[card_no].hw_ver = mailbox; -		cy_card[card_no].num_chips = (unsigned int)-1; -		cy_card[card_no].board_ctrl = &zfw_ctrl->board_ctrl; +		card->hw_ver = mailbox; +		card->num_chips = (unsigned int)-1; +		card->board_ctrl = &zfw_ctrl->board_ctrl;  #ifdef CONFIG_CYZ_INTR  		/* allocate IRQ only if board has an IRQ */  		if (irq != 0 && irq != 255) {  			retval = request_irq(irq, cyz_interrupt, -					IRQF_SHARED, "Cyclades-Z", -					&cy_card[card_no]); +					IRQF_SHARED, "Cyclades-Z", card);  			if (retval) {  				dev_err(&pdev->dev, "could not allocate IRQ\n");  				goto err_unmap; @@ -3873,17 +3876,17 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,  	}  	/* set cy_card */ -	cy_card[card_no].base_addr = addr2; -	cy_card[card_no].ctl_addr.p9050 = addr0; -	cy_card[card_no].irq = irq; -	cy_card[card_no].bus_index = 1; -	cy_card[card_no].first_line = cy_next_channel; -	cy_card[card_no].nports = nchan; -	retval = cy_init_card(&cy_card[card_no]); +	card->base_addr = addr2; +	card->ctl_addr.p9050 = addr0; +	card->irq = irq; +	card->bus_index = 1; +	card->first_line = cy_next_channel; +	card->nports = nchan; +	retval = cy_init_card(card);  	if (retval)  		goto err_null; -	pci_set_drvdata(pdev, &cy_card[card_no]); +	pci_set_drvdata(pdev, card);  	if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo ||  			device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) { @@ -3915,8 +3918,8 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,  	return 0;  err_null: -	cy_card[card_no].base_addr = NULL; -	free_irq(irq, &cy_card[card_no]); +	card->base_addr = NULL; +	free_irq(irq, card);  err_unmap:  	iounmap(addr0);  	if (addr2) diff --git a/drivers/tty/n_r3964.c b/drivers/tty/n_r3964.c index 5c6c31459a2f..1e6405070ce6 100644 --- a/drivers/tty/n_r3964.c +++ b/drivers/tty/n_r3964.c @@ -1065,7 +1065,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,  	TRACE_L("read()"); -	tty_lock(); +	tty_lock(tty);  	pClient = findClient(pInfo, task_pid(current));  	if (pClient) { @@ -1077,7 +1077,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,  				goto unlock;  			}  			/* block until there is a message: */ -			wait_event_interruptible_tty(pInfo->read_wait, +			wait_event_interruptible_tty(tty, pInfo->read_wait,  					(pMsg = remove_msg(pInfo, pClient)));  		} @@ -1107,7 +1107,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,  	}  	ret = -EPERM;  unlock: -	tty_unlock(); +	tty_unlock(tty);  	return ret;  } @@ -1156,7 +1156,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,  	pHeader->locks = 0;  	pHeader->owner = NULL; -	tty_lock(); +	tty_lock(tty);  	pClient = findClient(pInfo, task_pid(current));  	if (pClient) { @@ -1175,7 +1175,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,  	add_tx_queue(pInfo, pHeader);  	trigger_transmit(pInfo); -	tty_unlock(); +	tty_unlock(tty);  	return 0;  } diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index ee1c268f5f9d..4f34491b65c6 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1432,6 +1432,12 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,  	 */  	if (tty->receive_room < TTY_THRESHOLD_THROTTLE)  		tty_throttle(tty); + +        /* FIXME: there is a tiny race here if the receive room check runs +           before the other work executes and empties the buffer (upping +           the receiving room and unthrottling. We then throttle and get +           stuck. This has been observed and traced down by Vincent Pillet/ +           We need to address this when we sort out out the rx path locking */  }  int is_ignored(int sig) diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index 5505ffc91da4..a0ca0830cbcf 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -47,6 +47,7 @@ static void pty_close(struct tty_struct *tty, struct file *filp)  	wake_up_interruptible(&tty->read_wait);  	wake_up_interruptible(&tty->write_wait);  	tty->packet = 0; +	/* Review - krefs on tty_link ?? */  	if (!tty->link)  		return;  	tty->link->packet = 0; @@ -62,9 +63,9 @@ static void pty_close(struct tty_struct *tty, struct file *filp)  		        mutex_unlock(&devpts_mutex);  		}  #endif -		tty_unlock(); +		tty_unlock(tty);  		tty_vhangup(tty->link); -		tty_lock(); +		tty_lock(tty);  	}  } @@ -282,60 +283,98 @@ done:  	return 0;  } -/* Traditional BSD devices */ -#ifdef CONFIG_LEGACY_PTYS - -static int pty_install(struct tty_driver *driver, struct tty_struct *tty) +static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty, +		bool legacy)  {  	struct tty_struct *o_tty; +	struct tty_port *ports[2];  	int idx = tty->index; -	int retval; +	int retval = -ENOMEM;  	o_tty = alloc_tty_struct(); -	if (!o_tty) -		return -ENOMEM; +	ports[0] = kmalloc(sizeof **ports, GFP_KERNEL); +	ports[1] = kmalloc(sizeof **ports, GFP_KERNEL); +	if (!o_tty || !ports[0] || !ports[1]) +		goto err_free_tty;  	if (!try_module_get(driver->other->owner)) {  		/* This cannot in fact currently happen */ -		retval = -ENOMEM;  		goto err_free_tty;  	}  	initialize_tty_struct(o_tty, driver->other, idx); -	/* We always use new tty termios data so we can do this -	   the easy way .. */ -	retval = tty_init_termios(tty); -	if (retval) -		goto err_deinit_tty; - -	retval = tty_init_termios(o_tty); -	if (retval) -		goto err_free_termios; +	if (legacy) { +		/* We always use new tty termios data so we can do this +		   the easy way .. */ +		retval = tty_init_termios(tty); +		if (retval) +			goto err_deinit_tty; + +		retval = tty_init_termios(o_tty); +		if (retval) +			goto err_free_termios; + +		driver->other->ttys[idx] = o_tty; +		driver->ttys[idx] = tty; +	} else { +		tty->termios = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL); +		if (tty->termios == NULL) +			goto err_deinit_tty; +		*tty->termios = driver->init_termios; +		tty->termios_locked = tty->termios + 1; + +		o_tty->termios = kzalloc(sizeof(struct ktermios[2]), +				GFP_KERNEL); +		if (o_tty->termios == NULL) +			goto err_free_termios; +		*o_tty->termios = driver->other->init_termios; +		o_tty->termios_locked = o_tty->termios + 1; +	}  	/*  	 * Everything allocated ... set up the o_tty structure.  	 */ -	driver->other->ttys[idx] = o_tty;  	tty_driver_kref_get(driver->other);  	if (driver->subtype == PTY_TYPE_MASTER)  		o_tty->count++;  	/* Establish the links in both directions */  	tty->link   = o_tty;  	o_tty->link = tty; +	tty_port_init(ports[0]); +	tty_port_init(ports[1]); +	o_tty->port = ports[0]; +	tty->port = ports[1];  	tty_driver_kref_get(driver);  	tty->count++; -	driver->ttys[idx] = tty;  	return 0;  err_free_termios: -	tty_free_termios(tty); +	if (legacy) +		tty_free_termios(tty); +	else +		kfree(tty->termios);  err_deinit_tty:  	deinitialize_tty_struct(o_tty);  	module_put(o_tty->driver->owner);  err_free_tty: +	kfree(ports[0]); +	kfree(ports[1]);  	free_tty_struct(o_tty);  	return retval;  } +static void pty_cleanup(struct tty_struct *tty) +{ +	kfree(tty->port); +} + +/* Traditional BSD devices */ +#ifdef CONFIG_LEGACY_PTYS + +static int pty_install(struct tty_driver *driver, struct tty_struct *tty) +{ +	return pty_common_install(driver, tty, true); +} +  static int pty_bsd_ioctl(struct tty_struct *tty,  			 unsigned int cmd, unsigned long arg)  { @@ -366,6 +405,7 @@ static const struct tty_operations master_pty_ops_bsd = {  	.unthrottle = pty_unthrottle,  	.set_termios = pty_set_termios,  	.ioctl = pty_bsd_ioctl, +	.cleanup = pty_cleanup,  	.resize = pty_resize  }; @@ -379,6 +419,7 @@ static const struct tty_operations slave_pty_ops_bsd = {  	.chars_in_buffer = pty_chars_in_buffer,  	.unthrottle = pty_unthrottle,  	.set_termios = pty_set_termios, +	.cleanup = pty_cleanup,  	.resize = pty_resize  }; @@ -509,66 +550,17 @@ static void pty_unix98_shutdown(struct tty_struct *tty)  static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty)  { -	struct tty_struct *o_tty; -	int idx = tty->index; - -	o_tty = alloc_tty_struct(); -	if (!o_tty) -		return -ENOMEM; -	if (!try_module_get(driver->other->owner)) { -		/* This cannot in fact currently happen */ -		goto err_free_tty; -	} -	initialize_tty_struct(o_tty, driver->other, idx); - -	tty->termios = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL); -	if (tty->termios == NULL) -		goto err_free_mem; -	*tty->termios = driver->init_termios; -	tty->termios_locked = tty->termios + 1; - -	o_tty->termios = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL); -	if (o_tty->termios == NULL) -		goto err_free_mem; -	*o_tty->termios = driver->other->init_termios; -	o_tty->termios_locked = o_tty->termios + 1; - -	tty_driver_kref_get(driver->other); -	if (driver->subtype == PTY_TYPE_MASTER) -		o_tty->count++; -	/* Establish the links in both directions */ -	tty->link   = o_tty; -	o_tty->link = tty; -	/* -	 * All structures have been allocated, so now we install them. -	 * Failures after this point use release_tty to clean up, so -	 * there's no need to null out the local pointers. -	 */ -	tty_driver_kref_get(driver); -	tty->count++; -	return 0; -err_free_mem: -	deinitialize_tty_struct(o_tty); -	kfree(o_tty->termios); -	kfree(tty->termios); -	module_put(o_tty->driver->owner); -err_free_tty: -	free_tty_struct(o_tty); -	return -ENOMEM; -} - -static void ptm_unix98_remove(struct tty_driver *driver, struct tty_struct *tty) -{ +	return pty_common_install(driver, tty, false);  } -static void pts_unix98_remove(struct tty_driver *driver, struct tty_struct *tty) +static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)  {  }  static const struct tty_operations ptm_unix98_ops = {  	.lookup = ptm_unix98_lookup,  	.install = pty_unix98_install, -	.remove = ptm_unix98_remove, +	.remove = pty_unix98_remove,  	.open = pty_open,  	.close = pty_close,  	.write = pty_write, @@ -579,13 +571,14 @@ static const struct tty_operations ptm_unix98_ops = {  	.set_termios = pty_set_termios,  	.ioctl = pty_unix98_ioctl,  	.shutdown = pty_unix98_shutdown, +	.cleanup = pty_cleanup,  	.resize = pty_resize  };  static const struct tty_operations pty_unix98_ops = {  	.lookup = pts_unix98_lookup,  	.install = pty_unix98_install, -	.remove = pts_unix98_remove, +	.remove = pty_unix98_remove,  	.open = pty_open,  	.close = pty_close,  	.write = pty_write, @@ -594,7 +587,8 @@ static const struct tty_operations pty_unix98_ops = {  	.chars_in_buffer = pty_chars_in_buffer,  	.unthrottle = pty_unthrottle,  	.set_termios = pty_set_termios, -	.shutdown = pty_unix98_shutdown +	.shutdown = pty_unix98_shutdown, +	.cleanup = pty_cleanup,  };  /** @@ -622,26 +616,26 @@ static int ptmx_open(struct inode *inode, struct file *filp)  		return retval;  	/* find a device that is not in use. */ -	tty_lock(); +	mutex_lock(&devpts_mutex);  	index = devpts_new_index(inode); -	tty_unlock(); +	mutex_unlock(&devpts_mutex);  	if (index < 0) {  		retval = index;  		goto err_file;  	}  	mutex_lock(&tty_mutex); -	mutex_lock(&devpts_mutex);  	tty = tty_init_dev(ptm_driver, index); -	mutex_unlock(&devpts_mutex); -	tty_lock(); -	mutex_unlock(&tty_mutex);  	if (IS_ERR(tty)) {  		retval = PTR_ERR(tty);  		goto out;  	} +	/* The tty returned here is locked so we can safely +	   drop the mutex */ +	mutex_unlock(&tty_mutex); +  	set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */  	tty_add_file(tty, filp); @@ -654,15 +648,15 @@ static int ptmx_open(struct inode *inode, struct file *filp)  	if (retval)  		goto err_release; -	tty_unlock(); +	tty_unlock(tty);  	return 0;  err_release: -	tty_unlock(); +	tty_unlock(tty);  	tty_release(inode, filp);  	return retval;  out: +	mutex_unlock(&tty_mutex);  	devpts_kill_index(inode, index); -	tty_unlock();  err_file:  	tty_free_file(filp);  	return retval; diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c index 6e1958a325bd..44f52c6f15b9 100644 --- a/drivers/tty/serial/8250/8250.c +++ b/drivers/tty/serial/8250/8250.c @@ -282,6 +282,14 @@ static const struct serial8250_config uart_config[] = {  		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,  		.flags		= UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR,  	}, +	[PORT_LPC3220] = { +		.name		= "LPC3220", +		.fifo_size	= 64, +		.tx_loadsz	= 32, +		.fcr		= UART_FCR_DMA_SELECT | UART_FCR_ENABLE_FIFO | +				  UART_FCR_R_TRIG_00 | UART_FCR_T_TRIG_00, +		.flags		= UART_CAP_FIFO, +	},  };  /* Uart divisor latch read */ @@ -2194,6 +2202,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,  	unsigned char cval, fcr = 0;  	unsigned long flags;  	unsigned int baud, quot; +	int fifo_bug = 0;  	switch (termios->c_cflag & CSIZE) {  	case CS5: @@ -2213,8 +2222,11 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,  	if (termios->c_cflag & CSTOPB)  		cval |= UART_LCR_STOP; -	if (termios->c_cflag & PARENB) +	if (termios->c_cflag & PARENB) {  		cval |= UART_LCR_PARITY; +		if (up->bugs & UART_BUG_PARITY) +			fifo_bug = 1; +	}  	if (!(termios->c_cflag & PARODD))  		cval |= UART_LCR_EPAR;  #ifdef CMSPAR @@ -2238,7 +2250,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,  	if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) {  		fcr = uart_config[port->type].fcr; -		if (baud < 2400) { +		if (baud < 2400 || fifo_bug) {  			fcr &= ~UART_FCR_TRIGGER_MASK;  			fcr |= UART_FCR_TRIGGER_1;  		} @@ -2971,36 +2983,36 @@ void serial8250_resume_port(int line)  static int __devinit serial8250_probe(struct platform_device *dev)  {  	struct plat_serial8250_port *p = dev->dev.platform_data; -	struct uart_port port; +	struct uart_8250_port uart;  	int ret, i, irqflag = 0; -	memset(&port, 0, sizeof(struct uart_port)); +	memset(&uart, 0, sizeof(uart));  	if (share_irqs)  		irqflag = IRQF_SHARED;  	for (i = 0; p && p->flags != 0; p++, i++) { -		port.iobase		= p->iobase; -		port.membase		= p->membase; -		port.irq		= p->irq; -		port.irqflags		= p->irqflags; -		port.uartclk		= p->uartclk; -		port.regshift		= p->regshift; -		port.iotype		= p->iotype; -		port.flags		= p->flags; -		port.mapbase		= p->mapbase; -		port.hub6		= p->hub6; -		port.private_data	= p->private_data; -		port.type		= p->type; -		port.serial_in		= p->serial_in; -		port.serial_out		= p->serial_out; -		port.handle_irq		= p->handle_irq; -		port.handle_break	= p->handle_break; -		port.set_termios	= p->set_termios; -		port.pm			= p->pm; -		port.dev		= &dev->dev; -		port.irqflags		|= irqflag; -		ret = serial8250_register_port(&port); +		uart.port.iobase	= p->iobase; +		uart.port.membase	= p->membase; +		uart.port.irq		= p->irq; +		uart.port.irqflags	= p->irqflags; +		uart.port.uartclk	= p->uartclk; +		uart.port.regshift	= p->regshift; +		uart.port.iotype	= p->iotype; +		uart.port.flags		= p->flags; +		uart.port.mapbase	= p->mapbase; +		uart.port.hub6		= p->hub6; +		uart.port.private_data	= p->private_data; +		uart.port.type		= p->type; +		uart.port.serial_in	= p->serial_in; +		uart.port.serial_out	= p->serial_out; +		uart.port.handle_irq	= p->handle_irq; +		uart.port.handle_break	= p->handle_break; +		uart.port.set_termios	= p->set_termios; +		uart.port.pm		= p->pm; +		uart.port.dev		= &dev->dev; +		uart.port.irqflags	|= irqflag; +		ret = serial8250_register_8250_port(&uart);  		if (ret < 0) {  			dev_err(&dev->dev, "unable to register port at index %d "  				"(IO%lx MEM%llx IRQ%d): %d\n", i, @@ -3073,7 +3085,7 @@ static struct platform_driver serial8250_isa_driver = {  static struct platform_device *serial8250_isa_devs;  /* - * serial8250_register_port and serial8250_unregister_port allows for + * serial8250_register_8250_port and serial8250_unregister_port allows for   * 16x50 serial ports to be configured at run-time, to support PCMCIA   * modems and PCI multiport cards.   */ @@ -3147,6 +3159,7 @@ int serial8250_register_8250_port(struct uart_8250_port *up)  		uart->port.regshift     = up->port.regshift;  		uart->port.iotype       = up->port.iotype;  		uart->port.flags        = up->port.flags | UPF_BOOT_AUTOCONF; +		uart->bugs		= up->bugs;  		uart->port.mapbase      = up->port.mapbase;  		uart->port.private_data = up->port.private_data;  		if (up->port.dev) @@ -3190,29 +3203,6 @@ int serial8250_register_8250_port(struct uart_8250_port *up)  EXPORT_SYMBOL(serial8250_register_8250_port);  /** - *	serial8250_register_port - register a serial port - *	@port: serial port template - * - *	Configure the serial port specified by the request. If the - *	port exists and is in use, it is hung up and unregistered - *	first. - * - *	The port is then probed and if necessary the IRQ is autodetected - *	If this fails an error is returned. - * - *	On success the port is ready to use and the line number is returned. - */ -int serial8250_register_port(struct uart_port *port) -{ -	struct uart_8250_port up; - -	memset(&up, 0, sizeof(up)); -	memcpy(&up.port, port, sizeof(*port)); -	return serial8250_register_8250_port(&up); -} -EXPORT_SYMBOL(serial8250_register_port); - -/**   *	serial8250_unregister_port - remove a 16x50 serial port at runtime   *	@line: serial line number   * diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index f9719d167c8d..c335b2b23a5f 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -78,6 +78,7 @@ struct serial8250_config {  #define UART_BUG_TXEN	(1 << 1)	/* UART has buggy TX IIR status */  #define UART_BUG_NOMSR	(1 << 2)	/* UART has buggy MSR status bits (Au1x00) */  #define UART_BUG_THRE	(1 << 3)	/* UART has buggy THRE reassertion */ +#define UART_BUG_PARITY	(1 << 4)	/* UART mishandles parity if FIFO enabled */  #define PROBE_RSA	(1 << 0)  #define PROBE_ANY	(~0) diff --git a/drivers/tty/serial/8250/8250_acorn.c b/drivers/tty/serial/8250/8250_acorn.c index b0ce8c56f1a4..857498312a9a 100644 --- a/drivers/tty/serial/8250/8250_acorn.c +++ b/drivers/tty/serial/8250/8250_acorn.c @@ -43,7 +43,7 @@ serial_card_probe(struct expansion_card *ec, const struct ecard_id *id)  {  	struct serial_card_info *info;  	struct serial_card_type *type = id->data; -	struct uart_port port; +	struct uart_8250_port uart;  	unsigned long bus_addr;  	unsigned int i; @@ -62,19 +62,19 @@ serial_card_probe(struct expansion_card *ec, const struct ecard_id *id)  	ecard_set_drvdata(ec, info); -	memset(&port, 0, sizeof(struct uart_port)); -	port.irq	= ec->irq; -	port.flags	= UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ; -	port.uartclk	= type->uartclk; -	port.iotype	= UPIO_MEM; -	port.regshift	= 2; -	port.dev	= &ec->dev; +	memset(&uart, 0, sizeof(struct uart_8250_port)); +	uart.port.irq	= ec->irq; +	uart.port.flags	= UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ; +	uart.port.uartclk	= type->uartclk; +	uart.port.iotype	= UPIO_MEM; +	uart.port.regshift	= 2; +	uart.port.dev	= &ec->dev;  	for (i = 0; i < info->num_ports; i ++) { -		port.membase = info->vaddr + type->offset[i]; -		port.mapbase = bus_addr + type->offset[i]; +		uart.port.membase = info->vaddr + type->offset[i]; +		uart.port.mapbase = bus_addr + type->offset[i]; -		info->ports[i] = serial8250_register_port(&port); +		info->ports[i] = serial8250_register_8250_port(&uart);  	}  	return 0; diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index f574eef3075f..afb955fdef03 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -89,7 +89,7 @@ static int dw8250_handle_irq(struct uart_port *p)  static int __devinit dw8250_probe(struct platform_device *pdev)  { -	struct uart_port port = {}; +	struct uart_8250_port uart = {};  	struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);  	struct device_node *np = pdev->dev.of_node; @@ -104,28 +104,28 @@ static int __devinit dw8250_probe(struct platform_device *pdev)  	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);  	if (!data)  		return -ENOMEM; -	port.private_data = data; - -	spin_lock_init(&port.lock); -	port.mapbase = regs->start; -	port.irq = irq->start; -	port.handle_irq = dw8250_handle_irq; -	port.type = PORT_8250; -	port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP | +	uart.port.private_data = data; + +	spin_lock_init(&uart.port.lock); +	uart.port.mapbase = regs->start; +	uart.port.irq = irq->start; +	uart.port.handle_irq = dw8250_handle_irq; +	uart.port.type = PORT_8250; +	uart.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP |  		UPF_FIXED_PORT | UPF_FIXED_TYPE; -	port.dev = &pdev->dev; +	uart.port.dev = &pdev->dev; -	port.iotype = UPIO_MEM; -	port.serial_in = dw8250_serial_in; -	port.serial_out = dw8250_serial_out; +	uart.port.iotype = UPIO_MEM; +	uart.port.serial_in = dw8250_serial_in; +	uart.port.serial_out = dw8250_serial_out;  	if (!of_property_read_u32(np, "reg-io-width", &val)) {  		switch (val) {  		case 1:  			break;  		case 4: -			port.iotype = UPIO_MEM32; -			port.serial_in = dw8250_serial_in32; -			port.serial_out = dw8250_serial_out32; +			uart.port.iotype = UPIO_MEM32; +			uart.port.serial_in = dw8250_serial_in32; +			uart.port.serial_out = dw8250_serial_out32;  			break;  		default:  			dev_err(&pdev->dev, "unsupported reg-io-width (%u)\n", @@ -135,15 +135,15 @@ static int __devinit dw8250_probe(struct platform_device *pdev)  	}  	if (!of_property_read_u32(np, "reg-shift", &val)) -		port.regshift = val; +		uart.port.regshift = val;  	if (of_property_read_u32(np, "clock-frequency", &val)) {  		dev_err(&pdev->dev, "no clock-frequency property set\n");  		return -EINVAL;  	} -	port.uartclk = val; +	uart.uart.port.uartclk = val; -	data->line = serial8250_register_port(&port); +	data->line = serial8250_register_8250_port(&uart);  	if (data->line < 0)  		return data->line; diff --git a/drivers/tty/serial/8250/8250_gsc.c b/drivers/tty/serial/8250/8250_gsc.c index d8c0ffbfa6e3..097dff9c08ad 100644 --- a/drivers/tty/serial/8250/8250_gsc.c +++ b/drivers/tty/serial/8250/8250_gsc.c @@ -26,7 +26,7 @@  static int __init serial_init_chip(struct parisc_device *dev)  { -	struct uart_port port; +	struct uart_8250_port uart;  	unsigned long address;  	int err; @@ -48,21 +48,21 @@ static int __init serial_init_chip(struct parisc_device *dev)  	if (dev->id.sversion != 0x8d)  		address += 0x800; -	memset(&port, 0, sizeof(port)); -	port.iotype	= UPIO_MEM; +	memset(&uart, 0, sizeof(uart)); +	uart.port.iotype	= UPIO_MEM;  	/* 7.272727MHz on Lasi.  Assumed the same for Dino, Wax and Timi. */ -	port.uartclk	= 7272727; -	port.mapbase	= address; -	port.membase	= ioremap_nocache(address, 16); -	port.irq	= dev->irq; -	port.flags	= UPF_BOOT_AUTOCONF; -	port.dev	= &dev->dev; - -	err = serial8250_register_port(&port); +	uart.port.uartclk	= 7272727; +	uart.port.mapbase	= address; +	uart.port.membase	= ioremap_nocache(address, 16); +	uart.port.irq	= dev->irq; +	uart.port.flags	= UPF_BOOT_AUTOCONF; +	uart.port.dev	= &dev->dev; + +	err = serial8250_register_8250_port(&uart);  	if (err < 0) {  		printk(KERN_WARNING -			"serial8250_register_port returned error %d\n", err); -		iounmap(port.membase); +			"serial8250_register_8250_port returned error %d\n", err); +		iounmap(uart.port.membase);  		return err;  	} diff --git a/drivers/tty/serial/8250/8250_hp300.c b/drivers/tty/serial/8250/8250_hp300.c index c13438c93012..8f1dd2cc00a8 100644 --- a/drivers/tty/serial/8250/8250_hp300.c +++ b/drivers/tty/serial/8250/8250_hp300.c @@ -171,7 +171,7 @@ static int __devinit hpdca_init_one(struct dio_dev *d,  		return 0;  	}  #endif -	memset(&port, 0, sizeof(struct uart_port)); +	memset(&uart, 0, sizeof(uart));  	/* Memory mapped I/O */  	port.iotype = UPIO_MEM; @@ -182,7 +182,7 @@ static int __devinit hpdca_init_one(struct dio_dev *d,  	port.membase = (char *)(port.mapbase + DIO_VIRADDRBASE);  	port.regshift = 1;  	port.dev = &d->dev; -	line = serial8250_register_port(&port); +	line = serial8250_register_8250_port(&uart);  	if (line < 0) {  		printk(KERN_NOTICE "8250_hp300: register_serial() DCA scode %d" @@ -210,7 +210,7 @@ static int __init hp300_8250_init(void)  #ifdef CONFIG_HPAPCI  	int line;  	unsigned long base; -	struct uart_port uport; +	struct uart_8250_port uart;  	struct hp300_port *port;  	int i;  #endif @@ -248,26 +248,26 @@ static int __init hp300_8250_init(void)  		if (!port)  			return -ENOMEM; -		memset(&uport, 0, sizeof(struct uart_port)); +		memset(&uart, 0, sizeof(uart));  		base = (FRODO_BASE + FRODO_APCI_OFFSET(i));  		/* Memory mapped I/O */ -		uport.iotype = UPIO_MEM; -		uport.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ \ +		uart.port.iotype = UPIO_MEM; +		uart.port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ \  			      | UPF_BOOT_AUTOCONF;  		/* XXX - no interrupt support yet */ -		uport.irq = 0; -		uport.uartclk = HPAPCI_BAUD_BASE * 16; -		uport.mapbase = base; -		uport.membase = (char *)(base + DIO_VIRADDRBASE); -		uport.regshift = 2; +		uart.port.irq = 0; +		uart.port.uartclk = HPAPCI_BAUD_BASE * 16; +		uart.port.mapbase = base; +		uart.port.membase = (char *)(base + DIO_VIRADDRBASE); +		uart.port.regshift = 2; -		line = serial8250_register_port(&uport); +		line = serial8250_register_8250_port(&uart);  		if (line < 0) {  			printk(KERN_NOTICE "8250_hp300: register_serial() APCI" -			       " %d irq %d failed\n", i, uport.irq); +			       " %d irq %d failed\n", i, uart.port.irq);  			kfree(port);  			continue;  		} diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 28e7c7cce893..62e10fe747a8 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -44,7 +44,7 @@ struct pci_serial_quirk {  	int	(*init)(struct pci_dev *dev);  	int	(*setup)(struct serial_private *,  			 const struct pciserial_board *, -			 struct uart_port *, int); +			 struct uart_8250_port *, int);  	void	(*exit)(struct pci_dev *dev);  }; @@ -59,7 +59,7 @@ struct serial_private {  };  static int pci_default_setup(struct serial_private*, -	  const struct pciserial_board*, struct uart_port*, int); +	  const struct pciserial_board*, struct uart_8250_port *, int);  static void moan_device(const char *str, struct pci_dev *dev)  { @@ -74,7 +74,7 @@ static void moan_device(const char *str, struct pci_dev *dev)  }  static int -setup_port(struct serial_private *priv, struct uart_port *port, +setup_port(struct serial_private *priv, struct uart_8250_port *port,  	   int bar, int offset, int regshift)  {  	struct pci_dev *dev = priv->dev; @@ -93,17 +93,17 @@ setup_port(struct serial_private *priv, struct uart_port *port,  		if (!priv->remapped_bar[bar])  			return -ENOMEM; -		port->iotype = UPIO_MEM; -		port->iobase = 0; -		port->mapbase = base + offset; -		port->membase = priv->remapped_bar[bar] + offset; -		port->regshift = regshift; +		port->port.iotype = UPIO_MEM; +		port->port.iobase = 0; +		port->port.mapbase = base + offset; +		port->port.membase = priv->remapped_bar[bar] + offset; +		port->port.regshift = regshift;  	} else { -		port->iotype = UPIO_PORT; -		port->iobase = base + offset; -		port->mapbase = 0; -		port->membase = NULL; -		port->regshift = 0; +		port->port.iotype = UPIO_PORT; +		port->port.iobase = base + offset; +		port->port.mapbase = 0; +		port->port.membase = NULL; +		port->port.regshift = 0;  	}  	return 0;  } @@ -113,7 +113,7 @@ setup_port(struct serial_private *priv, struct uart_port *port,   */  static int addidata_apci7800_setup(struct serial_private *priv,  				const struct pciserial_board *board, -				struct uart_port *port, int idx) +				struct uart_8250_port *port, int idx)  {  	unsigned int bar = 0, offset = board->first_offset;  	bar = FL_GET_BASE(board->flags); @@ -140,7 +140,7 @@ static int addidata_apci7800_setup(struct serial_private *priv,   */  static int  afavlab_setup(struct serial_private *priv, const struct pciserial_board *board, -	      struct uart_port *port, int idx) +	      struct uart_8250_port *port, int idx)  {  	unsigned int bar, offset = board->first_offset; @@ -195,7 +195,7 @@ static int pci_hp_diva_init(struct pci_dev *dev)  static int  pci_hp_diva_setup(struct serial_private *priv,  		const struct pciserial_board *board, -		struct uart_port *port, int idx) +		struct uart_8250_port *port, int idx)  {  	unsigned int offset = board->first_offset;  	unsigned int bar = FL_GET_BASE(board->flags); @@ -370,7 +370,7 @@ static void __devexit pci_ni8430_exit(struct pci_dev *dev)  /* SBS Technologies Inc. PMC-OCTPRO and P-OCTAL cards */  static int  sbs_setup(struct serial_private *priv, const struct pciserial_board *board, -		struct uart_port *port, int idx) +		struct uart_8250_port *port, int idx)  {  	unsigned int bar, offset = board->first_offset; @@ -525,7 +525,7 @@ static int pci_siig_init(struct pci_dev *dev)  static int pci_siig_setup(struct serial_private *priv,  			  const struct pciserial_board *board, -			  struct uart_port *port, int idx) +			  struct uart_8250_port *port, int idx)  {  	unsigned int bar = FL_GET_BASE(board->flags) + idx, offset = 0; @@ -619,7 +619,7 @@ static int pci_timedia_init(struct pci_dev *dev)  static int  pci_timedia_setup(struct serial_private *priv,  		  const struct pciserial_board *board, -		  struct uart_port *port, int idx) +		  struct uart_8250_port *port, int idx)  {  	unsigned int bar = 0, offset = board->first_offset; @@ -653,7 +653,7 @@ pci_timedia_setup(struct serial_private *priv,  static int  titan_400l_800l_setup(struct serial_private *priv,  		      const struct pciserial_board *board, -		      struct uart_port *port, int idx) +		      struct uart_8250_port *port, int idx)  {  	unsigned int bar, offset = board->first_offset; @@ -754,7 +754,7 @@ static int pci_ni8430_init(struct pci_dev *dev)  static int  pci_ni8430_setup(struct serial_private *priv,  		 const struct pciserial_board *board, -		 struct uart_port *port, int idx) +		 struct uart_8250_port *port, int idx)  {  	void __iomem *p;  	unsigned long base, len; @@ -781,7 +781,7 @@ pci_ni8430_setup(struct serial_private *priv,  static int pci_netmos_9900_setup(struct serial_private *priv,  				const struct pciserial_board *board, -				struct uart_port *port, int idx) +				struct uart_8250_port *port, int idx)  {  	unsigned int bar; @@ -1032,10 +1032,17 @@ static int pci_oxsemi_tornado_init(struct pci_dev *dev)  	return number_uarts;  } -static int -pci_default_setup(struct serial_private *priv, +static int pci_asix_setup(struct serial_private *priv, +		  const struct pciserial_board *board, +		  struct uart_8250_port *port, int idx) +{ +	port->bugs |= UART_BUG_PARITY; +	return pci_default_setup(priv, board, port, idx); +} + +static int pci_default_setup(struct serial_private *priv,  		  const struct pciserial_board *board, -		  struct uart_port *port, int idx) +		  struct uart_8250_port *port, int idx)  {  	unsigned int bar, offset = board->first_offset, maxnr; @@ -1057,15 +1064,15 @@ pci_default_setup(struct serial_private *priv,  static int  ce4100_serial_setup(struct serial_private *priv,  		  const struct pciserial_board *board, -		  struct uart_port *port, int idx) +		  struct uart_8250_port *port, int idx)  {  	int ret;  	ret = setup_port(priv, port, 0, 0, board->reg_shift); -	port->iotype = UPIO_MEM32; -	port->type = PORT_XSCALE; -	port->flags = (port->flags | UPF_FIXED_PORT | UPF_FIXED_TYPE); -	port->regshift = 2; +	port->port.iotype = UPIO_MEM32; +	port->port.type = PORT_XSCALE; +	port->port.flags = (port->port.flags | UPF_FIXED_PORT | UPF_FIXED_TYPE); +	port->port.regshift = 2;  	return ret;  } @@ -1073,16 +1080,16 @@ ce4100_serial_setup(struct serial_private *priv,  static int  pci_omegapci_setup(struct serial_private *priv,  		      const struct pciserial_board *board, -		      struct uart_port *port, int idx) +		      struct uart_8250_port *port, int idx)  {  	return setup_port(priv, port, 2, idx * 8, 0);  }  static int skip_tx_en_setup(struct serial_private *priv,  			const struct pciserial_board *board, -			struct uart_port *port, int idx) +			struct uart_8250_port *port, int idx)  { -	port->flags |= UPF_NO_TXEN_TEST; +	port->port.flags |= UPF_NO_TXEN_TEST;  	printk(KERN_DEBUG "serial8250: skipping TxEn test for device "  			  "[%04x:%04x] subsystem [%04x:%04x]\n",  			  priv->dev->vendor, @@ -1131,11 +1138,11 @@ static unsigned int kt_serial_in(struct uart_port *p, int offset)  static int kt_serial_setup(struct serial_private *priv,  			   const struct pciserial_board *board, -			   struct uart_port *port, int idx) +			   struct uart_8250_port *port, int idx)  { -	port->flags |= UPF_BUG_THRE; -	port->serial_in = kt_serial_in; -	port->handle_break = kt_handle_break; +	port->port.flags |= UPF_BUG_THRE; +	port->port.serial_in = kt_serial_in; +	port->port.handle_break = kt_handle_break;  	return skip_tx_en_setup(priv, board, port, idx);  } @@ -1151,9 +1158,9 @@ static int pci_eg20t_init(struct pci_dev *dev)  static int  pci_xr17c154_setup(struct serial_private *priv,  		  const struct pciserial_board *board, -		  struct uart_port *port, int idx) +		  struct uart_8250_port *port, int idx)  { -	port->flags |= UPF_EXAR_EFR; +	port->port.flags |= UPF_EXAR_EFR;  	return pci_default_setup(priv, board, port, idx);  } @@ -1187,6 +1194,7 @@ pci_xr17c154_setup(struct serial_private *priv,  #define PCIE_DEVICE_ID_NEO_2_OX_IBM	0x00F6  #define PCI_DEVICE_ID_PLX_CRONYX_OMEGA	0xc001  #define PCI_DEVICE_ID_INTEL_PATSBURG_KT 0x1d3d +#define PCI_VENDOR_ID_ASIX		0x9710  /* Unknown vendors/cards - this should not be in linux/pci_ids.h */  #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584	0x1584 @@ -1726,7 +1734,17 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {  		.subvendor	= PCI_ANY_ID,  		.subdevice	= PCI_ANY_ID,  		.setup		= pci_omegapci_setup, -	 }, +	}, +	/* +	 * ASIX devices with FIFO bug +	 */ +	{ +		.vendor		= PCI_VENDOR_ID_ASIX, +		.device		= PCI_ANY_ID, +		.subvendor	= PCI_ANY_ID, +		.subdevice	= PCI_ANY_ID, +		.setup		= pci_asix_setup, +	},  	/*  	 * Default "match everything" terminator entry  	 */ @@ -1887,7 +1905,6 @@ enum pci_board_num_t {  	pbn_panacom,  	pbn_panacom2,  	pbn_panacom4, -	pbn_exsys_4055,  	pbn_plx_romulus,  	pbn_oxsemi,  	pbn_oxsemi_1_4000000, @@ -2393,13 +2410,6 @@ static struct pciserial_board pci_boards[] __devinitdata = {  		.reg_shift	= 7,  	}, -	[pbn_exsys_4055] = { -		.flags		= FL_BASE2, -		.num_ports	= 4, -		.base_baud	= 115200, -		.uart_offset	= 8, -	}, -  	/* I think this entry is broken - the first_offset looks wrong --rmk */  	[pbn_plx_romulus] = {  		.flags		= FL_BASE2, @@ -2728,7 +2738,7 @@ serial_pci_matches(const struct pciserial_board *board,  struct serial_private *  pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board)  { -	struct uart_port serial_port; +	struct uart_8250_port uart;  	struct serial_private *priv;  	struct pci_serial_quirk *quirk;  	int rc, nr_ports, i; @@ -2768,22 +2778,22 @@ pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board)  	priv->dev = dev;  	priv->quirk = quirk; -	memset(&serial_port, 0, sizeof(struct uart_port)); -	serial_port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ; -	serial_port.uartclk = board->base_baud * 16; -	serial_port.irq = get_pci_irq(dev, board); -	serial_port.dev = &dev->dev; +	memset(&uart, 0, sizeof(uart)); +	uart.port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ; +	uart.port.uartclk = board->base_baud * 16; +	uart.port.irq = get_pci_irq(dev, board); +	uart.port.dev = &dev->dev;  	for (i = 0; i < nr_ports; i++) { -		if (quirk->setup(priv, board, &serial_port, i)) +		if (quirk->setup(priv, board, &uart, i))  			break;  #ifdef SERIAL_DEBUG_PCI  		printk(KERN_DEBUG "Setup PCI port: port %lx, irq %d, type %d\n", -		       serial_port.iobase, serial_port.irq, serial_port.iotype); +		       uart.port.iobase, uart.port.irq, uart.port.iotype);  #endif -		priv->line[i] = serial8250_register_port(&serial_port); +		priv->line[i] = serial8250_register_8250_port(&uart);  		if (priv->line[i] < 0) {  			printk(KERN_WARNING "Couldn't register serial port %s: %d\n", pci_name(dev), priv->line[i]);  			break; @@ -3193,7 +3203,7 @@ static struct pci_device_id serial_pci_tbl[] = {  	{	PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,  		PCI_SUBVENDOR_ID_EXSYS,  		PCI_SUBDEVICE_ID_EXSYS_4055, 0, 0, -		pbn_exsys_4055 }, +		pbn_b2_4_115200 },  	/*  	 * Megawolf Romulus PCI Serial Card, from Mike Hudson  	 * (Exoray@isys.ca) diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c index a2f236510ff1..fde5aa60d51e 100644 --- a/drivers/tty/serial/8250/8250_pnp.c +++ b/drivers/tty/serial/8250/8250_pnp.c @@ -424,7 +424,7 @@ static int __devinit serial_pnp_guess_board(struct pnp_dev *dev, int *flags)  static int __devinit  serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)  { -	struct uart_port port; +	struct uart_8250_port uart;  	int ret, line, flags = dev_id->driver_data;  	if (flags & UNKNOWN_DEV) { @@ -433,32 +433,32 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)  			return ret;  	} -	memset(&port, 0, sizeof(struct uart_port)); +	memset(&uart, 0, sizeof(uart));  	if (pnp_irq_valid(dev, 0)) -		port.irq = pnp_irq(dev, 0); +		uart.port.irq = pnp_irq(dev, 0);  	if (pnp_port_valid(dev, 0)) { -		port.iobase = pnp_port_start(dev, 0); -		port.iotype = UPIO_PORT; +		uart.port.iobase = pnp_port_start(dev, 0); +		uart.port.iotype = UPIO_PORT;  	} else if (pnp_mem_valid(dev, 0)) { -		port.mapbase = pnp_mem_start(dev, 0); -		port.iotype = UPIO_MEM; -		port.flags = UPF_IOREMAP; +		uart.port.mapbase = pnp_mem_start(dev, 0); +		uart.port.iotype = UPIO_MEM; +		uart.port.flags = UPF_IOREMAP;  	} else  		return -ENODEV;  #ifdef SERIAL_DEBUG_PNP  	printk(KERN_DEBUG  		"Setup PNP port: port %x, mem 0x%lx, irq %d, type %d\n", -		       port.iobase, port.mapbase, port.irq, port.iotype); +		       uart.port.iobase, uart.port.mapbase, uart.port.irq, uart.port.iotype);  #endif -	port.flags |= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF; +	uart.port.flags |= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;  	if (pnp_irq_flags(dev, 0) & IORESOURCE_IRQ_SHAREABLE) -		port.flags |= UPF_SHARE_IRQ; -	port.uartclk = 1843200; -	port.dev = &dev->dev; +		uart.port.flags |= UPF_SHARE_IRQ; +	uart.port.uartclk = 1843200; +	uart.port.dev = &dev->dev; -	line = serial8250_register_port(&port); +	line = serial8250_register_8250_port(&uart);  	if (line < 0)  		return -ENODEV; diff --git a/drivers/tty/serial/8250/serial_cs.c b/drivers/tty/serial/8250/serial_cs.c index 29b695d041ec..b7d48b346393 100644 --- a/drivers/tty/serial/8250/serial_cs.c +++ b/drivers/tty/serial/8250/serial_cs.c @@ -73,7 +73,7 @@ struct serial_quirk {  	unsigned int prodid;  	int multi;		/* 1 = multifunction, > 1 = # ports */  	void (*config)(struct pcmcia_device *); -	void (*setup)(struct pcmcia_device *, struct uart_port *); +	void (*setup)(struct pcmcia_device *, struct uart_8250_port *);  	void (*wakeup)(struct pcmcia_device *);  	int (*post)(struct pcmcia_device *);  }; @@ -105,9 +105,9 @@ struct serial_cfg_mem {   * Elan VPU16551 UART with 14.7456MHz oscillator   * manfid 0x015D, 0x4C45   */ -static void quirk_setup_brainboxes_0104(struct pcmcia_device *link, struct uart_port *port) +static void quirk_setup_brainboxes_0104(struct pcmcia_device *link, struct uart_8250_port *uart)  { -	port->uartclk = 14745600; +	uart->port.uartclk = 14745600;  }  static int quirk_post_ibm(struct pcmcia_device *link) @@ -343,25 +343,25 @@ static void serial_detach(struct pcmcia_device *link)  static int setup_serial(struct pcmcia_device *handle, struct serial_info * info,  			unsigned int iobase, int irq)  { -	struct uart_port port; +	struct uart_8250_port uart;  	int line; -	memset(&port, 0, sizeof (struct uart_port)); -	port.iobase = iobase; -	port.irq = irq; -	port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ; -	port.uartclk = 1843200; -	port.dev = &handle->dev; +	memset(&uart, 0, sizeof(uart)); +	uart.port.iobase = iobase; +	uart.port.irq = irq; +	uart.port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ; +	uart.port.uartclk = 1843200; +	uart.port.dev = &handle->dev;  	if (buggy_uart) -		port.flags |= UPF_BUGGY_UART; +		uart.port.flags |= UPF_BUGGY_UART;  	if (info->quirk && info->quirk->setup) -		info->quirk->setup(handle, &port); +		info->quirk->setup(handle, &uart); -	line = serial8250_register_port(&port); +	line = serial8250_register_8250_port(&uart);  	if (line < 0) { -		printk(KERN_NOTICE "serial_cs: serial8250_register_port() at " -		       "0x%04lx, irq %d failed\n", (u_long)iobase, irq); +		pr_err("serial_cs: serial8250_register_8250_port() at 0x%04lx, irq %d failed\n", +							(unsigned long)iobase, irq);  		return -EINVAL;  	} diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 070b442c1f81..00207865ec55 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -704,6 +704,25 @@ config SERIAL_PNX8XXX_CONSOLE  	  If you have a MIPS-based Philips SoC such as PNX8550 or PNX8330  	  and you want to use serial console, say Y. Otherwise, say N. +config SERIAL_HS_LPC32XX +	tristate "LPC32XX high speed serial port support" +	depends on ARCH_LPC32XX && OF +	select SERIAL_CORE +	help +	  Support for the LPC32XX high speed serial ports (up to 900kbps). +	  Those are UARTs completely different from the Standard UARTs on the +	  LPC32XX SoC. +	  Choose M or Y here to build this driver. + +config SERIAL_HS_LPC32XX_CONSOLE +	bool "Enable LPC32XX high speed UART serial console" +	depends on SERIAL_HS_LPC32XX +	select SERIAL_CORE_CONSOLE +	help +	  If you would like to be able to use one of the high speed serial +	  ports on the LPC32XX as the console, you can do so by answering +	  Y to this option. +  config SERIAL_CORE  	tristate diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index 7257c5d898ae..8a5df3804e5f 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_SERIAL_MUX) += mux.o  obj-$(CONFIG_SERIAL_68328) += 68328serial.o  obj-$(CONFIG_SERIAL_MCF) += mcf.o  obj-$(CONFIG_SERIAL_PMACZILOG) += pmac_zilog.o +obj-$(CONFIG_SERIAL_HS_LPC32XX) += lpc32xx_hs.o  obj-$(CONFIG_SERIAL_DZ) += dz.o  obj-$(CONFIG_SERIAL_ZS) += zs.o  obj-$(CONFIG_SERIAL_SH_SCI) += sh-sci.o diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index c17923ec6e95..b81cc31f2657 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -1215,14 +1215,14 @@ static irqreturn_t pl011_int(int irq, void *dev_id)  	return IRQ_RETVAL(handled);  } -static unsigned int pl01x_tx_empty(struct uart_port *port) +static unsigned int pl011_tx_empty(struct uart_port *port)  {  	struct uart_amba_port *uap = (struct uart_amba_port *)port;  	unsigned int status = readw(uap->port.membase + UART01x_FR);  	return status & (UART01x_FR_BUSY|UART01x_FR_TXFF) ? 0 : TIOCSER_TEMT;  } -static unsigned int pl01x_get_mctrl(struct uart_port *port) +static unsigned int pl011_get_mctrl(struct uart_port *port)  {  	struct uart_amba_port *uap = (struct uart_amba_port *)port;  	unsigned int result = 0; @@ -1285,7 +1285,7 @@ static void pl011_break_ctl(struct uart_port *port, int break_state)  }  #ifdef CONFIG_CONSOLE_POLL -static int pl010_get_poll_char(struct uart_port *port) +static int pl011_get_poll_char(struct uart_port *port)  {  	struct uart_amba_port *uap = (struct uart_amba_port *)port;  	unsigned int status; @@ -1297,7 +1297,7 @@ static int pl010_get_poll_char(struct uart_port *port)  	return readw(uap->port.membase + UART01x_DR);  } -static void pl010_put_poll_char(struct uart_port *port, +static void pl011_put_poll_char(struct uart_port *port,  			 unsigned char ch)  {  	struct uart_amba_port *uap = (struct uart_amba_port *)port; @@ -1637,7 +1637,7 @@ static const char *pl011_type(struct uart_port *port)  /*   * Release the memory region(s) being used by 'port'   */ -static void pl010_release_port(struct uart_port *port) +static void pl011_release_port(struct uart_port *port)  {  	release_mem_region(port->mapbase, SZ_4K);  } @@ -1645,7 +1645,7 @@ static void pl010_release_port(struct uart_port *port)  /*   * Request the memory region(s) being used by 'port'   */ -static int pl010_request_port(struct uart_port *port) +static int pl011_request_port(struct uart_port *port)  {  	return request_mem_region(port->mapbase, SZ_4K, "uart-pl011")  			!= NULL ? 0 : -EBUSY; @@ -1654,18 +1654,18 @@ static int pl010_request_port(struct uart_port *port)  /*   * Configure/autoconfigure the port.   */ -static void pl010_config_port(struct uart_port *port, int flags) +static void pl011_config_port(struct uart_port *port, int flags)  {  	if (flags & UART_CONFIG_TYPE) {  		port->type = PORT_AMBA; -		pl010_request_port(port); +		pl011_request_port(port);  	}  }  /*   * verify the new serial_struct (for TIOCSSERIAL).   */ -static int pl010_verify_port(struct uart_port *port, struct serial_struct *ser) +static int pl011_verify_port(struct uart_port *port, struct serial_struct *ser)  {  	int ret = 0;  	if (ser->type != PORT_UNKNOWN && ser->type != PORT_AMBA) @@ -1678,9 +1678,9 @@ static int pl010_verify_port(struct uart_port *port, struct serial_struct *ser)  }  static struct uart_ops amba_pl011_pops = { -	.tx_empty	= pl01x_tx_empty, +	.tx_empty	= pl011_tx_empty,  	.set_mctrl	= pl011_set_mctrl, -	.get_mctrl	= pl01x_get_mctrl, +	.get_mctrl	= pl011_get_mctrl,  	.stop_tx	= pl011_stop_tx,  	.start_tx	= pl011_start_tx,  	.stop_rx	= pl011_stop_rx, @@ -1691,13 +1691,13 @@ static struct uart_ops amba_pl011_pops = {  	.flush_buffer	= pl011_dma_flush_buffer,  	.set_termios	= pl011_set_termios,  	.type		= pl011_type, -	.release_port	= pl010_release_port, -	.request_port	= pl010_request_port, -	.config_port	= pl010_config_port, -	.verify_port	= pl010_verify_port, +	.release_port	= pl011_release_port, +	.request_port	= pl011_request_port, +	.config_port	= pl011_config_port, +	.verify_port	= pl011_verify_port,  #ifdef CONFIG_CONSOLE_POLL -	.poll_get_char = pl010_get_poll_char, -	.poll_put_char = pl010_put_poll_char, +	.poll_get_char = pl011_get_poll_char, +	.poll_put_char = pl011_put_poll_char,  #endif  }; diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c index 80b6b1b1f725..7264d4d26717 100644 --- a/drivers/tty/serial/crisv10.c +++ b/drivers/tty/serial/crisv10.c @@ -3976,7 +3976,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,  	 */  	if (tty_hung_up_p(filp) ||  	    (info->flags & ASYNC_CLOSING)) { -		wait_event_interruptible_tty(info->close_wait, +		wait_event_interruptible_tty(tty, info->close_wait,  			!(info->flags & ASYNC_CLOSING));  #ifdef SERIAL_DO_RESTART  		if (info->flags & ASYNC_HUP_NOTIFY) @@ -4052,9 +4052,9 @@ block_til_ready(struct tty_struct *tty, struct file * filp,  		printk("block_til_ready blocking: ttyS%d, count = %d\n",  		       info->line, info->count);  #endif -		tty_unlock(); +		tty_unlock(tty);  		schedule(); -		tty_lock(); +		tty_lock(tty);  	}  	set_current_state(TASK_RUNNING);  	remove_wait_queue(&info->open_wait, &wait); @@ -4115,7 +4115,7 @@ rs_open(struct tty_struct *tty, struct file * filp)  	 */  	if (tty_hung_up_p(filp) ||  	    (info->flags & ASYNC_CLOSING)) { -		wait_event_interruptible_tty(info->close_wait, +		wait_event_interruptible_tty(tty, info->close_wait,  			!(info->flags & ASYNC_CLOSING));  #ifdef SERIAL_DO_RESTART  		return ((info->flags & ASYNC_HUP_NOTIFY) ? diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 4ef747307ecb..0af4eec8c7b1 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -207,7 +207,7 @@ struct imx_port {  	unsigned short		trcv_delay; /* transceiver delay */  	struct clk		*clk_ipg;  	struct clk		*clk_per; -	struct imx_uart_data	*devdata; +	const struct imx_uart_data *devdata;  };  struct imx_port_ucrs { diff --git a/drivers/tty/serial/lpc32xx_hs.c b/drivers/tty/serial/lpc32xx_hs.c new file mode 100644 index 000000000000..ba3af3bf6d43 --- /dev/null +++ b/drivers/tty/serial/lpc32xx_hs.c @@ -0,0 +1,823 @@ +/* + * High Speed Serial Ports on NXP LPC32xx SoC + * + * Authors: Kevin Wells <kevin.wells@nxp.com> + *          Roland Stigge <stigge@antcom.de> + * + * Copyright (C) 2010 NXP Semiconductors + * Copyright (C) 2012 Roland Stigge + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + */ + +#include <linux/module.h> +#include <linux/ioport.h> +#include <linux/init.h> +#include <linux/console.h> +#include <linux/sysrq.h> +#include <linux/tty.h> +#include <linux/tty_flip.h> +#include <linux/serial_core.h> +#include <linux/serial.h> +#include <linux/platform_device.h> +#include <linux/delay.h> +#include <linux/nmi.h> +#include <linux/io.h> +#include <linux/irq.h> +#include <linux/gpio.h> +#include <linux/of.h> +#include <mach/platform.h> +#include <mach/hardware.h> + +/* + * High Speed UART register offsets + */ +#define LPC32XX_HSUART_FIFO(x)			((x) + 0x00) +#define LPC32XX_HSUART_LEVEL(x)			((x) + 0x04) +#define LPC32XX_HSUART_IIR(x)			((x) + 0x08) +#define LPC32XX_HSUART_CTRL(x)			((x) + 0x0C) +#define LPC32XX_HSUART_RATE(x)			((x) + 0x10) + +#define LPC32XX_HSU_BREAK_DATA			(1 << 10) +#define LPC32XX_HSU_ERROR_DATA			(1 << 9) +#define LPC32XX_HSU_RX_EMPTY			(1 << 8) + +#define LPC32XX_HSU_TX_LEV(n)			(((n) >> 8) & 0xFF) +#define LPC32XX_HSU_RX_LEV(n)			((n) & 0xFF) + +#define LPC32XX_HSU_TX_INT_SET			(1 << 6) +#define LPC32XX_HSU_RX_OE_INT			(1 << 5) +#define LPC32XX_HSU_BRK_INT			(1 << 4) +#define LPC32XX_HSU_FE_INT			(1 << 3) +#define LPC32XX_HSU_RX_TIMEOUT_INT		(1 << 2) +#define LPC32XX_HSU_RX_TRIG_INT			(1 << 1) +#define LPC32XX_HSU_TX_INT			(1 << 0) + +#define LPC32XX_HSU_HRTS_INV			(1 << 21) +#define LPC32XX_HSU_HRTS_TRIG_8B		(0x0 << 19) +#define LPC32XX_HSU_HRTS_TRIG_16B		(0x1 << 19) +#define LPC32XX_HSU_HRTS_TRIG_32B		(0x2 << 19) +#define LPC32XX_HSU_HRTS_TRIG_48B		(0x3 << 19) +#define LPC32XX_HSU_HRTS_EN			(1 << 18) +#define LPC32XX_HSU_TMO_DISABLED		(0x0 << 16) +#define LPC32XX_HSU_TMO_INACT_4B		(0x1 << 16) +#define LPC32XX_HSU_TMO_INACT_8B		(0x2 << 16) +#define LPC32XX_HSU_TMO_INACT_16B		(0x3 << 16) +#define LPC32XX_HSU_HCTS_INV			(1 << 15) +#define LPC32XX_HSU_HCTS_EN			(1 << 14) +#define LPC32XX_HSU_OFFSET(n)			((n) << 9) +#define LPC32XX_HSU_BREAK			(1 << 8) +#define LPC32XX_HSU_ERR_INT_EN			(1 << 7) +#define LPC32XX_HSU_RX_INT_EN			(1 << 6) +#define LPC32XX_HSU_TX_INT_EN			(1 << 5) +#define LPC32XX_HSU_RX_TL1B			(0x0 << 2) +#define LPC32XX_HSU_RX_TL4B			(0x1 << 2) +#define LPC32XX_HSU_RX_TL8B			(0x2 << 2) +#define LPC32XX_HSU_RX_TL16B			(0x3 << 2) +#define LPC32XX_HSU_RX_TL32B			(0x4 << 2) +#define LPC32XX_HSU_RX_TL48B			(0x5 << 2) +#define LPC32XX_HSU_TX_TLEMPTY			(0x0 << 0) +#define LPC32XX_HSU_TX_TL0B			(0x0 << 0) +#define LPC32XX_HSU_TX_TL4B			(0x1 << 0) +#define LPC32XX_HSU_TX_TL8B			(0x2 << 0) +#define LPC32XX_HSU_TX_TL16B			(0x3 << 0) + +#define MODNAME "lpc32xx_hsuart" + +struct lpc32xx_hsuart_port { +	struct uart_port port; +}; + +#define FIFO_READ_LIMIT 128 +#define MAX_PORTS 3 +#define LPC32XX_TTY_NAME "ttyTX" +static struct lpc32xx_hsuart_port lpc32xx_hs_ports[MAX_PORTS]; + +#ifdef CONFIG_SERIAL_HS_LPC32XX_CONSOLE +static void wait_for_xmit_empty(struct uart_port *port) +{ +	unsigned int timeout = 10000; + +	do { +		if (LPC32XX_HSU_TX_LEV(readl(LPC32XX_HSUART_LEVEL( +							port->membase))) == 0) +			break; +		if (--timeout == 0) +			break; +		udelay(1); +	} while (1); +} + +static void wait_for_xmit_ready(struct uart_port *port) +{ +	unsigned int timeout = 10000; + +	while (1) { +		if (LPC32XX_HSU_TX_LEV(readl(LPC32XX_HSUART_LEVEL( +							port->membase))) < 32) +			break; +		if (--timeout == 0) +			break; +		udelay(1); +	} +} + +static void lpc32xx_hsuart_console_putchar(struct uart_port *port, int ch) +{ +	wait_for_xmit_ready(port); +	writel((u32)ch, LPC32XX_HSUART_FIFO(port->membase)); +} + +static void lpc32xx_hsuart_console_write(struct console *co, const char *s, +					 unsigned int count) +{ +	struct lpc32xx_hsuart_port *up = &lpc32xx_hs_ports[co->index]; +	unsigned long flags; +	int locked = 1; + +	touch_nmi_watchdog(); +	local_irq_save(flags); +	if (up->port.sysrq) +		locked = 0; +	else if (oops_in_progress) +		locked = spin_trylock(&up->port.lock); +	else +		spin_lock(&up->port.lock); + +	uart_console_write(&up->port, s, count, lpc32xx_hsuart_console_putchar); +	wait_for_xmit_empty(&up->port); + +	if (locked) +		spin_unlock(&up->port.lock); +	local_irq_restore(flags); +} + +static int __init lpc32xx_hsuart_console_setup(struct console *co, +					       char *options) +{ +	struct uart_port *port; +	int baud = 115200; +	int bits = 8; +	int parity = 'n'; +	int flow = 'n'; + +	if (co->index >= MAX_PORTS) +		co->index = 0; + +	port = &lpc32xx_hs_ports[co->index].port; +	if (!port->membase) +		return -ENODEV; + +	if (options) +		uart_parse_options(options, &baud, &parity, &bits, &flow); + +	return uart_set_options(port, co, baud, parity, bits, flow); +} + +static struct uart_driver lpc32xx_hsuart_reg; +static struct console lpc32xx_hsuart_console = { +	.name		= LPC32XX_TTY_NAME, +	.write		= lpc32xx_hsuart_console_write, +	.device		= uart_console_device, +	.setup		= lpc32xx_hsuart_console_setup, +	.flags		= CON_PRINTBUFFER, +	.index		= -1, +	.data		= &lpc32xx_hsuart_reg, +}; + +static int __init lpc32xx_hsuart_console_init(void) +{ +	register_console(&lpc32xx_hsuart_console); +	return 0; +} +console_initcall(lpc32xx_hsuart_console_init); + +#define LPC32XX_HSUART_CONSOLE (&lpc32xx_hsuart_console) +#else +#define LPC32XX_HSUART_CONSOLE NULL +#endif + +static struct uart_driver lpc32xx_hs_reg = { +	.owner		= THIS_MODULE, +	.driver_name	= MODNAME, +	.dev_name	= LPC32XX_TTY_NAME, +	.nr		= MAX_PORTS, +	.cons		= LPC32XX_HSUART_CONSOLE, +}; +static int uarts_registered; + +static unsigned int __serial_get_clock_div(unsigned long uartclk, +					   unsigned long rate) +{ +	u32 div, goodrate, hsu_rate, l_hsu_rate, comprate; +	u32 rate_diff; + +	/* Find the closest divider to get the desired clock rate */ +	div = uartclk / rate; +	goodrate = hsu_rate = (div / 14) - 1; +	if (hsu_rate != 0) +		hsu_rate--; + +	/* Tweak divider */ +	l_hsu_rate = hsu_rate + 3; +	rate_diff = 0xFFFFFFFF; + +	while (hsu_rate < l_hsu_rate) { +		comprate = uartclk / ((hsu_rate + 1) * 14); +		if (abs(comprate - rate) < rate_diff) { +			goodrate = hsu_rate; +			rate_diff = abs(comprate - rate); +		} + +		hsu_rate++; +	} +	if (hsu_rate > 0xFF) +		hsu_rate = 0xFF; + +	return goodrate; +} + +static void __serial_uart_flush(struct uart_port *port) +{ +	u32 tmp; +	int cnt = 0; + +	while ((readl(LPC32XX_HSUART_LEVEL(port->membase)) > 0) && +	       (cnt++ < FIFO_READ_LIMIT)) +		tmp = readl(LPC32XX_HSUART_FIFO(port->membase)); +} + +static void __serial_lpc32xx_rx(struct uart_port *port) +{ +	unsigned int tmp, flag; +	struct tty_struct *tty = tty_port_tty_get(&port->state->port); + +	if (!tty) { +		/* Discard data: no tty available */ +		while (!(readl(LPC32XX_HSUART_FIFO(port->membase)) & +			 LPC32XX_HSU_RX_EMPTY)) +			; + +		return; +	} + +	/* Read data from FIFO and push into terminal */ +	tmp = readl(LPC32XX_HSUART_FIFO(port->membase)); +	while (!(tmp & LPC32XX_HSU_RX_EMPTY)) { +		flag = TTY_NORMAL; +		port->icount.rx++; + +		if (tmp & LPC32XX_HSU_ERROR_DATA) { +			/* Framing error */ +			writel(LPC32XX_HSU_FE_INT, +			       LPC32XX_HSUART_IIR(port->membase)); +			port->icount.frame++; +			flag = TTY_FRAME; +			tty_insert_flip_char(tty, 0, TTY_FRAME); +		} + +		tty_insert_flip_char(tty, (tmp & 0xFF), flag); + +		tmp = readl(LPC32XX_HSUART_FIFO(port->membase)); +	} +	tty_flip_buffer_push(tty); +	tty_kref_put(tty); +} + +static void __serial_lpc32xx_tx(struct uart_port *port) +{ +	struct circ_buf *xmit = &port->state->xmit; +	unsigned int tmp; + +	if (port->x_char) { +		writel((u32)port->x_char, LPC32XX_HSUART_FIFO(port->membase)); +		port->icount.tx++; +		port->x_char = 0; +		return; +	} + +	if (uart_circ_empty(xmit) || uart_tx_stopped(port)) +		goto exit_tx; + +	/* Transfer data */ +	while (LPC32XX_HSU_TX_LEV(readl( +		LPC32XX_HSUART_LEVEL(port->membase))) < 64) { +		writel((u32) xmit->buf[xmit->tail], +		       LPC32XX_HSUART_FIFO(port->membase)); +		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); +		port->icount.tx++; +		if (uart_circ_empty(xmit)) +			break; +	} + +	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) +		uart_write_wakeup(port); + +exit_tx: +	if (uart_circ_empty(xmit)) { +		tmp = readl(LPC32XX_HSUART_CTRL(port->membase)); +		tmp &= ~LPC32XX_HSU_TX_INT_EN; +		writel(tmp, LPC32XX_HSUART_CTRL(port->membase)); +	} +} + +static irqreturn_t serial_lpc32xx_interrupt(int irq, void *dev_id) +{ +	struct uart_port *port = dev_id; +	struct tty_struct *tty = tty_port_tty_get(&port->state->port); +	u32 status; + +	spin_lock(&port->lock); + +	/* Read UART status and clear latched interrupts */ +	status = readl(LPC32XX_HSUART_IIR(port->membase)); + +	if (status & LPC32XX_HSU_BRK_INT) { +		/* Break received */ +		writel(LPC32XX_HSU_BRK_INT, LPC32XX_HSUART_IIR(port->membase)); +		port->icount.brk++; +		uart_handle_break(port); +	} + +	/* Framing error */ +	if (status & LPC32XX_HSU_FE_INT) +		writel(LPC32XX_HSU_FE_INT, LPC32XX_HSUART_IIR(port->membase)); + +	if (status & LPC32XX_HSU_RX_OE_INT) { +		/* Receive FIFO overrun */ +		writel(LPC32XX_HSU_RX_OE_INT, +		       LPC32XX_HSUART_IIR(port->membase)); +		port->icount.overrun++; +		if (tty) { +			tty_insert_flip_char(tty, 0, TTY_OVERRUN); +			tty_schedule_flip(tty); +		} +	} + +	/* Data received? */ +	if (status & (LPC32XX_HSU_RX_TIMEOUT_INT | LPC32XX_HSU_RX_TRIG_INT)) { +		__serial_lpc32xx_rx(port); +		if (tty) +			tty_flip_buffer_push(tty); +	} + +	/* Transmit data request? */ +	if ((status & LPC32XX_HSU_TX_INT) && (!uart_tx_stopped(port))) { +		writel(LPC32XX_HSU_TX_INT, LPC32XX_HSUART_IIR(port->membase)); +		__serial_lpc32xx_tx(port); +	} + +	spin_unlock(&port->lock); +	tty_kref_put(tty); + +	return IRQ_HANDLED; +} + +/* port->lock is not held.  */ +static unsigned int serial_lpc32xx_tx_empty(struct uart_port *port) +{ +	unsigned int ret = 0; + +	if (LPC32XX_HSU_TX_LEV(readl(LPC32XX_HSUART_LEVEL(port->membase))) == 0) +		ret = TIOCSER_TEMT; + +	return ret; +} + +/* port->lock held by caller.  */ +static void serial_lpc32xx_set_mctrl(struct uart_port *port, +				     unsigned int mctrl) +{ +	/* No signals are supported on HS UARTs */ +} + +/* port->lock is held by caller and interrupts are disabled.  */ +static unsigned int serial_lpc32xx_get_mctrl(struct uart_port *port) +{ +	/* No signals are supported on HS UARTs */ +	return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS; +} + +/* port->lock held by caller.  */ +static void serial_lpc32xx_stop_tx(struct uart_port *port) +{ +	u32 tmp; + +	tmp = readl(LPC32XX_HSUART_CTRL(port->membase)); +	tmp &= ~LPC32XX_HSU_TX_INT_EN; +	writel(tmp, LPC32XX_HSUART_CTRL(port->membase)); +} + +/* port->lock held by caller.  */ +static void serial_lpc32xx_start_tx(struct uart_port *port) +{ +	u32 tmp; + +	__serial_lpc32xx_tx(port); +	tmp = readl(LPC32XX_HSUART_CTRL(port->membase)); +	tmp |= LPC32XX_HSU_TX_INT_EN; +	writel(tmp, LPC32XX_HSUART_CTRL(port->membase)); +} + +/* port->lock held by caller.  */ +static void serial_lpc32xx_stop_rx(struct uart_port *port) +{ +	u32 tmp; + +	tmp = readl(LPC32XX_HSUART_CTRL(port->membase)); +	tmp &= ~(LPC32XX_HSU_RX_INT_EN | LPC32XX_HSU_ERR_INT_EN); +	writel(tmp, LPC32XX_HSUART_CTRL(port->membase)); + +	writel((LPC32XX_HSU_BRK_INT | LPC32XX_HSU_RX_OE_INT | +		LPC32XX_HSU_FE_INT), LPC32XX_HSUART_IIR(port->membase)); +} + +/* port->lock held by caller.  */ +static void serial_lpc32xx_enable_ms(struct uart_port *port) +{ +	/* Modem status is not supported */ +} + +/* port->lock is not held.  */ +static void serial_lpc32xx_break_ctl(struct uart_port *port, +				     int break_state) +{ +	unsigned long flags; +	u32 tmp; + +	spin_lock_irqsave(&port->lock, flags); +	tmp = readl(LPC32XX_HSUART_CTRL(port->membase)); +	if (break_state != 0) +		tmp |= LPC32XX_HSU_BREAK; +	else +		tmp &= ~LPC32XX_HSU_BREAK; +	writel(tmp, LPC32XX_HSUART_CTRL(port->membase)); +	spin_unlock_irqrestore(&port->lock, flags); +} + +/* LPC3250 Errata HSUART.1: Hang workaround via loopback mode on inactivity */ +static void lpc32xx_loopback_set(resource_size_t mapbase, int state) +{ +	int bit; +	u32 tmp; + +	switch (mapbase) { +	case LPC32XX_HS_UART1_BASE: +		bit = 0; +		break; +	case LPC32XX_HS_UART2_BASE: +		bit = 1; +		break; +	case LPC32XX_HS_UART7_BASE: +		bit = 6; +		break; +	default: +		WARN(1, "lpc32xx_hs: Warning: Unknown port at %08x\n", mapbase); +		return; +	} + +	tmp = readl(LPC32XX_UARTCTL_CLOOP); +	if (state) +		tmp |= (1 << bit); +	else +		tmp &= ~(1 << bit); +	writel(tmp, LPC32XX_UARTCTL_CLOOP); +} + +/* port->lock is not held.  */ +static int serial_lpc32xx_startup(struct uart_port *port) +{ +	int retval; +	unsigned long flags; +	u32 tmp; + +	spin_lock_irqsave(&port->lock, flags); + +	__serial_uart_flush(port); + +	writel((LPC32XX_HSU_TX_INT | LPC32XX_HSU_FE_INT | +		LPC32XX_HSU_BRK_INT | LPC32XX_HSU_RX_OE_INT), +	       LPC32XX_HSUART_IIR(port->membase)); + +	writel(0xFF, LPC32XX_HSUART_RATE(port->membase)); + +	/* +	 * Set receiver timeout, HSU offset of 20, no break, no interrupts, +	 * and default FIFO trigger levels +	 */ +	tmp = LPC32XX_HSU_TX_TL8B | LPC32XX_HSU_RX_TL32B | +		LPC32XX_HSU_OFFSET(20) | LPC32XX_HSU_TMO_INACT_4B; +	writel(tmp, LPC32XX_HSUART_CTRL(port->membase)); + +	lpc32xx_loopback_set(port->mapbase, 0); /* get out of loopback mode */ + +	spin_unlock_irqrestore(&port->lock, flags); + +	retval = request_irq(port->irq, serial_lpc32xx_interrupt, +			     0, MODNAME, port); +	if (!retval) +		writel((tmp | LPC32XX_HSU_RX_INT_EN | LPC32XX_HSU_ERR_INT_EN), +		       LPC32XX_HSUART_CTRL(port->membase)); + +	return retval; +} + +/* port->lock is not held.  */ +static void serial_lpc32xx_shutdown(struct uart_port *port) +{ +	u32 tmp; +	unsigned long flags; + +	spin_lock_irqsave(&port->lock, flags); + +	tmp = LPC32XX_HSU_TX_TL8B | LPC32XX_HSU_RX_TL32B | +		LPC32XX_HSU_OFFSET(20) | LPC32XX_HSU_TMO_INACT_4B; +	writel(tmp, LPC32XX_HSUART_CTRL(port->membase)); + +	lpc32xx_loopback_set(port->mapbase, 1); /* go to loopback mode */ + +	spin_unlock_irqrestore(&port->lock, flags); + +	free_irq(port->irq, port); +} + +/* port->lock is not held.  */ +static void serial_lpc32xx_set_termios(struct uart_port *port, +				       struct ktermios *termios, +				       struct ktermios *old) +{ +	unsigned long flags; +	unsigned int baud, quot; +	u32 tmp; + +	/* Always 8-bit, no parity, 1 stop bit */ +	termios->c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD); +	termios->c_cflag |= CS8; + +	termios->c_cflag &= ~(HUPCL | CMSPAR | CLOCAL | CRTSCTS); + +	baud = uart_get_baud_rate(port, termios, old, 0, +				  port->uartclk / 14); + +	quot = __serial_get_clock_div(port->uartclk, baud); + +	spin_lock_irqsave(&port->lock, flags); + +	/* Ignore characters? */ +	tmp = readl(LPC32XX_HSUART_CTRL(port->membase)); +	if ((termios->c_cflag & CREAD) == 0) +		tmp &= ~(LPC32XX_HSU_RX_INT_EN | LPC32XX_HSU_ERR_INT_EN); +	else +		tmp |= LPC32XX_HSU_RX_INT_EN | LPC32XX_HSU_ERR_INT_EN; +	writel(tmp, LPC32XX_HSUART_CTRL(port->membase)); + +	writel(quot, LPC32XX_HSUART_RATE(port->membase)); + +	uart_update_timeout(port, termios->c_cflag, baud); + +	spin_unlock_irqrestore(&port->lock, flags); + +	/* Don't rewrite B0 */ +	if (tty_termios_baud_rate(termios)) +		tty_termios_encode_baud_rate(termios, baud, baud); +} + +static const char *serial_lpc32xx_type(struct uart_port *port) +{ +	return MODNAME; +} + +static void serial_lpc32xx_release_port(struct uart_port *port) +{ +	if ((port->iotype == UPIO_MEM32) && (port->mapbase)) { +		if (port->flags & UPF_IOREMAP) { +			iounmap(port->membase); +			port->membase = NULL; +		} + +		release_mem_region(port->mapbase, SZ_4K); +	} +} + +static int serial_lpc32xx_request_port(struct uart_port *port) +{ +	int ret = -ENODEV; + +	if ((port->iotype == UPIO_MEM32) && (port->mapbase)) { +		ret = 0; + +		if (!request_mem_region(port->mapbase, SZ_4K, MODNAME)) +			ret = -EBUSY; +		else if (port->flags & UPF_IOREMAP) { +			port->membase = ioremap(port->mapbase, SZ_4K); +			if (!port->membase) { +				release_mem_region(port->mapbase, SZ_4K); +				ret = -ENOMEM; +			} +		} +	} + +	return ret; +} + +static void serial_lpc32xx_config_port(struct uart_port *port, int uflags) +{ +	int ret; + +	ret = serial_lpc32xx_request_port(port); +	if (ret < 0) +		return; +	port->type = PORT_UART00; +	port->fifosize = 64; + +	__serial_uart_flush(port); + +	writel((LPC32XX_HSU_TX_INT | LPC32XX_HSU_FE_INT | +		LPC32XX_HSU_BRK_INT | LPC32XX_HSU_RX_OE_INT), +	       LPC32XX_HSUART_IIR(port->membase)); + +	writel(0xFF, LPC32XX_HSUART_RATE(port->membase)); + +	/* Set receiver timeout, HSU offset of 20, no break, no interrupts, +	   and default FIFO trigger levels */ +	writel(LPC32XX_HSU_TX_TL8B | LPC32XX_HSU_RX_TL32B | +	       LPC32XX_HSU_OFFSET(20) | LPC32XX_HSU_TMO_INACT_4B, +	       LPC32XX_HSUART_CTRL(port->membase)); +} + +static int serial_lpc32xx_verify_port(struct uart_port *port, +				      struct serial_struct *ser) +{ +	int ret = 0; + +	if (ser->type != PORT_UART00) +		ret = -EINVAL; + +	return ret; +} + +static struct uart_ops serial_lpc32xx_pops = { +	.tx_empty	= serial_lpc32xx_tx_empty, +	.set_mctrl	= serial_lpc32xx_set_mctrl, +	.get_mctrl	= serial_lpc32xx_get_mctrl, +	.stop_tx	= serial_lpc32xx_stop_tx, +	.start_tx	= serial_lpc32xx_start_tx, +	.stop_rx	= serial_lpc32xx_stop_rx, +	.enable_ms	= serial_lpc32xx_enable_ms, +	.break_ctl	= serial_lpc32xx_break_ctl, +	.startup	= serial_lpc32xx_startup, +	.shutdown	= serial_lpc32xx_shutdown, +	.set_termios	= serial_lpc32xx_set_termios, +	.type		= serial_lpc32xx_type, +	.release_port	= serial_lpc32xx_release_port, +	.request_port	= serial_lpc32xx_request_port, +	.config_port	= serial_lpc32xx_config_port, +	.verify_port	= serial_lpc32xx_verify_port, +}; + +/* + * Register a set of serial devices attached to a platform device + */ +static int __devinit serial_hs_lpc32xx_probe(struct platform_device *pdev) +{ +	struct lpc32xx_hsuart_port *p = &lpc32xx_hs_ports[uarts_registered]; +	int ret = 0; +	struct resource *res; + +	if (uarts_registered >= MAX_PORTS) { +		dev_err(&pdev->dev, +			"Error: Number of possible ports exceeded (%d)!\n", +			uarts_registered + 1); +		return -ENXIO; +	} + +	memset(p, 0, sizeof(*p)); + +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	if (!res) { +		dev_err(&pdev->dev, +			"Error getting mem resource for HS UART port %d\n", +			uarts_registered); +		return -ENXIO; +	} +	p->port.mapbase = res->start; +	p->port.membase = NULL; + +	p->port.irq = platform_get_irq(pdev, 0); +	if (p->port.irq < 0) { +		dev_err(&pdev->dev, "Error getting irq for HS UART port %d\n", +			uarts_registered); +		return p->port.irq; +	} + +	p->port.iotype = UPIO_MEM32; +	p->port.uartclk = LPC32XX_MAIN_OSC_FREQ; +	p->port.regshift = 2; +	p->port.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_IOREMAP; +	p->port.dev = &pdev->dev; +	p->port.ops = &serial_lpc32xx_pops; +	p->port.line = uarts_registered++; +	spin_lock_init(&p->port.lock); + +	/* send port to loopback mode by default */ +	lpc32xx_loopback_set(p->port.mapbase, 1); + +	ret = uart_add_one_port(&lpc32xx_hs_reg, &p->port); + +	platform_set_drvdata(pdev, p); + +	return ret; +} + +/* + * Remove serial ports registered against a platform device. + */ +static int __devexit serial_hs_lpc32xx_remove(struct platform_device *pdev) +{ +	struct lpc32xx_hsuart_port *p = platform_get_drvdata(pdev); + +	uart_remove_one_port(&lpc32xx_hs_reg, &p->port); + +	return 0; +} + + +#ifdef CONFIG_PM +static int serial_hs_lpc32xx_suspend(struct platform_device *pdev, +				     pm_message_t state) +{ +	struct lpc32xx_hsuart_port *p = platform_get_drvdata(pdev); + +	uart_suspend_port(&lpc32xx_hs_reg, &p->port); + +	return 0; +} + +static int serial_hs_lpc32xx_resume(struct platform_device *pdev) +{ +	struct lpc32xx_hsuart_port *p = platform_get_drvdata(pdev); + +	uart_resume_port(&lpc32xx_hs_reg, &p->port); + +	return 0; +} +#else +#define serial_hs_lpc32xx_suspend	NULL +#define serial_hs_lpc32xx_resume	NULL +#endif + +static const struct of_device_id serial_hs_lpc32xx_dt_ids[] = { +	{ .compatible = "nxp,lpc3220-hsuart" }, +	{ /* sentinel */ } +}; + +MODULE_DEVICE_TABLE(of, serial_hs_lpc32xx_dt_ids); + +static struct platform_driver serial_hs_lpc32xx_driver = { +	.probe		= serial_hs_lpc32xx_probe, +	.remove		= __devexit_p(serial_hs_lpc32xx_remove), +	.suspend	= serial_hs_lpc32xx_suspend, +	.resume		= serial_hs_lpc32xx_resume, +	.driver		= { +		.name	= MODNAME, +		.owner	= THIS_MODULE, +		.of_match_table	= serial_hs_lpc32xx_dt_ids, +	}, +}; + +static int __init lpc32xx_hsuart_init(void) +{ +	int ret; + +	ret = uart_register_driver(&lpc32xx_hs_reg); +	if (ret) +		return ret; + +	ret = platform_driver_register(&serial_hs_lpc32xx_driver); +	if (ret) +		uart_unregister_driver(&lpc32xx_hs_reg); + +	return ret; +} + +static void __exit lpc32xx_hsuart_exit(void) +{ +	platform_driver_unregister(&serial_hs_lpc32xx_driver); +	uart_unregister_driver(&lpc32xx_hs_reg); +} + +module_init(lpc32xx_hsuart_init); +module_exit(lpc32xx_hsuart_exit); + +MODULE_AUTHOR("Kevin Wells <kevin.wells@nxp.com>"); +MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>"); +MODULE_DESCRIPTION("NXP LPC32XX High Speed UART driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c index 5410c0637266..34e71874a892 100644 --- a/drivers/tty/serial/of_serial.c +++ b/drivers/tty/serial/of_serial.c @@ -208,6 +208,7 @@ static struct of_device_id __devinitdata of_platform_serial_table[] = {  	{ .compatible = "ns16750",  .data = (void *)PORT_16750, },  	{ .compatible = "ns16850",  .data = (void *)PORT_16850, },  	{ .compatible = "nvidia,tegra20-uart", .data = (void *)PORT_TEGRA, }, +	{ .compatible = "nxp,lpc3220-uart", .data = (void *)PORT_LPC3220, },  #ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL  	{ .compatible = "ibm,qpace-nwp-serial",  		.data = (void *)PORT_NWPSERIAL, }, diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 4fdec6a6b758..d291518a58a4 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -253,6 +253,9 @@ struct eg20t_port {  	dma_addr_t			rx_buf_dma;  	struct dentry	*debugfs; + +	/* protect the eg20t_port private structure and io access to membase */ +	spinlock_t lock;  };  /** @@ -1058,7 +1061,7 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id)  	int next = 1;  	u8 msr; -	spin_lock_irqsave(&priv->port.lock, flags); +	spin_lock_irqsave(&priv->lock, flags);  	handled = 0;  	while (next) {  		iid = pch_uart_hal_get_iid(priv); @@ -1116,7 +1119,7 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id)  		handled |= (unsigned int)ret;  	} -	spin_unlock_irqrestore(&priv->port.lock, flags); +	spin_unlock_irqrestore(&priv->lock, flags);  	return IRQ_RETVAL(handled);  } @@ -1226,9 +1229,9 @@ static void pch_uart_break_ctl(struct uart_port *port, int ctl)  	unsigned long flags;  	priv = container_of(port, struct eg20t_port, port); -	spin_lock_irqsave(&port->lock, flags); +	spin_lock_irqsave(&priv->lock, flags);  	pch_uart_hal_set_break(priv, ctl); -	spin_unlock_irqrestore(&port->lock, flags); +	spin_unlock_irqrestore(&priv->lock, flags);  }  /* Grab any interrupt resources and initialise any low level driver state. */ @@ -1376,7 +1379,8 @@ static void pch_uart_set_termios(struct uart_port *port,  	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16); -	spin_lock_irqsave(&port->lock, flags); +	spin_lock_irqsave(&priv->lock, flags); +	spin_lock(&port->lock);  	uart_update_timeout(port, termios->c_cflag, baud);  	rtn = pch_uart_hal_set_line(priv, baud, parity, bits, stb); @@ -1389,7 +1393,8 @@ static void pch_uart_set_termios(struct uart_port *port,  		tty_termios_encode_baud_rate(termios, baud, baud);  out: -	spin_unlock_irqrestore(&port->lock, flags); +	spin_unlock(&port->lock); +	spin_unlock_irqrestore(&priv->lock, flags);  }  static const char *pch_uart_type(struct uart_port *port) @@ -1538,8 +1543,9 @@ pch_console_write(struct console *co, const char *s, unsigned int count)  {  	struct eg20t_port *priv;  	unsigned long flags; +	int priv_locked = 1; +	int port_locked = 1;  	u8 ier; -	int locked = 1;  	priv = pch_uart_ports[co->index]; @@ -1547,12 +1553,16 @@ pch_console_write(struct console *co, const char *s, unsigned int count)  	local_irq_save(flags);  	if (priv->port.sysrq) { -		/* serial8250_handle_port() already took the lock */ -		locked = 0; +		spin_lock(&priv->lock); +		/* serial8250_handle_port() already took the port lock */ +		port_locked = 0;  	} else if (oops_in_progress) { -		locked = spin_trylock(&priv->port.lock); -	} else +		priv_locked = spin_trylock(&priv->lock); +		port_locked = spin_trylock(&priv->port.lock); +	} else { +		spin_lock(&priv->lock);  		spin_lock(&priv->port.lock); +	}  	/*  	 *	First save the IER then disable the interrupts @@ -1570,8 +1580,10 @@ pch_console_write(struct console *co, const char *s, unsigned int count)  	wait_for_xmitr(priv, BOTH_EMPTY);  	iowrite8(ier, priv->membase + UART_IER); -	if (locked) +	if (port_locked)  		spin_unlock(&priv->port.lock); +	if (priv_locked) +		spin_unlock(&priv->lock);  	local_irq_restore(flags);  } @@ -1669,6 +1681,8 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev,  	pci_enable_msi(pdev);  	pci_set_master(pdev); +	spin_lock_init(&priv->lock); +  	iobase = pci_resource_start(pdev, 0);  	mapbase = pci_resource_start(pdev, 1);  	priv->mapbase = mapbase; diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c index 5847a4b855f7..9033fc6e0e4e 100644 --- a/drivers/tty/serial/pxa.c +++ b/drivers/tty/serial/pxa.c @@ -670,9 +670,19 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count)  {  	struct uart_pxa_port *up = serial_pxa_ports[co->index];  	unsigned int ier; +	unsigned long flags; +	int locked = 1;  	clk_prepare_enable(up->clk); +	local_irq_save(flags); +	if (up->port.sysrq) +		locked = 0; +	else if (oops_in_progress) +		locked = spin_trylock(&up->port.lock); +	else +		spin_lock(&up->port.lock); +  	/*  	 *	First save the IER then disable the interrupts  	 */ @@ -688,6 +698,10 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count)  	wait_for_xmitr(up);  	serial_out(up, UART_IER, ier); +	if (locked) +		spin_unlock(&up->port.lock); +	local_irq_restore(flags); +  	clk_disable_unprepare(up->clk);  } diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index d8b0aee35632..d57f165d6be8 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c @@ -529,7 +529,7 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,  	switch (level) {  	case 3: -		if (!IS_ERR(ourport->baudclk) && ourport->baudclk != NULL) +		if (!IS_ERR(ourport->baudclk))  			clk_disable(ourport->baudclk);  		clk_disable(ourport->clk); @@ -538,7 +538,7 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,  	case 0:  		clk_enable(ourport->clk); -		if (!IS_ERR(ourport->baudclk) && ourport->baudclk != NULL) +		if (!IS_ERR(ourport->baudclk))  			clk_enable(ourport->baudclk);  		break; @@ -604,7 +604,6 @@ static unsigned int s3c24xx_serial_getclk(struct s3c24xx_uart_port *ourport,  	char clkname[MAX_CLK_NAME_LENGTH];  	int calc_deviation, deviation = (1 << 30) - 1; -	*best_clk = NULL;  	clk_sel = (ourport->cfg->clk_sel) ? ourport->cfg->clk_sel :  			ourport->info->def_clk_sel;  	for (cnt = 0; cnt < info->num_clks; cnt++) { @@ -613,7 +612,7 @@ static unsigned int s3c24xx_serial_getclk(struct s3c24xx_uart_port *ourport,  		sprintf(clkname, "clk_uart_baud%d", cnt);  		clk = clk_get(ourport->port.dev, clkname); -		if (IS_ERR_OR_NULL(clk)) +		if (IS_ERR(clk))  			continue;  		rate = clk_get_rate(clk); @@ -684,7 +683,7 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,  {  	struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port);  	struct s3c24xx_uart_port *ourport = to_ourport(port); -	struct clk *clk = NULL; +	struct clk *clk = ERR_PTR(-EINVAL);  	unsigned long flags;  	unsigned int baud, quot, clk_sel = 0;  	unsigned int ulcon; @@ -705,7 +704,7 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,  	quot = s3c24xx_serial_getclk(ourport, baud, &clk, &clk_sel);  	if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST)  		quot = port->custom_divisor; -	if (!clk) +	if (IS_ERR(clk))  		return;  	/* check to see if we need  to change clock source */ @@ -713,9 +712,9 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,  	if (ourport->baudclk != clk) {  		s3c24xx_serial_setsource(port, clk_sel); -		if (ourport->baudclk != NULL && !IS_ERR(ourport->baudclk)) { +		if (!IS_ERR(ourport->baudclk)) {  			clk_disable(ourport->baudclk); -			ourport->baudclk  = NULL; +			ourport->baudclk = ERR_PTR(-EINVAL);  		}  		clk_enable(clk); @@ -1014,10 +1013,10 @@ static int s3c24xx_serial_cpufreq_transition(struct notifier_block *nb,  	 * a disturbance in the clock-rate over the change.  	 */ -	if (IS_ERR(port->clk)) +	if (IS_ERR(port->baudclk))  		goto exit; -	if (port->baudclk_rate == clk_get_rate(port->clk)) +	if (port->baudclk_rate == clk_get_rate(port->baudclk))  		goto exit;  	if (val == CPUFREQ_PRECHANGE) { @@ -1160,7 +1159,11 @@ static ssize_t s3c24xx_serial_show_clksrc(struct device *dev,  	struct uart_port *port = s3c24xx_dev_to_port(dev);  	struct s3c24xx_uart_port *ourport = to_ourport(port); -	return snprintf(buf, PAGE_SIZE, "* %s\n", ourport->baudclk->name); +	if (IS_ERR(ourport->baudclk)) +		return -EINVAL; + +	return snprintf(buf, PAGE_SIZE, "* %s\n", +			ourport->baudclk->name ?: "(null)");  }  static DEVICE_ATTR(clock_source, S_IRUGO, s3c24xx_serial_show_clksrc, NULL); @@ -1200,6 +1203,7 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)  		return -ENODEV;  	} +	ourport->baudclk = ERR_PTR(-EINVAL);  	ourport->info = ourport->drv_data->info;  	ourport->cfg = (pdev->dev.platform_data) ?  			(struct s3c2410_uartcfg *)pdev->dev.platform_data : @@ -1387,7 +1391,7 @@ s3c24xx_serial_get_options(struct uart_port *port, int *baud,  		sprintf(clk_name, "clk_uart_baud%d", clk_sel);  		clk = clk_get(port->dev, clk_name); -		if (!IS_ERR(clk) && clk != NULL) +		if (!IS_ERR(clk))  			rate = clk_get_rate(clk);  		else  			rate = 1; diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 246b823c1b27..a21dc8e3b7c0 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -2527,14 +2527,16 @@ void uart_insert_char(struct uart_port *port, unsigned int status,  	struct tty_struct *tty = port->state->port.tty;  	if ((status & port->ignore_status_mask & ~overrun) == 0) -		tty_insert_flip_char(tty, ch, flag); +		if (tty_insert_flip_char(tty, ch, flag) == 0) +			++port->icount.buf_overrun;  	/*  	 * Overrun is special.  Since it's reported immediately,  	 * it doesn't affect the current character.  	 */  	if (status & ~port->ignore_status_mask & overrun) -		tty_insert_flip_char(tty, 0, TTY_OVERRUN); +		if (tty_insert_flip_char(tty, 0, TTY_OVERRUN) == 0) +			++port->icount.buf_overrun;  }  EXPORT_SYMBOL_GPL(uart_insert_char); diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c index 593d40ad0a6b..5ed0daae6564 100644 --- a/drivers/tty/synclink.c +++ b/drivers/tty/synclink.c @@ -3338,9 +3338,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,  			printk("%s(%d):block_til_ready blocking on %s count=%d\n",  				 __FILE__,__LINE__, tty->driver->name, port->count ); -		tty_unlock(); +		tty_unlock(tty);  		schedule(); -		tty_lock(); +		tty_lock(tty);  	}  	set_current_state(TASK_RUNNING); diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c index aa1debf97cc7..45b43f11ca39 100644 --- a/drivers/tty/synclink_gt.c +++ b/drivers/tty/synclink_gt.c @@ -3336,9 +3336,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,  		}  		DBGINFO(("%s block_til_ready wait\n", tty->driver->name)); -		tty_unlock(); +		tty_unlock(tty);  		schedule(); -		tty_lock(); +		tty_lock(tty);  	}  	set_current_state(TASK_RUNNING); diff --git a/drivers/tty/synclinkmp.c b/drivers/tty/synclinkmp.c index a3dddc12d2fe..4a1e4f07765b 100644 --- a/drivers/tty/synclinkmp.c +++ b/drivers/tty/synclinkmp.c @@ -3357,9 +3357,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,  			printk("%s(%d):%s block_til_ready() count=%d\n",  				 __FILE__,__LINE__, tty->driver->name, port->count ); -		tty_unlock(); +		tty_unlock(tty);  		schedule(); -		tty_lock(); +		tty_lock(tty);  	}  	set_current_state(TASK_RUNNING); diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index b425c79675ad..ca7c25d9f6d5 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -185,6 +185,7 @@ void free_tty_struct(struct tty_struct *tty)  		put_device(tty->dev);  	kfree(tty->write_buf);  	tty_buffer_free_all(tty); +	tty->magic = 0xDEADDEAD;  	kfree(tty);  } @@ -573,7 +574,7 @@ void __tty_hangup(struct tty_struct *tty)  	}  	spin_unlock(&redirect_lock); -	tty_lock(); +	tty_lock(tty);  	/* some functions below drop BTM, so we need this bit */  	set_bit(TTY_HUPPING, &tty->flags); @@ -666,7 +667,7 @@ void __tty_hangup(struct tty_struct *tty)  	clear_bit(TTY_HUPPING, &tty->flags);  	tty_ldisc_enable(tty); -	tty_unlock(); +	tty_unlock(tty);  	if (f)  		fput(f); @@ -1103,12 +1104,12 @@ void tty_write_message(struct tty_struct *tty, char *msg)  {  	if (tty) {  		mutex_lock(&tty->atomic_write_lock); -		tty_lock(); +		tty_lock(tty);  		if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) { -			tty_unlock(); +			tty_unlock(tty);  			tty->ops->write(tty, msg, strlen(msg));  		} else -			tty_unlock(); +			tty_unlock(tty);  		tty_write_unlock(tty);  	}  	return; @@ -1403,10 +1404,14 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx)  	}  	initialize_tty_struct(tty, driver, idx); +	tty_lock(tty);  	retval = tty_driver_install_tty(driver, tty);  	if (retval < 0)  		goto err_deinit_tty; +	if (!tty->port) +		tty->port = driver->ports[idx]; +  	/*  	 * Structures all installed ... call the ldisc open routines.  	 * If we fail here just call release_tty to clean up.  No need @@ -1415,9 +1420,11 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx)  	retval = tty_ldisc_setup(tty, tty->link);  	if (retval)  		goto err_release_tty; +	/* Return the tty locked so that it cannot vanish under the caller */  	return tty;  err_deinit_tty: +	tty_unlock(tty);  	deinitialize_tty_struct(tty);  	free_tty_struct(tty);  err_module_put: @@ -1426,6 +1433,7 @@ err_module_put:  	/* call the tty release_tty routine to clean out this slot */  err_release_tty: +	tty_unlock(tty);  	printk_ratelimited(KERN_INFO "tty_init_dev: ldisc open failed, "  				 "clearing slot %d\n", idx);  	release_tty(tty, idx); @@ -1628,7 +1636,7 @@ int tty_release(struct inode *inode, struct file *filp)  	if (tty_paranoia_check(tty, inode, __func__))  		return 0; -	tty_lock(); +	tty_lock(tty);  	check_tty_count(tty, __func__);  	__tty_fasync(-1, filp, 0); @@ -1637,10 +1645,11 @@ int tty_release(struct inode *inode, struct file *filp)  	pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY &&  		      tty->driver->subtype == PTY_TYPE_MASTER);  	devpts = (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) != 0; +	/* Review: parallel close */  	o_tty = tty->link;  	if (tty_release_checks(tty, o_tty, idx)) { -		tty_unlock(); +		tty_unlock(tty);  		return 0;  	} @@ -1652,7 +1661,7 @@ int tty_release(struct inode *inode, struct file *filp)  	if (tty->ops->close)  		tty->ops->close(tty, filp); -	tty_unlock(); +	tty_unlock(tty);  	/*  	 * Sanity check: if tty->count is going to zero, there shouldn't be  	 * any waiters on tty->read_wait or tty->write_wait.  We test the @@ -1675,7 +1684,7 @@ int tty_release(struct inode *inode, struct file *filp)  		   opens on /dev/tty */  		mutex_lock(&tty_mutex); -		tty_lock(); +		tty_lock_pair(tty, o_tty);  		tty_closing = tty->count <= 1;  		o_tty_closing = o_tty &&  			(o_tty->count <= (pty_master ? 1 : 0)); @@ -1706,7 +1715,7 @@ int tty_release(struct inode *inode, struct file *filp)  		printk(KERN_WARNING "%s: %s: read/write wait queue active!\n",  				__func__, tty_name(tty, buf)); -		tty_unlock(); +		tty_unlock_pair(tty, o_tty);  		mutex_unlock(&tty_mutex);  		schedule();  	} @@ -1769,7 +1778,7 @@ int tty_release(struct inode *inode, struct file *filp)  	/* check whether both sides are closing ... */  	if (!tty_closing || (o_tty && !o_tty_closing)) { -		tty_unlock(); +		tty_unlock_pair(tty, o_tty);  		return 0;  	} @@ -1782,14 +1791,16 @@ int tty_release(struct inode *inode, struct file *filp)  	tty_ldisc_release(tty, o_tty);  	/*  	 * The release_tty function takes care of the details of clearing -	 * the slots and preserving the termios structure. +	 * the slots and preserving the termios structure. The tty_unlock_pair +	 * should be safe as we keep a kref while the tty is locked (so the +	 * unlock never unlocks a freed tty).  	 */  	release_tty(tty, idx); +	tty_unlock_pair(tty, o_tty);  	/* Make this pty number available for reallocation */  	if (devpts)  		devpts_kill_index(inode, idx); -	tty_unlock();  	return 0;  } @@ -1893,6 +1904,9 @@ static struct tty_driver *tty_lookup_driver(dev_t device, struct file *filp,   *	Locking: tty_mutex protects tty, tty_lookup_driver and tty_init_dev.   *		 tty->count should protect the rest.   *		 ->siglock protects ->signal/->sighand + * + *	Note: the tty_unlock/lock cases without a ref are only safe due to + *	tty_mutex   */  static int tty_open(struct inode *inode, struct file *filp) @@ -1916,8 +1930,7 @@ retry_open:  	retval = 0;  	mutex_lock(&tty_mutex); -	tty_lock(); - +	/* This is protected by the tty_mutex */  	tty = tty_open_current_tty(device, filp);  	if (IS_ERR(tty)) {  		retval = PTR_ERR(tty); @@ -1938,17 +1951,19 @@ retry_open:  	}  	if (tty) { +		tty_lock(tty);  		retval = tty_reopen(tty); -		if (retval) +		if (retval < 0) { +			tty_unlock(tty);  			tty = ERR_PTR(retval); -	} else +		} +	} else	/* Returns with the tty_lock held for now */  		tty = tty_init_dev(driver, index);  	mutex_unlock(&tty_mutex);  	if (driver)  		tty_driver_kref_put(driver);  	if (IS_ERR(tty)) { -		tty_unlock();  		retval = PTR_ERR(tty);  		goto err_file;  	} @@ -1977,7 +1992,7 @@ retry_open:  		printk(KERN_DEBUG "%s: error %d in opening %s...\n", __func__,  				retval, tty->name);  #endif -		tty_unlock(); /* need to call tty_release without BTM */ +		tty_unlock(tty); /* need to call tty_release without BTM */  		tty_release(inode, filp);  		if (retval != -ERESTARTSYS)  			return retval; @@ -1989,17 +2004,15 @@ retry_open:  		/*  		 * Need to reset f_op in case a hangup happened.  		 */ -		tty_lock();  		if (filp->f_op == &hung_up_tty_fops)  			filp->f_op = &tty_fops; -		tty_unlock();  		goto retry_open;  	} -	tty_unlock(); +	tty_unlock(tty);  	mutex_lock(&tty_mutex); -	tty_lock(); +	tty_lock(tty);  	spin_lock_irq(¤t->sighand->siglock);  	if (!noctty &&  	    current->signal->leader && @@ -2007,11 +2020,10 @@ retry_open:  	    tty->session == NULL)  		__proc_set_tty(current, tty);  	spin_unlock_irq(¤t->sighand->siglock); -	tty_unlock(); +	tty_unlock(tty);  	mutex_unlock(&tty_mutex);  	return 0;  err_unlock: -	tty_unlock();  	mutex_unlock(&tty_mutex);  	/* after locks to avoid deadlock */  	if (!IS_ERR_OR_NULL(driver)) @@ -2094,10 +2106,13 @@ out:  static int tty_fasync(int fd, struct file *filp, int on)  { +	struct tty_struct *tty = file_tty(filp);  	int retval; -	tty_lock(); + +	tty_lock(tty);  	retval = __tty_fasync(fd, filp, on); -	tty_unlock(); +	tty_unlock(tty); +  	return retval;  } @@ -2934,6 +2949,7 @@ void initialize_tty_struct(struct tty_struct *tty,  	tty->pgrp = NULL;  	tty->overrun_time = jiffies;  	tty_buffer_init(tty); +	mutex_init(&tty->legacy_mutex);  	mutex_init(&tty->termios_mutex);  	mutex_init(&tty->ldisc_mutex);  	init_waitqueue_head(&tty->write_wait); @@ -3094,6 +3110,7 @@ static void destruct_tty_driver(struct kref *kref)  		kfree(p);  		cdev_del(&driver->cdev);  	} +	kfree(driver->ports);  	kfree(driver);  } @@ -3132,6 +3149,18 @@ int tty_register_driver(struct tty_driver *driver)  		if (!p)  			return -ENOMEM;  	} +	/* +	 * There is too many lines in PTY and we won't need the array there +	 * since it has an ->install hook where it assigns ports properly. +	 */ +	if (driver->type != TTY_DRIVER_TYPE_PTY) { +		driver->ports = kcalloc(driver->num, sizeof(struct tty_port *), +				GFP_KERNEL); +		if (!driver->ports) { +			error = -ENOMEM; +			goto err_free_p; +		} +	}  	if (!driver->major) {  		error = alloc_chrdev_region(&dev, driver->minor_start, @@ -3144,10 +3173,8 @@ int tty_register_driver(struct tty_driver *driver)  		dev = MKDEV(driver->major, driver->minor_start);  		error = register_chrdev_region(dev, driver->num, driver->name);  	} -	if (error < 0) { -		kfree(p); -		return error; -	} +	if (error < 0) +		goto err_free_p;  	if (p) {  		driver->ttys = (struct tty_struct **)p; @@ -3160,13 +3187,8 @@ int tty_register_driver(struct tty_driver *driver)  	cdev_init(&driver->cdev, &tty_fops);  	driver->cdev.owner = driver->owner;  	error = cdev_add(&driver->cdev, dev, driver->num); -	if (error) { -		unregister_chrdev_region(dev, driver->num); -		driver->ttys = NULL; -		driver->termios = NULL; -		kfree(p); -		return error; -	} +	if (error) +		goto err_unreg_char;  	mutex_lock(&tty_mutex);  	list_add(&driver->tty_drivers, &tty_drivers); @@ -3193,13 +3215,14 @@ err:  	list_del(&driver->tty_drivers);  	mutex_unlock(&tty_mutex); +err_unreg_char:  	unregister_chrdev_region(dev, driver->num);  	driver->ttys = NULL;  	driver->termios = NULL; +err_free_p: /* destruct_tty_driver will free driver->ports */  	kfree(p);  	return error;  } -  EXPORT_SYMBOL(tty_register_driver);  /* diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 9911eb6b34cd..847f7ed7a3ed 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -568,7 +568,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)  	if (IS_ERR(new_ldisc))  		return PTR_ERR(new_ldisc); -	tty_lock(); +	tty_lock(tty);  	/*  	 *	We need to look at the tty locking here for pty/tty pairs  	 *	when both sides try to change in parallel. @@ -582,12 +582,12 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)  	 */  	if (tty->ldisc->ops->num == ldisc) { -		tty_unlock(); +		tty_unlock(tty);  		tty_ldisc_put(new_ldisc);  		return 0;  	} -	tty_unlock(); +	tty_unlock(tty);  	/*  	 *	Problem: What do we do if this blocks ?  	 *	We could deadlock here @@ -595,7 +595,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)  	tty_wait_until_sent(tty, 0); -	tty_lock(); +	tty_lock(tty);  	mutex_lock(&tty->ldisc_mutex);  	/* @@ -605,10 +605,10 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)  	while (test_bit(TTY_LDISC_CHANGING, &tty->flags)) {  		mutex_unlock(&tty->ldisc_mutex); -		tty_unlock(); +		tty_unlock(tty);  		wait_event(tty_ldisc_wait,  			test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0); -		tty_lock(); +		tty_lock(tty);  		mutex_lock(&tty->ldisc_mutex);  	} @@ -623,7 +623,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)  	o_ldisc = tty->ldisc; -	tty_unlock(); +	tty_unlock(tty);  	/*  	 *	Make sure we don't change while someone holds a  	 *	reference to the line discipline. The TTY_LDISC bit @@ -650,7 +650,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)  	retval = tty_ldisc_wait_idle(tty, 5 * HZ); -	tty_lock(); +	tty_lock(tty);  	mutex_lock(&tty->ldisc_mutex);  	/* handle wait idle failure locked */ @@ -659,13 +659,13 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)  		goto enable;  	} -	if (test_bit(TTY_HUPPED, &tty->flags)) { +	if (test_bit(TTY_HUPPING, &tty->flags)) {  		/* We were raced by the hangup method. It will have stomped  		   the ldisc data and closed the ldisc down */  		clear_bit(TTY_LDISC_CHANGING, &tty->flags);  		mutex_unlock(&tty->ldisc_mutex);  		tty_ldisc_put(new_ldisc); -		tty_unlock(); +		tty_unlock(tty);  		return -EIO;  	} @@ -708,7 +708,7 @@ enable:  	if (o_work)  		schedule_work(&o_tty->buf.work);  	mutex_unlock(&tty->ldisc_mutex); -	tty_unlock(); +	tty_unlock(tty);  	return retval;  } @@ -816,11 +816,11 @@ void tty_ldisc_hangup(struct tty_struct *tty)  	 * need to wait for another function taking the BTM  	 */  	clear_bit(TTY_LDISC, &tty->flags); -	tty_unlock(); +	tty_unlock(tty);  	cancel_work_sync(&tty->buf.work);  	mutex_unlock(&tty->ldisc_mutex);  retry: -	tty_lock(); +	tty_lock(tty);  	mutex_lock(&tty->ldisc_mutex);  	/* At this point we have a closed ldisc and we want to @@ -831,7 +831,7 @@ retry:  		if (atomic_read(&tty->ldisc->users) != 1) {  			char cur_n[TASK_COMM_LEN], tty_n[64];  			long timeout = 3 * HZ; -			tty_unlock(); +			tty_unlock(tty);  			while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) {  				timeout = MAX_SCHEDULE_TIMEOUT; @@ -894,6 +894,23 @@ int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty)  	tty_ldisc_enable(tty);  	return 0;  } + +static void tty_ldisc_kill(struct tty_struct *tty) +{ +	mutex_lock(&tty->ldisc_mutex); +	/* +	 * Now kill off the ldisc +	 */ +	tty_ldisc_close(tty, tty->ldisc); +	tty_ldisc_put(tty->ldisc); +	/* Force an oops if we mess this up */ +	tty->ldisc = NULL; + +	/* Ensure the next open requests the N_TTY ldisc */ +	tty_set_termios_ldisc(tty, N_TTY); +	mutex_unlock(&tty->ldisc_mutex); +} +  /**   *	tty_ldisc_release		-	release line discipline   *	@tty: tty being shut down @@ -912,27 +929,19 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)  	 * race with the set_ldisc code path.  	 */ -	tty_unlock(); +	tty_unlock_pair(tty, o_tty);  	tty_ldisc_halt(tty);  	tty_ldisc_flush_works(tty); -	tty_lock(); - -	mutex_lock(&tty->ldisc_mutex); -	/* -	 * Now kill off the ldisc -	 */ -	tty_ldisc_close(tty, tty->ldisc); -	tty_ldisc_put(tty->ldisc); -	/* Force an oops if we mess this up */ -	tty->ldisc = NULL; +	if (o_tty) { +		tty_ldisc_halt(o_tty); +		tty_ldisc_flush_works(o_tty); +	} +	tty_lock_pair(tty, o_tty); -	/* Ensure the next open requests the N_TTY ldisc */ -	tty_set_termios_ldisc(tty, N_TTY); -	mutex_unlock(&tty->ldisc_mutex); -	/* This will need doing differently if we need to lock */ +	tty_ldisc_kill(tty);  	if (o_tty) -		tty_ldisc_release(o_tty, NULL); +		tty_ldisc_kill(o_tty);  	/* And the memory resources remaining (buffers, termios) will be  	   disposed of when the kref hits zero */ diff --git a/drivers/tty/tty_mutex.c b/drivers/tty/tty_mutex.c index 9ff986c32a21..67feac9e6ebb 100644 --- a/drivers/tty/tty_mutex.c +++ b/drivers/tty/tty_mutex.c @@ -4,29 +4,70 @@  #include <linux/semaphore.h>  #include <linux/sched.h> -/* - * The 'big tty mutex' - * - * This mutex is taken and released by tty_lock() and tty_unlock(), - * replacing the older big kernel lock. - * It can no longer be taken recursively, and does not get - * released implicitly while sleeping. - * - * Don't use in new code. - */ -static DEFINE_MUTEX(big_tty_mutex); +/* Legacy tty mutex glue */ + +enum { +	TTY_MUTEX_NORMAL, +	TTY_MUTEX_NESTED, +};  /*   * Getting the big tty mutex.   */ -void __lockfunc tty_lock(void) + +static void __lockfunc tty_lock_nested(struct tty_struct *tty, +				       unsigned int subclass)  { -	mutex_lock(&big_tty_mutex); +	if (tty->magic != TTY_MAGIC) { +		printk(KERN_ERR "L Bad %p\n", tty); +		WARN_ON(1); +		return; +	} +	tty_kref_get(tty); +	mutex_lock_nested(&tty->legacy_mutex, subclass); +} + +void __lockfunc tty_lock(struct tty_struct *tty) +{ +	return tty_lock_nested(tty, TTY_MUTEX_NORMAL);  }  EXPORT_SYMBOL(tty_lock); -void __lockfunc tty_unlock(void) +void __lockfunc tty_unlock(struct tty_struct *tty)  { -	mutex_unlock(&big_tty_mutex); +	if (tty->magic != TTY_MAGIC) { +		printk(KERN_ERR "U Bad %p\n", tty); +		WARN_ON(1); +		return; +	} +	mutex_unlock(&tty->legacy_mutex); +	tty_kref_put(tty);  }  EXPORT_SYMBOL(tty_unlock); + +/* + * Getting the big tty mutex for a pair of ttys with lock ordering + * On a non pty/tty pair tty2 can be NULL which is just fine. + */ +void __lockfunc tty_lock_pair(struct tty_struct *tty, +					struct tty_struct *tty2) +{ +	if (tty < tty2) { +		tty_lock(tty); +		tty_lock_nested(tty2, TTY_MUTEX_NESTED); +	} else { +		if (tty2 && tty2 != tty) +			tty_lock(tty2); +		tty_lock_nested(tty, TTY_MUTEX_NESTED); +	} +} +EXPORT_SYMBOL(tty_lock_pair); + +void __lockfunc tty_unlock_pair(struct tty_struct *tty, +						struct tty_struct *tty2) +{ +	tty_unlock(tty); +	if (tty2 && tty2 != tty) +		tty_unlock(tty2); +} +EXPORT_SYMBOL(tty_unlock_pair); diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index bf6e238146ae..a3ba776c574c 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c @@ -33,6 +33,15 @@ void tty_port_init(struct tty_port *port)  }  EXPORT_SYMBOL(tty_port_init); +struct device *tty_port_register_device(struct tty_port *port, +		struct tty_driver *driver, unsigned index, +		struct device *device) +{ +	driver->ports[index] = port; +	return tty_register_device(driver, index, device); +} +EXPORT_SYMBOL_GPL(tty_port_register_device); +  int tty_port_alloc_xmit_buf(struct tty_port *port)  {  	/* We may sleep in get_zeroed_page() */ @@ -230,7 +239,7 @@ int tty_port_block_til_ready(struct tty_port *port,  	/* block if port is in the process of being closed */  	if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { -		wait_event_interruptible_tty(port->close_wait, +		wait_event_interruptible_tty(tty, port->close_wait,  				!(port->flags & ASYNC_CLOSING));  		if (port->flags & ASYNC_HUP_NOTIFY)  			return -EAGAIN; @@ -296,9 +305,9 @@ int tty_port_block_til_ready(struct tty_port *port,  			retval = -ERESTARTSYS;  			break;  		} -		tty_unlock(); +		tty_unlock(tty);  		schedule(); -		tty_lock(); +		tty_lock(tty);  	}  	finish_wait(&port->open_wait, &wait); @@ -413,6 +422,14 @@ void tty_port_close(struct tty_port *port, struct tty_struct *tty,  }  EXPORT_SYMBOL(tty_port_close); +int tty_port_install(struct tty_port *port, struct tty_driver *driver, +		struct tty_struct *tty) +{ +	tty->port = port; +	return tty_standard_install(driver, tty); +} +EXPORT_SYMBOL_GPL(tty_port_install); +  int tty_port_open(struct tty_port *port, struct tty_struct *tty,  							struct file *filp)  { diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c index 48cc6f25cfd3..9b4f60a6ab0e 100644 --- a/drivers/tty/vt/keyboard.c +++ b/drivers/tty/vt/keyboard.c @@ -310,7 +310,7 @@ static void put_queue(struct vc_data *vc, int ch)  	if (tty) {  		tty_insert_flip_char(tty, ch, 0); -		con_schedule_flip(tty); +		tty_schedule_flip(tty);  	}  } @@ -325,7 +325,7 @@ static void puts_queue(struct vc_data *vc, char *cp)  		tty_insert_flip_char(tty, *cp, 0);  		cp++;  	} -	con_schedule_flip(tty); +	tty_schedule_flip(tty);  }  static void applkey(struct vc_data *vc, int key, char mode) @@ -586,7 +586,7 @@ static void fn_send_intr(struct vc_data *vc)  	if (!tty)  		return;  	tty_insert_flip_char(tty, 0, TTY_BREAK); -	con_schedule_flip(tty); +	tty_schedule_flip(tty);  }  static void fn_scroll_forw(struct vc_data *vc) @@ -1049,13 +1049,10 @@ static int kbd_update_leds_helper(struct input_handle *handle, void *data)   */  int vt_get_leds(int console, int flag)  { -	unsigned long flags;  	struct kbd_struct * kbd = kbd_table + console;  	int ret; -	spin_lock_irqsave(&kbd_event_lock, flags);  	ret = vc_kbd_led(kbd, flag); -	spin_unlock_irqrestore(&kbd_event_lock, flags);  	return ret;  } diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 84cbf298c094..7cb53c236339 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -1380,7 +1380,7 @@ static void respond_string(const char *p, struct tty_struct *tty)  		tty_insert_flip_char(tty, *p, 0);  		p++;  	} -	con_schedule_flip(tty); +	tty_schedule_flip(tty);  }  static void cursor_report(struct vc_data *vc, struct tty_struct *tty) @@ -2792,41 +2792,52 @@ static void con_flush_chars(struct tty_struct *tty)  /*   * Allocate the console screen memory.   */ -static int con_open(struct tty_struct *tty, struct file *filp) +static int con_install(struct tty_driver *driver, struct tty_struct *tty)  {  	unsigned int currcons = tty->index; -	int ret = 0; +	struct vc_data *vc; +	int ret;  	console_lock(); -	if (tty->driver_data == NULL) { -		ret = vc_allocate(currcons); -		if (ret == 0) { -			struct vc_data *vc = vc_cons[currcons].d; +	ret = vc_allocate(currcons); +	if (ret) +		goto unlock; -			/* Still being freed */ -			if (vc->port.tty) { -				console_unlock(); -				return -ERESTARTSYS; -			} -			tty->driver_data = vc; -			vc->port.tty = tty; +	vc = vc_cons[currcons].d; -			if (!tty->winsize.ws_row && !tty->winsize.ws_col) { -				tty->winsize.ws_row = vc_cons[currcons].d->vc_rows; -				tty->winsize.ws_col = vc_cons[currcons].d->vc_cols; -			} -			if (vc->vc_utf) -				tty->termios->c_iflag |= IUTF8; -			else -				tty->termios->c_iflag &= ~IUTF8; -			console_unlock(); -			return ret; -		} +	/* Still being freed */ +	if (vc->port.tty) { +		ret = -ERESTARTSYS; +		goto unlock;  	} + +	ret = tty_port_install(&vc->port, driver, tty); +	if (ret) +		goto unlock; + +	tty->driver_data = vc; +	vc->port.tty = tty; + +	if (!tty->winsize.ws_row && !tty->winsize.ws_col) { +		tty->winsize.ws_row = vc_cons[currcons].d->vc_rows; +		tty->winsize.ws_col = vc_cons[currcons].d->vc_cols; +	} +	if (vc->vc_utf) +		tty->termios->c_iflag |= IUTF8; +	else +		tty->termios->c_iflag &= ~IUTF8; +unlock:  	console_unlock();  	return ret;  } +static int con_open(struct tty_struct *tty, struct file *filp) +{ +	/* everything done in install */ +	return 0; +} + +  static void con_close(struct tty_struct *tty, struct file *filp)  {  	/* Nothing to do - we defer to shutdown */ @@ -2947,6 +2958,7 @@ static int __init con_init(void)  console_initcall(con_init);  static const struct tty_operations con_ops = { +	.install = con_install,  	.open = con_open,  	.close = con_close,  	.write = con_write, diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c index 64618547be11..b841f56d2e66 100644 --- a/drivers/tty/vt/vt_ioctl.c +++ b/drivers/tty/vt/vt_ioctl.c @@ -110,16 +110,7 @@ void vt_event_post(unsigned int event, unsigned int old, unsigned int new)  		wake_up_interruptible(&vt_event_waitqueue);  } -/** - *	vt_event_wait		-	wait for an event - *	@vw: our event - * - *	Waits for an event to occur which completes our vt_event_wait - *	structure. On return the structure has wv->done set to 1 for success - *	or 0 if some event such as a signal ended the wait. - */ - -static void vt_event_wait(struct vt_event_wait *vw) +static void __vt_event_queue(struct vt_event_wait *vw)  {  	unsigned long flags;  	/* Prepare the event */ @@ -129,8 +120,18 @@ static void vt_event_wait(struct vt_event_wait *vw)  	spin_lock_irqsave(&vt_event_lock, flags);  	list_add(&vw->list, &vt_events);  	spin_unlock_irqrestore(&vt_event_lock, flags); +} + +static void __vt_event_wait(struct vt_event_wait *vw) +{  	/* Wait for it to pass */  	wait_event_interruptible(vt_event_waitqueue, vw->done); +} + +static void __vt_event_dequeue(struct vt_event_wait *vw) +{ +	unsigned long flags; +  	/* Dequeue it */  	spin_lock_irqsave(&vt_event_lock, flags);  	list_del(&vw->list); @@ -138,6 +139,22 @@ static void vt_event_wait(struct vt_event_wait *vw)  }  /** + *	vt_event_wait		-	wait for an event + *	@vw: our event + * + *	Waits for an event to occur which completes our vt_event_wait + *	structure. On return the structure has wv->done set to 1 for success + *	or 0 if some event such as a signal ended the wait. + */ + +static void vt_event_wait(struct vt_event_wait *vw) +{ +	__vt_event_queue(vw); +	__vt_event_wait(vw); +	__vt_event_dequeue(vw); +} + +/**   *	vt_event_wait_ioctl	-	event ioctl handler   *	@arg: argument to ioctl   * @@ -177,10 +194,14 @@ int vt_waitactive(int n)  {  	struct vt_event_wait vw;  	do { -		if (n == fg_console + 1) -			break;  		vw.event.event = VT_EVENT_SWITCH; -		vt_event_wait(&vw); +		__vt_event_queue(&vw); +		if (n == fg_console + 1) { +			__vt_event_dequeue(&vw); +			break; +		} +		__vt_event_wait(&vw); +		__vt_event_dequeue(&vw);  		if (vw.done == 0)  			return -EINTR;  	} while (vw.event.newev != n); diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c index d47eb06fe463..7ae9af6b2a54 100644 --- a/drivers/usb/serial/metro-usb.c +++ b/drivers/usb/serial/metro-usb.c @@ -130,20 +130,14 @@ static void metrousb_read_int_callback(struct urb *urb)  	/* Set the data read from the usb port into the serial port buffer. */  	tty = tty_port_tty_get(&port->port); -	if (!tty) { -		dev_err(&port->dev, "%s - bad tty pointer - exiting\n", -			__func__); -		return; -	} -  	if (tty && urb->actual_length) {  		/* Loop through the data copying each byte to the tty layer. */  		tty_insert_flip_string(tty, data, urb->actual_length);  		/* Force the data to the tty layer. */  		tty_flip_buffer_push(tty); +		tty_kref_put(tty);  	} -	tty_kref_put(tty);  	/* Set any port variables. */  	spin_lock_irqsave(&metro_priv->lock, flags); diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 27483f91a4a3..da67abb1945e 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -207,7 +207,7 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty)  	if (retval)  		goto error_get_interface; -	retval = tty_standard_install(driver, tty); +	retval = tty_port_install(&port->port, driver, tty);  	if (retval)  		goto error_init_termios; diff --git a/include/linux/Kbuild b/include/linux/Kbuild index 8760be30b375..cf41085e3331 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -84,7 +84,6 @@ header-y += capability.h  header-y += capi.h  header-y += cciss_defs.h  header-y += cciss_ioctl.h -header-y += cdk.h  header-y += cdrom.h  header-y += cgroupstats.h  header-y += chio.h @@ -93,7 +92,6 @@ header-y += cn_proc.h  header-y += coda.h  header-y += coda_psdev.h  header-y += coff.h -header-y += comstats.h  header-y += connector.h  header-y += const.h  header-y += cramfs_fs.h @@ -140,7 +138,6 @@ header-y += fuse.h  header-y += futex.h  header-y += gameport.h  header-y += gen_stats.h -header-y += generic_serial.h  header-y += genetlink.h  header-y += gfs2_ondisk.h  header-y += gigaset_dev.h diff --git a/include/linux/cd1400.h b/include/linux/cd1400.h deleted file mode 100644 index 1dc3ab0523fd..000000000000 --- a/include/linux/cd1400.h +++ /dev/null @@ -1,292 +0,0 @@ -/*****************************************************************************/ - -/* - *	cd1400.h  -- cd1400 UART hardware info. - * - *	Copyright (C) 1996-1998  Stallion Technologies - *	Copyright (C) 1994-1996  Greg Ungerer. - * - *	This program is free software; you can redistribute it and/or modify - *	it under the terms of the GNU General Public License as published by - *	the Free Software Foundation; either version 2 of the License, or - *	(at your option) any later version. - * - *	This program is distributed in the hope that it will be useful, - *	but WITHOUT ANY WARRANTY; without even the implied warranty of - *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - *	GNU General Public License for more details. - * - *	You should have received a copy of the GNU General Public License - *	along with this program; if not, write to the Free Software - *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/*****************************************************************************/ -#ifndef	_CD1400_H -#define	_CD1400_H -/*****************************************************************************/ - -/* - *	Define the number of async ports per cd1400 uart chip. - */ -#define	CD1400_PORTS		4 - -/* - *	Define the cd1400 uarts internal FIFO sizes. - */ -#define	CD1400_TXFIFOSIZE	12 -#define	CD1400_RXFIFOSIZE	12 - -/* - *	Local RX FIFO thresh hold level. Also define the RTS thresh hold - *	based on the RX thresh hold. - */ -#define	FIFO_RXTHRESHOLD	6 -#define	FIFO_RTSTHRESHOLD	7 - -/*****************************************************************************/ - -/* - *	Define the cd1400 register addresses. These are all the valid - *	registers with the cd1400. Some are global, some virtual, some - *	per port. - */ -#define	GFRCR		0x40 -#define	CAR		0x68 -#define	GCR		0x4b -#define	SVRR		0x67 -#define	RICR		0x44 -#define	TICR		0x45 -#define	MICR		0x46 -#define	RIR		0x6b -#define	TIR		0x6a -#define	MIR		0x69 -#define	PPR		0x7e - -#define	RIVR		0x43 -#define	TIVR		0x42 -#define	MIVR		0x41 -#define	TDR		0x63 -#define	RDSR		0x62 -#define	MISR		0x4c -#define	EOSRR		0x60 - -#define	LIVR		0x18 -#define	CCR		0x05 -#define	SRER		0x06 -#define	COR1		0x08 -#define	COR2		0x09 -#define	COR3		0x0a -#define	COR4		0x1e -#define	COR5		0x1f -#define	CCSR		0x0b -#define	RDCR		0x0e -#define	SCHR1		0x1a -#define	SCHR2		0x1b -#define	SCHR3		0x1c -#define	SCHR4		0x1d -#define	SCRL		0x22 -#define	SCRH		0x23 -#define	LNC		0x24 -#define	MCOR1		0x15 -#define	MCOR2		0x16 -#define	RTPR		0x21 -#define	MSVR1		0x6c -#define	MSVR2		0x6d -#define	PSVR		0x6f -#define	RBPR		0x78 -#define	RCOR		0x7c -#define	TBPR		0x72 -#define	TCOR		0x76 - -/*****************************************************************************/ - -/* - *	Define the set of baud rate clock divisors. - */ -#define	CD1400_CLK0	8 -#define	CD1400_CLK1	32 -#define	CD1400_CLK2	128 -#define	CD1400_CLK3	512 -#define	CD1400_CLK4	2048 - -#define	CD1400_NUMCLKS	5 - -/*****************************************************************************/ - -/* - *	Define the clock pre-scalar value to be a 5 ms clock. This should be - *	OK for now. It would probably be better to make it 10 ms, but we - *	can't fit that divisor into 8 bits! - */ -#define	PPR_SCALAR	244 - -/*****************************************************************************/ - -/* - *	Define values used to set character size options. - */ -#define	COR1_CHL5	0x00 -#define	COR1_CHL6	0x01 -#define	COR1_CHL7	0x02 -#define	COR1_CHL8	0x03 - -/* - *	Define values used to set the number of stop bits. - */ -#define	COR1_STOP1	0x00 -#define	COR1_STOP15	0x04 -#define	COR1_STOP2	0x08 - -/* - *	Define values used to set the parity scheme in use. - */ -#define	COR1_PARNONE	0x00 -#define	COR1_PARFORCE	0x20 -#define	COR1_PARENB	0x40 -#define	COR1_PARIGNORE	0x10 - -#define	COR1_PARODD	0x80 -#define	COR1_PAREVEN	0x00 - -#define	COR2_IXM	0x80 -#define	COR2_TXIBE	0x40 -#define	COR2_ETC	0x20 -#define	COR2_LLM	0x10 -#define	COR2_RLM	0x08 -#define	COR2_RTSAO	0x04 -#define	COR2_CTSAE	0x02 - -#define	COR3_SCDRNG	0x80 -#define	COR3_SCD34	0x40 -#define	COR3_FCT	0x20 -#define	COR3_SCD12	0x10 - -/* - *	Define values used by COR4. - */ -#define	COR4_BRKINT	0x08 -#define	COR4_IGNBRK	0x18 - -/*****************************************************************************/ - -/* - *	Define the modem control register values. - *	Note that the actual hardware is a little different to the conventional - *	pin names on the cd1400. - */ -#define	MSVR1_DTR	0x01 -#define	MSVR1_DSR	0x10 -#define	MSVR1_RI	0x20 -#define	MSVR1_CTS	0x40 -#define	MSVR1_DCD	0x80 - -#define	MSVR2_RTS	0x02 -#define	MSVR2_DSR	0x10 -#define	MSVR2_RI	0x20 -#define	MSVR2_CTS	0x40 -#define	MSVR2_DCD	0x80 - -#define	MCOR1_DCD	0x80 -#define	MCOR1_CTS	0x40 -#define	MCOR1_RI	0x20 -#define	MCOR1_DSR	0x10 - -#define	MCOR2_DCD	0x80 -#define	MCOR2_CTS	0x40 -#define	MCOR2_RI	0x20 -#define	MCOR2_DSR	0x10 - -/*****************************************************************************/ - -/* - *	Define the bits used with the service (interrupt) enable register. - */ -#define	SRER_NNDT	0x01 -#define	SRER_TXEMPTY	0x02 -#define	SRER_TXDATA	0x04 -#define	SRER_RXDATA	0x10 -#define	SRER_MODEM	0x80 - -/*****************************************************************************/ - -/* - *	Define operational commands for the command register. - */ -#define	CCR_RESET	0x80 -#define	CCR_CORCHANGE	0x4e -#define	CCR_SENDCH	0x20 -#define	CCR_CHANCTRL	0x10 - -#define	CCR_TXENABLE	(CCR_CHANCTRL | 0x08) -#define	CCR_TXDISABLE	(CCR_CHANCTRL | 0x04) -#define	CCR_RXENABLE	(CCR_CHANCTRL | 0x02) -#define	CCR_RXDISABLE	(CCR_CHANCTRL | 0x01) - -#define	CCR_SENDSCHR1	(CCR_SENDCH | 0x01) -#define	CCR_SENDSCHR2	(CCR_SENDCH | 0x02) -#define	CCR_SENDSCHR3	(CCR_SENDCH | 0x03) -#define	CCR_SENDSCHR4	(CCR_SENDCH | 0x04) - -#define	CCR_RESETCHAN	(CCR_RESET | 0x00) -#define	CCR_RESETFULL	(CCR_RESET | 0x01) -#define	CCR_TXFLUSHFIFO	(CCR_RESET | 0x02) - -#define	CCR_MAXWAIT	10000 - -/*****************************************************************************/ - -/* - *	Define the valid acknowledgement types (for hw ack cycle). - */ -#define	ACK_TYPMASK	0x07 -#define	ACK_TYPTX	0x02 -#define	ACK_TYPMDM	0x01 -#define	ACK_TYPRXGOOD	0x03 -#define	ACK_TYPRXBAD	0x07 - -#define	SVRR_RX		0x01 -#define	SVRR_TX		0x02 -#define	SVRR_MDM	0x04 - -#define	ST_OVERRUN	0x01 -#define	ST_FRAMING	0x02 -#define	ST_PARITY	0x04 -#define	ST_BREAK	0x08 -#define	ST_SCHAR1	0x10 -#define	ST_SCHAR2	0x20 -#define	ST_SCHAR3	0x30 -#define	ST_SCHAR4	0x40 -#define	ST_RANGE	0x70 -#define	ST_SCHARMASK	0x70 -#define	ST_TIMEOUT	0x80 - -#define	MISR_DCD	0x80 -#define	MISR_CTS	0x40 -#define	MISR_RI		0x20 -#define	MISR_DSR	0x10 - -/*****************************************************************************/ - -/* - *	Defines for the CCSR status register. - */ -#define	CCSR_RXENABLED	0x80 -#define	CCSR_RXFLOWON	0x40 -#define	CCSR_RXFLOWOFF	0x20 -#define	CCSR_TXENABLED	0x08 -#define	CCSR_TXFLOWON	0x04 -#define	CCSR_TXFLOWOFF	0x02 - -/*****************************************************************************/ - -/* - *	Define the embedded commands. - */ -#define	ETC_CMD		0x00 -#define	ETC_STARTBREAK	0x81 -#define	ETC_DELAY	0x82 -#define	ETC_STOPBREAK	0x83 - -/*****************************************************************************/ -#endif diff --git a/include/linux/cdk.h b/include/linux/cdk.h deleted file mode 100644 index 80093a8d4f64..000000000000 --- a/include/linux/cdk.h +++ /dev/null @@ -1,486 +0,0 @@ -/*****************************************************************************/ - -/* - *	cdk.h  -- CDK interface definitions. - * - *	Copyright (C) 1996-1998  Stallion Technologies - *	Copyright (C) 1994-1996  Greg Ungerer. - * - *	This program is free software; you can redistribute it and/or modify - *	it under the terms of the GNU General Public License as published by - *	the Free Software Foundation; either version 2 of the License, or - *	(at your option) any later version. - * - *	This program is distributed in the hope that it will be useful, - *	but WITHOUT ANY WARRANTY; without even the implied warranty of - *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - *	GNU General Public License for more details. - * - *	You should have received a copy of the GNU General Public License - *	along with this program; if not, write to the Free Software - *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/*****************************************************************************/ -#ifndef	_CDK_H -#define	_CDK_H -/*****************************************************************************/ - -#pragma	pack(2) - -/* - *	The following set of definitions is used to communicate with the - *	shared memory interface of the Stallion intelligent multiport serial - *	boards. The definitions in this file are taken directly from the - *	document titled "Generic Stackable Interface, Downloader and - *	Communications Development Kit". - */ - -/* - *	Define the set of important shared memory addresses. These are - *	required to initialize the board and get things started. All of these - *	addresses are relative to the start of the shared memory. - */ -#define	CDK_SIGADDR	0x200 -#define	CDK_FEATADDR	0x280 -#define	CDK_CDKADDR	0x300 -#define	CDK_RDYADDR	0x262 - -#define	CDK_ALIVEMARKER	13 - -/* - *	On hardware power up the ROMs located on the EasyConnection 8/64 will - *	fill out the following signature information into shared memory. This - *	way the host system can quickly determine that the board is present - *	and is operational. - */ -typedef struct cdkecpsig { -	unsigned long	magic; -	unsigned short	romver; -	unsigned short	cputype; -	unsigned char	panelid[8]; -} cdkecpsig_t; - -#define	ECP_MAGIC	0x21504345 - -/* - *	On hardware power up the ROMs located on the ONboard, Stallion and - *	Brumbys will fill out the following signature information into shared - *	memory. This way the host system can quickly determine that the board - *	is present and is operational. - */ -typedef struct cdkonbsig { -	unsigned short	magic0; -	unsigned short	magic1; -	unsigned short	magic2; -	unsigned short	magic3; -	unsigned short	romver; -	unsigned short	memoff; -	unsigned short	memseg; -	unsigned short	amask0; -	unsigned short	pic; -	unsigned short	status; -	unsigned short	btype; -	unsigned short	clkticks; -	unsigned short	clkspeed; -	unsigned short	amask1; -	unsigned short	amask2; -} cdkonbsig_t; - -#define	ONB_MAGIC0	0xf2a7 -#define	ONB_MAGIC1	0xa149 -#define	ONB_MAGIC2	0x6352 -#define	ONB_MAGIC3	0xf121 - -/* - *	Define the feature area structure. The feature area is the set of - *	startup parameters used by the slave image when it starts executing. - *	They allow for the specification of buffer sizes, debug trace, etc. - */ -typedef struct cdkfeature { -	unsigned long	debug; -	unsigned long	banner; -	unsigned long	etype; -	unsigned long	nrdevs; -	unsigned long	brdspec; -	unsigned long	txrqsize; -	unsigned long	rxrqsize; -	unsigned long	flags; -} cdkfeature_t; - -#define	ETYP_DDK	0 -#define	ETYP_CDK	1 - -/* - *	Define the CDK header structure. This is the info that the slave - *	environment sets up after it has been downloaded and started. It - *	essentially provides a memory map for the shared memory interface. - */ -typedef struct cdkhdr { -	unsigned short	command; -	unsigned short	status; -	unsigned short	port; -	unsigned short	mode; -	unsigned long	cmd_buf[14]; -	unsigned short	alive_cnt; -	unsigned short	intrpt_mode; -	unsigned char	intrpt_id[8]; -	unsigned char	ver_release; -	unsigned char	ver_modification; -	unsigned char	ver_fix; -	unsigned char	deadman_restart; -	unsigned short	deadman; -	unsigned short	nrdevs; -	unsigned long	memp; -	unsigned long	hostp; -	unsigned long	slavep; -	unsigned char	hostreq; -	unsigned char	slavereq; -	unsigned char	cmd_reserved[30]; -} cdkhdr_t; - -#define	MODE_DDK	0 -#define	MODE_CDK	1 - -#define	IMD_INTR	0x0 -#define	IMD_PPINTR	0x1 -#define	IMD_POLL	0xff - -/* - *	Define the memory mapping structure. This structure is pointed to by - *	the memp field in the stlcdkhdr struct. As many as these structures - *	as required are laid out in shared memory to define how the rest of - *	shared memory is divided up. There will be one for each port. - */ -typedef struct cdkmem { -	unsigned short	dtype; -	unsigned long	offset; -} cdkmem_t; - -#define	TYP_UNDEFINED	0x0 -#define	TYP_ASYNCTRL	0x1 -#define	TYP_ASYNC	0x20 -#define	TYP_PARALLEL	0x40 -#define	TYP_SYNCX21	0x60 - -/*****************************************************************************/ - -/* - *	Following is a set of defines and structures used to actually deal - *	with the serial ports on the board. Firstly is the set of commands - *	that can be applied to ports. - */ -#define	ASYCMD		(((unsigned long) 'a') << 8) - -#define	A_NULL		(ASYCMD | 0) -#define	A_FLUSH		(ASYCMD | 1) -#define	A_BREAK		(ASYCMD | 2) -#define	A_GETPORT	(ASYCMD | 3) -#define	A_SETPORT	(ASYCMD | 4) -#define	A_SETPORTF	(ASYCMD | 5) -#define	A_SETPORTFTX	(ASYCMD | 6) -#define	A_SETPORTFRX	(ASYCMD | 7) -#define	A_GETSIGNALS	(ASYCMD | 8) -#define	A_SETSIGNALS	(ASYCMD | 9) -#define	A_SETSIGNALSF	(ASYCMD | 10) -#define	A_SETSIGNALSFTX	(ASYCMD | 11) -#define	A_SETSIGNALSFRX	(ASYCMD | 12) -#define	A_GETNOTIFY	(ASYCMD | 13) -#define	A_SETNOTIFY	(ASYCMD | 14) -#define	A_NOTIFY	(ASYCMD | 15) -#define	A_PORTCTRL	(ASYCMD | 16) -#define	A_GETSTATS	(ASYCMD | 17) -#define	A_RQSTATE	(ASYCMD | 18) -#define	A_FLOWSTATE	(ASYCMD | 19) -#define	A_CLEARSTATS	(ASYCMD | 20) - -/* - *	Define those arguments used for simple commands. - */ -#define	FLUSHRX		0x1 -#define	FLUSHTX		0x2 - -#define	BREAKON		-1 -#define	BREAKOFF	-2 - -/* - *	Define the port setting structure, and all those defines that go along - *	with it. Basically this structure defines the characteristics of this - *	port: baud rate, chars, parity, input/output char cooking etc. - */ -typedef struct asyport { -	unsigned long	baudout; -	unsigned long	baudin; -	unsigned long	iflag; -	unsigned long	oflag; -	unsigned long	lflag; -	unsigned long	pflag; -	unsigned long	flow; -	unsigned long	spare1; -	unsigned short	vtime; -	unsigned short	vmin; -	unsigned short	txlo; -	unsigned short	txhi; -	unsigned short	rxlo; -	unsigned short	rxhi; -	unsigned short	rxhog; -	unsigned short	spare2; -	unsigned char	csize; -	unsigned char	stopbs; -	unsigned char	parity; -	unsigned char	stopin; -	unsigned char	startin; -	unsigned char	stopout; -	unsigned char	startout; -	unsigned char	parmark; -	unsigned char	brkmark; -	unsigned char	cc[11]; -} asyport_t; - -#define	PT_STOP1	0x0 -#define	PT_STOP15	0x1 -#define	PT_STOP2	0x2 - -#define	PT_NOPARITY	0x0 -#define	PT_ODDPARITY	0x1 -#define	PT_EVENPARITY	0x2 -#define	PT_MARKPARITY	0x3 -#define	PT_SPACEPARITY	0x4 - -#define	F_NONE		0x0 -#define	F_IXON		0x1 -#define	F_IXOFF		0x2 -#define	F_IXANY		0x4 -#define	F_IOXANY	0x8 -#define	F_RTSFLOW	0x10 -#define	F_CTSFLOW	0x20 -#define	F_DTRFLOW	0x40 -#define	F_DCDFLOW	0x80 -#define	F_DSROFLOW	0x100 -#define	F_DSRIFLOW	0x200 - -#define	FI_NORX		0x1 -#define	FI_RAW		0x2 -#define	FI_ISTRIP	0x4 -#define	FI_UCLC		0x8 -#define	FI_INLCR	0x10 -#define	FI_ICRNL	0x20 -#define	FI_IGNCR	0x40 -#define	FI_IGNBREAK	0x80 -#define	FI_DSCRDBREAK	0x100 -#define	FI_1MARKBREAK	0x200 -#define	FI_2MARKBREAK	0x400 -#define	FI_XCHNGBREAK	0x800 -#define	FI_IGNRXERRS	0x1000 -#define	FI_DSCDRXERRS	0x2000 -#define	FI_1MARKRXERRS	0x4000 -#define	FI_2MARKRXERRS	0x8000 -#define	FI_XCHNGRXERRS	0x10000 -#define	FI_DSCRDNULL	0x20000 - -#define	FO_OLCUC	0x1 -#define	FO_ONLCR	0x2 -#define	FO_OOCRNL	0x4 -#define	FO_ONOCR	0x8 -#define	FO_ONLRET	0x10 -#define	FO_ONL		0x20 -#define	FO_OBS		0x40 -#define	FO_OVT		0x80 -#define	FO_OFF		0x100 -#define	FO_OTAB1	0x200 -#define	FO_OTAB2	0x400 -#define	FO_OTAB3	0x800 -#define	FO_OCR1		0x1000 -#define	FO_OCR2		0x2000 -#define	FO_OCR3		0x4000 -#define	FO_OFILL	0x8000 -#define	FO_ODELL	0x10000 - -#define	P_RTSLOCK	0x1 -#define	P_CTSLOCK	0x2 -#define	P_MAPRTS	0x4 -#define	P_MAPCTS	0x8 -#define	P_LOOPBACK	0x10 -#define	P_DTRFOLLOW	0x20 -#define	P_FAKEDCD	0x40 - -#define	P_RXIMIN	0x10000 -#define	P_RXITIME	0x20000 -#define	P_RXTHOLD	0x40000 - -/* - *	Define a structure to communicate serial port signal and data state - *	information. - */ -typedef struct asysigs { -	unsigned long	data; -	unsigned long	signal; -	unsigned long	sigvalue; -} asysigs_t; - -#define	DT_TXBUSY	0x1 -#define	DT_TXEMPTY	0x2 -#define	DT_TXLOW	0x4 -#define	DT_TXHIGH	0x8 -#define	DT_TXFULL	0x10 -#define	DT_TXHOG	0x20 -#define	DT_TXFLOWED	0x40 -#define	DT_TXBREAK	0x80 - -#define	DT_RXBUSY	0x100 -#define	DT_RXEMPTY	0x200 -#define	DT_RXLOW	0x400 -#define	DT_RXHIGH	0x800 -#define	DT_RXFULL	0x1000 -#define	DT_RXHOG	0x2000 -#define	DT_RXFLOWED	0x4000 -#define	DT_RXBREAK	0x8000 - -#define	SG_DTR		0x1 -#define	SG_DCD		0x2 -#define	SG_RTS		0x4 -#define	SG_CTS		0x8 -#define	SG_DSR		0x10 -#define	SG_RI		0x20 - -/* - *	Define the notification setting structure. This is used to tell the - *	port what events we want to be informed about. Fields here use the - *	same defines as for the asysigs structure above. - */ -typedef struct asynotify { -	unsigned long	ctrl; -	unsigned long	data; -	unsigned long	signal; -	unsigned long	sigvalue; -} asynotify_t; - -/* - *	Define the port control structure. It is used to do fine grain - *	control operations on the port. - */ -typedef struct { -	unsigned long	rxctrl; -	unsigned long	txctrl; -	char		rximdch; -	char		tximdch; -	char		spare1; -	char		spare2; -} asyctrl_t; - -#define	CT_ENABLE	0x1 -#define	CT_DISABLE	0x2 -#define	CT_STOP		0x4 -#define	CT_START	0x8 -#define	CT_STARTFLOW	0x10 -#define	CT_STOPFLOW	0x20 -#define	CT_SENDCHR	0x40 - -/* - *	Define the stats structure kept for each port. This is a useful set - *	of data collected for each port on the slave. The A_GETSTATS command - *	is used to retrieve this data from the slave. - */ -typedef struct asystats { -	unsigned long	opens; -	unsigned long	txchars; -	unsigned long	rxchars; -	unsigned long	txringq; -	unsigned long	rxringq; -	unsigned long	txmsgs; -	unsigned long	rxmsgs; -	unsigned long	txflushes; -	unsigned long	rxflushes; -	unsigned long	overruns; -	unsigned long	framing; -	unsigned long	parity; -	unsigned long	ringover; -	unsigned long	lost; -	unsigned long	rxstart; -	unsigned long	rxstop; -	unsigned long	txstart; -	unsigned long	txstop; -	unsigned long	dcdcnt; -	unsigned long	dtrcnt; -	unsigned long	ctscnt; -	unsigned long	rtscnt; -	unsigned long	dsrcnt; -	unsigned long	ricnt; -	unsigned long	txbreaks; -	unsigned long	rxbreaks; -	unsigned long	signals; -	unsigned long	state; -	unsigned long	hwid; -} asystats_t; - -/*****************************************************************************/ - -/* - *	All command and control communication with a device on the slave is - *	via a control block in shared memory. Each device has its own control - *	block, defined by the following structure. The control block allows - *	the host to open, close and control the device on the slave. - */ -typedef struct cdkctrl { -	unsigned char	open; -	unsigned char	close; -	unsigned long	openarg; -	unsigned long	closearg; -	unsigned long	cmd; -	unsigned long	status; -	unsigned long	args[32]; -} cdkctrl_t; - -/* - *	Each device on the slave passes data to and from the host via a ring - *	queue in shared memory. Define a ring queue structure to hold the - *	vital information about each ring queue. Two ring queues will be - *	allocated for each port, one for receive data and one for transmit - *	data. - */ -typedef struct cdkasyrq { -	unsigned long	offset; -	unsigned short	size; -	unsigned short	head; -	unsigned short	tail; -} cdkasyrq_t; - -/* - *	Each asynchronous port is defined in shared memory by the following - *	structure. It contains a control block to command a device, and also - *	the necessary data channel information as well. - */ -typedef struct cdkasy { -	cdkctrl_t	ctrl; -	unsigned short	notify; -	asynotify_t	changed; -	unsigned short	receive; -	cdkasyrq_t	rxq; -	unsigned short	transmit; -	cdkasyrq_t	txq; -} cdkasy_t; - -#pragma	pack() - -/*****************************************************************************/ - -/* - *	Define the set of ioctls used by the driver to do special things - *	to the board. These include interrupting it, and initializing - *	the driver after board startup and shutdown. - */ -#include <linux/ioctl.h> - -#define	STL_BINTR	_IO('s',20) -#define	STL_BSTART	_IO('s',21) -#define	STL_BSTOP	_IO('s',22) -#define	STL_BRESET	_IO('s',23) - -/* - *	Define a set of ioctl extensions, used to get at special stuff. - */ -#define	STL_GETPFLAG	_IO('s',80) -#define	STL_SETPFLAG	_IO('s',81) - -/*****************************************************************************/ -#endif diff --git a/include/linux/comstats.h b/include/linux/comstats.h deleted file mode 100644 index 3f5ea8e8026d..000000000000 --- a/include/linux/comstats.h +++ /dev/null @@ -1,119 +0,0 @@ -/*****************************************************************************/ - -/* - *	comstats.h  -- Serial Port Stats. - * - *	Copyright (C) 1996-1998  Stallion Technologies - *	Copyright (C) 1994-1996  Greg Ungerer. - * - *	This program is free software; you can redistribute it and/or modify - *	it under the terms of the GNU General Public License as published by - *	the Free Software Foundation; either version 2 of the License, or - *	(at your option) any later version. - * - *	This program is distributed in the hope that it will be useful, - *	but WITHOUT ANY WARRANTY; without even the implied warranty of - *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - *	GNU General Public License for more details. - * - *	You should have received a copy of the GNU General Public License - *	along with this program; if not, write to the Free Software - *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/*****************************************************************************/ -#ifndef	_COMSTATS_H -#define	_COMSTATS_H -/*****************************************************************************/ - -/* - *	Serial port stats structure. The structure itself is UART - *	independent, but some fields may be UART/driver specific (for - *	example state). - */ - -typedef struct { -	unsigned long	brd; -	unsigned long	panel; -	unsigned long	port; -	unsigned long	hwid; -	unsigned long	type; -	unsigned long	txtotal; -	unsigned long	rxtotal; -	unsigned long	txbuffered; -	unsigned long	rxbuffered; -	unsigned long	rxoverrun; -	unsigned long	rxparity; -	unsigned long	rxframing; -	unsigned long	rxlost; -	unsigned long	txbreaks; -	unsigned long	rxbreaks; -	unsigned long	txxon; -	unsigned long	txxoff; -	unsigned long	rxxon; -	unsigned long	rxxoff; -	unsigned long	txctson; -	unsigned long	txctsoff; -	unsigned long	rxrtson; -	unsigned long	rxrtsoff; -	unsigned long	modem; -	unsigned long	state; -	unsigned long	flags; -	unsigned long	ttystate; -	unsigned long	cflags; -	unsigned long	iflags; -	unsigned long	oflags; -	unsigned long	lflags; -	unsigned long	signals; -} comstats_t; - - -/* - *	Board stats structure. Returns useful info about the board. - */ - -#define	COM_MAXPANELS	8 - -typedef struct { -	unsigned long	panel; -	unsigned long	type; -	unsigned long	hwid; -	unsigned long	nrports; -} companel_t; - -typedef struct { -	unsigned long	brd; -	unsigned long	type; -	unsigned long	hwid; -	unsigned long	state; -	unsigned long	ioaddr; -	unsigned long	ioaddr2; -	unsigned long	memaddr; -	unsigned long	irq; -	unsigned long	nrpanels; -	unsigned long	nrports; -	companel_t	panels[COM_MAXPANELS]; -} combrd_t; - - -/* - *	Define the ioctl operations for stats stuff. - */ -#include <linux/ioctl.h> - -#define	COM_GETPORTSTATS	_IO('c',30) -#define	COM_CLRPORTSTATS	_IO('c',31) -#define	COM_GETBRDSTATS		_IO('c',32) - - -/* - *	Define the set of ioctls that give user level access to the - *	private port, panel and board structures. The argument required - *	will be driver dependent!   - */ -#define	COM_READPORT		_IO('c',40) -#define	COM_READBOARD		_IO('c',41) -#define	COM_READPANEL		_IO('c',42) - -/*****************************************************************************/ -#endif diff --git a/include/linux/generic_serial.h b/include/linux/generic_serial.h deleted file mode 100644 index 79b3eb37243a..000000000000 --- a/include/linux/generic_serial.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - *  generic_serial.h - * - *  Copyright (C) 1998 R.E.Wolff@BitWizard.nl - * - *  written for the SX serial driver. - * - *  Version 0.1 -- December, 1998. - */ - -#ifndef GENERIC_SERIAL_H -#define GENERIC_SERIAL_H - -#warning Use of this header is deprecated. -#warning Since nobody sets the constants defined here for you, you should not, in any case, use them. Including the header is thus pointless. - -/* Flags */ -/* Warning: serial.h defines some ASYNC_ flags, they say they are "only" -   used in serial.c, but they are also used in all other serial drivers.  -   Make sure they don't clash with these here... */ -#define GS_TX_INTEN      0x00800000 -#define GS_RX_INTEN      0x00400000 -#define GS_ACTIVE        0x00200000 - -#define GS_TYPE_NORMAL   1 - -#define GS_DEBUG_FLUSH   0x00000001 -#define GS_DEBUG_BTR     0x00000002 -#define GS_DEBUG_TERMIOS 0x00000004 -#define GS_DEBUG_STUFF   0x00000008 -#define GS_DEBUG_CLOSE   0x00000010 -#define GS_DEBUG_FLOW    0x00000020 -#define GS_DEBUG_WRITE   0x00000040 - -#endif diff --git a/include/linux/istallion.h b/include/linux/istallion.h deleted file mode 100644 index ad700a60c158..000000000000 --- a/include/linux/istallion.h +++ /dev/null @@ -1,123 +0,0 @@ -/*****************************************************************************/ - -/* - *	istallion.h  -- stallion intelligent multiport serial driver. - * - *	Copyright (C) 1996-1998  Stallion Technologies - *	Copyright (C) 1994-1996  Greg Ungerer. - * - *	This program is free software; you can redistribute it and/or modify - *	it under the terms of the GNU General Public License as published by - *	the Free Software Foundation; either version 2 of the License, or - *	(at your option) any later version. - * - *	This program is distributed in the hope that it will be useful, - *	but WITHOUT ANY WARRANTY; without even the implied warranty of - *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - *	GNU General Public License for more details. - * - *	You should have received a copy of the GNU General Public License - *	along with this program; if not, write to the Free Software - *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/*****************************************************************************/ -#ifndef	_ISTALLION_H -#define	_ISTALLION_H -/*****************************************************************************/ - -/* - *	Define important driver constants here. - */ -#define	STL_MAXBRDS		4 -#define	STL_MAXPANELS		4 -#define	STL_MAXPORTS		64 -#define	STL_MAXCHANS		(STL_MAXPORTS + 1) -#define	STL_MAXDEVS		(STL_MAXBRDS * STL_MAXPORTS) - - -/* - *	Define a set of structures to hold all the board/panel/port info - *	for our ports. These will be dynamically allocated as required at - *	driver initialization time. - */ - -/* - *	Port and board structures to hold status info about each object. - *	The board structure contains pointers to structures for each port - *	connected to it. Panels are not distinguished here, since - *	communication with the slave board will always be on a per port - *	basis. - */ -struct stliport { -	unsigned long		magic; -	struct tty_port		port; -	unsigned int		portnr; -	unsigned int		panelnr; -	unsigned int		brdnr; -	unsigned long		state; -	unsigned int		devnr; -	int			baud_base; -	int			custom_divisor; -	int			closing_wait; -	int			rc; -	int			argsize; -	void			*argp; -	unsigned int		rxmarkmsk; -	wait_queue_head_t	raw_wait; -	struct asysigs		asig; -	unsigned long		addr; -	unsigned long		rxoffset; -	unsigned long		txoffset; -	unsigned long		sigs; -	unsigned long		pflag; -	unsigned int		rxsize; -	unsigned int		txsize; -	unsigned char		reqbit; -	unsigned char		portidx; -	unsigned char		portbit; -}; - -/* - *	Use a structure of function pointers to do board level operations. - *	These include, enable/disable, paging shared memory, interrupting, etc. - */ -struct stlibrd { -	unsigned long	magic; -	unsigned int	brdnr; -	unsigned int	brdtype; -	unsigned long	state; -	unsigned int	nrpanels; -	unsigned int	nrports; -	unsigned int	nrdevs; -	unsigned int	iobase; -	int		iosize; -	unsigned long	memaddr; -	void		__iomem *membase; -	unsigned long	memsize; -	int		pagesize; -	int		hostoffset; -	int		slaveoffset; -	int		bitsize; -	int		enabval; -	unsigned int	panels[STL_MAXPANELS]; -	int		panelids[STL_MAXPANELS]; -	void		(*init)(struct stlibrd *brdp); -	void		(*enable)(struct stlibrd *brdp); -	void		(*reenable)(struct stlibrd *brdp); -	void		(*disable)(struct stlibrd *brdp); -	void		__iomem *(*getmemptr)(struct stlibrd *brdp, unsigned long offset, int line); -	void		(*intr)(struct stlibrd *brdp); -	void		(*reset)(struct stlibrd *brdp); -	struct stliport	*ports[STL_MAXPORTS]; -}; - - -/* - *	Define MAGIC numbers used for above structures. - */ -#define	STLI_PORTMAGIC	0xe671c7a1 -#define	STLI_BOARDMAGIC	0x4bc6c825 - -/*****************************************************************************/ -#endif diff --git a/include/linux/kbd_kern.h b/include/linux/kbd_kern.h index daf4a3a40ee0..af9137db3035 100644 --- a/include/linux/kbd_kern.h +++ b/include/linux/kbd_kern.h @@ -145,16 +145,4 @@ void compute_shiftstate(void);  extern unsigned int keymap_count; -/* console.c */ - -static inline void con_schedule_flip(struct tty_struct *t) -{ -	unsigned long flags; -	spin_lock_irqsave(&t->buf.lock, flags); -	if (t->buf.tail != NULL) -		t->buf.tail->commit = t->buf.tail->used; -	spin_unlock_irqrestore(&t->buf.lock, flags); -	schedule_work(&t->buf.work); -} -  #endif diff --git a/include/linux/sc26198.h b/include/linux/sc26198.h deleted file mode 100644 index 7ca35abad387..000000000000 --- a/include/linux/sc26198.h +++ /dev/null @@ -1,533 +0,0 @@ -/*****************************************************************************/ - -/* - *	sc26198.h  -- SC26198 UART hardware info. - * - *	Copyright (C) 1995-1998  Stallion Technologies - * - *	This program is free software; you can redistribute it and/or modify - *	it under the terms of the GNU General Public License as published by - *	the Free Software Foundation; either version 2 of the License, or - *	(at your option) any later version. - * - *	This program is distributed in the hope that it will be useful, - *	but WITHOUT ANY WARRANTY; without even the implied warranty of - *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - *	GNU General Public License for more details. - * - *	You should have received a copy of the GNU General Public License - *	along with this program; if not, write to the Free Software - *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/*****************************************************************************/ -#ifndef	_SC26198_H -#define	_SC26198_H -/*****************************************************************************/ - -/* - *	Define the number of async ports per sc26198 uart device. - */ -#define	SC26198_PORTS		8 - -/* - *	Baud rate timing clocks. All derived from a master 14.7456 MHz clock. - */ -#define	SC26198_MASTERCLOCK	14745600L -#define	SC26198_DCLK		(SC26198_MASTERCLOCK) -#define	SC26198_CCLK		(SC26198_MASTERCLOCK / 2) -#define	SC26198_BCLK		(SC26198_MASTERCLOCK / 4) - -/* - *	Define internal FIFO sizes for the 26198 ports. - */ -#define	SC26198_TXFIFOSIZE	16 -#define	SC26198_RXFIFOSIZE	16 - -/*****************************************************************************/ - -/* - *	Global register definitions. These registers are global to each 26198 - *	device, not specific ports on it. - */ -#define	TSTR		0x0d -#define	GCCR		0x0f -#define	ICR		0x1b -#define	WDTRCR		0x1d -#define	IVR		0x1f -#define	BRGTRUA		0x84 -#define	GPOSR		0x87 -#define	GPOC		0x8b -#define	UCIR		0x8c -#define	CIR		0x8c -#define	BRGTRUB		0x8d -#define	GRXFIFO		0x8e -#define	GTXFIFO		0x8e -#define	GCCR2		0x8f -#define	BRGTRLA		0x94 -#define	GPOR		0x97 -#define	GPOD		0x9b -#define	BRGTCR		0x9c -#define	GICR		0x9c -#define	BRGTRLB		0x9d -#define	GIBCR		0x9d -#define	GITR		0x9f - -/* - *	Per port channel registers. These are the register offsets within - *	the port address space, so need to have the port address (0 to 7) - *	inserted in bit positions 4:6. - */ -#define	MR0		0x00 -#define	MR1		0x01 -#define	IOPCR		0x02 -#define	BCRBRK		0x03 -#define	BCRCOS		0x04 -#define	BCRX		0x06 -#define	BCRA		0x07 -#define	XONCR		0x08 -#define	XOFFCR		0x09 -#define	ARCR		0x0a -#define	RXCSR		0x0c -#define	TXCSR		0x0e -#define	MR2		0x80 -#define	SR		0x81 -#define SCCR		0x81 -#define	ISR		0x82 -#define	IMR		0x82 -#define	TXFIFO		0x83 -#define	RXFIFO		0x83 -#define	IPR		0x84 -#define	IOPIOR		0x85 -#define	XISR		0x86 - -/* - *	For any given port calculate the address to use to access a specified - *	register. This is only used for unusual access, mostly this is done - *	through the assembler access routines. - */ -#define	SC26198_PORTREG(port,reg)	((((port) & 0x07) << 4) | (reg)) - -/*****************************************************************************/ - -/* - *	Global configuration control register bit definitions. - */ -#define	GCCR_NOACK		0x00 -#define	GCCR_IVRACK		0x02 -#define	GCCR_IVRCHANACK		0x04 -#define	GCCR_IVRTYPCHANACK	0x06 -#define	GCCR_ASYNCCYCLE		0x00 -#define	GCCR_SYNCCYCLE		0x40 - -/*****************************************************************************/ - -/* - *	Mode register 0 bit definitions. - */ -#define	MR0_ADDRNONE		0x00 -#define	MR0_AUTOWAKE		0x01 -#define	MR0_AUTODOZE		0x02 -#define	MR0_AUTOWAKEDOZE	0x03 -#define	MR0_SWFNONE		0x00 -#define	MR0_SWFTX		0x04 -#define	MR0_SWFRX		0x08 -#define	MR0_SWFRXTX		0x0c -#define	MR0_TXMASK		0x30 -#define	MR0_TXEMPTY		0x00 -#define	MR0_TXHIGH		0x10 -#define	MR0_TXHALF		0x20 -#define	MR0_TXRDY		0x00 -#define	MR0_ADDRNT		0x00 -#define	MR0_ADDRT		0x40 -#define	MR0_SWFNT		0x00 -#define	MR0_SWFT		0x80 - -/* - *	Mode register 1 bit definitions. - */ -#define	MR1_CS5			0x00 -#define	MR1_CS6			0x01 -#define	MR1_CS7			0x02 -#define	MR1_CS8			0x03 -#define	MR1_PAREVEN		0x00 -#define	MR1_PARODD		0x04 -#define	MR1_PARENB		0x00 -#define	MR1_PARFORCE		0x08 -#define	MR1_PARNONE		0x10 -#define	MR1_PARSPECIAL		0x18 -#define	MR1_ERRCHAR		0x00 -#define	MR1_ERRBLOCK		0x20 -#define	MR1_ISRUNMASKED		0x00 -#define	MR1_ISRMASKED		0x40 -#define	MR1_AUTORTS		0x80 - -/* - *	Mode register 2 bit definitions. - */ -#define	MR2_STOP1		0x00 -#define	MR2_STOP15		0x01 -#define	MR2_STOP2		0x02 -#define	MR2_STOP916		0x03 -#define	MR2_RXFIFORDY		0x00 -#define	MR2_RXFIFOHALF		0x04 -#define	MR2_RXFIFOHIGH		0x08 -#define	MR2_RXFIFOFULL		0x0c -#define	MR2_AUTOCTS		0x10 -#define	MR2_TXRTS		0x20 -#define	MR2_MODENORM		0x00 -#define	MR2_MODEAUTOECHO	0x40 -#define	MR2_MODELOOP		0x80 -#define	MR2_MODEREMECHO		0xc0 - -/*****************************************************************************/ - -/* - *	Baud Rate Generator (BRG) selector values. - */ -#define	BRG_50			0x00 -#define	BRG_75			0x01 -#define	BRG_150			0x02 -#define	BRG_200			0x03 -#define	BRG_300			0x04 -#define	BRG_450			0x05 -#define	BRG_600			0x06 -#define	BRG_900			0x07 -#define	BRG_1200		0x08 -#define	BRG_1800		0x09 -#define	BRG_2400		0x0a -#define	BRG_3600		0x0b -#define	BRG_4800		0x0c -#define	BRG_7200		0x0d -#define	BRG_9600		0x0e -#define	BRG_14400		0x0f -#define	BRG_19200		0x10 -#define	BRG_28200		0x11 -#define	BRG_38400		0x12 -#define	BRG_57600		0x13 -#define	BRG_115200		0x14 -#define	BRG_230400		0x15 -#define	BRG_GIN0		0x16 -#define	BRG_GIN1		0x17 -#define	BRG_CT0			0x18 -#define	BRG_CT1			0x19 -#define	BRG_RX2TX316		0x1b -#define	BRG_RX2TX31		0x1c - -#define	SC26198_MAXBAUD		921600 - -/*****************************************************************************/ - -/* - *	Command register command definitions. - */ -#define	CR_NULL			0x04 -#define	CR_ADDRNORMAL		0x0c -#define	CR_RXRESET		0x14 -#define	CR_TXRESET		0x1c -#define	CR_CLEARRXERR		0x24 -#define	CR_BREAKRESET		0x2c -#define	CR_TXSTARTBREAK		0x34 -#define	CR_TXSTOPBREAK		0x3c -#define	CR_RTSON		0x44 -#define	CR_RTSOFF		0x4c -#define	CR_ADDRINIT		0x5c -#define	CR_RXERRBLOCK		0x6c -#define	CR_TXSENDXON		0x84 -#define	CR_TXSENDXOFF		0x8c -#define	CR_GANGXONSET		0x94 -#define	CR_GANGXOFFSET		0x9c -#define	CR_GANGXONINIT		0xa4 -#define	CR_GANGXOFFINIT		0xac -#define	CR_HOSTXON		0xb4 -#define	CR_HOSTXOFF		0xbc -#define	CR_CANCELXOFF		0xc4 -#define	CR_ADDRRESET		0xdc -#define	CR_RESETALLPORTS	0xf4 -#define	CR_RESETALL		0xfc - -#define	CR_RXENABLE		0x01 -#define	CR_TXENABLE		0x02 - -/*****************************************************************************/ - -/* - *	Channel status register. - */ -#define	SR_RXRDY		0x01 -#define	SR_RXFULL		0x02 -#define	SR_TXRDY		0x04 -#define	SR_TXEMPTY		0x08 -#define	SR_RXOVERRUN		0x10 -#define	SR_RXPARITY		0x20 -#define	SR_RXFRAMING		0x40 -#define	SR_RXBREAK		0x80 - -#define	SR_RXERRS		(SR_RXPARITY | SR_RXFRAMING | SR_RXOVERRUN) - -/*****************************************************************************/ - -/* - *	Interrupt status register and interrupt mask register bit definitions. - */ -#define	IR_TXRDY		0x01 -#define	IR_RXRDY		0x02 -#define	IR_RXBREAK		0x04 -#define	IR_XONXOFF		0x10 -#define	IR_ADDRRECOG		0x20 -#define	IR_RXWATCHDOG		0x40 -#define	IR_IOPORT		0x80 - -/*****************************************************************************/ - -/* - *	Interrupt vector register field definitions. - */ -#define	IVR_CHANMASK		0x07 -#define	IVR_TYPEMASK		0x18 -#define	IVR_CONSTMASK		0xc0 - -#define	IVR_RXDATA		0x10 -#define	IVR_RXBADDATA		0x18 -#define	IVR_TXDATA		0x08 -#define	IVR_OTHER		0x00 - -/*****************************************************************************/ - -/* - *	BRG timer control register bit definitions. - */ -#define	BRGCTCR_DISABCLK0	0x00 -#define	BRGCTCR_ENABCLK0	0x08 -#define	BRGCTCR_DISABCLK1	0x00 -#define	BRGCTCR_ENABCLK1	0x80 - -#define	BRGCTCR_0SCLK16		0x00 -#define	BRGCTCR_0SCLK32		0x01 -#define	BRGCTCR_0SCLK64		0x02 -#define	BRGCTCR_0SCLK128	0x03 -#define	BRGCTCR_0X1		0x04 -#define	BRGCTCR_0X12		0x05 -#define	BRGCTCR_0IO1A		0x06 -#define	BRGCTCR_0GIN0		0x07 - -#define	BRGCTCR_1SCLK16		0x00 -#define	BRGCTCR_1SCLK32		0x10 -#define	BRGCTCR_1SCLK64		0x20 -#define	BRGCTCR_1SCLK128	0x30 -#define	BRGCTCR_1X1		0x40 -#define	BRGCTCR_1X12		0x50 -#define	BRGCTCR_1IO1B		0x60 -#define	BRGCTCR_1GIN1		0x70 - -/*****************************************************************************/ - -/* - *	Watch dog timer enable register. - */ -#define	WDTRCR_ENABALL		0xff - -/*****************************************************************************/ - -/* - *	XON/XOFF interrupt status register. - */ -#define	XISR_TXCHARMASK		0x03 -#define	XISR_TXCHARNORMAL	0x00 -#define	XISR_TXWAIT		0x01 -#define	XISR_TXXOFFPEND		0x02 -#define	XISR_TXXONPEND		0x03 - -#define	XISR_TXFLOWMASK		0x0c -#define	XISR_TXNORMAL		0x00 -#define	XISR_TXSTOPPEND		0x04 -#define	XISR_TXSTARTED		0x08 -#define	XISR_TXSTOPPED		0x0c - -#define	XISR_RXFLOWMASK		0x30 -#define	XISR_RXFLOWNONE		0x00 -#define	XISR_RXXONSENT		0x10 -#define	XISR_RXXOFFSENT		0x20 - -#define	XISR_RXXONGOT		0x40 -#define	XISR_RXXOFFGOT		0x80 - -/*****************************************************************************/ - -/* - *	Current interrupt register. - */ -#define	CIR_TYPEMASK		0xc0 -#define	CIR_TYPEOTHER		0x00 -#define	CIR_TYPETX		0x40 -#define	CIR_TYPERXGOOD		0x80 -#define	CIR_TYPERXBAD		0xc0 - -#define	CIR_RXDATA		0x80 -#define	CIR_RXBADDATA		0x40 -#define	CIR_TXDATA		0x40 - -#define	CIR_CHANMASK		0x07 -#define	CIR_CNTMASK		0x38 - -#define	CIR_SUBTYPEMASK		0x38 -#define	CIR_SUBNONE		0x00 -#define	CIR_SUBCOS		0x08 -#define	CIR_SUBADDR		0x10 -#define	CIR_SUBXONXOFF		0x18 -#define	CIR_SUBBREAK		0x28 - -/*****************************************************************************/ - -/* - *	Global interrupting channel register. - */ -#define	GICR_CHANMASK		0x07 - -/*****************************************************************************/ - -/* - *	Global interrupting byte count register. - */ -#define	GICR_COUNTMASK		0x0f - -/*****************************************************************************/ - -/* - *	Global interrupting type register. - */ -#define	GITR_RXMASK		0xc0 -#define	GITR_RXNONE		0x00 -#define	GITR_RXBADDATA		0x80 -#define	GITR_RXGOODDATA		0xc0 -#define	GITR_TXDATA		0x20 - -#define	GITR_SUBTYPEMASK	0x07 -#define	GITR_SUBNONE		0x00 -#define	GITR_SUBCOS		0x01 -#define	GITR_SUBADDR		0x02 -#define	GITR_SUBXONXOFF		0x03 -#define	GITR_SUBBREAK		0x05 - -/*****************************************************************************/ - -/* - *	Input port change register. - */ -#define	IPR_CTS			0x01 -#define	IPR_DTR			0x02 -#define	IPR_RTS			0x04 -#define	IPR_DCD			0x08 -#define	IPR_CTSCHANGE		0x10 -#define	IPR_DTRCHANGE		0x20 -#define	IPR_RTSCHANGE		0x40 -#define	IPR_DCDCHANGE		0x80 - -#define	IPR_CHANGEMASK		0xf0 - -/*****************************************************************************/ - -/* - *	IO port interrupt and output register. - */ -#define	IOPR_CTS		0x01 -#define	IOPR_DTR		0x02 -#define	IOPR_RTS		0x04 -#define	IOPR_DCD		0x08 -#define	IOPR_CTSCOS		0x10 -#define	IOPR_DTRCOS		0x20 -#define	IOPR_RTSCOS		0x40 -#define	IOPR_DCDCOS		0x80 - -/*****************************************************************************/ - -/* - *	IO port configuration register. - */ -#define	IOPCR_SETCTS		0x00 -#define	IOPCR_SETDTR		0x04 -#define	IOPCR_SETRTS		0x10 -#define	IOPCR_SETDCD		0x00 - -#define	IOPCR_SETSIGS		(IOPCR_SETRTS | IOPCR_SETRTS | IOPCR_SETDTR | IOPCR_SETDCD) - -/*****************************************************************************/ - -/* - *	General purpose output select register. - */ -#define	GPORS_TXC1XA		0x08 -#define	GPORS_TXC16XA		0x09 -#define	GPORS_RXC16XA		0x0a -#define	GPORS_TXC16XB		0x0b -#define	GPORS_GPOR3		0x0c -#define	GPORS_GPOR2		0x0d -#define	GPORS_GPOR1		0x0e -#define	GPORS_GPOR0		0x0f - -/*****************************************************************************/ - -/* - *	General purpose output register. - */ -#define	GPOR_0			0x01 -#define	GPOR_1			0x02 -#define	GPOR_2			0x04 -#define	GPOR_3			0x08 - -/*****************************************************************************/ - -/* - *	General purpose output clock register. - */ -#define	GPORC_0NONE		0x00 -#define	GPORC_0GIN0		0x01 -#define	GPORC_0GIN1		0x02 -#define	GPORC_0IO3A		0x02 - -#define	GPORC_1NONE		0x00 -#define	GPORC_1GIN0		0x04 -#define	GPORC_1GIN1		0x08 -#define	GPORC_1IO3C		0x0c - -#define	GPORC_2NONE		0x00 -#define	GPORC_2GIN0		0x10 -#define	GPORC_2GIN1		0x20 -#define	GPORC_2IO3E		0x20 - -#define	GPORC_3NONE		0x00 -#define	GPORC_3GIN0		0x40 -#define	GPORC_3GIN1		0x80 -#define	GPORC_3IO3G		0xc0 - -/*****************************************************************************/ - -/* - *	General purpose output data register. - */ -#define	GPOD_0MASK		0x03 -#define	GPOD_0SET1		0x00 -#define	GPOD_0SET0		0x01 -#define	GPOD_0SETR0		0x02 -#define	GPOD_0SETIO3B		0x03 - -#define	GPOD_1MASK		0x0c -#define	GPOD_1SET1		0x00 -#define	GPOD_1SET0		0x04 -#define	GPOD_1SETR0		0x08 -#define	GPOD_1SETIO3D		0x0c - -#define	GPOD_2MASK		0x30 -#define	GPOD_2SET1		0x00 -#define	GPOD_2SET0		0x10 -#define	GPOD_2SETR0		0x20 -#define	GPOD_2SETIO3F		0x30 - -#define	GPOD_3MASK		0xc0 -#define	GPOD_3SET1		0x00 -#define	GPOD_3SET0		0x40 -#define	GPOD_3SETR0		0x80 -#define	GPOD_3SETIO3H		0xc0 - -/*****************************************************************************/ -#endif diff --git a/include/linux/serial167.h b/include/linux/serial167.h deleted file mode 100644 index 59c81b708562..000000000000 --- a/include/linux/serial167.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * serial167.h - * - * Richard Hirst [richard@sleepie.demon.co.uk] - * - * Based on cyclades.h - */ - -struct cyclades_monitor { -        unsigned long           int_count; -        unsigned long           char_count; -        unsigned long           char_max; -        unsigned long           char_last; -}; - -/* - * This is our internal structure for each serial port's state. - *  - * Many fields are paralleled by the structure used by the serial_struct - * structure. - * - * For definitions of the flags field, see tty.h - */ - -struct cyclades_port { -	int                     magic; -	int                     type; -	int			card; -	int			line; -	int			flags; 		/* defined in tty.h */ -	struct tty_struct 	*tty; -	int			read_status_mask; -	int			timeout; -	int			xmit_fifo_size; -	int                     cor1,cor2,cor3,cor4,cor5,cor6,cor7; -	int                     tbpr,tco,rbpr,rco; -	int			ignore_status_mask; -	int			close_delay; -	int			IER; 	/* Interrupt Enable Register */ -	unsigned long		last_active; -	int			count;	/* # of fd on device */ -	int                     x_char; /* to be pushed out ASAP */ -	int                     x_break; -	int			blocked_open; /* # of blocked opens */ -	unsigned char 		*xmit_buf; -	int			xmit_head; -	int			xmit_tail; -	int			xmit_cnt; -        int                     default_threshold; -        int                     default_timeout; -	wait_queue_head_t	open_wait; -	wait_queue_head_t	close_wait; -        struct cyclades_monitor mon; -}; - -#define CYCLADES_MAGIC  0x4359 - -#define CYGETMON                0x435901 -#define CYGETTHRESH             0x435902 -#define CYSETTHRESH             0x435903 -#define CYGETDEFTHRESH          0x435904 -#define CYSETDEFTHRESH          0x435905 -#define CYGETTIMEOUT            0x435906 -#define CYSETTIMEOUT            0x435907 -#define CYGETDEFTIMEOUT         0x435908 -#define CYSETDEFTIMEOUT         0x435909 - -#define CyMaxChipsPerCard 1 - -/**** cd2401 registers ****/ - -#define CyGFRCR         (0x81) -#define CyCCR		(0x13) -#define      CyCLR_CHAN		(0x40) -#define      CyINIT_CHAN	(0x20) -#define      CyCHIP_RESET	(0x10) -#define      CyENB_XMTR		(0x08) -#define      CyDIS_XMTR		(0x04) -#define      CyENB_RCVR		(0x02) -#define      CyDIS_RCVR		(0x01) -#define CyCAR		(0xee) -#define CyIER		(0x11) -#define      CyMdmCh		(0x80) -#define      CyRxExc		(0x20) -#define      CyRxData		(0x08) -#define      CyTxMpty		(0x02) -#define      CyTxRdy		(0x01) -#define CyLICR		(0x26) -#define CyRISR		(0x89) -#define      CyTIMEOUT		(0x80) -#define      CySPECHAR		(0x70) -#define      CyOVERRUN		(0x08) -#define      CyPARITY		(0x04) -#define      CyFRAME		(0x02) -#define      CyBREAK		(0x01) -#define CyREOIR		(0x84) -#define CyTEOIR		(0x85) -#define CyMEOIR		(0x86) -#define      CyNOTRANS		(0x08) -#define CyRFOC		(0x30) -#define CyRDR		(0xf8) -#define CyTDR		(0xf8) -#define CyMISR		(0x8b) -#define CyRISR		(0x89) -#define CyTISR		(0x8a) -#define CyMSVR1		(0xde) -#define CyMSVR2		(0xdf) -#define      CyDSR		(0x80) -#define      CyDCD		(0x40) -#define      CyCTS		(0x20) -#define      CyDTR		(0x02) -#define      CyRTS		(0x01) -#define CyRTPRL		(0x25) -#define CyRTPRH		(0x24) -#define CyCOR1		(0x10) -#define      CyPARITY_NONE	(0x00) -#define      CyPARITY_E		(0x40) -#define      CyPARITY_O		(0xC0) -#define      Cy_5_BITS		(0x04) -#define      Cy_6_BITS		(0x05) -#define      Cy_7_BITS		(0x06) -#define      Cy_8_BITS		(0x07) -#define CyCOR2		(0x17) -#define      CyETC		(0x20) -#define      CyCtsAE		(0x02) -#define CyCOR3		(0x16) -#define      Cy_1_STOP		(0x02) -#define      Cy_2_STOP		(0x04) -#define CyCOR4		(0x15) -#define      CyREC_FIFO		(0x0F)  /* Receive FIFO threshold */ -#define CyCOR5		(0x14) -#define CyCOR6		(0x18) -#define CyCOR7		(0x07) -#define CyRBPR		(0xcb) -#define CyRCOR		(0xc8) -#define CyTBPR		(0xc3) -#define CyTCOR		(0xc0) -#define CySCHR1		(0x1f) -#define CySCHR2 	(0x1e) -#define CyTPR		(0xda) -#define CyPILR1		(0xe3) -#define CyPILR2		(0xe0) -#define CyPILR3		(0xe1) -#define CyCMR		(0x1b) -#define      CyASYNC		(0x02) -#define CyLICR          (0x26) -#define CyLIVR          (0x09) -#define CySCRL		(0x23) -#define CySCRH		(0x22) -#define CyTFTC		(0x80) - - -/* max number of chars in the FIFO */ - -#define CyMAX_CHAR_FIFO	12 - -/***************************************************************************/ diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h index a416e92012ef..f41dcc949218 100644 --- a/include/linux/serial_8250.h +++ b/include/linux/serial_8250.h @@ -69,7 +69,6 @@ struct uart_port;  struct uart_8250_port;  int serial8250_register_8250_port(struct uart_8250_port *); -int serial8250_register_port(struct uart_port *);  void serial8250_unregister_port(int line);  void serial8250_suspend_port(int line);  void serial8250_resume_port(int line); diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 65db9928e15f..0253c2022e53 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -47,7 +47,8 @@  #define PORT_U6_16550A	19	/* ST-Ericsson U6xxx internal UART */  #define PORT_TEGRA	20	/* NVIDIA Tegra internal UART */  #define PORT_XR17D15X	21	/* Exar XR17D15x UART */ -#define PORT_MAX_8250	21	/* max port ID */ +#define PORT_LPC3220	22	/* NXP LPC32xx SoC "Standard" UART */ +#define PORT_MAX_8250	22	/* max port ID */  /*   * ARM specific type numbers.  These are not currently guaranteed diff --git a/include/linux/stallion.h b/include/linux/stallion.h deleted file mode 100644 index 336af33c6ea4..000000000000 --- a/include/linux/stallion.h +++ /dev/null @@ -1,147 +0,0 @@ -/*****************************************************************************/ - -/* - *	stallion.h  -- stallion multiport serial driver. - * - *	Copyright (C) 1996-1998  Stallion Technologies - *	Copyright (C) 1994-1996  Greg Ungerer. - * - *	This program is free software; you can redistribute it and/or modify - *	it under the terms of the GNU General Public License as published by - *	the Free Software Foundation; either version 2 of the License, or - *	(at your option) any later version. - * - *	This program is distributed in the hope that it will be useful, - *	but WITHOUT ANY WARRANTY; without even the implied warranty of - *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - *	GNU General Public License for more details. - * - *	You should have received a copy of the GNU General Public License - *	along with this program; if not, write to the Free Software - *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/*****************************************************************************/ -#ifndef	_STALLION_H -#define	_STALLION_H -/*****************************************************************************/ - -/* - *	Define important driver constants here. - */ -#define	STL_MAXBRDS		4 -#define	STL_MAXPANELS		4 -#define	STL_MAXBANKS		8 -#define	STL_PORTSPERPANEL	16 -#define	STL_MAXPORTS		64 -#define	STL_MAXDEVS		(STL_MAXBRDS * STL_MAXPORTS) - - -/* - *	Define a set of structures to hold all the board/panel/port info - *	for our ports. These will be dynamically allocated as required. - */ - -/* - *	Define a ring queue structure for each port. This will hold the - *	TX data waiting to be output. Characters are fed into this buffer - *	from the line discipline (or even direct from user space!) and - *	then fed into the UARTs during interrupts. Will use a classic ring - *	queue here for this. The good thing about this type of ring queue - *	is that the head and tail pointers can be updated without interrupt - *	protection - since "write" code only needs to change the head, and - *	interrupt code only needs to change the tail. - */ -struct stlrq { -	char	*buf; -	char	*head; -	char	*tail; -}; - -/* - *	Port, panel and board structures to hold status info about each. - *	The board structure contains pointers to structures for each panel - *	connected to it, and in turn each panel structure contains pointers - *	for each port structure for each port on that panel. Note that - *	the port structure also contains the board and panel number that it - *	is associated with, this makes it (fairly) easy to get back to the - *	board/panel info for a port. - */ -struct stlport { -	unsigned long		magic; -	struct tty_port		port; -	unsigned int		portnr; -	unsigned int		panelnr; -	unsigned int		brdnr; -	int			ioaddr; -	int			uartaddr; -	unsigned int		pagenr; -	unsigned long		istate; -	int			baud_base; -	int			custom_divisor; -	int			close_delay; -	int			closing_wait; -	int			openwaitcnt; -	int			brklen; -	unsigned int		sigs; -	unsigned int		rxignoremsk; -	unsigned int		rxmarkmsk; -	unsigned int		imr; -	unsigned int		crenable; -	unsigned long		clk; -	unsigned long		hwid; -	void			*uartp; -	comstats_t		stats; -	struct stlrq		tx; -}; - -struct stlpanel { -	unsigned long	magic; -	unsigned int	panelnr; -	unsigned int	brdnr; -	unsigned int	pagenr; -	unsigned int	nrports; -	int		iobase; -	void		*uartp; -	void		(*isr)(struct stlpanel *panelp, unsigned int iobase); -	unsigned int	hwid; -	unsigned int	ackmask; -	struct stlport	*ports[STL_PORTSPERPANEL]; -}; - -struct stlbrd { -	unsigned long	magic; -	unsigned int	brdnr; -	unsigned int	brdtype; -	unsigned int	state; -	unsigned int	nrpanels; -	unsigned int	nrports; -	unsigned int	nrbnks; -	int		irq; -	int		irqtype; -	int		(*isr)(struct stlbrd *brdp); -	unsigned int	ioaddr1; -	unsigned int	ioaddr2; -	unsigned int	iosize1; -	unsigned int	iosize2; -	unsigned int	iostatus; -	unsigned int	ioctrl; -	unsigned int	ioctrlval; -	unsigned int	hwid; -	unsigned long	clk; -	unsigned int	bnkpageaddr[STL_MAXBANKS]; -	unsigned int	bnkstataddr[STL_MAXBANKS]; -	struct stlpanel	*bnk2panel[STL_MAXBANKS]; -	struct stlpanel	*panels[STL_MAXPANELS]; -}; - - -/* - *	Define MAGIC numbers used for above structures. - */ -#define	STL_PORTMAGIC	0x5a7182c9 -#define	STL_PANELMAGIC	0x7ef621a1 -#define	STL_BOARDMAGIC	0xa2267f52 - -/*****************************************************************************/ -#endif diff --git a/include/linux/tty.h b/include/linux/tty.h index 9f47ab540f65..7f9d7df9b131 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -268,6 +268,7 @@ struct tty_struct {  	struct mutex ldisc_mutex;  	struct tty_ldisc *ldisc; +	struct mutex legacy_mutex;  	struct mutex termios_mutex;  	spinlock_t ctrl_lock;  	/* Termios values are protected by the termios mutex */ @@ -497,6 +498,9 @@ extern int tty_write_lock(struct tty_struct *tty, int ndelay);  #define tty_is_writelocked(tty)  (mutex_is_locked(&tty->atomic_write_lock))  extern void tty_port_init(struct tty_port *port); +extern struct device *tty_port_register_device(struct tty_port *port, +		struct tty_driver *driver, unsigned index, +		struct device *device);  extern int tty_port_alloc_xmit_buf(struct tty_port *port);  extern void tty_port_free_xmit_buf(struct tty_port *port);  extern void tty_port_put(struct tty_port *port); @@ -521,6 +525,8 @@ extern int tty_port_close_start(struct tty_port *port,  extern void tty_port_close_end(struct tty_port *port, struct tty_struct *tty);  extern void tty_port_close(struct tty_port *port,  				struct tty_struct *tty, struct file *filp); +extern int tty_port_install(struct tty_port *port, struct tty_driver *driver, +				struct tty_struct *tty);  extern int tty_port_open(struct tty_port *port,  				struct tty_struct *tty, struct file *filp);  static inline int tty_port_users(struct tty_port *port) @@ -605,8 +611,12 @@ extern long vt_compat_ioctl(struct tty_struct *tty,  /* tty_mutex.c */  /* functions for preparation of BKL removal */ -extern void __lockfunc tty_lock(void) __acquires(tty_lock); -extern void __lockfunc tty_unlock(void) __releases(tty_lock); +extern void __lockfunc tty_lock(struct tty_struct *tty); +extern void __lockfunc tty_unlock(struct tty_struct *tty); +extern void __lockfunc tty_lock_pair(struct tty_struct *tty, +				struct tty_struct *tty2); +extern void __lockfunc tty_unlock_pair(struct tty_struct *tty, +				struct tty_struct *tty2);  /*   * this shall be called only from where BTM is held (like close) @@ -621,9 +631,9 @@ extern void __lockfunc tty_unlock(void) __releases(tty_lock);  static inline void tty_wait_until_sent_from_close(struct tty_struct *tty,  		long timeout)  { -	tty_unlock(); /* tty->ops->close holds the BTM, drop it while waiting */ +	tty_unlock(tty); /* tty->ops->close holds the BTM, drop it while waiting */  	tty_wait_until_sent(tty, timeout); -	tty_lock(); +	tty_lock(tty);  }  /* @@ -638,16 +648,16 @@ static inline void tty_wait_until_sent_from_close(struct tty_struct *tty,   *   * Do not use in new code.   */ -#define wait_event_interruptible_tty(wq, condition)			\ +#define wait_event_interruptible_tty(tty, wq, condition)		\  ({									\  	int __ret = 0;							\  	if (!(condition)) {						\ -		__wait_event_interruptible_tty(wq, condition, __ret);	\ +		__wait_event_interruptible_tty(tty, wq, condition, __ret);	\  	}								\  	__ret;								\  }) -#define __wait_event_interruptible_tty(wq, condition, ret)		\ +#define __wait_event_interruptible_tty(tty, wq, condition, ret)		\  do {									\  	DEFINE_WAIT(__wait);						\  									\ @@ -656,9 +666,9 @@ do {									\  		if (condition)						\  			break;						\  		if (!signal_pending(current)) {				\ -			tty_unlock();					\ +			tty_unlock(tty);					\  			schedule();					\ -			tty_lock();					\ +			tty_lock(tty);					\  			continue;					\  		}							\  		ret = -ERESTARTSYS;					\ diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h index 6e6dbb7447b6..04419c141b00 100644 --- a/include/linux/tty_driver.h +++ b/include/linux/tty_driver.h @@ -313,6 +313,7 @@ struct tty_driver {  	 * Pointer to the tty data structures  	 */  	struct tty_struct **ttys; +	struct tty_port **ports;  	struct ktermios **termios;  	void *driver_state; diff --git a/include/net/irda/ircomm_tty.h b/include/net/irda/ircomm_tty.h index 59ba38bc400f..80ffde3bb164 100644 --- a/include/net/irda/ircomm_tty.h +++ b/include/net/irda/ircomm_tty.h @@ -52,21 +52,16 @@  /* Same for payload size. See qos.c for the smallest max data size */  #define IRCOMM_TTY_DATA_UNINITIALISED	(64 - IRCOMM_TTY_HDR_UNINITIALISED) -/* Those are really defined in include/linux/serial.h - Jean II */ -#define ASYNC_B_INITIALIZED	31	/* Serial port was initialized */ -#define ASYNC_B_NORMAL_ACTIVE	29	/* Normal device is active */ -#define ASYNC_B_CLOSING		27	/* Serial port is closing */ -  /*   * IrCOMM TTY driver state   */  struct ircomm_tty_cb {  	irda_queue_t queue;            /* Must be first */ +	struct tty_port port;  	magic_t magic;  	int state;                /* Connect state */ -	struct tty_struct *tty;  	struct ircomm_cb *ircomm; /* IrCOMM layer instance */  	struct sk_buff *tx_skb;   /* Transmit buffer */ @@ -80,7 +75,6 @@ struct ircomm_tty_cb {  	LOCAL_FLOW flow;          /* IrTTP flow status */  	int line; -	unsigned long flags;  	__u8 dlsap_sel;  	__u8 slsap_sel; @@ -97,19 +91,10 @@ struct ircomm_tty_cb {  	void *skey;  	void *ckey; -	wait_queue_head_t open_wait; -	wait_queue_head_t close_wait;  	struct timer_list watchdog_timer;  	struct work_struct  tqueue; -        unsigned short    close_delay; -        unsigned short    closing_wait; /* time to wait before closing */ - -	int  open_count; -	int  blocked_open;	/* # of blocked opens */ -  	/* Protect concurent access to : -	 *	o self->open_count  	 *	o self->ctrl_skb  	 *	o self->tx_skb  	 * Maybe other things may gain to be protected as well... diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index d1820ff14aee..aa5d73b786ac 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c @@ -710,9 +710,9 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)  			break;  		} -		tty_unlock(); +		tty_unlock(tty);  		schedule(); -		tty_lock(); +		tty_lock(tty);  	}  	set_current_state(TASK_RUNNING);  	remove_wait_queue(&dev->wait, &wait); diff --git a/net/irda/ircomm/ircomm_param.c b/net/irda/ircomm/ircomm_param.c index 8b915f3ac3b9..308939128359 100644 --- a/net/irda/ircomm/ircomm_param.c +++ b/net/irda/ircomm/ircomm_param.c @@ -99,7 +99,6 @@ pi_param_info_t ircomm_param_info = { pi_major_call_table, 3, 0x0f, 4 };   */  int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush)  { -	struct tty_struct *tty;  	unsigned long flags;  	struct sk_buff *skb;  	int count; @@ -109,10 +108,6 @@ int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush)  	IRDA_ASSERT(self != NULL, return -1;);  	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;); -	tty = self->tty; -	if (!tty) -		return 0; -  	/* Make sure we don't send parameters for raw mode */  	if (self->service_type == IRCOMM_3_WIRE_RAW)  		return 0; diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c index 6b9d5a0e42f9..4e35b45c1c73 100644 --- a/net/irda/ircomm/ircomm_tty.c +++ b/net/irda/ircomm/ircomm_tty.c @@ -104,6 +104,35 @@ static const struct tty_operations ops = {  #endif /* CONFIG_PROC_FS */  }; +static void ircomm_port_raise_dtr_rts(struct tty_port *port, int raise) +{ +	struct ircomm_tty_cb *self = container_of(port, struct ircomm_tty_cb, +			port); +	/* +	 * Here, we use to lock those two guys, but as ircomm_param_request() +	 * does it itself, I don't see the point (and I see the deadlock). +	 * Jean II +	 */ +	if (raise) +		self->settings.dte |= IRCOMM_RTS | IRCOMM_DTR; +	else +		self->settings.dte &= ~(IRCOMM_RTS | IRCOMM_DTR); + +	ircomm_param_request(self, IRCOMM_DTE, TRUE); +} + +static int ircomm_port_carrier_raised(struct tty_port *port) +{ +	struct ircomm_tty_cb *self = container_of(port, struct ircomm_tty_cb, +			port); +	return self->settings.dce & IRCOMM_CD; +} + +static const struct tty_port_operations ircomm_port_ops = { +	.dtr_rts = ircomm_port_raise_dtr_rts, +	.carrier_raised = ircomm_port_carrier_raised, +}; +  /*   * Function ircomm_tty_init()   * @@ -194,7 +223,7 @@ static int ircomm_tty_startup(struct ircomm_tty_cb *self)  	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);  	/* Check if already open */ -	if (test_and_set_bit(ASYNC_B_INITIALIZED, &self->flags)) { +	if (test_and_set_bit(ASYNCB_INITIALIZED, &self->port.flags)) {  		IRDA_DEBUG(2, "%s(), already open so break out!\n", __func__ );  		return 0;  	} @@ -231,7 +260,7 @@ static int ircomm_tty_startup(struct ircomm_tty_cb *self)  	return 0;  err: -	clear_bit(ASYNC_B_INITIALIZED, &self->flags); +	clear_bit(ASYNCB_INITIALIZED, &self->port.flags);  	return ret;  } @@ -242,25 +271,23 @@ err:   *   */  static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self, -				      struct file *filp) +		struct tty_struct *tty, struct file *filp)  { +	struct tty_port *port = &self->port;  	DECLARE_WAITQUEUE(wait, current);  	int		retval;  	int		do_clocal = 0, extra_count = 0;  	unsigned long	flags; -	struct tty_struct *tty;  	IRDA_DEBUG(2, "%s()\n", __func__ ); -	tty = self->tty; -  	/*  	 * If non-blocking mode is set, or the port is not enabled,  	 * then make the check up front and then exit.  	 */  	if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){  		/* nonblock mode is set or port is not enabled */ -		self->flags |= ASYNC_NORMAL_ACTIVE; +		port->flags |= ASYNC_NORMAL_ACTIVE;  		IRDA_DEBUG(1, "%s(), O_NONBLOCK requested!\n", __func__ );  		return 0;  	} @@ -272,42 +299,34 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,  	/* Wait for carrier detect and the line to become  	 * free (i.e., not in use by the callout).  While we are in -	 * this loop, self->open_count is dropped by one, so that +	 * this loop, port->count is dropped by one, so that  	 * mgsl_close() knows when to free things.  We restore it upon  	 * exit, either normal or abnormal.  	 */  	retval = 0; -	add_wait_queue(&self->open_wait, &wait); +	add_wait_queue(&port->open_wait, &wait);  	IRDA_DEBUG(2, "%s(%d):block_til_ready before block on %s open_count=%d\n", -	      __FILE__,__LINE__, tty->driver->name, self->open_count ); +	      __FILE__, __LINE__, tty->driver->name, port->count); -	/* As far as I can see, we protect open_count - Jean II */ -	spin_lock_irqsave(&self->spinlock, flags); +	spin_lock_irqsave(&port->lock, flags);  	if (!tty_hung_up_p(filp)) {  		extra_count = 1; -		self->open_count--; +		port->count--;  	} -	spin_unlock_irqrestore(&self->spinlock, flags); -	self->blocked_open++; +	spin_unlock_irqrestore(&port->lock, flags); +	port->blocked_open++;  	while (1) { -		if (tty->termios->c_cflag & CBAUD) { -			/* Here, we use to lock those two guys, but -			 * as ircomm_param_request() does it itself, -			 * I don't see the point (and I see the deadlock). -			 * Jean II */ -			self->settings.dte |= IRCOMM_RTS + IRCOMM_DTR; - -			ircomm_param_request(self, IRCOMM_DTE, TRUE); -		} +		if (tty->termios->c_cflag & CBAUD) +			tty_port_raise_dtr_rts(port);  		current->state = TASK_INTERRUPTIBLE;  		if (tty_hung_up_p(filp) || -		    !test_bit(ASYNC_B_INITIALIZED, &self->flags)) { -			retval = (self->flags & ASYNC_HUP_NOTIFY) ? +		    !test_bit(ASYNCB_INITIALIZED, &port->flags)) { +			retval = (port->flags & ASYNC_HUP_NOTIFY) ?  					-EAGAIN : -ERESTARTSYS;  			break;  		} @@ -317,8 +336,8 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,  		 * specified, we cannot return before the IrCOMM link is  		 * ready  		 */ -		if (!test_bit(ASYNC_B_CLOSING, &self->flags) && -		    (do_clocal || (self->settings.dce & IRCOMM_CD)) && +		if (!test_bit(ASYNCB_CLOSING, &port->flags) && +		    (do_clocal || tty_port_carrier_raised(port)) &&  		    self->state == IRCOMM_TTY_READY)  		{  			break; @@ -330,27 +349,27 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,  		}  		IRDA_DEBUG(1, "%s(%d):block_til_ready blocking on %s open_count=%d\n", -		      __FILE__,__LINE__, tty->driver->name, self->open_count ); +		      __FILE__, __LINE__, tty->driver->name, port->count);  		schedule();  	}  	__set_current_state(TASK_RUNNING); -	remove_wait_queue(&self->open_wait, &wait); +	remove_wait_queue(&port->open_wait, &wait);  	if (extra_count) {  		/* ++ is not atomic, so this should be protected - Jean II */ -		spin_lock_irqsave(&self->spinlock, flags); -		self->open_count++; -		spin_unlock_irqrestore(&self->spinlock, flags); +		spin_lock_irqsave(&port->lock, flags); +		port->count++; +		spin_unlock_irqrestore(&port->lock, flags);  	} -	self->blocked_open--; +	port->blocked_open--;  	IRDA_DEBUG(1, "%s(%d):block_til_ready after blocking on %s open_count=%d\n", -	      __FILE__,__LINE__, tty->driver->name, self->open_count); +	      __FILE__, __LINE__, tty->driver->name, port->count);  	if (!retval) -		self->flags |= ASYNC_NORMAL_ACTIVE; +		port->flags |= ASYNC_NORMAL_ACTIVE;  	return retval;  } @@ -381,6 +400,8 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)  			return -ENOMEM;  		} +		tty_port_init(&self->port); +		self->port.ops = &ircomm_port_ops;  		self->magic = IRCOMM_TTY_MAGIC;  		self->flow = FLOW_STOP; @@ -388,13 +409,9 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)  		INIT_WORK(&self->tqueue, ircomm_tty_do_softint);  		self->max_header_size = IRCOMM_TTY_HDR_UNINITIALISED;  		self->max_data_size = IRCOMM_TTY_DATA_UNINITIALISED; -		self->close_delay = 5*HZ/10; -		self->closing_wait = 30*HZ;  		/* Init some important stuff */  		init_timer(&self->watchdog_timer); -		init_waitqueue_head(&self->open_wait); -		init_waitqueue_head(&self->close_wait);  		spin_lock_init(&self->spinlock);  		/* @@ -408,27 +425,28 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)  		tty->termios->c_oflag = 0;  		/* Insert into hash */ +		/* FIXME there is a window from find to here */  		hashbin_insert(ircomm_tty, (irda_queue_t *) self, line, NULL);  	}  	/* ++ is not atomic, so this should be protected - Jean II */ -	spin_lock_irqsave(&self->spinlock, flags); -	self->open_count++; +	spin_lock_irqsave(&self->port.lock, flags); +	self->port.count++;  	tty->driver_data = self; -	self->tty = tty; -	spin_unlock_irqrestore(&self->spinlock, flags); +	spin_unlock_irqrestore(&self->port.lock, flags); +	tty_port_tty_set(&self->port, tty);  	IRDA_DEBUG(1, "%s(), %s%d, count = %d\n", __func__ , tty->driver->name, -		   self->line, self->open_count); +		   self->line, self->port.count);  	/* Not really used by us, but lets do it anyway */ -	self->tty->low_latency = (self->flags & ASYNC_LOW_LATENCY) ? 1 : 0; +	tty->low_latency = (self->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;  	/*  	 * If the port is the middle of closing, bail out now  	 */  	if (tty_hung_up_p(filp) || -	    test_bit(ASYNC_B_CLOSING, &self->flags)) { +	    test_bit(ASYNCB_CLOSING, &self->port.flags)) {  		/* Hm, why are we blocking on ASYNC_CLOSING if we  		 * do return -EAGAIN/-ERESTARTSYS below anyway? @@ -438,14 +456,15 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)  		 * probably better sleep uninterruptible?  		 */ -		if (wait_event_interruptible(self->close_wait, !test_bit(ASYNC_B_CLOSING, &self->flags))) { +		if (wait_event_interruptible(self->port.close_wait, +				!test_bit(ASYNCB_CLOSING, &self->port.flags))) {  			IRDA_WARNING("%s - got signal while blocking on ASYNC_CLOSING!\n",  				     __func__);  			return -ERESTARTSYS;  		}  #ifdef SERIAL_DO_RESTART -		return (self->flags & ASYNC_HUP_NOTIFY) ? +		return (self->port.flags & ASYNC_HUP_NOTIFY) ?  			-EAGAIN : -ERESTARTSYS;  #else  		return -EAGAIN; @@ -469,7 +488,7 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)  	if (ret)  		return ret; -	ret = ircomm_tty_block_til_ready(self, filp); +	ret = ircomm_tty_block_til_ready(self, tty, filp);  	if (ret) {  		IRDA_DEBUG(2,  		      "%s(), returning after block_til_ready with %d\n", __func__ , @@ -489,81 +508,22 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)  static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)  {  	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data; -	unsigned long flags; +	struct tty_port *port = &self->port;  	IRDA_DEBUG(0, "%s()\n", __func__ );  	IRDA_ASSERT(self != NULL, return;);  	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); -	spin_lock_irqsave(&self->spinlock, flags); - -	if (tty_hung_up_p(filp)) { -		spin_unlock_irqrestore(&self->spinlock, flags); - -		IRDA_DEBUG(0, "%s(), returning 1\n", __func__ ); -		return; -	} - -	if ((tty->count == 1) && (self->open_count != 1)) { -		/* -		 * Uh, oh.  tty->count is 1, which means that the tty -		 * structure will be freed.  state->count should always -		 * be one in these conditions.  If it's greater than -		 * one, we've got real problems, since it means the -		 * serial port won't be shutdown. -		 */ -		IRDA_DEBUG(0, "%s(), bad serial port count; " -			   "tty->count is 1, state->count is %d\n", __func__ , -			   self->open_count); -		self->open_count = 1; -	} - -	if (--self->open_count < 0) { -		IRDA_ERROR("%s(), bad serial port count for ttys%d: %d\n", -			   __func__, self->line, self->open_count); -		self->open_count = 0; -	} -	if (self->open_count) { -		spin_unlock_irqrestore(&self->spinlock, flags); - -		IRDA_DEBUG(0, "%s(), open count > 0\n", __func__ ); +	if (tty_port_close_start(port, tty, filp) == 0)  		return; -	} - -	/* Hum... Should be test_and_set_bit ??? - Jean II */ -	set_bit(ASYNC_B_CLOSING, &self->flags); - -	/* We need to unlock here (we were unlocking at the end of this -	 * function), because tty_wait_until_sent() may schedule. -	 * I don't know if the rest should be protected somehow, -	 * so someone should check. - Jean II */ -	spin_unlock_irqrestore(&self->spinlock, flags); - -	/* -	 * Now we wait for the transmit buffer to clear; and we notify -	 * the line discipline to only process XON/XOFF characters. -	 */ -	tty->closing = 1; -	if (self->closing_wait != ASYNC_CLOSING_WAIT_NONE) -		tty_wait_until_sent_from_close(tty, self->closing_wait);  	ircomm_tty_shutdown(self);  	tty_driver_flush_buffer(tty); -	tty_ldisc_flush(tty); -	tty->closing = 0; -	self->tty = NULL; - -	if (self->blocked_open) { -		if (self->close_delay) -			schedule_timeout_interruptible(self->close_delay); -		wake_up_interruptible(&self->open_wait); -	} - -	self->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); -	wake_up_interruptible(&self->close_wait); +	tty_port_close_end(port, tty); +	tty_port_tty_set(port, NULL);  }  /* @@ -606,7 +566,7 @@ static void ircomm_tty_do_softint(struct work_struct *work)  	if (!self || self->magic != IRCOMM_TTY_MAGIC)  		return; -	tty = self->tty; +	tty = tty_port_tty_get(&self->port);  	if (!tty)  		return; @@ -627,7 +587,7 @@ static void ircomm_tty_do_softint(struct work_struct *work)  	}  	if (tty->hw_stopped) -		return; +		goto put;  	/* Unlink transmit buffer */  	spin_lock_irqsave(&self->spinlock, flags); @@ -646,6 +606,8 @@ static void ircomm_tty_do_softint(struct work_struct *work)  	/* Check if user (still) wants to be waken up */  	tty_wakeup(tty); +put: +	tty_kref_put(tty);  }  /* @@ -955,7 +917,7 @@ static void ircomm_tty_shutdown(struct ircomm_tty_cb *self)  	IRDA_DEBUG(0, "%s()\n", __func__ ); -	if (!test_and_clear_bit(ASYNC_B_INITIALIZED, &self->flags)) +	if (!test_and_clear_bit(ASYNCB_INITIALIZED, &self->port.flags))  		return;  	ircomm_tty_detach_cable(self); @@ -994,6 +956,7 @@ static void ircomm_tty_shutdown(struct ircomm_tty_cb *self)  static void ircomm_tty_hangup(struct tty_struct *tty)  {  	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data; +	struct tty_port *port = &self->port;  	unsigned long	flags;  	IRDA_DEBUG(0, "%s()\n", __func__ ); @@ -1004,14 +967,17 @@ static void ircomm_tty_hangup(struct tty_struct *tty)  	/* ircomm_tty_flush_buffer(tty); */  	ircomm_tty_shutdown(self); -	/* I guess we need to lock here - Jean II */ -	spin_lock_irqsave(&self->spinlock, flags); -	self->flags &= ~ASYNC_NORMAL_ACTIVE; -	self->tty = NULL; -	self->open_count = 0; -	spin_unlock_irqrestore(&self->spinlock, flags); +	spin_lock_irqsave(&port->lock, flags); +	port->flags &= ~ASYNC_NORMAL_ACTIVE; +	if (port->tty) { +		set_bit(TTY_IO_ERROR, &port->tty->flags); +		tty_kref_put(port->tty); +	} +	port->tty = NULL; +	port->count = 0; +	spin_unlock_irqrestore(&port->lock, flags); -	wake_up_interruptible(&self->open_wait); +	wake_up_interruptible(&port->open_wait);  }  /* @@ -1071,20 +1037,20 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self)  	IRDA_ASSERT(self != NULL, return;);  	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); -	tty = self->tty; +	tty = tty_port_tty_get(&self->port);  	status = self->settings.dce;  	if (status & IRCOMM_DCE_DELTA_ANY) {  		/*wake_up_interruptible(&self->delta_msr_wait);*/  	} -	if ((self->flags & ASYNC_CHECK_CD) && (status & IRCOMM_DELTA_CD)) { +	if ((self->port.flags & ASYNC_CHECK_CD) && (status & IRCOMM_DELTA_CD)) {  		IRDA_DEBUG(2,  			   "%s(), ircomm%d CD now %s...\n", __func__ , self->line,  			   (status & IRCOMM_CD) ? "on" : "off");  		if (status & IRCOMM_CD) { -			wake_up_interruptible(&self->open_wait); +			wake_up_interruptible(&self->port.open_wait);  		} else {  			IRDA_DEBUG(2,  				   "%s(), Doing serial hangup..\n", __func__ ); @@ -1092,10 +1058,10 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self)  				tty_hangup(tty);  			/* Hangup will remote the tty, so better break out */ -			return; +			goto put;  		}  	} -	if (self->flags & ASYNC_CTS_FLOW) { +	if (tty && self->port.flags & ASYNC_CTS_FLOW) {  		if (tty->hw_stopped) {  			if (status & IRCOMM_CTS) {  				IRDA_DEBUG(2, @@ -1103,10 +1069,10 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self)  				tty->hw_stopped = 0;  				/* Wake up processes blocked on open */ -				wake_up_interruptible(&self->open_wait); +				wake_up_interruptible(&self->port.open_wait);  				schedule_work(&self->tqueue); -				return; +				goto put;  			}  		} else {  			if (!(status & IRCOMM_CTS)) { @@ -1116,6 +1082,8 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self)  			}  		}  	} +put: +	tty_kref_put(tty);  }  /* @@ -1128,6 +1096,7 @@ static int ircomm_tty_data_indication(void *instance, void *sap,  				      struct sk_buff *skb)  {  	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance; +	struct tty_struct *tty;  	IRDA_DEBUG(2, "%s()\n", __func__ ); @@ -1135,7 +1104,8 @@ static int ircomm_tty_data_indication(void *instance, void *sap,  	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);  	IRDA_ASSERT(skb != NULL, return -1;); -	if (!self->tty) { +	tty = tty_port_tty_get(&self->port); +	if (!tty) {  		IRDA_DEBUG(0, "%s(), no tty!\n", __func__ );  		return 0;  	} @@ -1146,7 +1116,7 @@ static int ircomm_tty_data_indication(void *instance, void *sap,  	 * Devices like WinCE can do this, and since they don't send any  	 * params, we can just as well declare the hardware for running.  	 */ -	if (self->tty->hw_stopped && (self->flow == FLOW_START)) { +	if (tty->hw_stopped && (self->flow == FLOW_START)) {  		IRDA_DEBUG(0, "%s(), polling for line settings!\n", __func__ );  		ircomm_param_request(self, IRCOMM_POLL, TRUE); @@ -1159,8 +1129,9 @@ static int ircomm_tty_data_indication(void *instance, void *sap,  	 * Use flip buffer functions since the code may be called from interrupt  	 * context  	 */ -	tty_insert_flip_string(self->tty, skb->data, skb->len); -	tty_flip_buffer_push(self->tty); +	tty_insert_flip_string(tty, skb->data, skb->len); +	tty_flip_buffer_push(tty); +	tty_kref_put(tty);  	/* No need to kfree_skb - see ircomm_ttp_data_indication() */ @@ -1211,12 +1182,13 @@ static void ircomm_tty_flow_indication(void *instance, void *sap,  	IRDA_ASSERT(self != NULL, return;);  	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); -	tty = self->tty; +	tty = tty_port_tty_get(&self->port);  	switch (cmd) {  	case FLOW_START:  		IRDA_DEBUG(2, "%s(), hw start!\n", __func__ ); -		tty->hw_stopped = 0; +		if (tty) +			tty->hw_stopped = 0;  		/* ircomm_tty_do_softint will take care of the rest */  		schedule_work(&self->tqueue); @@ -1224,15 +1196,19 @@ static void ircomm_tty_flow_indication(void *instance, void *sap,  	default:  /* If we get here, something is very wrong, better stop */  	case FLOW_STOP:  		IRDA_DEBUG(2, "%s(), hw stopped!\n", __func__ ); -		tty->hw_stopped = 1; +		if (tty) +			tty->hw_stopped = 1;  		break;  	} + +	tty_kref_put(tty);  	self->flow = cmd;  }  #ifdef CONFIG_PROC_FS  static void ircomm_tty_line_info(struct ircomm_tty_cb *self, struct seq_file *m)  { +	struct tty_struct *tty;  	char sep;  	seq_printf(m, "State: %s\n", ircomm_tty_state[self->state]); @@ -1328,40 +1304,43 @@ static void ircomm_tty_line_info(struct ircomm_tty_cb *self, struct seq_file *m)  	seq_puts(m, "Flags:");  	sep = ' '; -	if (self->flags & ASYNC_CTS_FLOW) { +	if (self->port.flags & ASYNC_CTS_FLOW) {  		seq_printf(m, "%cASYNC_CTS_FLOW", sep);  		sep = '|';  	} -	if (self->flags & ASYNC_CHECK_CD) { +	if (self->port.flags & ASYNC_CHECK_CD) {  		seq_printf(m, "%cASYNC_CHECK_CD", sep);  		sep = '|';  	} -	if (self->flags & ASYNC_INITIALIZED) { +	if (self->port.flags & ASYNC_INITIALIZED) {  		seq_printf(m, "%cASYNC_INITIALIZED", sep);  		sep = '|';  	} -	if (self->flags & ASYNC_LOW_LATENCY) { +	if (self->port.flags & ASYNC_LOW_LATENCY) {  		seq_printf(m, "%cASYNC_LOW_LATENCY", sep);  		sep = '|';  	} -	if (self->flags & ASYNC_CLOSING) { +	if (self->port.flags & ASYNC_CLOSING) {  		seq_printf(m, "%cASYNC_CLOSING", sep);  		sep = '|';  	} -	if (self->flags & ASYNC_NORMAL_ACTIVE) { +	if (self->port.flags & ASYNC_NORMAL_ACTIVE) {  		seq_printf(m, "%cASYNC_NORMAL_ACTIVE", sep);  		sep = '|';  	}  	seq_putc(m, '\n');  	seq_printf(m, "Role: %s\n", self->client ? "client" : "server"); -	seq_printf(m, "Open count: %d\n", self->open_count); +	seq_printf(m, "Open count: %d\n", self->port.count);  	seq_printf(m, "Max data size: %d\n", self->max_data_size);  	seq_printf(m, "Max header size: %d\n", self->max_header_size); -	if (self->tty) +	tty = tty_port_tty_get(&self->port); +	if (tty) {  		seq_printf(m, "Hardware: %s\n", -			       self->tty->hw_stopped ? "Stopped" : "Running"); +			       tty->hw_stopped ? "Stopped" : "Running"); +		tty_kref_put(tty); +	}  }  static int ircomm_tty_proc_show(struct seq_file *m, void *v) diff --git a/net/irda/ircomm/ircomm_tty_attach.c b/net/irda/ircomm/ircomm_tty_attach.c index b65d66e0d817..3ab70e7a0715 100644 --- a/net/irda/ircomm/ircomm_tty_attach.c +++ b/net/irda/ircomm/ircomm_tty_attach.c @@ -130,6 +130,8 @@ static int (*state[])(struct ircomm_tty_cb *self, IRCOMM_TTY_EVENT event,   */  int ircomm_tty_attach_cable(struct ircomm_tty_cb *self)  { +	struct tty_struct *tty; +  	IRDA_DEBUG(0, "%s()\n", __func__ );  	IRDA_ASSERT(self != NULL, return -1;); @@ -142,7 +144,11 @@ int ircomm_tty_attach_cable(struct ircomm_tty_cb *self)  	}  	/* Make sure nobody tries to write before the link is up */ -	self->tty->hw_stopped = 1; +	tty = tty_port_tty_get(&self->port); +	if (tty) { +		tty->hw_stopped = 1; +		tty_kref_put(tty); +	}  	ircomm_tty_ias_register(self); @@ -398,23 +404,26 @@ void ircomm_tty_disconnect_indication(void *instance, void *sap,  				      struct sk_buff *skb)  {  	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance; +	struct tty_struct *tty;  	IRDA_DEBUG(2, "%s()\n", __func__ );  	IRDA_ASSERT(self != NULL, return;);  	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); -	if (!self->tty) +	tty = tty_port_tty_get(&self->port); +	if (!tty)  		return;  	/* This will stop control data transfers */  	self->flow = FLOW_STOP;  	/* Stop data transfers */ -	self->tty->hw_stopped = 1; +	tty->hw_stopped = 1;  	ircomm_tty_do_event(self, IRCOMM_TTY_DISCONNECT_INDICATION, NULL,  			    NULL); +	tty_kref_put(tty);  }  /* @@ -550,12 +559,15 @@ void ircomm_tty_connect_indication(void *instance, void *sap,   */  void ircomm_tty_link_established(struct ircomm_tty_cb *self)  { +	struct tty_struct *tty; +  	IRDA_DEBUG(2, "%s()\n", __func__ );  	IRDA_ASSERT(self != NULL, return;);  	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); -	if (!self->tty) +	tty = tty_port_tty_get(&self->port); +	if (!tty)  		return;  	del_timer(&self->watchdog_timer); @@ -566,19 +578,22 @@ void ircomm_tty_link_established(struct ircomm_tty_cb *self)  	 * will have to wait for the peer device (DCE) to raise the CTS  	 * line.  	 */ -	if ((self->flags & ASYNC_CTS_FLOW) && ((self->settings.dce & IRCOMM_CTS) == 0)) { +	if ((self->port.flags & ASYNC_CTS_FLOW) && +			((self->settings.dce & IRCOMM_CTS) == 0)) {  		IRDA_DEBUG(0, "%s(), waiting for CTS ...\n", __func__ ); -		return; +		goto put;  	} else {  		IRDA_DEBUG(1, "%s(), starting hardware!\n", __func__ ); -		self->tty->hw_stopped = 0; +		tty->hw_stopped = 0;  		/* Wake up processes blocked on open */ -		wake_up_interruptible(&self->open_wait); +		wake_up_interruptible(&self->port.open_wait);  	}  	schedule_work(&self->tqueue); +put: +	tty_kref_put(tty);  }  /* @@ -977,14 +992,17 @@ static int ircomm_tty_state_ready(struct ircomm_tty_cb *self,  		ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH);  		ircomm_tty_start_watchdog_timer(self, 3*HZ); -		if (self->flags & ASYNC_CHECK_CD) { +		if (self->port.flags & ASYNC_CHECK_CD) {  			/* Drop carrier */  			self->settings.dce = IRCOMM_DELTA_CD;  			ircomm_tty_check_modem_status(self);  		} else { +			struct tty_struct *tty = tty_port_tty_get(&self->port);  			IRDA_DEBUG(0, "%s(), hanging up!\n", __func__ ); -			if (self->tty) -				tty_hangup(self->tty); +			if (tty) { +				tty_hangup(tty); +				tty_kref_put(tty); +			}  		}  		break;  	default: diff --git a/net/irda/ircomm/ircomm_tty_ioctl.c b/net/irda/ircomm/ircomm_tty_ioctl.c index d0667d68351d..0eab6500e99f 100644 --- a/net/irda/ircomm/ircomm_tty_ioctl.c +++ b/net/irda/ircomm/ircomm_tty_ioctl.c @@ -52,17 +52,18 @@   *    Change speed of the driver. If the remote device is a DCE, then this   *    should make it change the speed of its serial port   */ -static void ircomm_tty_change_speed(struct ircomm_tty_cb *self) +static void ircomm_tty_change_speed(struct ircomm_tty_cb *self, +		struct tty_struct *tty)  {  	unsigned int cflag, cval;  	int baud;  	IRDA_DEBUG(2, "%s()\n", __func__ ); -	if (!self->tty || !self->tty->termios || !self->ircomm) +	if (!self->ircomm)  		return; -	cflag = self->tty->termios->c_cflag; +	cflag = tty->termios->c_cflag;  	/*  byte size and parity */  	switch (cflag & CSIZE) { @@ -81,7 +82,7 @@ static void ircomm_tty_change_speed(struct ircomm_tty_cb *self)  		cval |= IRCOMM_PARITY_EVEN;  	/* Determine divisor based on baud rate */ -	baud = tty_get_baud_rate(self->tty); +	baud = tty_get_baud_rate(tty);  	if (!baud)  		baud = 9600;	/* B0 transition handled in rs_set_termios */ @@ -90,19 +91,19 @@ static void ircomm_tty_change_speed(struct ircomm_tty_cb *self)  	/* CTS flow control flag and modem status interrupts */  	if (cflag & CRTSCTS) { -		self->flags |= ASYNC_CTS_FLOW; +		self->port.flags |= ASYNC_CTS_FLOW;  		self->settings.flow_control |= IRCOMM_RTS_CTS_IN;  		/* This got me. Bummer. Jean II */  		if (self->service_type == IRCOMM_3_WIRE_RAW)  			IRDA_WARNING("%s(), enabling RTS/CTS on link that doesn't support it (3-wire-raw)\n", __func__);  	} else { -		self->flags &= ~ASYNC_CTS_FLOW; +		self->port.flags &= ~ASYNC_CTS_FLOW;  		self->settings.flow_control &= ~IRCOMM_RTS_CTS_IN;  	}  	if (cflag & CLOCAL) -		self->flags &= ~ASYNC_CHECK_CD; +		self->port.flags &= ~ASYNC_CHECK_CD;  	else -		self->flags |= ASYNC_CHECK_CD; +		self->port.flags |= ASYNC_CHECK_CD;  #if 0  	/*  	 * Set up parity check flag @@ -159,7 +160,7 @@ void ircomm_tty_set_termios(struct tty_struct *tty,  		return;  	} -	ircomm_tty_change_speed(self); +	ircomm_tty_change_speed(self, tty);  	/* Handle transition to B0 status */  	if ((old_termios->c_cflag & CBAUD) && @@ -270,10 +271,10 @@ static int ircomm_tty_get_serial_info(struct ircomm_tty_cb *self,  	memset(&info, 0, sizeof(info));  	info.line = self->line; -	info.flags = self->flags; +	info.flags = self->port.flags;  	info.baud_base = self->settings.data_rate; -	info.close_delay = self->close_delay; -	info.closing_wait = self->closing_wait; +	info.close_delay = self->port.close_delay; +	info.closing_wait = self->port.closing_wait;  	/* For compatibility  */  	info.type = PORT_16550A; | 
