⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mthca_provider.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
		if (i != 0 && i != num_phys_buf - 1 &&		    (buffer_list[i].size & ~PAGE_MASK))			return ERR_PTR(-EINVAL);		total_size += buffer_list[i].size;		if (i > 0)			mask |= buffer_list[i].addr;	}	/* Find largest page shift we can use to cover buffers */	for (shift = PAGE_SHIFT; shift < 31; ++shift)		if (num_phys_buf > 1) {			if ((1ULL << shift) & mask)				break;		} else {			if (1ULL << shift >=			    buffer_list[0].size +			    (buffer_list[0].addr & ((1ULL << shift) - 1)))				break;		}	buffer_list[0].size += buffer_list[0].addr & ((1ULL << shift) - 1);	buffer_list[0].addr &= ~0ull << shift;	mr = kmalloc(sizeof *mr, GFP_KERNEL);	if (!mr)		return ERR_PTR(-ENOMEM);	npages = 0;	for (i = 0; i < num_phys_buf; ++i)		npages += (buffer_list[i].size + (1ULL << shift) - 1) >> shift;	if (!npages)		return &mr->ibmr;	page_list = kmalloc(npages * sizeof *page_list, GFP_KERNEL);	if (!page_list) {		kfree(mr);		return ERR_PTR(-ENOMEM);	}	n = 0;	for (i = 0; i < num_phys_buf; ++i)		for (j = 0;		     j < (buffer_list[i].size + (1ULL << shift) - 1) >> shift;		     ++j)			page_list[n++] = buffer_list[i].addr + ((u64) j << shift);	mthca_dbg(to_mdev(pd->device), "Registering memory at %llx (iova %llx) "		  "in PD %x; shift %d, npages %d.\n",		  (unsigned long long) buffer_list[0].addr,		  (unsigned long long) *iova_start,		  to_mpd(pd)->pd_num,		  shift, npages);	err = mthca_mr_alloc_phys(to_mdev(pd->device),				  to_mpd(pd)->pd_num,				  page_list, shift, npages,				  *iova_start, total_size,				  convert_access(acc), mr);	if (err) {		kfree(page_list);		kfree(mr);		return ERR_PTR(err);	}	kfree(page_list);	return &mr->ibmr;}static struct ib_mr *mthca_reg_user_mr(struct ib_pd *pd, struct ib_umem *region,				       int acc, struct ib_udata *udata){	struct mthca_dev *dev = to_mdev(pd->device);	struct ib_umem_chunk *chunk;	struct mthca_mr *mr;	u64 *pages;	int shift, n, len;	int i, j, k;	int err = 0;	shift = ffs(region->page_size) - 1;	mr = kmalloc(sizeof *mr, GFP_KERNEL);	if (!mr)		return ERR_PTR(-ENOMEM);	n = 0;	list_for_each_entry(chunk, &region->chunk_list, list)		n += chunk->nents;	mr->mtt = mthca_alloc_mtt(dev, n);	if (IS_ERR(mr->mtt)) {		err = PTR_ERR(mr->mtt);		goto err;	}	pages = (u64 *) __get_free_page(GFP_KERNEL);	if (!pages) {		err = -ENOMEM;		goto err_mtt;	}	i = n = 0;	list_for_each_entry(chunk, &region->chunk_list, list)		for (j = 0; j < chunk->nmap; ++j) {			len = sg_dma_len(&chunk->page_list[j]) >> shift;			for (k = 0; k < len; ++k) {				pages[i++] = sg_dma_address(&chunk->page_list[j]) +					region->page_size * k;				/*				 * Be friendly to WRITE_MTT command				 * and leave two empty slots for the				 * index and reserved fields of the				 * mailbox.				 */				if (i == PAGE_SIZE / sizeof (u64) - 2) {					err = mthca_write_mtt(dev, mr->mtt,							      n, pages, i);					if (err)						goto mtt_done;					n += i;					i = 0;				}			}		}	if (i)		err = mthca_write_mtt(dev, mr->mtt, n, pages, i);mtt_done:	free_page((unsigned long) pages);	if (err)		goto err_mtt;	err = mthca_mr_alloc(dev, to_mpd(pd)->pd_num, shift, region->virt_base,			     region->length, convert_access(acc), mr);	if (err)		goto err_mtt;	return &mr->ibmr;err_mtt:	mthca_free_mtt(dev, mr->mtt);err:	kfree(mr);	return ERR_PTR(err);}static int mthca_dereg_mr(struct ib_mr *mr){	struct mthca_mr *mmr = to_mmr(mr);	mthca_free_mr(to_mdev(mr->device), mmr);	kfree(mmr);	return 0;}static struct ib_fmr *mthca_alloc_fmr(struct ib_pd *pd, int mr_access_flags,				      struct ib_fmr_attr *fmr_attr){	struct mthca_fmr *fmr;	int err;	fmr = kmalloc(sizeof *fmr, GFP_KERNEL);	if (!fmr)		return ERR_PTR(-ENOMEM);	memcpy(&fmr->attr, fmr_attr, sizeof *fmr_attr);	err = mthca_fmr_alloc(to_mdev(pd->device), to_mpd(pd)->pd_num,			     convert_access(mr_access_flags), fmr);	if (err) {		kfree(fmr);		return ERR_PTR(err);	}	return &fmr->ibmr;}static int mthca_dealloc_fmr(struct ib_fmr *fmr){	struct mthca_fmr *mfmr = to_mfmr(fmr);	int err;	err = mthca_free_fmr(to_mdev(fmr->device), mfmr);	if (err)		return err;	kfree(mfmr);	return 0;}static int mthca_unmap_fmr(struct list_head *fmr_list){	struct ib_fmr *fmr;	int err;	u8 status;	struct mthca_dev *mdev = NULL;	list_for_each_entry(fmr, fmr_list, list) {		if (mdev && to_mdev(fmr->device) != mdev)			return -EINVAL;		mdev = to_mdev(fmr->device);	}	if (!mdev)		return 0;	if (mthca_is_memfree(mdev)) {		list_for_each_entry(fmr, fmr_list, list)			mthca_arbel_fmr_unmap(mdev, to_mfmr(fmr));		wmb();	} else		list_for_each_entry(fmr, fmr_list, list)			mthca_tavor_fmr_unmap(mdev, to_mfmr(fmr));	err = mthca_SYNC_TPT(mdev, &status);	if (err)		return err;	if (status)		return -EINVAL;	return 0;}static ssize_t show_rev(struct class_device *cdev, char *buf){	struct mthca_dev *dev = container_of(cdev, struct mthca_dev, ib_dev.class_dev);	return sprintf(buf, "%x\n", dev->rev_id);}static ssize_t show_fw_ver(struct class_device *cdev, char *buf){	struct mthca_dev *dev = container_of(cdev, struct mthca_dev, ib_dev.class_dev);	return sprintf(buf, "%d.%d.%d\n", (int) (dev->fw_ver >> 32),		       (int) (dev->fw_ver >> 16) & 0xffff,		       (int) dev->fw_ver & 0xffff);}static ssize_t show_hca(struct class_device *cdev, char *buf){	struct mthca_dev *dev = container_of(cdev, struct mthca_dev, ib_dev.class_dev);	switch (dev->pdev->device) {	case PCI_DEVICE_ID_MELLANOX_TAVOR:		return sprintf(buf, "MT23108\n");	case PCI_DEVICE_ID_MELLANOX_ARBEL_COMPAT:		return sprintf(buf, "MT25208 (MT23108 compat mode)\n");	case PCI_DEVICE_ID_MELLANOX_ARBEL:		return sprintf(buf, "MT25208\n");	case PCI_DEVICE_ID_MELLANOX_SINAI:	case PCI_DEVICE_ID_MELLANOX_SINAI_OLD:		return sprintf(buf, "MT25204\n");	default:		return sprintf(buf, "unknown\n");	}}static ssize_t show_board(struct class_device *cdev, char *buf){	struct mthca_dev *dev = container_of(cdev, struct mthca_dev, ib_dev.class_dev);	return sprintf(buf, "%.*s\n", MTHCA_BOARD_ID_LEN, dev->board_id);}static CLASS_DEVICE_ATTR(hw_rev,   S_IRUGO, show_rev,    NULL);static CLASS_DEVICE_ATTR(fw_ver,   S_IRUGO, show_fw_ver, NULL);static CLASS_DEVICE_ATTR(hca_type, S_IRUGO, show_hca,    NULL);static CLASS_DEVICE_ATTR(board_id, S_IRUGO, show_board,  NULL);static struct class_device_attribute *mthca_class_attributes[] = {	&class_device_attr_hw_rev,	&class_device_attr_fw_ver,	&class_device_attr_hca_type,	&class_device_attr_board_id};int mthca_register_device(struct mthca_dev *dev){	int ret;	int i;	strlcpy(dev->ib_dev.name, "mthca%d", IB_DEVICE_NAME_MAX);	dev->ib_dev.owner                = THIS_MODULE;	dev->ib_dev.uverbs_abi_ver	 = MTHCA_UVERBS_ABI_VERSION;	dev->ib_dev.uverbs_cmd_mask	 =		(1ull << IB_USER_VERBS_CMD_GET_CONTEXT)		|		(1ull << IB_USER_VERBS_CMD_QUERY_DEVICE)	|		(1ull << IB_USER_VERBS_CMD_QUERY_PORT)		|		(1ull << IB_USER_VERBS_CMD_ALLOC_PD)		|		(1ull << IB_USER_VERBS_CMD_DEALLOC_PD)		|		(1ull << IB_USER_VERBS_CMD_REG_MR)		|		(1ull << IB_USER_VERBS_CMD_DEREG_MR)		|		(1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL)	|		(1ull << IB_USER_VERBS_CMD_CREATE_CQ)		|		(1ull << IB_USER_VERBS_CMD_DESTROY_CQ)		|		(1ull << IB_USER_VERBS_CMD_CREATE_QP)		|		(1ull << IB_USER_VERBS_CMD_MODIFY_QP)		|		(1ull << IB_USER_VERBS_CMD_DESTROY_QP)		|		(1ull << IB_USER_VERBS_CMD_ATTACH_MCAST)	|		(1ull << IB_USER_VERBS_CMD_DETACH_MCAST)	|		(1ull << IB_USER_VERBS_CMD_CREATE_SRQ)		|		(1ull << IB_USER_VERBS_CMD_MODIFY_SRQ)		|		(1ull << IB_USER_VERBS_CMD_DESTROY_SRQ);	dev->ib_dev.node_type            = IB_NODE_CA;	dev->ib_dev.phys_port_cnt        = dev->limits.num_ports;	dev->ib_dev.dma_device           = &dev->pdev->dev;	dev->ib_dev.class_dev.dev        = &dev->pdev->dev;	dev->ib_dev.query_device         = mthca_query_device;	dev->ib_dev.query_port           = mthca_query_port;	dev->ib_dev.modify_port          = mthca_modify_port;	dev->ib_dev.query_pkey           = mthca_query_pkey;	dev->ib_dev.query_gid            = mthca_query_gid;	dev->ib_dev.alloc_ucontext       = mthca_alloc_ucontext;	dev->ib_dev.dealloc_ucontext     = mthca_dealloc_ucontext;	dev->ib_dev.mmap                 = mthca_mmap_uar;	dev->ib_dev.alloc_pd             = mthca_alloc_pd;	dev->ib_dev.dealloc_pd           = mthca_dealloc_pd;	dev->ib_dev.create_ah            = mthca_ah_create;	dev->ib_dev.destroy_ah           = mthca_ah_destroy;	if (dev->mthca_flags & MTHCA_FLAG_SRQ) {		dev->ib_dev.create_srq           = mthca_create_srq;		dev->ib_dev.modify_srq		 = mthca_modify_srq;		dev->ib_dev.destroy_srq          = mthca_destroy_srq;		if (mthca_is_memfree(dev))			dev->ib_dev.post_srq_recv = mthca_arbel_post_srq_recv;		else			dev->ib_dev.post_srq_recv = mthca_tavor_post_srq_recv;	}	dev->ib_dev.create_qp            = mthca_create_qp;	dev->ib_dev.modify_qp            = mthca_modify_qp;	dev->ib_dev.destroy_qp           = mthca_destroy_qp;	dev->ib_dev.create_cq            = mthca_create_cq;	dev->ib_dev.destroy_cq           = mthca_destroy_cq;	dev->ib_dev.poll_cq              = mthca_poll_cq;	dev->ib_dev.get_dma_mr           = mthca_get_dma_mr;	dev->ib_dev.reg_phys_mr          = mthca_reg_phys_mr;	dev->ib_dev.reg_user_mr          = mthca_reg_user_mr;	dev->ib_dev.dereg_mr             = mthca_dereg_mr;	if (dev->mthca_flags & MTHCA_FLAG_FMR) {		dev->ib_dev.alloc_fmr            = mthca_alloc_fmr;		dev->ib_dev.unmap_fmr            = mthca_unmap_fmr;		dev->ib_dev.dealloc_fmr          = mthca_dealloc_fmr;		if (mthca_is_memfree(dev))			dev->ib_dev.map_phys_fmr = mthca_arbel_map_phys_fmr;		else			dev->ib_dev.map_phys_fmr = mthca_tavor_map_phys_fmr;	}	dev->ib_dev.attach_mcast         = mthca_multicast_attach;	dev->ib_dev.detach_mcast         = mthca_multicast_detach;	dev->ib_dev.process_mad          = mthca_process_mad;	if (mthca_is_memfree(dev)) {		dev->ib_dev.req_notify_cq = mthca_arbel_arm_cq;		dev->ib_dev.post_send     = mthca_arbel_post_send;		dev->ib_dev.post_recv     = mthca_arbel_post_receive;	} else {		dev->ib_dev.req_notify_cq = mthca_tavor_arm_cq;		dev->ib_dev.post_send     = mthca_tavor_post_send;		dev->ib_dev.post_recv     = mthca_tavor_post_receive;	}	init_MUTEX(&dev->cap_mask_mutex);	ret = ib_register_device(&dev->ib_dev);	if (ret)		return ret;	for (i = 0; i < ARRAY_SIZE(mthca_class_attributes); ++i) {		ret = class_device_create_file(&dev->ib_dev.class_dev,					       mthca_class_attributes[i]);		if (ret) {			ib_unregister_device(&dev->ib_dev);			return ret;		}	}	mthca_start_catas_poll(dev);	return 0;}void mthca_unregister_device(struct mthca_dev *dev){	mthca_stop_catas_poll(dev);	ib_unregister_device(&dev->ib_dev);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -