xref: /openbmc/linux/net/lapb/lapb_timer.c (revision cfbb9be8)
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 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
18 
19 #include <linux/errno.h>
20 #include <linux/types.h>
21 #include <linux/socket.h>
22 #include <linux/in.h>
23 #include <linux/kernel.h>
24 #include <linux/jiffies.h>
25 #include <linux/timer.h>
26 #include <linux/string.h>
27 #include <linux/sockios.h>
28 #include <linux/net.h>
29 #include <linux/inet.h>
30 #include <linux/skbuff.h>
31 #include <net/sock.h>
32 #include <linux/uaccess.h>
33 #include <linux/fcntl.h>
34 #include <linux/mm.h>
35 #include <linux/interrupt.h>
36 #include <net/lapb.h>
37 
38 static void lapb_t1timer_expiry(struct timer_list *);
39 static void lapb_t2timer_expiry(struct timer_list *);
40 
41 void lapb_start_t1timer(struct lapb_cb *lapb)
42 {
43 	del_timer(&lapb->t1timer);
44 
45 	lapb->t1timer.function = lapb_t1timer_expiry;
46 	lapb->t1timer.expires  = jiffies + lapb->t1;
47 
48 	add_timer(&lapb->t1timer);
49 }
50 
51 void lapb_start_t2timer(struct lapb_cb *lapb)
52 {
53 	del_timer(&lapb->t2timer);
54 
55 	lapb->t2timer.function = lapb_t2timer_expiry;
56 	lapb->t2timer.expires  = jiffies + lapb->t2;
57 
58 	add_timer(&lapb->t2timer);
59 }
60 
61 void lapb_stop_t1timer(struct lapb_cb *lapb)
62 {
63 	del_timer(&lapb->t1timer);
64 }
65 
66 void lapb_stop_t2timer(struct lapb_cb *lapb)
67 {
68 	del_timer(&lapb->t2timer);
69 }
70 
71 int lapb_t1timer_running(struct lapb_cb *lapb)
72 {
73 	return timer_pending(&lapb->t1timer);
74 }
75 
76 static void lapb_t2timer_expiry(struct timer_list *t)
77 {
78 	struct lapb_cb *lapb = from_timer(lapb, t, t2timer);
79 
80 	if (lapb->condition & LAPB_ACK_PENDING_CONDITION) {
81 		lapb->condition &= ~LAPB_ACK_PENDING_CONDITION;
82 		lapb_timeout_response(lapb);
83 	}
84 }
85 
86 static void lapb_t1timer_expiry(struct timer_list *t)
87 {
88 	struct lapb_cb *lapb = from_timer(lapb, t, t1timer);
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 				lapb_dbg(0, "(%p) S1 -> S0\n", lapb->dev);
109 				return;
110 			} else {
111 				lapb->n2count++;
112 				if (lapb->mode & LAPB_EXTENDED) {
113 					lapb_dbg(1, "(%p) S1 TX SABME(1)\n",
114 						 lapb->dev);
115 					lapb_send_control(lapb, LAPB_SABME, LAPB_POLLON, LAPB_COMMAND);
116 				} else {
117 					lapb_dbg(1, "(%p) S1 TX SABM(1)\n",
118 						 lapb->dev);
119 					lapb_send_control(lapb, LAPB_SABM, LAPB_POLLON, LAPB_COMMAND);
120 				}
121 			}
122 			break;
123 
124 		/*
125 		 *	Awaiting disconnection state, send DISC, up to N2 times.
126 		 */
127 		case LAPB_STATE_2:
128 			if (lapb->n2count == lapb->n2) {
129 				lapb_clear_queues(lapb);
130 				lapb->state = LAPB_STATE_0;
131 				lapb_disconnect_confirmation(lapb, LAPB_TIMEDOUT);
132 				lapb_dbg(0, "(%p) S2 -> S0\n", lapb->dev);
133 				return;
134 			} else {
135 				lapb->n2count++;
136 				lapb_dbg(1, "(%p) S2 TX DISC(1)\n", lapb->dev);
137 				lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND);
138 			}
139 			break;
140 
141 		/*
142 		 *	Data transfer state, restransmit I frames, up to N2 times.
143 		 */
144 		case LAPB_STATE_3:
145 			if (lapb->n2count == lapb->n2) {
146 				lapb_clear_queues(lapb);
147 				lapb->state = LAPB_STATE_0;
148 				lapb_stop_t2timer(lapb);
149 				lapb_disconnect_indication(lapb, LAPB_TIMEDOUT);
150 				lapb_dbg(0, "(%p) S3 -> S0\n", lapb->dev);
151 				return;
152 			} else {
153 				lapb->n2count++;
154 				lapb_requeue_frames(lapb);
155 				lapb_kick(lapb);
156 			}
157 			break;
158 
159 		/*
160 		 *	Frame reject state, restransmit FRMR frames, up to N2 times.
161 		 */
162 		case LAPB_STATE_4:
163 			if (lapb->n2count == lapb->n2) {
164 				lapb_clear_queues(lapb);
165 				lapb->state = LAPB_STATE_0;
166 				lapb_disconnect_indication(lapb, LAPB_TIMEDOUT);
167 				lapb_dbg(0, "(%p) S4 -> S0\n", lapb->dev);
168 				return;
169 			} else {
170 				lapb->n2count++;
171 				lapb_transmit_frmr(lapb);
172 			}
173 			break;
174 	}
175 
176 	lapb_start_t1timer(lapb);
177 }
178