diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-26 23:40:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-26 23:40:36 -0400 |
commit | 8be1a6d6c77ab4532e4476fdb8177030ef48b52c (patch) | |
tree | c94ff327a6291672e1f9071a79bf61d63f5f0cb9 /drivers/infiniband | |
parent | 852fef69c0d9510a28a70221cfddd004efa02552 (diff) | |
parent | cc9969c96765476db5e30c9e074a57838604c1d1 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband:
mlx4: Update/add Mellanox Technologies copyright lines to mlx4 driver files
mlx4_core: Add VLAN tag field to WQE control segment struct
RDMA/nes: CM connection setup/teardown rework
IPoIB: Correct help text for INFINIBAND_IPOIB_DEBUG
IPoIB/cm: Connected mode is no longer EXPERIMENTAL
RDMA/ucm: BKL is not needed for ib_ucm_open()
RDMA/ucma: BKL is not needed for ucma_open()
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/core/ucm.c | 10 | ||||
-rw-r--r-- | drivers/infiniband/core/ucma.c | 11 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx4/cq.c | 1 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx4/main.c | 1 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx4/mlx4_ib.h | 1 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx4/mr.c | 1 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx4/qp.c | 1 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx4/srq.c | 1 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx4/user.h | 1 | ||||
-rw-r--r-- | drivers/infiniband/hw/nes/nes.c | 4 | ||||
-rw-r--r-- | drivers/infiniband/hw/nes/nes_cm.c | 2034 | ||||
-rw-r--r-- | drivers/infiniband/hw/nes/nes_cm.h | 23 | ||||
-rw-r--r-- | drivers/infiniband/hw/nes/nes_hw.c | 9 | ||||
-rw-r--r-- | drivers/infiniband/hw/nes/nes_verbs.c | 15 | ||||
-rw-r--r-- | drivers/infiniband/ulp/ipoib/Kconfig | 22 |
15 files changed, 1191 insertions, 944 deletions
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c index 9494005d1c9a..e603736682bf 100644 --- a/drivers/infiniband/core/ucm.c +++ b/drivers/infiniband/core/ucm.c | |||
@@ -43,7 +43,6 @@ | |||
43 | #include <linux/cdev.h> | 43 | #include <linux/cdev.h> |
44 | #include <linux/idr.h> | 44 | #include <linux/idr.h> |
45 | #include <linux/mutex.h> | 45 | #include <linux/mutex.h> |
46 | #include <linux/smp_lock.h> | ||
47 | 46 | ||
48 | #include <asm/uaccess.h> | 47 | #include <asm/uaccess.h> |
49 | 48 | ||
@@ -1154,11 +1153,18 @@ static unsigned int ib_ucm_poll(struct file *filp, | |||
1154 | return mask; | 1153 | return mask; |
1155 | } | 1154 | } |
1156 | 1155 | ||
1156 | /* | ||
1157 | * ib_ucm_open() does not need the BKL: | ||
1158 | * | ||
1159 | * - no global state is referred to; | ||
1160 | * - there is no ioctl method to race against; | ||
1161 | * - no further module initialization is required for open to work | ||
1162 | * after the device is registered. | ||
1163 | */ | ||
1157 | static int ib_ucm_open(struct inode *inode, struct file *filp) | 1164 | static int ib_ucm_open(struct inode *inode, struct file *filp) |
1158 | { | 1165 | { |
1159 | struct ib_ucm_file *file; | 1166 | struct ib_ucm_file *file; |
1160 | 1167 | ||
1161 | cycle_kernel_lock(); | ||
1162 | file = kmalloc(sizeof(*file), GFP_KERNEL); | 1168 | file = kmalloc(sizeof(*file), GFP_KERNEL); |
1163 | if (!file) | 1169 | if (!file) |
1164 | return -ENOMEM; | 1170 | return -ENOMEM; |
diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c index 195f97302fe5..b41dd26bbfa1 100644 --- a/drivers/infiniband/core/ucma.c +++ b/drivers/infiniband/core/ucma.c | |||
@@ -38,7 +38,6 @@ | |||
38 | #include <linux/in.h> | 38 | #include <linux/in.h> |
39 | #include <linux/in6.h> | 39 | #include <linux/in6.h> |
40 | #include <linux/miscdevice.h> | 40 | #include <linux/miscdevice.h> |
41 | #include <linux/smp_lock.h> | ||
42 | 41 | ||
43 | #include <rdma/rdma_user_cm.h> | 42 | #include <rdma/rdma_user_cm.h> |
44 | #include <rdma/ib_marshall.h> | 43 | #include <rdma/ib_marshall.h> |
@@ -1149,6 +1148,14 @@ static unsigned int ucma_poll(struct file *filp, struct poll_table_struct *wait) | |||
1149 | return mask; | 1148 | return mask; |
1150 | } | 1149 | } |
1151 | 1150 | ||
1151 | /* | ||
1152 | * ucma_open() does not need the BKL: | ||
1153 | * | ||
1154 | * - no global state is referred to; | ||
1155 | * - there is no ioctl method to race against; | ||
1156 | * - no further module initialization is required for open to work | ||
1157 | * after the device is registered. | ||
1158 | */ | ||
1152 | static int ucma_open(struct inode *inode, struct file *filp) | 1159 | static int ucma_open(struct inode *inode, struct file *filp) |
1153 | { | 1160 | { |
1154 | struct ucma_file *file; | 1161 | struct ucma_file *file; |
@@ -1157,7 +1164,6 @@ static int ucma_open(struct inode *inode, struct file *filp) | |||
1157 | if (!file) | 1164 | if (!file) |
1158 | return -ENOMEM; | 1165 | return -ENOMEM; |
1159 | 1166 | ||
1160 | lock_kernel(); | ||
1161 | INIT_LIST_HEAD(&file->event_list); | 1167 | INIT_LIST_HEAD(&file->event_list); |
1162 | INIT_LIST_HEAD(&file->ctx_list); | 1168 | INIT_LIST_HEAD(&file->ctx_list); |
1163 | init_waitqueue_head(&file->poll_wait); | 1169 | init_waitqueue_head(&file->poll_wait); |
@@ -1165,7 +1171,6 @@ static int ucma_open(struct inode *inode, struct file *filp) | |||
1165 | 1171 | ||
1166 | filp->private_data = file; | 1172 | filp->private_data = file; |
1167 | file->filp = filp; | 1173 | file->filp = filp; |
1168 | unlock_kernel(); | ||
1169 | return 0; | 1174 | return 0; |
1170 | } | 1175 | } |
1171 | 1176 | ||
diff --git a/drivers/infiniband/hw/mlx4/cq.c b/drivers/infiniband/hw/mlx4/cq.c index 0b191a4842ce..a1464574bfdd 100644 --- a/drivers/infiniband/hw/mlx4/cq.c +++ b/drivers/infiniband/hw/mlx4/cq.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved. | 2 | * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved. |
3 | * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved. | ||
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * 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 | 6 | * licenses. You may choose to be licensed under the terms of the GNU |
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index 38d6907ab521..a3c2851c0545 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved. | 2 | * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved. |
3 | * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved. | ||
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * 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 | 6 | * licenses. You may choose to be licensed under the terms of the GNU |
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h index d26a91317d4d..6e2b0dc21b61 100644 --- a/drivers/infiniband/hw/mlx4/mlx4_ib.h +++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006, 2007 Cisco Systems. All rights reserved. | 2 | * Copyright (c) 2006, 2007 Cisco Systems. All rights reserved. |
3 | * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved. | ||
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * 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 | 6 | * licenses. You may choose to be licensed under the terms of the GNU |
diff --git a/drivers/infiniband/hw/mlx4/mr.c b/drivers/infiniband/hw/mlx4/mr.c index db2086faa4ed..a4cdb465cd1d 100644 --- a/drivers/infiniband/hw/mlx4/mr.c +++ b/drivers/infiniband/hw/mlx4/mr.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved. | 2 | * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved. |
3 | * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved. | ||
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * 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 | 6 | * licenses. You may choose to be licensed under the terms of the GNU |
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c index 02a99bc4442e..f7bc7dd8578a 100644 --- a/drivers/infiniband/hw/mlx4/qp.c +++ b/drivers/infiniband/hw/mlx4/qp.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved. | 2 | * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved. |
3 | * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved. | ||
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * 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 | 6 | * licenses. You may choose to be licensed under the terms of the GNU |
diff --git a/drivers/infiniband/hw/mlx4/srq.c b/drivers/infiniband/hw/mlx4/srq.c index 12d6bc6f8007..d42565258fb7 100644 --- a/drivers/infiniband/hw/mlx4/srq.c +++ b/drivers/infiniband/hw/mlx4/srq.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved. | 2 | * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved. |
3 | * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved. | ||
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * 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 | 6 | * licenses. You may choose to be licensed under the terms of the GNU |
diff --git a/drivers/infiniband/hw/mlx4/user.h b/drivers/infiniband/hw/mlx4/user.h index e2d11be4525c..13beedeeef9f 100644 --- a/drivers/infiniband/hw/mlx4/user.h +++ b/drivers/infiniband/hw/mlx4/user.h | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved. | 2 | * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved. |
3 | * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved. | ||
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * 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 | 6 | * licenses. You may choose to be licensed under the terms of the GNU |
diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c index d2884e778098..b0cab64e5e3d 100644 --- a/drivers/infiniband/hw/nes/nes.c +++ b/drivers/infiniband/hw/nes/nes.c | |||
@@ -276,6 +276,7 @@ static void nes_cqp_rem_ref_callback(struct nes_device *nesdev, struct nes_cqp_r | |||
276 | } | 276 | } |
277 | nes_free_resource(nesadapter, nesadapter->allocated_qps, nesqp->hwqp.qp_id); | 277 | nes_free_resource(nesadapter, nesadapter->allocated_qps, nesqp->hwqp.qp_id); |
278 | 278 | ||
279 | nesadapter->qp_table[nesqp->hwqp.qp_id-NES_FIRST_QPN] = NULL; | ||
279 | kfree(nesqp->allocated_buffer); | 280 | kfree(nesqp->allocated_buffer); |
280 | 281 | ||
281 | } | 282 | } |
@@ -289,7 +290,6 @@ void nes_rem_ref(struct ib_qp *ibqp) | |||
289 | struct nes_qp *nesqp; | 290 | struct nes_qp *nesqp; |
290 | struct nes_vnic *nesvnic = to_nesvnic(ibqp->device); | 291 | struct nes_vnic *nesvnic = to_nesvnic(ibqp->device); |
291 | struct nes_device *nesdev = nesvnic->nesdev; | 292 | struct nes_device *nesdev = nesvnic->nesdev; |
292 | struct nes_adapter *nesadapter = nesdev->nesadapter; | ||
293 | struct nes_hw_cqp_wqe *cqp_wqe; | 293 | struct nes_hw_cqp_wqe *cqp_wqe; |
294 | struct nes_cqp_request *cqp_request; | 294 | struct nes_cqp_request *cqp_request; |
295 | u32 opcode; | 295 | u32 opcode; |
@@ -303,8 +303,6 @@ void nes_rem_ref(struct ib_qp *ibqp) | |||
303 | } | 303 | } |
304 | 304 | ||
305 | if (atomic_dec_and_test(&nesqp->refcount)) { | 305 | if (atomic_dec_and_test(&nesqp->refcount)) { |
306 | nesadapter->qp_table[nesqp->hwqp.qp_id-NES_FIRST_QPN] = NULL; | ||
307 | |||
308 | /* Destroy the QP */ | 306 | /* Destroy the QP */ |
309 | cqp_request = nes_get_cqp_request(nesdev); | 307 | cqp_request = nes_get_cqp_request(nesdev); |
310 | if (cqp_request == NULL) { | 308 | if (cqp_request == NULL) { |
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index 6aa531d5276d..9f0b964b2c99 100644 --- a/drivers/infiniband/hw/nes/nes_cm.c +++ b/drivers/infiniband/hw/nes/nes_cm.c | |||
@@ -74,36 +74,59 @@ atomic_t cm_nodes_destroyed; | |||
74 | atomic_t cm_accel_dropped_pkts; | 74 | atomic_t cm_accel_dropped_pkts; |
75 | atomic_t cm_resets_recvd; | 75 | atomic_t cm_resets_recvd; |
76 | 76 | ||
77 | static inline int mini_cm_accelerated(struct nes_cm_core *, struct nes_cm_node *); | 77 | static inline int mini_cm_accelerated(struct nes_cm_core *, |
78 | struct nes_cm_node *); | ||
78 | static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *, | 79 | static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *, |
79 | struct nes_vnic *, struct nes_cm_info *); | 80 | struct nes_vnic *, struct nes_cm_info *); |
80 | static int add_ref_cm_node(struct nes_cm_node *); | ||
81 | static int rem_ref_cm_node(struct nes_cm_core *, struct nes_cm_node *); | ||
82 | static int mini_cm_del_listen(struct nes_cm_core *, struct nes_cm_listener *); | 81 | static int mini_cm_del_listen(struct nes_cm_core *, struct nes_cm_listener *); |
83 | static struct sk_buff *form_cm_frame(struct sk_buff *, struct nes_cm_node *, | ||
84 | void *, u32, void *, u32, u8); | ||
85 | static struct sk_buff *get_free_pkt(struct nes_cm_node *cm_node); | ||
86 | |||
87 | static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *, | 82 | static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *, |
88 | struct nes_vnic *, | 83 | struct nes_vnic *, u16, void *, struct nes_cm_info *); |
89 | struct ietf_mpa_frame *, | 84 | static int mini_cm_close(struct nes_cm_core *, struct nes_cm_node *); |
90 | struct nes_cm_info *); | ||
91 | static int mini_cm_accept(struct nes_cm_core *, struct ietf_mpa_frame *, | 85 | static int mini_cm_accept(struct nes_cm_core *, struct ietf_mpa_frame *, |
92 | struct nes_cm_node *); | 86 | struct nes_cm_node *); |
93 | static int mini_cm_reject(struct nes_cm_core *, struct ietf_mpa_frame *, | 87 | static int mini_cm_reject(struct nes_cm_core *, struct ietf_mpa_frame *, |
94 | struct nes_cm_node *); | 88 | struct nes_cm_node *); |
95 | static int mini_cm_close(struct nes_cm_core *, struct nes_cm_node *); | 89 | static void mini_cm_recv_pkt(struct nes_cm_core *, struct nes_vnic *, |
96 | static int mini_cm_recv_pkt(struct nes_cm_core *, struct nes_vnic *, | 90 | struct sk_buff *); |
97 | struct sk_buff *); | ||
98 | static int mini_cm_dealloc_core(struct nes_cm_core *); | 91 | static int mini_cm_dealloc_core(struct nes_cm_core *); |
99 | static int mini_cm_get(struct nes_cm_core *); | 92 | static int mini_cm_get(struct nes_cm_core *); |
100 | static int mini_cm_set(struct nes_cm_core *, u32, u32); | 93 | static int mini_cm_set(struct nes_cm_core *, u32, u32); |
94 | |||
95 | static struct sk_buff *form_cm_frame(struct sk_buff *, struct nes_cm_node *, | ||
96 | void *, u32, void *, u32, u8); | ||
97 | static struct sk_buff *get_free_pkt(struct nes_cm_node *cm_node); | ||
98 | static int add_ref_cm_node(struct nes_cm_node *); | ||
99 | static int rem_ref_cm_node(struct nes_cm_core *, struct nes_cm_node *); | ||
100 | |||
101 | static int nes_cm_disconn_true(struct nes_qp *); | 101 | static int nes_cm_disconn_true(struct nes_qp *); |
102 | static int nes_cm_post_event(struct nes_cm_event *event); | 102 | static int nes_cm_post_event(struct nes_cm_event *event); |
103 | static int nes_disconnect(struct nes_qp *nesqp, int abrupt); | 103 | static int nes_disconnect(struct nes_qp *nesqp, int abrupt); |
104 | static void nes_disconnect_worker(struct work_struct *work); | 104 | static void nes_disconnect_worker(struct work_struct *work); |
105 | static int send_ack(struct nes_cm_node *cm_node); | 105 | |
106 | static int send_mpa_request(struct nes_cm_node *, struct sk_buff *); | ||
107 | static int send_syn(struct nes_cm_node *, u32, struct sk_buff *); | ||
108 | static int send_reset(struct nes_cm_node *, struct sk_buff *); | ||
109 | static int send_ack(struct nes_cm_node *cm_node, struct sk_buff *skb); | ||
106 | static int send_fin(struct nes_cm_node *cm_node, struct sk_buff *skb); | 110 | static int send_fin(struct nes_cm_node *cm_node, struct sk_buff *skb); |
111 | static void process_packet(struct nes_cm_node *, struct sk_buff *, | ||
112 | struct nes_cm_core *); | ||
113 | |||
114 | static void active_open_err(struct nes_cm_node *, struct sk_buff *, int); | ||
115 | static void passive_open_err(struct nes_cm_node *, struct sk_buff *, int); | ||
116 | static void cleanup_retrans_entry(struct nes_cm_node *); | ||
117 | static void handle_rcv_mpa(struct nes_cm_node *, struct sk_buff *, | ||
118 | enum nes_cm_event_type); | ||
119 | static void free_retrans_entry(struct nes_cm_node *cm_node); | ||
120 | static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph, | ||
121 | struct sk_buff *skb, int optionsize, int passive); | ||
122 | |||
123 | /* CM event handler functions */ | ||
124 | static void cm_event_connected(struct nes_cm_event *); | ||
125 | static void cm_event_connect_error(struct nes_cm_event *); | ||
126 | static void cm_event_reset(struct nes_cm_event *); | ||
127 | static void cm_event_mpa_req(struct nes_cm_event *); | ||
128 | |||
129 | static void print_core(struct nes_cm_core *core); | ||
107 | 130 | ||
108 | /* External CM API Interface */ | 131 | /* External CM API Interface */ |
109 | /* instance of function pointers for client API */ | 132 | /* instance of function pointers for client API */ |
@@ -158,11 +181,11 @@ static struct nes_cm_event *create_event(struct nes_cm_node *cm_node, | |||
158 | event->cm_info.loc_port = cm_node->loc_port; | 181 | event->cm_info.loc_port = cm_node->loc_port; |
159 | event->cm_info.cm_id = cm_node->cm_id; | 182 | event->cm_info.cm_id = cm_node->cm_id; |
160 | 183 | ||
161 | nes_debug(NES_DBG_CM, "Created event=%p, type=%u, dst_addr=%08x[%x]," | 184 | nes_debug(NES_DBG_CM, "cm_node=%p Created event=%p, type=%u, " |
162 | " src_addr=%08x[%x]\n", | 185 | "dst_addr=%08x[%x], src_addr=%08x[%x]\n", |
163 | event, type, | 186 | cm_node, event, type, event->cm_info.loc_addr, |
164 | event->cm_info.loc_addr, event->cm_info.loc_port, | 187 | event->cm_info.loc_port, event->cm_info.rem_addr, |
165 | event->cm_info.rem_addr, event->cm_info.rem_port); | 188 | event->cm_info.rem_port); |
166 | 189 | ||
167 | nes_cm_post_event(event); | 190 | nes_cm_post_event(event); |
168 | return event; | 191 | return event; |
@@ -172,14 +195,11 @@ static struct nes_cm_event *create_event(struct nes_cm_node *cm_node, | |||
172 | /** | 195 | /** |
173 | * send_mpa_request | 196 | * send_mpa_request |
174 | */ | 197 | */ |
175 | static int send_mpa_request(struct nes_cm_node *cm_node) | 198 | static int send_mpa_request(struct nes_cm_node *cm_node, struct sk_buff *skb) |
176 | { | 199 | { |
177 | struct sk_buff *skb; | ||
178 | int ret; | 200 | int ret; |
179 | |||
180 | skb = get_free_pkt(cm_node); | ||
181 | if (!skb) { | 201 | if (!skb) { |
182 | nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n"); | 202 | nes_debug(NES_DBG_CM, "skb set to NULL\n"); |
183 | return -1; | 203 | return -1; |
184 | } | 204 | } |
185 | 205 | ||
@@ -188,9 +208,8 @@ static int send_mpa_request(struct nes_cm_node *cm_node) | |||
188 | cm_node->mpa_frame_size, SET_ACK); | 208 | cm_node->mpa_frame_size, SET_ACK); |
189 | 209 | ||
190 | ret = schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 1, 0); | 210 | ret = schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 1, 0); |
191 | if (ret < 0) { | 211 | if (ret < 0) |
192 | return ret; | 212 | return ret; |
193 | } | ||
194 | 213 | ||
195 | return 0; | 214 | return 0; |
196 | } | 215 | } |
@@ -229,46 +248,12 @@ static int parse_mpa(struct nes_cm_node *cm_node, u8 *buffer, u32 len) | |||
229 | 248 | ||
230 | 249 | ||
231 | /** | 250 | /** |
232 | * handle_exception_pkt - process an exception packet. | ||
233 | * We have been in a TSA state, and we have now received SW | ||
234 | * TCP/IP traffic should be a FIN request or IP pkt with options | ||
235 | */ | ||
236 | static int handle_exception_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb) | ||
237 | { | ||
238 | int ret = 0; | ||
239 | struct tcphdr *tcph = tcp_hdr(skb); | ||
240 | |||
241 | /* first check to see if this a FIN pkt */ | ||
242 | if (tcph->fin) { | ||
243 | /* we need to ACK the FIN request */ | ||
244 | send_ack(cm_node); | ||
245 | |||
246 | /* check which side we are (client/server) and set next state accordingly */ | ||
247 | if (cm_node->tcp_cntxt.client) | ||
248 | cm_node->state = NES_CM_STATE_CLOSING; | ||
249 | else { | ||
250 | /* we are the server side */ | ||
251 | cm_node->state = NES_CM_STATE_CLOSE_WAIT; | ||
252 | /* since this is a self contained CM we don't wait for */ | ||
253 | /* an APP to close us, just send final FIN immediately */ | ||
254 | ret = send_fin(cm_node, NULL); | ||
255 | cm_node->state = NES_CM_STATE_LAST_ACK; | ||
256 | } | ||
257 | } else { | ||
258 | ret = -EINVAL; | ||
259 | } | ||
260 | |||
261 | return ret; | ||
262 | } | ||
263 | |||
264 | |||
265 | /** | ||
266 | * form_cm_frame - get a free packet and build empty frame Use | 251 | * form_cm_frame - get a free packet and build empty frame Use |
267 | * node info to build. | 252 | * node info to build. |
268 | */ | 253 | */ |
269 | static struct sk_buff *form_cm_frame(struct sk_buff *skb, struct nes_cm_node *cm_node, | 254 | static struct sk_buff *form_cm_frame(struct sk_buff *skb, |
270 | void *options, u32 optionsize, void *data, | 255 | struct nes_cm_node *cm_node, void *options, u32 optionsize, |
271 | u32 datasize, u8 flags) | 256 | void *data, u32 datasize, u8 flags) |
272 | { | 257 | { |
273 | struct tcphdr *tcph; | 258 | struct tcphdr *tcph; |
274 | struct iphdr *iph; | 259 | struct iphdr *iph; |
@@ -332,10 +317,12 @@ static struct sk_buff *form_cm_frame(struct sk_buff *skb, struct nes_cm_node *cm | |||
332 | cm_node->tcp_cntxt.loc_seq_num++; | 317 | cm_node->tcp_cntxt.loc_seq_num++; |
333 | tcph->syn = 1; | 318 | tcph->syn = 1; |
334 | } else | 319 | } else |
335 | cm_node->tcp_cntxt.loc_seq_num += datasize; /* data (no headers) */ | 320 | cm_node->tcp_cntxt.loc_seq_num += datasize; |
336 | 321 | ||
337 | if (flags & SET_FIN) | 322 | if (flags & SET_FIN) { |
323 | cm_node->tcp_cntxt.loc_seq_num++; | ||
338 | tcph->fin = 1; | 324 | tcph->fin = 1; |
325 | } | ||
339 | 326 | ||
340 | if (flags & SET_RST) | 327 | if (flags & SET_RST) |
341 | tcph->rst = 1; | 328 | tcph->rst = 1; |
@@ -389,7 +376,7 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
389 | int close_when_complete) | 376 | int close_when_complete) |
390 | { | 377 | { |
391 | unsigned long flags; | 378 | unsigned long flags; |
392 | struct nes_cm_core *cm_core; | 379 | struct nes_cm_core *cm_core = cm_node->cm_core; |
393 | struct nes_timer_entry *new_send; | 380 | struct nes_timer_entry *new_send; |
394 | int ret = 0; | 381 | int ret = 0; |
395 | u32 was_timer_set; | 382 | u32 was_timer_set; |
@@ -411,7 +398,7 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
411 | new_send->close_when_complete = close_when_complete; | 398 | new_send->close_when_complete = close_when_complete; |
412 | 399 | ||
413 | if (type == NES_TIMER_TYPE_CLOSE) { | 400 | if (type == NES_TIMER_TYPE_CLOSE) { |
414 | new_send->timetosend += (HZ/2); /* TODO: decide on the correct value here */ | 401 | new_send->timetosend += (HZ/10); |
415 | spin_lock_irqsave(&cm_node->recv_list_lock, flags); | 402 | spin_lock_irqsave(&cm_node->recv_list_lock, flags); |
416 | list_add_tail(&new_send->list, &cm_node->recv_list); | 403 | list_add_tail(&new_send->list, &cm_node->recv_list); |
417 | spin_unlock_irqrestore(&cm_node->recv_list_lock, flags); | 404 | spin_unlock_irqrestore(&cm_node->recv_list_lock, flags); |
@@ -420,36 +407,28 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
420 | if (type == NES_TIMER_TYPE_SEND) { | 407 | if (type == NES_TIMER_TYPE_SEND) { |
421 | new_send->seq_num = ntohl(tcp_hdr(skb)->seq); | 408 | new_send->seq_num = ntohl(tcp_hdr(skb)->seq); |
422 | atomic_inc(&new_send->skb->users); | 409 | atomic_inc(&new_send->skb->users); |
410 | spin_lock_irqsave(&cm_node->retrans_list_lock, flags); | ||
411 | cm_node->send_entry = new_send; | ||
412 | add_ref_cm_node(cm_node); | ||
413 | spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags); | ||
414 | new_send->timetosend = jiffies + NES_RETRY_TIMEOUT; | ||
423 | 415 | ||
424 | ret = nes_nic_cm_xmit(new_send->skb, cm_node->netdev); | 416 | ret = nes_nic_cm_xmit(new_send->skb, cm_node->netdev); |
425 | if (ret != NETDEV_TX_OK) { | 417 | if (ret != NETDEV_TX_OK) { |
426 | nes_debug(NES_DBG_CM, "Error sending packet %p (jiffies = %lu)\n", | 418 | nes_debug(NES_DBG_CM, "Error sending packet %p " |
427 | new_send, jiffies); | 419 | "(jiffies = %lu)\n", new_send, jiffies); |
428 | atomic_dec(&new_send->skb->users); | 420 | atomic_dec(&new_send->skb->users); |
429 | new_send->timetosend = jiffies; | 421 | new_send->timetosend = jiffies; |
430 | } else { | 422 | } else { |
431 | cm_packets_sent++; | 423 | cm_packets_sent++; |
432 | if (!send_retrans) { | 424 | if (!send_retrans) { |
425 | cleanup_retrans_entry(cm_node); | ||
433 | if (close_when_complete) | 426 | if (close_when_complete) |
434 | rem_ref_cm_node(cm_node->cm_core, cm_node); | 427 | rem_ref_cm_node(cm_core, cm_node); |
435 | dev_kfree_skb_any(new_send->skb); | ||
436 | kfree(new_send); | ||
437 | return ret; | 428 | return ret; |
438 | } | 429 | } |
439 | new_send->timetosend = jiffies + NES_RETRY_TIMEOUT; | ||
440 | } | 430 | } |
441 | spin_lock_irqsave(&cm_node->retrans_list_lock, flags); | ||
442 | list_add_tail(&new_send->list, &cm_node->retrans_list); | ||
443 | spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags); | ||
444 | } | ||
445 | if (type == NES_TIMER_TYPE_RECV) { | ||
446 | new_send->seq_num = ntohl(tcp_hdr(skb)->seq); | ||
447 | new_send->timetosend = jiffies; | ||
448 | spin_lock_irqsave(&cm_node->recv_list_lock, flags); | ||
449 | list_add_tail(&new_send->list, &cm_node->recv_list); | ||
450 | spin_unlock_irqrestore(&cm_node->recv_list_lock, flags); | ||
451 | } | 431 | } |
452 | cm_core = cm_node->cm_core; | ||
453 | 432 | ||
454 | was_timer_set = timer_pending(&cm_core->tcp_timer); | 433 | was_timer_set = timer_pending(&cm_core->tcp_timer); |
455 | 434 | ||
@@ -476,23 +455,27 @@ static void nes_cm_timer_tick(unsigned long pass) | |||
476 | struct list_head *list_node, *list_node_temp; | 455 | struct list_head *list_node, *list_node_temp; |
477 | struct nes_cm_core *cm_core = g_cm_core; | 456 | struct nes_cm_core *cm_core = g_cm_core; |
478 | struct nes_qp *nesqp; | 457 | struct nes_qp *nesqp; |
479 | struct sk_buff *skb; | ||
480 | u32 settimer = 0; | 458 | u32 settimer = 0; |
481 | int ret = NETDEV_TX_OK; | 459 | int ret = NETDEV_TX_OK; |
482 | int node_done; | 460 | enum nes_cm_node_state last_state; |
483 | 461 | ||
484 | spin_lock_irqsave(&cm_core->ht_lock, flags); | 462 | spin_lock_irqsave(&cm_core->ht_lock, flags); |
485 | 463 | ||
486 | list_for_each_safe(list_node, list_core_temp, &cm_core->connected_nodes) { | 464 | list_for_each_safe(list_node, list_core_temp, |
465 | &cm_core->connected_nodes) { | ||
487 | cm_node = container_of(list_node, struct nes_cm_node, list); | 466 | cm_node = container_of(list_node, struct nes_cm_node, list); |
488 | add_ref_cm_node(cm_node); | 467 | add_ref_cm_node(cm_node); |
489 | spin_unlock_irqrestore(&cm_core->ht_lock, flags); | 468 | spin_unlock_irqrestore(&cm_core->ht_lock, flags); |
490 | spin_lock_irqsave(&cm_node->recv_list_lock, flags); | 469 | spin_lock_irqsave(&cm_node->recv_list_lock, flags); |
491 | list_for_each_safe(list_core, list_node_temp, &cm_node->recv_list) { | 470 | list_for_each_safe(list_core, list_node_temp, |
492 | recv_entry = container_of(list_core, struct nes_timer_entry, list); | 471 | &cm_node->recv_list) { |
493 | if ((time_after(recv_entry->timetosend, jiffies)) && | 472 | recv_entry = container_of(list_core, |
494 | (recv_entry->type == NES_TIMER_TYPE_CLOSE)) { | 473 | struct nes_timer_entry, list); |
495 | if (nexttimeout > recv_entry->timetosend || !settimer) { | 474 | if (!recv_entry) |
475 | break; | ||
476 | if (time_after(recv_entry->timetosend, jiffies)) { | ||
477 | if (nexttimeout > recv_entry->timetosend || | ||
478 | !settimer) { | ||
496 | nexttimeout = recv_entry->timetosend; | 479 | nexttimeout = recv_entry->timetosend; |
497 | settimer = 1; | 480 | settimer = 1; |
498 | } | 481 | } |
@@ -501,157 +484,143 @@ static void nes_cm_timer_tick(unsigned long pass) | |||
501 | list_del(&recv_entry->list); | 484 | list_del(&recv_entry->list); |
502 | cm_id = cm_node->cm_id; | 485 | cm_id = cm_node->cm_id; |
503 | spin_unlock_irqrestore(&cm_node->recv_list_lock, flags); | 486 | spin_unlock_irqrestore(&cm_node->recv_list_lock, flags); |
504 | if (recv_entry->type == NES_TIMER_TYPE_CLOSE) { | 487 | nesqp = (struct nes_qp *)recv_entry->skb; |
505 | nesqp = (struct nes_qp *)recv_entry->skb; | 488 | spin_lock_irqsave(&nesqp->lock, qplockflags); |
506 | spin_lock_irqsave(&nesqp->lock, qplockflags); | 489 | if (nesqp->cm_id) { |
507 | if (nesqp->cm_id) { | 490 | nes_debug(NES_DBG_CM, "QP%u: cm_id = %p, " |
508 | nes_debug(NES_DBG_CM, "QP%u: cm_id = %p, refcount = %d: " | 491 | "refcount = %d: HIT A " |
509 | "****** HIT A NES_TIMER_TYPE_CLOSE" | 492 | "NES_TIMER_TYPE_CLOSE with something " |
510 | " with something to do!!! ******\n", | 493 | "to do!!!\n", nesqp->hwqp.qp_id, cm_id, |
511 | nesqp->hwqp.qp_id, cm_id, | 494 | atomic_read(&nesqp->refcount)); |
512 | atomic_read(&nesqp->refcount)); | 495 | nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED; |
513 | nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED; | 496 | nesqp->last_aeq = NES_AEQE_AEID_RESET_SENT; |
514 | nesqp->last_aeq = NES_AEQE_AEID_RESET_SENT; | 497 | nesqp->ibqp_state = IB_QPS_ERR; |
515 | nesqp->ibqp_state = IB_QPS_ERR; | 498 | spin_unlock_irqrestore(&nesqp->lock, |
516 | spin_unlock_irqrestore(&nesqp->lock, qplockflags); | 499 | qplockflags); |
517 | nes_cm_disconn(nesqp); | 500 | nes_cm_disconn(nesqp); |
518 | } else { | 501 | } else { |
519 | spin_unlock_irqrestore(&nesqp->lock, qplockflags); | 502 | spin_unlock_irqrestore(&nesqp->lock, |
520 | nes_debug(NES_DBG_CM, "QP%u: cm_id = %p, refcount = %d:" | 503 | qplockflags); |
521 | " ****** HIT A NES_TIMER_TYPE_CLOSE" | 504 | nes_debug(NES_DBG_CM, "QP%u: cm_id = %p, " |
522 | " with nothing to do!!! ******\n", | 505 | "refcount = %d: HIT A " |
523 | nesqp->hwqp.qp_id, cm_id, | 506 | "NES_TIMER_TYPE_CLOSE with nothing " |
524 | atomic_read(&nesqp->refcount)); | 507 | "to do!!!\n", nesqp->hwqp.qp_id, cm_id, |
525 | nes_rem_ref(&nesqp->ibqp); | 508 | atomic_read(&nesqp->refcount)); |
526 | } | ||
527 | if (cm_id) | ||
528 | cm_id->rem_ref(cm_id); | ||
529 | } | 509 | } |
510 | if (cm_id) | ||
511 | cm_id->rem_ref(cm_id); | ||
512 | |||
530 | kfree(recv_entry); | 513 | kfree(recv_entry); |
531 | spin_lock_irqsave(&cm_node->recv_list_lock, flags); | 514 | spin_lock_irqsave(&cm_node->recv_list_lock, flags); |
532 | } | 515 | } |
533 | spin_unlock_irqrestore(&cm_node->recv_list_lock, flags); | 516 | spin_unlock_irqrestore(&cm_node->recv_list_lock, flags); |
534 | 517 | ||
535 | spin_lock_irqsave(&cm_node->retrans_list_lock, flags); | 518 | spin_lock_irqsave(&cm_node->retrans_list_lock, flags); |
536 | node_done = 0; | 519 | do { |
537 | list_for_each_safe(list_core, list_node_temp, &cm_node->retrans_list) { | 520 | send_entry = cm_node->send_entry; |
538 | if (node_done) { | 521 | if (!send_entry) |
539 | break; | 522 | continue; |
540 | } | ||
541 | send_entry = container_of(list_core, struct nes_timer_entry, list); | ||
542 | if (time_after(send_entry->timetosend, jiffies)) { | 523 | if (time_after(send_entry->timetosend, jiffies)) { |
543 | if (cm_node->state != NES_CM_STATE_TSA) { | 524 | if (cm_node->state != NES_CM_STATE_TSA) { |
544 | if ((nexttimeout > send_entry->timetosend) || !settimer) { | 525 | if ((nexttimeout > |
545 | nexttimeout = send_entry->timetosend; | 526 | send_entry->timetosend) || |
527 | !settimer) { | ||
528 | nexttimeout = | ||
529 | send_entry->timetosend; | ||
546 | settimer = 1; | 530 | settimer = 1; |
531 | continue; | ||
547 | } | 532 | } |
548 | node_done = 1; | ||
549 | continue; | ||
550 | } else { | 533 | } else { |
551 | list_del(&send_entry->list); | 534 | free_retrans_entry(cm_node); |
552 | skb = send_entry->skb; | ||
553 | spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags); | ||
554 | dev_kfree_skb_any(skb); | ||
555 | kfree(send_entry); | ||
556 | spin_lock_irqsave(&cm_node->retrans_list_lock, flags); | ||
557 | continue; | 535 | continue; |
558 | } | 536 | } |
559 | } | 537 | } |
560 | if (send_entry->type == NES_TIMER_NODE_CLEANUP) { | 538 | |
561 | list_del(&send_entry->list); | 539 | if ((cm_node->state == NES_CM_STATE_TSA) || |
562 | spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags); | 540 | (cm_node->state == NES_CM_STATE_CLOSED)) { |
563 | kfree(send_entry); | 541 | free_retrans_entry(cm_node); |
564 | spin_lock_irqsave(&cm_node->retrans_list_lock, flags); | ||
565 | continue; | ||
566 | } | ||
567 | if ((send_entry->seq_num < cm_node->tcp_cntxt.rem_ack_num) || | ||
568 | (cm_node->state == NES_CM_STATE_TSA) || | ||
569 | (cm_node->state == NES_CM_STATE_CLOSED)) { | ||
570 | skb = send_entry->skb; | ||
571 | list_del(&send_entry->list); | ||
572 | spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags); | ||
573 | kfree(send_entry); | ||
574 | dev_kfree_skb_any(skb); | ||
575 | spin_lock_irqsave(&cm_node->retrans_list_lock, flags); | ||
576 | continue; | 542 | continue; |
577 | } | 543 | } |
578 | 544 | ||
579 | if (!send_entry->retranscount || !send_entry->retrycount) { | 545 | if (!send_entry->retranscount || |
546 | !send_entry->retrycount) { | ||
580 | cm_packets_dropped++; | 547 | cm_packets_dropped++; |
581 | skb = send_entry->skb; | 548 | last_state = cm_node->state; |
582 | list_del(&send_entry->list); | 549 | cm_node->state = NES_CM_STATE_CLOSED; |
583 | spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags); | 550 | free_retrans_entry(cm_node); |
584 | dev_kfree_skb_any(skb); | 551 | spin_unlock_irqrestore( |
585 | kfree(send_entry); | 552 | &cm_node->retrans_list_lock, flags); |
586 | if (cm_node->state == NES_CM_STATE_SYN_RCVD) { | 553 | if (last_state == NES_CM_STATE_SYN_RCVD) |
587 | /* this node never even generated an indication up to the cm */ | ||
588 | rem_ref_cm_node(cm_core, cm_node); | 554 | rem_ref_cm_node(cm_core, cm_node); |
589 | } else { | 555 | else |
590 | cm_node->state = NES_CM_STATE_CLOSED; | 556 | create_event(cm_node, |
591 | create_event(cm_node, NES_CM_EVENT_ABORTED); | 557 | NES_CM_EVENT_ABORTED); |
592 | } | 558 | spin_lock_irqsave(&cm_node->retrans_list_lock, |
593 | spin_lock_irqsave(&cm_node->retrans_list_lock, flags); | 559 | flags); |
594 | continue; | 560 | continue; |
595 | } | 561 | } |
596 | /* this seems like the correct place, but leave send entry unprotected */ | ||
597 | /* spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags); */ | ||
598 | atomic_inc(&send_entry->skb->users); | 562 | atomic_inc(&send_entry->skb->users); |
599 | cm_packets_retrans++; | 563 | cm_packets_retrans++; |
600 | nes_debug(NES_DBG_CM, "Retransmitting send_entry %p for node %p," | 564 | nes_debug(NES_DBG_CM, "Retransmitting send_entry %p " |
601 | " jiffies = %lu, time to send = %lu, retranscount = %u, " | 565 | "for node %p, jiffies = %lu, time to send = " |
602 | "send_entry->seq_num = 0x%08X, cm_node->tcp_cntxt.rem_ack_num = 0x%08X\n", | 566 | "%lu, retranscount = %u, send_entry->seq_num = " |
603 | send_entry, cm_node, jiffies, send_entry->timetosend, send_entry->retranscount, | 567 | "0x%08X, cm_node->tcp_cntxt.rem_ack_num = " |
604 | send_entry->seq_num, cm_node->tcp_cntxt.rem_ack_num); | 568 | "0x%08X\n", send_entry, cm_node, jiffies, |
605 | 569 | send_entry->timetosend, | |
606 | spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags); | 570 | send_entry->retranscount, |
571 | send_entry->seq_num, | ||
572 | cm_node->tcp_cntxt.rem_ack_num); | ||
573 | |||
574 | spin_unlock_irqrestore(&cm_node->retrans_list_lock, | ||
575 | flags); | ||
607 | ret = nes_nic_cm_xmit(send_entry->skb, cm_node->netdev); | 576 | ret = nes_nic_cm_xmit(send_entry->skb, cm_node->netdev); |
577 | spin_lock_irqsave(&cm_node->retrans_list_lock, flags); | ||
608 | if (ret != NETDEV_TX_OK) { | 578 | if (ret != NETDEV_TX_OK) { |
579 | nes_debug(NES_DBG_CM, "rexmit failed for " | ||
580 | "node=%p\n", cm_node); | ||
609 | cm_packets_bounced++; | 581 | cm_packets_bounced++; |
610 | atomic_dec(&send_entry->skb->users); | 582 | atomic_dec(&send_entry->skb->users); |
611 | send_entry->retrycount--; | 583 | send_entry->retrycount--; |
612 | nexttimeout = jiffies + NES_SHORT_TIME; | 584 | nexttimeout = jiffies + NES_SHORT_TIME; |
613 | settimer = 1; | 585 | settimer = 1; |
614 | node_done = 1; | ||
615 | spin_lock_irqsave(&cm_node->retrans_list_lock, flags); | ||
616 | continue; | 586 | continue; |
617 | } else { | 587 | } else { |
618 | cm_packets_sent++; | 588 | cm_packets_sent++; |
619 | } | 589 | } |
620 | spin_lock_irqsave(&cm_node->retrans_list_lock, flags); | 590 | nes_debug(NES_DBG_CM, "Packet Sent: retrans count = " |
621 | list_del(&send_entry->list); | 591 | "%u, retry count = %u.\n", |
622 | nes_debug(NES_DBG_CM, "Packet Sent: retrans count = %u, retry count = %u.\n", | 592 | send_entry->retranscount, |
623 | send_entry->retranscount, send_entry->retrycount); | 593 | send_entry->retrycount); |
624 | if (send_entry->send_retrans) { | 594 | if (send_entry->send_retrans) { |
625 | send_entry->retranscount--; | 595 | send_entry->retranscount--; |
626 | send_entry->timetosend = jiffies + NES_RETRY_TIMEOUT; | 596 | send_entry->timetosend = jiffies + |
627 | if (nexttimeout > send_entry->timetosend || !settimer) { | 597 | NES_RETRY_TIMEOUT; |
598 | if (nexttimeout > send_entry->timetosend || | ||
599 | !settimer) { | ||
628 | nexttimeout = send_entry->timetosend; | 600 | nexttimeout = send_entry->timetosend; |
629 | settimer = 1; | 601 | settimer = 1; |
630 | } | 602 | } |
631 | list_add(&send_entry->list, &cm_node->retrans_list); | ||
632 | continue; | ||
633 | } else { | 603 | } else { |
634 | int close_when_complete; | 604 | int close_when_complete; |
635 | skb = send_entry->skb; | 605 | close_when_complete = |
636 | close_when_complete = send_entry->close_when_complete; | 606 | send_entry->close_when_complete; |
637 | spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags); | 607 | nes_debug(NES_DBG_CM, "cm_node=%p state=%d\n", |
638 | if (close_when_complete) { | 608 | cm_node, cm_node->state); |
639 | BUG_ON(atomic_read(&cm_node->ref_count) == 1); | 609 | free_retrans_entry(cm_node); |
640 | rem_ref_cm_node(cm_core, cm_node); | 610 | if (close_when_complete) |
641 | } | 611 | rem_ref_cm_node(cm_node->cm_core, |
642 | dev_kfree_skb_any(skb); | 612 | cm_node); |
643 | kfree(send_entry); | ||
644 | spin_lock_irqsave(&cm_node->retrans_list_lock, flags); | ||
645 | continue; | ||
646 | } | 613 | } |
647 | } | 614 | } while (0); |
648 | spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags); | ||
649 | |||
650 | rem_ref_cm_node(cm_core, cm_node); | ||
651 | 615 | ||
616 | spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags); | ||
617 | rem_ref_cm_node(cm_node->cm_core, cm_node); | ||
652 | spin_lock_irqsave(&cm_core->ht_lock, flags); | 618 | spin_lock_irqsave(&cm_core->ht_lock, flags); |
653 | if (ret != NETDEV_TX_OK) | 619 | if (ret != NETDEV_TX_OK) { |
620 | nes_debug(NES_DBG_CM, "rexmit failed for cm_node=%p\n", | ||
621 | cm_node); | ||
654 | break; | 622 | break; |
623 | } | ||
655 | } | 624 | } |
656 | spin_unlock_irqrestore(&cm_core->ht_lock, flags); | 625 | spin_unlock_irqrestore(&cm_core->ht_lock, flags); |
657 | 626 | ||
@@ -667,14 +636,14 @@ static void nes_cm_timer_tick(unsigned long pass) | |||
667 | /** | 636 | /** |
668 | * send_syn | 637 | * send_syn |
669 | */ | 638 | */ |
670 | static int send_syn(struct nes_cm_node *cm_node, u32 sendack) | 639 | static int send_syn(struct nes_cm_node *cm_node, u32 sendack, |
640 | struct sk_buff *skb) | ||
671 | { | 641 | { |
672 | int ret; | 642 | int ret; |
673 | int flags = SET_SYN; | 643 | int flags = SET_SYN; |
674 | struct sk_buff *skb; | ||
675 | char optionsbuffer[sizeof(struct option_mss) + | 644 | char optionsbuffer[sizeof(struct option_mss) + |
676 | sizeof(struct option_windowscale) + | 645 | sizeof(struct option_windowscale) + sizeof(struct option_base) + |
677 | sizeof(struct option_base) + 1]; | 646 | TCP_OPTIONS_PADDING]; |
678 | 647 | ||
679 | int optionssize = 0; | 648 | int optionssize = 0; |
680 | /* Sending MSS option */ | 649 | /* Sending MSS option */ |
@@ -695,8 +664,7 @@ static int send_syn(struct nes_cm_node *cm_node, u32 sendack) | |||
695 | options->as_windowscale.shiftcount = cm_node->tcp_cntxt.rcv_wscale; | 664 | options->as_windowscale.shiftcount = cm_node->tcp_cntxt.rcv_wscale; |
696 | optionssize += sizeof(struct option_windowscale); | 665 | optionssize += sizeof(struct option_windowscale); |
697 | 666 | ||
698 | if (sendack && !(NES_DRV_OPT_SUPRESS_OPTION_BC & nes_drv_opt) | 667 | if (sendack && !(NES_DRV_OPT_SUPRESS_OPTION_BC & nes_drv_opt)) { |
699 | ) { | ||
700 | options = (union all_known_options *)&optionsbuffer[optionssize]; | 668 | options = (union all_known_options *)&optionsbuffer[optionssize]; |
701 | options->as_base.optionnum = OPTION_NUMBER_WRITE0; | 669 | options->as_base.optionnum = OPTION_NUMBER_WRITE0; |
702 | options->as_base.length = sizeof(struct option_base); | 670 | options->as_base.length = sizeof(struct option_base); |
@@ -714,7 +682,8 @@ static int send_syn(struct nes_cm_node *cm_node, u32 sendack) | |||
714 | options->as_end = OPTION_NUMBER_END; | 682 | options->as_end = OPTION_NUMBER_END; |
715 | optionssize += 1; | 683 | optionssize += 1; |
716 | 684 | ||
717 | skb = get_free_pkt(cm_node); | 685 | if (!skb) |
686 | skb = get_free_pkt(cm_node); | ||
718 | if (!skb) { | 687 | if (!skb) { |
719 | nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n"); | 688 | nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n"); |
720 | return -1; | 689 | return -1; |
@@ -733,18 +702,18 @@ static int send_syn(struct nes_cm_node *cm_node, u32 sendack) | |||
733 | /** | 702 | /** |
734 | * send_reset | 703 | * send_reset |
735 | */ | 704 | */ |
736 | static int send_reset(struct nes_cm_node *cm_node) | 705 | static int send_reset(struct nes_cm_node *cm_node, struct sk_buff *skb) |
737 | { | 706 | { |
738 | int ret; | 707 | int ret; |
739 | struct sk_buff *skb = get_free_pkt(cm_node); | ||
740 | int flags = SET_RST | SET_ACK; | 708 | int flags = SET_RST | SET_ACK; |
741 | 709 | ||
710 | if (!skb) | ||
711 | skb = get_free_pkt(cm_node); | ||
742 | if (!skb) { | 712 | if (!skb) { |
743 | nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n"); | 713 | nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n"); |
744 | return -1; | 714 | return -1; |
745 | } | 715 | } |
746 | 716 | ||
747 | add_ref_cm_node(cm_node); | ||
748 | form_cm_frame(skb, cm_node, NULL, 0, NULL, 0, flags); | 717 | form_cm_frame(skb, cm_node, NULL, 0, NULL, 0, flags); |
749 | ret = schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 0, 1); | 718 | ret = schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 0, 1); |
750 | 719 | ||
@@ -755,10 +724,12 @@ static int send_reset(struct nes_cm_node *cm_node) | |||
755 | /** | 724 | /** |
756 | * send_ack | 725 | * send_ack |
757 | */ | 726 | */ |
758 | static int send_ack(struct nes_cm_node *cm_node) | 727 | static int send_ack(struct nes_cm_node *cm_node, struct sk_buff *skb) |
759 | { | 728 | { |
760 | int ret; | 729 | int ret; |
761 | struct sk_buff *skb = get_free_pkt(cm_node); | 730 | |
731 | if (!skb) | ||
732 | skb = get_free_pkt(cm_node); | ||
762 | 733 | ||
763 | if (!skb) { | 734 | if (!skb) { |
764 | nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n"); | 735 | nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n"); |
@@ -922,7 +893,8 @@ static int add_hte_node(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node | |||
922 | if (!cm_node || !cm_core) | 893 | if (!cm_node || !cm_core) |
923 | return -EINVAL; | 894 | return -EINVAL; |
924 | 895 | ||
925 | nes_debug(NES_DBG_CM, "Adding Node to Active Connection HT\n"); | 896 | nes_debug(NES_DBG_CM, "Adding Node %p to Active Connection HT\n", |
897 | cm_node); | ||
926 | 898 | ||
927 | /* first, make an index into our hash table */ | 899 | /* first, make an index into our hash table */ |
928 | hashkey = make_hashkey(cm_node->loc_port, cm_node->loc_addr, | 900 | hashkey = make_hashkey(cm_node->loc_port, cm_node->loc_addr, |
@@ -946,10 +918,35 @@ static int add_hte_node(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node | |||
946 | * mini_cm_dec_refcnt_listen | 918 | * mini_cm_dec_refcnt_listen |
947 | */ | 919 | */ |
948 | static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core, | 920 | static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core, |
949 | struct nes_cm_listener *listener, int free_hanging_nodes) | 921 | struct nes_cm_listener *listener, int free_hanging_nodes) |
950 | { | 922 | { |
951 | int ret = 1; | 923 | int ret = 1; |
952 | unsigned long flags; | 924 | unsigned long flags; |
925 | struct list_head *list_pos = NULL; | ||
926 | struct list_head *list_temp = NULL; | ||
927 | struct nes_cm_node *cm_node = NULL; | ||
928 | |||
929 | nes_debug(NES_DBG_CM, "attempting listener= %p free_nodes= %d, " | ||
930 | "refcnt=%d\n", listener, free_hanging_nodes, | ||
931 | atomic_read(&listener->ref_count)); | ||
932 | /* free non-accelerated child nodes for this listener */ | ||
933 | if (free_hanging_nodes) { | ||
934 | spin_lock_irqsave(&cm_core->ht_lock, flags); | ||
935 | list_for_each_safe(list_pos, list_temp, | ||
936 | &g_cm_core->connected_nodes) { | ||
937 | cm_node = container_of(list_pos, struct nes_cm_node, | ||
938 | list); | ||
939 | if ((cm_node->listener == listener) && | ||
940 | (!cm_node->accelerated)) { | ||
941 | cleanup_retrans_entry(cm_node); | ||
942 | spin_unlock_irqrestore(&cm_core->ht_lock, | ||
943 | flags); | ||
944 | send_reset(cm_node, NULL); | ||
945 | spin_lock_irqsave(&cm_core->ht_lock, flags); | ||
946 | } | ||
947 | } | ||
948 | spin_unlock_irqrestore(&cm_core->ht_lock, flags); | ||
949 | } | ||
953 | spin_lock_irqsave(&cm_core->listen_list_lock, flags); | 950 | spin_lock_irqsave(&cm_core->listen_list_lock, flags); |
954 | if (!atomic_dec_return(&listener->ref_count)) { | 951 | if (!atomic_dec_return(&listener->ref_count)) { |
955 | list_del(&listener->list); | 952 | list_del(&listener->list); |
@@ -1067,18 +1064,18 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core, | |||
1067 | cm_node->loc_port = cm_info->loc_port; | 1064 | cm_node->loc_port = cm_info->loc_port; |
1068 | cm_node->rem_port = cm_info->rem_port; | 1065 | cm_node->rem_port = cm_info->rem_port; |
1069 | cm_node->send_write0 = send_first; | 1066 | cm_node->send_write0 = send_first; |
1070 | nes_debug(NES_DBG_CM, "Make node addresses : loc = " NIPQUAD_FMT ":%x, rem = " NIPQUAD_FMT ":%x\n", | 1067 | nes_debug(NES_DBG_CM, "Make node addresses : loc = " NIPQUAD_FMT |
1071 | HIPQUAD(cm_node->loc_addr), cm_node->loc_port, | 1068 | ":%x, rem = " NIPQUAD_FMT ":%x\n", |
1072 | HIPQUAD(cm_node->rem_addr), cm_node->rem_port); | 1069 | HIPQUAD(cm_node->loc_addr), cm_node->loc_port, |
1070 | HIPQUAD(cm_node->rem_addr), cm_node->rem_port); | ||
1073 | cm_node->listener = listener; | 1071 | cm_node->listener = listener; |
1074 | cm_node->netdev = nesvnic->netdev; | 1072 | cm_node->netdev = nesvnic->netdev; |
1075 | cm_node->cm_id = cm_info->cm_id; | 1073 | cm_node->cm_id = cm_info->cm_id; |
1076 | memcpy(cm_node->loc_mac, nesvnic->netdev->dev_addr, ETH_ALEN); | 1074 | memcpy(cm_node->loc_mac, nesvnic->netdev->dev_addr, ETH_ALEN); |
1077 | 1075 | ||
1078 | nes_debug(NES_DBG_CM, "listener=%p, cm_id=%p\n", | 1076 | nes_debug(NES_DBG_CM, "listener=%p, cm_id=%p\n", cm_node->listener, |
1079 | cm_node->listener, cm_node->cm_id); | 1077 | cm_node->cm_id); |
1080 | 1078 | ||
1081 | INIT_LIST_HEAD(&cm_node->retrans_list); | ||
1082 | spin_lock_init(&cm_node->retrans_list_lock); | 1079 | spin_lock_init(&cm_node->retrans_list_lock); |
1083 | INIT_LIST_HEAD(&cm_node->recv_list); | 1080 | INIT_LIST_HEAD(&cm_node->recv_list); |
1084 | spin_lock_init(&cm_node->recv_list_lock); | 1081 | spin_lock_init(&cm_node->recv_list_lock); |
@@ -1142,10 +1139,9 @@ static int add_ref_cm_node(struct nes_cm_node *cm_node) | |||
1142 | * rem_ref_cm_node - destroy an instance of a cm node | 1139 | * rem_ref_cm_node - destroy an instance of a cm node |
1143 | */ | 1140 | */ |
1144 | static int rem_ref_cm_node(struct nes_cm_core *cm_core, | 1141 | static int rem_ref_cm_node(struct nes_cm_core *cm_core, |
1145 | struct nes_cm_node *cm_node) | 1142 | struct nes_cm_node *cm_node) |
1146 | { | 1143 | { |
1147 | unsigned long flags, qplockflags; | 1144 | unsigned long flags, qplockflags; |
1148 | struct nes_timer_entry *send_entry; | ||
1149 | struct nes_timer_entry *recv_entry; | 1145 | struct nes_timer_entry *recv_entry; |
1150 | struct iw_cm_id *cm_id; | 1146 | struct iw_cm_id *cm_id; |
1151 | struct list_head *list_core, *list_node_temp; | 1147 | struct list_head *list_core, *list_node_temp; |
@@ -1169,48 +1165,33 @@ static int rem_ref_cm_node(struct nes_cm_core *cm_core, | |||
1169 | atomic_dec(&cm_node->listener->pend_accepts_cnt); | 1165 | atomic_dec(&cm_node->listener->pend_accepts_cnt); |
1170 | BUG_ON(atomic_read(&cm_node->listener->pend_accepts_cnt) < 0); | 1166 | BUG_ON(atomic_read(&cm_node->listener->pend_accepts_cnt) < 0); |
1171 | } | 1167 | } |
1172 | 1168 | BUG_ON(cm_node->send_entry); | |
1173 | spin_lock_irqsave(&cm_node->retrans_list_lock, flags); | ||
1174 | list_for_each_safe(list_core, list_node_temp, &cm_node->retrans_list) { | ||
1175 | send_entry = container_of(list_core, struct nes_timer_entry, list); | ||
1176 | list_del(&send_entry->list); | ||
1177 | spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags); | ||
1178 | dev_kfree_skb_any(send_entry->skb); | ||
1179 | kfree(send_entry); | ||
1180 | spin_lock_irqsave(&cm_node->retrans_list_lock, flags); | ||
1181 | continue; | ||
1182 | } | ||
1183 | spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags); | ||
1184 | |||
1185 | spin_lock_irqsave(&cm_node->recv_list_lock, flags); | 1169 | spin_lock_irqsave(&cm_node->recv_list_lock, flags); |
1186 | list_for_each_safe(list_core, list_node_temp, &cm_node->recv_list) { | 1170 | list_for_each_safe(list_core, list_node_temp, &cm_node->recv_list) { |
1187 | recv_entry = container_of(list_core, struct nes_timer_entry, list); | 1171 | recv_entry = container_of(list_core, struct nes_timer_entry, |
1172 | list); | ||
1188 | list_del(&recv_entry->list); | 1173 | list_del(&recv_entry->list); |
1189 | cm_id = cm_node->cm_id; | 1174 | cm_id = cm_node->cm_id; |
1190 | spin_unlock_irqrestore(&cm_node->recv_list_lock, flags); | 1175 | spin_unlock_irqrestore(&cm_node->recv_list_lock, flags); |
1191 | if (recv_entry->type == NES_TIMER_TYPE_CLOSE) { | 1176 | nesqp = (struct nes_qp *)recv_entry->skb; |
1192 | nesqp = (struct nes_qp *)recv_entry->skb; | 1177 | spin_lock_irqsave(&nesqp->lock, qplockflags); |
1193 | spin_lock_irqsave(&nesqp->lock, qplockflags); | 1178 | if (nesqp->cm_id) { |
1194 | if (nesqp->cm_id) { | 1179 | nes_debug(NES_DBG_CM, "QP%u: cm_id = %p: HIT A " |
1195 | nes_debug(NES_DBG_CM, "QP%u: cm_id = %p: ****** HIT A NES_TIMER_TYPE_CLOSE" | 1180 | "NES_TIMER_TYPE_CLOSE with something to do!\n", |
1196 | " with something to do!!! ******\n", | 1181 | nesqp->hwqp.qp_id, cm_id); |
1197 | nesqp->hwqp.qp_id, cm_id); | 1182 | nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED; |
1198 | nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED; | 1183 | nesqp->last_aeq = NES_AEQE_AEID_RESET_SENT; |
1199 | nesqp->last_aeq = NES_AEQE_AEID_RESET_SENT; | 1184 | nesqp->ibqp_state = IB_QPS_ERR; |
1200 | nesqp->ibqp_state = IB_QPS_ERR; | 1185 | spin_unlock_irqrestore(&nesqp->lock, qplockflags); |
1201 | spin_unlock_irqrestore(&nesqp->lock, qplockflags); | 1186 | nes_cm_disconn(nesqp); |
1202 | nes_cm_disconn(nesqp); | 1187 | } else { |
1203 | } else { | 1188 | spin_unlock_irqrestore(&nesqp->lock, qplockflags); |
1204 | spin_unlock_irqrestore(&nesqp->lock, qplockflags); | 1189 | nes_debug(NES_DBG_CM, "QP%u: cm_id = %p: HIT A " |
1205 | nes_debug(NES_DBG_CM, "QP%u: cm_id = %p: ****** HIT A NES_TIMER_TYPE_CLOSE" | 1190 | "NES_TIMER_TYPE_CLOSE with nothing to do!\n", |
1206 | " with nothing to do!!! ******\n", | 1191 | nesqp->hwqp.qp_id, cm_id); |
1207 | nesqp->hwqp.qp_id, cm_id); | ||
1208 | nes_rem_ref(&nesqp->ibqp); | ||
1209 | } | ||
1210 | cm_id->rem_ref(cm_id); | ||
1211 | } else if (recv_entry->type == NES_TIMER_TYPE_RECV) { | ||
1212 | dev_kfree_skb_any(recv_entry->skb); | ||
1213 | } | 1192 | } |
1193 | cm_id->rem_ref(cm_id); | ||
1194 | |||
1214 | kfree(recv_entry); | 1195 | kfree(recv_entry); |
1215 | spin_lock_irqsave(&cm_node->recv_list_lock, flags); | 1196 | spin_lock_irqsave(&cm_node->recv_list_lock, flags); |
1216 | } | 1197 | } |
@@ -1221,23 +1202,31 @@ static int rem_ref_cm_node(struct nes_cm_core *cm_core, | |||
1221 | } else { | 1202 | } else { |
1222 | if (cm_node->apbvt_set && cm_node->nesvnic) { | 1203 | if (cm_node->apbvt_set && cm_node->nesvnic) { |
1223 | nes_manage_apbvt(cm_node->nesvnic, cm_node->loc_port, | 1204 | nes_manage_apbvt(cm_node->nesvnic, cm_node->loc_port, |
1224 | PCI_FUNC(cm_node->nesvnic->nesdev->pcidev->devfn), | 1205 | PCI_FUNC( |
1225 | NES_MANAGE_APBVT_DEL); | 1206 | cm_node->nesvnic->nesdev->pcidev->devfn), |
1207 | NES_MANAGE_APBVT_DEL); | ||
1226 | } | 1208 | } |
1227 | } | 1209 | } |
1228 | 1210 | ||
1229 | kfree(cm_node); | ||
1230 | atomic_dec(&cm_core->node_cnt); | 1211 | atomic_dec(&cm_core->node_cnt); |
1231 | atomic_inc(&cm_nodes_destroyed); | 1212 | atomic_inc(&cm_nodes_destroyed); |
1213 | nesqp = cm_node->nesqp; | ||
1214 | if (nesqp) { | ||
1215 | nesqp->cm_node = NULL; | ||
1216 | nes_rem_ref(&nesqp->ibqp); | ||
1217 | cm_node->nesqp = NULL; | ||
1218 | } | ||
1232 | 1219 | ||
1220 | cm_node->freed = 1; | ||
1221 | kfree(cm_node); | ||
1233 | return 0; | 1222 | return 0; |
1234 | } | 1223 | } |
1235 | 1224 | ||
1236 | |||
1237 | /** | 1225 | /** |
1238 | * process_options | 1226 | * process_options |
1239 | */ | 1227 | */ |
1240 | static int process_options(struct nes_cm_node *cm_node, u8 *optionsloc, u32 optionsize, u32 syn_packet) | 1228 | static int process_options(struct nes_cm_node *cm_node, u8 *optionsloc, |
1229 | u32 optionsize, u32 syn_packet) | ||
1241 | { | 1230 | { |
1242 | u32 tmp; | 1231 | u32 tmp; |
1243 | u32 offset = 0; | 1232 | u32 offset = 0; |
@@ -1247,35 +1236,37 @@ static int process_options(struct nes_cm_node *cm_node, u8 *optionsloc, u32 opti | |||
1247 | while (offset < optionsize) { | 1236 | while (offset < optionsize) { |
1248 | all_options = (union all_known_options *)(optionsloc + offset); | 1237 | all_options = (union all_known_options *)(optionsloc + offset); |
1249 | switch (all_options->as_base.optionnum) { | 1238 | switch (all_options->as_base.optionnum) { |
1250 | case OPTION_NUMBER_END: | 1239 | case OPTION_NUMBER_END: |
1251 | offset = optionsize; | 1240 | offset = optionsize; |
1252 | break; | 1241 | break; |
1253 | case OPTION_NUMBER_NONE: | 1242 | case OPTION_NUMBER_NONE: |
1254 | offset += 1; | 1243 | offset += 1; |
1255 | continue; | 1244 | continue; |
1256 | case OPTION_NUMBER_MSS: | 1245 | case OPTION_NUMBER_MSS: |
1257 | nes_debug(NES_DBG_CM, "%s: MSS Length: %d Offset: %d Size: %d\n", | 1246 | nes_debug(NES_DBG_CM, "%s: MSS Length: %d Offset: %d " |
1258 | __func__, | 1247 | "Size: %d\n", __func__, |
1259 | all_options->as_mss.length, offset, optionsize); | 1248 | all_options->as_mss.length, offset, optionsize); |
1260 | got_mss_option = 1; | 1249 | got_mss_option = 1; |
1261 | if (all_options->as_mss.length != 4) { | 1250 | if (all_options->as_mss.length != 4) { |
1262 | return 1; | 1251 | return 1; |
1263 | } else { | 1252 | } else { |
1264 | tmp = ntohs(all_options->as_mss.mss); | 1253 | tmp = ntohs(all_options->as_mss.mss); |
1265 | if (tmp > 0 && tmp < cm_node->tcp_cntxt.mss) | 1254 | if (tmp > 0 && tmp < |
1266 | cm_node->tcp_cntxt.mss = tmp; | 1255 | cm_node->tcp_cntxt.mss) |
1267 | } | 1256 | cm_node->tcp_cntxt.mss = tmp; |
1268 | break; | 1257 | } |
1269 | case OPTION_NUMBER_WINDOW_SCALE: | 1258 | break; |
1270 | cm_node->tcp_cntxt.snd_wscale = all_options->as_windowscale.shiftcount; | 1259 | case OPTION_NUMBER_WINDOW_SCALE: |
1271 | break; | 1260 | cm_node->tcp_cntxt.snd_wscale = |
1272 | case OPTION_NUMBER_WRITE0: | 1261 | all_options->as_windowscale.shiftcount; |
1273 | cm_node->send_write0 = 1; | 1262 | break; |
1274 | break; | 1263 | case OPTION_NUMBER_WRITE0: |
1275 | default: | 1264 | cm_node->send_write0 = 1; |
1276 | nes_debug(NES_DBG_CM, "TCP Option not understood: %x\n", | 1265 | break; |
1277 | all_options->as_base.optionnum); | 1266 | default: |
1278 | break; | 1267 | nes_debug(NES_DBG_CM, "TCP Option not understood: %x\n", |
1268 | all_options->as_base.optionnum); | ||
1269 | break; | ||
1279 | } | 1270 | } |
1280 | offset += all_options->as_base.length; | 1271 | offset += all_options->as_base.length; |
1281 | } | 1272 | } |
@@ -1284,300 +1275,491 @@ static int process_options(struct nes_cm_node *cm_node, u8 *optionsloc, u32 opti | |||
1284 | return 0; | 1275 | return 0; |
1285 | } | 1276 | } |
1286 | 1277 | ||
1278 | static void drop_packet(struct sk_buff *skb) | ||
1279 | { | ||
1280 | atomic_inc(&cm_accel_dropped_pkts); | ||
1281 | dev_kfree_skb_any(skb); | ||
1282 | } | ||
1287 | 1283 | ||
1288 | /** | 1284 | static void handle_fin_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, |
1289 | * process_packet | 1285 | struct tcphdr *tcph) |
1290 | */ | ||
1291 | static int process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb, | ||
1292 | struct nes_cm_core *cm_core) | ||
1293 | { | 1286 | { |
1294 | int optionsize; | 1287 | atomic_inc(&cm_resets_recvd); |
1295 | int datasize; | 1288 | nes_debug(NES_DBG_CM, "Received FIN, cm_node = %p, state = %u. " |
1296 | int ret = 0; | 1289 | "refcnt=%d\n", cm_node, cm_node->state, |
1297 | struct tcphdr *tcph = tcp_hdr(skb); | 1290 | atomic_read(&cm_node->ref_count)); |
1298 | u32 inc_sequence; | 1291 | cm_node->tcp_cntxt.rcv_nxt++; |
1299 | if (cm_node->state == NES_CM_STATE_SYN_SENT && tcph->syn) { | 1292 | cleanup_retrans_entry(cm_node); |
1300 | inc_sequence = ntohl(tcph->seq); | 1293 | switch (cm_node->state) { |
1301 | cm_node->tcp_cntxt.rcv_nxt = inc_sequence; | 1294 | case NES_CM_STATE_SYN_RCVD: |
1295 | case NES_CM_STATE_SYN_SENT: | ||
1296 | case NES_CM_STATE_ESTABLISHED: | ||
1297 | case NES_CM_STATE_MPAREQ_SENT: | ||
1298 | cm_node->state = NES_CM_STATE_LAST_ACK; | ||
1299 | send_fin(cm_node, skb); | ||
1300 | break; | ||
1301 | case NES_CM_STATE_FIN_WAIT1: | ||
1302 | cm_node->state = NES_CM_STATE_CLOSING; | ||
1303 | send_ack(cm_node, skb); | ||
1304 | break; | ||
1305 | case NES_CM_STATE_FIN_WAIT2: | ||
1306 | cm_node->state = NES_CM_STATE_TIME_WAIT; | ||
1307 | send_ack(cm_node, skb); | ||
1308 | cm_node->state = NES_CM_STATE_CLOSED; | ||
1309 | break; | ||
1310 | case NES_CM_STATE_TSA: | ||
1311 | default: | ||
1312 | nes_debug(NES_DBG_CM, "Error Rcvd FIN for node-%p state = %d\n", | ||
1313 | cm_node, cm_node->state); | ||
1314 | drop_packet(skb); | ||
1315 | break; | ||
1302 | } | 1316 | } |
1317 | } | ||
1303 | 1318 | ||
1304 | if ((!tcph) || (cm_node->state == NES_CM_STATE_TSA)) { | ||
1305 | BUG_ON(!tcph); | ||
1306 | atomic_inc(&cm_accel_dropped_pkts); | ||
1307 | return -1; | ||
1308 | } | ||
1309 | 1319 | ||
1310 | if (tcph->rst) { | 1320 | static void handle_rst_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, |
1311 | atomic_inc(&cm_resets_recvd); | 1321 | struct tcphdr *tcph) |
1312 | nes_debug(NES_DBG_CM, "Received Reset, cm_node = %p, state = %u. refcnt=%d\n", | 1322 | { |
1313 | cm_node, cm_node->state, atomic_read(&cm_node->ref_count)); | ||
1314 | switch (cm_node->state) { | ||
1315 | case NES_CM_STATE_LISTENING: | ||
1316 | rem_ref_cm_node(cm_core, cm_node); | ||
1317 | break; | ||
1318 | case NES_CM_STATE_TSA: | ||
1319 | case NES_CM_STATE_CLOSED: | ||
1320 | break; | ||
1321 | case NES_CM_STATE_SYN_RCVD: | ||
1322 | nes_debug(NES_DBG_CM, "Received a reset for local 0x%08X:%04X," | ||
1323 | " remote 0x%08X:%04X, node state = %u\n", | ||
1324 | cm_node->loc_addr, cm_node->loc_port, | ||
1325 | cm_node->rem_addr, cm_node->rem_port, | ||
1326 | cm_node->state); | ||
1327 | rem_ref_cm_node(cm_core, cm_node); | ||
1328 | break; | ||
1329 | case NES_CM_STATE_ONE_SIDE_ESTABLISHED: | ||
1330 | case NES_CM_STATE_ESTABLISHED: | ||
1331 | case NES_CM_STATE_MPAREQ_SENT: | ||
1332 | default: | ||
1333 | nes_debug(NES_DBG_CM, "Received a reset for local 0x%08X:%04X," | ||
1334 | " remote 0x%08X:%04X, node state = %u refcnt=%d\n", | ||
1335 | cm_node->loc_addr, cm_node->loc_port, | ||
1336 | cm_node->rem_addr, cm_node->rem_port, | ||
1337 | cm_node->state, atomic_read(&cm_node->ref_count)); | ||
1338 | /* create event */ | ||
1339 | cm_node->state = NES_CM_STATE_CLOSED; | ||
1340 | 1323 | ||
1341 | create_event(cm_node, NES_CM_EVENT_ABORTED); | 1324 | int reset = 0; /* whether to send reset in case of err.. */ |
1342 | break; | 1325 | atomic_inc(&cm_resets_recvd); |
1326 | nes_debug(NES_DBG_CM, "Received Reset, cm_node = %p, state = %u." | ||
1327 | " refcnt=%d\n", cm_node, cm_node->state, | ||
1328 | atomic_read(&cm_node->ref_count)); | ||
1329 | cleanup_retrans_entry(cm_node); | ||
1330 | switch (cm_node->state) { | ||
1331 | case NES_CM_STATE_SYN_SENT: | ||
1332 | case NES_CM_STATE_MPAREQ_SENT: | ||
1333 | nes_debug(NES_DBG_CM, "%s[%u] create abort for cm_node=%p " | ||
1334 | "listener=%p state=%d\n", __func__, __LINE__, cm_node, | ||
1335 | cm_node->listener, cm_node->state); | ||
1336 | active_open_err(cm_node, skb, reset); | ||
1337 | break; | ||
1338 | /* For PASSIVE open states, remove the cm_node event */ | ||
1339 | case NES_CM_STATE_ESTABLISHED: | ||
1340 | case NES_CM_STATE_SYN_RCVD: | ||
1341 | case NES_CM_STATE_LISTENING: | ||
1342 | nes_debug(NES_DBG_CM, "Bad state %s[%u]\n", __func__, __LINE__); | ||
1343 | passive_open_err(cm_node, skb, reset); | ||
1344 | break; | ||
1345 | case NES_CM_STATE_TSA: | ||
1346 | default: | ||
1347 | break; | ||
1348 | } | ||
1349 | } | ||
1343 | 1350 | ||
1351 | static void handle_rcv_mpa(struct nes_cm_node *cm_node, struct sk_buff *skb, | ||
1352 | enum nes_cm_event_type type) | ||
1353 | { | ||
1354 | |||
1355 | int ret; | ||
1356 | int datasize = skb->len; | ||
1357 | u8 *dataloc = skb->data; | ||
1358 | ret = parse_mpa(cm_node, dataloc, datasize); | ||
1359 | if (ret < 0) { | ||
1360 | nes_debug(NES_DBG_CM, "didn't like MPA Request\n"); | ||
1361 | if (type == NES_CM_EVENT_CONNECTED) { | ||
1362 | nes_debug(NES_DBG_CM, "%s[%u] create abort for " | ||
1363 | "cm_node=%p listener=%p state=%d\n", __func__, | ||
1364 | __LINE__, cm_node, cm_node->listener, | ||
1365 | cm_node->state); | ||
1366 | active_open_err(cm_node, skb, 1); | ||
1367 | } else { | ||
1368 | passive_open_err(cm_node, skb, 1); | ||
1344 | } | 1369 | } |
1345 | return -1; | 1370 | } else { |
1371 | cleanup_retrans_entry(cm_node); | ||
1372 | dev_kfree_skb_any(skb); | ||
1373 | if (type == NES_CM_EVENT_CONNECTED) | ||
1374 | cm_node->state = NES_CM_STATE_TSA; | ||
1375 | create_event(cm_node, type); | ||
1376 | |||
1377 | } | ||
1378 | return ; | ||
1379 | } | ||
1380 | |||
1381 | static void indicate_pkt_err(struct nes_cm_node *cm_node, struct sk_buff *skb) | ||
1382 | { | ||
1383 | switch (cm_node->state) { | ||
1384 | case NES_CM_STATE_SYN_SENT: | ||
1385 | case NES_CM_STATE_MPAREQ_SENT: | ||
1386 | nes_debug(NES_DBG_CM, "%s[%u] create abort for cm_node=%p " | ||
1387 | "listener=%p state=%d\n", __func__, __LINE__, cm_node, | ||
1388 | cm_node->listener, cm_node->state); | ||
1389 | active_open_err(cm_node, skb, 1); | ||
1390 | break; | ||
1391 | case NES_CM_STATE_ESTABLISHED: | ||
1392 | case NES_CM_STATE_SYN_RCVD: | ||
1393 | passive_open_err(cm_node, skb, 1); | ||
1394 | break; | ||
1395 | case NES_CM_STATE_TSA: | ||
1396 | default: | ||
1397 | drop_packet(skb); | ||
1346 | } | 1398 | } |
1399 | } | ||
1400 | |||
1401 | static int check_syn(struct nes_cm_node *cm_node, struct tcphdr *tcph, | ||
1402 | struct sk_buff *skb) | ||
1403 | { | ||
1404 | int err; | ||
1405 | |||
1406 | err = ((ntohl(tcph->ack_seq) == cm_node->tcp_cntxt.loc_seq_num))? 0 : 1; | ||
1407 | if (err) | ||
1408 | active_open_err(cm_node, skb, 1); | ||
1409 | |||
1410 | return err; | ||
1411 | } | ||
1412 | |||
1413 | static int check_seq(struct nes_cm_node *cm_node, struct tcphdr *tcph, | ||
1414 | struct sk_buff *skb) | ||
1415 | { | ||
1416 | int err = 0; | ||
1417 | u32 seq; | ||
1418 | u32 ack_seq; | ||
1419 | u32 loc_seq_num = cm_node->tcp_cntxt.loc_seq_num; | ||
1420 | u32 rcv_nxt = cm_node->tcp_cntxt.rcv_nxt; | ||
1421 | u32 rcv_wnd; | ||
1422 | seq = ntohl(tcph->seq); | ||
1423 | ack_seq = ntohl(tcph->ack_seq); | ||
1424 | rcv_wnd = cm_node->tcp_cntxt.rcv_wnd; | ||
1425 | if (ack_seq != loc_seq_num) | ||
1426 | err = 1; | ||
1427 | else if ((seq + rcv_wnd) < rcv_nxt) | ||
1428 | err = 1; | ||
1429 | if (err) { | ||
1430 | nes_debug(NES_DBG_CM, "%s[%u] create abort for cm_node=%p " | ||
1431 | "listener=%p state=%d\n", __func__, __LINE__, cm_node, | ||
1432 | cm_node->listener, cm_node->state); | ||
1433 | indicate_pkt_err(cm_node, skb); | ||
1434 | nes_debug(NES_DBG_CM, "seq ERROR cm_node =%p seq=0x%08X " | ||
1435 | "rcv_nxt=0x%08X rcv_wnd=0x%x\n", cm_node, seq, rcv_nxt, | ||
1436 | rcv_wnd); | ||
1437 | } | ||
1438 | return err; | ||
1439 | } | ||
1440 | |||
1441 | /* | ||
1442 | * handle_syn_pkt() is for Passive node. The syn packet is received when a node | ||
1443 | * is created with a listener or it may comein as rexmitted packet which in | ||
1444 | * that case will be just dropped. | ||
1445 | */ | ||
1446 | |||
1447 | static void handle_syn_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | ||
1448 | struct tcphdr *tcph) | ||
1449 | { | ||
1450 | int ret; | ||
1451 | u32 inc_sequence; | ||
1452 | int optionsize; | ||
1347 | 1453 | ||
1348 | optionsize = (tcph->doff << 2) - sizeof(struct tcphdr); | 1454 | optionsize = (tcph->doff << 2) - sizeof(struct tcphdr); |
1455 | skb_pull(skb, tcph->doff << 2); | ||
1456 | inc_sequence = ntohl(tcph->seq); | ||
1349 | 1457 | ||
1350 | skb_pull(skb, ip_hdr(skb)->ihl << 2); | 1458 | switch (cm_node->state) { |
1459 | case NES_CM_STATE_SYN_SENT: | ||
1460 | case NES_CM_STATE_MPAREQ_SENT: | ||
1461 | /* Rcvd syn on active open connection*/ | ||
1462 | active_open_err(cm_node, skb, 1); | ||
1463 | break; | ||
1464 | case NES_CM_STATE_LISTENING: | ||
1465 | /* Passive OPEN */ | ||
1466 | cm_node->accept_pend = 1; | ||
1467 | atomic_inc(&cm_node->listener->pend_accepts_cnt); | ||
1468 | if (atomic_read(&cm_node->listener->pend_accepts_cnt) > | ||
1469 | cm_node->listener->backlog) { | ||
1470 | nes_debug(NES_DBG_CM, "drop syn due to backlog " | ||
1471 | "pressure \n"); | ||
1472 | cm_backlog_drops++; | ||
1473 | passive_open_err(cm_node, skb, 0); | ||
1474 | break; | ||
1475 | } | ||
1476 | ret = handle_tcp_options(cm_node, tcph, skb, optionsize, | ||
1477 | 1); | ||
1478 | if (ret) { | ||
1479 | passive_open_err(cm_node, skb, 0); | ||
1480 | /* drop pkt */ | ||
1481 | break; | ||
1482 | } | ||
1483 | cm_node->tcp_cntxt.rcv_nxt = inc_sequence + 1; | ||
1484 | BUG_ON(cm_node->send_entry); | ||
1485 | cm_node->state = NES_CM_STATE_SYN_RCVD; | ||
1486 | send_syn(cm_node, 1, skb); | ||
1487 | break; | ||
1488 | case NES_CM_STATE_TSA: | ||
1489 | case NES_CM_STATE_ESTABLISHED: | ||
1490 | case NES_CM_STATE_FIN_WAIT1: | ||
1491 | case NES_CM_STATE_FIN_WAIT2: | ||
1492 | case NES_CM_STATE_MPAREQ_RCVD: | ||
1493 | case NES_CM_STATE_LAST_ACK: | ||
1494 | case NES_CM_STATE_CLOSING: | ||
1495 | case NES_CM_STATE_UNKNOWN: | ||
1496 | case NES_CM_STATE_CLOSED: | ||
1497 | default: | ||
1498 | drop_packet(skb); | ||
1499 | break; | ||
1500 | } | ||
1501 | } | ||
1502 | |||
1503 | static void handle_synack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | ||
1504 | struct tcphdr *tcph) | ||
1505 | { | ||
1506 | |||
1507 | int ret; | ||
1508 | u32 inc_sequence; | ||
1509 | int optionsize; | ||
1510 | |||
1511 | optionsize = (tcph->doff << 2) - sizeof(struct tcphdr); | ||
1351 | skb_pull(skb, tcph->doff << 2); | 1512 | skb_pull(skb, tcph->doff << 2); |
1513 | inc_sequence = ntohl(tcph->seq); | ||
1514 | switch (cm_node->state) { | ||
1515 | case NES_CM_STATE_SYN_SENT: | ||
1516 | /* active open */ | ||
1517 | if (check_syn(cm_node, tcph, skb)) | ||
1518 | return; | ||
1519 | cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq); | ||
1520 | /* setup options */ | ||
1521 | ret = handle_tcp_options(cm_node, tcph, skb, optionsize, 0); | ||
1522 | if (ret) { | ||
1523 | nes_debug(NES_DBG_CM, "cm_node=%p tcp_options failed\n", | ||
1524 | cm_node); | ||
1525 | break; | ||
1526 | } | ||
1527 | cleanup_retrans_entry(cm_node); | ||
1528 | cm_node->tcp_cntxt.rcv_nxt = inc_sequence + 1; | ||
1529 | send_mpa_request(cm_node, skb); | ||
1530 | cm_node->state = NES_CM_STATE_MPAREQ_SENT; | ||
1531 | break; | ||
1532 | case NES_CM_STATE_MPAREQ_RCVD: | ||
1533 | /* passive open, so should not be here */ | ||
1534 | passive_open_err(cm_node, skb, 1); | ||
1535 | break; | ||
1536 | case NES_CM_STATE_ESTABLISHED: | ||
1537 | case NES_CM_STATE_FIN_WAIT1: | ||
1538 | case NES_CM_STATE_FIN_WAIT2: | ||
1539 | case NES_CM_STATE_LAST_ACK: | ||
1540 | case NES_CM_STATE_TSA: | ||
1541 | case NES_CM_STATE_CLOSING: | ||
1542 | case NES_CM_STATE_UNKNOWN: | ||
1543 | case NES_CM_STATE_CLOSED: | ||
1544 | case NES_CM_STATE_MPAREQ_SENT: | ||
1545 | default: | ||
1546 | drop_packet(skb); | ||
1547 | break; | ||
1548 | } | ||
1549 | } | ||
1352 | 1550 | ||
1353 | datasize = skb->len; | 1551 | static void handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, |
1552 | struct tcphdr *tcph) | ||
1553 | { | ||
1554 | int datasize = 0; | ||
1555 | u32 inc_sequence; | ||
1556 | u32 rem_seq_ack; | ||
1557 | u32 rem_seq; | ||
1558 | if (check_seq(cm_node, tcph, skb)) | ||
1559 | return; | ||
1560 | |||
1561 | skb_pull(skb, tcph->doff << 2); | ||
1354 | inc_sequence = ntohl(tcph->seq); | 1562 | inc_sequence = ntohl(tcph->seq); |
1355 | nes_debug(NES_DBG_CM, "datasize = %u, sequence = 0x%08X, ack_seq = 0x%08X," | 1563 | rem_seq = ntohl(tcph->seq); |
1356 | " rcv_nxt = 0x%08X Flags: %s %s.\n", | 1564 | rem_seq_ack = ntohl(tcph->ack_seq); |
1357 | datasize, inc_sequence, ntohl(tcph->ack_seq), | 1565 | datasize = skb->len; |
1358 | cm_node->tcp_cntxt.rcv_nxt, (tcph->syn ? "SYN":""), | 1566 | |
1359 | (tcph->ack ? "ACK":"")); | 1567 | switch (cm_node->state) { |
1360 | 1568 | case NES_CM_STATE_SYN_RCVD: | |
1361 | if (!tcph->syn && (inc_sequence != cm_node->tcp_cntxt.rcv_nxt) | 1569 | /* Passive OPEN */ |
1362 | ) { | 1570 | cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq); |
1363 | nes_debug(NES_DBG_CM, "dropping packet, datasize = %u, sequence = 0x%08X," | 1571 | cm_node->state = NES_CM_STATE_ESTABLISHED; |
1364 | " ack_seq = 0x%08X, rcv_nxt = 0x%08X Flags: %s.\n", | 1572 | if (datasize) { |
1365 | datasize, inc_sequence, ntohl(tcph->ack_seq), | 1573 | cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize; |
1366 | cm_node->tcp_cntxt.rcv_nxt, (tcph->ack ? "ACK":"")); | 1574 | cm_node->state = NES_CM_STATE_MPAREQ_RCVD; |
1367 | if (cm_node->state == NES_CM_STATE_LISTENING) { | 1575 | handle_rcv_mpa(cm_node, skb, NES_CM_EVENT_MPA_REQ); |
1368 | rem_ref_cm_node(cm_core, cm_node); | 1576 | } else { /* rcvd ACK only */ |
1577 | dev_kfree_skb_any(skb); | ||
1578 | cleanup_retrans_entry(cm_node); | ||
1579 | } | ||
1580 | break; | ||
1581 | case NES_CM_STATE_ESTABLISHED: | ||
1582 | /* Passive OPEN */ | ||
1583 | /* We expect mpa frame to be received only */ | ||
1584 | if (datasize) { | ||
1585 | cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize; | ||
1586 | cm_node->state = NES_CM_STATE_MPAREQ_RCVD; | ||
1587 | handle_rcv_mpa(cm_node, skb, | ||
1588 | NES_CM_EVENT_MPA_REQ); | ||
1589 | } else | ||
1590 | drop_packet(skb); | ||
1591 | break; | ||
1592 | case NES_CM_STATE_MPAREQ_SENT: | ||
1593 | cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq); | ||
1594 | if (datasize) { | ||
1595 | cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize; | ||
1596 | handle_rcv_mpa(cm_node, skb, NES_CM_EVENT_CONNECTED); | ||
1597 | } else { /* Could be just an ack pkt.. */ | ||
1598 | cleanup_retrans_entry(cm_node); | ||
1599 | dev_kfree_skb_any(skb); | ||
1369 | } | 1600 | } |
1370 | return -1; | 1601 | break; |
1602 | case NES_CM_STATE_FIN_WAIT1: | ||
1603 | case NES_CM_STATE_SYN_SENT: | ||
1604 | case NES_CM_STATE_FIN_WAIT2: | ||
1605 | case NES_CM_STATE_TSA: | ||
1606 | case NES_CM_STATE_CLOSED: | ||
1607 | case NES_CM_STATE_MPAREQ_RCVD: | ||
1608 | case NES_CM_STATE_LAST_ACK: | ||
1609 | case NES_CM_STATE_CLOSING: | ||
1610 | case NES_CM_STATE_UNKNOWN: | ||
1611 | default: | ||
1612 | drop_packet(skb); | ||
1613 | break; | ||
1371 | } | 1614 | } |
1615 | } | ||
1372 | 1616 | ||
1373 | cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize; | ||
1374 | 1617 | ||
1375 | 1618 | ||
1619 | static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph, | ||
1620 | struct sk_buff *skb, int optionsize, int passive) | ||
1621 | { | ||
1622 | u8 *optionsloc = (u8 *)&tcph[1]; | ||
1376 | if (optionsize) { | 1623 | if (optionsize) { |
1377 | u8 *optionsloc = (u8 *)&tcph[1]; | 1624 | if (process_options(cm_node, optionsloc, optionsize, |
1378 | if (process_options(cm_node, optionsloc, optionsize, (u32)tcph->syn)) { | 1625 | (u32)tcph->syn)) { |
1379 | nes_debug(NES_DBG_CM, "%s: Node %p, Sending RESET\n", __func__, cm_node); | 1626 | nes_debug(NES_DBG_CM, "%s: Node %p, Sending RESET\n", |
1380 | send_reset(cm_node); | 1627 | __func__, cm_node); |
1381 | if (cm_node->state != NES_CM_STATE_SYN_SENT) | 1628 | if (passive) |
1382 | rem_ref_cm_node(cm_core, cm_node); | 1629 | passive_open_err(cm_node, skb, 0); |
1383 | return 0; | 1630 | else |
1631 | active_open_err(cm_node, skb, 0); | ||
1632 | return 1; | ||
1384 | } | 1633 | } |
1385 | } else if (tcph->syn) | 1634 | } |
1386 | cm_node->tcp_cntxt.mss = NES_CM_DEFAULT_MSS; | ||
1387 | 1635 | ||
1388 | cm_node->tcp_cntxt.snd_wnd = ntohs(tcph->window) << | 1636 | cm_node->tcp_cntxt.snd_wnd = ntohs(tcph->window) << |
1389 | cm_node->tcp_cntxt.snd_wscale; | 1637 | cm_node->tcp_cntxt.snd_wscale; |
1390 | 1638 | ||
1391 | if (cm_node->tcp_cntxt.snd_wnd > cm_node->tcp_cntxt.max_snd_wnd) { | 1639 | if (cm_node->tcp_cntxt.snd_wnd > cm_node->tcp_cntxt.max_snd_wnd) |
1392 | cm_node->tcp_cntxt.max_snd_wnd = cm_node->tcp_cntxt.snd_wnd; | 1640 | cm_node->tcp_cntxt.max_snd_wnd = cm_node->tcp_cntxt.snd_wnd; |
1393 | } | 1641 | return 0; |
1642 | } | ||
1394 | 1643 | ||
1395 | if (tcph->ack) { | 1644 | /* |
1396 | cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq); | 1645 | * active_open_err() will send reset() if flag set.. |
1397 | switch (cm_node->state) { | 1646 | * It will also send ABORT event. |
1398 | case NES_CM_STATE_SYN_RCVD: | 1647 | */ |
1399 | case NES_CM_STATE_SYN_SENT: | ||
1400 | /* read and stash current sequence number */ | ||
1401 | if (cm_node->tcp_cntxt.rem_ack_num != cm_node->tcp_cntxt.loc_seq_num) { | ||
1402 | nes_debug(NES_DBG_CM, "ERROR - cm_node->tcp_cntxt.rem_ack_num !=" | ||
1403 | " cm_node->tcp_cntxt.loc_seq_num\n"); | ||
1404 | send_reset(cm_node); | ||
1405 | return 0; | ||
1406 | } | ||
1407 | if (cm_node->state == NES_CM_STATE_SYN_SENT) | ||
1408 | cm_node->state = NES_CM_STATE_ONE_SIDE_ESTABLISHED; | ||
1409 | else { | ||
1410 | cm_node->state = NES_CM_STATE_ESTABLISHED; | ||
1411 | } | ||
1412 | break; | ||
1413 | case NES_CM_STATE_LAST_ACK: | ||
1414 | cm_node->state = NES_CM_STATE_CLOSED; | ||
1415 | break; | ||
1416 | case NES_CM_STATE_FIN_WAIT1: | ||
1417 | cm_node->state = NES_CM_STATE_FIN_WAIT2; | ||
1418 | break; | ||
1419 | case NES_CM_STATE_CLOSING: | ||
1420 | cm_node->state = NES_CM_STATE_TIME_WAIT; | ||
1421 | /* need to schedule this to happen in 2MSL timeouts */ | ||
1422 | cm_node->state = NES_CM_STATE_CLOSED; | ||
1423 | break; | ||
1424 | case NES_CM_STATE_ONE_SIDE_ESTABLISHED: | ||
1425 | case NES_CM_STATE_ESTABLISHED: | ||
1426 | case NES_CM_STATE_MPAREQ_SENT: | ||
1427 | case NES_CM_STATE_CLOSE_WAIT: | ||
1428 | case NES_CM_STATE_TIME_WAIT: | ||
1429 | case NES_CM_STATE_CLOSED: | ||
1430 | break; | ||
1431 | case NES_CM_STATE_LISTENING: | ||
1432 | nes_debug(NES_DBG_CM, "Received an ACK on a listening port (SYN %d)\n", tcph->syn); | ||
1433 | cm_node->tcp_cntxt.loc_seq_num = ntohl(tcph->ack_seq); | ||
1434 | send_reset(cm_node); | ||
1435 | /* send_reset bumps refcount, this should have been a new node */ | ||
1436 | rem_ref_cm_node(cm_core, cm_node); | ||
1437 | return -1; | ||
1438 | break; | ||
1439 | case NES_CM_STATE_TSA: | ||
1440 | nes_debug(NES_DBG_CM, "Received a packet with the ack bit set while in TSA state\n"); | ||
1441 | break; | ||
1442 | case NES_CM_STATE_UNKNOWN: | ||
1443 | case NES_CM_STATE_INITED: | ||
1444 | case NES_CM_STATE_ACCEPTING: | ||
1445 | case NES_CM_STATE_FIN_WAIT2: | ||
1446 | default: | ||
1447 | nes_debug(NES_DBG_CM, "Received ack from unknown state: %x\n", | ||
1448 | cm_node->state); | ||
1449 | send_reset(cm_node); | ||
1450 | break; | ||
1451 | } | ||
1452 | } | ||
1453 | 1648 | ||
1454 | if (tcph->syn) { | 1649 | static void active_open_err(struct nes_cm_node *cm_node, struct sk_buff *skb, |
1455 | if (cm_node->state == NES_CM_STATE_LISTENING) { | 1650 | int reset) |
1456 | /* do not exceed backlog */ | 1651 | { |
1457 | atomic_inc(&cm_node->listener->pend_accepts_cnt); | 1652 | cleanup_retrans_entry(cm_node); |
1458 | if (atomic_read(&cm_node->listener->pend_accepts_cnt) > | 1653 | if (reset) { |
1459 | cm_node->listener->backlog) { | 1654 | nes_debug(NES_DBG_CM, "ERROR active err called for cm_node=%p, " |
1460 | nes_debug(NES_DBG_CM, "drop syn due to backlog pressure \n"); | 1655 | "state=%d\n", cm_node, cm_node->state); |
1461 | cm_backlog_drops++; | 1656 | add_ref_cm_node(cm_node); |
1462 | atomic_dec(&cm_node->listener->pend_accepts_cnt); | 1657 | send_reset(cm_node, skb); |
1463 | rem_ref_cm_node(cm_core, cm_node); | 1658 | } else |
1464 | return 0; | 1659 | dev_kfree_skb_any(skb); |
1465 | } | ||
1466 | cm_node->accept_pend = 1; | ||
1467 | 1660 | ||
1468 | } | 1661 | cm_node->state = NES_CM_STATE_CLOSED; |
1469 | if (datasize == 0) | 1662 | create_event(cm_node, NES_CM_EVENT_ABORTED); |
1470 | cm_node->tcp_cntxt.rcv_nxt ++; | 1663 | } |
1471 | 1664 | ||
1472 | if (cm_node->state == NES_CM_STATE_LISTENING) { | 1665 | /* |
1473 | cm_node->state = NES_CM_STATE_SYN_RCVD; | 1666 | * passive_open_err() will either do a reset() or will free up the skb and |
1474 | send_syn(cm_node, 1); | 1667 | * remove the cm_node. |
1475 | } | 1668 | */ |
1476 | if (cm_node->state == NES_CM_STATE_ONE_SIDE_ESTABLISHED) { | ||
1477 | cm_node->state = NES_CM_STATE_ESTABLISHED; | ||
1478 | /* send final handshake ACK */ | ||
1479 | ret = send_ack(cm_node); | ||
1480 | if (ret < 0) | ||
1481 | return ret; | ||
1482 | 1669 | ||
1483 | cm_node->state = NES_CM_STATE_MPAREQ_SENT; | 1670 | static void passive_open_err(struct nes_cm_node *cm_node, struct sk_buff *skb, |
1484 | ret = send_mpa_request(cm_node); | 1671 | int reset) |
1485 | if (ret < 0) | 1672 | { |
1486 | return ret; | 1673 | cleanup_retrans_entry(cm_node); |
1487 | } | 1674 | cm_node->state = NES_CM_STATE_CLOSED; |
1675 | if (reset) { | ||
1676 | nes_debug(NES_DBG_CM, "passive_open_err sending RST for " | ||
1677 | "cm_node=%p state =%d\n", cm_node, cm_node->state); | ||
1678 | send_reset(cm_node, skb); | ||
1679 | } else { | ||
1680 | dev_kfree_skb_any(skb); | ||
1681 | rem_ref_cm_node(cm_node->cm_core, cm_node); | ||
1488 | } | 1682 | } |
1683 | } | ||
1489 | 1684 | ||
1490 | if (tcph->fin) { | 1685 | /* |
1491 | cm_node->tcp_cntxt.rcv_nxt++; | 1686 | * free_retrans_entry() routines assumes that the retrans_list_lock has |
1492 | switch (cm_node->state) { | 1687 | * been acquired before calling. |
1493 | case NES_CM_STATE_SYN_RCVD: | 1688 | */ |
1494 | case NES_CM_STATE_SYN_SENT: | 1689 | static void free_retrans_entry(struct nes_cm_node *cm_node) |
1495 | case NES_CM_STATE_ONE_SIDE_ESTABLISHED: | 1690 | { |
1496 | case NES_CM_STATE_ESTABLISHED: | 1691 | struct nes_timer_entry *send_entry; |
1497 | case NES_CM_STATE_ACCEPTING: | 1692 | send_entry = cm_node->send_entry; |
1498 | case NES_CM_STATE_MPAREQ_SENT: | 1693 | if (send_entry) { |
1499 | cm_node->state = NES_CM_STATE_CLOSE_WAIT; | 1694 | cm_node->send_entry = NULL; |
1500 | cm_node->state = NES_CM_STATE_LAST_ACK; | 1695 | dev_kfree_skb_any(send_entry->skb); |
1501 | ret = send_fin(cm_node, NULL); | 1696 | kfree(send_entry); |
1502 | break; | 1697 | rem_ref_cm_node(cm_node->cm_core, cm_node); |
1503 | case NES_CM_STATE_FIN_WAIT1: | ||
1504 | cm_node->state = NES_CM_STATE_CLOSING; | ||
1505 | ret = send_ack(cm_node); | ||
1506 | break; | ||
1507 | case NES_CM_STATE_FIN_WAIT2: | ||
1508 | cm_node->state = NES_CM_STATE_TIME_WAIT; | ||
1509 | cm_node->tcp_cntxt.loc_seq_num ++; | ||
1510 | ret = send_ack(cm_node); | ||
1511 | /* need to schedule this to happen in 2MSL timeouts */ | ||
1512 | cm_node->state = NES_CM_STATE_CLOSED; | ||
1513 | break; | ||
1514 | case NES_CM_STATE_CLOSE_WAIT: | ||
1515 | case NES_CM_STATE_LAST_ACK: | ||
1516 | case NES_CM_STATE_CLOSING: | ||
1517 | case NES_CM_STATE_TSA: | ||
1518 | default: | ||
1519 | nes_debug(NES_DBG_CM, "Received a fin while in %x state\n", | ||
1520 | cm_node->state); | ||
1521 | ret = -EINVAL; | ||
1522 | break; | ||
1523 | } | ||
1524 | } | 1698 | } |
1699 | } | ||
1525 | 1700 | ||
1526 | if (datasize) { | 1701 | static void cleanup_retrans_entry(struct nes_cm_node *cm_node) |
1527 | u8 *dataloc = skb->data; | 1702 | { |
1528 | /* figure out what state we are in and handle transition to next state */ | 1703 | unsigned long flags; |
1529 | switch (cm_node->state) { | ||
1530 | case NES_CM_STATE_LISTENING: | ||
1531 | case NES_CM_STATE_SYN_RCVD: | ||
1532 | case NES_CM_STATE_SYN_SENT: | ||
1533 | case NES_CM_STATE_FIN_WAIT1: | ||
1534 | case NES_CM_STATE_FIN_WAIT2: | ||
1535 | case NES_CM_STATE_CLOSE_WAIT: | ||
1536 | case NES_CM_STATE_LAST_ACK: | ||
1537 | case NES_CM_STATE_CLOSING: | ||
1538 | break; | ||
1539 | case NES_CM_STATE_MPAREQ_SENT: | ||
1540 | /* recv the mpa res frame, ret=frame len (incl priv data) */ | ||
1541 | ret = parse_mpa(cm_node, dataloc, datasize); | ||
1542 | if (ret < 0) | ||
1543 | break; | ||
1544 | /* set the req frame payload len in skb */ | ||
1545 | /* we are done handling this state, set node to a TSA state */ | ||
1546 | cm_node->state = NES_CM_STATE_TSA; | ||
1547 | send_ack(cm_node); | ||
1548 | create_event(cm_node, NES_CM_EVENT_CONNECTED); | ||
1549 | break; | ||
1550 | |||
1551 | case NES_CM_STATE_ESTABLISHED: | ||
1552 | /* we are expecting an MPA req frame */ | ||
1553 | ret = parse_mpa(cm_node, dataloc, datasize); | ||
1554 | if (ret < 0) { | ||
1555 | break; | ||
1556 | } | ||
1557 | cm_node->state = NES_CM_STATE_TSA; | ||
1558 | send_ack(cm_node); | ||
1559 | /* we got a valid MPA request, create an event */ | ||
1560 | create_event(cm_node, NES_CM_EVENT_MPA_REQ); | ||
1561 | break; | ||
1562 | case NES_CM_STATE_TSA: | ||
1563 | handle_exception_pkt(cm_node, skb); | ||
1564 | break; | ||
1565 | case NES_CM_STATE_UNKNOWN: | ||
1566 | case NES_CM_STATE_INITED: | ||
1567 | default: | ||
1568 | ret = -1; | ||
1569 | } | ||
1570 | } | ||
1571 | 1704 | ||
1572 | return ret; | 1705 | spin_lock_irqsave(&cm_node->retrans_list_lock, flags); |
1706 | free_retrans_entry(cm_node); | ||
1707 | spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags); | ||
1573 | } | 1708 | } |
1574 | 1709 | ||
1710 | /** | ||
1711 | * process_packet | ||
1712 | * Returns skb if to be freed, else it will return NULL if already used.. | ||
1713 | */ | ||
1714 | static void process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb, | ||
1715 | struct nes_cm_core *cm_core) | ||
1716 | { | ||
1717 | enum nes_tcpip_pkt_type pkt_type = NES_PKT_TYPE_UNKNOWN; | ||
1718 | struct tcphdr *tcph = tcp_hdr(skb); | ||
1719 | skb_pull(skb, ip_hdr(skb)->ihl << 2); | ||
1720 | |||
1721 | nes_debug(NES_DBG_CM, "process_packet: cm_node=%p state =%d syn=%d " | ||
1722 | "ack=%d rst=%d fin=%d\n", cm_node, cm_node->state, tcph->syn, | ||
1723 | tcph->ack, tcph->rst, tcph->fin); | ||
1724 | |||
1725 | if (tcph->rst) | ||
1726 | pkt_type = NES_PKT_TYPE_RST; | ||
1727 | else if (tcph->syn) { | ||
1728 | pkt_type = NES_PKT_TYPE_SYN; | ||
1729 | if (tcph->ack) | ||
1730 | pkt_type = NES_PKT_TYPE_SYNACK; | ||
1731 | } else if (tcph->fin) | ||
1732 | pkt_type = NES_PKT_TYPE_FIN; | ||
1733 | else if (tcph->ack) | ||
1734 | pkt_type = NES_PKT_TYPE_ACK; | ||
1735 | |||
1736 | switch (pkt_type) { | ||
1737 | case NES_PKT_TYPE_SYN: | ||
1738 | handle_syn_pkt(cm_node, skb, tcph); | ||
1739 | break; | ||
1740 | case NES_PKT_TYPE_SYNACK: | ||
1741 | handle_synack_pkt(cm_node, skb, tcph); | ||
1742 | break; | ||
1743 | case NES_PKT_TYPE_ACK: | ||
1744 | handle_ack_pkt(cm_node, skb, tcph); | ||
1745 | break; | ||
1746 | case NES_PKT_TYPE_RST: | ||
1747 | handle_rst_pkt(cm_node, skb, tcph); | ||
1748 | break; | ||
1749 | case NES_PKT_TYPE_FIN: | ||
1750 | handle_fin_pkt(cm_node, skb, tcph); | ||
1751 | break; | ||
1752 | default: | ||
1753 | drop_packet(skb); | ||
1754 | break; | ||
1755 | } | ||
1756 | } | ||
1575 | 1757 | ||
1576 | /** | 1758 | /** |
1577 | * mini_cm_listen - create a listen node with params | 1759 | * mini_cm_listen - create a listen node with params |
1578 | */ | 1760 | */ |
1579 | static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *cm_core, | 1761 | static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *cm_core, |
1580 | struct nes_vnic *nesvnic, struct nes_cm_info *cm_info) | 1762 | struct nes_vnic *nesvnic, struct nes_cm_info *cm_info) |
1581 | { | 1763 | { |
1582 | struct nes_cm_listener *listener; | 1764 | struct nes_cm_listener *listener; |
1583 | unsigned long flags; | 1765 | unsigned long flags; |
@@ -1644,37 +1826,36 @@ static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *cm_core, | |||
1644 | /** | 1826 | /** |
1645 | * mini_cm_connect - make a connection node with params | 1827 | * mini_cm_connect - make a connection node with params |
1646 | */ | 1828 | */ |
1647 | static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core, | 1829 | struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core, |
1648 | struct nes_vnic *nesvnic, | 1830 | struct nes_vnic *nesvnic, u16 private_data_len, |
1649 | struct ietf_mpa_frame *mpa_frame, | 1831 | void *private_data, struct nes_cm_info *cm_info) |
1650 | struct nes_cm_info *cm_info) | ||
1651 | { | 1832 | { |
1652 | int ret = 0; | 1833 | int ret = 0; |
1653 | struct nes_cm_node *cm_node; | 1834 | struct nes_cm_node *cm_node; |
1654 | struct nes_cm_listener *loopbackremotelistener; | 1835 | struct nes_cm_listener *loopbackremotelistener; |
1655 | struct nes_cm_node *loopbackremotenode; | 1836 | struct nes_cm_node *loopbackremotenode; |
1656 | struct nes_cm_info loopback_cm_info; | 1837 | struct nes_cm_info loopback_cm_info; |
1657 | 1838 | u16 mpa_frame_size = sizeof(struct ietf_mpa_frame) + private_data_len; | |
1658 | u16 mpa_frame_size = sizeof(struct ietf_mpa_frame) + | 1839 | struct ietf_mpa_frame *mpa_frame = NULL; |
1659 | ntohs(mpa_frame->priv_data_len); | ||
1660 | |||
1661 | cm_info->loc_addr = htonl(cm_info->loc_addr); | ||
1662 | cm_info->rem_addr = htonl(cm_info->rem_addr); | ||
1663 | cm_info->loc_port = htons(cm_info->loc_port); | ||
1664 | cm_info->rem_port = htons(cm_info->rem_port); | ||
1665 | 1840 | ||
1666 | /* create a CM connection node */ | 1841 | /* create a CM connection node */ |
1667 | cm_node = make_cm_node(cm_core, nesvnic, cm_info, NULL); | 1842 | cm_node = make_cm_node(cm_core, nesvnic, cm_info, NULL); |
1668 | if (!cm_node) | 1843 | if (!cm_node) |
1669 | return NULL; | 1844 | return NULL; |
1845 | mpa_frame = &cm_node->mpa_frame; | ||
1846 | strcpy(mpa_frame->key, IEFT_MPA_KEY_REQ); | ||
1847 | mpa_frame->flags = IETF_MPA_FLAGS_CRC; | ||
1848 | mpa_frame->rev = IETF_MPA_VERSION; | ||
1849 | mpa_frame->priv_data_len = htons(private_data_len); | ||
1670 | 1850 | ||
1671 | /* set our node side to client (active) side */ | 1851 | /* set our node side to client (active) side */ |
1672 | cm_node->tcp_cntxt.client = 1; | 1852 | cm_node->tcp_cntxt.client = 1; |
1673 | cm_node->tcp_cntxt.rcv_wscale = NES_CM_DEFAULT_RCV_WND_SCALE; | 1853 | cm_node->tcp_cntxt.rcv_wscale = NES_CM_DEFAULT_RCV_WND_SCALE; |
1674 | 1854 | ||
1675 | if (cm_info->loc_addr == cm_info->rem_addr) { | 1855 | if (cm_info->loc_addr == cm_info->rem_addr) { |
1676 | loopbackremotelistener = find_listener(cm_core, cm_node->rem_addr, | 1856 | loopbackremotelistener = find_listener(cm_core, |
1677 | cm_node->rem_port, NES_CM_LISTENER_ACTIVE_STATE); | 1857 | ntohl(nesvnic->local_ipaddr), cm_node->rem_port, |
1858 | NES_CM_LISTENER_ACTIVE_STATE); | ||
1678 | if (loopbackremotelistener == NULL) { | 1859 | if (loopbackremotelistener == NULL) { |
1679 | create_event(cm_node, NES_CM_EVENT_ABORTED); | 1860 | create_event(cm_node, NES_CM_EVENT_ABORTED); |
1680 | } else { | 1861 | } else { |
@@ -1683,26 +1864,35 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core, | |||
1683 | loopback_cm_info.loc_port = cm_info->rem_port; | 1864 | loopback_cm_info.loc_port = cm_info->rem_port; |
1684 | loopback_cm_info.rem_port = cm_info->loc_port; | 1865 | loopback_cm_info.rem_port = cm_info->loc_port; |
1685 | loopback_cm_info.cm_id = loopbackremotelistener->cm_id; | 1866 | loopback_cm_info.cm_id = loopbackremotelistener->cm_id; |
1686 | loopbackremotenode = make_cm_node(cm_core, nesvnic, &loopback_cm_info, | 1867 | loopbackremotenode = make_cm_node(cm_core, nesvnic, |
1687 | loopbackremotelistener); | 1868 | &loopback_cm_info, loopbackremotelistener); |
1688 | loopbackremotenode->loopbackpartner = cm_node; | 1869 | loopbackremotenode->loopbackpartner = cm_node; |
1689 | loopbackremotenode->tcp_cntxt.rcv_wscale = NES_CM_DEFAULT_RCV_WND_SCALE; | 1870 | loopbackremotenode->tcp_cntxt.rcv_wscale = |
1871 | NES_CM_DEFAULT_RCV_WND_SCALE; | ||
1690 | cm_node->loopbackpartner = loopbackremotenode; | 1872 | cm_node->loopbackpartner = loopbackremotenode; |
1691 | memcpy(loopbackremotenode->mpa_frame_buf, &mpa_frame->priv_data, | 1873 | memcpy(loopbackremotenode->mpa_frame_buf, private_data, |
1692 | mpa_frame_size); | 1874 | private_data_len); |
1693 | loopbackremotenode->mpa_frame_size = mpa_frame_size - | 1875 | loopbackremotenode->mpa_frame_size = private_data_len; |
1694 | sizeof(struct ietf_mpa_frame); | ||
1695 | 1876 | ||
1696 | /* we are done handling this state, set node to a TSA state */ | 1877 | /* we are done handling this state. */ |
1878 | /* set node to a TSA state */ | ||
1697 | cm_node->state = NES_CM_STATE_TSA; | 1879 | cm_node->state = NES_CM_STATE_TSA; |
1698 | cm_node->tcp_cntxt.rcv_nxt = loopbackremotenode->tcp_cntxt.loc_seq_num; | 1880 | cm_node->tcp_cntxt.rcv_nxt = |
1699 | loopbackremotenode->tcp_cntxt.rcv_nxt = cm_node->tcp_cntxt.loc_seq_num; | 1881 | loopbackremotenode->tcp_cntxt.loc_seq_num; |
1700 | cm_node->tcp_cntxt.max_snd_wnd = loopbackremotenode->tcp_cntxt.rcv_wnd; | 1882 | loopbackremotenode->tcp_cntxt.rcv_nxt = |
1701 | loopbackremotenode->tcp_cntxt.max_snd_wnd = cm_node->tcp_cntxt.rcv_wnd; | 1883 | cm_node->tcp_cntxt.loc_seq_num; |
1702 | cm_node->tcp_cntxt.snd_wnd = loopbackremotenode->tcp_cntxt.rcv_wnd; | 1884 | cm_node->tcp_cntxt.max_snd_wnd = |
1703 | loopbackremotenode->tcp_cntxt.snd_wnd = cm_node->tcp_cntxt.rcv_wnd; | 1885 | loopbackremotenode->tcp_cntxt.rcv_wnd; |
1704 | cm_node->tcp_cntxt.snd_wscale = loopbackremotenode->tcp_cntxt.rcv_wscale; | 1886 | loopbackremotenode->tcp_cntxt.max_snd_wnd = |
1705 | loopbackremotenode->tcp_cntxt.snd_wscale = cm_node->tcp_cntxt.rcv_wscale; | 1887 | cm_node->tcp_cntxt.rcv_wnd; |
1888 | cm_node->tcp_cntxt.snd_wnd = | ||
1889 | loopbackremotenode->tcp_cntxt.rcv_wnd; | ||
1890 | loopbackremotenode->tcp_cntxt.snd_wnd = | ||
1891 | cm_node->tcp_cntxt.rcv_wnd; | ||
1892 | cm_node->tcp_cntxt.snd_wscale = | ||
1893 | loopbackremotenode->tcp_cntxt.rcv_wscale; | ||
1894 | loopbackremotenode->tcp_cntxt.snd_wscale = | ||
1895 | cm_node->tcp_cntxt.rcv_wscale; | ||
1706 | 1896 | ||
1707 | create_event(loopbackremotenode, NES_CM_EVENT_MPA_REQ); | 1897 | create_event(loopbackremotenode, NES_CM_EVENT_MPA_REQ); |
1708 | } | 1898 | } |
@@ -1712,16 +1902,29 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core, | |||
1712 | /* set our node side to client (active) side */ | 1902 | /* set our node side to client (active) side */ |
1713 | cm_node->tcp_cntxt.client = 1; | 1903 | cm_node->tcp_cntxt.client = 1; |
1714 | /* init our MPA frame ptr */ | 1904 | /* init our MPA frame ptr */ |
1715 | memcpy(&cm_node->mpa_frame, mpa_frame, mpa_frame_size); | 1905 | memcpy(mpa_frame->priv_data, private_data, private_data_len); |
1906 | |||
1716 | cm_node->mpa_frame_size = mpa_frame_size; | 1907 | cm_node->mpa_frame_size = mpa_frame_size; |
1717 | 1908 | ||
1718 | /* send a syn and goto syn sent state */ | 1909 | /* send a syn and goto syn sent state */ |
1719 | cm_node->state = NES_CM_STATE_SYN_SENT; | 1910 | cm_node->state = NES_CM_STATE_SYN_SENT; |
1720 | ret = send_syn(cm_node, 0); | 1911 | ret = send_syn(cm_node, 0, NULL); |
1912 | |||
1913 | if (ret) { | ||
1914 | /* error in sending the syn free up the cm_node struct */ | ||
1915 | nes_debug(NES_DBG_CM, "Api - connect() FAILED: dest " | ||
1916 | "addr=0x%08X, port=0x%04x, cm_node=%p, cm_id = %p.\n", | ||
1917 | cm_node->rem_addr, cm_node->rem_port, cm_node, | ||
1918 | cm_node->cm_id); | ||
1919 | rem_ref_cm_node(cm_node->cm_core, cm_node); | ||
1920 | cm_node = NULL; | ||
1921 | } | ||
1721 | 1922 | ||
1722 | nes_debug(NES_DBG_CM, "Api - connect(): dest addr=0x%08X, port=0x%04x," | 1923 | if (cm_node) |
1723 | " cm_node=%p, cm_id = %p.\n", | 1924 | nes_debug(NES_DBG_CM, "Api - connect(): dest addr=0x%08X," |
1724 | cm_node->rem_addr, cm_node->rem_port, cm_node, cm_node->cm_id); | 1925 | "port=0x%04x, cm_node=%p, cm_id = %p.\n", |
1926 | cm_node->rem_addr, cm_node->rem_port, cm_node, | ||
1927 | cm_node->cm_id); | ||
1725 | 1928 | ||
1726 | return cm_node; | 1929 | return cm_node; |
1727 | } | 1930 | } |
@@ -1731,8 +1934,8 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core, | |||
1731 | * mini_cm_accept - accept a connection | 1934 | * mini_cm_accept - accept a connection |
1732 | * This function is never called | 1935 | * This function is never called |
1733 | */ | 1936 | */ |
1734 | static int mini_cm_accept(struct nes_cm_core *cm_core, struct ietf_mpa_frame *mpa_frame, | 1937 | static int mini_cm_accept(struct nes_cm_core *cm_core, |
1735 | struct nes_cm_node *cm_node) | 1938 | struct ietf_mpa_frame *mpa_frame, struct nes_cm_node *cm_node) |
1736 | { | 1939 | { |
1737 | return 0; | 1940 | return 0; |
1738 | } | 1941 | } |
@@ -1742,32 +1945,26 @@ static int mini_cm_accept(struct nes_cm_core *cm_core, struct ietf_mpa_frame *mp | |||
1742 | * mini_cm_reject - reject and teardown a connection | 1945 | * mini_cm_reject - reject and teardown a connection |
1743 | */ | 1946 | */ |
1744 | static int mini_cm_reject(struct nes_cm_core *cm_core, | 1947 | static int mini_cm_reject(struct nes_cm_core *cm_core, |
1745 | struct ietf_mpa_frame *mpa_frame, | 1948 | struct ietf_mpa_frame *mpa_frame, struct nes_cm_node *cm_node) |
1746 | struct nes_cm_node *cm_node) | ||
1747 | { | 1949 | { |
1748 | int ret = 0; | 1950 | int ret = 0; |
1749 | struct sk_buff *skb; | ||
1750 | u16 mpa_frame_size = sizeof(struct ietf_mpa_frame) + | ||
1751 | ntohs(mpa_frame->priv_data_len); | ||
1752 | 1951 | ||
1753 | skb = get_free_pkt(cm_node); | 1952 | nes_debug(NES_DBG_CM, "%s cm_node=%p type=%d state=%d\n", |
1754 | if (!skb) { | 1953 | __func__, cm_node, cm_node->tcp_cntxt.client, cm_node->state); |
1755 | nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n"); | ||
1756 | return -1; | ||
1757 | } | ||
1758 | |||
1759 | /* send an MPA Request frame */ | ||
1760 | form_cm_frame(skb, cm_node, NULL, 0, mpa_frame, mpa_frame_size, SET_ACK | SET_FIN); | ||
1761 | ret = schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 1, 0); | ||
1762 | 1954 | ||
1955 | if (cm_node->tcp_cntxt.client) | ||
1956 | return ret; | ||
1957 | cleanup_retrans_entry(cm_node); | ||
1763 | cm_node->state = NES_CM_STATE_CLOSED; | 1958 | cm_node->state = NES_CM_STATE_CLOSED; |
1764 | ret = send_fin(cm_node, NULL); | 1959 | ret = send_fin(cm_node, NULL); |
1765 | 1960 | ||
1766 | if (ret < 0) { | 1961 | if (cm_node->accept_pend) { |
1767 | printk(KERN_INFO PFX "failed to send MPA Reply (reject)\n"); | 1962 | BUG_ON(!cm_node->listener); |
1768 | return ret; | 1963 | atomic_dec(&cm_node->listener->pend_accepts_cnt); |
1964 | BUG_ON(atomic_read(&cm_node->listener->pend_accepts_cnt) < 0); | ||
1769 | } | 1965 | } |
1770 | 1966 | ||
1967 | ret = send_reset(cm_node, NULL); | ||
1771 | return ret; | 1968 | return ret; |
1772 | } | 1969 | } |
1773 | 1970 | ||
@@ -1783,35 +1980,39 @@ static int mini_cm_close(struct nes_cm_core *cm_core, struct nes_cm_node *cm_nod | |||
1783 | return -EINVAL; | 1980 | return -EINVAL; |
1784 | 1981 | ||
1785 | switch (cm_node->state) { | 1982 | switch (cm_node->state) { |
1786 | /* if passed in node is null, create a reference key node for node search */ | 1983 | case NES_CM_STATE_SYN_RCVD: |
1787 | /* check if we found an owner node for this pkt */ | 1984 | case NES_CM_STATE_SYN_SENT: |
1788 | case NES_CM_STATE_SYN_RCVD: | 1985 | case NES_CM_STATE_ONE_SIDE_ESTABLISHED: |
1789 | case NES_CM_STATE_SYN_SENT: | 1986 | case NES_CM_STATE_ESTABLISHED: |
1790 | case NES_CM_STATE_ONE_SIDE_ESTABLISHED: | 1987 | case NES_CM_STATE_ACCEPTING: |
1791 | case NES_CM_STATE_ESTABLISHED: | 1988 | case NES_CM_STATE_MPAREQ_SENT: |
1792 | case NES_CM_STATE_ACCEPTING: | 1989 | case NES_CM_STATE_MPAREQ_RCVD: |
1793 | case NES_CM_STATE_MPAREQ_SENT: | 1990 | cleanup_retrans_entry(cm_node); |
1794 | cm_node->state = NES_CM_STATE_FIN_WAIT1; | 1991 | send_reset(cm_node, NULL); |
1795 | send_fin(cm_node, NULL); | 1992 | break; |
1796 | break; | 1993 | case NES_CM_STATE_CLOSE_WAIT: |
1797 | case NES_CM_STATE_CLOSE_WAIT: | 1994 | cm_node->state = NES_CM_STATE_LAST_ACK; |
1798 | cm_node->state = NES_CM_STATE_LAST_ACK; | 1995 | send_fin(cm_node, NULL); |
1799 | send_fin(cm_node, NULL); | 1996 | break; |
1800 | break; | 1997 | case NES_CM_STATE_FIN_WAIT1: |
1801 | case NES_CM_STATE_FIN_WAIT1: | 1998 | case NES_CM_STATE_FIN_WAIT2: |
1802 | case NES_CM_STATE_FIN_WAIT2: | 1999 | case NES_CM_STATE_LAST_ACK: |
1803 | case NES_CM_STATE_LAST_ACK: | 2000 | case NES_CM_STATE_TIME_WAIT: |
1804 | case NES_CM_STATE_TIME_WAIT: | 2001 | case NES_CM_STATE_CLOSING: |
1805 | case NES_CM_STATE_CLOSING: | 2002 | ret = -1; |
1806 | ret = -1; | 2003 | break; |
1807 | break; | 2004 | case NES_CM_STATE_LISTENING: |
1808 | case NES_CM_STATE_LISTENING: | 2005 | case NES_CM_STATE_UNKNOWN: |
1809 | case NES_CM_STATE_UNKNOWN: | 2006 | case NES_CM_STATE_INITED: |
1810 | case NES_CM_STATE_INITED: | 2007 | case NES_CM_STATE_CLOSED: |
1811 | case NES_CM_STATE_CLOSED: | 2008 | ret = rem_ref_cm_node(cm_core, cm_node); |
1812 | case NES_CM_STATE_TSA: | 2009 | break; |
1813 | ret = rem_ref_cm_node(cm_core, cm_node); | 2010 | case NES_CM_STATE_TSA: |
1814 | break; | 2011 | if (cm_node->send_entry) |
2012 | printk(KERN_ERR "ERROR Close got called from STATE_TSA " | ||
2013 | "send_entry=%p\n", cm_node->send_entry); | ||
2014 | ret = rem_ref_cm_node(cm_core, cm_node); | ||
2015 | break; | ||
1815 | } | 2016 | } |
1816 | cm_node->cm_id = NULL; | 2017 | cm_node->cm_id = NULL; |
1817 | return ret; | 2018 | return ret; |
@@ -1822,25 +2023,30 @@ static int mini_cm_close(struct nes_cm_core *cm_core, struct nes_cm_node *cm_nod | |||
1822 | * recv_pkt - recv an ETHERNET packet, and process it through CM | 2023 | * recv_pkt - recv an ETHERNET packet, and process it through CM |
1823 | * node state machine | 2024 | * node state machine |
1824 | */ | 2025 | */ |
1825 | static int mini_cm_recv_pkt(struct nes_cm_core *cm_core, struct nes_vnic *nesvnic, | 2026 | static void mini_cm_recv_pkt(struct nes_cm_core *cm_core, |
1826 | struct sk_buff *skb) | 2027 | struct nes_vnic *nesvnic, struct sk_buff *skb) |
1827 | { | 2028 | { |
1828 | struct nes_cm_node *cm_node = NULL; | 2029 | struct nes_cm_node *cm_node = NULL; |
1829 | struct nes_cm_listener *listener = NULL; | 2030 | struct nes_cm_listener *listener = NULL; |
1830 | struct iphdr *iph; | 2031 | struct iphdr *iph; |
1831 | struct tcphdr *tcph; | 2032 | struct tcphdr *tcph; |
1832 | struct nes_cm_info nfo; | 2033 | struct nes_cm_info nfo; |
1833 | int ret = 0; | ||
1834 | 2034 | ||
1835 | if (!skb || skb->len < sizeof(struct iphdr) + sizeof(struct tcphdr)) { | 2035 | if (!skb) |
1836 | ret = -EINVAL; | 2036 | return; |
1837 | goto out; | 2037 | if (skb->len < sizeof(struct iphdr) + sizeof(struct tcphdr)) { |
2038 | dev_kfree_skb_any(skb); | ||
2039 | return; | ||
1838 | } | 2040 | } |
1839 | 2041 | ||
1840 | iph = (struct iphdr *)skb->data; | 2042 | iph = (struct iphdr *)skb->data; |
1841 | tcph = (struct tcphdr *)(skb->data + sizeof(struct iphdr)); | 2043 | tcph = (struct tcphdr *)(skb->data + sizeof(struct iphdr)); |
1842 | skb_reset_network_header(skb); | 2044 | skb_reset_network_header(skb); |
1843 | skb_set_transport_header(skb, sizeof(*tcph)); | 2045 | skb_set_transport_header(skb, sizeof(*tcph)); |
2046 | if (!tcph) { | ||
2047 | dev_kfree_skb_any(skb); | ||
2048 | return; | ||
2049 | } | ||
1844 | skb->len = ntohs(iph->tot_len); | 2050 | skb->len = ntohs(iph->tot_len); |
1845 | 2051 | ||
1846 | nfo.loc_addr = ntohl(iph->daddr); | 2052 | nfo.loc_addr = ntohl(iph->daddr); |
@@ -1853,61 +2059,60 @@ static int mini_cm_recv_pkt(struct nes_cm_core *cm_core, struct nes_vnic *nesvni | |||
1853 | NIPQUAD(iph->daddr), tcph->dest, | 2059 | NIPQUAD(iph->daddr), tcph->dest, |
1854 | NIPQUAD(iph->saddr), tcph->source); | 2060 | NIPQUAD(iph->saddr), tcph->source); |
1855 | 2061 | ||
1856 | /* note: this call is going to increment cm_node ref count */ | 2062 | do { |
1857 | cm_node = find_node(cm_core, | 2063 | cm_node = find_node(cm_core, |
1858 | nfo.rem_port, nfo.rem_addr, | 2064 | nfo.rem_port, nfo.rem_addr, |
1859 | nfo.loc_port, nfo.loc_addr); | 2065 | nfo.loc_port, nfo.loc_addr); |
1860 | 2066 | ||
1861 | if (!cm_node) { | ||
1862 | listener = find_listener(cm_core, nfo.loc_addr, nfo.loc_port, | ||
1863 | NES_CM_LISTENER_ACTIVE_STATE); | ||
1864 | if (listener) { | ||
1865 | nfo.cm_id = listener->cm_id; | ||
1866 | nfo.conn_type = listener->conn_type; | ||
1867 | } else { | ||
1868 | nfo.cm_id = NULL; | ||
1869 | nfo.conn_type = 0; | ||
1870 | } | ||
1871 | |||
1872 | cm_node = make_cm_node(cm_core, nesvnic, &nfo, listener); | ||
1873 | if (!cm_node) { | 2067 | if (!cm_node) { |
1874 | nes_debug(NES_DBG_CM, "Unable to allocate node\n"); | 2068 | /* Only type of packet accepted are for */ |
2069 | /* the PASSIVE open (syn only) */ | ||
2070 | if ((!tcph->syn) || (tcph->ack)) { | ||
2071 | cm_packets_dropped++; | ||
2072 | break; | ||
2073 | } | ||
2074 | listener = find_listener(cm_core, nfo.loc_addr, | ||
2075 | nfo.loc_port, | ||
2076 | NES_CM_LISTENER_ACTIVE_STATE); | ||
1875 | if (listener) { | 2077 | if (listener) { |
1876 | nes_debug(NES_DBG_CM, "unable to allocate node and decrementing listener refcount\n"); | 2078 | nfo.cm_id = listener->cm_id; |
2079 | nfo.conn_type = listener->conn_type; | ||
2080 | } else { | ||
2081 | nes_debug(NES_DBG_CM, "Unable to find listener " | ||
2082 | "for the pkt\n"); | ||
2083 | cm_packets_dropped++; | ||
2084 | dev_kfree_skb_any(skb); | ||
2085 | break; | ||
2086 | } | ||
2087 | |||
2088 | cm_node = make_cm_node(cm_core, nesvnic, &nfo, | ||
2089 | listener); | ||
2090 | if (!cm_node) { | ||
2091 | nes_debug(NES_DBG_CM, "Unable to allocate " | ||
2092 | "node\n"); | ||
2093 | cm_packets_dropped++; | ||
1877 | atomic_dec(&listener->ref_count); | 2094 | atomic_dec(&listener->ref_count); |
2095 | dev_kfree_skb_any(skb); | ||
2096 | break; | ||
1878 | } | 2097 | } |
1879 | ret = -1; | 2098 | if (!tcph->rst && !tcph->fin) { |
1880 | goto out; | 2099 | cm_node->state = NES_CM_STATE_LISTENING; |
1881 | } | 2100 | } else { |
1882 | if (!listener) { | 2101 | cm_packets_dropped++; |
1883 | nes_debug(NES_DBG_CM, "Packet found for unknown port %x refcnt=%d\n", | 2102 | rem_ref_cm_node(cm_core, cm_node); |
1884 | nfo.loc_port, atomic_read(&cm_node->ref_count)); | 2103 | dev_kfree_skb_any(skb); |
1885 | if (!tcph->rst) { | 2104 | break; |
1886 | nes_debug(NES_DBG_CM, "Packet found for unknown port=%d" | ||
1887 | " rem_port=%d refcnt=%d\n", | ||
1888 | nfo.loc_port, nfo.rem_port, atomic_read(&cm_node->ref_count)); | ||
1889 | |||
1890 | cm_node->tcp_cntxt.rcv_nxt = ntohl(tcph->seq); | ||
1891 | cm_node->tcp_cntxt.loc_seq_num = ntohl(tcph->ack_seq); | ||
1892 | send_reset(cm_node); | ||
1893 | } | 2105 | } |
2106 | add_ref_cm_node(cm_node); | ||
2107 | } else if (cm_node->state == NES_CM_STATE_TSA) { | ||
1894 | rem_ref_cm_node(cm_core, cm_node); | 2108 | rem_ref_cm_node(cm_core, cm_node); |
1895 | ret = -1; | 2109 | atomic_inc(&cm_accel_dropped_pkts); |
1896 | goto out; | 2110 | dev_kfree_skb_any(skb); |
2111 | break; | ||
1897 | } | 2112 | } |
1898 | add_ref_cm_node(cm_node); | 2113 | process_packet(cm_node, skb, cm_core); |
1899 | cm_node->state = NES_CM_STATE_LISTENING; | 2114 | rem_ref_cm_node(cm_core, cm_node); |
1900 | } | 2115 | } while (0); |
1901 | |||
1902 | nes_debug(NES_DBG_CM, "Processing Packet for node %p, data = (%p):\n", | ||
1903 | cm_node, skb->data); | ||
1904 | process_packet(cm_node, skb, cm_core); | ||
1905 | |||
1906 | rem_ref_cm_node(cm_core, cm_node); | ||
1907 | out: | ||
1908 | if (skb) | ||
1909 | dev_kfree_skb_any(skb); | ||
1910 | return ret; | ||
1911 | } | 2116 | } |
1912 | 2117 | ||
1913 | 2118 | ||
@@ -2107,15 +2312,12 @@ int nes_cm_disconn(struct nes_qp *nesqp) | |||
2107 | if (nesqp->disconn_pending == 0) { | 2312 | if (nesqp->disconn_pending == 0) { |
2108 | nesqp->disconn_pending++; | 2313 | nesqp->disconn_pending++; |
2109 | spin_unlock_irqrestore(&nesqp->lock, flags); | 2314 | spin_unlock_irqrestore(&nesqp->lock, flags); |
2110 | /* nes_add_ref(&nesqp->ibqp); */ | ||
2111 | /* init our disconnect work element, to */ | 2315 | /* init our disconnect work element, to */ |
2112 | INIT_WORK(&nesqp->disconn_work, nes_disconnect_worker); | 2316 | INIT_WORK(&nesqp->disconn_work, nes_disconnect_worker); |
2113 | 2317 | ||
2114 | queue_work(g_cm_core->disconn_wq, &nesqp->disconn_work); | 2318 | queue_work(g_cm_core->disconn_wq, &nesqp->disconn_work); |
2115 | } else { | 2319 | } else |
2116 | spin_unlock_irqrestore(&nesqp->lock, flags); | 2320 | spin_unlock_irqrestore(&nesqp->lock, flags); |
2117 | nes_rem_ref(&nesqp->ibqp); | ||
2118 | } | ||
2119 | 2321 | ||
2120 | return 0; | 2322 | return 0; |
2121 | } | 2323 | } |
@@ -2161,7 +2363,6 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp) | |||
2161 | nes_debug(NES_DBG_CM, "QP%u disconnect_worker cmid is NULL\n", | 2363 | nes_debug(NES_DBG_CM, "QP%u disconnect_worker cmid is NULL\n", |
2162 | nesqp->hwqp.qp_id); | 2364 | nesqp->hwqp.qp_id); |
2163 | spin_unlock_irqrestore(&nesqp->lock, flags); | 2365 | spin_unlock_irqrestore(&nesqp->lock, flags); |
2164 | nes_rem_ref(&nesqp->ibqp); | ||
2165 | return -1; | 2366 | return -1; |
2166 | } | 2367 | } |
2167 | 2368 | ||
@@ -2182,30 +2383,31 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp) | |||
2182 | atomic_inc(&cm_disconnects); | 2383 | atomic_inc(&cm_disconnects); |
2183 | cm_event.event = IW_CM_EVENT_DISCONNECT; | 2384 | cm_event.event = IW_CM_EVENT_DISCONNECT; |
2184 | if (last_ae == NES_AEQE_AEID_LLP_CONNECTION_RESET) { | 2385 | if (last_ae == NES_AEQE_AEID_LLP_CONNECTION_RESET) { |
2185 | issued_disconnect_reset = 1; | ||
2186 | cm_event.status = IW_CM_EVENT_STATUS_RESET; | 2386 | cm_event.status = IW_CM_EVENT_STATUS_RESET; |
2187 | nes_debug(NES_DBG_CM, "Generating a CM Disconnect Event (status reset) for " | 2387 | nes_debug(NES_DBG_CM, "Generating a CM " |
2188 | " QP%u, cm_id = %p. \n", | 2388 | "Disconnect Event (status reset) for " |
2189 | nesqp->hwqp.qp_id, cm_id); | 2389 | "QP%u, cm_id = %p. \n", |
2190 | } else { | 2390 | nesqp->hwqp.qp_id, cm_id); |
2391 | } else | ||
2191 | cm_event.status = IW_CM_EVENT_STATUS_OK; | 2392 | cm_event.status = IW_CM_EVENT_STATUS_OK; |
2192 | } | ||
2193 | 2393 | ||
2194 | cm_event.local_addr = cm_id->local_addr; | 2394 | cm_event.local_addr = cm_id->local_addr; |
2195 | cm_event.remote_addr = cm_id->remote_addr; | 2395 | cm_event.remote_addr = cm_id->remote_addr; |
2196 | cm_event.private_data = NULL; | 2396 | cm_event.private_data = NULL; |
2197 | cm_event.private_data_len = 0; | 2397 | cm_event.private_data_len = 0; |
2198 | 2398 | ||
2199 | nes_debug(NES_DBG_CM, "Generating a CM Disconnect Event for " | 2399 | nes_debug(NES_DBG_CM, "Generating a CM Disconnect Event" |
2200 | " QP%u, SQ Head = %u, SQ Tail = %u. cm_id = %p, refcount = %u.\n", | 2400 | " for QP%u, SQ Head = %u, SQ Tail = %u. " |
2201 | nesqp->hwqp.qp_id, | 2401 | "cm_id = %p, refcount = %u.\n", |
2202 | nesqp->hwqp.sq_head, nesqp->hwqp.sq_tail, cm_id, | 2402 | nesqp->hwqp.qp_id, nesqp->hwqp.sq_head, |
2203 | atomic_read(&nesqp->refcount)); | 2403 | nesqp->hwqp.sq_tail, cm_id, |
2404 | atomic_read(&nesqp->refcount)); | ||
2204 | 2405 | ||
2205 | spin_unlock_irqrestore(&nesqp->lock, flags); | 2406 | spin_unlock_irqrestore(&nesqp->lock, flags); |
2206 | ret = cm_id->event_handler(cm_id, &cm_event); | 2407 | ret = cm_id->event_handler(cm_id, &cm_event); |
2207 | if (ret) | 2408 | if (ret) |
2208 | nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret); | 2409 | nes_debug(NES_DBG_CM, "OFA CM event_handler " |
2410 | "returned, ret=%d\n", ret); | ||
2209 | spin_lock_irqsave(&nesqp->lock, flags); | 2411 | spin_lock_irqsave(&nesqp->lock, flags); |
2210 | } | 2412 | } |
2211 | 2413 | ||
@@ -2247,31 +2449,24 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp) | |||
2247 | if (nesqp->flush_issued == 0) { | 2449 | if (nesqp->flush_issued == 0) { |
2248 | nesqp->flush_issued = 1; | 2450 | nesqp->flush_issued = 1; |
2249 | spin_unlock_irqrestore(&nesqp->lock, flags); | 2451 | spin_unlock_irqrestore(&nesqp->lock, flags); |
2250 | flush_wqes(nesvnic->nesdev, nesqp, NES_CQP_FLUSH_RQ, 1); | 2452 | flush_wqes(nesvnic->nesdev, nesqp, |
2251 | } else { | 2453 | NES_CQP_FLUSH_RQ, 1); |
2454 | } else | ||
2252 | spin_unlock_irqrestore(&nesqp->lock, flags); | 2455 | spin_unlock_irqrestore(&nesqp->lock, flags); |
2253 | } | ||
2254 | |||
2255 | /* This reference is from either ModifyQP or the AE processing, | ||
2256 | there is still a race here with modifyqp */ | ||
2257 | nes_rem_ref(&nesqp->ibqp); | ||
2258 | |||
2259 | } else { | 2456 | } else { |
2260 | cm_id = nesqp->cm_id; | 2457 | cm_id = nesqp->cm_id; |
2261 | spin_unlock_irqrestore(&nesqp->lock, flags); | 2458 | spin_unlock_irqrestore(&nesqp->lock, flags); |
2262 | /* check to see if the inbound reset beat the outbound reset */ | 2459 | /* check to see if the inbound reset beat the outbound reset */ |
2263 | if ((!cm_id) && (last_ae==NES_AEQE_AEID_RESET_SENT)) { | 2460 | if ((!cm_id) && (last_ae==NES_AEQE_AEID_RESET_SENT)) { |
2264 | nes_debug(NES_DBG_CM, "QP%u: Decing refcount due to inbound reset" | 2461 | nes_debug(NES_DBG_CM, "QP%u: Decing refcount " |
2265 | " beating the outbound reset.\n", | 2462 | "due to inbound reset beating the " |
2266 | nesqp->hwqp.qp_id); | 2463 | "outbound reset.\n", nesqp->hwqp.qp_id); |
2267 | nes_rem_ref(&nesqp->ibqp); | ||
2268 | } | 2464 | } |
2269 | } | 2465 | } |
2270 | } else { | 2466 | } else { |
2271 | nesqp->disconn_pending = 0; | 2467 | nesqp->disconn_pending = 0; |
2272 | spin_unlock_irqrestore(&nesqp->lock, flags); | 2468 | spin_unlock_irqrestore(&nesqp->lock, flags); |
2273 | } | 2469 | } |
2274 | nes_rem_ref(&nesqp->ibqp); | ||
2275 | 2470 | ||
2276 | return 0; | 2471 | return 0; |
2277 | } | 2472 | } |
@@ -2349,71 +2544,82 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
2349 | nesdev = nesvnic->nesdev; | 2544 | nesdev = nesvnic->nesdev; |
2350 | adapter = nesdev->nesadapter; | 2545 | adapter = nesdev->nesadapter; |
2351 | 2546 | ||
2352 | nes_debug(NES_DBG_CM, "nesvnic=%p, netdev=%p, %s\n", | ||
2353 | nesvnic, nesvnic->netdev, nesvnic->netdev->name); | ||
2354 | |||
2355 | /* since this is from a listen, we were able to put node handle into cm_id */ | ||
2356 | cm_node = (struct nes_cm_node *)cm_id->provider_data; | 2547 | cm_node = (struct nes_cm_node *)cm_id->provider_data; |
2548 | nes_debug(NES_DBG_CM, "nes_accept: cm_node= %p nesvnic=%p, netdev=%p," | ||
2549 | "%s\n", cm_node, nesvnic, nesvnic->netdev, | ||
2550 | nesvnic->netdev->name); | ||
2357 | 2551 | ||
2358 | /* associate the node with the QP */ | 2552 | /* associate the node with the QP */ |
2359 | nesqp->cm_node = (void *)cm_node; | 2553 | nesqp->cm_node = (void *)cm_node; |
2554 | cm_node->nesqp = nesqp; | ||
2555 | nes_add_ref(&nesqp->ibqp); | ||
2360 | 2556 | ||
2361 | nes_debug(NES_DBG_CM, "QP%u, cm_node=%p, jiffies = %lu\n", | 2557 | nes_debug(NES_DBG_CM, "QP%u, cm_node=%p, jiffies = %lu listener = %p\n", |
2362 | nesqp->hwqp.qp_id, cm_node, jiffies); | 2558 | nesqp->hwqp.qp_id, cm_node, jiffies, cm_node->listener); |
2363 | atomic_inc(&cm_accepts); | 2559 | atomic_inc(&cm_accepts); |
2364 | 2560 | ||
2365 | nes_debug(NES_DBG_CM, "netdev refcnt = %u.\n", | 2561 | nes_debug(NES_DBG_CM, "netdev refcnt = %u.\n", |
2366 | atomic_read(&nesvnic->netdev->refcnt)); | 2562 | atomic_read(&nesvnic->netdev->refcnt)); |
2367 | 2563 | ||
2368 | /* allocate the ietf frame and space for private data */ | 2564 | /* allocate the ietf frame and space for private data */ |
2369 | nesqp->ietf_frame = pci_alloc_consistent(nesdev->pcidev, | 2565 | nesqp->ietf_frame = pci_alloc_consistent(nesdev->pcidev, |
2370 | sizeof(struct ietf_mpa_frame) + conn_param->private_data_len, | 2566 | sizeof(struct ietf_mpa_frame) + conn_param->private_data_len, |
2371 | &nesqp->ietf_frame_pbase); | 2567 | &nesqp->ietf_frame_pbase); |
2372 | |||
2373 | if (!nesqp->ietf_frame) { | ||
2374 | nes_debug(NES_DBG_CM, "Unable to allocate memory for private data\n"); | ||
2375 | return -ENOMEM; | ||
2376 | } | ||
2377 | 2568 | ||
2569 | if (!nesqp->ietf_frame) { | ||
2570 | nes_debug(NES_DBG_CM, "Unable to allocate memory for private " | ||
2571 | "data\n"); | ||
2572 | return -ENOMEM; | ||
2573 | } | ||
2378 | 2574 | ||
2379 | /* setup the MPA frame */ | ||
2380 | nesqp->private_data_len = conn_param->private_data_len; | ||
2381 | memcpy(nesqp->ietf_frame->key, IEFT_MPA_KEY_REP, IETF_MPA_KEY_SIZE); | ||
2382 | 2575 | ||
2383 | memcpy(nesqp->ietf_frame->priv_data, conn_param->private_data, | 2576 | /* setup the MPA frame */ |
2384 | conn_param->private_data_len); | 2577 | nesqp->private_data_len = conn_param->private_data_len; |
2578 | memcpy(nesqp->ietf_frame->key, IEFT_MPA_KEY_REP, IETF_MPA_KEY_SIZE); | ||
2385 | 2579 | ||
2386 | nesqp->ietf_frame->priv_data_len = cpu_to_be16(conn_param->private_data_len); | 2580 | memcpy(nesqp->ietf_frame->priv_data, conn_param->private_data, |
2387 | nesqp->ietf_frame->rev = mpa_version; | 2581 | conn_param->private_data_len); |
2388 | nesqp->ietf_frame->flags = IETF_MPA_FLAGS_CRC; | ||
2389 | 2582 | ||
2390 | /* setup our first outgoing iWarp send WQE (the IETF frame response) */ | 2583 | nesqp->ietf_frame->priv_data_len = |
2391 | wqe = &nesqp->hwqp.sq_vbase[0]; | 2584 | cpu_to_be16(conn_param->private_data_len); |
2585 | nesqp->ietf_frame->rev = mpa_version; | ||
2586 | nesqp->ietf_frame->flags = IETF_MPA_FLAGS_CRC; | ||
2392 | 2587 | ||
2393 | if (cm_id->remote_addr.sin_addr.s_addr != cm_id->local_addr.sin_addr.s_addr) { | 2588 | /* setup our first outgoing iWarp send WQE (the IETF frame response) */ |
2394 | u64temp = (unsigned long)nesqp; | 2589 | wqe = &nesqp->hwqp.sq_vbase[0]; |
2395 | u64temp |= NES_SW_CONTEXT_ALIGN>>1; | 2590 | |
2396 | set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX, | 2591 | if (cm_id->remote_addr.sin_addr.s_addr != |
2397 | u64temp); | 2592 | cm_id->local_addr.sin_addr.s_addr) { |
2398 | wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] = | 2593 | u64temp = (unsigned long)nesqp; |
2399 | cpu_to_le32(NES_IWARP_SQ_WQE_STREAMING | NES_IWARP_SQ_WQE_WRPDU); | 2594 | u64temp |= NES_SW_CONTEXT_ALIGN>>1; |
2400 | wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] = | 2595 | set_wqe_64bit_value(wqe->wqe_words, |
2401 | cpu_to_le32(conn_param->private_data_len + sizeof(struct ietf_mpa_frame)); | 2596 | NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX, |
2402 | wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_LOW_IDX] = | 2597 | u64temp); |
2403 | cpu_to_le32((u32)nesqp->ietf_frame_pbase); | 2598 | wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] = |
2404 | wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_HIGH_IDX] = | 2599 | cpu_to_le32(NES_IWARP_SQ_WQE_STREAMING | |
2405 | cpu_to_le32((u32)((u64)nesqp->ietf_frame_pbase >> 32)); | 2600 | NES_IWARP_SQ_WQE_WRPDU); |
2406 | wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] = | 2601 | wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] = |
2407 | cpu_to_le32(conn_param->private_data_len + sizeof(struct ietf_mpa_frame)); | 2602 | cpu_to_le32(conn_param->private_data_len + |
2408 | wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 0; | 2603 | sizeof(struct ietf_mpa_frame)); |
2409 | 2604 | wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_LOW_IDX] = | |
2410 | nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32( | 2605 | cpu_to_le32((u32)nesqp->ietf_frame_pbase); |
2411 | NES_QPCONTEXT_ORDIRD_LSMM_PRESENT | NES_QPCONTEXT_ORDIRD_WRPDU); | 2606 | wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_HIGH_IDX] = |
2412 | } else { | 2607 | cpu_to_le32((u32)((u64)nesqp->ietf_frame_pbase >> 32)); |
2413 | nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32((NES_QPCONTEXT_ORDIRD_LSMM_PRESENT | | 2608 | wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] = |
2414 | NES_QPCONTEXT_ORDIRD_WRPDU | NES_QPCONTEXT_ORDIRD_ALSMM)); | 2609 | cpu_to_le32(conn_param->private_data_len + |
2415 | } | 2610 | sizeof(struct ietf_mpa_frame)); |
2416 | nesqp->skip_lsmm = 1; | 2611 | wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 0; |
2612 | |||
2613 | nesqp->nesqp_context->ird_ord_sizes |= | ||
2614 | cpu_to_le32(NES_QPCONTEXT_ORDIRD_LSMM_PRESENT | | ||
2615 | NES_QPCONTEXT_ORDIRD_WRPDU); | ||
2616 | } else { | ||
2617 | nesqp->nesqp_context->ird_ord_sizes |= | ||
2618 | cpu_to_le32((NES_QPCONTEXT_ORDIRD_LSMM_PRESENT | | ||
2619 | NES_QPCONTEXT_ORDIRD_WRPDU | | ||
2620 | NES_QPCONTEXT_ORDIRD_ALSMM)); | ||
2621 | } | ||
2622 | nesqp->skip_lsmm = 1; | ||
2417 | 2623 | ||
2418 | 2624 | ||
2419 | /* Cache the cm_id in the qp */ | 2625 | /* Cache the cm_id in the qp */ |
@@ -2424,55 +2630,75 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
2424 | cm_id->provider_data = nesqp; | 2630 | cm_id->provider_data = nesqp; |
2425 | nesqp->active_conn = 0; | 2631 | nesqp->active_conn = 0; |
2426 | 2632 | ||
2633 | if (cm_node->state == NES_CM_STATE_TSA) | ||
2634 | nes_debug(NES_DBG_CM, "Already state = TSA for cm_node=%p\n", | ||
2635 | cm_node); | ||
2636 | |||
2427 | nes_cm_init_tsa_conn(nesqp, cm_node); | 2637 | nes_cm_init_tsa_conn(nesqp, cm_node); |
2428 | 2638 | ||
2429 | nesqp->nesqp_context->tcpPorts[0] = cpu_to_le16(ntohs(cm_id->local_addr.sin_port)); | 2639 | nesqp->nesqp_context->tcpPorts[0] = |
2430 | nesqp->nesqp_context->tcpPorts[1] = cpu_to_le16(ntohs(cm_id->remote_addr.sin_port)); | 2640 | cpu_to_le16(ntohs(cm_id->local_addr.sin_port)); |
2431 | nesqp->nesqp_context->ip0 = cpu_to_le32(ntohl(cm_id->remote_addr.sin_addr.s_addr)); | 2641 | nesqp->nesqp_context->tcpPorts[1] = |
2642 | cpu_to_le16(ntohs(cm_id->remote_addr.sin_port)); | ||
2643 | |||
2644 | if (ipv4_is_loopback(cm_id->remote_addr.sin_addr.s_addr)) | ||
2645 | nesqp->nesqp_context->ip0 = | ||
2646 | cpu_to_le32(ntohl(nesvnic->local_ipaddr)); | ||
2647 | else | ||
2648 | nesqp->nesqp_context->ip0 = | ||
2649 | cpu_to_le32(ntohl(cm_id->remote_addr.sin_addr.s_addr)); | ||
2432 | 2650 | ||
2433 | nesqp->nesqp_context->misc2 |= cpu_to_le32( | 2651 | nesqp->nesqp_context->misc2 |= cpu_to_le32( |
2434 | (u32)PCI_FUNC(nesdev->pcidev->devfn) << NES_QPCONTEXT_MISC2_SRC_IP_SHIFT); | 2652 | (u32)PCI_FUNC(nesdev->pcidev->devfn) << |
2653 | NES_QPCONTEXT_MISC2_SRC_IP_SHIFT); | ||
2435 | 2654 | ||
2436 | nesqp->nesqp_context->arp_index_vlan |= cpu_to_le32( | 2655 | nesqp->nesqp_context->arp_index_vlan |= |
2437 | nes_arp_table(nesdev, le32_to_cpu(nesqp->nesqp_context->ip0), NULL, | 2656 | cpu_to_le32(nes_arp_table(nesdev, |
2657 | le32_to_cpu(nesqp->nesqp_context->ip0), NULL, | ||
2438 | NES_ARP_RESOLVE) << 16); | 2658 | NES_ARP_RESOLVE) << 16); |
2439 | 2659 | ||
2440 | nesqp->nesqp_context->ts_val_delta = cpu_to_le32( | 2660 | nesqp->nesqp_context->ts_val_delta = cpu_to_le32( |
2441 | jiffies - nes_read_indexed(nesdev, NES_IDX_TCP_NOW)); | 2661 | jiffies - nes_read_indexed(nesdev, NES_IDX_TCP_NOW)); |
2442 | 2662 | ||
2443 | nesqp->nesqp_context->ird_index = cpu_to_le32(nesqp->hwqp.qp_id); | 2663 | nesqp->nesqp_context->ird_index = cpu_to_le32(nesqp->hwqp.qp_id); |
2444 | 2664 | ||
2445 | nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32( | 2665 | nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32( |
2446 | ((u32)1 << NES_QPCONTEXT_ORDIRD_IWARP_MODE_SHIFT)); | 2666 | ((u32)1 << NES_QPCONTEXT_ORDIRD_IWARP_MODE_SHIFT)); |
2447 | nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32((u32)conn_param->ord); | 2667 | nesqp->nesqp_context->ird_ord_sizes |= |
2668 | cpu_to_le32((u32)conn_param->ord); | ||
2448 | 2669 | ||
2449 | memset(&nes_quad, 0, sizeof(nes_quad)); | 2670 | memset(&nes_quad, 0, sizeof(nes_quad)); |
2450 | nes_quad.DstIpAdrIndex = cpu_to_le32((u32)PCI_FUNC(nesdev->pcidev->devfn) << 24); | 2671 | nes_quad.DstIpAdrIndex = |
2451 | nes_quad.SrcIpadr = cm_id->remote_addr.sin_addr.s_addr; | 2672 | cpu_to_le32((u32)PCI_FUNC(nesdev->pcidev->devfn) << 24); |
2452 | nes_quad.TcpPorts[0] = cm_id->remote_addr.sin_port; | 2673 | if (ipv4_is_loopback(cm_id->remote_addr.sin_addr.s_addr)) |
2453 | nes_quad.TcpPorts[1] = cm_id->local_addr.sin_port; | 2674 | nes_quad.SrcIpadr = nesvnic->local_ipaddr; |
2675 | else | ||
2676 | nes_quad.SrcIpadr = cm_id->remote_addr.sin_addr.s_addr; | ||
2677 | nes_quad.TcpPorts[0] = cm_id->remote_addr.sin_port; | ||
2678 | nes_quad.TcpPorts[1] = cm_id->local_addr.sin_port; | ||
2454 | 2679 | ||
2455 | /* Produce hash key */ | 2680 | /* Produce hash key */ |
2456 | crc_value = get_crc_value(&nes_quad); | 2681 | crc_value = get_crc_value(&nes_quad); |
2457 | nesqp->hte_index = cpu_to_be32(crc_value ^ 0xffffffff); | 2682 | nesqp->hte_index = cpu_to_be32(crc_value ^ 0xffffffff); |
2458 | nes_debug(NES_DBG_CM, "HTE Index = 0x%08X, CRC = 0x%08X\n", | 2683 | nes_debug(NES_DBG_CM, "HTE Index = 0x%08X, CRC = 0x%08X\n", |
2459 | nesqp->hte_index, nesqp->hte_index & adapter->hte_index_mask); | 2684 | nesqp->hte_index, nesqp->hte_index & adapter->hte_index_mask); |
2460 | 2685 | ||
2461 | nesqp->hte_index &= adapter->hte_index_mask; | 2686 | nesqp->hte_index &= adapter->hte_index_mask; |
2462 | nesqp->nesqp_context->hte_index = cpu_to_le32(nesqp->hte_index); | 2687 | nesqp->nesqp_context->hte_index = cpu_to_le32(nesqp->hte_index); |
2463 | 2688 | ||
2464 | cm_node->cm_core->api->accelerated(cm_node->cm_core, cm_node); | 2689 | cm_node->cm_core->api->accelerated(cm_node->cm_core, cm_node); |
2465 | 2690 | ||
2466 | nes_debug(NES_DBG_CM, "QP%u, Destination IP = 0x%08X:0x%04X, local = 0x%08X:0x%04X," | 2691 | nes_debug(NES_DBG_CM, "QP%u, Destination IP = 0x%08X:0x%04X, local = " |
2467 | " rcv_nxt=0x%08X, snd_nxt=0x%08X, mpa + private data length=%zu.\n", | 2692 | "0x%08X:0x%04X, rcv_nxt=0x%08X, snd_nxt=0x%08X, mpa + " |
2468 | nesqp->hwqp.qp_id, | 2693 | "private data length=%zu.\n", nesqp->hwqp.qp_id, |
2469 | ntohl(cm_id->remote_addr.sin_addr.s_addr), | 2694 | ntohl(cm_id->remote_addr.sin_addr.s_addr), |
2470 | ntohs(cm_id->remote_addr.sin_port), | 2695 | ntohs(cm_id->remote_addr.sin_port), |
2471 | ntohl(cm_id->local_addr.sin_addr.s_addr), | 2696 | ntohl(cm_id->local_addr.sin_addr.s_addr), |
2472 | ntohs(cm_id->local_addr.sin_port), | 2697 | ntohs(cm_id->local_addr.sin_port), |
2473 | le32_to_cpu(nesqp->nesqp_context->rcv_nxt), | 2698 | le32_to_cpu(nesqp->nesqp_context->rcv_nxt), |
2474 | le32_to_cpu(nesqp->nesqp_context->snd_nxt), | 2699 | le32_to_cpu(nesqp->nesqp_context->snd_nxt), |
2475 | conn_param->private_data_len+sizeof(struct ietf_mpa_frame)); | 2700 | conn_param->private_data_len + |
2701 | sizeof(struct ietf_mpa_frame)); | ||
2476 | 2702 | ||
2477 | attr.qp_state = IB_QPS_RTS; | 2703 | attr.qp_state = IB_QPS_RTS; |
2478 | nes_modify_qp(&nesqp->ibqp, &attr, IB_QP_STATE, NULL); | 2704 | nes_modify_qp(&nesqp->ibqp, &attr, IB_QP_STATE, NULL); |
@@ -2489,15 +2715,16 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
2489 | cm_event.private_data_len = 0; | 2715 | cm_event.private_data_len = 0; |
2490 | ret = cm_id->event_handler(cm_id, &cm_event); | 2716 | ret = cm_id->event_handler(cm_id, &cm_event); |
2491 | if (cm_node->loopbackpartner) { | 2717 | if (cm_node->loopbackpartner) { |
2492 | cm_node->loopbackpartner->mpa_frame_size = nesqp->private_data_len; | 2718 | cm_node->loopbackpartner->mpa_frame_size = |
2719 | nesqp->private_data_len; | ||
2493 | /* copy entire MPA frame to our cm_node's frame */ | 2720 | /* copy entire MPA frame to our cm_node's frame */ |
2494 | memcpy(cm_node->loopbackpartner->mpa_frame_buf, nesqp->ietf_frame->priv_data, | 2721 | memcpy(cm_node->loopbackpartner->mpa_frame_buf, |
2495 | nesqp->private_data_len); | 2722 | nesqp->ietf_frame->priv_data, nesqp->private_data_len); |
2496 | create_event(cm_node->loopbackpartner, NES_CM_EVENT_CONNECTED); | 2723 | create_event(cm_node->loopbackpartner, NES_CM_EVENT_CONNECTED); |
2497 | } | 2724 | } |
2498 | if (ret) | 2725 | if (ret) |
2499 | printk("%s[%u] OFA CM event_handler returned, ret=%d\n", | 2726 | printk(KERN_ERR "%s[%u] OFA CM event_handler returned, " |
2500 | __func__, __LINE__, ret); | 2727 | "ret=%d\n", __func__, __LINE__, ret); |
2501 | 2728 | ||
2502 | return 0; | 2729 | return 0; |
2503 | } | 2730 | } |
@@ -2555,74 +2782,61 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
2555 | if (!nesdev) | 2782 | if (!nesdev) |
2556 | return -EINVAL; | 2783 | return -EINVAL; |
2557 | 2784 | ||
2558 | atomic_inc(&cm_connects); | 2785 | nes_debug(NES_DBG_CM, "QP%u, current IP = 0x%08X, Destination IP = " |
2559 | 2786 | "0x%08X:0x%04X, local = 0x%08X:0x%04X.\n", nesqp->hwqp.qp_id, | |
2560 | nesqp->ietf_frame = kzalloc(sizeof(struct ietf_mpa_frame) + | 2787 | ntohl(nesvnic->local_ipaddr), |
2561 | conn_param->private_data_len, GFP_KERNEL); | 2788 | ntohl(cm_id->remote_addr.sin_addr.s_addr), |
2562 | if (!nesqp->ietf_frame) | 2789 | ntohs(cm_id->remote_addr.sin_port), |
2563 | return -ENOMEM; | 2790 | ntohl(cm_id->local_addr.sin_addr.s_addr), |
2791 | ntohs(cm_id->local_addr.sin_port)); | ||
2564 | 2792 | ||
2565 | /* set qp as having an active connection */ | 2793 | atomic_inc(&cm_connects); |
2566 | nesqp->active_conn = 1; | 2794 | nesqp->active_conn = 1; |
2567 | 2795 | ||
2568 | nes_debug(NES_DBG_CM, "QP%u, Destination IP = 0x%08X:0x%04X, local = 0x%08X:0x%04X.\n", | ||
2569 | nesqp->hwqp.qp_id, | ||
2570 | ntohl(cm_id->remote_addr.sin_addr.s_addr), | ||
2571 | ntohs(cm_id->remote_addr.sin_port), | ||
2572 | ntohl(cm_id->local_addr.sin_addr.s_addr), | ||
2573 | ntohs(cm_id->local_addr.sin_port)); | ||
2574 | |||
2575 | /* cache the cm_id in the qp */ | 2796 | /* cache the cm_id in the qp */ |
2576 | nesqp->cm_id = cm_id; | 2797 | nesqp->cm_id = cm_id; |
2577 | 2798 | ||
2578 | cm_id->provider_data = nesqp; | 2799 | cm_id->provider_data = nesqp; |
2579 | 2800 | ||
2580 | /* copy the private data */ | ||
2581 | if (conn_param->private_data_len) { | ||
2582 | memcpy(nesqp->ietf_frame->priv_data, conn_param->private_data, | ||
2583 | conn_param->private_data_len); | ||
2584 | } | ||
2585 | |||
2586 | nesqp->private_data_len = conn_param->private_data_len; | 2801 | nesqp->private_data_len = conn_param->private_data_len; |
2587 | nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32((u32)conn_param->ord); | 2802 | nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32((u32)conn_param->ord); |
2588 | nes_debug(NES_DBG_CM, "requested ord = 0x%08X.\n", (u32)conn_param->ord); | 2803 | nes_debug(NES_DBG_CM, "requested ord = 0x%08X.\n", (u32)conn_param->ord); |
2589 | nes_debug(NES_DBG_CM, "mpa private data len =%u\n", conn_param->private_data_len); | 2804 | nes_debug(NES_DBG_CM, "mpa private data len =%u\n", |
2590 | 2805 | conn_param->private_data_len); | |
2591 | strcpy(&nesqp->ietf_frame->key[0], IEFT_MPA_KEY_REQ); | ||
2592 | nesqp->ietf_frame->flags = IETF_MPA_FLAGS_CRC; | ||
2593 | nesqp->ietf_frame->rev = IETF_MPA_VERSION; | ||
2594 | nesqp->ietf_frame->priv_data_len = htons(conn_param->private_data_len); | ||
2595 | 2806 | ||
2596 | if (cm_id->local_addr.sin_addr.s_addr != cm_id->remote_addr.sin_addr.s_addr) | 2807 | if (cm_id->local_addr.sin_addr.s_addr != |
2808 | cm_id->remote_addr.sin_addr.s_addr) | ||
2597 | nes_manage_apbvt(nesvnic, ntohs(cm_id->local_addr.sin_port), | 2809 | nes_manage_apbvt(nesvnic, ntohs(cm_id->local_addr.sin_port), |
2598 | PCI_FUNC(nesdev->pcidev->devfn), NES_MANAGE_APBVT_ADD); | 2810 | PCI_FUNC(nesdev->pcidev->devfn), NES_MANAGE_APBVT_ADD); |
2599 | 2811 | ||
2600 | /* set up the connection params for the node */ | 2812 | /* set up the connection params for the node */ |
2601 | cm_info.loc_addr = (cm_id->local_addr.sin_addr.s_addr); | 2813 | cm_info.loc_addr = htonl(cm_id->local_addr.sin_addr.s_addr); |
2602 | cm_info.loc_port = (cm_id->local_addr.sin_port); | 2814 | cm_info.loc_port = htons(cm_id->local_addr.sin_port); |
2603 | cm_info.rem_addr = (cm_id->remote_addr.sin_addr.s_addr); | 2815 | cm_info.rem_addr = htonl(cm_id->remote_addr.sin_addr.s_addr); |
2604 | cm_info.rem_port = (cm_id->remote_addr.sin_port); | 2816 | cm_info.rem_port = htons(cm_id->remote_addr.sin_port); |
2605 | cm_info.cm_id = cm_id; | 2817 | cm_info.cm_id = cm_id; |
2606 | cm_info.conn_type = NES_CM_IWARP_CONN_TYPE; | 2818 | cm_info.conn_type = NES_CM_IWARP_CONN_TYPE; |
2607 | 2819 | ||
2608 | cm_id->add_ref(cm_id); | 2820 | cm_id->add_ref(cm_id); |
2609 | nes_add_ref(&nesqp->ibqp); | ||
2610 | 2821 | ||
2611 | /* create a connect CM node connection */ | 2822 | /* create a connect CM node connection */ |
2612 | cm_node = g_cm_core->api->connect(g_cm_core, nesvnic, nesqp->ietf_frame, &cm_info); | 2823 | cm_node = g_cm_core->api->connect(g_cm_core, nesvnic, |
2824 | conn_param->private_data_len, (void *)conn_param->private_data, | ||
2825 | &cm_info); | ||
2613 | if (!cm_node) { | 2826 | if (!cm_node) { |
2614 | if (cm_id->local_addr.sin_addr.s_addr != cm_id->remote_addr.sin_addr.s_addr) | 2827 | if (cm_id->local_addr.sin_addr.s_addr != |
2828 | cm_id->remote_addr.sin_addr.s_addr) | ||
2615 | nes_manage_apbvt(nesvnic, ntohs(cm_id->local_addr.sin_port), | 2829 | nes_manage_apbvt(nesvnic, ntohs(cm_id->local_addr.sin_port), |
2616 | PCI_FUNC(nesdev->pcidev->devfn), NES_MANAGE_APBVT_DEL); | 2830 | PCI_FUNC(nesdev->pcidev->devfn), |
2617 | nes_rem_ref(&nesqp->ibqp); | 2831 | NES_MANAGE_APBVT_DEL); |
2618 | kfree(nesqp->ietf_frame); | 2832 | |
2619 | nesqp->ietf_frame = NULL; | ||
2620 | cm_id->rem_ref(cm_id); | 2833 | cm_id->rem_ref(cm_id); |
2621 | return -ENOMEM; | 2834 | return -ENOMEM; |
2622 | } | 2835 | } |
2623 | 2836 | ||
2624 | cm_node->apbvt_set = 1; | 2837 | cm_node->apbvt_set = 1; |
2625 | nesqp->cm_node = cm_node; | 2838 | nesqp->cm_node = cm_node; |
2839 | cm_node->nesqp = nesqp; | ||
2626 | 2840 | ||
2627 | return 0; | 2841 | return 0; |
2628 | } | 2842 | } |
@@ -2664,7 +2878,7 @@ int nes_create_listen(struct iw_cm_id *cm_id, int backlog) | |||
2664 | 2878 | ||
2665 | cm_node = g_cm_core->api->listen(g_cm_core, nesvnic, &cm_info); | 2879 | cm_node = g_cm_core->api->listen(g_cm_core, nesvnic, &cm_info); |
2666 | if (!cm_node) { | 2880 | if (!cm_node) { |
2667 | printk("%s[%u] Error returned from listen API call\n", | 2881 | printk(KERN_ERR "%s[%u] Error returned from listen API call\n", |
2668 | __func__, __LINE__); | 2882 | __func__, __LINE__); |
2669 | return -ENOMEM; | 2883 | return -ENOMEM; |
2670 | } | 2884 | } |
@@ -2672,10 +2886,13 @@ int nes_create_listen(struct iw_cm_id *cm_id, int backlog) | |||
2672 | cm_id->provider_data = cm_node; | 2886 | cm_id->provider_data = cm_node; |
2673 | 2887 | ||
2674 | if (!cm_node->reused_node) { | 2888 | if (!cm_node->reused_node) { |
2675 | err = nes_manage_apbvt(nesvnic, ntohs(cm_id->local_addr.sin_port), | 2889 | err = nes_manage_apbvt(nesvnic, |
2676 | PCI_FUNC(nesvnic->nesdev->pcidev->devfn), NES_MANAGE_APBVT_ADD); | 2890 | ntohs(cm_id->local_addr.sin_port), |
2891 | PCI_FUNC(nesvnic->nesdev->pcidev->devfn), | ||
2892 | NES_MANAGE_APBVT_ADD); | ||
2677 | if (err) { | 2893 | if (err) { |
2678 | printk("nes_manage_apbvt call returned %d.\n", err); | 2894 | printk(KERN_ERR "nes_manage_apbvt call returned %d.\n", |
2895 | err); | ||
2679 | g_cm_core->api->stop_listener(g_cm_core, (void *)cm_node); | 2896 | g_cm_core->api->stop_listener(g_cm_core, (void *)cm_node); |
2680 | return err; | 2897 | return err; |
2681 | } | 2898 | } |
@@ -2795,53 +3012,70 @@ static void cm_event_connected(struct nes_cm_event *event) | |||
2795 | nes_cm_init_tsa_conn(nesqp, cm_node); | 3012 | nes_cm_init_tsa_conn(nesqp, cm_node); |
2796 | 3013 | ||
2797 | /* set the QP tsa context */ | 3014 | /* set the QP tsa context */ |
2798 | nesqp->nesqp_context->tcpPorts[0] = cpu_to_le16(ntohs(cm_id->local_addr.sin_port)); | 3015 | nesqp->nesqp_context->tcpPorts[0] = |
2799 | nesqp->nesqp_context->tcpPorts[1] = cpu_to_le16(ntohs(cm_id->remote_addr.sin_port)); | 3016 | cpu_to_le16(ntohs(cm_id->local_addr.sin_port)); |
2800 | nesqp->nesqp_context->ip0 = cpu_to_le32(ntohl(cm_id->remote_addr.sin_addr.s_addr)); | 3017 | nesqp->nesqp_context->tcpPorts[1] = |
3018 | cpu_to_le16(ntohs(cm_id->remote_addr.sin_port)); | ||
3019 | if (ipv4_is_loopback(cm_id->remote_addr.sin_addr.s_addr)) | ||
3020 | nesqp->nesqp_context->ip0 = | ||
3021 | cpu_to_le32(ntohl(nesvnic->local_ipaddr)); | ||
3022 | else | ||
3023 | nesqp->nesqp_context->ip0 = | ||
3024 | cpu_to_le32(ntohl(cm_id->remote_addr.sin_addr.s_addr)); | ||
2801 | 3025 | ||
2802 | nesqp->nesqp_context->misc2 |= cpu_to_le32( | 3026 | nesqp->nesqp_context->misc2 |= cpu_to_le32( |
2803 | (u32)PCI_FUNC(nesdev->pcidev->devfn) << NES_QPCONTEXT_MISC2_SRC_IP_SHIFT); | 3027 | (u32)PCI_FUNC(nesdev->pcidev->devfn) << |
3028 | NES_QPCONTEXT_MISC2_SRC_IP_SHIFT); | ||
2804 | nesqp->nesqp_context->arp_index_vlan |= cpu_to_le32( | 3029 | nesqp->nesqp_context->arp_index_vlan |= cpu_to_le32( |
2805 | nes_arp_table(nesdev, le32_to_cpu(nesqp->nesqp_context->ip0), | 3030 | nes_arp_table(nesdev, |
3031 | le32_to_cpu(nesqp->nesqp_context->ip0), | ||
2806 | NULL, NES_ARP_RESOLVE) << 16); | 3032 | NULL, NES_ARP_RESOLVE) << 16); |
2807 | nesqp->nesqp_context->ts_val_delta = cpu_to_le32( | 3033 | nesqp->nesqp_context->ts_val_delta = cpu_to_le32( |
2808 | jiffies - nes_read_indexed(nesdev, NES_IDX_TCP_NOW)); | 3034 | jiffies - nes_read_indexed(nesdev, NES_IDX_TCP_NOW)); |
2809 | nesqp->nesqp_context->ird_index = cpu_to_le32(nesqp->hwqp.qp_id); | 3035 | nesqp->nesqp_context->ird_index = cpu_to_le32(nesqp->hwqp.qp_id); |
2810 | nesqp->nesqp_context->ird_ord_sizes |= | 3036 | nesqp->nesqp_context->ird_ord_sizes |= |
2811 | cpu_to_le32((u32)1 << NES_QPCONTEXT_ORDIRD_IWARP_MODE_SHIFT); | 3037 | cpu_to_le32((u32)1 << |
3038 | NES_QPCONTEXT_ORDIRD_IWARP_MODE_SHIFT); | ||
2812 | 3039 | ||
2813 | /* Adjust tail for not having a LSMM */ | 3040 | /* Adjust tail for not having a LSMM */ |
2814 | nesqp->hwqp.sq_tail = 1; | 3041 | nesqp->hwqp.sq_tail = 1; |
2815 | 3042 | ||
2816 | #if defined(NES_SEND_FIRST_WRITE) | 3043 | #if defined(NES_SEND_FIRST_WRITE) |
2817 | if (cm_node->send_write0) { | 3044 | if (cm_node->send_write0) { |
2818 | nes_debug(NES_DBG_CM, "Sending first write.\n"); | 3045 | nes_debug(NES_DBG_CM, "Sending first write.\n"); |
2819 | wqe = &nesqp->hwqp.sq_vbase[0]; | 3046 | wqe = &nesqp->hwqp.sq_vbase[0]; |
2820 | u64temp = (unsigned long)nesqp; | 3047 | u64temp = (unsigned long)nesqp; |
2821 | u64temp |= NES_SW_CONTEXT_ALIGN>>1; | 3048 | u64temp |= NES_SW_CONTEXT_ALIGN>>1; |
2822 | set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX, | 3049 | set_wqe_64bit_value(wqe->wqe_words, |
2823 | u64temp); | 3050 | NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX, u64temp); |
2824 | wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] = cpu_to_le32(NES_IWARP_SQ_OP_RDMAW); | 3051 | wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] = |
2825 | wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] = 0; | 3052 | cpu_to_le32(NES_IWARP_SQ_OP_RDMAW); |
2826 | wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_LOW_IDX] = 0; | 3053 | wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] = 0; |
2827 | wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_HIGH_IDX] = 0; | 3054 | wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_LOW_IDX] = 0; |
2828 | wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] = 0; | 3055 | wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_HIGH_IDX] = 0; |
2829 | wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 0; | 3056 | wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] = 0; |
2830 | 3057 | wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 0; | |
2831 | /* use the reserved spot on the WQ for the extra first WQE */ | 3058 | |
2832 | nesqp->nesqp_context->ird_ord_sizes &= cpu_to_le32(~(NES_QPCONTEXT_ORDIRD_LSMM_PRESENT | | 3059 | /* use the reserved spot on the WQ for the extra first WQE */ |
2833 | NES_QPCONTEXT_ORDIRD_WRPDU | NES_QPCONTEXT_ORDIRD_ALSMM)); | 3060 | nesqp->nesqp_context->ird_ord_sizes &= |
2834 | nesqp->skip_lsmm = 1; | 3061 | cpu_to_le32(~(NES_QPCONTEXT_ORDIRD_LSMM_PRESENT | |
2835 | nesqp->hwqp.sq_tail = 0; | 3062 | NES_QPCONTEXT_ORDIRD_WRPDU | |
2836 | nes_write32(nesdev->regs + NES_WQE_ALLOC, | 3063 | NES_QPCONTEXT_ORDIRD_ALSMM)); |
2837 | (1 << 24) | 0x00800000 | nesqp->hwqp.qp_id); | 3064 | nesqp->skip_lsmm = 1; |
2838 | } | 3065 | nesqp->hwqp.sq_tail = 0; |
3066 | nes_write32(nesdev->regs + NES_WQE_ALLOC, | ||
3067 | (1 << 24) | 0x00800000 | nesqp->hwqp.qp_id); | ||
3068 | } | ||
2839 | #endif | 3069 | #endif |
2840 | 3070 | ||
2841 | memset(&nes_quad, 0, sizeof(nes_quad)); | 3071 | memset(&nes_quad, 0, sizeof(nes_quad)); |
2842 | 3072 | ||
2843 | nes_quad.DstIpAdrIndex = cpu_to_le32((u32)PCI_FUNC(nesdev->pcidev->devfn) << 24); | 3073 | nes_quad.DstIpAdrIndex = |
2844 | nes_quad.SrcIpadr = cm_id->remote_addr.sin_addr.s_addr; | 3074 | cpu_to_le32((u32)PCI_FUNC(nesdev->pcidev->devfn) << 24); |
3075 | if (ipv4_is_loopback(cm_id->remote_addr.sin_addr.s_addr)) | ||
3076 | nes_quad.SrcIpadr = nesvnic->local_ipaddr; | ||
3077 | else | ||
3078 | nes_quad.SrcIpadr = cm_id->remote_addr.sin_addr.s_addr; | ||
2845 | nes_quad.TcpPorts[0] = cm_id->remote_addr.sin_port; | 3079 | nes_quad.TcpPorts[0] = cm_id->remote_addr.sin_port; |
2846 | nes_quad.TcpPorts[1] = cm_id->local_addr.sin_port; | 3080 | nes_quad.TcpPorts[1] = cm_id->local_addr.sin_port; |
2847 | 3081 | ||
@@ -2858,10 +3092,6 @@ static void cm_event_connected(struct nes_cm_event *event) | |||
2858 | nesqp->private_data_len = (u8) cm_node->mpa_frame_size; | 3092 | nesqp->private_data_len = (u8) cm_node->mpa_frame_size; |
2859 | cm_node->cm_core->api->accelerated(cm_node->cm_core, cm_node); | 3093 | cm_node->cm_core->api->accelerated(cm_node->cm_core, cm_node); |
2860 | 3094 | ||
2861 | /* modify QP state to rts */ | ||
2862 | attr.qp_state = IB_QPS_RTS; | ||
2863 | nes_modify_qp(&nesqp->ibqp, &attr, IB_QP_STATE, NULL); | ||
2864 | |||
2865 | /* notify OF layer we successfully created the requested connection */ | 3095 | /* notify OF layer we successfully created the requested connection */ |
2866 | cm_event.event = IW_CM_EVENT_CONNECT_REPLY; | 3096 | cm_event.event = IW_CM_EVENT_CONNECT_REPLY; |
2867 | cm_event.status = IW_CM_EVENT_STATUS_ACCEPTED; | 3097 | cm_event.status = IW_CM_EVENT_STATUS_ACCEPTED; |
@@ -2870,20 +3100,21 @@ static void cm_event_connected(struct nes_cm_event *event) | |||
2870 | cm_event.local_addr.sin_port = cm_id->local_addr.sin_port; | 3100 | cm_event.local_addr.sin_port = cm_id->local_addr.sin_port; |
2871 | cm_event.remote_addr = cm_id->remote_addr; | 3101 | cm_event.remote_addr = cm_id->remote_addr; |
2872 | 3102 | ||
2873 | cm_event.private_data = (void *)event->cm_node->mpa_frame_buf; | 3103 | cm_event.private_data = (void *)event->cm_node->mpa_frame_buf; |
2874 | cm_event.private_data_len = (u8) event->cm_node->mpa_frame_size; | 3104 | cm_event.private_data_len = (u8) event->cm_node->mpa_frame_size; |
2875 | 3105 | ||
2876 | cm_event.local_addr.sin_addr.s_addr = event->cm_info.rem_addr; | 3106 | cm_event.local_addr.sin_addr.s_addr = event->cm_info.rem_addr; |
2877 | ret = cm_id->event_handler(cm_id, &cm_event); | 3107 | ret = cm_id->event_handler(cm_id, &cm_event); |
2878 | nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret); | 3108 | nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret); |
2879 | 3109 | ||
2880 | if (ret) | 3110 | if (ret) |
2881 | printk("%s[%u] OFA CM event_handler returned, ret=%d\n", | 3111 | printk(KERN_ERR "%s[%u] OFA CM event_handler returned, " |
2882 | __func__, __LINE__, ret); | 3112 | "ret=%d\n", __func__, __LINE__, ret); |
2883 | nes_debug(NES_DBG_CM, "Exiting connect thread for QP%u. jiffies = %lu\n", | 3113 | attr.qp_state = IB_QPS_RTS; |
2884 | nesqp->hwqp.qp_id, jiffies ); | 3114 | nes_modify_qp(&nesqp->ibqp, &attr, IB_QP_STATE, NULL); |
2885 | 3115 | ||
2886 | nes_rem_ref(&nesqp->ibqp); | 3116 | nes_debug(NES_DBG_CM, "Exiting connect thread for QP%u. jiffies = " |
3117 | "%lu\n", nesqp->hwqp.qp_id, jiffies); | ||
2887 | 3118 | ||
2888 | return; | 3119 | return; |
2889 | } | 3120 | } |
@@ -2927,17 +3158,19 @@ static void cm_event_connect_error(struct nes_cm_event *event) | |||
2927 | cm_event.private_data = NULL; | 3158 | cm_event.private_data = NULL; |
2928 | cm_event.private_data_len = 0; | 3159 | cm_event.private_data_len = 0; |
2929 | 3160 | ||
2930 | nes_debug(NES_DBG_CM, "call CM_EVENT REJECTED, local_addr=%08x, remove_addr=%08x\n", | 3161 | nes_debug(NES_DBG_CM, "call CM_EVENT REJECTED, local_addr=%08x, " |
2931 | cm_event.local_addr.sin_addr.s_addr, cm_event.remote_addr.sin_addr.s_addr); | 3162 | "remove_addr=%08x\n", cm_event.local_addr.sin_addr.s_addr, |
3163 | cm_event.remote_addr.sin_addr.s_addr); | ||
2932 | 3164 | ||
2933 | ret = cm_id->event_handler(cm_id, &cm_event); | 3165 | ret = cm_id->event_handler(cm_id, &cm_event); |
2934 | nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret); | 3166 | nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret); |
2935 | if (ret) | 3167 | if (ret) |
2936 | printk("%s[%u] OFA CM event_handler returned, ret=%d\n", | 3168 | printk(KERN_ERR "%s[%u] OFA CM event_handler returned, " |
2937 | __func__, __LINE__, ret); | 3169 | "ret=%d\n", __func__, __LINE__, ret); |
2938 | nes_rem_ref(&nesqp->ibqp); | 3170 | nes_rem_ref(&nesqp->ibqp); |
2939 | cm_id->rem_ref(cm_id); | 3171 | cm_id->rem_ref(cm_id); |
2940 | 3172 | ||
3173 | rem_ref_cm_node(event->cm_node->cm_core, event->cm_node); | ||
2941 | return; | 3174 | return; |
2942 | } | 3175 | } |
2943 | 3176 | ||
@@ -3040,7 +3273,8 @@ static int nes_cm_post_event(struct nes_cm_event *event) | |||
3040 | add_ref_cm_node(event->cm_node); | 3273 | add_ref_cm_node(event->cm_node); |
3041 | event->cm_info.cm_id->add_ref(event->cm_info.cm_id); | 3274 | event->cm_info.cm_id->add_ref(event->cm_info.cm_id); |
3042 | INIT_WORK(&event->event_work, nes_cm_event_handler); | 3275 | INIT_WORK(&event->event_work, nes_cm_event_handler); |
3043 | nes_debug(NES_DBG_CM, "queue_work, event=%p\n", event); | 3276 | nes_debug(NES_DBG_CM, "cm_node=%p queue_work, event=%p\n", |
3277 | event->cm_node, event); | ||
3044 | 3278 | ||
3045 | queue_work(event->cm_node->cm_core->event_wq, &event->event_work); | 3279 | queue_work(event->cm_node->cm_core->event_wq, &event->event_work); |
3046 | 3280 | ||
@@ -3056,46 +3290,48 @@ static int nes_cm_post_event(struct nes_cm_event *event) | |||
3056 | */ | 3290 | */ |
3057 | static void nes_cm_event_handler(struct work_struct *work) | 3291 | static void nes_cm_event_handler(struct work_struct *work) |
3058 | { | 3292 | { |
3059 | struct nes_cm_event *event = container_of(work, struct nes_cm_event, event_work); | 3293 | struct nes_cm_event *event = container_of(work, struct nes_cm_event, |
3294 | event_work); | ||
3060 | struct nes_cm_core *cm_core; | 3295 | struct nes_cm_core *cm_core; |
3061 | 3296 | ||
3062 | if ((!event) || (!event->cm_node) || (!event->cm_node->cm_core)) { | 3297 | if ((!event) || (!event->cm_node) || (!event->cm_node->cm_core)) |
3063 | return; | 3298 | return; |
3064 | } | 3299 | |
3065 | cm_core = event->cm_node->cm_core; | 3300 | cm_core = event->cm_node->cm_core; |
3066 | nes_debug(NES_DBG_CM, "event=%p, event->type=%u, events posted=%u\n", | 3301 | nes_debug(NES_DBG_CM, "event=%p, event->type=%u, events posted=%u\n", |
3067 | event, event->type, atomic_read(&cm_core->events_posted)); | 3302 | event, event->type, atomic_read(&cm_core->events_posted)); |
3068 | 3303 | ||
3069 | switch (event->type) { | 3304 | switch (event->type) { |
3070 | case NES_CM_EVENT_MPA_REQ: | 3305 | case NES_CM_EVENT_MPA_REQ: |
3071 | cm_event_mpa_req(event); | 3306 | cm_event_mpa_req(event); |
3072 | nes_debug(NES_DBG_CM, "CM Event: MPA REQUEST\n"); | 3307 | nes_debug(NES_DBG_CM, "cm_node=%p CM Event: MPA REQUEST\n", |
3073 | break; | 3308 | event->cm_node); |
3074 | case NES_CM_EVENT_RESET: | 3309 | break; |
3075 | nes_debug(NES_DBG_CM, "CM Event: RESET\n"); | 3310 | case NES_CM_EVENT_RESET: |
3076 | cm_event_reset(event); | 3311 | nes_debug(NES_DBG_CM, "cm_node = %p CM Event: RESET\n", |
3077 | break; | 3312 | event->cm_node); |
3078 | case NES_CM_EVENT_CONNECTED: | 3313 | cm_event_reset(event); |
3079 | if ((!event->cm_node->cm_id) || | 3314 | break; |
3080 | (event->cm_node->state != NES_CM_STATE_TSA)) { | 3315 | case NES_CM_EVENT_CONNECTED: |
3081 | break; | 3316 | if ((!event->cm_node->cm_id) || |
3082 | } | 3317 | (event->cm_node->state != NES_CM_STATE_TSA)) |
3083 | cm_event_connected(event); | ||
3084 | nes_debug(NES_DBG_CM, "CM Event: CONNECTED\n"); | ||
3085 | break; | 3318 | break; |
3086 | case NES_CM_EVENT_ABORTED: | 3319 | cm_event_connected(event); |
3087 | if ((!event->cm_node->cm_id) || (event->cm_node->state == NES_CM_STATE_TSA)) { | 3320 | nes_debug(NES_DBG_CM, "CM Event: CONNECTED\n"); |
3088 | break; | 3321 | break; |
3089 | } | 3322 | case NES_CM_EVENT_ABORTED: |
3090 | cm_event_connect_error(event); | 3323 | if ((!event->cm_node->cm_id) || |
3091 | nes_debug(NES_DBG_CM, "CM Event: ABORTED\n"); | 3324 | (event->cm_node->state == NES_CM_STATE_TSA)) |
3092 | break; | ||
3093 | case NES_CM_EVENT_DROPPED_PKT: | ||
3094 | nes_debug(NES_DBG_CM, "CM Event: DROPPED PKT\n"); | ||
3095 | break; | ||
3096 | default: | ||
3097 | nes_debug(NES_DBG_CM, "CM Event: UNKNOWN EVENT TYPE\n"); | ||
3098 | break; | 3325 | break; |
3326 | cm_event_connect_error(event); | ||
3327 | nes_debug(NES_DBG_CM, "CM Event: ABORTED\n"); | ||
3328 | break; | ||
3329 | case NES_CM_EVENT_DROPPED_PKT: | ||
3330 | nes_debug(NES_DBG_CM, "CM Event: DROPPED PKT\n"); | ||
3331 | break; | ||
3332 | default: | ||
3333 | nes_debug(NES_DBG_CM, "CM Event: UNKNOWN EVENT TYPE\n"); | ||
3334 | break; | ||
3099 | } | 3335 | } |
3100 | 3336 | ||
3101 | atomic_dec(&cm_core->events_posted); | 3337 | atomic_dec(&cm_core->events_posted); |
diff --git a/drivers/infiniband/hw/nes/nes_cm.h b/drivers/infiniband/hw/nes/nes_cm.h index 7717cb2ab500..367b3d290140 100644 --- a/drivers/infiniband/hw/nes/nes_cm.h +++ b/drivers/infiniband/hw/nes/nes_cm.h | |||
@@ -83,6 +83,8 @@ enum nes_timer_type { | |||
83 | #define SET_FIN 4 | 83 | #define SET_FIN 4 |
84 | #define SET_RST 8 | 84 | #define SET_RST 8 |
85 | 85 | ||
86 | #define TCP_OPTIONS_PADDING 3 | ||
87 | |||
86 | struct option_base { | 88 | struct option_base { |
87 | u8 optionnum; | 89 | u8 optionnum; |
88 | u8 length; | 90 | u8 length; |
@@ -177,6 +179,7 @@ enum nes_cm_node_state { | |||
177 | NES_CM_STATE_ESTABLISHED, | 179 | NES_CM_STATE_ESTABLISHED, |
178 | NES_CM_STATE_ACCEPTING, | 180 | NES_CM_STATE_ACCEPTING, |
179 | NES_CM_STATE_MPAREQ_SENT, | 181 | NES_CM_STATE_MPAREQ_SENT, |
182 | NES_CM_STATE_MPAREQ_RCVD, | ||
180 | NES_CM_STATE_TSA, | 183 | NES_CM_STATE_TSA, |
181 | NES_CM_STATE_FIN_WAIT1, | 184 | NES_CM_STATE_FIN_WAIT1, |
182 | NES_CM_STATE_FIN_WAIT2, | 185 | NES_CM_STATE_FIN_WAIT2, |
@@ -187,6 +190,16 @@ enum nes_cm_node_state { | |||
187 | NES_CM_STATE_CLOSED | 190 | NES_CM_STATE_CLOSED |
188 | }; | 191 | }; |
189 | 192 | ||
193 | enum nes_tcpip_pkt_type { | ||
194 | NES_PKT_TYPE_UNKNOWN, | ||
195 | NES_PKT_TYPE_SYN, | ||
196 | NES_PKT_TYPE_SYNACK, | ||
197 | NES_PKT_TYPE_ACK, | ||
198 | NES_PKT_TYPE_FIN, | ||
199 | NES_PKT_TYPE_RST | ||
200 | }; | ||
201 | |||
202 | |||
190 | /* type of nes connection */ | 203 | /* type of nes connection */ |
191 | enum nes_cm_conn_type { | 204 | enum nes_cm_conn_type { |
192 | NES_CM_IWARP_CONN_TYPE, | 205 | NES_CM_IWARP_CONN_TYPE, |
@@ -257,7 +270,9 @@ struct nes_cm_node { | |||
257 | struct net_device *netdev; | 270 | struct net_device *netdev; |
258 | 271 | ||
259 | struct nes_cm_node *loopbackpartner; | 272 | struct nes_cm_node *loopbackpartner; |
260 | struct list_head retrans_list; | 273 | |
274 | struct nes_timer_entry *send_entry; | ||
275 | |||
261 | spinlock_t retrans_list_lock; | 276 | spinlock_t retrans_list_lock; |
262 | struct list_head recv_list; | 277 | struct list_head recv_list; |
263 | spinlock_t recv_list_lock; | 278 | spinlock_t recv_list_lock; |
@@ -276,6 +291,8 @@ struct nes_cm_node { | |||
276 | struct nes_vnic *nesvnic; | 291 | struct nes_vnic *nesvnic; |
277 | int apbvt_set; | 292 | int apbvt_set; |
278 | int accept_pend; | 293 | int accept_pend; |
294 | int freed; | ||
295 | struct nes_qp *nesqp; | ||
279 | }; | 296 | }; |
280 | 297 | ||
281 | /* structure for client or CM to fill when making CM api calls. */ | 298 | /* structure for client or CM to fill when making CM api calls. */ |
@@ -366,14 +383,14 @@ struct nes_cm_ops { | |||
366 | struct nes_cm_info *); | 383 | struct nes_cm_info *); |
367 | int (*stop_listener)(struct nes_cm_core *, struct nes_cm_listener *); | 384 | int (*stop_listener)(struct nes_cm_core *, struct nes_cm_listener *); |
368 | struct nes_cm_node * (*connect)(struct nes_cm_core *, | 385 | struct nes_cm_node * (*connect)(struct nes_cm_core *, |
369 | struct nes_vnic *, struct ietf_mpa_frame *, | 386 | struct nes_vnic *, u16, void *, |
370 | struct nes_cm_info *); | 387 | struct nes_cm_info *); |
371 | int (*close)(struct nes_cm_core *, struct nes_cm_node *); | 388 | int (*close)(struct nes_cm_core *, struct nes_cm_node *); |
372 | int (*accept)(struct nes_cm_core *, struct ietf_mpa_frame *, | 389 | int (*accept)(struct nes_cm_core *, struct ietf_mpa_frame *, |
373 | struct nes_cm_node *); | 390 | struct nes_cm_node *); |
374 | int (*reject)(struct nes_cm_core *, struct ietf_mpa_frame *, | 391 | int (*reject)(struct nes_cm_core *, struct ietf_mpa_frame *, |
375 | struct nes_cm_node *); | 392 | struct nes_cm_node *); |
376 | int (*recv_pkt)(struct nes_cm_core *, struct nes_vnic *, | 393 | void (*recv_pkt)(struct nes_cm_core *, struct nes_vnic *, |
377 | struct sk_buff *); | 394 | struct sk_buff *); |
378 | int (*destroy_cm_core)(struct nes_cm_core *); | 395 | int (*destroy_cm_core)(struct nes_cm_core *); |
379 | int (*get)(struct nes_cm_core *); | 396 | int (*get)(struct nes_cm_core *); |
diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c index 85f26d19a32b..1513d4066f1b 100644 --- a/drivers/infiniband/hw/nes/nes_hw.c +++ b/drivers/infiniband/hw/nes/nes_hw.c | |||
@@ -2814,7 +2814,6 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev, | |||
2814 | nesqp = *((struct nes_qp **)&context); | 2814 | nesqp = *((struct nes_qp **)&context); |
2815 | if (atomic_inc_return(&nesqp->close_timer_started) == 1) { | 2815 | if (atomic_inc_return(&nesqp->close_timer_started) == 1) { |
2816 | nesqp->cm_id->add_ref(nesqp->cm_id); | 2816 | nesqp->cm_id->add_ref(nesqp->cm_id); |
2817 | nes_add_ref(&nesqp->ibqp); | ||
2818 | schedule_nes_timer(nesqp->cm_node, (struct sk_buff *)nesqp, | 2817 | schedule_nes_timer(nesqp->cm_node, (struct sk_buff *)nesqp, |
2819 | NES_TIMER_TYPE_CLOSE, 1, 0); | 2818 | NES_TIMER_TYPE_CLOSE, 1, 0); |
2820 | nes_debug(NES_DBG_AEQ, "QP%u Not decrementing QP refcount (%d)," | 2819 | nes_debug(NES_DBG_AEQ, "QP%u Not decrementing QP refcount (%d)," |
@@ -2838,7 +2837,6 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev, | |||
2838 | if (async_event_id == NES_AEQE_AEID_RESET_SENT) { | 2837 | if (async_event_id == NES_AEQE_AEID_RESET_SENT) { |
2839 | tcp_state = NES_AEQE_TCP_STATE_CLOSED; | 2838 | tcp_state = NES_AEQE_TCP_STATE_CLOSED; |
2840 | } | 2839 | } |
2841 | nes_add_ref(&nesqp->ibqp); | ||
2842 | spin_lock_irqsave(&nesqp->lock, flags); | 2840 | spin_lock_irqsave(&nesqp->lock, flags); |
2843 | nesqp->hw_iwarp_state = iwarp_state; | 2841 | nesqp->hw_iwarp_state = iwarp_state; |
2844 | nesqp->hw_tcp_state = tcp_state; | 2842 | nesqp->hw_tcp_state = tcp_state; |
@@ -2876,7 +2874,6 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev, | |||
2876 | } | 2874 | } |
2877 | spin_unlock_irqrestore(&nesqp->lock, flags); | 2875 | spin_unlock_irqrestore(&nesqp->lock, flags); |
2878 | if (next_iwarp_state) { | 2876 | if (next_iwarp_state) { |
2879 | nes_add_ref(&nesqp->ibqp); | ||
2880 | nes_debug(NES_DBG_AEQ, "issuing hw modifyqp for QP%u. next state = 0x%08X," | 2877 | nes_debug(NES_DBG_AEQ, "issuing hw modifyqp for QP%u. next state = 0x%08X," |
2881 | " also added another reference\n", | 2878 | " also added another reference\n", |
2882 | nesqp->hwqp.qp_id, next_iwarp_state); | 2879 | nesqp->hwqp.qp_id, next_iwarp_state); |
@@ -2888,7 +2885,6 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev, | |||
2888 | /* FIN Received but ib state not RTS, | 2885 | /* FIN Received but ib state not RTS, |
2889 | close complete will be on its way */ | 2886 | close complete will be on its way */ |
2890 | spin_unlock_irqrestore(&nesqp->lock, flags); | 2887 | spin_unlock_irqrestore(&nesqp->lock, flags); |
2891 | nes_rem_ref(&nesqp->ibqp); | ||
2892 | return; | 2888 | return; |
2893 | } | 2889 | } |
2894 | spin_unlock_irqrestore(&nesqp->lock, flags); | 2890 | spin_unlock_irqrestore(&nesqp->lock, flags); |
@@ -2922,7 +2918,6 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev, | |||
2922 | if ((tcp_state == NES_AEQE_TCP_STATE_CLOSE_WAIT) || | 2918 | if ((tcp_state == NES_AEQE_TCP_STATE_CLOSE_WAIT) || |
2923 | ((nesqp->ibqp_state == IB_QPS_RTS)&& | 2919 | ((nesqp->ibqp_state == IB_QPS_RTS)&& |
2924 | (async_event_id == NES_AEQE_AEID_LLP_CONNECTION_RESET))) { | 2920 | (async_event_id == NES_AEQE_AEID_LLP_CONNECTION_RESET))) { |
2925 | nes_add_ref(&nesqp->ibqp); | ||
2926 | nes_cm_disconn(nesqp); | 2921 | nes_cm_disconn(nesqp); |
2927 | } else { | 2922 | } else { |
2928 | nesqp->in_disconnect = 0; | 2923 | nesqp->in_disconnect = 0; |
@@ -2931,7 +2926,6 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev, | |||
2931 | break; | 2926 | break; |
2932 | case NES_AEQE_AEID_LLP_TOO_MANY_RETRIES: | 2927 | case NES_AEQE_AEID_LLP_TOO_MANY_RETRIES: |
2933 | nesqp = *((struct nes_qp **)&context); | 2928 | nesqp = *((struct nes_qp **)&context); |
2934 | nes_add_ref(&nesqp->ibqp); | ||
2935 | spin_lock_irqsave(&nesqp->lock, flags); | 2929 | spin_lock_irqsave(&nesqp->lock, flags); |
2936 | nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_ERROR; | 2930 | nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_ERROR; |
2937 | nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED; | 2931 | nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED; |
@@ -3042,7 +3036,6 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev, | |||
3042 | nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context); | 3036 | nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context); |
3043 | } | 3037 | } |
3044 | /* tell cm to disconnect, cm will queue work to thread */ | 3038 | /* tell cm to disconnect, cm will queue work to thread */ |
3045 | nes_add_ref(&nesqp->ibqp); | ||
3046 | nes_cm_disconn(nesqp); | 3039 | nes_cm_disconn(nesqp); |
3047 | break; | 3040 | break; |
3048 | case NES_AEQE_AEID_DDP_UBE_INVALID_MSN_NO_BUFFER_AVAILABLE: | 3041 | case NES_AEQE_AEID_DDP_UBE_INVALID_MSN_NO_BUFFER_AVAILABLE: |
@@ -3062,7 +3055,6 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev, | |||
3062 | nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context); | 3055 | nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context); |
3063 | } | 3056 | } |
3064 | /* tell cm to disconnect, cm will queue work to thread */ | 3057 | /* tell cm to disconnect, cm will queue work to thread */ |
3065 | nes_add_ref(&nesqp->ibqp); | ||
3066 | nes_cm_disconn(nesqp); | 3058 | nes_cm_disconn(nesqp); |
3067 | break; | 3059 | break; |
3068 | case NES_AEQE_AEID_LLP_RECEIVED_MPA_CRC_ERROR: | 3060 | case NES_AEQE_AEID_LLP_RECEIVED_MPA_CRC_ERROR: |
@@ -3082,7 +3074,6 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev, | |||
3082 | nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context); | 3074 | nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context); |
3083 | } | 3075 | } |
3084 | /* tell cm to disconnect, cm will queue work to thread */ | 3076 | /* tell cm to disconnect, cm will queue work to thread */ |
3085 | nes_add_ref(&nesqp->ibqp); | ||
3086 | nes_cm_disconn(nesqp); | 3077 | nes_cm_disconn(nesqp); |
3087 | break; | 3078 | break; |
3088 | /* TODO: additional AEs need to be here */ | 3079 | /* TODO: additional AEs need to be here */ |
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c index e3939d13484e..d79942e84979 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.c +++ b/drivers/infiniband/hw/nes/nes_verbs.c | |||
@@ -2867,7 +2867,6 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, | |||
2867 | nesqp->hwqp.qp_id, attr->qp_state, nesqp->ibqp_state, | 2867 | nesqp->hwqp.qp_id, attr->qp_state, nesqp->ibqp_state, |
2868 | nesqp->iwarp_state, atomic_read(&nesqp->refcount)); | 2868 | nesqp->iwarp_state, atomic_read(&nesqp->refcount)); |
2869 | 2869 | ||
2870 | nes_add_ref(&nesqp->ibqp); | ||
2871 | spin_lock_irqsave(&nesqp->lock, qplockflags); | 2870 | spin_lock_irqsave(&nesqp->lock, qplockflags); |
2872 | 2871 | ||
2873 | nes_debug(NES_DBG_MOD_QP, "QP%u: hw_iwarp_state=0x%X, hw_tcp_state=0x%X," | 2872 | nes_debug(NES_DBG_MOD_QP, "QP%u: hw_iwarp_state=0x%X, hw_tcp_state=0x%X," |
@@ -2882,7 +2881,6 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, | |||
2882 | nesqp->hwqp.qp_id); | 2881 | nesqp->hwqp.qp_id); |
2883 | if (nesqp->iwarp_state > (u32)NES_CQP_QP_IWARP_STATE_IDLE) { | 2882 | if (nesqp->iwarp_state > (u32)NES_CQP_QP_IWARP_STATE_IDLE) { |
2884 | spin_unlock_irqrestore(&nesqp->lock, qplockflags); | 2883 | spin_unlock_irqrestore(&nesqp->lock, qplockflags); |
2885 | nes_rem_ref(&nesqp->ibqp); | ||
2886 | return -EINVAL; | 2884 | return -EINVAL; |
2887 | } | 2885 | } |
2888 | next_iwarp_state = NES_CQP_QP_IWARP_STATE_IDLE; | 2886 | next_iwarp_state = NES_CQP_QP_IWARP_STATE_IDLE; |
@@ -2893,7 +2891,6 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, | |||
2893 | nesqp->hwqp.qp_id); | 2891 | nesqp->hwqp.qp_id); |
2894 | if (nesqp->iwarp_state>(u32)NES_CQP_QP_IWARP_STATE_IDLE) { | 2892 | if (nesqp->iwarp_state>(u32)NES_CQP_QP_IWARP_STATE_IDLE) { |
2895 | spin_unlock_irqrestore(&nesqp->lock, qplockflags); | 2893 | spin_unlock_irqrestore(&nesqp->lock, qplockflags); |
2896 | nes_rem_ref(&nesqp->ibqp); | ||
2897 | return -EINVAL; | 2894 | return -EINVAL; |
2898 | } | 2895 | } |
2899 | next_iwarp_state = NES_CQP_QP_IWARP_STATE_IDLE; | 2896 | next_iwarp_state = NES_CQP_QP_IWARP_STATE_IDLE; |
@@ -2904,14 +2901,12 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, | |||
2904 | nesqp->hwqp.qp_id); | 2901 | nesqp->hwqp.qp_id); |
2905 | if (nesqp->iwarp_state>(u32)NES_CQP_QP_IWARP_STATE_RTS) { | 2902 | if (nesqp->iwarp_state>(u32)NES_CQP_QP_IWARP_STATE_RTS) { |
2906 | spin_unlock_irqrestore(&nesqp->lock, qplockflags); | 2903 | spin_unlock_irqrestore(&nesqp->lock, qplockflags); |
2907 | nes_rem_ref(&nesqp->ibqp); | ||
2908 | return -EINVAL; | 2904 | return -EINVAL; |
2909 | } | 2905 | } |
2910 | if (nesqp->cm_id == NULL) { | 2906 | if (nesqp->cm_id == NULL) { |
2911 | nes_debug(NES_DBG_MOD_QP, "QP%u: Failing attempt to move QP to RTS without a CM_ID. \n", | 2907 | nes_debug(NES_DBG_MOD_QP, "QP%u: Failing attempt to move QP to RTS without a CM_ID. \n", |
2912 | nesqp->hwqp.qp_id ); | 2908 | nesqp->hwqp.qp_id ); |
2913 | spin_unlock_irqrestore(&nesqp->lock, qplockflags); | 2909 | spin_unlock_irqrestore(&nesqp->lock, qplockflags); |
2914 | nes_rem_ref(&nesqp->ibqp); | ||
2915 | return -EINVAL; | 2910 | return -EINVAL; |
2916 | } | 2911 | } |
2917 | next_iwarp_state = NES_CQP_QP_IWARP_STATE_RTS; | 2912 | next_iwarp_state = NES_CQP_QP_IWARP_STATE_RTS; |
@@ -2929,7 +2924,6 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, | |||
2929 | nesqp->hwqp.qp_id, nesqp->hwqp.sq_head, nesqp->hwqp.sq_tail); | 2924 | nesqp->hwqp.qp_id, nesqp->hwqp.sq_head, nesqp->hwqp.sq_tail); |
2930 | if (nesqp->iwarp_state == (u32)NES_CQP_QP_IWARP_STATE_CLOSING) { | 2925 | if (nesqp->iwarp_state == (u32)NES_CQP_QP_IWARP_STATE_CLOSING) { |
2931 | spin_unlock_irqrestore(&nesqp->lock, qplockflags); | 2926 | spin_unlock_irqrestore(&nesqp->lock, qplockflags); |
2932 | nes_rem_ref(&nesqp->ibqp); | ||
2933 | return 0; | 2927 | return 0; |
2934 | } else { | 2928 | } else { |
2935 | if (nesqp->iwarp_state > (u32)NES_CQP_QP_IWARP_STATE_CLOSING) { | 2929 | if (nesqp->iwarp_state > (u32)NES_CQP_QP_IWARP_STATE_CLOSING) { |
@@ -2937,7 +2931,6 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, | |||
2937 | " ignored due to current iWARP state\n", | 2931 | " ignored due to current iWARP state\n", |
2938 | nesqp->hwqp.qp_id); | 2932 | nesqp->hwqp.qp_id); |
2939 | spin_unlock_irqrestore(&nesqp->lock, qplockflags); | 2933 | spin_unlock_irqrestore(&nesqp->lock, qplockflags); |
2940 | nes_rem_ref(&nesqp->ibqp); | ||
2941 | return -EINVAL; | 2934 | return -EINVAL; |
2942 | } | 2935 | } |
2943 | if (nesqp->hw_iwarp_state != NES_AEQE_IWARP_STATE_RTS) { | 2936 | if (nesqp->hw_iwarp_state != NES_AEQE_IWARP_STATE_RTS) { |
@@ -2969,7 +2962,6 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, | |||
2969 | nesqp->hwqp.qp_id); | 2962 | nesqp->hwqp.qp_id); |
2970 | if (nesqp->iwarp_state>=(u32)NES_CQP_QP_IWARP_STATE_TERMINATE) { | 2963 | if (nesqp->iwarp_state>=(u32)NES_CQP_QP_IWARP_STATE_TERMINATE) { |
2971 | spin_unlock_irqrestore(&nesqp->lock, qplockflags); | 2964 | spin_unlock_irqrestore(&nesqp->lock, qplockflags); |
2972 | nes_rem_ref(&nesqp->ibqp); | ||
2973 | return -EINVAL; | 2965 | return -EINVAL; |
2974 | } | 2966 | } |
2975 | /* next_iwarp_state = (NES_CQP_QP_IWARP_STATE_TERMINATE | 0x02000000); */ | 2967 | /* next_iwarp_state = (NES_CQP_QP_IWARP_STATE_TERMINATE | 0x02000000); */ |
@@ -2982,7 +2974,6 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, | |||
2982 | case IB_QPS_RESET: | 2974 | case IB_QPS_RESET: |
2983 | if (nesqp->iwarp_state == (u32)NES_CQP_QP_IWARP_STATE_ERROR) { | 2975 | if (nesqp->iwarp_state == (u32)NES_CQP_QP_IWARP_STATE_ERROR) { |
2984 | spin_unlock_irqrestore(&nesqp->lock, qplockflags); | 2976 | spin_unlock_irqrestore(&nesqp->lock, qplockflags); |
2985 | nes_rem_ref(&nesqp->ibqp); | ||
2986 | return -EINVAL; | 2977 | return -EINVAL; |
2987 | } | 2978 | } |
2988 | nes_debug(NES_DBG_MOD_QP, "QP%u: new state = error\n", | 2979 | nes_debug(NES_DBG_MOD_QP, "QP%u: new state = error\n", |
@@ -3008,7 +2999,6 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, | |||
3008 | break; | 2999 | break; |
3009 | default: | 3000 | default: |
3010 | spin_unlock_irqrestore(&nesqp->lock, qplockflags); | 3001 | spin_unlock_irqrestore(&nesqp->lock, qplockflags); |
3011 | nes_rem_ref(&nesqp->ibqp); | ||
3012 | return -EINVAL; | 3002 | return -EINVAL; |
3013 | break; | 3003 | break; |
3014 | } | 3004 | } |
@@ -3088,7 +3078,6 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, | |||
3088 | nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount), | 3078 | nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount), |
3089 | original_last_aeq, nesqp->last_aeq); | 3079 | original_last_aeq, nesqp->last_aeq); |
3090 | /* this one is for the cm_disconnect thread */ | 3080 | /* this one is for the cm_disconnect thread */ |
3091 | nes_add_ref(&nesqp->ibqp); | ||
3092 | spin_lock_irqsave(&nesqp->lock, qplockflags); | 3081 | spin_lock_irqsave(&nesqp->lock, qplockflags); |
3093 | nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED; | 3082 | nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED; |
3094 | nesqp->last_aeq = NES_AEQE_AEID_RESET_SENT; | 3083 | nesqp->last_aeq = NES_AEQE_AEID_RESET_SENT; |
@@ -3097,14 +3086,12 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, | |||
3097 | } else { | 3086 | } else { |
3098 | nes_debug(NES_DBG_MOD_QP, "QP%u No fake disconnect, QP refcount=%d\n", | 3087 | nes_debug(NES_DBG_MOD_QP, "QP%u No fake disconnect, QP refcount=%d\n", |
3099 | nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount)); | 3088 | nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount)); |
3100 | nes_rem_ref(&nesqp->ibqp); | ||
3101 | } | 3089 | } |
3102 | } else { | 3090 | } else { |
3103 | spin_lock_irqsave(&nesqp->lock, qplockflags); | 3091 | spin_lock_irqsave(&nesqp->lock, qplockflags); |
3104 | if (nesqp->cm_id) { | 3092 | if (nesqp->cm_id) { |
3105 | /* These two are for the timer thread */ | 3093 | /* These two are for the timer thread */ |
3106 | if (atomic_inc_return(&nesqp->close_timer_started) == 1) { | 3094 | if (atomic_inc_return(&nesqp->close_timer_started) == 1) { |
3107 | nes_add_ref(&nesqp->ibqp); | ||
3108 | nesqp->cm_id->add_ref(nesqp->cm_id); | 3095 | nesqp->cm_id->add_ref(nesqp->cm_id); |
3109 | nes_debug(NES_DBG_MOD_QP, "QP%u Not decrementing QP refcount (%d)," | 3096 | nes_debug(NES_DBG_MOD_QP, "QP%u Not decrementing QP refcount (%d)," |
3110 | " need ae to finish up, original_last_aeq = 0x%04X." | 3097 | " need ae to finish up, original_last_aeq = 0x%04X." |
@@ -3128,14 +3115,12 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, | |||
3128 | " original_last_aeq = 0x%04X. last_aeq = 0x%04X.\n", | 3115 | " original_last_aeq = 0x%04X. last_aeq = 0x%04X.\n", |
3129 | nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount), | 3116 | nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount), |
3130 | original_last_aeq, nesqp->last_aeq); | 3117 | original_last_aeq, nesqp->last_aeq); |
3131 | nes_rem_ref(&nesqp->ibqp); | ||
3132 | } | 3118 | } |
3133 | } else { | 3119 | } else { |
3134 | nes_debug(NES_DBG_MOD_QP, "QP%u Decrementing QP refcount (%d), No ae to finish up," | 3120 | nes_debug(NES_DBG_MOD_QP, "QP%u Decrementing QP refcount (%d), No ae to finish up," |
3135 | " original_last_aeq = 0x%04X. last_aeq = 0x%04X.\n", | 3121 | " original_last_aeq = 0x%04X. last_aeq = 0x%04X.\n", |
3136 | nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount), | 3122 | nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount), |
3137 | original_last_aeq, nesqp->last_aeq); | 3123 | original_last_aeq, nesqp->last_aeq); |
3138 | nes_rem_ref(&nesqp->ibqp); | ||
3139 | } | 3124 | } |
3140 | 3125 | ||
3141 | err = 0; | 3126 | err = 0; |
diff --git a/drivers/infiniband/ulp/ipoib/Kconfig b/drivers/infiniband/ulp/ipoib/Kconfig index 691525cf394a..9d9a9dc51f18 100644 --- a/drivers/infiniband/ulp/ipoib/Kconfig +++ b/drivers/infiniband/ulp/ipoib/Kconfig | |||
@@ -11,16 +11,17 @@ config INFINIBAND_IPOIB | |||
11 | 11 | ||
12 | config INFINIBAND_IPOIB_CM | 12 | config INFINIBAND_IPOIB_CM |
13 | bool "IP-over-InfiniBand Connected Mode support" | 13 | bool "IP-over-InfiniBand Connected Mode support" |
14 | depends on INFINIBAND_IPOIB && EXPERIMENTAL | 14 | depends on INFINIBAND_IPOIB |
15 | default n | 15 | default n |
16 | ---help--- | 16 | ---help--- |
17 | This option enables experimental support for IPoIB connected mode. | 17 | This option enables support for IPoIB connected mode. After |
18 | After enabling this option, you need to switch to connected mode through | 18 | enabling this option, you need to switch to connected mode |
19 | /sys/class/net/ibXXX/mode to actually create connections, and then increase | 19 | through /sys/class/net/ibXXX/mode to actually create |
20 | the interface MTU with e.g. ifconfig ib0 mtu 65520. | 20 | connections, and then increase the interface MTU with |
21 | e.g. ifconfig ib0 mtu 65520. | ||
21 | 22 | ||
22 | WARNING: Enabling connected mode will trigger some | 23 | WARNING: Enabling connected mode will trigger some packet |
23 | packet drops for multicast and UD mode traffic from this interface, | 24 | drops for multicast and UD mode traffic from this interface, |
24 | unless you limit mtu for these destinations to 2044. | 25 | unless you limit mtu for these destinations to 2044. |
25 | 26 | ||
26 | config INFINIBAND_IPOIB_DEBUG | 27 | config INFINIBAND_IPOIB_DEBUG |
@@ -33,9 +34,10 @@ config INFINIBAND_IPOIB_DEBUG | |||
33 | debug_level and mcast_debug_level module parameters (which | 34 | debug_level and mcast_debug_level module parameters (which |
34 | can also be set after the driver is loaded through sysfs). | 35 | can also be set after the driver is loaded through sysfs). |
35 | 36 | ||
36 | This option also creates an "ipoib_debugfs," which can be | 37 | This option also creates a directory tree under ipoib/ in |
37 | mounted to expose debugging information about IB multicast | 38 | debugfs, which contains files that expose debugging |
38 | groups used by the IPoIB driver. | 39 | information about IB multicast groups used by the IPoIB |
40 | driver. | ||
39 | 41 | ||
40 | config INFINIBAND_IPOIB_DEBUG_DATA | 42 | config INFINIBAND_IPOIB_DEBUG_DATA |
41 | bool "IP-over-InfiniBand data path debugging" | 43 | bool "IP-over-InfiniBand data path debugging" |