ipath_verbs.c

来自「linux 内核源代码」· C语言 代码 · 共 1,887 行 · 第 1/4 页

C
1,887
字号
	return 0;}/** * ipath_get_npkeys - return the size of the PKEY table for port 0 * @dd: the infinipath device */unsigned ipath_get_npkeys(struct ipath_devdata *dd){	return ARRAY_SIZE(dd->ipath_pd[0]->port_pkeys);}/** * ipath_get_pkey - return the indexed PKEY from the port 0 PKEY table * @dd: the infinipath device * @index: the PKEY index */unsigned ipath_get_pkey(struct ipath_devdata *dd, unsigned index){	unsigned ret;	if (index >= ARRAY_SIZE(dd->ipath_pd[0]->port_pkeys))		ret = 0;	else		ret = dd->ipath_pd[0]->port_pkeys[index];	return ret;}static int ipath_query_pkey(struct ib_device *ibdev, u8 port, u16 index,			    u16 *pkey){	struct ipath_ibdev *dev = to_idev(ibdev);	int ret;	if (index >= ipath_get_npkeys(dev->dd)) {		ret = -EINVAL;		goto bail;	}	*pkey = ipath_get_pkey(dev->dd, index);	ret = 0;bail:	return ret;}/** * ipath_alloc_ucontext - allocate a ucontest * @ibdev: the infiniband device * @udata: not used by the InfiniPath driver */static struct ib_ucontext *ipath_alloc_ucontext(struct ib_device *ibdev,						struct ib_udata *udata){	struct ipath_ucontext *context;	struct ib_ucontext *ret;	context = kmalloc(sizeof *context, GFP_KERNEL);	if (!context) {		ret = ERR_PTR(-ENOMEM);		goto bail;	}	ret = &context->ibucontext;bail:	return ret;}static int ipath_dealloc_ucontext(struct ib_ucontext *context){	kfree(to_iucontext(context));	return 0;}static int ipath_verbs_register_sysfs(struct ib_device *dev);static void __verbs_timer(unsigned long arg){	struct ipath_devdata *dd = (struct ipath_devdata *) arg;	/* Handle verbs layer timeouts. */	ipath_ib_timer(dd->verbs_dev);	mod_timer(&dd->verbs_timer, jiffies + 1);}static int enable_timer(struct ipath_devdata *dd){	/*	 * Early chips had a design flaw where the chip and kernel idea	 * of the tail register don't always agree, and therefore we won't	 * get an interrupt on the next packet received.	 * If the board supports per packet receive interrupts, use it.	 * Otherwise, the timer function periodically checks for packets	 * to cover this case.	 * Either way, the timer is needed for verbs layer related	 * processing.	 */	if (dd->ipath_flags & IPATH_GPIO_INTR) {		ipath_write_kreg(dd, dd->ipath_kregs->kr_debugportselect,				 0x2074076542310ULL);		/* Enable GPIO bit 2 interrupt */		dd->ipath_gpio_mask |= (u64) (1 << IPATH_GPIO_PORT0_BIT);		ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_mask,				 dd->ipath_gpio_mask);	}	init_timer(&dd->verbs_timer);	dd->verbs_timer.function = __verbs_timer;	dd->verbs_timer.data = (unsigned long)dd;	dd->verbs_timer.expires = jiffies + 1;	add_timer(&dd->verbs_timer);	return 0;}static int disable_timer(struct ipath_devdata *dd){	/* Disable GPIO bit 2 interrupt */	if (dd->ipath_flags & IPATH_GPIO_INTR) {                /* Disable GPIO bit 2 interrupt */		dd->ipath_gpio_mask &= ~((u64) (1 << IPATH_GPIO_PORT0_BIT));		ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_mask,				 dd->ipath_gpio_mask);		/*		 * We might want to undo changes to debugportselect,		 * but how?		 */	}	del_timer_sync(&dd->verbs_timer);	return 0;}/** * ipath_register_ib_device - register our device with the infiniband core * @dd: the device data structure * Return the allocated ipath_ibdev pointer or NULL on error. */int ipath_register_ib_device(struct ipath_devdata *dd){	struct ipath_verbs_counters cntrs;	struct ipath_ibdev *idev;	struct ib_device *dev;	int ret;	idev = (struct ipath_ibdev *)ib_alloc_device(sizeof *idev);	if (idev == NULL) {		ret = -ENOMEM;		goto bail;	}	dev = &idev->ibdev;	/* Only need to initialize non-zero fields. */	spin_lock_init(&idev->n_pds_lock);	spin_lock_init(&idev->n_ahs_lock);	spin_lock_init(&idev->n_cqs_lock);	spin_lock_init(&idev->n_qps_lock);	spin_lock_init(&idev->n_srqs_lock);	spin_lock_init(&idev->n_mcast_grps_lock);	spin_lock_init(&idev->qp_table.lock);	spin_lock_init(&idev->lk_table.lock);	idev->sm_lid = __constant_be16_to_cpu(IB_LID_PERMISSIVE);	/* Set the prefix to the default value (see ch. 4.1.1) */	idev->gid_prefix = __constant_cpu_to_be64(0xfe80000000000000ULL);	ret = ipath_init_qp_table(idev, ib_ipath_qp_table_size);	if (ret)		goto err_qp;	/*	 * The top ib_ipath_lkey_table_size bits are used to index the	 * table.  The lower 8 bits can be owned by the user (copied from	 * the LKEY).  The remaining bits act as a generation number or tag.	 */	idev->lk_table.max = 1 << ib_ipath_lkey_table_size;	idev->lk_table.table = kzalloc(idev->lk_table.max *				       sizeof(*idev->lk_table.table),				       GFP_KERNEL);	if (idev->lk_table.table == NULL) {		ret = -ENOMEM;		goto err_lk;	}	INIT_LIST_HEAD(&idev->pending_mmaps);	spin_lock_init(&idev->pending_lock);	idev->mmap_offset = PAGE_SIZE;	spin_lock_init(&idev->mmap_offset_lock);	INIT_LIST_HEAD(&idev->pending[0]);	INIT_LIST_HEAD(&idev->pending[1]);	INIT_LIST_HEAD(&idev->pending[2]);	INIT_LIST_HEAD(&idev->piowait);	INIT_LIST_HEAD(&idev->rnrwait);	idev->pending_index = 0;	idev->port_cap_flags =		IB_PORT_SYS_IMAGE_GUID_SUP | IB_PORT_CLIENT_REG_SUP;	idev->pma_counter_select[0] = IB_PMA_PORT_XMIT_DATA;	idev->pma_counter_select[1] = IB_PMA_PORT_RCV_DATA;	idev->pma_counter_select[2] = IB_PMA_PORT_XMIT_PKTS;	idev->pma_counter_select[3] = IB_PMA_PORT_RCV_PKTS;	idev->pma_counter_select[4] = IB_PMA_PORT_XMIT_WAIT;	idev->link_width_enabled = 3;	/* 1x or 4x */	/* Snapshot current HW counters to "clear" them. */	ipath_get_counters(dd, &cntrs);	idev->z_symbol_error_counter = cntrs.symbol_error_counter;	idev->z_link_error_recovery_counter =		cntrs.link_error_recovery_counter;	idev->z_link_downed_counter = cntrs.link_downed_counter;	idev->z_port_rcv_errors = cntrs.port_rcv_errors;	idev->z_port_rcv_remphys_errors =		cntrs.port_rcv_remphys_errors;	idev->z_port_xmit_discards = cntrs.port_xmit_discards;	idev->z_port_xmit_data = cntrs.port_xmit_data;	idev->z_port_rcv_data = cntrs.port_rcv_data;	idev->z_port_xmit_packets = cntrs.port_xmit_packets;	idev->z_port_rcv_packets = cntrs.port_rcv_packets;	idev->z_local_link_integrity_errors =		cntrs.local_link_integrity_errors;	idev->z_excessive_buffer_overrun_errors =		cntrs.excessive_buffer_overrun_errors;	/*	 * The system image GUID is supposed to be the same for all	 * IB HCAs in a single system but since there can be other	 * device types in the system, we can't be sure this is unique.	 */	if (!sys_image_guid)		sys_image_guid = dd->ipath_guid;	idev->sys_image_guid = sys_image_guid;	idev->ib_unit = dd->ipath_unit;	idev->dd = dd;	strlcpy(dev->name, "ipath%d", IB_DEVICE_NAME_MAX);	dev->owner = THIS_MODULE;	dev->node_guid = dd->ipath_guid;	dev->uverbs_abi_ver = IPATH_UVERBS_ABI_VERSION;	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_CREATE_AH)		|		(1ull << IB_USER_VERBS_CMD_DESTROY_AH)		|		(1ull << IB_USER_VERBS_CMD_QUERY_AH)		|		(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_RESIZE_CQ)		|		(1ull << IB_USER_VERBS_CMD_DESTROY_CQ)		|		(1ull << IB_USER_VERBS_CMD_POLL_CQ)		|		(1ull << IB_USER_VERBS_CMD_REQ_NOTIFY_CQ)	|		(1ull << IB_USER_VERBS_CMD_CREATE_QP)		|		(1ull << IB_USER_VERBS_CMD_QUERY_QP)		|		(1ull << IB_USER_VERBS_CMD_MODIFY_QP)		|		(1ull << IB_USER_VERBS_CMD_DESTROY_QP)		|		(1ull << IB_USER_VERBS_CMD_POST_SEND)		|		(1ull << IB_USER_VERBS_CMD_POST_RECV)		|		(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_QUERY_SRQ)		|		(1ull << IB_USER_VERBS_CMD_DESTROY_SRQ)		|		(1ull << IB_USER_VERBS_CMD_POST_SRQ_RECV);	dev->node_type = RDMA_NODE_IB_CA;	dev->phys_port_cnt = 1;	dev->num_comp_vectors = 1;	dev->dma_device = &dd->pcidev->dev;	dev->query_device = ipath_query_device;	dev->modify_device = ipath_modify_device;	dev->query_port = ipath_query_port;	dev->modify_port = ipath_modify_port;	dev->query_pkey = ipath_query_pkey;	dev->query_gid = ipath_query_gid;	dev->alloc_ucontext = ipath_alloc_ucontext;	dev->dealloc_ucontext = ipath_dealloc_ucontext;	dev->alloc_pd = ipath_alloc_pd;	dev->dealloc_pd = ipath_dealloc_pd;	dev->create_ah = ipath_create_ah;	dev->destroy_ah = ipath_destroy_ah;	dev->query_ah = ipath_query_ah;	dev->create_srq = ipath_create_srq;	dev->modify_srq = ipath_modify_srq;	dev->query_srq = ipath_query_srq;	dev->destroy_srq = ipath_destroy_srq;	dev->create_qp = ipath_create_qp;	dev->modify_qp = ipath_modify_qp;	dev->query_qp = ipath_query_qp;	dev->destroy_qp = ipath_destroy_qp;	dev->post_send = ipath_post_send;	dev->post_recv = ipath_post_receive;	dev->post_srq_recv = ipath_post_srq_receive;	dev->create_cq = ipath_create_cq;	dev->destroy_cq = ipath_destroy_cq;	dev->resize_cq = ipath_resize_cq;	dev->poll_cq = ipath_poll_cq;	dev->req_notify_cq = ipath_req_notify_cq;	dev->get_dma_mr = ipath_get_dma_mr;	dev->reg_phys_mr = ipath_reg_phys_mr;	dev->reg_user_mr = ipath_reg_user_mr;	dev->dereg_mr = ipath_dereg_mr;	dev->alloc_fmr = ipath_alloc_fmr;	dev->map_phys_fmr = ipath_map_phys_fmr;	dev->unmap_fmr = ipath_unmap_fmr;	dev->dealloc_fmr = ipath_dealloc_fmr;	dev->attach_mcast = ipath_multicast_attach;	dev->detach_mcast = ipath_multicast_detach;	dev->process_mad = ipath_process_mad;	dev->mmap = ipath_mmap;	dev->dma_ops = &ipath_dma_mapping_ops;	snprintf(dev->node_desc, sizeof(dev->node_desc),		 IPATH_IDSTR " %s", init_utsname()->nodename);	ret = ib_register_device(dev);	if (ret)		goto err_reg;	if (ipath_verbs_register_sysfs(dev))		goto err_class;	enable_timer(dd);	goto bail;err_class:	ib_unregister_device(dev);err_reg:	kfree(idev->lk_table.table);err_lk:	kfree(idev->qp_table.table);err_qp:	ib_dealloc_device(dev);	ipath_dev_err(dd, "cannot register verbs: %d!\n", -ret);	idev = NULL;bail:	dd->verbs_dev = idev;	return ret;}void ipath_unregister_ib_device(struct ipath_ibdev *dev){	struct ib_device *ibdev = &dev->ibdev;	disable_timer(dev->dd);	ib_unregister_device(ibdev);	if (!list_empty(&dev->pending[0]) ||	    !list_empty(&dev->pending[1]) ||	    !list_empty(&dev->pending[2]))		ipath_dev_err(dev->dd, "pending list not empty!\n");	if (!list_empty(&dev->piowait))		ipath_dev_err(dev->dd, "piowait list not empty!\n");	if (!list_empty(&dev->rnrwait))		ipath_dev_err(dev->dd, "rnrwait list not empty!\n");	if (!ipath_mcast_tree_empty())		ipath_dev_err(dev->dd, "multicast table memory leak!\n");	/*	 * Note that ipath_unregister_ib_device() can be called before all	 * the QPs are destroyed!	 */	ipath_free_all_qps(&dev->qp_table);	kfree(dev->qp_table.table);	kfree(dev->lk_table.table);	ib_dealloc_device(ibdev);}static ssize_t show_rev(struct class_device *cdev, char *buf){	struct ipath_ibdev *dev =		container_of(cdev, struct ipath_ibdev, ibdev.class_dev);	return sprintf(buf, "%x\n", dev->dd->ipath_pcirev);}static ssize_t show_hca(struct class_device *cdev, char *buf){	struct ipath_ibdev *dev =		container_of(cdev, struct ipath_ibdev, ibdev.class_dev);	int ret;	ret = dev->dd->ipath_f_get_boardname(dev->dd, buf, 128);	if (ret < 0)		goto bail;	strcat(buf, "\n");	ret = strlen(buf);bail:	return ret;}static ssize_t show_stats(struct class_device *cdev, char *buf){	struct ipath_ibdev *dev =		container_of(cdev, struct ipath_ibdev, ibdev.class_dev);	int i;	int len;	len = sprintf(buf,		      "RC resends  %d\n"		      "RC no QACK  %d\n"		      "RC ACKs     %d\n"		      "RC SEQ NAKs %d\n"		      "RC RDMA seq %d\n"		      "RC RNR NAKs %d\n"		      "RC OTH NAKs %d\n"		      "RC timeouts %d\n"		      "RC RDMA dup %d\n"		      "RC stalls   %d\n"		      "piobuf wait %d\n"		      "no piobuf   %d\n"		      "PKT drops   %d\n"		      "WQE errs    %d\n",		      dev->n_rc_resends, dev->n_rc_qacks, dev->n_rc_acks,		      dev->n_seq_naks, dev->n_rdma_seq, dev->n_rnr_naks,		      dev->n_other_naks, dev->n_timeouts,		      dev->n_rdma_dup_busy, dev->n_rc_stalls, dev->n_piowait,		      dev->n_no_piobuf, dev->n_pkt_drops, dev->n_wqe_errs);	for (i = 0; i < ARRAY_SIZE(dev->opstats); i++) {		const struct ipath_opcode_stats *si = &dev->opstats[i];		if (!si->n_packets && !si->n_bytes)			continue;		len += sprintf(buf + len, "%02x %llu/%llu\n", i,			       (unsigned long long) si->n_packets,			       (unsigned long long) si->n_bytes);	}	return len;}static CLASS_DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);static CLASS_DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);static CLASS_DEVICE_ATTR(board_id, S_IRUGO, show_hca, NULL);static CLASS_DEVICE_ATTR(stats, S_IRUGO, show_stats, NULL);static struct class_device_attribute *ipath_class_attributes[] = {	&class_device_attr_hw_rev,	&class_device_attr_hca_type,	&class_device_attr_board_id,	&class_device_attr_stats};static int ipath_verbs_register_sysfs(struct ib_device *dev){	int i;	int ret;	for (i = 0; i < ARRAY_SIZE(ipath_class_attributes); ++i)		if (class_device_create_file(&dev->class_dev,					     ipath_class_attributes[i])) {			ret = 1;			goto bail;		}	ret = 0;bail:	return ret;}

⌨️ 快捷键说明

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