mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-10-31 16:54:21 +00:00 
			
		
		
		
	cyclades: remove block_til_ready
Use a tty_port common instead. This saves lots of .text and makes the code a lot more readable. This involves separation of a dtr_rts handling, next patches will use that to not duplicate the code all over the place. Signed-off-by: Jiri Slaby <jirislaby@gmail.com> Signed-off-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
		
							parent
							
								
									d13549f804
								
							
						
					
					
						commit
						f073757942
					
				
					 1 changed files with 108 additions and 194 deletions
				
			
		|  | @ -2172,199 +2172,6 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty) | |||
|  * ------------------------------------------------------------ | ||||
|  */ | ||||
| 
 | ||||
| static int | ||||
| block_til_ready(struct tty_struct *tty, struct file *filp, | ||||
| 		struct cyclades_port *info) | ||||
| { | ||||
| 	DECLARE_WAITQUEUE(wait, current); | ||||
| 	struct cyclades_card *cinfo; | ||||
| 	unsigned long flags; | ||||
| 	int chip, channel, index; | ||||
| 	int retval; | ||||
| 	void __iomem *base_addr; | ||||
| 
 | ||||
| 	cinfo = info->card; | ||||
| 	channel = info->line - cinfo->first_line; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * If the device is in the middle of being closed, then block | ||||
| 	 * until it's done, and then try again. | ||||
| 	 */ | ||||
| 	if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) { | ||||
| 		wait_event_interruptible(info->port.close_wait, | ||||
| 				!(info->port.flags & ASYNC_CLOSING)); | ||||
| 		return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS; | ||||
| 	} | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * If non-blocking mode is set, then make the check up front | ||||
| 	 * and then exit. | ||||
| 	 */ | ||||
| 	if ((filp->f_flags & O_NONBLOCK) || | ||||
| 					(tty->flags & (1 << TTY_IO_ERROR))) { | ||||
| 		info->port.flags |= ASYNC_NORMAL_ACTIVE; | ||||
| 		return 0; | ||||
| 	} | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Block waiting for the carrier detect and the line to become | ||||
| 	 * free (i.e., not in use by the callout).  While we are in | ||||
| 	 * this loop, info->port.count is dropped by one, so that | ||||
| 	 * cy_close() knows when to free things.  We restore it upon | ||||
| 	 * exit, either normal or abnormal. | ||||
| 	 */ | ||||
| 	retval = 0; | ||||
| 	add_wait_queue(&info->port.open_wait, &wait); | ||||
| #ifdef CY_DEBUG_OPEN | ||||
| 	printk(KERN_DEBUG "cyc block_til_ready before block: ttyC%d, " | ||||
| 		"count = %d\n", info->line, info->port.count); | ||||
| #endif | ||||
| 	spin_lock_irqsave(&cinfo->card_lock, flags); | ||||
| 	if (!tty_hung_up_p(filp)) | ||||
| 		info->port.count--; | ||||
| 	spin_unlock_irqrestore(&cinfo->card_lock, flags); | ||||
| #ifdef CY_DEBUG_COUNT | ||||
| 	printk(KERN_DEBUG "cyc block_til_ready: (%d): decrementing count to " | ||||
| 		"%d\n", current->pid, info->port.count); | ||||
| #endif | ||||
| 	info->port.blocked_open++; | ||||
| 
 | ||||
