diff options
author | Jiri Slaby <jirislaby@gmail.com> | 2009-09-19 16:13:12 -0400 |
---|---|---|
committer | Live-CD User <linux@linux.site> | 2009-09-19 16:13:12 -0400 |
commit | f0737579424dd2c4e68bdd54c718455a3f42c7b5 (patch) | |
tree | 32f332b945f816342f620deb2d5b3ce432d53b98 /drivers/char/cyclades.c | |
parent | d13549f804d2965a9f279a8ff867f35d949572c8 (diff) |
cyclades: remove block_til_ready
Use a tty_port common instead. This saves lots of .text and makes the
code a lot more readable.
This involves separation of a dtr_rts handling, next patches will use
that to not duplicate the code all over the place.
Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/char/cyclades.c')
-rw-r--r-- | 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 e2f731b70763..9e0cd7020aef 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c | |||
@@ -2172,199 +2172,6 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty) | |||
2172 | * ------------------------------------------------------------ | 2172 | * ------------------------------------------------------------ |
2173 | */ | 2173 | */ |
2174 | 2174 | ||
2175 | static int | ||
2176 | block_til_ready(struct tty_struct *tty, struct file *filp, | ||
2177 | struct cyclades_port *info) | ||
2178 | { | ||
2179 | DECLARE_WAITQUEUE(wait, current); | ||
2180 | struct cyclades_card *cinfo; | ||
2181 | unsigned long flags; | ||
2182 | int chip, channel, index; | ||
2183 | int retval; | ||
2184 | void __iomem *base_addr; | ||
2185 | |||
2186 | cinfo = info->card; | ||
2187 | channel = info->line - cinfo->first_line; | ||
2188 | |||
2189 | /* | ||
2190 | * If the device is in the middle of being closed, then block | ||
2191 | * until it's done, and then try again. | ||
2192 | */ | ||
2193 | if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) { | ||
2194 | wait_event_interruptible(info->port.close_wait, | ||
2195 | !(info->port.flags & ASYNC_CLOSING)); | ||
2196 | return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS; | ||
2197 | } | ||
2198 | |||
2199 | /* | ||
2200 | * If non-blocking mode is set, then make the check up front | ||
2201 | * and then exit. | ||
2202 | */ | ||
2203 | if ((filp->f_flags & O_NONBLOCK) || | ||
2204 | (tty->flags & (1 << TTY_IO_ERROR))) { | ||
2205 | info->port.flags |= ASYNC_NORMAL_ACTIVE; | ||
2206 | return 0; | ||
2207 | } | ||
2208 | |||
2209 | /* | ||
2210 | * Block waiting for the carrier detect and the line to become | ||
2211 | * free (i.e., not in use by the callout). While we are in | ||
2212 | * this loop, info->port.count is dropped by one, so that | ||
2213 | * cy_close() knows when to free things. We restore it upon | ||
2214 | * exit, either normal or abnormal. | ||
2215 | */ | ||
2216 | retval = 0; | ||
2217 | add_wait_queue(&info->port.open_wait, &wait); | ||
2218 | #ifdef CY_DEBUG_OPEN | ||
2219 | printk(KERN_DEBUG "cyc block_til_ready before block: ttyC%d, " | ||
2220 | "count = %d\n", info->line, info->port.count); | ||
2221 | #endif | ||
2222 | spin_lock_irqsave(&cinfo->card_lock, flags); | ||
2223 | if (!tty_hung_up_p(filp)) | ||
2224 | info->port.count--; | ||
2225 | spin_unlock_irqrestore(&cinfo->card_lock, flags); | ||
2226 | #ifdef CY_DEBUG_COUNT | ||
2227 | printk(KERN_DEBUG "cyc block_til_ready: (%d): decrementing count to " | ||
2228 | "%d\n", current->pid, info->port.count); | ||
2229 | #endif | ||
2230 | info->port.blocked_open++; | ||
2231 | |||
2232 | if (!cy_is_Z(cinfo)) { | ||
2233 | chip = channel >> 2; | ||
2234 | channel &= 0x03; | ||
2235 | index = cinfo->bus_index; | ||
2236 | base_addr = cinfo->base_addr + (cy_chip_offset[chip] << index); | ||
2237 | |||
2238 | while (1) { | ||
2239 | spin_lock_irqsave(&cinfo->card_lock, flags); | ||
2240 | if ((tty->termios->c_cflag & CBAUD)) { | ||
2241 | cy_writeb(base_addr + (CyCAR << index), | ||
2242 | (u_char) channel); | ||
2243 | cy_writeb(base_addr + (CyMSVR1 << index), | ||
2244 | CyRTS); | ||
2245 | cy_writeb(base_addr + (CyMSVR2 << index), | ||
2246 | CyDTR); | ||
2247 | #ifdef CY_DEBUG_DTR | ||
2248 | printk(KERN_DEBUG "cyc:block_til_ready raising " | ||
2249 | "DTR\n"); | ||
2250 | printk(KERN_DEBUG " status: 0x%x, 0x%x\n", | ||
2251 | readb(base_addr + (CyMSVR1 << index)), | ||
2252 | readb(base_addr + (CyMSVR2 << index))); | ||
2253 | #endif | ||
2254 | } | ||
2255 | spin_unlock_irqrestore(&cinfo->card_lock, flags); | ||
2256 | |||
2257 | set_current_state(TASK_INTERRUPTIBLE); | ||
2258 | if (tty_hung_up_p(filp) || | ||
2259 | !(info->port.flags & ASYNC_INITIALIZED)) { | ||
2260 | retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ? | ||
2261 | -EAGAIN : -ERESTARTSYS); | ||
2262 | break; | ||
2263 | } | ||
2264 | |||
2265 | spin_lock_irqsave(&cinfo->card_lock, flags); | ||
2266 | cy_writeb(base_addr + (CyCAR << index), | ||
2267 | (u_char) channel); | ||
2268 | if (!(info->port.flags & ASYNC_CLOSING) && (C_CLOCAL(tty) || | ||
2269 | (readb(base_addr + | ||
2270 | (CyMSVR1 << index)) & CyDCD))) { | ||
2271 | spin_unlock_irqrestore(&cinfo->card_lock, flags); | ||
2272 | break; | ||
2273 | } | ||
2274 | spin_unlock_irqrestore(&cinfo->card_lock, flags); | ||
2275 | |||
2276 | if (signal_pending(current)) { | ||
2277 | retval = -ERESTARTSYS; | ||
2278 | break; | ||
2279 | } | ||
2280 | #ifdef CY_DEBUG_OPEN | ||
2281 | printk(KERN_DEBUG "cyc block_til_ready blocking: " | ||
2282 | "ttyC%d, count = %d\n", | ||
2283 | info->line, info->port.count); | ||
2284 | #endif | ||
2285 | schedule(); | ||
2286 | } | ||
2287 | } else { | ||
2288 | struct FIRM_ID __iomem *firm_id; | ||
2289 | struct ZFW_CTRL __iomem *zfw_ctrl; | ||
2290 | struct BOARD_CTRL __iomem *board_ctrl; | ||
2291 | struct CH_CTRL __iomem *ch_ctrl; | ||
2292 | |||
2293 | base_addr = cinfo->base_addr; | ||
2294 | firm_id = base_addr + ID_ADDRESS; | ||
2295 | if (!cyz_is_loaded(cinfo)) { | ||
2296 | __set_current_state(TASK_RUNNING); | ||
2297 | remove_wait_queue(&info->port.open_wait, &wait); | ||
2298 | return -EINVAL; | ||
2299 | } | ||
2300 | |||
2301 | zfw_ctrl = base_addr + (readl(&firm_id->zfwctrl_addr) | ||
2302 | & 0xfffff); | ||
2303 | board_ctrl = &zfw_ctrl->board_ctrl; | ||
2304 | ch_ctrl = zfw_ctrl->ch_ctrl; | ||
2305 | |||
2306 | while (1) { | ||
2307 | if ((tty->termios->c_cflag & CBAUD)) { | ||
2308 | cy_writel(&ch_ctrl[channel].rs_control, | ||
2309 | readl(&ch_ctrl[channel].rs_control) | | ||
2310 | C_RS_RTS | C_RS_DTR); | ||
2311 | retval = cyz_issue_cmd(cinfo, | ||
2312 | channel, C_CM_IOCTLM, 0L); | ||
2313 | if (retval != 0) { | ||
2314 | printk(KERN_ERR "cyc:block_til_ready " | ||
2315 | "retval on ttyC%d was %x\n", | ||
2316 | info->line, retval); | ||
2317 | } | ||
2318 | #ifdef CY_DEBUG_DTR | ||
2319 | printk(KERN_DEBUG "cyc:block_til_ready raising " | ||
2320 | "Z DTR\n"); | ||
2321 | #endif | ||
2322 | } | ||
2323 | |||
2324 | set_current_state(TASK_INTERRUPTIBLE); | ||
2325 | if (tty_hung_up_p(filp) || | ||
2326 | !(info->port.flags & ASYNC_INITIALIZED)) { | ||
2327 | retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ? | ||
2328 | -EAGAIN : -ERESTARTSYS); | ||
2329 | break; | ||
2330 | } | ||
2331 | if (!(info->port.flags & ASYNC_CLOSING) && (C_CLOCAL(tty) || | ||
2332 | (readl(&ch_ctrl[channel].rs_status) & | ||
2333 | C_RS_DCD))) { | ||
2334 | break; | ||
2335 | } | ||
2336 | if (signal_pending(current)) { | ||
2337 | retval = -ERESTARTSYS; | ||
2338 | break; | ||
2339 | } | ||
2340 | #ifdef CY_DEBUG_OPEN | ||
2341 | printk(KERN_DEBUG "cyc block_til_ready blocking: " | ||
2342 | "ttyC%d, count = %d\n", | ||
2343 | info->line, info->port.count); | ||
2344 | #endif | ||
2345 | schedule(); | ||
2346 | } | ||
2347 | } | ||
2348 | __set_current_state(TASK_RUNNING); | ||
2349 | remove_wait_queue(&info->port.open_wait, &wait); | ||
2350 | if (!tty_hung_up_p(filp)) { | ||
2351 | info->port.count++; | ||
2352 | #ifdef CY_DEBUG_COUNT | ||
2353 | printk(KERN_DEBUG "cyc:block_til_ready (%d): incrementing " | ||
2354 | "count to %d\n", current->pid, info->port.count); | ||
2355 | #endif | ||
2356 | } | ||
2357 | info->port.blocked_open--; | ||
2358 | #ifdef CY_DEBUG_OPEN | ||
2359 | printk(KERN_DEBUG "cyc:block_til_ready after blocking: ttyC%d, " | ||
2360 | "count = %d\n", info->line, info->port.count); | ||
2361 | #endif | ||
2362 | if (retval) | ||
2363 | return retval; | ||
2364 | info->port.flags |= ASYNC_NORMAL_ACTIVE; | ||
2365 | return 0; | ||
2366 | } /* block_til_ready */ | ||
2367 | |||
2368 | /* | 2175 | /* |
2369 | * This routine is called whenever a serial port is opened. It | 2176 | * This routine is called whenever a serial port is opened. It |
2370 | * performs the serial-specific initialization for the tty structure. | 2177 | * performs the serial-specific initialization for the tty structure. |
@@ -2472,7 +2279,7 @@ static int cy_open(struct tty_struct *tty, struct file *filp) | |||
2472 | if (retval) | 2279 | if (retval) |
2473 | return retval; | 2280 | return retval; |
2474 | 2281 | ||
2475 | retval = block_til_ready(tty, filp, info); | 2282 | retval = tty_port_block_til_ready(&info->port, tty, filp); |
2476 | if (retval) { | 2283 | if (retval) { |
2477 | #ifdef CY_DEBUG_OPEN | 2284 | #ifdef CY_DEBUG_OPEN |
2478 | printk(KERN_DEBUG "cyc:cy_open returning after block_til_ready " | 2285 | printk(KERN_DEBUG "cyc:cy_open returning after block_til_ready " |
@@ -4312,6 +4119,111 @@ static void cy_hangup(struct tty_struct *tty) | |||
4312 | wake_up_interruptible(&info->port.open_wait); | 4119 | wake_up_interruptible(&info->port.open_wait); |
4313 | } /* cy_hangup */ | 4120 | } /* cy_hangup */ |
4314 | 4121 | ||
4122 | static int cyy_carrier_raised(struct tty_port *port) | ||
4123 | { | ||
4124 | struct cyclades_port *info = container_of(port, struct cyclades_port, | ||
4125 | port); | ||
4126 | struct cyclades_card *cinfo = info->card; | ||
4127 | void __iomem *base = cinfo->base_addr; | ||
4128 | unsigned long flags; | ||
4129 | int channel = info->line - cinfo->first_line; | ||
4130 | int chip = channel >> 2, index = cinfo->bus_index; | ||
4131 | u32 cd; | ||
4132 | |||
4133 | channel &= 0x03; | ||
4134 | base += cy_chip_offset[chip] << index; | ||
4135 | |||
4136 | spin_lock_irqsave(&cinfo->card_lock, flags); | ||
4137 | cy_writeb(base + (CyCAR << index), (u8)channel); | ||
4138 | cd = readb(base + (CyMSVR1 << index)) & CyDCD; | ||
4139 | spin_unlock_irqrestore(&cinfo->card_lock, flags); | ||
4140 | |||
4141 | return cd; | ||
4142 | } | ||
4143 | |||
4144 | static void cyy_dtr_rts(struct tty_port *port, int raise) | ||
4145 | { | ||
4146 | struct cyclades_port *info = container_of(port, struct cyclades_port, | ||
4147 | port); | ||
4148 | struct cyclades_card *cinfo = info->card; | ||
4149 | void __iomem *base = cinfo->base_addr; | ||
4150 | unsigned long flags; | ||
4151 | int channel = info->line - cinfo->first_line; | ||
4152 | int chip = channel >> 2, index = cinfo->bus_index; | ||
4153 | |||
4154 | channel &= 0x03; | ||
4155 | base += cy_chip_offset[chip] << index; | ||
4156 | |||
4157 | spin_lock_irqsave(&cinfo->card_lock, flags); | ||
4158 | cy_writeb(base + (CyCAR << index), (u8)channel); | ||
4159 | cy_writeb(base + (CyMSVR1 << index), raise ? CyRTS : ~CyRTS); | ||
4160 | cy_writeb(base + (CyMSVR2 << index), raise ? CyDTR : ~CyDTR); | ||
4161 | #ifdef CY_DEBUG_DTR | ||
4162 | printk(KERN_DEBUG "%s: raising DTR\n", __func__); | ||
4163 | printk(KERN_DEBUG " status: 0x%x, 0x%x\n", | ||
4164 | readb(base + (CyMSVR1 << index)), | ||
4165 | readb(base + (CyMSVR2 << index))); | ||
4166 | #endif | ||
4167 | spin_unlock_irqrestore(&cinfo->card_lock, flags); | ||
4168 | } | ||
4169 | |||
4170 | static int cyz_carrier_raised(struct tty_port *port) | ||
4171 | { | ||
4172 | struct cyclades_port *info = container_of(port, struct cyclades_port, | ||
4173 | port); | ||
4174 | struct cyclades_card *cinfo = info->card; | ||
4175 | void __iomem *base = cinfo->base_addr; | ||
4176 | struct FIRM_ID __iomem *firm_id = base + ID_ADDRESS; | ||
4177 | struct ZFW_CTRL __iomem *zfw_ctrl; | ||
4178 | struct CH_CTRL __iomem *ch_ctrl; | ||
4179 | int channel = info->line - cinfo->first_line; | ||
4180 | |||
4181 | zfw_ctrl = base + (readl(&firm_id->zfwctrl_addr) & 0xfffff); | ||
4182 | ch_ctrl = zfw_ctrl->ch_ctrl; | ||
4183 | |||
4184 | return readl(&ch_ctrl[channel].rs_status) & C_RS_DCD; | ||
4185 | } | ||
4186 | |||
4187 | static void cyz_dtr_rts(struct tty_port *port, int raise) | ||
4188 | { | ||
4189 | struct cyclades_port *info = container_of(port, struct cyclades_port, | ||
4190 | port); | ||
4191 | struct cyclades_card *cinfo = info->card; | ||
4192 | void __iomem *base = cinfo->base_addr; | ||
4193 | struct FIRM_ID __iomem *firm_id = base + ID_ADDRESS; | ||
4194 | struct ZFW_CTRL __iomem *zfw_ctrl; | ||
4195 | struct CH_CTRL __iomem *ch_ctrl; | ||
4196 | int ret, channel = info->line - cinfo->first_line; | ||
4197 | u32 rs; | ||
4198 | |||
4199 | zfw_ctrl = base + (readl(&firm_id->zfwctrl_addr) & 0xfffff); | ||
4200 | ch_ctrl = zfw_ctrl->ch_ctrl; | ||
4201 | |||
4202 | rs = readl(&ch_ctrl[channel].rs_control); | ||
4203 | if (raise) | ||
4204 | rs |= C_RS_RTS | C_RS_DTR; | ||
4205 | else | ||
4206 | rs &= ~(C_RS_RTS | C_RS_DTR); | ||
4207 | cy_writel(&ch_ctrl[channel].rs_control, rs); | ||
4208 | ret = cyz_issue_cmd(cinfo, channel, C_CM_IOCTLM, 0L); | ||
4209 | if (ret != 0) | ||
4210 | printk(KERN_ERR "%s: retval on ttyC%d was %x\n", | ||
4211 | __func__, info->line, ret); | ||
4212 | #ifdef CY_DEBUG_DTR | ||
4213 | printk(KERN_DEBUG "%s: raising Z DTR\n", __func__); | ||
4214 | #endif | ||
4215 | } | ||
4216 | |||
4217 | static const struct tty_port_operations cyy_port_ops = { | ||
4218 | .carrier_raised = cyy_carrier_raised, | ||
4219 | .dtr_rts = cyy_dtr_rts, | ||
4220 | }; | ||
4221 | |||
4222 | static const struct tty_port_operations cyz_port_ops = { | ||
4223 | .carrier_raised = cyz_carrier_raised, | ||
4224 | .dtr_rts = cyz_dtr_rts, | ||
4225 | }; | ||
4226 | |||
4315 | /* | 4227 | /* |
4316 | * --------------------------------------------------------------------- | 4228 | * --------------------------------------------------------------------- |
4317 | * cy_init() and friends | 4229 | * cy_init() and friends |
@@ -4351,6 +4263,7 @@ static int __devinit cy_init_card(struct cyclades_card *cinfo) | |||
4351 | init_waitqueue_head(&info->delta_msr_wait); | 4263 | init_waitqueue_head(&info->delta_msr_wait); |
4352 | 4264 | ||
4353 | if (cy_is_Z(cinfo)) { | 4265 | if (cy_is_Z(cinfo)) { |
4266 | info->port.ops = &cyz_port_ops; | ||
4354 | info->type = PORT_STARTECH; | 4267 | info->type = PORT_STARTECH; |
4355 | if (cinfo->hw_ver == ZO_V1) | 4268 | if (cinfo->hw_ver == ZO_V1) |
4356 | info->xmit_fifo_size = CYZ_FIFO_SIZE; | 4269 | info->xmit_fifo_size = CYZ_FIFO_SIZE; |
@@ -4362,6 +4275,7 @@ static int __devinit cy_init_card(struct cyclades_card *cinfo) | |||
4362 | #endif | 4275 | #endif |
4363 | } else { | 4276 | } else { |
4364 | int index = cinfo->bus_index; | 4277 | int index = cinfo->bus_index; |
4278 | info->port.ops = &cyy_port_ops; | ||
4365 | info->type = PORT_CIRRUS; | 4279 | info->type = PORT_CIRRUS; |
4366 | info->xmit_fifo_size = CyMAX_CHAR_FIFO; | 4280 | info->xmit_fifo_size = CyMAX_CHAR_FIFO; |
4367 | info->cor1 = CyPARITY_NONE | Cy_1_STOP | Cy_8_BITS; | 4281 | info->cor1 = CyPARITY_NONE | Cy_1_STOP | Cy_8_BITS; |