aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Cox <alan@linux.intel.com>2009-09-19 16:13:17 -0400
committerLive-CD User <linux@linux.site>2009-09-19 16:13:17 -0400
commit5342b77c4123ba39f911d92a813295fb3bb21f69 (patch)
tree9a1e0019453b81ca4bb9e729764887a27e175688
parent46fb782522092f772c6ce2b129f201ca6e1e15a2 (diff)
slip: Clean up create and destroy
The network layer now has a destructor we can hook to clean up the slip devices array. That needs us to initiate unregister events in the right places which with the current tty layer we can do, and with network refcounting is safe to do. Signed-off-by: Alan Cox <alan@lxorguk.ukuu.org.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/net/slip.c96
1 files changed, 23 insertions, 73 deletions
diff --git a/drivers/net/slip.c b/drivers/net/slip.c
index 26f6ee93a064..e17c535a577e 100644
--- a/drivers/net/slip.c
+++ b/drivers/net/slip.c
@@ -616,6 +616,14 @@ static void sl_uninit(struct net_device *dev)
616 sl_free_bufs(sl); 616 sl_free_bufs(sl);
617} 617}
618 618
619/* Hook the destructor so we can free slip devices at the right point in time */
620static void sl_free_netdev(struct net_device *dev)
621{
622 int i = dev->base_addr;
623 free_netdev(dev);
624 slip_devs[i] = NULL;
625}
626
619static const struct net_device_ops sl_netdev_ops = { 627static const struct net_device_ops sl_netdev_ops = {
620 .ndo_init = sl_init, 628 .ndo_init = sl_init,
621 .ndo_uninit = sl_uninit, 629 .ndo_uninit = sl_uninit,
@@ -634,7 +642,7 @@ static const struct net_device_ops sl_netdev_ops = {
634static void sl_setup(struct net_device *dev) 642static void sl_setup(struct net_device *dev)
635{ 643{
636 dev->netdev_ops = &sl_netdev_ops; 644 dev->netdev_ops = &sl_netdev_ops;
637 dev->destructor = free_netdev; 645 dev->destructor = sl_free_netdev;
638 646
639 dev->hard_header_len = 0; 647 dev->hard_header_len = 0;
640 dev->addr_len = 0; 648 dev->addr_len = 0;
@@ -712,8 +720,6 @@ static void sl_sync(void)
712static struct slip *sl_alloc(dev_t line) 720static struct slip *sl_alloc(dev_t line)
713{ 721{
714 int i; 722 int i;
715 int sel = -1;
716 int score = -1;
717 struct net_device *dev = NULL; 723 struct net_device *dev = NULL;
718 struct slip *sl; 724 struct slip *sl;
719 725
@@ -724,55 +730,7 @@ static struct slip *sl_alloc(dev_t line)
724 dev = slip_devs[i]; 730 dev = slip_devs[i];
725 if (dev == NULL) 731 if (dev == NULL)
726 break; 732 break;
727
728 sl = netdev_priv(dev);
729 if (sl->leased) {
730 if (sl->line != line)
731 continue;
732 if (sl->tty)
733 return NULL;
734
735 /* Clear ESCAPE & ERROR flags */
736 sl->flags &= (1 << SLF_INUSE);
737 return sl;
738 }
739
740 if (sl->tty)
741 continue;
742
743 if (current->pid == sl->pid) {
744 if (sl->line == line && score < 3) {
745 sel = i;
746 score = 3;
747 continue;
748 }
749 if (score < 2) {
750 sel = i;
751 score = 2;
752 }
753 continue;
754 }
755 if (sl->line == line && score < 1) {
756 sel = i;
757 score = 1;
758 continue;
759 }
760 if (score < 0) {
761 sel = i;
762 score = 0;
763 }
764 }
765
766 if (sel >= 0) {
767 i = sel;
768 dev = slip_devs[i];
769 if (score > 1) {
770 sl = netdev_priv(dev);
771 sl->flags &= (1 << SLF_INUSE);
772 return sl;
773 }
774 } 733 }
775
776 /* Sorry, too many, all slots in use */ 734 /* Sorry, too many, all slots in use */
777 if (i >= slip_maxdev) 735 if (i >= slip_maxdev)
778 return NULL; 736 return NULL;
@@ -909,30 +867,13 @@ err_exit:
909} 867}
910 868
911/* 869/*
912
913 FIXME: 1,2 are fixed 3 was never true anyway.
914
915 Let me to blame a bit.
916 1. TTY module calls this funstion on soft interrupt.
917 2. TTY module calls this function WITH MASKED INTERRUPTS!
918 3. TTY module does not notify us about line discipline
919 shutdown,
920
921 Seems, now it is clean. The solution is to consider netdevice and
922 line discipline sides as two independent threads.
923
924 By-product (not desired): sl? does not feel hangups and remains open.
925 It is supposed, that user level program (dip, diald, slattach...)
926 will catch SIGHUP and make the rest of work.
927
928 I see no way to make more with current tty code. --ANK
929 */
930
931/*
932 * Close down a SLIP channel. 870 * Close down a SLIP channel.
933 * This means flushing out any pending queues, and then returning. This 871 * This means flushing out any pending queues, and then returning. This
934 * call is serialized against other ldisc functions. 872 * call is serialized against other ldisc functions.
873 *
874 * We also use this method fo a hangup event
935 */ 875 */
876
936static void slip_close(struct tty_struct *tty) 877static void slip_close(struct tty_struct *tty)
937{ 878{
938 struct slip *sl = tty->disc_data; 879 struct slip *sl = tty->disc_data;
@@ -951,10 +892,16 @@ static void slip_close(struct tty_struct *tty)
951 del_timer_sync(&sl->keepalive_timer); 892 del_timer_sync(&sl->keepalive_timer);
952 del_timer_sync(&sl->outfill_timer); 893 del_timer_sync(&sl->outfill_timer);
953#endif 894#endif
954 895 /* Flush network side */
955 /* Count references from TTY module */ 896 unregister_netdev(sl->dev);
897 /* This will complete via sl_free_netdev */
956} 898}
957 899
900static int slip_hangup(struct tty_struct *tty)
901{
902 slip_close(tty);
903 return 0;
904}
958 /************************************************************************ 905 /************************************************************************
959 * STANDARD SLIP ENCAPSULATION * 906 * STANDARD SLIP ENCAPSULATION *
960 ************************************************************************/ 907 ************************************************************************/
@@ -1311,6 +1258,7 @@ static struct tty_ldisc_ops sl_ldisc = {
1311 .name = "slip", 1258 .name = "slip",
1312 .open = slip_open, 1259 .open = slip_open,
1313 .close = slip_close, 1260 .close = slip_close,
1261 .hangup = slip_hangup,
1314 .ioctl = slip_ioctl, 1262 .ioctl = slip_ioctl,
1315 .receive_buf = slip_receive_buf, 1263 .receive_buf = slip_receive_buf,
1316 .write_wakeup = slip_write_wakeup, 1264 .write_wakeup = slip_write_wakeup,
@@ -1384,6 +1332,8 @@ static void __exit slip_exit(void)
1384 } 1332 }
1385 } while (busy && time_before(jiffies, timeout)); 1333 } while (busy && time_before(jiffies, timeout));
1386 1334
1335 /* FIXME: hangup is async so we should wait when doing this second
1336 phase */
1387 1337
1388 for (i = 0; i < slip_maxdev; i++) { 1338 for (i = 0; i < slip_maxdev; i++) {
1389 dev = slip_devs[i]; 1339 dev = slip_devs[i];