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 + -
显示快捷键?