diff options
-rw-r--r-- | drivers/infiniband/hw/nes/nes_cm.c | 1102 | ||||
-rw-r--r-- | drivers/infiniband/hw/nes/nes_cm.h | 73 | ||||
-rw-r--r-- | drivers/infiniband/hw/nes/nes_verbs.h | 3 |
3 files changed, 703 insertions, 475 deletions
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index c118663e4437..7dc43ea7d4e7 100644 --- a/drivers/infiniband/hw/nes/nes_cm.c +++ b/drivers/infiniband/hw/nes/nes_cm.c | |||
@@ -77,26 +77,19 @@ atomic_t cm_nodes_destroyed; | |||
77 | atomic_t cm_accel_dropped_pkts; | 77 | atomic_t cm_accel_dropped_pkts; |
78 | atomic_t cm_resets_recvd; | 78 | atomic_t cm_resets_recvd; |
79 | 79 | ||
80 | static inline int mini_cm_accelerated(struct nes_cm_core *, | 80 | static inline int mini_cm_accelerated(struct nes_cm_core *, struct nes_cm_node *); |
81 | struct nes_cm_node *); | 81 | static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *, struct nes_vnic *, struct nes_cm_info *); |
82 | static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *, | ||
83 | struct nes_vnic *, struct nes_cm_info *); | ||
84 | static int mini_cm_del_listen(struct nes_cm_core *, struct nes_cm_listener *); | 82 | static int mini_cm_del_listen(struct nes_cm_core *, struct nes_cm_listener *); |
85 | static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *, | 83 | static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *, struct nes_vnic *, u16, void *, struct nes_cm_info *); |
86 | struct nes_vnic *, u16, void *, struct nes_cm_info *); | ||
87 | static int mini_cm_close(struct nes_cm_core *, struct nes_cm_node *); | 84 | static int mini_cm_close(struct nes_cm_core *, struct nes_cm_node *); |
88 | static int mini_cm_accept(struct nes_cm_core *, struct ietf_mpa_frame *, | 85 | static int mini_cm_accept(struct nes_cm_core *, struct nes_cm_node *); |
89 | struct nes_cm_node *); | 86 | static int mini_cm_reject(struct nes_cm_core *, struct nes_cm_node *); |
90 | static int mini_cm_reject(struct nes_cm_core *, struct ietf_mpa_frame *, | 87 | static int mini_cm_recv_pkt(struct nes_cm_core *, struct nes_vnic *, struct sk_buff *); |
91 | struct nes_cm_node *); | ||
92 | static int mini_cm_recv_pkt(struct nes_cm_core *, struct nes_vnic *, | ||
93 | struct sk_buff *); | ||
94 | static int mini_cm_dealloc_core(struct nes_cm_core *); | 88 | static int mini_cm_dealloc_core(struct nes_cm_core *); |
95 | static int mini_cm_get(struct nes_cm_core *); | 89 | static int mini_cm_get(struct nes_cm_core *); |
96 | static int mini_cm_set(struct nes_cm_core *, u32, u32); | 90 | static int mini_cm_set(struct nes_cm_core *, u32, u32); |
97 | 91 | ||
98 | static void form_cm_frame(struct sk_buff *, struct nes_cm_node *, | 92 | static void form_cm_frame(struct sk_buff *, struct nes_cm_node *, void *, u32, void *, u32, u8); |
99 | void *, u32, void *, u32, u8); | ||
100 | static int add_ref_cm_node(struct nes_cm_node *); | 93 | static int add_ref_cm_node(struct nes_cm_node *); |
101 | static int rem_ref_cm_node(struct nes_cm_core *, struct nes_cm_node *); | 94 | static int rem_ref_cm_node(struct nes_cm_core *, struct nes_cm_node *); |
102 | 95 | ||
@@ -111,16 +104,14 @@ static int send_syn(struct nes_cm_node *, u32, struct sk_buff *); | |||
111 | static int send_reset(struct nes_cm_node *, struct sk_buff *); | 104 | static int send_reset(struct nes_cm_node *, struct sk_buff *); |
112 | static int send_ack(struct nes_cm_node *cm_node, struct sk_buff *skb); | 105 | static int send_ack(struct nes_cm_node *cm_node, struct sk_buff *skb); |
113 | static int send_fin(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); |
114 | static void process_packet(struct nes_cm_node *, struct sk_buff *, | 107 | static void process_packet(struct nes_cm_node *, struct sk_buff *, struct nes_cm_core *); |
115 | struct nes_cm_core *); | ||
116 | 108 | ||
117 | static void active_open_err(struct nes_cm_node *, struct sk_buff *, int); | 109 | static void active_open_err(struct nes_cm_node *, struct sk_buff *, int); |
118 | static void passive_open_err(struct nes_cm_node *, struct sk_buff *, int); | 110 | static void passive_open_err(struct nes_cm_node *, struct sk_buff *, int); |
119 | static void cleanup_retrans_entry(struct nes_cm_node *); | 111 | static void cleanup_retrans_entry(struct nes_cm_node *); |
120 | static void handle_rcv_mpa(struct nes_cm_node *, struct sk_buff *); | 112 | static void handle_rcv_mpa(struct nes_cm_node *, struct sk_buff *); |
121 | static void free_retrans_entry(struct nes_cm_node *cm_node); | 113 | static void free_retrans_entry(struct nes_cm_node *cm_node); |
122 | static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph, | 114 | static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph, struct sk_buff *skb, int optionsize, int passive); |
123 | struct sk_buff *skb, int optionsize, int passive); | ||
124 | 115 | ||
125 | /* CM event handler functions */ | 116 | /* CM event handler functions */ |
126 | static void cm_event_connected(struct nes_cm_event *); | 117 | static void cm_event_connected(struct nes_cm_event *); |
@@ -130,6 +121,12 @@ static void cm_event_mpa_req(struct nes_cm_event *); | |||
130 | static void cm_event_mpa_reject(struct nes_cm_event *); | 121 | static void cm_event_mpa_reject(struct nes_cm_event *); |
131 | static void handle_recv_entry(struct nes_cm_node *cm_node, u32 rem_node); | 122 | static void handle_recv_entry(struct nes_cm_node *cm_node, u32 rem_node); |
132 | 123 | ||
124 | /* MPA build functions */ | ||
125 | static int cm_build_mpa_frame(struct nes_cm_node *, u8 **, u16 *, u8 *, u8); | ||
126 | static void build_mpa_v2(struct nes_cm_node *, void *, u8); | ||
127 | static void build_mpa_v1(struct nes_cm_node *, void *, u8); | ||
128 | static void build_rdma0_msg(struct nes_cm_node *, struct nes_qp **); | ||
129 | |||
133 | static void print_core(struct nes_cm_core *core); | 130 | static void print_core(struct nes_cm_core *core); |
134 | 131 | ||
135 | /* External CM API Interface */ | 132 | /* External CM API Interface */ |
@@ -163,8 +160,8 @@ atomic_t cm_rejects; | |||
163 | /** | 160 | /** |
164 | * create_event | 161 | * create_event |
165 | */ | 162 | */ |
166 | static struct nes_cm_event *create_event(struct nes_cm_node *cm_node, | 163 | static struct nes_cm_event *create_event(struct nes_cm_node * cm_node, |
167 | enum nes_cm_event_type type) | 164 | enum nes_cm_event_type type) |
168 | { | 165 | { |
169 | struct nes_cm_event *event; | 166 | struct nes_cm_event *event; |
170 | 167 | ||
@@ -186,10 +183,10 @@ static struct nes_cm_event *create_event(struct nes_cm_node *cm_node, | |||
186 | event->cm_info.cm_id = cm_node->cm_id; | 183 | event->cm_info.cm_id = cm_node->cm_id; |
187 | 184 | ||
188 | nes_debug(NES_DBG_CM, "cm_node=%p Created event=%p, type=%u, " | 185 | nes_debug(NES_DBG_CM, "cm_node=%p Created event=%p, type=%u, " |
189 | "dst_addr=%08x[%x], src_addr=%08x[%x]\n", | 186 | "dst_addr=%08x[%x], src_addr=%08x[%x]\n", |
190 | cm_node, event, type, event->cm_info.loc_addr, | 187 | cm_node, event, type, event->cm_info.loc_addr, |
191 | event->cm_info.loc_port, event->cm_info.rem_addr, | 188 | event->cm_info.loc_port, event->cm_info.rem_addr, |
192 | event->cm_info.rem_port); | 189 | event->cm_info.rem_port); |
193 | 190 | ||
194 | nes_cm_post_event(event); | 191 | nes_cm_post_event(event); |
195 | return event; | 192 | return event; |
@@ -201,14 +198,19 @@ static struct nes_cm_event *create_event(struct nes_cm_node *cm_node, | |||
201 | */ | 198 | */ |
202 | static int send_mpa_request(struct nes_cm_node *cm_node, struct sk_buff *skb) | 199 | static int send_mpa_request(struct nes_cm_node *cm_node, struct sk_buff *skb) |
203 | { | 200 | { |
201 | u8 start_addr = 0; | ||
202 | u8 *start_ptr = &start_addr; | ||
203 | u8 **start_buff = &start_ptr; | ||
204 | u16 buff_len = 0; | ||
205 | |||
204 | if (!skb) { | 206 | if (!skb) { |
205 | nes_debug(NES_DBG_CM, "skb set to NULL\n"); | 207 | nes_debug(NES_DBG_CM, "skb set to NULL\n"); |
206 | return -1; | 208 | return -1; |
207 | } | 209 | } |
208 | 210 | ||
209 | /* send an MPA Request frame */ | 211 | /* send an MPA Request frame */ |
210 | form_cm_frame(skb, cm_node, NULL, 0, &cm_node->mpa_frame, | 212 | cm_build_mpa_frame(cm_node, start_buff, &buff_len, NULL, MPA_KEY_REQUEST); |
211 | cm_node->mpa_frame_size, SET_ACK); | 213 | form_cm_frame(skb, cm_node, NULL, 0, *start_buff, buff_len, SET_ACK); |
212 | 214 | ||
213 | return schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 1, 0); | 215 | return schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 1, 0); |
214 | } | 216 | } |
@@ -217,7 +219,11 @@ static int send_mpa_request(struct nes_cm_node *cm_node, struct sk_buff *skb) | |||
217 | 219 | ||
218 | static int send_mpa_reject(struct nes_cm_node *cm_node) | 220 | static int send_mpa_reject(struct nes_cm_node *cm_node) |
219 | { | 221 | { |
220 | struct sk_buff *skb = NULL; | 222 | struct sk_buff *skb = NULL; |
223 | u8 start_addr = 0; | ||
224 | u8 *start_ptr = &start_addr; | ||
225 | u8 **start_buff = &start_ptr; | ||
226 | u16 buff_len = 0; | ||
221 | 227 | ||
222 | skb = dev_alloc_skb(MAX_CM_BUFFER); | 228 | skb = dev_alloc_skb(MAX_CM_BUFFER); |
223 | if (!skb) { | 229 | if (!skb) { |
@@ -226,8 +232,8 @@ static int send_mpa_reject(struct nes_cm_node *cm_node) | |||
226 | } | 232 | } |
227 | 233 | ||
228 | /* send an MPA reject frame */ | 234 | /* send an MPA reject frame */ |
229 | form_cm_frame(skb, cm_node, NULL, 0, &cm_node->mpa_frame, | 235 | cm_build_mpa_frame(cm_node, start_buff, &buff_len, NULL, MPA_KEY_REPLY); |
230 | cm_node->mpa_frame_size, SET_ACK | SET_FIN); | 236 | form_cm_frame(skb, cm_node, NULL, 0, *start_buff, buff_len, SET_ACK | SET_FIN); |
231 | 237 | ||
232 | cm_node->state = NES_CM_STATE_FIN_WAIT1; | 238 | cm_node->state = NES_CM_STATE_FIN_WAIT1; |
233 | return schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 1, 0); | 239 | return schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 1, 0); |
@@ -239,24 +245,31 @@ static int send_mpa_reject(struct nes_cm_node *cm_node) | |||
239 | * IETF MPA frame | 245 | * IETF MPA frame |
240 | */ | 246 | */ |
241 | static int parse_mpa(struct nes_cm_node *cm_node, u8 *buffer, u32 *type, | 247 | static int parse_mpa(struct nes_cm_node *cm_node, u8 *buffer, u32 *type, |
242 | u32 len) | 248 | u32 len) |
243 | { | 249 | { |
244 | struct ietf_mpa_frame *mpa_frame; | 250 | struct ietf_mpa_v1 *mpa_frame; |
251 | struct ietf_mpa_v2 *mpa_v2_frame; | ||
252 | struct ietf_rtr_msg *rtr_msg; | ||
253 | int mpa_hdr_len; | ||
254 | int priv_data_len; | ||
245 | 255 | ||
246 | *type = NES_MPA_REQUEST_ACCEPT; | 256 | *type = NES_MPA_REQUEST_ACCEPT; |
247 | 257 | ||
248 | /* assume req frame is in tcp data payload */ | 258 | /* assume req frame is in tcp data payload */ |
249 | if (len < sizeof(struct ietf_mpa_frame)) { | 259 | if (len < sizeof(struct ietf_mpa_v1)) { |
250 | nes_debug(NES_DBG_CM, "The received ietf buffer was too small (%x)\n", len); | 260 | nes_debug(NES_DBG_CM, "The received ietf buffer was too small (%x)\n", len); |
251 | return -EINVAL; | 261 | return -EINVAL; |
252 | } | 262 | } |
253 | 263 | ||
254 | mpa_frame = (struct ietf_mpa_frame *)buffer; | 264 | /* points to the beginning of the frame, which could be MPA V1 or V2 */ |
255 | cm_node->mpa_frame_size = ntohs(mpa_frame->priv_data_len); | 265 | mpa_frame = (struct ietf_mpa_v1 *)buffer; |
266 | mpa_hdr_len = sizeof(struct ietf_mpa_v1); | ||
267 | priv_data_len = ntohs(mpa_frame->priv_data_len); | ||
268 | |||
256 | /* make sure mpa private data len is less than 512 bytes */ | 269 | /* make sure mpa private data len is less than 512 bytes */ |
257 | if (cm_node->mpa_frame_size > IETF_MAX_PRIV_DATA_LEN) { | 270 | if (priv_data_len > IETF_MAX_PRIV_DATA_LEN) { |
258 | nes_debug(NES_DBG_CM, "The received Length of Private" | 271 | nes_debug(NES_DBG_CM, "The received Length of Private" |
259 | " Data field exceeds 512 octets\n"); | 272 | " Data field exceeds 512 octets\n"); |
260 | return -EINVAL; | 273 | return -EINVAL; |
261 | } | 274 | } |
262 | /* | 275 | /* |
@@ -264,11 +277,22 @@ static int parse_mpa(struct nes_cm_node *cm_node, u8 *buffer, u32 *type, | |||
264 | * received MPA version and MPA key information | 277 | * received MPA version and MPA key information |
265 | * | 278 | * |
266 | */ | 279 | */ |
267 | if (mpa_frame->rev != mpa_version) { | 280 | if (mpa_frame->rev != IETF_MPA_V1 && mpa_frame->rev != IETF_MPA_V2) { |
281 | nes_debug(NES_DBG_CM, "The received mpa version" | ||
282 | " is not supported\n"); | ||
283 | return -EINVAL; | ||
284 | } | ||
285 | /* | ||
286 | * backwards compatibility only | ||
287 | */ | ||
288 | if (mpa_frame->rev > cm_node->mpa_frame_rev) { | ||
268 | nes_debug(NES_DBG_CM, "The received mpa version" | 289 | nes_debug(NES_DBG_CM, "The received mpa version" |
269 | " can not be interoperated\n"); | 290 | " can not be interoperated\n"); |
270 | return -EINVAL; | 291 | return -EINVAL; |
292 | } else { | ||
293 | cm_node->mpa_frame_rev = mpa_frame->rev; | ||
271 | } | 294 | } |
295 | |||
272 | if (cm_node->state != NES_CM_STATE_MPAREQ_SENT) { | 296 | if (cm_node->state != NES_CM_STATE_MPAREQ_SENT) { |
273 | if (memcmp(mpa_frame->key, IEFT_MPA_KEY_REQ, IETF_MPA_KEY_SIZE)) { | 297 | if (memcmp(mpa_frame->key, IEFT_MPA_KEY_REQ, IETF_MPA_KEY_SIZE)) { |
274 | nes_debug(NES_DBG_CM, "Unexpected MPA Key received \n"); | 298 | nes_debug(NES_DBG_CM, "Unexpected MPA Key received \n"); |
@@ -281,25 +305,75 @@ static int parse_mpa(struct nes_cm_node *cm_node, u8 *buffer, u32 *type, | |||
281 | } | 305 | } |
282 | } | 306 | } |
283 | 307 | ||
284 | if (cm_node->mpa_frame_size + sizeof(struct ietf_mpa_frame) != len) { | 308 | |
309 | if (priv_data_len + mpa_hdr_len != len) { | ||
285 | nes_debug(NES_DBG_CM, "The received ietf buffer was not right" | 310 | nes_debug(NES_DBG_CM, "The received ietf buffer was not right" |
286 | " complete (%x + %x != %x)\n", | 311 | " complete (%x + %x != %x)\n", |
287 | cm_node->mpa_frame_size, | 312 | priv_data_len, mpa_hdr_len, len); |
288 | (u32)sizeof(struct ietf_mpa_frame), len); | ||
289 | return -EINVAL; | 313 | return -EINVAL; |
290 | } | 314 | } |
291 | /* make sure it does not exceed the max size */ | 315 | /* make sure it does not exceed the max size */ |
292 | if (len > MAX_CM_BUFFER) { | 316 | if (len > MAX_CM_BUFFER) { |
293 | nes_debug(NES_DBG_CM, "The received ietf buffer was too large" | 317 | nes_debug(NES_DBG_CM, "The received ietf buffer was too large" |
294 | " (%x + %x != %x)\n", | 318 | " (%x + %x != %x)\n", |
295 | cm_node->mpa_frame_size, | 319 | priv_data_len, mpa_hdr_len, len); |
296 | (u32)sizeof(struct ietf_mpa_frame), len); | ||
297 | return -EINVAL; | 320 | return -EINVAL; |
298 | } | 321 | } |
299 | 322 | ||
323 | cm_node->mpa_frame_size = priv_data_len; | ||
324 | |||
325 | switch (mpa_frame->rev) { | ||
326 | case IETF_MPA_V2: { | ||
327 | u16 ird_size; | ||
328 | u16 ord_size; | ||
329 | mpa_v2_frame = (struct ietf_mpa_v2 *)buffer; | ||
330 | mpa_hdr_len += IETF_RTR_MSG_SIZE; | ||
331 | cm_node->mpa_frame_size -= IETF_RTR_MSG_SIZE; | ||
332 | rtr_msg = &mpa_v2_frame->rtr_msg; | ||
333 | |||
334 | /* parse rtr message */ | ||
335 | rtr_msg->ctrl_ird = ntohs(rtr_msg->ctrl_ird); | ||
336 | rtr_msg->ctrl_ord = ntohs(rtr_msg->ctrl_ord); | ||
337 | ird_size = rtr_msg->ctrl_ird & IETF_NO_IRD_ORD; | ||
338 | ord_size = rtr_msg->ctrl_ord & IETF_NO_IRD_ORD; | ||
339 | |||
340 | if (!(rtr_msg->ctrl_ird & IETF_PEER_TO_PEER)) { | ||
341 | /* send reset */ | ||
342 | return -EINVAL; | ||
343 | } | ||
344 | |||
345 | if (cm_node->state != NES_CM_STATE_MPAREQ_SENT) { | ||
346 | /* responder */ | ||
347 | if (cm_node->ord_size > ird_size) | ||
348 | cm_node->ord_size = ird_size; | ||
349 | } else { | ||
350 | /* initiator */ | ||
351 | if (cm_node->ord_size > ird_size) | ||
352 | cm_node->ord_size = ird_size; | ||
353 | |||
354 | if (cm_node->ird_size < ord_size) { | ||
355 | /* no resources available */ | ||
356 | /* send terminate message */ | ||
357 | return -EINVAL; | ||
358 | } | ||
359 | } | ||
360 | |||
361 | if (rtr_msg->ctrl_ord & IETF_RDMA0_READ) { | ||
362 | cm_node->send_rdma0_op = SEND_RDMA_READ_ZERO; | ||
363 | } else if (rtr_msg->ctrl_ord & IETF_RDMA0_WRITE) { | ||
364 | cm_node->send_rdma0_op = SEND_RDMA_WRITE_ZERO; | ||
365 | } else { /* Not supported RDMA0 operation */ | ||
366 | return -EINVAL; | ||
367 | } | ||
368 | break; | ||
369 | } | ||
370 | case IETF_MPA_V1: | ||
371 | default: | ||
372 | break; | ||
373 | } | ||
374 | |||
300 | /* copy entire MPA frame to our cm_node's frame */ | 375 | /* copy entire MPA frame to our cm_node's frame */ |
301 | memcpy(cm_node->mpa_frame_buf, buffer + sizeof(struct ietf_mpa_frame), | 376 | memcpy(cm_node->mpa_frame_buf, buffer + mpa_hdr_len, cm_node->mpa_frame_size); |
302 | cm_node->mpa_frame_size); | ||
303 | 377 | ||
304 | if (mpa_frame->flags & IETF_MPA_FLAGS_REJECT) | 378 | if (mpa_frame->flags & IETF_MPA_FLAGS_REJECT) |
305 | *type = NES_MPA_REQUEST_REJECT; | 379 | *type = NES_MPA_REQUEST_REJECT; |
@@ -312,8 +386,8 @@ static int parse_mpa(struct nes_cm_node *cm_node, u8 *buffer, u32 *type, | |||
312 | * node info to build. | 386 | * node info to build. |
313 | */ | 387 | */ |
314 | static void form_cm_frame(struct sk_buff *skb, | 388 | static void form_cm_frame(struct sk_buff *skb, |
315 | struct nes_cm_node *cm_node, void *options, u32 optionsize, | 389 | struct nes_cm_node *cm_node, void *options, u32 optionsize, |
316 | void *data, u32 datasize, u8 flags) | 390 | void *data, u32 datasize, u8 flags) |
317 | { | 391 | { |
318 | struct tcphdr *tcph; | 392 | struct tcphdr *tcph; |
319 | struct iphdr *iph; | 393 | struct iphdr *iph; |
@@ -322,14 +396,14 @@ static void form_cm_frame(struct sk_buff *skb, | |||
322 | u16 packetsize = sizeof(*iph); | 396 | u16 packetsize = sizeof(*iph); |
323 | 397 | ||
324 | packetsize += sizeof(*tcph); | 398 | packetsize += sizeof(*tcph); |
325 | packetsize += optionsize + datasize; | 399 | packetsize += optionsize + datasize; |
326 | 400 | ||
401 | skb_trim(skb, 0); | ||
327 | memset(skb->data, 0x00, ETH_HLEN + sizeof(*iph) + sizeof(*tcph)); | 402 | memset(skb->data, 0x00, ETH_HLEN + sizeof(*iph) + sizeof(*tcph)); |
328 | 403 | ||
329 | skb->len = 0; | ||
330 | buf = skb_put(skb, packetsize + ETH_HLEN); | 404 | buf = skb_put(skb, packetsize + ETH_HLEN); |
331 | 405 | ||
332 | ethh = (struct ethhdr *) buf; | 406 | ethh = (struct ethhdr *)buf; |
333 | buf += ETH_HLEN; | 407 | buf += ETH_HLEN; |
334 | 408 | ||
335 | iph = (struct iphdr *)buf; | 409 | iph = (struct iphdr *)buf; |
@@ -337,7 +411,7 @@ static void form_cm_frame(struct sk_buff *skb, | |||
337 | tcph = (struct tcphdr *)buf; | 411 | tcph = (struct tcphdr *)buf; |
338 | skb_reset_mac_header(skb); | 412 | skb_reset_mac_header(skb); |
339 | skb_set_network_header(skb, ETH_HLEN); | 413 | skb_set_network_header(skb, ETH_HLEN); |
340 | skb_set_transport_header(skb, ETH_HLEN+sizeof(*iph)); | 414 | skb_set_transport_header(skb, ETH_HLEN + sizeof(*iph)); |
341 | buf += sizeof(*tcph); | 415 | buf += sizeof(*tcph); |
342 | 416 | ||
343 | skb->ip_summed = CHECKSUM_PARTIAL; | 417 | skb->ip_summed = CHECKSUM_PARTIAL; |
@@ -350,14 +424,14 @@ static void form_cm_frame(struct sk_buff *skb, | |||
350 | ethh->h_proto = htons(0x0800); | 424 | ethh->h_proto = htons(0x0800); |
351 | 425 | ||
352 | iph->version = IPVERSION; | 426 | iph->version = IPVERSION; |
353 | iph->ihl = 5; /* 5 * 4Byte words, IP headr len */ | 427 | iph->ihl = 5; /* 5 * 4Byte words, IP headr len */ |
354 | iph->tos = 0; | 428 | iph->tos = 0; |
355 | iph->tot_len = htons(packetsize); | 429 | iph->tot_len = htons(packetsize); |
356 | iph->id = htons(++cm_node->tcp_cntxt.loc_id); | 430 | iph->id = htons(++cm_node->tcp_cntxt.loc_id); |
357 | 431 | ||
358 | iph->frag_off = htons(0x4000); | 432 | iph->frag_off = htons(0x4000); |
359 | iph->ttl = 0x40; | 433 | iph->ttl = 0x40; |
360 | iph->protocol = 0x06; /* IPPROTO_TCP */ | 434 | iph->protocol = 0x06; /* IPPROTO_TCP */ |
361 | 435 | ||
362 | iph->saddr = htonl(cm_node->loc_addr); | 436 | iph->saddr = htonl(cm_node->loc_addr); |
363 | iph->daddr = htonl(cm_node->rem_addr); | 437 | iph->daddr = htonl(cm_node->rem_addr); |
@@ -370,14 +444,16 @@ static void form_cm_frame(struct sk_buff *skb, | |||
370 | cm_node->tcp_cntxt.loc_ack_num = cm_node->tcp_cntxt.rcv_nxt; | 444 | cm_node->tcp_cntxt.loc_ack_num = cm_node->tcp_cntxt.rcv_nxt; |
371 | tcph->ack_seq = htonl(cm_node->tcp_cntxt.loc_ack_num); | 445 | tcph->ack_seq = htonl(cm_node->tcp_cntxt.loc_ack_num); |
372 | tcph->ack = 1; | 446 | tcph->ack = 1; |
373 | } else | 447 | } else { |
374 | tcph->ack_seq = 0; | 448 | tcph->ack_seq = 0; |
449 | } | ||
375 | 450 | ||
376 | if (flags & SET_SYN) { | 451 | if (flags & SET_SYN) { |
377 | cm_node->tcp_cntxt.loc_seq_num++; | 452 | cm_node->tcp_cntxt.loc_seq_num++; |
378 | tcph->syn = 1; | 453 | tcph->syn = 1; |
379 | } else | 454 | } else { |
380 | cm_node->tcp_cntxt.loc_seq_num += datasize; | 455 | cm_node->tcp_cntxt.loc_seq_num += datasize; |
456 | } | ||
381 | 457 | ||
382 | if (flags & SET_FIN) { | 458 | if (flags & SET_FIN) { |
383 | cm_node->tcp_cntxt.loc_seq_num++; | 459 | cm_node->tcp_cntxt.loc_seq_num++; |
@@ -398,10 +474,8 @@ static void form_cm_frame(struct sk_buff *skb, | |||
398 | 474 | ||
399 | skb_shinfo(skb)->nr_frags = 0; | 475 | skb_shinfo(skb)->nr_frags = 0; |
400 | cm_packets_created++; | 476 | cm_packets_created++; |
401 | |||
402 | } | 477 | } |
403 | 478 | ||
404 | |||
405 | /** | 479 | /** |
406 | * print_core - dump a cm core | 480 | * print_core - dump a cm core |
407 | */ | 481 | */ |
@@ -413,7 +487,7 @@ static void print_core(struct nes_cm_core *core) | |||
413 | return; | 487 | return; |
414 | nes_debug(NES_DBG_CM, "---------------------------------------------\n"); | 488 | nes_debug(NES_DBG_CM, "---------------------------------------------\n"); |
415 | 489 | ||
416 | nes_debug(NES_DBG_CM, "State : %u \n", core->state); | 490 | nes_debug(NES_DBG_CM, "State : %u \n", core->state); |
417 | 491 | ||
418 | nes_debug(NES_DBG_CM, "Listen Nodes : %u \n", atomic_read(&core->listen_node_cnt)); | 492 | nes_debug(NES_DBG_CM, "Listen Nodes : %u \n", atomic_read(&core->listen_node_cnt)); |
419 | nes_debug(NES_DBG_CM, "Active Nodes : %u \n", atomic_read(&core->node_cnt)); | 493 | nes_debug(NES_DBG_CM, "Active Nodes : %u \n", atomic_read(&core->node_cnt)); |
@@ -423,6 +497,147 @@ static void print_core(struct nes_cm_core *core) | |||
423 | nes_debug(NES_DBG_CM, "-------------- end core ---------------\n"); | 497 | nes_debug(NES_DBG_CM, "-------------- end core ---------------\n"); |
424 | } | 498 | } |
425 | 499 | ||
500 | /** | ||
501 | * cm_build_mpa_frame - build a MPA V1 frame or MPA V2 frame | ||
502 | */ | ||
503 | static int cm_build_mpa_frame(struct nes_cm_node *cm_node, u8 **start_buff, | ||
504 | u16 *buff_len, u8 *pci_mem, u8 mpa_key) | ||
505 | { | ||
506 | int ret = 0; | ||
507 | |||
508 | *start_buff = (pci_mem) ? pci_mem : &cm_node->mpa_frame_buf[0]; | ||
509 | |||
510 | switch (cm_node->mpa_frame_rev) { | ||
511 | case IETF_MPA_V1: | ||
512 | *start_buff = (u8 *)*start_buff + sizeof(struct ietf_rtr_msg); | ||
513 | *buff_len = sizeof(struct ietf_mpa_v1) + cm_node->mpa_frame_size; | ||
514 | build_mpa_v1(cm_node, *start_buff, mpa_key); | ||
515 | break; | ||
516 | case IETF_MPA_V2: | ||
517 | *buff_len = sizeof(struct ietf_mpa_v2) + cm_node->mpa_frame_size; | ||
518 | build_mpa_v2(cm_node, *start_buff, mpa_key); | ||
519 | break; | ||
520 | default: | ||
521 | ret = -EINVAL; | ||
522 | } | ||
523 | return ret; | ||
524 | } | ||
525 | |||
526 | /** | ||
527 | * build_mpa_v2 - build a MPA V2 frame | ||
528 | */ | ||
529 | static void build_mpa_v2(struct nes_cm_node *cm_node, | ||
530 | void *start_addr, u8 mpa_key) | ||
531 | { | ||
532 | struct ietf_mpa_v2 *mpa_frame = (struct ietf_mpa_v2 *)start_addr; | ||
533 | struct ietf_rtr_msg *rtr_msg = &mpa_frame->rtr_msg; | ||
534 | |||
535 | /* initialize the upper 5 bytes of the frame */ | ||
536 | build_mpa_v1(cm_node, start_addr, mpa_key); | ||
537 | mpa_frame->flags |= IETF_MPA_V2_FLAG; /* set a bit to indicate MPA V2 */ | ||
538 | mpa_frame->priv_data_len += htons(IETF_RTR_MSG_SIZE); | ||
539 | |||
540 | /* initialize RTR msg */ | ||
541 | rtr_msg->ctrl_ird = (cm_node->ird_size > IETF_NO_IRD_ORD) ? | ||
542 | IETF_NO_IRD_ORD : cm_node->ird_size; | ||
543 | rtr_msg->ctrl_ord = (cm_node->ord_size > IETF_NO_IRD_ORD) ? | ||
544 | IETF_NO_IRD_ORD : cm_node->ord_size; | ||
545 | |||
546 | rtr_msg->ctrl_ird |= IETF_PEER_TO_PEER; | ||
547 | rtr_msg->ctrl_ird |= IETF_FLPDU_ZERO_LEN; | ||
548 | |||
549 | switch (mpa_key) { | ||
550 | case MPA_KEY_REQUEST: | ||
551 | rtr_msg->ctrl_ord |= IETF_RDMA0_WRITE; | ||
552 | rtr_msg->ctrl_ord |= IETF_RDMA0_READ; | ||
553 | break; | ||
554 | case MPA_KEY_REPLY: | ||
555 | switch (cm_node->send_rdma0_op) { | ||
556 | case SEND_RDMA_WRITE_ZERO: | ||
557 | rtr_msg->ctrl_ord |= IETF_RDMA0_WRITE; | ||
558 | break; | ||
559 | case SEND_RDMA_READ_ZERO: | ||
560 | rtr_msg->ctrl_ord |= IETF_RDMA0_READ; | ||
561 | break; | ||
562 | } | ||
563 | } | ||
564 | rtr_msg->ctrl_ird = htons(rtr_msg->ctrl_ird); | ||
565 | rtr_msg->ctrl_ord = htons(rtr_msg->ctrl_ord); | ||
566 | } | ||
567 | |||
568 | /** | ||
569 | * build_mpa_v1 - build a MPA V1 frame | ||
570 | */ | ||
571 | static void build_mpa_v1(struct nes_cm_node *cm_node, void *start_addr, u8 mpa_key) | ||
572 | { | ||
573 | struct ietf_mpa_v1 *mpa_frame = (struct ietf_mpa_v1 *)start_addr; | ||
574 | |||
575 | switch (mpa_key) { | ||
576 | case MPA_KEY_REQUEST: | ||
577 | memcpy(mpa_frame->key, IEFT_MPA_KEY_REQ, IETF_MPA_KEY_SIZE); | ||
578 | break; | ||
579 | case MPA_KEY_REPLY: | ||
580 | memcpy(mpa_frame->key, IEFT_MPA_KEY_REP, IETF_MPA_KEY_SIZE); | ||
581 | break; | ||
582 | } | ||
583 | mpa_frame->flags = IETF_MPA_FLAGS_CRC; | ||
584 | mpa_frame->rev = cm_node->mpa_frame_rev; | ||
585 | mpa_frame->priv_data_len = htons(cm_node->mpa_frame_size); | ||
586 | } | ||
587 | |||
588 | static void build_rdma0_msg(struct nes_cm_node *cm_node, struct nes_qp **nesqp_addr) | ||
589 | { | ||
590 | u64 u64temp; | ||
591 | struct nes_qp *nesqp = *nesqp_addr; | ||
592 | struct nes_hw_qp_wqe *wqe = &nesqp->hwqp.sq_vbase[0]; | ||
593 | |||
594 | u64temp = (unsigned long)nesqp; | ||
595 | u64temp |= NES_SW_CONTEXT_ALIGN >> 1; | ||
596 | set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX, u64temp); | ||
597 | |||
598 | wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_LOW_IDX] = 0; | ||
599 | wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_HIGH_IDX] = 0; | ||
600 | |||
601 | switch (cm_node->send_rdma0_op) { | ||
602 | case SEND_RDMA_WRITE_ZERO: | ||
603 | nes_debug(NES_DBG_CM, "Sending first write.\n"); | ||
604 | wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] = | ||
605 | cpu_to_le32(NES_IWARP_SQ_OP_RDMAW); | ||
606 | wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] = 0; | ||
607 | wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] = 0; | ||
608 | wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 0; | ||
609 | break; | ||
610 | |||
611 | case SEND_RDMA_READ_ZERO: | ||
612 | default: | ||
613 | if (cm_node->send_rdma0_op != SEND_RDMA_READ_ZERO) { | ||
614 | printk(KERN_ERR "%s[%u]: Unsupported RDMA0 len operation=%u\n", | ||
615 | __func__, __LINE__, cm_node->send_rdma0_op); | ||
616 | WARN_ON(1); | ||
617 | } | ||
618 | nes_debug(NES_DBG_CM, "Sending first rdma operation.\n"); | ||
619 | wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] = | ||
620 | cpu_to_le32(NES_IWARP_SQ_OP_RDMAR); | ||
621 | wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_TO_LOW_IDX] = 1; | ||
622 | wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_TO_HIGH_IDX] = 0; | ||
623 | wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_LENGTH_IDX] = 0; | ||
624 | wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_STAG_IDX] = 1; | ||
625 | wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 1; | ||
626 | break; | ||
627 | } | ||
628 | |||
629 | if (nesqp->sq_kmapped) { | ||
630 | nesqp->sq_kmapped = 0; | ||
631 | kunmap(nesqp->page); | ||
632 | } | ||
633 | |||
634 | /*use the reserved spot on the WQ for the extra first WQE*/ | ||
635 | nesqp->nesqp_context->ird_ord_sizes &= cpu_to_le32(~(NES_QPCONTEXT_ORDIRD_LSMM_PRESENT | | ||
636 | NES_QPCONTEXT_ORDIRD_WRPDU | | ||
637 | NES_QPCONTEXT_ORDIRD_ALSMM)); | ||
638 | nesqp->skip_lsmm = 1; | ||
639 | nesqp->hwqp.sq_tail = 0; | ||
640 | } | ||
426 | 641 | ||
427 | /** | 642 | /** |
428 | * schedule_nes_timer | 643 | * schedule_nes_timer |
@@ -430,10 +645,10 @@ static void print_core(struct nes_cm_core *core) | |||
430 | * rem_ref_cm_node(cm_core, cm_node);add_ref_cm_node(cm_node); | 645 | * rem_ref_cm_node(cm_core, cm_node);add_ref_cm_node(cm_node); |
431 | */ | 646 | */ |
432 | int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb, | 647 | int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb, |
433 | enum nes_timer_type type, int send_retrans, | 648 | enum nes_timer_type type, int send_retrans, |
434 | int close_when_complete) | 649 | int close_when_complete) |
435 | { | 650 | { |
436 | unsigned long flags; | 651 | unsigned long flags; |
437 | struct nes_cm_core *cm_core = cm_node->cm_core; | 652 | struct nes_cm_core *cm_core = cm_node->cm_core; |
438 | struct nes_timer_entry *new_send; | 653 | struct nes_timer_entry *new_send; |
439 | int ret = 0; | 654 | int ret = 0; |
@@ -454,7 +669,7 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
454 | new_send->close_when_complete = close_when_complete; | 669 | new_send->close_when_complete = close_when_complete; |
455 | 670 | ||
456 | if (type == NES_TIMER_TYPE_CLOSE) { | 671 | if (type == NES_TIMER_TYPE_CLOSE) { |
457 | new_send->timetosend += (HZ/10); | 672 | new_send->timetosend += (HZ / 10); |
458 | if (cm_node->recv_entry) { | 673 | if (cm_node->recv_entry) { |
459 | kfree(new_send); | 674 | kfree(new_send); |
460 | WARN_ON(1); | 675 | WARN_ON(1); |
@@ -475,7 +690,7 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
475 | ret = nes_nic_cm_xmit(new_send->skb, cm_node->netdev); | 690 | ret = nes_nic_cm_xmit(new_send->skb, cm_node->netdev); |
476 | if (ret != NETDEV_TX_OK) { | 691 | if (ret != NETDEV_TX_OK) { |
477 | nes_debug(NES_DBG_CM, "Error sending packet %p " | 692 | nes_debug(NES_DBG_CM, "Error sending packet %p " |
478 | "(jiffies = %lu)\n", new_send, jiffies); | 693 | "(jiffies = %lu)\n", new_send, jiffies); |
479 | new_send->timetosend = jiffies; | 694 | new_send->timetosend = jiffies; |
480 | ret = NETDEV_TX_OK; | 695 | ret = NETDEV_TX_OK; |
481 | } else { | 696 | } else { |
@@ -504,6 +719,7 @@ static void nes_retrans_expired(struct nes_cm_node *cm_node) | |||
504 | struct iw_cm_id *cm_id = cm_node->cm_id; | 719 | struct iw_cm_id *cm_id = cm_node->cm_id; |
505 | enum nes_cm_node_state state = cm_node->state; | 720 | enum nes_cm_node_state state = cm_node->state; |
506 | cm_node->state = NES_CM_STATE_CLOSED; | 721 | cm_node->state = NES_CM_STATE_CLOSED; |
722 | |||
507 | switch (state) { | 723 | switch (state) { |
508 | case NES_CM_STATE_SYN_RCVD: | 724 | case NES_CM_STATE_SYN_RCVD: |
509 | case NES_CM_STATE_CLOSING: | 725 | case NES_CM_STATE_CLOSING: |
@@ -536,10 +752,10 @@ static void handle_recv_entry(struct nes_cm_node *cm_node, u32 rem_node) | |||
536 | spin_lock_irqsave(&nesqp->lock, qplockflags); | 752 | spin_lock_irqsave(&nesqp->lock, qplockflags); |
537 | if (nesqp->cm_id) { | 753 | if (nesqp->cm_id) { |
538 | nes_debug(NES_DBG_CM, "QP%u: cm_id = %p, " | 754 | nes_debug(NES_DBG_CM, "QP%u: cm_id = %p, " |
539 | "refcount = %d: HIT A " | 755 | "refcount = %d: HIT A " |
540 | "NES_TIMER_TYPE_CLOSE with something " | 756 | "NES_TIMER_TYPE_CLOSE with something " |
541 | "to do!!!\n", nesqp->hwqp.qp_id, cm_id, | 757 | "to do!!!\n", nesqp->hwqp.qp_id, cm_id, |
542 | atomic_read(&nesqp->refcount)); | 758 | atomic_read(&nesqp->refcount)); |
543 | nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED; | 759 | nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED; |
544 | nesqp->last_aeq = NES_AEQE_AEID_RESET_SENT; | 760 | nesqp->last_aeq = NES_AEQE_AEID_RESET_SENT; |
545 | nesqp->ibqp_state = IB_QPS_ERR; | 761 | nesqp->ibqp_state = IB_QPS_ERR; |
@@ -548,10 +764,10 @@ static void handle_recv_entry(struct nes_cm_node *cm_node, u32 rem_node) | |||
548 | } else { | 764 | } else { |
549 | spin_unlock_irqrestore(&nesqp->lock, qplockflags); | 765 | spin_unlock_irqrestore(&nesqp->lock, qplockflags); |
550 | nes_debug(NES_DBG_CM, "QP%u: cm_id = %p, " | 766 | nes_debug(NES_DBG_CM, "QP%u: cm_id = %p, " |
551 | "refcount = %d: HIT A " | 767 | "refcount = %d: HIT A " |
552 | "NES_TIMER_TYPE_CLOSE with nothing " | 768 | "NES_TIMER_TYPE_CLOSE with nothing " |
553 | "to do!!!\n", nesqp->hwqp.qp_id, cm_id, | 769 | "to do!!!\n", nesqp->hwqp.qp_id, cm_id, |
554 | atomic_read(&nesqp->refcount)); | 770 | atomic_read(&nesqp->refcount)); |
555 | } | 771 | } |
556 | } else if (rem_node) { | 772 | } else if (rem_node) { |
557 | /* TIME_WAIT state */ | 773 | /* TIME_WAIT state */ |
@@ -580,11 +796,12 @@ static void nes_cm_timer_tick(unsigned long pass) | |||
580 | int ret = NETDEV_TX_OK; | 796 | int ret = NETDEV_TX_OK; |
581 | 797 | ||
582 | struct list_head timer_list; | 798 | struct list_head timer_list; |
799 | |||
583 | INIT_LIST_HEAD(&timer_list); | 800 | INIT_LIST_HEAD(&timer_list); |
584 | spin_lock_irqsave(&cm_core->ht_lock, flags); | 801 | spin_lock_irqsave(&cm_core->ht_lock, flags); |
585 | 802 | ||
586 | list_for_each_safe(list_node, list_core_temp, | 803 | list_for_each_safe(list_node, list_core_temp, |
587 | &cm_core->connected_nodes) { | 804 | &cm_core->connected_nodes) { |
588 | cm_node = container_of(list_node, struct nes_cm_node, list); | 805 | cm_node = container_of(list_node, struct nes_cm_node, list); |
589 | if ((cm_node->recv_entry) || (cm_node->send_entry)) { | 806 | if ((cm_node->recv_entry) || (cm_node->send_entry)) { |
590 | add_ref_cm_node(cm_node); | 807 | add_ref_cm_node(cm_node); |
@@ -595,18 +812,19 @@ static void nes_cm_timer_tick(unsigned long pass) | |||
595 | 812 | ||
596 | list_for_each_safe(list_node, list_core_temp, &timer_list) { | 813 | list_for_each_safe(list_node, list_core_temp, &timer_list) { |
597 | cm_node = container_of(list_node, struct nes_cm_node, | 814 | cm_node = container_of(list_node, struct nes_cm_node, |
598 | timer_entry); | 815 | timer_entry); |
599 | recv_entry = cm_node->recv_entry; | 816 | recv_entry = cm_node->recv_entry; |
600 | 817 | ||
601 | if (recv_entry) { | 818 | if (recv_entry) { |
602 | if (time_after(recv_entry->timetosend, jiffies)) { | 819 | if (time_after(recv_entry->timetosend, jiffies)) { |
603 | if (nexttimeout > recv_entry->timetosend || | 820 | if (nexttimeout > recv_entry->timetosend || |
604 | !settimer) { | 821 | !settimer) { |
605 | nexttimeout = recv_entry->timetosend; | 822 | nexttimeout = recv_entry->timetosend; |
606 | settimer = 1; | 823 | settimer = 1; |
607 | } | 824 | } |
608 | } else | 825 | } else { |
609 | handle_recv_entry(cm_node, 1); | 826 | handle_recv_entry(cm_node, 1); |
827 | } | ||
610 | } | 828 | } |
611 | 829 | ||
612 | spin_lock_irqsave(&cm_node->retrans_list_lock, flags); | 830 | spin_lock_irqsave(&cm_node->retrans_list_lock, flags); |
@@ -617,8 +835,8 @@ static void nes_cm_timer_tick(unsigned long pass) | |||
617 | if (time_after(send_entry->timetosend, jiffies)) { | 835 | if (time_after(send_entry->timetosend, jiffies)) { |
618 | if (cm_node->state != NES_CM_STATE_TSA) { | 836 | if (cm_node->state != NES_CM_STATE_TSA) { |
619 | if ((nexttimeout > | 837 | if ((nexttimeout > |
620 | send_entry->timetosend) || | 838 | send_entry->timetosend) || |
621 | !settimer) { | 839 | !settimer) { |
622 | nexttimeout = | 840 | nexttimeout = |
623 | send_entry->timetosend; | 841 | send_entry->timetosend; |
624 | settimer = 1; | 842 | settimer = 1; |
@@ -630,13 +848,13 @@ static void nes_cm_timer_tick(unsigned long pass) | |||
630 | } | 848 | } |
631 | 849 | ||
632 | if ((cm_node->state == NES_CM_STATE_TSA) || | 850 | if ((cm_node->state == NES_CM_STATE_TSA) || |
633 | (cm_node->state == NES_CM_STATE_CLOSED)) { | 851 | (cm_node->state == NES_CM_STATE_CLOSED)) { |
634 | free_retrans_entry(cm_node); | 852 | free_retrans_entry(cm_node); |
635 | break; | 853 | break; |
636 | } | 854 | } |
637 | 855 | ||
638 | if (!send_entry->retranscount || | 856 | if (!send_entry->retranscount || |
639 | !send_entry->retrycount) { | 857 | !send_entry->retrycount) { |
640 | cm_packets_dropped++; | 858 | cm_packets_dropped++; |
641 | free_retrans_entry(cm_node); | 859 | free_retrans_entry(cm_node); |
642 | 860 | ||
@@ -645,28 +863,28 @@ static void nes_cm_timer_tick(unsigned long pass) | |||
645 | nes_retrans_expired(cm_node); | 863 | nes_retrans_expired(cm_node); |
646 | cm_node->state = NES_CM_STATE_CLOSED; | 864 | cm_node->state = NES_CM_STATE_CLOSED; |
647 | spin_lock_irqsave(&cm_node->retrans_list_lock, | 865 | spin_lock_irqsave(&cm_node->retrans_list_lock, |
648 | flags); | 866 | flags); |
649 | break; | 867 | break; |
650 | } | 868 | } |
651 | atomic_inc(&send_entry->skb->users); | 869 | atomic_inc(&send_entry->skb->users); |
652 | cm_packets_retrans++; | 870 | cm_packets_retrans++; |
653 | nes_debug(NES_DBG_CM, "Retransmitting send_entry %p " | 871 | nes_debug(NES_DBG_CM, "Retransmitting send_entry %p " |
654 | "for node %p, jiffies = %lu, time to send = " | 872 | "for node %p, jiffies = %lu, time to send = " |
655 | "%lu, retranscount = %u, send_entry->seq_num = " | 873 | "%lu, retranscount = %u, send_entry->seq_num = " |
656 | "0x%08X, cm_node->tcp_cntxt.rem_ack_num = " | 874 | "0x%08X, cm_node->tcp_cntxt.rem_ack_num = " |
657 | "0x%08X\n", send_entry, cm_node, jiffies, | 875 | "0x%08X\n", send_entry, cm_node, jiffies, |
658 | send_entry->timetosend, | 876 | send_entry->timetosend, |
659 | send_entry->retranscount, | 877 | send_entry->retranscount, |
660 | send_entry->seq_num, | 878 | send_entry->seq_num, |
661 | cm_node->tcp_cntxt.rem_ack_num); | 879 | cm_node->tcp_cntxt.rem_ack_num); |
662 | 880 | ||
663 | spin_unlock_irqrestore(&cm_node->retrans_list_lock, | 881 | spin_unlock_irqrestore(&cm_node->retrans_list_lock, |
664 | flags); | 882 | flags); |
665 | ret = nes_nic_cm_xmit(send_entry->skb, cm_node->netdev); | 883 | ret = nes_nic_cm_xmit(send_entry->skb, cm_node->netdev); |
666 | spin_lock_irqsave(&cm_node->retrans_list_lock, flags); | 884 | spin_lock_irqsave(&cm_node->retrans_list_lock, flags); |
667 | if (ret != NETDEV_TX_OK) { | 885 | if (ret != NETDEV_TX_OK) { |
668 | nes_debug(NES_DBG_CM, "rexmit failed for " | 886 | nes_debug(NES_DBG_CM, "rexmit failed for " |
669 | "node=%p\n", cm_node); | 887 | "node=%p\n", cm_node); |
670 | cm_packets_bounced++; | 888 | cm_packets_bounced++; |
671 | send_entry->retrycount--; | 889 | send_entry->retrycount--; |
672 | nexttimeout = jiffies + NES_SHORT_TIME; | 890 | nexttimeout = jiffies + NES_SHORT_TIME; |
@@ -676,18 +894,18 @@ static void nes_cm_timer_tick(unsigned long pass) | |||
676 | cm_packets_sent++; | 894 | cm_packets_sent++; |
677 | } | 895 | } |
678 | nes_debug(NES_DBG_CM, "Packet Sent: retrans count = " | 896 | nes_debug(NES_DBG_CM, "Packet Sent: retrans count = " |
679 | "%u, retry count = %u.\n", | 897 | "%u, retry count = %u.\n", |
680 | send_entry->retranscount, | 898 | send_entry->retranscount, |
681 | send_entry->retrycount); | 899 | send_entry->retrycount); |
682 | if (send_entry->send_retrans) { | 900 | if (send_entry->send_retrans) { |
683 | send_entry->retranscount--; | 901 | send_entry->retranscount--; |
684 | timetosend = (NES_RETRY_TIMEOUT << | 902 | timetosend = (NES_RETRY_TIMEOUT << |
685 | (NES_DEFAULT_RETRANS - send_entry->retranscount)); | 903 | (NES_DEFAULT_RETRANS - send_entry->retranscount)); |
686 | 904 | ||
687 | send_entry->timetosend = jiffies + | 905 | send_entry->timetosend = jiffies + |
688 | min(timetosend, NES_MAX_TIMEOUT); | 906 | min(timetosend, NES_MAX_TIMEOUT); |
689 | if (nexttimeout > send_entry->timetosend || | 907 | if (nexttimeout > send_entry->timetosend || |
690 | !settimer) { | 908 | !settimer) { |
691 | nexttimeout = send_entry->timetosend; | 909 | nexttimeout = send_entry->timetosend; |
692 | settimer = 1; | 910 | settimer = 1; |
693 | } | 911 | } |
@@ -696,11 +914,11 @@ static void nes_cm_timer_tick(unsigned long pass) | |||
696 | close_when_complete = | 914 | close_when_complete = |
697 | send_entry->close_when_complete; | 915 | send_entry->close_when_complete; |
698 | nes_debug(NES_DBG_CM, "cm_node=%p state=%d\n", | 916 | nes_debug(NES_DBG_CM, "cm_node=%p state=%d\n", |
699 | cm_node, cm_node->state); | 917 | cm_node, cm_node->state); |
700 | free_retrans_entry(cm_node); | 918 | free_retrans_entry(cm_node); |
701 | if (close_when_complete) | 919 | if (close_when_complete) |
702 | rem_ref_cm_node(cm_node->cm_core, | 920 | rem_ref_cm_node(cm_node->cm_core, |
703 | cm_node); | 921 | cm_node); |
704 | } | 922 | } |
705 | } while (0); | 923 | } while (0); |
706 | 924 | ||
@@ -710,7 +928,7 @@ static void nes_cm_timer_tick(unsigned long pass) | |||
710 | 928 | ||
711 | if (settimer) { | 929 | if (settimer) { |
712 | if (!timer_pending(&cm_core->tcp_timer)) { | 930 | if (!timer_pending(&cm_core->tcp_timer)) { |
713 | cm_core->tcp_timer.expires = nexttimeout; | 931 | cm_core->tcp_timer.expires = nexttimeout; |
714 | add_timer(&cm_core->tcp_timer); | 932 | add_timer(&cm_core->tcp_timer); |
715 | } | 933 | } |
716 | } | 934 | } |
@@ -721,13 +939,13 @@ static void nes_cm_timer_tick(unsigned long pass) | |||
721 | * send_syn | 939 | * send_syn |
722 | */ | 940 | */ |
723 | static int send_syn(struct nes_cm_node *cm_node, u32 sendack, | 941 | static int send_syn(struct nes_cm_node *cm_node, u32 sendack, |
724 | struct sk_buff *skb) | 942 | struct sk_buff *skb) |
725 | { | 943 | { |
726 | int ret; | 944 | int ret; |
727 | int flags = SET_SYN; | 945 | int flags = SET_SYN; |
728 | char optionsbuffer[sizeof(struct option_mss) + | 946 | char optionsbuffer[sizeof(struct option_mss) + |
729 | sizeof(struct option_windowscale) + sizeof(struct option_base) + | 947 | sizeof(struct option_windowscale) + sizeof(struct option_base) + |
730 | TCP_OPTIONS_PADDING]; | 948 | TCP_OPTIONS_PADDING]; |
731 | 949 | ||
732 | int optionssize = 0; | 950 | int optionssize = 0; |
733 | /* Sending MSS option */ | 951 | /* Sending MSS option */ |
@@ -854,7 +1072,7 @@ static int send_fin(struct nes_cm_node *cm_node, struct sk_buff *skb) | |||
854 | * find_node - find a cm node that matches the reference cm node | 1072 | * find_node - find a cm node that matches the reference cm node |
855 | */ | 1073 | */ |
856 | static struct nes_cm_node *find_node(struct nes_cm_core *cm_core, | 1074 | static struct nes_cm_node *find_node(struct nes_cm_core *cm_core, |
857 | u16 rem_port, nes_addr_t rem_addr, u16 loc_port, nes_addr_t loc_addr) | 1075 | u16 rem_port, nes_addr_t rem_addr, u16 loc_port, nes_addr_t loc_addr) |
858 | { | 1076 | { |
859 | unsigned long flags; | 1077 | unsigned long flags; |
860 | struct list_head *hte; | 1078 | struct list_head *hte; |
@@ -868,12 +1086,12 @@ static struct nes_cm_node *find_node(struct nes_cm_core *cm_core, | |||
868 | list_for_each_entry(cm_node, hte, list) { | 1086 | list_for_each_entry(cm_node, hte, list) { |
869 | /* compare quad, return node handle if a match */ | 1087 | /* compare quad, return node handle if a match */ |
870 | nes_debug(NES_DBG_CM, "finding node %x:%x =? %x:%x ^ %x:%x =? %x:%x\n", | 1088 | nes_debug(NES_DBG_CM, "finding node %x:%x =? %x:%x ^ %x:%x =? %x:%x\n", |
871 | cm_node->loc_addr, cm_node->loc_port, | 1089 | cm_node->loc_addr, cm_node->loc_port, |
872 | loc_addr, loc_port, | 1090 | loc_addr, loc_port, |
873 | cm_node->rem_addr, cm_node->rem_port, | 1091 | cm_node->rem_addr, cm_node->rem_port, |
874 | rem_addr, rem_port); | 1092 | rem_addr, rem_port); |
875 | if ((cm_node->loc_addr == loc_addr) && (cm_node->loc_port == loc_port) && | 1093 | if ((cm_node->loc_addr == loc_addr) && (cm_node->loc_port == loc_port) && |
876 | (cm_node->rem_addr == rem_addr) && (cm_node->rem_port == rem_port)) { | 1094 | (cm_node->rem_addr == rem_addr) && (cm_node->rem_port == rem_port)) { |
877 | add_ref_cm_node(cm_node); | 1095 | add_ref_cm_node(cm_node); |
878 | spin_unlock_irqrestore(&cm_core->ht_lock, flags); | 1096 | spin_unlock_irqrestore(&cm_core->ht_lock, flags); |
879 | return cm_node; | 1097 | return cm_node; |
@@ -890,7 +1108,7 @@ static struct nes_cm_node *find_node(struct nes_cm_core *cm_core, | |||
890 | * find_listener - find a cm node listening on this addr-port pair | 1108 | * find_listener - find a cm node listening on this addr-port pair |
891 | */ | 1109 | */ |
892 | static struct nes_cm_listener *find_listener(struct nes_cm_core *cm_core, | 1110 | static struct nes_cm_listener *find_listener(struct nes_cm_core *cm_core, |
893 | nes_addr_t dst_addr, u16 dst_port, enum nes_cm_listener_state listener_state) | 1111 | nes_addr_t dst_addr, u16 dst_port, enum nes_cm_listener_state listener_state) |
894 | { | 1112 | { |
895 | unsigned long flags; | 1113 | unsigned long flags; |
896 | struct nes_cm_listener *listen_node; | 1114 | struct nes_cm_listener *listen_node; |
@@ -900,9 +1118,9 @@ static struct nes_cm_listener *find_listener(struct nes_cm_core *cm_core, | |||
900 | list_for_each_entry(listen_node, &cm_core->listen_list.list, list) { | 1118 | list_for_each_entry(listen_node, &cm_core->listen_list.list, list) { |
901 | /* compare node pair, return node handle if a match */ | 1119 | /* compare node pair, return node handle if a match */ |
902 | if (((listen_node->loc_addr == dst_addr) || | 1120 | if (((listen_node->loc_addr == dst_addr) || |
903 | listen_node->loc_addr == 0x00000000) && | 1121 | listen_node->loc_addr == 0x00000000) && |
904 | (listen_node->loc_port == dst_port) && | 1122 | (listen_node->loc_port == dst_port) && |
905 | (listener_state & listen_node->listener_state)) { | 1123 | (listener_state & listen_node->listener_state)) { |
906 | atomic_inc(&listen_node->ref_count); | 1124 | atomic_inc(&listen_node->ref_count); |
907 | spin_unlock_irqrestore(&cm_core->listen_list_lock, flags); | 1125 | spin_unlock_irqrestore(&cm_core->listen_list_lock, flags); |
908 | return listen_node; | 1126 | return listen_node; |
@@ -927,7 +1145,7 @@ static int add_hte_node(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node | |||
927 | return -EINVAL; | 1145 | return -EINVAL; |
928 | 1146 | ||
929 | nes_debug(NES_DBG_CM, "Adding Node %p to Active Connection HT\n", | 1147 | nes_debug(NES_DBG_CM, "Adding Node %p to Active Connection HT\n", |
930 | cm_node); | 1148 | cm_node); |
931 | 1149 | ||
932 | spin_lock_irqsave(&cm_core->ht_lock, flags); | 1150 | spin_lock_irqsave(&cm_core->ht_lock, flags); |
933 | 1151 | ||
@@ -946,7 +1164,7 @@ static int add_hte_node(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node | |||
946 | * mini_cm_dec_refcnt_listen | 1164 | * mini_cm_dec_refcnt_listen |
947 | */ | 1165 | */ |
948 | static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core, | 1166 | static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core, |
949 | struct nes_cm_listener *listener, int free_hanging_nodes) | 1167 | struct nes_cm_listener *listener, int free_hanging_nodes) |
950 | { | 1168 | { |
951 | int ret = -EINVAL; | 1169 | int ret = -EINVAL; |
952 | int err = 0; | 1170 | int err = 0; |
@@ -957,8 +1175,8 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core, | |||
957 | struct list_head reset_list; | 1175 | struct list_head reset_list; |
958 | 1176 | ||
959 | nes_debug(NES_DBG_CM, "attempting listener= %p free_nodes= %d, " | 1177 | nes_debug(NES_DBG_CM, "attempting listener= %p free_nodes= %d, " |
960 | "refcnt=%d\n", listener, free_hanging_nodes, | 1178 | "refcnt=%d\n", listener, free_hanging_nodes, |
961 | atomic_read(&listener->ref_count)); | 1179 | atomic_read(&listener->ref_count)); |
962 | /* free non-accelerated child nodes for this listener */ | 1180 | /* free non-accelerated child nodes for this listener */ |
963 | INIT_LIST_HEAD(&reset_list); | 1181 | INIT_LIST_HEAD(&reset_list); |
964 | if (free_hanging_nodes) { | 1182 | if (free_hanging_nodes) { |
@@ -966,7 +1184,7 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core, | |||
966 | list_for_each_safe(list_pos, list_temp, | 1184 | list_for_each_safe(list_pos, list_temp, |
967 | &g_cm_core->connected_nodes) { | 1185 | &g_cm_core->connected_nodes) { |
968 | cm_node = container_of(list_pos, struct nes_cm_node, | 1186 | cm_node = container_of(list_pos, struct nes_cm_node, |
969 | list); | 1187 | list); |
970 | if ((cm_node->listener == listener) && | 1188 | if ((cm_node->listener == listener) && |
971 | (!cm_node->accelerated)) { | 1189 | (!cm_node->accelerated)) { |
972 | add_ref_cm_node(cm_node); | 1190 | add_ref_cm_node(cm_node); |
@@ -978,7 +1196,7 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core, | |||
978 | 1196 | ||
979 | list_for_each_safe(list_pos, list_temp, &reset_list) { | 1197 | list_for_each_safe(list_pos, list_temp, &reset_list) { |
980 | cm_node = container_of(list_pos, struct nes_cm_node, | 1198 | cm_node = container_of(list_pos, struct nes_cm_node, |
981 | reset_entry); | 1199 | reset_entry); |
982 | { | 1200 | { |
983 | struct nes_cm_node *loopback = cm_node->loopbackpartner; | 1201 | struct nes_cm_node *loopback = cm_node->loopbackpartner; |
984 | enum nes_cm_node_state old_state; | 1202 | enum nes_cm_node_state old_state; |
@@ -990,7 +1208,7 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core, | |||
990 | err = send_reset(cm_node, NULL); | 1208 | err = send_reset(cm_node, NULL); |
991 | if (err) { | 1209 | if (err) { |
992 | cm_node->state = | 1210 | cm_node->state = |
993 | NES_CM_STATE_CLOSED; | 1211 | NES_CM_STATE_CLOSED; |
994 | WARN_ON(1); | 1212 | WARN_ON(1); |
995 | } else { | 1213 | } else { |
996 | old_state = cm_node->state; | 1214 | old_state = cm_node->state; |
@@ -1035,10 +1253,9 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core, | |||
1035 | 1253 | ||
1036 | spin_unlock_irqrestore(&cm_core->listen_list_lock, flags); | 1254 | spin_unlock_irqrestore(&cm_core->listen_list_lock, flags); |
1037 | 1255 | ||
1038 | if (listener->nesvnic) { | 1256 | if (listener->nesvnic) |
1039 | nes_manage_apbvt(listener->nesvnic, listener->loc_port, | 1257 | nes_manage_apbvt(listener->nesvnic, listener->loc_port, |
1040 | PCI_FUNC(listener->nesvnic->nesdev->pcidev->devfn), NES_MANAGE_APBVT_DEL); | 1258 | PCI_FUNC(listener->nesvnic->nesdev->pcidev->devfn), NES_MANAGE_APBVT_DEL); |
1041 | } | ||
1042 | 1259 | ||
1043 | nes_debug(NES_DBG_CM, "destroying listener (%p)\n", listener); | 1260 | nes_debug(NES_DBG_CM, "destroying listener (%p)\n", listener); |
1044 | 1261 | ||
@@ -1052,8 +1269,8 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core, | |||
1052 | if (listener) { | 1269 | if (listener) { |
1053 | if (atomic_read(&listener->pend_accepts_cnt) > 0) | 1270 | if (atomic_read(&listener->pend_accepts_cnt) > 0) |
1054 | nes_debug(NES_DBG_CM, "destroying listener (%p)" | 1271 | nes_debug(NES_DBG_CM, "destroying listener (%p)" |
1055 | " with non-zero pending accepts=%u\n", | 1272 | " with non-zero pending accepts=%u\n", |
1056 | listener, atomic_read(&listener->pend_accepts_cnt)); | 1273 | listener, atomic_read(&listener->pend_accepts_cnt)); |
1057 | } | 1274 | } |
1058 | 1275 | ||
1059 | return ret; | 1276 | return ret; |
@@ -1064,7 +1281,7 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core, | |||
1064 | * mini_cm_del_listen | 1281 | * mini_cm_del_listen |
1065 | */ | 1282 | */ |
1066 | static int mini_cm_del_listen(struct nes_cm_core *cm_core, | 1283 | static int mini_cm_del_listen(struct nes_cm_core *cm_core, |
1067 | struct nes_cm_listener *listener) | 1284 | struct nes_cm_listener *listener) |
1068 | { | 1285 | { |
1069 | listener->listener_state = NES_CM_LISTENER_PASSIVE_STATE; | 1286 | listener->listener_state = NES_CM_LISTENER_PASSIVE_STATE; |
1070 | listener->cm_id = NULL; /* going to be destroyed pretty soon */ | 1287 | listener->cm_id = NULL; /* going to be destroyed pretty soon */ |
@@ -1076,9 +1293,10 @@ static int mini_cm_del_listen(struct nes_cm_core *cm_core, | |||
1076 | * mini_cm_accelerated | 1293 | * mini_cm_accelerated |
1077 | */ | 1294 | */ |
1078 | static inline int mini_cm_accelerated(struct nes_cm_core *cm_core, | 1295 | static inline int mini_cm_accelerated(struct nes_cm_core *cm_core, |
1079 | struct nes_cm_node *cm_node) | 1296 | struct nes_cm_node *cm_node) |
1080 | { | 1297 | { |
1081 | u32 was_timer_set; | 1298 | u32 was_timer_set; |
1299 | |||
1082 | cm_node->accelerated = 1; | 1300 | cm_node->accelerated = 1; |
1083 | 1301 | ||
1084 | if (cm_node->accept_pend) { | 1302 | if (cm_node->accept_pend) { |
@@ -1112,7 +1330,7 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi | |||
1112 | rt = ip_route_output(&init_net, htonl(dst_ip), 0, 0, 0); | 1330 | rt = ip_route_output(&init_net, htonl(dst_ip), 0, 0, 0); |
1113 | if (IS_ERR(rt)) { | 1331 | if (IS_ERR(rt)) { |
1114 | printk(KERN_ERR "%s: ip_route_output_key failed for 0x%08X\n", | 1332 | printk(KERN_ERR "%s: ip_route_output_key failed for 0x%08X\n", |
1115 | __func__, dst_ip); | 1333 | __func__, dst_ip); |
1116 | return rc; | 1334 | return rc; |
1117 | } | 1335 | } |
1118 | 1336 | ||
@@ -1130,7 +1348,7 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi | |||
1130 | 1348 | ||
1131 | if (arpindex >= 0) { | 1349 | if (arpindex >= 0) { |
1132 | if (!memcmp(nesadapter->arp_table[arpindex].mac_addr, | 1350 | if (!memcmp(nesadapter->arp_table[arpindex].mac_addr, |
1133 | neigh->ha, ETH_ALEN)){ | 1351 | neigh->ha, ETH_ALEN)) { |
1134 | /* Mac address same as in nes_arp_table */ | 1352 | /* Mac address same as in nes_arp_table */ |
1135 | neigh_release(neigh); | 1353 | neigh_release(neigh); |
1136 | ip_rt_put(rt); | 1354 | ip_rt_put(rt); |
@@ -1138,8 +1356,8 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi | |||
1138 | } | 1356 | } |
1139 | 1357 | ||
1140 | nes_manage_arp_cache(nesvnic->netdev, | 1358 | nes_manage_arp_cache(nesvnic->netdev, |
1141 | nesadapter->arp_table[arpindex].mac_addr, | 1359 | nesadapter->arp_table[arpindex].mac_addr, |
1142 | dst_ip, NES_ARP_DELETE); | 1360 | dst_ip, NES_ARP_DELETE); |
1143 | } | 1361 | } |
1144 | 1362 | ||
1145 | nes_manage_arp_cache(nesvnic->netdev, neigh->ha, | 1363 | nes_manage_arp_cache(nesvnic->netdev, neigh->ha, |
@@ -1161,8 +1379,8 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi | |||
1161 | * make_cm_node - create a new instance of a cm node | 1379 | * make_cm_node - create a new instance of a cm node |
1162 | */ | 1380 | */ |
1163 | static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core, | 1381 | static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core, |
1164 | struct nes_vnic *nesvnic, struct nes_cm_info *cm_info, | 1382 | struct nes_vnic *nesvnic, struct nes_cm_info *cm_info, |
1165 | struct nes_cm_listener *listener) | 1383 | struct nes_cm_listener *listener) |
1166 | { | 1384 | { |
1167 | struct nes_cm_node *cm_node; | 1385 | struct nes_cm_node *cm_node; |
1168 | struct timespec ts; | 1386 | struct timespec ts; |
@@ -1181,7 +1399,12 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core, | |||
1181 | cm_node->rem_addr = cm_info->rem_addr; | 1399 | cm_node->rem_addr = cm_info->rem_addr; |
1182 | cm_node->loc_port = cm_info->loc_port; | 1400 | cm_node->loc_port = cm_info->loc_port; |
1183 | cm_node->rem_port = cm_info->rem_port; | 1401 | cm_node->rem_port = cm_info->rem_port; |
1184 | cm_node->send_write0 = send_first; | 1402 | |
1403 | cm_node->mpa_frame_rev = mpa_version; | ||
1404 | cm_node->send_rdma0_op = SEND_RDMA_READ_ZERO; | ||
1405 | cm_node->ird_size = IETF_NO_IRD_ORD; | ||
1406 | cm_node->ord_size = IETF_NO_IRD_ORD; | ||
1407 | |||
1185 | nes_debug(NES_DBG_CM, "Make node addresses : loc = %pI4:%x, rem = %pI4:%x\n", | 1408 | nes_debug(NES_DBG_CM, "Make node addresses : loc = %pI4:%x, rem = %pI4:%x\n", |
1186 | &cm_node->loc_addr, cm_node->loc_port, | 1409 | &cm_node->loc_addr, cm_node->loc_port, |
1187 | &cm_node->rem_addr, cm_node->rem_port); | 1410 | &cm_node->rem_addr, cm_node->rem_port); |
@@ -1191,7 +1414,7 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core, | |||
1191 | memcpy(cm_node->loc_mac, nesvnic->netdev->dev_addr, ETH_ALEN); | 1414 | memcpy(cm_node->loc_mac, nesvnic->netdev->dev_addr, ETH_ALEN); |
1192 | 1415 | ||
1193 | nes_debug(NES_DBG_CM, "listener=%p, cm_id=%p\n", cm_node->listener, | 1416 | nes_debug(NES_DBG_CM, "listener=%p, cm_id=%p\n", cm_node->listener, |
1194 | cm_node->cm_id); | 1417 | cm_node->cm_id); |
1195 | 1418 | ||
1196 | spin_lock_init(&cm_node->retrans_list_lock); | 1419 | spin_lock_init(&cm_node->retrans_list_lock); |
1197 | 1420 | ||
@@ -1202,11 +1425,11 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core, | |||
1202 | cm_node->tcp_cntxt.loc_id = NES_CM_DEF_LOCAL_ID; | 1425 | cm_node->tcp_cntxt.loc_id = NES_CM_DEF_LOCAL_ID; |
1203 | cm_node->tcp_cntxt.rcv_wscale = NES_CM_DEFAULT_RCV_WND_SCALE; | 1426 | cm_node->tcp_cntxt.rcv_wscale = NES_CM_DEFAULT_RCV_WND_SCALE; |
1204 | cm_node->tcp_cntxt.rcv_wnd = NES_CM_DEFAULT_RCV_WND_SCALED >> | 1427 | cm_node->tcp_cntxt.rcv_wnd = NES_CM_DEFAULT_RCV_WND_SCALED >> |
1205 | NES_CM_DEFAULT_RCV_WND_SCALE; | 1428 | NES_CM_DEFAULT_RCV_WND_SCALE; |
1206 | ts = current_kernel_time(); | 1429 | ts = current_kernel_time(); |
1207 | cm_node->tcp_cntxt.loc_seq_num = htonl(ts.tv_nsec); | 1430 | cm_node->tcp_cntxt.loc_seq_num = htonl(ts.tv_nsec); |
1208 | cm_node->tcp_cntxt.mss = nesvnic->max_frame_size - sizeof(struct iphdr) - | 1431 | cm_node->tcp_cntxt.mss = nesvnic->max_frame_size - sizeof(struct iphdr) - |
1209 | sizeof(struct tcphdr) - ETH_HLEN - VLAN_HLEN; | 1432 | sizeof(struct tcphdr) - ETH_HLEN - VLAN_HLEN; |
1210 | cm_node->tcp_cntxt.rcv_nxt = 0; | 1433 | cm_node->tcp_cntxt.rcv_nxt = 0; |
1211 | /* get a unique session ID , add thread_id to an upcounter to handle race */ | 1434 | /* get a unique session ID , add thread_id to an upcounter to handle race */ |
1212 | atomic_inc(&cm_core->node_cnt); | 1435 | atomic_inc(&cm_core->node_cnt); |
@@ -1222,12 +1445,11 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core, | |||
1222 | cm_node->loopbackpartner = NULL; | 1445 | cm_node->loopbackpartner = NULL; |
1223 | 1446 | ||
1224 | /* get the mac addr for the remote node */ | 1447 | /* get the mac addr for the remote node */ |
1225 | if (ipv4_is_loopback(htonl(cm_node->rem_addr))) | 1448 | if (ipv4_is_loopback(htonl(cm_node->rem_addr))) { |
1226 | arpindex = nes_arp_table(nesdev, ntohl(nesvnic->local_ipaddr), NULL, NES_ARP_RESOLVE); | 1449 | arpindex = nes_arp_table(nesdev, ntohl(nesvnic->local_ipaddr), NULL, NES_ARP_RESOLVE); |
1227 | else { | 1450 | } else { |
1228 | oldarpindex = nes_arp_table(nesdev, cm_node->rem_addr, NULL, NES_ARP_RESOLVE); | 1451 | oldarpindex = nes_arp_table(nesdev, cm_node->rem_addr, NULL, NES_ARP_RESOLVE); |
1229 | arpindex = nes_addr_resolve_neigh(nesvnic, cm_info->rem_addr, oldarpindex); | 1452 | arpindex = nes_addr_resolve_neigh(nesvnic, cm_info->rem_addr, oldarpindex); |
1230 | |||
1231 | } | 1453 | } |
1232 | if (arpindex < 0) { | 1454 | if (arpindex < 0) { |
1233 | kfree(cm_node); | 1455 | kfree(cm_node); |
@@ -1260,7 +1482,7 @@ static int add_ref_cm_node(struct nes_cm_node *cm_node) | |||
1260 | * rem_ref_cm_node - destroy an instance of a cm node | 1482 | * rem_ref_cm_node - destroy an instance of a cm node |
1261 | */ | 1483 | */ |
1262 | static int rem_ref_cm_node(struct nes_cm_core *cm_core, | 1484 | static int rem_ref_cm_node(struct nes_cm_core *cm_core, |
1263 | struct nes_cm_node *cm_node) | 1485 | struct nes_cm_node *cm_node) |
1264 | { | 1486 | { |
1265 | unsigned long flags; | 1487 | unsigned long flags; |
1266 | struct nes_qp *nesqp; | 1488 | struct nes_qp *nesqp; |
@@ -1291,9 +1513,9 @@ static int rem_ref_cm_node(struct nes_cm_core *cm_core, | |||
1291 | } else { | 1513 | } else { |
1292 | if (cm_node->apbvt_set && cm_node->nesvnic) { | 1514 | if (cm_node->apbvt_set && cm_node->nesvnic) { |
1293 | nes_manage_apbvt(cm_node->nesvnic, cm_node->loc_port, | 1515 | nes_manage_apbvt(cm_node->nesvnic, cm_node->loc_port, |
1294 | PCI_FUNC( | 1516 | PCI_FUNC( |
1295 | cm_node->nesvnic->nesdev->pcidev->devfn), | 1517 | cm_node->nesvnic->nesdev->pcidev->devfn), |
1296 | NES_MANAGE_APBVT_DEL); | 1518 | NES_MANAGE_APBVT_DEL); |
1297 | } | 1519 | } |
1298 | } | 1520 | } |
1299 | 1521 | ||
@@ -1314,7 +1536,7 @@ static int rem_ref_cm_node(struct nes_cm_core *cm_core, | |||
1314 | * process_options | 1536 | * process_options |
1315 | */ | 1537 | */ |
1316 | static int process_options(struct nes_cm_node *cm_node, u8 *optionsloc, | 1538 | static int process_options(struct nes_cm_node *cm_node, u8 *optionsloc, |
1317 | u32 optionsize, u32 syn_packet) | 1539 | u32 optionsize, u32 syn_packet) |
1318 | { | 1540 | { |
1319 | u32 tmp; | 1541 | u32 tmp; |
1320 | u32 offset = 0; | 1542 | u32 offset = 0; |
@@ -1332,15 +1554,15 @@ static int process_options(struct nes_cm_node *cm_node, u8 *optionsloc, | |||
1332 | continue; | 1554 | continue; |
1333 | case OPTION_NUMBER_MSS: | 1555 | case OPTION_NUMBER_MSS: |
1334 | nes_debug(NES_DBG_CM, "%s: MSS Length: %d Offset: %d " | 1556 | nes_debug(NES_DBG_CM, "%s: MSS Length: %d Offset: %d " |
1335 | "Size: %d\n", __func__, | 1557 | "Size: %d\n", __func__, |
1336 | all_options->as_mss.length, offset, optionsize); | 1558 | all_options->as_mss.length, offset, optionsize); |
1337 | got_mss_option = 1; | 1559 | got_mss_option = 1; |
1338 | if (all_options->as_mss.length != 4) { | 1560 | if (all_options->as_mss.length != 4) { |
1339 | return 1; | 1561 | return 1; |
1340 | } else { | 1562 | } else { |
1341 | tmp = ntohs(all_options->as_mss.mss); | 1563 | tmp = ntohs(all_options->as_mss.mss); |
1342 | if (tmp > 0 && tmp < | 1564 | if (tmp > 0 && tmp < |
1343 | cm_node->tcp_cntxt.mss) | 1565 | cm_node->tcp_cntxt.mss) |
1344 | cm_node->tcp_cntxt.mss = tmp; | 1566 | cm_node->tcp_cntxt.mss = tmp; |
1345 | } | 1567 | } |
1346 | break; | 1568 | break; |
@@ -1348,12 +1570,9 @@ static int process_options(struct nes_cm_node *cm_node, u8 *optionsloc, | |||
1348 | cm_node->tcp_cntxt.snd_wscale = | 1570 | cm_node->tcp_cntxt.snd_wscale = |
1349 | all_options->as_windowscale.shiftcount; | 1571 | all_options->as_windowscale.shiftcount; |
1350 | break; | 1572 | break; |
1351 | case OPTION_NUMBER_WRITE0: | ||
1352 | cm_node->send_write0 = 1; | ||
1353 | break; | ||
1354 | default: | 1573 | default: |
1355 | nes_debug(NES_DBG_CM, "TCP Option not understood: %x\n", | 1574 | nes_debug(NES_DBG_CM, "TCP Option not understood: %x\n", |
1356 | all_options->as_base.optionnum); | 1575 | all_options->as_base.optionnum); |
1357 | break; | 1576 | break; |
1358 | } | 1577 | } |
1359 | offset += all_options->as_base.length; | 1578 | offset += all_options->as_base.length; |
@@ -1372,8 +1591,8 @@ static void drop_packet(struct sk_buff *skb) | |||
1372 | static void handle_fin_pkt(struct nes_cm_node *cm_node) | 1591 | static void handle_fin_pkt(struct nes_cm_node *cm_node) |
1373 | { | 1592 | { |
1374 | nes_debug(NES_DBG_CM, "Received FIN, cm_node = %p, state = %u. " | 1593 | nes_debug(NES_DBG_CM, "Received FIN, cm_node = %p, state = %u. " |
1375 | "refcnt=%d\n", cm_node, cm_node->state, | 1594 | "refcnt=%d\n", cm_node, cm_node->state, |
1376 | atomic_read(&cm_node->ref_count)); | 1595 | atomic_read(&cm_node->ref_count)); |
1377 | switch (cm_node->state) { | 1596 | switch (cm_node->state) { |
1378 | case NES_CM_STATE_SYN_RCVD: | 1597 | case NES_CM_STATE_SYN_RCVD: |
1379 | case NES_CM_STATE_SYN_SENT: | 1598 | case NES_CM_STATE_SYN_SENT: |
@@ -1439,7 +1658,20 @@ static void handle_rst_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1439 | nes_debug(NES_DBG_CM, "%s[%u] create abort for cm_node=%p " | 1658 | nes_debug(NES_DBG_CM, "%s[%u] create abort for cm_node=%p " |
1440 | "listener=%p state=%d\n", __func__, __LINE__, cm_node, | 1659 | "listener=%p state=%d\n", __func__, __LINE__, cm_node, |
1441 | cm_node->listener, cm_node->state); | 1660 | cm_node->listener, cm_node->state); |
1442 | active_open_err(cm_node, skb, reset); | 1661 | switch (cm_node->mpa_frame_rev) { |
1662 | case IETF_MPA_V2: | ||
1663 | cm_node->mpa_frame_rev = IETF_MPA_V1; | ||
1664 | /* send a syn and goto syn sent state */ | ||
1665 | cm_node->state = NES_CM_STATE_SYN_SENT; | ||
1666 | if (send_syn(cm_node, 0, NULL)) { | ||
1667 | active_open_err(cm_node, skb, reset); | ||
1668 | } | ||
1669 | break; | ||
1670 | case IETF_MPA_V1: | ||
1671 | default: | ||
1672 | active_open_err(cm_node, skb, reset); | ||
1673 | break; | ||
1674 | } | ||
1443 | break; | 1675 | break; |
1444 | case NES_CM_STATE_MPAREQ_RCVD: | 1676 | case NES_CM_STATE_MPAREQ_RCVD: |
1445 | atomic_inc(&cm_node->passive_state); | 1677 | atomic_inc(&cm_node->passive_state); |
@@ -1475,21 +1707,21 @@ static void handle_rst_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1475 | 1707 | ||
1476 | static void handle_rcv_mpa(struct nes_cm_node *cm_node, struct sk_buff *skb) | 1708 | static void handle_rcv_mpa(struct nes_cm_node *cm_node, struct sk_buff *skb) |
1477 | { | 1709 | { |
1478 | 1710 | int ret = 0; | |
1479 | int ret = 0; | ||
1480 | int datasize = skb->len; | 1711 | int datasize = skb->len; |
1481 | u8 *dataloc = skb->data; | 1712 | u8 *dataloc = skb->data; |
1482 | 1713 | ||
1483 | enum nes_cm_event_type type = NES_CM_EVENT_UNKNOWN; | 1714 | enum nes_cm_event_type type = NES_CM_EVENT_UNKNOWN; |
1484 | u32 res_type; | 1715 | u32 res_type; |
1716 | |||
1485 | ret = parse_mpa(cm_node, dataloc, &res_type, datasize); | 1717 | ret = parse_mpa(cm_node, dataloc, &res_type, datasize); |
1486 | if (ret) { | 1718 | if (ret) { |
1487 | nes_debug(NES_DBG_CM, "didn't like MPA Request\n"); | 1719 | nes_debug(NES_DBG_CM, "didn't like MPA Request\n"); |
1488 | if (cm_node->state == NES_CM_STATE_MPAREQ_SENT) { | 1720 | if (cm_node->state == NES_CM_STATE_MPAREQ_SENT) { |
1489 | nes_debug(NES_DBG_CM, "%s[%u] create abort for " | 1721 | nes_debug(NES_DBG_CM, "%s[%u] create abort for " |
1490 | "cm_node=%p listener=%p state=%d\n", __func__, | 1722 | "cm_node=%p listener=%p state=%d\n", __func__, |
1491 | __LINE__, cm_node, cm_node->listener, | 1723 | __LINE__, cm_node, cm_node->listener, |
1492 | cm_node->state); | 1724 | cm_node->state); |
1493 | active_open_err(cm_node, skb, 1); | 1725 | active_open_err(cm_node, skb, 1); |
1494 | } else { | 1726 | } else { |
1495 | passive_open_err(cm_node, skb, 1); | 1727 | passive_open_err(cm_node, skb, 1); |
@@ -1499,16 +1731,15 @@ static void handle_rcv_mpa(struct nes_cm_node *cm_node, struct sk_buff *skb) | |||
1499 | 1731 | ||
1500 | switch (cm_node->state) { | 1732 | switch (cm_node->state) { |
1501 | case NES_CM_STATE_ESTABLISHED: | 1733 | case NES_CM_STATE_ESTABLISHED: |
1502 | if (res_type == NES_MPA_REQUEST_REJECT) { | 1734 | if (res_type == NES_MPA_REQUEST_REJECT) |
1503 | /*BIG problem as we are receiving the MPA.. So should | 1735 | /*BIG problem as we are receiving the MPA.. So should |
1504 | * not be REJECT.. This is Passive Open.. We can | 1736 | * not be REJECT.. This is Passive Open.. We can |
1505 | * only receive it Reject for Active Open...*/ | 1737 | * only receive it Reject for Active Open...*/ |
1506 | WARN_ON(1); | 1738 | WARN_ON(1); |
1507 | } | ||
1508 | cm_node->state = NES_CM_STATE_MPAREQ_RCVD; | 1739 | cm_node->state = NES_CM_STATE_MPAREQ_RCVD; |
1509 | type = NES_CM_EVENT_MPA_REQ; | 1740 | type = NES_CM_EVENT_MPA_REQ; |
1510 | atomic_set(&cm_node->passive_state, | 1741 | atomic_set(&cm_node->passive_state, |
1511 | NES_PASSIVE_STATE_INDICATED); | 1742 | NES_PASSIVE_STATE_INDICATED); |
1512 | break; | 1743 | break; |
1513 | case NES_CM_STATE_MPAREQ_SENT: | 1744 | case NES_CM_STATE_MPAREQ_SENT: |
1514 | cleanup_retrans_entry(cm_node); | 1745 | cleanup_retrans_entry(cm_node); |
@@ -1535,8 +1766,8 @@ static void indicate_pkt_err(struct nes_cm_node *cm_node, struct sk_buff *skb) | |||
1535 | case NES_CM_STATE_SYN_SENT: | 1766 | case NES_CM_STATE_SYN_SENT: |
1536 | case NES_CM_STATE_MPAREQ_SENT: | 1767 | case NES_CM_STATE_MPAREQ_SENT: |
1537 | nes_debug(NES_DBG_CM, "%s[%u] create abort for cm_node=%p " | 1768 | nes_debug(NES_DBG_CM, "%s[%u] create abort for cm_node=%p " |
1538 | "listener=%p state=%d\n", __func__, __LINE__, cm_node, | 1769 | "listener=%p state=%d\n", __func__, __LINE__, cm_node, |
1539 | cm_node->listener, cm_node->state); | 1770 | cm_node->listener, cm_node->state); |
1540 | active_open_err(cm_node, skb, 1); | 1771 | active_open_err(cm_node, skb, 1); |
1541 | break; | 1772 | break; |
1542 | case NES_CM_STATE_ESTABLISHED: | 1773 | case NES_CM_STATE_ESTABLISHED: |
@@ -1550,11 +1781,11 @@ static void indicate_pkt_err(struct nes_cm_node *cm_node, struct sk_buff *skb) | |||
1550 | } | 1781 | } |
1551 | 1782 | ||
1552 | static int check_syn(struct nes_cm_node *cm_node, struct tcphdr *tcph, | 1783 | static int check_syn(struct nes_cm_node *cm_node, struct tcphdr *tcph, |
1553 | struct sk_buff *skb) | 1784 | struct sk_buff *skb) |
1554 | { | 1785 | { |
1555 | int err; | 1786 | int err; |
1556 | 1787 | ||
1557 | err = ((ntohl(tcph->ack_seq) == cm_node->tcp_cntxt.loc_seq_num))? 0 : 1; | 1788 | err = ((ntohl(tcph->ack_seq) == cm_node->tcp_cntxt.loc_seq_num)) ? 0 : 1; |
1558 | if (err) | 1789 | if (err) |
1559 | active_open_err(cm_node, skb, 1); | 1790 | active_open_err(cm_node, skb, 1); |
1560 | 1791 | ||
@@ -1562,7 +1793,7 @@ static int check_syn(struct nes_cm_node *cm_node, struct tcphdr *tcph, | |||
1562 | } | 1793 | } |
1563 | 1794 | ||
1564 | static int check_seq(struct nes_cm_node *cm_node, struct tcphdr *tcph, | 1795 | static int check_seq(struct nes_cm_node *cm_node, struct tcphdr *tcph, |
1565 | struct sk_buff *skb) | 1796 | struct sk_buff *skb) |
1566 | { | 1797 | { |
1567 | int err = 0; | 1798 | int err = 0; |
1568 | u32 seq; | 1799 | u32 seq; |
@@ -1570,21 +1801,22 @@ static int check_seq(struct nes_cm_node *cm_node, struct tcphdr *tcph, | |||
1570 | u32 loc_seq_num = cm_node->tcp_cntxt.loc_seq_num; | 1801 | u32 loc_seq_num = cm_node->tcp_cntxt.loc_seq_num; |
1571 | u32 rcv_nxt = cm_node->tcp_cntxt.rcv_nxt; | 1802 | u32 rcv_nxt = cm_node->tcp_cntxt.rcv_nxt; |
1572 | u32 rcv_wnd; | 1803 | u32 rcv_wnd; |
1804 | |||
1573 | seq = ntohl(tcph->seq); | 1805 | seq = ntohl(tcph->seq); |
1574 | ack_seq = ntohl(tcph->ack_seq); | 1806 | ack_seq = ntohl(tcph->ack_seq); |
1575 | rcv_wnd = cm_node->tcp_cntxt.rcv_wnd; | 1807 | rcv_wnd = cm_node->tcp_cntxt.rcv_wnd; |
1576 | if (ack_seq != loc_seq_num) | 1808 | if (ack_seq != loc_seq_num) |
1577 | err = 1; | 1809 | err = 1; |
1578 | else if (!between(seq, rcv_nxt, (rcv_nxt+rcv_wnd))) | 1810 | else if (!between(seq, rcv_nxt, (rcv_nxt + rcv_wnd))) |
1579 | err = 1; | 1811 | err = 1; |
1580 | if (err) { | 1812 | if (err) { |
1581 | nes_debug(NES_DBG_CM, "%s[%u] create abort for cm_node=%p " | 1813 | nes_debug(NES_DBG_CM, "%s[%u] create abort for cm_node=%p " |
1582 | "listener=%p state=%d\n", __func__, __LINE__, cm_node, | 1814 | "listener=%p state=%d\n", __func__, __LINE__, cm_node, |
1583 | cm_node->listener, cm_node->state); | 1815 | cm_node->listener, cm_node->state); |
1584 | indicate_pkt_err(cm_node, skb); | 1816 | indicate_pkt_err(cm_node, skb); |
1585 | nes_debug(NES_DBG_CM, "seq ERROR cm_node =%p seq=0x%08X " | 1817 | nes_debug(NES_DBG_CM, "seq ERROR cm_node =%p seq=0x%08X " |
1586 | "rcv_nxt=0x%08X rcv_wnd=0x%x\n", cm_node, seq, rcv_nxt, | 1818 | "rcv_nxt=0x%08X rcv_wnd=0x%x\n", cm_node, seq, rcv_nxt, |
1587 | rcv_wnd); | 1819 | rcv_wnd); |
1588 | } | 1820 | } |
1589 | return err; | 1821 | return err; |
1590 | } | 1822 | } |
@@ -1594,9 +1826,8 @@ static int check_seq(struct nes_cm_node *cm_node, struct tcphdr *tcph, | |||
1594 | * is created with a listener or it may comein as rexmitted packet which in | 1826 | * is created with a listener or it may comein as rexmitted packet which in |
1595 | * that case will be just dropped. | 1827 | * that case will be just dropped. |
1596 | */ | 1828 | */ |
1597 | |||
1598 | static void handle_syn_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | 1829 | static void handle_syn_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, |
1599 | struct tcphdr *tcph) | 1830 | struct tcphdr *tcph) |
1600 | { | 1831 | { |
1601 | int ret; | 1832 | int ret; |
1602 | u32 inc_sequence; | 1833 | u32 inc_sequence; |
@@ -1615,15 +1846,15 @@ static void handle_syn_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1615 | case NES_CM_STATE_LISTENING: | 1846 | case NES_CM_STATE_LISTENING: |
1616 | /* Passive OPEN */ | 1847 | /* Passive OPEN */ |
1617 | if (atomic_read(&cm_node->listener->pend_accepts_cnt) > | 1848 | if (atomic_read(&cm_node->listener->pend_accepts_cnt) > |
1618 | cm_node->listener->backlog) { | 1849 | cm_node->listener->backlog) { |
1619 | nes_debug(NES_DBG_CM, "drop syn due to backlog " | 1850 | nes_debug(NES_DBG_CM, "drop syn due to backlog " |
1620 | "pressure \n"); | 1851 | "pressure \n"); |
1621 | cm_backlog_drops++; | 1852 | cm_backlog_drops++; |
1622 | passive_open_err(cm_node, skb, 0); | 1853 | passive_open_err(cm_node, skb, 0); |
1623 | break; | 1854 | break; |
1624 | } | 1855 | } |
1625 | ret = handle_tcp_options(cm_node, tcph, skb, optionsize, | 1856 | ret = handle_tcp_options(cm_node, tcph, skb, optionsize, |
1626 | 1); | 1857 | 1); |
1627 | if (ret) { | 1858 | if (ret) { |
1628 | passive_open_err(cm_node, skb, 0); | 1859 | passive_open_err(cm_node, skb, 0); |
1629 | /* drop pkt */ | 1860 | /* drop pkt */ |
@@ -1657,9 +1888,8 @@ static void handle_syn_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1657 | } | 1888 | } |
1658 | 1889 | ||
1659 | static void handle_synack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | 1890 | static void handle_synack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, |
1660 | struct tcphdr *tcph) | 1891 | struct tcphdr *tcph) |
1661 | { | 1892 | { |
1662 | |||
1663 | int ret; | 1893 | int ret; |
1664 | u32 inc_sequence; | 1894 | u32 inc_sequence; |
1665 | int optionsize; | 1895 | int optionsize; |
@@ -1678,7 +1908,7 @@ static void handle_synack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1678 | ret = handle_tcp_options(cm_node, tcph, skb, optionsize, 0); | 1908 | ret = handle_tcp_options(cm_node, tcph, skb, optionsize, 0); |
1679 | if (ret) { | 1909 | if (ret) { |
1680 | nes_debug(NES_DBG_CM, "cm_node=%p tcp_options failed\n", | 1910 | nes_debug(NES_DBG_CM, "cm_node=%p tcp_options failed\n", |
1681 | cm_node); | 1911 | cm_node); |
1682 | break; | 1912 | break; |
1683 | } | 1913 | } |
1684 | cleanup_retrans_entry(cm_node); | 1914 | cleanup_retrans_entry(cm_node); |
@@ -1717,12 +1947,13 @@ static void handle_synack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1717 | } | 1947 | } |
1718 | 1948 | ||
1719 | static int handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | 1949 | static int handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, |
1720 | struct tcphdr *tcph) | 1950 | struct tcphdr *tcph) |
1721 | { | 1951 | { |
1722 | int datasize = 0; | 1952 | int datasize = 0; |
1723 | u32 inc_sequence; | 1953 | u32 inc_sequence; |
1724 | int ret = 0; | 1954 | int ret = 0; |
1725 | int optionsize; | 1955 | int optionsize; |
1956 | |||
1726 | optionsize = (tcph->doff << 2) - sizeof(struct tcphdr); | 1957 | optionsize = (tcph->doff << 2) - sizeof(struct tcphdr); |
1727 | 1958 | ||
1728 | if (check_seq(cm_node, tcph, skb)) | 1959 | if (check_seq(cm_node, tcph, skb)) |
@@ -1743,8 +1974,9 @@ static int handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1743 | if (datasize) { | 1974 | if (datasize) { |
1744 | cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize; | 1975 | cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize; |
1745 | handle_rcv_mpa(cm_node, skb); | 1976 | handle_rcv_mpa(cm_node, skb); |
1746 | } else /* rcvd ACK only */ | 1977 | } else { /* rcvd ACK only */ |
1747 | dev_kfree_skb_any(skb); | 1978 | dev_kfree_skb_any(skb); |
1979 | } | ||
1748 | break; | 1980 | break; |
1749 | case NES_CM_STATE_ESTABLISHED: | 1981 | case NES_CM_STATE_ESTABLISHED: |
1750 | /* Passive OPEN */ | 1982 | /* Passive OPEN */ |
@@ -1752,16 +1984,18 @@ static int handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1752 | if (datasize) { | 1984 | if (datasize) { |
1753 | cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize; | 1985 | cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize; |
1754 | handle_rcv_mpa(cm_node, skb); | 1986 | handle_rcv_mpa(cm_node, skb); |
1755 | } else | 1987 | } else { |
1756 | drop_packet(skb); | 1988 | drop_packet(skb); |
1989 | } | ||
1757 | break; | 1990 | break; |
1758 | case NES_CM_STATE_MPAREQ_SENT: | 1991 | case NES_CM_STATE_MPAREQ_SENT: |
1759 | cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq); | 1992 | cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq); |
1760 | if (datasize) { | 1993 | if (datasize) { |
1761 | cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize; | 1994 | cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize; |
1762 | handle_rcv_mpa(cm_node, skb); | 1995 | handle_rcv_mpa(cm_node, skb); |
1763 | } else /* Could be just an ack pkt.. */ | 1996 | } else { /* Could be just an ack pkt.. */ |
1764 | dev_kfree_skb_any(skb); | 1997 | dev_kfree_skb_any(skb); |
1998 | } | ||
1765 | break; | 1999 | break; |
1766 | case NES_CM_STATE_LISTENING: | 2000 | case NES_CM_STATE_LISTENING: |
1767 | cleanup_retrans_entry(cm_node); | 2001 | cleanup_retrans_entry(cm_node); |
@@ -1802,14 +2036,15 @@ static int handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1802 | 2036 | ||
1803 | 2037 | ||
1804 | static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph, | 2038 | static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph, |
1805 | struct sk_buff *skb, int optionsize, int passive) | 2039 | struct sk_buff *skb, int optionsize, int passive) |
1806 | { | 2040 | { |
1807 | u8 *optionsloc = (u8 *)&tcph[1]; | 2041 | u8 *optionsloc = (u8 *)&tcph[1]; |
2042 | |||
1808 | if (optionsize) { | 2043 | if (optionsize) { |
1809 | if (process_options(cm_node, optionsloc, optionsize, | 2044 | if (process_options(cm_node, optionsloc, optionsize, |
1810 | (u32)tcph->syn)) { | 2045 | (u32)tcph->syn)) { |
1811 | nes_debug(NES_DBG_CM, "%s: Node %p, Sending RESET\n", | 2046 | nes_debug(NES_DBG_CM, "%s: Node %p, Sending RESET\n", |
1812 | __func__, cm_node); | 2047 | __func__, cm_node); |
1813 | if (passive) | 2048 | if (passive) |
1814 | passive_open_err(cm_node, skb, 1); | 2049 | passive_open_err(cm_node, skb, 1); |
1815 | else | 2050 | else |
@@ -1819,7 +2054,7 @@ static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph, | |||
1819 | } | 2054 | } |
1820 | 2055 | ||
1821 | cm_node->tcp_cntxt.snd_wnd = ntohs(tcph->window) << | 2056 | cm_node->tcp_cntxt.snd_wnd = ntohs(tcph->window) << |
1822 | cm_node->tcp_cntxt.snd_wscale; | 2057 | cm_node->tcp_cntxt.snd_wscale; |
1823 | 2058 | ||
1824 | if (cm_node->tcp_cntxt.snd_wnd > cm_node->tcp_cntxt.max_snd_wnd) | 2059 | if (cm_node->tcp_cntxt.snd_wnd > cm_node->tcp_cntxt.max_snd_wnd) |
1825 | cm_node->tcp_cntxt.max_snd_wnd = cm_node->tcp_cntxt.snd_wnd; | 2060 | cm_node->tcp_cntxt.max_snd_wnd = cm_node->tcp_cntxt.snd_wnd; |
@@ -1830,18 +2065,18 @@ static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph, | |||
1830 | * active_open_err() will send reset() if flag set.. | 2065 | * active_open_err() will send reset() if flag set.. |
1831 | * It will also send ABORT event. | 2066 | * It will also send ABORT event. |
1832 | */ | 2067 | */ |
1833 | |||
1834 | static void active_open_err(struct nes_cm_node *cm_node, struct sk_buff *skb, | 2068 | static void active_open_err(struct nes_cm_node *cm_node, struct sk_buff *skb, |
1835 | int reset) | 2069 | int reset) |
1836 | { | 2070 | { |
1837 | cleanup_retrans_entry(cm_node); | 2071 | cleanup_retrans_entry(cm_node); |
1838 | if (reset) { | 2072 | if (reset) { |
1839 | nes_debug(NES_DBG_CM, "ERROR active err called for cm_node=%p, " | 2073 | nes_debug(NES_DBG_CM, "ERROR active err called for cm_node=%p, " |
1840 | "state=%d\n", cm_node, cm_node->state); | 2074 | "state=%d\n", cm_node, cm_node->state); |
1841 | add_ref_cm_node(cm_node); | 2075 | add_ref_cm_node(cm_node); |
1842 | send_reset(cm_node, skb); | 2076 | send_reset(cm_node, skb); |
1843 | } else | 2077 | } else { |
1844 | dev_kfree_skb_any(skb); | 2078 | dev_kfree_skb_any(skb); |
2079 | } | ||
1845 | 2080 | ||
1846 | cm_node->state = NES_CM_STATE_CLOSED; | 2081 | cm_node->state = NES_CM_STATE_CLOSED; |
1847 | create_event(cm_node, NES_CM_EVENT_ABORTED); | 2082 | create_event(cm_node, NES_CM_EVENT_ABORTED); |
@@ -1851,15 +2086,14 @@ static void active_open_err(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1851 | * passive_open_err() will either do a reset() or will free up the skb and | 2086 | * passive_open_err() will either do a reset() or will free up the skb and |
1852 | * remove the cm_node. | 2087 | * remove the cm_node. |
1853 | */ | 2088 | */ |
1854 | |||
1855 | static void passive_open_err(struct nes_cm_node *cm_node, struct sk_buff *skb, | 2089 | static void passive_open_err(struct nes_cm_node *cm_node, struct sk_buff *skb, |
1856 | int reset) | 2090 | int reset) |
1857 | { | 2091 | { |
1858 | cleanup_retrans_entry(cm_node); | 2092 | cleanup_retrans_entry(cm_node); |
1859 | cm_node->state = NES_CM_STATE_CLOSED; | 2093 | cm_node->state = NES_CM_STATE_CLOSED; |
1860 | if (reset) { | 2094 | if (reset) { |
1861 | nes_debug(NES_DBG_CM, "passive_open_err sending RST for " | 2095 | nes_debug(NES_DBG_CM, "passive_open_err sending RST for " |
1862 | "cm_node=%p state =%d\n", cm_node, cm_node->state); | 2096 | "cm_node=%p state =%d\n", cm_node, cm_node->state); |
1863 | send_reset(cm_node, skb); | 2097 | send_reset(cm_node, skb); |
1864 | } else { | 2098 | } else { |
1865 | dev_kfree_skb_any(skb); | 2099 | dev_kfree_skb_any(skb); |
@@ -1874,6 +2108,7 @@ static void passive_open_err(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1874 | static void free_retrans_entry(struct nes_cm_node *cm_node) | 2108 | static void free_retrans_entry(struct nes_cm_node *cm_node) |
1875 | { | 2109 | { |
1876 | struct nes_timer_entry *send_entry; | 2110 | struct nes_timer_entry *send_entry; |
2111 | |||
1877 | send_entry = cm_node->send_entry; | 2112 | send_entry = cm_node->send_entry; |
1878 | if (send_entry) { | 2113 | if (send_entry) { |
1879 | cm_node->send_entry = NULL; | 2114 | cm_node->send_entry = NULL; |
@@ -1897,26 +2132,28 @@ static void cleanup_retrans_entry(struct nes_cm_node *cm_node) | |||
1897 | * Returns skb if to be freed, else it will return NULL if already used.. | 2132 | * Returns skb if to be freed, else it will return NULL if already used.. |
1898 | */ | 2133 | */ |
1899 | static void process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb, | 2134 | static void process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb, |
1900 | struct nes_cm_core *cm_core) | 2135 | struct nes_cm_core *cm_core) |
1901 | { | 2136 | { |
1902 | enum nes_tcpip_pkt_type pkt_type = NES_PKT_TYPE_UNKNOWN; | 2137 | enum nes_tcpip_pkt_type pkt_type = NES_PKT_TYPE_UNKNOWN; |
1903 | struct tcphdr *tcph = tcp_hdr(skb); | 2138 | struct tcphdr *tcph = tcp_hdr(skb); |
1904 | u32 fin_set = 0; | 2139 | u32 fin_set = 0; |
1905 | int ret = 0; | 2140 | int ret = 0; |
2141 | |||
1906 | skb_pull(skb, ip_hdr(skb)->ihl << 2); | 2142 | skb_pull(skb, ip_hdr(skb)->ihl << 2); |
1907 | 2143 | ||
1908 | nes_debug(NES_DBG_CM, "process_packet: cm_node=%p state =%d syn=%d " | 2144 | nes_debug(NES_DBG_CM, "process_packet: cm_node=%p state =%d syn=%d " |
1909 | "ack=%d rst=%d fin=%d\n", cm_node, cm_node->state, tcph->syn, | 2145 | "ack=%d rst=%d fin=%d\n", cm_node, cm_node->state, tcph->syn, |
1910 | tcph->ack, tcph->rst, tcph->fin); | 2146 | tcph->ack, tcph->rst, tcph->fin); |
1911 | 2147 | ||
1912 | if (tcph->rst) | 2148 | if (tcph->rst) { |
1913 | pkt_type = NES_PKT_TYPE_RST; | 2149 | pkt_type = NES_PKT_TYPE_RST; |
1914 | else if (tcph->syn) { | 2150 | } else if (tcph->syn) { |
1915 | pkt_type = NES_PKT_TYPE_SYN; | 2151 | pkt_type = NES_PKT_TYPE_SYN; |
1916 | if (tcph->ack) | 2152 | if (tcph->ack) |
1917 | pkt_type = NES_PKT_TYPE_SYNACK; | 2153 | pkt_type = NES_PKT_TYPE_SYNACK; |
1918 | } else if (tcph->ack) | 2154 | } else if (tcph->ack) { |
1919 | pkt_type = NES_PKT_TYPE_ACK; | 2155 | pkt_type = NES_PKT_TYPE_ACK; |
2156 | } | ||
1920 | if (tcph->fin) | 2157 | if (tcph->fin) |
1921 | fin_set = 1; | 2158 | fin_set = 1; |
1922 | 2159 | ||
@@ -1947,17 +2184,17 @@ static void process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1947 | * mini_cm_listen - create a listen node with params | 2184 | * mini_cm_listen - create a listen node with params |
1948 | */ | 2185 | */ |
1949 | static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *cm_core, | 2186 | static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *cm_core, |
1950 | struct nes_vnic *nesvnic, struct nes_cm_info *cm_info) | 2187 | struct nes_vnic *nesvnic, struct nes_cm_info *cm_info) |
1951 | { | 2188 | { |
1952 | struct nes_cm_listener *listener; | 2189 | struct nes_cm_listener *listener; |
1953 | unsigned long flags; | 2190 | unsigned long flags; |
1954 | 2191 | ||
1955 | nes_debug(NES_DBG_CM, "Search for 0x%08x : 0x%04x\n", | 2192 | nes_debug(NES_DBG_CM, "Search for 0x%08x : 0x%04x\n", |
1956 | cm_info->loc_addr, cm_info->loc_port); | 2193 | cm_info->loc_addr, cm_info->loc_port); |
1957 | 2194 | ||
1958 | /* cannot have multiple matching listeners */ | 2195 | /* cannot have multiple matching listeners */ |
1959 | listener = find_listener(cm_core, htonl(cm_info->loc_addr), | 2196 | listener = find_listener(cm_core, htonl(cm_info->loc_addr), |
1960 | htons(cm_info->loc_port), NES_CM_LISTENER_EITHER_STATE); | 2197 | htons(cm_info->loc_port), NES_CM_LISTENER_EITHER_STATE); |
1961 | if (listener && listener->listener_state == NES_CM_LISTENER_ACTIVE_STATE) { | 2198 | if (listener && listener->listener_state == NES_CM_LISTENER_ACTIVE_STATE) { |
1962 | /* find automatically incs ref count ??? */ | 2199 | /* find automatically incs ref count ??? */ |
1963 | atomic_dec(&listener->ref_count); | 2200 | atomic_dec(&listener->ref_count); |
@@ -2003,9 +2240,9 @@ static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *cm_core, | |||
2003 | } | 2240 | } |
2004 | 2241 | ||
2005 | nes_debug(NES_DBG_CM, "Api - listen(): addr=0x%08X, port=0x%04x," | 2242 | nes_debug(NES_DBG_CM, "Api - listen(): addr=0x%08X, port=0x%04x," |
2006 | " listener = %p, backlog = %d, cm_id = %p.\n", | 2243 | " listener = %p, backlog = %d, cm_id = %p.\n", |
2007 | cm_info->loc_addr, cm_info->loc_port, | 2244 | cm_info->loc_addr, cm_info->loc_port, |
2008 | listener, listener->backlog, listener->cm_id); | 2245 | listener, listener->backlog, listener->cm_id); |
2009 | 2246 | ||
2010 | return listener; | 2247 | return listener; |
2011 | } | 2248 | } |
@@ -2015,26 +2252,20 @@ static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *cm_core, | |||
2015 | * mini_cm_connect - make a connection node with params | 2252 | * mini_cm_connect - make a connection node with params |
2016 | */ | 2253 | */ |
2017 | static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core, | 2254 | static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core, |
2018 | struct nes_vnic *nesvnic, u16 private_data_len, | 2255 | struct nes_vnic *nesvnic, u16 private_data_len, |
2019 | void *private_data, struct nes_cm_info *cm_info) | 2256 | void *private_data, struct nes_cm_info *cm_info) |
2020 | { | 2257 | { |
2021 | int ret = 0; | 2258 | int ret = 0; |
2022 | struct nes_cm_node *cm_node; | 2259 | struct nes_cm_node *cm_node; |
2023 | struct nes_cm_listener *loopbackremotelistener; | 2260 | struct nes_cm_listener *loopbackremotelistener; |
2024 | struct nes_cm_node *loopbackremotenode; | 2261 | struct nes_cm_node *loopbackremotenode; |
2025 | struct nes_cm_info loopback_cm_info; | 2262 | struct nes_cm_info loopback_cm_info; |
2026 | u16 mpa_frame_size = sizeof(struct ietf_mpa_frame) + private_data_len; | 2263 | u8 *start_buff; |
2027 | struct ietf_mpa_frame *mpa_frame = NULL; | ||
2028 | 2264 | ||
2029 | /* create a CM connection node */ | 2265 | /* create a CM connection node */ |
2030 | cm_node = make_cm_node(cm_core, nesvnic, cm_info, NULL); | 2266 | cm_node = make_cm_node(cm_core, nesvnic, cm_info, NULL); |
2031 | if (!cm_node) | 2267 | if (!cm_node) |
2032 | return NULL; | 2268 | return NULL; |
2033 | mpa_frame = &cm_node->mpa_frame; | ||
2034 | memcpy(mpa_frame->key, IEFT_MPA_KEY_REQ, IETF_MPA_KEY_SIZE); | ||
2035 | mpa_frame->flags = IETF_MPA_FLAGS_CRC; | ||
2036 | mpa_frame->rev = IETF_MPA_VERSION; | ||
2037 | mpa_frame->priv_data_len = htons(private_data_len); | ||
2038 | 2269 | ||
2039 | /* set our node side to client (active) side */ | 2270 | /* set our node side to client (active) side */ |
2040 | cm_node->tcp_cntxt.client = 1; | 2271 | cm_node->tcp_cntxt.client = 1; |
@@ -2042,8 +2273,8 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core, | |||
2042 | 2273 | ||
2043 | if (cm_info->loc_addr == cm_info->rem_addr) { | 2274 | if (cm_info->loc_addr == cm_info->rem_addr) { |
2044 | loopbackremotelistener = find_listener(cm_core, | 2275 | loopbackremotelistener = find_listener(cm_core, |
2045 | ntohl(nesvnic->local_ipaddr), cm_node->rem_port, | 2276 | ntohl(nesvnic->local_ipaddr), cm_node->rem_port, |
2046 | NES_CM_LISTENER_ACTIVE_STATE); | 2277 | NES_CM_LISTENER_ACTIVE_STATE); |
2047 | if (loopbackremotelistener == NULL) { | 2278 | if (loopbackremotelistener == NULL) { |
2048 | create_event(cm_node, NES_CM_EVENT_ABORTED); | 2279 | create_event(cm_node, NES_CM_EVENT_ABORTED); |
2049 | } else { | 2280 | } else { |
@@ -2052,7 +2283,7 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core, | |||
2052 | loopback_cm_info.rem_port = cm_info->loc_port; | 2283 | loopback_cm_info.rem_port = cm_info->loc_port; |
2053 | loopback_cm_info.cm_id = loopbackremotelistener->cm_id; | 2284 | loopback_cm_info.cm_id = loopbackremotelistener->cm_id; |
2054 | loopbackremotenode = make_cm_node(cm_core, nesvnic, | 2285 | loopbackremotenode = make_cm_node(cm_core, nesvnic, |
2055 | &loopback_cm_info, loopbackremotelistener); | 2286 | &loopback_cm_info, loopbackremotelistener); |
2056 | if (!loopbackremotenode) { | 2287 | if (!loopbackremotenode) { |
2057 | rem_ref_cm_node(cm_node->cm_core, cm_node); | 2288 | rem_ref_cm_node(cm_node->cm_core, cm_node); |
2058 | return NULL; | 2289 | return NULL; |
@@ -2063,7 +2294,7 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core, | |||
2063 | NES_CM_DEFAULT_RCV_WND_SCALE; | 2294 | NES_CM_DEFAULT_RCV_WND_SCALE; |
2064 | cm_node->loopbackpartner = loopbackremotenode; | 2295 | cm_node->loopbackpartner = loopbackremotenode; |
2065 | memcpy(loopbackremotenode->mpa_frame_buf, private_data, | 2296 | memcpy(loopbackremotenode->mpa_frame_buf, private_data, |
2066 | private_data_len); | 2297 | private_data_len); |
2067 | loopbackremotenode->mpa_frame_size = private_data_len; | 2298 | loopbackremotenode->mpa_frame_size = private_data_len; |
2068 | 2299 | ||
2069 | /* we are done handling this state. */ | 2300 | /* we are done handling this state. */ |
@@ -2091,12 +2322,10 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core, | |||
2091 | return cm_node; | 2322 | return cm_node; |
2092 | } | 2323 | } |
2093 | 2324 | ||
2094 | /* set our node side to client (active) side */ | 2325 | start_buff = &cm_node->mpa_frame_buf[0] + sizeof(struct ietf_mpa_v2); |
2095 | cm_node->tcp_cntxt.client = 1; | 2326 | cm_node->mpa_frame_size = private_data_len; |
2096 | /* init our MPA frame ptr */ | ||
2097 | memcpy(mpa_frame->priv_data, private_data, private_data_len); | ||
2098 | 2327 | ||
2099 | cm_node->mpa_frame_size = mpa_frame_size; | 2328 | memcpy(start_buff, private_data, private_data_len); |
2100 | 2329 | ||
2101 | /* send a syn and goto syn sent state */ | 2330 | /* send a syn and goto syn sent state */ |
2102 | cm_node->state = NES_CM_STATE_SYN_SENT; | 2331 | cm_node->state = NES_CM_STATE_SYN_SENT; |
@@ -2105,18 +2334,19 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core, | |||
2105 | if (ret) { | 2334 | if (ret) { |
2106 | /* error in sending the syn free up the cm_node struct */ | 2335 | /* error in sending the syn free up the cm_node struct */ |
2107 | nes_debug(NES_DBG_CM, "Api - connect() FAILED: dest " | 2336 | nes_debug(NES_DBG_CM, "Api - connect() FAILED: dest " |
2108 | "addr=0x%08X, port=0x%04x, cm_node=%p, cm_id = %p.\n", | 2337 | "addr=0x%08X, port=0x%04x, cm_node=%p, cm_id = %p.\n", |
2109 | cm_node->rem_addr, cm_node->rem_port, cm_node, | 2338 | cm_node->rem_addr, cm_node->rem_port, cm_node, |
2110 | cm_node->cm_id); | 2339 | cm_node->cm_id); |
2111 | rem_ref_cm_node(cm_node->cm_core, cm_node); | 2340 | rem_ref_cm_node(cm_node->cm_core, cm_node); |
2112 | cm_node = NULL; | 2341 | cm_node = NULL; |
2113 | } | 2342 | } |
2114 | 2343 | ||
2115 | if (cm_node) | 2344 | if (cm_node) { |
2116 | nes_debug(NES_DBG_CM, "Api - connect(): dest addr=0x%08X," | 2345 | nes_debug(NES_DBG_CM, "Api - connect(): dest addr=0x%08X," |
2117 | "port=0x%04x, cm_node=%p, cm_id = %p.\n", | 2346 | "port=0x%04x, cm_node=%p, cm_id = %p.\n", |
2118 | cm_node->rem_addr, cm_node->rem_port, cm_node, | 2347 | cm_node->rem_addr, cm_node->rem_port, cm_node, |
2119 | cm_node->cm_id); | 2348 | cm_node->cm_id); |
2349 | } | ||
2120 | 2350 | ||
2121 | return cm_node; | 2351 | return cm_node; |
2122 | } | 2352 | } |
@@ -2126,8 +2356,7 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core, | |||
2126 | * mini_cm_accept - accept a connection | 2356 | * mini_cm_accept - accept a connection |
2127 | * This function is never called | 2357 | * This function is never called |
2128 | */ | 2358 | */ |
2129 | static int mini_cm_accept(struct nes_cm_core *cm_core, | 2359 | static int mini_cm_accept(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node) |
2130 | struct ietf_mpa_frame *mpa_frame, struct nes_cm_node *cm_node) | ||
2131 | { | 2360 | { |
2132 | return 0; | 2361 | return 0; |
2133 | } | 2362 | } |
@@ -2136,8 +2365,7 @@ static int mini_cm_accept(struct nes_cm_core *cm_core, | |||
2136 | /** | 2365 | /** |
2137 | * mini_cm_reject - reject and teardown a connection | 2366 | * mini_cm_reject - reject and teardown a connection |
2138 | */ | 2367 | */ |
2139 | static int mini_cm_reject(struct nes_cm_core *cm_core, | 2368 | static int mini_cm_reject(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node) |
2140 | struct ietf_mpa_frame *mpa_frame, struct nes_cm_node *cm_node) | ||
2141 | { | 2369 | { |
2142 | int ret = 0; | 2370 | int ret = 0; |
2143 | int err = 0; | 2371 | int err = 0; |
@@ -2147,7 +2375,7 @@ static int mini_cm_reject(struct nes_cm_core *cm_core, | |||
2147 | struct nes_cm_node *loopback = cm_node->loopbackpartner; | 2375 | struct nes_cm_node *loopback = cm_node->loopbackpartner; |
2148 | 2376 | ||
2149 | nes_debug(NES_DBG_CM, "%s cm_node=%p type=%d state=%d\n", | 2377 | nes_debug(NES_DBG_CM, "%s cm_node=%p type=%d state=%d\n", |
2150 | __func__, cm_node, cm_node->tcp_cntxt.client, cm_node->state); | 2378 | __func__, cm_node, cm_node->tcp_cntxt.client, cm_node->state); |
2151 | 2379 | ||
2152 | if (cm_node->tcp_cntxt.client) | 2380 | if (cm_node->tcp_cntxt.client) |
2153 | return ret; | 2381 | return ret; |
@@ -2168,8 +2396,9 @@ static int mini_cm_reject(struct nes_cm_core *cm_core, | |||
2168 | err = send_reset(cm_node, NULL); | 2396 | err = send_reset(cm_node, NULL); |
2169 | if (err) | 2397 | if (err) |
2170 | WARN_ON(1); | 2398 | WARN_ON(1); |
2171 | } else | 2399 | } else { |
2172 | cm_id->add_ref(cm_id); | 2400 | cm_id->add_ref(cm_id); |
2401 | } | ||
2173 | } | 2402 | } |
2174 | } | 2403 | } |
2175 | } else { | 2404 | } else { |
@@ -2244,7 +2473,7 @@ static int mini_cm_close(struct nes_cm_core *cm_core, struct nes_cm_node *cm_nod | |||
2244 | case NES_CM_STATE_TSA: | 2473 | case NES_CM_STATE_TSA: |
2245 | if (cm_node->send_entry) | 2474 | if (cm_node->send_entry) |
2246 | printk(KERN_ERR "ERROR Close got called from STATE_TSA " | 2475 | printk(KERN_ERR "ERROR Close got called from STATE_TSA " |
2247 | "send_entry=%p\n", cm_node->send_entry); | 2476 | "send_entry=%p\n", cm_node->send_entry); |
2248 | ret = rem_ref_cm_node(cm_core, cm_node); | 2477 | ret = rem_ref_cm_node(cm_core, cm_node); |
2249 | break; | 2478 | break; |
2250 | } | 2479 | } |
@@ -2257,7 +2486,7 @@ static int mini_cm_close(struct nes_cm_core *cm_core, struct nes_cm_node *cm_nod | |||
2257 | * node state machine | 2486 | * node state machine |
2258 | */ | 2487 | */ |
2259 | static int mini_cm_recv_pkt(struct nes_cm_core *cm_core, | 2488 | static int mini_cm_recv_pkt(struct nes_cm_core *cm_core, |
2260 | struct nes_vnic *nesvnic, struct sk_buff *skb) | 2489 | struct nes_vnic *nesvnic, struct sk_buff *skb) |
2261 | { | 2490 | { |
2262 | struct nes_cm_node *cm_node = NULL; | 2491 | struct nes_cm_node *cm_node = NULL; |
2263 | struct nes_cm_listener *listener = NULL; | 2492 | struct nes_cm_listener *listener = NULL; |
@@ -2269,9 +2498,8 @@ static int mini_cm_recv_pkt(struct nes_cm_core *cm_core, | |||
2269 | 2498 | ||
2270 | if (!skb) | 2499 | if (!skb) |
2271 | return 0; | 2500 | return 0; |
2272 | if (skb->len < sizeof(struct iphdr) + sizeof(struct tcphdr)) { | 2501 | if (skb->len < sizeof(struct iphdr) + sizeof(struct tcphdr)) |
2273 | return 0; | 2502 | return 0; |
2274 | } | ||
2275 | 2503 | ||
2276 | iph = (struct iphdr *)skb->data; | 2504 | iph = (struct iphdr *)skb->data; |
2277 | tcph = (struct tcphdr *)(skb->data + sizeof(struct iphdr)); | 2505 | tcph = (struct tcphdr *)(skb->data + sizeof(struct iphdr)); |
@@ -2289,8 +2517,8 @@ static int mini_cm_recv_pkt(struct nes_cm_core *cm_core, | |||
2289 | 2517 | ||
2290 | do { | 2518 | do { |
2291 | cm_node = find_node(cm_core, | 2519 | cm_node = find_node(cm_core, |
2292 | nfo.rem_port, nfo.rem_addr, | 2520 | nfo.rem_port, nfo.rem_addr, |
2293 | nfo.loc_port, nfo.loc_addr); | 2521 | nfo.loc_port, nfo.loc_addr); |
2294 | 2522 | ||
2295 | if (!cm_node) { | 2523 | if (!cm_node) { |
2296 | /* Only type of packet accepted are for */ | 2524 | /* Only type of packet accepted are for */ |
@@ -2300,8 +2528,8 @@ static int mini_cm_recv_pkt(struct nes_cm_core *cm_core, | |||
2300 | break; | 2528 | break; |
2301 | } | 2529 | } |
2302 | listener = find_listener(cm_core, nfo.loc_addr, | 2530 | listener = find_listener(cm_core, nfo.loc_addr, |
2303 | nfo.loc_port, | 2531 | nfo.loc_port, |
2304 | NES_CM_LISTENER_ACTIVE_STATE); | 2532 | NES_CM_LISTENER_ACTIVE_STATE); |
2305 | if (!listener) { | 2533 | if (!listener) { |
2306 | nfo.cm_id = NULL; | 2534 | nfo.cm_id = NULL; |
2307 | nfo.conn_type = 0; | 2535 | nfo.conn_type = 0; |
@@ -2312,10 +2540,10 @@ static int mini_cm_recv_pkt(struct nes_cm_core *cm_core, | |||
2312 | nfo.cm_id = listener->cm_id; | 2540 | nfo.cm_id = listener->cm_id; |
2313 | nfo.conn_type = listener->conn_type; | 2541 | nfo.conn_type = listener->conn_type; |
2314 | cm_node = make_cm_node(cm_core, nesvnic, &nfo, | 2542 | cm_node = make_cm_node(cm_core, nesvnic, &nfo, |
2315 | listener); | 2543 | listener); |
2316 | if (!cm_node) { | 2544 | if (!cm_node) { |
2317 | nes_debug(NES_DBG_CM, "Unable to allocate " | 2545 | nes_debug(NES_DBG_CM, "Unable to allocate " |
2318 | "node\n"); | 2546 | "node\n"); |
2319 | cm_packets_dropped++; | 2547 | cm_packets_dropped++; |
2320 | atomic_dec(&listener->ref_count); | 2548 | atomic_dec(&listener->ref_count); |
2321 | dev_kfree_skb_any(skb); | 2549 | dev_kfree_skb_any(skb); |
@@ -2363,7 +2591,7 @@ static struct nes_cm_core *nes_cm_alloc_core(void) | |||
2363 | init_timer(&cm_core->tcp_timer); | 2591 | init_timer(&cm_core->tcp_timer); |
2364 | cm_core->tcp_timer.function = nes_cm_timer_tick; | 2592 | cm_core->tcp_timer.function = nes_cm_timer_tick; |
2365 | 2593 | ||
2366 | cm_core->mtu = NES_CM_DEFAULT_MTU; | 2594 | cm_core->mtu = NES_CM_DEFAULT_MTU; |
2367 | cm_core->state = NES_CM_STATE_INITED; | 2595 | cm_core->state = NES_CM_STATE_INITED; |
2368 | cm_core->free_tx_pkt_max = NES_CM_DEFAULT_FREE_PKTS; | 2596 | cm_core->free_tx_pkt_max = NES_CM_DEFAULT_FREE_PKTS; |
2369 | 2597 | ||
@@ -2401,9 +2629,8 @@ static int mini_cm_dealloc_core(struct nes_cm_core *cm_core) | |||
2401 | 2629 | ||
2402 | barrier(); | 2630 | barrier(); |
2403 | 2631 | ||
2404 | if (timer_pending(&cm_core->tcp_timer)) { | 2632 | if (timer_pending(&cm_core->tcp_timer)) |
2405 | del_timer(&cm_core->tcp_timer); | 2633 | del_timer(&cm_core->tcp_timer); |
2406 | } | ||
2407 | 2634 | ||
2408 | destroy_workqueue(cm_core->event_wq); | 2635 | destroy_workqueue(cm_core->event_wq); |
2409 | destroy_workqueue(cm_core->disconn_wq); | 2636 | destroy_workqueue(cm_core->disconn_wq); |
@@ -2458,8 +2685,8 @@ static int nes_cm_init_tsa_conn(struct nes_qp *nesqp, struct nes_cm_node *cm_nod | |||
2458 | return -EINVAL; | 2685 | return -EINVAL; |
2459 | 2686 | ||
2460 | nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_IPV4 | | 2687 | nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_IPV4 | |
2461 | NES_QPCONTEXT_MISC_NO_NAGLE | NES_QPCONTEXT_MISC_DO_NOT_FRAG | | 2688 | NES_QPCONTEXT_MISC_NO_NAGLE | NES_QPCONTEXT_MISC_DO_NOT_FRAG | |
2462 | NES_QPCONTEXT_MISC_DROS); | 2689 | NES_QPCONTEXT_MISC_DROS); |
2463 | 2690 | ||
2464 | if (cm_node->tcp_cntxt.snd_wscale || cm_node->tcp_cntxt.rcv_wscale) | 2691 | if (cm_node->tcp_cntxt.snd_wscale || cm_node->tcp_cntxt.rcv_wscale) |
2465 | nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_WSCALE); | 2692 | nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_WSCALE); |
@@ -2469,15 +2696,15 @@ static int nes_cm_init_tsa_conn(struct nes_qp *nesqp, struct nes_cm_node *cm_nod | |||
2469 | nesqp->nesqp_context->mss |= cpu_to_le32(((u32)cm_node->tcp_cntxt.mss) << 16); | 2696 | nesqp->nesqp_context->mss |= cpu_to_le32(((u32)cm_node->tcp_cntxt.mss) << 16); |
2470 | 2697 | ||
2471 | nesqp->nesqp_context->tcp_state_flow_label |= cpu_to_le32( | 2698 | nesqp->nesqp_context->tcp_state_flow_label |= cpu_to_le32( |
2472 | (u32)NES_QPCONTEXT_TCPSTATE_EST << NES_QPCONTEXT_TCPFLOW_TCP_STATE_SHIFT); | 2699 | (u32)NES_QPCONTEXT_TCPSTATE_EST << NES_QPCONTEXT_TCPFLOW_TCP_STATE_SHIFT); |
2473 | 2700 | ||
2474 | nesqp->nesqp_context->pd_index_wscale |= cpu_to_le32( | 2701 | nesqp->nesqp_context->pd_index_wscale |= cpu_to_le32( |
2475 | (cm_node->tcp_cntxt.snd_wscale << NES_QPCONTEXT_PDWSCALE_SND_WSCALE_SHIFT) & | 2702 | (cm_node->tcp_cntxt.snd_wscale << NES_QPCONTEXT_PDWSCALE_SND_WSCALE_SHIFT) & |
2476 | NES_QPCONTEXT_PDWSCALE_SND_WSCALE_MASK); | 2703 | NES_QPCONTEXT_PDWSCALE_SND_WSCALE_MASK); |
2477 | 2704 | ||
2478 | nesqp->nesqp_context->pd_index_wscale |= cpu_to_le32( | 2705 | nesqp->nesqp_context->pd_index_wscale |= cpu_to_le32( |
2479 | (cm_node->tcp_cntxt.rcv_wscale << NES_QPCONTEXT_PDWSCALE_RCV_WSCALE_SHIFT) & | 2706 | (cm_node->tcp_cntxt.rcv_wscale << NES_QPCONTEXT_PDWSCALE_RCV_WSCALE_SHIFT) & |
2480 | NES_QPCONTEXT_PDWSCALE_RCV_WSCALE_MASK); | 2707 | NES_QPCONTEXT_PDWSCALE_RCV_WSCALE_MASK); |
2481 | 2708 | ||
2482 | nesqp->nesqp_context->keepalive = cpu_to_le32(0x80); | 2709 | nesqp->nesqp_context->keepalive = cpu_to_le32(0x80); |
2483 | nesqp->nesqp_context->ts_recent = 0; | 2710 | nesqp->nesqp_context->ts_recent = 0; |
@@ -2486,24 +2713,24 @@ static int nes_cm_init_tsa_conn(struct nes_qp *nesqp, struct nes_cm_node *cm_nod | |||
2486 | nesqp->nesqp_context->snd_wnd = cpu_to_le32(cm_node->tcp_cntxt.snd_wnd); | 2713 | nesqp->nesqp_context->snd_wnd = cpu_to_le32(cm_node->tcp_cntxt.snd_wnd); |
2487 | nesqp->nesqp_context->rcv_nxt = cpu_to_le32(cm_node->tcp_cntxt.rcv_nxt); | 2714 | nesqp->nesqp_context->rcv_nxt = cpu_to_le32(cm_node->tcp_cntxt.rcv_nxt); |
2488 | nesqp->nesqp_context->rcv_wnd = cpu_to_le32(cm_node->tcp_cntxt.rcv_wnd << | 2715 | nesqp->nesqp_context->rcv_wnd = cpu_to_le32(cm_node->tcp_cntxt.rcv_wnd << |
2489 | cm_node->tcp_cntxt.rcv_wscale); | 2716 | cm_node->tcp_cntxt.rcv_wscale); |
2490 | nesqp->nesqp_context->snd_max = cpu_to_le32(cm_node->tcp_cntxt.loc_seq_num); | 2717 | nesqp->nesqp_context->snd_max = cpu_to_le32(cm_node->tcp_cntxt.loc_seq_num); |
2491 | nesqp->nesqp_context->snd_una = cpu_to_le32(cm_node->tcp_cntxt.loc_seq_num); | 2718 | nesqp->nesqp_context->snd_una = cpu_to_le32(cm_node->tcp_cntxt.loc_seq_num); |
2492 | nesqp->nesqp_context->srtt = 0; | 2719 | nesqp->nesqp_context->srtt = 0; |
2493 | nesqp->nesqp_context->rttvar = cpu_to_le32(0x6); | 2720 | nesqp->nesqp_context->rttvar = cpu_to_le32(0x6); |
2494 | nesqp->nesqp_context->ssthresh = cpu_to_le32(0x3FFFC000); | 2721 | nesqp->nesqp_context->ssthresh = cpu_to_le32(0x3FFFC000); |
2495 | nesqp->nesqp_context->cwnd = cpu_to_le32(2*cm_node->tcp_cntxt.mss); | 2722 | nesqp->nesqp_context->cwnd = cpu_to_le32(2 * cm_node->tcp_cntxt.mss); |
2496 | nesqp->nesqp_context->snd_wl1 = cpu_to_le32(cm_node->tcp_cntxt.rcv_nxt); | 2723 | nesqp->nesqp_context->snd_wl1 = cpu_to_le32(cm_node->tcp_cntxt.rcv_nxt); |
2497 | nesqp->nesqp_context->snd_wl2 = cpu_to_le32(cm_node->tcp_cntxt.loc_seq_num); | 2724 | nesqp->nesqp_context->snd_wl2 = cpu_to_le32(cm_node->tcp_cntxt.loc_seq_num); |
2498 | nesqp->nesqp_context->max_snd_wnd = cpu_to_le32(cm_node->tcp_cntxt.max_snd_wnd); | 2725 | nesqp->nesqp_context->max_snd_wnd = cpu_to_le32(cm_node->tcp_cntxt.max_snd_wnd); |
2499 | 2726 | ||
2500 | nes_debug(NES_DBG_CM, "QP%u: rcv_nxt = 0x%08X, snd_nxt = 0x%08X," | 2727 | nes_debug(NES_DBG_CM, "QP%u: rcv_nxt = 0x%08X, snd_nxt = 0x%08X," |
2501 | " Setting MSS to %u, PDWscale = 0x%08X, rcv_wnd = %u, context misc = 0x%08X.\n", | 2728 | " Setting MSS to %u, PDWscale = 0x%08X, rcv_wnd = %u, context misc = 0x%08X.\n", |
2502 | nesqp->hwqp.qp_id, le32_to_cpu(nesqp->nesqp_context->rcv_nxt), | 2729 | nesqp->hwqp.qp_id, le32_to_cpu(nesqp->nesqp_context->rcv_nxt), |
2503 | le32_to_cpu(nesqp->nesqp_context->snd_nxt), | 2730 | le32_to_cpu(nesqp->nesqp_context->snd_nxt), |
2504 | cm_node->tcp_cntxt.mss, le32_to_cpu(nesqp->nesqp_context->pd_index_wscale), | 2731 | cm_node->tcp_cntxt.mss, le32_to_cpu(nesqp->nesqp_context->pd_index_wscale), |
2505 | le32_to_cpu(nesqp->nesqp_context->rcv_wnd), | 2732 | le32_to_cpu(nesqp->nesqp_context->rcv_wnd), |
2506 | le32_to_cpu(nesqp->nesqp_context->misc)); | 2733 | le32_to_cpu(nesqp->nesqp_context->misc)); |
2507 | nes_debug(NES_DBG_CM, " snd_wnd = 0x%08X.\n", le32_to_cpu(nesqp->nesqp_context->snd_wnd)); | 2734 | nes_debug(NES_DBG_CM, " snd_wnd = 0x%08X.\n", le32_to_cpu(nesqp->nesqp_context->snd_wnd)); |
2508 | nes_debug(NES_DBG_CM, " snd_cwnd = 0x%08X.\n", le32_to_cpu(nesqp->nesqp_context->cwnd)); | 2735 | nes_debug(NES_DBG_CM, " snd_cwnd = 0x%08X.\n", le32_to_cpu(nesqp->nesqp_context->cwnd)); |
2509 | nes_debug(NES_DBG_CM, " max_swnd = 0x%08X.\n", le32_to_cpu(nesqp->nesqp_context->max_snd_wnd)); | 2736 | nes_debug(NES_DBG_CM, " max_swnd = 0x%08X.\n", le32_to_cpu(nesqp->nesqp_context->max_snd_wnd)); |
@@ -2524,7 +2751,7 @@ int nes_cm_disconn(struct nes_qp *nesqp) | |||
2524 | 2751 | ||
2525 | work = kzalloc(sizeof *work, GFP_ATOMIC); | 2752 | work = kzalloc(sizeof *work, GFP_ATOMIC); |
2526 | if (!work) | 2753 | if (!work) |
2527 | return -ENOMEM; /* Timer will clean up */ | 2754 | return -ENOMEM; /* Timer will clean up */ |
2528 | 2755 | ||
2529 | nes_add_ref(&nesqp->ibqp); | 2756 | nes_add_ref(&nesqp->ibqp); |
2530 | work->nesqp = nesqp; | 2757 | work->nesqp = nesqp; |
@@ -2544,7 +2771,7 @@ static void nes_disconnect_worker(struct work_struct *work) | |||
2544 | 2771 | ||
2545 | kfree(dwork); | 2772 | kfree(dwork); |
2546 | nes_debug(NES_DBG_CM, "processing AEQE id 0x%04X for QP%u.\n", | 2773 | nes_debug(NES_DBG_CM, "processing AEQE id 0x%04X for QP%u.\n", |
2547 | nesqp->last_aeq, nesqp->hwqp.qp_id); | 2774 | nesqp->last_aeq, nesqp->hwqp.qp_id); |
2548 | nes_cm_disconn_true(nesqp); | 2775 | nes_cm_disconn_true(nesqp); |
2549 | nes_rem_ref(&nesqp->ibqp); | 2776 | nes_rem_ref(&nesqp->ibqp); |
2550 | } | 2777 | } |
@@ -2580,7 +2807,7 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp) | |||
2580 | /* make sure we havent already closed this connection */ | 2807 | /* make sure we havent already closed this connection */ |
2581 | if (!cm_id) { | 2808 | if (!cm_id) { |
2582 | nes_debug(NES_DBG_CM, "QP%u disconnect_worker cmid is NULL\n", | 2809 | nes_debug(NES_DBG_CM, "QP%u disconnect_worker cmid is NULL\n", |
2583 | nesqp->hwqp.qp_id); | 2810 | nesqp->hwqp.qp_id); |
2584 | spin_unlock_irqrestore(&nesqp->lock, flags); | 2811 | spin_unlock_irqrestore(&nesqp->lock, flags); |
2585 | return -1; | 2812 | return -1; |
2586 | } | 2813 | } |
@@ -2589,7 +2816,7 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp) | |||
2589 | nes_debug(NES_DBG_CM, "Disconnecting QP%u\n", nesqp->hwqp.qp_id); | 2816 | nes_debug(NES_DBG_CM, "Disconnecting QP%u\n", nesqp->hwqp.qp_id); |
2590 | 2817 | ||
2591 | original_hw_tcp_state = nesqp->hw_tcp_state; | 2818 | original_hw_tcp_state = nesqp->hw_tcp_state; |
2592 | original_ibqp_state = nesqp->ibqp_state; | 2819 | original_ibqp_state = nesqp->ibqp_state; |
2593 | last_ae = nesqp->last_aeq; | 2820 | last_ae = nesqp->last_aeq; |
2594 | 2821 | ||
2595 | if (nesqp->term_flags) { | 2822 | if (nesqp->term_flags) { |
@@ -2647,16 +2874,16 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp) | |||
2647 | cm_event.private_data_len = 0; | 2874 | cm_event.private_data_len = 0; |
2648 | 2875 | ||
2649 | nes_debug(NES_DBG_CM, "Generating a CM Disconnect Event" | 2876 | nes_debug(NES_DBG_CM, "Generating a CM Disconnect Event" |
2650 | " for QP%u, SQ Head = %u, SQ Tail = %u. " | 2877 | " for QP%u, SQ Head = %u, SQ Tail = %u. " |
2651 | "cm_id = %p, refcount = %u.\n", | 2878 | "cm_id = %p, refcount = %u.\n", |
2652 | nesqp->hwqp.qp_id, nesqp->hwqp.sq_head, | 2879 | nesqp->hwqp.qp_id, nesqp->hwqp.sq_head, |
2653 | nesqp->hwqp.sq_tail, cm_id, | 2880 | nesqp->hwqp.sq_tail, cm_id, |
2654 | atomic_read(&nesqp->refcount)); | 2881 | atomic_read(&nesqp->refcount)); |
2655 | 2882 | ||
2656 | ret = cm_id->event_handler(cm_id, &cm_event); | 2883 | ret = cm_id->event_handler(cm_id, &cm_event); |
2657 | if (ret) | 2884 | if (ret) |
2658 | nes_debug(NES_DBG_CM, "OFA CM event_handler " | 2885 | nes_debug(NES_DBG_CM, "OFA CM event_handler " |
2659 | "returned, ret=%d\n", ret); | 2886 | "returned, ret=%d\n", ret); |
2660 | } | 2887 | } |
2661 | 2888 | ||
2662 | if (issue_close) { | 2889 | if (issue_close) { |
@@ -2674,9 +2901,8 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp) | |||
2674 | cm_event.private_data_len = 0; | 2901 | cm_event.private_data_len = 0; |
2675 | 2902 | ||
2676 | ret = cm_id->event_handler(cm_id, &cm_event); | 2903 | ret = cm_id->event_handler(cm_id, &cm_event); |
2677 | if (ret) { | 2904 | if (ret) |
2678 | nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret); | 2905 | nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret); |
2679 | } | ||
2680 | 2906 | ||
2681 | cm_id->rem_ref(cm_id); | 2907 | cm_id->rem_ref(cm_id); |
2682 | } | 2908 | } |
@@ -2716,8 +2942,8 @@ static int nes_disconnect(struct nes_qp *nesqp, int abrupt) | |||
2716 | if (nesqp->lsmm_mr) | 2942 | if (nesqp->lsmm_mr) |
2717 | nesibdev->ibdev.dereg_mr(nesqp->lsmm_mr); | 2943 | nesibdev->ibdev.dereg_mr(nesqp->lsmm_mr); |
2718 | pci_free_consistent(nesdev->pcidev, | 2944 | pci_free_consistent(nesdev->pcidev, |
2719 | nesqp->private_data_len+sizeof(struct ietf_mpa_frame), | 2945 | nesqp->private_data_len + nesqp->ietf_frame_size, |
2720 | nesqp->ietf_frame, nesqp->ietf_frame_pbase); | 2946 | nesqp->ietf_frame, nesqp->ietf_frame_pbase); |
2721 | } | 2947 | } |
2722 | } | 2948 | } |
2723 | 2949 | ||
@@ -2756,6 +2982,12 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
2756 | struct ib_phys_buf ibphysbuf; | 2982 | struct ib_phys_buf ibphysbuf; |
2757 | struct nes_pd *nespd; | 2983 | struct nes_pd *nespd; |
2758 | u64 tagged_offset; | 2984 | u64 tagged_offset; |
2985 | u8 mpa_frame_offset = 0; | ||
2986 | struct ietf_mpa_v2 *mpa_v2_frame; | ||
2987 | u8 start_addr = 0; | ||
2988 | u8 *start_ptr = &start_addr; | ||
2989 | u8 **start_buff = &start_ptr; | ||
2990 | u16 buff_len = 0; | ||
2759 | 2991 | ||
2760 | ibqp = nes_get_qp(cm_id->device, conn_param->qpn); | 2992 | ibqp = nes_get_qp(cm_id->device, conn_param->qpn); |
2761 | if (!ibqp) | 2993 | if (!ibqp) |
@@ -2796,53 +3028,49 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
2796 | nes_debug(NES_DBG_CM, "netdev refcnt = %u.\n", | 3028 | nes_debug(NES_DBG_CM, "netdev refcnt = %u.\n", |
2797 | netdev_refcnt_read(nesvnic->netdev)); | 3029 | netdev_refcnt_read(nesvnic->netdev)); |
2798 | 3030 | ||
3031 | nesqp->ietf_frame_size = sizeof(struct ietf_mpa_v2); | ||
2799 | /* allocate the ietf frame and space for private data */ | 3032 | /* allocate the ietf frame and space for private data */ |
2800 | nesqp->ietf_frame = pci_alloc_consistent(nesdev->pcidev, | 3033 | nesqp->ietf_frame = pci_alloc_consistent(nesdev->pcidev, |
2801 | sizeof(struct ietf_mpa_frame) + conn_param->private_data_len, | 3034 | nesqp->ietf_frame_size + conn_param->private_data_len, |
2802 | &nesqp->ietf_frame_pbase); | 3035 | &nesqp->ietf_frame_pbase); |
2803 | 3036 | ||
2804 | if (!nesqp->ietf_frame) { | 3037 | if (!nesqp->ietf_frame) { |
2805 | nes_debug(NES_DBG_CM, "Unable to allocate memory for private " | 3038 | nes_debug(NES_DBG_CM, "Unable to allocate memory for private data\n"); |
2806 | "data\n"); | ||
2807 | return -ENOMEM; | 3039 | return -ENOMEM; |
2808 | } | 3040 | } |
3041 | mpa_v2_frame = (struct ietf_mpa_v2 *)nesqp->ietf_frame; | ||
2809 | 3042 | ||
3043 | if (cm_node->mpa_frame_rev == IETF_MPA_V1) | ||
3044 | mpa_frame_offset = 4; | ||
2810 | 3045 | ||
2811 | /* setup the MPA frame */ | 3046 | memcpy(mpa_v2_frame->priv_data, conn_param->private_data, |
2812 | nesqp->private_data_len = conn_param->private_data_len; | 3047 | conn_param->private_data_len); |
2813 | memcpy(nesqp->ietf_frame->key, IEFT_MPA_KEY_REP, IETF_MPA_KEY_SIZE); | ||
2814 | |||
2815 | memcpy(nesqp->ietf_frame->priv_data, conn_param->private_data, | ||
2816 | conn_param->private_data_len); | ||
2817 | 3048 | ||
2818 | nesqp->ietf_frame->priv_data_len = | 3049 | cm_build_mpa_frame(cm_node, start_buff, &buff_len, nesqp->ietf_frame, MPA_KEY_REPLY); |
2819 | cpu_to_be16(conn_param->private_data_len); | 3050 | nesqp->private_data_len = conn_param->private_data_len; |
2820 | nesqp->ietf_frame->rev = mpa_version; | ||
2821 | nesqp->ietf_frame->flags = IETF_MPA_FLAGS_CRC; | ||
2822 | 3051 | ||
2823 | /* setup our first outgoing iWarp send WQE (the IETF frame response) */ | 3052 | /* setup our first outgoing iWarp send WQE (the IETF frame response) */ |
2824 | wqe = &nesqp->hwqp.sq_vbase[0]; | 3053 | wqe = &nesqp->hwqp.sq_vbase[0]; |
2825 | 3054 | ||
2826 | if (cm_id->remote_addr.sin_addr.s_addr != | 3055 | if (cm_id->remote_addr.sin_addr.s_addr != |
2827 | cm_id->local_addr.sin_addr.s_addr) { | 3056 | cm_id->local_addr.sin_addr.s_addr) { |
2828 | u64temp = (unsigned long)nesqp; | 3057 | u64temp = (unsigned long)nesqp; |
2829 | nesibdev = nesvnic->nesibdev; | 3058 | nesibdev = nesvnic->nesibdev; |
2830 | nespd = nesqp->nespd; | 3059 | nespd = nesqp->nespd; |
2831 | ibphysbuf.addr = nesqp->ietf_frame_pbase; | 3060 | ibphysbuf.addr = nesqp->ietf_frame_pbase + mpa_frame_offset; |
2832 | ibphysbuf.size = conn_param->private_data_len + | 3061 | ibphysbuf.size = buff_len; |
2833 | sizeof(struct ietf_mpa_frame); | 3062 | tagged_offset = (u64)(unsigned long)*start_buff; |
2834 | tagged_offset = (u64)(unsigned long)nesqp->ietf_frame; | ||
2835 | ibmr = nesibdev->ibdev.reg_phys_mr((struct ib_pd *)nespd, | 3063 | ibmr = nesibdev->ibdev.reg_phys_mr((struct ib_pd *)nespd, |
2836 | &ibphysbuf, 1, | 3064 | &ibphysbuf, 1, |
2837 | IB_ACCESS_LOCAL_WRITE, | 3065 | IB_ACCESS_LOCAL_WRITE, |
2838 | &tagged_offset); | 3066 | &tagged_offset); |
2839 | if (!ibmr) { | 3067 | if (!ibmr) { |
2840 | nes_debug(NES_DBG_CM, "Unable to register memory region" | 3068 | nes_debug(NES_DBG_CM, "Unable to register memory region" |
2841 | "for lSMM for cm_node = %p \n", | 3069 | "for lSMM for cm_node = %p \n", |
2842 | cm_node); | 3070 | cm_node); |
2843 | pci_free_consistent(nesdev->pcidev, | 3071 | pci_free_consistent(nesdev->pcidev, |
2844 | nesqp->private_data_len+sizeof(struct ietf_mpa_frame), | 3072 | nesqp->private_data_len + nesqp->ietf_frame_size, |
2845 | nesqp->ietf_frame, nesqp->ietf_frame_pbase); | 3073 | nesqp->ietf_frame, nesqp->ietf_frame_pbase); |
2846 | return -ENOMEM; | 3074 | return -ENOMEM; |
2847 | } | 3075 | } |
2848 | 3076 | ||
@@ -2850,22 +3078,20 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
2850 | ibmr->device = nespd->ibpd.device; | 3078 | ibmr->device = nespd->ibpd.device; |
2851 | nesqp->lsmm_mr = ibmr; | 3079 | nesqp->lsmm_mr = ibmr; |
2852 | 3080 | ||
2853 | u64temp |= NES_SW_CONTEXT_ALIGN>>1; | 3081 | u64temp |= NES_SW_CONTEXT_ALIGN >> 1; |
2854 | set_wqe_64bit_value(wqe->wqe_words, | 3082 | set_wqe_64bit_value(wqe->wqe_words, |
2855 | NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX, | 3083 | NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX, |
2856 | u64temp); | 3084 | u64temp); |
2857 | wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] = | 3085 | wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] = |
2858 | cpu_to_le32(NES_IWARP_SQ_WQE_STREAMING | | 3086 | cpu_to_le32(NES_IWARP_SQ_WQE_STREAMING | |
2859 | NES_IWARP_SQ_WQE_WRPDU); | 3087 | NES_IWARP_SQ_WQE_WRPDU); |
2860 | wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] = | 3088 | wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] = |
2861 | cpu_to_le32(conn_param->private_data_len + | 3089 | cpu_to_le32(buff_len); |
2862 | sizeof(struct ietf_mpa_frame)); | ||
2863 | set_wqe_64bit_value(wqe->wqe_words, | 3090 | set_wqe_64bit_value(wqe->wqe_words, |
2864 | NES_IWARP_SQ_WQE_FRAG0_LOW_IDX, | 3091 | NES_IWARP_SQ_WQE_FRAG0_LOW_IDX, |
2865 | (u64)(unsigned long)nesqp->ietf_frame); | 3092 | (u64)(unsigned long)(*start_buff)); |
2866 | wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] = | 3093 | wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] = |
2867 | cpu_to_le32(conn_param->private_data_len + | 3094 | cpu_to_le32(buff_len); |
2868 | sizeof(struct ietf_mpa_frame)); | ||
2869 | wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = ibmr->lkey; | 3095 | wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = ibmr->lkey; |
2870 | if (nesqp->sq_kmapped) { | 3096 | if (nesqp->sq_kmapped) { |
2871 | nesqp->sq_kmapped = 0; | 3097 | nesqp->sq_kmapped = 0; |
@@ -2874,7 +3100,7 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
2874 | 3100 | ||
2875 | nesqp->nesqp_context->ird_ord_sizes |= | 3101 | nesqp->nesqp_context->ird_ord_sizes |= |
2876 | cpu_to_le32(NES_QPCONTEXT_ORDIRD_LSMM_PRESENT | | 3102 | cpu_to_le32(NES_QPCONTEXT_ORDIRD_LSMM_PRESENT | |
2877 | NES_QPCONTEXT_ORDIRD_WRPDU); | 3103 | NES_QPCONTEXT_ORDIRD_WRPDU); |
2878 | } else { | 3104 | } else { |
2879 | nesqp->nesqp_context->ird_ord_sizes |= | 3105 | nesqp->nesqp_context->ird_ord_sizes |= |
2880 | cpu_to_le32(NES_QPCONTEXT_ORDIRD_WRPDU); | 3106 | cpu_to_le32(NES_QPCONTEXT_ORDIRD_WRPDU); |
@@ -2888,11 +3114,11 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
2888 | 3114 | ||
2889 | /* nesqp->cm_node = (void *)cm_id->provider_data; */ | 3115 | /* nesqp->cm_node = (void *)cm_id->provider_data; */ |
2890 | cm_id->provider_data = nesqp; | 3116 | cm_id->provider_data = nesqp; |
2891 | nesqp->active_conn = 0; | 3117 | nesqp->active_conn = 0; |
2892 | 3118 | ||
2893 | if (cm_node->state == NES_CM_STATE_TSA) | 3119 | if (cm_node->state == NES_CM_STATE_TSA) |
2894 | nes_debug(NES_DBG_CM, "Already state = TSA for cm_node=%p\n", | 3120 | nes_debug(NES_DBG_CM, "Already state = TSA for cm_node=%p\n", |
2895 | cm_node); | 3121 | cm_node); |
2896 | 3122 | ||
2897 | nes_cm_init_tsa_conn(nesqp, cm_node); | 3123 | nes_cm_init_tsa_conn(nesqp, cm_node); |
2898 | 3124 | ||
@@ -2909,13 +3135,13 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
2909 | cpu_to_le32(ntohl(cm_id->remote_addr.sin_addr.s_addr)); | 3135 | cpu_to_le32(ntohl(cm_id->remote_addr.sin_addr.s_addr)); |
2910 | 3136 | ||
2911 | nesqp->nesqp_context->misc2 |= cpu_to_le32( | 3137 | nesqp->nesqp_context->misc2 |= cpu_to_le32( |
2912 | (u32)PCI_FUNC(nesdev->pcidev->devfn) << | 3138 | (u32)PCI_FUNC(nesdev->pcidev->devfn) << |
2913 | NES_QPCONTEXT_MISC2_SRC_IP_SHIFT); | 3139 | NES_QPCONTEXT_MISC2_SRC_IP_SHIFT); |
2914 | 3140 | ||
2915 | nesqp->nesqp_context->arp_index_vlan |= | 3141 | nesqp->nesqp_context->arp_index_vlan |= |
2916 | cpu_to_le32(nes_arp_table(nesdev, | 3142 | cpu_to_le32(nes_arp_table(nesdev, |
2917 | le32_to_cpu(nesqp->nesqp_context->ip0), NULL, | 3143 | le32_to_cpu(nesqp->nesqp_context->ip0), NULL, |
2918 | NES_ARP_RESOLVE) << 16); | 3144 | NES_ARP_RESOLVE) << 16); |
2919 | 3145 | ||
2920 | nesqp->nesqp_context->ts_val_delta = cpu_to_le32( | 3146 | nesqp->nesqp_context->ts_val_delta = cpu_to_le32( |
2921 | jiffies - nes_read_indexed(nesdev, NES_IDX_TCP_NOW)); | 3147 | jiffies - nes_read_indexed(nesdev, NES_IDX_TCP_NOW)); |
@@ -2941,7 +3167,7 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
2941 | crc_value = get_crc_value(&nes_quad); | 3167 | crc_value = get_crc_value(&nes_quad); |
2942 | nesqp->hte_index = cpu_to_be32(crc_value ^ 0xffffffff); | 3168 | nesqp->hte_index = cpu_to_be32(crc_value ^ 0xffffffff); |
2943 | nes_debug(NES_DBG_CM, "HTE Index = 0x%08X, CRC = 0x%08X\n", | 3169 | nes_debug(NES_DBG_CM, "HTE Index = 0x%08X, CRC = 0x%08X\n", |
2944 | nesqp->hte_index, nesqp->hte_index & adapter->hte_index_mask); | 3170 | nesqp->hte_index, nesqp->hte_index & adapter->hte_index_mask); |
2945 | 3171 | ||
2946 | nesqp->hte_index &= adapter->hte_index_mask; | 3172 | nesqp->hte_index &= adapter->hte_index_mask; |
2947 | nesqp->nesqp_context->hte_index = cpu_to_le32(nesqp->hte_index); | 3173 | nesqp->nesqp_context->hte_index = cpu_to_le32(nesqp->hte_index); |
@@ -2949,17 +3175,15 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
2949 | cm_node->cm_core->api->accelerated(cm_node->cm_core, cm_node); | 3175 | cm_node->cm_core->api->accelerated(cm_node->cm_core, cm_node); |
2950 | 3176 | ||
2951 | nes_debug(NES_DBG_CM, "QP%u, Destination IP = 0x%08X:0x%04X, local = " | 3177 | nes_debug(NES_DBG_CM, "QP%u, Destination IP = 0x%08X:0x%04X, local = " |
2952 | "0x%08X:0x%04X, rcv_nxt=0x%08X, snd_nxt=0x%08X, mpa + " | 3178 | "0x%08X:0x%04X, rcv_nxt=0x%08X, snd_nxt=0x%08X, mpa + " |
2953 | "private data length=%zu.\n", nesqp->hwqp.qp_id, | 3179 | "private data length=%u.\n", nesqp->hwqp.qp_id, |
2954 | ntohl(cm_id->remote_addr.sin_addr.s_addr), | 3180 | ntohl(cm_id->remote_addr.sin_addr.s_addr), |
2955 | ntohs(cm_id->remote_addr.sin_port), | 3181 | ntohs(cm_id->remote_addr.sin_port), |
2956 | ntohl(cm_id->local_addr.sin_addr.s_addr), | 3182 | ntohl(cm_id->local_addr.sin_addr.s_addr), |
2957 | ntohs(cm_id->local_addr.sin_port), | 3183 | ntohs(cm_id->local_addr.sin_port), |
2958 | le32_to_cpu(nesqp->nesqp_context->rcv_nxt), | 3184 | le32_to_cpu(nesqp->nesqp_context->rcv_nxt), |
2959 | le32_to_cpu(nesqp->nesqp_context->snd_nxt), | 3185 | le32_to_cpu(nesqp->nesqp_context->snd_nxt), |
2960 | conn_param->private_data_len + | 3186 | buff_len); |
2961 | sizeof(struct ietf_mpa_frame)); | ||
2962 | |||
2963 | 3187 | ||
2964 | /* notify OF layer that accept event was successful */ | 3188 | /* notify OF layer that accept event was successful */ |
2965 | cm_id->add_ref(cm_id); | 3189 | cm_id->add_ref(cm_id); |
@@ -2980,12 +3204,12 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
2980 | nesqp->private_data_len; | 3204 | nesqp->private_data_len; |
2981 | /* copy entire MPA frame to our cm_node's frame */ | 3205 | /* copy entire MPA frame to our cm_node's frame */ |
2982 | memcpy(cm_node->loopbackpartner->mpa_frame_buf, | 3206 | memcpy(cm_node->loopbackpartner->mpa_frame_buf, |
2983 | nesqp->ietf_frame->priv_data, nesqp->private_data_len); | 3207 | conn_param->private_data, conn_param->private_data_len); |
2984 | create_event(cm_node->loopbackpartner, NES_CM_EVENT_CONNECTED); | 3208 | create_event(cm_node->loopbackpartner, NES_CM_EVENT_CONNECTED); |
2985 | } | 3209 | } |
2986 | if (ret) | 3210 | if (ret) |
2987 | printk(KERN_ERR "%s[%u] OFA CM event_handler returned, " | 3211 | printk(KERN_ERR "%s[%u] OFA CM event_handler returned, " |
2988 | "ret=%d\n", __func__, __LINE__, ret); | 3212 | "ret=%d\n", __func__, __LINE__, ret); |
2989 | 3213 | ||
2990 | return 0; | 3214 | return 0; |
2991 | } | 3215 | } |
@@ -2998,34 +3222,28 @@ int nes_reject(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len) | |||
2998 | { | 3222 | { |
2999 | struct nes_cm_node *cm_node; | 3223 | struct nes_cm_node *cm_node; |
3000 | struct nes_cm_node *loopback; | 3224 | struct nes_cm_node *loopback; |
3001 | |||
3002 | struct nes_cm_core *cm_core; | 3225 | struct nes_cm_core *cm_core; |
3226 | u8 *start_buff; | ||
3003 | 3227 | ||
3004 | atomic_inc(&cm_rejects); | 3228 | atomic_inc(&cm_rejects); |
3005 | cm_node = (struct nes_cm_node *) cm_id->provider_data; | 3229 | cm_node = (struct nes_cm_node *)cm_id->provider_data; |
3006 | loopback = cm_node->loopbackpartner; | 3230 | loopback = cm_node->loopbackpartner; |
3007 | cm_core = cm_node->cm_core; | 3231 | cm_core = cm_node->cm_core; |
3008 | cm_node->cm_id = cm_id; | 3232 | cm_node->cm_id = cm_id; |
3009 | cm_node->mpa_frame_size = sizeof(struct ietf_mpa_frame) + pdata_len; | ||
3010 | 3233 | ||
3011 | if (cm_node->mpa_frame_size > MAX_CM_BUFFER) | 3234 | if (pdata_len + sizeof(struct ietf_mpa_v2) > MAX_CM_BUFFER) |
3012 | return -EINVAL; | 3235 | return -EINVAL; |
3013 | 3236 | ||
3014 | memcpy(&cm_node->mpa_frame.key[0], IEFT_MPA_KEY_REP, IETF_MPA_KEY_SIZE); | ||
3015 | if (loopback) { | 3237 | if (loopback) { |
3016 | memcpy(&loopback->mpa_frame.priv_data, pdata, pdata_len); | 3238 | memcpy(&loopback->mpa_frame.priv_data, pdata, pdata_len); |
3017 | loopback->mpa_frame.priv_data_len = pdata_len; | 3239 | loopback->mpa_frame.priv_data_len = pdata_len; |
3018 | loopback->mpa_frame_size = sizeof(struct ietf_mpa_frame) + | 3240 | loopback->mpa_frame_size = pdata_len; |
3019 | pdata_len; | ||
3020 | } else { | 3241 | } else { |
3021 | memcpy(&cm_node->mpa_frame.priv_data, pdata, pdata_len); | 3242 | start_buff = &cm_node->mpa_frame_buf[0] + sizeof(struct ietf_mpa_v2); |
3022 | cm_node->mpa_frame.priv_data_len = cpu_to_be16(pdata_len); | 3243 | cm_node->mpa_frame_size = pdata_len; |
3244 | memcpy(start_buff, pdata, pdata_len); | ||
3023 | } | 3245 | } |
3024 | 3246 | return cm_core->api->reject(cm_core, cm_node); | |
3025 | cm_node->mpa_frame.rev = mpa_version; | ||
3026 | cm_node->mpa_frame.flags = IETF_MPA_FLAGS_CRC | IETF_MPA_FLAGS_REJECT; | ||
3027 | |||
3028 | return cm_core->api->reject(cm_core, &cm_node->mpa_frame, cm_node); | ||
3029 | } | 3247 | } |
3030 | 3248 | ||
3031 | 3249 | ||
@@ -3052,7 +3270,7 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
3052 | nesvnic = to_nesvnic(nesqp->ibqp.device); | 3270 | nesvnic = to_nesvnic(nesqp->ibqp.device); |
3053 | if (!nesvnic) | 3271 | if (!nesvnic) |
3054 | return -EINVAL; | 3272 | return -EINVAL; |
3055 | nesdev = nesvnic->nesdev; | 3273 | nesdev = nesvnic->nesdev; |
3056 | if (!nesdev) | 3274 | if (!nesdev) |
3057 | return -EINVAL; | 3275 | return -EINVAL; |
3058 | 3276 | ||
@@ -3060,12 +3278,12 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
3060 | return -EINVAL; | 3278 | return -EINVAL; |
3061 | 3279 | ||
3062 | nes_debug(NES_DBG_CM, "QP%u, current IP = 0x%08X, Destination IP = " | 3280 | nes_debug(NES_DBG_CM, "QP%u, current IP = 0x%08X, Destination IP = " |
3063 | "0x%08X:0x%04X, local = 0x%08X:0x%04X.\n", nesqp->hwqp.qp_id, | 3281 | "0x%08X:0x%04X, local = 0x%08X:0x%04X.\n", nesqp->hwqp.qp_id, |
3064 | ntohl(nesvnic->local_ipaddr), | 3282 | ntohl(nesvnic->local_ipaddr), |
3065 | ntohl(cm_id->remote_addr.sin_addr.s_addr), | 3283 | ntohl(cm_id->remote_addr.sin_addr.s_addr), |
3066 | ntohs(cm_id->remote_addr.sin_port), | 3284 | ntohs(cm_id->remote_addr.sin_port), |
3067 | ntohl(cm_id->local_addr.sin_addr.s_addr), | 3285 | ntohl(cm_id->local_addr.sin_addr.s_addr), |
3068 | ntohs(cm_id->local_addr.sin_port)); | 3286 | ntohs(cm_id->local_addr.sin_port)); |
3069 | 3287 | ||
3070 | atomic_inc(&cm_connects); | 3288 | atomic_inc(&cm_connects); |
3071 | nesqp->active_conn = 1; | 3289 | nesqp->active_conn = 1; |
@@ -3079,12 +3297,12 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
3079 | nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32((u32)conn_param->ord); | 3297 | nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32((u32)conn_param->ord); |
3080 | nes_debug(NES_DBG_CM, "requested ord = 0x%08X.\n", (u32)conn_param->ord); | 3298 | nes_debug(NES_DBG_CM, "requested ord = 0x%08X.\n", (u32)conn_param->ord); |
3081 | nes_debug(NES_DBG_CM, "mpa private data len =%u\n", | 3299 | nes_debug(NES_DBG_CM, "mpa private data len =%u\n", |
3082 | conn_param->private_data_len); | 3300 | conn_param->private_data_len); |
3083 | 3301 | ||
3084 | if (cm_id->local_addr.sin_addr.s_addr != | 3302 | if (cm_id->local_addr.sin_addr.s_addr != |
3085 | cm_id->remote_addr.sin_addr.s_addr) { | 3303 | cm_id->remote_addr.sin_addr.s_addr) { |
3086 | nes_manage_apbvt(nesvnic, ntohs(cm_id->local_addr.sin_port), | 3304 | nes_manage_apbvt(nesvnic, ntohs(cm_id->local_addr.sin_port), |
3087 | PCI_FUNC(nesdev->pcidev->devfn), NES_MANAGE_APBVT_ADD); | 3305 | PCI_FUNC(nesdev->pcidev->devfn), NES_MANAGE_APBVT_ADD); |
3088 | apbvt_set = 1; | 3306 | apbvt_set = 1; |
3089 | } | 3307 | } |
3090 | 3308 | ||
@@ -3100,13 +3318,13 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
3100 | 3318 | ||
3101 | /* create a connect CM node connection */ | 3319 | /* create a connect CM node connection */ |
3102 | cm_node = g_cm_core->api->connect(g_cm_core, nesvnic, | 3320 | cm_node = g_cm_core->api->connect(g_cm_core, nesvnic, |
3103 | conn_param->private_data_len, (void *)conn_param->private_data, | 3321 | conn_param->private_data_len, (void *)conn_param->private_data, |
3104 | &cm_info); | 3322 | &cm_info); |
3105 | if (!cm_node) { | 3323 | if (!cm_node) { |
3106 | if (apbvt_set) | 3324 | if (apbvt_set) |
3107 | nes_manage_apbvt(nesvnic, ntohs(cm_id->local_addr.sin_port), | 3325 | nes_manage_apbvt(nesvnic, ntohs(cm_id->local_addr.sin_port), |
3108 | PCI_FUNC(nesdev->pcidev->devfn), | 3326 | PCI_FUNC(nesdev->pcidev->devfn), |
3109 | NES_MANAGE_APBVT_DEL); | 3327 | NES_MANAGE_APBVT_DEL); |
3110 | 3328 | ||
3111 | cm_id->rem_ref(cm_id); | 3329 | cm_id->rem_ref(cm_id); |
3112 | return -ENOMEM; | 3330 | return -ENOMEM; |
@@ -3156,7 +3374,7 @@ int nes_create_listen(struct iw_cm_id *cm_id, int backlog) | |||
3156 | cm_node = g_cm_core->api->listen(g_cm_core, nesvnic, &cm_info); | 3374 | cm_node = g_cm_core->api->listen(g_cm_core, nesvnic, &cm_info); |
3157 | if (!cm_node) { | 3375 | if (!cm_node) { |
3158 | printk(KERN_ERR "%s[%u] Error returned from listen API call\n", | 3376 | printk(KERN_ERR "%s[%u] Error returned from listen API call\n", |
3159 | __func__, __LINE__); | 3377 | __func__, __LINE__); |
3160 | return -ENOMEM; | 3378 | return -ENOMEM; |
3161 | } | 3379 | } |
3162 | 3380 | ||
@@ -3164,12 +3382,12 @@ int nes_create_listen(struct iw_cm_id *cm_id, int backlog) | |||
3164 | 3382 | ||
3165 | if (!cm_node->reused_node) { | 3383 | if (!cm_node->reused_node) { |
3166 | err = nes_manage_apbvt(nesvnic, | 3384 | err = nes_manage_apbvt(nesvnic, |
3167 | ntohs(cm_id->local_addr.sin_port), | 3385 | ntohs(cm_id->local_addr.sin_port), |
3168 | PCI_FUNC(nesvnic->nesdev->pcidev->devfn), | 3386 | PCI_FUNC(nesvnic->nesdev->pcidev->devfn), |
3169 | NES_MANAGE_APBVT_ADD); | 3387 | NES_MANAGE_APBVT_ADD); |
3170 | if (err) { | 3388 | if (err) { |
3171 | printk(KERN_ERR "nes_manage_apbvt call returned %d.\n", | 3389 | printk(KERN_ERR "nes_manage_apbvt call returned %d.\n", |
3172 | err); | 3390 | err); |
3173 | g_cm_core->api->stop_listener(g_cm_core, (void *)cm_node); | 3391 | g_cm_core->api->stop_listener(g_cm_core, (void *)cm_node); |
3174 | return err; | 3392 | return err; |
3175 | } | 3393 | } |
@@ -3206,13 +3424,13 @@ int nes_destroy_listen(struct iw_cm_id *cm_id) | |||
3206 | int nes_cm_recv(struct sk_buff *skb, struct net_device *netdevice) | 3424 | int nes_cm_recv(struct sk_buff *skb, struct net_device *netdevice) |
3207 | { | 3425 | { |
3208 | int rc = 0; | 3426 | int rc = 0; |
3427 | |||
3209 | cm_packets_received++; | 3428 | cm_packets_received++; |
3210 | if ((g_cm_core) && (g_cm_core->api)) { | 3429 | if ((g_cm_core) && (g_cm_core->api)) |
3211 | rc = g_cm_core->api->recv_pkt(g_cm_core, netdev_priv(netdevice), skb); | 3430 | rc = g_cm_core->api->recv_pkt(g_cm_core, netdev_priv(netdevice), skb); |
3212 | } else { | 3431 | else |
3213 | nes_debug(NES_DBG_CM, "Unable to process packet for CM," | 3432 | nes_debug(NES_DBG_CM, "Unable to process packet for CM," |
3214 | " cm is not setup properly.\n"); | 3433 | " cm is not setup properly.\n"); |
3215 | } | ||
3216 | 3434 | ||
3217 | return rc; | 3435 | return rc; |
3218 | } | 3436 | } |
@@ -3227,11 +3445,10 @@ int nes_cm_start(void) | |||
3227 | nes_debug(NES_DBG_CM, "\n"); | 3445 | nes_debug(NES_DBG_CM, "\n"); |
3228 | /* create the primary CM core, pass this handle to subsequent core inits */ | 3446 | /* create the primary CM core, pass this handle to subsequent core inits */ |
3229 | g_cm_core = nes_cm_alloc_core(); | 3447 | g_cm_core = nes_cm_alloc_core(); |
3230 | if (g_cm_core) { | 3448 | if (g_cm_core) |
3231 | return 0; | 3449 | return 0; |
3232 | } else { | 3450 | else |
3233 | return -ENOMEM; | 3451 | return -ENOMEM; |
3234 | } | ||
3235 | } | 3452 | } |
3236 | 3453 | ||
3237 | 3454 | ||
@@ -3252,7 +3469,6 @@ int nes_cm_stop(void) | |||
3252 | */ | 3469 | */ |
3253 | static void cm_event_connected(struct nes_cm_event *event) | 3470 | static void cm_event_connected(struct nes_cm_event *event) |
3254 | { | 3471 | { |
3255 | u64 u64temp; | ||
3256 | struct nes_qp *nesqp; | 3472 | struct nes_qp *nesqp; |
3257 | struct nes_vnic *nesvnic; | 3473 | struct nes_vnic *nesvnic; |
3258 | struct nes_device *nesdev; | 3474 | struct nes_device *nesdev; |
@@ -3261,7 +3477,6 @@ static void cm_event_connected(struct nes_cm_event *event) | |||
3261 | struct ib_qp_attr attr; | 3477 | struct ib_qp_attr attr; |
3262 | struct iw_cm_id *cm_id; | 3478 | struct iw_cm_id *cm_id; |
3263 | struct iw_cm_event cm_event; | 3479 | struct iw_cm_event cm_event; |
3264 | struct nes_hw_qp_wqe *wqe; | ||
3265 | struct nes_v4_quad nes_quad; | 3480 | struct nes_v4_quad nes_quad; |
3266 | u32 crc_value; | 3481 | u32 crc_value; |
3267 | int ret; | 3482 | int ret; |
@@ -3275,17 +3490,16 @@ static void cm_event_connected(struct nes_cm_event *event) | |||
3275 | nesdev = nesvnic->nesdev; | 3490 | nesdev = nesvnic->nesdev; |
3276 | nesadapter = nesdev->nesadapter; | 3491 | nesadapter = nesdev->nesadapter; |
3277 | 3492 | ||
3278 | if (nesqp->destroyed) { | 3493 | if (nesqp->destroyed) |
3279 | return; | 3494 | return; |
3280 | } | ||
3281 | atomic_inc(&cm_connecteds); | 3495 | atomic_inc(&cm_connecteds); |
3282 | nes_debug(NES_DBG_CM, "QP%u attempting to connect to 0x%08X:0x%04X on" | 3496 | nes_debug(NES_DBG_CM, "QP%u attempting to connect to 0x%08X:0x%04X on" |
3283 | " local port 0x%04X. jiffies = %lu.\n", | 3497 | " local port 0x%04X. jiffies = %lu.\n", |
3284 | nesqp->hwqp.qp_id, | 3498 | nesqp->hwqp.qp_id, |
3285 | ntohl(cm_id->remote_addr.sin_addr.s_addr), | 3499 | ntohl(cm_id->remote_addr.sin_addr.s_addr), |
3286 | ntohs(cm_id->remote_addr.sin_port), | 3500 | ntohs(cm_id->remote_addr.sin_port), |
3287 | ntohs(cm_id->local_addr.sin_port), | 3501 | ntohs(cm_id->local_addr.sin_port), |
3288 | jiffies); | 3502 | jiffies); |
3289 | 3503 | ||
3290 | nes_cm_init_tsa_conn(nesqp, cm_node); | 3504 | nes_cm_init_tsa_conn(nesqp, cm_node); |
3291 | 3505 | ||
@@ -3316,40 +3530,12 @@ static void cm_event_connected(struct nes_cm_event *event) | |||
3316 | NES_QPCONTEXT_ORDIRD_IWARP_MODE_SHIFT); | 3530 | NES_QPCONTEXT_ORDIRD_IWARP_MODE_SHIFT); |
3317 | 3531 | ||
3318 | /* Adjust tail for not having a LSMM */ | 3532 | /* Adjust tail for not having a LSMM */ |
3319 | nesqp->hwqp.sq_tail = 1; | 3533 | /*nesqp->hwqp.sq_tail = 1;*/ |
3320 | |||
3321 | #if defined(NES_SEND_FIRST_WRITE) | ||
3322 | if (cm_node->send_write0) { | ||
3323 | nes_debug(NES_DBG_CM, "Sending first write.\n"); | ||
3324 | wqe = &nesqp->hwqp.sq_vbase[0]; | ||
3325 | u64temp = (unsigned long)nesqp; | ||
3326 | u64temp |= NES_SW_CONTEXT_ALIGN>>1; | ||
3327 | set_wqe_64bit_value(wqe->wqe_words, | ||
3328 | NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX, u64temp); | ||
3329 | wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] = | ||
3330 | cpu_to_le32(NES_IWARP_SQ_OP_RDMAW); | ||
3331 | wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] = 0; | ||
3332 | wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_LOW_IDX] = 0; | ||
3333 | wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_HIGH_IDX] = 0; | ||
3334 | wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] = 0; | ||
3335 | wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 0; | ||
3336 | 3534 | ||
3337 | if (nesqp->sq_kmapped) { | 3535 | build_rdma0_msg(cm_node, &nesqp); |
3338 | nesqp->sq_kmapped = 0; | ||
3339 | kunmap(nesqp->page); | ||
3340 | } | ||
3341 | 3536 | ||
3342 | /* use the reserved spot on the WQ for the extra first WQE */ | 3537 | nes_write32(nesdev->regs + NES_WQE_ALLOC, |
3343 | nesqp->nesqp_context->ird_ord_sizes &= | 3538 | (1 << 24) | 0x00800000 | nesqp->hwqp.qp_id); |
3344 | cpu_to_le32(~(NES_QPCONTEXT_ORDIRD_LSMM_PRESENT | | ||
3345 | NES_QPCONTEXT_ORDIRD_WRPDU | | ||
3346 | NES_QPCONTEXT_ORDIRD_ALSMM)); | ||
3347 | nesqp->skip_lsmm = 1; | ||
3348 | nesqp->hwqp.sq_tail = 0; | ||
3349 | nes_write32(nesdev->regs + NES_WQE_ALLOC, | ||
3350 | (1 << 24) | 0x00800000 | nesqp->hwqp.qp_id); | ||
3351 | } | ||
3352 | #endif | ||
3353 | 3539 | ||
3354 | memset(&nes_quad, 0, sizeof(nes_quad)); | 3540 | memset(&nes_quad, 0, sizeof(nes_quad)); |
3355 | 3541 | ||
@@ -3366,13 +3552,13 @@ static void cm_event_connected(struct nes_cm_event *event) | |||
3366 | crc_value = get_crc_value(&nes_quad); | 3552 | crc_value = get_crc_value(&nes_quad); |
3367 | nesqp->hte_index = cpu_to_be32(crc_value ^ 0xffffffff); | 3553 | nesqp->hte_index = cpu_to_be32(crc_value ^ 0xffffffff); |
3368 | nes_debug(NES_DBG_CM, "HTE Index = 0x%08X, After CRC = 0x%08X\n", | 3554 | nes_debug(NES_DBG_CM, "HTE Index = 0x%08X, After CRC = 0x%08X\n", |
3369 | nesqp->hte_index, nesqp->hte_index & nesadapter->hte_index_mask); | 3555 | nesqp->hte_index, nesqp->hte_index & nesadapter->hte_index_mask); |
3370 | 3556 | ||
3371 | nesqp->hte_index &= nesadapter->hte_index_mask; | 3557 | nesqp->hte_index &= nesadapter->hte_index_mask; |
3372 | nesqp->nesqp_context->hte_index = cpu_to_le32(nesqp->hte_index); | 3558 | nesqp->nesqp_context->hte_index = cpu_to_le32(nesqp->hte_index); |
3373 | 3559 | ||
3374 | nesqp->ietf_frame = &cm_node->mpa_frame; | 3560 | nesqp->ietf_frame = &cm_node->mpa_frame; |
3375 | nesqp->private_data_len = (u8) cm_node->mpa_frame_size; | 3561 | nesqp->private_data_len = (u8)cm_node->mpa_frame_size; |
3376 | cm_node->cm_core->api->accelerated(cm_node->cm_core, cm_node); | 3562 | cm_node->cm_core->api->accelerated(cm_node->cm_core, cm_node); |
3377 | 3563 | ||
3378 | /* notify OF layer we successfully created the requested connection */ | 3564 | /* notify OF layer we successfully created the requested connection */ |
@@ -3384,7 +3570,9 @@ static void cm_event_connected(struct nes_cm_event *event) | |||
3384 | cm_event.remote_addr = cm_id->remote_addr; | 3570 | cm_event.remote_addr = cm_id->remote_addr; |
3385 | 3571 | ||
3386 | cm_event.private_data = (void *)event->cm_node->mpa_frame_buf; | 3572 | cm_event.private_data = (void *)event->cm_node->mpa_frame_buf; |
3387 | cm_event.private_data_len = (u8) event->cm_node->mpa_frame_size; | 3573 | cm_event.private_data_len = (u8)event->cm_node->mpa_frame_size; |
3574 | cm_event.ird = cm_node->ird_size; | ||
3575 | cm_event.ord = cm_node->ord_size; | ||
3388 | 3576 | ||
3389 | cm_event.local_addr.sin_addr.s_addr = event->cm_info.rem_addr; | 3577 | cm_event.local_addr.sin_addr.s_addr = event->cm_info.rem_addr; |
3390 | ret = cm_id->event_handler(cm_id, &cm_event); | 3578 | ret = cm_id->event_handler(cm_id, &cm_event); |
@@ -3392,12 +3580,12 @@ static void cm_event_connected(struct nes_cm_event *event) | |||
3392 | 3580 | ||
3393 | if (ret) | 3581 | if (ret) |
3394 | printk(KERN_ERR "%s[%u] OFA CM event_handler returned, " | 3582 | printk(KERN_ERR "%s[%u] OFA CM event_handler returned, " |
3395 | "ret=%d\n", __func__, __LINE__, ret); | 3583 | "ret=%d\n", __func__, __LINE__, ret); |
3396 | attr.qp_state = IB_QPS_RTS; | 3584 | attr.qp_state = IB_QPS_RTS; |
3397 | nes_modify_qp(&nesqp->ibqp, &attr, IB_QP_STATE, NULL); | 3585 | nes_modify_qp(&nesqp->ibqp, &attr, IB_QP_STATE, NULL); |
3398 | 3586 | ||
3399 | nes_debug(NES_DBG_CM, "Exiting connect thread for QP%u. jiffies = " | 3587 | nes_debug(NES_DBG_CM, "Exiting connect thread for QP%u. jiffies = " |
3400 | "%lu\n", nesqp->hwqp.qp_id, jiffies); | 3588 | "%lu\n", nesqp->hwqp.qp_id, jiffies); |
3401 | 3589 | ||
3402 | return; | 3590 | return; |
3403 | } | 3591 | } |
@@ -3418,16 +3606,14 @@ static void cm_event_connect_error(struct nes_cm_event *event) | |||
3418 | return; | 3606 | return; |
3419 | 3607 | ||
3420 | cm_id = event->cm_node->cm_id; | 3608 | cm_id = event->cm_node->cm_id; |
3421 | if (!cm_id) { | 3609 | if (!cm_id) |
3422 | return; | 3610 | return; |
3423 | } | ||
3424 | 3611 | ||
3425 | nes_debug(NES_DBG_CM, "cm_node=%p, cm_id=%p\n", event->cm_node, cm_id); | 3612 | nes_debug(NES_DBG_CM, "cm_node=%p, cm_id=%p\n", event->cm_node, cm_id); |
3426 | nesqp = cm_id->provider_data; | 3613 | nesqp = cm_id->provider_data; |
3427 | 3614 | ||
3428 | if (!nesqp) { | 3615 | if (!nesqp) |
3429 | return; | 3616 | return; |
3430 | } | ||
3431 | 3617 | ||
3432 | /* notify OF layer about this connection error event */ | 3618 | /* notify OF layer about this connection error event */ |
3433 | /* cm_id->rem_ref(cm_id); */ | 3619 | /* cm_id->rem_ref(cm_id); */ |
@@ -3442,14 +3628,14 @@ static void cm_event_connect_error(struct nes_cm_event *event) | |||
3442 | cm_event.private_data_len = 0; | 3628 | cm_event.private_data_len = 0; |
3443 | 3629 | ||
3444 | nes_debug(NES_DBG_CM, "call CM_EVENT REJECTED, local_addr=%08x, " | 3630 | nes_debug(NES_DBG_CM, "call CM_EVENT REJECTED, local_addr=%08x, " |
3445 | "remove_addr=%08x\n", cm_event.local_addr.sin_addr.s_addr, | 3631 | "remove_addr=%08x\n", cm_event.local_addr.sin_addr.s_addr, |
3446 | cm_event.remote_addr.sin_addr.s_addr); | 3632 | cm_event.remote_addr.sin_addr.s_addr); |
3447 | 3633 | ||
3448 | ret = cm_id->event_handler(cm_id, &cm_event); | 3634 | ret = cm_id->event_handler(cm_id, &cm_event); |
3449 | nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret); | 3635 | nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret); |
3450 | if (ret) | 3636 | if (ret) |
3451 | printk(KERN_ERR "%s[%u] OFA CM event_handler returned, " | 3637 | printk(KERN_ERR "%s[%u] OFA CM event_handler returned, " |
3452 | "ret=%d\n", __func__, __LINE__, ret); | 3638 | "ret=%d\n", __func__, __LINE__, ret); |
3453 | cm_id->rem_ref(cm_id); | 3639 | cm_id->rem_ref(cm_id); |
3454 | 3640 | ||
3455 | rem_ref_cm_node(event->cm_node->cm_core, event->cm_node); | 3641 | rem_ref_cm_node(event->cm_node->cm_core, event->cm_node); |
@@ -3519,7 +3705,7 @@ static void cm_event_reset(struct nes_cm_event *event) | |||
3519 | */ | 3705 | */ |
3520 | static void cm_event_mpa_req(struct nes_cm_event *event) | 3706 | static void cm_event_mpa_req(struct nes_cm_event *event) |
3521 | { | 3707 | { |
3522 | struct iw_cm_id *cm_id; | 3708 | struct iw_cm_id *cm_id; |
3523 | struct iw_cm_event cm_event; | 3709 | struct iw_cm_event cm_event; |
3524 | int ret; | 3710 | int ret; |
3525 | struct nes_cm_node *cm_node; | 3711 | struct nes_cm_node *cm_node; |
@@ -3531,7 +3717,7 @@ static void cm_event_mpa_req(struct nes_cm_event *event) | |||
3531 | 3717 | ||
3532 | atomic_inc(&cm_connect_reqs); | 3718 | atomic_inc(&cm_connect_reqs); |
3533 | nes_debug(NES_DBG_CM, "cm_node = %p - cm_id = %p, jiffies = %lu\n", | 3719 | nes_debug(NES_DBG_CM, "cm_node = %p - cm_id = %p, jiffies = %lu\n", |
3534 | cm_node, cm_id, jiffies); | 3720 | cm_node, cm_id, jiffies); |
3535 | 3721 | ||
3536 | cm_event.event = IW_CM_EVENT_CONNECT_REQUEST; | 3722 | cm_event.event = IW_CM_EVENT_CONNECT_REQUEST; |
3537 | cm_event.status = 0; | 3723 | cm_event.status = 0; |
@@ -3545,19 +3731,21 @@ static void cm_event_mpa_req(struct nes_cm_event *event) | |||
3545 | cm_event.remote_addr.sin_port = htons(event->cm_info.rem_port); | 3731 | cm_event.remote_addr.sin_port = htons(event->cm_info.rem_port); |
3546 | cm_event.remote_addr.sin_addr.s_addr = htonl(event->cm_info.rem_addr); | 3732 | cm_event.remote_addr.sin_addr.s_addr = htonl(event->cm_info.rem_addr); |
3547 | cm_event.private_data = cm_node->mpa_frame_buf; | 3733 | cm_event.private_data = cm_node->mpa_frame_buf; |
3548 | cm_event.private_data_len = (u8) cm_node->mpa_frame_size; | 3734 | cm_event.private_data_len = (u8)cm_node->mpa_frame_size; |
3735 | cm_event.ird = cm_node->ird_size; | ||
3736 | cm_event.ord = cm_node->ord_size; | ||
3549 | 3737 | ||
3550 | ret = cm_id->event_handler(cm_id, &cm_event); | 3738 | ret = cm_id->event_handler(cm_id, &cm_event); |
3551 | if (ret) | 3739 | if (ret) |
3552 | printk(KERN_ERR "%s[%u] OFA CM event_handler returned, ret=%d\n", | 3740 | printk(KERN_ERR "%s[%u] OFA CM event_handler returned, ret=%d\n", |
3553 | __func__, __LINE__, ret); | 3741 | __func__, __LINE__, ret); |
3554 | return; | 3742 | return; |
3555 | } | 3743 | } |
3556 | 3744 | ||
3557 | 3745 | ||
3558 | static void cm_event_mpa_reject(struct nes_cm_event *event) | 3746 | static void cm_event_mpa_reject(struct nes_cm_event *event) |
3559 | { | 3747 | { |
3560 | struct iw_cm_id *cm_id; | 3748 | struct iw_cm_id *cm_id; |
3561 | struct iw_cm_event cm_event; | 3749 | struct iw_cm_event cm_event; |
3562 | struct nes_cm_node *cm_node; | 3750 | struct nes_cm_node *cm_node; |
3563 | int ret; | 3751 | int ret; |
@@ -3569,7 +3757,7 @@ static void cm_event_mpa_reject(struct nes_cm_event *event) | |||
3569 | 3757 | ||
3570 | atomic_inc(&cm_connect_reqs); | 3758 | atomic_inc(&cm_connect_reqs); |
3571 | nes_debug(NES_DBG_CM, "cm_node = %p - cm_id = %p, jiffies = %lu\n", | 3759 | nes_debug(NES_DBG_CM, "cm_node = %p - cm_id = %p, jiffies = %lu\n", |
3572 | cm_node, cm_id, jiffies); | 3760 | cm_node, cm_id, jiffies); |
3573 | 3761 | ||
3574 | cm_event.event = IW_CM_EVENT_CONNECT_REPLY; | 3762 | cm_event.event = IW_CM_EVENT_CONNECT_REPLY; |
3575 | cm_event.status = -ECONNREFUSED; | 3763 | cm_event.status = -ECONNREFUSED; |
@@ -3584,17 +3772,17 @@ static void cm_event_mpa_reject(struct nes_cm_event *event) | |||
3584 | cm_event.remote_addr.sin_addr.s_addr = htonl(event->cm_info.rem_addr); | 3772 | cm_event.remote_addr.sin_addr.s_addr = htonl(event->cm_info.rem_addr); |
3585 | 3773 | ||
3586 | cm_event.private_data = cm_node->mpa_frame_buf; | 3774 | cm_event.private_data = cm_node->mpa_frame_buf; |
3587 | cm_event.private_data_len = (u8) cm_node->mpa_frame_size; | 3775 | cm_event.private_data_len = (u8)cm_node->mpa_frame_size; |
3588 | 3776 | ||
3589 | nes_debug(NES_DBG_CM, "call CM_EVENT_MPA_REJECTED, local_addr=%08x, " | 3777 | nes_debug(NES_DBG_CM, "call CM_EVENT_MPA_REJECTED, local_addr=%08x, " |
3590 | "remove_addr=%08x\n", | 3778 | "remove_addr=%08x\n", |
3591 | cm_event.local_addr.sin_addr.s_addr, | 3779 | cm_event.local_addr.sin_addr.s_addr, |
3592 | cm_event.remote_addr.sin_addr.s_addr); | 3780 | cm_event.remote_addr.sin_addr.s_addr); |
3593 | 3781 | ||
3594 | ret = cm_id->event_handler(cm_id, &cm_event); | 3782 | ret = cm_id->event_handler(cm_id, &cm_event); |
3595 | if (ret) | 3783 | if (ret) |
3596 | printk(KERN_ERR "%s[%u] OFA CM event_handler returned, ret=%d\n", | 3784 | printk(KERN_ERR "%s[%u] OFA CM event_handler returned, ret=%d\n", |
3597 | __func__, __LINE__, ret); | 3785 | __func__, __LINE__, ret); |
3598 | 3786 | ||
3599 | return; | 3787 | return; |
3600 | } | 3788 | } |
@@ -3613,7 +3801,7 @@ static int nes_cm_post_event(struct nes_cm_event *event) | |||
3613 | event->cm_info.cm_id->add_ref(event->cm_info.cm_id); | 3801 | event->cm_info.cm_id->add_ref(event->cm_info.cm_id); |
3614 | INIT_WORK(&event->event_work, nes_cm_event_handler); | 3802 | INIT_WORK(&event->event_work, nes_cm_event_handler); |
3615 | nes_debug(NES_DBG_CM, "cm_node=%p queue_work, event=%p\n", | 3803 | nes_debug(NES_DBG_CM, "cm_node=%p queue_work, event=%p\n", |
3616 | event->cm_node, event); | 3804 | event->cm_node, event); |
3617 | 3805 | ||
3618 | queue_work(event->cm_node->cm_core->event_wq, &event->event_work); | 3806 | queue_work(event->cm_node->cm_core->event_wq, &event->event_work); |
3619 | 3807 | ||
@@ -3630,7 +3818,7 @@ static int nes_cm_post_event(struct nes_cm_event *event) | |||
3630 | static void nes_cm_event_handler(struct work_struct *work) | 3818 | static void nes_cm_event_handler(struct work_struct *work) |
3631 | { | 3819 | { |
3632 | struct nes_cm_event *event = container_of(work, struct nes_cm_event, | 3820 | struct nes_cm_event *event = container_of(work, struct nes_cm_event, |
3633 | event_work); | 3821 | event_work); |
3634 | struct nes_cm_core *cm_core; | 3822 | struct nes_cm_core *cm_core; |
3635 | 3823 | ||
3636 | if ((!event) || (!event->cm_node) || (!event->cm_node->cm_core)) | 3824 | if ((!event) || (!event->cm_node) || (!event->cm_node->cm_core)) |
@@ -3638,29 +3826,29 @@ static void nes_cm_event_handler(struct work_struct *work) | |||
3638 | 3826 | ||
3639 | cm_core = event->cm_node->cm_core; | 3827 | cm_core = event->cm_node->cm_core; |
3640 | nes_debug(NES_DBG_CM, "event=%p, event->type=%u, events posted=%u\n", | 3828 | nes_debug(NES_DBG_CM, "event=%p, event->type=%u, events posted=%u\n", |
3641 | event, event->type, atomic_read(&cm_core->events_posted)); | 3829 | event, event->type, atomic_read(&cm_core->events_posted)); |
3642 | 3830 | ||
3643 | switch (event->type) { | 3831 | switch (event->type) { |
3644 | case NES_CM_EVENT_MPA_REQ: | 3832 | case NES_CM_EVENT_MPA_REQ: |
3645 | cm_event_mpa_req(event); | 3833 | cm_event_mpa_req(event); |
3646 | nes_debug(NES_DBG_CM, "cm_node=%p CM Event: MPA REQUEST\n", | 3834 | nes_debug(NES_DBG_CM, "cm_node=%p CM Event: MPA REQUEST\n", |
3647 | event->cm_node); | 3835 | event->cm_node); |
3648 | break; | 3836 | break; |
3649 | case NES_CM_EVENT_RESET: | 3837 | case NES_CM_EVENT_RESET: |
3650 | nes_debug(NES_DBG_CM, "cm_node = %p CM Event: RESET\n", | 3838 | nes_debug(NES_DBG_CM, "cm_node = %p CM Event: RESET\n", |
3651 | event->cm_node); | 3839 | event->cm_node); |
3652 | cm_event_reset(event); | 3840 | cm_event_reset(event); |
3653 | break; | 3841 | break; |
3654 | case NES_CM_EVENT_CONNECTED: | 3842 | case NES_CM_EVENT_CONNECTED: |
3655 | if ((!event->cm_node->cm_id) || | 3843 | if ((!event->cm_node->cm_id) || |
3656 | (event->cm_node->state != NES_CM_STATE_TSA)) | 3844 | (event->cm_node->state != NES_CM_STATE_TSA)) |
3657 | break; | 3845 | break; |
3658 | cm_event_connected(event); | 3846 | cm_event_connected(event); |
3659 | nes_debug(NES_DBG_CM, "CM Event: CONNECTED\n"); | 3847 | nes_debug(NES_DBG_CM, "CM Event: CONNECTED\n"); |
3660 | break; | 3848 | break; |
3661 | case NES_CM_EVENT_MPA_REJECT: | 3849 | case NES_CM_EVENT_MPA_REJECT: |
3662 | if ((!event->cm_node->cm_id) || | 3850 | if ((!event->cm_node->cm_id) || |
3663 | (event->cm_node->state == NES_CM_STATE_TSA)) | 3851 | (event->cm_node->state == NES_CM_STATE_TSA)) |
3664 | break; | 3852 | break; |
3665 | cm_event_mpa_reject(event); | 3853 | cm_event_mpa_reject(event); |
3666 | nes_debug(NES_DBG_CM, "CM Event: REJECT\n"); | 3854 | nes_debug(NES_DBG_CM, "CM Event: REJECT\n"); |
@@ -3668,7 +3856,7 @@ static void nes_cm_event_handler(struct work_struct *work) | |||
3668 | 3856 | ||
3669 | case NES_CM_EVENT_ABORTED: | 3857 | case NES_CM_EVENT_ABORTED: |
3670 | if ((!event->cm_node->cm_id) || | 3858 | if ((!event->cm_node->cm_id) || |
3671 | (event->cm_node->state == NES_CM_STATE_TSA)) | 3859 | (event->cm_node->state == NES_CM_STATE_TSA)) |
3672 | break; | 3860 | break; |
3673 | cm_event_connect_error(event); | 3861 | cm_event_connect_error(event); |
3674 | nes_debug(NES_DBG_CM, "CM Event: ABORTED\n"); | 3862 | nes_debug(NES_DBG_CM, "CM Event: ABORTED\n"); |
diff --git a/drivers/infiniband/hw/nes/nes_cm.h b/drivers/infiniband/hw/nes/nes_cm.h index d9825fda70a1..85f53d9521b0 100644 --- a/drivers/infiniband/hw/nes/nes_cm.h +++ b/drivers/infiniband/hw/nes/nes_cm.h | |||
@@ -48,7 +48,16 @@ | |||
48 | #define IETF_MPA_KEY_SIZE 16 | 48 | #define IETF_MPA_KEY_SIZE 16 |
49 | #define IETF_MPA_VERSION 1 | 49 | #define IETF_MPA_VERSION 1 |
50 | #define IETF_MAX_PRIV_DATA_LEN 512 | 50 | #define IETF_MAX_PRIV_DATA_LEN 512 |
51 | #define IETF_MPA_FRAME_SIZE 20 | 51 | #define IETF_MPA_FRAME_SIZE 20 |
52 | #define IETF_RTR_MSG_SIZE 4 | ||
53 | #define IETF_MPA_V2_FLAG 0x10 | ||
54 | |||
55 | /* IETF RTR MSG Fields */ | ||
56 | #define IETF_PEER_TO_PEER 0x8000 | ||
57 | #define IETF_FLPDU_ZERO_LEN 0x4000 | ||
58 | #define IETF_RDMA0_WRITE 0x8000 | ||
59 | #define IETF_RDMA0_READ 0x4000 | ||
60 | #define IETF_NO_IRD_ORD 0x3FFF | ||
52 | 61 | ||
53 | enum ietf_mpa_flags { | 62 | enum ietf_mpa_flags { |
54 | IETF_MPA_FLAGS_MARKERS = 0x80, /* receive Markers */ | 63 | IETF_MPA_FLAGS_MARKERS = 0x80, /* receive Markers */ |
@@ -56,7 +65,7 @@ enum ietf_mpa_flags { | |||
56 | IETF_MPA_FLAGS_REJECT = 0x20, /* Reject */ | 65 | IETF_MPA_FLAGS_REJECT = 0x20, /* Reject */ |
57 | }; | 66 | }; |
58 | 67 | ||
59 | struct ietf_mpa_frame { | 68 | struct ietf_mpa_v1 { |
60 | u8 key[IETF_MPA_KEY_SIZE]; | 69 | u8 key[IETF_MPA_KEY_SIZE]; |
61 | u8 flags; | 70 | u8 flags; |
62 | u8 rev; | 71 | u8 rev; |
@@ -66,6 +75,20 @@ struct ietf_mpa_frame { | |||
66 | 75 | ||
67 | #define ietf_mpa_req_resp_frame ietf_mpa_frame | 76 | #define ietf_mpa_req_resp_frame ietf_mpa_frame |
68 | 77 | ||
78 | struct ietf_rtr_msg { | ||
79 | __be16 ctrl_ird; | ||
80 | __be16 ctrl_ord; | ||
81 | }; | ||
82 | |||
83 | struct ietf_mpa_v2 { | ||
84 | u8 key[IETF_MPA_KEY_SIZE]; | ||
85 | u8 flags; | ||
86 | u8 rev; | ||
87 | __be16 priv_data_len; | ||
88 | struct ietf_rtr_msg rtr_msg; | ||
89 | u8 priv_data[0]; | ||
90 | }; | ||
91 | |||
69 | struct nes_v4_quad { | 92 | struct nes_v4_quad { |
70 | u32 rsvd0; | 93 | u32 rsvd0; |
71 | __le32 DstIpAdrIndex; /* Only most significant 5 bits are valid */ | 94 | __le32 DstIpAdrIndex; /* Only most significant 5 bits are valid */ |
@@ -171,8 +194,7 @@ struct nes_timer_entry { | |||
171 | 194 | ||
172 | #define NES_CM_DEF_SEQ2 0x18ed5740 | 195 | #define NES_CM_DEF_SEQ2 0x18ed5740 |
173 | #define NES_CM_DEF_LOCAL_ID2 0xb807 | 196 | #define NES_CM_DEF_LOCAL_ID2 0xb807 |
174 | #define MAX_CM_BUFFER (IETF_MPA_FRAME_SIZE + IETF_MAX_PRIV_DATA_LEN) | 197 | #define MAX_CM_BUFFER (IETF_MPA_FRAME_SIZE + IETF_RTR_MSG_SIZE + IETF_MAX_PRIV_DATA_LEN) |
175 | |||
176 | 198 | ||
177 | typedef u32 nes_addr_t; | 199 | typedef u32 nes_addr_t; |
178 | 200 | ||
@@ -204,6 +226,21 @@ enum nes_cm_node_state { | |||
204 | NES_CM_STATE_CLOSED | 226 | NES_CM_STATE_CLOSED |
205 | }; | 227 | }; |
206 | 228 | ||
229 | enum mpa_frame_version { | ||
230 | IETF_MPA_V1 = 1, | ||
231 | IETF_MPA_V2 = 2 | ||
232 | }; | ||
233 | |||
234 | enum mpa_frame_key { | ||
235 | MPA_KEY_REQUEST, | ||
236 | MPA_KEY_REPLY | ||
237 | }; | ||
238 | |||
239 | enum send_rdma0 { | ||
240 | SEND_RDMA_READ_ZERO = 1, | ||
241 | SEND_RDMA_WRITE_ZERO = 2 | ||
242 | }; | ||
243 | |||
207 | enum nes_tcpip_pkt_type { | 244 | enum nes_tcpip_pkt_type { |
208 | NES_PKT_TYPE_UNKNOWN, | 245 | NES_PKT_TYPE_UNKNOWN, |
209 | NES_PKT_TYPE_SYN, | 246 | NES_PKT_TYPE_SYN, |
@@ -245,9 +282,9 @@ struct nes_cm_tcp_context { | |||
245 | 282 | ||
246 | 283 | ||
247 | enum nes_cm_listener_state { | 284 | enum nes_cm_listener_state { |
248 | NES_CM_LISTENER_PASSIVE_STATE=1, | 285 | NES_CM_LISTENER_PASSIVE_STATE = 1, |
249 | NES_CM_LISTENER_ACTIVE_STATE=2, | 286 | NES_CM_LISTENER_ACTIVE_STATE = 2, |
250 | NES_CM_LISTENER_EITHER_STATE=3 | 287 | NES_CM_LISTENER_EITHER_STATE = 3 |
251 | }; | 288 | }; |
252 | 289 | ||
253 | struct nes_cm_listener { | 290 | struct nes_cm_listener { |
@@ -283,16 +320,20 @@ struct nes_cm_node { | |||
283 | 320 | ||
284 | struct nes_cm_node *loopbackpartner; | 321 | struct nes_cm_node *loopbackpartner; |
285 | 322 | ||
286 | struct nes_timer_entry *send_entry; | 323 | struct nes_timer_entry *send_entry; |
287 | 324 | struct nes_timer_entry *recv_entry; | |
288 | spinlock_t retrans_list_lock; | 325 | spinlock_t retrans_list_lock; |
289 | struct nes_timer_entry *recv_entry; | 326 | enum send_rdma0 send_rdma0_op; |
290 | 327 | ||
291 | int send_write0; | ||
292 | union { | 328 | union { |
293 | struct ietf_mpa_frame mpa_frame; | 329 | struct ietf_mpa_v1 mpa_frame; |
294 | u8 mpa_frame_buf[MAX_CM_BUFFER]; | 330 | struct ietf_mpa_v2 mpa_v2_frame; |
331 | u8 mpa_frame_buf[MAX_CM_BUFFER]; | ||
295 | }; | 332 | }; |
333 | enum mpa_frame_version mpa_frame_rev; | ||
334 | u16 ird_size; | ||
335 | u16 ord_size; | ||
336 | |||
296 | u16 mpa_frame_size; | 337 | u16 mpa_frame_size; |
297 | struct iw_cm_id *cm_id; | 338 | struct iw_cm_id *cm_id; |
298 | struct list_head list; | 339 | struct list_head list; |
@@ -399,10 +440,8 @@ struct nes_cm_ops { | |||
399 | struct nes_vnic *, u16, void *, | 440 | struct nes_vnic *, u16, void *, |
400 | struct nes_cm_info *); | 441 | struct nes_cm_info *); |
401 | int (*close)(struct nes_cm_core *, struct nes_cm_node *); | 442 | int (*close)(struct nes_cm_core *, struct nes_cm_node *); |
402 | int (*accept)(struct nes_cm_core *, struct ietf_mpa_frame *, | 443 | int (*accept)(struct nes_cm_core *, struct nes_cm_node *); |
403 | struct nes_cm_node *); | 444 | int (*reject)(struct nes_cm_core *, struct nes_cm_node *); |
404 | int (*reject)(struct nes_cm_core *, struct ietf_mpa_frame *, | ||
405 | struct nes_cm_node *); | ||
406 | int (*recv_pkt)(struct nes_cm_core *, struct nes_vnic *, | 445 | int (*recv_pkt)(struct nes_cm_core *, struct nes_vnic *, |
407 | struct sk_buff *); | 446 | struct sk_buff *); |
408 | int (*destroy_cm_core)(struct nes_cm_core *); | 447 | int (*destroy_cm_core)(struct nes_cm_core *); |
diff --git a/drivers/infiniband/hw/nes/nes_verbs.h b/drivers/infiniband/hw/nes/nes_verbs.h index 2df9993e0cac..854316d6694f 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.h +++ b/drivers/infiniband/hw/nes/nes_verbs.h | |||
@@ -139,7 +139,8 @@ struct nes_qp { | |||
139 | struct nes_cq *nesrcq; | 139 | struct nes_cq *nesrcq; |
140 | struct nes_pd *nespd; | 140 | struct nes_pd *nespd; |
141 | void *cm_node; /* handle of the node this QP is associated with */ | 141 | void *cm_node; /* handle of the node this QP is associated with */ |
142 | struct ietf_mpa_frame *ietf_frame; | 142 | void *ietf_frame; |
143 | u8 ietf_frame_size; | ||
143 | dma_addr_t ietf_frame_pbase; | 144 | dma_addr_t ietf_frame_pbase; |
144 | struct ib_mr *lsmm_mr; | 145 | struct ib_mr *lsmm_mr; |
145 | struct nes_hw_qp hwqp; | 146 | struct nes_hw_qp hwqp; |