Commit 0f4974c4 authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6: (58 commits)
  tty: split the lock up a bit further
  tty: Move the leader test in disassociate
  tty: Push the bkl down a bit in the hangup code
  tty: Push the lock down further into the ldisc code
  tty: push the BKL down into the handlers a bit
  tty: moxa: split open lock
  tty: moxa: Kill the use of lock_kernel
  tty: moxa: Fix modem op locking
  tty: moxa: Kill off the throttle method
  tty: moxa: Locking clean up
  tty: moxa: rework the locking a bit
  tty: moxa: Use more tty_port ops
  tty: isicom: fix deadlock on shutdown
  tty: mxser: Use the new locking rules to fix setserial properly
  tty: mxser: use the tty_port_open method
  tty: isicom: sort out the board init logic
  tty: isicom: switch to the new tty_port_open helper
  tty: tty_port: Add a kref object to the tty port
  tty: istallion: tty port open/close methods
  tty: stallion: Convert to the tty_port_open/close methods
  ...
parents 3126c136 36ba782e
HAYES ESP DRIVER VERSION 2.1
A big thanks to the people at Hayes, especially Alan Adamson. Their support
has enabled me to provide enhancements to the driver.
Please report your experiences with this driver to me (arobinso@nyx.net). I
am looking for both positive and negative feedback.
*** IMPORTANT CHANGES FOR 2.1 ***
Support for PIO mode. Five situations will cause PIO mode to be used:
1) A multiport card is detected. PIO mode will always be used. (8 port cards
do not support DMA).
2) The DMA channel is set to an invalid value (anything other than 1 or 3).
3) The DMA buffer/channel could not be allocated. The port will revert to PIO
mode until it is reopened.
4) Less than a specified number of bytes need to be transferred to/from the
FIFOs. PIO mode will be used for that transfer only.
5) A port needs to do a DMA transfer and another port is already using the
DMA channel. PIO mode will be used for that transfer only.
Since the Hayes ESP seems to conflict with other cards (notably sound cards)
when using DMA, DMA is turned off by default. To use DMA, it must be turned
on explicitly, either with the "dma=" option described below or with
setserial. A multiport card can be forced into DMA mode by using setserial;
however, most multiport cards don't support DMA.
The latest version of setserial allows the enhanced configuration of the ESP
card to be viewed and modified.
***
This package contains the files needed to compile a module to support the Hayes
ESP card. The drivers are basically a modified version of the serial drivers.
Features:
- Uses the enhanced mode of the ESP card, allowing a wider range of
interrupts and features than compatibility mode
- Uses DMA and 16 bit PIO mode to transfer data to and from the ESP's FIFOs,
reducing CPU load
- Supports primary and secondary ports
If the driver is compiled as a module, the IRQs to use can be specified by
using the irq= option. The format is:
irq=[0x100],[0x140],[0x180],[0x200],[0x240],[0x280],[0x300],[0x380]
The address in brackets is the base address of the card. The IRQ of
nonexistent cards can be set to 0. If an IRQ of a card that does exist is set
to 0, the driver will attempt to guess at the correct IRQ. For example, to set
the IRQ of the card at address 0x300 to 12, the insmod command would be:
insmod esp irq=0,0,0,0,0,0,12,0
The custom divisor can be set by using the divisor= option. The format is the
same as for the irq= option. Each divisor value is a series of hex digits,
with each digit representing the divisor to use for a corresponding port. The
divisor value is constructed RIGHT TO LEFT. Specifying a nonzero divisor value
will automatically set the spd_cust flag. To calculate the divisor to use for
a certain baud rate, divide the port's base baud (generally 921600) by the
desired rate. For example, to set the divisor of the primary port at 0x300 to
4 and the divisor of the secondary port at 0x308 to 8, the insmod command would
be:
insmod esp divisor=0,0,0,0,0,0,0x84,0
The dma= option can be used to set the DMA channel. The channel can be either
1 or 3. Specifying any other value will force the driver to use PIO mode.
For example, to set the DMA channel to 3, the insmod command would be:
insmod esp dma=3
The rx_trigger= and tx_trigger= options can be used to set the FIFO trigger
levels. They specify when the ESP card should send an interrupt. Larger
values will decrease the number of interrupts; however, a value too high may
result in data loss. Valid values are 1 through 1023, with 768 being the
default. For example, to set the receive trigger level to 512 bytes and the
transmit trigger level to 700 bytes, the insmod command would be:
insmod esp rx_trigger=512 tx_trigger=700
The flow_off= and flow_on= options can be used to set the hardware flow off/
flow on levels. The flow on level must be lower than the flow off level, and
the flow off level should be higher than rx_trigger. Valid values are 1
through 1023, with 1016 being the default flow off level and 944 being the
default flow on level. For example, to set the flow off level to 1000 bytes
and the flow on level to 935 bytes, the insmod command would be:
insmod esp flow_off=1000 flow_on=935
The rx_timeout= option can be used to set the receive timeout value. This
value indicates how long after receiving the last character that the ESP card
should wait before signalling an interrupt. Valid values are 0 though 255,
with 128 being the default. A value too high will increase latency, and a
value too low will cause unnecessary interrupts. For example, to set the
receive timeout to 255, the insmod command would be:
insmod esp rx_timeout=255
The pio_threshold= option sets the threshold (in number of characters) for
using PIO mode instead of DMA mode. For example, if this value is 32,
transfers of 32 bytes or less will always use PIO mode.
insmod esp pio_threshold=32
Multiple options can be listed on the insmod command line by separating each
option with a space. For example:
insmod esp dma=3 trigger=512
The esp module can be automatically loaded when needed. To cause this to
happen, add the following lines to /etc/modprobe.conf (replacing the last line
with options for your configuration):
alias char-major-57 esp
alias char-major-58 esp
options esp irq=0,0,0,0,0,0,3,0 divisor=0,0,0,0,0,0,0x4,0
You may also need to run 'depmod -a'.
Devices must be created manually. To create the devices, note the output from
the module after it is inserted. The output will appear in the location where
kernel messages usually appear (usually /var/adm/messages). Create two devices
for each 'tty' mentioned, one with major of 57 and the other with major of 58.
The minor number should be the same as the tty number reported. The commands
would be (replace ? with the tty number):
mknod /dev/ttyP? c 57 ?
mknod /dev/cup? c 58 ?
For example, if the following line appears:
Oct 24 18:17:23 techno kernel: ttyP8 at 0x0140 (irq = 3) is an ESP primary port
...two devices should be created:
mknod /dev/ttyP8 c 57 8
mknod /dev/cup8 c 58 8
You may need to set the permissions on the devices:
chmod 666 /dev/ttyP*
chmod 666 /dev/cup*
The ESP module and the serial module should not conflict (they can be used at
the same time). After the ESP module has been loaded the ports on the ESP card
will no longer be accessible by the serial driver.
If I/O errors are experienced when accessing the port, check for IRQ and DMA
conflicts ('cat /proc/interrupts' and 'cat /proc/dma' for a list of IRQs and
DMAs currently in use).
Enjoy!
Andrew J. Robinson <arobinso@nyx.net>
......@@ -42,7 +42,8 @@ TTY side interfaces:
open() - Called when the line discipline is attached to
the terminal. No other call into the line
discipline for this tty will occur until it
completes successfully. Can sleep.
completes successfully. Returning an error will
prevent the ldisc from being attached. Can sleep.
close() - This is called on a terminal when the line
discipline is being unplugged. At the point of
......@@ -52,7 +53,7 @@ close() - This is called on a terminal when the line
hangup() - Called when the tty line is hung up.
The line discipline should cease I/O to the tty.
No further calls into the ldisc code will occur.
Can sleep.
The return value is ignored. Can sleep.
write() - A process is writing data through the line
discipline. Multiple write calls are serialized
......@@ -83,6 +84,10 @@ ioctl() - Called when an ioctl is handed to the tty layer
that might be for the ldisc. Multiple ioctl calls
may occur in parallel. May sleep.
compat_ioctl() - Called when a 32 bit ioctl is handed to the tty layer
that might be for the ldisc. Multiple ioctl calls
may occur in parallel. May sleep.
Driver Side Interfaces:
receive_buf() - Hand buffers of bytes from the driver to the ldisc
......
......@@ -196,7 +196,7 @@ static const struct file_operations rs_proc_fops = {
.release = single_release,
};
static struct tty_operations serial_ops = {
static const struct tty_operations serial_ops = {
.open = rs_open,
.close = rs_close,
.write = rs_write,
......
......@@ -201,19 +201,6 @@ config DIGIEPCA
To compile this driver as a module, choose M here: the
module will be called epca.
config ESPSERIAL
tristate "Hayes ESP serial port support"
depends on SERIAL_NONSTANDARD && ISA && ISA_DMA_API && BROKEN
help
This is a driver which supports Hayes ESP serial ports. Both single
port cards and multiport cards are supported. Make sure to read
<file:Documentation/hayes-esp.txt>.
To compile this driver as a module, choose M here: the
module will be called esp.
If unsure, say N.
config MOXA_INTELLIO
tristate "Moxa Intellio support"
depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI)
......
......@@ -18,7 +18,6 @@ obj-$(CONFIG_CONSOLE_TRANSLATIONS) += consolemap.o consolemap_deftbl.o
obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o
obj-$(CONFIG_AUDIT) += tty_audit.o
obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o
obj-$(CONFIG_ESPSERIAL) += esp.o
obj-$(CONFIG_MVME147_SCC) += generic_serial.o vme_scc.o
obj-$(CONFIG_MVME162_SCC) += generic_serial.o vme_scc.o
obj-$(CONFIG_BVME6000_SCC) += generic_serial.o vme_scc.o
......
......@@ -226,7 +226,7 @@ bfin_jc_wait_until_sent(struct tty_struct *tty, int timeout)
}
}
static struct tty_operations bfin_jc_ops = {
static const struct tty_operations bfin_jc_ops = {
.open = bfin_jc_open,
.close = bfin_jc_close,
.write = bfin_jc_write,
......
......@@ -935,7 +935,7 @@ static int info_open(struct tty_struct *tty, struct file *filp)
return 0;
}
static struct tty_operations info_ops = {
static const struct tty_operations info_ops = {
.open = info_open,
.ioctl = info_ioctl,
};
......
This diff is collapsed.
......@@ -793,35 +793,30 @@ static inline void isicom_setup_board(struct isi_board *bp)
{
int channel;
struct isi_port *port;
unsigned long flags;
spin_lock_irqsave(&bp->card_lock, flags);
if (bp->status & BOARD_ACTIVE) {
spin_unlock_irqrestore(&bp->card_lock, flags);
return;
bp->count++;
if (!(bp->status & BOARD_INIT)) {
port = bp->ports;
for (channel = 0; channel < bp->port_count; channel++, port++)
drop_dtr_rts(port);
}
port = bp->ports;
bp->status |= BOARD_ACTIVE;
for (channel = 0; channel < bp->port_count; channel++, port++)
drop_dtr_rts(port);
spin_unlock_irqrestore(&bp->card_lock, flags);
bp->status |= BOARD_ACTIVE | BOARD_INIT;
}
static int isicom_setup_port(struct tty_struct *tty)
/* Activate and thus setup board are protected from races against shutdown
by the tty_port mutex */
static int isicom_activate(struct tty_port *tport, struct tty_struct *tty)
{
struct isi_port *port = tty->driver_data;
struct isi_port *port = container_of(tport, struct isi_port, port);
struct isi_board *card = port->card;
unsigned long flags;
if (port->port.flags & ASYNC_INITIALIZED)
return 0;
if (tty_port_alloc_xmit_buf(&port->port) < 0)
if (tty_port_alloc_xmit_buf(tport) < 0)
return -ENOMEM;
spin_lock_irqsave(&card->card_lock, flags);
clear_bit(TTY_IO_ERROR, &tty->flags);
if (port->port.count == 1)
card->count++;
isicom_setup_board(card);
port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
......@@ -832,9 +827,7 @@ static int isicom_setup_port(struct tty_struct *tty)
outw(((ISICOM_KILLTX | ISICOM_KILLRX) << 8) | 0x06, card->base);
InterruptTheCard(card->base);
}
isicom_config_port(tty);
port->port.flags |= ASYNC_INITIALIZED;
spin_unlock_irqrestore(&card->card_lock, flags);
return 0;
......@@ -871,85 +864,37 @@ static struct tty_port *isicom_find_port(struct tty_struct *tty)
return &port->port;
}
static int isicom_open(struct tty_struct *tty, struct file *filp)
{
struct isi_port *port;
struct isi_board *card;
struct tty_port *tport;
int error = 0;
tport = isicom_find_port(tty);
if (tport == NULL)
return -ENODEV;
port = container_of(tport, struct isi_port, port);
card = &isi_card[BOARD(tty->index)];
isicom_setup_board(card);
/* FIXME: locking on port.count etc */
port->port.count++;
tty->driver_data = port;
tty_port_tty_set(&port->port, tty);
/* FIXME: Locking on Initialized flag */
if (!test_bit(ASYNCB_INITIALIZED, &tport->flags))
error = isicom_setup_port(tty);
if (error == 0)
error = tty_port_block_til_ready(&port->port, tty, filp);
return error;
return tty_port_open(tport, tty, filp);
}
/* close et all */
static inline void isicom_shutdown_board(struct isi_board *bp)
{
if (bp->status & BOARD_ACTIVE)
bp->status &= ~BOARD_ACTIVE;
}
/* card->lock HAS to be held */
static void isicom_shutdown_port(struct isi_port *port)
{
struct isi_board *card = port->card;
struct tty_struct *tty;
tty = tty_port_tty_get(&port->port);
if (!(port->port.flags & ASYNC_INITIALIZED)) {
tty_kref_put(tty);
return;
}
tty_port_free_xmit_buf(&port->port);
port->port.flags &= ~ASYNC_INITIALIZED;
/* 3rd October 2000 : Vinayak P Risbud */
tty_port_tty_set(&port->port, NULL);
/*Fix done by Anil .S on 30-04-2001
remote login through isi port has dtr toggle problem
due to which the carrier drops before the password prompt
appears on the remote end. Now we drop the dtr only if the
HUPCL(Hangup on close) flag is set for the tty*/
if (C_HUPCL(tty))
/* drop dtr on this port */
drop_dtr(port);
/* any other port uninits */
if (tty)
set_bit(TTY_IO_ERROR, &tty->flags);
if (--card->count < 0) {
pr_dbg("isicom_shutdown_port: bad board(0x%lx) count %d.\n",
card->base, card->count);
card->count = 0;
}
/* last port was closed, shutdown that boad too */
if (C_HUPCL(tty)) {
if (!card->count)
isicom_shutdown_board(card);
}
tty_kref_put(tty);
/* last port was closed, shutdown that board too */
if (!card->count)
card->status &= BOARD_ACTIVE;
}
static void isicom_flush_buffer(struct tty_struct *tty)
......@@ -968,7 +913,7 @@ static void isicom_flush_buffer(struct tty_struct *tty)
tty_wakeup(tty);
}
static void isicom_close_port(struct tty_port *port)
static void isicom_shutdown(struct tty_port *port)
{
struct isi_port *ip = container_of(port, struct isi_port, port);
struct isi_board *card = ip->card;
......@@ -977,12 +922,11 @@ static void isicom_close_port(struct tty_port *port)
/* indicate to the card that no more data can be received
on this port */
spin_lock_irqsave(&card->card_lock, flags);
if (port->flags & ASYNC_INITIALIZED) {
card->port_status &= ~(1 << ip->channel);
outw(card->port_status, card->base + 0x02);
}
card->port_status &= ~(1 << ip->channel);
outw(card->port_status, card->base + 0x02);
isicom_shutdown_port(ip);
spin_unlock_irqrestore(&card->card_lock, flags);
tty_port_free_xmit_buf(port);
}
static void isicom_close(struct tty_struct *tty, struct file *filp)
......@@ -991,12 +935,7 @@ static void isicom_close(struct tty_struct *tty, struct file *filp)
struct tty_port *port = &ip->port;
if (isicom_paranoia_check(ip, tty->name, "isicom_close"))
return;
if (tty_port_close_start(port, tty, filp) == 0)
return;
isicom_close_port(port);
isicom_flush_buffer(tty);
tty_port_close_end(port, tty);
tty_port_close(port, tty, filp);
}
/* write et all */
......@@ -1326,15 +1265,9 @@ static void isicom_start(struct tty_struct *tty)
static void isicom_hangup(struct tty_struct *tty)
{
struct isi_port *port = tty->driver_data;
unsigned long flags;
if (isicom_paranoia_check(port, tty->name, "isicom_hangup"))
return;
spin_lock_irqsave(&port->card->card_lock, flags);
isicom_shutdown_port(port);
spin_unlock_irqrestore(&port->card->card_lock, flags);
tty_port_hangup(&port->port);
}
......@@ -1367,6 +1300,8 @@ static const struct tty_operations isicom_ops = {
static const struct tty_port_operations isicom_port_ops = {
.carrier_raised = isicom_carrier_raised,
.dtr_rts = isicom_dtr_rts,
.activate = isicom_activate,
.shutdown = isicom_shutdown,
};
static int __devinit reset_card(struct pci_dev *pdev,
......
......@@ -213,7 +213,6 @@ static int stli_shared;
* with the slave. Most of them need to be updated atomically, so always
* use the bit setting operations (unless protected by cli/sti).
*/
#define ST_INITIALIZING 1
#define ST_OPENING 2
#define ST_CLOSING 3
#define ST_CMDING 4
......@@ -621,7 +620,7 @@ static int stli_brdinit(struct stlibrd *brdp);
static int stli_startbrd(struct stlibrd *brdp);
static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, loff_t *offp);
static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t count, loff_t *offp);
static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);
static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg);
static void stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp);
static void stli_poll(unsigned long arg);
static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp);
......@@ -704,7 +703,7 @@ static const struct file_operations stli_fsiomem = {
.owner = THIS_MODULE,
.read = stli_memread,
.write = stli_memwrite,
.ioctl = stli_memioctl,
.unlocked_ioctl = stli_memioctl,
};
/*****************************************************************************/
......@@ -783,13 +782,32 @@ static int stli_parsebrd(struct stlconf *confp, char **argp)
/*****************************************************************************/
/*
* On the first open of the device setup the port hardware, and
* initialize the per port data structure. Since initializing the port
* requires several commands to the board we will need to wait for any
* other open that is already initializing the port.
*
* Locking: protected by the port mutex.
*/
static int stli_activate(struct tty_port *port, struct tty_struct *tty)
{
struct stliport *portp = container_of(port, struct stliport, port);
struct stlibrd *brdp = stli_brds[portp->brdnr];
int rc;
if ((rc = stli_initopen(tty, brdp, portp)) >= 0)
clear_bit(TTY_IO_ERROR, &tty->flags);
wake_up_interruptible(&portp->raw_wait);
return rc;
}
static int stli_open(struct tty_struct *tty, struct file *filp)
{
struct stlibrd *brdp;
struct stliport *portp;
struct tty_port *port;
unsigned int minordev, brdnr, portnr;
int rc;
minordev = tty->index;
brdnr = MINOR2BRD(minordev);
......@@ -809,95 +827,56 @@ static int stli_open(struct tty_struct *tty, struct file *filp)
return -ENODEV;
if (portp->devnr < 1)
return -ENODEV;
port = &portp->port;
/*
* On the first open of the device setup the port hardware, and
* initialize the per port data structure. Since initializing the port
* requires several commands to the board we will need to wait for any
* other open that is already initializing the port.
*
* Review - locking
*/
tty_port_tty_set(port, tty);
tty->driver_data = portp;
port->count++;
wait_event_interruptible(portp->raw_wait,
!test_bit(ST_INITIALIZING, &portp->state));
if (signal_pending(current))
return -ERESTARTSYS;
if ((portp->port.flags & ASYNC_INITIALIZED) == 0) {
set_bit(ST_INITIALIZING, &portp->state);
if ((rc = stli_initopen(tty, brdp, portp)) >= 0) {
/* Locking */
port->flags |= ASYNC_INITIALIZED;
clear_bit(TTY_IO_ERROR, &tty->flags);
}
clear_bit(ST_INITIALIZING, &portp->state);
wake_up_interruptible(&portp->raw_wait);
if (rc < 0)
return rc;
}
return tty_port_block_til_ready(&portp->port, tty, filp);
return tty_port_open(&portp->port, tty, filp);
}
/*****************************************************************************/
static void stli_close(struct tty_struct *tty, struct file *filp)
static void stli_shutdown(struct tty_port *port)
{
struct stlibrd *brdp;
struct stliport *portp;
struct tty_port *port;
unsigned long ftype;
unsigned long flags;
struct stliport *portp = container_of(port, struct stliport, port);
portp = tty->driver_data;
if (portp == NULL)
if (portp->brdnr >= stli_nrbrds)
return;
port = &portp->port;
if (tty_port_close_start(port, tty, filp) == 0)
brdp = stli_brds[portp->brdnr];
if (brdp == NULL)
return;
/*
* May want to wait for data to drain before closing. The BUSY flag
* keeps track of whether we are still transmitting or not. It is
* updated by messages from the slave - indicating when all chars
* really have drained.
*/
spin_lock_irqsave(&stli_lock, flags);
if (tty == stli_txcooktty)
stli_flushchars(tty);
spin_unlock_irqrestore(&stli_lock, flags);
/* We end up doing this twice for the moment. This needs looking at
eventually. Note we still use portp->closing_wait as a result */
if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE)
tty_wait_until_sent(tty, portp->closing_wait);
/*
* May want to wait for data to drain before closing. The BUSY
* flag keeps track of whether we are still transmitting or not.
* It is updated by messages from the slave - indicating when all
* chars really have drained.
*/
/* FIXME: port locking here needs attending to */
port->flags &= ~ASYNC_INITIALIZED;
if (!test_bit(ST_CLOSING, &portp->state))
stli_rawclose(brdp, portp, 0, 0);
brdp = stli_brds[portp->brdnr];
stli_rawclose(brdp, portp, 0, 0);
if (tty->termios->c_cflag & HUPCL) {
stli_mkasysigs(&portp->asig, 0, 0);
if (test_bit(ST_CMDING, &portp->state))
set_bit(ST_DOSIGS, &portp->state);
else
stli_sendcmd(brdp, portp, A_SETSIGNALS, &portp->asig,
sizeof(asysigs_t), 0);
}
spin_lock_irqsave(&stli_lock, flags);
clear_bit(ST_TXBUSY, &portp->state);
clear_bit(ST_RXSTOP, &portp->state);
set_bit(TTY_IO_ERROR, &tty->flags);
tty_ldisc_flush(tty);
set_bit(ST_DOFLUSHRX, &portp->state);
stli_flushbuffer(tty);
spin_unlock_irqrestore(&stli_lock, flags);
tty_port_close_end(port, tty);
tty_port_tty_set(port, NULL);
ftype = FLUSHTX | FLUSHRX;
stli_cmdwait(brdp, portp, A_FLUSH, &ftype, sizeof(u32), 0);
}
static void stli_close(struct tty_struct *tty, struct file *filp)
{
struct stliport *portp = tty->driver_data;
unsigned long flags;
if (portp == NULL)
return;
spin_lock_irqsave(&stli_lock, flags);
/* Flush any internal buffering out first */
if (tty == stli_txcooktty)
stli_flushchars(tty);
spin_unlock_irqrestore(&stli_lock, flags);
tty_port_close(&portp->port, tty, filp);
}
/*****************************************************************************/
......@@ -1724,6 +1703,7 @@ static void stli_start(struct tty_struct *tty)
/*****************************************************************************/
/*
* Hangup this port. This is pretty much like closing the port, only
* a little more brutal. No waiting for data to drain. Shutdown the
......@@ -1733,47 +1713,8 @@ static void stli_start(struct tty_struct *tty)
static void stli_hangup(struct tty_struct *tty)
{
struct stliport *portp;
struct stlibrd *brdp;
struct tty_port *port;
unsigned long flags;
portp = tty->driver_data;
if (portp == NULL)
return;
if (portp->brdnr >= stli_nrbrds)
return;
brdp = stli_brds[portp->brdnr];
if (brdp == NULL)
return;
port = &portp->port;
spin_lock_irqsave(&port->lock, flags);
port->flags &= ~ASYNC_INITIALIZED;
spin_unlock_irqrestore(&port->lock, flags);
if (!test_bit(ST_CLOSING, &portp->state))
stli_rawclose(brdp, portp, 0, 0);
spin_lock_irqsave(&stli_lock, flags);
if (tty->termios->c_cflag & HUPCL) {
stli_mkasysigs(&portp->asig, 0, 0);
if (test_bit(ST_CMDING, &portp->state)) {
set_bit(ST_DOSIGS, &portp->state);
set_bit(ST_DOFLUSHTX, &portp->state);
set_bit(ST_DOFLUSHRX, &portp->state);
} else {
stli_sendcmd(brdp, portp, A_SETSIGNALSF,
&portp->asig, sizeof(asysigs_t), 0);
}
}
clear_bit(ST_TXBUSY, &portp->state);
clear_bit(ST_RXSTOP, &portp->state);
set_bit(TTY_IO_ERROR, &tty->flags);
spin_unlock_irqrestore(&stli_lock, flags);
tty_port_hangup(port);
struct stliport *portp = tty->driver_data;
tty_port_hangup(&portp->port);
}
/*****************************************************************************/
......@@ -4311,7 +4252,7 @@ static int stli_getbrdstruct(struct stlibrd __user *arg)
* reset it, and start/stop it.
*/
static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg)
{
struct stlibrd *brdp;
int brdnr, rc, done;
......@@ -4356,7 +4297,7 @@ static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, un
* Now handle the board specific ioctls. These all depend on the
* minor number of the device they were called from.