| 	if (!cy_is_Z(cinfo)) { | ||||
| 		chip = channel >> 2; | ||||
| 		channel &= 0x03; | ||||
| 		index = cinfo->bus_index; | ||||
| 		base_addr = cinfo->base_addr + (cy_chip_offset[chip] << index); | ||||
| 
 | ||||
| 		while (1) { | ||||
| 			spin_lock_irqsave(&cinfo->card_lock, flags); | ||||
| 			if ((tty->termios->c_cflag & CBAUD)) { | ||||
| 				cy_writeb(base_addr + (CyCAR << index), | ||||
| 					  (u_char) channel); | ||||
| 				cy_writeb(base_addr + (CyMSVR1 << index), | ||||
| 					  CyRTS); | ||||
| 				cy_writeb(base_addr + (CyMSVR2 << index), | ||||
| 					  CyDTR); | ||||
| #ifdef CY_DEBUG_DTR | ||||
| 				printk(KERN_DEBUG "cyc:block_til_ready raising " | ||||
| 					"DTR\n"); | ||||
| 				printk(KERN_DEBUG "     status: 0x%x, 0x%x\n", | ||||
| 					readb(base_addr + (CyMSVR1 << index)), | ||||
| 					readb(base_addr + (CyMSVR2 << index))); | ||||
| #endif | ||||
| 			} | ||||
| 			spin_unlock_irqrestore(&cinfo->card_lock, flags); | ||||
| 
 | ||||
| 			set_current_state(TASK_INTERRUPTIBLE); | ||||
| 			if (tty_hung_up_p(filp) || | ||||
| 					!(info->port.flags & ASYNC_INITIALIZED)) { | ||||
| 				retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ? | ||||
| 					  -EAGAIN : -ERESTARTSYS); | ||||
| 				break; | ||||
| 			} | ||||
| 
 | ||||
| 			spin_lock_irqsave(&cinfo->card_lock, flags); | ||||
| 			cy_writeb(base_addr + (CyCAR << index), | ||||
| 				  (u_char) channel); | ||||
| 			if (!(info->port.flags & ASYNC_CLOSING) && (C_CLOCAL(tty) || | ||||
| 					(readb(base_addr + | ||||
| 						(CyMSVR1 << index)) & CyDCD))) { | ||||
| 				spin_unlock_irqrestore(&cinfo->card_lock, flags); | ||||
| 				break; | ||||
| 			} | ||||
| 			spin_unlock_irqrestore(&cinfo->card_lock, flags); | ||||
| 
 | ||||
| 			if (signal_pending(current)) { | ||||
| 				retval = -ERESTARTSYS; | ||||
| 				break; | ||||
| 			} | ||||
| #ifdef CY_DEBUG_OPEN | ||||
| 			printk(KERN_DEBUG "cyc block_til_ready blocking: " | ||||
| 				"ttyC%d, count = %d\n", | ||||
| 				info->line, info->port.count); | ||||
| #endif | ||||
| 			schedule(); | ||||
| 		} | ||||
| 	} else { | ||||
| 		struct FIRM_ID __iomem *firm_id; | ||||
| 		struct ZFW_CTRL __iomem *zfw_ctrl; | ||||
| 		struct BOARD_CTRL __iomem *board_ctrl; | ||||
| 		struct CH_CTRL __iomem *ch_ctrl; | ||||
| 
 | ||||
| 		base_addr = cinfo->base_addr; | ||||
| 		firm_id = base_addr + ID_ADDRESS; | ||||
| 		if (!cyz_is_loaded(cinfo)) { | ||||
| 			__set_current_state(TASK_RUNNING); | ||||
| 			remove_wait_queue(&info->port.open_wait, &wait); | ||||
| 			return -EINVAL; | ||||
| 		} | ||||
| 
 | ||||
| 		zfw_ctrl = base_addr + (readl(&firm_id->zfwctrl_addr) | ||||
| 								& 0xfffff); | ||||
| 		board_ctrl = &zfw_ctrl->board_ctrl; | ||||
| 		ch_ctrl = zfw_ctrl->ch_ctrl; | ||||
| 
 | ||||
| 		while (1) { | ||||
| 			if ((tty->termios->c_cflag & CBAUD)) { | ||||
| 				cy_writel(&ch_ctrl[channel].rs_control, | ||||
| 					readl(&ch_ctrl[channel].rs_control) | | ||||
| 					C_RS_RTS | C_RS_DTR); | ||||
| 				retval = cyz_issue_cmd(cinfo, | ||||
| 					channel, C_CM_IOCTLM, 0L); | ||||
| 				if (retval != 0) { | ||||
| 					printk(KERN_ERR "cyc:block_til_ready " | ||||
| 						"retval on ttyC%d was %x\n", | ||||
| 						info->line, retval); | ||||
| 				} | ||||
| #ifdef CY_DEBUG_DTR | ||||
| 				printk(KERN_DEBUG "cyc:block_til_ready raising " | ||||
| 					"Z DTR\n"); | ||||
| #endif | ||||
| 			} | ||||
| 
 | ||||
| 			set_current_state(TASK_INTERRUPTIBLE); | ||||
| 			if (tty_hung_up_p(filp) || | ||||
| 					!(info->port.flags & ASYNC_INITIALIZED)) { | ||||
| 				retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ? | ||||
| 					  -EAGAIN : -ERESTARTSYS); | ||||
| 				break; | ||||
| 			} | ||||
| 			if (!(info->port.flags & ASYNC_CLOSING) && (C_CLOCAL(tty) || | ||||
| 					(readl(&ch_ctrl[channel].rs_status) & | ||||
| 						C_RS_DCD))) { | ||||
| 				break; | ||||
| 			} | ||||
| 			if (signal_pending(current)) { | ||||
| 				retval = -ERESTARTSYS; | ||||
| 				break; | ||||
| 			} | ||||
| #ifdef CY_DEBUG_OPEN | ||||
| 			printk(KERN_DEBUG "cyc block_til_ready blocking: " | ||||
| 				"ttyC%d, count = %d\n", | ||||
| 				info->line, info->port.count); | ||||
| #endif | ||||
| 			schedule(); | ||||
| 		} | ||||
| 	} | ||||
| 	__set_current_state(TASK_RUNNING); | ||||
| 	remove_wait_queue(&info->port.open_wait, &wait); | ||||
| 	if (!tty_hung_up_p(filp)) { | ||||
| 		info->port.count++; | ||||
| #ifdef CY_DEBUG_COUNT | ||||
| 		printk(KERN_DEBUG "cyc:block_til_ready (%d): incrementing " | ||||
| 			"count to %d\n", current->pid, info->port.count); | ||||
| #endif | ||||
| 	} | ||||
| 	info->port.blocked_open--; | ||||
| #ifdef CY_DEBUG_OPEN | ||||
| 	printk(KERN_DEBUG "cyc:block_til_ready after blocking: ttyC%d, " | ||||
| 		"count = %d\n", info->line, info->port.count); | ||||
| #endif | ||||
| 	if (retval) | ||||
| 		return retval; | ||||
| 	info->port.flags |= ASYNC_NORMAL_ACTIVE; | ||||
| 	return 0; | ||||
| }				/* block_til_ready */ | ||||
| 
 | ||||
