All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 01/13] Char: cyclades, add tty refcounting
@ 2009-06-18  7:41 Jiri Slaby
  2009-06-18  7:41 ` [PATCH 02/13] Char: cyclades, remove block_til_ready Jiri Slaby
                   ` (12 more replies)
  0 siblings, 13 replies; 14+ messages in thread
From: Jiri Slaby @ 2009-06-18  7:41 UTC (permalink / raw)
  To: alan; +Cc: Andrew Morton, linux-kernel, Jiri Slaby

While this is not problem for Y card handlers (they are protected
by card_lock), Z handlers and other functions may dereference NULL
at any point after hangup/close. Even if (tty == NULL) was already
performed in the handler.

Note that it's not an issue for Y cards just for now. After
switching to tty_port_close_* et al. this will be a problem. So
add refcounting to them all.

Also proc .show doesn't take a tty reference and it should (along
with a ldisc one).

While at it and changing prototypes (adding tty param), prepend
cy_ to functions which don't have it yet.

Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
---
 drivers/char/cyclades.c |  172 +++++++++++++++++++++++++---------------------
 1 files changed, 93 insertions(+), 79 deletions(-)

diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index f3366d3..de9c1d9 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -849,7 +849,7 @@ MODULE_DEVICE_TABLE(pci, cy_pci_dev_id);
 #endif
 
 static void cy_start(struct tty_struct *);
-static void set_line_char(struct cyclades_port *);
+static void cy_set_line_char(struct cyclades_port *, struct tty_struct *);
 static int cyz_issue_cmd(struct cyclades_card *, __u32, __u8, __u32);
 #ifdef CONFIG_ISA
 static unsigned detect_isa_irq(void __iomem *);
