Root/
1 | /* |
2 | * This program is free software; you can redistribute it and/or modify |
3 | * it under the terms of the GNU General Public License as published by |
4 | * the Free Software Foundation; either version 2 of the License, or |
5 | * (at your option) any later version. |
6 | * |
7 | * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk) |
8 | * Copyright (C) 2002 Ralf Baechle DO1GRB (ralf@gnu.org) |
9 | */ |
10 | #include <linux/errno.h> |
11 | #include <linux/types.h> |
12 | #include <linux/socket.h> |
13 | #include <linux/in.h> |
14 | #include <linux/kernel.h> |
15 | #include <linux/jiffies.h> |
16 | #include <linux/timer.h> |
17 | #include <linux/string.h> |
18 | #include <linux/sockios.h> |
19 | #include <linux/net.h> |
20 | #include <net/ax25.h> |
21 | #include <linux/inet.h> |
22 | #include <linux/netdevice.h> |
23 | #include <linux/skbuff.h> |
24 | #include <net/sock.h> |
25 | #include <net/tcp_states.h> |
26 | #include <asm/system.h> |
27 | #include <linux/fcntl.h> |
28 | #include <linux/mm.h> |
29 | #include <linux/interrupt.h> |
30 | #include <net/rose.h> |
31 | |
32 | static void rose_heartbeat_expiry(unsigned long); |
33 | static void rose_timer_expiry(unsigned long); |
34 | static void rose_idletimer_expiry(unsigned long); |
35 | |
36 | void rose_start_heartbeat(struct sock *sk) |
37 | { |
38 | del_timer(&sk->sk_timer); |
39 | |
40 | sk->sk_timer.data = (unsigned long)sk; |
41 | sk->sk_timer.function = &rose_heartbeat_expiry; |
42 | sk->sk_timer.expires = jiffies + 5 * HZ; |
43 | |
44 | add_timer(&sk->sk_timer); |
45 | } |
46 | |
47 | void rose_start_t1timer(struct sock *sk) |
48 | { |
49 | struct rose_sock *rose = rose_sk(sk); |
50 | |
51 | del_timer(&rose->timer); |
52 | |
53 | rose->timer.data = (unsigned long)sk; |
54 | rose->timer.function = &rose_timer_expiry; |
55 | rose->timer.expires = jiffies + rose->t1; |
56 | |
57 | add_timer(&rose->timer); |
58 | } |
59 | |
60 | void rose_start_t2timer(struct sock *sk) |
61 | { |
62 | struct rose_sock *rose = rose_sk(sk); |
63 | |
64 | del_timer(&rose->timer); |
65 | |
66 | rose->timer.data = (unsigned long)sk; |
67 | rose->timer.function = &rose_timer_expiry; |
68 | rose->timer.expires = jiffies + rose->t2; |
69 | |
70 | add_timer(&rose->timer); |
71 | } |
72 | |
73 | void rose_start_t3timer(struct sock *sk) |
74 | { |
75 | struct rose_sock *rose = rose_sk(sk); |
76 | |
77 | del_timer(&rose->timer); |
78 | |
79 | rose->timer.data = (unsigned long)sk; |
80 | rose->timer.function = &rose_timer_expiry; |
81 | rose->timer.expires = jiffies + rose->t3; |
82 | |
83 | add_timer(&rose->timer); |
84 | } |
85 | |
86 | void rose_start_hbtimer(struct sock *sk) |
87 | { |
88 | struct rose_sock *rose = rose_sk(sk); |
89 | |
90 | del_timer(&rose->timer); |
91 | |
92 | rose->timer.data = (unsigned long)sk; |
93 | rose->timer.function = &rose_timer_expiry; |
94 | rose->timer.expires = jiffies + rose->hb; |
95 | |
96 | add_timer(&rose->timer); |
97 | } |
98 | |
99 | void rose_start_idletimer(struct sock *sk) |
100 | { |
101 | struct rose_sock *rose = rose_sk(sk); |
102 | |
103 | del_timer(&rose->idletimer); |
104 | |
105 | if (rose->idle > 0) { |
106 | rose->idletimer.data = (unsigned long)sk; |
107 | rose->idletimer.function = &rose_idletimer_expiry; |
108 | rose->idletimer.expires = jiffies + rose->idle; |
109 | |
110 | add_timer(&rose->idletimer); |
111 | } |
112 | } |
113 | |
114 | void rose_stop_heartbeat(struct sock *sk) |
115 | { |
116 | del_timer(&sk->sk_timer); |
117 | } |
118 | |
119 | void rose_stop_timer(struct sock *sk) |
120 | { |
121 | del_timer(&rose_sk(sk)->timer); |
122 | } |
123 | |
124 | void rose_stop_idletimer(struct sock *sk) |
125 | { |
126 | del_timer(&rose_sk(sk)->idletimer); |
127 | } |
128 | |
129 | static void rose_heartbeat_expiry(unsigned long param) |
130 | { |
131 | struct sock *sk = (struct sock *)param; |
132 | struct rose_sock *rose = rose_sk(sk); |
133 | |
134 | bh_lock_sock(sk); |
135 | switch (rose->state) { |
136 | case ROSE_STATE_0: |
137 | /* Magic here: If we listen() and a new link dies before it |
138 | is accepted() it isn't 'dead' so doesn't get removed. */ |
139 | if (sock_flag(sk, SOCK_DESTROY) || |
140 | (sk->sk_state == TCP_LISTEN && sock_flag(sk, SOCK_DEAD))) { |
141 | bh_unlock_sock(sk); |
142 | rose_destroy_socket(sk); |
143 | return; |
144 | } |
145 | break; |
146 | |
147 | case ROSE_STATE_3: |
148 | /* |
149 | * Check for the state of the receive buffer. |
150 | */ |
151 | if (atomic_read(&sk->sk_rmem_alloc) < (sk->sk_rcvbuf / 2) && |
152 | (rose->condition & ROSE_COND_OWN_RX_BUSY)) { |
153 | rose->condition &= ~ROSE_COND_OWN_RX_BUSY; |
154 | rose->condition &= ~ROSE_COND_ACK_PENDING; |
155 | rose->vl = rose->vr; |
156 | rose_write_internal(sk, ROSE_RR); |
157 | rose_stop_timer(sk); /* HB */ |
158 | break; |
159 | } |
160 | break; |
161 | } |
162 | |
163 | rose_start_heartbeat(sk); |
164 | bh_unlock_sock(sk); |
165 | } |
166 | |
167 | static void rose_timer_expiry(unsigned long param) |
168 | { |
169 | struct sock *sk = (struct sock *)param; |
170 | struct rose_sock *rose = rose_sk(sk); |
171 | |
172 | bh_lock_sock(sk); |
173 | switch (rose->state) { |
174 | case ROSE_STATE_1: /* T1 */ |
175 | case ROSE_STATE_4: /* T2 */ |
176 | rose_write_internal(sk, ROSE_CLEAR_REQUEST); |
177 | rose->state = ROSE_STATE_2; |
178 | rose_start_t3timer(sk); |
179 | break; |
180 | |
181 | case ROSE_STATE_2: /* T3 */ |
182 | rose->neighbour->use--; |
183 | rose_disconnect(sk, ETIMEDOUT, -1, -1); |
184 | break; |
185 | |
186 | case ROSE_STATE_3: /* HB */ |
187 | if (rose->condition & ROSE_COND_ACK_PENDING) { |
188 | rose->condition &= ~ROSE_COND_ACK_PENDING; |
189 | rose_enquiry_response(sk); |
190 | } |
191 | break; |
192 | } |
193 | bh_unlock_sock(sk); |
194 | } |
195 | |
196 | static void rose_idletimer_expiry(unsigned long param) |
197 | { |
198 | struct sock *sk = (struct sock *)param; |
199 | |
200 | bh_lock_sock(sk); |
201 | rose_clear_queues(sk); |
202 | |
203 | rose_write_internal(sk, ROSE_CLEAR_REQUEST); |
204 | rose_sk(sk)->state = ROSE_STATE_2; |
205 | |
206 | rose_start_t3timer(sk); |
207 | |
208 | sk->sk_state = TCP_CLOSE; |
209 | sk->sk_err = 0; |
210 | sk->sk_shutdown |= SEND_SHUTDOWN; |
211 | |
212 | if (!sock_flag(sk, SOCK_DEAD)) { |
213 | sk->sk_state_change(sk); |
214 | sock_set_flag(sk, SOCK_DEAD); |
215 | } |
216 | bh_unlock_sock(sk); |
217 | } |
218 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9