Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 187c72e3 authored by Hoang-Nam Nguyen's avatar Hoang-Nam Nguyen Committed by Roland Dreier
Browse files

IB/ehca: Restructure ehca_set_pagebuf()



Split ehca_set_pagebuf() into three functions depending on MR type
(phys/user/fast) and remove superfluous ehca_set_pagebuf_1().

Signed-off-by: default avatarJoachim Fenkes <fenkes@de.ibm.com>
Signed-off-by: default avatarRoland Dreier <rolandd@cisco.com>
parent df17bfd4
Loading
Loading
Loading
Loading
+200 −331
Original line number Original line Diff line number Diff line
@@ -824,6 +824,7 @@ int ehca_map_phys_fmr(struct ib_fmr *fmr,
	pginfo.u.fmr.page_list = page_list;
	pginfo.u.fmr.page_list = page_list;
	pginfo.next_hwpage = ((iova & (e_fmr->fmr_page_size-1)) /
	pginfo.next_hwpage = ((iova & (e_fmr->fmr_page_size-1)) /
			      EHCA_PAGESIZE);
			      EHCA_PAGESIZE);
	pginfo.u.fmr.fmr_pgsize = e_fmr->fmr_page_size;


	ret = ehca_rereg_mr(shca, e_fmr, (u64*)iova,
	ret = ehca_rereg_mr(shca, e_fmr, (u64*)iova,
			    list_len * e_fmr->fmr_page_size,
			    list_len * e_fmr->fmr_page_size,
@@ -1044,15 +1045,15 @@ int ehca_reg_mr_rpages(struct ehca_shca *shca,
		} else
		} else
			rnum = MAX_RPAGES;
			rnum = MAX_RPAGES;


		if (rnum > 1) {
		ret = ehca_set_pagebuf(pginfo, rnum, kpage);
			ret = ehca_set_pagebuf(e_mr, pginfo, rnum, kpage);
		if (ret) {
		if (ret) {
			ehca_err(&shca->ib_device, "ehca_set_pagebuf "
			ehca_err(&shca->ib_device, "ehca_set_pagebuf "
					 "bad rc, ret=%x rnum=%x kpage=%p",
					 "bad rc, ret=%x rnum=%x kpage=%p",
					 ret, rnum, kpage);
					 ret, rnum, kpage);
				ret = -EFAULT;
			goto ehca_reg_mr_rpages_exit1;
			goto ehca_reg_mr_rpages_exit1;
		}
		}

		if (rnum > 1) {
			rpage = virt_to_abs(kpage);
			rpage = virt_to_abs(kpage);
			if (!rpage) {
			if (!rpage) {
				ehca_err(&shca->ib_device, "kpage=%p i=%x",
				ehca_err(&shca->ib_device, "kpage=%p i=%x",
@@ -1060,15 +1061,8 @@ int ehca_reg_mr_rpages(struct ehca_shca *shca,
				ret = -EFAULT;
				ret = -EFAULT;
				goto ehca_reg_mr_rpages_exit1;
				goto ehca_reg_mr_rpages_exit1;
			}
			}
		} else {  /* rnum==1 */
		} else
			ret = ehca_set_pagebuf_1(e_mr, pginfo, &rpage);
			rpage = *kpage;
			if (ret) {
				ehca_err(&shca->ib_device, "ehca_set_pagebuf_1 "
					 "bad rc, ret=%x i=%x", ret, i);
				ret = -EFAULT;
				goto ehca_reg_mr_rpages_exit1;
			}
		}


		h_ret = hipz_h_register_rpage_mr(shca->ipz_hca_handle, e_mr,
		h_ret = hipz_h_register_rpage_mr(shca->ipz_hca_handle, e_mr,
						 0, /* pagesize 4k */
						 0, /* pagesize 4k */
@@ -1146,7 +1140,7 @@ inline int ehca_rereg_mr_rereg1(struct ehca_shca *shca,
	}
	}


	pginfo_save = *pginfo;
	pginfo_save = *pginfo;
	ret = ehca_set_pagebuf(e_mr, pginfo, pginfo->num_hwpages, kpage);
	ret = ehca_set_pagebuf(pginfo, pginfo->num_hwpages, kpage);
	if (ret) {
	if (ret) {
		ehca_err(&shca->ib_device, "set pagebuf failed, e_mr=%p "
		ehca_err(&shca->ib_device, "set pagebuf failed, e_mr=%p "
			 "pginfo=%p type=%x num_kpages=%lx num_hwpages=%lx "
			 "pginfo=%p type=%x num_kpages=%lx num_hwpages=%lx "
@@ -1306,29 +1300,29 @@ int ehca_unmap_one_fmr(struct ehca_shca *shca,
{
{
	int ret = 0;
	int ret = 0;
	u64 h_ret;
	u64 h_ret;
	int rereg_1_hcall = 1; /* 1: use hipz_mr_reregister directly */
	int rereg_3_hcall = 0; /* 1: use 3 hipz calls for unmapping */
	struct ehca_pd *e_pd =
	struct ehca_pd *e_pd =
		container_of(e_fmr->ib.ib_fmr.pd, struct ehca_pd, ib_pd);
		container_of(e_fmr->ib.ib_fmr.pd, struct ehca_pd, ib_pd);
	struct ehca_mr save_fmr;
	struct ehca_mr save_fmr;
	u32 tmp_lkey, tmp_rkey;
	u32 tmp_lkey, tmp_rkey;
	struct ehca_mr_pginfo pginfo;
	struct ehca_mr_pginfo pginfo;
	struct ehca_mr_hipzout_parms hipzout = {{0},0,0,0,0,0};
	struct ehca_mr_hipzout_parms hipzout = {{0},0,0,0,0,0};
	struct ehca_mr save_mr;


	/* first check if reregistration hCall can be used for unmap */
	if (e_fmr->fmr_max_pages <= MAX_RPAGES) {
	if (e_fmr->fmr_max_pages > MAX_RPAGES) {
		rereg_1_hcall = 0;
		rereg_3_hcall = 1;
	}

	if (rereg_1_hcall) {
		/*
		/*
		 * note: after using rereg hcall with len=0,
		 * note: after using rereg hcall with len=0,
		 * rereg hcall must be used again for registering pages
		 * rereg hcall must be used again for registering pages
		 */
		 */
		h_ret = hipz_h_reregister_pmr(shca->ipz_hca_handle, e_fmr, 0,
		h_ret = hipz_h_reregister_pmr(shca->ipz_hca_handle, e_fmr, 0,
					      0, 0, e_pd->fw_pd, 0, &hipzout);
					      0, 0, e_pd->fw_pd, 0, &hipzout);
		if (h_ret != H_SUCCESS) {
		if (h_ret == H_SUCCESS) {
			/* successful reregistration */
			e_fmr->start = NULL;
			e_fmr->size = 0;
			tmp_lkey = hipzout.lkey;
			tmp_rkey = hipzout.rkey;
			return 0;
		}
		/*
		/*
		 * should not happen, because length checked above,
		 * should not happen, because length checked above,
		 * FMRs are not shared and no MW bound to FMRs
		 * FMRs are not shared and no MW bound to FMRs
@@ -1339,18 +1333,8 @@ int ehca_unmap_one_fmr(struct ehca_shca *shca,
			 h_ret, e_fmr, shca->ipz_hca_handle.handle,
			 h_ret, e_fmr, shca->ipz_hca_handle.handle,
			 e_fmr->ipz_mr_handle.handle,
			 e_fmr->ipz_mr_handle.handle,
			 e_fmr->ib.ib_fmr.lkey, hipzout.lkey);
			 e_fmr->ib.ib_fmr.lkey, hipzout.lkey);
			rereg_3_hcall = 1;
		/* try free and rereg */
		} else {
			/* successful reregistration */
			e_fmr->start = NULL;
			e_fmr->size = 0;
			tmp_lkey = hipzout.lkey;
			tmp_rkey = hipzout.rkey;
	}
	}
	}

	if (rereg_3_hcall) {
		struct ehca_mr save_mr;


	/* first free old FMR */
	/* first free old FMR */
	h_ret = hipz_h_free_resource_mr(shca->ipz_hca_handle, e_fmr);
	h_ret = hipz_h_free_resource_mr(shca->ipz_hca_handle, e_fmr);
@@ -1390,14 +1374,12 @@ int ehca_unmap_one_fmr(struct ehca_shca *shca,
		       sizeof(struct ehca_mr) - offset);
		       sizeof(struct ehca_mr) - offset);
		goto ehca_unmap_one_fmr_exit0;
		goto ehca_unmap_one_fmr_exit0;
	}
	}
	}


ehca_unmap_one_fmr_exit0:
ehca_unmap_one_fmr_exit0:
	if (ret)
	if (ret)
		ehca_err(&shca->ib_device, "ret=%x tmp_lkey=%x tmp_rkey=%x "
		ehca_err(&shca->ib_device, "ret=%x tmp_lkey=%x tmp_rkey=%x "
			 "fmr_max_pages=%x rereg_1_hcall=%x rereg_3_hcall=%x",
			 "fmr_max_pages=%x",
			 ret, tmp_lkey, tmp_rkey, e_fmr->fmr_max_pages,
			 ret, tmp_lkey, tmp_rkey, e_fmr->fmr_max_pages);
			 rereg_1_hcall, rereg_3_hcall);
	return ret;
	return ret;
} /* end ehca_unmap_one_fmr() */
} /* end ehca_unmap_one_fmr() */


@@ -1690,95 +1672,37 @@ int ehca_fmr_check_page_list(struct ehca_mr *e_fmr,


/*----------------------------------------------------------------------*/
/*----------------------------------------------------------------------*/


/* setup page buffer from page info */
/* PAGE_SIZE >= pginfo->hwpage_size */
int ehca_set_pagebuf(struct ehca_mr *e_mr,
static int ehca_set_pagebuf_user1(struct ehca_mr_pginfo *pginfo,
		     struct ehca_mr_pginfo *pginfo,
				  u32 number,
				  u32 number,
				  u64 *kpage)
				  u64 *kpage)
{
{
	int ret = 0;
	int ret = 0;
	struct ib_umem_chunk *prev_chunk;
	struct ib_umem_chunk *prev_chunk;
	struct ib_umem_chunk *chunk;
	struct ib_umem_chunk *chunk;
	struct ib_phys_buf *pbuf;
	u64 pgaddr;
	u64 *fmrlist;
	u64 num_hw, pgaddr, offs_hw;
	u32 i = 0;
	u32 i = 0;
	u32 j = 0;
	u32 j = 0;


	if (pginfo->type == EHCA_MR_PGI_PHYS) {
		/* loop over desired phys_buf_array entries */
		while (i < number) {
			pbuf   = pginfo->u.phy.phys_buf_array
				+ pginfo->u.phy.next_buf;
			num_hw  = NUM_CHUNKS((pbuf->addr % EHCA_PAGESIZE) +
					     pbuf->size, EHCA_PAGESIZE);
			offs_hw = (pbuf->addr & ~PAGE_MASK) / EHCA_PAGESIZE;
			while (pginfo->next_hwpage < offs_hw + num_hw) {
				/* sanity check */
				if ((pginfo->kpage_cnt >= pginfo->num_kpages) ||
				    (pginfo->hwpage_cnt >= pginfo->num_hwpages)) {
					ehca_gen_err("kpage_cnt >= num_kpages, "
						     "kpage_cnt=%lx "
						     "num_kpages=%lx "
						     "hwpage_cnt=%lx "
						     "num_hwpages=%lx i=%x",
						     pginfo->kpage_cnt,
						     pginfo->num_kpages,
						     pginfo->hwpage_cnt,
						     pginfo->num_hwpages, i);
					ret = -EFAULT;
					goto ehca_set_pagebuf_exit0;
				}
				*kpage = phys_to_abs(
					(pbuf->addr & EHCA_PAGEMASK)
					+ (pginfo->next_hwpage * EHCA_PAGESIZE));
				if ( !(*kpage) && pbuf->addr ) {
					ehca_gen_err("pbuf->addr=%lx "
						     "pbuf->size=%lx "
						     "next_hwpage=%lx", pbuf->addr,
						     pbuf->size,
						     pginfo->next_hwpage);
					ret = -EFAULT;
					goto ehca_set_pagebuf_exit0;
				}
				(pginfo->hwpage_cnt)++;
				(pginfo->next_hwpage)++;
				if (pginfo->next_hwpage %
				    (PAGE_SIZE / EHCA_PAGESIZE) == 0)
					(pginfo->kpage_cnt)++;
				kpage++;
				i++;
				if (i >= number) break;
			}
			if (pginfo->next_hwpage >= offs_hw + num_hw) {
				(pginfo->u.phy.next_buf)++;
				pginfo->next_hwpage = 0;
			}
		}
	} else if (pginfo->type == EHCA_MR_PGI_USER) {
	/* loop over desired chunk entries */
	/* loop over desired chunk entries */
	chunk      = pginfo->u.usr.next_chunk;
	chunk      = pginfo->u.usr.next_chunk;
	prev_chunk = pginfo->u.usr.next_chunk;
	prev_chunk = pginfo->u.usr.next_chunk;
		list_for_each_entry_continue(chunk,
	list_for_each_entry_continue(
					     (&(pginfo->u.usr.region->chunk_list)),
		chunk, (&(pginfo->u.usr.region->chunk_list)), list) {
					     list) {
		for (i = pginfo->u.usr.next_nmap; i < chunk->nmap; ) {
		for (i = pginfo->u.usr.next_nmap; i < chunk->nmap; ) {
				pgaddr = ( page_to_pfn(chunk->page_list[i].page)
			pgaddr = page_to_pfn(chunk->page_list[i].page)
					   << PAGE_SHIFT );
				<< PAGE_SHIFT ;
			*kpage = phys_to_abs(pgaddr +
			*kpage = phys_to_abs(pgaddr +
					     (pginfo->next_hwpage *
					     (pginfo->next_hwpage *
					      EHCA_PAGESIZE));
					      EHCA_PAGESIZE));
			if ( !(*kpage) ) {
			if ( !(*kpage) ) {
				ehca_gen_err("pgaddr=%lx "
				ehca_gen_err("pgaddr=%lx "
					     "chunk->page_list[i]=%lx "
					     "chunk->page_list[i]=%lx "
						     "i=%x next_hwpage=%lx mr=%p",
					     "i=%x next_hwpage=%lx",
						     pgaddr,
					     pgaddr, (u64)sg_dma_address(
						     (u64)sg_dma_address(
						     &chunk->page_list[i]),
							     &chunk->
					     i, pginfo->next_hwpage);
							     page_list[i]),
				return -EFAULT;
						     i, pginfo->next_hwpage, e_mr);
					ret = -EFAULT;
					goto ehca_set_pagebuf_exit0;
			}
			}
			(pginfo->hwpage_cnt)++;
			(pginfo->hwpage_cnt)++;
			(pginfo->next_hwpage)++;
			(pginfo->next_hwpage)++;
@@ -1810,180 +1734,125 @@ int ehca_set_pagebuf(struct ehca_mr *e_mr,
		list_prepare_entry(prev_chunk,
		list_prepare_entry(prev_chunk,
				   (&(pginfo->u.usr.region->chunk_list)),
				   (&(pginfo->u.usr.region->chunk_list)),
				   list);
				   list);
	} else if (pginfo->type == EHCA_MR_PGI_FMR) {
		/* loop over desired page_list entries */
		fmrlist = pginfo->u.fmr.page_list + pginfo->u.fmr.next_listelem;
		for (i = 0; i < number; i++) {
			*kpage = phys_to_abs((*fmrlist & EHCA_PAGEMASK) +
					     pginfo->next_hwpage * EHCA_PAGESIZE);
			if ( !(*kpage) ) {
				ehca_gen_err("*fmrlist=%lx fmrlist=%p "
					     "next_listelem=%lx next_hwpage=%lx",
					     *fmrlist, fmrlist,
					     pginfo->u.fmr.next_listelem,
					     pginfo->next_hwpage);
				ret = -EFAULT;
				goto ehca_set_pagebuf_exit0;
			}
			(pginfo->hwpage_cnt)++;
			(pginfo->next_hwpage)++;
			kpage++;
			if (pginfo->next_hwpage %
			    (e_mr->fmr_page_size / EHCA_PAGESIZE) == 0) {
				(pginfo->kpage_cnt)++;
				(pginfo->u.fmr.next_listelem)++;
				fmrlist++;
				pginfo->next_hwpage = 0;
			}
		}
	} else {
		ehca_gen_err("bad pginfo->type=%x", pginfo->type);
		ret = -EFAULT;
		goto ehca_set_pagebuf_exit0;
	}

ehca_set_pagebuf_exit0:
	if (ret)
		ehca_gen_err("ret=%x e_mr=%p pginfo=%p type=%x num_kpages=%lx "
			     "num_hwpages=%lx next_buf=%lx next_hwpage=%lx number=%x "
			     "kpage=%p kpage_cnt=%lx hwpage_cnt=%lx i=%x "
			     "next_listelem=%lx region=%p next_chunk=%p "
			     "next_nmap=%lx", ret, e_mr, pginfo, pginfo->type,
			     pginfo->num_kpages, pginfo->num_hwpages,
			     pginfo->u.phy.next_buf, pginfo->next_hwpage, number, kpage,
			     pginfo->kpage_cnt, pginfo->hwpage_cnt, i,
			     pginfo->u.fmr.next_listelem, pginfo->u.usr.region,
			     pginfo->u.usr.next_chunk, pginfo->u.usr.next_nmap);
	return ret;
	return ret;
} /* end ehca_set_pagebuf() */
}

/*----------------------------------------------------------------------*/


/* setup 1 page from page info page buffer */
int ehca_set_pagebuf_phys(struct ehca_mr_pginfo *pginfo,
int ehca_set_pagebuf_1(struct ehca_mr *e_mr,
			  u32 number,
		       struct ehca_mr_pginfo *pginfo,
			  u64 *kpage)
		       u64 *rpage)
{
{
	int ret = 0;
	int ret = 0;
	struct ib_phys_buf *tmp_pbuf;
	struct ib_phys_buf *pbuf;
	u64 *fmrlist;
	u64 num_hw, offs_hw;
	struct ib_umem_chunk *chunk;
	u32 i = 0;
	struct ib_umem_chunk *prev_chunk;
	u64 pgaddr, num_hw, offs_hw;


	if (pginfo->type == EHCA_MR_PGI_PHYS) {
	/* loop over desired phys_buf_array entries */
	while (i < number) {
		pbuf   = pginfo->u.phy.phys_buf_array + pginfo->u.phy.next_buf;
		num_hw  = NUM_CHUNKS((pbuf->addr % EHCA_PAGESIZE) +
				     pbuf->size, EHCA_PAGESIZE);
		offs_hw = (pbuf->addr & ~PAGE_MASK) / EHCA_PAGESIZE;
		while (pginfo->next_hwpage < offs_hw + num_hw) {
			/* sanity check */
			/* sanity check */
			if ((pginfo->kpage_cnt >= pginfo->num_kpages) ||
			if ((pginfo->kpage_cnt >= pginfo->num_kpages) ||
			    (pginfo->hwpage_cnt >= pginfo->num_hwpages)) {
			    (pginfo->hwpage_cnt >= pginfo->num_hwpages)) {
			ehca_gen_err("kpage_cnt >= num_hwpages, kpage_cnt=%lx "
				ehca_gen_err("kpage_cnt >= num_kpages, "
				     "num_hwpages=%lx hwpage_cnt=%lx num_hwpages=%lx",
					     "kpage_cnt=%lx num_kpages=%lx "
				     pginfo->kpage_cnt, pginfo->num_kpages,
					     "hwpage_cnt=%lx "
				     pginfo->hwpage_cnt, pginfo->num_hwpages);
					     "num_hwpages=%lx i=%x",
			ret = -EFAULT;
					     pginfo->kpage_cnt,
			goto ehca_set_pagebuf_1_exit0;
					     pginfo->num_kpages,
		}
					     pginfo->hwpage_cnt,
		tmp_pbuf = pginfo->u.phy.phys_buf_array + pginfo->u.phy.next_buf;
					     pginfo->num_hwpages, i);
		num_hw  = NUM_CHUNKS((tmp_pbuf->addr % EHCA_PAGESIZE) +
				return -EFAULT;
				     tmp_pbuf->size, EHCA_PAGESIZE);
			}
		offs_hw = (tmp_pbuf->addr & ~PAGE_MASK) / EHCA_PAGESIZE;
			*kpage = phys_to_abs(
		*rpage = phys_to_abs((tmp_pbuf->addr & EHCA_PAGEMASK) +
				(pbuf->addr & EHCA_PAGEMASK)
				     (pginfo->next_hwpage * EHCA_PAGESIZE));
				+ (pginfo->next_hwpage * EHCA_PAGESIZE));
		if ( !(*rpage) && tmp_pbuf->addr ) {
			if ( !(*kpage) && pbuf->addr ) {
			ehca_gen_err("tmp_pbuf->addr=%lx"
				ehca_gen_err("pbuf->addr=%lx "
				     " tmp_pbuf->size=%lx next_hwpage=%lx",
					     "pbuf->size=%lx "
				     tmp_pbuf->addr, tmp_pbuf->size,
					     "next_hwpage=%lx", pbuf->addr,
					     pbuf->size,
					     pginfo->next_hwpage);
					     pginfo->next_hwpage);
			ret = -EFAULT;
				return -EFAULT;
			goto ehca_set_pagebuf_1_exit0;
			}
			}
			(pginfo->hwpage_cnt)++;
			(pginfo->hwpage_cnt)++;
			(pginfo->next_hwpage)++;
			(pginfo->next_hwpage)++;
		if (pginfo->next_hwpage % (PAGE_SIZE / EHCA_PAGESIZE) == 0)
			if (pginfo->next_hwpage %
			    (PAGE_SIZE / EHCA_PAGESIZE) == 0)
				(pginfo->kpage_cnt)++;
				(pginfo->kpage_cnt)++;
			kpage++;
			i++;
			if (i >= number) break;
		}
		if (pginfo->next_hwpage >= offs_hw + num_hw) {
		if (pginfo->next_hwpage >= offs_hw + num_hw) {
			(pginfo->u.phy.next_buf)++;
			(pginfo->u.phy.next_buf)++;
			pginfo->next_hwpage = 0;
			pginfo->next_hwpage = 0;
		}
		}
	} else if (pginfo->type == EHCA_MR_PGI_USER) {
		chunk = pginfo->u.usr.next_chunk;
		prev_chunk = pginfo->u.usr.next_chunk;
		list_for_each_entry_continue(chunk,
					     (&(pginfo->u.usr.region->chunk_list)),
					     list) {
			pgaddr = ( page_to_pfn(chunk->page_list[
						       pginfo->u.usr.next_nmap].page)
				   << PAGE_SHIFT);
			*rpage = phys_to_abs(pgaddr +
					     (pginfo->next_hwpage * EHCA_PAGESIZE));
			if ( !(*rpage) ) {
				ehca_gen_err("pgaddr=%lx chunk->page_list[]=%lx"
					     " next_nmap=%lx next_hwpage=%lx mr=%p",
					     pgaddr, (u64)sg_dma_address(
						     &chunk->page_list[
							     pginfo->u.usr.
							     next_nmap]),
					     pginfo->u.usr.next_nmap, pginfo->next_hwpage,
					     e_mr);
				ret = -EFAULT;
				goto ehca_set_pagebuf_1_exit0;
			}
			(pginfo->hwpage_cnt)++;
			(pginfo->next_hwpage)++;
			if (pginfo->next_hwpage %
			    (PAGE_SIZE / EHCA_PAGESIZE) == 0) {
				(pginfo->kpage_cnt)++;
				(pginfo->u.usr.next_nmap)++;
				pginfo->next_hwpage = 0;
			}
			if (pginfo->u.usr.next_nmap >= chunk->nmap) {
				pginfo->u.usr.next_nmap = 0;
				prev_chunk = chunk;
	}
	}
			break;
	return ret;
}
}
		pginfo->u.usr.next_chunk =

			list_prepare_entry(prev_chunk,
int ehca_set_pagebuf_fmr(struct ehca_mr_pginfo *pginfo,
					   (&(pginfo->u.usr.region->chunk_list)),
			 u32 number,
					   list);
			 u64 *kpage)
	} else if (pginfo->type == EHCA_MR_PGI_FMR) {
{
	int ret = 0;
	u64 *fmrlist;
	u32 i;

	/* loop over desired page_list entries */
	fmrlist = pginfo->u.fmr.page_list + pginfo->u.fmr.next_listelem;
	fmrlist = pginfo->u.fmr.page_list + pginfo->u.fmr.next_listelem;
		*rpage = phys_to_abs((*fmrlist & EHCA_PAGEMASK) +
	for (i = 0; i < number; i++) {
		*kpage = phys_to_abs((*fmrlist & EHCA_PAGEMASK) +
				     pginfo->next_hwpage * EHCA_PAGESIZE);
				     pginfo->next_hwpage * EHCA_PAGESIZE);
		if ( !(*rpage) ) {
		if ( !(*kpage) ) {
			ehca_gen_err("*fmrlist=%lx fmrlist=%p "
			ehca_gen_err("*fmrlist=%lx fmrlist=%p "
				     "next_listelem=%lx next_hwpage=%lx",
				     "next_listelem=%lx next_hwpage=%lx",
				     *fmrlist, fmrlist, pginfo->u.fmr.next_listelem,
				     *fmrlist, fmrlist,
				     pginfo->u.fmr.next_listelem,
				     pginfo->next_hwpage);
				     pginfo->next_hwpage);
			ret = -EFAULT;
			return -EFAULT;
			goto ehca_set_pagebuf_1_exit0;
		}
		}
		(pginfo->hwpage_cnt)++;
		(pginfo->hwpage_cnt)++;
		(pginfo->next_hwpage)++;
		(pginfo->next_hwpage)++;
		kpage++;
		if (pginfo->next_hwpage %
		if (pginfo->next_hwpage %
		    (e_mr->fmr_page_size / EHCA_PAGESIZE) == 0) {
		    (pginfo->u.fmr.fmr_pgsize / EHCA_PAGESIZE) == 0) {
			(pginfo->kpage_cnt)++;
			(pginfo->kpage_cnt)++;
			(pginfo->u.fmr.next_listelem)++;
			(pginfo->u.fmr.next_listelem)++;
			fmrlist++;
			pginfo->next_hwpage = 0;
			pginfo->next_hwpage = 0;
		}
		}
	} else {
	}
	return ret;
}

/* setup page buffer from page info */
int ehca_set_pagebuf(struct ehca_mr_pginfo *pginfo,
		     u32 number,
		     u64 *kpage)
{
	int ret;

	switch (pginfo->type) {
	case EHCA_MR_PGI_PHYS:
		ret = ehca_set_pagebuf_phys(pginfo, number, kpage);
		break;
	case EHCA_MR_PGI_USER:
		ret = ehca_set_pagebuf_user1(pginfo, number, kpage);
		break;
	case EHCA_MR_PGI_FMR:
		ret = ehca_set_pagebuf_fmr(pginfo, number, kpage);
		break;
	default:
		ehca_gen_err("bad pginfo->type=%x", pginfo->type);
		ehca_gen_err("bad pginfo->type=%x", pginfo->type);
		ret = -EFAULT;
		ret = -EFAULT;
		goto ehca_set_pagebuf_1_exit0;
		break;
	}
	}

ehca_set_pagebuf_1_exit0:
	if (ret)
		ehca_gen_err("ret=%x e_mr=%p pginfo=%p type=%x num_kpages=%lx "
			     "num_hwpages=%lx next_buf=%lx next_hwpage=%lx rpage=%p "
			     "kpage_cnt=%lx hwpage_cnt=%lx next_listelem=%lx "
			     "region=%p next_chunk=%p next_nmap=%lx", ret, e_mr,
			     pginfo, pginfo->type, pginfo->num_kpages,
			     pginfo->num_hwpages, pginfo->u.phy.next_buf, pginfo->next_hwpage,
			     rpage, pginfo->kpage_cnt, pginfo->hwpage_cnt,
			     pginfo->u.fmr.next_listelem, pginfo->u.usr.region,
			     pginfo->u.usr.next_chunk, pginfo->u.usr.next_nmap);
	return ret;
	return ret;
} /* end ehca_set_pagebuf_1() */
} /* end ehca_set_pagebuf() */


/*----------------------------------------------------------------------*/
/*----------------------------------------------------------------------*/