1 /*
2  *	LAPB release 002
3  *
4  *	This code REQUIRES 2.1.15 or higher/ NET3.038
5  *
6  *	This module:
7  *		This module is free software; you can redistribute it and/or
8  *		modify it under the terms of the GNU General Public License
9  *		as published by the Free Software Foundation; either version
10  *		2 of the License, or (at your option) any later version.
11  *
12  *	History
13  *	LAPB 001	Jonathan Naylor	Started Coding
14  *	LAPB 002	Jonathan Naylor	New timer architecture.
15  */
16 
17 #include <linux/errno.h>
18 #include <linux/types.h>
19 #include <linux/socket.h>
20 #include <linux/in.h>
21 #include <linux/kernel.h>
22 #include <linux/jiffies.h>
23 #include <linux/timer.h>
24 #include <linux/string.h>
25 #include <linux/sockios.h>
26 #include <linux/net.h>
27 #include <linux/inet.h>
28 #include <linux/skbuff.h>
29 #include <net/sock.h>
30 #include <asm/uaccess.h>
31 #include <linux/fcntl.h>
32 #include <linux/mm.h>
33 #include <linux/interrupt.h>
34 #include <net/lapb.h>
35 
36 static void lapb_t1timer_expiry(unsigned long);
37 static void lapb_t2timer_expiry(unsigned long);
38 
lapb_start_t1timer(struct lapb_cb * lapb)39 void lapb_start_t1timer(struct lapb_cb *lapb)
40 {
41 	del_timer(&lapb->t1timer);
42 
43 	lapb->t1timer.data     = (unsigned long)lapb;
44 	lapb->t1timer.function = &lapb_t1timer_expiry;
45 	lapb->t1timer.expires  = jiffies + lapb->t1;
46 
47 	add_timer(&lapb->t1timer);
48 }
49 
lapb_start_t2timer(struct lapb_cb * lapb)50 void lapb_start_t2timer(struct lapb_cb *lapb)
51 {
52 	del_timer(&lapb->t2timer);
53 
54 	lapb->t2timer.data     = (unsigned long)lapb;
55 	lapb->t2timer.function = &lapb_t2timer_expiry;
56 	lapb->t2timer.expires  = jiffies + lapb->t2;
57 
58 	add_timer(&lapb->t2timer);
59 }
60 
lapb_stop_t1timer(struct lapb_cb * lapb)61 void lapb_stop_t1timer(struct lapb_cb *lapb)
62 {
63 	del_timer(&lapb->t1timer);
64 }
65 
lapb_stop_t2timer(struct lapb_cb * lapb)66 void lapb_stop_t2timer(struct lapb_cb *lapb)
67 {
68 	del_timer(&lapb->t2timer);
69 }
70 
lapb_t1timer_running(struct lapb_cb * lapb)71 int lapb_t1timer_running(struct lapb_cb *lapb)
72 {
73 	return timer_pending(&lapb->t1timer);
74 }
75 
lapb_t2timer_expiry(unsigned long param)76 static void lapb_t2timer_expiry(unsigned long param)
77 {
78 	struct lapb_cb *lapb = (struct lapb_cb *)param;
79 
80 	if (lapb->condition & LAPB_ACK_PENDING_CONDITION) {
81 		lapb->condition &= ~LAPB_ACK_PENDING_CONDITION;
82 		lapb_timeout_response(lapb);
83 	}
84 }
85 
lapb_t1timer_expiry(unsigned long param)86 static void lapb_t1timer_expiry(unsigned long param)
87 {
88 	struct lapb_cb *lapb = (struct lapb_cb *)param;
89 
90 	switch (lapb->state) {
91 
92 		/*
93 		 *	If we are a DCE, keep going DM .. DM .. DM
94 		 */
95 		case LAPB_STATE_0:
96 			if (lapb->mode & LAPB_DCE)
97 				lapb_send_control(lapb, LAPB_DM, LAPB_POLLOFF, LAPB_RESPONSE);
98 			break;
99 
100 		/*
101 		 *	Awaiting connection state, send SABM(E), up to N2 times.
102 		 */
103 		case LAPB_STATE_1:
104 			if (lapb->n2count == lapb->n2) {
105 				lapb_clear_queues(lapb);
106 				lapb->state = LAPB_STATE_0;
107 				lapb_disconnect_indication(lapb, LAPB_TIMEDOUT);
108 #if LAPB_DEBUG > 0
109 				printk(KERN_DEBUG "lapb: (%p) S1 -> S0\n", lapb->dev);
110 #endif
111 				return;
112 			} else {
113 				lapb->n2count++;
114 				if (lapb->mode & LAPB_EXTENDED) {
115 #if LAPB_DEBUG > 1
116 					printk(KERN_DEBUG "lapb: (%p) S1 TX SABME(1)\n", lapb->dev);
117 #endif
118 					lapb_send_control(lapb, LAPB_SABME, LAPB_POLLON, LAPB_COMMAND);
119 				} else {
120 #if LAPB_DEBUG > 1
121 					printk(KERN_DEBUG "lapb: (%p) S1 TX SABM(1)\n", lapb->dev);
122 #endif
123 					lapb_send_control(lapb, LAPB_SABM, LAPB_POLLON, LAPB_COMMAND);
124 				}
125 			}
126 			break;
127 
128 		/*
129 		 *	Awaiting disconnection state, send DISC, up to N2 times.
130 		 */
131 		case LAPB_STATE_2:
132 			if (lapb->n2count == lapb->n2) {
133 				lapb_clear_queues(lapb);
134 				lapb->state = LAPB_STATE_0;
135 				lapb_disconnect_confirmation(lapb, LAPB_TIMEDOUT);
136 #if LAPB_DEBUG > 0
137 				printk(KERN_DEBUG "lapb: (%p) S2 -> S0\n", lapb->dev);
138 #endif
139 				return;
140 			} else {
141 				lapb->n2count++;
142 #if LAPB_DEBUG > 1
143 				printk(KERN_DEBUG "lapb: (%p) S2 TX DISC(1)\n", lapb->dev);
144 #endif
145 				lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND);
146 			}
147 			break;
148 
149 		/*
150 		 *	Data transfer state, restransmit I frames, up to N2 times.
151 		 */
152 		case LAPB_STATE_3:
153 			if (lapb->n2count == lapb->n2) {
154 				lapb_clear_queues(lapb);
155 				lapb->state = LAPB_STATE_0;
156 				lapb_stop_t2timer(lapb);
157 				lapb_disconnect_indication(lapb, LAPB_TIMEDOUT);
158 #if LAPB_DEBUG > 0
159 				printk(KERN_DEBUG "lapb: (%p) S3 -> S0\n", lapb->dev);
160 #endif
161 				return;
162 			} else {
163 				lapb->n2count++;
164 				lapb_requeue_frames(lapb);
165 			}
166 			break;
167 
168 		/*
169 		 *	Frame reject state, restransmit FRMR frames, up to N2 times.
170 		 */
171 		case LAPB_STATE_4:
172 			if (lapb->n2count == lapb->n2) {
173 				lapb_clear_queues(lapb);
174 				lapb->state = LAPB_STATE_0;
175 				lapb_disconnect_indication(lapb, LAPB_TIMEDOUT);
176 #if LAPB_DEBUG > 0
177 				printk(KERN_DEBUG "lapb: (%p) S4 -> S0\n", lapb->dev);
178 #endif
179 				return;
180 			} else {
181 				lapb->n2count++;
182 				lapb_transmit_frmr(lapb);
183 			}
184 			break;
185 	}
186 
187 	lapb_start_t1timer(lapb);
188 }
189