diff options
Diffstat (limited to 'drivers/infiniband/hw/nes/nes_cm.c')
| -rw-r--r-- | drivers/infiniband/hw/nes/nes_cm.c | 444 | 
1 files changed, 352 insertions, 92 deletions
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index 6b29249aa85..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 - 2011 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 @@ -59,6 +59,7 @@  #include <net/route.h>  #include <net/ip_fib.h>  #include <net/tcp.h> +#include <linux/fcntl.h>  #include "nes.h" @@ -128,6 +129,7 @@ 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 */ @@ -165,7 +167,6 @@ 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   */ @@ -317,7 +318,6 @@ static int parse_mpa(struct nes_cm_node *cm_node, u8 *buffer, u32 *type,  		}  	} -  	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", @@ -356,25 +356,57 @@ static int parse_mpa(struct nes_cm_node *cm_node, u8 *buffer, u32 *type,  			/* 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->state != NES_CM_STATE_MPAREQ_SENT) { +		if (cm_node->mpav2_ird_ord != IETF_NO_IRD_ORD) {  			/* responder */ -			if (cm_node->ord_size > ird_size) -				cm_node->ord_size = ird_size; -		} else { -			/* initiator */ -			if (cm_node->ord_size > ird_size) -				cm_node->ord_size = ird_size; - -			if (cm_node->ird_size < ord_size) { -				/* no resources available */ -				/* send terminate message */ -				return -EINVAL; +			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 */ @@ -450,11 +482,11 @@ static void form_cm_frame(struct sk_buff *skb,  	iph->ttl = 0x40;  	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) { @@ -493,6 +525,100 @@ static void form_cm_frame(struct sk_buff *skb,  	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   */ @@ -514,6 +640,19 @@ 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   */ @@ -557,11 +696,13 @@ static void build_mpa_v2(struct nes_cm_node *cm_node,  	mpa_frame->priv_data_len += htons(IETF_RTR_MSG_SIZE);  	/* initialize RTR msg */ -	ctrl_ird = (cm_node->ird_size > IETF_NO_IRD_ORD) ? -			    IETF_NO_IRD_ORD : cm_node->ird_size; -	ctrl_ord = (cm_node->ord_size > IETF_NO_IRD_ORD) ? -			    IETF_NO_IRD_ORD : cm_node->ord_size; - +	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; @@ -610,7 +751,7 @@ static void build_rdma0_msg(struct nes_cm_node *cm_node, struct nes_qp **nesqp_a  	struct nes_qp *nesqp = *nesqp_addr;  	struct nes_hw_qp_wqe *wqe = &nesqp->hwqp.sq_vbase[0]; -	u64temp = (unsigned long)nesqp; +	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); @@ -1100,8 +1241,11 @@ static struct nes_cm_node *find_node(struct nes_cm_core *cm_core,  			  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)) { +		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; @@ -1118,18 +1262,28 @@ 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) && +		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); @@ -1142,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   */ @@ -1263,9 +1416,20 @@ 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); +		if (listener->nesvnic) { +			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); @@ -1354,8 +1518,7 @@ 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 */  					goto out;  				} @@ -1408,10 +1571,16 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,  	cm_node->loc_port = cm_info->loc_port;  	cm_node->rem_port = cm_info->rem_port; +	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->ird_size = IETF_NO_IRD_ORD; -	cm_node->ord_size = IETF_NO_IRD_ORD; +	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, @@ -1453,8 +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 */ -	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; @@ -1516,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(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); @@ -2188,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);  	/* 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); @@ -2207,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) { @@ -2214,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); @@ -2277,14 +2473,18 @@ 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); @@ -2513,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); @@ -2521,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 */ @@ -2531,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; @@ -3028,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); @@ -3055,6 +3261,11 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)  	if (cm_node->mpa_frame_rev == IETF_MPA_V1)  		mpa_frame_offset = 4; +	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(mpa_v2_frame->priv_data, conn_param->private_data,  	       conn_param->private_data_len); @@ -3118,7 +3329,6 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)  	}  	nesqp->skip_lsmm = 1; -  	/* Cache the cm_id in the qp */  	nesqp->cm_id = cm_id;  	cm_node->cm_id = cm_id; @@ -3133,10 +3343,12 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)  	nes_cm_init_tsa_conn(nesqp, cm_node); -	nesqp->nesqp_context->tcpPorts[0] = cpu_to_le16(ntohs(laddr->sin_port)); -	nesqp->nesqp_context->tcpPorts[1] = cpu_to_le16(ntohs(raddr->sin_port)); +	nesqp->nesqp_context->tcpPorts[0] = +				cpu_to_le16(cm_node->mapped_loc_port); +	nesqp->nesqp_context->tcpPorts[1] = +				cpu_to_le16(cm_node->mapped_rem_port); -	nesqp->nesqp_context->ip0 = cpu_to_le32(ntohl(raddr->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) << @@ -3155,14 +3367,14 @@ 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); -	nes_quad.SrcIpadr = raddr->sin_addr.s_addr; -	nes_quad.TcpPorts[0] = raddr->sin_port; -	nes_quad.TcpPorts[1] = laddr->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); @@ -3195,6 +3407,9 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)  	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); @@ -3261,6 +3476,9 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)  	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; @@ -3291,33 +3509,51 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)  	/* 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); -	/* space for rdma0 read msg */ -	if (conn_param->ord == 0) -		nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32(1);  	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); +	/* 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; + +	/* 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, ntohs(laddr->sin_port), -				 PCI_FUNC(nesdev->pcidev->devfn), -				 NES_MANAGE_APBVT_ADD); +		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(laddr->sin_addr.s_addr); -	cm_info.loc_port = htons(laddr->sin_port); -	cm_info.rem_addr = htonl(raddr->sin_addr.s_addr); -	cm_info.rem_port = htons(raddr->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); @@ -3327,14 +3563,23 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)  					  &cm_info);  	if (!cm_node) {  		if (apbvt_set) -			nes_manage_apbvt(nesvnic, ntohs(laddr->sin_port), +			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; @@ -3371,13 +3616,16 @@ int nes_create_listen(struct iw_cm_id *cm_id, int backlog)  			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 = laddr->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) { @@ -3389,7 +3637,10 @@ int nes_create_listen(struct iw_cm_id *cm_id, int backlog)  	cm_id->provider_data = cm_node;  	if (!cm_node->reused_node) { -		err = nes_manage_apbvt(nesvnic, ntohs(laddr->sin_port), +		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) { @@ -3514,9 +3765,11 @@ static void cm_event_connected(struct nes_cm_event *event)  	nes_cm_init_tsa_conn(nesqp, cm_node);  	/* set the QP tsa context */ -	nesqp->nesqp_context->tcpPorts[0] = cpu_to_le16(ntohs(laddr->sin_port)); -	nesqp->nesqp_context->tcpPorts[1] = cpu_to_le16(ntohs(raddr->sin_port)); -	nesqp->nesqp_context->ip0 = cpu_to_le32(ntohl(raddr->sin_addr.s_addr)); +	nesqp->nesqp_context->tcpPorts[0] = +			cpu_to_le16(cm_node->mapped_loc_port); +	nesqp->nesqp_context->tcpPorts[1] = +			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) << @@ -3531,6 +3784,8 @@ 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;*/ @@ -3544,9 +3799,9 @@ static void cm_event_connected(struct nes_cm_event *event)  	nes_quad.DstIpAdrIndex =  		cpu_to_le32((u32)PCI_FUNC(nesdev->pcidev->devfn) << 24); -	nes_quad.SrcIpadr = raddr->sin_addr.s_addr; -	nes_quad.TcpPorts[0] = raddr->sin_port; -	nes_quad.TcpPorts[1] = laddr->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); @@ -3574,7 +3829,7 @@ static void cm_event_connected(struct nes_cm_event *event)  	cm_event.ird = cm_node->ird_size;  	cm_event.ord = cm_node->ord_size; -	cm_event_laddr->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); @@ -3743,8 +3998,13 @@ static void cm_event_mpa_req(struct nes_cm_event *event)  	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; +	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)  | 