| /*
 | ||||
|  * This routine is called whenever a serial port is opened.  It | ||||
|  * performs the serial-specific initialization for the tty structure. | ||||
|  | @ -2472,7 +2279,7 @@ static int cy_open(struct tty_struct *tty, struct file *filp) | |||
| 	if (retval) | ||||
| 		return retval; | ||||
| 
 | ||||
| 	retval = block_til_ready(tty, filp, info); | ||||
| 	retval = tty_port_block_til_ready(&info->port, tty, filp); | ||||
| 	if (retval) { | ||||
| #ifdef CY_DEBUG_OPEN | ||||
| 		printk(KERN_DEBUG "cyc:cy_open returning after block_til_ready " | ||||
|  | @ -4312,6 +4119,111 @@ static void cy_hangup(struct tty_struct *tty) | |||
| 	wake_up_interruptible(&info->port.open_wait); | ||||
| }				/* cy_hangup */ | ||||
| 
 | ||||
| static int cyy_carrier_raised(struct tty_port *port) | ||||
| { | ||||
| 	struct cyclades_port *info = container_of(port, struct cyclades_port, | ||||
| 			port); | ||||
| 	struct cyclades_card *cinfo = info->card; | ||||
| 	void __iomem *base = cinfo->base_addr; | ||||
| 	unsigned long flags; | ||||
| 	int channel = info->line - cinfo->first_line; | ||||
| 	int chip = channel >> 2, index = cinfo->bus_index; | ||||
| 	u32 cd; | ||||
| 
 | ||||
| 	channel &= 0x03; | ||||
| 	base += cy_chip_offset[chip] << index; | ||||
| 
 | ||||
| 	spin_lock_irqsave(&cinfo->card_lock, flags); | ||||
| 	cy_writeb(base + (CyCAR << index), (u8)channel); | ||||
| 	cd = readb(base + (CyMSVR1 << index)) & CyDCD; | ||||
| 	spin_unlock_irqrestore(&cinfo->card_lock, flags); | ||||
| 
 | ||||
| 	return cd; | ||||
| } | ||||
| 
 | ||||
| static void cyy_dtr_rts(struct tty_port *port, int raise) | ||||
| { | ||||
| 	struct cyclades_port *info = container_of(port, struct cyclades_port, | ||||
| 			port); | ||||
| 	struct cyclades_card *cinfo = info->card; | ||||
| 	void __iomem *base = cinfo->base_addr; | ||||
| 	unsigned long flags; | ||||
| 	int channel = info->line - cinfo->first_line; | ||||
| 	int chip = channel >> 2, index = cinfo->bus_index; | ||||
| 
 | ||||
| 	channel &= 0x03; | ||||
| 	base += cy_chip_offset[chip] << index; | ||||
| 
 | ||||
| 	spin_lock_irqsave(&cinfo->card_lock, flags); | ||||
| 	cy_writeb(base + (CyCAR << index), (u8)channel); | ||||
| 	cy_writeb(base + (CyMSVR1 << index), raise ? CyRTS : ~CyRTS); | ||||
| 	cy_writeb(base + (CyMSVR2 << index), raise ? CyDTR : ~CyDTR); | ||||
| #ifdef CY_DEBUG_DTR | ||||
| 	printk(KERN_DEBUG "%s: raising DTR\n", __func__); | ||||
| 	printk(KERN_DEBUG "     status: 0x%x, 0x%x\n", | ||||
| 			readb(base + (CyMSVR1 << index)), | ||||
| 			readb(base + (CyMSVR2 << index))); | ||||
| #endif | ||||
| 	spin_unlock_irqrestore(&cinfo->card_lock, flags); | ||||
| } | ||||
| 
 | ||||