@@ -1010,8 +1010,9 @@ static void cyy_chip_rx(struct cyclades_card *cinfo, int chip,
 	save_car = readb(base_addr + (CyCAR << index));
 	cy_writeb(base_addr + (CyCAR << index), save_xir);
 
+	tty = tty_port_tty_get(&info->port);
 	/* if there is nowhere to put the data, discard it */
-	if (info->port.tty == NULL) {
+	if (tty == NULL) {
 		if ((readb(base_addr + (CyRIVR << index)) & CyIVRMask) ==
 				CyIVRRxEx) {	/* exception */
 			data = readb(base_addr + (CyRDSR << index));
@@ -1023,7 +1024,6 @@ static void cyy_chip_rx(struct cyclades_card *cinfo, int chip,
 		goto end;
 	}
 	/* there is an open port for this data */
-	tty = info->port.tty;
 	if ((readb(base_addr + (CyRIVR << index)) & CyIVRMask) ==
 			CyIVRRxEx) {	/* exception */
 		data = readb(base_addr + (CyRDSR << index));
@@ -1040,6 +1040,7 @@ static void cyy_chip_rx(struct cyclades_card *cinfo, int chip,
 
 		if (data & info->ignore_status_mask) {
 			info->icount.rx++;
+			tty_kref_put(tty);
 			return;
 		}
 		if (tty_buffer_request_room(tty, 1)) {
@@ -1120,6 +1121,7 @@ static void cyy_chip_rx(struct cyclades_card *cinfo, int chip,
 		info->idle_stats.recv_idle = jiffies;
 	}
 	tty_schedule_flip(tty);
+	tty_kref_put(tty);
 end:
 	/* end of service */
 	cy_writeb(base_addr + (CyRIR << index), save_xir & 0x3f);
@@ -1130,6 +1132,7 @@ static void cyy_chip_tx(struct cyclades_card *cinfo, unsigned int chip,
 		void __iomem *base_addr)
 {
 	struct cyclades_port *info;
+	struct tty_struct *tty;
 	int char_count, index = cinfo->bus_index;
 	u8 save_xir, channel, save_car, outch;
 
@@ -1153,7 +1156,8 @@ static void cyy_chip_tx(struct cyclades_card *cinfo, unsigned int chip,
 		goto end;
 	}
 	info = &cinfo->ports[channel + chip * 4];
-	if (info->port.tty == NULL) {
+	tty = tty_port_tty_get(&info->port);
+	if (tty == NULL) {
 		cy_writeb(base_addr + (CySRER << index),
 			  readb(base_addr + (CySRER << index)) & ~CyTxRdy);
 		goto end;
@@ -1204,7 +1208,7 @@ static void cyy_chip_tx(struct cyclades_card *cinfo, unsigned int chip,
 					~CyTxRdy);
 			goto done;
 		}
-		if (info->port.tty->stopped || info->port.tty->hw_stopped) {
+		if (tty->stopped || tty->hw_stopped) {
 			cy_writeb(base_addr + (CySRER << index),
 				readb(base_addr + (CySRER << index)) &
 					~CyTxRdy);
@@ -1240,7 +1244,8 @@ static void cyy_chip_tx(struct cyclades_card *cinfo, unsigned int chip,
 	}
 
 done:
-	tty_wakeup(info->port.tty);
+	tty_wakeup(tty);
+	tty_kref_put(tty);
 end:
 	/* end of service */
 	cy_writeb(base_addr + (CyTIR << index), save_xir & 0x3f);
@@ -1251,6 +1256,7 @@ static void cyy_chip_modem(struct cyclades_card *cinfo, int chip,
 		void __iomem *base_addr)
 {
 	struct cyclades_port *info;
+	struct tty_struct *tty;
 	int index = cinfo->bus_index;
 	u8 save_xir, channel, save_car, mdm_change, mdm_status;
 
@@ -1264,7 +1270,8 @@ static void cyy_chip_modem(struct cyclades_card *cinfo, int chip,
 	mdm_change = readb(base_addr + (CyMISR << index));
 	mdm_status = readb(base_addr + (CyMSVR1 << index));
 
-	if (!info->port.tty)
+	tty = tty_port_tty_get(&info->port);
+	if (!tty)
 		goto end;
 
 	if (mdm_change & CyANY_DELTA) {
@@ -1283,27 +1290,27 @@ static void cyy_chip_modem(struct cyclades_card *cinfo, int chip,
 
 	if ((mdm_change & CyDCD) && (info->port.flags & ASYNC_CHECK_CD)) {
 		if (!(mdm_status & CyDCD)) {
-			tty_hangup(info->port.tty);
+			tty_hangup(tty);
 			info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
 		}
 		wake_up_interruptible(&info->port.open_wait);
 	}
 	if ((mdm_change & CyCTS) && (info->port.flags & ASYNC_CTS_FLOW)) {
-		if (info->port.tty->hw_stopped) {
+		if (tty->hw_stopped) {
 			if (mdm_status & CyCTS) {
 				/* cy_start isn't used
 				   because... !!! */
-				info->port.tty->hw_stopped = 0;
+				tty->hw_stopped = 0;
 				cy_writeb(base_addr + (CySRER << index),
 					readb(base_addr + (CySRER << index)) |
 						CyTxRdy);
-				tty_wakeup(info->port.tty);
+				tty_wakeup(tty);
 			}
 		} else {
 			if (!(mdm_status & CyCTS)) {
 				/* cy_stop isn't used
 				   because ... !!! */
-				info->port.tty->hw_stopped = 1;
+				tty->hw_stopped = 1;
 				cy_writeb(base_addr + (CySRER << index),
 					readb(base_addr + (CySRER << index)) &
 						~CyTxRdy);
@@ -1314,6 +1321,7 @@ static void cyy_chip_modem(struct cyclades_card *cinfo, int chip,
 	}
 	if (mdm_change & CyRI) {
 	}*/
+	tty_kref_put(tty);
 end:
 	/* end of service */
 	cy_writeb(base_addr + (CyMIR << index), save_xir & 0x3f);
@@ -1448,11 +1456,10 @@ cyz_issue_cmd(struct cyclades_card *cinfo,
 	return 0;
 }				/* cyz_issue_cmd */
 
-static void cyz_handle_rx(struct cyclades_port *info,
+static void cyz_handle_rx(struct cyclades_port *info, struct tty_struct *tty,
 		struct BUF_CTRL __iomem *buf_ctrl)
 {
 	struct cyclades_card *cinfo = info->card;
-	struct tty_struct *tty = info->port.tty;
 	unsigned int char_count;
 	int len;
 #ifdef BLOCKMOVE
@@ -1541,11 +1548,10 @@ static void cyz_handle_rx(struct cyclades_port *info,
 	}
 }
 
-static void cyz_handle_tx(struct cyclades_port *info,
+static void cyz_handle_tx(struct cyclades_port *info, struct tty_struct *tty,
 		struct BUF_CTRL __iomem *buf_ctrl)
 {
 	struct cyclades_card *cinfo = info->card;
-	struct tty_struct *tty = info->port.tty;
 	u8 data;
 	unsigned int char_count;
 #ifdef BLOCKMOVE
@@ -1641,7 +1647,7 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
 		special_count = 0;
 		delta_count = 0;
 		info = &cinfo->ports[channel];
-		tty = info->port.tty;
+		tty = tty_port_tty_get(&info->port);
 		if (tty == NULL)
 			continue;
 
@@ -1673,7 +1679,7 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
 						C_RS_DCD) {
 					wake_up_interruptible(&info->port.open_wait);
 				} else {
-					tty_hangup(info->port.tty);
+					tty_hangup(tty);
 					wake_up_interruptible(&info->port.open_wait);
 					info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
 				}
@@ -1705,7 +1711,7 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
 			printk(KERN_DEBUG "cyz_interrupt: rcvd intr, card %d, "
 					"port %ld\n", info->card, channel);
 #endif
-			cyz_handle_rx(info, buf_ctrl);
+			cyz_handle_rx(info, tty, buf_ctrl);
 			break;
 		case C_CM_TXBEMPTY:
 		case C_CM_TXLOWWM:
@@ -1715,7 +1721,7 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
 			printk(KERN_DEBUG "cyz_interrupt: xmit intr, card %d, "
 					"port %ld\n", info->card, channel);
 #endif
-			cyz_handle_tx(info, buf_ctrl);
+			cyz_handle_tx(info, tty, buf_ctrl);
 			break;
 #endif				/* CONFIG_CYZ_INTR */
 		case C_CM_FATAL:
@@ -1728,6 +1734,7 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
 			wake_up_interruptible(&info->delta_msr_wait);
 		if (special_count)
 			tty_schedule_flip(tty);
+		tty_kref_put(tty);
 	}
 }
 
@@ -1773,7 +1780,6 @@ static void cyz_poll(unsigned long arg)
 {
 	struct cyclades_card *cinfo;
 	struct cyclades_port *info;
-	struct tty_struct *tty;
 	struct FIRM_ID __iomem *firm_id;
 	struct ZFW_CTRL __iomem *zfw_ctrl;
 	struct BUF_CTRL __iomem *buf_ctrl;
@@ -1801,13 +1807,19 @@ static void cyz_poll(unsigned long arg)
 		cyz_handle_cmd(cinfo);
 
 		for (port = 0; port < cinfo->nports; port++) {
+			struct tty_struct *tty;
+
 			info = &cinfo->ports[port];
-			tty = info->port.tty;
 			buf_ctrl = &(zfw_ctrl->buf_ctrl[port]);
 
+			tty = tty_port_tty_get(&info->port);
+			/* OK to pass NULL to the handle functions below.
+			   They need to drop the data in that case. */
+
 			if (!info->throttle)
-				cyz_handle_rx(info, buf_ctrl);
-			cyz_handle_tx(info, buf_ctrl);
+				cyz_handle_rx(info, tty, buf_ctrl);
+			cyz_handle_tx(info, tty, buf_ctrl);
+			tty_kref_put(tty);
 		}
 		/* poll every 'cyz_polling_cycle' period */
 		expires = jiffies + cyz_polling_cycle;
@@ -1823,7 +1835,7 @@ static void cyz_poll(unsigned long arg)
 /* This is called whenever a port becomes active;
    interrupts are enabled and DTR & RTS are turned on.
  */
-static int startup(struct cyclades_port *info)
+static int cy_startup(struct cyclades_port *info, struct tty_struct *tty)
 {
 	struct cyclades_card *card;
 	unsigned long flags;
@@ -1847,8 +1859,7 @@ static int startup(struct cyclades_port *info)
 	}
 
 	if (!info->type) {
-		if (info->port.tty)
-			set_bit(TTY_IO_ERROR, &info->port.tty->flags);
+		set_bit(TTY_IO_ERROR, &tty->flags);
 		free_page(page);
 		goto errout;
 	}
@@ -1860,7 +1871,7 @@ static int startup(struct cyclades_port *info)
 
 	spin_unlock_irqrestore(&card->card_lock, flags);
 
-	set_line_char(info);
+	cy_set_line_char(info, tty);
 
 	if (!cy_is_Z(card)) {
 		chip = channel >> 2;
@@ -1899,8 +1910,7 @@ static int startup(struct cyclades_port *info)
 			readb(base_addr + (CySRER << index)) | CyRxData);
 		info->port.flags |= ASYNC_INITIALIZED;
 
-		if (info->port.tty)
-			clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
+		clear_bit(TTY_IO_ERROR, &tty->flags);
 		info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
 		info->breakon = info->breakoff = 0;
 		memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats));
@@ -1983,8 +1993,7 @@ static int startup(struct cyclades_port *info)
 		/* enable send, recv, modem !!! */
 
 		info->port.flags |= ASYNC_INITIALIZED;
-		if (info->port.tty)
-			clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
+		clear_bit(TTY_IO_ERROR, &tty->flags);
 		info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
 		info->breakon = info->breakoff = 0;
 		memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats));
@@ -2046,7 +2055,7 @@ static void start_xmit(struct cyclades_port *info)
  * This routine shuts down a serial port; interrupts are disabled,
  * and DTR is dropped if the hangup on close termio flag is on.
  */
-static void shutdown(struct cyclades_port *info)
+static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty)
 {
 	struct cyclades_card *card;
 	unsigned long flags;
@@ -2082,7 +2091,7 @@ static void shutdown(struct cyclades_port *info)
 			free_page((unsigned long)temp);
 		}
 		cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
-		if (!info->port.tty || (info->port.tty->termios->c_cflag & HUPCL)) {
+		if (tty->termios->c_cflag & HUPCL) {
 			cy_writeb(base_addr + (CyMSVR1 << index), ~CyRTS);
 			cy_writeb(base_addr + (CyMSVR2 << index), ~CyDTR);
 #ifdef CY_DEBUG_DTR
@@ -2096,8 +2105,7 @@ static void shutdown(struct cyclades_port *info)
 		/* it may be appropriate to clear _XMIT at
 		   some later date (after testing)!!! */
 
-		if (info->port.tty)
-			set_bit(TTY_IO_ERROR, &info->port.tty->flags);
+		set_bit(TTY_IO_ERROR, &tty->flags);
 		info->port.flags &= ~ASYNC_INITIALIZED;
 		spin_unlock_irqrestore(&card->card_lock, flags);
 	} else {
@@ -2131,7 +2139,7 @@ static void shutdown(struct cyclades_port *info)
 			free_page((unsigned long)temp);
 		}
 
-		if (!info->port.tty || (info->port.tty->termios->c_cflag & HUPCL)) {
+		if (tty->termios->c_cflag & HUPCL) {
 			cy_writel(&ch_ctrl[channel].rs_control,
 				(__u32)(readl(&ch_ctrl[channel].rs_control) &
 					~(C_RS_RTS | C_RS_DTR)));
@@ -2146,8 +2154,7 @@ static void shutdown(struct cyclades_port *info)
 #endif
 		}
 
-		if (info->port.tty)
-			set_bit(TTY_IO_ERROR, &info->port.tty->flags);
+		set_bit(TTY_IO_ERROR, &tty->flags);
 		info->port.flags &= ~ASYNC_INITIALIZED;
 
 		spin_unlock_irqrestore(&card->card_lock, flags);
@@ -2435,7 +2442,6 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
 	printk(KERN_DEBUG "cyc:cy_open ttyC%d\n", info->line);
 #endif
 	tty->driver_data = info;
-	info->port.tty = tty;
 	if (serial_paranoia_check(info, tty->name, "cy_open"))
 		return -ENODEV;
 
@@ -2461,7 +2467,7 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
 	/*
 	 * Start up serial port
 	 */
-	retval = startup(info);
+	retval = cy_startup(info, tty);
 	if (retval)
 		return retval;
 
@@ -2475,6 +2481,7 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
 	}
 
 	info->throttle = 0;
+	tty_port_tty_set(&info->port, tty);
 
 #ifdef CY_DEBUG_OPEN
 	printk(KERN_DEBUG "cyc:cy_open done\n");
@@ -2704,13 +2711,13 @@ static void cy_close(struct tty_struct *tty, struct file *filp)
 	}
 
 	spin_unlock_irqrestore(&card->card_lock, flags);
-	shutdown(info);
+	cy_shutdown(info, tty);
 	cy_flush_buffer(tty);
 	tty_ldisc_flush(tty);
 	spin_lock_irqsave(&card->card_lock, flags);
 
 	tty->closing = 0;
-	info->port.tty = NULL;
+	tty_port_tty_set(&info->port, NULL);
 	if (info->port.blocked_open) {
 		spin_unlock_irqrestore(&card->card_lock, flags);
 		if (info->port.close_delay) {
@@ -2956,7 +2963,7 @@ static void cyy_baud_calc(struct cyclades_port *info, __u32 baud)
  * This routine finds or computes the various line characteristics.
  * It used to be called config_setup
  */
-static void set_line_char(struct cyclades_port *info)
+static void cy_set_line_char(struct cyclades_port *info, struct tty_struct *tty)
 {
 	struct cyclades_card *card;
 	unsigned long flags;
@@ -2966,28 +2973,26 @@ static void set_line_char(struct cyclades_port *info)
 	int baud, baud_rate = 0;
 	int i;
 
-	if (!info->port.tty || !info->port.tty->termios)
+	if (!tty->termios) /* XXX can this happen at all? */
 		return;
 
 	if (info->line == -1)
 		return;
 
-	cflag = info->port.tty->termios->c_cflag;
-	iflag = info->port.tty->termios->c_iflag;
+	cflag = tty->termios->c_cflag;
+	iflag = tty->termios->c_iflag;
 
 	/*
 	 * Set up the tty->alt_speed kludge
 	 */
-	if (info->port.tty) {
-		if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-			info->port.tty->alt_speed = 57600;
-		if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-			info->port.tty->alt_speed = 115200;
-		if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
-			info->port.tty->alt_speed = 230400;
-		if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
-			info->port.tty->alt_speed = 460800;
-	}
+	if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+		tty->alt_speed = 57600;
+	if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+		tty->alt_speed = 115200;
+	if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
+		tty->alt_speed = 230400;
+	if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+		tty->alt_speed = 460800;
 
 	card = info->card;
 	channel = info->line - card->first_line;
@@ -2997,7 +3002,7 @@ static void set_line_char(struct cyclades_port *info)
 		index = card->bus_index;
 
 		/* baud rate */
-		baud = tty_get_baud_rate(info->port.tty);
+		baud = tty_get_baud_rate(tty);
 		if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
 				ASYNC_SPD_CUST) {
 			if (info->custom_divisor)
@@ -3122,9 +3127,8 @@ static void set_line_char(struct cyclades_port *info)
 
 		/* set line characteristics  according configuration */
 
-		cy_writeb(base_addr + (CySCHR1 << index),
-			  START_CHAR(info->port.tty));
-		cy_writeb(base_addr + (CySCHR2 << index), STOP_CHAR(info->port.tty));
+		cy_writeb(base_addr + (CySCHR1 << index), START_CHAR(tty));
+		cy_writeb(base_addr + (CySCHR2 << index), STOP_CHAR(tty));
 		cy_writeb(base_addr + (CyCOR1 << index), info->cor1);
 		cy_writeb(base_addr + (CyCOR2 << index), info->cor2);
 		cy_writeb(base_addr + (CyCOR3 << index), info->cor3);
@@ -3140,7 +3144,7 @@ static void set_line_char(struct cyclades_port *info)
 			(info->default_timeout ? info->default_timeout : 0x02));
 		/* 10ms rx timeout */
 
-		if (C_CLOCAL(info->port.tty)) {
+		if (C_CLOCAL(tty)) {
 			/* without modem intr */
 			cy_writeb(base_addr + (CySRER << index),
 				readb(base_addr + (CySRER << index)) | CyMdmCh);
@@ -3203,8 +3207,7 @@ static void set_line_char(struct cyclades_port *info)
 #endif
 		}
 
-		if (info->port.tty)
-			clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
+		clear_bit(TTY_IO_ERROR, &tty->flags);
 		spin_unlock_irqrestore(&card->card_lock, flags);
 
 	} else {
@@ -3223,7 +3226,7 @@ static void set_line_char(struct cyclades_port *info)
 		ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
 
 		/* baud rate */
-		baud = tty_get_baud_rate(info->port.tty);
+		baud = tty_get_baud_rate(tty);
 		if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
 				ASYNC_SPD_CUST) {
 			if (info->custom_divisor)
@@ -3334,8 +3337,7 @@ static void set_line_char(struct cyclades_port *info)
 				"was %x\n", info->line, retval);
 		}
 
-		if (info->port.tty)
-			clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
+		clear_bit(TTY_IO_ERROR, &tty->flags);
 	}
 }				/* set_line_char */
 
@@ -3364,7 +3366,7 @@ get_serial_info(struct cyclades_port *info,
 }				/* get_serial_info */
 
 static int
-set_serial_info(struct cyclades_port *info,
+cy_set_serial_info(struct cyclades_port *info, struct tty_struct *tty,
 		struct serial_struct __user *new_info)
 {
 	struct serial_struct new_serial;
@@ -3402,10 +3404,10 @@ set_serial_info(struct cyclades_port *info,
 
 check_and_exit:
 	if (info->port.flags & ASYNC_INITIALIZED) {
-		set_line_char(info);
+		cy_set_line_char(info, tty);
 		return 0;
 	} else {
-		return startup(info);
+		return cy_startup(info, tty);
 	}
 }				/* set_serial_info */
 
@@ -3954,7 +3956,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
 		ret_val = get_serial_info(info, argp);
 		break;
 	case TIOCSSERIAL:
-		ret_val = set_serial_info(info, argp);
+		ret_val = cy_set_serial_info(info, tty, argp);
 		break;
 	case TIOCSERGETLSR:	/* Get line status register */
 		ret_val = get_lsr_info(info, argp);
@@ -4054,7 +4056,7 @@ static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 	printk(KERN_DEBUG "cyc:cy_set_termios ttyC%d\n", info->line);
 #endif
 
-	set_line_char(info);
+	cy_set_line_char(info, tty);
 
 	if ((old_termios->c_cflag & CRTSCTS) &&
 			!(tty->termios->c_cflag & CRTSCTS)) {
@@ -4298,13 +4300,13 @@ static void cy_hangup(struct tty_struct *tty)
 		return;
 
 	cy_flush_buffer(tty);
-	shutdown(info);
+	cy_shutdown(info, tty);
 	info->port.count = 0;
 #ifdef CY_DEBUG_COUNT
 	printk(KERN_DEBUG "cyc:cy_hangup (%d): setting count to 0\n",
 		current->pid);
 #endif
-	info->port.tty = NULL;
+	tty_port_tty_set(&info->port, NULL);
 	info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
 	wake_up_interruptible(&info->port.open_wait);
 }				/* cy_hangup */
@@ -5190,18 +5192,30 @@ static int cyclades_proc_show(struct seq_file *m, void *v)
 		for (j = 0; j < cy_card[i].nports; j++) {
 			info = &cy_card[i].ports[j];
 
-			if (info->port.count)
+			if (info->port.count) {
+				/* XXX is the ldisc num worth this? */
+				struct tty_struct *tty;
+				struct tty_ldisc *ld;
+				int num = 0;
+				tty = tty_port_tty_get(&info->port);
+				if (tty) {
+					ld = tty_ldisc_ref(tty);
+					if (ld) {
+						num = ld->ops->num;
+						tty_ldisc_deref(ld);
+					}
+					tty_kref_put(tty);
+				}
 				seq_printf(m, "%3d %8lu %10lu %8lu "
-					"%10lu %8lu %9lu %6ld\n", info->line,
+					"%10lu %8lu %9lu %6d\n", info->line,
 					(cur_jifs - info->idle_stats.in_use) /
 					HZ, info->idle_stats.xmit_bytes,
 					(cur_jifs - info->idle_stats.xmit_idle)/
 					HZ, info->idle_stats.recv_bytes,
 					(cur_jifs - info->idle_stats.recv_idle)/
 					HZ, info->idle_stats.overruns,
-					/* FIXME: double check locking */
-					(long)info->port.tty->ldisc->ops->num);
-			else
+					num);
+			} else
 				seq_printf(m, "%3d %8lu %10lu %8lu "
 					"%10lu %8lu %9lu %6ld\n",
 					info->line, 0L, 0L, 0L, 0L, 0L, 0L, 0L);
-- 
1.6.3.2


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

* [PATCH 02/13] Char: cyclades, remove block_til_ready
  2009-06-18  7:41 [PATCH 01/13] Char: cyclades, add tty refcounting Jiri Slaby
@ 2009-06-18  7:41 ` Jiri Slaby
  2009-06-18  7:41 ` [PATCH 03/13] Char: cyclades, avoid addresses recomputation Jiri Slaby
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Jiri Slaby @ 2009-06-18  7:41 UTC (permalink / raw)
  To: alan; +Cc: Andrew Morton, linux-kernel, Jiri Slaby

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>
---
 drivers/char/cyclades.c |  302 +++++++++++++++++------------------------------
 1 files changed, 108 insertions(+), 194 deletions(-)

diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index de9c1d9..c6709e4 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -2171,199 +2171,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.
@@ -2471,7 +2278,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 "
@@ -4311,6 +4118,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
@@ -4350,6 +4262,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;
@@ -4361,6 +4274,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;
-- 
1.6.3.2


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

* [PATCH 03/13] Char: cyclades, avoid addresses recomputation
  2009-06-18  7:41 [PATCH 01/13] Char: cyclades, add tty refcounting Jiri Slaby
  2009-06-18  7:41 ` [PATCH 02/13] Char: cyclades, remove block_til_ready Jiri Slaby
@ 2009-06-18  7:41 ` Jiri Slaby
  2009-06-18  7:41 ` [PATCH 04/13] Char: cyclades, switch to tty_port_hangup Jiri Slaby
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Jiri Slaby @ 2009-06-18  7:41 UTC (permalink / raw)
  To: alan; +Cc: Andrew Morton, linux-kernel, Jiri Slaby

Don't fetch firmware address and recompute channel control on each
port access. Precompute the values on init and use them later all
the time.

The same for board control.

This simplify code and improves readability.

Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
---
 drivers/char/cyclades.c  |  241 ++++++++++++++--------------------------------
 include/linux/cyclades.h |   10 ++
 2 files changed, 81 insertions(+), 170 deletions(-)

diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index c6709e4..691a765 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -813,7 +813,7 @@ static char rflow_thr[] = {	/* rflow threshold */
 /*  The Cyclom-Ye has placed the sequential chips in non-sequential
  *  address order.  This look-up table overcomes that problem.
  */
-static int cy_chip_offset[] = { 0x0000,
+static const unsigned int cy_chip_offset[] = { 0x0000,
 	0x0400,
 	0x0800,
 	0x0C00,
@@ -1405,15 +1405,9 @@ static int
 cyz_fetch_msg(struct cyclades_card *cinfo,
 		__u32 *channel, __u8 *cmd, __u32 *param)
 {
-	struct FIRM_ID __iomem *firm_id;
-	struct ZFW_CTRL __iomem *zfw_ctrl;
-	struct BOARD_CTRL __iomem *board_ctrl;
+	struct BOARD_CTRL __iomem *board_ctrl = cinfo->board_ctrl;
 	unsigned long loc_doorbell;
 
-	firm_id = cinfo->base_addr + ID_ADDRESS;
-	zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff);
-	board_ctrl = &zfw_ctrl->board_ctrl;
-
 	loc_doorbell = readl(&cinfo->ctl_addr.p9060->loc_doorbell);
 	if (loc_doorbell) {
 		*cmd = (char)(0xff & loc_doorbell);
@@ -1429,19 +1423,13 @@ static int
 cyz_issue_cmd(struct cyclades_card *cinfo,
 		__u32 channel, __u8 cmd, __u32 param)
 {
-	struct FIRM_ID __iomem *firm_id;
-	struct ZFW_CTRL __iomem *zfw_ctrl;
-	struct BOARD_CTRL __iomem *board_ctrl;
+	struct BOARD_CTRL __iomem *board_ctrl = cinfo->board_ctrl;
 	__u32 __iomem *pci_doorbell;
 	unsigned int index;
 
-	firm_id = cinfo->base_addr + ID_ADDRESS;
 	if (!cyz_is_loaded(cinfo))
 		return -1;
 
-	zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff);
-	board_ctrl = &zfw_ctrl->board_ctrl;
-
 	index = 0;
 	pci_doorbell = &cinfo->ctl_addr.p9060->pci_doorbell;
 	while ((readl(pci_doorbell) & 0xff) != 0) {
@@ -1456,9 +1444,9 @@ cyz_issue_cmd(struct cyclades_card *cinfo,
 	return 0;
 }				/* cyz_issue_cmd */
 
-static void cyz_handle_rx(struct cyclades_port *info, struct tty_struct *tty,
-		struct BUF_CTRL __iomem *buf_ctrl)
+static void cyz_handle_rx(struct cyclades_port *info, struct tty_struct *tty)
 {
+	struct BUF_CTRL __iomem *buf_ctrl = info->u.cyz.buf_ctrl;
 	struct cyclades_card *cinfo = info->card;
 	unsigned int char_count;
 	int len;
@@ -1548,9 +1536,9 @@ static void cyz_handle_rx(struct cyclades_port *info, struct tty_struct *tty,
 	}
 }
 
-static void cyz_handle_tx(struct cyclades_port *info, struct tty_struct *tty,
-		struct BUF_CTRL __iomem *buf_ctrl)
+static void cyz_handle_tx(struct cyclades_port *info, struct tty_struct *tty)
 {
+	struct BUF_CTRL __iomem *buf_ctrl = info->u.cyz.buf_ctrl;
 	struct cyclades_card *cinfo = info->card;
 	u8 data;
 	unsigned int char_count;
@@ -1626,21 +1614,14 @@ ztxdone:
 
 static void cyz_handle_cmd(struct cyclades_card *cinfo)
 {
+	struct BOARD_CTRL __iomem *board_ctrl = cinfo->board_ctrl;
 	struct tty_struct *tty;
 	struct cyclades_port *info;
-	static struct FIRM_ID __iomem *firm_id;
-	static struct ZFW_CTRL __iomem *zfw_ctrl;
-	static struct BOARD_CTRL __iomem *board_ctrl;
-	static struct CH_CTRL __iomem *ch_ctrl;
-	static struct BUF_CTRL __iomem *buf_ctrl;
 	__u32 channel, param, fw_ver;
 	__u8 cmd;
 	int special_count;
 	int delta_count;
 
-	firm_id = cinfo->base_addr + ID_ADDRESS;
-	zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff);
-	board_ctrl = &zfw_ctrl->board_ctrl;
 	fw_ver = readl(&board_ctrl->fw_version);
 
 	while (cyz_fetch_msg(cinfo, &channel, &cmd, &param) == 1) {
@@ -1651,9 +1632,6 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
 		if (tty == NULL)
 			continue;
 
-		ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
-		buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]);
-
 		switch (cmd) {
 		case C_CM_PR_ERROR:
 			tty_insert_flip_char(tty, 0, TTY_PARITY);
@@ -1674,9 +1652,9 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
 			info->icount.dcd++;
 			delta_count++;
 			if (info->port.flags & ASYNC_CHECK_CD) {
-				if ((fw_ver > 241 ? ((u_long) param) :
-						readl(&ch_ctrl->rs_status)) &
-						C_RS_DCD) {
+				u32 dcd = fw_ver > 241 ? param :
+					readl(&info->u.cyz.ch_ctrl->rs_status);
+				if (dcd & C_RS_DCD) {
 					wake_up_interruptible(&info->port.open_wait);
 				} else {
 					tty_hangup(tty);
@@ -1711,7 +1689,7 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
 			printk(KERN_DEBUG "cyz_interrupt: rcvd intr, card %d, "
 					"port %ld\n", info->card, channel);
 #endif
-			cyz_handle_rx(info, tty, buf_ctrl);
+			cyz_handle_rx(info, tty);
 			break;
 		case C_CM_TXBEMPTY:
 		case C_CM_TXLOWWM:
@@ -1721,7 +1699,7 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
 			printk(KERN_DEBUG "cyz_interrupt: xmit intr, card %d, "
 					"port %ld\n", info->card, channel);
 #endif
-			cyz_handle_tx(info, tty, buf_ctrl);
+			cyz_handle_tx(info, tty);
 			break;
 #endif				/* CONFIG_CYZ_INTR */
 		case C_CM_FATAL:
@@ -1780,9 +1758,6 @@ static void cyz_poll(unsigned long arg)
 {
 	struct cyclades_card *cinfo;
 	struct cyclades_port *info;
-	struct FIRM_ID __iomem *firm_id;
-	struct ZFW_CTRL __iomem *zfw_ctrl;
-	struct BUF_CTRL __iomem *buf_ctrl;
 	unsigned long expires = jiffies + HZ;
 	unsigned int port, card;
 
@@ -1794,10 +1769,6 @@ static void cyz_poll(unsigned long arg)
 		if (!cyz_is_loaded(cinfo))
 			continue;
 
-		firm_id = cinfo->base_addr + ID_ADDRESS;
-		zfw_ctrl = cinfo->base_addr +
-				(readl(&firm_id->zfwctrl_addr) & 0xfffff);
-
 	/* Skip first polling cycle to avoid racing conditions with the FW */
 		if (!cinfo->intr_enabled) {
 			cinfo->intr_enabled = 1;
@@ -1810,15 +1781,13 @@ static void cyz_poll(unsigned long arg)
 			struct tty_struct *tty;
 
 			info = &cinfo->ports[port];
-			buf_ctrl = &(zfw_ctrl->buf_ctrl[port]);
-
 			tty = tty_port_tty_get(&info->port);
 			/* OK to pass NULL to the handle functions below.
 			   They need to drop the data in that case. */
 
 			if (!info->throttle)
-				cyz_handle_rx(info, tty, buf_ctrl);
-			cyz_handle_tx(info, tty, buf_ctrl);
+				cyz_handle_rx(info, tty);
+			cyz_handle_tx(info, tty);
 			tty_kref_put(tty);
 		}
 		/* poll every 'cyz_polling_cycle' period */
@@ -1921,45 +1890,34 @@ static int cy_startup(struct cyclades_port *info, struct tty_struct *tty)
 		spin_unlock_irqrestore(&card->card_lock, flags);
 
 	} 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 = card->base_addr;
+		struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
 
-		firm_id = base_addr + ID_ADDRESS;
 		if (!cyz_is_loaded(card))
 			return -ENODEV;
 
-		zfw_ctrl = card->base_addr +
-				(readl(&firm_id->zfwctrl_addr) & 0xfffff);
-		board_ctrl = &zfw_ctrl->board_ctrl;
-		ch_ctrl = zfw_ctrl->ch_ctrl;
-
 #ifdef CY_DEBUG_OPEN
 		printk(KERN_DEBUG "cyc startup Z card %d, channel %d, "
-			"base_addr %p\n", card, channel, base_addr);
+			"base_addr %p\n", card, channel, card->base_addr);
 #endif
 		spin_lock_irqsave(&card->card_lock, flags);
 
-		cy_writel(&ch_ctrl[channel].op_mode, C_CH_ENABLE);
+		cy_writel(&ch_ctrl->op_mode, C_CH_ENABLE);
 #ifdef Z_WAKE
 #ifdef CONFIG_CYZ_INTR
-		cy_writel(&ch_ctrl[channel].intr_enable,
+		cy_writel(&ch_ctrl->intr_enable,
 			  C_IN_TXBEMPTY | C_IN_TXLOWWM | C_IN_RXHIWM |
 			  C_IN_RXNNDT | C_IN_IOCTLW | C_IN_MDCD);
 #else
-		cy_writel(&ch_ctrl[channel].intr_enable,
+		cy_writel(&ch_ctrl->intr_enable,
 			  C_IN_IOCTLW | C_IN_MDCD);
 #endif				/* CONFIG_CYZ_INTR */
 #else
 #ifdef CONFIG_CYZ_INTR
-		cy_writel(&ch_ctrl[channel].intr_enable,
+		cy_writel(&ch_ctrl->intr_enable,
 			  C_IN_TXBEMPTY | C_IN_TXLOWWM | C_IN_RXHIWM |
 			  C_IN_RXNNDT | C_IN_MDCD);
 #else
-		cy_writel(&ch_ctrl[channel].intr_enable, C_IN_MDCD);
+		cy_writel(&ch_ctrl->intr_enable, C_IN_MDCD);
 #endif				/* CONFIG_CYZ_INTR */
 #endif				/* Z_WAKE */
 
@@ -1978,9 +1936,8 @@ static int cy_startup(struct cyclades_port *info, struct tty_struct *tty)
 
 		/* set timeout !!! */
 		/* set RTS and DTR !!! */
-		cy_writel(&ch_ctrl[channel].rs_control,
-			readl(&ch_ctrl[channel].rs_control) | C_RS_RTS |
-			C_RS_DTR);
+		cy_writel(&ch_ctrl->rs_control, readl(&ch_ctrl->rs_control) |
+				C_RS_RTS | C_RS_DTR);
 		retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L);
 		if (retval != 0) {
 			printk(KERN_ERR "cyc:startup(3) retval on ttyC%d was "
@@ -2109,27 +2066,17 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty)
 		info->port.flags &= ~ASYNC_INITIALIZED;
 		spin_unlock_irqrestore(&card->card_lock, flags);
 	} 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;
+		struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
 		int retval;
 
-		base_addr = card->base_addr;
 #ifdef CY_DEBUG_OPEN
 		printk(KERN_DEBUG "cyc shutdown Z card %d, channel %d, "
-			"base_addr %p\n", card, channel, base_addr);
+			"base_addr %p\n", card, channel, card->base_addr);
 #endif
 
-		firm_id = base_addr + ID_ADDRESS;
 		if (!cyz_is_loaded(card))
 			return;
 
-		zfw_ctrl = card->base_addr +
-				(readl(&firm_id->zfwctrl_addr) & 0xfffff);
-		board_ctrl = &zfw_ctrl->board_ctrl;
-		ch_ctrl = zfw_ctrl->ch_ctrl;
-
 		spin_lock_irqsave(&card->card_lock, flags);
 
 		if (info->port.xmit_buf) {
@@ -2140,9 +2087,9 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty)
 		}
 
 		if (tty->termios->c_cflag & HUPCL) {
-			cy_writel(&ch_ctrl[channel].rs_control,
-				(__u32)(readl(&ch_ctrl[channel].rs_control) &
-					~(C_RS_RTS | C_RS_DTR)));
+			cy_writel(&ch_ctrl->rs_control,
+				readl(&ch_ctrl->rs_control) &
+					~(C_RS_RTS | C_RS_DTR));
 			retval = cyz_issue_cmd(info->card, channel,
 					C_CM_IOCTLM, 0L);
 			if (retval != 0) {
@@ -2496,15 +2443,11 @@ static void cy_close(struct tty_struct *tty, struct file *filp)
 #ifdef Z_WAKE
 		/* Waiting for on-board buffers to be empty before closing
 		   the port */
-		void __iomem *base_addr = card->base_addr;
-		struct FIRM_ID __iomem *firm_id = base_addr + ID_ADDRESS;
-		struct ZFW_CTRL __iomem *zfw_ctrl =
-		    base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff);
-		struct CH_CTRL __iomem *ch_ctrl = zfw_ctrl->ch_ctrl;
+		struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
 		int channel = info->line - card->first_line;
 		int retval;
 
-		if (readl(&ch_ctrl[channel].flow_status) != C_FS_TXIDLE) {
+		if (readl(&ch_ctrl->flow_status) != C_FS_TXIDLE) {
 			retval = cyz_issue_cmd(card, channel, C_CM_IOCTLW, 0L);
 			if (retval != 0) {
 				printk(KERN_DEBUG "cyc:cy_close retval on "
@@ -2684,18 +2627,13 @@ static int cy_write_room(struct tty_struct *tty)
 
 static int cy_chars_in_buffer(struct tty_struct *tty)
 {
-	struct cyclades_card *card;
 	struct cyclades_port *info = tty->driver_data;
-	int channel;
 
 	if (serial_paranoia_check(info, tty->name, "cy_chars_in_buffer"))
 		return 0;
 
-	card = info->card;
-	channel = (info->line) - (card->first_line);
-
 #ifdef Z_EXT_CHARS_IN_BUFFER
-	if (!cy_is_Z(card)) {
+	if (!cy_is_Z(info->card)) {
 #endif				/* Z_EXT_CHARS_IN_BUFFER */
 #ifdef CY_DEBUG_IO
 		printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n",
@@ -2704,20 +2642,11 @@ static int cy_chars_in_buffer(struct tty_struct *tty)
 		return info->xmit_cnt;
 #ifdef Z_EXT_CHARS_IN_BUFFER
 	} else {
-		static struct FIRM_ID *firm_id;
-		static struct ZFW_CTRL *zfw_ctrl;
-		static struct CH_CTRL *ch_ctrl;
-		static struct BUF_CTRL *buf_ctrl;
+		struct BUF_CTRL __iomem *buf_ctrl = info->u.cyz.buf_ctrl;
 		int char_count;
 		__u32 tx_put, tx_get, tx_bufsize;
 
 		lock_kernel();
-		firm_id = card->base_addr + ID_ADDRESS;
-		zfw_ctrl = card->base_addr +
-			(readl(&firm_id->zfwctrl_addr) & 0xfffff);
-		ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
-		buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]);
-
 		tx_get = readl(&buf_ctrl->tx_get);
 		tx_put = readl(&buf_ctrl->tx_put);
 		tx_bufsize = readl(&buf_ctrl->tx_bufsize);
@@ -3018,20 +2947,13 @@ static void cy_set_line_char(struct cyclades_port *info, struct tty_struct *tty)
 		spin_unlock_irqrestore(&card->card_lock, flags);
 
 	} else {
-		struct FIRM_ID __iomem *firm_id;
-		struct ZFW_CTRL __iomem *zfw_ctrl;
-		struct CH_CTRL __iomem *ch_ctrl;
+		struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
 		__u32 sw_flow;
 		int retval;
 
-		firm_id = card->base_addr + ID_ADDRESS;
 		if (!cyz_is_loaded(card))
 			return;
 
-		zfw_ctrl = card->base_addr +
-			(readl(&firm_id->zfwctrl_addr) & 0xfffff);
-		ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
-
 		/* baud rate */
 		baud = tty_get_baud_rate(tty);
 		if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
@@ -3267,10 +3189,6 @@ static int cy_tiocmget(struct tty_struct *tty, struct file *file)
 	unsigned char status;
 	unsigned long lstatus;
 	unsigned int result;
-	struct FIRM_ID __iomem *firm_id;
-	struct ZFW_CTRL __iomem *zfw_ctrl;
-	struct BOARD_CTRL __iomem *board_ctrl;
-	struct CH_CTRL __iomem *ch_ctrl;
 
 	if (serial_paranoia_check(info, tty->name, __func__))
 		return -ENODEV;
@@ -3303,14 +3221,8 @@ static int cy_tiocmget(struct tty_struct *tty, struct file *file)
 			((status & CyDSR) ? TIOCM_DSR : 0) |
 			((status & CyCTS) ? TIOCM_CTS : 0);
 	} else {
-		base_addr = card->base_addr;
-		firm_id = card->base_addr + ID_ADDRESS;
 		if (cyz_is_loaded(card)) {
-			zfw_ctrl = card->base_addr +
-				(readl(&firm_id->zfwctrl_addr) & 0xfffff);
-			board_ctrl = &zfw_ctrl->board_ctrl;
-			ch_ctrl = zfw_ctrl->ch_ctrl;
-			lstatus = readl(&ch_ctrl[channel].rs_status);
+			lstatus = readl(&info->u.cyz.ch_ctrl->rs_status);
 			result = ((lstatus & C_RS_RTS) ? TIOCM_RTS : 0) |
 				((lstatus & C_RS_DTR) ? TIOCM_DTR : 0) |
 				((lstatus & C_RS_DCD) ? TIOCM_CAR : 0) |
@@ -3335,12 +3247,7 @@ cy_tiocmset(struct tty_struct *tty, struct file *file,
 	struct cyclades_port *info = tty->driver_data;
 	struct cyclades_card *card;
 	int chip, channel, index;
-	void __iomem *base_addr;
 	unsigned long flags;
-	struct FIRM_ID __iomem *firm_id;
-	struct ZFW_CTRL __iomem *zfw_ctrl;
-	struct BOARD_CTRL __iomem *board_ctrl;
-	struct CH_CTRL __iomem *ch_ctrl;
 	int retval;
 
 	if (serial_paranoia_check(info, tty->name, __func__))
@@ -3349,6 +3256,7 @@ cy_tiocmset(struct tty_struct *tty, struct file *file,
 	card = info->card;
 	channel = (info->line) - (card->first_line);
 	if (!cy_is_Z(card)) {
+		void __iomem *base_addr;
 		chip = channel >> 2;
 		channel &= 0x03;
 		index = card->bus_index;
@@ -3420,34 +3328,26 @@ cy_tiocmset(struct tty_struct *tty, struct file *file,
 			spin_unlock_irqrestore(&card->card_lock, flags);
 		}
 	} else {
-		base_addr = card->base_addr;
-
-		firm_id = card->base_addr + ID_ADDRESS;
 		if (cyz_is_loaded(card)) {
-			zfw_ctrl = card->base_addr +
-				(readl(&firm_id->zfwctrl_addr) & 0xfffff);
-			board_ctrl = &zfw_ctrl->board_ctrl;
-			ch_ctrl = zfw_ctrl->ch_ctrl;
+			struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
 
 			if (set & TIOCM_RTS) {
 				spin_lock_irqsave(&card->card_lock, flags);
-				cy_writel(&ch_ctrl[channel].rs_control,
-					readl(&ch_ctrl[channel].rs_control) |
-					C_RS_RTS);
+				cy_writel(&ch_ctrl->rs_control,
+					readl(&ch_ctrl->rs_control) | C_RS_RTS);
 				spin_unlock_irqrestore(&card->card_lock, flags);
 			}
 			if (clear & TIOCM_RTS) {
 				spin_lock_irqsave(&card->card_lock, flags);
-				cy_writel(&ch_ctrl[channel].rs_control,
-					readl(&ch_ctrl[channel].rs_control) &
+				cy_writel(&ch_ctrl->rs_control,
+					readl(&ch_ctrl->rs_control) &
 					~C_RS_RTS);
 				spin_unlock_irqrestore(&card->card_lock, flags);
 			}
 			if (set & TIOCM_DTR) {
 				spin_lock_irqsave(&card->card_lock, flags);
-				cy_writel(&ch_ctrl[channel].rs_control,
-					readl(&ch_ctrl[channel].rs_control) |
-					C_RS_DTR);
+				cy_writel(&ch_ctrl->rs_control,
+					readl(&ch_ctrl->rs_control) | C_RS_DTR);
 #ifdef CY_DEBUG_DTR
 				printk(KERN_DEBUG "cyc:set_modem_info raising "
 					"Z DTR\n");
@@ -3456,8 +3356,8 @@ cy_tiocmset(struct tty_struct *tty, struct file *file,
 			}
 			if (clear & TIOCM_DTR) {
 				spin_lock_irqsave(&card->card_lock, flags);
-				cy_writel(&ch_ctrl[channel].rs_control,
-					readl(&ch_ctrl[channel].rs_control) &
+				cy_writel(&ch_ctrl->rs_control,
+					readl(&ch_ctrl->rs_control) &
 					~C_RS_DTR);
 #ifdef CY_DEBUG_DTR
 				printk(KERN_DEBUG "cyc:set_modem_info clearing "
@@ -4170,17 +4070,8 @@ 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;
+	return readl(&info->u.cyz.ch_ctrl->rs_status) & C_RS_DCD;
 }
 
 static void cyz_dtr_rts(struct tty_port *port, int raise)
@@ -4188,22 +4079,16 @@ 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;
+	struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.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);
+	rs = readl(&ch_ctrl->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);
+	cy_writel(&ch_ctrl->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",
@@ -4234,8 +4119,7 @@ static const struct tty_port_operations cyz_port_ops = {
 static int __devinit cy_init_card(struct cyclades_card *cinfo)
 {
 	struct cyclades_port *info;
-	unsigned int port;
-	unsigned short chip_number;
+	unsigned int channel, port;
 
 	spin_lock_init(&cinfo->card_lock);
 	cinfo->intr_enabled = 0;
@@ -4247,9 +4131,9 @@ static int __devinit cy_init_card(struct cyclades_card *cinfo)
 		return -ENOMEM;
 	}
 
-	for (port = cinfo->first_line; port < cinfo->first_line + cinfo->nports;
-			port++) {
-		info = &cinfo->ports[port - cinfo->first_line];
+	for (channel = 0, port = cinfo->first_line; channel < cinfo->nports;
+			channel++, port++) {
+		info = &cinfo->ports[channel];
 		tty_port_init(&info->port);
 		info->magic = CYCLADES_MAGIC;
 		info->card = cinfo;
@@ -4262,8 +4146,17 @@ static int __devinit cy_init_card(struct cyclades_card *cinfo)
 		init_waitqueue_head(&info->delta_msr_wait);
 
 		if (cy_is_Z(cinfo)) {
+			struct FIRM_ID *firm_id = cinfo->base_addr + ID_ADDRESS;
+			struct ZFW_CTRL *zfw_ctrl;
+
 			info->port.ops = &cyz_port_ops;
 			info->type = PORT_STARTECH;
+
+			zfw_ctrl = cinfo->base_addr +
+				(readl(&firm_id->zfwctrl_addr) & 0xfffff);
+			info->u.cyz.ch_ctrl = &zfw_ctrl->ch_ctrl[channel];
+			info->u.cyz.buf_ctrl = &zfw_ctrl->buf_ctrl[channel];
+
 			if (cinfo->hw_ver == ZO_V1)
 				info->xmit_fifo_size = CYZ_FIFO_SIZE;
 			else
@@ -4273,7 +4166,9 @@ static int __devinit cy_init_card(struct cyclades_card *cinfo)
 				cyz_rx_restart, (unsigned long)info);
 #endif
 		} else {
+			unsigned short chip_number;
 			int index = cinfo->bus_index;
+
 			info->port.ops = &cyy_port_ops;
 			info->type = PORT_CIRRUS;
 			info->xmit_fifo_size = CyMAX_CHAR_FIFO;
@@ -4281,7 +4176,7 @@ static int __devinit cy_init_card(struct cyclades_card *cinfo)
 			info->cor2 = CyETC;
 			info->cor3 = 0x08;	/* _very_ small rcv threshold */
 
-			chip_number = (port - cinfo->first_line) / 4;
+			chip_number = channel / CyPORTS_PER_CHIP;
 			info->chip_rev = readb(cinfo->base_addr +
 				      (cy_chip_offset[chip_number] << index) +
 				      (CyGFRCR << index));
@@ -4975,8 +4870,14 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
 		}
 		cy_card[card_no].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;
 #ifdef CONFIG_CYZ_INTR
 		/* allocate IRQ only if board has an IRQ */
 		if (irq != 0 && irq != 255) {
diff --git a/include/linux/cyclades.h b/include/linux/cyclades.h
index 1fbdea4..1eb87a6 100644
--- a/include/linux/cyclades.h
+++ b/include/linux/cyclades.h
@@ -499,6 +499,7 @@ struct cyclades_card {
 		void __iomem *p9050;
 		struct RUNTIME_9060 __iomem *p9060;
 	} ctl_addr;
+	struct BOARD_CTRL __iomem *board_ctrl;	/* cyz specific */
 	int irq;
 	unsigned int num_chips;	/* 0 if card absent, -1 if Z/PCI, else Y */
 	unsigned int first_line;	/* minor number of first channel on card */
@@ -541,6 +542,15 @@ struct cyclades_port {
 	int                     magic;
 	struct tty_port		port;
 	struct cyclades_card	*card;
+	union {
+		struct {
+			int filler;
+		} cyy;
+		struct {
+			struct CH_CTRL __iomem	*ch_ctrl;
+			struct BUF_CTRL __iomem	*buf_ctrl;
+		} cyz;
+	} u;
 	int			line;
 	int			flags; 		/* defined in tty.h */
 	int                     type;		/* UART type */
-- 
1.6.3.2


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

* [PATCH 04/13] Char: cyclades, switch to tty_port_hangup
  2009-06-18  7:41 [PATCH 01/13] Char: cyclades, add tty refcounting Jiri Slaby
  2009-06-18  7:41 ` [PATCH 02/13] Char: cyclades, remove block_til_ready Jiri Slaby
  2009-06-18  7:41 ` [PATCH 03/13] Char: cyclades, avoid addresses recomputation Jiri Slaby
@ 2009-06-18  7:41 ` Jiri Slaby
  2009-06-18  7:41 ` [PATCH 05/13] Char: cyclades, close cleanup Jiri Slaby
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Jiri Slaby @ 2009-06-18  7:41 UTC (permalink / raw)
  To: alan; +Cc: Andrew Morton, linux-kernel, Jiri Slaby

Do not duplicate common tty_port_hangup code. Use it instead.

Also do not unset ASYNC_NORMAL_ACTIVE and wake up from the
tty_hangup() caller. It makes no sense since we don't check that
flag in sleepers. tty_port_hangup() performed later will do the
right job.

Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
---
 drivers/char/cyclades.c |   23 ++++++-----------------
 1 files changed, 6 insertions(+), 17 deletions(-)

diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index 691a765..44bd42d 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -1289,11 +1289,10 @@ static void cyy_chip_modem(struct cyclades_card *cinfo, int chip,
 	}
 
 	if ((mdm_change & CyDCD) && (info->port.flags & ASYNC_CHECK_CD)) {
-		if (!(mdm_status & CyDCD)) {
+		if (mdm_status & CyDCD)
+			wake_up_interruptible(&info->port.open_wait);
+		else
 			tty_hangup(tty);
-			info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
-		}
-		wake_up_interruptible(&info->port.open_wait);
 	}
 	if ((mdm_change & CyCTS) && (info->port.flags & ASYNC_CTS_FLOW)) {
 		if (tty->hw_stopped) {
@@ -1654,13 +1653,10 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
 			if (info->port.flags & ASYNC_CHECK_CD) {
 				u32 dcd = fw_ver > 241 ? param :
 					readl(&info->u.cyz.ch_ctrl->rs_status);
-				if (dcd & C_RS_DCD) {
+				if (dcd & C_RS_DCD)
 					wake_up_interruptible(&info->port.open_wait);
-				} else {
+				else
 					tty_hangup(tty);
-					wake_up_interruptible(&info->port.open_wait);
-					info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
-				}
 			}
 			break;
 		case C_CM_MCTS:
@@ -4008,14 +4004,7 @@ static void cy_hangup(struct tty_struct *tty)
 
 	cy_flush_buffer(tty);
 	cy_shutdown(info, tty);
-	info->port.count = 0;
-#ifdef CY_DEBUG_COUNT
-	printk(KERN_DEBUG "cyc:cy_hangup (%d): setting count to 0\n",
-		current->pid);
-#endif
-	tty_port_tty_set(&info->port, NULL);
-	info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
-	wake_up_interruptible(&info->port.open_wait);
+	tty_port_hangup(&info->port);
 }				/* cy_hangup */
 
 static int cyy_carrier_raised(struct tty_port *port)
-- 
1.6.3.2


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

* [PATCH 05/13] Char: cyclades, close cleanup
  2009-06-18  7:41 [PATCH 01/13] Char: cyclades, add tty refcounting Jiri Slaby
                   ` (2 preceding siblings ...)
  2009-06-18  7:41 ` [PATCH 04/13] Char: cyclades, switch to tty_port_hangup Jiri Slaby
@ 2009-06-18  7:41 ` Jiri Slaby
  2009-06-18  7:41 ` [PATCH 06/13] Char: cyclades, overall cleanup Jiri Slaby
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Jiri Slaby @ 2009-06-18  7:41 UTC (permalink / raw)
  To: alan; +Cc: Andrew Morton, linux-kernel, Jiri Slaby

Use new tty helpers for close, which allows much code removal.

The only real change is locking. card_lock for protecting was
used inappropriately (just to have a critical section, no matter
which lock is used), so the change to port->lock is fine.

Remove also useless debug printks while being there.

Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
---
 drivers/char/cyclades.c |   70 +---------------------------------------------
 1 files changed, 2 insertions(+), 68 deletions(-)

diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index 44bd42d..67f1739 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -2360,61 +2360,13 @@ static void cy_close(struct tty_struct *tty, struct file *filp)
 	struct cyclades_card *card;
 	unsigned long flags;
 
-#ifdef CY_DEBUG_OTHER
-	printk(KERN_DEBUG "cyc:cy_close ttyC%d\n", info->line);
-#endif
-
 	if (!info || serial_paranoia_check(info, tty->name, "cy_close"))
 		return;
 
 	card = info->card;
 
-	spin_lock_irqsave(&card->card_lock, flags);
-	/* If the TTY is being hung up, nothing to do */
-	if (tty_hung_up_p(filp)) {
-		spin_unlock_irqrestore(&card->card_lock, flags);
+	if (!tty_port_close_start(&info->port, tty, filp))
 		return;
-	}
-#ifdef CY_DEBUG_OPEN
-	printk(KERN_DEBUG "cyc:cy_close ttyC%d, count = %d\n", info->line,
-		info->port.count);
-#endif
-	if ((tty->count == 1) && (info->port.count != 1)) {
-		/*
-		 * Uh, oh.  tty->count is 1, which means that the tty
-		 * structure will be freed.  Info->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.
-		 */
-		printk(KERN_ERR "cyc:cy_close: bad serial port count; "
-			"tty->count is 1, info->port.count is %d\n", info->port.count);
-		info->port.count = 1;
-	}
-#ifdef CY_DEBUG_COUNT
-	printk(KERN_DEBUG  "cyc:cy_close at (%d): decrementing count to %d\n",
-		current->pid, info->port.count - 1);
-#endif
-	if (--info->port.count < 0) {
-#ifdef CY_DEBUG_COUNT
-		printk(KERN_DEBUG "cyc:cyc_close setting count to 0\n");
-#endif
-		info->port.count = 0;
-	}
-	if (info->port.count) {
-		spin_unlock_irqrestore(&card->card_lock, flags);
-		return;
-	}
-	info->port.flags |= ASYNC_CLOSING;
-
-	/*
-	 * Now we wait for the transmit buffer to clear; and we notify
-	 * the line discipline to only process XON/XOFF characters.
-	 */
-	tty->closing = 1;
-	spin_unlock_irqrestore(&card->card_lock, flags);
-	if (info->port.closing_wait != CY_CLOSING_WAIT_NONE)
-		tty_wait_until_sent(tty, info->port.closing_wait);
 
 	spin_lock_irqsave(&card->card_lock, flags);
 
@@ -2459,28 +2411,10 @@ static void cy_close(struct tty_struct *tty, struct file *filp)
 	spin_unlock_irqrestore(&card->card_lock, flags);
 	cy_shutdown(info, tty);
 	cy_flush_buffer(tty);
-	tty_ldisc_flush(tty);
-	spin_lock_irqsave(&card->card_lock, flags);
 
-	tty->closing = 0;
 	tty_port_tty_set(&info->port, NULL);
-	if (info->port.blocked_open) {
-		spin_unlock_irqrestore(&card->card_lock, flags);
-		if (info->port.close_delay) {
-			msleep_interruptible(jiffies_to_msecs
-						(info->port.close_delay));
-		}
-		wake_up_interruptible(&info->port.open_wait);
-		spin_lock_irqsave(&card->card_lock, flags);
-	}
-	info->port.flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
-	wake_up_interruptible(&info->port.close_wait);
 
-#ifdef CY_DEBUG_OTHER
-	printk(KERN_DEBUG "cyc:cy_close done\n");
-#endif
-
-	spin_unlock_irqrestore(&card->card_lock, flags);
+	tty_port_close_end(&info->port, tty);
 }				/* cy_close */
 
 /* This routine gets called when tty_write has put something into
-- 
1.6.3.2


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

* [PATCH 06/13] Char: cyclades, overall cleanup
  2009-06-18  7:41 [PATCH 01/13] Char: cyclades, add tty refcounting Jiri Slaby
                   ` (3 preceding siblings ...)
  2009-06-18  7:41 ` [PATCH 05/13] Char: cyclades, close cleanup Jiri Slaby
@ 2009-06-18  7:41 ` Jiri Slaby
  2009-06-18  7:41 ` [PATCH 07/13] Char: cyclades, sleep instead busy-wait Jiri Slaby
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Jiri Slaby @ 2009-06-18  7:41 UTC (permalink / raw)
  To: alan; +Cc: Andrew Morton, linux-kernel, Jiri Slaby

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 30753 bytes --]

- remove changelog from the file. we don't care about ancient
  history
- update copyright year
- update version
- constify some stuff
- empty lines removal
- unused variables and macros removal
- remove some asm/ includes, they are sucked by linux/ variants

Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
---
 drivers/char/cyclades.c |  600 +----------------------------------------------
 1 files changed, 13 insertions(+), 587 deletions(-)

diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index 67f1739..1510506 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -11,7 +11,7 @@
  * Initially written by Randolph Bentson <bentson@grieg.seaslug.org>.
  * Modified and maintained by Marcio Saito <marcio@cyclades.com>.
  *
- * Copyright (C) 2007 Jiri Slaby <jirislaby@gmail.com>
+ * Copyright (C) 2007-2009 Jiri Slaby <jirislaby@gmail.com>
  *
  * Much of the design and some of the code came from serial.c
  * which was copyright (C) 1991, 1992  Linus Torvalds.  It was
@@ -19,577 +19,9 @@
  * and then fixed as suggested by Michael K. Johnson 12/12/92.
  * Converted to pci probing and cleaned up by Jiri Slaby.
  *
- * This version supports shared IRQ's (only for PCI boards).
- *
- * Prevent users from opening non-existing Z ports.
- *
- * Revision 2.3.2.8   2000/07/06 18:14:16 ivan
- * Fixed the PCI detection function to work properly on Alpha systems.
- * Implemented support for TIOCSERGETLSR ioctl.
- * Implemented full support for non-standard baud rates.
- *
- * Revision 2.3.2.7   2000/06/01 18:26:34 ivan
- * Request PLX I/O region, although driver doesn't use it, to avoid
- * problems with other drivers accessing it.
- * Removed count for on-board buffer characters in cy_chars_in_buffer
- * (Cyclades-Z only).
- *
- * Revision 2.3.2.6   2000/05/05 13:56:05 ivan
- * Driver now reports physical instead of virtual memory addresses.
- * Masks were added to some Cyclades-Z read accesses.
- * Implemented workaround for PLX9050 bug that would cause a system lockup
- * in certain systems, depending on the MMIO addresses allocated to the
- * board.
- * Changed the Tx interrupt programming in the CD1400 chips to boost up
- * performance (Cyclom-Y only).
- * Code is now compliant with the new module interface (module_[init|exit]).
- * Make use of the PCI helper functions to access PCI resources.
- * Did some code "housekeeping".
- *
- * Revision 2.3.2.5   2000/01/19 14:35:33 ivan
- * Fixed bug in cy_set_termios on CRTSCTS flag turnoff.
- *
- * Revision 2.3.2.4   2000/01/17 09:19:40 ivan
- * Fixed SMP locking in Cyclom-Y interrupt handler.
- *
- * Revision 2.3.2.3   1999/12/28 12:11:39 ivan
- * Added a new cyclades_card field called nports to allow the driver to
- * know the exact number of ports found by the Z firmware after its load;
- * RX buffer contention prevention logic on interrupt op mode revisited
- * (Cyclades-Z only);
- * Revisited printk's for Z debug;
- * Driver now makes sure that the constant SERIAL_XMIT_SIZE is defined;
- *
- * Revision 2.3.2.2   1999/10/01 11:27:43 ivan
- * Fixed bug in cyz_poll that would make all ports but port 0
- * unable to transmit/receive data (Cyclades-Z only);
- * Implemented logic to prevent the RX buffer from being stuck with data
- * due to a driver / firmware race condition in interrupt op mode
- * (Cyclades-Z only);
- * Fixed bug in block_til_ready logic that would lead to a system crash;
- * Revisited cy_close spinlock usage;
- *
- * Revision 2.3.2.1   1999/09/28 11:01:22 ivan
- * Revisited CONFIG_PCI conditional compilation for PCI board support;
- * Implemented TIOCGICOUNT and TIOCMIWAIT ioctl support;
- * _Major_ cleanup on the Cyclades-Z interrupt support code / logic;
- * Removed CTS handling from the driver -- this is now completely handled
- * by the firmware (Cyclades-Z only);
- * Flush RX on-board buffers on a port open (Cyclades-Z only);
- * Fixed handling of ASYNC_SPD_* TTY flags;
- * Module unload now unmaps all memory area allocated by ioremap;
- *
- * Revision 2.3.1.1   1999/07/15 16:45:53 ivan
- * Removed CY_PROC conditional compilation;
- * Implemented SMP-awareness for the driver;
- * Implemented a new ISA IRQ autoprobe that uses the irq_probe_[on|off]
- * functions;
- * The driver now accepts memory addresses (maddr=0xMMMMM) and IRQs
- * (irq=NN) as parameters (only for ISA boards);
- * Fixed bug in set_line_char that would prevent the Cyclades-Z
- * ports from being configured at speeds above 115.2Kbps;
- * Fixed bug in cy_set_termios that would prevent XON/XOFF flow control
- * switching from working properly;
- * The driver now only prints IRQ info for the Cyclades-Z if it's
- * configured to work in interrupt mode;
- *
- * Revision 2.2.2.3   1999/06/28 11:13:29 ivan
- * Added support for interrupt mode operation for the Z cards;
- * Removed the driver inactivity control for the Z;
- * Added a missing MOD_DEC_USE_COUNT in the cy_open function for when
- * the Z firmware is not loaded yet;
- * Replaced the "manual" Z Tx flush buffer by a call to a FW command of
- * same functionality;
- * Implemented workaround for IRQ setting loss on the PCI configuration
- * registers after a PCI bridge EEPROM reload (affects PLX9060 only);
- *
- * Revision 2.2.2.2  1999/05/14 17:18:15 ivan
- * /proc entry location changed to /proc/tty/driver/cyclades;
- * Added support to shared IRQ's (only for PCI boards);
- * Added support for Cobalt Qube2 systems;
- * IRQ [de]allocation scheme revisited;
- * BREAK implementation changed in order to make use of the 'break_ctl'
- * TTY facility;
- * Fixed typo in TTY structure field 'driver_name';
- * Included a PCI bridge reset and EEPROM reload in the board
- * initialization code (for both Y and Z series).
- *
- * Revision 2.2.2.1  1999/04/08 16:17:43 ivan
- * Fixed a bug in cy_wait_until_sent that was preventing the port to be
- * closed properly after a SIGINT;
- * Module usage counter scheme revisited;
- * Added support to the upcoming Y PCI boards (i.e., support to additional
- * PCI Device ID's).
- *
- * Revision 2.2.1.10 1999/01/20 16:14:29 ivan
- * Removed all unnecessary page-alignement operations in ioremap calls
- * (ioremap is currently safe for these operations).
- *
- * Revision 2.2.1.9  1998/12/30 18:18:30 ivan
- * Changed access to PLX PCI bridge registers from I/O to MMIO, in
- * order to make PLX9050-based boards work with certain motherboards.
- *
- * Revision 2.2.1.8  1998/11/13 12:46:20 ivan
- * cy_close function now resets (correctly) the tty->closing flag;
- * JIFFIES_DIFF macro fixed.
- *
- * Revision 2.2.1.7  1998/09/03 12:07:28 ivan
- * Fixed bug in cy_close function, which was not informing HW of
- * which port should have the reception disabled before doing so;
- * fixed Cyclom-8YoP hardware detection bug.
- *
- * Revision 2.2.1.6  1998/08/20 17:15:39 ivan
- * Fixed bug in cy_close function, which causes malfunction
- * of one of the first 4 ports when a higher port is closed
- * (Cyclom-Y only).
- *
- * Revision 2.2.1.5  1998/08/10 18:10:28 ivan
- * Fixed Cyclom-4Yo hardware detection bug.
- *
- * Revision 2.2.1.4  1998/08/04 11:02:50 ivan
- * /proc/cyclades implementation with great collaboration of
- * Marc Lewis <marc@blarg.net>;
- * cyy_interrupt was changed to avoid occurrence of kernel oopses
- * during PPP operation.
- *
- * Revision 2.2.1.3  1998/06/01 12:09:10 ivan
- * General code review in order to comply with 2.1 kernel standards;
- * data loss prevention for slow devices revisited (cy_wait_until_sent
- * was created);
- * removed conditional compilation for new/old PCI structure support
- * (now the driver only supports the new PCI structure).
- *
- * Revision 2.2.1.1  1998/03/19 16:43:12 ivan
- * added conditional compilation for new/old PCI structure support;
- * removed kernel series (2.0.x / 2.1.x) conditional compilation.
- *
- * Revision 2.1.1.3  1998/03/16 18:01:12 ivan
- * cleaned up the data loss fix;
- * fixed XON/XOFF handling once more (Cyclades-Z);
- * general review of the driver routines;
- * introduction of a mechanism to prevent data loss with slow
- * printers, by forcing a delay before closing the port.
- *
- * Revision 2.1.1.2  1998/02/17 16:50:00 ivan
- * fixed detection/handling of new CD1400 in Ye boards;
- * fixed XON/XOFF handling (Cyclades-Z);
- * fixed data loss caused by a premature port close;
- * introduction of a flag that holds the CD1400 version ID per port
- * (used by the CYGETCD1400VER new ioctl).
- *
- * Revision 2.1.1.1  1997/12/03 17:31:19 ivan
- * Code review for the module cleanup routine;
- * fixed RTS and DTR status report for new CD1400's in get_modem_info;
- * includes anonymous changes regarding signal_pending.
- *
- * Revision 2.1  1997/11/01 17:42:41 ivan
- * Changes in the driver to support Alpha systems (except 8Zo V_1);
- * BREAK fix for the Cyclades-Z boards;
- * driver inactivity control by FW implemented;
- * introduction of flag that allows driver to take advantage of
- * a special CD1400 feature related to HW flow control;
- * added support for the CD1400  rev. J (Cyclom-Y boards);
- * introduction of ioctls to:
- *  - control the rtsdtr_inv flag (Cyclom-Y);
- *  - control the rflow flag (Cyclom-Y);
- *  - adjust the polling interval (Cyclades-Z);
- *
- * Revision 1.36.4.33  1997/06/27 19:00:00  ivan
- * Fixes related to kernel version conditional
- * compilation.
- *
- * Revision 1.36.4.32  1997/06/14 19:30:00  ivan
- * Compatibility issues between kernels 2.0.x and
- * 2.1.x (mainly related to clear_bit function).
- *
- * Revision 1.36.4.31  1997/06/03 15:30:00  ivan
- * Changes to define the memory window according to the
- * board type.
- *
- * Revision 1.36.4.30  1997/05/16 15:30:00  daniel
- * Changes to support new cycladesZ boards.
- *
- * Revision 1.36.4.29  1997/05/12 11:30:00  daniel
- * Merge of Bentson's and Daniel's version 1.36.4.28.
- * Corrects bug in cy_detect_pci: check if there are more
- * ports than the number of static structs allocated.
- * Warning message during initialization if this driver is
- * used with the new generation of cycladesZ boards.  Those
- * will be supported only in next release of the driver.
- * Corrects bug in cy_detect_pci and cy_detect_isa that
- * returned wrong number of VALID boards, when a cyclomY
- * was found with no serial modules connected.
- * Changes to use current (2.1.x) kernel subroutine names
- * and created macros for compilation with 2.0.x kernel,
- * instead of the other way around.
- *
- * Revision 1.36.4.28  1997/05/?? ??:00:00  bentson
- * Change queue_task_irq_off to queue_task_irq.
- * The inline function queue_task_irq_off (tqueue.h)
- * was removed from latest releases of 2.1.x kernel.
- * Use of macro __init to mark the initialization
- * routines, so memory can be reused.
- * Also incorporate implementation of critical region
- * in function cleanup_module() created by anonymous
- * linuxer.
- *
- * Revision 1.36.4.28  1997/04/25 16:00:00  daniel
- * Change to support new firmware that solves DCD problem:
- * application could fail to receive SIGHUP signal when DCD
- * varying too fast.
- *
- * Revision 1.36.4.27  1997/03/26 10:30:00  daniel
- * Changed for support linux versions 2.1.X.
- * Backward compatible with linux versions 2.0.X.
- * Corrected illegal use of filler field in
- * CH_CTRL struct.
- * Deleted some debug messages.
- *
- * Revision 1.36.4.26  1997/02/27 12:00:00  daniel
- * Included check for NULL tty pointer in cyz_poll.
- *
- * Revision 1.36.4.25  1997/02/26 16:28:30  bentson
- * Bill Foster at Blarg! Online services noticed that
- * some of the switch elements of -Z modem control
- * lacked a closing "break;"
- *
- * Revision 1.36.4.24  1997/02/24 11:00:00  daniel
- * Changed low water threshold for buffer xmit_buf
- *
- * Revision 1.36.4.23  1996/12/02 21:50:16  bentson
- * Marcio provided fix to modem status fetch for -Z
- *
- * Revision 1.36.4.22  1996/10/28 22:41:17  bentson
- * improve mapping of -Z control page (thanks to Steve
- * Price <stevep@fa.tdktca.com> for help on this)
- *
- * Revision 1.36.4.21  1996/09/10 17:00:10  bentson
- * shift from CPU-bound to memcopy in cyz_polling operation
- *
- * Revision 1.36.4.20  1996/09/09 18:30:32  Bentson
- * Added support to set and report higher speeds.
- *
- * Revision 1.36.4.19c  1996/08/09 10:00:00  Marcio Saito
- * Some fixes in the HW flow control for the BETA release.
- * Don't try to register the IRQ.
- *
- * Revision 1.36.4.19  1996/08/08 16:23:18  Bentson
- * make sure "cyc" appears in all kernel messages; all soft interrupts
- * handled by same routine; recognize out-of-band reception; comment
- * out some diagnostic messages; leave RTS/CTS flow control to hardware;
- * fix race condition in -Z buffer management; only -Y needs to explicitly
- * flush chars; tidy up some startup messages;
- *
- * Revision 1.36.4.18  1996/07/25 18:57:31  bentson
- * shift MOD_INC_USE_COUNT location to match
- * serial.c; purge some diagnostic messages;
- *
- * Revision 1.36.4.17  1996/07/25 18:01:08  bentson
- * enable modem status messages and fetch & process them; note
- * time of last activity type for each port; set_line_char now
- * supports more than line 0 and treats 0 baud correctly;
- * get_modem_info senses rs_status;
- *
- * Revision 1.36.4.16  1996/07/20 08:43:15  bentson
- * barely works--now's time to turn on
- * more features 'til it breaks
- *
- * Revision 1.36.4.15  1996/07/19 22:30:06  bentson
- * check more -Z board status; shorten boot message
- *
- * Revision 1.36.4.14  1996/07/19 22:20:37  bentson
- * fix reference to ch_ctrl in startup; verify return
- * values from cyz_issue_cmd and cyz_update_channel;
- * more stuff to get modem control correct;
- *
- * Revision 1.36.4.13  1996/07/11 19:53:33  bentson
- * more -Z stuff folded in; re-order changes to put -Z stuff
- * after -Y stuff (to make changes clearer)
- *
- * Revision 1.36.4.12  1996/07/11 15:40:55  bentson
- * Add code to poll Cyclades-Z.  Add code to get & set RS-232 control.
- * Add code to send break.  Clear firmware ID word at startup (so
- * that other code won't talk to inactive board).
- *
- * Revision 1.36.4.11  1996/07/09 05:28:29  bentson
- * add code for -Z in set_line_char
- *
- * Revision 1.36.4.10  1996/07/08 19:28:37  bentson
- * fold more -Z stuff (or in some cases, error messages)
- * into driver; add text to "don't know what to do" messages.
- *
- * Revision 1.36.4.9  1996/07/08 18:38:38  bentson
- * moved compile-time flags near top of file; cosmetic changes
- * to narrow text (to allow 2-up printing); changed many declarations
- * to "static" to limit external symbols; shuffled code order to
- * coalesce -Y and -Z specific code, also to put internal functions
- * in order of tty_driver structure; added code to recognize -Z
- * ports (and for moment, do nothing or report error); add cy_startup
- * to parse boot command line for extra base addresses for ISA probes;
- *
- * Revision 1.36.4.8  1996/06/25 17:40:19  bentson
- * reorder some code, fix types of some vars (int vs. long),
- * add cy_setup to support user declared ISA addresses
- *
- * Revision 1.36.4.7  1996/06/21 23:06:18  bentson
- * dump ioctl based firmware load (it's now a user level
- * program); ensure uninitialzed ports cannot be used
- *
- * Revision 1.36.4.6  1996/06/20 23:17:19  bentson
- * rename vars and restructure some code
- *
- * Revision 1.36.4.5  1996/06/14 15:09:44  bentson
- * get right status back after boot load
- *
- * Revision 1.36.4.4  1996/06/13 19:51:44  bentson
- * successfully loads firmware
- *
- * Revision 1.36.4.3  1996/06/13 06:08:33  bentson
- * add more of the code for the boot/load ioctls
- *
- * Revision 1.36.4.2  1996/06/11 21:00:51  bentson
- * start to add Z functionality--starting with ioctl
- * for loading firmware
- *
- * Revision 1.36.4.1  1996/06/10 18:03:02  bentson
- * added code to recognize Z/PCI card at initialization; report
- * presence, but card is not initialized (because firmware needs
- * to be loaded)
- *
- * Revision 1.36.3.8  1996/06/07 16:29:00  bentson
- * starting minor number at zero; added missing verify_area
- * as noted by Heiko Eißfeldt <heiko@colossus.escape.de>
- *
- * Revision 1.36.3.7  1996/04/19 21:06:18  bentson
- * remove unneeded boot message & fix CLOCAL hardware flow
- * control (Miquel van Smoorenburg <miquels@Q.cistron.nl>);
- * remove unused diagnostic statements; minor 0 is first;
- *
- * Revision 1.36.3.6  1996/03/13 13:21:17  marcio
- * The kernel function vremap (available only in later 1.3.xx kernels)
- * allows the access to memory addresses above the RAM. This revision
- * of the driver supports PCI boards below 1Mb (device id 0x100) and
- * above 1Mb (device id 0x101).
- *
- * Revision 1.36.3.5  1996/03/07 15:20:17  bentson
- * Some global changes to interrupt handling spilled into
- * this driver--mostly unused arguments in system function
- * calls.  Also added change by Marcio Saito which should
- * reduce lost interrupts at startup by fast processors.
- *
- * Revision 1.36.3.4  1995/11/13  20:45:10  bentson
- * Changes by Corey Minyard <minyard@wf-rch.cirr.com> distributed
- * in 1.3.41 kernel to remove a possible race condition, extend
- * some error messages, and let the driver run as a loadable module
- * Change by Alan Wendt <alan@ez0.ezlink.com> to remove a
- * possible race condition.
- * Change by Marcio Saito <marcio@cyclades.com> to fix PCI addressing.
- *
- * Revision 1.36.3.3  1995/11/13  19:44:48  bentson
- * Changes by Linus Torvalds in 1.3.33 kernel distribution
- * required due to reordering of driver initialization.
- * Drivers are now initialized *after* memory management.
- *
- * Revision 1.36.3.2  1995/09/08  22:07:14  bentson
- * remove printk from ISR; fix typo
- *
- * Revision 1.36.3.1  1995/09/01  12:00:42  marcio
- * Minor fixes in the PCI board support. PCI function calls in
- * conditional compilation (CONFIG_PCI). Thanks to Jim Duncan
- * <duncan@okay.com>. "bad serial count" message removed.
- *
- * Revision 1.36.3  1995/08/22  09:19:42  marcio
- * Cyclom-Y/PCI support added. Changes in the cy_init routine and
- * board initialization. Changes in the boot messages. The driver
- * supports up to 4 boards and 64 ports by default.
- *
- * Revision 1.36.1.4  1995/03/29  06:14:14  bentson
- * disambiguate between Cyclom-16Y and Cyclom-32Ye;
- *
- * Revision 1.36.1.3  1995/03/23  22:15:35  bentson
- * add missing break in modem control block in ioctl switch statement
- * (discovered by Michael Edward Chastain <mec@jobe.shell.portal.com>);
- *
- * Revision 1.36.1.2  1995/03/22  19:16:22  bentson
- * make sure CTS flow control is set as soon as possible (thanks
- * to note from David Lambert <lambert@chesapeake.rps.slb.com>);
- *
- * Revision 1.36.1.1  1995/03/13  15:44:43  bentson
- * initialize defaults for receive threshold and stale data timeout;
- * cosmetic changes;
- *
- * Revision 1.36  1995/03/10  23:33:53  bentson
- * added support of chips 4-7 in 32 port Cyclom-Ye;
- * fix cy_interrupt pointer dereference problem
- * (Joe Portman <baron@aa.net>);
- * give better error response if open is attempted on non-existent port
- * (Zachariah Vaum <jchryslr@netcom.com>);
- * correct command timeout (Kenneth Lerman <lerman@@seltd.newnet.com>);
- * conditional compilation for -16Y on systems with fast, noisy bus;
- * comment out diagnostic print function;
- * cleaned up table of base addresses;
- * set receiver time-out period register to correct value,
- * set receive threshold to better default values,
- * set chip timer to more accurate 200 Hz ticking,
- * add code to monitor and modify receive parameters
- * (Rik Faith <faith@cs.unc.edu> Nick Simicich
- * <njs@scifi.emi.net>);
- *
- * Revision 1.35  1994/12/16  13:54:18  steffen
- * additional patch by Marcio Saito for board detection
- * Accidently left out in 1.34
- *
- * Revision 1.34  1994/12/10  12:37:12  steffen
- * This is the corrected version as suggested by Marcio Saito
- *
- * Revision 1.33  1994/12/01  22:41:18  bentson
- * add hooks to support more high speeds directly; add tytso
- * patch regarding CLOCAL wakeups
- *
- * Revision 1.32  1994/11/23  19:50:04  bentson
- * allow direct kernel control of higher signalling rates;
- * look for cards at additional locations
- *
- * Revision 1.31  1994/11/16  04:33:28  bentson
- * ANOTHER fix from Corey Minyard, minyard@wf-rch.cirr.com--
- * a problem in chars_in_buffer has been resolved by some
- * small changes;  this should yield smoother output
- *
- * Revision 1.30  1994/11/16  04:28:05  bentson
- * Fix from Corey Minyard, Internet: minyard@metronet.com,
- * UUCP: minyard@wf-rch.cirr.com, WORK: minyardbnr.ca, to
- * cy_hangup that appears to clear up much (all?) of the
- * DTR glitches; also he's added/cleaned-up diagnostic messages
- *
- * Revision 1.29  1994/11/16  04:16:07  bentson
- * add change proposed by Ralph Sims, ralphs@halcyon.com, to
- * operate higher speeds in same way as other serial ports;
- * add more serial ports (for up to two 16-port muxes).
- *
- * Revision 1.28  1994/11/04  00:13:16  root
- * turn off diagnostic messages
- *
- * Revision 1.27  1994/11/03  23:46:37  root
- * bunch of changes to bring driver into greater conformance
- * with the serial.c driver (looking for missed fixes)
- *
- * Revision 1.26  1994/11/03  22:40:36  root
- * automatic interrupt probing fixed.
- *
- * Revision 1.25  1994/11/03  20:17:02  root
- * start to implement auto-irq
- *
- * Revision 1.24  1994/11/03  18:01:55  root
- * still working on modem signals--trying not to drop DTR
- * during the getty/login processes
- *
- * Revision 1.23  1994/11/03  17:51:36  root
- * extend baud rate support; set receive threshold as function
- * of baud rate; fix some problems with RTS/CTS;
- *
- * Revision 1.22  1994/11/02  18:05:35  root
- * changed arguments to udelay to type long to get
- * delays to be of correct duration
- *
- * Revision 1.21  1994/11/02  17:37:30  root
- * employ udelay (after calibrating loops_per_second earlier
- * in init/main.c) instead of using home-grown delay routines
- *
- * Revision 1.20  1994/11/02  03:11:38  root
- * cy_chars_in_buffer forces a return value of 0 to let
- * login work (don't know why it does); some functions
- * that were returning EFAULT, now executes the code;
- * more work on deciding when to disable xmit interrupts;
- *
- * Revision 1.19  1994/11/01  20:10:14  root
- * define routine to start transmission interrupts (by enabling
- * transmit interrupts); directly enable/disable modem interrupts;
- *
- * Revision 1.18  1994/11/01  18:40:45  bentson
- * Don't always enable transmit interrupts in startup; interrupt on
- * TxMpty instead of TxRdy to help characters get out before shutdown;
- * restructure xmit interrupt to check for chars first and quit if
- * none are ready to go; modem status (MXVRx) is upright, _not_ inverted
- * (to my view);
- *
- * Revision 1.17  1994/10/30  04:39:45  bentson
- * rename serial_driver and callout_driver to cy_serial_driver and
- * cy_callout_driver to avoid linkage interference; initialize
- * info->type to PORT_CIRRUS; ruggedize paranoia test; elide ->port
- * from cyclades_port structure; add paranoia check to cy_close;
- *
- * Revision 1.16  1994/10/30  01:14:33  bentson
- * change major numbers; add some _early_ return statements;
- *
- * Revision 1.15  1994/10/29  06:43:15  bentson
- * final tidying up for clean compile;  enable some error reporting
- *
- * Revision 1.14  1994/10/28  20:30:22  Bentson
- * lots of changes to drag the driver towards the new tty_io
- * structures and operation.  not expected to work, but may
- * compile cleanly.
- *
- * Revision 1.13  1994/07/21  23:08:57  Bentson
- * add some diagnostic cruft; support 24 lines (for testing
- * both -8Y and -16Y cards; be more thorough in servicing all
- * chips during interrupt; add "volatile" a few places to
- * circumvent compiler optimizations; fix base & offset
- * computations in block_til_ready (was causing chip 0 to
- * stop operation)
- *
- * Revision 1.12  1994/07/19  16:42:11  Bentson
- * add some hackery for kernel version 1.1.8; expand
- * error messages; refine timing for delay loops and
- * declare loop params volatile
- *
- * Revision 1.11  1994/06/11  21:53:10  bentson
- * get use of save_car right in transmit interrupt service
- *
- * Revision 1.10.1.1  1994/06/11  21:31:18  bentson
- * add some diagnostic printing; try to fix save_car stuff
- *
- * Revision 1.10  1994/06/11  20:36:08  bentson
- * clean up compiler warnings
- *
- * Revision 1.9  1994/06/11  19:42:46  bentson
- * added a bunch of code to support modem signalling
- *
- * Revision 1.8  1994/06/11  17:57:07  bentson
- * recognize break & parity error
- *
- * Revision 1.7  1994/06/05  05:51:34  bentson
- * Reorder baud table to be monotonic; add cli to CP; discard
- * incoming characters and status if the line isn't open; start to
- * fold code into cy_throttle; start to port get_serial_info,
- * set_serial_info, get_modem_info, set_modem_info, and send_break
- * from serial.c; expand cy_ioctl; relocate and expand config_setup;
- * get flow control characters from tty struct; invalidate ports w/o
- * hardware;
- *
- * Revision 1.6  1994/05/31  18:42:21  bentson
- * add a loop-breaker in the interrupt service routine;
- * note when port is initialized so that it can be shut
- * down under the right conditions; receive works without
- * any obvious errors
- *
- * Revision 1.5  1994/05/30  00:55:02  bentson
- * transmit works without obvious errors
- *
- * Revision 1.4  1994/05/27  18:46:27  bentson
- * incorporated more code from lib_y.c; can now print short
- * strings under interrupt control to port zero; seems to
- * select ports/channels/lines correctly
- *
- * Revision 1.3  1994/05/25  22:12:44  bentson
- * shifting from multi-port on a card to proper multiplexor
- * data structures;  added skeletons of most routines
- *
- * Revision 1.2  1994/05/19  13:21:43  bentson
- * start to crib from other sources
- *
  */
 
-#define CY_VERSION	"2.5"
+#define CY_VERSION	"2.6"
 
 /* If you need to install more boards than NR_CARDS, change the constant
    in the definition below. No other change is necessary to support up to
@@ -647,9 +79,7 @@
 #include <linux/firmware.h>
 #include <linux/device.h>
 
-#include <asm/system.h>
 #include <linux/io.h>
-#include <asm/irq.h>
 #include <linux/uaccess.h>
 
 #include <linux/kernel.h>
@@ -665,7 +95,6 @@ static void cy_send_xchar(struct tty_struct *tty, char ch);
 #ifndef SERIAL_XMIT_SIZE
 #define	SERIAL_XMIT_SIZE	(min(PAGE_SIZE, 4096))
 #endif
-#define WAKEUP_CHARS		256
 
 #define STD_COM_FLAGS (0)
 
@@ -715,7 +144,7 @@ static struct tty_driver *cy_serial_driver;
    causing problems, remove the offending address from this table.
 */
 
-static unsigned int cy_isa_addresses[] = {
+static const unsigned int cy_isa_addresses[] = {
 	0xD0000,
 	0xD2000,
 	0xD4000,
@@ -755,25 +184,25 @@ static int cy_next_channel;	/* next minor available */
  *                                               HI            VHI
  *     20
  */
-static int baud_table[] = {
+static const int baud_table[] = {
 	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
 	1800, 2400, 4800, 9600, 19200, 38400, 57600, 76800, 115200, 150000,
 	230400, 0
 };
 
-static char baud_co_25[] = {	/* 25 MHz clock option table */
+static const char baud_co_25[] = {	/* 25 MHz clock option table */
 	/* value =>    00    01   02    03    04 */
 	/* divide by    8    32   128   512  2048 */
 	0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02,
 	0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 };
 
-static char baud_bpr_25[] = {	/* 25 MHz baud rate period table */
+static const char baud_bpr_25[] = {	/* 25 MHz baud rate period table */
 	0x00, 0xf5, 0xa3, 0x6f, 0x5c, 0x51, 0xf5, 0xa3, 0x51, 0xa3,
 	0x6d, 0x51, 0xa3, 0x51, 0xa3, 0x51, 0x36, 0x29, 0x1b, 0x15
 };
 
-static char baud_co_60[] = {	/* 60 MHz clock option table (CD1400 J) */
+static const char baud_co_60[] = {	/* 60 MHz clock option table (CD1400 J) */
 	/* value =>    00    01   02    03    04 */
 	/* divide by    8    32   128   512  2048 */
 	0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03,
@@ -781,13 +210,13 @@ static char baud_co_60[] = {	/* 60 MHz clock option table (CD1400 J) */
 	0x00
 };
 
-static char baud_bpr_60[] = {	/* 60 MHz baud rate period table (CD1400 J) */
+static const char baud_bpr_60[] = {	/* 60 MHz baud rate period table (CD1400 J) */
 	0x00, 0x82, 0x21, 0xff, 0xdb, 0xc3, 0x92, 0x62, 0xc3, 0x62,
 	0x41, 0xc3, 0x62, 0xc3, 0x62, 0xc3, 0x82, 0x62, 0x41, 0x32,
 	0x21
 };
 
-static char baud_cor3[] = {	/* receive threshold */
+static const char baud_cor3[] = {	/* receive threshold */
 	0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
 	0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x07,
 	0x07
@@ -804,7 +233,7 @@ static char baud_cor3[] = {	/* receive threshold */
  * cables.
  */
 
-static char rflow_thr[] = {	/* rflow threshold */
+static const char rflow_thr[] = {	/* rflow threshold */
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 	0x00, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
 	0x0a
@@ -826,7 +255,7 @@ static const unsigned int cy_chip_offset[] = { 0x0000,
 /* PCI related definitions */
 
 #ifdef CONFIG_PCI
-static struct pci_device_id cy_pci_dev_id[] __devinitdata = {
+static const struct pci_device_id cy_pci_dev_id[] = {
 	/* PCI < 1Mb */
 	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Y_Lo) },
 	/* PCI > 1Mb */
@@ -892,7 +321,7 @@ static inline bool cyz_is_loaded(struct cyclades_card *card)
 }
 
 static inline int serial_paranoia_check(struct cyclades_port *info,
-		char *name, const char *routine)
+		const char *name, const char *routine)
 {
 #ifdef SERIAL_PARANOIA_CHECK
 	if (!info) {
@@ -908,7 +337,7 @@ static inline int serial_paranoia_check(struct cyclades_port *info,
 	}
 #endif
 	return 0;
-}				/* serial_paranoia_check */
+}
 
 /***********************************************************/
 /********* Start of block of Cyclom-Y specific code ********/
@@ -3029,11 +2458,9 @@ cy_set_serial_info(struct cyclades_port *info, struct tty_struct *tty,
 		struct serial_struct __user *new_info)
 {
 	struct serial_struct new_serial;
-	struct cyclades_port old_info;
 
 	if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
 		return -EFAULT;
-	old_info = *info;
 
 	if (!capable(CAP_SYS_ADMIN)) {
 		if (new_serial.close_delay != info->port.close_delay ||
@@ -3375,7 +2802,6 @@ static int cy_break(struct tty_struct *tty, int break_state)
 static int get_mon_info(struct cyclades_port *info,
 				struct cyclades_monitor __user *mon)
 {
-
 	if (copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor)))
 		return -EFAULT;
 	info->mon.int_count = 0;
-- 
1.6.3.2


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

* [PATCH 07/13] Char: cyclades, sleep instead busy-wait
  2009-06-18  7:41 [PATCH 01/13] Char: cyclades, add tty refcounting Jiri Slaby
                   ` (4 preceding siblings ...)
  2009-06-18  7:41 ` [PATCH 06/13] Char: cyclades, overall cleanup Jiri Slaby
@ 2009-06-18  7:41 ` Jiri Slaby
  2009-06-18  7:41 ` [PATCH 08/13] Char: cyclades, use dtr_rts helpers Jiri Slaby
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Jiri Slaby @ 2009-06-18  7:41 UTC (permalink / raw)
  To: alan; +Cc: Andrew Morton, linux-kernel, Jiri Slaby

Avoid long busy loops (5 ms) which may be replaced by sleeps.

Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
---
 drivers/char/cyclades.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index 1510506..1fca273 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -388,7 +388,7 @@ static unsigned detect_isa_irq(void __iomem *address)
 
 	irqs = probe_irq_on();
 	/* Wait ... */
-	udelay(5000L);
+	msleep(5);
 
 	/* Enable the Tx interrupts on the CD1400 */
 	local_irq_save(flags);
@@ -401,7 +401,7 @@ static unsigned detect_isa_irq(void __iomem *address)
 	local_irq_restore(flags);
 
 	/* Wait ... */
-	udelay(5000L);
+	msleep(5);
 
 	/* Check which interrupt is in use */
 	irq = probe_irq_off(irqs);
-- 
1.6.3.2


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

* [PATCH 08/13] Char: cyclades, use dtr_rts helpers
  2009-06-18  7:41 [PATCH 01/13] Char: cyclades, add tty refcounting Jiri Slaby
                   ` (5 preceding siblings ...)
  2009-06-18  7:41 ` [PATCH 07/13] Char: cyclades, sleep instead busy-wait Jiri Slaby
@ 2009-06-18  7:41 ` Jiri Slaby
  2009-06-18  7:41 ` [PATCH 09/13] Char: cyclades, merge cy_startup tails Jiri Slaby
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Jiri Slaby @ 2009-06-18  7:41 UTC (permalink / raw)
  To: alan; +Cc: Andrew Morton, linux-kernel, Jiri Slaby

For Z cards, use tty helpers for dtr_rts.

If we did the same for Y cards, it will cause a deadlock, because
cyy_dtr_rts takes a lock which we already hold.

Instead, we introduce an Y helper expecting card lock to be held.
It may then be called with set/clear masks from other places.

Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
---
 drivers/char/cyclades.c |  280 +++++++++++++---------------------------------
 1 files changed, 79 insertions(+), 201 deletions(-)

diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index 1fca273..bad3010 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -824,6 +824,66 @@ static irqreturn_t cyy_interrupt(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }				/* cyy_interrupt */
 
+static void cyy_change_rts_dtr(struct cyclades_port *info, unsigned int set,
+		unsigned int clear)
+{
+	struct cyclades_card *card = info->card;
+	void __iomem *base_addr;
+	int chip, channel, index;
+
+	channel = info->line - card->first_line;
+	chip = channel >> 2;
+	channel &= 0x03;
+	index = card->bus_index;
+	base_addr = card->base_addr + (cy_chip_offset[chip] << index);
+
+	if (set & TIOCM_RTS) {
+		cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
+		if (info->rtsdtr_inv) {
+			cy_writeb(base_addr + (CyMSVR2 << index), CyDTR);
+		} else {
+			cy_writeb(base_addr + (CyMSVR1 << index), CyRTS);
+		}
+	}
+	if (clear & TIOCM_RTS) {
+		cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
+		if (info->rtsdtr_inv) {
+			cy_writeb(base_addr + (CyMSVR2 << index), ~CyDTR);
+		} else {
+			cy_writeb(base_addr + (CyMSVR1 << index), ~CyRTS);
+		}
+	}
+	if (set & TIOCM_DTR) {
+		cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
+		if (info->rtsdtr_inv) {
+			cy_writeb(base_addr + (CyMSVR1 << index), CyRTS);
+		} else {
+			cy_writeb(base_addr + (CyMSVR2 << index), CyDTR);
+		}
+#ifdef CY_DEBUG_DTR
+		printk(KERN_DEBUG "cyc:set_modem_info raising DTR\n");
+		printk(KERN_DEBUG "     status: 0x%x, 0x%x\n",
+			readb(base_addr + (CyMSVR1 << index)),
+			readb(base_addr + (CyMSVR2 << index)));
+#endif
+	}
+	if (clear & TIOCM_DTR) {
+		cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
+		if (info->rtsdtr_inv) {
+			cy_writeb(base_addr + (CyMSVR1 << index), ~CyRTS);
+		} else {
+			cy_writeb(base_addr + (CyMSVR2 << index), ~CyDTR);
+		}
+
+#ifdef CY_DEBUG_DTR
+		printk(KERN_DEBUG "cyc:set_modem_info dropping DTR\n");
+		printk(KERN_DEBUG "     status: 0x%x, 0x%x\n",
+			readb(base_addr + (CyMSVR1 << index)),
+			readb(base_addr + (CyMSVR2 << index)));
+#endif
+	}
+}
+
 /***********************************************************/
 /********* End of block of Cyclom-Y specific code **********/
 /******** Start of block of Cyclades-Z specific code *******/
@@ -1289,16 +1349,7 @@ static int cy_startup(struct cyclades_port *info, struct tty_struct *tty)
 		cyy_issue_cmd(base_addr, CyCHAN_CTL | CyENB_RCVR | CyENB_XMTR,
 				index);
 
-		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:startup raising DTR\n");
-		printk(KERN_DEBUG "     status: 0x%x, 0x%x\n",
-			readb(base_addr + (CyMSVR1 << index)),
-			readb(base_addr + (CyMSVR2 << index)));
-#endif
+		cyy_change_rts_dtr(info, TIOCM_RTS | TIOCM_DTR, 0);
 
 		cy_writeb(base_addr + (CySRER << index),
 			readb(base_addr + (CySRER << index)) | CyRxData);
@@ -1361,16 +1412,7 @@ static int cy_startup(struct cyclades_port *info, struct tty_struct *tty)
 
 		/* set timeout !!! */
 		/* set RTS and DTR !!! */
-		cy_writel(&ch_ctrl->rs_control, readl(&ch_ctrl->rs_control) |
-				C_RS_RTS | C_RS_DTR);
-		retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L);
-		if (retval != 0) {
-			printk(KERN_ERR "cyc:startup(3) retval on ttyC%d was "
-				"%x\n", info->line, retval);
-		}
-#ifdef CY_DEBUG_DTR
-		printk(KERN_DEBUG "cyc:startup raising Z DTR\n");
-#endif
+		tty_port_raise_dtr_rts(&info->port);
 
 		/* enable send, recv, modem !!! */
 
@@ -1472,17 +1514,9 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty)
 			info->port.xmit_buf = NULL;
 			free_page((unsigned long)temp);
 		}
-		cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
-		if (tty->termios->c_cflag & HUPCL) {
-			cy_writeb(base_addr + (CyMSVR1 << index), ~CyRTS);
-			cy_writeb(base_addr + (CyMSVR2 << index), ~CyDTR);
-#ifdef CY_DEBUG_DTR
-			printk(KERN_DEBUG "cyc shutdown dropping DTR\n");
-			printk(KERN_DEBUG "     status: 0x%x, 0x%x\n",
-				readb(base_addr + (CyMSVR1 << index)),
-				readb(base_addr + (CyMSVR2 << index)));
-#endif
-		}
+		if (tty->termios->c_cflag & HUPCL)
+			cyy_change_rts_dtr(info, 0, TIOCM_RTS | TIOCM_DTR);
+
 		cyy_issue_cmd(base_addr, CyCHAN_CTL | CyDIS_RCVR, index);
 		/* it may be appropriate to clear _XMIT at
 		   some later date (after testing)!!! */
@@ -1491,9 +1525,6 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty)
 		info->port.flags &= ~ASYNC_INITIALIZED;
 		spin_unlock_irqrestore(&card->card_lock, flags);
 	} else {
-		struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
-		int retval;
-
 #ifdef CY_DEBUG_OPEN
 		printk(KERN_DEBUG "cyc shutdown Z card %d, channel %d, "
 			"base_addr %p\n", card, channel, card->base_addr);
@@ -1511,20 +1542,8 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty)
 			free_page((unsigned long)temp);
 		}
 
-		if (tty->termios->c_cflag & HUPCL) {
-			cy_writel(&ch_ctrl->rs_control,
-				readl(&ch_ctrl->rs_control) &
-					~(C_RS_RTS | C_RS_DTR));
-			retval = cyz_issue_cmd(info->card, channel,
-					C_CM_IOCTLM, 0L);
-			if (retval != 0) {
-				printk(KERN_ERR"cyc:shutdown retval on ttyC%d "
-					"was %x\n", info->line, retval);
-			}
-#ifdef CY_DEBUG_DTR
-			printk(KERN_DEBUG "cyc:shutdown dropping Z DTR\n");
-#endif
-		}
+		if (tty->termios->c_cflag & HUPCL)
+			tty_port_lower_dtr_rts(&info->port);
 
 		set_bit(TTY_IO_ERROR, &tty->flags);
 		info->port.flags &= ~ASYNC_INITIALIZED;
@@ -2272,35 +2291,10 @@ static void cy_set_line_char(struct cyclades_port *info, struct tty_struct *tty)
 				  CyDSR | CyCTS | CyRI | CyDCD);
 		}
 
-		if (i == 0) {	/* baud rate is zero, turn off line */
-			if (info->rtsdtr_inv) {
-				cy_writeb(base_addr + (CyMSVR1 << index),
-					  ~CyRTS);
-			} else {
-				cy_writeb(base_addr + (CyMSVR2 << index),
-					  ~CyDTR);
-			}
-#ifdef CY_DEBUG_DTR
-			printk(KERN_DEBUG "cyc:set_line_char dropping DTR\n");
-			printk(KERN_DEBUG "     status: 0x%x, 0x%x\n",
-				readb(base_addr + (CyMSVR1 << index)),
-				readb(base_addr + (CyMSVR2 << index)));
-#endif
-		} else {
-			if (info->rtsdtr_inv) {
-				cy_writeb(base_addr + (CyMSVR1 << index),
-					  CyRTS);
-			} else {
-				cy_writeb(base_addr + (CyMSVR2 << index),
-					  CyDTR);
-			}
-#ifdef CY_DEBUG_DTR
-			printk(KERN_DEBUG "cyc:set_line_char raising DTR\n");
-			printk(KERN_DEBUG "     status: 0x%x, 0x%x\n",
-				readb(base_addr + (CyMSVR1 << index)),
-				readb(base_addr + (CyMSVR2 << index)));
-#endif
-		}
+		if (i == 0)	/* baud rate is zero, turn off line */
+			cyy_change_rts_dtr(info, 0, TIOCM_DTR);
+		else
+			cyy_change_rts_dtr(info, TIOCM_DTR, 0);
 
 		clear_bit(TTY_IO_ERROR, &tty->flags);
 		spin_unlock_irqrestore(&card->card_lock, flags);
@@ -2603,9 +2597,8 @@ cy_tiocmset(struct tty_struct *tty, struct file *file,
 {
 	struct cyclades_port *info = tty->driver_data;
 	struct cyclades_card *card;
-	int chip, channel, index;
 	unsigned long flags;
-	int retval;
+	int channel, retval;
 
 	if (serial_paranoia_check(info, tty->name, __func__))
 		return -ENODEV;
@@ -2613,77 +2606,9 @@ cy_tiocmset(struct tty_struct *tty, struct file *file,
 	card = info->card;
 	channel = (info->line) - (card->first_line);
 	if (!cy_is_Z(card)) {
-		void __iomem *base_addr;
-		chip = channel >> 2;
-		channel &= 0x03;
-		index = card->bus_index;
-		base_addr = card->base_addr + (cy_chip_offset[chip] << index);
-
-		if (set & TIOCM_RTS) {
-			spin_lock_irqsave(&card->card_lock, flags);
-			cy_writeb(base_addr + (CyCAR << index),
-				  (u_char) channel);
-			if (info->rtsdtr_inv) {
-				cy_writeb(base_addr + (CyMSVR2 << index),
-					  CyDTR);
-			} else {
-				cy_writeb(base_addr + (CyMSVR1 << index),
-					  CyRTS);
-			}
-			spin_unlock_irqrestore(&card->card_lock, flags);
-		}
-		if (clear & TIOCM_RTS) {
-			spin_lock_irqsave(&card->card_lock, flags);
-			cy_writeb(base_addr + (CyCAR << index),
-				  (u_char) channel);
-			if (info->rtsdtr_inv) {
-				cy_writeb(base_addr + (CyMSVR2 << index),
-					  ~CyDTR);
-			} else {
-				cy_writeb(base_addr + (CyMSVR1 << index),
-					  ~CyRTS);
-			}
-			spin_unlock_irqrestore(&card->card_lock, flags);
-		}
-		if (set & TIOCM_DTR) {
-			spin_lock_irqsave(&card->card_lock, flags);
-			cy_writeb(base_addr + (CyCAR << index),
-				  (u_char) channel);
-			if (info->rtsdtr_inv) {
-				cy_writeb(base_addr + (CyMSVR1 << index),
-					  CyRTS);
-			} else {
-				cy_writeb(base_addr + (CyMSVR2 << index),
-					  CyDTR);
-			}
-#ifdef CY_DEBUG_DTR
-			printk(KERN_DEBUG "cyc:set_modem_info 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(&card->card_lock, flags);
-		}
-		if (clear & TIOCM_DTR) {
-			spin_lock_irqsave(&card->card_lock, flags);
-			cy_writeb(base_addr + (CyCAR << index),
-				  (u_char) channel);
-			if (info->rtsdtr_inv) {
-				cy_writeb(base_addr + (CyMSVR1 << index),
-					  ~CyRTS);
-			} else {
-				cy_writeb(base_addr + (CyMSVR2 << index),
-					  ~CyDTR);
-			}
-
-#ifdef CY_DEBUG_DTR
-			printk(KERN_DEBUG "cyc:set_modem_info dropping 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(&card->card_lock, flags);
-		}
+		spin_lock_irqsave(&card->card_lock, flags);
+		cyy_change_rts_dtr(info, set, clear);
+		spin_unlock_irqrestore(&card->card_lock, flags);
 	} else {
 		if (cyz_is_loaded(card)) {
 			struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
@@ -3176,8 +3101,6 @@ static void cy_throttle(struct tty_struct *tty)
 	struct cyclades_port *info = tty->driver_data;
 	struct cyclades_card *card;
 	unsigned long flags;
-	void __iomem *base_addr;
-	int chip, channel, index;
 
 #ifdef CY_DEBUG_THROTTLE
 	char buf[64];
@@ -3199,24 +3122,9 @@ static void cy_throttle(struct tty_struct *tty)
 	}
 
 	if (tty->termios->c_cflag & CRTSCTS) {
-		channel = info->line - card->first_line;
 		if (!cy_is_Z(card)) {
-			chip = channel >> 2;
-			channel &= 0x03;
-			index = card->bus_index;
-			base_addr = card->base_addr +
-				(cy_chip_offset[chip] << index);
-
 			spin_lock_irqsave(&card->card_lock, flags);
-			cy_writeb(base_addr + (CyCAR << index),
-				  (u_char) channel);
-			if (info->rtsdtr_inv) {
-				cy_writeb(base_addr + (CyMSVR2 << index),
-					  ~CyDTR);
-			} else {
-				cy_writeb(base_addr + (CyMSVR1 << index),
-					  ~CyRTS);
-			}
+			cyy_change_rts_dtr(info, 0, TIOCM_RTS);
 			spin_unlock_irqrestore(&card->card_lock, flags);
 		} else {
 			info->throttle = 1;
@@ -3234,8 +3142,6 @@ static void cy_unthrottle(struct tty_struct *tty)
 	struct cyclades_port *info = tty->driver_data;
 	struct cyclades_card *card;
 	unsigned long flags;
-	void __iomem *base_addr;
-	int chip, channel, index;
 
 #ifdef CY_DEBUG_THROTTLE
 	char buf[64];
@@ -3256,24 +3162,9 @@ static void cy_unthrottle(struct tty_struct *tty)
 
 	if (tty->termios->c_cflag & CRTSCTS) {
 		card = info->card;
-		channel = info->line - card->first_line;
 		if (!cy_is_Z(card)) {
-			chip = channel >> 2;
-			channel &= 0x03;
-			index = card->bus_index;
-			base_addr = card->base_addr +
-				(cy_chip_offset[chip] << index);
-
 			spin_lock_irqsave(&card->card_lock, flags);
-			cy_writeb(base_addr + (CyCAR << index),
-				  (u_char) channel);
-			if (info->rtsdtr_inv) {
-				cy_writeb(base_addr + (CyMSVR2 << index),
-					  CyDTR);
-			} else {
-				cy_writeb(base_addr + (CyMSVR1 << index),
-					  CyRTS);
-			}
+			cyy_change_rts_dtr(info, TIOCM_RTS, 0);
 			spin_unlock_irqrestore(&card->card_lock, flags);
 		} else {
 			info->throttle = 0;
@@ -3394,24 +3285,11 @@ 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
+	cyy_change_rts_dtr(info, raise ? TIOCM_RTS | TIOCM_DTR : 0,
+			raise ? 0 : TIOCM_RTS | TIOCM_DTR);
 	spin_unlock_irqrestore(&cinfo->card_lock, flags);
 }
 
-- 
1.6.3.2


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

* [PATCH 09/13] Char: cyclades, merge cy_startup tails
  2009-06-18  7:41 [PATCH 01/13] Char: cyclades, add tty refcounting Jiri Slaby
                   ` (6 preceding siblings ...)
  2009-06-18  7:41 ` [PATCH 08/13] Char: cyclades, use dtr_rts helpers Jiri Slaby
@ 2009-06-18  7:41 ` Jiri Slaby
  2009-06-18  7:41 ` [PATCH 10/13] Char: cyclades, ioctls cleanup Jiri Slaby
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Jiri Slaby @ 2009-06-18  7:41 UTC (permalink / raw)
  To: alan; +Cc: Andrew Morton, linux-kernel, Jiri Slaby

There is a duplicated code for Y and Z in cy_startup, merge the paths.

Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
---
 drivers/char/cyclades.c |   45 ++++++++++++++++-----------------------------
 1 files changed, 16 insertions(+), 29 deletions(-)

diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index bad3010..5dd176d 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -1295,7 +1295,7 @@ static int cy_startup(struct cyclades_port *info, struct tty_struct *tty)
 	unsigned long flags;
 	int retval = 0;
 	void __iomem *base_addr;
-	int chip, channel, index;
+	int channel;
 	unsigned long page;
 
 	card = info->card;
@@ -1307,14 +1307,11 @@ static int cy_startup(struct cyclades_port *info, struct tty_struct *tty)
 
 	spin_lock_irqsave(&card->card_lock, flags);
 
-	if (info->port.flags & ASYNC_INITIALIZED) {
-		free_page(page);
+	if (info->port.flags & ASYNC_INITIALIZED)
 		goto errout;
-	}
 
 	if (!info->type) {
 		set_bit(TTY_IO_ERROR, &tty->flags);
-		free_page(page);
 		goto errout;
 	}
 
@@ -1328,9 +1325,9 @@ static int cy_startup(struct cyclades_port *info, struct tty_struct *tty)
 	cy_set_line_char(info, tty);
 
 	if (!cy_is_Z(card)) {
-		chip = channel >> 2;
+		int chip = channel >> 2;
+		int index = card->bus_index;
 		channel &= 0x03;
-		index = card->bus_index;
 		base_addr = card->base_addr + (cy_chip_offset[chip] << index);
 
 #ifdef CY_DEBUG_OPEN
@@ -1353,18 +1350,6 @@ static int cy_startup(struct cyclades_port *info, struct tty_struct *tty)
 
 		cy_writeb(base_addr + (CySRER << index),
 			readb(base_addr + (CySRER << index)) | CyRxData);
-		info->port.flags |= ASYNC_INITIALIZED;
-
-		clear_bit(TTY_IO_ERROR, &tty->flags);
-		info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-		info->breakon = info->breakoff = 0;
-		memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats));
-		info->idle_stats.in_use =
-		info->idle_stats.recv_idle =
-		info->idle_stats.xmit_idle = jiffies;
-
-		spin_unlock_irqrestore(&card->card_lock, flags);
-
 	} else {
 		struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
 
@@ -1415,18 +1400,19 @@ static int cy_startup(struct cyclades_port *info, struct tty_struct *tty)
 		tty_port_raise_dtr_rts(&info->port);
 
 		/* enable send, recv, modem !!! */
+	}
 
-		info->port.flags |= ASYNC_INITIALIZED;
-		clear_bit(TTY_IO_ERROR, &tty->flags);
-		info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-		info->breakon = info->breakoff = 0;
-		memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats));
-		info->idle_stats.in_use =
-		info->idle_stats.recv_idle =
-		info->idle_stats.xmit_idle = jiffies;
+	info->port.flags |= ASYNC_INITIALIZED;
 
-		spin_unlock_irqrestore(&card->card_lock, flags);
-	}
+	clear_bit(TTY_IO_ERROR, &tty->flags);
+	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+	info->breakon = info->breakoff = 0;
+	memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats));
+	info->idle_stats.in_use =
+	info->idle_stats.recv_idle =
+	info->idle_stats.xmit_idle = jiffies;
+
+	spin_unlock_irqrestore(&card->card_lock, flags);
 
 #ifdef CY_DEBUG_OPEN
 	printk(KERN_DEBUG "cyc startup done\n");
@@ -1435,6 +1421,7 @@ static int cy_startup(struct cyclades_port *info, struct tty_struct *tty)
 
 errout:
 	spin_unlock_irqrestore(&card->card_lock, flags);
+	free_page(page);
 	return retval;
 }				/* startup */
 
-- 
1.6.3.2


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

* [PATCH 10/13] Char: cyclades, ioctls cleanup
  2009-06-18  7:41 [PATCH 01/13] Char: cyclades, add tty refcounting Jiri Slaby
                   ` (7 preceding siblings ...)
  2009-06-18  7:41 ` [PATCH 09/13] Char: cyclades, merge cy_startup tails Jiri Slaby
@ 2009-06-18  7:41 ` Jiri Slaby
  2009-06-18  7:41 ` [PATCH 11/13] Char: cyclades, tiocm cleanup Jiri Slaby
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Jiri Slaby @ 2009-06-18  7:41 UTC (permalink / raw)
  To: alan; +Cc: Andrew Morton, linux-kernel, Jiri Slaby

- add a cy_ prefix to functions with changed prototypes
- cy_get_serial_info: initialize serial_struct by initializer,
  save a memset
- inline simple functions (get_mon_info, {s,g}et_default_threshold,
  {s,g}et_default_timeout) directly in the ioctl handler
- add a cy_cflags_changed helper to not copy its code by
  wait_event_interruptible
- remove some ret_val = 0 assignments, it's preset to 0
- TIOCGICOUNT: don't do many put_user's, do one copy_to_user

Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
---
 drivers/char/cyclades.c |  179 ++++++++++++++++++-----------------------------
 1 files changed, 67 insertions(+), 112 deletions(-)

diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index 5dd176d..934eebe 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -2410,29 +2410,25 @@ static void cy_set_line_char(struct cyclades_port *info, struct tty_struct *tty)
 	}
 }				/* set_line_char */
 
-static int
-get_serial_info(struct cyclades_port *info,
+static int cy_get_serial_info(struct cyclades_port *info,
 		struct serial_struct __user *retinfo)
 {
-	struct serial_struct tmp;
 	struct cyclades_card *cinfo = info->card;
-
-	if (!retinfo)
-		return -EFAULT;
-	memset(&tmp, 0, sizeof(tmp));
-	tmp.type = info->type;
-	tmp.line = info->line;
-	tmp.port = (info->card - cy_card) * 0x100 + info->line -
-		cinfo->first_line;
-	tmp.irq = cinfo->irq;
-	tmp.flags = info->port.flags;
-	tmp.close_delay = info->port.close_delay;
-	tmp.closing_wait = info->port.closing_wait;
-	tmp.baud_base = info->baud;
-	tmp.custom_divisor = info->custom_divisor;
-	tmp.hub6 = 0;		/*!!! */
+	struct serial_struct tmp = {
+		.type = info->type,
+		.line = info->line,
+		.port = (info->card - cy_card) * 0x100 + info->line -
+			cinfo->first_line,
+		.irq = cinfo->irq,
+		.flags = info->port.flags,
+		.close_delay = info->port.close_delay,
+		.closing_wait = info->port.closing_wait,
+		.baud_base = info->baud,
+		.custom_divisor = info->custom_divisor,
+		.hub6 = 0,		/*!!! */
+	};
 	return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0;
-}				/* get_serial_info */
+}
 
 static int
 cy_set_serial_info(struct cyclades_port *info, struct tty_struct *tty,
@@ -2711,18 +2707,6 @@ static int cy_break(struct tty_struct *tty, int break_state)
 	return retval;
 }				/* cy_break */
 
-static int get_mon_info(struct cyclades_port *info,
-				struct cyclades_monitor __user *mon)
-{
-	if (copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor)))
-		return -EFAULT;
-	info->mon.int_count = 0;
-	info->mon.char_count = 0;
-	info->mon.char_max = 0;
-	info->mon.char_last = 0;
-	return 0;
-}				/* get_mon_info */
-
 static int set_threshold(struct cyclades_port *info, unsigned long value)
 {
 	struct cyclades_card *card;
@@ -2772,19 +2756,6 @@ static int get_threshold(struct cyclades_port *info,
 	return 0;
 }				/* get_threshold */
 
-static int set_default_threshold(struct cyclades_port *info,
-							unsigned long value)
-{
-	info->default_threshold = value & 0x0f;
-	return 0;
-}				/* set_default_threshold */
-
-static int get_default_threshold(struct cyclades_port *info,
-						unsigned long __user *value)
-{
-	return put_user(info->default_threshold, value);
-}				/* get_default_threshold */
-
 static int set_timeout(struct cyclades_port *info, unsigned long value)
 {
 	struct cyclades_card *card;
@@ -2829,17 +2800,26 @@ static int get_timeout(struct cyclades_port *info,
 	return 0;
 }				/* get_timeout */
 
-static int set_default_timeout(struct cyclades_port *info, unsigned long value)
+static int cy_cflags_changed(struct cyclades_port *info, unsigned long arg,
+		struct cyclades_icount *cprev)
 {
-	info->default_timeout = value & 0xff;
-	return 0;
-}				/* set_default_timeout */
+	struct cyclades_icount cnow;
+	unsigned long flags;
+	int ret;
 
-static int get_default_timeout(struct cyclades_port *info,
-					unsigned long __user *value)
-{
-	return put_user(info->default_timeout, value);
-}				/* get_default_timeout */
+	spin_lock_irqsave(&info->card->card_lock, flags);
+	cnow = info->icount;	/* atomic copy */
+	spin_unlock_irqrestore(&info->card->card_lock, flags);
+
+	ret =	((arg & TIOCM_RNG) && (cnow.rng != cprev->rng)) ||
+		((arg & TIOCM_DSR) && (cnow.dsr != cprev->dsr)) ||
+		((arg & TIOCM_CD)  && (cnow.dcd != cprev->dcd)) ||
+		((arg & TIOCM_CTS) && (cnow.cts != cprev->cts));
+
+	*cprev = cnow;
+
+	return ret;
+}
 
 /*
  * This routine allows the tty driver to implement device-
@@ -2851,8 +2831,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
 	 unsigned int cmd, unsigned long arg)
 {
 	struct cyclades_port *info = tty->driver_data;
-	struct cyclades_icount cprev, cnow;	/* kernel counter temps */
-	struct serial_icounter_struct __user *p_cuser;	/* user space */
+	struct cyclades_icount cnow;	/* kernel counter temps */
 	int ret_val = 0;
 	unsigned long flags;
 	void __user *argp = (void __user *)arg;
@@ -2868,7 +2847,11 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
 
 	switch (cmd) {
 	case CYGETMON:
-		ret_val = get_mon_info(info, argp);
+		if (copy_to_user(argp, &info->mon, sizeof(info->mon))) {
+			ret_val = -EFAULT;
+			break;
+		}
+		memset(&info->mon, 0, sizeof(info->mon));
 		break;
 	case CYGETTHRESH:
 		ret_val = get_threshold(info, argp);
@@ -2877,10 +2860,11 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
 		ret_val = set_threshold(info, arg);
 		break;
 	case CYGETDEFTHRESH:
-		ret_val = get_default_threshold(info, argp);
+		ret_val = put_user(info->default_threshold,
+				(unsigned long __user *)argp);
 		break;
 	case CYSETDEFTHRESH:
-		ret_val = set_default_threshold(info, arg);
+		info->default_threshold = arg & 0x0f;
 		break;
 	case CYGETTIMEOUT:
 		ret_val = get_timeout(info, argp);
@@ -2889,21 +2873,20 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
 		ret_val = set_timeout(info, arg);
 		break;
 	case CYGETDEFTIMEOUT:
-		ret_val = get_default_timeout(info, argp);
+		ret_val = put_user(info->default_timeout,
+				(unsigned long __user *)argp);
 		break;
 	case CYSETDEFTIMEOUT:
-		ret_val = set_default_timeout(info, arg);
+		info->default_timeout = arg & 0xff;
 		break;
 	case CYSETRFLOW:
 		info->rflow = (int)arg;
-		ret_val = 0;
 		break;
 	case CYGETRFLOW:
 		ret_val = info->rflow;
 		break;
 	case CYSETRTSDTR_INV:
 		info->rtsdtr_inv = (int)arg;
-		ret_val = 0;
 		break;
 	case CYGETRTSDTR_INV:
 		ret_val = info->rtsdtr_inv;
@@ -2914,7 +2897,6 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
 #ifndef CONFIG_CYZ_INTR
 	case CYZSETPOLLCYCLE:
 		cyz_polling_cycle = (arg * HZ) / 1000;
-		ret_val = 0;
 		break;
 	case CYZGETPOLLCYCLE:
 		ret_val = (cyz_polling_cycle * 1000) / HZ;
@@ -2922,13 +2904,12 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
 #endif				/* CONFIG_CYZ_INTR */
 	case CYSETWAIT:
 		info->port.closing_wait = (unsigned short)arg * HZ / 100;
-		ret_val = 0;
 		break;
 	case CYGETWAIT:
 		ret_val = info->port.closing_wait / (HZ / 100);
 		break;
 	case TIOCGSERIAL:
-		ret_val = get_serial_info(info, argp);
+		ret_val = cy_get_serial_info(info, argp);
 		break;
 	case TIOCSSERIAL:
 		ret_val = cy_set_serial_info(info, tty, argp);
@@ -2947,17 +2928,8 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
 		/* note the counters on entry */
 		cnow = info->icount;
 		spin_unlock_irqrestore(&info->card->card_lock, flags);
-		ret_val = wait_event_interruptible(info->delta_msr_wait, ({
-			cprev = cnow;
-			spin_lock_irqsave(&info->card->card_lock, flags);
-			cnow = info->icount;	/* atomic copy */
-			spin_unlock_irqrestore(&info->card->card_lock, flags);
-
-			((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
-			((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
-			((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
-			((arg & TIOCM_CTS) && (cnow.cts != cprev.cts));
-		}));
+		ret_val = wait_event_interruptible(info->delta_msr_wait,
+				cy_cflags_changed(info, arg, &cnow));
 		break;
 
 		/*
@@ -2966,46 +2938,29 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
 		 * NB: both 1->0 and 0->1 transitions are counted except for
 		 *     RI where only 0->1 is counted.
 		 */
-	case TIOCGICOUNT:
+	case TIOCGICOUNT: {
+		struct serial_icounter_struct sic = { };
+
 		spin_lock_irqsave(&info->card->card_lock, flags);
 		cnow = info->icount;
 		spin_unlock_irqrestore(&info->card->card_lock, flags);
-		p_cuser = argp;
-		ret_val = put_user(cnow.cts, &p_cuser->cts);
-		if (ret_val)
-			break;
-		ret_val = put_user(cnow.dsr, &p_cuser->dsr);
-		if (ret_val)
-			break;
-		ret_val = put_user(cnow.rng, &p_cuser->rng);
-		if (ret_val)
-			break;
-		ret_val = put_user(cnow.dcd, &p_cuser->dcd);
-		if (ret_val)
-			break;
-		ret_val = put_user(cnow.rx, &p_cuser->rx);
-		if (ret_val)
-			break;
-		ret_val = put_user(cnow.tx, &p_cuser->tx);
-		if (ret_val)
-			break;
-		ret_val = put_user(cnow.frame, &p_cuser->frame);
-		if (ret_val)
-			break;
-		ret_val = put_user(cnow.overrun, &p_cuser->overrun);
-		if (ret_val)
-			break;
-		ret_val = put_user(cnow.parity, &p_cuser->parity);
-		if (ret_val)
-			break;
-		ret_val = put_user(cnow.brk, &p_cuser->brk);
-		if (ret_val)
-			break;
-		ret_val = put_user(cnow.buf_overrun, &p_cuser->buf_overrun);
-		if (ret_val)
-			break;
-		ret_val = 0;
+
+		sic.cts = cnow.cts;
+		sic.dsr = cnow.dsr;
+		sic.rng = cnow.rng;
+		sic.dcd = cnow.dcd;
+		sic.rx = cnow.rx;
+		sic.tx = cnow.tx;
+		sic.frame = cnow.frame;
+		sic.overrun = cnow.overrun;
+		sic.parity = cnow.parity;
+		sic.brk = cnow.brk;
+		sic.buf_overrun = cnow.buf_overrun;
+
+		if (copy_to_user(argp, &sic, sizeof(sic)))
+			ret_val = -EFAULT;
 		break;
+	}
 	default:
 		ret_val = -ENOIOCTLCMD;
 	}
-- 
1.6.3.2


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

* [PATCH 11/13] Char: cyclades, tiocm cleanup
  2009-06-18  7:41 [PATCH 01/13] Char: cyclades, add tty refcounting Jiri Slaby
                   ` (8 preceding siblings ...)
  2009-06-18  7:41 ` [PATCH 10/13] Char: cyclades, ioctls cleanup Jiri Slaby
@ 2009-06-18  7:41 ` Jiri Slaby
  2009-06-18  7:41 ` [PATCH 12/13] Char: cyclades, introduce cyy_readb/writeb Jiri Slaby
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Jiri Slaby @ 2009-06-18  7:41 UTC (permalink / raw)
  To: alan; +Cc: Andrew Morton, linux-kernel, Jiri Slaby

- save one indent level by inverting !fw_loaded condition
- read rs_status on Z and write it after we cahnge all the flags,
  don't do that separately
- remove Y inverted rts/dtr branching, precompute registers and use
  them

Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
---
 drivers/char/cyclades.c |  153 ++++++++++++++++++++---------------------------
 1 files changed, 66 insertions(+), 87 deletions(-)

diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index 934eebe..ed9ec2c 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -830,6 +830,7 @@ static void cyy_change_rts_dtr(struct cyclades_port *info, unsigned int set,
 	struct cyclades_card *card = info->card;
 	void __iomem *base_addr;
 	int chip, channel, index;
+	u32 rts, dtr, msvrr, msvrd;
 
 	channel = info->line - card->first_line;
 	chip = channel >> 2;
@@ -837,29 +838,28 @@ static void cyy_change_rts_dtr(struct cyclades_port *info, unsigned int set,
 	index = card->bus_index;
 	base_addr = card->base_addr + (cy_chip_offset[chip] << index);
 
+	if (info->rtsdtr_inv) {
+		msvrr = CyMSVR2;
+		msvrd = CyMSVR1;
+		rts = CyDTR;
+		dtr = CyRTS;
+	} else {
+		msvrr = CyMSVR1;
+		msvrd = CyMSVR2;
+		rts = CyRTS;
+		dtr = CyDTR;
+	}
 	if (set & TIOCM_RTS) {
-		cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
-		if (info->rtsdtr_inv) {
-			cy_writeb(base_addr + (CyMSVR2 << index), CyDTR);
-		} else {
-			cy_writeb(base_addr + (CyMSVR1 << index), CyRTS);
-		}
+		cy_writeb(base_addr + (CyCAR << index), (u8)channel);
+		cy_writeb(base_addr + (msvrr << index), rts);
 	}
 	if (clear & TIOCM_RTS) {
-		cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
-		if (info->rtsdtr_inv) {
-			cy_writeb(base_addr + (CyMSVR2 << index), ~CyDTR);
-		} else {
-			cy_writeb(base_addr + (CyMSVR1 << index), ~CyRTS);
-		}
+		cy_writeb(base_addr + (CyCAR << index), (u8)channel);
+		cy_writeb(base_addr + (msvrr << index), ~rts);
 	}
 	if (set & TIOCM_DTR) {
-		cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
-		if (info->rtsdtr_inv) {
-			cy_writeb(base_addr + (CyMSVR1 << index), CyRTS);
-		} else {
-			cy_writeb(base_addr + (CyMSVR2 << index), CyDTR);
-		}
+		cy_writeb(base_addr + (CyCAR << index), (u8)channel);
+		cy_writeb(base_addr + (msvrd << index), dtr);
 #ifdef CY_DEBUG_DTR
 		printk(KERN_DEBUG "cyc:set_modem_info raising DTR\n");
 		printk(KERN_DEBUG "     status: 0x%x, 0x%x\n",
@@ -868,13 +868,8 @@ static void cyy_change_rts_dtr(struct cyclades_port *info, unsigned int set,
 #endif
 	}
 	if (clear & TIOCM_DTR) {
-		cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
-		if (info->rtsdtr_inv) {
-			cy_writeb(base_addr + (CyMSVR1 << index), ~CyRTS);
-		} else {
-			cy_writeb(base_addr + (CyMSVR2 << index), ~CyDTR);
-		}
-
+		cy_writeb(base_addr + (CyCAR << index), (u8)channel);
+		cy_writeb(base_addr + (msvrd << index), ~dtr);
 #ifdef CY_DEBUG_DTR
 		printk(KERN_DEBUG "cyc:set_modem_info dropping DTR\n");
 		printk(KERN_DEBUG "     status: 0x%x, 0x%x\n",
@@ -2517,28 +2512,27 @@ static int cy_tiocmget(struct tty_struct *tty, struct file *file)
 {
 	struct cyclades_port *info = tty->driver_data;
 	struct cyclades_card *card;
-	int chip, channel, index;
 	void __iomem *base_addr;
-	unsigned long flags;
-	unsigned char status;
-	unsigned long lstatus;
-	unsigned int result;
+	int result, channel;
 
 	if (serial_paranoia_check(info, tty->name, __func__))
 		return -ENODEV;
 
-	lock_kernel();
-
 	card = info->card;
 	channel = info->line - card->first_line;
+
+	lock_kernel();
 	if (!cy_is_Z(card)) {
-		chip = channel >> 2;
+		unsigned long flags;
+		unsigned char status;
+		int chip = channel >> 2;
+		int index = card->bus_index;
+
 		channel &= 0x03;
-		index = card->bus_index;
 		base_addr = card->base_addr + (cy_chip_offset[chip] << index);
 
 		spin_lock_irqsave(&card->card_lock, flags);
-		cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
+		cy_writeb(base_addr + (CyCAR << index), (u8)channel);
 		status = readb(base_addr + (CyMSVR1 << index));
 		status |= readb(base_addr + (CyMSVR2 << index));
 		spin_unlock_irqrestore(&card->card_lock, flags);
@@ -2555,21 +2549,22 @@ static int cy_tiocmget(struct tty_struct *tty, struct file *file)
 			((status & CyDSR) ? TIOCM_DSR : 0) |
 			((status & CyCTS) ? TIOCM_CTS : 0);
 	} else {
-		if (cyz_is_loaded(card)) {
-			lstatus = readl(&info->u.cyz.ch_ctrl->rs_status);
-			result = ((lstatus & C_RS_RTS) ? TIOCM_RTS : 0) |
-				((lstatus & C_RS_DTR) ? TIOCM_DTR : 0) |
-				((lstatus & C_RS_DCD) ? TIOCM_CAR : 0) |
-				((lstatus & C_RS_RI) ? TIOCM_RNG : 0) |
-				((lstatus & C_RS_DSR) ? TIOCM_DSR : 0) |
-				((lstatus & C_RS_CTS) ? TIOCM_CTS : 0);
-		} else {
-			result = 0;
-			unlock_kernel();
-			return -ENODEV;
+		u32 lstatus;
+
+		if (!cyz_is_loaded(card)) {
+			result = -ENODEV;
+			goto end;
 		}
 
+		lstatus = readl(&info->u.cyz.ch_ctrl->rs_status);
+		result = ((lstatus & C_RS_RTS) ? TIOCM_RTS : 0) |
+			((lstatus & C_RS_DTR) ? TIOCM_DTR : 0) |
+			((lstatus & C_RS_DCD) ? TIOCM_CAR : 0) |
+			((lstatus & C_RS_RI) ? TIOCM_RNG : 0) |
+			((lstatus & C_RS_DSR) ? TIOCM_DSR : 0) |
+			((lstatus & C_RS_CTS) ? TIOCM_CTS : 0);
 	}
+end:
 	unlock_kernel();
 	return result;
 }				/* cy_tiomget */
@@ -2581,68 +2576,52 @@ cy_tiocmset(struct tty_struct *tty, struct file *file,
 	struct cyclades_port *info = tty->driver_data;
 	struct cyclades_card *card;
 	unsigned long flags;
-	int channel, retval;
 
 	if (serial_paranoia_check(info, tty->name, __func__))
 		return -ENODEV;
 
 	card = info->card;
-	channel = (info->line) - (card->first_line);
 	if (!cy_is_Z(card)) {
 		spin_lock_irqsave(&card->card_lock, flags);
 		cyy_change_rts_dtr(info, set, clear);
 		spin_unlock_irqrestore(&card->card_lock, flags);
 	} else {
-		if (cyz_is_loaded(card)) {
-			struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
-
-			if (set & TIOCM_RTS) {
-				spin_lock_irqsave(&card->card_lock, flags);
-				cy_writel(&ch_ctrl->rs_control,
-					readl(&ch_ctrl->rs_control) | C_RS_RTS);
-				spin_unlock_irqrestore(&card->card_lock, flags);
-			}
-			if (clear & TIOCM_RTS) {
-				spin_lock_irqsave(&card->card_lock, flags);
-				cy_writel(&ch_ctrl->rs_control,
-					readl(&ch_ctrl->rs_control) &
-					~C_RS_RTS);
-				spin_unlock_irqrestore(&card->card_lock, flags);
-			}
-			if (set & TIOCM_DTR) {
-				spin_lock_irqsave(&card->card_lock, flags);
-				cy_writel(&ch_ctrl->rs_control,
-					readl(&ch_ctrl->rs_control) | C_RS_DTR);
+		struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
+		int retval, channel = info->line - card->first_line;
+		u32 rs;
+
+		if (!cyz_is_loaded(card))
+			return -ENODEV;
+
+		spin_lock_irqsave(&card->card_lock, flags);
+		rs = readl(&ch_ctrl->rs_control);
+		if (set & TIOCM_RTS)
+			rs |= C_RS_RTS;
+		if (clear & TIOCM_RTS)
+			rs &= ~C_RS_RTS;
+		if (set & TIOCM_DTR) {
+			rs |= C_RS_DTR;
 #ifdef CY_DEBUG_DTR
-				printk(KERN_DEBUG "cyc:set_modem_info raising "
-					"Z DTR\n");
+			printk(KERN_DEBUG "cyc:set_modem_info raising Z DTR\n");
 #endif
-				spin_unlock_irqrestore(&card->card_lock, flags);
-			}
-			if (clear & TIOCM_DTR) {
-				spin_lock_irqsave(&card->card_lock, flags);
-				cy_writel(&ch_ctrl->rs_control,
-					readl(&ch_ctrl->rs_control) &
-					~C_RS_DTR);
+		}
+		if (clear & TIOCM_DTR) {
+			rs &= ~C_RS_DTR;
 #ifdef CY_DEBUG_DTR
-				printk(KERN_DEBUG "cyc:set_modem_info clearing "
-					"Z DTR\n");
+			printk(KERN_DEBUG "cyc:set_modem_info clearing "
+				"Z DTR\n");
 #endif
-				spin_unlock_irqrestore(&card->card_lock, flags);
-			}
-		} else {
-			return -ENODEV;
 		}
-		spin_lock_irqsave(&card->card_lock, flags);
+		cy_writel(&ch_ctrl->rs_control, rs);
 		retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L);
+		spin_unlock_irqrestore(&card->card_lock, flags);
 		if (retval != 0) {
 			printk(KERN_ERR "cyc:set_modem_info retval on ttyC%d "
 				"was %x\n", info->line, retval);
 		}
-		spin_unlock_irqrestore(&card->card_lock, flags);
 	}
 	return 0;
-}				/* cy_tiocmset */
+}
 
 /*
  * cy_break() --- routine which turns the break handling on or off
-- 
1.6.3.2


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

* [PATCH 12/13] Char: cyclades, introduce cyy_readb/writeb
  2009-06-18  7:41 [PATCH 01/13] Char: cyclades, add tty refcounting Jiri Slaby
                   ` (9 preceding siblings ...)
  2009-06-18  7:41 ` [PATCH 11/13] Char: cyclades, tiocm cleanup Jiri Slaby
@ 2009-06-18  7:41 ` Jiri Slaby
  2009-06-18  7:41 ` [PATCH 13/13] Char: cyclades, remove more duplicated code Jiri Slaby
  2009-06-18 13:17 ` [PATCH 01/13] Char: cyclades, add tty refcounting Alan Cox
  12 siblings, 0 replies; 14+ messages in thread
From: Jiri Slaby @ 2009-06-18  7:41 UTC (permalink / raw)
  To: alan; +Cc: Andrew Morton, linux-kernel, Jiri Slaby

Add helpers for io operations, so that we can eliminate huge
amount of supporting code. It is now centralized in those
helpers and used values are precomputed in the init phase.

Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
---
 drivers/char/cyclades.c  |  448 +++++++++++++++++-----------------------------
 include/linux/cyclades.h |    2 +-
 2 files changed, 165 insertions(+), 285 deletions(-)

diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index ed9ec2c..76248aa 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -89,7 +89,6 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 
-static void cy_throttle(struct tty_struct *tty);
 static void cy_send_xchar(struct tty_struct *tty, char ch);
 
 #ifndef SERIAL_XMIT_SIZE
@@ -297,6 +296,20 @@ static void cyz_rx_restart(unsigned long);
 static struct timer_list cyz_rx_full_timer[NR_PORTS];
 #endif				/* CONFIG_CYZ_INTR */
 
+static inline void cyy_writeb(struct cyclades_port *port, u32 reg, u8 val)
+{
+	struct cyclades_card *card = port->card;
+
+	cy_writeb(port->u.cyy.base_addr + (reg << card->bus_index), val);
+}
+
+static inline u8 cyy_readb(struct cyclades_port *port, u32 reg)
+{
+	struct cyclades_card *card = port->card;
+
+	return readb(port->u.cyy.base_addr + (reg << card->bus_index));
+}
+
 static inline bool cy_is_Z(struct cyclades_card *card)
 {
 	return card->num_chips == (unsigned int)-1;
@@ -349,13 +362,14 @@ static inline int serial_paranoia_check(struct cyclades_port *info,
 
    This function is only called from inside spinlock-protected code.
  */
-static int cyy_issue_cmd(void __iomem *base_addr, u_char cmd, int index)
+static int __cyy_issue_cmd(void __iomem *base_addr, u8 cmd, int index)
 {
+	void __iomem *ccr = base_addr + (CyCCR << index);
 	unsigned int i;
 
 	/* Check to see that the previous command has completed */
 	for (i = 0; i < 100; i++) {
-		if (readb(base_addr + (CyCCR << index)) == 0)
+		if (readb(ccr) == 0)
 			break;
 		udelay(10L);
 	}
@@ -365,10 +379,16 @@ static int cyy_issue_cmd(void __iomem *base_addr, u_char cmd, int index)
 		return -1;
 
 	/* Issue the new command */
-	cy_writeb(base_addr + (CyCCR << index), cmd);
+	cy_writeb(ccr, cmd);
 
 	return 0;
-}				/* cyy_issue_cmd */
+}
+
+static inline int cyy_issue_cmd(struct cyclades_port *port, u8 cmd)
+{
+	return __cyy_issue_cmd(port->u.cyy.base_addr, cmd,
+			port->card->bus_index);
+}
 
 #ifdef CONFIG_ISA
 /* ISA interrupt detection code */
@@ -393,7 +413,7 @@ static unsigned detect_isa_irq(void __iomem *address)
 	/* Enable the Tx interrupts on the CD1400 */
 	local_irq_save(flags);
 	cy_writeb(address + (CyCAR << index), 0);
-	cyy_issue_cmd(address, CyCHAN_CTL | CyENB_XMTR, index);
+	__cyy_issue_cmd(address, CyCHAN_CTL | CyENB_XMTR, index);
 
 	cy_writeb(address + (CyCAR << index), 0);
 	cy_writeb(address + (CySRER << index),
@@ -427,7 +447,7 @@ static void cyy_chip_rx(struct cyclades_card *cinfo, int chip,
 	struct cyclades_port *info;
 	struct tty_struct *tty;
 	int len, index = cinfo->bus_index;
-	u8 save_xir, channel, save_car, data, char_count;
+	u8 ivr, save_xir, channel, save_car, data, char_count;
 
 #ifdef CY_DEBUG_INTERRUPTS
 	printk(KERN_DEBUG "cyy_interrupt: rcvd intr, chip %d\n", chip);
@@ -436,26 +456,25 @@ static void cyy_chip_rx(struct cyclades_card *cinfo, int chip,
 	save_xir = readb(base_addr + (CyRIR << index));
 	channel = save_xir & CyIRChannel;
 	info = &cinfo->ports[channel + chip * 4];
-	save_car = readb(base_addr + (CyCAR << index));
-	cy_writeb(base_addr + (CyCAR << index), save_xir);
+	save_car = cyy_readb(info, CyCAR);
+	cyy_writeb(info, CyCAR, save_xir);
+	ivr = cyy_readb(info, CyRIVR) & CyIVRMask;
 
 	tty = tty_port_tty_get(&info->port);
 	/* if there is nowhere to put the data, discard it */
 	if (tty == NULL) {
-		if ((readb(base_addr + (CyRIVR << index)) & CyIVRMask) ==
-				CyIVRRxEx) {	/* exception */
-			data = readb(base_addr + (CyRDSR << index));
+		if (ivr == CyIVRRxEx) {	/* exception */
+			data = cyy_readb(info, CyRDSR);
 		} else {	/* normal character reception */
-			char_count = readb(base_addr + (CyRDCR << index));
+			char_count = cyy_readb(info, CyRDCR);
 			while (char_count--)
-				data = readb(base_addr + (CyRDSR << index));
+				data = cyy_readb(info, CyRDSR);
 		}
 		goto end;
 	}
 	/* there is an open port for this data */
-	if ((readb(base_addr + (CyRIVR << index)) & CyIVRMask) ==
-			CyIVRRxEx) {	/* exception */
-		data = readb(base_addr + (CyRDSR << index));
+	if (ivr == CyIVRRxEx) {	/* exception */
+		data = cyy_readb(info, CyRDSR);
 
 		/* For statistics only */
 		if (data & CyBREAK)
@@ -476,22 +495,22 @@ static void cyy_chip_rx(struct cyclades_card *cinfo, int chip,
 			if (data & info->read_status_mask) {
 				if (data & CyBREAK) {
 					tty_insert_flip_char(tty,
-						readb(base_addr + (CyRDSR <<
-							index)), TTY_BREAK);
+						cyy_readb(info, CyRDSR),
+						TTY_BREAK);
 					info->icount.rx++;
 					if (info->port.flags & ASYNC_SAK)
 						do_SAK(tty);
 				} else if (data & CyFRAME) {
 					tty_insert_flip_char(tty,
-						readb(base_addr + (CyRDSR <<
-							index)), TTY_FRAME);
+						cyy_readb(info, CyRDSR),
+						TTY_FRAME);
 					info->icount.rx++;
 					info->idle_stats.frame_errs++;
 				} else if (data & CyPARITY) {
 					/* Pieces of seven... */
 					tty_insert_flip_char(tty,
-						readb(base_addr + (CyRDSR <<
-							index)), TTY_PARITY);
+						cyy_readb(info, CyRDSR),
+						TTY_PARITY);
 					info->icount.rx++;
 					info->idle_stats.parity_errs++;
 				} else if (data & CyOVERRUN) {
@@ -503,8 +522,8 @@ static void cyy_chip_rx(struct cyclades_card *cinfo, int chip,
 					   the next incoming character.
 					 */
 					tty_insert_flip_char(tty,
-						readb(base_addr + (CyRDSR <<
-							index)), TTY_FRAME);
+						cyy_readb(info, CyRDSR),
+						TTY_FRAME);
 					info->icount.rx++;
 					info->idle_stats.overruns++;
 				/* These two conditions may imply */
@@ -528,7 +547,7 @@ static void cyy_chip_rx(struct cyclades_card *cinfo, int chip,
 		}
 	} else {	/* normal character reception */
 		/* load # chars available from the chip */
-		char_count = readb(base_addr + (CyRDCR << index));
+		char_count = cyy_readb(info, CyRDCR);
 
 #ifdef CY_ENABLE_MONITORING
 		++info->mon.int_count;
@@ -539,7 +558,7 @@ static void cyy_chip_rx(struct cyclades_card *cinfo, int chip,
 #endif
 		len = tty_buffer_request_room(tty, char_count);
 		while (len--) {
-			data = readb(base_addr + (CyRDSR << index));
+			data = cyy_readb(info, CyRDSR);
 			tty_insert_flip_char(tty, data, TTY_NORMAL);
 			info->idle_stats.recv_bytes++;
 			info->icount.rx++;
@@ -553,8 +572,8 @@ static void cyy_chip_rx(struct cyclades_card *cinfo, int chip,
 	tty_kref_put(tty);
 end:
 	/* end of service */
-	cy_writeb(base_addr + (CyRIR << index), save_xir & 0x3f);
-	cy_writeb(base_addr + (CyCAR << index), save_car);
+	cyy_writeb(info, CyRIR, save_xir & 0x3f);
+	cyy_writeb(info, CyCAR, save_car);
 }
 
 static void cyy_chip_tx(struct cyclades_card *cinfo, unsigned int chip,
@@ -587,8 +606,7 @@ static void cyy_chip_tx(struct cyclades_card *cinfo, unsigned int chip,
 	info = &cinfo->ports[channel + chip * 4];
 	tty = tty_port_tty_get(&info->port);
 	if (tty == NULL) {
-		cy_writeb(base_addr + (CySRER << index),
-			  readb(base_addr + (CySRER << index)) & ~CyTxRdy);
+		cyy_writeb(info, CySRER, cyy_readb(info, CySRER) & ~CyTxRdy);
 		goto end;
 	}
 
@@ -597,7 +615,7 @@ static void cyy_chip_tx(struct cyclades_card *cinfo, unsigned int chip,
 
 	if (info->x_char) {	/* send special char */
 		outch = info->x_char;
-		cy_writeb(base_addr + (CyTDR << index), outch);
+		cyy_writeb(info, CyTDR, outch);
 		char_count--;
 		info->icount.tx++;
 		info->x_char = 0;
@@ -605,14 +623,14 @@ static void cyy_chip_tx(struct cyclades_card *cinfo, unsigned int chip,
 
 	if (info->breakon || info->breakoff) {
 		if (info->breakon) {
-			cy_writeb(base_addr + (CyTDR << index), 0);
-			cy_writeb(base_addr + (CyTDR << index), 0x81);
+			cyy_writeb(info, CyTDR, 0);
+			cyy_writeb(info, CyTDR, 0x81);
 			info->breakon = 0;
 			char_count -= 2;
 		}
 		if (info->breakoff) {
-			cy_writeb(base_addr + (CyTDR << index), 0);
-			cy_writeb(base_addr + (CyTDR << index), 0x83);
+			cyy_writeb(info, CyTDR, 0);
+			cyy_writeb(info, CyTDR, 0x83);
 			info->breakoff = 0;
 			char_count -= 2;
 		}
@@ -620,27 +638,23 @@ static void cyy_chip_tx(struct cyclades_card *cinfo, unsigned int chip,
 
 	while (char_count-- > 0) {
 		if (!info->xmit_cnt) {
-			if (readb(base_addr + (CySRER << index)) & CyTxMpty) {
-				cy_writeb(base_addr + (CySRER << index),
-					readb(base_addr + (CySRER << index)) &
-						~CyTxMpty);
+			if (cyy_readb(info, CySRER) & CyTxMpty) {
+				cyy_writeb(info, CySRER,
+					cyy_readb(info, CySRER) & ~CyTxMpty);
 			} else {
-				cy_writeb(base_addr + (CySRER << index),
-					(readb(base_addr + (CySRER << index)) &
-						~CyTxRdy) | CyTxMpty);
+				cyy_writeb(info, CySRER, CyTxMpty |
+					(cyy_readb(info, CySRER) & ~CyTxRdy));
 			}
 			goto done;
 		}
 		if (info->port.xmit_buf == NULL) {
-			cy_writeb(base_addr + (CySRER << index),
-				readb(base_addr + (CySRER << index)) &
-					~CyTxRdy);
+			cyy_writeb(info, CySRER,
+				cyy_readb(info, CySRER) & ~CyTxRdy);
 			goto done;
 		}
 		if (tty->stopped || tty->hw_stopped) {
-			cy_writeb(base_addr + (CySRER << index),
-				readb(base_addr + (CySRER << index)) &
-					~CyTxRdy);
+			cyy_writeb(info, CySRER,
+				cyy_readb(info, CySRER) & ~CyTxRdy);
 			goto done;
 		}
 		/* Because the Embedded Transmit Commands have been enabled,
@@ -657,15 +671,15 @@ static void cyy_chip_tx(struct cyclades_card *cinfo, unsigned int chip,
 			info->xmit_cnt--;
 			info->xmit_tail = (info->xmit_tail + 1) &
 					(SERIAL_XMIT_SIZE - 1);
-			cy_writeb(base_addr + (CyTDR << index), outch);
+			cyy_writeb(info, CyTDR, outch);
 			info->icount.tx++;
 		} else {
 			if (char_count > 1) {
 				info->xmit_cnt--;
 				info->xmit_tail = (info->xmit_tail + 1) &
 					(SERIAL_XMIT_SIZE - 1);
-				cy_writeb(base_addr + (CyTDR << index), outch);
-				cy_writeb(base_addr + (CyTDR << index), 0);
+				cyy_writeb(info, CyTDR, outch);
+				cyy_writeb(info, CyTDR, 0);
 				info->icount.tx++;
 				char_count--;
 			}
@@ -677,8 +691,8 @@ done:
 	tty_kref_put(tty);
 end:
 	/* end of service */
-	cy_writeb(base_addr + (CyTIR << index), save_xir & 0x3f);
-	cy_writeb(base_addr + (CyCAR << index), save_car);
+	cyy_writeb(info, CyTIR, save_xir & 0x3f);
+	cyy_writeb(info, CyCAR, save_car);
 }
 
 static void cyy_chip_modem(struct cyclades_card *cinfo, int chip,
@@ -693,11 +707,11 @@ static void cyy_chip_modem(struct cyclades_card *cinfo, int chip,
 	save_xir = readb(base_addr + (CyMIR << index));
 	channel = save_xir & CyIRChannel;
 	info = &cinfo->ports[channel + chip * 4];
-	save_car = readb(base_addr + (CyCAR << index));
-	cy_writeb(base_addr + (CyCAR << index), save_xir);
+	save_car = cyy_readb(info, CyCAR);
+	cyy_writeb(info, CyCAR, save_xir);
 
-	mdm_change = readb(base_addr + (CyMISR << index));
-	mdm_status = readb(base_addr + (CyMSVR1 << index));
+	mdm_change = cyy_readb(info, CyMISR);
+	mdm_status = cyy_readb(info, CyMSVR1);
 
 	tty = tty_port_tty_get(&info->port);
 	if (!tty)
@@ -729,9 +743,8 @@ static void cyy_chip_modem(struct cyclades_card *cinfo, int chip,
 				/* cy_start isn't used
 				   because... !!! */
 				tty->hw_stopped = 0;
-				cy_writeb(base_addr + (CySRER << index),
-					readb(base_addr + (CySRER << index)) |
-						CyTxRdy);
+				cyy_writeb(info, CySRER,
+					cyy_readb(info, CySRER) | CyTxRdy);
 				tty_wakeup(tty);
 			}
 		} else {
@@ -739,9 +752,8 @@ static void cyy_chip_modem(struct cyclades_card *cinfo, int chip,
 				/* cy_stop isn't used
 				   because ... !!! */
 				tty->hw_stopped = 1;
-				cy_writeb(base_addr + (CySRER << index),
-					readb(base_addr + (CySRER << index)) &
-						~CyTxRdy);
+				cyy_writeb(info, CySRER,
+					cyy_readb(info, CySRER) & ~CyTxRdy);
 			}
 		}
 	}
@@ -752,8 +764,8 @@ static void cyy_chip_modem(struct cyclades_card *cinfo, int chip,
 	tty_kref_put(tty);
 end:
 	/* end of service */
-	cy_writeb(base_addr + (CyMIR << index), save_xir & 0x3f);
-	cy_writeb(base_addr + (CyCAR << index), save_car);
+	cyy_writeb(info, CyMIR, save_xir & 0x3f);
+	cyy_writeb(info, CyCAR, save_car);
 }
 
 /* The real interrupt service routine is called
@@ -828,15 +840,10 @@ static void cyy_change_rts_dtr(struct cyclades_port *info, unsigned int set,
 		unsigned int clear)
 {
 	struct cyclades_card *card = info->card;
-	void __iomem *base_addr;
-	int chip, channel, index;
+	int channel = info->line - card->first_line;
 	u32 rts, dtr, msvrr, msvrd;
 
-	channel = info->line - card->first_line;
-	chip = channel >> 2;
 	channel &= 0x03;
-	index = card->bus_index;
-	base_addr = card->base_addr + (cy_chip_offset[chip] << index);
 
 	if (info->rtsdtr_inv) {
 		msvrr = CyMSVR2;
@@ -850,31 +857,31 @@ static void cyy_change_rts_dtr(struct cyclades_port *info, unsigned int set,
 		dtr = CyDTR;
 	}
 	if (set & TIOCM_RTS) {
-		cy_writeb(base_addr + (CyCAR << index), (u8)channel);
-		cy_writeb(base_addr + (msvrr << index), rts);
+		cyy_writeb(info, CyCAR, channel);
+		cyy_writeb(info, msvrr, rts);
 	}
 	if (clear & TIOCM_RTS) {
-		cy_writeb(base_addr + (CyCAR << index), (u8)channel);
-		cy_writeb(base_addr + (msvrr << index), ~rts);
+		cyy_writeb(info, CyCAR, channel);
+		cyy_writeb(info, msvrr, ~rts);
 	}
 	if (set & TIOCM_DTR) {
-		cy_writeb(base_addr + (CyCAR << index), (u8)channel);
-		cy_writeb(base_addr + (msvrd << index), dtr);
+		cyy_writeb(info, CyCAR, channel);
+		cyy_writeb(info, msvrd, dtr);
 #ifdef CY_DEBUG_DTR
 		printk(KERN_DEBUG "cyc:set_modem_info raising DTR\n");
 		printk(KERN_DEBUG "     status: 0x%x, 0x%x\n",
-			readb(base_addr + (CyMSVR1 << index)),
-			readb(base_addr + (CyMSVR2 << index)));
+			cyy_readb(info, CyMSVR1),
+			cyy_readb(info, CyMSVR2));
 #endif
 	}
 	if (clear & TIOCM_DTR) {
-		cy_writeb(base_addr + (CyCAR << index), (u8)channel);
-		cy_writeb(base_addr + (msvrd << index), ~dtr);
+		cyy_writeb(info, CyCAR, channel);
+		cyy_writeb(info, msvrd, ~dtr);
 #ifdef CY_DEBUG_DTR
 		printk(KERN_DEBUG "cyc:set_modem_info dropping DTR\n");
 		printk(KERN_DEBUG "     status: 0x%x, 0x%x\n",
-			readb(base_addr + (CyMSVR1 << index)),
-			readb(base_addr + (CyMSVR2 << index)));
+			cyy_readb(info, CyMSVR1),
+			cyy_readb(info, CyMSVR2));
 #endif
 	}
 }
@@ -1289,7 +1296,6 @@ static int cy_startup(struct cyclades_port *info, struct tty_struct *tty)
 	struct cyclades_card *card;
 	unsigned long flags;
 	int retval = 0;
-	void __iomem *base_addr;
 	int channel;
 	unsigned long page;
 
@@ -1320,31 +1326,21 @@ static int cy_startup(struct cyclades_port *info, struct tty_struct *tty)
 	cy_set_line_char(info, tty);
 
 	if (!cy_is_Z(card)) {
-		int chip = channel >> 2;
-		int index = card->bus_index;
 		channel &= 0x03;
-		base_addr = card->base_addr + (cy_chip_offset[chip] << index);
 
-#ifdef CY_DEBUG_OPEN
-		printk(KERN_DEBUG "cyc startup card %d, chip %d, channel %d, "
-				"base_addr %p\n",
-				card, chip, channel, base_addr);
-#endif
 		spin_lock_irqsave(&card->card_lock, flags);
 
-		cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
+		cyy_writeb(info, CyCAR, channel);
 
-		cy_writeb(base_addr + (CyRTPR << index),
+		cyy_writeb(info, CyRTPR,
 			(info->default_timeout ? info->default_timeout : 0x02));
 		/* 10ms rx timeout */
 
-		cyy_issue_cmd(base_addr, CyCHAN_CTL | CyENB_RCVR | CyENB_XMTR,
-				index);
+		cyy_issue_cmd(info, CyCHAN_CTL | CyENB_RCVR | CyENB_XMTR);
 
 		cyy_change_rts_dtr(info, TIOCM_RTS | TIOCM_DTR, 0);
 
-		cy_writeb(base_addr + (CySRER << index),
-			readb(base_addr + (CySRER << index)) | CyRxData);
+		cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyRxData);
 	} else {
 		struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
 
@@ -1422,23 +1418,14 @@ errout:
 
 static void start_xmit(struct cyclades_port *info)
 {
-	struct cyclades_card *card;
+	struct cyclades_card *card = info->card;
 	unsigned long flags;
-	void __iomem *base_addr;
-	int chip, channel, index;
+	int channel = info->line - card->first_line;
 
-	card = info->card;
-	channel = info->line - card->first_line;
 	if (!cy_is_Z(card)) {
-		chip = channel >> 2;
-		channel &= 0x03;
-		index = card->bus_index;
-		base_addr = card->base_addr + (cy_chip_offset[chip] << index);
-
 		spin_lock_irqsave(&card->card_lock, flags);
-		cy_writeb(base_addr + (CyCAR << index), channel);
-		cy_writeb(base_addr + (CySRER << index),
-			readb(base_addr + (CySRER << index)) | CyTxRdy);
+		cyy_writeb(info, CyCAR, channel & 0x03);
+		cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyTxRdy);
 		spin_unlock_irqrestore(&card->card_lock, flags);
 	} else {
 #ifdef CONFIG_CYZ_INTR
@@ -1465,8 +1452,7 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty)
 {
 	struct cyclades_card *card;
 	unsigned long flags;
-	void __iomem *base_addr;
-	int chip, channel, index;
+	int channel;
 
 	if (!(info->port.flags & ASYNC_INITIALIZED))
 		return;
@@ -1474,17 +1460,6 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty)
 	card = info->card;
 	channel = info->line - card->first_line;
 	if (!cy_is_Z(card)) {
-		chip = channel >> 2;
-		channel &= 0x03;
-		index = card->bus_index;
-		base_addr = card->base_addr + (cy_chip_offset[chip] << index);
-
-#ifdef CY_DEBUG_OPEN
-		printk(KERN_DEBUG "cyc shutdown Y card %d, chip %d, "
-				"channel %d, base_addr %p\n",
-				card, chip, channel, base_addr);
-#endif
-
 		spin_lock_irqsave(&card->card_lock, flags);
 
 		/* Clear delta_msr_wait queue to avoid mem leaks. */
@@ -1499,7 +1474,7 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty)
 		if (tty->termios->c_cflag & HUPCL)
 			cyy_change_rts_dtr(info, 0, TIOCM_RTS | TIOCM_DTR);
 
-		cyy_issue_cmd(base_addr, CyCHAN_CTL | CyDIS_RCVR, index);
+		cyy_issue_cmd(info, CyCHAN_CTL | CyDIS_RCVR);
 		/* it may be appropriate to clear _XMIT at
 		   some later date (after testing)!!! */
 
@@ -1676,8 +1651,6 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout)
 {
 	struct cyclades_card *card;
 	struct cyclades_port *info = tty->driver_data;
-	void __iomem *base_addr;
-	int chip, channel, index;
 	unsigned long orig_jiffies;
 	int char_time;
 
@@ -1721,13 +1694,8 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout)
 		timeout, char_time, jiffies);
 #endif
 	card = info->card;
-	channel = (info->line) - (card->first_line);
 	if (!cy_is_Z(card)) {
-		chip = channel >> 2;
-		channel &= 0x03;
-		index = card->bus_index;
-		base_addr = card->base_addr + (cy_chip_offset[chip] << index);
-		while (readb(base_addr + (CySRER << index)) & CyTxRdy) {
+		while (cyy_readb(info, CySRER) & CyTxRdy) {
 #ifdef CY_DEBUG_WAIT_UNTIL_SENT
 			printk(KERN_DEBUG "Not clean (jiff=%lu)...", jiffies);
 #endif
@@ -1789,6 +1757,7 @@ static void cy_close(struct tty_struct *tty, struct file *filp)
 	struct cyclades_port *info = tty->driver_data;
 	struct cyclades_card *card;
 	unsigned long flags;
+	int channel;
 
 	if (!info || serial_paranoia_check(info, tty->name, "cy_close"))
 		return;
@@ -1798,18 +1767,13 @@ static void cy_close(struct tty_struct *tty, struct file *filp)
 	if (!tty_port_close_start(&info->port, tty, filp))
 		return;
 
+	channel = info->line - card->first_line;
 	spin_lock_irqsave(&card->card_lock, flags);
 
 	if (!cy_is_Z(card)) {
-		int channel = info->line - card->first_line;
-		int index = card->bus_index;
-		void __iomem *base_addr = card->base_addr +
-			(cy_chip_offset[channel >> 2] << index);
 		/* Stop accepting input */
-		channel &= 0x03;
-		cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
-		cy_writeb(base_addr + (CySRER << index),
-			  readb(base_addr + (CySRER << index)) & ~CyRxData);
+		cyy_writeb(info, CyCAR, channel & 0x03);
+		cyy_writeb(info, CySRER, cyy_readb(info, CySRER) & ~CyRxData);
 		if (info->port.flags & ASYNC_INITIALIZED) {
 			/* Waiting for on-board buffers to be empty before
 			   closing the port */
@@ -1822,7 +1786,6 @@ static void cy_close(struct tty_struct *tty, struct file *filp)
 		/* Waiting for on-board buffers to be empty before closing
 		   the port */
 		struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
-		int channel = info->line - card->first_line;
 		int retval;
 
 		if (readl(&ch_ctrl->flow_status) != C_FS_TXIDLE) {
@@ -2063,8 +2026,7 @@ static void cy_set_line_char(struct cyclades_port *info, struct tty_struct *tty)
 {
 	struct cyclades_card *card;
 	unsigned long flags;
-	void __iomem *base_addr;
-	int chip, channel, index;
+	int channel;
 	unsigned cflag, iflag;
 	int baud, baud_rate = 0;
 	int i;
@@ -2094,9 +2056,6 @@ static void cy_set_line_char(struct cyclades_port *info, struct tty_struct *tty)
 	channel = info->line - card->first_line;
 
 	if (!cy_is_Z(card)) {
-
-		index = card->bus_index;
-
 		/* baud rate */
 		baud = tty_get_baud_rate(tty);
 		if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
@@ -2207,70 +2166,67 @@ static void cy_set_line_char(struct cyclades_port *info, struct tty_struct *tty)
 	    cable.  Contact Marcio Saito for details.
 	 ***********************************************/
 
-		chip = channel >> 2;
 		channel &= 0x03;
-		base_addr = card->base_addr + (cy_chip_offset[chip] << index);
 
 		spin_lock_irqsave(&card->card_lock, flags);
-		cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
+		cyy_writeb(info, CyCAR, channel);
 
 		/* tx and rx baud rate */
 
-		cy_writeb(base_addr + (CyTCOR << index), info->tco);
-		cy_writeb(base_addr + (CyTBPR << index), info->tbpr);
-		cy_writeb(base_addr + (CyRCOR << index), info->rco);
-		cy_writeb(base_addr + (CyRBPR << index), info->rbpr);
+		cyy_writeb(info, CyTCOR, info->tco);
+		cyy_writeb(info, CyTBPR, info->tbpr);
+		cyy_writeb(info, CyRCOR, info->rco);
+		cyy_writeb(info, CyRBPR, info->rbpr);
 
 		/* set line characteristics  according configuration */
 
-		cy_writeb(base_addr + (CySCHR1 << index), START_CHAR(tty));
-		cy_writeb(base_addr + (CySCHR2 << index), STOP_CHAR(tty));
-		cy_writeb(base_addr + (CyCOR1 << index), info->cor1);
-		cy_writeb(base_addr + (CyCOR2 << index), info->cor2);
-		cy_writeb(base_addr + (CyCOR3 << index), info->cor3);
-		cy_writeb(base_addr + (CyCOR4 << index), info->cor4);
-		cy_writeb(base_addr + (CyCOR5 << index), info->cor5);
+		cyy_writeb(info, CySCHR1, START_CHAR(tty));
+		cyy_writeb(info, CySCHR2, STOP_CHAR(tty));
+		cyy_writeb(info, CyCOR1, info->cor1);
+		cyy_writeb(info, CyCOR2, info->cor2);
+		cyy_writeb(info, CyCOR3, info->cor3);
+		cyy_writeb(info, CyCOR4, info->cor4);
+		cyy_writeb(info, CyCOR5, info->cor5);
 
-		cyy_issue_cmd(base_addr, CyCOR_CHANGE | CyCOR1ch | CyCOR2ch |
-				CyCOR3ch, index);
+		cyy_issue_cmd(info, CyCOR_CHANGE | CyCOR1ch | CyCOR2ch |
+				CyCOR3ch);
 
 		/* !!! Is this needed? */
-		cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
-		cy_writeb(base_addr + (CyRTPR << index),
+		cyy_writeb(info, CyCAR, channel);
+		cyy_writeb(info, CyRTPR,
 			(info->default_timeout ? info->default_timeout : 0x02));
 		/* 10ms rx timeout */
 
 		if (C_CLOCAL(tty)) {
 			/* without modem intr */
-			cy_writeb(base_addr + (CySRER << index),
-				readb(base_addr + (CySRER << index)) | CyMdmCh);
+			cyy_writeb(info, CySRER,
+					cyy_readb(info, CySRER) | CyMdmCh);
 			/* act on 1->0 modem transitions */
 			if ((cflag & CRTSCTS) && info->rflow) {
-				cy_writeb(base_addr + (CyMCOR1 << index),
+				cyy_writeb(info, CyMCOR1,
 					  (CyCTS | rflow_thr[i]));
 			} else {
-				cy_writeb(base_addr + (CyMCOR1 << index),
+				cyy_writeb(info, CyMCOR1,
 					  CyCTS);
 			}
 			/* act on 0->1 modem transitions */
-			cy_writeb(base_addr + (CyMCOR2 << index), CyCTS);
+			cyy_writeb(info, CyMCOR2, CyCTS);
 		} else {
 			/* without modem intr */
-			cy_writeb(base_addr + (CySRER << index),
-				  readb(base_addr +
-					   (CySRER << index)) | CyMdmCh);
+			cyy_writeb(info, CySRER,
+					cyy_readb(info, CySRER) | CyMdmCh);
 			/* act on 1->0 modem transitions */
 			if ((cflag & CRTSCTS) && info->rflow) {
-				cy_writeb(base_addr + (CyMCOR1 << index),
+				cyy_writeb(info, CyMCOR1,
 					  (CyDSR | CyCTS | CyRI | CyDCD |
 					   rflow_thr[i]));
 			} else {
-				cy_writeb(base_addr + (CyMCOR1 << index),
-					  CyDSR | CyCTS | CyRI | CyDCD);
+				cyy_writeb(info, CyMCOR1,
+						CyDSR | CyCTS | CyRI | CyDCD);
 			}
 			/* act on 0->1 modem transitions */
-			cy_writeb(base_addr + (CyMCOR2 << index),
-				  CyDSR | CyCTS | CyRI | CyDCD);
+			cyy_writeb(info, CyMCOR2,
+					CyDSR | CyCTS | CyRI | CyDCD);
 		}
 
 		if (i == 0)	/* baud rate is zero, turn off line */
@@ -2481,24 +2437,14 @@ check_and_exit:
  */
 static int get_lsr_info(struct cyclades_port *info, unsigned int __user *value)
 {
-	struct cyclades_card *card;
-	int chip, channel, index;
-	unsigned char status;
+	struct cyclades_card *card = info->card;
 	unsigned int result;
 	unsigned long flags;
-	void __iomem *base_addr;
+	u8 status;
 
-	card = info->card;
-	channel = (info->line) - (card->first_line);
 	if (!cy_is_Z(card)) {
-		chip = channel >> 2;
-		channel &= 0x03;
-		index = card->bus_index;
-		base_addr = card->base_addr + (cy_chip_offset[chip] << index);
-
 		spin_lock_irqsave(&card->card_lock, flags);
-		status = readb(base_addr + (CySRER << index)) &
-				(CyTxRdy | CyTxMpty);
+		status = cyy_readb(info, CySRER) & (CyTxRdy | CyTxMpty);
 		spin_unlock_irqrestore(&card->card_lock, flags);
 		result = (status ? 0 : TIOCSER_TEMT);
 	} else {
@@ -2512,29 +2458,23 @@ static int cy_tiocmget(struct tty_struct *tty, struct file *file)
 {
 	struct cyclades_port *info = tty->driver_data;
 	struct cyclades_card *card;
-	void __iomem *base_addr;
-	int result, channel;
+	int result;
 
 	if (serial_paranoia_check(info, tty->name, __func__))
 		return -ENODEV;
 
 	card = info->card;
-	channel = info->line - card->first_line;
 
 	lock_kernel();
 	if (!cy_is_Z(card)) {
 		unsigned long flags;
-		unsigned char status;
-		int chip = channel >> 2;
-		int index = card->bus_index;
-
-		channel &= 0x03;
-		base_addr = card->base_addr + (cy_chip_offset[chip] << index);
+		int channel = info->line - card->first_line;
+		u8 status;
 
 		spin_lock_irqsave(&card->card_lock, flags);
-		cy_writeb(base_addr + (CyCAR << index), (u8)channel);
-		status = readb(base_addr + (CyMSVR1 << index));
-		status |= readb(base_addr + (CyMSVR2 << index));
+		cyy_writeb(info, CyCAR, channel & 0x03);
+		status = cyy_readb(info, CyMSVR1);
+		status |= cyy_readb(info, CyMSVR2);
 		spin_unlock_irqrestore(&card->card_lock, flags);
 
 		if (info->rtsdtr_inv) {
@@ -2688,26 +2628,16 @@ static int cy_break(struct tty_struct *tty, int break_state)
 
 static int set_threshold(struct cyclades_port *info, unsigned long value)
 {
-	struct cyclades_card *card;
-	void __iomem *base_addr;
-	int channel, chip, index;
+	struct cyclades_card *card = info->card;
 	unsigned long flags;
 
-	card = info->card;
-	channel = info->line - card->first_line;
 	if (!cy_is_Z(card)) {
-		chip = channel >> 2;
-		channel &= 0x03;
-		index = card->bus_index;
-		base_addr =
-		    card->base_addr + (cy_chip_offset[chip] << index);
-
 		info->cor3 &= ~CyREC_FIFO;
 		info->cor3 |= value & CyREC_FIFO;
 
 		spin_lock_irqsave(&card->card_lock, flags);
-		cy_writeb(base_addr + (CyCOR3 << index), info->cor3);
-		cyy_issue_cmd(base_addr, CyCOR_CHANGE | CyCOR3ch, index);
+		cyy_writeb(info, CyCOR3, info->cor3);
+		cyy_issue_cmd(info, CyCOR_CHANGE | CyCOR3ch);
 		spin_unlock_irqrestore(&card->card_lock, flags);
 	}
 	return 0;
@@ -2716,20 +2646,10 @@ static int set_threshold(struct cyclades_port *info, unsigned long value)
 static int get_threshold(struct cyclades_port *info,
 						unsigned long __user *value)
 {
-	struct cyclades_card *card;
-	void __iomem *base_addr;
-	int channel, chip, index;
-	unsigned long tmp;
+	struct cyclades_card *card = info->card;
 
-	card = info->card;
-	channel = info->line - card->first_line;
 	if (!cy_is_Z(card)) {
-		chip = channel >> 2;
-		channel &= 0x03;
-		index = card->bus_index;
-		base_addr = card->base_addr + (cy_chip_offset[chip] << index);
-
-		tmp = readb(base_addr + (CyCOR3 << index)) & CyREC_FIFO;
+		u8 tmp = cyy_readb(info, CyCOR3) & CyREC_FIFO;
 		return put_user(tmp, value);
 	}
 	return 0;
@@ -2737,21 +2657,12 @@ static int get_threshold(struct cyclades_port *info,
 
 static int set_timeout(struct cyclades_port *info, unsigned long value)
 {
-	struct cyclades_card *card;
-	void __iomem *base_addr;
-	int channel, chip, index;
+	struct cyclades_card *card = info->card;
 	unsigned long flags;
 
-	card = info->card;
-	channel = info->line - card->first_line;
 	if (!cy_is_Z(card)) {
-		chip = channel >> 2;
-		channel &= 0x03;
-		index = card->bus_index;
-		base_addr = card->base_addr + (cy_chip_offset[chip] << index);
-
 		spin_lock_irqsave(&card->card_lock, flags);
-		cy_writeb(base_addr + (CyRTPR << index), value & 0xff);
+		cyy_writeb(info, CyRTPR, value & 0xff);
 		spin_unlock_irqrestore(&card->card_lock, flags);
 	}
 	return 0;
@@ -2760,20 +2671,10 @@ static int set_timeout(struct cyclades_port *info, unsigned long value)
 static int get_timeout(struct cyclades_port *info,
 						unsigned long __user *value)
 {
-	struct cyclades_card *card;
-	void __iomem *base_addr;
-	int channel, chip, index;
-	unsigned long tmp;
+	struct cyclades_card *card = info->card;
 
-	card = info->card;
-	channel = info->line - card->first_line;
 	if (!cy_is_Z(card)) {
-		chip = channel >> 2;
-		channel &= 0x03;
-		index = card->bus_index;
-		base_addr = card->base_addr + (cy_chip_offset[chip] << index);
-
-		tmp = readb(base_addr + (CyRTPR << index));
+		u8 tmp = cyy_readb(info, CyRTPR);
 		return put_user(tmp, value);
 	}
 	return 0;
@@ -3100,8 +3001,7 @@ static void cy_stop(struct tty_struct *tty)
 {
 	struct cyclades_card *cinfo;
 	struct cyclades_port *info = tty->driver_data;
-	void __iomem *base_addr;
-	int chip, channel, index;
+	int channel;
 	unsigned long flags;
 
 #ifdef CY_DEBUG_OTHER
@@ -3114,16 +3014,9 @@ static void cy_stop(struct tty_struct *tty)
 	cinfo = info->card;
 	channel = info->line - cinfo->first_line;
 	if (!cy_is_Z(cinfo)) {
-		index = cinfo->bus_index;
-		chip = channel >> 2;
-		channel &= 0x03;
-		base_addr = cinfo->base_addr + (cy_chip_offset[chip] << index);
-
 		spin_lock_irqsave(&cinfo->card_lock, flags);
-		cy_writeb(base_addr + (CyCAR << index),
-			(u_char)(channel & 0x0003)); /* index channel */
-		cy_writeb(base_addr + (CySRER << index),
-			  readb(base_addr + (CySRER << index)) & ~CyTxRdy);
+		cyy_writeb(info, CyCAR, channel & 0x03);
+		cyy_writeb(info, CySRER, cyy_readb(info, CySRER) & ~CyTxRdy);
 		spin_unlock_irqrestore(&cinfo->card_lock, flags);
 	}
 }				/* cy_stop */
@@ -3132,8 +3025,7 @@ static void cy_start(struct tty_struct *tty)
 {
 	struct cyclades_card *cinfo;
 	struct cyclades_port *info = tty->driver_data;
-	void __iomem *base_addr;
-	int chip, channel, index;
+	int channel;
 	unsigned long flags;
 
 #ifdef CY_DEBUG_OTHER
@@ -3145,17 +3037,10 @@ static void cy_start(struct tty_struct *tty)
 
 	cinfo = info->card;
 	channel = info->line - cinfo->first_line;
-	index = cinfo->bus_index;
 	if (!cy_is_Z(cinfo)) {
-		chip = channel >> 2;
-		channel &= 0x03;
-		base_addr = cinfo->base_addr + (cy_chip_offset[chip] << index);
-
 		spin_lock_irqsave(&cinfo->card_lock, flags);
-		cy_writeb(base_addr + (CyCAR << index),
-			(u_char) (channel & 0x0003));	/* index channel */
-		cy_writeb(base_addr + (CySRER << index),
-			  readb(base_addr + (CySRER << index)) | CyTxRdy);
+		cyy_writeb(info, CyCAR, channel & 0x03);
+		cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyTxRdy);
 		spin_unlock_irqrestore(&cinfo->card_lock, flags);
 	}
 }				/* cy_start */
@@ -3184,18 +3069,13 @@ 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;
+	cyy_writeb(info, CyCAR, channel & 0x03);
+	cd = cyy_readb(info, CyMSVR1) & CyDCD;
 	spin_unlock_irqrestore(&cinfo->card_lock, flags);
 
 	return cd;
@@ -3325,9 +3205,9 @@ static int __devinit cy_init_card(struct cyclades_card *cinfo)
 			info->cor3 = 0x08;	/* _very_ small rcv threshold */
 
 			chip_number = channel / CyPORTS_PER_CHIP;
-			info->chip_rev = readb(cinfo->base_addr +
-				      (cy_chip_offset[chip_number] << index) +
-				      (CyGFRCR << index));
+			info->u.cyy.base_addr = cinfo->base_addr +
+				(cy_chip_offset[chip_number] << index);
+			info->chip_rev = cyy_readb(info, CyGFRCR);
 
 			if (info->chip_rev >= CD1400_REV_J) {
 				/* It is a CD1400 rev. J or later */
diff --git a/include/linux/cyclades.h b/include/linux/cyclades.h
index 1eb87a6..bbebef7 100644
--- a/include/linux/cyclades.h
+++ b/include/linux/cyclades.h
@@ -544,7 +544,7 @@ struct cyclades_port {
 	struct cyclades_card	*card;
 	union {
 		struct {
-			int filler;
+			void __iomem *base_addr;
 		} cyy;
 		struct {
 			struct CH_CTRL __iomem	*ch_ctrl;
-- 
1.6.3.2


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

* [PATCH 13/13] Char: cyclades, remove more duplicated code
  2009-06-18  7:41 [PATCH 01/13] Char: cyclades, add tty refcounting Jiri Slaby
                   ` (10 preceding siblings ...)
  2009-06-18  7:41 ` [PATCH 12/13] Char: cyclades, introduce cyy_readb/writeb Jiri Slaby
@ 2009-06-18  7:41 ` Jiri Slaby
  2009-06-18 13:17 ` [PATCH 01/13] Char: cyclades, add tty refcounting Alan Cox
  12 siblings, 0 replies; 14+ messages in thread
From: Jiri Slaby @ 2009-06-18  7:41 UTC (permalink / raw)
  To: alan; +Cc: Andrew Morton, linux-kernel, Jiri Slaby

Remove duplicated code from cy_set_line_char. There were 2 if
branches with same contents except flags.

Branch only for the flags computation and use them in the only copy
of the code.

Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
---
 drivers/char/cyclades.c |   45 ++++++++++++++-------------------------------
 1 files changed, 14 insertions(+), 31 deletions(-)

diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index 76248aa..5cec450 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -2056,6 +2056,8 @@ static void cy_set_line_char(struct cyclades_port *info, struct tty_struct *tty)
 	channel = info->line - card->first_line;
 
 	if (!cy_is_Z(card)) {
+		u32 cflags;
+
 		/* baud rate */
 		baud = tty_get_baud_rate(tty);
 		if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
@@ -2197,37 +2199,18 @@ static void cy_set_line_char(struct cyclades_port *info, struct tty_struct *tty)
 			(info->default_timeout ? info->default_timeout : 0x02));
 		/* 10ms rx timeout */
 
-		if (C_CLOCAL(tty)) {
-			/* without modem intr */
-			cyy_writeb(info, CySRER,
-					cyy_readb(info, CySRER) | CyMdmCh);
-			/* act on 1->0 modem transitions */
-			if ((cflag & CRTSCTS) && info->rflow) {
-				cyy_writeb(info, CyMCOR1,
-					  (CyCTS | rflow_thr[i]));
-			} else {
-				cyy_writeb(info, CyMCOR1,
-					  CyCTS);
-			}
-			/* act on 0->1 modem transitions */
-			cyy_writeb(info, CyMCOR2, CyCTS);
-		} else {
-			/* without modem intr */
-			cyy_writeb(info, CySRER,
-					cyy_readb(info, CySRER) | CyMdmCh);
-			/* act on 1->0 modem transitions */
-			if ((cflag & CRTSCTS) && info->rflow) {
-				cyy_writeb(info, CyMCOR1,
-					  (CyDSR | CyCTS | CyRI | CyDCD |
-					   rflow_thr[i]));
-			} else {
-				cyy_writeb(info, CyMCOR1,
-						CyDSR | CyCTS | CyRI | CyDCD);
-			}
-			/* act on 0->1 modem transitions */
-			cyy_writeb(info, CyMCOR2,
-					CyDSR | CyCTS | CyRI | CyDCD);
-		}
+		cflags = CyCTS;
+		if (!C_CLOCAL(tty))
+			cflags |= CyDSR | CyRI | CyDCD;
+		/* without modem intr */
+		cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyMdmCh);
+		/* act on 1->0 modem transitions */
+		if ((cflag & CRTSCTS) && info->rflow)
+			cyy_writeb(info, CyMCOR1, cflags | rflow_thr[i]);
+		else
+			cyy_writeb(info, CyMCOR1, cflags);
+		/* act on 0->1 modem transitions */
+		cyy_writeb(info, CyMCOR2, cflags);
 
 		if (i == 0)	/* baud rate is zero, turn off line */
 			cyy_change_rts_dtr(info, 0, TIOCM_DTR);
-- 
1.6.3.2


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

* Re: [PATCH 01/13] Char: cyclades, add tty refcounting
  2009-06-18  7:41 [PATCH 01/13] Char: cyclades, add tty refcounting Jiri Slaby
                   ` (11 preceding siblings ...)
  2009-06-18  7:41 ` [PATCH 13/13] Char: cyclades, remove more duplicated code Jiri Slaby
@ 2009-06-18 13:17 ` Alan Cox
  12 siblings, 0 replies; 14+ messages in thread
From: Alan Cox @ 2009-06-18 13:17 UTC (permalink / raw)
  To: Jiri Slaby; +Cc: Andrew Morton, linux-kernel, Jiri Slaby

Series merged into ttydev tree ready for 2.6.32 window

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

end of thread, other threads:[~2009-06-18 13:16 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-06-18  7:41 [PATCH 01/13] Char: cyclades, add tty refcounting Jiri Slaby
2009-06-18  7:41 ` [PATCH 02/13] Char: cyclades, remove block_til_ready Jiri Slaby
2009-06-18  7:41 ` [PATCH 03/13] Char: cyclades, avoid addresses recomputation Jiri Slaby
2009-06-18  7:41 ` [PATCH 04/13] Char: cyclades, switch to tty_port_hangup Jiri Slaby
2009-06-18  7:41 ` [PATCH 05/13] Char: cyclades, close cleanup Jiri Slaby
2009-06-18  7:41 ` [PATCH 06/13] Char: cyclades, overall cleanup Jiri Slaby
2009-06-18  7:41 ` [PATCH 07/13] Char: cyclades, sleep instead busy-wait Jiri Slaby
2009-06-18  7:41 ` [PATCH 08/13] Char: cyclades, use dtr_rts helpers Jiri Slaby
2009-06-18  7:41 ` [PATCH 09/13] Char: cyclades, merge cy_startup tails Jiri Slaby
2009-06-18  7:41 ` [PATCH 10/13] Char: cyclades, ioctls cleanup Jiri Slaby
2009-06-18  7:41 ` [PATCH 11/13] Char: cyclades, tiocm cleanup Jiri Slaby
2009-06-18  7:41 ` [PATCH 12/13] Char: cyclades, introduce cyy_readb/writeb Jiri Slaby
2009-06-18  7:41 ` [PATCH 13/13] Char: cyclades, remove more duplicated code Jiri Slaby
2009-06-18 13:17 ` [PATCH 01/13] Char: cyclades, add tty refcounting Alan Cox

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.