diff options
Diffstat (limited to 'drivers/infiniband/hw/nes')
| -rw-r--r-- | drivers/infiniband/hw/nes/nes.c | 30 | ||||
| -rw-r--r-- | drivers/infiniband/hw/nes/nes.h | 3 | ||||
| -rw-r--r-- | drivers/infiniband/hw/nes/nes_cm.c | 444 | ||||
| -rw-r--r-- | drivers/infiniband/hw/nes/nes_cm.h | 15 | ||||
| -rw-r--r-- | drivers/infiniband/hw/nes/nes_user.h | 5 | ||||
| -rw-r--r-- | drivers/infiniband/hw/nes/nes_verbs.c | 263 | ||||
| -rw-r--r-- | drivers/infiniband/hw/nes/nes_verbs.h | 1 | 
7 files changed, 531 insertions, 230 deletions
diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c index 429141078ee..3b2a6dc8ea9 100644 --- a/drivers/infiniband/hw/nes/nes.c +++ b/drivers/infiniband/hw/nes/nes.c @@ -68,7 +68,6 @@ MODULE_VERSION(DRV_VERSION);  int max_mtu = 9000;  int interrupt_mod_interval = 0; -  /* Interoperability */  int mpa_version = 1;  module_param(mpa_version, int, 0644); @@ -112,6 +111,16 @@ static struct pci_device_id nes_pci_table[] = {  MODULE_DEVICE_TABLE(pci, nes_pci_table); +/* registered nes netlink callbacks */ +static struct ibnl_client_cbs nes_nl_cb_table[] = { +	[RDMA_NL_IWPM_REG_PID] = {.dump = iwpm_register_pid_cb}, +	[RDMA_NL_IWPM_ADD_MAPPING] = {.dump = iwpm_add_mapping_cb}, +	[RDMA_NL_IWPM_QUERY_MAPPING] = {.dump = iwpm_add_and_query_mapping_cb}, +	[RDMA_NL_IWPM_HANDLE_ERR] = {.dump = iwpm_mapping_error_cb}, +	[RDMA_NL_IWPM_MAPINFO] = {.dump = iwpm_mapping_info_cb}, +	[RDMA_NL_IWPM_MAPINFO_NUM] = {.dump = iwpm_ack_mapping_info_cb} +}; +  static int nes_inetaddr_event(struct notifier_block *, unsigned long, void *);  static int nes_net_event(struct notifier_block *, unsigned long, void *);  static int nes_notifiers_registered; @@ -672,11 +681,25 @@ static int nes_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)  	}  	nes_notifiers_registered++; +	if (ibnl_add_client(RDMA_NL_NES, RDMA_NL_IWPM_NUM_OPS, nes_nl_cb_table)) +		printk(KERN_ERR PFX "%s[%u]: Failed to add netlink callback\n", +			__func__, __LINE__); + +	ret = iwpm_init(RDMA_NL_NES); +	if (ret) { +		printk(KERN_ERR PFX "%s: port mapper initialization failed\n", +				pci_name(pcidev)); +		goto bail7; +	} +  	INIT_DELAYED_WORK(&nesdev->work, nes_recheck_link_status);  	/* Initialize network devices */ -	if ((netdev = nes_netdev_init(nesdev, mmio_regs)) == NULL) +	netdev = nes_netdev_init(nesdev, mmio_regs); +	if (netdev == NULL) { +		ret = -ENOMEM;  		goto bail7; +	}  	/* Register network device */  	ret = register_netdev(netdev); @@ -707,6 +730,7 @@ static int nes_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)  	nes_debug(NES_DBG_INIT, "netdev_count=%d, nesadapter->netdev_count=%d\n",  			nesdev->netdev_count, nesdev->nesadapter->netdev_count); +	ibnl_remove_client(RDMA_NL_NES);  	nes_notifiers_registered--;  	if (nes_notifiers_registered == 0) { @@ -770,6 +794,8 @@ static void nes_remove(struct pci_dev *pcidev)  				nesdev->nesadapter->netdev_count--;  			}  		} +	ibnl_remove_client(RDMA_NL_NES); +	iwpm_exit(RDMA_NL_NES);  	nes_notifiers_registered--;  	if (nes_notifiers_registered == 0) { diff --git a/drivers/infiniband/hw/nes/nes.h b/drivers/infiniband/hw/nes/nes.h index 33cc58941a3..bd9d132f11c 100644 --- a/drivers/infiniband/hw/nes/nes.h +++ b/drivers/infiniband/hw/nes/nes.h @@ -51,6 +51,8 @@  #include <rdma/ib_pack.h>  #include <rdma/rdma_cm.h>  #include <rdma/iw_cm.h> +#include <rdma/rdma_netlink.h> +#include <rdma/iw_portmap.h>  #define NES_SEND_FIRST_WRITE @@ -130,6 +132,7 @@  #define NES_DBG_IW_TX       0x00040000  #define NES_DBG_SHUTDOWN    0x00080000  #define NES_DBG_PAU         0x00100000 +#define NES_DBG_NLMSG       0x00200000  #define NES_DBG_RSVD1       0x10000000  #define NES_DBG_RSVD2       0x20000000  #define NES_DBG_RSVD3       0x40000000 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) diff --git a/drivers/infiniband/hw/nes/nes_cm.h b/drivers/infiniband/hw/nes/nes_cm.h index 4646e666608..f522cf63978 100644 --- a/drivers/infiniband/hw/nes/nes_cm.h +++ b/drivers/infiniband/hw/nes/nes_cm.h @@ -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 @@ -58,6 +58,8 @@  #define IETF_RDMA0_WRITE        0x8000  #define IETF_RDMA0_READ         0x4000  #define IETF_NO_IRD_ORD         0x3FFF +#define NES_MAX_IRD		 0x40 +#define NES_MAX_ORD		 0x7F  enum ietf_mpa_flags {  	IETF_MPA_FLAGS_MARKERS = 0x80,	/* receive Markers */ @@ -291,8 +293,8 @@ struct nes_cm_listener {  	struct list_head           list;  	struct nes_cm_core         *cm_core;  	u8                         loc_mac[ETH_ALEN]; -	nes_addr_t                 loc_addr; -	u16                        loc_port; +	nes_addr_t                 loc_addr, mapped_loc_addr; +	u16                        loc_port, mapped_loc_port;  	struct iw_cm_id            *cm_id;  	enum nes_cm_conn_type      conn_type;  	atomic_t                   ref_count; @@ -306,7 +308,9 @@ struct nes_cm_listener {  /* per connection node and node state information */  struct nes_cm_node {  	nes_addr_t                loc_addr, rem_addr; +	nes_addr_t                mapped_loc_addr, mapped_rem_addr;  	u16                       loc_port, rem_port; +	u16                       mapped_loc_port, mapped_rem_port;  	u8                        loc_mac[ETH_ALEN];  	u8                        rem_mac[ETH_ALEN]; @@ -333,6 +337,7 @@ struct nes_cm_node {  	enum mpa_frame_version    mpa_frame_rev;  	u16			  ird_size;  	u16                       ord_size; +	u16			  mpav2_ird_ord;  	u16                       mpa_frame_size;  	struct iw_cm_id           *cm_id; @@ -361,6 +366,10 @@ struct nes_cm_info {  	u16 rem_port;  	nes_addr_t loc_addr;  	nes_addr_t rem_addr; +	u16 mapped_loc_port; +	u16 mapped_rem_port; +	nes_addr_t mapped_loc_addr; +	nes_addr_t mapped_rem_addr;  	enum nes_cm_conn_type  conn_type;  	int backlog; diff --git a/drivers/infiniband/hw/nes/nes_user.h b/drivers/infiniband/hw/nes/nes_user.h index 4926de74448..529c421bb15 100644 --- a/drivers/infiniband/hw/nes/nes_user.h +++ b/drivers/infiniband/hw/nes/nes_user.h @@ -39,8 +39,8 @@  #include <linux/types.h> -#define NES_ABI_USERSPACE_VER 1 -#define NES_ABI_KERNEL_VER    1 +#define NES_ABI_USERSPACE_VER 2 +#define NES_ABI_KERNEL_VER    2  /*   * Make sure that all structs defined in this file remain laid out so @@ -78,6 +78,7 @@ struct nes_create_cq_req {  struct nes_create_qp_req {  	__u64 user_wqe_buffers; +	__u64 user_qp_buffer;  };  enum iwnes_memreg_type { diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c index 5b53ca5a228..218dd357428 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.c +++ b/drivers/infiniband/hw/nes/nes_verbs.c @@ -1186,11 +1186,13 @@ static struct ib_qp *nes_create_qp(struct ib_pd *ibpd,  					nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num);  					kfree(nesqp->allocated_buffer);  					nes_debug(NES_DBG_QP, "ib_copy_from_udata() Failed \n"); -					return NULL; +					return ERR_PTR(-EFAULT);  				}  				if (req.user_wqe_buffers) {  					virt_wqs = 1;  				} +				if (req.user_qp_buffer) +					nesqp->nesuqp_addr = req.user_qp_buffer;  				if ((ibpd->uobject) && (ibpd->uobject->context)) {  					nesqp->user_mode = 1;  					nes_ucontext = to_nesucontext(ibpd->uobject->context); @@ -2307,7 +2309,7 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,  	struct nes_device *nesdev = nesvnic->nesdev;  	struct nes_adapter *nesadapter = nesdev->nesadapter;  	struct ib_mr *ibmr = ERR_PTR(-EINVAL); -	struct ib_umem_chunk *chunk; +	struct scatterlist *sg;  	struct nes_ucontext *nes_ucontext;  	struct nes_pbl *nespbl;  	struct nes_mr *nesmr; @@ -2315,7 +2317,7 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,  	struct nes_mem_reg_req req;  	struct nes_vpbl vpbl;  	struct nes_root_vpbl root_vpbl; -	int nmap_index, page_index; +	int entry, page_index;  	int page_count = 0;  	int err, pbl_depth = 0;  	int chunk_pages; @@ -2330,6 +2332,7 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,  	u16 pbl_count;  	u8 single_page = 1;  	u8 stag_key; +	int first_page = 1;  	region = ib_umem_get(pd->uobject->context, start, length, acc, 0);  	if (IS_ERR(region)) { @@ -2380,128 +2383,125 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,  			}  			nesmr->region = region; -			list_for_each_entry(chunk, ®ion->chunk_list, list) { -				nes_debug(NES_DBG_MR, "Chunk: nents = %u, nmap = %u .\n", -						chunk->nents, chunk->nmap); -				for (nmap_index = 0; nmap_index < chunk->nmap; ++nmap_index) { -					if (sg_dma_address(&chunk->page_list[nmap_index]) & ~PAGE_MASK) { -						ib_umem_release(region); -						nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index); -						nes_debug(NES_DBG_MR, "Unaligned Memory Buffer: 0x%x\n", -								(unsigned int) sg_dma_address(&chunk->page_list[nmap_index])); -						ibmr = ERR_PTR(-EINVAL); -						kfree(nesmr); -						goto reg_user_mr_err; -					} +			for_each_sg(region->sg_head.sgl, sg, region->nmap, entry) { +				if (sg_dma_address(sg) & ~PAGE_MASK) { +					ib_umem_release(region); +					nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index); +					nes_debug(NES_DBG_MR, "Unaligned Memory Buffer: 0x%x\n", +						  (unsigned int) sg_dma_address(sg)); +					ibmr = ERR_PTR(-EINVAL); +					kfree(nesmr); +					goto reg_user_mr_err; +				} -					if (!sg_dma_len(&chunk->page_list[nmap_index])) { -						ib_umem_release(region); -						nes_free_resource(nesadapter, nesadapter->allocated_mrs, -								stag_index); -						nes_debug(NES_DBG_MR, "Invalid Buffer Size\n"); -						ibmr = ERR_PTR(-EINVAL); -						kfree(nesmr); -						goto reg_user_mr_err; -					} +				if (!sg_dma_len(sg)) { +					ib_umem_release(region); +					nes_free_resource(nesadapter, nesadapter->allocated_mrs, +							  stag_index); +					nes_debug(NES_DBG_MR, "Invalid Buffer Size\n"); +					ibmr = ERR_PTR(-EINVAL); +					kfree(nesmr); +					goto reg_user_mr_err; +				} -					region_length += sg_dma_len(&chunk->page_list[nmap_index]); -					chunk_pages = sg_dma_len(&chunk->page_list[nmap_index]) >> 12; -					region_length -= skip_pages << 12; -					for (page_index=skip_pages; page_index < chunk_pages; page_index++) { -						skip_pages = 0; -						if ((page_count!=0)&&(page_count<<12)-(region->offset&(4096-1))>=region->length) -							goto enough_pages; -						if ((page_count&0x01FF) == 0) { -							if (page_count >= 1024 * 512) { +				region_length += sg_dma_len(sg); +				chunk_pages = sg_dma_len(sg) >> 12; +				region_length -= skip_pages << 12; +				for (page_index = skip_pages; page_index < chunk_pages; page_index++) { +					skip_pages = 0; +					if ((page_count != 0) && (page_count<<12)-(region->offset&(4096-1)) >= region->length) +						goto enough_pages; +					if ((page_count&0x01FF) == 0) { +						if (page_count >= 1024 * 512) { +							ib_umem_release(region); +							nes_free_resource(nesadapter, +									  nesadapter->allocated_mrs, stag_index); +							kfree(nesmr); +							ibmr = ERR_PTR(-E2BIG); +							goto reg_user_mr_err; +						} +						if (root_pbl_index == 1) { +							root_vpbl.pbl_vbase = pci_alloc_consistent(nesdev->pcidev, +									8192, &root_vpbl.pbl_pbase); +							nes_debug(NES_DBG_MR, "Allocating root PBL, va = %p, pa = 0x%08X\n", +								  root_vpbl.pbl_vbase, (unsigned int)root_vpbl.pbl_pbase); +							if (!root_vpbl.pbl_vbase) {  								ib_umem_release(region); -								nes_free_resource(nesadapter, -										nesadapter->allocated_mrs, stag_index); +								pci_free_consistent(nesdev->pcidev, 4096, vpbl.pbl_vbase, +										    vpbl.pbl_pbase); +								nes_free_resource(nesadapter, nesadapter->allocated_mrs, +										  stag_index);  								kfree(nesmr); -								ibmr = ERR_PTR(-E2BIG); +								ibmr = ERR_PTR(-ENOMEM);  								goto reg_user_mr_err;  							} -							if (root_pbl_index == 1) { -								root_vpbl.pbl_vbase = pci_alloc_consistent(nesdev->pcidev, -										8192, &root_vpbl.pbl_pbase); -								nes_debug(NES_DBG_MR, "Allocating root PBL, va = %p, pa = 0x%08X\n", -										root_vpbl.pbl_vbase, (unsigned int)root_vpbl.pbl_pbase); -								if (!root_vpbl.pbl_vbase) { -									ib_umem_release(region); -									pci_free_consistent(nesdev->pcidev, 4096, vpbl.pbl_vbase, -											vpbl.pbl_pbase); -									nes_free_resource(nesadapter, nesadapter->allocated_mrs, -											stag_index); -									kfree(nesmr); -									ibmr = ERR_PTR(-ENOMEM); -									goto reg_user_mr_err; -								} -								root_vpbl.leaf_vpbl = kzalloc(sizeof(*root_vpbl.leaf_vpbl)*1024, -										GFP_KERNEL); -								if (!root_vpbl.leaf_vpbl) { -									ib_umem_release(region); -									pci_free_consistent(nesdev->pcidev, 8192, root_vpbl.pbl_vbase, -											root_vpbl.pbl_pbase); -									pci_free_consistent(nesdev->pcidev, 4096, vpbl.pbl_vbase, -											vpbl.pbl_pbase); -									nes_free_resource(nesadapter, nesadapter->allocated_mrs, -											stag_index); -									kfree(nesmr); -									ibmr = ERR_PTR(-ENOMEM); -									goto reg_user_mr_err; -								} -								root_vpbl.pbl_vbase[0].pa_low = -										cpu_to_le32((u32)vpbl.pbl_pbase); -								root_vpbl.pbl_vbase[0].pa_high = -										cpu_to_le32((u32)((((u64)vpbl.pbl_pbase) >> 32))); -								root_vpbl.leaf_vpbl[0] = vpbl; -							} -							vpbl.pbl_vbase = pci_alloc_consistent(nesdev->pcidev, 4096, -									&vpbl.pbl_pbase); -							nes_debug(NES_DBG_MR, "Allocating leaf PBL, va = %p, pa = 0x%08X\n", -									vpbl.pbl_vbase, (unsigned int)vpbl.pbl_pbase); -							if (!vpbl.pbl_vbase) { +							root_vpbl.leaf_vpbl = kzalloc(sizeof(*root_vpbl.leaf_vpbl)*1024, +									GFP_KERNEL); +							if (!root_vpbl.leaf_vpbl) {  								ib_umem_release(region); -								nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index); -								ibmr = ERR_PTR(-ENOMEM); +								pci_free_consistent(nesdev->pcidev, 8192, root_vpbl.pbl_vbase, +										    root_vpbl.pbl_pbase); +								pci_free_consistent(nesdev->pcidev, 4096, vpbl.pbl_vbase, +										    vpbl.pbl_pbase); +								nes_free_resource(nesadapter, nesadapter->allocated_mrs, +										  stag_index);  								kfree(nesmr); +								ibmr = ERR_PTR(-ENOMEM);  								goto reg_user_mr_err;  							} -							if (1 <= root_pbl_index) { -								root_vpbl.pbl_vbase[root_pbl_index].pa_low = -										cpu_to_le32((u32)vpbl.pbl_pbase); -								root_vpbl.pbl_vbase[root_pbl_index].pa_high = -										cpu_to_le32((u32)((((u64)vpbl.pbl_pbase)>>32))); -								root_vpbl.leaf_vpbl[root_pbl_index] = vpbl; -							} -							root_pbl_index++; -							cur_pbl_index = 0; +							root_vpbl.pbl_vbase[0].pa_low = +									cpu_to_le32((u32)vpbl.pbl_pbase); +							root_vpbl.pbl_vbase[0].pa_high = +									cpu_to_le32((u32)((((u64)vpbl.pbl_pbase) >> 32))); +							root_vpbl.leaf_vpbl[0] = vpbl;  						} -						if (single_page) { -							if (page_count != 0) { -								if ((last_dma_addr+4096) != -										(sg_dma_address(&chunk->page_list[nmap_index])+ -										(page_index*4096))) -									single_page = 0; -								last_dma_addr = sg_dma_address(&chunk->page_list[nmap_index])+ -										(page_index*4096); -							} else { -								first_dma_addr = sg_dma_address(&chunk->page_list[nmap_index])+ -										(page_index*4096); -								last_dma_addr = first_dma_addr; -							} +						vpbl.pbl_vbase = pci_alloc_consistent(nesdev->pcidev, 4096, +								&vpbl.pbl_pbase); +						nes_debug(NES_DBG_MR, "Allocating leaf PBL, va = %p, pa = 0x%08X\n", +							  vpbl.pbl_vbase, (unsigned int)vpbl.pbl_pbase); +						if (!vpbl.pbl_vbase) { +							ib_umem_release(region); +							nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index); +							ibmr = ERR_PTR(-ENOMEM); +							kfree(nesmr); +							goto reg_user_mr_err; +						} +						if (1 <= root_pbl_index) { +							root_vpbl.pbl_vbase[root_pbl_index].pa_low = +									cpu_to_le32((u32)vpbl.pbl_pbase); +							root_vpbl.pbl_vbase[root_pbl_index].pa_high = +									cpu_to_le32((u32)((((u64)vpbl.pbl_pbase)>>32))); +							root_vpbl.leaf_vpbl[root_pbl_index] = vpbl; +						} +						root_pbl_index++; +						cur_pbl_index = 0; +					} +					if (single_page) { +						if (page_count != 0) { +							if ((last_dma_addr+4096) != +									(sg_dma_address(sg)+ +									(page_index*4096))) +								single_page = 0; +							last_dma_addr = sg_dma_address(sg)+ +									(page_index*4096); +						} else { +							first_dma_addr = sg_dma_address(sg)+ +									(page_index*4096); +							last_dma_addr = first_dma_addr;  						} - -						vpbl.pbl_vbase[cur_pbl_index].pa_low = -								cpu_to_le32((u32)(sg_dma_address(&chunk->page_list[nmap_index])+ -								(page_index*4096))); -						vpbl.pbl_vbase[cur_pbl_index].pa_high = -								cpu_to_le32((u32)((((u64)(sg_dma_address(&chunk->page_list[nmap_index])+ -								(page_index*4096))) >> 32))); -						cur_pbl_index++; -						page_count++;  					} + +					vpbl.pbl_vbase[cur_pbl_index].pa_low = +							cpu_to_le32((u32)(sg_dma_address(sg)+ +							(page_index*4096))); +					vpbl.pbl_vbase[cur_pbl_index].pa_high = +							cpu_to_le32((u32)((((u64)(sg_dma_address(sg)+ +							(page_index*4096))) >> 32))); +					cur_pbl_index++; +					page_count++;  				}  			} +  			enough_pages:  			nes_debug(NES_DBG_MR, "calculating stag, stag_index=0x%08x, driver_key=0x%08x,"  					" stag_key=0x%08x\n", @@ -2613,25 +2613,28 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,  				  nespbl->pbl_size, (unsigned long) nespbl->pbl_pbase,  				  (void *) nespbl->pbl_vbase, nespbl->user_base); -			list_for_each_entry(chunk, ®ion->chunk_list, list) { -				for (nmap_index = 0; nmap_index < chunk->nmap; ++nmap_index) { -					chunk_pages = sg_dma_len(&chunk->page_list[nmap_index]) >> 12; -					chunk_pages += (sg_dma_len(&chunk->page_list[nmap_index]) & (4096-1)) ? 1 : 0; -					nespbl->page = sg_page(&chunk->page_list[0]); -					for (page_index=0; page_index<chunk_pages; page_index++) { -						((__le32 *)pbl)[0] = cpu_to_le32((u32) -								(sg_dma_address(&chunk->page_list[nmap_index])+ -								(page_index*4096))); -						((__le32 *)pbl)[1] = cpu_to_le32(((u64) -								(sg_dma_address(&chunk->page_list[nmap_index])+ -								(page_index*4096)))>>32); -						nes_debug(NES_DBG_MR, "pbl=%p, *pbl=0x%016llx, 0x%08x%08x\n", pbl, -								(unsigned long long)*pbl, -								le32_to_cpu(((__le32 *)pbl)[1]), le32_to_cpu(((__le32 *)pbl)[0])); -						pbl++; -					} +			for_each_sg(region->sg_head.sgl, sg, region->nmap, entry) { +				chunk_pages = sg_dma_len(sg) >> 12; +				chunk_pages += (sg_dma_len(sg) & (4096-1)) ? 1 : 0; +				if (first_page) { +					nespbl->page = sg_page(sg); +					first_page = 0; +				} + +				for (page_index = 0; page_index < chunk_pages; page_index++) { +					((__le32 *)pbl)[0] = cpu_to_le32((u32) +							(sg_dma_address(sg)+ +							(page_index*4096))); +					((__le32 *)pbl)[1] = cpu_to_le32(((u64) +							(sg_dma_address(sg)+ +							(page_index*4096)))>>32); +					nes_debug(NES_DBG_MR, "pbl=%p, *pbl=0x%016llx, 0x%08x%08x\n", pbl, +						  (unsigned long long)*pbl, +						  le32_to_cpu(((__le32 *)pbl)[1]), le32_to_cpu(((__le32 *)pbl)[0])); +					pbl++;  				}  			} +  			if (req.reg_type == IWNES_MEMREG_TYPE_QP) {  				list_add_tail(&nespbl->list, &nes_ucontext->qp_reg_mem_list);  			} else { @@ -2834,7 +2837,7 @@ static int nes_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,  	init_attr->qp_context = nesqp->ibqp.qp_context;  	init_attr->send_cq = nesqp->ibqp.send_cq;  	init_attr->recv_cq = nesqp->ibqp.recv_cq; -	init_attr->srq = nesqp->ibqp.srq = nesqp->ibqp.srq; +	init_attr->srq = nesqp->ibqp.srq;  	init_attr->cap = attr->cap;  	return 0; @@ -3134,9 +3137,7 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,  				" original_last_aeq = 0x%04X. last_aeq = 0x%04X.\n",  				nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount),  				original_last_aeq, nesqp->last_aeq); -		if ((!ret) || -				((original_last_aeq != NES_AEQE_AEID_RDMAP_ROE_BAD_LLP_CLOSE) && -				(ret))) { +		if (!ret || original_last_aeq != NES_AEQE_AEID_RDMAP_ROE_BAD_LLP_CLOSE) {  			if (dont_wait) {  				if (nesqp->cm_id && nesqp->hw_tcp_state != 0) {  					nes_debug(NES_DBG_MOD_QP, "QP%u Queuing fake disconnect for QP refcount (%d)," diff --git a/drivers/infiniband/hw/nes/nes_verbs.h b/drivers/infiniband/hw/nes/nes_verbs.h index 0eff7c44d76..309b31c31ae 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.h +++ b/drivers/infiniband/hw/nes/nes_verbs.h @@ -184,5 +184,6 @@ struct nes_qp {  	u8                    pau_busy;  	u8                    pau_pending;  	u8                    pau_state; +	__u64                 nesuqp_addr;  };  #endif			/* NES_VERBS_H */  | 
