cyclades: remove block_til_ready
authorJiri Slaby <jirislaby@gmail.com>
Sat, 19 Sep 2009 20:13:12 +0000 (13:13 -0700)
committerLive-CD User <linux@linux.site>
Sat, 19 Sep 2009 20:13:12 +0000 (13:13 -0700)
Use a tty_port common instead. This saves lots of .text and makes the
code a lot more readable.

This involves separation of a dtr_rts handling, next patches will use
that to not duplicate the code all over the place.

Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/char/cyclades.c

index e2f731b..9e0cd70 100644 (file)
@@ -2172,199 +2172,6 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty)
  * ------------------------------------------------------------
  */
 
-static int
-block_til_ready(struct tty_struct *tty, struct file *filp,
-               struct cyclades_port *info)
-{
-       DECLARE_WAITQUEUE(wait, current);
-       struct cyclades_card *cinfo;
-       unsigned long flags;
-       int chip, channel, index;
-       int retval;
-       void __iomem *base_addr;
-
-       cinfo = info->card;
-       channel = info->line - cinfo->first_line;
-
-       /*
-        * If the device is in the middle of being closed, then block
-        * until it's done, and then try again.
-        */
-       if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) {
-               wait_event_interruptible(info->port.close_wait,
-                               !(info->port.flags & ASYNC_CLOSING));
-               return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;
-       }
-
-       /*
-        * If non-blocking mode is set, then make the check up front
-        * and then exit.
-        */
-       if ((filp->f_flags & O_NONBLOCK) ||
-                                       (tty->flags & (1 << TTY_IO_ERROR))) {
-               info->port.flags |= ASYNC_NORMAL_ACTIVE;
-               return 0;
-       }
-
-       /*
-        * Block waiting for the carrier detect and the line to become
-        * free (i.e., not in use by the callout).  While we are in
-        * this loop, info->port.count is dropped by one, so that
-        * cy_close() knows when to free things.  We restore it upon
-        * exit, either normal or abnormal.
-        */
-       retval = 0;
-       add_wait_queue(&info->port.open_wait, &wait);
-#ifdef CY_DEBUG_OPEN
-       printk(KERN_DEBUG "cyc block_til_ready before block: ttyC%d, "
-               "count = %d\n", info->line, info->port.count);
-#endif
-       spin_lock_irqsave(&cinfo->card_lock, flags);
-       if (!tty_hung_up_p(filp))
-               info->port.count--;
-       spin_unlock_irqrestore(&cinfo->card_lock, flags);
-#ifdef CY_DEBUG_COUNT
-       printk(KERN_DEBUG "cyc block_til_ready: (%d): decrementing count to "
-               "%d\n", current->pid, info->port.count);
-#endif
-       info->port.blocked_open++;
-
-       if (!cy_is_Z(cinfo)) {
-               chip = channel >> 2;
-               channel &= 0x03;
-               index = cinfo->bus_index;
-               base_addr = cinfo->base_addr + (cy_chip_offset[chip] << index);
-
-               while (1) {
-                       spin_lock_irqsave(&cinfo->card_lock, flags);
-                       if ((tty->termios->c_cflag & CBAUD)) {
-                               cy_writeb(base_addr + (CyCAR << index),
-                                         (u_char) channel);
-                               cy_writeb(base_addr + (CyMSVR1 << index),
-                                         CyRTS);
-                               cy_writeb(base_addr + (CyMSVR2 << index),
-                                         CyDTR);
-#ifdef CY_DEBUG_DTR
-                               printk(KERN_DEBUG "cyc:block_til_ready raising "
-                                       "DTR\n");
-                               printk(KERN_DEBUG "     status: 0x%x, 0x%x\n",
-                                       readb(base_addr + (CyMSVR1 << index)),
-                                       readb(base_addr + (CyMSVR2 << index)));
-#endif
-                       }
-                       spin_unlock_irqrestore(&cinfo->card_lock, flags);
-
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       if (tty_hung_up_p(filp) ||
-                                       !(info->port.flags & ASYNC_INITIALIZED)) {
-                               retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
-                                         -EAGAIN : -ERESTARTSYS);
-                               break;
-                       }
-
-                       spin_lock_irqsave(&cinfo->card_lock, flags);
-                       cy_writeb(base_addr + (CyCAR << index),
-                                 (u_char) channel);
-                       if (!(info->port.flags & ASYNC_CLOSING) && (C_CLOCAL(tty) ||
-                                       (readb(base_addr +
-                                               (CyMSVR1 << index)) & CyDCD))) {
-                               spin_unlock_irqrestore(&cinfo->card_lock, flags);
-                               break;
-                       }
-                       spin_unlock_irqrestore(&cinfo->card_lock, flags);
-
-                       if (signal_pending(current)) {
-                               retval = -ERESTARTSYS;
-                               break;
-                       }
-#ifdef CY_DEBUG_OPEN
-                       printk(KERN_DEBUG "cyc block_til_ready blocking: "
-                               "ttyC%d, count = %d\n",
-                               info->line, info->port.count);
-#endif
-                       schedule();
-               }
-       } else {
-               struct FIRM_ID __iomem *firm_id;
-               struct ZFW_CTRL __iomem *zfw_ctrl;
-               struct BOARD_CTRL __iomem *board_ctrl;
-               struct CH_CTRL __iomem *ch_ctrl;
-
-               base_addr = cinfo->base_addr;
-               firm_id = base_addr + ID_ADDRESS;
-               if (!cyz_is_loaded(cinfo)) {
-                       __set_current_state(TASK_RUNNING);
-                       remove_wait_queue(&info->port.open_wait, &wait);
-                       return -EINVAL;
-               }
-
-               zfw_ctrl = base_addr + (readl(&firm_id->zfwctrl_addr)
-                                                               & 0xfffff);
-               board_ctrl = &zfw_ctrl->board_ctrl;
-               ch_ctrl = zfw_ctrl->ch_ctrl;
-
-               while (1) {
-                       if ((tty->termios->c_cflag & CBAUD)) {
-                               cy_writel(&ch_ctrl[channel].rs_control,
-                                       readl(&ch_ctrl[channel].rs_control) |
-                                       C_RS_RTS | C_RS_DTR);
-                               retval = cyz_issue_cmd(cinfo,
-                                       channel, C_CM_IOCTLM, 0L);
-                               if (retval != 0) {
-                                       printk(KERN_ERR "cyc:block_til_ready "
-                                               "retval on ttyC%d was %x\n",
-                                               info->line, retval);
-                               }
-#ifdef CY_DEBUG_DTR
-                               printk(KERN_DEBUG "cyc:block_til_ready raising "
-                                       "Z DTR\n");
-#endif
-                       }
-
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       if (tty_hung_up_p(filp) ||
-                                       !(info->port.flags & ASYNC_INITIALIZED)) {
-                               retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
-                                         -EAGAIN : -ERESTARTSYS);
-                               break;
-                       }
-                       if (!(info->port.flags & ASYNC_CLOSING) && (C_CLOCAL(tty) ||
-                                       (readl(&ch_ctrl[channel].rs_status) &
-                                               C_RS_DCD))) {
-                               break;
-                       }
-                       if (signal_pending(current)) {
-                               retval = -ERESTARTSYS;
-                               break;
-                       }
-#ifdef CY_DEBUG_OPEN
-                       printk(KERN_DEBUG "cyc block_til_ready blocking: "
-                               "ttyC%d, count = %d\n",
-                               info->line, info->port.count);
-#endif
-                       schedule();
-               }
-       }
-       __set_current_state(TASK_RUNNING);
-       remove_wait_queue(&info->port.open_wait, &wait);
-       if (!tty_hung_up_p(filp)) {
-               info->port.count++;
-#ifdef CY_DEBUG_COUNT
-               printk(KERN_DEBUG "cyc:block_til_ready (%d): incrementing "
-                       "count to %d\n", current->pid, info->port.count);
-#endif
-       }
-       info->port.blocked_open--;
-#ifdef CY_DEBUG_OPEN
-       printk(KERN_DEBUG "cyc:block_til_ready after blocking: ttyC%d, "
-               "count = %d\n", info->line, info->port.count);
-#endif
-       if (retval)
-               return retval;
-       info->port.flags |= ASYNC_NORMAL_ACTIVE;
-       return 0;
-}                              /* block_til_ready */
-
 /*
  * This routine is called whenever a serial port is opened.  It
  * performs the serial-specific initialization for the tty structure.
@@ -2472,7 +2279,7 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
        if (retval)
                return retval;
 
-       retval = block_til_ready(tty, filp, info);
+       retval = tty_port_block_til_ready(&info->port, tty, filp);
        if (retval) {
 #ifdef CY_DEBUG_OPEN
                printk(KERN_DEBUG "cyc:cy_open returning after block_til_ready "
@@ -4312,6 +4119,111 @@ static void cy_hangup(struct tty_struct *tty)
        wake_up_interruptible(&info->port.open_wait);
 }                              /* cy_hangup */
 
+static int cyy_carrier_raised(struct tty_port *port)
+{
+       struct cyclades_port *info = container_of(port, struct cyclades_port,
+                       port);
+       struct cyclades_card *cinfo = info->card;
+       void __iomem *base = cinfo->base_addr;
+       unsigned long flags;
+       int channel = info->line - cinfo->first_line;
+       int chip = channel >> 2, index = cinfo->bus_index;
+       u32 cd;
+
+       channel &= 0x03;
+       base += cy_chip_offset[chip] << index;
+
+       spin_lock_irqsave(&cinfo->card_lock, flags);
+       cy_writeb(base + (CyCAR << index), (u8)channel);
+       cd = readb(base + (CyMSVR1 << index)) & CyDCD;
+       spin_unlock_irqrestore(&cinfo->card_lock, flags);
+
+       return cd;
+}
+
+static void cyy_dtr_rts(struct tty_port *port, int raise)
+{
+       struct cyclades_port *info = container_of(port, struct cyclades_port,
+                       port);
+       struct cyclades_card *cinfo = info->card;
+       void __iomem *base = cinfo->base_addr;
+       unsigned long flags;
+       int channel = info->line - cinfo->first_line;
+       int chip = channel >> 2, index = cinfo->bus_index;
+
+       channel &= 0x03;
+       base += cy_chip_offset[chip] << index;
+
+       spin_lock_irqsave(&cinfo->card_lock, flags);
+       cy_writeb(base + (CyCAR << index), (u8)channel);
+       cy_writeb(base + (CyMSVR1 << index), raise ? CyRTS : ~CyRTS);
+       cy_writeb(base + (CyMSVR2 << index), raise ? CyDTR : ~CyDTR);
+#ifdef CY_DEBUG_DTR
+       printk(KERN_DEBUG "%s: raising DTR\n", __func__);
+       printk(KERN_DEBUG "     status: 0x%x, 0x%x\n",
+                       readb(base + (CyMSVR1 << index)),
+                       readb(base + (CyMSVR2 << index)));
+#endif
+       spin_unlock_irqrestore(&cinfo->card_lock, flags);
+}
+
+static int cyz_carrier_raised(struct tty_port *port)
+{
+       struct cyclades_port *info = container_of(port, struct cyclades_port,
+                       port);
+       struct cyclades_card *cinfo = info->card;
+       void __iomem *base = cinfo->base_addr;
+       struct FIRM_ID __iomem *firm_id = base + ID_ADDRESS;
+       struct ZFW_CTRL __iomem *zfw_ctrl;
+       struct CH_CTRL __iomem *ch_ctrl;
+       int channel = info->line - cinfo->first_line;
+
+       zfw_ctrl = base + (readl(&firm_id->zfwctrl_addr) & 0xfffff);
+       ch_ctrl = zfw_ctrl->ch_ctrl;
+
+       return readl(&ch_ctrl[channel].rs_status) & C_RS_DCD;
+}
+
+static void cyz_dtr_rts(struct tty_port *port, int raise)
+{
+       struct cyclades_port *info = container_of(port, struct cyclades_port,
+                       port);
+       struct cyclades_card *cinfo = info->card;
+       void __iomem *base = cinfo->base_addr;
+       struct FIRM_ID __iomem *firm_id = base + ID_ADDRESS;
+       struct ZFW_CTRL __iomem *zfw_ctrl;
+       struct CH_CTRL __iomem *ch_ctrl;
+       int ret, channel = info->line - cinfo->first_line;
+       u32 rs;
+
+       zfw_ctrl = base + (readl(&firm_id->zfwctrl_addr) & 0xfffff);
+       ch_ctrl = zfw_ctrl->ch_ctrl;
+
+       rs = readl(&ch_ctrl[channel].rs_control);
+       if (raise)
+               rs |= C_RS_RTS | C_RS_DTR;
+       else
+               rs &= ~(C_RS_RTS | C_RS_DTR);
+       cy_writel(&ch_ctrl[channel].rs_control, rs);
+       ret = cyz_issue_cmd(cinfo, channel, C_CM_IOCTLM, 0L);
+       if (ret != 0)
+               printk(KERN_ERR "%s: retval on ttyC%d was %x\n",
+                               __func__, info->line, ret);
+#ifdef CY_DEBUG_DTR
+       printk(KERN_DEBUG "%s: raising Z DTR\n", __func__);
+#endif
+}
+
+static const struct tty_port_operations cyy_port_ops = {
+       .carrier_raised = cyy_carrier_raised,
+       .dtr_rts = cyy_dtr_rts,
+};
+
+static const struct tty_port_operations cyz_port_ops = {
+       .carrier_raised = cyz_carrier_raised,
+       .dtr_rts = cyz_dtr_rts,
+};
+
 /*
  * ---------------------------------------------------------------------
  * cy_init() and friends
@@ -4351,6 +4263,7 @@ static int __devinit cy_init_card(struct cyclades_card *cinfo)
                init_waitqueue_head(&info->delta_msr_wait);
 
                if (cy_is_Z(cinfo)) {
+                       info->port.ops = &cyz_port_ops;
                        info->type = PORT_STARTECH;
                        if (cinfo->hw_ver == ZO_V1)
                                info->xmit_fifo_size = CYZ_FIFO_SIZE;
@@ -4362,6 +4275,7 @@ static int __devinit cy_init_card(struct cyclades_card *cinfo)
 #endif
                } else {
                        int index = cinfo->bus_index;
+                       info->port.ops = &cyy_port_ops;
                        info->type = PORT_CIRRUS;
                        info->xmit_fifo_size = CyMAX_CHAR_FIFO;
                        info->cor1 = CyPARITY_NONE | Cy_1_STOP | Cy_8_BITS;