diff options
Diffstat (limited to 'drivers/infiniband/hw/nes/nes_cm.c')
-rw-r--r-- | drivers/infiniband/hw/nes/nes_cm.c | 586 |
1 files changed, 393 insertions, 193 deletions
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index 4a65b96db2c..52425154acd 100644 --- a/drivers/infiniband/hw/nes/nes_cm.c +++ b/drivers/infiniband/hw/nes/nes_cm.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006 - 2008 NetEffect, Inc. All rights reserved. | 2 | * Copyright (c) 2006 - 2009 Intel-NE, Inc. All rights reserved. |
3 | * | 3 | * |
4 | * This software is available to you under a choice of one of two | 4 | * This software is available to you under a choice of one of two |
5 | * licenses. You may choose to be licensed under the terms of the GNU | 5 | * licenses. You may choose to be licensed under the terms of the GNU |
@@ -103,6 +103,7 @@ static int nes_disconnect(struct nes_qp *nesqp, int abrupt); | |||
103 | static void nes_disconnect_worker(struct work_struct *work); | 103 | static void nes_disconnect_worker(struct work_struct *work); |
104 | 104 | ||
105 | static int send_mpa_request(struct nes_cm_node *, struct sk_buff *); | 105 | static int send_mpa_request(struct nes_cm_node *, struct sk_buff *); |
106 | static int send_mpa_reject(struct nes_cm_node *); | ||
106 | static int send_syn(struct nes_cm_node *, u32, struct sk_buff *); | 107 | static int send_syn(struct nes_cm_node *, u32, struct sk_buff *); |
107 | static int send_reset(struct nes_cm_node *, struct sk_buff *); | 108 | static int send_reset(struct nes_cm_node *, struct sk_buff *); |
108 | static int send_ack(struct nes_cm_node *cm_node, struct sk_buff *skb); | 109 | static int send_ack(struct nes_cm_node *cm_node, struct sk_buff *skb); |
@@ -113,8 +114,7 @@ static void process_packet(struct nes_cm_node *, struct sk_buff *, | |||
113 | static void active_open_err(struct nes_cm_node *, struct sk_buff *, int); | 114 | static void active_open_err(struct nes_cm_node *, struct sk_buff *, int); |
114 | static void passive_open_err(struct nes_cm_node *, struct sk_buff *, int); | 115 | static void passive_open_err(struct nes_cm_node *, struct sk_buff *, int); |
115 | static void cleanup_retrans_entry(struct nes_cm_node *); | 116 | static void cleanup_retrans_entry(struct nes_cm_node *); |
116 | static void handle_rcv_mpa(struct nes_cm_node *, struct sk_buff *, | 117 | static void handle_rcv_mpa(struct nes_cm_node *, struct sk_buff *); |
117 | enum nes_cm_event_type); | ||
118 | static void free_retrans_entry(struct nes_cm_node *cm_node); | 118 | static void free_retrans_entry(struct nes_cm_node *cm_node); |
119 | static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph, | 119 | static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph, |
120 | struct sk_buff *skb, int optionsize, int passive); | 120 | struct sk_buff *skb, int optionsize, int passive); |
@@ -124,6 +124,8 @@ static void cm_event_connected(struct nes_cm_event *); | |||
124 | static void cm_event_connect_error(struct nes_cm_event *); | 124 | static void cm_event_connect_error(struct nes_cm_event *); |
125 | static void cm_event_reset(struct nes_cm_event *); | 125 | static void cm_event_reset(struct nes_cm_event *); |
126 | static void cm_event_mpa_req(struct nes_cm_event *); | 126 | static void cm_event_mpa_req(struct nes_cm_event *); |
127 | static void cm_event_mpa_reject(struct nes_cm_event *); | ||
128 | static void handle_recv_entry(struct nes_cm_node *cm_node, u32 rem_node); | ||
127 | 129 | ||
128 | static void print_core(struct nes_cm_core *core); | 130 | static void print_core(struct nes_cm_core *core); |
129 | 131 | ||
@@ -196,7 +198,6 @@ static struct nes_cm_event *create_event(struct nes_cm_node *cm_node, | |||
196 | */ | 198 | */ |
197 | static int send_mpa_request(struct nes_cm_node *cm_node, struct sk_buff *skb) | 199 | static int send_mpa_request(struct nes_cm_node *cm_node, struct sk_buff *skb) |
198 | { | 200 | { |
199 | int ret; | ||
200 | if (!skb) { | 201 | if (!skb) { |
201 | nes_debug(NES_DBG_CM, "skb set to NULL\n"); | 202 | nes_debug(NES_DBG_CM, "skb set to NULL\n"); |
202 | return -1; | 203 | return -1; |
@@ -206,11 +207,27 @@ static int send_mpa_request(struct nes_cm_node *cm_node, struct sk_buff *skb) | |||
206 | form_cm_frame(skb, cm_node, NULL, 0, &cm_node->mpa_frame, | 207 | form_cm_frame(skb, cm_node, NULL, 0, &cm_node->mpa_frame, |
207 | cm_node->mpa_frame_size, SET_ACK); | 208 | cm_node->mpa_frame_size, SET_ACK); |
208 | 209 | ||
209 | ret = schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 1, 0); | 210 | return schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 1, 0); |
210 | if (ret < 0) | 211 | } |
211 | return ret; | ||
212 | 212 | ||
213 | return 0; | 213 | |
214 | |||
215 | static int send_mpa_reject(struct nes_cm_node *cm_node) | ||
216 | { | ||
217 | struct sk_buff *skb = NULL; | ||
218 | |||
219 | skb = dev_alloc_skb(MAX_CM_BUFFER); | ||
220 | if (!skb) { | ||
221 | nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n"); | ||
222 | return -ENOMEM; | ||
223 | } | ||
224 | |||
225 | /* send an MPA reject frame */ | ||
226 | form_cm_frame(skb, cm_node, NULL, 0, &cm_node->mpa_frame, | ||
227 | cm_node->mpa_frame_size, SET_ACK | SET_FIN); | ||
228 | |||
229 | cm_node->state = NES_CM_STATE_FIN_WAIT1; | ||
230 | return schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 1, 0); | ||
214 | } | 231 | } |
215 | 232 | ||
216 | 233 | ||
@@ -218,14 +235,17 @@ static int send_mpa_request(struct nes_cm_node *cm_node, struct sk_buff *skb) | |||
218 | * recv_mpa - process a received TCP pkt, we are expecting an | 235 | * recv_mpa - process a received TCP pkt, we are expecting an |
219 | * IETF MPA frame | 236 | * IETF MPA frame |
220 | */ | 237 | */ |
221 | static int parse_mpa(struct nes_cm_node *cm_node, u8 *buffer, u32 len) | 238 | static int parse_mpa(struct nes_cm_node *cm_node, u8 *buffer, u32 *type, |
239 | u32 len) | ||
222 | { | 240 | { |
223 | struct ietf_mpa_frame *mpa_frame; | 241 | struct ietf_mpa_frame *mpa_frame; |
224 | 242 | ||
243 | *type = NES_MPA_REQUEST_ACCEPT; | ||
244 | |||
225 | /* assume req frame is in tcp data payload */ | 245 | /* assume req frame is in tcp data payload */ |
226 | if (len < sizeof(struct ietf_mpa_frame)) { | 246 | if (len < sizeof(struct ietf_mpa_frame)) { |
227 | nes_debug(NES_DBG_CM, "The received ietf buffer was too small (%x)\n", len); | 247 | nes_debug(NES_DBG_CM, "The received ietf buffer was too small (%x)\n", len); |
228 | return -1; | 248 | return -EINVAL; |
229 | } | 249 | } |
230 | 250 | ||
231 | mpa_frame = (struct ietf_mpa_frame *)buffer; | 251 | mpa_frame = (struct ietf_mpa_frame *)buffer; |
@@ -234,14 +254,25 @@ static int parse_mpa(struct nes_cm_node *cm_node, u8 *buffer, u32 len) | |||
234 | if (cm_node->mpa_frame_size + sizeof(struct ietf_mpa_frame) != len) { | 254 | if (cm_node->mpa_frame_size + sizeof(struct ietf_mpa_frame) != len) { |
235 | nes_debug(NES_DBG_CM, "The received ietf buffer was not right" | 255 | nes_debug(NES_DBG_CM, "The received ietf buffer was not right" |
236 | " complete (%x + %x != %x)\n", | 256 | " complete (%x + %x != %x)\n", |
237 | cm_node->mpa_frame_size, (u32)sizeof(struct ietf_mpa_frame), len); | 257 | cm_node->mpa_frame_size, |
238 | return -1; | 258 | (u32)sizeof(struct ietf_mpa_frame), len); |
259 | return -EINVAL; | ||
260 | } | ||
261 | /* make sure it does not exceed the max size */ | ||
262 | if (len > MAX_CM_BUFFER) { | ||
263 | nes_debug(NES_DBG_CM, "The received ietf buffer was too large" | ||
264 | " (%x + %x != %x)\n", | ||
265 | cm_node->mpa_frame_size, | ||
266 | (u32)sizeof(struct ietf_mpa_frame), len); | ||
267 | return -EINVAL; | ||
239 | } | 268 | } |
240 | 269 | ||
241 | /* copy entire MPA frame to our cm_node's frame */ | 270 | /* copy entire MPA frame to our cm_node's frame */ |
242 | memcpy(cm_node->mpa_frame_buf, buffer + sizeof(struct ietf_mpa_frame), | 271 | memcpy(cm_node->mpa_frame_buf, buffer + sizeof(struct ietf_mpa_frame), |
243 | cm_node->mpa_frame_size); | 272 | cm_node->mpa_frame_size); |
244 | 273 | ||
274 | if (mpa_frame->flags & IETF_MPA_FLAGS_REJECT) | ||
275 | *type = NES_MPA_REQUEST_REJECT; | ||
245 | return 0; | 276 | return 0; |
246 | } | 277 | } |
247 | 278 | ||
@@ -380,7 +411,7 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
380 | 411 | ||
381 | new_send = kzalloc(sizeof(*new_send), GFP_ATOMIC); | 412 | new_send = kzalloc(sizeof(*new_send), GFP_ATOMIC); |
382 | if (!new_send) | 413 | if (!new_send) |
383 | return -1; | 414 | return -ENOMEM; |
384 | 415 | ||
385 | /* new_send->timetosend = currenttime */ | 416 | /* new_send->timetosend = currenttime */ |
386 | new_send->retrycount = NES_DEFAULT_RETRYS; | 417 | new_send->retrycount = NES_DEFAULT_RETRYS; |
@@ -394,9 +425,11 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
394 | 425 | ||
395 | if (type == NES_TIMER_TYPE_CLOSE) { | 426 | if (type == NES_TIMER_TYPE_CLOSE) { |
396 | new_send->timetosend += (HZ/10); | 427 | new_send->timetosend += (HZ/10); |
397 | spin_lock_irqsave(&cm_node->recv_list_lock, flags); | 428 | if (cm_node->recv_entry) { |
398 | list_add_tail(&new_send->list, &cm_node->recv_list); | 429 | WARN_ON(1); |
399 | spin_unlock_irqrestore(&cm_node->recv_list_lock, flags); | 430 | return -EINVAL; |
431 | } | ||
432 | cm_node->recv_entry = new_send; | ||
400 | } | 433 | } |
401 | 434 | ||
402 | if (type == NES_TIMER_TYPE_SEND) { | 435 | if (type == NES_TIMER_TYPE_SEND) { |
@@ -435,24 +468,78 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
435 | return ret; | 468 | return ret; |
436 | } | 469 | } |
437 | 470 | ||
471 | static void nes_retrans_expired(struct nes_cm_node *cm_node) | ||
472 | { | ||
473 | switch (cm_node->state) { | ||
474 | case NES_CM_STATE_SYN_RCVD: | ||
475 | case NES_CM_STATE_CLOSING: | ||
476 | rem_ref_cm_node(cm_node->cm_core, cm_node); | ||
477 | break; | ||
478 | case NES_CM_STATE_LAST_ACK: | ||
479 | case NES_CM_STATE_FIN_WAIT1: | ||
480 | case NES_CM_STATE_MPAREJ_RCVD: | ||
481 | send_reset(cm_node, NULL); | ||
482 | break; | ||
483 | default: | ||
484 | create_event(cm_node, NES_CM_EVENT_ABORTED); | ||
485 | } | ||
486 | } | ||
487 | |||
488 | static void handle_recv_entry(struct nes_cm_node *cm_node, u32 rem_node) | ||
489 | { | ||
490 | struct nes_timer_entry *recv_entry = cm_node->recv_entry; | ||
491 | struct iw_cm_id *cm_id = cm_node->cm_id; | ||
492 | struct nes_qp *nesqp; | ||
493 | unsigned long qplockflags; | ||
494 | |||
495 | if (!recv_entry) | ||
496 | return; | ||
497 | nesqp = (struct nes_qp *)recv_entry->skb; | ||
498 | if (nesqp) { | ||
499 | spin_lock_irqsave(&nesqp->lock, qplockflags); | ||
500 | if (nesqp->cm_id) { | ||
501 | nes_debug(NES_DBG_CM, "QP%u: cm_id = %p, " | ||
502 | "refcount = %d: HIT A " | ||
503 | "NES_TIMER_TYPE_CLOSE with something " | ||
504 | "to do!!!\n", nesqp->hwqp.qp_id, cm_id, | ||
505 | atomic_read(&nesqp->refcount)); | ||
506 | nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED; | ||
507 | nesqp->last_aeq = NES_AEQE_AEID_RESET_SENT; | ||
508 | nesqp->ibqp_state = IB_QPS_ERR; | ||
509 | spin_unlock_irqrestore(&nesqp->lock, qplockflags); | ||
510 | nes_cm_disconn(nesqp); | ||
511 | } else { | ||
512 | spin_unlock_irqrestore(&nesqp->lock, qplockflags); | ||
513 | nes_debug(NES_DBG_CM, "QP%u: cm_id = %p, " | ||
514 | "refcount = %d: HIT A " | ||
515 | "NES_TIMER_TYPE_CLOSE with nothing " | ||
516 | "to do!!!\n", nesqp->hwqp.qp_id, cm_id, | ||
517 | atomic_read(&nesqp->refcount)); | ||
518 | } | ||
519 | } else if (rem_node) { | ||
520 | /* TIME_WAIT state */ | ||
521 | rem_ref_cm_node(cm_node->cm_core, cm_node); | ||
522 | } | ||
523 | if (cm_node->cm_id) | ||
524 | cm_id->rem_ref(cm_id); | ||
525 | kfree(recv_entry); | ||
526 | cm_node->recv_entry = NULL; | ||
527 | } | ||
438 | 528 | ||
439 | /** | 529 | /** |
440 | * nes_cm_timer_tick | 530 | * nes_cm_timer_tick |
441 | */ | 531 | */ |
442 | static void nes_cm_timer_tick(unsigned long pass) | 532 | static void nes_cm_timer_tick(unsigned long pass) |
443 | { | 533 | { |
444 | unsigned long flags, qplockflags; | 534 | unsigned long flags; |
445 | unsigned long nexttimeout = jiffies + NES_LONG_TIME; | 535 | unsigned long nexttimeout = jiffies + NES_LONG_TIME; |
446 | struct iw_cm_id *cm_id; | ||
447 | struct nes_cm_node *cm_node; | 536 | struct nes_cm_node *cm_node; |
448 | struct nes_timer_entry *send_entry, *recv_entry; | 537 | struct nes_timer_entry *send_entry, *recv_entry; |
449 | struct list_head *list_core, *list_core_temp; | 538 | struct list_head *list_core_temp; |
450 | struct list_head *list_node, *list_node_temp; | 539 | struct list_head *list_node; |
451 | struct nes_cm_core *cm_core = g_cm_core; | 540 | struct nes_cm_core *cm_core = g_cm_core; |
452 | struct nes_qp *nesqp; | ||
453 | u32 settimer = 0; | 541 | u32 settimer = 0; |
454 | int ret = NETDEV_TX_OK; | 542 | int ret = NETDEV_TX_OK; |
455 | enum nes_cm_node_state last_state; | ||
456 | 543 | ||
457 | struct list_head timer_list; | 544 | struct list_head timer_list; |
458 | INIT_LIST_HEAD(&timer_list); | 545 | INIT_LIST_HEAD(&timer_list); |
@@ -461,7 +548,7 @@ static void nes_cm_timer_tick(unsigned long pass) | |||
461 | list_for_each_safe(list_node, list_core_temp, | 548 | list_for_each_safe(list_node, list_core_temp, |
462 | &cm_core->connected_nodes) { | 549 | &cm_core->connected_nodes) { |
463 | cm_node = container_of(list_node, struct nes_cm_node, list); | 550 | cm_node = container_of(list_node, struct nes_cm_node, list); |
464 | if (!list_empty(&cm_node->recv_list) || (cm_node->send_entry)) { | 551 | if ((cm_node->recv_entry) || (cm_node->send_entry)) { |
465 | add_ref_cm_node(cm_node); | 552 | add_ref_cm_node(cm_node); |
466 | list_add(&cm_node->timer_entry, &timer_list); | 553 | list_add(&cm_node->timer_entry, &timer_list); |
467 | } | 554 | } |
@@ -471,54 +558,18 @@ static void nes_cm_timer_tick(unsigned long pass) | |||
471 | list_for_each_safe(list_node, list_core_temp, &timer_list) { | 558 | list_for_each_safe(list_node, list_core_temp, &timer_list) { |
472 | cm_node = container_of(list_node, struct nes_cm_node, | 559 | cm_node = container_of(list_node, struct nes_cm_node, |
473 | timer_entry); | 560 | timer_entry); |
474 | spin_lock_irqsave(&cm_node->recv_list_lock, flags); | 561 | recv_entry = cm_node->recv_entry; |
475 | list_for_each_safe(list_core, list_node_temp, | 562 | |
476 | &cm_node->recv_list) { | 563 | if (recv_entry) { |
477 | recv_entry = container_of(list_core, | ||
478 | struct nes_timer_entry, list); | ||
479 | if (!recv_entry) | ||
480 | break; | ||
481 | if (time_after(recv_entry->timetosend, jiffies)) { | 564 | if (time_after(recv_entry->timetosend, jiffies)) { |
482 | if (nexttimeout > recv_entry->timetosend || | 565 | if (nexttimeout > recv_entry->timetosend || |
483 | !settimer) { | 566 | !settimer) { |
484 | nexttimeout = recv_entry->timetosend; | 567 | nexttimeout = recv_entry->timetosend; |
485 | settimer = 1; | 568 | settimer = 1; |
486 | } | 569 | } |
487 | continue; | 570 | } else |
488 | } | 571 | handle_recv_entry(cm_node, 1); |
489 | list_del(&recv_entry->list); | ||
490 | cm_id = cm_node->cm_id; | ||
491 | spin_unlock_irqrestore(&cm_node->recv_list_lock, flags); | ||
492 | nesqp = (struct nes_qp *)recv_entry->skb; | ||
493 | spin_lock_irqsave(&nesqp->lock, qplockflags); | ||
494 | if (nesqp->cm_id) { | ||
495 | nes_debug(NES_DBG_CM, "QP%u: cm_id = %p, " | ||
496 | "refcount = %d: HIT A " | ||
497 | "NES_TIMER_TYPE_CLOSE with something " | ||
498 | "to do!!!\n", nesqp->hwqp.qp_id, cm_id, | ||
499 | atomic_read(&nesqp->refcount)); | ||
500 | nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED; | ||
501 | nesqp->last_aeq = NES_AEQE_AEID_RESET_SENT; | ||
502 | nesqp->ibqp_state = IB_QPS_ERR; | ||
503 | spin_unlock_irqrestore(&nesqp->lock, | ||
504 | qplockflags); | ||
505 | nes_cm_disconn(nesqp); | ||
506 | } else { | ||
507 | spin_unlock_irqrestore(&nesqp->lock, | ||
508 | qplockflags); | ||
509 | nes_debug(NES_DBG_CM, "QP%u: cm_id = %p, " | ||
510 | "refcount = %d: HIT A " | ||
511 | "NES_TIMER_TYPE_CLOSE with nothing " | ||
512 | "to do!!!\n", nesqp->hwqp.qp_id, cm_id, | ||
513 | atomic_read(&nesqp->refcount)); | ||
514 | } | ||
515 | if (cm_id) | ||
516 | cm_id->rem_ref(cm_id); | ||
517 | |||
518 | kfree(recv_entry); | ||
519 | spin_lock_irqsave(&cm_node->recv_list_lock, flags); | ||
520 | } | 572 | } |
521 | spin_unlock_irqrestore(&cm_node->recv_list_lock, flags); | ||
522 | 573 | ||
523 | spin_lock_irqsave(&cm_node->retrans_list_lock, flags); | 574 | spin_lock_irqsave(&cm_node->retrans_list_lock, flags); |
524 | do { | 575 | do { |
@@ -533,12 +584,11 @@ static void nes_cm_timer_tick(unsigned long pass) | |||
533 | nexttimeout = | 584 | nexttimeout = |
534 | send_entry->timetosend; | 585 | send_entry->timetosend; |
535 | settimer = 1; | 586 | settimer = 1; |
536 | break; | ||
537 | } | 587 | } |
538 | } else { | 588 | } else { |
539 | free_retrans_entry(cm_node); | 589 | free_retrans_entry(cm_node); |
540 | break; | ||
541 | } | 590 | } |
591 | break; | ||
542 | } | 592 | } |
543 | 593 | ||
544 | if ((cm_node->state == NES_CM_STATE_TSA) || | 594 | if ((cm_node->state == NES_CM_STATE_TSA) || |
@@ -550,16 +600,12 @@ static void nes_cm_timer_tick(unsigned long pass) | |||
550 | if (!send_entry->retranscount || | 600 | if (!send_entry->retranscount || |
551 | !send_entry->retrycount) { | 601 | !send_entry->retrycount) { |
552 | cm_packets_dropped++; | 602 | cm_packets_dropped++; |
553 | last_state = cm_node->state; | ||
554 | cm_node->state = NES_CM_STATE_CLOSED; | ||
555 | free_retrans_entry(cm_node); | 603 | free_retrans_entry(cm_node); |
604 | |||
556 | spin_unlock_irqrestore( | 605 | spin_unlock_irqrestore( |
557 | &cm_node->retrans_list_lock, flags); | 606 | &cm_node->retrans_list_lock, flags); |
558 | if (last_state == NES_CM_STATE_SYN_RCVD) | 607 | nes_retrans_expired(cm_node); |
559 | rem_ref_cm_node(cm_core, cm_node); | 608 | cm_node->state = NES_CM_STATE_CLOSED; |
560 | else | ||
561 | create_event(cm_node, | ||
562 | NES_CM_EVENT_ABORTED); | ||
563 | spin_lock_irqsave(&cm_node->retrans_list_lock, | 609 | spin_lock_irqsave(&cm_node->retrans_list_lock, |
564 | flags); | 610 | flags); |
565 | break; | 611 | break; |
@@ -714,7 +760,7 @@ static int send_reset(struct nes_cm_node *cm_node, struct sk_buff *skb) | |||
714 | skb = dev_alloc_skb(MAX_CM_BUFFER); | 760 | skb = dev_alloc_skb(MAX_CM_BUFFER); |
715 | if (!skb) { | 761 | if (!skb) { |
716 | nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n"); | 762 | nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n"); |
717 | return -1; | 763 | return -ENOMEM; |
718 | } | 764 | } |
719 | 765 | ||
720 | form_cm_frame(skb, cm_node, NULL, 0, NULL, 0, flags); | 766 | form_cm_frame(skb, cm_node, NULL, 0, NULL, 0, flags); |
@@ -778,14 +824,10 @@ static struct nes_cm_node *find_node(struct nes_cm_core *cm_core, | |||
778 | unsigned long flags; | 824 | unsigned long flags; |
779 | struct list_head *hte; | 825 | struct list_head *hte; |
780 | struct nes_cm_node *cm_node; | 826 | struct nes_cm_node *cm_node; |
781 | __be32 tmp_addr = cpu_to_be32(loc_addr); | ||
782 | 827 | ||
783 | /* get a handle on the hte */ | 828 | /* get a handle on the hte */ |
784 | hte = &cm_core->connected_nodes; | 829 | hte = &cm_core->connected_nodes; |
785 | 830 | ||
786 | nes_debug(NES_DBG_CM, "Searching for an owner node: %pI4:%x from core %p->%p\n", | ||
787 | &tmp_addr, loc_port, cm_core, hte); | ||
788 | |||
789 | /* walk list and find cm_node associated with this session ID */ | 831 | /* walk list and find cm_node associated with this session ID */ |
790 | spin_lock_irqsave(&cm_core->ht_lock, flags); | 832 | spin_lock_irqsave(&cm_core->ht_lock, flags); |
791 | list_for_each_entry(cm_node, hte, list) { | 833 | list_for_each_entry(cm_node, hte, list) { |
@@ -875,7 +917,8 @@ static int add_hte_node(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node | |||
875 | static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core, | 917 | static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core, |
876 | struct nes_cm_listener *listener, int free_hanging_nodes) | 918 | struct nes_cm_listener *listener, int free_hanging_nodes) |
877 | { | 919 | { |
878 | int ret = 1; | 920 | int ret = -EINVAL; |
921 | int err = 0; | ||
879 | unsigned long flags; | 922 | unsigned long flags; |
880 | struct list_head *list_pos = NULL; | 923 | struct list_head *list_pos = NULL; |
881 | struct list_head *list_temp = NULL; | 924 | struct list_head *list_temp = NULL; |
@@ -904,10 +947,60 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core, | |||
904 | 947 | ||
905 | list_for_each_safe(list_pos, list_temp, &reset_list) { | 948 | list_for_each_safe(list_pos, list_temp, &reset_list) { |
906 | cm_node = container_of(list_pos, struct nes_cm_node, | 949 | cm_node = container_of(list_pos, struct nes_cm_node, |
907 | reset_entry); | 950 | reset_entry); |
908 | cleanup_retrans_entry(cm_node); | 951 | { |
909 | send_reset(cm_node, NULL); | 952 | struct nes_cm_node *loopback = cm_node->loopbackpartner; |
910 | rem_ref_cm_node(cm_node->cm_core, cm_node); | 953 | if (NES_CM_STATE_FIN_WAIT1 <= cm_node->state) { |
954 | rem_ref_cm_node(cm_node->cm_core, cm_node); | ||
955 | } else { | ||
956 | if (!loopback) { | ||
957 | cleanup_retrans_entry(cm_node); | ||
958 | err = send_reset(cm_node, NULL); | ||
959 | if (err) { | ||
960 | cm_node->state = | ||
961 | NES_CM_STATE_CLOSED; | ||
962 | WARN_ON(1); | ||
963 | } else { | ||
964 | cm_node->state = | ||
965 | NES_CM_STATE_CLOSED; | ||
966 | rem_ref_cm_node( | ||
967 | cm_node->cm_core, | ||
968 | cm_node); | ||
969 | } | ||
970 | } else { | ||
971 | struct nes_cm_event event; | ||
972 | |||
973 | event.cm_node = loopback; | ||
974 | event.cm_info.rem_addr = | ||
975 | loopback->rem_addr; | ||
976 | event.cm_info.loc_addr = | ||
977 | loopback->loc_addr; | ||
978 | event.cm_info.rem_port = | ||
979 | loopback->rem_port; | ||
980 | event.cm_info.loc_port = | ||
981 | loopback->loc_port; | ||
982 | event.cm_info.cm_id = loopback->cm_id; | ||
983 | cm_event_connect_error(&event); | ||
984 | loopback->state = NES_CM_STATE_CLOSED; | ||
985 | |||
986 | event.cm_node = cm_node; | ||
987 | event.cm_info.rem_addr = | ||
988 | cm_node->rem_addr; | ||
989 | event.cm_info.loc_addr = | ||
990 | cm_node->loc_addr; | ||
991 | event.cm_info.rem_port = | ||
992 | cm_node->rem_port; | ||
993 | event.cm_info.loc_port = | ||
994 | cm_node->loc_port; | ||
995 | event.cm_info.cm_id = cm_node->cm_id; | ||
996 | cm_event_reset(&event); | ||
997 | |||
998 | rem_ref_cm_node(cm_node->cm_core, | ||
999 | cm_node); | ||
1000 | |||
1001 | } | ||
1002 | } | ||
1003 | } | ||
911 | } | 1004 | } |
912 | 1005 | ||
913 | spin_lock_irqsave(&cm_core->listen_list_lock, flags); | 1006 | spin_lock_irqsave(&cm_core->listen_list_lock, flags); |
@@ -968,6 +1061,7 @@ static inline int mini_cm_accelerated(struct nes_cm_core *cm_core, | |||
968 | if (cm_node->accept_pend) { | 1061 | if (cm_node->accept_pend) { |
969 | BUG_ON(!cm_node->listener); | 1062 | BUG_ON(!cm_node->listener); |
970 | atomic_dec(&cm_node->listener->pend_accepts_cnt); | 1063 | atomic_dec(&cm_node->listener->pend_accepts_cnt); |
1064 | cm_node->accept_pend = 0; | ||
971 | BUG_ON(atomic_read(&cm_node->listener->pend_accepts_cnt) < 0); | 1065 | BUG_ON(atomic_read(&cm_node->listener->pend_accepts_cnt) < 0); |
972 | } | 1066 | } |
973 | 1067 | ||
@@ -994,7 +1088,7 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip) | |||
994 | memset(&fl, 0, sizeof fl); | 1088 | memset(&fl, 0, sizeof fl); |
995 | fl.nl_u.ip4_u.daddr = htonl(dst_ip); | 1089 | fl.nl_u.ip4_u.daddr = htonl(dst_ip); |
996 | if (ip_route_output_key(&init_net, &rt, &fl)) { | 1090 | if (ip_route_output_key(&init_net, &rt, &fl)) { |
997 | printk("%s: ip_route_output_key failed for 0x%08X\n", | 1091 | printk(KERN_ERR "%s: ip_route_output_key failed for 0x%08X\n", |
998 | __func__, dst_ip); | 1092 | __func__, dst_ip); |
999 | return rc; | 1093 | return rc; |
1000 | } | 1094 | } |
@@ -1057,8 +1151,6 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core, | |||
1057 | cm_node->cm_id); | 1151 | cm_node->cm_id); |
1058 | 1152 | ||
1059 | spin_lock_init(&cm_node->retrans_list_lock); | 1153 | spin_lock_init(&cm_node->retrans_list_lock); |
1060 | INIT_LIST_HEAD(&cm_node->recv_list); | ||
1061 | spin_lock_init(&cm_node->recv_list_lock); | ||
1062 | 1154 | ||
1063 | cm_node->loopbackpartner = NULL; | 1155 | cm_node->loopbackpartner = NULL; |
1064 | atomic_set(&cm_node->ref_count, 1); | 1156 | atomic_set(&cm_node->ref_count, 1); |
@@ -1126,10 +1218,7 @@ static int add_ref_cm_node(struct nes_cm_node *cm_node) | |||
1126 | static int rem_ref_cm_node(struct nes_cm_core *cm_core, | 1218 | static int rem_ref_cm_node(struct nes_cm_core *cm_core, |
1127 | struct nes_cm_node *cm_node) | 1219 | struct nes_cm_node *cm_node) |
1128 | { | 1220 | { |
1129 | unsigned long flags, qplockflags; | 1221 | unsigned long flags; |
1130 | struct nes_timer_entry *recv_entry; | ||
1131 | struct iw_cm_id *cm_id; | ||
1132 | struct list_head *list_core, *list_node_temp; | ||
1133 | struct nes_qp *nesqp; | 1222 | struct nes_qp *nesqp; |
1134 | 1223 | ||
1135 | if (!cm_node) | 1224 | if (!cm_node) |
@@ -1150,38 +1239,9 @@ static int rem_ref_cm_node(struct nes_cm_core *cm_core, | |||
1150 | atomic_dec(&cm_node->listener->pend_accepts_cnt); | 1239 | atomic_dec(&cm_node->listener->pend_accepts_cnt); |
1151 | BUG_ON(atomic_read(&cm_node->listener->pend_accepts_cnt) < 0); | 1240 | BUG_ON(atomic_read(&cm_node->listener->pend_accepts_cnt) < 0); |
1152 | } | 1241 | } |
1153 | BUG_ON(cm_node->send_entry); | 1242 | WARN_ON(cm_node->send_entry); |
1154 | spin_lock_irqsave(&cm_node->recv_list_lock, flags); | 1243 | if (cm_node->recv_entry) |
1155 | list_for_each_safe(list_core, list_node_temp, &cm_node->recv_list) { | 1244 | handle_recv_entry(cm_node, 0); |
1156 | recv_entry = container_of(list_core, struct nes_timer_entry, | ||
1157 | list); | ||
1158 | list_del(&recv_entry->list); | ||
1159 | cm_id = cm_node->cm_id; | ||
1160 | spin_unlock_irqrestore(&cm_node->recv_list_lock, flags); | ||
1161 | nesqp = (struct nes_qp *)recv_entry->skb; | ||
1162 | spin_lock_irqsave(&nesqp->lock, qplockflags); | ||
1163 | if (nesqp->cm_id) { | ||
1164 | nes_debug(NES_DBG_CM, "QP%u: cm_id = %p: HIT A " | ||
1165 | "NES_TIMER_TYPE_CLOSE with something to do!\n", | ||
1166 | nesqp->hwqp.qp_id, cm_id); | ||
1167 | nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED; | ||
1168 | nesqp->last_aeq = NES_AEQE_AEID_RESET_SENT; | ||
1169 | nesqp->ibqp_state = IB_QPS_ERR; | ||
1170 | spin_unlock_irqrestore(&nesqp->lock, qplockflags); | ||
1171 | nes_cm_disconn(nesqp); | ||
1172 | } else { | ||
1173 | spin_unlock_irqrestore(&nesqp->lock, qplockflags); | ||
1174 | nes_debug(NES_DBG_CM, "QP%u: cm_id = %p: HIT A " | ||
1175 | "NES_TIMER_TYPE_CLOSE with nothing to do!\n", | ||
1176 | nesqp->hwqp.qp_id, cm_id); | ||
1177 | } | ||
1178 | cm_id->rem_ref(cm_id); | ||
1179 | |||
1180 | kfree(recv_entry); | ||
1181 | spin_lock_irqsave(&cm_node->recv_list_lock, flags); | ||
1182 | } | ||
1183 | spin_unlock_irqrestore(&cm_node->recv_list_lock, flags); | ||
1184 | |||
1185 | if (cm_node->listener) { | 1245 | if (cm_node->listener) { |
1186 | mini_cm_dec_refcnt_listen(cm_core, cm_node->listener, 0); | 1246 | mini_cm_dec_refcnt_listen(cm_core, cm_node->listener, 0); |
1187 | } else { | 1247 | } else { |
@@ -1266,8 +1326,7 @@ static void drop_packet(struct sk_buff *skb) | |||
1266 | dev_kfree_skb_any(skb); | 1326 | dev_kfree_skb_any(skb); |
1267 | } | 1327 | } |
1268 | 1328 | ||
1269 | static void handle_fin_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | 1329 | static void handle_fin_pkt(struct nes_cm_node *cm_node) |
1270 | struct tcphdr *tcph) | ||
1271 | { | 1330 | { |
1272 | nes_debug(NES_DBG_CM, "Received FIN, cm_node = %p, state = %u. " | 1331 | nes_debug(NES_DBG_CM, "Received FIN, cm_node = %p, state = %u. " |
1273 | "refcnt=%d\n", cm_node, cm_node->state, | 1332 | "refcnt=%d\n", cm_node, cm_node->state, |
@@ -1279,23 +1338,30 @@ static void handle_fin_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1279 | case NES_CM_STATE_SYN_SENT: | 1338 | case NES_CM_STATE_SYN_SENT: |
1280 | case NES_CM_STATE_ESTABLISHED: | 1339 | case NES_CM_STATE_ESTABLISHED: |
1281 | case NES_CM_STATE_MPAREQ_SENT: | 1340 | case NES_CM_STATE_MPAREQ_SENT: |
1341 | case NES_CM_STATE_MPAREJ_RCVD: | ||
1282 | cm_node->state = NES_CM_STATE_LAST_ACK; | 1342 | cm_node->state = NES_CM_STATE_LAST_ACK; |
1283 | send_fin(cm_node, skb); | 1343 | send_fin(cm_node, NULL); |
1284 | break; | 1344 | break; |
1285 | case NES_CM_STATE_FIN_WAIT1: | 1345 | case NES_CM_STATE_FIN_WAIT1: |
1286 | cm_node->state = NES_CM_STATE_CLOSING; | 1346 | cm_node->state = NES_CM_STATE_CLOSING; |
1287 | send_ack(cm_node, skb); | 1347 | send_ack(cm_node, NULL); |
1348 | /* Wait for ACK as this is simultanous close.. | ||
1349 | * After we receive ACK, do not send anything.. | ||
1350 | * Just rm the node.. Done.. */ | ||
1288 | break; | 1351 | break; |
1289 | case NES_CM_STATE_FIN_WAIT2: | 1352 | case NES_CM_STATE_FIN_WAIT2: |
1290 | cm_node->state = NES_CM_STATE_TIME_WAIT; | 1353 | cm_node->state = NES_CM_STATE_TIME_WAIT; |
1291 | send_ack(cm_node, skb); | 1354 | send_ack(cm_node, NULL); |
1355 | schedule_nes_timer(cm_node, NULL, NES_TIMER_TYPE_CLOSE, 1, 0); | ||
1356 | break; | ||
1357 | case NES_CM_STATE_TIME_WAIT: | ||
1292 | cm_node->state = NES_CM_STATE_CLOSED; | 1358 | cm_node->state = NES_CM_STATE_CLOSED; |
1359 | rem_ref_cm_node(cm_node->cm_core, cm_node); | ||
1293 | break; | 1360 | break; |
1294 | case NES_CM_STATE_TSA: | 1361 | case NES_CM_STATE_TSA: |
1295 | default: | 1362 | default: |
1296 | nes_debug(NES_DBG_CM, "Error Rcvd FIN for node-%p state = %d\n", | 1363 | nes_debug(NES_DBG_CM, "Error Rcvd FIN for node-%p state = %d\n", |
1297 | cm_node, cm_node->state); | 1364 | cm_node, cm_node->state); |
1298 | drop_packet(skb); | ||
1299 | break; | 1365 | break; |
1300 | } | 1366 | } |
1301 | } | 1367 | } |
@@ -1341,23 +1407,35 @@ static void handle_rst_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1341 | cleanup_retrans_entry(cm_node); | 1407 | cleanup_retrans_entry(cm_node); |
1342 | drop_packet(skb); | 1408 | drop_packet(skb); |
1343 | break; | 1409 | break; |
1410 | case NES_CM_STATE_TIME_WAIT: | ||
1411 | cleanup_retrans_entry(cm_node); | ||
1412 | cm_node->state = NES_CM_STATE_CLOSED; | ||
1413 | rem_ref_cm_node(cm_node->cm_core, cm_node); | ||
1414 | drop_packet(skb); | ||
1415 | break; | ||
1416 | case NES_CM_STATE_FIN_WAIT1: | ||
1417 | cleanup_retrans_entry(cm_node); | ||
1418 | nes_debug(NES_DBG_CM, "Bad state %s[%u]\n", __func__, __LINE__); | ||
1344 | default: | 1419 | default: |
1345 | drop_packet(skb); | 1420 | drop_packet(skb); |
1346 | break; | 1421 | break; |
1347 | } | 1422 | } |
1348 | } | 1423 | } |
1349 | 1424 | ||
1350 | static void handle_rcv_mpa(struct nes_cm_node *cm_node, struct sk_buff *skb, | 1425 | |
1351 | enum nes_cm_event_type type) | 1426 | static void handle_rcv_mpa(struct nes_cm_node *cm_node, struct sk_buff *skb) |
1352 | { | 1427 | { |
1353 | 1428 | ||
1354 | int ret; | 1429 | int ret = 0; |
1355 | int datasize = skb->len; | 1430 | int datasize = skb->len; |
1356 | u8 *dataloc = skb->data; | 1431 | u8 *dataloc = skb->data; |
1357 | ret = parse_mpa(cm_node, dataloc, datasize); | 1432 | |
1358 | if (ret < 0) { | 1433 | enum nes_cm_event_type type = NES_CM_EVENT_UNKNOWN; |
1434 | u32 res_type; | ||
1435 | ret = parse_mpa(cm_node, dataloc, &res_type, datasize); | ||
1436 | if (ret) { | ||
1359 | nes_debug(NES_DBG_CM, "didn't like MPA Request\n"); | 1437 | nes_debug(NES_DBG_CM, "didn't like MPA Request\n"); |
1360 | if (type == NES_CM_EVENT_CONNECTED) { | 1438 | if (cm_node->state == NES_CM_STATE_MPAREQ_SENT) { |
1361 | nes_debug(NES_DBG_CM, "%s[%u] create abort for " | 1439 | nes_debug(NES_DBG_CM, "%s[%u] create abort for " |
1362 | "cm_node=%p listener=%p state=%d\n", __func__, | 1440 | "cm_node=%p listener=%p state=%d\n", __func__, |
1363 | __LINE__, cm_node, cm_node->listener, | 1441 | __LINE__, cm_node, cm_node->listener, |
@@ -1366,18 +1444,38 @@ static void handle_rcv_mpa(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1366 | } else { | 1444 | } else { |
1367 | passive_open_err(cm_node, skb, 1); | 1445 | passive_open_err(cm_node, skb, 1); |
1368 | } | 1446 | } |
1369 | } else { | 1447 | return; |
1370 | cleanup_retrans_entry(cm_node); | 1448 | } |
1371 | dev_kfree_skb_any(skb); | 1449 | |
1372 | if (type == NES_CM_EVENT_CONNECTED) | 1450 | switch (cm_node->state) { |
1451 | case NES_CM_STATE_ESTABLISHED: | ||
1452 | if (res_type == NES_MPA_REQUEST_REJECT) { | ||
1453 | /*BIG problem as we are receiving the MPA.. So should | ||
1454 | * not be REJECT.. This is Passive Open.. We can | ||
1455 | * only receive it Reject for Active Open...*/ | ||
1456 | WARN_ON(1); | ||
1457 | } | ||
1458 | cm_node->state = NES_CM_STATE_MPAREQ_RCVD; | ||
1459 | type = NES_CM_EVENT_MPA_REQ; | ||
1460 | atomic_set(&cm_node->passive_state, | ||
1461 | NES_PASSIVE_STATE_INDICATED); | ||
1462 | break; | ||
1463 | case NES_CM_STATE_MPAREQ_SENT: | ||
1464 | if (res_type == NES_MPA_REQUEST_REJECT) { | ||
1465 | type = NES_CM_EVENT_MPA_REJECT; | ||
1466 | cm_node->state = NES_CM_STATE_MPAREJ_RCVD; | ||
1467 | } else { | ||
1468 | type = NES_CM_EVENT_CONNECTED; | ||
1373 | cm_node->state = NES_CM_STATE_TSA; | 1469 | cm_node->state = NES_CM_STATE_TSA; |
1374 | else | 1470 | } |
1375 | atomic_set(&cm_node->passive_state, | ||
1376 | NES_PASSIVE_STATE_INDICATED); | ||
1377 | create_event(cm_node, type); | ||
1378 | 1471 | ||
1472 | break; | ||
1473 | default: | ||
1474 | WARN_ON(1); | ||
1475 | break; | ||
1379 | } | 1476 | } |
1380 | return ; | 1477 | dev_kfree_skb_any(skb); |
1478 | create_event(cm_node, type); | ||
1381 | } | 1479 | } |
1382 | 1480 | ||
1383 | static void indicate_pkt_err(struct nes_cm_node *cm_node, struct sk_buff *skb) | 1481 | static void indicate_pkt_err(struct nes_cm_node *cm_node, struct sk_buff *skb) |
@@ -1465,8 +1563,6 @@ static void handle_syn_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1465 | break; | 1563 | break; |
1466 | case NES_CM_STATE_LISTENING: | 1564 | case NES_CM_STATE_LISTENING: |
1467 | /* Passive OPEN */ | 1565 | /* Passive OPEN */ |
1468 | cm_node->accept_pend = 1; | ||
1469 | atomic_inc(&cm_node->listener->pend_accepts_cnt); | ||
1470 | if (atomic_read(&cm_node->listener->pend_accepts_cnt) > | 1566 | if (atomic_read(&cm_node->listener->pend_accepts_cnt) > |
1471 | cm_node->listener->backlog) { | 1567 | cm_node->listener->backlog) { |
1472 | nes_debug(NES_DBG_CM, "drop syn due to backlog " | 1568 | nes_debug(NES_DBG_CM, "drop syn due to backlog " |
@@ -1484,6 +1580,9 @@ static void handle_syn_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1484 | } | 1580 | } |
1485 | cm_node->tcp_cntxt.rcv_nxt = inc_sequence + 1; | 1581 | cm_node->tcp_cntxt.rcv_nxt = inc_sequence + 1; |
1486 | BUG_ON(cm_node->send_entry); | 1582 | BUG_ON(cm_node->send_entry); |
1583 | cm_node->accept_pend = 1; | ||
1584 | atomic_inc(&cm_node->listener->pend_accepts_cnt); | ||
1585 | |||
1487 | cm_node->state = NES_CM_STATE_SYN_RCVD; | 1586 | cm_node->state = NES_CM_STATE_SYN_RCVD; |
1488 | send_syn(cm_node, 1, skb); | 1587 | send_syn(cm_node, 1, skb); |
1489 | break; | 1588 | break; |
@@ -1518,6 +1617,7 @@ static void handle_synack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1518 | inc_sequence = ntohl(tcph->seq); | 1617 | inc_sequence = ntohl(tcph->seq); |
1519 | switch (cm_node->state) { | 1618 | switch (cm_node->state) { |
1520 | case NES_CM_STATE_SYN_SENT: | 1619 | case NES_CM_STATE_SYN_SENT: |
1620 | cleanup_retrans_entry(cm_node); | ||
1521 | /* active open */ | 1621 | /* active open */ |
1522 | if (check_syn(cm_node, tcph, skb)) | 1622 | if (check_syn(cm_node, tcph, skb)) |
1523 | return; | 1623 | return; |
@@ -1567,10 +1667,7 @@ static void handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1567 | u32 rem_seq; | 1667 | u32 rem_seq; |
1568 | int ret; | 1668 | int ret; |
1569 | int optionsize; | 1669 | int optionsize; |
1570 | u32 temp_seq = cm_node->tcp_cntxt.loc_seq_num; | ||
1571 | |||
1572 | optionsize = (tcph->doff << 2) - sizeof(struct tcphdr); | 1670 | optionsize = (tcph->doff << 2) - sizeof(struct tcphdr); |
1573 | cm_node->tcp_cntxt.loc_seq_num = ntohl(tcph->ack_seq); | ||
1574 | 1671 | ||
1575 | if (check_seq(cm_node, tcph, skb)) | 1672 | if (check_seq(cm_node, tcph, skb)) |
1576 | return; | 1673 | return; |
@@ -1580,7 +1677,7 @@ static void handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1580 | rem_seq = ntohl(tcph->seq); | 1677 | rem_seq = ntohl(tcph->seq); |
1581 | rem_seq_ack = ntohl(tcph->ack_seq); | 1678 | rem_seq_ack = ntohl(tcph->ack_seq); |
1582 | datasize = skb->len; | 1679 | datasize = skb->len; |
1583 | 1680 | cleanup_retrans_entry(cm_node); | |
1584 | switch (cm_node->state) { | 1681 | switch (cm_node->state) { |
1585 | case NES_CM_STATE_SYN_RCVD: | 1682 | case NES_CM_STATE_SYN_RCVD: |
1586 | /* Passive OPEN */ | 1683 | /* Passive OPEN */ |
@@ -1588,7 +1685,6 @@ static void handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1588 | if (ret) | 1685 | if (ret) |
1589 | break; | 1686 | break; |
1590 | cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq); | 1687 | cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq); |
1591 | cm_node->tcp_cntxt.loc_seq_num = temp_seq; | ||
1592 | if (cm_node->tcp_cntxt.rem_ack_num != | 1688 | if (cm_node->tcp_cntxt.rem_ack_num != |
1593 | cm_node->tcp_cntxt.loc_seq_num) { | 1689 | cm_node->tcp_cntxt.loc_seq_num) { |
1594 | nes_debug(NES_DBG_CM, "rem_ack_num != loc_seq_num\n"); | 1690 | nes_debug(NES_DBG_CM, "rem_ack_num != loc_seq_num\n"); |
@@ -1597,31 +1693,30 @@ static void handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1597 | return; | 1693 | return; |
1598 | } | 1694 | } |
1599 | cm_node->state = NES_CM_STATE_ESTABLISHED; | 1695 | cm_node->state = NES_CM_STATE_ESTABLISHED; |
1696 | cleanup_retrans_entry(cm_node); | ||
1600 | if (datasize) { | 1697 | if (datasize) { |
1601 | cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize; | 1698 | cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize; |
1602 | cm_node->state = NES_CM_STATE_MPAREQ_RCVD; | 1699 | handle_rcv_mpa(cm_node, skb); |
1603 | handle_rcv_mpa(cm_node, skb, NES_CM_EVENT_MPA_REQ); | 1700 | } else { /* rcvd ACK only */ |
1604 | } else { /* rcvd ACK only */ | ||
1605 | dev_kfree_skb_any(skb); | 1701 | dev_kfree_skb_any(skb); |
1606 | cleanup_retrans_entry(cm_node); | 1702 | cleanup_retrans_entry(cm_node); |
1607 | } | 1703 | } |
1608 | break; | 1704 | break; |
1609 | case NES_CM_STATE_ESTABLISHED: | 1705 | case NES_CM_STATE_ESTABLISHED: |
1610 | /* Passive OPEN */ | 1706 | /* Passive OPEN */ |
1611 | /* We expect mpa frame to be received only */ | 1707 | cleanup_retrans_entry(cm_node); |
1612 | if (datasize) { | 1708 | if (datasize) { |
1613 | cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize; | 1709 | cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize; |
1614 | cm_node->state = NES_CM_STATE_MPAREQ_RCVD; | 1710 | handle_rcv_mpa(cm_node, skb); |
1615 | handle_rcv_mpa(cm_node, skb, | ||
1616 | NES_CM_EVENT_MPA_REQ); | ||
1617 | } else | 1711 | } else |
1618 | drop_packet(skb); | 1712 | drop_packet(skb); |
1619 | break; | 1713 | break; |
1620 | case NES_CM_STATE_MPAREQ_SENT: | 1714 | case NES_CM_STATE_MPAREQ_SENT: |
1715 | cleanup_retrans_entry(cm_node); | ||
1621 | cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq); | 1716 | cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq); |
1622 | if (datasize) { | 1717 | if (datasize) { |
1623 | cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize; | 1718 | cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize; |
1624 | handle_rcv_mpa(cm_node, skb, NES_CM_EVENT_CONNECTED); | 1719 | handle_rcv_mpa(cm_node, skb); |
1625 | } else { /* Could be just an ack pkt.. */ | 1720 | } else { /* Could be just an ack pkt.. */ |
1626 | cleanup_retrans_entry(cm_node); | 1721 | cleanup_retrans_entry(cm_node); |
1627 | dev_kfree_skb_any(skb); | 1722 | dev_kfree_skb_any(skb); |
@@ -1632,13 +1727,24 @@ static void handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1632 | cleanup_retrans_entry(cm_node); | 1727 | cleanup_retrans_entry(cm_node); |
1633 | send_reset(cm_node, skb); | 1728 | send_reset(cm_node, skb); |
1634 | break; | 1729 | break; |
1730 | case NES_CM_STATE_LAST_ACK: | ||
1731 | cleanup_retrans_entry(cm_node); | ||
1732 | cm_node->state = NES_CM_STATE_CLOSED; | ||
1733 | cm_node->cm_id->rem_ref(cm_node->cm_id); | ||
1734 | case NES_CM_STATE_CLOSING: | ||
1735 | cleanup_retrans_entry(cm_node); | ||
1736 | rem_ref_cm_node(cm_node->cm_core, cm_node); | ||
1737 | drop_packet(skb); | ||
1738 | break; | ||
1635 | case NES_CM_STATE_FIN_WAIT1: | 1739 | case NES_CM_STATE_FIN_WAIT1: |
1740 | cleanup_retrans_entry(cm_node); | ||
1741 | drop_packet(skb); | ||
1742 | cm_node->state = NES_CM_STATE_FIN_WAIT2; | ||
1743 | break; | ||
1636 | case NES_CM_STATE_SYN_SENT: | 1744 | case NES_CM_STATE_SYN_SENT: |
1637 | case NES_CM_STATE_FIN_WAIT2: | 1745 | case NES_CM_STATE_FIN_WAIT2: |
1638 | case NES_CM_STATE_TSA: | 1746 | case NES_CM_STATE_TSA: |
1639 | case NES_CM_STATE_MPAREQ_RCVD: | 1747 | case NES_CM_STATE_MPAREQ_RCVD: |
1640 | case NES_CM_STATE_LAST_ACK: | ||
1641 | case NES_CM_STATE_CLOSING: | ||
1642 | case NES_CM_STATE_UNKNOWN: | 1748 | case NES_CM_STATE_UNKNOWN: |
1643 | default: | 1749 | default: |
1644 | drop_packet(skb); | 1750 | drop_packet(skb); |
@@ -1748,6 +1854,7 @@ static void process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1748 | { | 1854 | { |
1749 | enum nes_tcpip_pkt_type pkt_type = NES_PKT_TYPE_UNKNOWN; | 1855 | enum nes_tcpip_pkt_type pkt_type = NES_PKT_TYPE_UNKNOWN; |
1750 | struct tcphdr *tcph = tcp_hdr(skb); | 1856 | struct tcphdr *tcph = tcp_hdr(skb); |
1857 | u32 fin_set = 0; | ||
1751 | skb_pull(skb, ip_hdr(skb)->ihl << 2); | 1858 | skb_pull(skb, ip_hdr(skb)->ihl << 2); |
1752 | 1859 | ||
1753 | nes_debug(NES_DBG_CM, "process_packet: cm_node=%p state =%d syn=%d " | 1860 | nes_debug(NES_DBG_CM, "process_packet: cm_node=%p state =%d syn=%d " |
@@ -1760,10 +1867,10 @@ static void process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1760 | pkt_type = NES_PKT_TYPE_SYN; | 1867 | pkt_type = NES_PKT_TYPE_SYN; |
1761 | if (tcph->ack) | 1868 | if (tcph->ack) |
1762 | pkt_type = NES_PKT_TYPE_SYNACK; | 1869 | pkt_type = NES_PKT_TYPE_SYNACK; |
1763 | } else if (tcph->fin) | 1870 | } else if (tcph->ack) |
1764 | pkt_type = NES_PKT_TYPE_FIN; | ||
1765 | else if (tcph->ack) | ||
1766 | pkt_type = NES_PKT_TYPE_ACK; | 1871 | pkt_type = NES_PKT_TYPE_ACK; |
1872 | if (tcph->fin) | ||
1873 | fin_set = 1; | ||
1767 | 1874 | ||
1768 | switch (pkt_type) { | 1875 | switch (pkt_type) { |
1769 | case NES_PKT_TYPE_SYN: | 1876 | case NES_PKT_TYPE_SYN: |
@@ -1774,15 +1881,16 @@ static void process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1774 | break; | 1881 | break; |
1775 | case NES_PKT_TYPE_ACK: | 1882 | case NES_PKT_TYPE_ACK: |
1776 | handle_ack_pkt(cm_node, skb, tcph); | 1883 | handle_ack_pkt(cm_node, skb, tcph); |
1884 | if (fin_set) | ||
1885 | handle_fin_pkt(cm_node); | ||
1777 | break; | 1886 | break; |
1778 | case NES_PKT_TYPE_RST: | 1887 | case NES_PKT_TYPE_RST: |
1779 | handle_rst_pkt(cm_node, skb, tcph); | 1888 | handle_rst_pkt(cm_node, skb, tcph); |
1780 | break; | 1889 | break; |
1781 | case NES_PKT_TYPE_FIN: | ||
1782 | handle_fin_pkt(cm_node, skb, tcph); | ||
1783 | break; | ||
1784 | default: | 1890 | default: |
1785 | drop_packet(skb); | 1891 | drop_packet(skb); |
1892 | if (fin_set) | ||
1893 | handle_fin_pkt(cm_node); | ||
1786 | break; | 1894 | break; |
1787 | } | 1895 | } |
1788 | } | 1896 | } |
@@ -1925,7 +2033,7 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core, | |||
1925 | loopbackremotenode->tcp_cntxt.rcv_wscale; | 2033 | loopbackremotenode->tcp_cntxt.rcv_wscale; |
1926 | loopbackremotenode->tcp_cntxt.snd_wscale = | 2034 | loopbackremotenode->tcp_cntxt.snd_wscale = |
1927 | cm_node->tcp_cntxt.rcv_wscale; | 2035 | cm_node->tcp_cntxt.rcv_wscale; |
1928 | 2036 | loopbackremotenode->state = NES_CM_STATE_MPAREQ_RCVD; | |
1929 | create_event(loopbackremotenode, NES_CM_EVENT_MPA_REQ); | 2037 | create_event(loopbackremotenode, NES_CM_EVENT_MPA_REQ); |
1930 | } | 2038 | } |
1931 | return cm_node; | 2039 | return cm_node; |
@@ -1980,7 +2088,11 @@ static int mini_cm_reject(struct nes_cm_core *cm_core, | |||
1980 | struct ietf_mpa_frame *mpa_frame, struct nes_cm_node *cm_node) | 2088 | struct ietf_mpa_frame *mpa_frame, struct nes_cm_node *cm_node) |
1981 | { | 2089 | { |
1982 | int ret = 0; | 2090 | int ret = 0; |
2091 | int err = 0; | ||
1983 | int passive_state; | 2092 | int passive_state; |
2093 | struct nes_cm_event event; | ||
2094 | struct iw_cm_id *cm_id = cm_node->cm_id; | ||
2095 | struct nes_cm_node *loopback = cm_node->loopbackpartner; | ||
1984 | 2096 | ||
1985 | nes_debug(NES_DBG_CM, "%s cm_node=%p type=%d state=%d\n", | 2097 | nes_debug(NES_DBG_CM, "%s cm_node=%p type=%d state=%d\n", |
1986 | __func__, cm_node, cm_node->tcp_cntxt.client, cm_node->state); | 2098 | __func__, cm_node, cm_node->tcp_cntxt.client, cm_node->state); |
@@ -1989,12 +2101,38 @@ static int mini_cm_reject(struct nes_cm_core *cm_core, | |||
1989 | return ret; | 2101 | return ret; |
1990 | cleanup_retrans_entry(cm_node); | 2102 | cleanup_retrans_entry(cm_node); |
1991 | 2103 | ||
1992 | passive_state = atomic_add_return(1, &cm_node->passive_state); | 2104 | if (!loopback) { |
1993 | cm_node->state = NES_CM_STATE_CLOSED; | 2105 | passive_state = atomic_add_return(1, &cm_node->passive_state); |
1994 | if (passive_state == NES_SEND_RESET_EVENT) | 2106 | if (passive_state == NES_SEND_RESET_EVENT) { |
2107 | cm_node->state = NES_CM_STATE_CLOSED; | ||
2108 | rem_ref_cm_node(cm_core, cm_node); | ||
2109 | } else { | ||
2110 | ret = send_mpa_reject(cm_node); | ||
2111 | if (ret) { | ||
2112 | cm_node->state = NES_CM_STATE_CLOSED; | ||
2113 | err = send_reset(cm_node, NULL); | ||
2114 | if (err) | ||
2115 | WARN_ON(1); | ||
2116 | } else | ||
2117 | cm_id->add_ref(cm_id); | ||
2118 | } | ||
2119 | } else { | ||
2120 | cm_node->cm_id = NULL; | ||
2121 | event.cm_node = loopback; | ||
2122 | event.cm_info.rem_addr = loopback->rem_addr; | ||
2123 | event.cm_info.loc_addr = loopback->loc_addr; | ||
2124 | event.cm_info.rem_port = loopback->rem_port; | ||
2125 | event.cm_info.loc_port = loopback->loc_port; | ||
2126 | event.cm_info.cm_id = loopback->cm_id; | ||
2127 | cm_event_mpa_reject(&event); | ||
1995 | rem_ref_cm_node(cm_core, cm_node); | 2128 | rem_ref_cm_node(cm_core, cm_node); |
1996 | else | 2129 | loopback->state = NES_CM_STATE_CLOSING; |
1997 | ret = send_reset(cm_node, NULL); | 2130 | |
2131 | cm_id = loopback->cm_id; | ||
2132 | rem_ref_cm_node(cm_core, loopback); | ||
2133 | cm_id->rem_ref(cm_id); | ||
2134 | } | ||
2135 | |||
1998 | return ret; | 2136 | return ret; |
1999 | } | 2137 | } |
2000 | 2138 | ||
@@ -2031,6 +2169,7 @@ static int mini_cm_close(struct nes_cm_core *cm_core, struct nes_cm_node *cm_nod | |||
2031 | case NES_CM_STATE_CLOSING: | 2169 | case NES_CM_STATE_CLOSING: |
2032 | ret = -1; | 2170 | ret = -1; |
2033 | break; | 2171 | break; |
2172 | case NES_CM_STATE_MPAREJ_RCVD: | ||
2034 | case NES_CM_STATE_LISTENING: | 2173 | case NES_CM_STATE_LISTENING: |
2035 | case NES_CM_STATE_UNKNOWN: | 2174 | case NES_CM_STATE_UNKNOWN: |
2036 | case NES_CM_STATE_INITED: | 2175 | case NES_CM_STATE_INITED: |
@@ -2227,15 +2366,15 @@ static int mini_cm_set(struct nes_cm_core *cm_core, u32 type, u32 value) | |||
2227 | int ret = 0; | 2366 | int ret = 0; |
2228 | 2367 | ||
2229 | switch (type) { | 2368 | switch (type) { |
2230 | case NES_CM_SET_PKT_SIZE: | 2369 | case NES_CM_SET_PKT_SIZE: |
2231 | cm_core->mtu = value; | 2370 | cm_core->mtu = value; |
2232 | break; | 2371 | break; |
2233 | case NES_CM_SET_FREE_PKT_Q_SIZE: | 2372 | case NES_CM_SET_FREE_PKT_Q_SIZE: |
2234 | cm_core->free_tx_pkt_max = value; | 2373 | cm_core->free_tx_pkt_max = value; |
2235 | break; | 2374 | break; |
2236 | default: | 2375 | default: |
2237 | /* unknown set option */ | 2376 | /* unknown set option */ |
2238 | ret = -EINVAL; | 2377 | ret = -EINVAL; |
2239 | } | 2378 | } |
2240 | 2379 | ||
2241 | return ret; | 2380 | return ret; |
@@ -2654,9 +2793,7 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
2654 | NES_QPCONTEXT_ORDIRD_WRPDU); | 2793 | NES_QPCONTEXT_ORDIRD_WRPDU); |
2655 | } else { | 2794 | } else { |
2656 | nesqp->nesqp_context->ird_ord_sizes |= | 2795 | nesqp->nesqp_context->ird_ord_sizes |= |
2657 | cpu_to_le32((NES_QPCONTEXT_ORDIRD_LSMM_PRESENT | | 2796 | cpu_to_le32(NES_QPCONTEXT_ORDIRD_WRPDU); |
2658 | NES_QPCONTEXT_ORDIRD_WRPDU | | ||
2659 | NES_QPCONTEXT_ORDIRD_ALSMM)); | ||
2660 | } | 2797 | } |
2661 | nesqp->skip_lsmm = 1; | 2798 | nesqp->skip_lsmm = 1; |
2662 | 2799 | ||
@@ -2778,23 +2915,35 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
2778 | int nes_reject(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len) | 2915 | int nes_reject(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len) |
2779 | { | 2916 | { |
2780 | struct nes_cm_node *cm_node; | 2917 | struct nes_cm_node *cm_node; |
2918 | struct nes_cm_node *loopback; | ||
2919 | |||
2781 | struct nes_cm_core *cm_core; | 2920 | struct nes_cm_core *cm_core; |
2782 | 2921 | ||
2783 | atomic_inc(&cm_rejects); | 2922 | atomic_inc(&cm_rejects); |
2784 | cm_node = (struct nes_cm_node *) cm_id->provider_data; | 2923 | cm_node = (struct nes_cm_node *) cm_id->provider_data; |
2924 | loopback = cm_node->loopbackpartner; | ||
2785 | cm_core = cm_node->cm_core; | 2925 | cm_core = cm_node->cm_core; |
2926 | cm_node->cm_id = cm_id; | ||
2786 | cm_node->mpa_frame_size = sizeof(struct ietf_mpa_frame) + pdata_len; | 2927 | cm_node->mpa_frame_size = sizeof(struct ietf_mpa_frame) + pdata_len; |
2787 | 2928 | ||
2929 | if (cm_node->mpa_frame_size > MAX_CM_BUFFER) | ||
2930 | return -EINVAL; | ||
2931 | |||
2788 | strcpy(&cm_node->mpa_frame.key[0], IEFT_MPA_KEY_REP); | 2932 | strcpy(&cm_node->mpa_frame.key[0], IEFT_MPA_KEY_REP); |
2789 | memcpy(&cm_node->mpa_frame.priv_data, pdata, pdata_len); | 2933 | if (loopback) { |
2934 | memcpy(&loopback->mpa_frame.priv_data, pdata, pdata_len); | ||
2935 | loopback->mpa_frame.priv_data_len = pdata_len; | ||
2936 | loopback->mpa_frame_size = sizeof(struct ietf_mpa_frame) + | ||
2937 | pdata_len; | ||
2938 | } else { | ||
2939 | memcpy(&cm_node->mpa_frame.priv_data, pdata, pdata_len); | ||
2940 | cm_node->mpa_frame.priv_data_len = cpu_to_be16(pdata_len); | ||
2941 | } | ||
2790 | 2942 | ||
2791 | cm_node->mpa_frame.priv_data_len = cpu_to_be16(pdata_len); | ||
2792 | cm_node->mpa_frame.rev = mpa_version; | 2943 | cm_node->mpa_frame.rev = mpa_version; |
2793 | cm_node->mpa_frame.flags = IETF_MPA_FLAGS_CRC | IETF_MPA_FLAGS_REJECT; | 2944 | cm_node->mpa_frame.flags = IETF_MPA_FLAGS_CRC | IETF_MPA_FLAGS_REJECT; |
2794 | 2945 | ||
2795 | cm_core->api->reject(cm_core, &cm_node->mpa_frame, cm_node); | 2946 | return cm_core->api->reject(cm_core, &cm_node->mpa_frame, cm_node); |
2796 | |||
2797 | return 0; | ||
2798 | } | 2947 | } |
2799 | 2948 | ||
2800 | 2949 | ||
@@ -3303,13 +3452,56 @@ static void cm_event_mpa_req(struct nes_cm_event *event) | |||
3303 | cm_event.remote_addr.sin_family = AF_INET; | 3452 | cm_event.remote_addr.sin_family = AF_INET; |
3304 | cm_event.remote_addr.sin_port = htons(event->cm_info.rem_port); | 3453 | cm_event.remote_addr.sin_port = htons(event->cm_info.rem_port); |
3305 | cm_event.remote_addr.sin_addr.s_addr = htonl(event->cm_info.rem_addr); | 3454 | cm_event.remote_addr.sin_addr.s_addr = htonl(event->cm_info.rem_addr); |
3455 | cm_event.private_data = cm_node->mpa_frame_buf; | ||
3456 | cm_event.private_data_len = (u8) cm_node->mpa_frame_size; | ||
3457 | |||
3458 | ret = cm_id->event_handler(cm_id, &cm_event); | ||
3459 | if (ret) | ||
3460 | printk(KERN_ERR "%s[%u] OFA CM event_handler returned, ret=%d\n", | ||
3461 | __func__, __LINE__, ret); | ||
3462 | return; | ||
3463 | } | ||
3464 | |||
3465 | |||
3466 | static void cm_event_mpa_reject(struct nes_cm_event *event) | ||
3467 | { | ||
3468 | struct iw_cm_id *cm_id; | ||
3469 | struct iw_cm_event cm_event; | ||
3470 | struct nes_cm_node *cm_node; | ||
3471 | int ret; | ||
3472 | |||
3473 | cm_node = event->cm_node; | ||
3474 | if (!cm_node) | ||
3475 | return; | ||
3476 | cm_id = cm_node->cm_id; | ||
3477 | |||
3478 | atomic_inc(&cm_connect_reqs); | ||
3479 | nes_debug(NES_DBG_CM, "cm_node = %p - cm_id = %p, jiffies = %lu\n", | ||
3480 | cm_node, cm_id, jiffies); | ||
3481 | |||
3482 | cm_event.event = IW_CM_EVENT_CONNECT_REPLY; | ||
3483 | cm_event.status = -ECONNREFUSED; | ||
3484 | cm_event.provider_data = cm_id->provider_data; | ||
3485 | |||
3486 | cm_event.local_addr.sin_family = AF_INET; | ||
3487 | cm_event.local_addr.sin_port = htons(event->cm_info.loc_port); | ||
3488 | cm_event.local_addr.sin_addr.s_addr = htonl(event->cm_info.loc_addr); | ||
3489 | |||
3490 | cm_event.remote_addr.sin_family = AF_INET; | ||
3491 | cm_event.remote_addr.sin_port = htons(event->cm_info.rem_port); | ||
3492 | cm_event.remote_addr.sin_addr.s_addr = htonl(event->cm_info.rem_addr); | ||
3306 | 3493 | ||
3307 | cm_event.private_data = cm_node->mpa_frame_buf; | 3494 | cm_event.private_data = cm_node->mpa_frame_buf; |
3308 | cm_event.private_data_len = (u8) cm_node->mpa_frame_size; | 3495 | cm_event.private_data_len = (u8) cm_node->mpa_frame_size; |
3496 | |||
3497 | nes_debug(NES_DBG_CM, "call CM_EVENT_MPA_REJECTED, local_addr=%08x, " | ||
3498 | "remove_addr=%08x\n", | ||
3499 | cm_event.local_addr.sin_addr.s_addr, | ||
3500 | cm_event.remote_addr.sin_addr.s_addr); | ||
3309 | 3501 | ||
3310 | ret = cm_id->event_handler(cm_id, &cm_event); | 3502 | ret = cm_id->event_handler(cm_id, &cm_event); |
3311 | if (ret) | 3503 | if (ret) |
3312 | printk("%s[%u] OFA CM event_handler returned, ret=%d\n", | 3504 | printk(KERN_ERR "%s[%u] OFA CM event_handler returned, ret=%d\n", |
3313 | __func__, __LINE__, ret); | 3505 | __func__, __LINE__, ret); |
3314 | 3506 | ||
3315 | return; | 3507 | return; |
@@ -3374,6 +3566,14 @@ static void nes_cm_event_handler(struct work_struct *work) | |||
3374 | cm_event_connected(event); | 3566 | cm_event_connected(event); |
3375 | nes_debug(NES_DBG_CM, "CM Event: CONNECTED\n"); | 3567 | nes_debug(NES_DBG_CM, "CM Event: CONNECTED\n"); |
3376 | break; | 3568 | break; |
3569 | case NES_CM_EVENT_MPA_REJECT: | ||
3570 | if ((!event->cm_node->cm_id) || | ||
3571 | (event->cm_node->state == NES_CM_STATE_TSA)) | ||
3572 | break; | ||
3573 | cm_event_mpa_reject(event); | ||
3574 | nes_debug(NES_DBG_CM, "CM Event: REJECT\n"); | ||
3575 | break; | ||
3576 | |||
3377 | case NES_CM_EVENT_ABORTED: | 3577 | case NES_CM_EVENT_ABORTED: |
3378 | if ((!event->cm_node->cm_id) || | 3578 | if ((!event->cm_node->cm_id) || |
3379 | (event->cm_node->state == NES_CM_STATE_TSA)) | 3579 | (event->cm_node->state == NES_CM_STATE_TSA)) |