mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	net/smc: introduce sg-logic for RMBs
The follow-on patch makes use of ib_map_mr_sg() when introducing separate memory regions for RMBs. This function is based on scatterlists; thus this patch introduces scatterlists for RMBs. Signed-off-by: Ursula Braun <ubraun@linux.vnet.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									c45abf31e7
								
							
						
					
					
						commit
						a3fe3d01bd
					
				
					 5 changed files with 76 additions and 26 deletions
				
			
		| 
						 | 
					@ -204,13 +204,13 @@ int smc_clc_send_confirm(struct smc_sock *smc)
 | 
				
			||||||
	memcpy(&cclc.lcl.mac, &link->smcibdev->mac[link->ibport - 1], ETH_ALEN);
 | 
						memcpy(&cclc.lcl.mac, &link->smcibdev->mac[link->ibport - 1], ETH_ALEN);
 | 
				
			||||||
	hton24(cclc.qpn, link->roce_qp->qp_num);
 | 
						hton24(cclc.qpn, link->roce_qp->qp_num);
 | 
				
			||||||
	cclc.rmb_rkey =
 | 
						cclc.rmb_rkey =
 | 
				
			||||||
		htonl(conn->rmb_desc->rkey[SMC_SINGLE_LINK]);
 | 
							htonl(link->roce_pd->unsafe_global_rkey);
 | 
				
			||||||
	cclc.conn_idx = 1; /* for now: 1 RMB = 1 RMBE */
 | 
						cclc.conn_idx = 1; /* for now: 1 RMB = 1 RMBE */
 | 
				
			||||||
	cclc.rmbe_alert_token = htonl(conn->alert_token_local);
 | 
						cclc.rmbe_alert_token = htonl(conn->alert_token_local);
 | 
				
			||||||
	cclc.qp_mtu = min(link->path_mtu, link->peer_mtu);
 | 
						cclc.qp_mtu = min(link->path_mtu, link->peer_mtu);
 | 
				
			||||||
	cclc.rmbe_size = conn->rmbe_size_short;
 | 
						cclc.rmbe_size = conn->rmbe_size_short;
 | 
				
			||||||
	cclc.rmb_dma_addr =
 | 
						cclc.rmb_dma_addr = cpu_to_be64(
 | 
				
			||||||
		cpu_to_be64((u64)conn->rmb_desc->dma_addr[SMC_SINGLE_LINK]);
 | 
							(u64)sg_dma_address(conn->rmb_desc->sgt[SMC_SINGLE_LINK].sgl));
 | 
				
			||||||
	hton24(cclc.psn, link->psn_initial);
 | 
						hton24(cclc.psn, link->psn_initial);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memcpy(cclc.trl.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
 | 
						memcpy(cclc.trl.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
 | 
				
			||||||
| 
						 | 
					@ -256,13 +256,13 @@ int smc_clc_send_accept(struct smc_sock *new_smc, int srv_first_contact)
 | 
				
			||||||
	memcpy(&aclc.lcl.mac, link->smcibdev->mac[link->ibport - 1], ETH_ALEN);
 | 
						memcpy(&aclc.lcl.mac, link->smcibdev->mac[link->ibport - 1], ETH_ALEN);
 | 
				
			||||||
	hton24(aclc.qpn, link->roce_qp->qp_num);
 | 
						hton24(aclc.qpn, link->roce_qp->qp_num);
 | 
				
			||||||
	aclc.rmb_rkey =
 | 
						aclc.rmb_rkey =
 | 
				
			||||||
		htonl(conn->rmb_desc->rkey[SMC_SINGLE_LINK]);
 | 
							htonl(link->roce_pd->unsafe_global_rkey);
 | 
				
			||||||
	aclc.conn_idx = 1;			/* as long as 1 RMB = 1 RMBE */
 | 
						aclc.conn_idx = 1;			/* as long as 1 RMB = 1 RMBE */
 | 
				
			||||||
	aclc.rmbe_alert_token = htonl(conn->alert_token_local);
 | 
						aclc.rmbe_alert_token = htonl(conn->alert_token_local);
 | 
				
			||||||
	aclc.qp_mtu = link->path_mtu;
 | 
						aclc.qp_mtu = link->path_mtu;
 | 
				
			||||||
	aclc.rmbe_size = conn->rmbe_size_short,
 | 
						aclc.rmbe_size = conn->rmbe_size_short,
 | 
				
			||||||
	aclc.rmb_dma_addr =
 | 
						aclc.rmb_dma_addr = cpu_to_be64(
 | 
				
			||||||
		cpu_to_be64((u64)conn->rmb_desc->dma_addr[SMC_SINGLE_LINK]);
 | 
							(u64)sg_dma_address(conn->rmb_desc->sgt[SMC_SINGLE_LINK].sgl));
 | 
				
			||||||
	hton24(aclc.psn, link->psn_initial);
 | 
						hton24(aclc.psn, link->psn_initial);
 | 
				
			||||||
	memcpy(aclc.trl.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
 | 
						memcpy(aclc.trl.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -266,17 +266,16 @@ static void smc_lgr_free_sndbufs(struct smc_link_group *lgr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void smc_lgr_free_rmbs(struct smc_link_group *lgr)
 | 
					static void smc_lgr_free_rmbs(struct smc_link_group *lgr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct smc_buf_desc *rmb_desc, *bf_desc;
 | 
					 | 
				
			||||||
	struct smc_link *lnk = &lgr->lnk[SMC_SINGLE_LINK];
 | 
						struct smc_link *lnk = &lgr->lnk[SMC_SINGLE_LINK];
 | 
				
			||||||
 | 
						struct smc_buf_desc *rmb_desc, *bf_desc;
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < SMC_RMBE_SIZES; i++) {
 | 
						for (i = 0; i < SMC_RMBE_SIZES; i++) {
 | 
				
			||||||
		list_for_each_entry_safe(rmb_desc, bf_desc, &lgr->rmbs[i],
 | 
							list_for_each_entry_safe(rmb_desc, bf_desc, &lgr->rmbs[i],
 | 
				
			||||||
					 list) {
 | 
										 list) {
 | 
				
			||||||
			list_del(&rmb_desc->list);
 | 
								list_del(&rmb_desc->list);
 | 
				
			||||||
			smc_ib_buf_unmap(lnk->smcibdev,
 | 
								smc_ib_buf_unmap_sg(lnk->smcibdev, rmb_desc,
 | 
				
			||||||
					 smc_uncompress_bufsize(i),
 | 
										    DMA_FROM_DEVICE);
 | 
				
			||||||
					 rmb_desc, DMA_FROM_DEVICE);
 | 
					 | 
				
			||||||
			kfree(rmb_desc->cpu_addr);
 | 
								kfree(rmb_desc->cpu_addr);
 | 
				
			||||||
			kfree(rmb_desc);
 | 
								kfree(rmb_desc);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -580,38 +579,54 @@ int smc_rmb_create(struct smc_sock *smc)
 | 
				
			||||||
	for (bufsize_short = smc_compress_bufsize(smc->sk.sk_rcvbuf / 2);
 | 
						for (bufsize_short = smc_compress_bufsize(smc->sk.sk_rcvbuf / 2);
 | 
				
			||||||
	     bufsize_short >= 0; bufsize_short--) {
 | 
						     bufsize_short >= 0; bufsize_short--) {
 | 
				
			||||||
		bufsize = smc_uncompress_bufsize(bufsize_short);
 | 
							bufsize = smc_uncompress_bufsize(bufsize_short);
 | 
				
			||||||
 | 
							if ((1 << get_order(bufsize)) > SG_MAX_SINGLE_ALLOC)
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* check for reusable rmb_slot in the link group */
 | 
							/* check for reusable rmb_slot in the link group */
 | 
				
			||||||
		rmb_desc = smc_rmb_get_slot(lgr, bufsize_short);
 | 
							rmb_desc = smc_rmb_get_slot(lgr, bufsize_short);
 | 
				
			||||||
		if (rmb_desc) {
 | 
							if (rmb_desc) {
 | 
				
			||||||
			memset(rmb_desc->cpu_addr, 0, bufsize);
 | 
								memset(rmb_desc->cpu_addr, 0, bufsize);
 | 
				
			||||||
			break; /* found reusable slot */
 | 
								break; /* found reusable slot */
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* try to alloc a new RMB */
 | 
							/* try to alloc a new RMB */
 | 
				
			||||||
		rmb_desc = kzalloc(sizeof(*rmb_desc), GFP_KERNEL);
 | 
							rmb_desc = kzalloc(sizeof(*rmb_desc), GFP_KERNEL);
 | 
				
			||||||
		if (!rmb_desc)
 | 
							if (!rmb_desc)
 | 
				
			||||||
			break; /* give up with -ENOMEM */
 | 
								break; /* give up with -ENOMEM */
 | 
				
			||||||
		rmb_desc->cpu_addr = kzalloc(bufsize,
 | 
							rmb_desc->cpu_addr =
 | 
				
			||||||
					     GFP_KERNEL | __GFP_NOWARN |
 | 
								(void *)__get_free_pages(GFP_KERNEL | __GFP_NOWARN |
 | 
				
			||||||
					     __GFP_NOMEMALLOC |
 | 
											 __GFP_NOMEMALLOC |
 | 
				
			||||||
					     __GFP_NORETRY);
 | 
											 __GFP_NORETRY | __GFP_ZERO,
 | 
				
			||||||
 | 
											 get_order(bufsize));
 | 
				
			||||||
		if (!rmb_desc->cpu_addr) {
 | 
							if (!rmb_desc->cpu_addr) {
 | 
				
			||||||
			kfree(rmb_desc);
 | 
								kfree(rmb_desc);
 | 
				
			||||||
			rmb_desc = NULL;
 | 
								rmb_desc = NULL;
 | 
				
			||||||
			/* if RMB allocation has failed,
 | 
					 | 
				
			||||||
			 * try a smaller one
 | 
					 | 
				
			||||||
			 */
 | 
					 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		rc = smc_ib_buf_map(lgr->lnk[SMC_SINGLE_LINK].smcibdev,
 | 
							rmb_desc->order = get_order(bufsize);
 | 
				
			||||||
				    bufsize, rmb_desc, DMA_FROM_DEVICE);
 | 
					
 | 
				
			||||||
 | 
							rc = sg_alloc_table(&rmb_desc->sgt[SMC_SINGLE_LINK], 1,
 | 
				
			||||||
 | 
									    GFP_KERNEL);
 | 
				
			||||||
		if (rc) {
 | 
							if (rc) {
 | 
				
			||||||
			kfree(rmb_desc->cpu_addr);
 | 
								free_pages((unsigned long)rmb_desc->cpu_addr,
 | 
				
			||||||
 | 
									   rmb_desc->order);
 | 
				
			||||||
 | 
								kfree(rmb_desc);
 | 
				
			||||||
 | 
								rmb_desc = NULL;
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							sg_set_buf(rmb_desc->sgt[SMC_SINGLE_LINK].sgl,
 | 
				
			||||||
 | 
								   rmb_desc->cpu_addr, bufsize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							rc = smc_ib_buf_map_sg(lgr->lnk[SMC_SINGLE_LINK].smcibdev,
 | 
				
			||||||
 | 
									       rmb_desc, DMA_FROM_DEVICE);
 | 
				
			||||||
 | 
							if (rc != 1)  {
 | 
				
			||||||
 | 
								sg_free_table(&rmb_desc->sgt[SMC_SINGLE_LINK]);
 | 
				
			||||||
 | 
								free_pages((unsigned long)rmb_desc->cpu_addr,
 | 
				
			||||||
 | 
									   rmb_desc->order);
 | 
				
			||||||
			kfree(rmb_desc);
 | 
								kfree(rmb_desc);
 | 
				
			||||||
			rmb_desc = NULL;
 | 
								rmb_desc = NULL;
 | 
				
			||||||
			continue; /* if mapping failed, try smaller one */
 | 
								continue; /* if mapping failed, try smaller one */
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		rmb_desc->rkey[SMC_SINGLE_LINK] =
 | 
					 | 
				
			||||||
			lgr->lnk[SMC_SINGLE_LINK].roce_pd->unsafe_global_rkey;
 | 
					 | 
				
			||||||
		rmb_desc->used = 1;
 | 
							rmb_desc->used = 1;
 | 
				
			||||||
		write_lock_bh(&lgr->rmbs_lock);
 | 
							write_lock_bh(&lgr->rmbs_lock);
 | 
				
			||||||
		list_add(&rmb_desc->list, &lgr->rmbs[bufsize_short]);
 | 
							list_add(&rmb_desc->list, &lgr->rmbs[bufsize_short]);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -93,10 +93,8 @@ struct smc_buf_desc {
 | 
				
			||||||
	u64			dma_addr[SMC_LINKS_PER_LGR_MAX];
 | 
						u64			dma_addr[SMC_LINKS_PER_LGR_MAX];
 | 
				
			||||||
						/* mapped address of buffer */
 | 
											/* mapped address of buffer */
 | 
				
			||||||
	void			*cpu_addr;	/* virtual address of buffer */
 | 
						void			*cpu_addr;	/* virtual address of buffer */
 | 
				
			||||||
	u32			rkey[SMC_LINKS_PER_LGR_MAX];
 | 
						struct sg_table		sgt[SMC_LINKS_PER_LGR_MAX];/* virtual buffer */
 | 
				
			||||||
						/* for rmb only:
 | 
						u32			order;		/* allocation order */
 | 
				
			||||||
						 * rkey provided to peer
 | 
					 | 
				
			||||||
						 */
 | 
					 | 
				
			||||||
	u32			used;		/* currently used / unused */
 | 
						u32			used;		/* currently used / unused */
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -283,6 +283,37 @@ void smc_ib_buf_unmap(struct smc_ib_device *smcibdev, int buf_size,
 | 
				
			||||||
	buf_slot->dma_addr[SMC_SINGLE_LINK] = 0;
 | 
						buf_slot->dma_addr[SMC_SINGLE_LINK] = 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Map a new TX or RX buffer SG-table to DMA */
 | 
				
			||||||
 | 
					int smc_ib_buf_map_sg(struct smc_ib_device *smcibdev,
 | 
				
			||||||
 | 
							      struct smc_buf_desc *buf_slot,
 | 
				
			||||||
 | 
							      enum dma_data_direction data_direction)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int mapped_nents;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mapped_nents = ib_dma_map_sg(smcibdev->ibdev,
 | 
				
			||||||
 | 
									     buf_slot->sgt[SMC_SINGLE_LINK].sgl,
 | 
				
			||||||
 | 
									     buf_slot->sgt[SMC_SINGLE_LINK].orig_nents,
 | 
				
			||||||
 | 
									     data_direction);
 | 
				
			||||||
 | 
						if (!mapped_nents)
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return mapped_nents;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void smc_ib_buf_unmap_sg(struct smc_ib_device *smcibdev,
 | 
				
			||||||
 | 
								 struct smc_buf_desc *buf_slot,
 | 
				
			||||||
 | 
								 enum dma_data_direction data_direction)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!buf_slot->sgt[SMC_SINGLE_LINK].sgl->dma_address)
 | 
				
			||||||
 | 
							return; /* already unmapped */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ib_dma_unmap_sg(smcibdev->ibdev,
 | 
				
			||||||
 | 
								buf_slot->sgt[SMC_SINGLE_LINK].sgl,
 | 
				
			||||||
 | 
								buf_slot->sgt[SMC_SINGLE_LINK].orig_nents,
 | 
				
			||||||
 | 
								data_direction);
 | 
				
			||||||
 | 
						buf_slot->sgt[SMC_SINGLE_LINK].sgl->dma_address = 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int smc_ib_fill_gid_and_mac(struct smc_ib_device *smcibdev, u8 ibport)
 | 
					static int smc_ib_fill_gid_and_mac(struct smc_ib_device *smcibdev, u8 ibport)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct net_device *ndev;
 | 
						struct net_device *ndev;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -57,6 +57,12 @@ int smc_ib_buf_map(struct smc_ib_device *smcibdev, int buf_size,
 | 
				
			||||||
void smc_ib_buf_unmap(struct smc_ib_device *smcibdev, int bufsize,
 | 
					void smc_ib_buf_unmap(struct smc_ib_device *smcibdev, int bufsize,
 | 
				
			||||||
		      struct smc_buf_desc *buf_slot,
 | 
							      struct smc_buf_desc *buf_slot,
 | 
				
			||||||
		      enum dma_data_direction data_direction);
 | 
							      enum dma_data_direction data_direction);
 | 
				
			||||||
 | 
					int smc_ib_buf_map_sg(struct smc_ib_device *smcibdev,
 | 
				
			||||||
 | 
							      struct smc_buf_desc *buf_slot,
 | 
				
			||||||
 | 
							      enum dma_data_direction data_direction);
 | 
				
			||||||
 | 
					void smc_ib_buf_unmap_sg(struct smc_ib_device *smcibdev,
 | 
				
			||||||
 | 
								 struct smc_buf_desc *buf_slot,
 | 
				
			||||||
 | 
								 enum dma_data_direction data_direction);
 | 
				
			||||||
void smc_ib_dealloc_protection_domain(struct smc_link *lnk);
 | 
					void smc_ib_dealloc_protection_domain(struct smc_link *lnk);
 | 
				
			||||||
int smc_ib_create_protection_domain(struct smc_link *lnk);
 | 
					int smc_ib_create_protection_domain(struct smc_link *lnk);
 | 
				
			||||||
void smc_ib_destroy_queue_pair(struct smc_link *lnk);
 | 
					void smc_ib_destroy_queue_pair(struct smc_link *lnk);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue