diff options
author | Faisal Latif <faisal.latif@intel.com> | 2009-03-06 18:15:01 -0500 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2009-03-06 18:15:01 -0500 |
commit | 9d5ab13325d0bb855cf856946c140a68ceb20e32 (patch) | |
tree | c226cba67009db77052aceb1c7bf885da63fa4b8 /drivers/infiniband | |
parent | 0145f341a951b998d6d0fa38992a42d2a90b5bab (diff) |
RDMA/nes: Handle MPA Reject message properly
While doing testing, there are failures as MPA Reject call is not
handled. To handle MPA Reject call, following changes are done:
*Handle inbound/outbound MPA Reject response message.
When nes_reject() is called for pending MPA request reply,
send the MPA Reject message to its peer (active
side)cm_node. The peer cm_node (active side) will indicate
Reject message event for the pending Connect Request.
*Handle MPA Reject response message for loopback connections and listener.
When MPA Request is rejected, check if it is a loopback
connection and if it is then it will send Reject message event
to its peer loopback node. Also when destroying listener,
check if the cm_nodes for that listener are loopback or not.
*Add gracefull connection close with the MPA Reject response message.
Send gracefull close (FIN, FIN ACK..) to terminate the cm_nodes.
*Some code re-org while making the above changes.
Removed recv_list and recv_list_lock from the cm_node
structure as there can be only one receive close entry on the
timer. Also implemented handle_recv_entry() as receive close
entry is processed from both nes_rem_ref_cm_node() as well as
nes_cm_timer_tick().
Signed-off-by: Faisal Latif <faisal.latif@intel.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/hw/nes/nes_cm.c | 580 | ||||
-rw-r--r-- | drivers/infiniband/hw/nes/nes_cm.h | 10 |
2 files changed, 399 insertions, 191 deletions
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index bd918df3d22c..5327f2bec6bf 100644 --- a/drivers/infiniband/hw/nes/nes_cm.c +++ b/drivers/infiniband/hw/nes/nes_cm.c | |||
@@ -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); |
@@ -871,7 +917,8 @@ static int add_hte_node(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node | |||
871 | 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, |
872 | struct nes_cm_listener *listener, int free_hanging_nodes) | 918 | struct nes_cm_listener *listener, int free_hanging_nodes) |
873 | { | 919 | { |
874 | int ret = 1; | 920 | int ret = -EINVAL; |
921 | int err = 0; | ||
875 | unsigned long flags; | 922 | unsigned long flags; |
876 | struct list_head *list_pos = NULL; | 923 | struct list_head *list_pos = NULL; |
877 | struct list_head *list_temp = NULL; | 924 | struct list_head *list_temp = NULL; |
@@ -900,10 +947,60 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core, | |||
900 | 947 | ||
901 | list_for_each_safe(list_pos, list_temp, &reset_list) { | 948 | list_for_each_safe(list_pos, list_temp, &reset_list) { |
902 | cm_node = container_of(list_pos, struct nes_cm_node, | 949 | cm_node = container_of(list_pos, struct nes_cm_node, |
903 | reset_entry); | 950 | reset_entry); |
904 | cleanup_retrans_entry(cm_node); | 951 | { |
905 | send_reset(cm_node, NULL); | 952 | struct nes_cm_node *loopback = cm_node->loopbackpartner; |
906 | 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 | } | ||
907 | } | 1004 | } |
908 | 1005 | ||
909 | spin_lock_irqsave(&cm_core->listen_list_lock, flags); | 1006 | spin_lock_irqsave(&cm_core->listen_list_lock, flags); |
@@ -964,6 +1061,7 @@ static inline int mini_cm_accelerated(struct nes_cm_core *cm_core, | |||
964 | if (cm_node->accept_pend) { | 1061 | if (cm_node->accept_pend) { |
965 | BUG_ON(!cm_node->listener); | 1062 | BUG_ON(!cm_node->listener); |
966 | atomic_dec(&cm_node->listener->pend_accepts_cnt); | 1063 | atomic_dec(&cm_node->listener->pend_accepts_cnt); |
1064 | cm_node->accept_pend = 0; | ||
967 | BUG_ON(atomic_read(&cm_node->listener->pend_accepts_cnt) < 0); | 1065 | BUG_ON(atomic_read(&cm_node->listener->pend_accepts_cnt) < 0); |
968 | } | 1066 | } |
969 | 1067 | ||
@@ -990,7 +1088,7 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip) | |||
990 | memset(&fl, 0, sizeof fl); | 1088 | memset(&fl, 0, sizeof fl); |
991 | fl.nl_u.ip4_u.daddr = htonl(dst_ip); | 1089 | fl.nl_u.ip4_u.daddr = htonl(dst_ip); |
992 | if (ip_route_output_key(&init_net, &rt, &fl)) { | 1090 | if (ip_route_output_key(&init_net, &rt, &fl)) { |
993 | 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", |
994 | __func__, dst_ip); | 1092 | __func__, dst_ip); |
995 | return rc; | 1093 | return rc; |
996 | } | 1094 | } |
@@ -1053,8 +1151,6 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core, | |||
1053 | cm_node->cm_id); | 1151 | cm_node->cm_id); |
1054 | 1152 | ||
1055 | spin_lock_init(&cm_node->retrans_list_lock); | 1153 | spin_lock_init(&cm_node->retrans_list_lock); |
1056 | INIT_LIST_HEAD(&cm_node->recv_list); | ||
1057 | spin_lock_init(&cm_node->recv_list_lock); | ||
1058 | 1154 | ||
1059 | cm_node->loopbackpartner = NULL; | 1155 | cm_node->loopbackpartner = NULL; |
1060 | atomic_set(&cm_node->ref_count, 1); | 1156 | atomic_set(&cm_node->ref_count, 1); |
@@ -1122,10 +1218,7 @@ static int add_ref_cm_node(struct nes_cm_node *cm_node) | |||
1122 | 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, |
1123 | struct nes_cm_node *cm_node) | 1219 | struct nes_cm_node *cm_node) |
1124 | { | 1220 | { |
1125 | unsigned long flags, qplockflags; | 1221 | unsigned long flags; |
1126 | struct nes_timer_entry *recv_entry; | ||
1127 | struct iw_cm_id *cm_id; | ||
1128 | struct list_head *list_core, *list_node_temp; | ||
1129 | struct nes_qp *nesqp; | 1222 | struct nes_qp *nesqp; |
1130 | 1223 | ||
1131 | if (!cm_node) | 1224 | if (!cm_node) |
@@ -1146,38 +1239,9 @@ static int rem_ref_cm_node(struct nes_cm_core *cm_core, | |||
1146 | atomic_dec(&cm_node->listener->pend_accepts_cnt); | 1239 | atomic_dec(&cm_node->listener->pend_accepts_cnt); |
1147 | BUG_ON(atomic_read(&cm_node->listener->pend_accepts_cnt) < 0); | 1240 | BUG_ON(atomic_read(&cm_node->listener->pend_accepts_cnt) < 0); |
1148 | } | 1241 | } |
1149 | BUG_ON(cm_node->send_entry); | 1242 | WARN_ON(cm_node->send_entry); |
1150 | spin_lock_irqsave(&cm_node->recv_list_lock, flags); | 1243 | if (cm_node->recv_entry) |
1151 | list_for_each_safe(list_core, list_node_temp, &cm_node->recv_list) { | 1244 | handle_recv_entry(cm_node, 0); |
1152 | recv_entry = container_of(list_core, struct nes_timer_entry, | ||
1153 | list); | ||
1154 | list_del(&recv_entry->list); | ||
1155 | cm_id = cm_node->cm_id; | ||
1156 | spin_unlock_irqrestore(&cm_node->recv_list_lock, flags); | ||
1157 | nesqp = (struct nes_qp *)recv_entry->skb; | ||
1158 | spin_lock_irqsave(&nesqp->lock, qplockflags); | ||
1159 | if (nesqp->cm_id) { | ||
1160 | nes_debug(NES_DBG_CM, "QP%u: cm_id = %p: HIT A " | ||
1161 | "NES_TIMER_TYPE_CLOSE with something to do!\n", | ||
1162 | nesqp->hwqp.qp_id, cm_id); | ||
1163 | nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED; | ||
1164 | nesqp->last_aeq = NES_AEQE_AEID_RESET_SENT; | ||
1165 | nesqp->ibqp_state = IB_QPS_ERR; | ||
1166 | spin_unlock_irqrestore(&nesqp->lock, qplockflags); | ||
1167 | nes_cm_disconn(nesqp); | ||
1168 | } else { | ||
1169 | spin_unlock_irqrestore(&nesqp->lock, qplockflags); | ||
1170 | nes_debug(NES_DBG_CM, "QP%u: cm_id = %p: HIT A " | ||
1171 | "NES_TIMER_TYPE_CLOSE with nothing to do!\n", | ||
1172 | nesqp->hwqp.qp_id, cm_id); | ||
1173 | } | ||
1174 | cm_id->rem_ref(cm_id); | ||
1175 | |||
1176 | kfree(recv_entry); | ||
1177 | spin_lock_irqsave(&cm_node->recv_list_lock, flags); | ||
1178 | } | ||
1179 | spin_unlock_irqrestore(&cm_node->recv_list_lock, flags); | ||
1180 | |||
1181 | if (cm_node->listener) { | 1245 | if (cm_node->listener) { |
1182 | mini_cm_dec_refcnt_listen(cm_core, cm_node->listener, 0); | 1246 | mini_cm_dec_refcnt_listen(cm_core, cm_node->listener, 0); |
1183 | } else { | 1247 | } else { |
@@ -1262,8 +1326,7 @@ static void drop_packet(struct sk_buff *skb) | |||
1262 | dev_kfree_skb_any(skb); | 1326 | dev_kfree_skb_any(skb); |
1263 | } | 1327 | } |
1264 | 1328 | ||
1265 | 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) |
1266 | struct tcphdr *tcph) | ||
1267 | { | 1330 | { |
1268 | 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. " |
1269 | "refcnt=%d\n", cm_node, cm_node->state, | 1332 | "refcnt=%d\n", cm_node, cm_node->state, |
@@ -1275,23 +1338,30 @@ static void handle_fin_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1275 | case NES_CM_STATE_SYN_SENT: | 1338 | case NES_CM_STATE_SYN_SENT: |
1276 | case NES_CM_STATE_ESTABLISHED: | 1339 | case NES_CM_STATE_ESTABLISHED: |
1277 | case NES_CM_STATE_MPAREQ_SENT: | 1340 | case NES_CM_STATE_MPAREQ_SENT: |
1341 | case NES_CM_STATE_MPAREJ_RCVD: | ||
1278 | cm_node->state = NES_CM_STATE_LAST_ACK; | 1342 | cm_node->state = NES_CM_STATE_LAST_ACK; |
1279 | send_fin(cm_node, skb); | 1343 | send_fin(cm_node, NULL); |
1280 | break; | 1344 | break; |
1281 | case NES_CM_STATE_FIN_WAIT1: | 1345 | case NES_CM_STATE_FIN_WAIT1: |
1282 | cm_node->state = NES_CM_STATE_CLOSING; | 1346 | cm_node->state = NES_CM_STATE_CLOSING; |
1283 | 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.. */ | ||
1284 | break; | 1351 | break; |
1285 | case NES_CM_STATE_FIN_WAIT2: | 1352 | case NES_CM_STATE_FIN_WAIT2: |
1286 | cm_node->state = NES_CM_STATE_TIME_WAIT; | 1353 | cm_node->state = NES_CM_STATE_TIME_WAIT; |
1287 | 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: | ||
1288 | 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); | ||
1289 | break; | 1360 | break; |
1290 | case NES_CM_STATE_TSA: | 1361 | case NES_CM_STATE_TSA: |
1291 | default: | 1362 | default: |
1292 | 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", |
1293 | cm_node, cm_node->state); | 1364 | cm_node, cm_node->state); |
1294 | drop_packet(skb); | ||
1295 | break; | 1365 | break; |
1296 | } | 1366 | } |
1297 | } | 1367 | } |
@@ -1337,23 +1407,35 @@ static void handle_rst_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1337 | cleanup_retrans_entry(cm_node); | 1407 | cleanup_retrans_entry(cm_node); |
1338 | drop_packet(skb); | 1408 | drop_packet(skb); |
1339 | 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__); | ||
1340 | default: | 1419 | default: |
1341 | drop_packet(skb); | 1420 | drop_packet(skb); |
1342 | break; | 1421 | break; |
1343 | } | 1422 | } |
1344 | } | 1423 | } |
1345 | 1424 | ||
1346 | static void handle_rcv_mpa(struct nes_cm_node *cm_node, struct sk_buff *skb, | 1425 | |
1347 | enum nes_cm_event_type type) | 1426 | static void handle_rcv_mpa(struct nes_cm_node *cm_node, struct sk_buff *skb) |
1348 | { | 1427 | { |
1349 | 1428 | ||
1350 | int ret; | 1429 | int ret = 0; |
1351 | int datasize = skb->len; | 1430 | int datasize = skb->len; |
1352 | u8 *dataloc = skb->data; | 1431 | u8 *dataloc = skb->data; |
1353 | ret = parse_mpa(cm_node, dataloc, datasize); | 1432 | |
1354 | 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) { | ||
1355 | nes_debug(NES_DBG_CM, "didn't like MPA Request\n"); | 1437 | nes_debug(NES_DBG_CM, "didn't like MPA Request\n"); |
1356 | if (type == NES_CM_EVENT_CONNECTED) { | 1438 | if (cm_node->state == NES_CM_STATE_MPAREQ_SENT) { |
1357 | nes_debug(NES_DBG_CM, "%s[%u] create abort for " | 1439 | nes_debug(NES_DBG_CM, "%s[%u] create abort for " |
1358 | "cm_node=%p listener=%p state=%d\n", __func__, | 1440 | "cm_node=%p listener=%p state=%d\n", __func__, |
1359 | __LINE__, cm_node, cm_node->listener, | 1441 | __LINE__, cm_node, cm_node->listener, |
@@ -1362,18 +1444,38 @@ static void handle_rcv_mpa(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1362 | } else { | 1444 | } else { |
1363 | passive_open_err(cm_node, skb, 1); | 1445 | passive_open_err(cm_node, skb, 1); |
1364 | } | 1446 | } |
1365 | } else { | 1447 | return; |
1366 | cleanup_retrans_entry(cm_node); | 1448 | } |
1367 | dev_kfree_skb_any(skb); | 1449 | |
1368 | 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; | ||
1369 | cm_node->state = NES_CM_STATE_TSA; | 1469 | cm_node->state = NES_CM_STATE_TSA; |
1370 | else | 1470 | } |
1371 | atomic_set(&cm_node->passive_state, | ||
1372 | NES_PASSIVE_STATE_INDICATED); | ||
1373 | create_event(cm_node, type); | ||
1374 | 1471 | ||
1472 | break; | ||
1473 | default: | ||
1474 | WARN_ON(1); | ||
1475 | break; | ||
1375 | } | 1476 | } |
1376 | return ; | 1477 | dev_kfree_skb_any(skb); |
1478 | create_event(cm_node, type); | ||
1377 | } | 1479 | } |
1378 | 1480 | ||
1379 | 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) |
@@ -1461,8 +1563,6 @@ static void handle_syn_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1461 | break; | 1563 | break; |
1462 | case NES_CM_STATE_LISTENING: | 1564 | case NES_CM_STATE_LISTENING: |
1463 | /* Passive OPEN */ | 1565 | /* Passive OPEN */ |
1464 | cm_node->accept_pend = 1; | ||
1465 | atomic_inc(&cm_node->listener->pend_accepts_cnt); | ||
1466 | if (atomic_read(&cm_node->listener->pend_accepts_cnt) > | 1566 | if (atomic_read(&cm_node->listener->pend_accepts_cnt) > |
1467 | cm_node->listener->backlog) { | 1567 | cm_node->listener->backlog) { |
1468 | nes_debug(NES_DBG_CM, "drop syn due to backlog " | 1568 | nes_debug(NES_DBG_CM, "drop syn due to backlog " |
@@ -1480,6 +1580,9 @@ static void handle_syn_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1480 | } | 1580 | } |
1481 | cm_node->tcp_cntxt.rcv_nxt = inc_sequence + 1; | 1581 | cm_node->tcp_cntxt.rcv_nxt = inc_sequence + 1; |
1482 | 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 | |||
1483 | cm_node->state = NES_CM_STATE_SYN_RCVD; | 1586 | cm_node->state = NES_CM_STATE_SYN_RCVD; |
1484 | send_syn(cm_node, 1, skb); | 1587 | send_syn(cm_node, 1, skb); |
1485 | break; | 1588 | break; |
@@ -1514,6 +1617,7 @@ static void handle_synack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1514 | inc_sequence = ntohl(tcph->seq); | 1617 | inc_sequence = ntohl(tcph->seq); |
1515 | switch (cm_node->state) { | 1618 | switch (cm_node->state) { |
1516 | case NES_CM_STATE_SYN_SENT: | 1619 | case NES_CM_STATE_SYN_SENT: |
1620 | cleanup_retrans_entry(cm_node); | ||
1517 | /* active open */ | 1621 | /* active open */ |
1518 | if (check_syn(cm_node, tcph, skb)) | 1622 | if (check_syn(cm_node, tcph, skb)) |
1519 | return; | 1623 | return; |
@@ -1563,10 +1667,7 @@ static void handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1563 | u32 rem_seq; | 1667 | u32 rem_seq; |
1564 | int ret; | 1668 | int ret; |
1565 | int optionsize; | 1669 | int optionsize; |
1566 | u32 temp_seq = cm_node->tcp_cntxt.loc_seq_num; | ||
1567 | |||
1568 | optionsize = (tcph->doff << 2) - sizeof(struct tcphdr); | 1670 | optionsize = (tcph->doff << 2) - sizeof(struct tcphdr); |
1569 | cm_node->tcp_cntxt.loc_seq_num = ntohl(tcph->ack_seq); | ||
1570 | 1671 | ||
1571 | if (check_seq(cm_node, tcph, skb)) | 1672 | if (check_seq(cm_node, tcph, skb)) |
1572 | return; | 1673 | return; |
@@ -1576,7 +1677,7 @@ static void handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1576 | rem_seq = ntohl(tcph->seq); | 1677 | rem_seq = ntohl(tcph->seq); |
1577 | rem_seq_ack = ntohl(tcph->ack_seq); | 1678 | rem_seq_ack = ntohl(tcph->ack_seq); |
1578 | datasize = skb->len; | 1679 | datasize = skb->len; |
1579 | 1680 | cleanup_retrans_entry(cm_node); | |
1580 | switch (cm_node->state) { | 1681 | switch (cm_node->state) { |
1581 | case NES_CM_STATE_SYN_RCVD: | 1682 | case NES_CM_STATE_SYN_RCVD: |
1582 | /* Passive OPEN */ | 1683 | /* Passive OPEN */ |
@@ -1584,7 +1685,6 @@ static void handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1584 | if (ret) | 1685 | if (ret) |
1585 | break; | 1686 | break; |
1586 | cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq); | 1687 | cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq); |
1587 | cm_node->tcp_cntxt.loc_seq_num = temp_seq; | ||
1588 | if (cm_node->tcp_cntxt.rem_ack_num != | 1688 | if (cm_node->tcp_cntxt.rem_ack_num != |
1589 | cm_node->tcp_cntxt.loc_seq_num) { | 1689 | cm_node->tcp_cntxt.loc_seq_num) { |
1590 | 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"); |
@@ -1593,31 +1693,30 @@ static void handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1593 | return; | 1693 | return; |
1594 | } | 1694 | } |
1595 | cm_node->state = NES_CM_STATE_ESTABLISHED; | 1695 | cm_node->state = NES_CM_STATE_ESTABLISHED; |
1696 | cleanup_retrans_entry(cm_node); | ||
1596 | if (datasize) { | 1697 | if (datasize) { |
1597 | cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize; | 1698 | cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize; |
1598 | cm_node->state = NES_CM_STATE_MPAREQ_RCVD; | 1699 | handle_rcv_mpa(cm_node, skb); |
1599 | handle_rcv_mpa(cm_node, skb, NES_CM_EVENT_MPA_REQ); | 1700 | } else { /* rcvd ACK only */ |
1600 | } else { /* rcvd ACK only */ | ||
1601 | dev_kfree_skb_any(skb); | 1701 | dev_kfree_skb_any(skb); |
1602 | cleanup_retrans_entry(cm_node); | 1702 | cleanup_retrans_entry(cm_node); |
1603 | } | 1703 | } |
1604 | break; | 1704 | break; |
1605 | case NES_CM_STATE_ESTABLISHED: | 1705 | case NES_CM_STATE_ESTABLISHED: |
1606 | /* Passive OPEN */ | 1706 | /* Passive OPEN */ |
1607 | /* We expect mpa frame to be received only */ | 1707 | cleanup_retrans_entry(cm_node); |
1608 | if (datasize) { | 1708 | if (datasize) { |
1609 | cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize; | 1709 | cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize; |
1610 | cm_node->state = NES_CM_STATE_MPAREQ_RCVD; | 1710 | handle_rcv_mpa(cm_node, skb); |
1611 | handle_rcv_mpa(cm_node, skb, | ||
1612 | NES_CM_EVENT_MPA_REQ); | ||
1613 | } else | 1711 | } else |
1614 | drop_packet(skb); | 1712 | drop_packet(skb); |
1615 | break; | 1713 | break; |
1616 | case NES_CM_STATE_MPAREQ_SENT: | 1714 | case NES_CM_STATE_MPAREQ_SENT: |
1715 | cleanup_retrans_entry(cm_node); | ||
1617 | cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq); | 1716 | cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq); |
1618 | if (datasize) { | 1717 | if (datasize) { |
1619 | cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize; | 1718 | cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize; |
1620 | handle_rcv_mpa(cm_node, skb, NES_CM_EVENT_CONNECTED); | 1719 | handle_rcv_mpa(cm_node, skb); |
1621 | } else { /* Could be just an ack pkt.. */ | 1720 | } else { /* Could be just an ack pkt.. */ |
1622 | cleanup_retrans_entry(cm_node); | 1721 | cleanup_retrans_entry(cm_node); |
1623 | dev_kfree_skb_any(skb); | 1722 | dev_kfree_skb_any(skb); |
@@ -1628,13 +1727,24 @@ static void handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1628 | cleanup_retrans_entry(cm_node); | 1727 | cleanup_retrans_entry(cm_node); |
1629 | send_reset(cm_node, skb); | 1728 | send_reset(cm_node, skb); |
1630 | 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; | ||
1631 | 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; | ||
1632 | case NES_CM_STATE_SYN_SENT: | 1744 | case NES_CM_STATE_SYN_SENT: |
1633 | case NES_CM_STATE_FIN_WAIT2: | 1745 | case NES_CM_STATE_FIN_WAIT2: |
1634 | case NES_CM_STATE_TSA: | 1746 | case NES_CM_STATE_TSA: |
1635 | case NES_CM_STATE_MPAREQ_RCVD: | 1747 | case NES_CM_STATE_MPAREQ_RCVD: |
1636 | case NES_CM_STATE_LAST_ACK: | ||
1637 | case NES_CM_STATE_CLOSING: | ||
1638 | case NES_CM_STATE_UNKNOWN: | 1748 | case NES_CM_STATE_UNKNOWN: |
1639 | default: | 1749 | default: |
1640 | drop_packet(skb); | 1750 | drop_packet(skb); |
@@ -1744,6 +1854,7 @@ static void process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1744 | { | 1854 | { |
1745 | enum nes_tcpip_pkt_type pkt_type = NES_PKT_TYPE_UNKNOWN; | 1855 | enum nes_tcpip_pkt_type pkt_type = NES_PKT_TYPE_UNKNOWN; |
1746 | struct tcphdr *tcph = tcp_hdr(skb); | 1856 | struct tcphdr *tcph = tcp_hdr(skb); |
1857 | u32 fin_set = 0; | ||
1747 | skb_pull(skb, ip_hdr(skb)->ihl << 2); | 1858 | skb_pull(skb, ip_hdr(skb)->ihl << 2); |
1748 | 1859 | ||
1749 | 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 " |
@@ -1756,10 +1867,10 @@ static void process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1756 | pkt_type = NES_PKT_TYPE_SYN; | 1867 | pkt_type = NES_PKT_TYPE_SYN; |
1757 | if (tcph->ack) | 1868 | if (tcph->ack) |
1758 | pkt_type = NES_PKT_TYPE_SYNACK; | 1869 | pkt_type = NES_PKT_TYPE_SYNACK; |
1759 | } else if (tcph->fin) | 1870 | } else if (tcph->ack) |
1760 | pkt_type = NES_PKT_TYPE_FIN; | ||
1761 | else if (tcph->ack) | ||
1762 | pkt_type = NES_PKT_TYPE_ACK; | 1871 | pkt_type = NES_PKT_TYPE_ACK; |
1872 | if (tcph->fin) | ||
1873 | fin_set = 1; | ||
1763 | 1874 | ||
1764 | switch (pkt_type) { | 1875 | switch (pkt_type) { |
1765 | case NES_PKT_TYPE_SYN: | 1876 | case NES_PKT_TYPE_SYN: |
@@ -1770,15 +1881,16 @@ static void process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1770 | break; | 1881 | break; |
1771 | case NES_PKT_TYPE_ACK: | 1882 | case NES_PKT_TYPE_ACK: |
1772 | 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); | ||
1773 | break; | 1886 | break; |
1774 | case NES_PKT_TYPE_RST: | 1887 | case NES_PKT_TYPE_RST: |
1775 | handle_rst_pkt(cm_node, skb, tcph); | 1888 | handle_rst_pkt(cm_node, skb, tcph); |
1776 | break; | 1889 | break; |
1777 | case NES_PKT_TYPE_FIN: | ||
1778 | handle_fin_pkt(cm_node, skb, tcph); | ||
1779 | break; | ||
1780 | default: | 1890 | default: |
1781 | drop_packet(skb); | 1891 | drop_packet(skb); |
1892 | if (fin_set) | ||
1893 | handle_fin_pkt(cm_node); | ||
1782 | break; | 1894 | break; |
1783 | } | 1895 | } |
1784 | } | 1896 | } |
@@ -1921,7 +2033,7 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core, | |||
1921 | loopbackremotenode->tcp_cntxt.rcv_wscale; | 2033 | loopbackremotenode->tcp_cntxt.rcv_wscale; |
1922 | loopbackremotenode->tcp_cntxt.snd_wscale = | 2034 | loopbackremotenode->tcp_cntxt.snd_wscale = |
1923 | cm_node->tcp_cntxt.rcv_wscale; | 2035 | cm_node->tcp_cntxt.rcv_wscale; |
1924 | 2036 | loopbackremotenode->state = NES_CM_STATE_MPAREQ_RCVD; | |
1925 | create_event(loopbackremotenode, NES_CM_EVENT_MPA_REQ); | 2037 | create_event(loopbackremotenode, NES_CM_EVENT_MPA_REQ); |
1926 | } | 2038 | } |
1927 | return cm_node; | 2039 | return cm_node; |
@@ -1976,7 +2088,11 @@ static int mini_cm_reject(struct nes_cm_core *cm_core, | |||
1976 | 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) |
1977 | { | 2089 | { |
1978 | int ret = 0; | 2090 | int ret = 0; |
2091 | int err = 0; | ||
1979 | 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; | ||
1980 | 2096 | ||
1981 | 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", |
1982 | __func__, cm_node, cm_node->tcp_cntxt.client, cm_node->state); | 2098 | __func__, cm_node, cm_node->tcp_cntxt.client, cm_node->state); |
@@ -1985,12 +2101,38 @@ static int mini_cm_reject(struct nes_cm_core *cm_core, | |||
1985 | return ret; | 2101 | return ret; |
1986 | cleanup_retrans_entry(cm_node); | 2102 | cleanup_retrans_entry(cm_node); |
1987 | 2103 | ||
1988 | passive_state = atomic_add_return(1, &cm_node->passive_state); | 2104 | if (!loopback) { |
1989 | cm_node->state = NES_CM_STATE_CLOSED; | 2105 | passive_state = atomic_add_return(1, &cm_node->passive_state); |
1990 | 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); | ||
1991 | rem_ref_cm_node(cm_core, cm_node); | 2128 | rem_ref_cm_node(cm_core, cm_node); |
1992 | else | 2129 | loopback->state = NES_CM_STATE_CLOSING; |
1993 | 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 | |||
1994 | return ret; | 2136 | return ret; |
1995 | } | 2137 | } |
1996 | 2138 | ||
@@ -2027,6 +2169,7 @@ static int mini_cm_close(struct nes_cm_core *cm_core, struct nes_cm_node *cm_nod | |||
2027 | case NES_CM_STATE_CLOSING: | 2169 | case NES_CM_STATE_CLOSING: |
2028 | ret = -1; | 2170 | ret = -1; |
2029 | break; | 2171 | break; |
2172 | case NES_CM_STATE_MPAREJ_RCVD: | ||
2030 | case NES_CM_STATE_LISTENING: | 2173 | case NES_CM_STATE_LISTENING: |
2031 | case NES_CM_STATE_UNKNOWN: | 2174 | case NES_CM_STATE_UNKNOWN: |
2032 | case NES_CM_STATE_INITED: | 2175 | case NES_CM_STATE_INITED: |
@@ -2223,15 +2366,15 @@ static int mini_cm_set(struct nes_cm_core *cm_core, u32 type, u32 value) | |||
2223 | int ret = 0; | 2366 | int ret = 0; |
2224 | 2367 | ||
2225 | switch (type) { | 2368 | switch (type) { |
2226 | case NES_CM_SET_PKT_SIZE: | 2369 | case NES_CM_SET_PKT_SIZE: |
2227 | cm_core->mtu = value; | 2370 | cm_core->mtu = value; |
2228 | break; | 2371 | break; |
2229 | case NES_CM_SET_FREE_PKT_Q_SIZE: | 2372 | case NES_CM_SET_FREE_PKT_Q_SIZE: |
2230 | cm_core->free_tx_pkt_max = value; | 2373 | cm_core->free_tx_pkt_max = value; |
2231 | break; | 2374 | break; |
2232 | default: | 2375 | default: |
2233 | /* unknown set option */ | 2376 | /* unknown set option */ |
2234 | ret = -EINVAL; | 2377 | ret = -EINVAL; |
2235 | } | 2378 | } |
2236 | 2379 | ||
2237 | return ret; | 2380 | return ret; |
@@ -2621,9 +2764,7 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
2621 | NES_QPCONTEXT_ORDIRD_WRPDU); | 2764 | NES_QPCONTEXT_ORDIRD_WRPDU); |
2622 | } else { | 2765 | } else { |
2623 | nesqp->nesqp_context->ird_ord_sizes |= | 2766 | nesqp->nesqp_context->ird_ord_sizes |= |
2624 | cpu_to_le32((NES_QPCONTEXT_ORDIRD_LSMM_PRESENT | | 2767 | cpu_to_le32(NES_QPCONTEXT_ORDIRD_WRPDU); |
2625 | NES_QPCONTEXT_ORDIRD_WRPDU | | ||
2626 | NES_QPCONTEXT_ORDIRD_ALSMM)); | ||
2627 | } | 2768 | } |
2628 | nesqp->skip_lsmm = 1; | 2769 | nesqp->skip_lsmm = 1; |
2629 | 2770 | ||
@@ -2745,23 +2886,35 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
2745 | int nes_reject(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len) | 2886 | int nes_reject(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len) |
2746 | { | 2887 | { |
2747 | struct nes_cm_node *cm_node; | 2888 | struct nes_cm_node *cm_node; |
2889 | struct nes_cm_node *loopback; | ||
2890 | |||
2748 | struct nes_cm_core *cm_core; | 2891 | struct nes_cm_core *cm_core; |
2749 | 2892 | ||
2750 | atomic_inc(&cm_rejects); | 2893 | atomic_inc(&cm_rejects); |
2751 | cm_node = (struct nes_cm_node *) cm_id->provider_data; | 2894 | cm_node = (struct nes_cm_node *) cm_id->provider_data; |
2895 | loopback = cm_node->loopbackpartner; | ||
2752 | cm_core = cm_node->cm_core; | 2896 | cm_core = cm_node->cm_core; |
2897 | cm_node->cm_id = cm_id; | ||
2753 | cm_node->mpa_frame_size = sizeof(struct ietf_mpa_frame) + pdata_len; | 2898 | cm_node->mpa_frame_size = sizeof(struct ietf_mpa_frame) + pdata_len; |
2754 | 2899 | ||
2900 | if (cm_node->mpa_frame_size > MAX_CM_BUFFER) | ||
2901 | return -EINVAL; | ||
2902 | |||
2755 | strcpy(&cm_node->mpa_frame.key[0], IEFT_MPA_KEY_REP); | 2903 | strcpy(&cm_node->mpa_frame.key[0], IEFT_MPA_KEY_REP); |
2756 | memcpy(&cm_node->mpa_frame.priv_data, pdata, pdata_len); | 2904 | if (loopback) { |
2905 | memcpy(&loopback->mpa_frame.priv_data, pdata, pdata_len); | ||
2906 | loopback->mpa_frame.priv_data_len = pdata_len; | ||
2907 | loopback->mpa_frame_size = sizeof(struct ietf_mpa_frame) + | ||
2908 | pdata_len; | ||
2909 | } else { | ||
2910 | memcpy(&cm_node->mpa_frame.priv_data, pdata, pdata_len); | ||
2911 | cm_node->mpa_frame.priv_data_len = cpu_to_be16(pdata_len); | ||
2912 | } | ||
2757 | 2913 | ||
2758 | cm_node->mpa_frame.priv_data_len = cpu_to_be16(pdata_len); | ||
2759 | cm_node->mpa_frame.rev = mpa_version; | 2914 | cm_node->mpa_frame.rev = mpa_version; |
2760 | cm_node->mpa_frame.flags = IETF_MPA_FLAGS_CRC | IETF_MPA_FLAGS_REJECT; | 2915 | cm_node->mpa_frame.flags = IETF_MPA_FLAGS_CRC | IETF_MPA_FLAGS_REJECT; |
2761 | 2916 | ||
2762 | cm_core->api->reject(cm_core, &cm_node->mpa_frame, cm_node); | 2917 | return cm_core->api->reject(cm_core, &cm_node->mpa_frame, cm_node); |
2763 | |||
2764 | return 0; | ||
2765 | } | 2918 | } |
2766 | 2919 | ||
2767 | 2920 | ||
@@ -3270,13 +3423,56 @@ static void cm_event_mpa_req(struct nes_cm_event *event) | |||
3270 | cm_event.remote_addr.sin_family = AF_INET; | 3423 | cm_event.remote_addr.sin_family = AF_INET; |
3271 | cm_event.remote_addr.sin_port = htons(event->cm_info.rem_port); | 3424 | cm_event.remote_addr.sin_port = htons(event->cm_info.rem_port); |
3272 | cm_event.remote_addr.sin_addr.s_addr = htonl(event->cm_info.rem_addr); | 3425 | cm_event.remote_addr.sin_addr.s_addr = htonl(event->cm_info.rem_addr); |
3426 | cm_event.private_data = cm_node->mpa_frame_buf; | ||
3427 | cm_event.private_data_len = (u8) cm_node->mpa_frame_size; | ||
3428 | |||
3429 | ret = cm_id->event_handler(cm_id, &cm_event); | ||
3430 | if (ret) | ||
3431 | printk(KERN_ERR "%s[%u] OFA CM event_handler returned, ret=%d\n", | ||
3432 | __func__, __LINE__, ret); | ||
3433 | return; | ||
3434 | } | ||
3435 | |||
3436 | |||
3437 | static void cm_event_mpa_reject(struct nes_cm_event *event) | ||
3438 | { | ||
3439 | struct iw_cm_id *cm_id; | ||
3440 | struct iw_cm_event cm_event; | ||
3441 | struct nes_cm_node *cm_node; | ||
3442 | int ret; | ||
3443 | |||
3444 | cm_node = event->cm_node; | ||
3445 | if (!cm_node) | ||
3446 | return; | ||
3447 | cm_id = cm_node->cm_id; | ||
3448 | |||
3449 | atomic_inc(&cm_connect_reqs); | ||
3450 | nes_debug(NES_DBG_CM, "cm_node = %p - cm_id = %p, jiffies = %lu\n", | ||
3451 | cm_node, cm_id, jiffies); | ||
3452 | |||
3453 | cm_event.event = IW_CM_EVENT_CONNECT_REPLY; | ||
3454 | cm_event.status = -ECONNREFUSED; | ||
3455 | cm_event.provider_data = cm_id->provider_data; | ||
3456 | |||
3457 | cm_event.local_addr.sin_family = AF_INET; | ||
3458 | cm_event.local_addr.sin_port = htons(event->cm_info.loc_port); | ||
3459 | cm_event.local_addr.sin_addr.s_addr = htonl(event->cm_info.loc_addr); | ||
3460 | |||
3461 | cm_event.remote_addr.sin_family = AF_INET; | ||
3462 | cm_event.remote_addr.sin_port = htons(event->cm_info.rem_port); | ||
3463 | cm_event.remote_addr.sin_addr.s_addr = htonl(event->cm_info.rem_addr); | ||
3273 | 3464 | ||
3274 | cm_event.private_data = cm_node->mpa_frame_buf; | 3465 | cm_event.private_data = cm_node->mpa_frame_buf; |
3275 | cm_event.private_data_len = (u8) cm_node->mpa_frame_size; | 3466 | cm_event.private_data_len = (u8) cm_node->mpa_frame_size; |
3467 | |||
3468 | nes_debug(NES_DBG_CM, "call CM_EVENT_MPA_REJECTED, local_addr=%08x, " | ||
3469 | "remove_addr=%08x\n", | ||
3470 | cm_event.local_addr.sin_addr.s_addr, | ||
3471 | cm_event.remote_addr.sin_addr.s_addr); | ||
3276 | 3472 | ||
3277 | ret = cm_id->event_handler(cm_id, &cm_event); | 3473 | ret = cm_id->event_handler(cm_id, &cm_event); |
3278 | if (ret) | 3474 | if (ret) |
3279 | printk("%s[%u] OFA CM event_handler returned, ret=%d\n", | 3475 | printk(KERN_ERR "%s[%u] OFA CM event_handler returned, ret=%d\n", |
3280 | __func__, __LINE__, ret); | 3476 | __func__, __LINE__, ret); |
3281 | 3477 | ||
3282 | return; | 3478 | return; |
@@ -3341,6 +3537,14 @@ static void nes_cm_event_handler(struct work_struct *work) | |||
3341 | cm_event_connected(event); | 3537 | cm_event_connected(event); |
3342 | nes_debug(NES_DBG_CM, "CM Event: CONNECTED\n"); | 3538 | nes_debug(NES_DBG_CM, "CM Event: CONNECTED\n"); |
3343 | break; | 3539 | break; |
3540 | case NES_CM_EVENT_MPA_REJECT: | ||
3541 | if ((!event->cm_node->cm_id) || | ||
3542 | (event->cm_node->state == NES_CM_STATE_TSA)) | ||
3543 | break; | ||
3544 | cm_event_mpa_reject(event); | ||
3545 | nes_debug(NES_DBG_CM, "CM Event: REJECT\n"); | ||
3546 | break; | ||
3547 | |||
3344 | case NES_CM_EVENT_ABORTED: | 3548 | case NES_CM_EVENT_ABORTED: |
3345 | if ((!event->cm_node->cm_id) || | 3549 | if ((!event->cm_node->cm_id) || |
3346 | (event->cm_node->state == NES_CM_STATE_TSA)) | 3550 | (event->cm_node->state == NES_CM_STATE_TSA)) |
diff --git a/drivers/infiniband/hw/nes/nes_cm.h b/drivers/infiniband/hw/nes/nes_cm.h index 4ab2bebf12ac..d5f778202eb7 100644 --- a/drivers/infiniband/hw/nes/nes_cm.h +++ b/drivers/infiniband/hw/nes/nes_cm.h | |||
@@ -39,6 +39,9 @@ | |||
39 | #define NES_MANAGE_APBVT_DEL 0 | 39 | #define NES_MANAGE_APBVT_DEL 0 |
40 | #define NES_MANAGE_APBVT_ADD 1 | 40 | #define NES_MANAGE_APBVT_ADD 1 |
41 | 41 | ||
42 | #define NES_MPA_REQUEST_ACCEPT 1 | ||
43 | #define NES_MPA_REQUEST_REJECT 2 | ||
44 | |||
42 | /* IETF MPA -- defines, enums, structs */ | 45 | /* IETF MPA -- defines, enums, structs */ |
43 | #define IEFT_MPA_KEY_REQ "MPA ID Req Frame" | 46 | #define IEFT_MPA_KEY_REQ "MPA ID Req Frame" |
44 | #define IEFT_MPA_KEY_REP "MPA ID Rep Frame" | 47 | #define IEFT_MPA_KEY_REP "MPA ID Rep Frame" |
@@ -186,6 +189,7 @@ enum nes_cm_node_state { | |||
186 | NES_CM_STATE_ACCEPTING, | 189 | NES_CM_STATE_ACCEPTING, |
187 | NES_CM_STATE_MPAREQ_SENT, | 190 | NES_CM_STATE_MPAREQ_SENT, |
188 | NES_CM_STATE_MPAREQ_RCVD, | 191 | NES_CM_STATE_MPAREQ_RCVD, |
192 | NES_CM_STATE_MPAREJ_RCVD, | ||
189 | NES_CM_STATE_TSA, | 193 | NES_CM_STATE_TSA, |
190 | NES_CM_STATE_FIN_WAIT1, | 194 | NES_CM_STATE_FIN_WAIT1, |
191 | NES_CM_STATE_FIN_WAIT2, | 195 | NES_CM_STATE_FIN_WAIT2, |
@@ -278,13 +282,12 @@ struct nes_cm_node { | |||
278 | struct nes_timer_entry *send_entry; | 282 | struct nes_timer_entry *send_entry; |
279 | 283 | ||
280 | spinlock_t retrans_list_lock; | 284 | spinlock_t retrans_list_lock; |
281 | struct list_head recv_list; | 285 | struct nes_timer_entry *recv_entry; |
282 | spinlock_t recv_list_lock; | ||
283 | 286 | ||
284 | int send_write0; | 287 | int send_write0; |
285 | union { | 288 | union { |
286 | struct ietf_mpa_frame mpa_frame; | 289 | struct ietf_mpa_frame mpa_frame; |
287 | u8 mpa_frame_buf[NES_CM_DEFAULT_MTU]; | 290 | u8 mpa_frame_buf[MAX_CM_BUFFER]; |
288 | }; | 291 | }; |
289 | u16 mpa_frame_size; | 292 | u16 mpa_frame_size; |
290 | struct iw_cm_id *cm_id; | 293 | struct iw_cm_id *cm_id; |
@@ -326,6 +329,7 @@ enum nes_cm_event_type { | |||
326 | NES_CM_EVENT_MPA_REQ, | 329 | NES_CM_EVENT_MPA_REQ, |
327 | NES_CM_EVENT_MPA_CONNECT, | 330 | NES_CM_EVENT_MPA_CONNECT, |
328 | NES_CM_EVENT_MPA_ACCEPT, | 331 | NES_CM_EVENT_MPA_ACCEPT, |
332 | NES_CM_EVENT_MPA_REJECT, | ||
329 | NES_CM_EVENT_MPA_ESTABLISHED, | 333 | NES_CM_EVENT_MPA_ESTABLISHED, |
330 | NES_CM_EVENT_CONNECTED, | 334 | NES_CM_EVENT_CONNECTED, |
331 | NES_CM_EVENT_CLOSED, | 335 | NES_CM_EVENT_CLOSED, |