diff options
author | Federico Vaga <federico.vaga@cern.ch> | 2014-09-02 11:31:41 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-09-24 02:13:13 -0400 |
commit | 82a82340bab6c251e0705339f60763718eaa2a22 (patch) | |
tree | 949a69ef011d3fdb4046b302029e30b01d13d98b | |
parent | 36c53b3cc3fac6952af68f43609b15ae050c9318 (diff) |
ipoctal: get carrier driver to avoid rmmod
Signed-off-by: Federico Vaga <federico.vaga@cern.ch>
Acked-by: Samuel Iglesias Gonsalvez <siglesias@igalia.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/ipack/devices/ipoctal.c | 30 |
1 files changed, 27 insertions, 3 deletions
diff --git a/drivers/ipack/devices/ipoctal.c b/drivers/ipack/devices/ipoctal.c index a1514a79e487..42700815d05f 100644 --- a/drivers/ipack/devices/ipoctal.c +++ b/drivers/ipack/devices/ipoctal.c | |||
@@ -55,6 +55,12 @@ struct ipoctal { | |||
55 | u8 __iomem *int_space; | 55 | u8 __iomem *int_space; |
56 | }; | 56 | }; |
57 | 57 | ||
58 | static inline struct ipoctal *chan_to_ipoctal(struct ipoctal_channel *chan, | ||
59 | unsigned int index) | ||
60 | { | ||
61 | return container_of(chan, struct ipoctal, channel[index]); | ||
62 | } | ||
63 | |||
58 | static void ipoctal_reset_channel(struct ipoctal_channel *channel) | 64 | static void ipoctal_reset_channel(struct ipoctal_channel *channel) |
59 | { | 65 | { |
60 | iowrite8(CR_DISABLE_RX | CR_DISABLE_TX, &channel->regs->w.cr); | 66 | iowrite8(CR_DISABLE_RX | CR_DISABLE_TX, &channel->regs->w.cr); |
@@ -82,12 +88,20 @@ static int ipoctal_port_activate(struct tty_port *port, struct tty_struct *tty) | |||
82 | 88 | ||
83 | static int ipoctal_open(struct tty_struct *tty, struct file *file) | 89 | static int ipoctal_open(struct tty_struct *tty, struct file *file) |
84 | { | 90 | { |
85 | struct ipoctal_channel *channel; | 91 | struct ipoctal_channel *channel = dev_get_drvdata(tty->dev); |
92 | struct ipoctal *ipoctal = chan_to_ipoctal(channel, tty->index); | ||
93 | int err; | ||
86 | 94 | ||
87 | channel = dev_get_drvdata(tty->dev); | ||
88 | tty->driver_data = channel; | 95 | tty->driver_data = channel; |
89 | 96 | ||
90 | return tty_port_open(&channel->tty_port, tty, file); | 97 | if (!ipack_get_carrier(ipoctal->dev)) |
98 | return -EBUSY; | ||
99 | |||
100 | err = tty_port_open(&channel->tty_port, tty, file); | ||
101 | if (err) | ||
102 | ipack_put_carrier(ipoctal->dev); | ||
103 | |||
104 | return err; | ||
91 | } | 105 | } |
92 | 106 | ||
93 | static void ipoctal_reset_stats(struct ipoctal_stats *stats) | 107 | static void ipoctal_reset_stats(struct ipoctal_stats *stats) |
@@ -629,6 +643,15 @@ static void ipoctal_shutdown(struct tty_struct *tty) | |||
629 | clear_bit(ASYNCB_INITIALIZED, &channel->tty_port.flags); | 643 | clear_bit(ASYNCB_INITIALIZED, &channel->tty_port.flags); |
630 | } | 644 | } |
631 | 645 | ||
646 | static void ipoctal_cleanup(struct tty_struct *tty) | ||
647 | { | ||
648 | struct ipoctal_channel *channel = tty->driver_data; | ||
649 | struct ipoctal *ipoctal = chan_to_ipoctal(channel, tty->index); | ||
650 | |||
651 | /* release the carrier driver */ | ||
652 | ipack_put_carrier(ipoctal->dev); | ||
653 | } | ||
654 | |||
632 | static const struct tty_operations ipoctal_fops = { | 655 | static const struct tty_operations ipoctal_fops = { |
633 | .ioctl = NULL, | 656 | .ioctl = NULL, |
634 | .open = ipoctal_open, | 657 | .open = ipoctal_open, |
@@ -640,6 +663,7 @@ static const struct tty_operations ipoctal_fops = { | |||
640 | .get_icount = ipoctal_get_icount, | 663 | .get_icount = ipoctal_get_icount, |
641 | .hangup = ipoctal_hangup, | 664 | .hangup = ipoctal_hangup, |
642 | .shutdown = ipoctal_shutdown, | 665 | .shutdown = ipoctal_shutdown, |
666 | .cleanup = ipoctal_cleanup, | ||
643 | }; | 667 | }; |
644 | 668 | ||
645 | static int ipoctal_probe(struct ipack_device *dev) | 669 | static int ipoctal_probe(struct ipack_device *dev) |