double send_reset race, free_ack_conns on reset, lock both conn sides on reset, skip...
[cor_2_6_31.git] / net / cor / cpacket_parse.c
blobd45aae3b73eba46f2e5f0ee9d812c2afbb8fbb81
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;
120 int doparse = 1;
122 if (list_empty(&cpacket_bufferwaiting))
123 goto finish;
125 if (cpacket_kmallocfailed)
126 break;
128 trtg_unconn = container_of(cpacket_bufferwaiting.next,
129 struct conn,
130 target.unconnected.buffer_wait_list);
132 kref_get(&(trtg_unconn->ref));
134 spin_unlock_irqrestore(&cpacket_bufferlimits_lock, iflags);
136 mutex_lock(&(trtg_unconn->rcv_lock));
138 if (unlikely(trtg_unconn->targettype != TARGET_UNCONNECTED)) {
139 doparse = 0;
140 goto unlock;
143 spin_lock_irqsave(&cpacket_bufferlimits_lock, iflags);
145 if (unlikely(trtg_unconn->target.unconnected.in_buffer_wait_list
146 == 0)) {
147 doparse = 0;
148 } else if (unlikely(trtg_unconn->isreset != 0)) {
149 trtg_unconn->target.unconnected.in_buffer_wait_list = 0;
150 list_del(&(trtg_unconn->target.unconnected.buffer_wait_list));
151 kref_put(&(trtg_unconn->ref), free_conn);
152 doparse = 0;
155 spin_unlock_irqrestore(&cpacket_bufferlimits_lock, iflags);
157 unlock:
158 mutex_unlock(&(trtg_unconn->rcv_lock));
160 if (likely(doparse))
161 parse(trtg_unconn, 1);
163 kref_put(&(trtg_unconn->ref), free_conn);
164 spin_lock_irqsave(&cpacket_bufferlimits_lock, iflags);
167 schedule_work(&cpacket_resume_work);
169 if (0) {
170 finish:
171 cpacket_resume_running = 0;
174 spin_unlock_irqrestore(&cpacket_bufferlimits_lock, iflags);
177 void free_cpacket_buffer(__s32 amount)
179 unsigned long iflags;
180 spin_lock_irqsave(&cpacket_bufferlimits_lock, iflags);
181 BUG_ON(amount > 0 && amount > cpacket_bufferusage);
182 cpacket_bufferusage -= amount;
184 if (amount > 0 && list_empty(&cpacket_bufferwaiting) == 0 &&
185 cpacket_resume_running == 0) {
186 schedule_work(&cpacket_resume_work);
187 cpacket_resume_running = 1;
189 spin_unlock_irqrestore(&cpacket_bufferlimits_lock, iflags);
192 void connreset_cpacket_buffer(struct conn *trtg_unconn_l)
194 if (trtg_unconn_l->target.unconnected.in_buffer_wait_list) {
195 unsigned long iflags;
196 spin_lock_irqsave(&cpacket_bufferlimits_lock, iflags);
197 trtg_unconn_l->target.unconnected.in_buffer_wait_list = 0;
198 list_del(&(trtg_unconn_l->target.unconnected.buffer_wait_list));
199 spin_unlock_irqrestore(&cpacket_bufferlimits_lock, iflags);
200 kref_put(&(trtg_unconn_l->ref), free_conn);
203 if (trtg_unconn_l->target.unconnected.cmdparams != 0) {
204 BUG_ON(trtg_unconn_l->target.unconnected.paramlen <= 0);
205 kfree(trtg_unconn_l->target.unconnected.cmdparams);
206 trtg_unconn_l->target.unconnected.cmdparams = 0;
207 free_cpacket_buffer(trtg_unconn_l->target.unconnected.paramlen);
211 int encode_len(char *buf, int buflen, __u32 len)
213 BUG_ON(buf == 0);
214 BUG_ON(buflen < 4);
216 if (len <= 127) {
217 buf[0] = (__u8) len;
218 return 1;
221 if (len <= 16511) {
222 buf[0] = (__u8) ((len - 128) /256 + 128);
223 buf[1] = (__u8) ((len- 128) & 255);
224 return 2;
227 if (len < 1073741951) {
228 __u32 len_be = cpu_to_be32(len - 16511);
229 char *len_p = (char *) &len_be;
231 buf[0] = len_p[0] + 192;
232 buf[1] = len_p[1];
233 buf[2] = len_p[2];
234 buf[3] = len_p[3];
235 return 4;
238 return -1;
241 int decode_len(char *buf, int buflen, __u32 *len)
243 if (buflen < 1)
244 return 0;
246 if ((__u8) buf[0] <= 127) {
247 *len = (__u8) buf[0];
248 return 1;
251 if (buflen < 2)
252 return 0;
254 if ((__u8) buf[0] <= 191) {
255 *len = 128 + ((__u32) ((__u8) buf[0]) - 128) * 256 +
256 ((__u8) buf[1]);
257 return 2;
260 if (buflen < 4)
261 return 0;
263 ((char *) len)[0] = buf[0] - 192;
264 ((char *) len)[1] = buf[1];
265 ((char *) len)[2] = buf[2];
266 ((char *) len)[3] = buf[3];
268 *len = be32_to_cpu(*len) + 16511;
269 return 4;
272 static void send_resp_ok(struct conn *trtg_unconn_l)
274 __u8 respcode = CDR_EXECOK;
276 mutex_lock(&(trtg_unconn_l->reversedir->rcv_lock));
277 receive_cpacketresp(trtg_unconn_l->reversedir, (char *) &respcode, 1);
278 mutex_unlock(&(trtg_unconn_l->reversedir->rcv_lock));
281 static char *get_error_reason_text(__u16 reasoncode)
283 if (reasoncode == CDR_EXECFAILED_UNKNOWN_COMMAND)
284 return "Unknown command";
285 else if (reasoncode == CDR_EXECFAILED_PERMISSION_DENIED)
286 return "Permission denied";
287 else if (reasoncode == CDR_EXECFAILED_TEMPORARILY_OUT_OF_RESSOURCES)
288 return "Temporarily out of ressources";
289 else if (reasoncode == CDR_EXECFAILED_CMD_TOO_SHORT)
290 return "The length of the command is too short for all params";
291 else if (reasoncode == CDR_EXECFAILED_CMD_TOO_LONG)
292 return "command param is too long";
293 else if (reasoncode == CDR_EXECFAILED_TARGETADDRTYPE_UNKNOWN)
294 return "targettype unknown";
295 else if (reasoncode == CDR_EXECFAILED_TARGETADDR_DOESNTEXIST)
296 return "targetaddr does not exist";
297 else if (reasoncode == CDR_EXECFAILED_TARGETADDR_PORTCLOSED)
298 return "Port is on open";
299 else if (reasoncode == CDR_EXECFAILED_LISTENERQUEUE_FULL)
300 return "Listener queue full";
301 else
302 return 0;
305 static void send_resp_failed(struct conn *trtg_unconn_l, __u16 reasoncode)
307 char hdr[7];
309 char *reasontext;
310 int reasonlen = 0;
311 int reasonlen_len;
313 hdr[0] = CDR_EXECFAILED;
315 reasoncode = cpu_to_be16(reasoncode);
316 hdr[1] = ((char *) &reasoncode)[0];
317 hdr[2] = ((char *) &reasoncode)[1];
319 reasontext = get_error_reason_text(reasoncode);
320 if (reasontext)
321 reasonlen = strnlen(reasontext, 1024);
322 reasonlen_len = encode_len(hdr + 3, 4, reasonlen);
323 BUG_ON(reasonlen_len <= 0);
325 mutex_lock(&(trtg_unconn_l->reversedir->rcv_lock));
326 receive_cpacketresp(trtg_unconn_l->reversedir, hdr, 3 + reasonlen_len);
327 receive_cpacketresp(trtg_unconn_l->reversedir, reasontext, reasonlen);
328 mutex_unlock(&(trtg_unconn_l->reversedir->rcv_lock));
331 static void send_resp_bin(struct conn *trtg_unconn_l, char *buf, __u32 len)
333 char hdr[5];
334 int len_len;
336 hdr[0] = CDR_BINDATA;
337 len_len = encode_len(hdr + 1, 4, len);
339 BUG_ON(len_len <= 0);
341 mutex_lock(&(trtg_unconn_l->reversedir->rcv_lock));
342 receive_cpacketresp(trtg_unconn_l->reversedir, hdr, len_len + 1);
343 receive_cpacketresp(trtg_unconn_l->reversedir, buf, len);
344 mutex_unlock(&(trtg_unconn_l->reversedir->rcv_lock));
347 static void parse_set_tos(struct conn *trtg_unconn_l)
349 if (unlikely(trtg_unconn_l->target.unconnected.paramlen < 2)) {
350 send_resp_failed(trtg_unconn_l, CDR_EXECFAILED_CMD_TOO_SHORT);
351 return;
354 trtg_unconn_l->tos =
355 (trtg_unconn_l->target.unconnected.cmdparams[0]) & 3;
356 trtg_unconn_l->reversedir->tos =
357 (trtg_unconn_l->target.unconnected.cmdparams[1]) & 3;
360 static void parse_list_neigh(struct conn *trtg_unconn_l)
362 __u32 limit;
363 __u32 offset;
364 __u32 len;
366 __u32 read = 0;
367 int rc;
369 char *buf;
371 BUG_ON(read > trtg_unconn_l->target.unconnected.paramlen);
372 rc = decode_len(trtg_unconn_l->target.unconnected.cmdparams + read,
373 trtg_unconn_l->target.unconnected.paramlen - read,
374 &limit);
376 if (unlikely(rc <= 0)) {
377 send_resp_failed(trtg_unconn_l, CDR_EXECFAILED_CMD_TOO_SHORT);
378 return;
381 read += rc;
383 BUG_ON(read > trtg_unconn_l->target.unconnected.paramlen);
384 rc = decode_len(trtg_unconn_l->target.unconnected.cmdparams + read,
385 trtg_unconn_l->target.unconnected.paramlen - read,
386 &offset);
388 if (unlikely(rc <= 0)) {
389 send_resp_failed(trtg_unconn_l, CDR_EXECFAILED_CMD_TOO_SHORT);
390 return;
393 read += rc;
395 buf = kmalloc(LISTNEIGH_RESP_MAXSIZE, GFP_KERNEL);
397 if (unlikely(buf == 0)) {
398 send_resp_failed(trtg_unconn_l,
399 CDR_EXECFAILED_TEMPORARILY_OUT_OF_RESSOURCES);
400 return;
403 send_resp_ok(trtg_unconn_l);
405 len = generate_neigh_list(buf, 2048, limit, offset);
406 send_resp_bin(trtg_unconn_l, buf, len);
409 static void parse_connect_port(struct conn *trtg_unconn_l)
411 __be64 addr;
412 int rc;
414 if (unlikely(trtg_unconn_l->target.unconnected.paramlen < 8)) {
415 send_resp_failed(trtg_unconn_l, CDR_EXECFAILED_CMD_TOO_SHORT);
416 return;
419 memcpy((char *) &addr, trtg_unconn_l->target.unconnected.cmdparams, 8);
421 rc = connect_port(trtg_unconn_l, addr);
423 if (rc == 0) {
424 send_resp_ok(trtg_unconn_l);
425 } else if (rc == 2) {
426 send_resp_failed(trtg_unconn_l,
427 CDR_EXECFAILED_TARGETADDR_DOESNTEXIST);
428 } else if (rc == 3) {
429 send_resp_failed(trtg_unconn_l,
430 CDR_EXECFAILED_LISTENERQUEUE_FULL);
431 } else {
432 BUG();
436 static void parse_connect_nb(struct conn *trtg_unconn_l)
438 __u32 addrtypelen;
439 __u32 addrlen;
440 __u8 *addrtype;
441 __u8 *addr;
443 __u32 read = 0;
444 int rc;
446 BUG_ON(read > trtg_unconn_l->target.unconnected.paramlen);
447 rc = decode_len(trtg_unconn_l->target.unconnected.cmdparams + read,
448 trtg_unconn_l->target.unconnected.paramlen - read,
449 &addrtypelen);
451 if (unlikely(rc <= 0)) {
452 send_resp_failed(trtg_unconn_l, CDR_EXECFAILED_CMD_TOO_SHORT);
453 return;
456 read += rc;
458 BUG_ON(read > trtg_unconn_l->target.unconnected.paramlen);
459 rc = decode_len(trtg_unconn_l->target.unconnected.cmdparams + read,
460 trtg_unconn_l->target.unconnected.paramlen - read,
461 &addrlen);
463 if (unlikely(rc <= 0)) {
464 send_resp_failed(trtg_unconn_l, CDR_EXECFAILED_CMD_TOO_SHORT);
465 return;
468 read += rc;
470 if (unlikely(addrtypelen > 65535 || addrtypelen > 65535)) {
471 send_resp_failed(trtg_unconn_l,
472 CDR_EXECFAILED_TARGETADDR_DOESNTEXIST);
473 return;
476 if (unlikely((read + addrtypelen + addrlen) >
477 trtg_unconn_l->target.unconnected.paramlen)) {
478 send_resp_failed(trtg_unconn_l, CDR_EXECFAILED_CMD_TOO_SHORT);
479 return;
482 addrtype = trtg_unconn_l->target.unconnected.cmdparams + read;
483 addr = addrtype + addrtypelen;
485 rc = connect_neigh(trtg_unconn_l, (__u16) addrtypelen, addrtype,
486 (__u16) addrlen, addr);
488 if (rc == 0) {
489 send_resp_ok(trtg_unconn_l);
490 } else if (rc == 2) {
491 send_resp_failed(trtg_unconn_l,
492 CDR_EXECFAILED_TARGETADDRTYPE_UNKNOWN);
493 } else if (rc == 3) {
494 send_resp_failed(trtg_unconn_l,
495 CDR_EXECFAILED_TARGETADDR_DOESNTEXIST);
496 } else if (rc == 4) {
497 send_resp_failed(trtg_unconn_l,
498 CDR_EXECFAILED_TEMPORARILY_OUT_OF_RESSOURCES);
499 } else {
500 BUG();
504 static void parse_cmd(struct conn *trtg_unconn_l)
506 __u16 code = trtg_unconn_l->target.unconnected.cmd;
508 BUG_ON(trtg_unconn_l->target.unconnected.cmdparams == 0);
510 if (code == CD_CONNECT_NB) {
511 parse_connect_nb(trtg_unconn_l);
512 } else if (code == CD_CONNECT_PORT) {
513 parse_connect_port(trtg_unconn_l);
514 } else if (code == CD_LIST_NEIGH) {
515 parse_list_neigh(trtg_unconn_l);
516 } else if (code == CD_SET_TOS) {
517 parse_set_tos(trtg_unconn_l);
518 } else {
519 send_resp_failed(trtg_unconn_l, CDR_EXECFAILED_UNKNOWN_COMMAND);
523 static void read_cmd(struct conn *trtg_unconn_l)
525 int pull;
527 pull = min(trtg_unconn_l->target.unconnected.paramlen -
528 trtg_unconn_l->target.unconnected.cmdread,
529 trtg_unconn_l->data_buf.read_remaining);
531 BUG_ON(pull < 0);
532 BUG_ON(trtg_unconn_l->target.unconnected.cmdparams == 0);
534 if (pull == 0)
535 return;
537 databuf_pull(trtg_unconn_l,
538 trtg_unconn_l->target.unconnected.cmdparams +
539 trtg_unconn_l->target.unconnected.cmdread, pull);
540 databuf_ackread(trtg_unconn_l);
542 trtg_unconn_l->target.unconnected.cmdread += pull;
545 static void read_discard(struct conn *trtg_unconn_l)
547 BUG_ON(trtg_unconn_l->target.unconnected.paramlen_read == 0);
549 while (trtg_unconn_l->target.unconnected.paramlen <
550 trtg_unconn_l->target.unconnected.cmdread &&
551 trtg_unconn_l->data_buf.read_remaining > 0) {
552 char buf[1];
553 databuf_pull(trtg_unconn_l, buf, 1);
554 databuf_ackread(trtg_unconn_l);
556 trtg_unconn_l->target.unconnected.cmdread++;
560 static void read_hdr(struct conn *trtg_unconn_l)
562 BUG_ON(trtg_unconn_l->target.unconnected.cmdparams != 0);
564 while (trtg_unconn_l->target.unconnected.paramlen_read == 0 &&
565 trtg_unconn_l->data_buf.read_remaining > 0) {
566 int rc;
568 BUG_ON(trtg_unconn_l->target.unconnected.cmdread >= 6);
570 if (trtg_unconn_l->target.unconnected.cmdread < 2) {
571 char buf[1];
572 databuf_pull(trtg_unconn_l, buf, 1);
573 trtg_unconn_l->target.unconnected.cmd <<= 8;
574 trtg_unconn_l->target.unconnected.cmd += buf[0];
575 trtg_unconn_l->target.unconnected.cmdread += 1;
576 continue;
579 databuf_pull(trtg_unconn_l,
580 trtg_unconn_l->target.unconnected.paramlen_buf +
581 trtg_unconn_l->target.unconnected.cmdread - 2,
583 trtg_unconn_l->target.unconnected.cmdread += 1;
585 rc = decode_len(trtg_unconn_l->target.unconnected.paramlen_buf,
586 trtg_unconn_l->target.unconnected.cmdread - 2,
587 &(trtg_unconn_l->target.unconnected.paramlen));
589 if (rc > 0) {
590 trtg_unconn_l->target.unconnected.paramlen_read = 1;
591 trtg_unconn_l->target.unconnected.cmdread = 0;
592 break;
597 void parse(struct conn *trtg_unconn, int fromresume)
599 start:
600 mutex_lock(&(trtg_unconn->rcv_lock));
602 if (unlikely(trtg_unconn->isreset != 0))
603 goto out;
605 if (unlikely(trtg_unconn->targettype != TARGET_UNCONNECTED))
606 goto out;
608 BUG_ON(trtg_unconn->data_buf.cpacket_buffer != 0);
610 if (trtg_unconn->target.unconnected.paramlen_read == 0) {
611 read_hdr(trtg_unconn);
612 if (trtg_unconn->target.unconnected.paramlen_read == 0)
613 goto out;
615 if (trtg_unconn->target.unconnected.paramlen >
616 MAX_CONN_CMD_LEN) {
617 send_resp_failed(trtg_unconn,
618 CDR_EXECFAILED_CMD_TOO_LONG);
622 if (trtg_unconn->target.unconnected.paramlen > MAX_CONN_CMD_LEN) {
623 read_discard(trtg_unconn);
624 goto out;
627 if (trtg_unconn->target.unconnected.cmdparams == 0) {
628 if (reserve_cpacket_buffer(trtg_unconn, fromresume))
629 goto out;
632 if (trtg_unconn->target.unconnected.paramlen >
633 trtg_unconn->target.unconnected.cmdread) {
634 read_cmd(trtg_unconn);
637 if (trtg_unconn->target.unconnected.paramlen ==
638 trtg_unconn->target.unconnected.cmdread) {
639 char *cmd = trtg_unconn->target.unconnected.cmdparams;
640 __s32 cpacket_buffer;
641 __u32 paramlen = trtg_unconn->target.unconnected.paramlen;
642 int flush = 0;
644 BUG_ON(trtg_unconn->is_client == 0);
645 mutex_lock(&(trtg_unconn->reversedir->rcv_lock));
646 cpacket_buffer = trtg_unconn->reversedir->data_buf.cpacket_buffer;
647 mutex_unlock(&(trtg_unconn->reversedir->rcv_lock));
648 parse_cmd(trtg_unconn);
649 kfree(cmd);
650 mutex_lock(&(trtg_unconn->reversedir->rcv_lock));
651 trtg_unconn->reversedir->data_buf.cpacket_buffer =
652 trtg_unconn->reversedir->data_buf.totalsize +
653 trtg_unconn->reversedir->data_buf.overhead;
654 cpacket_buffer -= trtg_unconn->reversedir->data_buf.cpacket_buffer;
655 mutex_unlock(&(trtg_unconn->reversedir->rcv_lock));
656 free_cpacket_buffer(paramlen + cpacket_buffer);
658 if (trtg_unconn->targettype != TARGET_UNCONNECTED) {
659 flush = 1;
660 } else {
661 trtg_unconn->target.unconnected.cmdparams = 0;
662 trtg_unconn->target.unconnected.cmdread = 0;
663 trtg_unconn->target.unconnected.paramlen_read = 0;
664 trtg_unconn->target.unconnected.cmd = 0;
665 trtg_unconn->target.unconnected.paramlen = 0;
668 mutex_unlock(&(trtg_unconn->rcv_lock));
669 if (flush)
670 flush_buf(trtg_unconn);
671 flush_buf(trtg_unconn->reversedir);
672 if (flush == 0)
673 goto start;
674 return;
677 out:
678 mutex_unlock(&(trtg_unconn->rcv_lock));
681 int __init cor_cpacket_init(void)
683 INIT_WORK(&cpacket_resume_work, cpacket_buffer_resume);
684 cpacket_resume_running = 0;
685 cpacket_bufferusage = 0;
686 cpacket_kmallocfailed = 0;
687 return 0;
690 MODULE_LICENSE("GPL");