diff options
Diffstat (limited to 'drivers/infiniband/hw/nes/nes_cm.c')
| -rw-r--r-- | drivers/infiniband/hw/nes/nes_cm.c | 1627 | 
1 files changed, 1047 insertions, 580 deletions
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index 25ad0f9944c..6f09a72e78d 100644 --- a/drivers/infiniband/hw/nes/nes_cm.c +++ b/drivers/infiniband/hw/nes/nes_cm.c @@ -1,5 +1,5 @@  /* - * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved. + * Copyright (c) 2006 - 2014 Intel Corporation.  All rights reserved.   *   * This software is available to you under a choice of one of two   * licenses.  You may choose to be licensed under the terms of the GNU @@ -34,7 +34,7 @@  #define TCPOPT_TIMESTAMP 8 -#include <asm/atomic.h> +#include <linux/atomic.h>  #include <linux/skbuff.h>  #include <linux/ip.h>  #include <linux/tcp.h> @@ -59,6 +59,7 @@  #include <net/route.h>  #include <net/ip_fib.h>  #include <net/tcp.h> +#include <linux/fcntl.h>  #include "nes.h" @@ -77,26 +78,19 @@ atomic_t cm_nodes_destroyed;  atomic_t cm_accel_dropped_pkts;  atomic_t cm_resets_recvd; -static inline int mini_cm_accelerated(struct nes_cm_core *, -	struct nes_cm_node *); -static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *, -	struct nes_vnic *, struct nes_cm_info *); +static inline int mini_cm_accelerated(struct nes_cm_core *, struct nes_cm_node *); +static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *, struct nes_vnic *, struct nes_cm_info *);  static int mini_cm_del_listen(struct nes_cm_core *, struct nes_cm_listener *); -static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *, -	struct nes_vnic *, u16, void *, struct nes_cm_info *); +static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *, struct nes_vnic *, u16, void *, struct nes_cm_info *);  static int mini_cm_close(struct nes_cm_core *, struct nes_cm_node *); -static int mini_cm_accept(struct nes_cm_core *, struct ietf_mpa_frame *, -	struct nes_cm_node *); -static int mini_cm_reject(struct nes_cm_core *, struct ietf_mpa_frame *, -	struct nes_cm_node *); -static int mini_cm_recv_pkt(struct nes_cm_core *, struct nes_vnic *, -	struct sk_buff *); +static int mini_cm_accept(struct nes_cm_core *, struct nes_cm_node *); +static int mini_cm_reject(struct nes_cm_core *, struct nes_cm_node *); +static int mini_cm_recv_pkt(struct nes_cm_core *, struct nes_vnic *, struct sk_buff *);  static int mini_cm_dealloc_core(struct nes_cm_core *);  static int mini_cm_get(struct nes_cm_core *);  static int mini_cm_set(struct nes_cm_core *, u32, u32); -static void form_cm_frame(struct sk_buff *, struct nes_cm_node *, -	void *, u32, void *, u32, u8); +static void form_cm_frame(struct sk_buff *, struct nes_cm_node *, void *, u32, void *, u32, u8);  static int add_ref_cm_node(struct nes_cm_node *);  static int rem_ref_cm_node(struct nes_cm_core *, struct nes_cm_node *); @@ -111,16 +105,14 @@ static int send_syn(struct nes_cm_node *, u32, struct sk_buff *);  static int send_reset(struct nes_cm_node *, struct sk_buff *);  static int send_ack(struct nes_cm_node *cm_node, struct sk_buff *skb);  static int send_fin(struct nes_cm_node *cm_node, struct sk_buff *skb); -static void process_packet(struct nes_cm_node *, struct sk_buff *, -	struct nes_cm_core *); +static void process_packet(struct nes_cm_node *, struct sk_buff *, struct nes_cm_core *);  static void active_open_err(struct nes_cm_node *, struct sk_buff *, int);  static void passive_open_err(struct nes_cm_node *, struct sk_buff *, int);  static void cleanup_retrans_entry(struct nes_cm_node *);  static void handle_rcv_mpa(struct nes_cm_node *, struct sk_buff *);  static void free_retrans_entry(struct nes_cm_node *cm_node); -static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph, -	struct sk_buff *skb, int optionsize, int passive); +static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph, struct sk_buff *skb, int optionsize, int passive);  /* CM event handler functions */  static void cm_event_connected(struct nes_cm_event *); @@ -130,7 +122,14 @@ static void cm_event_mpa_req(struct nes_cm_event *);  static void cm_event_mpa_reject(struct nes_cm_event *);  static void handle_recv_entry(struct nes_cm_node *cm_node, u32 rem_node); +/* MPA build functions */ +static int cm_build_mpa_frame(struct nes_cm_node *, u8 **, u16 *, u8 *, u8); +static void build_mpa_v2(struct nes_cm_node *, void *, u8); +static void build_mpa_v1(struct nes_cm_node *, void *, u8); +static void build_rdma0_msg(struct nes_cm_node *, struct nes_qp **); +  static void print_core(struct nes_cm_core *core); +static void record_ird_ord(struct nes_cm_node *, u16, u16);  /* External CM API Interface */  /* instance of function pointers for client API */ @@ -159,12 +158,20 @@ atomic_t cm_connecteds;  atomic_t cm_connect_reqs;  atomic_t cm_rejects; +int nes_add_ref_cm_node(struct nes_cm_node *cm_node) +{ +	return add_ref_cm_node(cm_node); +} +int nes_rem_ref_cm_node(struct nes_cm_node *cm_node) +{ +	return rem_ref_cm_node(cm_node->cm_core, cm_node); +}  /**   * create_event   */ -static struct nes_cm_event *create_event(struct nes_cm_node *cm_node, -		enum nes_cm_event_type type) +static struct nes_cm_event *create_event(struct nes_cm_node *	cm_node, +					 enum nes_cm_event_type type)  {  	struct nes_cm_event *event; @@ -186,10 +193,10 @@ static struct nes_cm_event *create_event(struct nes_cm_node *cm_node,  	event->cm_info.cm_id = cm_node->cm_id;  	nes_debug(NES_DBG_CM, "cm_node=%p Created event=%p, type=%u, " -		"dst_addr=%08x[%x], src_addr=%08x[%x]\n", -		cm_node, event, type, event->cm_info.loc_addr, -		event->cm_info.loc_port, event->cm_info.rem_addr, -		event->cm_info.rem_port); +		  "dst_addr=%08x[%x], src_addr=%08x[%x]\n", +		  cm_node, event, type, event->cm_info.loc_addr, +		  event->cm_info.loc_port, event->cm_info.rem_addr, +		  event->cm_info.rem_port);  	nes_cm_post_event(event);  	return event; @@ -201,14 +208,19 @@ static struct nes_cm_event *create_event(struct nes_cm_node *cm_node,   */  static int send_mpa_request(struct nes_cm_node *cm_node, struct sk_buff *skb)  { +	u8 start_addr = 0; +	u8 *start_ptr = &start_addr; +	u8 **start_buff = &start_ptr; +	u16 buff_len = 0; +  	if (!skb) {  		nes_debug(NES_DBG_CM, "skb set to NULL\n");  		return -1;  	}  	/* send an MPA Request frame */ -	form_cm_frame(skb, cm_node, NULL, 0, &cm_node->mpa_frame, -			cm_node->mpa_frame_size, SET_ACK); +	cm_build_mpa_frame(cm_node, start_buff, &buff_len, NULL, MPA_KEY_REQUEST); +	form_cm_frame(skb, cm_node, NULL, 0, *start_buff, buff_len, SET_ACK);  	return schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 1, 0);  } @@ -217,7 +229,12 @@ static int send_mpa_request(struct nes_cm_node *cm_node, struct sk_buff *skb)  static int send_mpa_reject(struct nes_cm_node *cm_node)  { -	struct sk_buff  *skb = NULL; +	struct sk_buff *skb = NULL; +	u8 start_addr = 0; +	u8 *start_ptr = &start_addr; +	u8 **start_buff = &start_ptr; +	u16 buff_len = 0; +	struct ietf_mpa_v1 *mpa_frame;  	skb = dev_alloc_skb(MAX_CM_BUFFER);  	if (!skb) { @@ -226,8 +243,10 @@ static int send_mpa_reject(struct nes_cm_node *cm_node)  	}  	/* send an MPA reject frame */ -	form_cm_frame(skb, cm_node, NULL, 0, &cm_node->mpa_frame, -			cm_node->mpa_frame_size, SET_ACK | SET_FIN); +	cm_build_mpa_frame(cm_node, start_buff, &buff_len, NULL, MPA_KEY_REPLY); +	mpa_frame = (struct ietf_mpa_v1 *)*start_buff; +	mpa_frame->flags |= IETF_MPA_FLAGS_REJECT; +	form_cm_frame(skb, cm_node, NULL, 0, *start_buff, buff_len, SET_ACK | SET_FIN);  	cm_node->state = NES_CM_STATE_FIN_WAIT1;  	return schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 1, 0); @@ -239,24 +258,31 @@ static int send_mpa_reject(struct nes_cm_node *cm_node)   * IETF MPA frame   */  static int parse_mpa(struct nes_cm_node *cm_node, u8 *buffer, u32 *type, -		u32 len) +		     u32 len)  { -	struct ietf_mpa_frame *mpa_frame; +	struct ietf_mpa_v1 *mpa_frame; +	struct ietf_mpa_v2 *mpa_v2_frame; +	struct ietf_rtr_msg *rtr_msg; +	int mpa_hdr_len; +	int priv_data_len;  	*type = NES_MPA_REQUEST_ACCEPT;  	/* assume req frame is in tcp data payload */ -	if (len < sizeof(struct ietf_mpa_frame)) { +	if (len < sizeof(struct ietf_mpa_v1)) {  		nes_debug(NES_DBG_CM, "The received ietf buffer was too small (%x)\n", len);  		return -EINVAL;  	} -	mpa_frame = (struct ietf_mpa_frame *)buffer; -	cm_node->mpa_frame_size = ntohs(mpa_frame->priv_data_len); +	/* points to the beginning of the frame, which could be MPA V1 or V2 */ +	mpa_frame = (struct ietf_mpa_v1 *)buffer; +	mpa_hdr_len = sizeof(struct ietf_mpa_v1); +	priv_data_len = ntohs(mpa_frame->priv_data_len); +  	/* make sure mpa private data len is less than 512 bytes */ -	if (cm_node->mpa_frame_size > IETF_MAX_PRIV_DATA_LEN) { +	if (priv_data_len > IETF_MAX_PRIV_DATA_LEN) {  		nes_debug(NES_DBG_CM, "The received Length of Private" -			" Data field exceeds 512 octets\n"); +			  " Data field exceeds 512 octets\n");  		return -EINVAL;  	}  	/* @@ -264,11 +290,22 @@ static int parse_mpa(struct nes_cm_node *cm_node, u8 *buffer, u32 *type,  	 * received MPA version and MPA key information  	 *  	 */ -	if (mpa_frame->rev != mpa_version) { +	if (mpa_frame->rev != IETF_MPA_V1 && mpa_frame->rev != IETF_MPA_V2) { +		nes_debug(NES_DBG_CM, "The received mpa version" +			  " is not supported\n"); +		return -EINVAL; +	} +	/* +	* backwards compatibility only +	*/ +	if (mpa_frame->rev > cm_node->mpa_frame_rev) {  		nes_debug(NES_DBG_CM, "The received mpa version" -				" can not be interoperated\n"); +			" can not be interoperated\n");  		return -EINVAL; +	} else { +		cm_node->mpa_frame_rev = mpa_frame->rev;  	} +  	if (cm_node->state != NES_CM_STATE_MPAREQ_SENT) {  		if (memcmp(mpa_frame->key, IEFT_MPA_KEY_REQ, IETF_MPA_KEY_SIZE)) {  			nes_debug(NES_DBG_CM, "Unexpected MPA Key received \n"); @@ -281,25 +318,109 @@ static int parse_mpa(struct nes_cm_node *cm_node, u8 *buffer, u32 *type,  		}  	} -	if (cm_node->mpa_frame_size + sizeof(struct ietf_mpa_frame) != len) { +	if (priv_data_len + mpa_hdr_len != len) {  		nes_debug(NES_DBG_CM, "The received ietf buffer was not right" -				" complete (%x + %x != %x)\n", -				cm_node->mpa_frame_size, -				(u32)sizeof(struct ietf_mpa_frame), len); +			" complete (%x + %x != %x)\n", +			priv_data_len, mpa_hdr_len, len);  		return -EINVAL;  	}  	/* make sure it does not exceed the max size */  	if (len > MAX_CM_BUFFER) {  		nes_debug(NES_DBG_CM, "The received ietf buffer was too large" -				" (%x + %x != %x)\n", -				cm_node->mpa_frame_size, -				(u32)sizeof(struct ietf_mpa_frame), len); +			" (%x + %x != %x)\n", +			priv_data_len, mpa_hdr_len, len);  		return -EINVAL;  	} +	cm_node->mpa_frame_size = priv_data_len; + +	switch (mpa_frame->rev) { +	case IETF_MPA_V2: { +		u16 ird_size; +		u16 ord_size; +		u16 rtr_ctrl_ird; +		u16 rtr_ctrl_ord; + +		mpa_v2_frame = (struct ietf_mpa_v2 *)buffer; +		mpa_hdr_len += IETF_RTR_MSG_SIZE; +		cm_node->mpa_frame_size -= IETF_RTR_MSG_SIZE; +		rtr_msg = &mpa_v2_frame->rtr_msg; + +		/* parse rtr message */ +		rtr_ctrl_ird = ntohs(rtr_msg->ctrl_ird); +		rtr_ctrl_ord = ntohs(rtr_msg->ctrl_ord); +		ird_size = rtr_ctrl_ird & IETF_NO_IRD_ORD; +		ord_size = rtr_ctrl_ord & IETF_NO_IRD_ORD; + +		if (!(rtr_ctrl_ird & IETF_PEER_TO_PEER)) { +			/* send reset */ +			return -EINVAL; +		} +		if (ird_size == IETF_NO_IRD_ORD || ord_size == IETF_NO_IRD_ORD) +			cm_node->mpav2_ird_ord = IETF_NO_IRD_ORD; + +		if (cm_node->mpav2_ird_ord != IETF_NO_IRD_ORD) { +			/* responder */ +			if (cm_node->state != NES_CM_STATE_MPAREQ_SENT) { +				/* we are still negotiating */ +				if (ord_size > NES_MAX_IRD) { +					cm_node->ird_size = NES_MAX_IRD; +				} else { +					cm_node->ird_size = ord_size; +					if (ord_size == 0 && +					(rtr_ctrl_ord & IETF_RDMA0_READ)) { +						cm_node->ird_size = 1; +						nes_debug(NES_DBG_CM, +						"%s: Remote peer doesn't support RDMA0_READ (ord=%u)\n", +							__func__, ord_size); +					} +				} +				if (ird_size > NES_MAX_ORD) +					cm_node->ord_size = NES_MAX_ORD; +				else +					cm_node->ord_size = ird_size; +			} else { /* initiator */ +				if (ord_size > NES_MAX_IRD) { +					nes_debug(NES_DBG_CM, +					"%s: Unable to support the requested (ord =%u)\n", +							__func__, ord_size); +					return -EINVAL; +				} +				cm_node->ird_size = ord_size; + +				if (ird_size > NES_MAX_ORD) { +					cm_node->ord_size = NES_MAX_ORD; +				} else { +					if (ird_size == 0 && +					(rtr_ctrl_ord & IETF_RDMA0_READ)) { +						nes_debug(NES_DBG_CM, +						"%s: Remote peer doesn't support RDMA0_READ (ird=%u)\n", +							__func__, ird_size); +						return -EINVAL; +					} else { +						cm_node->ord_size = ird_size; +					} +				} +			} +		} + +		if (rtr_ctrl_ord & IETF_RDMA0_READ) { +			cm_node->send_rdma0_op = SEND_RDMA_READ_ZERO; + +		} else if (rtr_ctrl_ord & IETF_RDMA0_WRITE) { +			cm_node->send_rdma0_op = SEND_RDMA_WRITE_ZERO; +		} else {        /* Not supported RDMA0 operation */ +			return -EINVAL; +		} +		break; +	} +	case IETF_MPA_V1: +	default: +		break; +	} +  	/* copy entire MPA frame to our cm_node's frame */ -	memcpy(cm_node->mpa_frame_buf, buffer + sizeof(struct ietf_mpa_frame), -			cm_node->mpa_frame_size); +	memcpy(cm_node->mpa_frame_buf, buffer + mpa_hdr_len, cm_node->mpa_frame_size);  	if (mpa_frame->flags & IETF_MPA_FLAGS_REJECT)  		*type = NES_MPA_REQUEST_REJECT; @@ -312,8 +433,8 @@ static int parse_mpa(struct nes_cm_node *cm_node, u8 *buffer, u32 *type,   * node info to build.   */  static void form_cm_frame(struct sk_buff *skb, -	struct nes_cm_node *cm_node, void *options, u32 optionsize, -	void *data, u32 datasize, u8 flags) +			  struct nes_cm_node *cm_node, void *options, u32 optionsize, +			  void *data, u32 datasize, u8 flags)  {  	struct tcphdr *tcph;  	struct iphdr *iph; @@ -322,14 +443,14 @@ static void form_cm_frame(struct sk_buff *skb,  	u16 packetsize = sizeof(*iph);  	packetsize += sizeof(*tcph); -	packetsize +=  optionsize + datasize; +	packetsize += optionsize + datasize; +	skb_trim(skb, 0);  	memset(skb->data, 0x00, ETH_HLEN + sizeof(*iph) + sizeof(*tcph)); -	skb->len = 0;  	buf = skb_put(skb, packetsize + ETH_HLEN); -	ethh = (struct ethhdr *) buf; +	ethh = (struct ethhdr *)buf;  	buf += ETH_HLEN;  	iph = (struct iphdr *)buf; @@ -337,10 +458,12 @@ static void form_cm_frame(struct sk_buff *skb,  	tcph = (struct tcphdr *)buf;  	skb_reset_mac_header(skb);  	skb_set_network_header(skb, ETH_HLEN); -	skb_set_transport_header(skb, ETH_HLEN+sizeof(*iph)); +	skb_set_transport_header(skb, ETH_HLEN + sizeof(*iph));  	buf += sizeof(*tcph);  	skb->ip_summed = CHECKSUM_PARTIAL; +	if (!(cm_node->netdev->features & NETIF_F_IP_CSUM)) +		skb->ip_summed = CHECKSUM_NONE;  	skb->protocol = htons(0x800);  	skb->data_len = 0;  	skb->mac_len = ETH_HLEN; @@ -350,34 +473,36 @@ static void form_cm_frame(struct sk_buff *skb,  	ethh->h_proto = htons(0x0800);  	iph->version = IPVERSION; -	iph->ihl = 5;		/* 5 * 4Byte words, IP headr len */ +	iph->ihl = 5;           /* 5 * 4Byte words, IP headr len */  	iph->tos = 0;  	iph->tot_len = htons(packetsize);  	iph->id = htons(++cm_node->tcp_cntxt.loc_id);  	iph->frag_off = htons(0x4000);  	iph->ttl = 0x40; -	iph->protocol = 0x06;	/* IPPROTO_TCP */ +	iph->protocol = 0x06;   /* IPPROTO_TCP */ -	iph->saddr = htonl(cm_node->loc_addr); -	iph->daddr = htonl(cm_node->rem_addr); +	iph->saddr = htonl(cm_node->mapped_loc_addr); +	iph->daddr = htonl(cm_node->mapped_rem_addr); -	tcph->source = htons(cm_node->loc_port); -	tcph->dest = htons(cm_node->rem_port); +	tcph->source = htons(cm_node->mapped_loc_port); +	tcph->dest = htons(cm_node->mapped_rem_port);  	tcph->seq = htonl(cm_node->tcp_cntxt.loc_seq_num);  	if (flags & SET_ACK) {  		cm_node->tcp_cntxt.loc_ack_num = cm_node->tcp_cntxt.rcv_nxt;  		tcph->ack_seq = htonl(cm_node->tcp_cntxt.loc_ack_num);  		tcph->ack = 1; -	} else +	} else {  		tcph->ack_seq = 0; +	}  	if (flags & SET_SYN) {  		cm_node->tcp_cntxt.loc_seq_num++;  		tcph->syn = 1; -	} else +	} else {  		cm_node->tcp_cntxt.loc_seq_num += datasize; +	}  	if (flags & SET_FIN) {  		cm_node->tcp_cntxt.loc_seq_num++; @@ -398,9 +523,101 @@ static void form_cm_frame(struct sk_buff *skb,  	skb_shinfo(skb)->nr_frags = 0;  	cm_packets_created++; +} + +/* + * nes_create_sockaddr - Record ip addr and tcp port in a sockaddr struct + */ +static void nes_create_sockaddr(__be32 ip_addr, __be16 port, +				struct sockaddr_storage *addr) +{ +	struct sockaddr_in *nes_sockaddr = (struct sockaddr_in *)addr; +	nes_sockaddr->sin_family = AF_INET; +	memcpy(&nes_sockaddr->sin_addr.s_addr, &ip_addr, sizeof(__be32)); +	nes_sockaddr->sin_port = port; +} + +/* + * nes_create_mapinfo - Create a mapinfo object in the port mapper data base + */ +static int nes_create_mapinfo(struct nes_cm_info *cm_info) +{ +	struct sockaddr_storage local_sockaddr; +	struct sockaddr_storage mapped_sockaddr; + +	nes_create_sockaddr(htonl(cm_info->loc_addr), htons(cm_info->loc_port), +				&local_sockaddr); +	nes_create_sockaddr(htonl(cm_info->mapped_loc_addr), +			htons(cm_info->mapped_loc_port), &mapped_sockaddr); + +	return iwpm_create_mapinfo(&local_sockaddr, +				&mapped_sockaddr, RDMA_NL_NES); +} + +/* + * nes_remove_mapinfo - Remove a mapinfo object from the port mapper data base + *                      and send a remove mapping op message to + *                      the userspace port mapper + */ +static int nes_remove_mapinfo(u32 loc_addr, u16 loc_port, +			u32 mapped_loc_addr, u16 mapped_loc_port) +{ +	struct sockaddr_storage local_sockaddr; +	struct sockaddr_storage mapped_sockaddr; +	nes_create_sockaddr(htonl(loc_addr), htons(loc_port), &local_sockaddr); +	nes_create_sockaddr(htonl(mapped_loc_addr), htons(mapped_loc_port), +				&mapped_sockaddr); + +	iwpm_remove_mapinfo(&local_sockaddr, &mapped_sockaddr); +	return iwpm_remove_mapping(&local_sockaddr, RDMA_NL_NES);  } +/* + * nes_form_pm_msg - Form a port mapper message with mapping info + */ +static void nes_form_pm_msg(struct nes_cm_info *cm_info, +				struct iwpm_sa_data *pm_msg) +{ +	nes_create_sockaddr(htonl(cm_info->loc_addr), htons(cm_info->loc_port), +				&pm_msg->loc_addr); +	nes_create_sockaddr(htonl(cm_info->rem_addr), htons(cm_info->rem_port), +				&pm_msg->rem_addr); +} + +/* + * nes_form_reg_msg - Form a port mapper message with dev info + */ +static void nes_form_reg_msg(struct nes_vnic *nesvnic, +			struct iwpm_dev_data *pm_msg) +{ +	memcpy(pm_msg->dev_name, nesvnic->nesibdev->ibdev.name, +				IWPM_DEVNAME_SIZE); +	memcpy(pm_msg->if_name, nesvnic->netdev->name, IWPM_IFNAME_SIZE); +} + +/* + * nes_record_pm_msg - Save the received mapping info + */ +static void nes_record_pm_msg(struct nes_cm_info *cm_info, +			struct iwpm_sa_data *pm_msg) +{ +	struct sockaddr_in *mapped_loc_addr = +			(struct sockaddr_in *)&pm_msg->mapped_loc_addr; +	struct sockaddr_in *mapped_rem_addr = +			(struct sockaddr_in *)&pm_msg->mapped_rem_addr; + +	if (mapped_loc_addr->sin_family == AF_INET) { +		cm_info->mapped_loc_addr = +			ntohl(mapped_loc_addr->sin_addr.s_addr); +		cm_info->mapped_loc_port = ntohs(mapped_loc_addr->sin_port); +	} +	if (mapped_rem_addr->sin_family == AF_INET) { +		cm_info->mapped_rem_addr = +			ntohl(mapped_rem_addr->sin_addr.s_addr); +		cm_info->mapped_rem_port = ntohs(mapped_rem_addr->sin_port); +	} +}  /**   * print_core - dump a cm core @@ -413,7 +630,7 @@ static void print_core(struct nes_cm_core *core)  		return;  	nes_debug(NES_DBG_CM, "---------------------------------------------\n"); -	nes_debug(NES_DBG_CM, "State         : %u \n",  core->state); +	nes_debug(NES_DBG_CM, "State         : %u \n", core->state);  	nes_debug(NES_DBG_CM, "Listen Nodes  : %u \n", atomic_read(&core->listen_node_cnt));  	nes_debug(NES_DBG_CM, "Active Nodes  : %u \n", atomic_read(&core->node_cnt)); @@ -423,6 +640,162 @@ static void print_core(struct nes_cm_core *core)  	nes_debug(NES_DBG_CM, "-------------- end core ---------------\n");  } +static void record_ird_ord(struct nes_cm_node *cm_node, +					u16 conn_ird, u16 conn_ord) +{ +	if (conn_ird > NES_MAX_IRD) +		conn_ird = NES_MAX_IRD; + +	if (conn_ord > NES_MAX_ORD) +		conn_ord = NES_MAX_ORD; + +	cm_node->ird_size = conn_ird; +	cm_node->ord_size = conn_ord; +} + +/** + * cm_build_mpa_frame - build a MPA V1 frame or MPA V2 frame + */ +static int cm_build_mpa_frame(struct nes_cm_node *cm_node, u8 **start_buff, +			      u16 *buff_len, u8 *pci_mem, u8 mpa_key) +{ +	int ret = 0; + +	*start_buff = (pci_mem) ? pci_mem : &cm_node->mpa_frame_buf[0]; + +	switch (cm_node->mpa_frame_rev) { +	case IETF_MPA_V1: +		*start_buff = (u8 *)*start_buff + sizeof(struct ietf_rtr_msg); +		*buff_len = sizeof(struct ietf_mpa_v1) + cm_node->mpa_frame_size; +		build_mpa_v1(cm_node, *start_buff, mpa_key); +		break; +	case IETF_MPA_V2: +		*buff_len = sizeof(struct ietf_mpa_v2) + cm_node->mpa_frame_size; +		build_mpa_v2(cm_node, *start_buff, mpa_key); +		break; +	default: +		ret = -EINVAL; +	} +	return ret; +} + +/** + * build_mpa_v2 - build a MPA V2 frame + */ +static void build_mpa_v2(struct nes_cm_node *cm_node, +			 void *start_addr, u8 mpa_key) +{ +	struct ietf_mpa_v2 *mpa_frame = (struct ietf_mpa_v2 *)start_addr; +	struct ietf_rtr_msg *rtr_msg = &mpa_frame->rtr_msg; +	u16 ctrl_ird; +	u16 ctrl_ord; + +	/* initialize the upper 5 bytes of the frame */ +	build_mpa_v1(cm_node, start_addr, mpa_key); +	mpa_frame->flags |= IETF_MPA_V2_FLAG; /* set a bit to indicate MPA V2 */ +	mpa_frame->priv_data_len += htons(IETF_RTR_MSG_SIZE); + +	/* initialize RTR msg */ +	if (cm_node->mpav2_ird_ord == IETF_NO_IRD_ORD) { +		ctrl_ird = IETF_NO_IRD_ORD; +		ctrl_ord = IETF_NO_IRD_ORD; +	} else { +		ctrl_ird = cm_node->ird_size & IETF_NO_IRD_ORD; +		ctrl_ord = cm_node->ord_size & IETF_NO_IRD_ORD; +	} +	ctrl_ird |= IETF_PEER_TO_PEER; +	ctrl_ird |= IETF_FLPDU_ZERO_LEN; + +	switch (mpa_key) { +	case MPA_KEY_REQUEST: +		ctrl_ord |= IETF_RDMA0_WRITE; +		ctrl_ord |= IETF_RDMA0_READ; +		break; +	case MPA_KEY_REPLY: +		switch (cm_node->send_rdma0_op) { +		case SEND_RDMA_WRITE_ZERO: +			ctrl_ord |= IETF_RDMA0_WRITE; +			break; +		case SEND_RDMA_READ_ZERO: +			ctrl_ord |= IETF_RDMA0_READ; +			break; +		} +	} +	rtr_msg->ctrl_ird = htons(ctrl_ird); +	rtr_msg->ctrl_ord = htons(ctrl_ord); +} + +/** + * build_mpa_v1 - build a MPA V1 frame + */ +static void build_mpa_v1(struct nes_cm_node *cm_node, void *start_addr, u8 mpa_key) +{ +	struct ietf_mpa_v1 *mpa_frame = (struct ietf_mpa_v1 *)start_addr; + +	switch (mpa_key) { +	case MPA_KEY_REQUEST: +		memcpy(mpa_frame->key, IEFT_MPA_KEY_REQ, IETF_MPA_KEY_SIZE); +		break; +	case MPA_KEY_REPLY: +		memcpy(mpa_frame->key, IEFT_MPA_KEY_REP, IETF_MPA_KEY_SIZE); +		break; +	} +	mpa_frame->flags = IETF_MPA_FLAGS_CRC; +	mpa_frame->rev = cm_node->mpa_frame_rev; +	mpa_frame->priv_data_len = htons(cm_node->mpa_frame_size); +} + +static void build_rdma0_msg(struct nes_cm_node *cm_node, struct nes_qp **nesqp_addr) +{ +	u64 u64temp; +	struct nes_qp *nesqp = *nesqp_addr; +	struct nes_hw_qp_wqe *wqe = &nesqp->hwqp.sq_vbase[0]; + +	u64temp = (unsigned long)nesqp->nesuqp_addr; +	u64temp |= NES_SW_CONTEXT_ALIGN >> 1; +	set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX, u64temp); + +	wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_LOW_IDX] = 0; +	wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_HIGH_IDX] = 0; + +	switch (cm_node->send_rdma0_op) { +	case SEND_RDMA_WRITE_ZERO: +		nes_debug(NES_DBG_CM, "Sending first write.\n"); +		wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] = +			cpu_to_le32(NES_IWARP_SQ_OP_RDMAW); +		wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] = 0; +		wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] = 0; +		wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 0; +		break; + +	case SEND_RDMA_READ_ZERO: +	default: +		if (cm_node->send_rdma0_op != SEND_RDMA_READ_ZERO) +			WARN(1, "Unsupported RDMA0 len operation=%u\n", +			     cm_node->send_rdma0_op); +		nes_debug(NES_DBG_CM, "Sending first rdma operation.\n"); +		wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] = +			cpu_to_le32(NES_IWARP_SQ_OP_RDMAR); +		wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_TO_LOW_IDX] = 1; +		wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_TO_HIGH_IDX] = 0; +		wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_LENGTH_IDX] = 0; +		wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_STAG_IDX] = 1; +		wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 1; +		break; +	} + +	if (nesqp->sq_kmapped) { +		nesqp->sq_kmapped = 0; +		kunmap(nesqp->page); +	} + +	/*use the reserved spot on the WQ for the extra first WQE*/ +	nesqp->nesqp_context->ird_ord_sizes &= cpu_to_le32(~(NES_QPCONTEXT_ORDIRD_LSMM_PRESENT | +							     NES_QPCONTEXT_ORDIRD_WRPDU | +							     NES_QPCONTEXT_ORDIRD_ALSMM)); +	nesqp->skip_lsmm = 1; +	nesqp->hwqp.sq_tail = 0; +}  /**   * schedule_nes_timer @@ -430,14 +803,13 @@ static void print_core(struct nes_cm_core *core)   *			rem_ref_cm_node(cm_core, cm_node);add_ref_cm_node(cm_node);   */  int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb, -		enum nes_timer_type type, int send_retrans, -		int close_when_complete) +		       enum nes_timer_type type, int send_retrans, +		       int close_when_complete)  { -	unsigned long  flags; +	unsigned long flags;  	struct nes_cm_core *cm_core = cm_node->cm_core;  	struct nes_timer_entry *new_send;  	int ret = 0; -	u32 was_timer_set;  	new_send = kzalloc(sizeof(*new_send), GFP_ATOMIC);  	if (!new_send) @@ -454,7 +826,7 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb,  	new_send->close_when_complete = close_when_complete;  	if (type == NES_TIMER_TYPE_CLOSE) { -		new_send->timetosend += (HZ/10); +		new_send->timetosend += (HZ / 10);  		if (cm_node->recv_entry) {  			kfree(new_send);  			WARN_ON(1); @@ -475,7 +847,7 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb,  		ret = nes_nic_cm_xmit(new_send->skb, cm_node->netdev);  		if (ret != NETDEV_TX_OK) {  			nes_debug(NES_DBG_CM, "Error sending packet %p " -				"(jiffies = %lu)\n", new_send, jiffies); +				  "(jiffies = %lu)\n", new_send, jiffies);  			new_send->timetosend = jiffies;  			ret = NETDEV_TX_OK;  		} else { @@ -489,12 +861,8 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb,  		}  	} -	was_timer_set = timer_pending(&cm_core->tcp_timer); - -	if (!was_timer_set) { -		cm_core->tcp_timer.expires = new_send->timetosend; -		add_timer(&cm_core->tcp_timer); -	} +	if (!timer_pending(&cm_core->tcp_timer)) +		mod_timer(&cm_core->tcp_timer, new_send->timetosend);  	return ret;  } @@ -504,6 +872,7 @@ static void nes_retrans_expired(struct nes_cm_node *cm_node)  	struct iw_cm_id *cm_id = cm_node->cm_id;  	enum nes_cm_node_state state = cm_node->state;  	cm_node->state = NES_CM_STATE_CLOSED; +  	switch (state) {  	case NES_CM_STATE_SYN_RCVD:  	case NES_CM_STATE_CLOSING: @@ -536,10 +905,10 @@ static void handle_recv_entry(struct nes_cm_node *cm_node, u32 rem_node)  		spin_lock_irqsave(&nesqp->lock, qplockflags);  		if (nesqp->cm_id) {  			nes_debug(NES_DBG_CM, "QP%u: cm_id = %p, " -				"refcount = %d: HIT A " -				"NES_TIMER_TYPE_CLOSE with something " -				"to do!!!\n", nesqp->hwqp.qp_id, cm_id, -				atomic_read(&nesqp->refcount)); +				  "refcount = %d: HIT A " +				  "NES_TIMER_TYPE_CLOSE with something " +				  "to do!!!\n", nesqp->hwqp.qp_id, cm_id, +				  atomic_read(&nesqp->refcount));  			nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED;  			nesqp->last_aeq = NES_AEQE_AEID_RESET_SENT;  			nesqp->ibqp_state = IB_QPS_ERR; @@ -548,10 +917,10 @@ static void handle_recv_entry(struct nes_cm_node *cm_node, u32 rem_node)  		} else {  			spin_unlock_irqrestore(&nesqp->lock, qplockflags);  			nes_debug(NES_DBG_CM, "QP%u: cm_id = %p, " -				"refcount = %d: HIT A " -				"NES_TIMER_TYPE_CLOSE with nothing " -				"to do!!!\n", nesqp->hwqp.qp_id, cm_id, -				atomic_read(&nesqp->refcount)); +				  "refcount = %d: HIT A " +				  "NES_TIMER_TYPE_CLOSE with nothing " +				  "to do!!!\n", nesqp->hwqp.qp_id, cm_id, +				  atomic_read(&nesqp->refcount));  		}  	} else if (rem_node) {  		/* TIME_WAIT state */ @@ -580,11 +949,12 @@ static void nes_cm_timer_tick(unsigned long pass)  	int ret = NETDEV_TX_OK;  	struct list_head timer_list; +  	INIT_LIST_HEAD(&timer_list);  	spin_lock_irqsave(&cm_core->ht_lock, flags);  	list_for_each_safe(list_node, list_core_temp, -				&cm_core->connected_nodes) { +			   &cm_core->connected_nodes) {  		cm_node = container_of(list_node, struct nes_cm_node, list);  		if ((cm_node->recv_entry) || (cm_node->send_entry)) {  			add_ref_cm_node(cm_node); @@ -595,18 +965,19 @@ static void nes_cm_timer_tick(unsigned long pass)  	list_for_each_safe(list_node, list_core_temp, &timer_list) {  		cm_node = container_of(list_node, struct nes_cm_node, -					timer_entry); +				       timer_entry);  		recv_entry = cm_node->recv_entry;  		if (recv_entry) {  			if (time_after(recv_entry->timetosend, jiffies)) {  				if (nexttimeout > recv_entry->timetosend || -						!settimer) { +				    !settimer) {  					nexttimeout = recv_entry->timetosend;  					settimer = 1;  				} -			} else +			} else {  				handle_recv_entry(cm_node, 1); +			}  		}  		spin_lock_irqsave(&cm_node->retrans_list_lock, flags); @@ -617,8 +988,8 @@ static void nes_cm_timer_tick(unsigned long pass)  			if (time_after(send_entry->timetosend, jiffies)) {  				if (cm_node->state != NES_CM_STATE_TSA) {  					if ((nexttimeout > -						send_entry->timetosend) || -						!settimer) { +					     send_entry->timetosend) || +					    !settimer) {  						nexttimeout =  							send_entry->timetosend;  						settimer = 1; @@ -630,13 +1001,13 @@ static void nes_cm_timer_tick(unsigned long pass)  			}  			if ((cm_node->state == NES_CM_STATE_TSA) || -				(cm_node->state == NES_CM_STATE_CLOSED)) { +			    (cm_node->state == NES_CM_STATE_CLOSED)) {  				free_retrans_entry(cm_node);  				break;  			}  			if (!send_entry->retranscount || -				!send_entry->retrycount) { +			    !send_entry->retrycount) {  				cm_packets_dropped++;  				free_retrans_entry(cm_node); @@ -645,28 +1016,28 @@ static void nes_cm_timer_tick(unsigned long pass)  				nes_retrans_expired(cm_node);  				cm_node->state = NES_CM_STATE_CLOSED;  				spin_lock_irqsave(&cm_node->retrans_list_lock, -					flags); +						  flags);  				break;  			}  			atomic_inc(&send_entry->skb->users);  			cm_packets_retrans++;  			nes_debug(NES_DBG_CM, "Retransmitting send_entry %p " -				"for node %p, jiffies = %lu, time to send = " -				"%lu, retranscount = %u, send_entry->seq_num = " -				"0x%08X, cm_node->tcp_cntxt.rem_ack_num = " -				"0x%08X\n", send_entry, cm_node, jiffies, -				send_entry->timetosend, -				send_entry->retranscount, -				send_entry->seq_num, -				cm_node->tcp_cntxt.rem_ack_num); +				  "for node %p, jiffies = %lu, time to send = " +				  "%lu, retranscount = %u, send_entry->seq_num = " +				  "0x%08X, cm_node->tcp_cntxt.rem_ack_num = " +				  "0x%08X\n", send_entry, cm_node, jiffies, +				  send_entry->timetosend, +				  send_entry->retranscount, +				  send_entry->seq_num, +				  cm_node->tcp_cntxt.rem_ack_num);  			spin_unlock_irqrestore(&cm_node->retrans_list_lock, -				flags); +					       flags);  			ret = nes_nic_cm_xmit(send_entry->skb, cm_node->netdev);  			spin_lock_irqsave(&cm_node->retrans_list_lock, flags);  			if (ret != NETDEV_TX_OK) {  				nes_debug(NES_DBG_CM, "rexmit failed for " -					"node=%p\n", cm_node); +					  "node=%p\n", cm_node);  				cm_packets_bounced++;  				send_entry->retrycount--;  				nexttimeout = jiffies + NES_SHORT_TIME; @@ -676,18 +1047,18 @@ static void nes_cm_timer_tick(unsigned long pass)  				cm_packets_sent++;  			}  			nes_debug(NES_DBG_CM, "Packet Sent: retrans count = " -				"%u, retry count = %u.\n", -				send_entry->retranscount, -				send_entry->retrycount); +				  "%u, retry count = %u.\n", +				  send_entry->retranscount, +				  send_entry->retrycount);  			if (send_entry->send_retrans) {  				send_entry->retranscount--;  				timetosend = (NES_RETRY_TIMEOUT << -					(NES_DEFAULT_RETRANS - send_entry->retranscount)); +					      (NES_DEFAULT_RETRANS - send_entry->retranscount));  				send_entry->timetosend = jiffies + -					min(timetosend, NES_MAX_TIMEOUT); +							 min(timetosend, NES_MAX_TIMEOUT);  				if (nexttimeout > send_entry->timetosend || -					!settimer) { +				    !settimer) {  					nexttimeout = send_entry->timetosend;  					settimer = 1;  				} @@ -696,11 +1067,11 @@ static void nes_cm_timer_tick(unsigned long pass)  				close_when_complete =  					send_entry->close_when_complete;  				nes_debug(NES_DBG_CM, "cm_node=%p state=%d\n", -					cm_node, cm_node->state); +					  cm_node, cm_node->state);  				free_retrans_entry(cm_node);  				if (close_when_complete)  					rem_ref_cm_node(cm_node->cm_core, -						cm_node); +							cm_node);  			}  		} while (0); @@ -709,10 +1080,8 @@ static void nes_cm_timer_tick(unsigned long pass)  	}  	if (settimer) { -		if (!timer_pending(&cm_core->tcp_timer)) { -			cm_core->tcp_timer.expires  = nexttimeout; -			add_timer(&cm_core->tcp_timer); -		} +		if (!timer_pending(&cm_core->tcp_timer)) +			mod_timer(&cm_core->tcp_timer, nexttimeout);  	}  } @@ -721,13 +1090,13 @@ static void nes_cm_timer_tick(unsigned long pass)   * send_syn   */  static int send_syn(struct nes_cm_node *cm_node, u32 sendack, -	struct sk_buff *skb) +		    struct sk_buff *skb)  {  	int ret;  	int flags = SET_SYN;  	char optionsbuffer[sizeof(struct option_mss) + -		sizeof(struct option_windowscale) + sizeof(struct option_base) + -		TCP_OPTIONS_PADDING]; +			   sizeof(struct option_windowscale) + sizeof(struct option_base) + +			   TCP_OPTIONS_PADDING];  	int optionssize = 0;  	/* Sending MSS option */ @@ -854,7 +1223,7 @@ static int send_fin(struct nes_cm_node *cm_node, struct sk_buff *skb)   * find_node - find a cm node that matches the reference cm node   */  static struct nes_cm_node *find_node(struct nes_cm_core *cm_core, -		u16 rem_port, nes_addr_t rem_addr, u16 loc_port, nes_addr_t loc_addr) +				     u16 rem_port, nes_addr_t rem_addr, u16 loc_port, nes_addr_t loc_addr)  {  	unsigned long flags;  	struct list_head *hte; @@ -868,12 +1237,15 @@ static struct nes_cm_node *find_node(struct nes_cm_core *cm_core,  	list_for_each_entry(cm_node, hte, list) {  		/* compare quad, return node handle if a match */  		nes_debug(NES_DBG_CM, "finding node %x:%x =? %x:%x ^ %x:%x =? %x:%x\n", -				cm_node->loc_addr, cm_node->loc_port, -				loc_addr, loc_port, -				cm_node->rem_addr, cm_node->rem_port, -				rem_addr, rem_port); -		if ((cm_node->loc_addr == loc_addr) && (cm_node->loc_port == loc_port) && -				(cm_node->rem_addr == rem_addr) && (cm_node->rem_port == rem_port)) { +			  cm_node->loc_addr, cm_node->loc_port, +			  loc_addr, loc_port, +			  cm_node->rem_addr, cm_node->rem_port, +			  rem_addr, rem_port); +		if ((cm_node->mapped_loc_addr == loc_addr) && +			(cm_node->mapped_loc_port == loc_port) && +			(cm_node->mapped_rem_addr == rem_addr) && +			(cm_node->mapped_rem_port == rem_port)) { +  			add_ref_cm_node(cm_node);  			spin_unlock_irqrestore(&cm_core->ht_lock, flags);  			return cm_node; @@ -890,19 +1262,29 @@ static struct nes_cm_node *find_node(struct nes_cm_core *cm_core,   * find_listener - find a cm node listening on this addr-port pair   */  static struct nes_cm_listener *find_listener(struct nes_cm_core *cm_core, -		nes_addr_t dst_addr, u16 dst_port, enum nes_cm_listener_state listener_state) +					nes_addr_t dst_addr, u16 dst_port, +					enum nes_cm_listener_state listener_state, int local)  {  	unsigned long flags;  	struct nes_cm_listener *listen_node; +	nes_addr_t listen_addr; +	u16 listen_port;  	/* walk list and find cm_node associated with this session ID */  	spin_lock_irqsave(&cm_core->listen_list_lock, flags);  	list_for_each_entry(listen_node, &cm_core->listen_list.list, list) { +		if (local) { +			listen_addr = listen_node->loc_addr; +			listen_port = listen_node->loc_port; +		} else { +			listen_addr = listen_node->mapped_loc_addr; +			listen_port = listen_node->mapped_loc_port; +		}  		/* compare node pair, return node handle if a match */ -		if (((listen_node->loc_addr == dst_addr) || -				listen_node->loc_addr == 0x00000000) && -				(listen_node->loc_port == dst_port) && -				(listener_state & listen_node->listener_state)) { +		if (((listen_addr == dst_addr) || +		     listen_addr == 0x00000000) && +		    (listen_port == dst_port) && +		    (listener_state & listen_node->listener_state)) {  			atomic_inc(&listen_node->ref_count);  			spin_unlock_irqrestore(&cm_core->listen_list_lock, flags);  			return listen_node; @@ -914,7 +1296,6 @@ static struct nes_cm_listener *find_listener(struct nes_cm_core *cm_core,  	return NULL;  } -  /**   * add_hte_node - add a cm node to the hash table   */ @@ -927,7 +1308,7 @@ static int add_hte_node(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node  		return -EINVAL;  	nes_debug(NES_DBG_CM, "Adding Node %p to Active Connection HT\n", -		cm_node); +		  cm_node);  	spin_lock_irqsave(&cm_core->ht_lock, flags); @@ -946,7 +1327,7 @@ static int add_hte_node(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node   * mini_cm_dec_refcnt_listen   */  static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core, -	struct nes_cm_listener *listener, int free_hanging_nodes) +				     struct nes_cm_listener *listener, int free_hanging_nodes)  {  	int ret = -EINVAL;  	int err = 0; @@ -957,8 +1338,8 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,  	struct list_head reset_list;  	nes_debug(NES_DBG_CM, "attempting listener= %p free_nodes= %d, " -		"refcnt=%d\n", listener, free_hanging_nodes, -		atomic_read(&listener->ref_count)); +		  "refcnt=%d\n", listener, free_hanging_nodes, +		  atomic_read(&listener->ref_count));  	/* free non-accelerated child nodes for this listener */  	INIT_LIST_HEAD(&reset_list);  	if (free_hanging_nodes) { @@ -966,7 +1347,7 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,  		list_for_each_safe(list_pos, list_temp,  				   &g_cm_core->connected_nodes) {  			cm_node = container_of(list_pos, struct nes_cm_node, -				list); +					       list);  			if ((cm_node->listener == listener) &&  			    (!cm_node->accelerated)) {  				add_ref_cm_node(cm_node); @@ -978,7 +1359,7 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,  	list_for_each_safe(list_pos, list_temp, &reset_list) {  		cm_node = container_of(list_pos, struct nes_cm_node, -				reset_entry); +				       reset_entry);  		{  			struct nes_cm_node *loopback = cm_node->loopbackpartner;  			enum nes_cm_node_state old_state; @@ -990,7 +1371,7 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,  					err = send_reset(cm_node, NULL);  					if (err) {  						cm_node->state = -							 NES_CM_STATE_CLOSED; +							NES_CM_STATE_CLOSED;  						WARN_ON(1);  					} else {  						old_state = cm_node->state; @@ -1036,8 +1417,18 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,  		spin_unlock_irqrestore(&cm_core->listen_list_lock, flags);  		if (listener->nesvnic) { -			nes_manage_apbvt(listener->nesvnic, listener->loc_port, -					PCI_FUNC(listener->nesvnic->nesdev->pcidev->devfn), NES_MANAGE_APBVT_DEL); +			nes_manage_apbvt(listener->nesvnic, +				listener->mapped_loc_port, +				PCI_FUNC(listener->nesvnic->nesdev->pcidev->devfn), +				NES_MANAGE_APBVT_DEL); + +			nes_remove_mapinfo(listener->loc_addr, +					listener->loc_port, +					listener->mapped_loc_addr, +					listener->mapped_loc_port); +			nes_debug(NES_DBG_NLMSG, +					"Delete APBVT mapped_loc_port = %04X\n", +					listener->mapped_loc_port);  		}  		nes_debug(NES_DBG_CM, "destroying listener (%p)\n", listener); @@ -1052,8 +1443,8 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,  	if (listener) {  		if (atomic_read(&listener->pend_accepts_cnt) > 0)  			nes_debug(NES_DBG_CM, "destroying listener (%p)" -					" with non-zero pending accepts=%u\n", -					listener, atomic_read(&listener->pend_accepts_cnt)); +				  " with non-zero pending accepts=%u\n", +				  listener, atomic_read(&listener->pend_accepts_cnt));  	}  	return ret; @@ -1064,7 +1455,7 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,   * mini_cm_del_listen   */  static int mini_cm_del_listen(struct nes_cm_core *cm_core, -		struct nes_cm_listener *listener) +			      struct nes_cm_listener *listener)  {  	listener->listener_state = NES_CM_LISTENER_PASSIVE_STATE;  	listener->cm_id = NULL; /* going to be destroyed pretty soon */ @@ -1076,9 +1467,8 @@ static int mini_cm_del_listen(struct nes_cm_core *cm_core,   * mini_cm_accelerated   */  static inline int mini_cm_accelerated(struct nes_cm_core *cm_core, -		struct nes_cm_node *cm_node) +				      struct nes_cm_node *cm_node)  { -	u32 was_timer_set;  	cm_node->accelerated = 1;  	if (cm_node->accept_pend) { @@ -1088,11 +1478,8 @@ static inline int mini_cm_accelerated(struct nes_cm_core *cm_core,  		BUG_ON(atomic_read(&cm_node->listener->pend_accepts_cnt) < 0);  	} -	was_timer_set = timer_pending(&cm_core->tcp_timer); -	if (!was_timer_set) { -		cm_core->tcp_timer.expires = jiffies + NES_SHORT_TIME; -		add_timer(&cm_core->tcp_timer); -	} +	if (!timer_pending(&cm_core->tcp_timer)) +		mod_timer(&cm_core->tcp_timer, (jiffies + NES_SHORT_TIME));  	return 0;  } @@ -1104,20 +1491,26 @@ static inline int mini_cm_accelerated(struct nes_cm_core *cm_core,  static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpindex)  {  	struct rtable *rt; -	struct flowi fl;  	struct neighbour *neigh;  	int rc = arpindex; +	struct net_device *netdev;  	struct nes_adapter *nesadapter = nesvnic->nesdev->nesadapter; -	memset(&fl, 0, sizeof fl); -	fl.nl_u.ip4_u.daddr = htonl(dst_ip); -	if (ip_route_output_key(&init_net, &rt, &fl)) { +	rt = ip_route_output(&init_net, htonl(dst_ip), 0, 0, 0); +	if (IS_ERR(rt)) {  		printk(KERN_ERR "%s: ip_route_output_key failed for 0x%08X\n", -				__func__, dst_ip); +		       __func__, dst_ip);  		return rc;  	} -	neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, nesvnic->netdev); +	if (netif_is_bond_slave(nesvnic->netdev)) +		netdev = netdev_master_upper_dev_get(nesvnic->netdev); +	else +		netdev = nesvnic->netdev; + +	neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, netdev); + +	rcu_read_lock();  	if (neigh) {  		if (neigh->nud_state & NUD_VALID) {  			nes_debug(NES_DBG_CM, "Neighbor MAC address for 0x%08X" @@ -1125,29 +1518,29 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi  				  neigh->ha, ntohl(rt->rt_gateway));  			if (arpindex >= 0) { -				if (!memcmp(nesadapter->arp_table[arpindex].mac_addr, -							neigh->ha, ETH_ALEN)){ +				if (ether_addr_equal(nesadapter->arp_table[arpindex].mac_addr, neigh->ha)) {  					/* Mac address same as in nes_arp_table */ -					neigh_release(neigh); -					ip_rt_put(rt); -					return rc; +					goto out;  				}  				nes_manage_arp_cache(nesvnic->netdev, -						nesadapter->arp_table[arpindex].mac_addr, -						dst_ip, NES_ARP_DELETE); +						     nesadapter->arp_table[arpindex].mac_addr, +						     dst_ip, NES_ARP_DELETE);  			}  			nes_manage_arp_cache(nesvnic->netdev, neigh->ha,  					     dst_ip, NES_ARP_ADD);  			rc = nes_arp_table(nesvnic->nesdev, dst_ip, NULL,  					   NES_ARP_RESOLVE); +		} else { +			neigh_event_send(neigh, NULL);  		} -		neigh_release(neigh);  	} +out: +	rcu_read_unlock(); -	if ((neigh == NULL) || (!(neigh->nud_state & NUD_VALID))) -		neigh_event_send(rt->dst.neighbour, NULL); +	if (neigh) +		neigh_release(neigh);  	ip_rt_put(rt);  	return rc; @@ -1157,8 +1550,8 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi   * make_cm_node - create a new instance of a cm node   */  static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core, -		struct nes_vnic *nesvnic, struct nes_cm_info *cm_info, -		struct nes_cm_listener *listener) +					struct nes_vnic *nesvnic, struct nes_cm_info *cm_info, +					struct nes_cm_listener *listener)  {  	struct nes_cm_node *cm_node;  	struct timespec ts; @@ -1177,7 +1570,18 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,  	cm_node->rem_addr = cm_info->rem_addr;  	cm_node->loc_port = cm_info->loc_port;  	cm_node->rem_port = cm_info->rem_port; -	cm_node->send_write0 = send_first; + +	cm_node->mapped_loc_addr = cm_info->mapped_loc_addr; +	cm_node->mapped_rem_addr = cm_info->mapped_rem_addr; +	cm_node->mapped_loc_port = cm_info->mapped_loc_port; +	cm_node->mapped_rem_port = cm_info->mapped_rem_port; + +	cm_node->mpa_frame_rev = mpa_version; +	cm_node->send_rdma0_op = SEND_RDMA_READ_ZERO; +	cm_node->mpav2_ird_ord = 0; +	cm_node->ird_size = 0; +	cm_node->ord_size = 0; +  	nes_debug(NES_DBG_CM, "Make node addresses : loc = %pI4:%x, rem = %pI4:%x\n",  		  &cm_node->loc_addr, cm_node->loc_port,  		  &cm_node->rem_addr, cm_node->rem_port); @@ -1187,7 +1591,7 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,  	memcpy(cm_node->loc_mac, nesvnic->netdev->dev_addr, ETH_ALEN);  	nes_debug(NES_DBG_CM, "listener=%p, cm_id=%p\n", cm_node->listener, -			cm_node->cm_id); +		  cm_node->cm_id);  	spin_lock_init(&cm_node->retrans_list_lock); @@ -1198,11 +1602,11 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,  	cm_node->tcp_cntxt.loc_id = NES_CM_DEF_LOCAL_ID;  	cm_node->tcp_cntxt.rcv_wscale = NES_CM_DEFAULT_RCV_WND_SCALE;  	cm_node->tcp_cntxt.rcv_wnd = NES_CM_DEFAULT_RCV_WND_SCALED >> -			NES_CM_DEFAULT_RCV_WND_SCALE; +				     NES_CM_DEFAULT_RCV_WND_SCALE;  	ts = current_kernel_time();  	cm_node->tcp_cntxt.loc_seq_num = htonl(ts.tv_nsec);  	cm_node->tcp_cntxt.mss = nesvnic->max_frame_size - sizeof(struct iphdr) - -			sizeof(struct tcphdr) - ETH_HLEN - VLAN_HLEN; +				 sizeof(struct tcphdr) - ETH_HLEN - VLAN_HLEN;  	cm_node->tcp_cntxt.rcv_nxt = 0;  	/* get a unique session ID , add thread_id to an upcounter to handle race */  	atomic_inc(&cm_core->node_cnt); @@ -1218,13 +1622,10 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,  	cm_node->loopbackpartner = NULL;  	/* get the mac addr for the remote node */ -	if (ipv4_is_loopback(htonl(cm_node->rem_addr))) -		arpindex = nes_arp_table(nesdev, ntohl(nesvnic->local_ipaddr), NULL, NES_ARP_RESOLVE); -	else { -		oldarpindex = nes_arp_table(nesdev, cm_node->rem_addr, NULL, NES_ARP_RESOLVE); -		arpindex = nes_addr_resolve_neigh(nesvnic, cm_info->rem_addr, oldarpindex); - -	} +	oldarpindex = nes_arp_table(nesdev, cm_node->mapped_rem_addr, +				NULL, NES_ARP_RESOLVE); +	arpindex = nes_addr_resolve_neigh(nesvnic, +				cm_node->mapped_rem_addr, oldarpindex);  	if (arpindex < 0) {  		kfree(cm_node);  		return NULL; @@ -1256,7 +1657,7 @@ static int add_ref_cm_node(struct nes_cm_node *cm_node)   * rem_ref_cm_node - destroy an instance of a cm node   */  static int rem_ref_cm_node(struct nes_cm_core *cm_core, -	struct nes_cm_node *cm_node) +			   struct nes_cm_node *cm_node)  {  	unsigned long flags;  	struct nes_qp *nesqp; @@ -1286,11 +1687,14 @@ static int rem_ref_cm_node(struct nes_cm_core *cm_core,  		mini_cm_dec_refcnt_listen(cm_core, cm_node->listener, 0);  	} else {  		if (cm_node->apbvt_set && cm_node->nesvnic) { -			nes_manage_apbvt(cm_node->nesvnic, cm_node->loc_port, -				PCI_FUNC( -				cm_node->nesvnic->nesdev->pcidev->devfn), -				NES_MANAGE_APBVT_DEL); +			nes_manage_apbvt(cm_node->nesvnic, cm_node->mapped_loc_port, +					 PCI_FUNC(cm_node->nesvnic->nesdev->pcidev->devfn), +					 NES_MANAGE_APBVT_DEL);  		} +		nes_debug(NES_DBG_NLMSG, "Delete APBVT mapped_loc_port = %04X\n", +					cm_node->mapped_loc_port); +		nes_remove_mapinfo(cm_node->loc_addr, cm_node->loc_port, +			cm_node->mapped_loc_addr, cm_node->mapped_loc_port);  	}  	atomic_dec(&cm_core->node_cnt); @@ -1310,7 +1714,7 @@ static int rem_ref_cm_node(struct nes_cm_core *cm_core,   * process_options   */  static int process_options(struct nes_cm_node *cm_node, u8 *optionsloc, -	u32 optionsize, u32 syn_packet) +			   u32 optionsize, u32 syn_packet)  {  	u32 tmp;  	u32 offset = 0; @@ -1328,15 +1732,15 @@ static int process_options(struct nes_cm_node *cm_node, u8 *optionsloc,  			continue;  		case OPTION_NUMBER_MSS:  			nes_debug(NES_DBG_CM, "%s: MSS Length: %d Offset: %d " -				"Size: %d\n", __func__, -				all_options->as_mss.length, offset, optionsize); +				  "Size: %d\n", __func__, +				  all_options->as_mss.length, offset, optionsize);  			got_mss_option = 1;  			if (all_options->as_mss.length != 4) {  				return 1;  			} else {  				tmp = ntohs(all_options->as_mss.mss);  				if (tmp > 0 && tmp < -					cm_node->tcp_cntxt.mss) +				    cm_node->tcp_cntxt.mss)  					cm_node->tcp_cntxt.mss = tmp;  			}  			break; @@ -1344,12 +1748,9 @@ static int process_options(struct nes_cm_node *cm_node, u8 *optionsloc,  			cm_node->tcp_cntxt.snd_wscale =  				all_options->as_windowscale.shiftcount;  			break; -		case OPTION_NUMBER_WRITE0: -			cm_node->send_write0 = 1; -			break;  		default:  			nes_debug(NES_DBG_CM, "TCP Option not understood: %x\n", -				all_options->as_base.optionnum); +				  all_options->as_base.optionnum);  			break;  		}  		offset += all_options->as_base.length; @@ -1368,8 +1769,8 @@ static void drop_packet(struct sk_buff *skb)  static void handle_fin_pkt(struct nes_cm_node *cm_node)  {  	nes_debug(NES_DBG_CM, "Received FIN, cm_node = %p, state = %u. " -		"refcnt=%d\n", cm_node, cm_node->state, -		atomic_read(&cm_node->ref_count)); +		  "refcnt=%d\n", cm_node, cm_node->state, +		  atomic_read(&cm_node->ref_count));  	switch (cm_node->state) {  	case NES_CM_STATE_SYN_RCVD:  	case NES_CM_STATE_SYN_SENT: @@ -1393,7 +1794,7 @@ static void handle_fin_pkt(struct nes_cm_node *cm_node)  		cleanup_retrans_entry(cm_node);  		cm_node->state = NES_CM_STATE_CLOSING;  		send_ack(cm_node, NULL); -		/* Wait for ACK as this is simultanous close.. +		/* Wait for ACK as this is simultaneous close..  		* After we receive ACK, do not send anything..  		* Just rm the node.. Done.. */  		break; @@ -1435,7 +1836,20 @@ static void handle_rst_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,  		nes_debug(NES_DBG_CM, "%s[%u] create abort for cm_node=%p "  			"listener=%p state=%d\n", __func__, __LINE__, cm_node,  			cm_node->listener, cm_node->state); -		active_open_err(cm_node, skb, reset); +		switch (cm_node->mpa_frame_rev) { +		case IETF_MPA_V2: +			cm_node->mpa_frame_rev = IETF_MPA_V1; +			/* send a syn and goto syn sent state */ +			cm_node->state = NES_CM_STATE_SYN_SENT; +			if (send_syn(cm_node, 0, NULL)) { +				active_open_err(cm_node, skb, reset); +			} +			break; +		case IETF_MPA_V1: +		default: +			active_open_err(cm_node, skb, reset); +			break; +		}  		break;  	case NES_CM_STATE_MPAREQ_RCVD:  		atomic_inc(&cm_node->passive_state); @@ -1471,21 +1885,21 @@ static void handle_rst_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,  static void handle_rcv_mpa(struct nes_cm_node *cm_node, struct sk_buff *skb)  { - -	int	ret = 0; +	int ret = 0;  	int datasize = skb->len;  	u8 *dataloc = skb->data;  	enum nes_cm_event_type type = NES_CM_EVENT_UNKNOWN; -	u32     res_type; +	u32 res_type; +  	ret = parse_mpa(cm_node, dataloc, &res_type, datasize);  	if (ret) {  		nes_debug(NES_DBG_CM, "didn't like MPA Request\n");  		if (cm_node->state == NES_CM_STATE_MPAREQ_SENT) {  			nes_debug(NES_DBG_CM, "%s[%u] create abort for " -				"cm_node=%p listener=%p state=%d\n", __func__, -				__LINE__, cm_node, cm_node->listener, -				cm_node->state); +				  "cm_node=%p listener=%p state=%d\n", __func__, +				  __LINE__, cm_node, cm_node->listener, +				  cm_node->state);  			active_open_err(cm_node, skb, 1);  		} else {  			passive_open_err(cm_node, skb, 1); @@ -1495,16 +1909,15 @@ static void handle_rcv_mpa(struct nes_cm_node *cm_node, struct sk_buff *skb)  	switch (cm_node->state) {  	case NES_CM_STATE_ESTABLISHED: -		if (res_type == NES_MPA_REQUEST_REJECT) { +		if (res_type == NES_MPA_REQUEST_REJECT)  			/*BIG problem as we are receiving the MPA.. So should -			* not be REJECT.. This is Passive Open.. We can -			* only receive it Reject for Active Open...*/ +			 * not be REJECT.. This is Passive Open.. We can +			 * only receive it Reject for Active Open...*/  			WARN_ON(1); -		}  		cm_node->state = NES_CM_STATE_MPAREQ_RCVD;  		type = NES_CM_EVENT_MPA_REQ;  		atomic_set(&cm_node->passive_state, -				NES_PASSIVE_STATE_INDICATED); +			   NES_PASSIVE_STATE_INDICATED);  		break;  	case NES_CM_STATE_MPAREQ_SENT:  		cleanup_retrans_entry(cm_node); @@ -1531,8 +1944,8 @@ static void indicate_pkt_err(struct nes_cm_node *cm_node, struct sk_buff *skb)  	case NES_CM_STATE_SYN_SENT:  	case NES_CM_STATE_MPAREQ_SENT:  		nes_debug(NES_DBG_CM, "%s[%u] create abort for cm_node=%p " -			"listener=%p state=%d\n", __func__, __LINE__, cm_node, -			cm_node->listener, cm_node->state); +			  "listener=%p state=%d\n", __func__, __LINE__, cm_node, +			  cm_node->listener, cm_node->state);  		active_open_err(cm_node, skb, 1);  		break;  	case NES_CM_STATE_ESTABLISHED: @@ -1546,11 +1959,11 @@ static void indicate_pkt_err(struct nes_cm_node *cm_node, struct sk_buff *skb)  }  static int check_syn(struct nes_cm_node *cm_node, struct tcphdr *tcph, -	struct sk_buff *skb) +		     struct sk_buff *skb)  {  	int err; -	err = ((ntohl(tcph->ack_seq) == cm_node->tcp_cntxt.loc_seq_num))? 0 : 1; +	err = ((ntohl(tcph->ack_seq) == cm_node->tcp_cntxt.loc_seq_num)) ? 0 : 1;  	if (err)  		active_open_err(cm_node, skb, 1); @@ -1558,7 +1971,7 @@ static int check_syn(struct nes_cm_node *cm_node, struct tcphdr *tcph,  }  static int check_seq(struct nes_cm_node *cm_node, struct tcphdr *tcph, -	struct sk_buff *skb) +		     struct sk_buff *skb)  {  	int err = 0;  	u32 seq; @@ -1566,21 +1979,22 @@ static int check_seq(struct nes_cm_node *cm_node, struct tcphdr *tcph,  	u32 loc_seq_num = cm_node->tcp_cntxt.loc_seq_num;  	u32 rcv_nxt = cm_node->tcp_cntxt.rcv_nxt;  	u32 rcv_wnd; +  	seq = ntohl(tcph->seq);  	ack_seq = ntohl(tcph->ack_seq);  	rcv_wnd = cm_node->tcp_cntxt.rcv_wnd;  	if (ack_seq != loc_seq_num)  		err = 1; -	else if (!between(seq, rcv_nxt, (rcv_nxt+rcv_wnd))) +	else if (!between(seq, rcv_nxt, (rcv_nxt + rcv_wnd)))  		err = 1;  	if (err) {  		nes_debug(NES_DBG_CM, "%s[%u] create abort for cm_node=%p " -			"listener=%p state=%d\n", __func__, __LINE__, cm_node, -			cm_node->listener, cm_node->state); +			  "listener=%p state=%d\n", __func__, __LINE__, cm_node, +			  cm_node->listener, cm_node->state);  		indicate_pkt_err(cm_node, skb);  		nes_debug(NES_DBG_CM, "seq ERROR cm_node =%p seq=0x%08X " -			"rcv_nxt=0x%08X rcv_wnd=0x%x\n", cm_node, seq, rcv_nxt, -			rcv_wnd); +			  "rcv_nxt=0x%08X rcv_wnd=0x%x\n", cm_node, seq, rcv_nxt, +			  rcv_wnd);  	}  	return err;  } @@ -1590,9 +2004,8 @@ static int check_seq(struct nes_cm_node *cm_node, struct tcphdr *tcph,   * is created with a listener or it may comein as rexmitted packet which in   * that case will be just dropped.   */ -  static void handle_syn_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, -	struct tcphdr *tcph) +			   struct tcphdr *tcph)  {  	int ret;  	u32 inc_sequence; @@ -1611,15 +2024,15 @@ static void handle_syn_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,  	case NES_CM_STATE_LISTENING:  		/* Passive OPEN */  		if (atomic_read(&cm_node->listener->pend_accepts_cnt) > -				cm_node->listener->backlog) { +		    cm_node->listener->backlog) {  			nes_debug(NES_DBG_CM, "drop syn due to backlog " -				"pressure \n"); +				  "pressure \n");  			cm_backlog_drops++;  			passive_open_err(cm_node, skb, 0);  			break;  		}  		ret = handle_tcp_options(cm_node, tcph, skb, optionsize, -			1); +					 1);  		if (ret) {  			passive_open_err(cm_node, skb, 0);  			/* drop pkt */ @@ -1653,9 +2066,8 @@ static void handle_syn_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,  }  static void handle_synack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, -	struct tcphdr *tcph) +			      struct tcphdr *tcph)  { -  	int ret;  	u32 inc_sequence;  	int optionsize; @@ -1674,7 +2086,7 @@ static void handle_synack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,  		ret = handle_tcp_options(cm_node, tcph, skb, optionsize, 0);  		if (ret) {  			nes_debug(NES_DBG_CM, "cm_node=%p tcp_options failed\n", -				cm_node); +				  cm_node);  			break;  		}  		cleanup_retrans_entry(cm_node); @@ -1713,12 +2125,13 @@ static void handle_synack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,  }  static int handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, -	struct tcphdr *tcph) +			  struct tcphdr *tcph)  {  	int datasize = 0;  	u32 inc_sequence;  	int ret = 0;  	int optionsize; +  	optionsize = (tcph->doff << 2) - sizeof(struct tcphdr);  	if (check_seq(cm_node, tcph, skb)) @@ -1739,8 +2152,9 @@ static int handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,  		if (datasize) {  			cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize;  			handle_rcv_mpa(cm_node, skb); -		} else  /* rcvd ACK only */ +		} else { /* rcvd ACK only */  			dev_kfree_skb_any(skb); +		}  		break;  	case NES_CM_STATE_ESTABLISHED:  		/* Passive OPEN */ @@ -1748,16 +2162,18 @@ static int handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,  		if (datasize) {  			cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize;  			handle_rcv_mpa(cm_node, skb); -		} else +		} else {  			drop_packet(skb); +		}  		break;  	case NES_CM_STATE_MPAREQ_SENT:  		cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq);  		if (datasize) {  			cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize;  			handle_rcv_mpa(cm_node, skb); -		} else  /* Could be just an ack pkt.. */ +		} else { /* Could be just an ack pkt.. */  			dev_kfree_skb_any(skb); +		}  		break;  	case NES_CM_STATE_LISTENING:  		cleanup_retrans_entry(cm_node); @@ -1798,14 +2214,15 @@ static int handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,  static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph, -	struct sk_buff *skb, int optionsize, int passive) +			      struct sk_buff *skb, int optionsize, int passive)  {  	u8 *optionsloc = (u8 *)&tcph[1]; +  	if (optionsize) {  		if (process_options(cm_node, optionsloc, optionsize, -			(u32)tcph->syn)) { +				    (u32)tcph->syn)) {  			nes_debug(NES_DBG_CM, "%s: Node %p, Sending RESET\n", -				__func__, cm_node); +				  __func__, cm_node);  			if (passive)  				passive_open_err(cm_node, skb, 1);  			else @@ -1815,7 +2232,7 @@ static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph,  	}  	cm_node->tcp_cntxt.snd_wnd = ntohs(tcph->window) << -			cm_node->tcp_cntxt.snd_wscale; +				     cm_node->tcp_cntxt.snd_wscale;  	if (cm_node->tcp_cntxt.snd_wnd > cm_node->tcp_cntxt.max_snd_wnd)  		cm_node->tcp_cntxt.max_snd_wnd = cm_node->tcp_cntxt.snd_wnd; @@ -1826,18 +2243,18 @@ static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph,   * active_open_err() will send reset() if flag set..   * It will also send ABORT event.   */ -  static void active_open_err(struct nes_cm_node *cm_node, struct sk_buff *skb, -	int reset) +			    int reset)  {  	cleanup_retrans_entry(cm_node);  	if (reset) {  		nes_debug(NES_DBG_CM, "ERROR active err called for cm_node=%p, " -				"state=%d\n", cm_node, cm_node->state); +			  "state=%d\n", cm_node, cm_node->state);  		add_ref_cm_node(cm_node);  		send_reset(cm_node, skb); -	} else +	} else {  		dev_kfree_skb_any(skb); +	}  	cm_node->state = NES_CM_STATE_CLOSED;  	create_event(cm_node, NES_CM_EVENT_ABORTED); @@ -1847,15 +2264,14 @@ static void active_open_err(struct nes_cm_node *cm_node, struct sk_buff *skb,   * passive_open_err() will either do a reset() or will free up the skb and   * remove the cm_node.   */ -  static void passive_open_err(struct nes_cm_node *cm_node, struct sk_buff *skb, -	int reset) +			     int reset)  {  	cleanup_retrans_entry(cm_node);  	cm_node->state = NES_CM_STATE_CLOSED;  	if (reset) {  		nes_debug(NES_DBG_CM, "passive_open_err sending RST for " -			"cm_node=%p state =%d\n", cm_node, cm_node->state); +			  "cm_node=%p state =%d\n", cm_node, cm_node->state);  		send_reset(cm_node, skb);  	} else {  		dev_kfree_skb_any(skb); @@ -1870,6 +2286,7 @@ static void passive_open_err(struct nes_cm_node *cm_node, struct sk_buff *skb,  static void free_retrans_entry(struct nes_cm_node *cm_node)  {  	struct nes_timer_entry *send_entry; +  	send_entry = cm_node->send_entry;  	if (send_entry) {  		cm_node->send_entry = NULL; @@ -1893,26 +2310,28 @@ static void cleanup_retrans_entry(struct nes_cm_node *cm_node)   * Returns skb if to be freed, else it will return NULL if already used..   */  static void process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb, -	struct nes_cm_core *cm_core) +			   struct nes_cm_core *cm_core)  { -	enum nes_tcpip_pkt_type	pkt_type = NES_PKT_TYPE_UNKNOWN; +	enum nes_tcpip_pkt_type pkt_type = NES_PKT_TYPE_UNKNOWN;  	struct tcphdr *tcph = tcp_hdr(skb); -	u32     fin_set = 0; +	u32 fin_set = 0;  	int ret = 0; +  	skb_pull(skb, ip_hdr(skb)->ihl << 2);  	nes_debug(NES_DBG_CM, "process_packet: cm_node=%p state =%d syn=%d " -		"ack=%d rst=%d fin=%d\n", cm_node, cm_node->state, tcph->syn, -		tcph->ack, tcph->rst, tcph->fin); +		  "ack=%d rst=%d fin=%d\n", cm_node, cm_node->state, tcph->syn, +		  tcph->ack, tcph->rst, tcph->fin); -	if (tcph->rst) +	if (tcph->rst) {  		pkt_type = NES_PKT_TYPE_RST; -	else if (tcph->syn) { +	} else if (tcph->syn) {  		pkt_type = NES_PKT_TYPE_SYN;  		if (tcph->ack)  			pkt_type = NES_PKT_TYPE_SYNACK; -	} else if (tcph->ack) +	} else if (tcph->ack) {  		pkt_type = NES_PKT_TYPE_ACK; +	}  	if (tcph->fin)  		fin_set = 1; @@ -1943,17 +2362,21 @@ static void process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb,   * mini_cm_listen - create a listen node with params   */  static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *cm_core, -	struct nes_vnic *nesvnic, struct nes_cm_info *cm_info) +			struct nes_vnic *nesvnic, struct nes_cm_info *cm_info)  {  	struct nes_cm_listener *listener; +	struct iwpm_dev_data pm_reg_msg; +	struct iwpm_sa_data pm_msg;  	unsigned long flags; +	int iwpm_err = 0;  	nes_debug(NES_DBG_CM, "Search for 0x%08x : 0x%04x\n", -		cm_info->loc_addr, cm_info->loc_port); +		  cm_info->loc_addr, cm_info->loc_port);  	/* cannot have multiple matching listeners */ -	listener = find_listener(cm_core, htonl(cm_info->loc_addr), -			htons(cm_info->loc_port), NES_CM_LISTENER_EITHER_STATE); +	listener = find_listener(cm_core, cm_info->loc_addr, cm_info->loc_port, +				NES_CM_LISTENER_EITHER_STATE, 1); +  	if (listener && listener->listener_state == NES_CM_LISTENER_ACTIVE_STATE) {  		/* find automatically incs ref count ??? */  		atomic_dec(&listener->ref_count); @@ -1962,6 +2385,22 @@ static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *cm_core,  	}  	if (!listener) { +		nes_form_reg_msg(nesvnic, &pm_reg_msg); +		iwpm_err = iwpm_register_pid(&pm_reg_msg, RDMA_NL_NES); +		if (iwpm_err) { +			nes_debug(NES_DBG_NLMSG, +			"Port Mapper reg pid fail (err = %d).\n", iwpm_err); +		} +		if (iwpm_valid_pid() && !iwpm_err) { +			nes_form_pm_msg(cm_info, &pm_msg); +			iwpm_err = iwpm_add_mapping(&pm_msg, RDMA_NL_NES); +			if (iwpm_err) +				nes_debug(NES_DBG_NLMSG, +				"Port Mapper query fail (err = %d).\n", iwpm_err); +			else +				nes_record_pm_msg(cm_info, &pm_msg); +		} +  		/* create a CM listen node (1/2 node to compare incoming traffic to) */  		listener = kzalloc(sizeof(*listener), GFP_ATOMIC);  		if (!listener) { @@ -1969,8 +2408,10 @@ static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *cm_core,  			return NULL;  		} -		listener->loc_addr = htonl(cm_info->loc_addr); -		listener->loc_port = htons(cm_info->loc_port); +		listener->loc_addr = cm_info->loc_addr; +		listener->loc_port = cm_info->loc_port; +		listener->mapped_loc_addr = cm_info->mapped_loc_addr; +		listener->mapped_loc_port = cm_info->mapped_loc_port;  		listener->reused_node = 0;  		atomic_set(&listener->ref_count, 1); @@ -1999,9 +2440,9 @@ static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *cm_core,  	}  	nes_debug(NES_DBG_CM, "Api - listen(): addr=0x%08X, port=0x%04x," -			" listener = %p, backlog = %d, cm_id = %p.\n", -			cm_info->loc_addr, cm_info->loc_port, -			listener, listener->backlog, listener->cm_id); +		  " listener = %p, backlog = %d, cm_id = %p.\n", +		  cm_info->loc_addr, cm_info->loc_port, +		  listener, listener->backlog, listener->cm_id);  	return listener;  } @@ -2011,26 +2452,20 @@ static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *cm_core,   * mini_cm_connect - make a connection node with params   */  static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core, -	struct nes_vnic *nesvnic, u16 private_data_len, -	void *private_data, struct nes_cm_info *cm_info) +					   struct nes_vnic *nesvnic, u16 private_data_len, +					   void *private_data, struct nes_cm_info *cm_info)  {  	int ret = 0;  	struct nes_cm_node *cm_node;  	struct nes_cm_listener *loopbackremotelistener;  	struct nes_cm_node *loopbackremotenode;  	struct nes_cm_info loopback_cm_info; -	u16 mpa_frame_size = sizeof(struct ietf_mpa_frame) + private_data_len; -	struct ietf_mpa_frame *mpa_frame = NULL; +	u8 *start_buff;  	/* create a CM connection node */  	cm_node = make_cm_node(cm_core, nesvnic, cm_info, NULL);  	if (!cm_node)  		return NULL; -	mpa_frame = &cm_node->mpa_frame; -	memcpy(mpa_frame->key, IEFT_MPA_KEY_REQ, IETF_MPA_KEY_SIZE); -	mpa_frame->flags = IETF_MPA_FLAGS_CRC; -	mpa_frame->rev =  IETF_MPA_VERSION; -	mpa_frame->priv_data_len = htons(private_data_len);  	/* set our node side to client (active) side */  	cm_node->tcp_cntxt.client = 1; @@ -2038,17 +2473,21 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,  	if (cm_info->loc_addr == cm_info->rem_addr) {  		loopbackremotelistener = find_listener(cm_core, -				ntohl(nesvnic->local_ipaddr), cm_node->rem_port, -				NES_CM_LISTENER_ACTIVE_STATE); +			cm_node->mapped_loc_addr, cm_node->mapped_rem_port, +			NES_CM_LISTENER_ACTIVE_STATE, 0);  		if (loopbackremotelistener == NULL) {  			create_event(cm_node, NES_CM_EVENT_ABORTED);  		} else {  			loopback_cm_info = *cm_info;  			loopback_cm_info.loc_port = cm_info->rem_port;  			loopback_cm_info.rem_port = cm_info->loc_port; +			loopback_cm_info.mapped_loc_port = +				cm_info->mapped_rem_port; +			loopback_cm_info.mapped_rem_port = +				cm_info->mapped_loc_port;  			loopback_cm_info.cm_id = loopbackremotelistener->cm_id;  			loopbackremotenode = make_cm_node(cm_core, nesvnic, -				&loopback_cm_info, loopbackremotelistener); +							  &loopback_cm_info, loopbackremotelistener);  			if (!loopbackremotenode) {  				rem_ref_cm_node(cm_node->cm_core, cm_node);  				return NULL; @@ -2059,7 +2498,7 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,  				NES_CM_DEFAULT_RCV_WND_SCALE;  			cm_node->loopbackpartner = loopbackremotenode;  			memcpy(loopbackremotenode->mpa_frame_buf, private_data, -				private_data_len); +			       private_data_len);  			loopbackremotenode->mpa_frame_size = private_data_len;  			/* we are done handling this state. */ @@ -2087,12 +2526,10 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,  		return cm_node;  	} -	/* set our node side to client (active) side */ -	cm_node->tcp_cntxt.client = 1; -	/* init our MPA frame ptr */ -	memcpy(mpa_frame->priv_data, private_data, private_data_len); +	start_buff = &cm_node->mpa_frame_buf[0] + sizeof(struct ietf_mpa_v2); +	cm_node->mpa_frame_size = private_data_len; -	cm_node->mpa_frame_size = mpa_frame_size; +	memcpy(start_buff, private_data, private_data_len);  	/* send a syn and goto syn sent state */  	cm_node->state = NES_CM_STATE_SYN_SENT; @@ -2101,18 +2538,19 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,  	if (ret) {  		/* error in sending the syn free up the cm_node struct */  		nes_debug(NES_DBG_CM, "Api - connect() FAILED: dest " -			"addr=0x%08X, port=0x%04x, cm_node=%p, cm_id = %p.\n", -			cm_node->rem_addr, cm_node->rem_port, cm_node, -			cm_node->cm_id); +			  "addr=0x%08X, port=0x%04x, cm_node=%p, cm_id = %p.\n", +			  cm_node->rem_addr, cm_node->rem_port, cm_node, +			  cm_node->cm_id);  		rem_ref_cm_node(cm_node->cm_core, cm_node);  		cm_node = NULL;  	} -	if (cm_node) +	if (cm_node) {  		nes_debug(NES_DBG_CM, "Api - connect(): dest addr=0x%08X," -			"port=0x%04x, cm_node=%p, cm_id = %p.\n", -			cm_node->rem_addr, cm_node->rem_port, cm_node, -			cm_node->cm_id); +			  "port=0x%04x, cm_node=%p, cm_id = %p.\n", +			  cm_node->rem_addr, cm_node->rem_port, cm_node, +			  cm_node->cm_id); +	}  	return cm_node;  } @@ -2122,8 +2560,7 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,   * mini_cm_accept - accept a connection   * This function is never called   */ -static int mini_cm_accept(struct nes_cm_core *cm_core, -	struct ietf_mpa_frame *mpa_frame, struct nes_cm_node *cm_node) +static int mini_cm_accept(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node)  {  	return 0;  } @@ -2132,8 +2569,7 @@ static int mini_cm_accept(struct nes_cm_core *cm_core,  /**   * mini_cm_reject - reject and teardown a connection   */ -static int mini_cm_reject(struct nes_cm_core *cm_core, -	struct ietf_mpa_frame *mpa_frame, struct nes_cm_node *cm_node) +static int mini_cm_reject(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node)  {  	int ret = 0;  	int err = 0; @@ -2143,7 +2579,7 @@ static int mini_cm_reject(struct nes_cm_core *cm_core,  	struct nes_cm_node *loopback = cm_node->loopbackpartner;  	nes_debug(NES_DBG_CM, "%s cm_node=%p type=%d state=%d\n", -		__func__, cm_node, cm_node->tcp_cntxt.client, cm_node->state); +		  __func__, cm_node, cm_node->tcp_cntxt.client, cm_node->state);  	if (cm_node->tcp_cntxt.client)  		return ret; @@ -2164,8 +2600,9 @@ static int mini_cm_reject(struct nes_cm_core *cm_core,  					err = send_reset(cm_node, NULL);  					if (err)  						WARN_ON(1); -				} else +				} else {  					cm_id->add_ref(cm_id); +				}  			}  		}  	} else { @@ -2240,7 +2677,7 @@ static int mini_cm_close(struct nes_cm_core *cm_core, struct nes_cm_node *cm_nod  	case NES_CM_STATE_TSA:  		if (cm_node->send_entry)  			printk(KERN_ERR "ERROR Close got called from STATE_TSA " -				"send_entry=%p\n", cm_node->send_entry); +			       "send_entry=%p\n", cm_node->send_entry);  		ret = rem_ref_cm_node(cm_core, cm_node);  		break;  	} @@ -2253,7 +2690,7 @@ static int mini_cm_close(struct nes_cm_core *cm_core, struct nes_cm_node *cm_nod   * node state machine   */  static int mini_cm_recv_pkt(struct nes_cm_core *cm_core, -	struct nes_vnic *nesvnic, struct sk_buff *skb) +			    struct nes_vnic *nesvnic, struct sk_buff *skb)  {  	struct nes_cm_node *cm_node = NULL;  	struct nes_cm_listener *listener = NULL; @@ -2265,9 +2702,8 @@ static int mini_cm_recv_pkt(struct nes_cm_core *cm_core,  	if (!skb)  		return 0; -	if (skb->len < sizeof(struct iphdr) + sizeof(struct tcphdr)) { +	if (skb->len < sizeof(struct iphdr) + sizeof(struct tcphdr))  		return 0; -	}  	iph = (struct iphdr *)skb->data;  	tcph = (struct tcphdr *)(skb->data + sizeof(struct iphdr)); @@ -2277,6 +2713,12 @@ static int mini_cm_recv_pkt(struct nes_cm_core *cm_core,  	nfo.rem_addr = ntohl(iph->saddr);  	nfo.rem_port = ntohs(tcph->source); +	/* If port mapper is available these should be mapped address info */ +	nfo.mapped_loc_addr = ntohl(iph->daddr); +	nfo.mapped_loc_port = ntohs(tcph->dest); +	nfo.mapped_rem_addr = ntohl(iph->saddr); +	nfo.mapped_rem_port = ntohs(tcph->source); +  	tmp_daddr = cpu_to_be32(iph->daddr);  	tmp_saddr = cpu_to_be32(iph->saddr); @@ -2285,8 +2727,8 @@ static int mini_cm_recv_pkt(struct nes_cm_core *cm_core,  	do {  		cm_node = find_node(cm_core, -			nfo.rem_port, nfo.rem_addr, -			nfo.loc_port, nfo.loc_addr); +				    nfo.mapped_rem_port, nfo.mapped_rem_addr, +				    nfo.mapped_loc_port, nfo.mapped_loc_addr);  		if (!cm_node) {  			/* Only type of packet accepted are for */ @@ -2295,9 +2737,9 @@ static int mini_cm_recv_pkt(struct nes_cm_core *cm_core,  				skb_handled = 0;  				break;  			} -			listener = find_listener(cm_core, nfo.loc_addr, -				nfo.loc_port, -				NES_CM_LISTENER_ACTIVE_STATE); +			listener = find_listener(cm_core, nfo.mapped_loc_addr, +					nfo.mapped_loc_port, +					NES_CM_LISTENER_ACTIVE_STATE, 0);  			if (!listener) {  				nfo.cm_id = NULL;  				nfo.conn_type = 0; @@ -2308,10 +2750,10 @@ static int mini_cm_recv_pkt(struct nes_cm_core *cm_core,  			nfo.cm_id = listener->cm_id;  			nfo.conn_type = listener->conn_type;  			cm_node = make_cm_node(cm_core, nesvnic, &nfo, -				listener); +					       listener);  			if (!cm_node) {  				nes_debug(NES_DBG_CM, "Unable to allocate " -					"node\n"); +					  "node\n");  				cm_packets_dropped++;  				atomic_dec(&listener->ref_count);  				dev_kfree_skb_any(skb); @@ -2327,9 +2769,13 @@ static int mini_cm_recv_pkt(struct nes_cm_core *cm_core,  			}  			add_ref_cm_node(cm_node);  		} else if (cm_node->state == NES_CM_STATE_TSA) { -			rem_ref_cm_node(cm_core, cm_node); -			atomic_inc(&cm_accel_dropped_pkts); -			dev_kfree_skb_any(skb); +			if (cm_node->nesqp->pau_mode) +				nes_queue_mgt_skbs(skb, nesvnic, cm_node->nesqp); +			else { +				rem_ref_cm_node(cm_core, cm_node); +				atomic_inc(&cm_accel_dropped_pkts); +				dev_kfree_skb_any(skb); +			}  			break;  		}  		skb_reset_network_header(skb); @@ -2359,7 +2805,7 @@ static struct nes_cm_core *nes_cm_alloc_core(void)  	init_timer(&cm_core->tcp_timer);  	cm_core->tcp_timer.function = nes_cm_timer_tick; -	cm_core->mtu   = NES_CM_DEFAULT_MTU; +	cm_core->mtu = NES_CM_DEFAULT_MTU;  	cm_core->state = NES_CM_STATE_INITED;  	cm_core->free_tx_pkt_max = NES_CM_DEFAULT_FREE_PKTS; @@ -2397,9 +2843,8 @@ static int mini_cm_dealloc_core(struct nes_cm_core *cm_core)  	barrier(); -	if (timer_pending(&cm_core->tcp_timer)) { +	if (timer_pending(&cm_core->tcp_timer))  		del_timer(&cm_core->tcp_timer); -	}  	destroy_workqueue(cm_core->event_wq);  	destroy_workqueue(cm_core->disconn_wq); @@ -2454,8 +2899,8 @@ static int nes_cm_init_tsa_conn(struct nes_qp *nesqp, struct nes_cm_node *cm_nod  		return -EINVAL;  	nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_IPV4 | -			NES_QPCONTEXT_MISC_NO_NAGLE | NES_QPCONTEXT_MISC_DO_NOT_FRAG | -			NES_QPCONTEXT_MISC_DROS); +						  NES_QPCONTEXT_MISC_NO_NAGLE | NES_QPCONTEXT_MISC_DO_NOT_FRAG | +						  NES_QPCONTEXT_MISC_DROS);  	if (cm_node->tcp_cntxt.snd_wscale || cm_node->tcp_cntxt.rcv_wscale)  		nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_WSCALE); @@ -2465,15 +2910,15 @@ static int nes_cm_init_tsa_conn(struct nes_qp *nesqp, struct nes_cm_node *cm_nod  	nesqp->nesqp_context->mss |= cpu_to_le32(((u32)cm_node->tcp_cntxt.mss) << 16);  	nesqp->nesqp_context->tcp_state_flow_label |= cpu_to_le32( -			(u32)NES_QPCONTEXT_TCPSTATE_EST << NES_QPCONTEXT_TCPFLOW_TCP_STATE_SHIFT); +		(u32)NES_QPCONTEXT_TCPSTATE_EST << NES_QPCONTEXT_TCPFLOW_TCP_STATE_SHIFT);  	nesqp->nesqp_context->pd_index_wscale |= cpu_to_le32( -			(cm_node->tcp_cntxt.snd_wscale << NES_QPCONTEXT_PDWSCALE_SND_WSCALE_SHIFT) & -			NES_QPCONTEXT_PDWSCALE_SND_WSCALE_MASK); +		(cm_node->tcp_cntxt.snd_wscale << NES_QPCONTEXT_PDWSCALE_SND_WSCALE_SHIFT) & +		NES_QPCONTEXT_PDWSCALE_SND_WSCALE_MASK);  	nesqp->nesqp_context->pd_index_wscale |= cpu_to_le32( -			(cm_node->tcp_cntxt.rcv_wscale << NES_QPCONTEXT_PDWSCALE_RCV_WSCALE_SHIFT) & -			NES_QPCONTEXT_PDWSCALE_RCV_WSCALE_MASK); +		(cm_node->tcp_cntxt.rcv_wscale << NES_QPCONTEXT_PDWSCALE_RCV_WSCALE_SHIFT) & +		NES_QPCONTEXT_PDWSCALE_RCV_WSCALE_MASK);  	nesqp->nesqp_context->keepalive = cpu_to_le32(0x80);  	nesqp->nesqp_context->ts_recent = 0; @@ -2482,24 +2927,24 @@ static int nes_cm_init_tsa_conn(struct nes_qp *nesqp, struct nes_cm_node *cm_nod  	nesqp->nesqp_context->snd_wnd = cpu_to_le32(cm_node->tcp_cntxt.snd_wnd);  	nesqp->nesqp_context->rcv_nxt = cpu_to_le32(cm_node->tcp_cntxt.rcv_nxt);  	nesqp->nesqp_context->rcv_wnd = cpu_to_le32(cm_node->tcp_cntxt.rcv_wnd << -			cm_node->tcp_cntxt.rcv_wscale); +						    cm_node->tcp_cntxt.rcv_wscale);  	nesqp->nesqp_context->snd_max = cpu_to_le32(cm_node->tcp_cntxt.loc_seq_num);  	nesqp->nesqp_context->snd_una = cpu_to_le32(cm_node->tcp_cntxt.loc_seq_num);  	nesqp->nesqp_context->srtt = 0;  	nesqp->nesqp_context->rttvar = cpu_to_le32(0x6);  	nesqp->nesqp_context->ssthresh = cpu_to_le32(0x3FFFC000); -	nesqp->nesqp_context->cwnd = cpu_to_le32(2*cm_node->tcp_cntxt.mss); +	nesqp->nesqp_context->cwnd = cpu_to_le32(2 * cm_node->tcp_cntxt.mss);  	nesqp->nesqp_context->snd_wl1 = cpu_to_le32(cm_node->tcp_cntxt.rcv_nxt);  	nesqp->nesqp_context->snd_wl2 = cpu_to_le32(cm_node->tcp_cntxt.loc_seq_num);  	nesqp->nesqp_context->max_snd_wnd = cpu_to_le32(cm_node->tcp_cntxt.max_snd_wnd);  	nes_debug(NES_DBG_CM, "QP%u: rcv_nxt = 0x%08X, snd_nxt = 0x%08X," -			" Setting MSS to %u, PDWscale = 0x%08X, rcv_wnd = %u, context misc = 0x%08X.\n", -			nesqp->hwqp.qp_id, le32_to_cpu(nesqp->nesqp_context->rcv_nxt), -			le32_to_cpu(nesqp->nesqp_context->snd_nxt), -			cm_node->tcp_cntxt.mss, le32_to_cpu(nesqp->nesqp_context->pd_index_wscale), -			le32_to_cpu(nesqp->nesqp_context->rcv_wnd), -			le32_to_cpu(nesqp->nesqp_context->misc)); +		  " Setting MSS to %u, PDWscale = 0x%08X, rcv_wnd = %u, context misc = 0x%08X.\n", +		  nesqp->hwqp.qp_id, le32_to_cpu(nesqp->nesqp_context->rcv_nxt), +		  le32_to_cpu(nesqp->nesqp_context->snd_nxt), +		  cm_node->tcp_cntxt.mss, le32_to_cpu(nesqp->nesqp_context->pd_index_wscale), +		  le32_to_cpu(nesqp->nesqp_context->rcv_wnd), +		  le32_to_cpu(nesqp->nesqp_context->misc));  	nes_debug(NES_DBG_CM, "  snd_wnd  = 0x%08X.\n", le32_to_cpu(nesqp->nesqp_context->snd_wnd));  	nes_debug(NES_DBG_CM, "  snd_cwnd = 0x%08X.\n", le32_to_cpu(nesqp->nesqp_context->cwnd));  	nes_debug(NES_DBG_CM, "  max_swnd = 0x%08X.\n", le32_to_cpu(nesqp->nesqp_context->max_snd_wnd)); @@ -2520,7 +2965,7 @@ int nes_cm_disconn(struct nes_qp *nesqp)  	work = kzalloc(sizeof *work, GFP_ATOMIC);  	if (!work) -		return -ENOMEM; /* Timer will clean up */ +		return -ENOMEM;  /* Timer will clean up */  	nes_add_ref(&nesqp->ibqp);  	work->nesqp = nesqp; @@ -2540,7 +2985,7 @@ static void nes_disconnect_worker(struct work_struct *work)  	kfree(dwork);  	nes_debug(NES_DBG_CM, "processing AEQE id 0x%04X for QP%u.\n", -			nesqp->last_aeq, nesqp->hwqp.qp_id); +		  nesqp->last_aeq, nesqp->hwqp.qp_id);  	nes_cm_disconn_true(nesqp);  	nes_rem_ref(&nesqp->ibqp);  } @@ -2559,7 +3004,7 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp)  	u16 last_ae;  	u8 original_hw_tcp_state;  	u8 original_ibqp_state; -	enum iw_cm_event_status disconn_status = IW_CM_EVENT_STATUS_OK; +	int disconn_status = 0;  	int issue_disconn = 0;  	int issue_close = 0;  	int issue_flush = 0; @@ -2576,7 +3021,7 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp)  	/* make sure we havent already closed this connection */  	if (!cm_id) {  		nes_debug(NES_DBG_CM, "QP%u disconnect_worker cmid is NULL\n", -				nesqp->hwqp.qp_id); +			  nesqp->hwqp.qp_id);  		spin_unlock_irqrestore(&nesqp->lock, flags);  		return -1;  	} @@ -2585,13 +3030,14 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp)  	nes_debug(NES_DBG_CM, "Disconnecting QP%u\n", nesqp->hwqp.qp_id);  	original_hw_tcp_state = nesqp->hw_tcp_state; -	original_ibqp_state   = nesqp->ibqp_state; +	original_ibqp_state = nesqp->ibqp_state;  	last_ae = nesqp->last_aeq;  	if (nesqp->term_flags) {  		issue_disconn = 1;  		issue_close = 1;  		nesqp->cm_id = NULL; +		del_timer(&nesqp->terminate_timer);  		if (nesqp->flush_issued == 0) {  			nesqp->flush_issued = 1;  			issue_flush = 1; @@ -2601,7 +3047,7 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp)  			(last_ae == NES_AEQE_AEID_LLP_CONNECTION_RESET))) {  		issue_disconn = 1;  		if (last_ae == NES_AEQE_AEID_LLP_CONNECTION_RESET) -			disconn_status = IW_CM_EVENT_STATUS_RESET; +			disconn_status = -ECONNRESET;  	}  	if (((original_hw_tcp_state == NES_AEQE_TCP_STATE_CLOSED) || @@ -2628,7 +3074,8 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp)  			ibevent.device = nesqp->ibqp.device;  			ibevent.event = nesqp->terminate_eventtype;  			ibevent.element.qp = &nesqp->ibqp; -			nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context); +			if (nesqp->ibqp.event_handler) +				nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);  		}  	} @@ -2643,16 +3090,16 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp)  			cm_event.private_data_len = 0;  			nes_debug(NES_DBG_CM, "Generating a CM Disconnect Event" -				" for  QP%u, SQ Head = %u, SQ Tail = %u. " -				"cm_id = %p, refcount = %u.\n", -				nesqp->hwqp.qp_id, nesqp->hwqp.sq_head, -				nesqp->hwqp.sq_tail, cm_id, -				atomic_read(&nesqp->refcount)); +				  " for  QP%u, SQ Head = %u, SQ Tail = %u. " +				  "cm_id = %p, refcount = %u.\n", +				  nesqp->hwqp.qp_id, nesqp->hwqp.sq_head, +				  nesqp->hwqp.sq_tail, cm_id, +				  atomic_read(&nesqp->refcount));  			ret = cm_id->event_handler(cm_id, &cm_event);  			if (ret)  				nes_debug(NES_DBG_CM, "OFA CM event_handler " -					"returned, ret=%d\n", ret); +					  "returned, ret=%d\n", ret);  		}  		if (issue_close) { @@ -2662,7 +3109,7 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp)  			cm_id->provider_data = nesqp;  			/* Send up the close complete event */  			cm_event.event = IW_CM_EVENT_CLOSE; -			cm_event.status = IW_CM_EVENT_STATUS_OK; +			cm_event.status = 0;  			cm_event.provider_data = cm_id->provider_data;  			cm_event.local_addr = cm_id->local_addr;  			cm_event.remote_addr = cm_id->remote_addr; @@ -2670,9 +3117,8 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp)  			cm_event.private_data_len = 0;  			ret = cm_id->event_handler(cm_id, &cm_event); -			if (ret) { +			if (ret)  				nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret); -			}  			cm_id->rem_ref(cm_id);  		} @@ -2712,8 +3158,8 @@ static int nes_disconnect(struct nes_qp *nesqp, int abrupt)  			if (nesqp->lsmm_mr)  				nesibdev->ibdev.dereg_mr(nesqp->lsmm_mr);  			pci_free_consistent(nesdev->pcidev, -					nesqp->private_data_len+sizeof(struct ietf_mpa_frame), -					nesqp->ietf_frame, nesqp->ietf_frame_pbase); +					    nesqp->private_data_len + nesqp->ietf_frame_size, +					    nesqp->ietf_frame, nesqp->ietf_frame_pbase);  		}  	} @@ -2752,6 +3198,14 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)  	struct ib_phys_buf ibphysbuf;  	struct nes_pd *nespd;  	u64 tagged_offset; +	u8 mpa_frame_offset = 0; +	struct ietf_mpa_v2 *mpa_v2_frame; +	u8 start_addr = 0; +	u8 *start_ptr = &start_addr; +	u8 **start_buff = &start_ptr; +	u16 buff_len = 0; +	struct sockaddr_in *laddr = (struct sockaddr_in *)&cm_id->local_addr; +	struct sockaddr_in *raddr = (struct sockaddr_in *)&cm_id->remote_addr;  	ibqp = nes_get_qp(cm_id->device, conn_param->qpn);  	if (!ibqp) @@ -2780,11 +3234,11 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)  		rem_ref_cm_node(cm_node->cm_core, cm_node);  		return -ECONNRESET;  	} -  	/* associate the node with the QP */  	nesqp->cm_node = (void *)cm_node;  	cm_node->nesqp = nesqp; +  	nes_debug(NES_DBG_CM, "QP%u, cm_node=%p, jiffies = %lu listener = %p\n",  		nesqp->hwqp.qp_id, cm_node, jiffies, cm_node->listener);  	atomic_inc(&cm_accepts); @@ -2792,53 +3246,53 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)  	nes_debug(NES_DBG_CM, "netdev refcnt = %u.\n",  			netdev_refcnt_read(nesvnic->netdev)); +	nesqp->ietf_frame_size = sizeof(struct ietf_mpa_v2);  	/* allocate the ietf frame and space for private data */  	nesqp->ietf_frame = pci_alloc_consistent(nesdev->pcidev, -		sizeof(struct ietf_mpa_frame) + conn_param->private_data_len, -		&nesqp->ietf_frame_pbase); +						 nesqp->ietf_frame_size + conn_param->private_data_len, +						 &nesqp->ietf_frame_pbase);  	if (!nesqp->ietf_frame) { -		nes_debug(NES_DBG_CM, "Unable to allocate memory for private " -			"data\n"); +		nes_debug(NES_DBG_CM, "Unable to allocate memory for private data\n");  		return -ENOMEM;  	} +	mpa_v2_frame = (struct ietf_mpa_v2 *)nesqp->ietf_frame; +	if (cm_node->mpa_frame_rev == IETF_MPA_V1) +		mpa_frame_offset = 4; -	/* setup the MPA frame */ -	nesqp->private_data_len = conn_param->private_data_len; -	memcpy(nesqp->ietf_frame->key, IEFT_MPA_KEY_REP, IETF_MPA_KEY_SIZE); +	if (cm_node->mpa_frame_rev == IETF_MPA_V1 || +			cm_node->mpav2_ird_ord == IETF_NO_IRD_ORD) { +		record_ird_ord(cm_node, (u16)conn_param->ird, (u16)conn_param->ord); +	} -	memcpy(nesqp->ietf_frame->priv_data, conn_param->private_data, -			conn_param->private_data_len); +	memcpy(mpa_v2_frame->priv_data, conn_param->private_data, +	       conn_param->private_data_len); -	nesqp->ietf_frame->priv_data_len = -		cpu_to_be16(conn_param->private_data_len); -	nesqp->ietf_frame->rev = mpa_version; -	nesqp->ietf_frame->flags = IETF_MPA_FLAGS_CRC; +	cm_build_mpa_frame(cm_node, start_buff, &buff_len, nesqp->ietf_frame, MPA_KEY_REPLY); +	nesqp->private_data_len = conn_param->private_data_len;  	/* setup our first outgoing iWarp send WQE (the IETF frame response) */  	wqe = &nesqp->hwqp.sq_vbase[0]; -	if (cm_id->remote_addr.sin_addr.s_addr != -			cm_id->local_addr.sin_addr.s_addr) { +	if (raddr->sin_addr.s_addr != laddr->sin_addr.s_addr) {  		u64temp = (unsigned long)nesqp;  		nesibdev = nesvnic->nesibdev;  		nespd = nesqp->nespd; -		ibphysbuf.addr = nesqp->ietf_frame_pbase; -		ibphysbuf.size = conn_param->private_data_len + -					sizeof(struct ietf_mpa_frame); -		tagged_offset = (u64)(unsigned long)nesqp->ietf_frame; +		ibphysbuf.addr = nesqp->ietf_frame_pbase + mpa_frame_offset; +		ibphysbuf.size = buff_len; +		tagged_offset = (u64)(unsigned long)*start_buff;  		ibmr = nesibdev->ibdev.reg_phys_mr((struct ib_pd *)nespd, -						&ibphysbuf, 1, -						IB_ACCESS_LOCAL_WRITE, -						&tagged_offset); +						   &ibphysbuf, 1, +						   IB_ACCESS_LOCAL_WRITE, +						   &tagged_offset);  		if (!ibmr) {  			nes_debug(NES_DBG_CM, "Unable to register memory region" -					"for lSMM for cm_node = %p \n", -					cm_node); +				  "for lSMM for cm_node = %p \n", +				  cm_node);  			pci_free_consistent(nesdev->pcidev, -				nesqp->private_data_len+sizeof(struct ietf_mpa_frame), -				nesqp->ietf_frame, nesqp->ietf_frame_pbase); +					    nesqp->private_data_len + nesqp->ietf_frame_size, +					    nesqp->ietf_frame, nesqp->ietf_frame_pbase);  			return -ENOMEM;  		} @@ -2846,22 +3300,20 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)  		ibmr->device = nespd->ibpd.device;  		nesqp->lsmm_mr = ibmr; -		u64temp |= NES_SW_CONTEXT_ALIGN>>1; +		u64temp |= NES_SW_CONTEXT_ALIGN >> 1;  		set_wqe_64bit_value(wqe->wqe_words, -			NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX, -			u64temp); +				    NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX, +				    u64temp);  		wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] =  			cpu_to_le32(NES_IWARP_SQ_WQE_STREAMING | -			NES_IWARP_SQ_WQE_WRPDU); +				    NES_IWARP_SQ_WQE_WRPDU);  		wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] = -			cpu_to_le32(conn_param->private_data_len + -			sizeof(struct ietf_mpa_frame)); +			cpu_to_le32(buff_len);  		set_wqe_64bit_value(wqe->wqe_words, -					NES_IWARP_SQ_WQE_FRAG0_LOW_IDX, -					(u64)(unsigned long)nesqp->ietf_frame); +				    NES_IWARP_SQ_WQE_FRAG0_LOW_IDX, +				    (u64)(unsigned long)(*start_buff));  		wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] = -			cpu_to_le32(conn_param->private_data_len + -			sizeof(struct ietf_mpa_frame)); +			cpu_to_le32(buff_len);  		wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = ibmr->lkey;  		if (nesqp->sq_kmapped) {  			nesqp->sq_kmapped = 0; @@ -2870,48 +3322,42 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)  		nesqp->nesqp_context->ird_ord_sizes |=  			cpu_to_le32(NES_QPCONTEXT_ORDIRD_LSMM_PRESENT | -			NES_QPCONTEXT_ORDIRD_WRPDU); +				    NES_QPCONTEXT_ORDIRD_WRPDU);  	} else {  		nesqp->nesqp_context->ird_ord_sizes |=  			cpu_to_le32(NES_QPCONTEXT_ORDIRD_WRPDU);  	}  	nesqp->skip_lsmm = 1; -  	/* Cache the cm_id in the qp */  	nesqp->cm_id = cm_id;  	cm_node->cm_id = cm_id;  	/*  nesqp->cm_node = (void *)cm_id->provider_data; */  	cm_id->provider_data = nesqp; -	nesqp->active_conn   = 0; +	nesqp->active_conn = 0;  	if (cm_node->state == NES_CM_STATE_TSA)  		nes_debug(NES_DBG_CM, "Already state = TSA for cm_node=%p\n", -			cm_node); +			  cm_node);  	nes_cm_init_tsa_conn(nesqp, cm_node);  	nesqp->nesqp_context->tcpPorts[0] = -		cpu_to_le16(ntohs(cm_id->local_addr.sin_port)); +				cpu_to_le16(cm_node->mapped_loc_port);  	nesqp->nesqp_context->tcpPorts[1] = -		cpu_to_le16(ntohs(cm_id->remote_addr.sin_port)); +				cpu_to_le16(cm_node->mapped_rem_port); -	if (ipv4_is_loopback(cm_id->remote_addr.sin_addr.s_addr)) -		nesqp->nesqp_context->ip0 = -			cpu_to_le32(ntohl(nesvnic->local_ipaddr)); -	else -		nesqp->nesqp_context->ip0 = -			cpu_to_le32(ntohl(cm_id->remote_addr.sin_addr.s_addr)); +	nesqp->nesqp_context->ip0 = cpu_to_le32(cm_node->mapped_rem_addr);  	nesqp->nesqp_context->misc2 |= cpu_to_le32( -			(u32)PCI_FUNC(nesdev->pcidev->devfn) << -			NES_QPCONTEXT_MISC2_SRC_IP_SHIFT); +		(u32)PCI_FUNC(nesdev->pcidev->devfn) << +		NES_QPCONTEXT_MISC2_SRC_IP_SHIFT);  	nesqp->nesqp_context->arp_index_vlan |=  		cpu_to_le32(nes_arp_table(nesdev, -			le32_to_cpu(nesqp->nesqp_context->ip0), NULL, -			NES_ARP_RESOLVE) << 16); +					  le32_to_cpu(nesqp->nesqp_context->ip0), NULL, +					  NES_ARP_RESOLVE) << 16);  	nesqp->nesqp_context->ts_val_delta = cpu_to_le32(  		jiffies - nes_read_indexed(nesdev, NES_IDX_TCP_NOW)); @@ -2921,23 +3367,20 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)  	nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32(  		((u32)1 << NES_QPCONTEXT_ORDIRD_IWARP_MODE_SHIFT));  	nesqp->nesqp_context->ird_ord_sizes |= -		cpu_to_le32((u32)conn_param->ord); +		cpu_to_le32((u32)cm_node->ord_size);  	memset(&nes_quad, 0, sizeof(nes_quad));  	nes_quad.DstIpAdrIndex =  		cpu_to_le32((u32)PCI_FUNC(nesdev->pcidev->devfn) << 24); -	if (ipv4_is_loopback(cm_id->remote_addr.sin_addr.s_addr)) -		nes_quad.SrcIpadr = nesvnic->local_ipaddr; -	else -		nes_quad.SrcIpadr = cm_id->remote_addr.sin_addr.s_addr; -	nes_quad.TcpPorts[0] = cm_id->remote_addr.sin_port; -	nes_quad.TcpPorts[1] = cm_id->local_addr.sin_port; +	nes_quad.SrcIpadr = htonl(cm_node->mapped_rem_addr); +	nes_quad.TcpPorts[0] = htons(cm_node->mapped_rem_port); +	nes_quad.TcpPorts[1] = htons(cm_node->mapped_loc_port);  	/* Produce hash key */  	crc_value = get_crc_value(&nes_quad);  	nesqp->hte_index = cpu_to_be32(crc_value ^ 0xffffffff);  	nes_debug(NES_DBG_CM, "HTE Index = 0x%08X, CRC = 0x%08X\n", -		nesqp->hte_index, nesqp->hte_index & adapter->hte_index_mask); +		  nesqp->hte_index, nesqp->hte_index & adapter->hte_index_mask);  	nesqp->hte_index &= adapter->hte_index_mask;  	nesqp->nesqp_context->hte_index = cpu_to_le32(nesqp->hte_index); @@ -2945,29 +3388,28 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)  	cm_node->cm_core->api->accelerated(cm_node->cm_core, cm_node);  	nes_debug(NES_DBG_CM, "QP%u, Destination IP = 0x%08X:0x%04X, local = " -			"0x%08X:0x%04X, rcv_nxt=0x%08X, snd_nxt=0x%08X, mpa + " -			"private data length=%zu.\n", nesqp->hwqp.qp_id, -			ntohl(cm_id->remote_addr.sin_addr.s_addr), -			ntohs(cm_id->remote_addr.sin_port), -			ntohl(cm_id->local_addr.sin_addr.s_addr), -			ntohs(cm_id->local_addr.sin_port), -			le32_to_cpu(nesqp->nesqp_context->rcv_nxt), -			le32_to_cpu(nesqp->nesqp_context->snd_nxt), -			conn_param->private_data_len + -			sizeof(struct ietf_mpa_frame)); - +		  "0x%08X:0x%04X, rcv_nxt=0x%08X, snd_nxt=0x%08X, mpa + " +		  "private data length=%u.\n", nesqp->hwqp.qp_id, +		  ntohl(raddr->sin_addr.s_addr), ntohs(raddr->sin_port), +		  ntohl(laddr->sin_addr.s_addr), ntohs(laddr->sin_port), +		  le32_to_cpu(nesqp->nesqp_context->rcv_nxt), +		  le32_to_cpu(nesqp->nesqp_context->snd_nxt), +		  buff_len);  	/* notify OF layer that accept event was successful */  	cm_id->add_ref(cm_id);  	nes_add_ref(&nesqp->ibqp);  	cm_event.event = IW_CM_EVENT_ESTABLISHED; -	cm_event.status = IW_CM_EVENT_STATUS_ACCEPTED; +	cm_event.status = 0;  	cm_event.provider_data = (void *)nesqp;  	cm_event.local_addr = cm_id->local_addr;  	cm_event.remote_addr = cm_id->remote_addr;  	cm_event.private_data = NULL;  	cm_event.private_data_len = 0; +	cm_event.ird = cm_node->ird_size; +	cm_event.ord = cm_node->ord_size; +  	ret = cm_id->event_handler(cm_id, &cm_event);  	attr.qp_state = IB_QPS_RTS;  	nes_modify_qp(&nesqp->ibqp, &attr, IB_QP_STATE, NULL); @@ -2976,12 +3418,12 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)  			nesqp->private_data_len;  		/* copy entire MPA frame to our cm_node's frame */  		memcpy(cm_node->loopbackpartner->mpa_frame_buf, -			nesqp->ietf_frame->priv_data, nesqp->private_data_len); +		       conn_param->private_data, conn_param->private_data_len);  		create_event(cm_node->loopbackpartner, NES_CM_EVENT_CONNECTED);  	}  	if (ret)  		printk(KERN_ERR "%s[%u] OFA CM event_handler returned, " -			"ret=%d\n", __func__, __LINE__, ret); +		       "ret=%d\n", __func__, __LINE__, ret);  	return 0;  } @@ -2994,34 +3436,28 @@ int nes_reject(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len)  {  	struct nes_cm_node *cm_node;  	struct nes_cm_node *loopback; -  	struct nes_cm_core *cm_core; +	u8 *start_buff;  	atomic_inc(&cm_rejects); -	cm_node = (struct nes_cm_node *) cm_id->provider_data; +	cm_node = (struct nes_cm_node *)cm_id->provider_data;  	loopback = cm_node->loopbackpartner;  	cm_core = cm_node->cm_core;  	cm_node->cm_id = cm_id; -	cm_node->mpa_frame_size = sizeof(struct ietf_mpa_frame) + pdata_len; -	if (cm_node->mpa_frame_size > MAX_CM_BUFFER) +	if (pdata_len + sizeof(struct ietf_mpa_v2) > MAX_CM_BUFFER)  		return -EINVAL; -	memcpy(&cm_node->mpa_frame.key[0], IEFT_MPA_KEY_REP, IETF_MPA_KEY_SIZE);  	if (loopback) {  		memcpy(&loopback->mpa_frame.priv_data, pdata, pdata_len);  		loopback->mpa_frame.priv_data_len = pdata_len; -		loopback->mpa_frame_size = sizeof(struct ietf_mpa_frame) + -				pdata_len; +		loopback->mpa_frame_size = pdata_len;  	} else { -		memcpy(&cm_node->mpa_frame.priv_data, pdata, pdata_len); -		cm_node->mpa_frame.priv_data_len = cpu_to_be16(pdata_len); +		start_buff = &cm_node->mpa_frame_buf[0] + sizeof(struct ietf_mpa_v2); +		cm_node->mpa_frame_size = pdata_len; +		memcpy(start_buff, pdata, pdata_len);  	} - -	cm_node->mpa_frame.rev = mpa_version; -	cm_node->mpa_frame.flags = IETF_MPA_FLAGS_CRC | IETF_MPA_FLAGS_REJECT; - -	return cm_core->api->reject(cm_core, &cm_node->mpa_frame, cm_node); +	return cm_core->api->reject(cm_core, cm_node);  } @@ -3038,7 +3474,14 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)  	struct nes_cm_node *cm_node;  	struct nes_cm_info cm_info;  	int apbvt_set = 0; - +	struct sockaddr_in *laddr = (struct sockaddr_in *)&cm_id->local_addr; +	struct sockaddr_in *raddr = (struct sockaddr_in *)&cm_id->remote_addr; +	struct iwpm_dev_data pm_reg_msg; +	struct iwpm_sa_data pm_msg; +	int iwpm_err = 0; + +	if (cm_id->remote_addr.ss_family != AF_INET) +		return -ENOSYS;  	ibqp = nes_get_qp(cm_id->device, conn_param->qpn);  	if (!ibqp)  		return -EINVAL; @@ -3048,66 +3491,95 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)  	nesvnic = to_nesvnic(nesqp->ibqp.device);  	if (!nesvnic)  		return -EINVAL; -	nesdev  = nesvnic->nesdev; +	nesdev = nesvnic->nesdev;  	if (!nesdev)  		return -EINVAL; -	if (!(cm_id->local_addr.sin_port) || !(cm_id->remote_addr.sin_port)) +	if (!laddr->sin_port || !raddr->sin_port)  		return -EINVAL;  	nes_debug(NES_DBG_CM, "QP%u, current IP = 0x%08X, Destination IP = " -		"0x%08X:0x%04X, local = 0x%08X:0x%04X.\n", nesqp->hwqp.qp_id, -		ntohl(nesvnic->local_ipaddr), -		ntohl(cm_id->remote_addr.sin_addr.s_addr), -		ntohs(cm_id->remote_addr.sin_port), -		ntohl(cm_id->local_addr.sin_addr.s_addr), -		ntohs(cm_id->local_addr.sin_port)); +		  "0x%08X:0x%04X, local = 0x%08X:0x%04X.\n", nesqp->hwqp.qp_id, +		  ntohl(nesvnic->local_ipaddr), ntohl(raddr->sin_addr.s_addr), +		  ntohs(raddr->sin_port), ntohl(laddr->sin_addr.s_addr), +		  ntohs(laddr->sin_port));  	atomic_inc(&cm_connects);  	nesqp->active_conn = 1;  	/* cache the cm_id in the qp */  	nesqp->cm_id = cm_id; -  	cm_id->provider_data = nesqp; -  	nesqp->private_data_len = conn_param->private_data_len; -	nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32((u32)conn_param->ord); +  	nes_debug(NES_DBG_CM, "requested ord = 0x%08X.\n", (u32)conn_param->ord);  	nes_debug(NES_DBG_CM, "mpa private data len =%u\n", -		conn_param->private_data_len); +		  conn_param->private_data_len); + +	/* set up the connection params for the node */ +	cm_info.loc_addr = ntohl(laddr->sin_addr.s_addr); +	cm_info.loc_port = ntohs(laddr->sin_port); +	cm_info.rem_addr = ntohl(raddr->sin_addr.s_addr); +	cm_info.rem_port = ntohs(raddr->sin_port); +	cm_info.cm_id = cm_id; +	cm_info.conn_type = NES_CM_IWARP_CONN_TYPE; -	if (cm_id->local_addr.sin_addr.s_addr != -		cm_id->remote_addr.sin_addr.s_addr) { -		nes_manage_apbvt(nesvnic, ntohs(cm_id->local_addr.sin_port), +	/* No port mapper available, go with the specified peer information */ +	cm_info.mapped_loc_addr = cm_info.loc_addr; +	cm_info.mapped_loc_port = cm_info.loc_port; +	cm_info.mapped_rem_addr = cm_info.rem_addr; +	cm_info.mapped_rem_port = cm_info.rem_port; + +	nes_form_reg_msg(nesvnic, &pm_reg_msg); +	iwpm_err = iwpm_register_pid(&pm_reg_msg, RDMA_NL_NES); +	if (iwpm_err) { +		nes_debug(NES_DBG_NLMSG, +			"Port Mapper reg pid fail (err = %d).\n", iwpm_err); +	} +	if (iwpm_valid_pid() && !iwpm_err) { +		nes_form_pm_msg(&cm_info, &pm_msg); +		iwpm_err = iwpm_add_and_query_mapping(&pm_msg, RDMA_NL_NES); +		if (iwpm_err) +			nes_debug(NES_DBG_NLMSG, +			"Port Mapper query fail (err = %d).\n", iwpm_err); +		else +			nes_record_pm_msg(&cm_info, &pm_msg); +	} + +	if (laddr->sin_addr.s_addr != raddr->sin_addr.s_addr) { +		nes_manage_apbvt(nesvnic, cm_info.mapped_loc_port,  			PCI_FUNC(nesdev->pcidev->devfn), NES_MANAGE_APBVT_ADD);  		apbvt_set = 1;  	} -	/* set up the connection params for the node */ -	cm_info.loc_addr = htonl(cm_id->local_addr.sin_addr.s_addr); -	cm_info.loc_port = htons(cm_id->local_addr.sin_port); -	cm_info.rem_addr = htonl(cm_id->remote_addr.sin_addr.s_addr); -	cm_info.rem_port = htons(cm_id->remote_addr.sin_port); -	cm_info.cm_id = cm_id; -	cm_info.conn_type = NES_CM_IWARP_CONN_TYPE; +	if (nes_create_mapinfo(&cm_info)) +		return -ENOMEM;  	cm_id->add_ref(cm_id);  	/* create a connect CM node connection */  	cm_node = g_cm_core->api->connect(g_cm_core, nesvnic, -		conn_param->private_data_len, (void *)conn_param->private_data, -		&cm_info); +					  conn_param->private_data_len, (void *)conn_param->private_data, +					  &cm_info);  	if (!cm_node) {  		if (apbvt_set) -			nes_manage_apbvt(nesvnic, ntohs(cm_id->local_addr.sin_port), -				PCI_FUNC(nesdev->pcidev->devfn), -				NES_MANAGE_APBVT_DEL); - +			nes_manage_apbvt(nesvnic, cm_info.mapped_loc_port, +					 PCI_FUNC(nesdev->pcidev->devfn), +					 NES_MANAGE_APBVT_DEL); + +		nes_debug(NES_DBG_NLMSG, "Delete mapped_loc_port = %04X\n", +				cm_info.mapped_loc_port); +		nes_remove_mapinfo(cm_info.loc_addr, cm_info.loc_port, +			cm_info.mapped_loc_addr, cm_info.mapped_loc_port);  		cm_id->rem_ref(cm_id);  		return -ENOMEM;  	} +	record_ird_ord(cm_node, (u16)conn_param->ird, (u16)conn_param->ord); +	if (cm_node->send_rdma0_op == SEND_RDMA_READ_ZERO && +				cm_node->ord_size == 0) +		cm_node->ord_size = 1; +  	cm_node->apbvt_set = apbvt_set;  	nesqp->cm_node = cm_node;  	cm_node->nesqp = nesqp; @@ -3126,10 +3598,13 @@ int nes_create_listen(struct iw_cm_id *cm_id, int backlog)  	struct nes_cm_listener *cm_node;  	struct nes_cm_info cm_info;  	int err; +	struct sockaddr_in *laddr = (struct sockaddr_in *)&cm_id->local_addr;  	nes_debug(NES_DBG_CM, "cm_id = %p, local port = 0x%04X.\n", -			cm_id, ntohs(cm_id->local_addr.sin_port)); +		  cm_id, ntohs(laddr->sin_port)); +	if (cm_id->local_addr.ss_family != AF_INET) +		return -ENOSYS;  	nesvnic = to_nesvnic(cm_id->device);  	if (!nesvnic)  		return -EINVAL; @@ -3138,34 +3613,39 @@ int nes_create_listen(struct iw_cm_id *cm_id, int backlog)  			nesvnic, nesvnic->netdev, nesvnic->netdev->name);  	nes_debug(NES_DBG_CM, "nesvnic->local_ipaddr=0x%08x, sin_addr.s_addr=0x%08x\n", -			nesvnic->local_ipaddr, cm_id->local_addr.sin_addr.s_addr); +			nesvnic->local_ipaddr, laddr->sin_addr.s_addr);  	/* setup listen params in our api call struct */ -	cm_info.loc_addr = nesvnic->local_ipaddr; -	cm_info.loc_port = cm_id->local_addr.sin_port; +	cm_info.loc_addr = ntohl(nesvnic->local_ipaddr); +	cm_info.loc_port = ntohs(laddr->sin_port);  	cm_info.backlog = backlog;  	cm_info.cm_id = cm_id;  	cm_info.conn_type = NES_CM_IWARP_CONN_TYPE; +	/* No port mapper available, go with the specified info */ +	cm_info.mapped_loc_addr = cm_info.loc_addr; +	cm_info.mapped_loc_port = cm_info.loc_port;  	cm_node = g_cm_core->api->listen(g_cm_core, nesvnic, &cm_info);  	if (!cm_node) {  		printk(KERN_ERR "%s[%u] Error returned from listen API call\n", -				__func__, __LINE__); +		       __func__, __LINE__);  		return -ENOMEM;  	}  	cm_id->provider_data = cm_node;  	if (!cm_node->reused_node) { -		err = nes_manage_apbvt(nesvnic, -			ntohs(cm_id->local_addr.sin_port), -			PCI_FUNC(nesvnic->nesdev->pcidev->devfn), -			NES_MANAGE_APBVT_ADD); +		if (nes_create_mapinfo(&cm_info)) +			return -ENOMEM; + +		err = nes_manage_apbvt(nesvnic, cm_node->mapped_loc_port, +				       PCI_FUNC(nesvnic->nesdev->pcidev->devfn), +				       NES_MANAGE_APBVT_ADD);  		if (err) {  			printk(KERN_ERR "nes_manage_apbvt call returned %d.\n", -				err); +			       err);  			g_cm_core->api->stop_listener(g_cm_core, (void *)cm_node);  			return err;  		} @@ -3202,13 +3682,13 @@ int nes_destroy_listen(struct iw_cm_id *cm_id)  int nes_cm_recv(struct sk_buff *skb, struct net_device *netdevice)  {  	int rc = 0; +  	cm_packets_received++; -	if ((g_cm_core) && (g_cm_core->api)) { +	if ((g_cm_core) && (g_cm_core->api))  		rc = g_cm_core->api->recv_pkt(g_cm_core, netdev_priv(netdevice), skb); -	} else { +	else  		nes_debug(NES_DBG_CM, "Unable to process packet for CM," -				" cm is not setup properly.\n"); -	} +			  " cm is not setup properly.\n");  	return rc;  } @@ -3223,11 +3703,10 @@ int nes_cm_start(void)  	nes_debug(NES_DBG_CM, "\n");  	/* create the primary CM core, pass this handle to subsequent core inits */  	g_cm_core = nes_cm_alloc_core(); -	if (g_cm_core) { +	if (g_cm_core)  		return 0; -	} else { +	else  		return -ENOMEM; -	}  } @@ -3248,7 +3727,6 @@ int nes_cm_stop(void)   */  static void cm_event_connected(struct nes_cm_event *event)  { -	u64 u64temp;  	struct nes_qp *nesqp;  	struct nes_vnic *nesvnic;  	struct nes_device *nesdev; @@ -3257,10 +3735,12 @@ static void cm_event_connected(struct nes_cm_event *event)  	struct ib_qp_attr attr;  	struct iw_cm_id *cm_id;  	struct iw_cm_event cm_event; -	struct nes_hw_qp_wqe *wqe;  	struct nes_v4_quad nes_quad;  	u32 crc_value;  	int ret; +	struct sockaddr_in *laddr; +	struct sockaddr_in *raddr; +	struct sockaddr_in *cm_event_laddr;  	/* get all our handles */  	cm_node = event->cm_node; @@ -3270,32 +3750,26 @@ static void cm_event_connected(struct nes_cm_event *event)  	nesvnic = to_nesvnic(nesqp->ibqp.device);  	nesdev = nesvnic->nesdev;  	nesadapter = nesdev->nesadapter; +	laddr = (struct sockaddr_in *)&cm_id->local_addr; +	raddr = (struct sockaddr_in *)&cm_id->remote_addr; +	cm_event_laddr = (struct sockaddr_in *)&cm_event.local_addr; -	if (nesqp->destroyed) { +	if (nesqp->destroyed)  		return; -	}  	atomic_inc(&cm_connecteds);  	nes_debug(NES_DBG_CM, "QP%u attempting to connect to  0x%08X:0x%04X on" -			" local port 0x%04X. jiffies = %lu.\n", -			nesqp->hwqp.qp_id, -			ntohl(cm_id->remote_addr.sin_addr.s_addr), -			ntohs(cm_id->remote_addr.sin_port), -			ntohs(cm_id->local_addr.sin_port), -			jiffies); +		  " local port 0x%04X. jiffies = %lu.\n", +		  nesqp->hwqp.qp_id, ntohl(raddr->sin_addr.s_addr), +		  ntohs(raddr->sin_port), ntohs(laddr->sin_port), jiffies);  	nes_cm_init_tsa_conn(nesqp, cm_node);  	/* set the QP tsa context */  	nesqp->nesqp_context->tcpPorts[0] = -		cpu_to_le16(ntohs(cm_id->local_addr.sin_port)); +			cpu_to_le16(cm_node->mapped_loc_port);  	nesqp->nesqp_context->tcpPorts[1] = -		cpu_to_le16(ntohs(cm_id->remote_addr.sin_port)); -	if (ipv4_is_loopback(cm_id->remote_addr.sin_addr.s_addr)) -		nesqp->nesqp_context->ip0 = -			cpu_to_le32(ntohl(nesvnic->local_ipaddr)); -	else -		nesqp->nesqp_context->ip0 = -			cpu_to_le32(ntohl(cm_id->remote_addr.sin_addr.s_addr)); +			cpu_to_le16(cm_node->mapped_rem_port); +	nesqp->nesqp_context->ip0 = cpu_to_le32(cm_node->mapped_rem_addr);  	nesqp->nesqp_context->misc2 |= cpu_to_le32(  			(u32)PCI_FUNC(nesdev->pcidev->devfn) << @@ -3310,90 +3784,63 @@ static void cm_event_connected(struct nes_cm_event *event)  	nesqp->nesqp_context->ird_ord_sizes |=  			cpu_to_le32((u32)1 <<  			NES_QPCONTEXT_ORDIRD_IWARP_MODE_SHIFT); +	nesqp->nesqp_context->ird_ord_sizes |= +			cpu_to_le32((u32)cm_node->ord_size);  	/* Adjust tail for not having a LSMM */ -	nesqp->hwqp.sq_tail = 1; - -#if defined(NES_SEND_FIRST_WRITE) -	if (cm_node->send_write0) { -		nes_debug(NES_DBG_CM, "Sending first write.\n"); -		wqe = &nesqp->hwqp.sq_vbase[0]; -		u64temp = (unsigned long)nesqp; -		u64temp |= NES_SW_CONTEXT_ALIGN>>1; -		set_wqe_64bit_value(wqe->wqe_words, -				NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX, u64temp); -		wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] = -			cpu_to_le32(NES_IWARP_SQ_OP_RDMAW); -		wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] = 0; -		wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_LOW_IDX] = 0; -		wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_HIGH_IDX] = 0; -		wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] = 0; -		wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 0; +	/*nesqp->hwqp.sq_tail = 1;*/ -		if (nesqp->sq_kmapped) { -			nesqp->sq_kmapped = 0; -			kunmap(nesqp->page); -		} +	build_rdma0_msg(cm_node, &nesqp); -		/* use the reserved spot on the WQ for the extra first WQE */ -		nesqp->nesqp_context->ird_ord_sizes &= -			cpu_to_le32(~(NES_QPCONTEXT_ORDIRD_LSMM_PRESENT | -						NES_QPCONTEXT_ORDIRD_WRPDU | -						NES_QPCONTEXT_ORDIRD_ALSMM)); -		nesqp->skip_lsmm = 1; -		nesqp->hwqp.sq_tail = 0; -		nes_write32(nesdev->regs + NES_WQE_ALLOC, -				(1 << 24) | 0x00800000 | nesqp->hwqp.qp_id); -	} -#endif +	nes_write32(nesdev->regs + NES_WQE_ALLOC, +		    (1 << 24) | 0x00800000 | nesqp->hwqp.qp_id);  	memset(&nes_quad, 0, sizeof(nes_quad));  	nes_quad.DstIpAdrIndex =  		cpu_to_le32((u32)PCI_FUNC(nesdev->pcidev->devfn) << 24); -	if (ipv4_is_loopback(cm_id->remote_addr.sin_addr.s_addr)) -		nes_quad.SrcIpadr = nesvnic->local_ipaddr; -	else -		nes_quad.SrcIpadr = cm_id->remote_addr.sin_addr.s_addr; -	nes_quad.TcpPorts[0] = cm_id->remote_addr.sin_port; -	nes_quad.TcpPorts[1] = cm_id->local_addr.sin_port; +	nes_quad.SrcIpadr = htonl(cm_node->mapped_rem_addr); +	nes_quad.TcpPorts[0] = htons(cm_node->mapped_rem_port); +	nes_quad.TcpPorts[1] = htons(cm_node->mapped_loc_port);  	/* Produce hash key */  	crc_value = get_crc_value(&nes_quad);  	nesqp->hte_index = cpu_to_be32(crc_value ^ 0xffffffff);  	nes_debug(NES_DBG_CM, "HTE Index = 0x%08X, After CRC = 0x%08X\n", -			nesqp->hte_index, nesqp->hte_index & nesadapter->hte_index_mask); +		  nesqp->hte_index, nesqp->hte_index & nesadapter->hte_index_mask);  	nesqp->hte_index &= nesadapter->hte_index_mask;  	nesqp->nesqp_context->hte_index = cpu_to_le32(nesqp->hte_index);  	nesqp->ietf_frame = &cm_node->mpa_frame; -	nesqp->private_data_len = (u8) cm_node->mpa_frame_size; +	nesqp->private_data_len = (u8)cm_node->mpa_frame_size;  	cm_node->cm_core->api->accelerated(cm_node->cm_core, cm_node);  	/* notify OF layer we successfully created the requested connection */  	cm_event.event = IW_CM_EVENT_CONNECT_REPLY; -	cm_event.status = IW_CM_EVENT_STATUS_ACCEPTED; +	cm_event.status = 0;  	cm_event.provider_data = cm_id->provider_data; -	cm_event.local_addr.sin_family = AF_INET; -	cm_event.local_addr.sin_port = cm_id->local_addr.sin_port; +	cm_event_laddr->sin_family = AF_INET; +	cm_event_laddr->sin_port = laddr->sin_port;  	cm_event.remote_addr = cm_id->remote_addr;  	cm_event.private_data = (void *)event->cm_node->mpa_frame_buf; -	cm_event.private_data_len = (u8) event->cm_node->mpa_frame_size; +	cm_event.private_data_len = (u8)event->cm_node->mpa_frame_size; +	cm_event.ird = cm_node->ird_size; +	cm_event.ord = cm_node->ord_size; -	cm_event.local_addr.sin_addr.s_addr = event->cm_info.rem_addr; +	cm_event_laddr->sin_addr.s_addr = htonl(event->cm_info.rem_addr);  	ret = cm_id->event_handler(cm_id, &cm_event);  	nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret);  	if (ret)  		printk(KERN_ERR "%s[%u] OFA CM event_handler returned, " -			"ret=%d\n", __func__, __LINE__, ret); +		       "ret=%d\n", __func__, __LINE__, ret);  	attr.qp_state = IB_QPS_RTS;  	nes_modify_qp(&nesqp->ibqp, &attr, IB_QP_STATE, NULL);  	nes_debug(NES_DBG_CM, "Exiting connect thread for QP%u. jiffies = " -		"%lu\n", nesqp->hwqp.qp_id, jiffies); +		  "%lu\n", nesqp->hwqp.qp_id, jiffies);  	return;  } @@ -3414,16 +3861,14 @@ static void cm_event_connect_error(struct nes_cm_event *event)  		return;  	cm_id = event->cm_node->cm_id; -	if (!cm_id) { +	if (!cm_id)  		return; -	}  	nes_debug(NES_DBG_CM, "cm_node=%p, cm_id=%p\n", event->cm_node, cm_id);  	nesqp = cm_id->provider_data; -	if (!nesqp) { +	if (!nesqp)  		return; -	}  	/* notify OF layer about this connection error event */  	/* cm_id->rem_ref(cm_id); */ @@ -3437,15 +3882,22 @@ static void cm_event_connect_error(struct nes_cm_event *event)  	cm_event.private_data = NULL;  	cm_event.private_data_len = 0; -	nes_debug(NES_DBG_CM, "call CM_EVENT REJECTED, local_addr=%08x, " -		"remove_addr=%08x\n", cm_event.local_addr.sin_addr.s_addr, -		cm_event.remote_addr.sin_addr.s_addr); +#ifdef CONFIG_INFINIBAND_NES_DEBUG +	{ +		struct sockaddr_in *cm_event_laddr = (struct sockaddr_in *) +						     &cm_event.local_addr; +		struct sockaddr_in *cm_event_raddr = (struct sockaddr_in *) +						     &cm_event.remote_addr; +		nes_debug(NES_DBG_CM, "call CM_EVENT REJECTED, local_addr=%08x, remote_addr=%08x\n", +			  cm_event_laddr->sin_addr.s_addr, cm_event_raddr->sin_addr.s_addr); +	} +#endif  	ret = cm_id->event_handler(cm_id, &cm_event);  	nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret);  	if (ret)  		printk(KERN_ERR "%s[%u] OFA CM event_handler returned, " -			"ret=%d\n", __func__, __LINE__, ret); +		       "ret=%d\n", __func__, __LINE__, ret);  	cm_id->rem_ref(cm_id);  	rem_ref_cm_node(event->cm_node->cm_core, event->cm_node); @@ -3480,7 +3932,7 @@ static void cm_event_reset(struct nes_cm_event *event)  	nesqp->cm_id = NULL;  	/* cm_id->provider_data = NULL; */  	cm_event.event = IW_CM_EVENT_DISCONNECT; -	cm_event.status = IW_CM_EVENT_STATUS_RESET; +	cm_event.status = -ECONNRESET;  	cm_event.provider_data = cm_id->provider_data;  	cm_event.local_addr = cm_id->local_addr;  	cm_event.remote_addr = cm_id->remote_addr; @@ -3491,7 +3943,7 @@ static void cm_event_reset(struct nes_cm_event *event)  	ret = cm_id->event_handler(cm_id, &cm_event);  	atomic_inc(&cm_closes);  	cm_event.event = IW_CM_EVENT_CLOSE; -	cm_event.status = IW_CM_EVENT_STATUS_OK; +	cm_event.status = 0;  	cm_event.provider_data = cm_id->provider_data;  	cm_event.local_addr = cm_id->local_addr;  	cm_event.remote_addr = cm_id->remote_addr; @@ -3515,10 +3967,14 @@ static void cm_event_reset(struct nes_cm_event *event)   */  static void cm_event_mpa_req(struct nes_cm_event *event)  { -	struct iw_cm_id   *cm_id; +	struct iw_cm_id *cm_id;  	struct iw_cm_event cm_event;  	int ret;  	struct nes_cm_node *cm_node; +	struct sockaddr_in *cm_event_laddr = (struct sockaddr_in *) +					     &cm_event.local_addr; +	struct sockaddr_in *cm_event_raddr = (struct sockaddr_in *) +					     &cm_event.remote_addr;  	cm_node = event->cm_node;  	if (!cm_node) @@ -3527,36 +3983,47 @@ static void cm_event_mpa_req(struct nes_cm_event *event)  	atomic_inc(&cm_connect_reqs);  	nes_debug(NES_DBG_CM, "cm_node = %p - cm_id = %p, jiffies = %lu\n", -			cm_node, cm_id, jiffies); +		  cm_node, cm_id, jiffies);  	cm_event.event = IW_CM_EVENT_CONNECT_REQUEST; -	cm_event.status = IW_CM_EVENT_STATUS_OK; +	cm_event.status = 0;  	cm_event.provider_data = (void *)cm_node; -	cm_event.local_addr.sin_family = AF_INET; -	cm_event.local_addr.sin_port = htons(event->cm_info.loc_port); -	cm_event.local_addr.sin_addr.s_addr = htonl(event->cm_info.loc_addr); +	cm_event_laddr->sin_family = AF_INET; +	cm_event_laddr->sin_port = htons(event->cm_info.loc_port); +	cm_event_laddr->sin_addr.s_addr = htonl(event->cm_info.loc_addr); -	cm_event.remote_addr.sin_family = AF_INET; -	cm_event.remote_addr.sin_port = htons(event->cm_info.rem_port); -	cm_event.remote_addr.sin_addr.s_addr = htonl(event->cm_info.rem_addr); +	cm_event_raddr->sin_family = AF_INET; +	cm_event_raddr->sin_port = htons(event->cm_info.rem_port); +	cm_event_raddr->sin_addr.s_addr = htonl(event->cm_info.rem_addr);  	cm_event.private_data = cm_node->mpa_frame_buf; -	cm_event.private_data_len  = (u8) cm_node->mpa_frame_size; +	cm_event.private_data_len = (u8)cm_node->mpa_frame_size; +	if (cm_node->mpa_frame_rev == IETF_MPA_V1) { +		cm_event.ird = NES_MAX_IRD; +		cm_event.ord = NES_MAX_ORD; +	} else { +	cm_event.ird = cm_node->ird_size; +	cm_event.ord = cm_node->ord_size; +	}  	ret = cm_id->event_handler(cm_id, &cm_event);  	if (ret)  		printk(KERN_ERR "%s[%u] OFA CM event_handler returned, ret=%d\n", -				__func__, __LINE__, ret); +		       __func__, __LINE__, ret);  	return;  }  static void cm_event_mpa_reject(struct nes_cm_event *event)  { -	struct iw_cm_id   *cm_id; +	struct iw_cm_id *cm_id;  	struct iw_cm_event cm_event;  	struct nes_cm_node *cm_node;  	int ret; +	struct sockaddr_in *cm_event_laddr = (struct sockaddr_in *) +					     &cm_event.local_addr; +	struct sockaddr_in *cm_event_raddr = (struct sockaddr_in *) +					     &cm_event.remote_addr;  	cm_node = event->cm_node;  	if (!cm_node) @@ -3565,32 +4032,32 @@ static void cm_event_mpa_reject(struct nes_cm_event *event)  	atomic_inc(&cm_connect_reqs);  	nes_debug(NES_DBG_CM, "cm_node = %p - cm_id = %p, jiffies = %lu\n", -			cm_node, cm_id, jiffies); +		  cm_node, cm_id, jiffies);  	cm_event.event = IW_CM_EVENT_CONNECT_REPLY;  	cm_event.status = -ECONNREFUSED;  	cm_event.provider_data = cm_id->provider_data; -	cm_event.local_addr.sin_family = AF_INET; -	cm_event.local_addr.sin_port = htons(event->cm_info.loc_port); -	cm_event.local_addr.sin_addr.s_addr = htonl(event->cm_info.loc_addr); +	cm_event_laddr->sin_family = AF_INET; +	cm_event_laddr->sin_port = htons(event->cm_info.loc_port); +	cm_event_laddr->sin_addr.s_addr = htonl(event->cm_info.loc_addr); -	cm_event.remote_addr.sin_family = AF_INET; -	cm_event.remote_addr.sin_port = htons(event->cm_info.rem_port); -	cm_event.remote_addr.sin_addr.s_addr = htonl(event->cm_info.rem_addr); +	cm_event_raddr->sin_family = AF_INET; +	cm_event_raddr->sin_port = htons(event->cm_info.rem_port); +	cm_event_raddr->sin_addr.s_addr = htonl(event->cm_info.rem_addr);  	cm_event.private_data = cm_node->mpa_frame_buf; -	cm_event.private_data_len = (u8) cm_node->mpa_frame_size; +	cm_event.private_data_len = (u8)cm_node->mpa_frame_size;  	nes_debug(NES_DBG_CM, "call CM_EVENT_MPA_REJECTED, local_addr=%08x, " -			"remove_addr=%08x\n", -			cm_event.local_addr.sin_addr.s_addr, -			cm_event.remote_addr.sin_addr.s_addr); +		  "remove_addr=%08x\n", +		  cm_event_laddr->sin_addr.s_addr, +		  cm_event_raddr->sin_addr.s_addr);  	ret = cm_id->event_handler(cm_id, &cm_event);  	if (ret)  		printk(KERN_ERR "%s[%u] OFA CM event_handler returned, ret=%d\n", -				__func__, __LINE__, ret); +		       __func__, __LINE__, ret);  	return;  } @@ -3609,7 +4076,7 @@ static int nes_cm_post_event(struct nes_cm_event *event)  	event->cm_info.cm_id->add_ref(event->cm_info.cm_id);  	INIT_WORK(&event->event_work, nes_cm_event_handler);  	nes_debug(NES_DBG_CM, "cm_node=%p queue_work, event=%p\n", -		event->cm_node, event); +		  event->cm_node, event);  	queue_work(event->cm_node->cm_core->event_wq, &event->event_work); @@ -3626,7 +4093,7 @@ static int nes_cm_post_event(struct nes_cm_event *event)  static void nes_cm_event_handler(struct work_struct *work)  {  	struct nes_cm_event *event = container_of(work, struct nes_cm_event, -			event_work); +						  event_work);  	struct nes_cm_core *cm_core;  	if ((!event) || (!event->cm_node) || (!event->cm_node->cm_core)) @@ -3634,29 +4101,29 @@ static void nes_cm_event_handler(struct work_struct *work)  	cm_core = event->cm_node->cm_core;  	nes_debug(NES_DBG_CM, "event=%p, event->type=%u, events posted=%u\n", -		event, event->type, atomic_read(&cm_core->events_posted)); +		  event, event->type, atomic_read(&cm_core->events_posted));  	switch (event->type) {  	case NES_CM_EVENT_MPA_REQ:  		cm_event_mpa_req(event);  		nes_debug(NES_DBG_CM, "cm_node=%p CM Event: MPA REQUEST\n", -			event->cm_node); +			  event->cm_node);  		break;  	case NES_CM_EVENT_RESET:  		nes_debug(NES_DBG_CM, "cm_node = %p CM Event: RESET\n", -			event->cm_node); +			  event->cm_node);  		cm_event_reset(event);  		break;  	case NES_CM_EVENT_CONNECTED:  		if ((!event->cm_node->cm_id) || -			(event->cm_node->state != NES_CM_STATE_TSA)) +		    (event->cm_node->state != NES_CM_STATE_TSA))  			break;  		cm_event_connected(event);  		nes_debug(NES_DBG_CM, "CM Event: CONNECTED\n");  		break;  	case NES_CM_EVENT_MPA_REJECT:  		if ((!event->cm_node->cm_id) || -				(event->cm_node->state == NES_CM_STATE_TSA)) +		    (event->cm_node->state == NES_CM_STATE_TSA))  			break;  		cm_event_mpa_reject(event);  		nes_debug(NES_DBG_CM, "CM Event: REJECT\n"); @@ -3664,7 +4131,7 @@ static void nes_cm_event_handler(struct work_struct *work)  	case NES_CM_EVENT_ABORTED:  		if ((!event->cm_node->cm_id) || -			(event->cm_node->state == NES_CM_STATE_TSA)) +		    (event->cm_node->state == NES_CM_STATE_TSA))  			break;  		cm_event_connect_error(event);  		nes_debug(NES_DBG_CM, "CM Event: ABORTED\n");  | 
