conn rcv_lock converted to spinlock, struct cor_sock created, kernel_packet skb_clone...
[cor_2_6_31.git] / net / cor / cpacket_parse.c
blob74166682e5371a53cf05655501c3846829ba510a
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_ATOMIC);
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 spin_lock_bh(&(trtg_unconn_l->reversedir->rcv_lock));
100 trtg_unconn_l->reversedir->data_buf.cpacket_buffer += resplen;
101 spin_unlock_bh(&(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 spin_lock_bh(&(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 spin_unlock_bh(&(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 spin_lock_bh(&(trtg_unconn_l->reversedir->rcv_lock));
277 receive_cpacketresp(trtg_unconn_l->reversedir, (char *) &respcode, 1);
278 spin_unlock_bh(&(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 spin_lock_bh(&(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 spin_unlock_bh(&(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 spin_lock_bh(&(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 spin_unlock_bh(&(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_ATOMIC);
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 #warning todo send ok when receiving conn_success and failed when receiving reset
490 send_resp_ok(trtg_unconn_l);
491 } else if (rc == 2) {
492 send_resp_failed(trtg_unconn_l,
493 CDR_EXECFAILED_TARGETADDRTYPE_UNKNOWN);
494 } else if (rc == 3) {
495 send_resp_failed(trtg_unconn_l,
496 CDR_EXECFAILED_TARGETADDR_DOESNTEXIST);
497 } else if (rc == 4) {
498 send_resp_failed(trtg_unconn_l,
499 CDR_EXECFAILED_TEMPORARILY_OUT_OF_RESSOURCES);
500 } else {
501 BUG();
505 static void parse_cmd(struct conn *trtg_unconn_l)
507 __u16 code = trtg_unconn_l->target.unconnected.cmd;
509 BUG_ON(trtg_unconn_l->target.unconnected.cmdparams == 0);
511 if (code == CD_CONNECT_NB) {
512 parse_connect_nb(trtg_unconn_l);
513 } else if (code == CD_CONNECT_PORT) {
514 parse_connect_port(trtg_unconn_l);
515 } else if (code == CD_LIST_NEIGH) {
516 parse_list_neigh(trtg_unconn_l);
517 } else if (code == CD_SET_TOS) {
518 parse_set_tos(trtg_unconn_l);
519 } else {
520 send_resp_failed(trtg_unconn_l, CDR_EXECFAILED_UNKNOWN_COMMAND);
524 static void read_cmd(struct conn *trtg_unconn_l)
526 int pull;
528 pull = min(trtg_unconn_l->target.unconnected.paramlen -
529 trtg_unconn_l->target.unconnected.cmdread,
530 trtg_unconn_l->data_buf.read_remaining);
532 BUG_ON(pull < 0);
533 BUG_ON(trtg_unconn_l->target.unconnected.cmdparams == 0);
535 if (pull == 0)
536 return;
538 databuf_pull(trtg_unconn_l,
539 trtg_unconn_l->target.unconnected.cmdparams +
540 trtg_unconn_l->target.unconnected.cmdread, pull);
541 databuf_ackread(trtg_unconn_l);
543 trtg_unconn_l->target.unconnected.cmdread += pull;
546 static void read_discard(struct conn *trtg_unconn_l)
548 BUG_ON(trtg_unconn_l->target.unconnected.paramlen_read == 0);
550 while (trtg_unconn_l->target.unconnected.paramlen <
551 trtg_unconn_l->target.unconnected.cmdread &&
552 trtg_unconn_l->data_buf.read_remaining > 0) {
553 char buf[1];
554 databuf_pull(trtg_unconn_l, buf, 1);
555 databuf_ackread(trtg_unconn_l);
557 trtg_unconn_l->target.unconnected.cmdread++;
561 static void read_hdr(struct conn *trtg_unconn_l)
563 BUG_ON(trtg_unconn_l->target.unconnected.cmdparams != 0);
565 while (trtg_unconn_l->target.unconnected.paramlen_read == 0 &&
566 trtg_unconn_l->data_buf.read_remaining > 0) {
567 int rc;
569 BUG_ON(trtg_unconn_l->target.unconnected.cmdread >= 6);
571 if (trtg_unconn_l->target.unconnected.cmdread < 2) {
572 char buf[1];
573 databuf_pull(trtg_unconn_l, buf, 1);
574 trtg_unconn_l->target.unconnected.cmd <<= 8;
575 trtg_unconn_l->target.unconnected.cmd += buf[0];
576 trtg_unconn_l->target.unconnected.cmdread += 1;
577 continue;
580 databuf_pull(trtg_unconn_l,
581 trtg_unconn_l->target.unconnected.paramlen_buf +
582 trtg_unconn_l->target.unconnected.cmdread - 2,
584 trtg_unconn_l->target.unconnected.cmdread += 1;
586 rc = decode_len(trtg_unconn_l->target.unconnected.paramlen_buf,
587 trtg_unconn_l->target.unconnected.cmdread - 2,
588 &(trtg_unconn_l->target.unconnected.paramlen));
590 if (rc > 0) {
591 trtg_unconn_l->target.unconnected.paramlen_read = 1;
592 trtg_unconn_l->target.unconnected.cmdread = 0;
593 break;
598 void parse(struct conn *trtg_unconn, int fromresume)
600 start:
601 spin_lock_bh(&(trtg_unconn->rcv_lock));
603 if (unlikely(trtg_unconn->isreset != 0))
604 goto out;
606 if (unlikely(trtg_unconn->targettype != TARGET_UNCONNECTED))
607 goto out;
609 BUG_ON(trtg_unconn->data_buf.cpacket_buffer != 0);
611 if (trtg_unconn->target.unconnected.paramlen_read == 0) {
612 read_hdr(trtg_unconn);
613 if (trtg_unconn->target.unconnected.paramlen_read == 0)
614 goto out;
616 if (trtg_unconn->target.unconnected.paramlen >
617 MAX_CONN_CMD_LEN) {
618 send_resp_failed(trtg_unconn,
619 CDR_EXECFAILED_CMD_TOO_LONG);
623 if (trtg_unconn->target.unconnected.paramlen > MAX_CONN_CMD_LEN) {
624 read_discard(trtg_unconn);
625 goto out;
628 if (trtg_unconn->target.unconnected.cmdparams == 0) {
629 if (reserve_cpacket_buffer(trtg_unconn, fromresume))
630 goto out;
633 if (trtg_unconn->target.unconnected.paramlen >
634 trtg_unconn->target.unconnected.cmdread) {
635 read_cmd(trtg_unconn);
638 if (trtg_unconn->target.unconnected.paramlen ==
639 trtg_unconn->target.unconnected.cmdread) {
640 char *cmd = trtg_unconn->target.unconnected.cmdparams;
641 __s32 cpacket_buffer;
642 __u32 paramlen = trtg_unconn->target.unconnected.paramlen;
643 int flush = 0;
645 BUG_ON(trtg_unconn->is_client == 0);
646 spin_lock_bh(&(trtg_unconn->reversedir->rcv_lock));
647 cpacket_buffer = trtg_unconn->reversedir->data_buf.cpacket_buffer;
648 spin_unlock_bh(&(trtg_unconn->reversedir->rcv_lock));
649 parse_cmd(trtg_unconn);
650 kfree(cmd);
651 spin_lock_bh(&(trtg_unconn->reversedir->rcv_lock));
652 trtg_unconn->reversedir->data_buf.cpacket_buffer =
653 trtg_unconn->reversedir->data_buf.totalsize +
654 trtg_unconn->reversedir->data_buf.overhead;
655 cpacket_buffer -= trtg_unconn->reversedir->data_buf.cpacket_buffer;
656 spin_unlock_bh(&(trtg_unconn->reversedir->rcv_lock));
657 free_cpacket_buffer(paramlen + cpacket_buffer);
659 if (trtg_unconn->targettype != TARGET_UNCONNECTED) {
660 flush = 1;
661 } else {
662 trtg_unconn->target.unconnected.cmdparams = 0;
663 trtg_unconn->target.unconnected.cmdread = 0;
664 trtg_unconn->target.unconnected.paramlen_read = 0;
665 trtg_unconn->target.unconnected.cmd = 0;
666 trtg_unconn->target.unconnected.paramlen = 0;
669 spin_unlock_bh(&(trtg_unconn->rcv_lock));
670 if (flush)
671 flush_buf(trtg_unconn);
672 flush_buf(trtg_unconn->reversedir);
673 if (flush == 0)
674 goto start;
675 return;
678 out:
679 spin_unlock_bh(&(trtg_unconn->rcv_lock));
682 int __init cor_cpacket_init(void)
684 INIT_WORK(&cpacket_resume_work, cpacket_buffer_resume);
685 cpacket_resume_running = 0;
686 cpacket_bufferusage = 0;
687 cpacket_kmallocfailed = 0;
688 return 0;
691 MODULE_LICENSE("GPL");