📄 ehca_main.c
字号:
if (sport->ibcq_aqp1) { ehca_err(&shca->ib_device, "AQP1 CQ is already created."); return -EPERM; } ibcq = ib_create_cq(&shca->ib_device, NULL, NULL, (void *)(-1), 10, 0); if (IS_ERR(ibcq)) { ehca_err(&shca->ib_device, "Cannot create AQP1 CQ."); return PTR_ERR(ibcq); } sport->ibcq_aqp1 = ibcq; if (sport->ibqp_aqp1) { ehca_err(&shca->ib_device, "AQP1 QP is already created."); ret = -EPERM; goto create_aqp1; } memset(&qp_init_attr, 0, sizeof(struct ib_qp_init_attr)); qp_init_attr.send_cq = ibcq; qp_init_attr.recv_cq = ibcq; qp_init_attr.sq_sig_type = IB_SIGNAL_ALL_WR; qp_init_attr.cap.max_send_wr = 100; qp_init_attr.cap.max_recv_wr = 100; qp_init_attr.cap.max_send_sge = 2; qp_init_attr.cap.max_recv_sge = 1; qp_init_attr.qp_type = IB_QPT_GSI; qp_init_attr.port_num = port; qp_init_attr.qp_context = NULL; qp_init_attr.event_handler = NULL; qp_init_attr.srq = NULL; ibqp = ib_create_qp(&shca->pd->ib_pd, &qp_init_attr); if (IS_ERR(ibqp)) { ehca_err(&shca->ib_device, "Cannot create AQP1 QP."); ret = PTR_ERR(ibqp); goto create_aqp1; } sport->ibqp_aqp1 = ibqp; return 0;create_aqp1: ib_destroy_cq(sport->ibcq_aqp1); return ret;}static int ehca_destroy_aqp1(struct ehca_sport *sport){ int ret; ret = ib_destroy_qp(sport->ibqp_aqp1); if (ret) { ehca_gen_err("Cannot destroy AQP1 QP. ret=%i", ret); return ret; } ret = ib_destroy_cq(sport->ibcq_aqp1); if (ret) ehca_gen_err("Cannot destroy AQP1 CQ. ret=%i", ret); return ret;}static ssize_t ehca_show_debug_level(struct device_driver *ddp, char *buf){ return snprintf(buf, PAGE_SIZE, "%d\n", ehca_debug_level);}static ssize_t ehca_store_debug_level(struct device_driver *ddp, const char *buf, size_t count){ int value = (*buf) - '0'; if (value >= 0 && value <= 9) ehca_debug_level = value; return 1;}DRIVER_ATTR(debug_level, S_IRUSR | S_IWUSR, ehca_show_debug_level, ehca_store_debug_level);static struct attribute *ehca_drv_attrs[] = { &driver_attr_debug_level.attr, NULL};static struct attribute_group ehca_drv_attr_grp = { .attrs = ehca_drv_attrs};#define EHCA_RESOURCE_ATTR(name) \static ssize_t ehca_show_##name(struct device *dev, \ struct device_attribute *attr, \ char *buf) \{ \ struct ehca_shca *shca; \ struct hipz_query_hca *rblock; \ int data; \ \ shca = dev->driver_data; \ \ rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL); \ if (!rblock) { \ dev_err(dev, "Can't allocate rblock memory.\n"); \ return 0; \ } \ \ if (hipz_h_query_hca(shca->ipz_hca_handle, rblock) != H_SUCCESS) { \ dev_err(dev, "Can't query device properties\n"); \ ehca_free_fw_ctrlblock(rblock); \ return 0; \ } \ \ data = rblock->name; \ ehca_free_fw_ctrlblock(rblock); \ \ if ((strcmp(#name, "num_ports") == 0) && (ehca_nr_ports == 1)) \ return snprintf(buf, 256, "1\n"); \ else \ return snprintf(buf, 256, "%d\n", data); \ \} \static DEVICE_ATTR(name, S_IRUGO, ehca_show_##name, NULL);EHCA_RESOURCE_ATTR(num_ports);EHCA_RESOURCE_ATTR(hw_ver);EHCA_RESOURCE_ATTR(max_eq);EHCA_RESOURCE_ATTR(cur_eq);EHCA_RESOURCE_ATTR(max_cq);EHCA_RESOURCE_ATTR(cur_cq);EHCA_RESOURCE_ATTR(max_qp);EHCA_RESOURCE_ATTR(cur_qp);EHCA_RESOURCE_ATTR(max_mr);EHCA_RESOURCE_ATTR(cur_mr);EHCA_RESOURCE_ATTR(max_mw);EHCA_RESOURCE_ATTR(cur_mw);EHCA_RESOURCE_ATTR(max_pd);EHCA_RESOURCE_ATTR(max_ah);static ssize_t ehca_show_adapter_handle(struct device *dev, struct device_attribute *attr, char *buf){ struct ehca_shca *shca = dev->driver_data; return sprintf(buf, "%lx\n", shca->ipz_hca_handle.handle);}static DEVICE_ATTR(adapter_handle, S_IRUGO, ehca_show_adapter_handle, NULL);static ssize_t ehca_show_mr_largepage(struct device *dev, struct device_attribute *attr, char *buf){ return sprintf(buf, "%d\n", ehca_mr_largepage);}static DEVICE_ATTR(mr_largepage, S_IRUGO, ehca_show_mr_largepage, NULL);static struct attribute *ehca_dev_attrs[] = { &dev_attr_adapter_handle.attr, &dev_attr_num_ports.attr, &dev_attr_hw_ver.attr, &dev_attr_max_eq.attr, &dev_attr_cur_eq.attr, &dev_attr_max_cq.attr, &dev_attr_cur_cq.attr, &dev_attr_max_qp.attr, &dev_attr_cur_qp.attr, &dev_attr_max_mr.attr, &dev_attr_cur_mr.attr, &dev_attr_max_mw.attr, &dev_attr_cur_mw.attr, &dev_attr_max_pd.attr, &dev_attr_max_ah.attr, &dev_attr_mr_largepage.attr, NULL};static struct attribute_group ehca_dev_attr_grp = { .attrs = ehca_dev_attrs};static int __devinit ehca_probe(struct of_device *dev, const struct of_device_id *id){ struct ehca_shca *shca; const u64 *handle; struct ib_pd *ibpd; int ret; handle = of_get_property(dev->node, "ibm,hca-handle", NULL); if (!handle) { ehca_gen_err("Cannot get eHCA handle for adapter: %s.", dev->node->full_name); return -ENODEV; } if (!(*handle)) { ehca_gen_err("Wrong eHCA handle for adapter: %s.", dev->node->full_name); return -ENODEV; } shca = (struct ehca_shca *)ib_alloc_device(sizeof(*shca)); if (!shca) { ehca_gen_err("Cannot allocate shca memory."); return -ENOMEM; } mutex_init(&shca->modify_mutex); shca->ofdev = dev; shca->ipz_hca_handle.handle = *handle; dev->dev.driver_data = shca; ret = ehca_sense_attributes(shca); if (ret < 0) { ehca_gen_err("Cannot sense eHCA attributes."); goto probe1; } ret = ehca_init_device(shca); if (ret) { ehca_gen_err("Cannot init ehca device struct"); goto probe1; } /* create event queues */ ret = ehca_create_eq(shca, &shca->eq, EHCA_EQ, 2048); if (ret) { ehca_err(&shca->ib_device, "Cannot create EQ."); goto probe1; } ret = ehca_create_eq(shca, &shca->neq, EHCA_NEQ, 513); if (ret) { ehca_err(&shca->ib_device, "Cannot create NEQ."); goto probe3; } /* create internal protection domain */ ibpd = ehca_alloc_pd(&shca->ib_device, (void *)(-1), NULL); if (IS_ERR(ibpd)) { ehca_err(&shca->ib_device, "Cannot create internal PD."); ret = PTR_ERR(ibpd); goto probe4; } shca->pd = container_of(ibpd, struct ehca_pd, ib_pd); shca->pd->ib_pd.device = &shca->ib_device; /* create internal max MR */ ret = ehca_reg_internal_maxmr(shca, shca->pd, &shca->maxmr); if (ret) { ehca_err(&shca->ib_device, "Cannot create internal MR ret=%i", ret); goto probe5; } ret = ib_register_device(&shca->ib_device); if (ret) { ehca_err(&shca->ib_device, "ib_register_device() failed ret=%i", ret); goto probe6; } /* create AQP1 for port 1 */ if (ehca_open_aqp1 == 1) { shca->sport[0].port_state = IB_PORT_DOWN; ret = ehca_create_aqp1(shca, 1); if (ret) { ehca_err(&shca->ib_device, "Cannot create AQP1 for port 1."); goto probe7; } } /* create AQP1 for port 2 */ if ((ehca_open_aqp1 == 1) && (shca->num_ports == 2)) { shca->sport[1].port_state = IB_PORT_DOWN; ret = ehca_create_aqp1(shca, 2); if (ret) { ehca_err(&shca->ib_device, "Cannot create AQP1 for port 2."); goto probe8; } } ret = sysfs_create_group(&dev->dev.kobj, &ehca_dev_attr_grp); if (ret) /* only complain; we can live without attributes */ ehca_err(&shca->ib_device, "Cannot create device attributes ret=%d", ret); spin_lock(&shca_list_lock); list_add(&shca->shca_list, &shca_list); spin_unlock(&shca_list_lock); return 0;probe8: ret = ehca_destroy_aqp1(&shca->sport[0]); if (ret) ehca_err(&shca->ib_device, "Cannot destroy AQP1 for port 1. ret=%i", ret);probe7: ib_unregister_device(&shca->ib_device);probe6: ret = ehca_dereg_internal_maxmr(shca); if (ret) ehca_err(&shca->ib_device, "Cannot destroy internal MR. ret=%x", ret);probe5: ret = ehca_dealloc_pd(&shca->pd->ib_pd); if (ret) ehca_err(&shca->ib_device, "Cannot destroy internal PD. ret=%x", ret);probe4: ret = ehca_destroy_eq(shca, &shca->neq); if (ret) ehca_err(&shca->ib_device, "Cannot destroy NEQ. ret=%x", ret);probe3: ret = ehca_destroy_eq(shca, &shca->eq); if (ret) ehca_err(&shca->ib_device, "Cannot destroy EQ. ret=%x", ret);probe1: ib_dealloc_device(&shca->ib_device); return -EINVAL;}static int __devexit ehca_remove(struct of_device *dev){ struct ehca_shca *shca = dev->dev.driver_data; int ret; sysfs_remove_group(&dev->dev.kobj, &ehca_dev_attr_grp); if (ehca_open_aqp1 == 1) { int i; for (i = 0; i < shca->num_ports; i++) { ret = ehca_destroy_aqp1(&shca->sport[i]); if (ret) ehca_err(&shca->ib_device, "Cannot destroy AQP1 for port %x " "ret=%i", ret, i); } } ib_unregister_device(&shca->ib_device); ret = ehca_dereg_internal_maxmr(shca); if (ret) ehca_err(&shca->ib_device, "Cannot destroy internal MR. ret=%i", ret); ret = ehca_dealloc_pd(&shca->pd->ib_pd); if (ret) ehca_err(&shca->ib_device, "Cannot destroy internal PD. ret=%i", ret); ret = ehca_destroy_eq(shca, &shca->eq); if (ret) ehca_err(&shca->ib_device, "Cannot destroy EQ. ret=%i", ret); ret = ehca_destroy_eq(shca, &shca->neq); if (ret) ehca_err(&shca->ib_device, "Canot destroy NEQ. ret=%i", ret); ib_dealloc_device(&shca->ib_device); spin_lock(&shca_list_lock); list_del(&shca->shca_list); spin_unlock(&shca_list_lock); return ret;}static struct of_device_id ehca_device_table[] ={ { .name = "lhca", .compatible = "IBM,lhca", }, {},};static struct of_platform_driver ehca_driver = { .name = "ehca", .match_table = ehca_device_table, .probe = ehca_probe, .remove = ehca_remove,};void ehca_poll_eqs(unsigned long data){ struct ehca_shca *shca; spin_lock(&shca_list_lock); list_for_each_entry(shca, &shca_list, shca_list) { if (shca->eq.is_initialized) { /* call deadman proc only if eq ptr does not change */ struct ehca_eq *eq = &shca->eq; int max = 3; volatile u64 q_ofs, q_ofs2; u64 flags; spin_lock_irqsave(&eq->spinlock, flags); q_ofs = eq->ipz_queue.current_q_offset; spin_unlock_irqrestore(&eq->spinlock, flags); do { spin_lock_irqsave(&eq->spinlock, flags); q_ofs2 = eq->ipz_queue.current_q_offset; spin_unlock_irqrestore(&eq->spinlock, flags); max--; } while (q_ofs == q_ofs2 && max > 0); if (q_ofs == q_ofs2) ehca_process_eq(shca, 0); } } mod_timer(&poll_eqs_timer, jiffies + HZ); spin_unlock(&shca_list_lock);}int __init ehca_module_init(void){ int ret; printk(KERN_INFO "eHCA Infiniband Device Driver " "(Version " HCAD_VERSION ")\n"); ret = ehca_create_comp_pool(); if (ret) { ehca_gen_err("Cannot create comp pool."); return ret; } ret = ehca_create_slab_caches(); if (ret) { ehca_gen_err("Cannot create SLAB caches"); ret = -ENOMEM; goto module_init1; } ret = ibmebus_register_driver(&ehca_driver); if (ret) { ehca_gen_err("Cannot register eHCA device driver"); ret = -EINVAL; goto module_init2; } ret = sysfs_create_group(&ehca_driver.driver.kobj, &ehca_drv_attr_grp); if (ret) /* only complain; we can live without attributes */ ehca_gen_err("Cannot create driver attributes ret=%d", ret); if (ehca_poll_all_eqs != 1) { ehca_gen_err("WARNING!!!"); ehca_gen_err("It is possible to lose interrupts."); } else { init_timer(&poll_eqs_timer); poll_eqs_timer.function = ehca_poll_eqs; poll_eqs_timer.expires = jiffies + HZ; add_timer(&poll_eqs_timer); } return 0;module_init2: ehca_destroy_slab_caches();module_init1: ehca_destroy_comp_pool(); return ret;};void __exit ehca_module_exit(void){ if (ehca_poll_all_eqs == 1) del_timer_sync(&poll_eqs_timer); sysfs_remove_group(&ehca_driver.driver.kobj, &ehca_drv_attr_grp); ibmebus_unregister_driver(&ehca_driver); ehca_destroy_slab_caches(); ehca_destroy_comp_pool(); idr_destroy(&ehca_cq_idr); idr_destroy(&ehca_qp_idr);};module_init(ehca_module_init);module_exit(ehca_module_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -