conn reference renaming and locking logic
[cor_2_6_31.git] / net / cor / cpacket_parse.c
blob0126da20cb4275f9ec9ff8555912dc1e415e5bd5
1 /**
2 * Connection oriented routing
3 * Copyright (C) 2007-2011 Michael Blizek
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA.
21 #include "cor.h"
23 struct work_struct cpacket_resume_work;
24 static int cpacket_resume_running;
25 DEFINE_SPINLOCK(cpacket_bufferlimits_lock);
26 static __u64 cpacket_bufferusage;
27 static int cpacket_kmallocfailed;
28 LIST_HEAD(cpacket_bufferwaiting);
30 static int reserve_cpacket_buffer(struct conn *trtg_unconn_l, int fromresume)
32 unsigned long iflags;
33 int putconn = 0;
35 __u32 paramlen = trtg_unconn_l->target.unconnected.paramlen;
36 __u32 resplen = 128;
38 if (trtg_unconn_l->target.unconnected.cmd == CD_LIST_NEIGH)
39 resplen = LISTNEIGH_RESP_MAXSIZE + 128;
41 if (trtg_unconn_l->target.unconnected.in_buffer_wait_list &&
42 fromresume == 0)
43 return 1;
45 if (trtg_unconn_l->data_buf.cpacket_buffer + paramlen + resplen >
46 BUFFERLIMIT_CONNDATA_PERCONN)
47 return 1;
49 spin_lock_irqsave(&cpacket_bufferlimits_lock, iflags);
51 if (list_empty(&cpacket_bufferwaiting) == 0 || paramlen + resplen +
52 cpacket_bufferusage > BUFFERLIMIT_CONNDATA_GLOBAL) {
53 /* out of bufferspace */
54 if (trtg_unconn_l->target.unconnected.in_buffer_wait_list == 0){
55 trtg_unconn_l->target.unconnected.in_buffer_wait_list=1;
56 list_add_tail(&(trtg_unconn_l->target.unconnected.buffer_wait_list),
57 &cpacket_bufferwaiting);
58 kref_get(&(trtg_unconn_l->ref));
60 if (cpacket_resume_running == 0) {
61 schedule_work(&cpacket_resume_work);
62 cpacket_resume_running = 1;
65 spin_unlock_irqrestore(&cpacket_bufferlimits_lock,
66 iflags);
67 return 1;
70 cpacket_bufferusage += paramlen + resplen;
72 if (trtg_unconn_l->target.unconnected.in_buffer_wait_list) {
73 trtg_unconn_l->target.unconnected.in_buffer_wait_list = 0;
74 list_del(&(trtg_unconn_l->target.unconnected.buffer_wait_list));
75 putconn = 1;
78 spin_unlock_irqrestore(&cpacket_bufferlimits_lock, iflags);
80 trtg_unconn_l->target.unconnected.cmdparams = kmalloc(paramlen,
81 GFP_KERNEL);
82 if (unlikely(trtg_unconn_l->target.unconnected.cmdparams == 0)) {
83 spin_lock_irqsave(&cpacket_bufferlimits_lock, iflags);
84 cpacket_kmallocfailed = 1;
85 trtg_unconn_l->target.unconnected.in_buffer_wait_list = 1;
86 list_add(&(trtg_unconn_l->target.unconnected.buffer_wait_list),
87 &cpacket_bufferwaiting);
88 if (cpacket_resume_running == 0) {
89 schedule_work(&cpacket_resume_work);
90 cpacket_resume_running = 1;
92 if (putconn == 0)
93 kref_get(&(trtg_unconn_l->ref));
94 cpacket_bufferusage -= paramlen + resplen;
95 spin_unlock_irqrestore(&cpacket_bufferlimits_lock, iflags);
96 return 1;
99 mutex_lock(&(trtg_unconn_l->reversedir->rcv_lock));
100 trtg_unconn_l->reversedir->data_buf.cpacket_buffer += resplen;
101 mutex_unlock(&(trtg_unconn_l->reversedir->rcv_lock));
103 if (putconn)
104 kref_put(&(trtg_unconn_l->ref), free_conn);
106 return 0;
109 static void cpacket_buffer_resume(struct work_struct *work)
111 unsigned long iflags;
112 int i;
114 spin_lock_irqsave(&cpacket_bufferlimits_lock, iflags);
116 cpacket_kmallocfailed = 0;
118 for (i=0;i<100;i++) {
119 struct conn *trtg_unconn;
121 if (list_empty(&cpacket_bufferwaiting))
122 goto finish;
124 if (cpacket_kmallocfailed)
125 break;
127 trtg_unconn = container_of(cpacket_bufferwaiting.next,
128 struct conn,
129 target.unconnected.buffer_wait_list);
131 kref_get(&(trtg_unconn->ref));
133 spin_unlock_irqrestore(&cpacket_bufferlimits_lock, iflags);
135 mutex_lock(&(trtg_unconn->rcv_lock));
137 if (unlikely(trtg_unconn->targettype != TARGET_UNCONNECTED))
138 goto cont;
140 spin_lock_irqsave(&cpacket_bufferlimits_lock, iflags);
142 BUG_ON(trtg_unconn->target.unconnected.in_buffer_wait_list ==
145 if (unlikely(atomic_read(&(trtg_unconn->isreset)) != 0)) {
146 trtg_unconn->target.unconnected.in_buffer_wait_list = 0;
147 list_del(&(trtg_unconn->target.unconnected.buffer_wait_list));
148 goto cont;
152 spin_unlock_irqrestore(&cpacket_bufferlimits_lock, iflags);
153 mutex_unlock(&(trtg_unconn->rcv_lock));
155 parse(trtg_unconn, 1);
157 cont:
158 kref_put(&(trtg_unconn->ref), free_conn);
159 spin_lock_irqsave(&cpacket_bufferlimits_lock, iflags);
162 schedule_work(&cpacket_resume_work);
164 if (0) {
165 finish:
166 cpacket_resume_running = 0;
169 spin_unlock_irqrestore(&cpacket_bufferlimits_lock, iflags);
172 void free_cpacket_buffer(__s32 amount)
174 unsigned long iflags;
175 spin_lock_irqsave(&cpacket_bufferlimits_lock, iflags);
176 BUG_ON(amount > 0 && amount > cpacket_bufferusage);
177 cpacket_bufferusage -= amount;
179 if (amount > 0 && list_empty(&cpacket_bufferwaiting) == 0 &&
180 cpacket_resume_running == 0) {
181 schedule_work(&cpacket_resume_work);
182 cpacket_resume_running = 1;
184 spin_unlock_irqrestore(&cpacket_bufferlimits_lock, iflags);
187 void connreset_cpacket_buffer(struct conn *trtg_unconn_l)
189 if (trtg_unconn_l->target.unconnected.in_buffer_wait_list) {
190 unsigned long iflags;
191 spin_lock_irqsave(&cpacket_bufferlimits_lock, iflags);
192 trtg_unconn_l->target.unconnected.in_buffer_wait_list = 0;
193 list_del(&(trtg_unconn_l->target.unconnected.buffer_wait_list));
194 spin_unlock_irqrestore(&cpacket_bufferlimits_lock, iflags);
197 if (trtg_unconn_l->target.unconnected.cmdparams != 0) {
198 BUG_ON(trtg_unconn_l->target.unconnected.paramlen <= 0);
199 kfree(trtg_unconn_l->target.unconnected.cmdparams);
200 trtg_unconn_l->target.unconnected.cmdparams = 0;
201 free_cpacket_buffer(trtg_unconn_l->target.unconnected.paramlen);
205 int encode_len(char *buf, int buflen, __u32 len)
207 BUG_ON(buf == 0);
208 BUG_ON(buflen < 4);
210 if (len <= 127) {
211 buf[0] = (__u8) len;
212 return 1;
215 if (len <= 16511) {
216 buf[0] = (__u8) ((len - 128) /256 + 128);
217 buf[1] = (__u8) ((len- 128) & 255);
218 return 2;
221 if (len < 1073741951) {
222 __u32 len_be = cpu_to_be32(len - 16511);
223 char *len_p = (char *) &len_be;
225 buf[0] = len_p[0] + 192;
226 buf[1] = len_p[1];
227 buf[2] = len_p[2];
228 buf[3] = len_p[3];
229 return 4;
232 return -1;
235 int decode_len(char *buf, int buflen, __u32 *len)
237 if (buflen < 1)
238 return 0;
240 if ((__u8) buf[0] <= 127) {
241 *len = (__u8) buf[0];
242 return 1;
245 if (buflen < 2)
246 return 0;
248 if ((__u8) buf[0] <= 191) {
249 *len = 128 + ((__u32) ((__u8) buf[0]) - 128) * 256 +
250 ((__u8) buf[1]);
251 return 2;
254 if (buflen < 4)
255 return 0;
257 ((char *) len)[0] = buf[0] - 192;
258 ((char *) len)[1] = buf[1];
259 ((char *) len)[2] = buf[2];
260 ((char *) len)[3] = buf[3];
262 *len = be32_to_cpu(*len) + 16511;
263 return 4;
266 static void send_resp_ok(struct conn *trtg_unconn_l)
268 __u8 respcode = CDR_EXECOK;
270 mutex_lock(&(trtg_unconn_l->reversedir->rcv_lock));
271 receive_cpacketresp(trtg_unconn_l->reversedir, (char *) &respcode, 1);
272 mutex_unlock(&(trtg_unconn_l->reversedir->rcv_lock));
275 static char *get_error_reason_text(__u16 reasoncode)
277 if (reasoncode == CDR_EXECFAILED_UNKNOWN_COMMAND)
278 return "Unknown command";
279 else if (reasoncode == CDR_EXECFAILED_PERMISSION_DENIED)
280 return "Permission denied";
281 else if (reasoncode == CDR_EXECFAILED_TEMPORARILY_OUT_OF_RESSOURCES)
282 return "Temporarily out of ressources";
283 else if (reasoncode == CDR_EXECFAILED_CMD_TOO_SHORT)
284 return "The length of the command is too short for all params";
285 else if (reasoncode == CDR_EXECFAILED_CMD_TOO_LONG)
286 return "command param is too long";
287 else if (reasoncode == CDR_EXECFAILED_TARGETADDRTYPE_UNKNOWN)
288 return "targettype unknown";
289 else if (reasoncode == CDR_EXECFAILED_TARGETADDR_DOESNTEXIST)
290 return "targetaddr does not exist";
291 else if (reasoncode == CDR_EXECFAILED_TARGETADDR_PORTCLOSED)
292 return "Port is on open";
293 else if (reasoncode == CDR_EXECFAILED_LISTENERQUEUE_FULL)
294 return "Listener queue full";
295 else
296 return 0;
299 static void send_resp_failed(struct conn *trtg_unconn_l, __u16 reasoncode)
301 char hdr[7];
303 char *reasontext;
304 int reasonlen = 0;
305 int reasonlen_len;
307 hdr[0] = CDR_EXECFAILED;
309 reasoncode = cpu_to_be16(reasoncode);
310 hdr[1] = ((char *) &reasoncode)[0];
311 hdr[2] = ((char *) &reasoncode)[1];
313 reasontext = get_error_reason_text(reasoncode);
314 if (reasontext)
315 reasonlen = strnlen(reasontext, 1024);
316 reasonlen_len = encode_len(hdr + 3, 4, reasonlen);
317 BUG_ON(reasonlen_len <= 0);
319 mutex_lock(&(trtg_unconn_l->reversedir->rcv_lock));
320 receive_cpacketresp(trtg_unconn_l->reversedir, hdr, 3 + reasonlen_len);
321 receive_cpacketresp(trtg_unconn_l->reversedir, reasontext, reasonlen);
322 mutex_unlock(&(trtg_unconn_l->reversedir->rcv_lock));
325 static void send_resp_bin(struct conn *trtg_unconn_l, char *buf, __u32 len)
327 char hdr[5];
328 int len_len;
330 hdr[0] = CDR_BINDATA;
331 len_len = encode_len(hdr + 1, 4, len);
333 BUG_ON(len_len <= 0);
335 mutex_lock(&(trtg_unconn_l->reversedir->rcv_lock));
336 receive_cpacketresp(trtg_unconn_l->reversedir, hdr, len_len + 1);
337 receive_cpacketresp(trtg_unconn_l->reversedir, buf, len);
338 mutex_unlock(&(trtg_unconn_l->reversedir->rcv_lock));
341 static void parse_set_tos(struct conn *trtg_unconn_l)
343 if (unlikely(trtg_unconn_l->target.unconnected.paramlen < 2)) {
344 send_resp_failed(trtg_unconn_l, CDR_EXECFAILED_CMD_TOO_SHORT);
345 return;
348 trtg_unconn_l->tos =
349 (trtg_unconn_l->target.unconnected.cmdparams[0]) & 3;
350 trtg_unconn_l->reversedir->tos =
351 (trtg_unconn_l->target.unconnected.cmdparams[1]) & 3;
354 static void parse_list_neigh(struct conn *trtg_unconn_l)
356 __u32 limit;
357 __u32 offset;
358 __u32 len;
360 __u32 read = 0;
361 int rc;
363 char *buf;
365 BUG_ON(read > trtg_unconn_l->target.unconnected.paramlen);
366 rc = decode_len(trtg_unconn_l->target.unconnected.cmdparams + read,
367 trtg_unconn_l->target.unconnected.paramlen - read,
368 &limit);
370 if (unlikely(rc <= 0)) {
371 send_resp_failed(trtg_unconn_l, CDR_EXECFAILED_CMD_TOO_SHORT);
372 return;
375 read += rc;
377 BUG_ON(read > trtg_unconn_l->target.unconnected.paramlen);
378 rc = decode_len(trtg_unconn_l->target.unconnected.cmdparams + read,
379 trtg_unconn_l->target.unconnected.paramlen - read,
380 &offset);
382 if (unlikely(rc <= 0)) {
383 send_resp_failed(trtg_unconn_l, CDR_EXECFAILED_CMD_TOO_SHORT);
384 return;
387 read += rc;
389 buf = kmalloc(LISTNEIGH_RESP_MAXSIZE, GFP_KERNEL);
391 if (unlikely(buf == 0)) {
392 send_resp_failed(trtg_unconn_l,
393 CDR_EXECFAILED_TEMPORARILY_OUT_OF_RESSOURCES);
394 return;
397 send_resp_ok(trtg_unconn_l);
399 len = generate_neigh_list(buf, 2048, limit, offset);
400 send_resp_bin(trtg_unconn_l, buf, len);
403 static void parse_connect_port(struct conn *trtg_unconn_l)
405 __be64 addr;
406 int rc;
408 if (unlikely(trtg_unconn_l->target.unconnected.paramlen < 8)) {
409 send_resp_failed(trtg_unconn_l, CDR_EXECFAILED_CMD_TOO_SHORT);
410 return;
413 memcpy((char *) &addr, trtg_unconn_l->target.unconnected.cmdparams, 8);
415 rc = connect_port(trtg_unconn_l, addr);
417 if (rc == 0) {
418 send_resp_ok(trtg_unconn_l);
419 } else if (rc == 2) {
420 send_resp_failed(trtg_unconn_l,
421 CDR_EXECFAILED_TARGETADDR_DOESNTEXIST);
422 } else if (rc == 3) {
423 send_resp_failed(trtg_unconn_l,
424 CDR_EXECFAILED_LISTENERQUEUE_FULL);
425 } else {
426 BUG();
430 static void parse_connect_nb(struct conn *trtg_unconn_l)
432 __u32 addrtypelen;
433 __u32 addrlen;
434 __u8 *addrtype;
435 __u8 *addr;
437 __u32 read = 0;
438 int rc;
440 BUG_ON(read > trtg_unconn_l->target.unconnected.paramlen);
441 rc = decode_len(trtg_unconn_l->target.unconnected.cmdparams + read,
442 trtg_unconn_l->target.unconnected.paramlen - read,
443 &addrtypelen);
445 if (unlikely(rc <= 0)) {
446 send_resp_failed(trtg_unconn_l, CDR_EXECFAILED_CMD_TOO_SHORT);
447 return;
450 read += rc;
452 BUG_ON(read > trtg_unconn_l->target.unconnected.paramlen);
453 rc = decode_len(trtg_unconn_l->target.unconnected.cmdparams + read,
454 trtg_unconn_l->target.unconnected.paramlen - read,
455 &addrlen);
457 if (unlikely(rc <= 0)) {
458 send_resp_failed(trtg_unconn_l, CDR_EXECFAILED_CMD_TOO_SHORT);
459 return;
462 read += rc;
464 if (unlikely(addrtypelen > 65535 || addrtypelen > 65535)) {
465 send_resp_failed(trtg_unconn_l,
466 CDR_EXECFAILED_TARGETADDR_DOESNTEXIST);
467 return;
470 if (unlikely((read + addrtypelen + addrlen) >
471 trtg_unconn_l->target.unconnected.paramlen)) {
472 send_resp_failed(trtg_unconn_l, CDR_EXECFAILED_CMD_TOO_SHORT);
473 return;
476 addrtype = trtg_unconn_l->target.unconnected.cmdparams + read;
477 addr = addrtype + addrtypelen;
479 rc = connect_neigh(trtg_unconn_l, (__u16) addrtypelen, addrtype,
480 (__u16) addrlen, addr);
482 if (rc == 0) {
483 send_resp_ok(trtg_unconn_l);
484 } else if (rc == 2) {
485 send_resp_failed(trtg_unconn_l,
486 CDR_EXECFAILED_TARGETADDRTYPE_UNKNOWN);
487 } else if (rc == 3) {
488 send_resp_failed(trtg_unconn_l,
489 CDR_EXECFAILED_TARGETADDR_DOESNTEXIST);
490 } else if (rc == 4) {
491 send_resp_failed(trtg_unconn_l,
492 CDR_EXECFAILED_TEMPORARILY_OUT_OF_RESSOURCES);
493 } else {
494 BUG();
498 static void parse_cmd(struct conn *trtg_unconn_l)
500 __u16 code = trtg_unconn_l->target.unconnected.cmd;
502 BUG_ON(trtg_unconn_l->target.unconnected.cmdparams == 0);
504 if (code == CD_CONNECT_NB) {
505 parse_connect_nb(trtg_unconn_l);
506 } else if (code == CD_CONNECT_PORT) {
507 parse_connect_port(trtg_unconn_l);
508 } else if (code == CD_LIST_NEIGH) {
509 parse_list_neigh(trtg_unconn_l);
510 } else if (code == CD_SET_TOS) {
511 parse_set_tos(trtg_unconn_l);
512 } else {
513 send_resp_failed(trtg_unconn_l, CDR_EXECFAILED_UNKNOWN_COMMAND);
517 static void read_cmd(struct conn *trtg_unconn_l)
519 int pull;
521 pull = min(trtg_unconn_l->target.unconnected.paramlen -
522 trtg_unconn_l->target.unconnected.cmdread,
523 trtg_unconn_l->data_buf.read_remaining);
525 BUG_ON(pull < 0);
526 BUG_ON(trtg_unconn_l->target.unconnected.cmdparams == 0);
528 if (pull == 0)
529 return;
531 databuf_pull(trtg_unconn_l,
532 trtg_unconn_l->target.unconnected.cmdparams +
533 trtg_unconn_l->target.unconnected.cmdread, pull);
534 databuf_ackread(trtg_unconn_l);
536 trtg_unconn_l->target.unconnected.cmdread += pull;
539 static void read_discard(struct conn *trtg_unconn_l)
541 BUG_ON(trtg_unconn_l->target.unconnected.paramlen_read == 0);
543 while (trtg_unconn_l->target.unconnected.paramlen <
544 trtg_unconn_l->target.unconnected.cmdread &&
545 trtg_unconn_l->data_buf.read_remaining > 0) {
546 char buf[1];
547 databuf_pull(trtg_unconn_l, buf, 1);
548 databuf_ackread(trtg_unconn_l);
550 trtg_unconn_l->target.unconnected.cmdread++;
554 static void read_hdr(struct conn *trtg_unconn_l)
556 BUG_ON(trtg_unconn_l->target.unconnected.cmdparams != 0);
558 while (trtg_unconn_l->target.unconnected.paramlen_read == 0 &&
559 trtg_unconn_l->data_buf.read_remaining > 0) {
560 int rc;
562 BUG_ON(trtg_unconn_l->target.unconnected.cmdread >= 6);
564 if (trtg_unconn_l->target.unconnected.cmdread < 2) {
565 char buf[1];
566 databuf_pull(trtg_unconn_l, buf, 1);
567 trtg_unconn_l->target.unconnected.cmd <<= 8;
568 trtg_unconn_l->target.unconnected.cmd += buf[0];
569 trtg_unconn_l->target.unconnected.cmdread += 1;
570 continue;
573 databuf_pull(trtg_unconn_l,
574 trtg_unconn_l->target.unconnected.paramlen_buf +
575 trtg_unconn_l->target.unconnected.cmdread - 2,
577 trtg_unconn_l->target.unconnected.cmdread += 1;
579 rc = decode_len(trtg_unconn_l->target.unconnected.paramlen_buf,
580 trtg_unconn_l->target.unconnected.cmdread - 2,
581 &(trtg_unconn_l->target.unconnected.paramlen));
583 if (rc > 0) {
584 trtg_unconn_l->target.unconnected.paramlen_read = 1;
585 trtg_unconn_l->target.unconnected.cmdread = 0;
586 break;
591 void parse(struct conn *trtg_unconn, int fromresume)
593 start:
594 mutex_lock(&(trtg_unconn->rcv_lock));
596 if (unlikely(atomic_read(&(trtg_unconn->isreset)) != 0))
597 goto out;
599 if (unlikely(trtg_unconn->targettype != TARGET_UNCONNECTED))
600 goto out;
602 BUG_ON(trtg_unconn->data_buf.cpacket_buffer != 0);
604 if (trtg_unconn->target.unconnected.paramlen_read == 0) {
605 read_hdr(trtg_unconn);
606 if (trtg_unconn->target.unconnected.paramlen_read == 0)
607 goto out;
609 if (trtg_unconn->target.unconnected.paramlen >
610 MAX_CONN_CMD_LEN) {
611 send_resp_failed(trtg_unconn,
612 CDR_EXECFAILED_CMD_TOO_LONG);
616 if (trtg_unconn->target.unconnected.paramlen > MAX_CONN_CMD_LEN) {
617 read_discard(trtg_unconn);
618 goto out;
621 if (trtg_unconn->target.unconnected.cmdparams == 0) {
622 if (reserve_cpacket_buffer(trtg_unconn, fromresume))
623 goto out;
626 if (trtg_unconn->target.unconnected.paramlen >
627 trtg_unconn->target.unconnected.cmdread) {
628 read_cmd(trtg_unconn);
631 if (trtg_unconn->target.unconnected.paramlen ==
632 trtg_unconn->target.unconnected.cmdread) {
633 char *cmd = trtg_unconn->target.unconnected.cmdparams;
634 __s32 cpacket_buffer;
635 __u32 paramlen = trtg_unconn->target.unconnected.paramlen;
636 int flush = 0;
638 BUG_ON(trtg_unconn->is_client == 0);
639 mutex_lock(&(trtg_unconn->reversedir->rcv_lock));
640 cpacket_buffer = trtg_unconn->reversedir->data_buf.cpacket_buffer;
641 mutex_unlock(&(trtg_unconn->reversedir->rcv_lock));
642 parse_cmd(trtg_unconn);
643 kfree(cmd);
644 mutex_lock(&(trtg_unconn->reversedir->rcv_lock));
645 trtg_unconn->reversedir->data_buf.cpacket_buffer =
646 trtg_unconn->reversedir->data_buf.totalsize +
647 trtg_unconn->reversedir->data_buf.overhead;
648 cpacket_buffer -= trtg_unconn->reversedir->data_buf.cpacket_buffer;
649 mutex_unlock(&(trtg_unconn->reversedir->rcv_lock));
650 free_cpacket_buffer(paramlen + cpacket_buffer);
652 if (trtg_unconn->targettype != TARGET_UNCONNECTED) {
653 flush = 1;
654 } else {
655 trtg_unconn->target.unconnected.cmdparams = 0;
656 trtg_unconn->target.unconnected.cmdread = 0;
657 trtg_unconn->target.unconnected.paramlen_read = 0;
658 trtg_unconn->target.unconnected.cmd = 0;
659 trtg_unconn->target.unconnected.paramlen = 0;
662 mutex_unlock(&(trtg_unconn->rcv_lock));
663 if (flush)
664 flush_buf(trtg_unconn);
665 flush_buf(trtg_unconn->reversedir);
666 if (flush == 0)
667 goto start;
668 return;
671 out:
672 mutex_unlock(&(trtg_unconn->rcv_lock));
675 int __init cor_cpacket_init(void)
677 INIT_WORK(&cpacket_resume_work, cpacket_buffer_resume);
678 cpacket_resume_running = 0;
679 cpacket_bufferusage = 0;
680 cpacket_kmallocfailed = 0;
681 return 0;
684 MODULE_LICENSE("GPL");