aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/isicom.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/isicom.c')
-rw-r--r--drivers/char/isicom.c115
1 files changed, 25 insertions, 90 deletions
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
index 426bfdd7f3e0..300d5bd6cd06 100644
--- a/drivers/char/isicom.c
+++ b/drivers/char/isicom.c
@@ -793,35 +793,30 @@ static inline void isicom_setup_board(struct isi_board *bp)
793{ 793{
794 int channel; 794 int channel;
795 struct isi_port *port; 795 struct isi_port *port;
796 unsigned long flags;
797 796
798 spin_lock_irqsave(&bp->card_lock, flags); 797 bp->count++;
799 if (bp->status & BOARD_ACTIVE) { 798 if (!(bp->status & BOARD_INIT)) {
800 spin_unlock_irqrestore(&bp->card_lock, flags); 799 port = bp->ports;
801 return; 800 for (channel = 0; channel < bp->port_count; channel++, port++)
801 drop_dtr_rts(port);
802 } 802 }
803 port = bp->ports; 803 bp->status |= BOARD_ACTIVE | BOARD_INIT;
804 bp->status |= BOARD_ACTIVE;
805 for (channel = 0; channel < bp->port_count; channel++, port++)
806 drop_dtr_rts(port);
807 spin_unlock_irqrestore(&bp->card_lock, flags);
808} 804}
809 805
810static int isicom_setup_port(struct tty_struct *tty) 806/* Activate and thus setup board are protected from races against shutdown
807 by the tty_port mutex */
808
809static int isicom_activate(struct tty_port *tport, struct tty_struct *tty)
811{ 810{
812 struct isi_port *port = tty->driver_data; 811 struct isi_port *port = container_of(tport, struct isi_port, port);
813 struct isi_board *card = port->card; 812 struct isi_board *card = port->card;
814 unsigned long flags; 813 unsigned long flags;
815 814
816 if (port->port.flags & ASYNC_INITIALIZED) 815 if (tty_port_alloc_xmit_buf(tport) < 0)
817 return 0;
818 if (tty_port_alloc_xmit_buf(&port->port) < 0)
819 return -ENOMEM; 816 return -ENOMEM;
820 817
821 spin_lock_irqsave(&card->card_lock, flags); 818 spin_lock_irqsave(&card->card_lock, flags);
822 clear_bit(TTY_IO_ERROR, &tty->flags); 819 isicom_setup_board(card);
823 if (port->port.count == 1)
824 card->count++;
825 820
826 port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; 821 port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
827 822
@@ -832,9 +827,7 @@ static int isicom_setup_port(struct tty_struct *tty)
832 outw(((ISICOM_KILLTX | ISICOM_KILLRX) << 8) | 0x06, card->base); 827 outw(((ISICOM_KILLTX | ISICOM_KILLRX) << 8) | 0x06, card->base);
833 InterruptTheCard(card->base); 828 InterruptTheCard(card->base);
834 } 829 }
835
836 isicom_config_port(tty); 830 isicom_config_port(tty);
837 port->port.flags |= ASYNC_INITIALIZED;
838 spin_unlock_irqrestore(&card->card_lock, flags); 831 spin_unlock_irqrestore(&card->card_lock, flags);
839 832
840 return 0; 833 return 0;
@@ -871,85 +864,37 @@ static struct tty_port *isicom_find_port(struct tty_struct *tty)
871 864
872 return &port->port; 865 return &port->port;
873} 866}
874 867
875static int isicom_open(struct tty_struct *tty, struct file *filp) 868static int isicom_open(struct tty_struct *tty, struct file *filp)
876{ 869{
877 struct isi_port *port; 870 struct isi_port *port;
878 struct isi_board *card; 871 struct isi_board *card;
879 struct tty_port *tport; 872 struct tty_port *tport;
880 int error = 0;
881 873
882 tport = isicom_find_port(tty); 874 tport = isicom_find_port(tty);
883 if (tport == NULL) 875 if (tport == NULL)
884 return -ENODEV; 876 return -ENODEV;
885 port = container_of(tport, struct isi_port, port); 877 port = container_of(tport, struct isi_port, port);
886 card = &isi_card[BOARD(tty->index)]; 878 card = &isi_card[BOARD(tty->index)];
887 isicom_setup_board(card);
888 879
889 /* FIXME: locking on port.count etc */ 880 return tty_port_open(tport, tty, filp);
890 port->port.count++;
891 tty->driver_data = port;
892 tty_port_tty_set(&port->port, tty);
893 /* FIXME: Locking on Initialized flag */
894 if (!test_bit(ASYNCB_INITIALIZED, &tport->flags))
895 error = isicom_setup_port(tty);
896 if (error == 0)
897 error = tty_port_block_til_ready(&port->port, tty, filp);
898 return error;
899} 881}
900 882
901/* close et all */ 883/* close et all */
902 884
903static inline void isicom_shutdown_board(struct isi_board *bp)
904{
905 if (bp->status & BOARD_ACTIVE)
906 bp->status &= ~BOARD_ACTIVE;
907}
908
909/* card->lock HAS to be held */ 885/* card->lock HAS to be held */
910static void isicom_shutdown_port(struct isi_port *port) 886static void isicom_shutdown_port(struct isi_port *port)
911{ 887{
912 struct isi_board *card = port->card; 888 struct isi_board *card = port->card;
913 struct tty_struct *tty;
914
915 tty = tty_port_tty_get(&port->port);
916
917 if (!(port->port.flags & ASYNC_INITIALIZED)) {
918 tty_kref_put(tty);
919 return;
920 }
921
922 tty_port_free_xmit_buf(&port->port);
923 port->port.flags &= ~ASYNC_INITIALIZED;
924 /* 3rd October 2000 : Vinayak P Risbud */
925 tty_port_tty_set(&port->port, NULL);
926
927 /*Fix done by Anil .S on 30-04-2001
928 remote login through isi port has dtr toggle problem
929 due to which the carrier drops before the password prompt
930 appears on the remote end. Now we drop the dtr only if the
931 HUPCL(Hangup on close) flag is set for the tty*/
932
933 if (C_HUPCL(tty))
934 /* drop dtr on this port */
935 drop_dtr(port);
936
937 /* any other port uninits */
938 if (tty)
939 set_bit(TTY_IO_ERROR, &tty->flags);
940 889
941 if (--card->count < 0) { 890 if (--card->count < 0) {
942 pr_dbg("isicom_shutdown_port: bad board(0x%lx) count %d.\n", 891 pr_dbg("isicom_shutdown_port: bad board(0x%lx) count %d.\n",
943 card->base, card->count); 892 card->base, card->count);
944 card->count = 0; 893 card->count = 0;
945 } 894 }
946 895 /* last port was closed, shutdown that board too */
947 /* last port was closed, shutdown that boad too */ 896 if (!card->count)
948 if (C_HUPCL(tty)) { 897 card->status &= BOARD_ACTIVE;
949 if (!card->count)
950 isicom_shutdown_board(card);
951 }
952 tty_kref_put(tty);
953} 898}
954 899
955static void isicom_flush_buffer(struct tty_struct *tty) 900static void isicom_flush_buffer(struct tty_struct *tty)
@@ -968,7 +913,7 @@ static void isicom_flush_buffer(struct tty_struct *tty)
968 tty_wakeup(tty); 913 tty_wakeup(tty);
969} 914}
970 915
971static void isicom_close_port(struct tty_port *port) 916static void isicom_shutdown(struct tty_port *port)
972{ 917{
973 struct isi_port *ip = container_of(port, struct isi_port, port); 918 struct isi_port *ip = container_of(port, struct isi_port, port);
974 struct isi_board *card = ip->card; 919 struct isi_board *card = ip->card;
@@ -977,12 +922,11 @@ static void isicom_close_port(struct tty_port *port)
977 /* indicate to the card that no more data can be received 922 /* indicate to the card that no more data can be received
978 on this port */ 923 on this port */
979 spin_lock_irqsave(&card->card_lock, flags); 924 spin_lock_irqsave(&card->card_lock, flags);
980 if (port->flags & ASYNC_INITIALIZED) { 925 card->port_status &= ~(1 << ip->channel);
981 card->port_status &= ~(1 << ip->channel); 926 outw(card->port_status, card->base + 0x02);
982 outw(card->port_status, card->base + 0x02);
983 }
984 isicom_shutdown_port(ip); 927 isicom_shutdown_port(ip);
985 spin_unlock_irqrestore(&card->card_lock, flags); 928 spin_unlock_irqrestore(&card->card_lock, flags);
929 tty_port_free_xmit_buf(port);
986} 930}
987 931
988static void isicom_close(struct tty_struct *tty, struct file *filp) 932static 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)
991 struct tty_port *port = &ip->port; 935 struct tty_port *port = &ip->port;
992 if (isicom_paranoia_check(ip, tty->name, "isicom_close")) 936 if (isicom_paranoia_check(ip, tty->name, "isicom_close"))
993 return; 937 return;
994 938 tty_port_close(port, tty, filp);
995 if (tty_port_close_start(port, tty, filp) == 0)
996 return;
997 isicom_close_port(port);
998 isicom_flush_buffer(tty);
999 tty_port_close_end(port, tty);
1000} 939}
1001 940
1002/* write et all */ 941/* write et all */
@@ -1326,15 +1265,9 @@ static void isicom_start(struct tty_struct *tty)
1326static void isicom_hangup(struct tty_struct *tty) 1265static void isicom_hangup(struct tty_struct *tty)
1327{ 1266{
1328 struct isi_port *port = tty->driver_data; 1267 struct isi_port *port = tty->driver_data;
1329 unsigned long flags;
1330 1268
1331 if (isicom_paranoia_check(port, tty->name, "isicom_hangup")) 1269 if (isicom_paranoia_check(port, tty->name, "isicom_hangup"))
1332 return; 1270 return;
1333
1334 spin_lock_irqsave(&port->card->card_lock, flags);
1335 isicom_shutdown_port(port);
1336 spin_unlock_irqrestore(&port->card->card_lock, flags);
1337
1338 tty_port_hangup(&port->port); 1271 tty_port_hangup(&port->port);
1339} 1272}
1340 1273
@@ -1367,6 +1300,8 @@ static const struct tty_operations isicom_ops = {
1367static const struct tty_port_operations isicom_port_ops = { 1300static const struct tty_port_operations isicom_port_ops = {
1368 .carrier_raised = isicom_carrier_raised, 1301 .carrier_raised = isicom_carrier_raised,
1369 .dtr_rts = isicom_dtr_rts, 1302 .dtr_rts = isicom_dtr_rts,
1303 .activate = isicom_activate,
1304 .shutdown = isicom_shutdown,
1370}; 1305};
1371 1306
1372static int __devinit reset_card(struct pci_dev *pdev, 1307static int __devinit reset_card(struct pci_dev *pdev,