brintos

brintos / linux-shallow public Read only

0
0
Text · 29.3 KiB · 846da8c Raw
1214 lines · c
1/*2 * Copyright (c) 2016 Hisilicon Limited.3 * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved.4 *5 * This software is available to you under a choice of one of two6 * licenses.  You may choose to be licensed under the terms of the GNU7 * General Public License (GPL) Version 2, available from the file8 * COPYING in the main directory of this source tree, or the9 * OpenIB.org BSD license below:10 *11 *     Redistribution and use in source and binary forms, with or12 *     without modification, are permitted provided that the following13 *     conditions are met:14 *15 *      - Redistributions of source code must retain the above16 *        copyright notice, this list of conditions and the following17 *        disclaimer.18 *19 *      - Redistributions in binary form must reproduce the above20 *        copyright notice, this list of conditions and the following21 *        disclaimer in the documentation and/or other materials22 *        provided with the distribution.23 *24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE31 * SOFTWARE.32 */33 34#include <linux/vmalloc.h>35#include <linux/count_zeros.h>36#include <rdma/ib_umem.h>37#include <linux/math.h>38#include "hns_roce_device.h"39#include "hns_roce_cmd.h"40#include "hns_roce_hem.h"41 42static u32 hw_index_to_key(int ind)43{44	return ((u32)ind >> 24) | ((u32)ind << 8);45}46 47unsigned long key_to_hw_index(u32 key)48{49	return (key << 24) | (key >> 8);50}51 52static int alloc_mr_key(struct hns_roce_dev *hr_dev, struct hns_roce_mr *mr)53{54	struct hns_roce_ida *mtpt_ida = &hr_dev->mr_table.mtpt_ida;55	struct ib_device *ibdev = &hr_dev->ib_dev;56	int err;57	int id;58 59	/* Allocate a key for mr from mr_table */60	id = ida_alloc_range(&mtpt_ida->ida, mtpt_ida->min, mtpt_ida->max,61			     GFP_KERNEL);62	if (id < 0) {63		ibdev_err(ibdev, "failed to alloc id for MR key, id(%d)\n", id);64		return -ENOMEM;65	}66 67	mr->key = hw_index_to_key(id); /* MR key */68 69	err = hns_roce_table_get(hr_dev, &hr_dev->mr_table.mtpt_table,70				 (unsigned long)id);71	if (err) {72		ibdev_err(ibdev, "failed to alloc mtpt, ret = %d.\n", err);73		goto err_free_bitmap;74	}75 76	return 0;77err_free_bitmap:78	ida_free(&mtpt_ida->ida, id);79	return err;80}81 82static void free_mr_key(struct hns_roce_dev *hr_dev, struct hns_roce_mr *mr)83{84	unsigned long obj = key_to_hw_index(mr->key);85 86	hns_roce_table_put(hr_dev, &hr_dev->mr_table.mtpt_table, obj);87	ida_free(&hr_dev->mr_table.mtpt_ida.ida, (int)obj);88}89 90static int alloc_mr_pbl(struct hns_roce_dev *hr_dev, struct hns_roce_mr *mr,91			struct ib_udata *udata, u64 start)92{93	struct ib_device *ibdev = &hr_dev->ib_dev;94	bool is_fast = mr->type == MR_TYPE_FRMR;95	struct hns_roce_buf_attr buf_attr = {};96	int err;97 98	mr->pbl_hop_num = is_fast ? 1 : hr_dev->caps.pbl_hop_num;99	buf_attr.page_shift = is_fast ? PAGE_SHIFT :100			      hr_dev->caps.pbl_buf_pg_sz + PAGE_SHIFT;101	buf_attr.region[0].size = mr->size;102	buf_attr.region[0].hopnum = mr->pbl_hop_num;103	buf_attr.region_count = 1;104	buf_attr.user_access = mr->access;105	/* fast MR's buffer is alloced before mapping, not at creation */106	buf_attr.mtt_only = is_fast;107	buf_attr.iova = mr->iova;108	/* pagesize and hopnum is fixed for fast MR */109	buf_attr.adaptive = !is_fast;110	buf_attr.type = MTR_PBL;111 112	err = hns_roce_mtr_create(hr_dev, &mr->pbl_mtr, &buf_attr,113				  hr_dev->caps.pbl_ba_pg_sz + PAGE_SHIFT,114				  udata, start);115	if (err) {116		ibdev_err(ibdev, "failed to alloc pbl mtr, ret = %d.\n", err);117		return err;118	}119 120	mr->npages = mr->pbl_mtr.hem_cfg.buf_pg_count;121	mr->pbl_hop_num = buf_attr.region[0].hopnum;122 123	return err;124}125 126static void free_mr_pbl(struct hns_roce_dev *hr_dev, struct hns_roce_mr *mr)127{128	hns_roce_mtr_destroy(hr_dev, &mr->pbl_mtr);129}130 131static void hns_roce_mr_free(struct hns_roce_dev *hr_dev, struct hns_roce_mr *mr)132{133	struct ib_device *ibdev = &hr_dev->ib_dev;134	int ret;135 136	if (mr->enabled) {137		ret = hns_roce_destroy_hw_ctx(hr_dev, HNS_ROCE_CMD_DESTROY_MPT,138					      key_to_hw_index(mr->key) &139					      (hr_dev->caps.num_mtpts - 1));140		if (ret)141			ibdev_warn(ibdev, "failed to destroy mpt, ret = %d.\n",142				   ret);143	}144 145	free_mr_pbl(hr_dev, mr);146	free_mr_key(hr_dev, mr);147}148 149static int hns_roce_mr_enable(struct hns_roce_dev *hr_dev,150			      struct hns_roce_mr *mr)151{152	unsigned long mtpt_idx = key_to_hw_index(mr->key);153	struct hns_roce_cmd_mailbox *mailbox;154	struct device *dev = hr_dev->dev;155	int ret;156 157	/* Allocate mailbox memory */158	mailbox = hns_roce_alloc_cmd_mailbox(hr_dev);159	if (IS_ERR(mailbox))160		return PTR_ERR(mailbox);161 162	if (mr->type != MR_TYPE_FRMR)163		ret = hr_dev->hw->write_mtpt(hr_dev, mailbox->buf, mr);164	else165		ret = hr_dev->hw->frmr_write_mtpt(mailbox->buf, mr);166	if (ret) {167		dev_err(dev, "failed to write mtpt, ret = %d.\n", ret);168		goto err_page;169	}170 171	ret = hns_roce_create_hw_ctx(hr_dev, mailbox, HNS_ROCE_CMD_CREATE_MPT,172				     mtpt_idx & (hr_dev->caps.num_mtpts - 1));173	if (ret) {174		dev_err(dev, "failed to create mpt, ret = %d.\n", ret);175		goto err_page;176	}177 178	mr->enabled = 1;179 180err_page:181	hns_roce_free_cmd_mailbox(hr_dev, mailbox);182 183	return ret;184}185 186void hns_roce_init_mr_table(struct hns_roce_dev *hr_dev)187{188	struct hns_roce_ida *mtpt_ida = &hr_dev->mr_table.mtpt_ida;189 190	ida_init(&mtpt_ida->ida);191	mtpt_ida->max = hr_dev->caps.num_mtpts - 1;192	mtpt_ida->min = hr_dev->caps.reserved_mrws;193}194 195struct ib_mr *hns_roce_get_dma_mr(struct ib_pd *pd, int acc)196{197	struct hns_roce_dev *hr_dev = to_hr_dev(pd->device);198	struct hns_roce_mr *mr;199	int ret;200 201	mr = kzalloc(sizeof(*mr), GFP_KERNEL);202	if (!mr)203		return  ERR_PTR(-ENOMEM);204 205	mr->type = MR_TYPE_DMA;206	mr->pd = to_hr_pd(pd)->pdn;207	mr->access = acc;208 209	/* Allocate memory region key */210	hns_roce_hem_list_init(&mr->pbl_mtr.hem_list);211	ret = alloc_mr_key(hr_dev, mr);212	if (ret)213		goto err_free;214 215	ret = hns_roce_mr_enable(hr_dev, mr);216	if (ret)217		goto err_mr;218 219	mr->ibmr.rkey = mr->ibmr.lkey = mr->key;220 221	return &mr->ibmr;222err_mr:223	free_mr_key(hr_dev, mr);224 225err_free:226	kfree(mr);227	return ERR_PTR(ret);228}229 230struct ib_mr *hns_roce_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,231				   u64 virt_addr, int access_flags,232				   struct ib_udata *udata)233{234	struct hns_roce_dev *hr_dev = to_hr_dev(pd->device);235	struct hns_roce_mr *mr;236	int ret;237 238	mr = kzalloc(sizeof(*mr), GFP_KERNEL);239	if (!mr) {240		ret = -ENOMEM;241		goto err_out;242	}243 244	mr->iova = virt_addr;245	mr->size = length;246	mr->pd = to_hr_pd(pd)->pdn;247	mr->access = access_flags;248	mr->type = MR_TYPE_MR;249 250	ret = alloc_mr_key(hr_dev, mr);251	if (ret)252		goto err_alloc_mr;253 254	ret = alloc_mr_pbl(hr_dev, mr, udata, start);255	if (ret)256		goto err_alloc_key;257 258	ret = hns_roce_mr_enable(hr_dev, mr);259	if (ret)260		goto err_alloc_pbl;261 262	mr->ibmr.rkey = mr->ibmr.lkey = mr->key;263 264	return &mr->ibmr;265 266err_alloc_pbl:267	free_mr_pbl(hr_dev, mr);268err_alloc_key:269	free_mr_key(hr_dev, mr);270err_alloc_mr:271	kfree(mr);272err_out:273	atomic64_inc(&hr_dev->dfx_cnt[HNS_ROCE_DFX_MR_REG_ERR_CNT]);274 275	return ERR_PTR(ret);276}277 278struct ib_mr *hns_roce_rereg_user_mr(struct ib_mr *ibmr, int flags, u64 start,279				     u64 length, u64 virt_addr,280				     int mr_access_flags, struct ib_pd *pd,281				     struct ib_udata *udata)282{283	struct hns_roce_dev *hr_dev = to_hr_dev(ibmr->device);284	struct ib_device *ib_dev = &hr_dev->ib_dev;285	struct hns_roce_mr *mr = to_hr_mr(ibmr);286	struct hns_roce_cmd_mailbox *mailbox;287	unsigned long mtpt_idx;288	int ret;289 290	if (!mr->enabled) {291		ret = -EINVAL;292		goto err_out;293	}294 295	mailbox = hns_roce_alloc_cmd_mailbox(hr_dev);296	ret = PTR_ERR_OR_ZERO(mailbox);297	if (ret)298		goto err_out;299 300	mtpt_idx = key_to_hw_index(mr->key) & (hr_dev->caps.num_mtpts - 1);301 302	ret = hns_roce_cmd_mbox(hr_dev, 0, mailbox->dma, HNS_ROCE_CMD_QUERY_MPT,303				mtpt_idx);304	if (ret)305		goto free_cmd_mbox;306 307	ret = hns_roce_destroy_hw_ctx(hr_dev, HNS_ROCE_CMD_DESTROY_MPT,308				      mtpt_idx);309	if (ret)310		ibdev_warn(ib_dev, "failed to destroy MPT, ret = %d.\n", ret);311 312	mr->enabled = 0;313	mr->iova = virt_addr;314	mr->size = length;315 316	if (flags & IB_MR_REREG_PD)317		mr->pd = to_hr_pd(pd)->pdn;318 319	if (flags & IB_MR_REREG_ACCESS)320		mr->access = mr_access_flags;321 322	if (flags & IB_MR_REREG_TRANS) {323		free_mr_pbl(hr_dev, mr);324		ret = alloc_mr_pbl(hr_dev, mr, udata, start);325		if (ret) {326			ibdev_err(ib_dev, "failed to alloc mr PBL, ret = %d.\n",327				  ret);328			goto free_cmd_mbox;329		}330	}331 332	ret = hr_dev->hw->rereg_write_mtpt(hr_dev, mr, flags, mailbox->buf);333	if (ret) {334		ibdev_err(ib_dev, "failed to write mtpt, ret = %d.\n", ret);335		goto free_cmd_mbox;336	}337 338	ret = hns_roce_create_hw_ctx(hr_dev, mailbox, HNS_ROCE_CMD_CREATE_MPT,339				     mtpt_idx);340	if (ret) {341		ibdev_err(ib_dev, "failed to create MPT, ret = %d.\n", ret);342		goto free_cmd_mbox;343	}344 345	mr->enabled = 1;346 347free_cmd_mbox:348	hns_roce_free_cmd_mailbox(hr_dev, mailbox);349 350err_out:351	if (ret) {352		atomic64_inc(&hr_dev->dfx_cnt[HNS_ROCE_DFX_MR_REREG_ERR_CNT]);353		return ERR_PTR(ret);354	}355 356	return NULL;357}358 359int hns_roce_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata)360{361	struct hns_roce_dev *hr_dev = to_hr_dev(ibmr->device);362	struct hns_roce_mr *mr = to_hr_mr(ibmr);363 364	if (hr_dev->hw->dereg_mr)365		hr_dev->hw->dereg_mr(hr_dev);366 367	hns_roce_mr_free(hr_dev, mr);368	kfree(mr);369 370	return 0;371}372 373struct ib_mr *hns_roce_alloc_mr(struct ib_pd *pd, enum ib_mr_type mr_type,374				u32 max_num_sg)375{376	struct hns_roce_dev *hr_dev = to_hr_dev(pd->device);377	struct device *dev = hr_dev->dev;378	struct hns_roce_mr *mr;379	int ret;380 381	if (mr_type != IB_MR_TYPE_MEM_REG)382		return ERR_PTR(-EINVAL);383 384	if (max_num_sg > HNS_ROCE_FRMR_MAX_PA) {385		dev_err(dev, "max_num_sg larger than %d\n",386			HNS_ROCE_FRMR_MAX_PA);387		return ERR_PTR(-EINVAL);388	}389 390	mr = kzalloc(sizeof(*mr), GFP_KERNEL);391	if (!mr)392		return ERR_PTR(-ENOMEM);393 394	mr->type = MR_TYPE_FRMR;395	mr->pd = to_hr_pd(pd)->pdn;396	mr->size = max_num_sg * (1 << PAGE_SHIFT);397 398	/* Allocate memory region key */399	ret = alloc_mr_key(hr_dev, mr);400	if (ret)401		goto err_free;402 403	ret = alloc_mr_pbl(hr_dev, mr, NULL, 0);404	if (ret)405		goto err_key;406 407	ret = hns_roce_mr_enable(hr_dev, mr);408	if (ret)409		goto err_pbl;410 411	mr->ibmr.rkey = mr->ibmr.lkey = mr->key;412	mr->ibmr.length = mr->size;413 414	return &mr->ibmr;415 416err_pbl:417	free_mr_pbl(hr_dev, mr);418err_key:419	free_mr_key(hr_dev, mr);420err_free:421	kfree(mr);422	return ERR_PTR(ret);423}424 425static int hns_roce_set_page(struct ib_mr *ibmr, u64 addr)426{427	struct hns_roce_mr *mr = to_hr_mr(ibmr);428 429	if (likely(mr->npages < mr->pbl_mtr.hem_cfg.buf_pg_count)) {430		mr->page_list[mr->npages++] = addr;431		return 0;432	}433 434	return -ENOBUFS;435}436 437int hns_roce_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_nents,438		       unsigned int *sg_offset)439{440	struct hns_roce_dev *hr_dev = to_hr_dev(ibmr->device);441	struct ib_device *ibdev = &hr_dev->ib_dev;442	struct hns_roce_mr *mr = to_hr_mr(ibmr);443	struct hns_roce_mtr *mtr = &mr->pbl_mtr;444	int ret, sg_num = 0;445 446	if (!IS_ALIGNED(*sg_offset, HNS_ROCE_FRMR_ALIGN_SIZE) ||447	    ibmr->page_size < HNS_HW_PAGE_SIZE ||448	    ibmr->page_size > HNS_HW_MAX_PAGE_SIZE)449		return sg_num;450 451	mr->npages = 0;452	mr->page_list = kvcalloc(mr->pbl_mtr.hem_cfg.buf_pg_count,453				 sizeof(dma_addr_t), GFP_KERNEL);454	if (!mr->page_list)455		return sg_num;456 457	sg_num = ib_sg_to_pages(ibmr, sg, sg_nents, sg_offset, hns_roce_set_page);458	if (sg_num < 1) {459		ibdev_err(ibdev, "failed to store sg pages %u %u, cnt = %d.\n",460			  mr->npages, mr->pbl_mtr.hem_cfg.buf_pg_count, sg_num);461		goto err_page_list;462	}463 464	mtr->hem_cfg.region[0].offset = 0;465	mtr->hem_cfg.region[0].count = mr->npages;466	mtr->hem_cfg.region[0].hopnum = mr->pbl_hop_num;467	mtr->hem_cfg.region_count = 1;468	ret = hns_roce_mtr_map(hr_dev, mtr, mr->page_list, mr->npages);469	if (ret) {470		ibdev_err(ibdev, "failed to map sg mtr, ret = %d.\n", ret);471		sg_num = 0;472	} else {473		mr->pbl_mtr.hem_cfg.buf_pg_shift = (u32)ilog2(ibmr->page_size);474	}475 476err_page_list:477	kvfree(mr->page_list);478	mr->page_list = NULL;479 480	return sg_num;481}482 483static void hns_roce_mw_free(struct hns_roce_dev *hr_dev,484			     struct hns_roce_mw *mw)485{486	struct device *dev = hr_dev->dev;487	int ret;488 489	if (mw->enabled) {490		ret = hns_roce_destroy_hw_ctx(hr_dev, HNS_ROCE_CMD_DESTROY_MPT,491					      key_to_hw_index(mw->rkey) &492					      (hr_dev->caps.num_mtpts - 1));493		if (ret)494			dev_warn(dev, "MW DESTROY_MPT failed (%d)\n", ret);495 496		hns_roce_table_put(hr_dev, &hr_dev->mr_table.mtpt_table,497				   key_to_hw_index(mw->rkey));498	}499 500	ida_free(&hr_dev->mr_table.mtpt_ida.ida,501		 (int)key_to_hw_index(mw->rkey));502}503 504static int hns_roce_mw_enable(struct hns_roce_dev *hr_dev,505			      struct hns_roce_mw *mw)506{507	struct hns_roce_mr_table *mr_table = &hr_dev->mr_table;508	struct hns_roce_cmd_mailbox *mailbox;509	struct device *dev = hr_dev->dev;510	unsigned long mtpt_idx = key_to_hw_index(mw->rkey);511	int ret;512 513	/* prepare HEM entry memory */514	ret = hns_roce_table_get(hr_dev, &mr_table->mtpt_table, mtpt_idx);515	if (ret)516		return ret;517 518	mailbox = hns_roce_alloc_cmd_mailbox(hr_dev);519	if (IS_ERR(mailbox)) {520		ret = PTR_ERR(mailbox);521		goto err_table;522	}523 524	ret = hr_dev->hw->mw_write_mtpt(mailbox->buf, mw);525	if (ret) {526		dev_err(dev, "MW write mtpt fail!\n");527		goto err_page;528	}529 530	ret = hns_roce_create_hw_ctx(hr_dev, mailbox, HNS_ROCE_CMD_CREATE_MPT,531				     mtpt_idx & (hr_dev->caps.num_mtpts - 1));532	if (ret) {533		dev_err(dev, "MW CREATE_MPT failed (%d)\n", ret);534		goto err_page;535	}536 537	mw->enabled = 1;538 539	hns_roce_free_cmd_mailbox(hr_dev, mailbox);540 541	return 0;542 543err_page:544	hns_roce_free_cmd_mailbox(hr_dev, mailbox);545 546err_table:547	hns_roce_table_put(hr_dev, &mr_table->mtpt_table, mtpt_idx);548 549	return ret;550}551 552int hns_roce_alloc_mw(struct ib_mw *ibmw, struct ib_udata *udata)553{554	struct hns_roce_dev *hr_dev = to_hr_dev(ibmw->device);555	struct hns_roce_ida *mtpt_ida = &hr_dev->mr_table.mtpt_ida;556	struct ib_device *ibdev = &hr_dev->ib_dev;557	struct hns_roce_mw *mw = to_hr_mw(ibmw);558	int ret;559	int id;560 561	/* Allocate a key for mw from mr_table */562	id = ida_alloc_range(&mtpt_ida->ida, mtpt_ida->min, mtpt_ida->max,563			     GFP_KERNEL);564	if (id < 0) {565		ibdev_err(ibdev, "failed to alloc id for MW key, id(%d)\n", id);566		return -ENOMEM;567	}568 569	mw->rkey = hw_index_to_key(id);570 571	ibmw->rkey = mw->rkey;572	mw->pdn = to_hr_pd(ibmw->pd)->pdn;573	mw->pbl_hop_num = hr_dev->caps.pbl_hop_num;574	mw->pbl_ba_pg_sz = hr_dev->caps.pbl_ba_pg_sz;575	mw->pbl_buf_pg_sz = hr_dev->caps.pbl_buf_pg_sz;576 577	ret = hns_roce_mw_enable(hr_dev, mw);578	if (ret)579		goto err_mw;580 581	return 0;582 583err_mw:584	hns_roce_mw_free(hr_dev, mw);585	return ret;586}587 588int hns_roce_dealloc_mw(struct ib_mw *ibmw)589{590	struct hns_roce_dev *hr_dev = to_hr_dev(ibmw->device);591	struct hns_roce_mw *mw = to_hr_mw(ibmw);592 593	hns_roce_mw_free(hr_dev, mw);594	return 0;595}596 597static int mtr_map_region(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,598			  struct hns_roce_buf_region *region, dma_addr_t *pages,599			  int max_count)600{601	int count, npage;602	int offset, end;603	__le64 *mtts;604	u64 addr;605	int i;606 607	offset = region->offset;608	end = offset + region->count;609	npage = 0;610	while (offset < end && npage < max_count) {611		count = 0;612		mtts = hns_roce_hem_list_find_mtt(hr_dev, &mtr->hem_list,613						  offset, &count);614		if (!mtts)615			return -ENOBUFS;616 617		for (i = 0; i < count && npage < max_count; i++) {618			addr = pages[npage];619 620			mtts[i] = cpu_to_le64(addr);621			npage++;622		}623		offset += count;624	}625 626	return npage;627}628 629static inline bool mtr_has_mtt(struct hns_roce_buf_attr *attr)630{631	int i;632 633	for (i = 0; i < attr->region_count; i++)634		if (attr->region[i].hopnum != HNS_ROCE_HOP_NUM_0 &&635		    attr->region[i].hopnum > 0)636			return true;637 638	/* because the mtr only one root base address, when hopnum is 0 means639	 * root base address equals the first buffer address, thus all alloced640	 * memory must in a continuous space accessed by direct mode.641	 */642	return false;643}644 645static inline size_t mtr_bufs_size(struct hns_roce_buf_attr *attr)646{647	size_t size = 0;648	int i;649 650	for (i = 0; i < attr->region_count; i++)651		size += attr->region[i].size;652 653	return size;654}655 656/*657 * check the given pages in continuous address space658 * Returns 0 on success, or the error page num.659 */660static inline int mtr_check_direct_pages(dma_addr_t *pages, int page_count,661					 unsigned int page_shift)662{663	size_t page_size = 1 << page_shift;664	int i;665 666	for (i = 1; i < page_count; i++)667		if (pages[i] - pages[i - 1] != page_size)668			return i;669 670	return 0;671}672 673static void mtr_free_bufs(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr)674{675	/* release user buffers */676	if (mtr->umem) {677		ib_umem_release(mtr->umem);678		mtr->umem = NULL;679	}680 681	/* release kernel buffers */682	if (mtr->kmem) {683		hns_roce_buf_free(hr_dev, mtr->kmem);684		mtr->kmem = NULL;685	}686}687 688static int mtr_alloc_bufs(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,689			  struct hns_roce_buf_attr *buf_attr,690			  struct ib_udata *udata, unsigned long user_addr)691{692	struct ib_device *ibdev = &hr_dev->ib_dev;693	size_t total_size;694 695	total_size = mtr_bufs_size(buf_attr);696 697	if (udata) {698		mtr->kmem = NULL;699		mtr->umem = ib_umem_get(ibdev, user_addr, total_size,700					buf_attr->user_access);701		if (IS_ERR(mtr->umem)) {702			ibdev_err(ibdev, "failed to get umem, ret = %ld.\n",703				  PTR_ERR(mtr->umem));704			return -ENOMEM;705		}706	} else {707		mtr->umem = NULL;708		mtr->kmem = hns_roce_buf_alloc(hr_dev, total_size,709					       buf_attr->page_shift,710					       !mtr_has_mtt(buf_attr) ?711					       HNS_ROCE_BUF_DIRECT : 0);712		if (IS_ERR(mtr->kmem)) {713			ibdev_err(ibdev, "failed to alloc kmem, ret = %ld.\n",714				  PTR_ERR(mtr->kmem));715			return PTR_ERR(mtr->kmem);716		}717	}718 719	return 0;720}721 722static int cal_mtr_pg_cnt(struct hns_roce_mtr *mtr)723{724	struct hns_roce_buf_region *region;725	int page_cnt = 0;726	int i;727 728	for (i = 0; i < mtr->hem_cfg.region_count; i++) {729		region = &mtr->hem_cfg.region[i];730		page_cnt += region->count;731	}732 733	return page_cnt;734}735 736static bool need_split_huge_page(struct hns_roce_mtr *mtr)737{738	/* When HEM buffer uses 0-level addressing, the page size is739	 * equal to the whole buffer size. If the current MTR has multiple740	 * regions, we split the buffer into small pages(4k, required by hns741	 * ROCEE). These pages will be used in multiple regions.742	 */743	return mtr->hem_cfg.is_direct && mtr->hem_cfg.region_count > 1;744}745 746static int mtr_map_bufs(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr)747{748	struct ib_device *ibdev = &hr_dev->ib_dev;749	int page_count = cal_mtr_pg_cnt(mtr);750	unsigned int page_shift;751	dma_addr_t *pages;752	int npage;753	int ret;754 755	page_shift = need_split_huge_page(mtr) ? HNS_HW_PAGE_SHIFT :756						 mtr->hem_cfg.buf_pg_shift;757	/* alloc a tmp array to store buffer's dma address */758	pages = kvcalloc(page_count, sizeof(dma_addr_t), GFP_KERNEL);759	if (!pages)760		return -ENOMEM;761 762	if (mtr->umem)763		npage = hns_roce_get_umem_bufs(pages, page_count,764					       mtr->umem, page_shift);765	else766		npage = hns_roce_get_kmem_bufs(hr_dev, pages, page_count,767					       mtr->kmem, page_shift);768 769	if (npage != page_count) {770		ibdev_err(ibdev, "failed to get mtr page %d != %d.\n", npage,771			  page_count);772		ret = -ENOBUFS;773		goto err_alloc_list;774	}775 776	if (need_split_huge_page(mtr) && npage > 1) {777		ret = mtr_check_direct_pages(pages, npage, page_shift);778		if (ret) {779			ibdev_err(ibdev, "failed to check %s page: %d / %d.\n",780				  mtr->umem ? "umtr" : "kmtr", ret, npage);781			ret = -ENOBUFS;782			goto err_alloc_list;783		}784	}785 786	ret = hns_roce_mtr_map(hr_dev, mtr, pages, page_count);787	if (ret)788		ibdev_err(ibdev, "failed to map mtr pages, ret = %d.\n", ret);789 790err_alloc_list:791	kvfree(pages);792 793	return ret;794}795 796int hns_roce_mtr_map(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,797		     dma_addr_t *pages, unsigned int page_cnt)798{799	struct ib_device *ibdev = &hr_dev->ib_dev;800	struct hns_roce_buf_region *r;801	unsigned int i, mapped_cnt;802	int ret = 0;803 804	/*805	 * Only use the first page address as root ba when hopnum is 0, this806	 * is because the addresses of all pages are consecutive in this case.807	 */808	if (mtr->hem_cfg.is_direct) {809		mtr->hem_cfg.root_ba = pages[0];810		return 0;811	}812 813	for (i = 0, mapped_cnt = 0; i < mtr->hem_cfg.region_count &&814	     mapped_cnt < page_cnt; i++) {815		r = &mtr->hem_cfg.region[i];816		/* if hopnum is 0, no need to map pages in this region */817		if (!r->hopnum) {818			mapped_cnt += r->count;819			continue;820		}821 822		if (r->offset + r->count > page_cnt) {823			ret = -EINVAL;824			ibdev_err(ibdev,825				  "failed to check mtr%u count %u + %u > %u.\n",826				  i, r->offset, r->count, page_cnt);827			return ret;828		}829 830		ret = mtr_map_region(hr_dev, mtr, r, &pages[r->offset],831				     page_cnt - mapped_cnt);832		if (ret < 0) {833			ibdev_err(ibdev,834				  "failed to map mtr%u offset %u, ret = %d.\n",835				  i, r->offset, ret);836			return ret;837		}838		mapped_cnt += ret;839		ret = 0;840	}841 842	if (mapped_cnt < page_cnt) {843		ret = -ENOBUFS;844		ibdev_err(ibdev, "failed to map mtr pages count: %u < %u.\n",845			  mapped_cnt, page_cnt);846	}847 848	return ret;849}850 851static int hns_roce_get_direct_addr_mtt(struct hns_roce_hem_cfg *cfg,852					u32 start_index, u64 *mtt_buf,853					int mtt_cnt)854{855	int mtt_count;856	int total = 0;857	u32 npage;858	u64 addr;859 860	if (mtt_cnt > cfg->region_count)861		return -EINVAL;862 863	for (mtt_count = 0; mtt_count < cfg->region_count && total < mtt_cnt;864	     mtt_count++) {865		npage = cfg->region[mtt_count].offset;866		if (npage < start_index)867			continue;868 869		addr = cfg->root_ba + (npage << HNS_HW_PAGE_SHIFT);870		mtt_buf[total] = addr;871 872		total++;873	}874 875	if (!total)876		return -ENOENT;877 878	return 0;879}880 881static int hns_roce_get_mhop_mtt(struct hns_roce_dev *hr_dev,882				 struct hns_roce_mtr *mtr, u32 start_index,883				 u64 *mtt_buf, int mtt_cnt)884{885	int left = mtt_cnt;886	int total = 0;887	int mtt_count;888	__le64 *mtts;889	u32 npage;890 891	while (left > 0) {892		mtt_count = 0;893		mtts = hns_roce_hem_list_find_mtt(hr_dev, &mtr->hem_list,894						  start_index + total,895						  &mtt_count);896		if (!mtts || !mtt_count)897			break;898 899		npage = min(mtt_count, left);900		left -= npage;901		for (mtt_count = 0; mtt_count < npage; mtt_count++)902			mtt_buf[total++] = le64_to_cpu(mtts[mtt_count]);903	}904 905	if (!total)906		return -ENOENT;907 908	return 0;909}910 911int hns_roce_mtr_find(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,912		      u32 offset, u64 *mtt_buf, int mtt_max)913{914	struct hns_roce_hem_cfg *cfg = &mtr->hem_cfg;915	u32 start_index;916	int ret;917 918	if (!mtt_buf || mtt_max < 1)919		return -EINVAL;920 921	/* no mtt memory in direct mode, so just return the buffer address */922	if (cfg->is_direct) {923		start_index = offset >> HNS_HW_PAGE_SHIFT;924		ret = hns_roce_get_direct_addr_mtt(cfg, start_index,925						   mtt_buf, mtt_max);926	} else {927		start_index = offset >> cfg->buf_pg_shift;928		ret = hns_roce_get_mhop_mtt(hr_dev, mtr, start_index,929					    mtt_buf, mtt_max);930	}931	return ret;932}933 934static int get_best_page_shift(struct hns_roce_dev *hr_dev,935			       struct hns_roce_mtr *mtr,936			       struct hns_roce_buf_attr *buf_attr)937{938	unsigned int page_sz;939 940	if (!buf_attr->adaptive || buf_attr->type != MTR_PBL || !mtr->umem)941		return 0;942 943	page_sz = ib_umem_find_best_pgsz(mtr->umem,944					 hr_dev->caps.page_size_cap,945					 buf_attr->iova);946	if (!page_sz)947		return -EINVAL;948 949	buf_attr->page_shift = order_base_2(page_sz);950	return 0;951}952 953static int get_best_hop_num(struct hns_roce_dev *hr_dev,954			    struct hns_roce_mtr *mtr,955			    struct hns_roce_buf_attr *buf_attr,956			    unsigned int ba_pg_shift)957{958#define INVALID_HOPNUM -1959#define MIN_BA_CNT 1960	size_t buf_pg_sz = 1 << buf_attr->page_shift;961	struct ib_device *ibdev = &hr_dev->ib_dev;962	size_t ba_pg_sz = 1 << ba_pg_shift;963	int hop_num = INVALID_HOPNUM;964	size_t unit = MIN_BA_CNT;965	size_t ba_cnt;966	int j;967 968	if (!buf_attr->adaptive || buf_attr->type != MTR_PBL)969		return 0;970 971	/* Caculating the number of buf pages, each buf page need a BA */972	if (mtr->umem)973		ba_cnt = ib_umem_num_dma_blocks(mtr->umem, buf_pg_sz);974	else975		ba_cnt = DIV_ROUND_UP(buf_attr->region[0].size, buf_pg_sz);976 977	for (j = 0; j <= HNS_ROCE_MAX_HOP_NUM; j++) {978		if (ba_cnt <= unit) {979			hop_num = j;980			break;981		}982		/* Number of BAs can be represented at per hop */983		unit *= ba_pg_sz / BA_BYTE_LEN;984	}985 986	if (hop_num < 0) {987		ibdev_err(ibdev,988			  "failed to calculate a valid hopnum.\n");989		return -EINVAL;990	}991 992	buf_attr->region[0].hopnum = hop_num;993 994	return 0;995}996 997static bool is_buf_attr_valid(struct hns_roce_dev *hr_dev,998			      struct hns_roce_buf_attr *attr)999{1000	struct ib_device *ibdev = &hr_dev->ib_dev;1001 1002	if (attr->region_count > ARRAY_SIZE(attr->region) ||1003	    attr->region_count < 1 || attr->page_shift < HNS_HW_PAGE_SHIFT) {1004		ibdev_err(ibdev,1005			  "invalid buf attr, region count %d, page shift %u.\n",1006			  attr->region_count, attr->page_shift);1007		return false;1008	}1009 1010	return true;1011}1012 1013static int mtr_init_buf_cfg(struct hns_roce_dev *hr_dev,1014			    struct hns_roce_mtr *mtr,1015			    struct hns_roce_buf_attr *attr)1016{1017	struct hns_roce_hem_cfg *cfg = &mtr->hem_cfg;1018	struct hns_roce_buf_region *r;1019	size_t buf_pg_sz;1020	size_t buf_size;1021	int page_cnt, i;1022	u64 pgoff = 0;1023 1024	if (!is_buf_attr_valid(hr_dev, attr))1025		return -EINVAL;1026 1027	/* If mtt is disabled, all pages must be within a continuous range */1028	cfg->is_direct = !mtr_has_mtt(attr);1029	cfg->region_count = attr->region_count;1030	buf_size = mtr_bufs_size(attr);1031	if (need_split_huge_page(mtr)) {1032		buf_pg_sz = HNS_HW_PAGE_SIZE;1033		cfg->buf_pg_count = 1;1034		/* The ROCEE requires the page size to be 4K * 2 ^ N. */1035		cfg->buf_pg_shift = HNS_HW_PAGE_SHIFT +1036			order_base_2(DIV_ROUND_UP(buf_size, HNS_HW_PAGE_SIZE));1037	} else {1038		buf_pg_sz = 1 << attr->page_shift;1039		cfg->buf_pg_count = mtr->umem ?1040			ib_umem_num_dma_blocks(mtr->umem, buf_pg_sz) :1041			DIV_ROUND_UP(buf_size, buf_pg_sz);1042		cfg->buf_pg_shift = attr->page_shift;1043		pgoff = mtr->umem ? mtr->umem->address & ~PAGE_MASK : 0;1044	}1045 1046	/* Convert buffer size to page index and page count for each region and1047	 * the buffer's offset needs to be appended to the first region.1048	 */1049	for (page_cnt = 0, i = 0; i < attr->region_count; i++) {1050		r = &cfg->region[i];1051		r->offset = page_cnt;1052		buf_size = hr_hw_page_align(attr->region[i].size + pgoff);1053		if (attr->type == MTR_PBL && mtr->umem)1054			r->count = ib_umem_num_dma_blocks(mtr->umem, buf_pg_sz);1055		else1056			r->count = DIV_ROUND_UP(buf_size, buf_pg_sz);1057 1058		pgoff = 0;1059		page_cnt += r->count;1060		r->hopnum = to_hr_hem_hopnum(attr->region[i].hopnum, r->count);1061	}1062 1063	return 0;1064}1065 1066static u64 cal_pages_per_l1ba(unsigned int ba_per_bt, unsigned int hopnum)1067{1068	return int_pow(ba_per_bt, hopnum - 1);1069}1070 1071static unsigned int cal_best_bt_pg_sz(struct hns_roce_dev *hr_dev,1072				      struct hns_roce_mtr *mtr,1073				      unsigned int pg_shift)1074{1075	unsigned long cap = hr_dev->caps.page_size_cap;1076	struct hns_roce_buf_region *re;1077	unsigned int pgs_per_l1ba;1078	unsigned int ba_per_bt;1079	unsigned int ba_num;1080	int i;1081 1082	for_each_set_bit_from(pg_shift, &cap, sizeof(cap) * BITS_PER_BYTE) {1083		if (!(BIT(pg_shift) & cap))1084			continue;1085 1086		ba_per_bt = BIT(pg_shift) / BA_BYTE_LEN;1087		ba_num = 0;1088		for (i = 0; i < mtr->hem_cfg.region_count; i++) {1089			re = &mtr->hem_cfg.region[i];1090			if (re->hopnum == 0)1091				continue;1092 1093			pgs_per_l1ba = cal_pages_per_l1ba(ba_per_bt, re->hopnum);1094			ba_num += DIV_ROUND_UP(re->count, pgs_per_l1ba);1095		}1096 1097		if (ba_num <= ba_per_bt)1098			return pg_shift;1099	}1100 1101	return 0;1102}1103 1104static int mtr_alloc_mtt(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,1105			 unsigned int ba_page_shift)1106{1107	struct hns_roce_hem_cfg *cfg = &mtr->hem_cfg;1108	int ret;1109 1110	hns_roce_hem_list_init(&mtr->hem_list);1111	if (!cfg->is_direct) {1112		ba_page_shift = cal_best_bt_pg_sz(hr_dev, mtr, ba_page_shift);1113		if (!ba_page_shift)1114			return -ERANGE;1115 1116		ret = hns_roce_hem_list_request(hr_dev, &mtr->hem_list,1117						cfg->region, cfg->region_count,1118						ba_page_shift);1119		if (ret)1120			return ret;1121		cfg->root_ba = mtr->hem_list.root_ba;1122		cfg->ba_pg_shift = ba_page_shift;1123	} else {1124		cfg->ba_pg_shift = cfg->buf_pg_shift;1125	}1126 1127	return 0;1128}1129 1130static void mtr_free_mtt(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr)1131{1132	hns_roce_hem_list_release(hr_dev, &mtr->hem_list);1133}1134 1135/**1136 * hns_roce_mtr_create - Create hns memory translate region.1137 *1138 * @hr_dev: RoCE device struct pointer1139 * @mtr: memory translate region1140 * @buf_attr: buffer attribute for creating mtr1141 * @ba_page_shift: page shift for multi-hop base address table1142 * @udata: user space context, if it's NULL, means kernel space1143 * @user_addr: userspace virtual address to start at1144 */1145int hns_roce_mtr_create(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,1146			struct hns_roce_buf_attr *buf_attr,1147			unsigned int ba_page_shift, struct ib_udata *udata,1148			unsigned long user_addr)1149{1150	struct ib_device *ibdev = &hr_dev->ib_dev;1151	int ret;1152 1153	/* The caller has its own buffer list and invokes the hns_roce_mtr_map()1154	 * to finish the MTT configuration.1155	 */1156	if (buf_attr->mtt_only) {1157		mtr->umem = NULL;1158		mtr->kmem = NULL;1159	} else {1160		ret = mtr_alloc_bufs(hr_dev, mtr, buf_attr, udata, user_addr);1161		if (ret) {1162			ibdev_err(ibdev,1163				  "failed to alloc mtr bufs, ret = %d.\n", ret);1164			return ret;1165		}1166 1167		ret = get_best_page_shift(hr_dev, mtr, buf_attr);1168		if (ret)1169			goto err_init_buf;1170 1171		ret = get_best_hop_num(hr_dev, mtr, buf_attr, ba_page_shift);1172		if (ret)1173			goto err_init_buf;1174	}1175 1176	ret = mtr_init_buf_cfg(hr_dev, mtr, buf_attr);1177	if (ret)1178		goto err_init_buf;1179 1180	ret = mtr_alloc_mtt(hr_dev, mtr, ba_page_shift);1181	if (ret) {1182		ibdev_err(ibdev, "failed to alloc mtr mtt, ret = %d.\n", ret);1183		goto err_init_buf;1184	}1185 1186	if (buf_attr->mtt_only)1187		return 0;1188 1189	/* Write buffer's dma address to MTT */1190	ret = mtr_map_bufs(hr_dev, mtr);1191	if (ret) {1192		ibdev_err(ibdev, "failed to map mtr bufs, ret = %d.\n", ret);1193		goto err_alloc_mtt;1194	}1195 1196	return 0;1197 1198err_alloc_mtt:1199	mtr_free_mtt(hr_dev, mtr);1200err_init_buf:1201	mtr_free_bufs(hr_dev, mtr);1202 1203	return ret;1204}1205 1206void hns_roce_mtr_destroy(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr)1207{1208	/* release multi-hop addressing resource */1209	hns_roce_hem_list_release(hr_dev, &mtr->hem_list);1210 1211	/* free buffers */1212	mtr_free_bufs(hr_dev, mtr);1213}1214