| static int cyz_carrier_raised(struct tty_port *port) | ||||
| { | ||||
| 	struct cyclades_port *info = container_of(port, struct cyclades_port, | ||||
| 			port); | ||||
| 	struct cyclades_card *cinfo = info->card; | ||||
| 	void __iomem *base = cinfo->base_addr; | ||||
| 	struct FIRM_ID __iomem *firm_id = base + ID_ADDRESS; | ||||
| 	struct ZFW_CTRL __iomem *zfw_ctrl; | ||||
| 	struct CH_CTRL __iomem *ch_ctrl; | ||||
| 	int channel = info->line - cinfo->first_line; | ||||
| 
 | ||||
| 	zfw_ctrl = base + (readl(&firm_id->zfwctrl_addr) & 0xfffff); | ||||
| 	ch_ctrl = zfw_ctrl->ch_ctrl; | ||||
| 
 | ||||
| 	return readl(&ch_ctrl[channel].rs_status) & C_RS_DCD; | ||||
| } | ||||
| 
 | ||||
| static void cyz_dtr_rts(struct tty_port *port, int raise) | ||||
| { | ||||
| 	struct cyclades_port *info = container_of(port, struct cyclades_port, | ||||
| 			port); | ||||
| 	struct cyclades_card *cinfo = info->card; | ||||
| 	void __iomem *base = cinfo->base_addr; | ||||
| 	struct FIRM_ID __iomem *firm_id = base + ID_ADDRESS; | ||||
| 	struct ZFW_CTRL __iomem *zfw_ctrl; | ||||
| 	struct CH_CTRL __iomem *ch_ctrl; | ||||
| 	int ret, channel = info->line - cinfo->first_line; | ||||
| 	u32 rs; | ||||
| 
 | ||||
| 	zfw_ctrl = base + (readl(&firm_id->zfwctrl_addr) & 0xfffff); | ||||
| 	ch_ctrl = zfw_ctrl->ch_ctrl; | ||||
| 
 | ||||
| 	rs = readl(&ch_ctrl[channel].rs_control); | ||||
| 	if (raise) | ||||
| 		rs |= C_RS_RTS | C_RS_DTR; | ||||
| 	else | ||||
| 		rs &= ~(C_RS_RTS | C_RS_DTR); | ||||
| 	cy_writel(&ch_ctrl[channel].rs_control, rs); | ||||
| 	ret = cyz_issue_cmd(cinfo, channel, C_CM_IOCTLM, 0L); | ||||
| 	if (ret != 0) | ||||
| 		printk(KERN_ERR "%s: retval on ttyC%d was %x\n", | ||||
| 				__func__, info->line, ret); | ||||
| #ifdef CY_DEBUG_DTR | ||||
| 	printk(KERN_DEBUG "%s: raising Z DTR\n", __func__); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| static const struct tty_port_operations cyy_port_ops = { | ||||
| 	.carrier_raised = cyy_carrier_raised, | ||||
| 	.dtr_rts = cyy_dtr_rts, | ||||
| }; | ||||
| 
 | ||||
| static const struct tty_port_operations cyz_port_ops = { | ||||
| 	.carrier_raised = cyz_carrier_raised, | ||||
| 	.dtr_rts = cyz_dtr_rts, | ||||
| }; | ||||
| 
 | ||||
| /*
 | ||||
|  * --------------------------------------------------------------------- | ||||
|  * cy_init() and friends | ||||
|  | @ -4351,6 +4263,7 @@ static int __devinit cy_init_card(struct cyclades_card *cinfo) | |||
| 		init_waitqueue_head(&info->delta_msr_wait); | ||||
| 
 | ||||
| 		if (cy_is_Z(cinfo)) { | ||||
| 			info->port.ops = &cyz_port_ops; | ||||
| 			info->type = PORT_STARTECH; | ||||
| 			if (cinfo->hw_ver == ZO_V1) | ||||
| 				info->xmit_fifo_size = CYZ_FIFO_SIZE; | ||||
|  | @ -4362,6 +4275,7 @@ static int __devinit cy_init_card(struct cyclades_card *cinfo) | |||
| #endif | ||||
| 		} else { | ||||
| 			int index = cinfo->bus_index; | ||||
| 			info->port.ops = &cyy_port_ops; | ||||
| 			info->type = PORT_CIRRUS; | ||||
| 			info->xmit_fifo_size = CyMAX_CHAR_FIFO; | ||||
| 			info->cor1 = CyPARITY_NONE | Cy_1_STOP | Cy_8_BITS; | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Jiri Slaby
						Jiri Slaby