diff options
author | Ram Amrani <Ram.Amrani@cavium.com> | 2016-10-10 06:15:39 -0400 |
---|---|---|
committer | Doug Ledford <dledford@redhat.com> | 2016-10-14 15:00:10 -0400 |
commit | 993d1b52615e1a549e55875c3b74308391672d9f (patch) | |
tree | 810e5780781f62536163a95167bfae2f6b7febdf | |
parent | 048867793046e6bd665869816f4702fc49cc9a18 (diff) |
qedr: Add events support and register IB device
Add error handling support.
Register ib device with ib stack.
Signed-off-by: Rajesh Borundia <rajesh.borundia@cavium.com>
Signed-off-by: Ram Amrani <Ram.Amrani@cavium.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r-- | drivers/infiniband/hw/qedr/main.c | 114 | ||||
-rw-r--r-- | drivers/infiniband/hw/qedr/verbs.c | 37 | ||||
-rw-r--r-- | drivers/infiniband/hw/qedr/verbs.h | 9 |
3 files changed, 158 insertions, 2 deletions
diff --git a/drivers/infiniband/hw/qedr/main.c b/drivers/infiniband/hw/qedr/main.c index 42dff48a3171..7b74d09a8217 100644 --- a/drivers/infiniband/hw/qedr/main.c +++ b/drivers/infiniband/hw/qedr/main.c | |||
@@ -79,10 +79,25 @@ static void qedr_get_dev_fw_str(struct ib_device *ibdev, char *str, | |||
79 | (fw_ver >> 8) & 0xFF, fw_ver & 0xFF); | 79 | (fw_ver >> 8) & 0xFF, fw_ver & 0xFF); |
80 | } | 80 | } |
81 | 81 | ||
82 | static struct net_device *qedr_get_netdev(struct ib_device *dev, u8 port_num) | ||
83 | { | ||
84 | struct qedr_dev *qdev; | ||
85 | |||
86 | qdev = get_qedr_dev(dev); | ||
87 | dev_hold(qdev->ndev); | ||
88 | |||
89 | /* The HW vendor's device driver must guarantee | ||
90 | * that this function returns NULL before the net device reaches | ||
91 | * NETDEV_UNREGISTER_FINAL state. | ||
92 | */ | ||
93 | return qdev->ndev; | ||
94 | } | ||
95 | |||
82 | static int qedr_register_device(struct qedr_dev *dev) | 96 | static int qedr_register_device(struct qedr_dev *dev) |
83 | { | 97 | { |
84 | strlcpy(dev->ibdev.name, "qedr%d", IB_DEVICE_NAME_MAX); | 98 | strlcpy(dev->ibdev.name, "qedr%d", IB_DEVICE_NAME_MAX); |
85 | 99 | ||
100 | dev->ibdev.node_guid = dev->attr.node_guid; | ||
86 | memcpy(dev->ibdev.node_desc, QEDR_NODE_DESC, sizeof(QEDR_NODE_DESC)); | 101 | memcpy(dev->ibdev.node_desc, QEDR_NODE_DESC, sizeof(QEDR_NODE_DESC)); |
87 | dev->ibdev.owner = THIS_MODULE; | 102 | dev->ibdev.owner = THIS_MODULE; |
88 | dev->ibdev.uverbs_abi_ver = QEDR_ABI_VERSION; | 103 | dev->ibdev.uverbs_abi_ver = QEDR_ABI_VERSION; |
@@ -151,12 +166,16 @@ static int qedr_register_device(struct qedr_dev *dev) | |||
151 | dev->ibdev.post_send = qedr_post_send; | 166 | dev->ibdev.post_send = qedr_post_send; |
152 | dev->ibdev.post_recv = qedr_post_recv; | 167 | dev->ibdev.post_recv = qedr_post_recv; |
153 | 168 | ||
169 | dev->ibdev.process_mad = qedr_process_mad; | ||
170 | dev->ibdev.get_port_immutable = qedr_port_immutable; | ||
171 | dev->ibdev.get_netdev = qedr_get_netdev; | ||
172 | |||
154 | dev->ibdev.dma_device = &dev->pdev->dev; | 173 | dev->ibdev.dma_device = &dev->pdev->dev; |
155 | 174 | ||
156 | dev->ibdev.get_link_layer = qedr_link_layer; | 175 | dev->ibdev.get_link_layer = qedr_link_layer; |
157 | dev->ibdev.get_dev_fw_str = qedr_get_dev_fw_str; | 176 | dev->ibdev.get_dev_fw_str = qedr_get_dev_fw_str; |
158 | 177 | ||
159 | return 0; | 178 | return ib_register_device(&dev->ibdev, NULL); |
160 | } | 179 | } |
161 | 180 | ||
162 | /* This function allocates fast-path status block memory */ | 181 | /* This function allocates fast-path status block memory */ |
@@ -557,6 +576,92 @@ static int qedr_set_device_attr(struct qedr_dev *dev) | |||
557 | return 0; | 576 | return 0; |
558 | } | 577 | } |
559 | 578 | ||
579 | void qedr_unaffiliated_event(void *context, | ||
580 | u8 event_code) | ||
581 | { | ||
582 | pr_err("unaffiliated event not implemented yet\n"); | ||
583 | } | ||
584 | |||
585 | void qedr_affiliated_event(void *context, u8 e_code, void *fw_handle) | ||
586 | { | ||
587 | #define EVENT_TYPE_NOT_DEFINED 0 | ||
588 | #define EVENT_TYPE_CQ 1 | ||
589 | #define EVENT_TYPE_QP 2 | ||
590 | struct qedr_dev *dev = (struct qedr_dev *)context; | ||
591 | union event_ring_data *data = fw_handle; | ||
592 | u64 roce_handle64 = ((u64)data->roce_handle.hi << 32) + | ||
593 | data->roce_handle.lo; | ||
594 | u8 event_type = EVENT_TYPE_NOT_DEFINED; | ||
595 | struct ib_event event; | ||
596 | struct ib_cq *ibcq; | ||
597 | struct ib_qp *ibqp; | ||
598 | struct qedr_cq *cq; | ||
599 | struct qedr_qp *qp; | ||
600 | |||
601 | switch (e_code) { | ||
602 | case ROCE_ASYNC_EVENT_CQ_OVERFLOW_ERR: | ||
603 | event.event = IB_EVENT_CQ_ERR; | ||
604 | event_type = EVENT_TYPE_CQ; | ||
605 | break; | ||
606 | case ROCE_ASYNC_EVENT_SQ_DRAINED: | ||
607 | event.event = IB_EVENT_SQ_DRAINED; | ||
608 | event_type = EVENT_TYPE_QP; | ||
609 | break; | ||
610 | case ROCE_ASYNC_EVENT_QP_CATASTROPHIC_ERR: | ||
611 | event.event = IB_EVENT_QP_FATAL; | ||
612 | event_type = EVENT_TYPE_QP; | ||
613 | break; | ||
614 | case ROCE_ASYNC_EVENT_LOCAL_INVALID_REQUEST_ERR: | ||
615 | event.event = IB_EVENT_QP_REQ_ERR; | ||
616 | event_type = EVENT_TYPE_QP; | ||
617 | break; | ||
618 | case ROCE_ASYNC_EVENT_LOCAL_ACCESS_ERR: | ||
619 | event.event = IB_EVENT_QP_ACCESS_ERR; | ||
620 | event_type = EVENT_TYPE_QP; | ||
621 | break; | ||
622 | default: | ||
623 | DP_ERR(dev, "unsupported event %d on handle=%llx\n", e_code, | ||
624 | roce_handle64); | ||
625 | } | ||
626 | |||
627 | switch (event_type) { | ||
628 | case EVENT_TYPE_CQ: | ||
629 | cq = (struct qedr_cq *)(uintptr_t)roce_handle64; | ||
630 | if (cq) { | ||
631 | ibcq = &cq->ibcq; | ||
632 | if (ibcq->event_handler) { | ||
633 | event.device = ibcq->device; | ||
634 | event.element.cq = ibcq; | ||
635 | ibcq->event_handler(&event, ibcq->cq_context); | ||
636 | } | ||
637 | } else { | ||
638 | WARN(1, | ||
639 | "Error: CQ event with NULL pointer ibcq. Handle=%llx\n", | ||
640 | roce_handle64); | ||
641 | } | ||
642 | DP_ERR(dev, "CQ event %d on hanlde %p\n", e_code, cq); | ||
643 | break; | ||
644 | case EVENT_TYPE_QP: | ||
645 | qp = (struct qedr_qp *)(uintptr_t)roce_handle64; | ||
646 | if (qp) { | ||
647 | ibqp = &qp->ibqp; | ||
648 | if (ibqp->event_handler) { | ||
649 | event.device = ibqp->device; | ||
650 | event.element.qp = ibqp; | ||
651 | ibqp->event_handler(&event, ibqp->qp_context); | ||
652 | } | ||
653 | } else { | ||
654 | WARN(1, | ||
655 | "Error: QP event with NULL pointer ibqp. Handle=%llx\n", | ||
656 | roce_handle64); | ||
657 | } | ||
658 | DP_ERR(dev, "QP event %d on hanlde %p\n", e_code, qp); | ||
659 | break; | ||
660 | default: | ||
661 | break; | ||
662 | } | ||
663 | } | ||
664 | |||
560 | static int qedr_init_hw(struct qedr_dev *dev) | 665 | static int qedr_init_hw(struct qedr_dev *dev) |
561 | { | 666 | { |
562 | struct qed_rdma_add_user_out_params out_params; | 667 | struct qed_rdma_add_user_out_params out_params; |
@@ -585,6 +690,8 @@ static int qedr_init_hw(struct qedr_dev *dev) | |||
585 | cur_pbl->pbl_ptr = (u64)p_phys_table; | 690 | cur_pbl->pbl_ptr = (u64)p_phys_table; |
586 | } | 691 | } |
587 | 692 | ||
693 | events.affiliated_event = qedr_affiliated_event; | ||
694 | events.unaffiliated_event = qedr_unaffiliated_event; | ||
588 | events.context = dev; | 695 | events.context = dev; |
589 | 696 | ||
590 | in_params->events = &events; | 697 | in_params->events = &events; |
@@ -683,11 +790,13 @@ static struct qedr_dev *qedr_add(struct qed_dev *cdev, struct pci_dev *pdev, | |||
683 | 790 | ||
684 | for (i = 0; i < ARRAY_SIZE(qedr_attributes); i++) | 791 | for (i = 0; i < ARRAY_SIZE(qedr_attributes); i++) |
685 | if (device_create_file(&dev->ibdev.dev, qedr_attributes[i])) | 792 | if (device_create_file(&dev->ibdev.dev, qedr_attributes[i])) |
686 | goto reg_err; | 793 | goto sysfs_err; |
687 | 794 | ||
688 | DP_DEBUG(dev, QEDR_MSG_INIT, "qedr driver loaded successfully\n"); | 795 | DP_DEBUG(dev, QEDR_MSG_INIT, "qedr driver loaded successfully\n"); |
689 | return dev; | 796 | return dev; |
690 | 797 | ||
798 | sysfs_err: | ||
799 | ib_unregister_device(&dev->ibdev); | ||
691 | reg_err: | 800 | reg_err: |
692 | qedr_sync_free_irqs(dev); | 801 | qedr_sync_free_irqs(dev); |
693 | irq_err: | 802 | irq_err: |
@@ -707,6 +816,7 @@ static void qedr_remove(struct qedr_dev *dev) | |||
707 | * of the registered clients. | 816 | * of the registered clients. |
708 | */ | 817 | */ |
709 | qedr_remove_sysfiles(dev); | 818 | qedr_remove_sysfiles(dev); |
819 | ib_unregister_device(&dev->ibdev); | ||
710 | 820 | ||
711 | qedr_stop_hw(dev); | 821 | qedr_stop_hw(dev); |
712 | qedr_sync_free_irqs(dev); | 822 | qedr_sync_free_irqs(dev); |
diff --git a/drivers/infiniband/hw/qedr/verbs.c b/drivers/infiniband/hw/qedr/verbs.c index 44ad6ae036c9..a61514296767 100644 --- a/drivers/infiniband/hw/qedr/verbs.c +++ b/drivers/infiniband/hw/qedr/verbs.c | |||
@@ -3508,3 +3508,40 @@ int qedr_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc) | |||
3508 | spin_unlock_irqrestore(&cq->cq_lock, flags); | 3508 | spin_unlock_irqrestore(&cq->cq_lock, flags); |
3509 | return done; | 3509 | return done; |
3510 | } | 3510 | } |
3511 | |||
3512 | int qedr_process_mad(struct ib_device *ibdev, int process_mad_flags, | ||
3513 | u8 port_num, | ||
3514 | const struct ib_wc *in_wc, | ||
3515 | const struct ib_grh *in_grh, | ||
3516 | const struct ib_mad_hdr *mad_hdr, | ||
3517 | size_t in_mad_size, struct ib_mad_hdr *out_mad, | ||
3518 | size_t *out_mad_size, u16 *out_mad_pkey_index) | ||
3519 | { | ||
3520 | struct qedr_dev *dev = get_qedr_dev(ibdev); | ||
3521 | |||
3522 | DP_DEBUG(dev, QEDR_MSG_GSI, | ||
3523 | "QEDR_PROCESS_MAD in_mad %x %x %x %x %x %x %x %x\n", | ||
3524 | mad_hdr->attr_id, mad_hdr->base_version, mad_hdr->attr_mod, | ||
3525 | mad_hdr->class_specific, mad_hdr->class_version, | ||
3526 | mad_hdr->method, mad_hdr->mgmt_class, mad_hdr->status); | ||
3527 | return IB_MAD_RESULT_SUCCESS; | ||
3528 | } | ||
3529 | |||
3530 | int qedr_port_immutable(struct ib_device *ibdev, u8 port_num, | ||
3531 | struct ib_port_immutable *immutable) | ||
3532 | { | ||
3533 | struct ib_port_attr attr; | ||
3534 | int err; | ||
3535 | |||
3536 | err = qedr_query_port(ibdev, port_num, &attr); | ||
3537 | if (err) | ||
3538 | return err; | ||
3539 | |||
3540 | immutable->pkey_tbl_len = attr.pkey_tbl_len; | ||
3541 | immutable->gid_tbl_len = attr.gid_tbl_len; | ||
3542 | immutable->core_cap_flags = RDMA_CORE_PORT_IBA_ROCE | | ||
3543 | RDMA_CORE_PORT_IBA_ROCE_UDP_ENCAP; | ||
3544 | immutable->max_mad_size = IB_MGMT_MAD_SIZE; | ||
3545 | |||
3546 | return 0; | ||
3547 | } | ||
diff --git a/drivers/infiniband/hw/qedr/verbs.h b/drivers/infiniband/hw/qedr/verbs.h index fbc6db5a5e1f..a9b5e67bb81e 100644 --- a/drivers/infiniband/hw/qedr/verbs.h +++ b/drivers/infiniband/hw/qedr/verbs.h | |||
@@ -89,4 +89,13 @@ int qedr_post_send(struct ib_qp *, struct ib_send_wr *, | |||
89 | struct ib_send_wr **bad_wr); | 89 | struct ib_send_wr **bad_wr); |
90 | int qedr_post_recv(struct ib_qp *, struct ib_recv_wr *, | 90 | int qedr_post_recv(struct ib_qp *, struct ib_recv_wr *, |
91 | struct ib_recv_wr **bad_wr); | 91 | struct ib_recv_wr **bad_wr); |
92 | int qedr_process_mad(struct ib_device *ibdev, int process_mad_flags, | ||
93 | u8 port_num, const struct ib_wc *in_wc, | ||
94 | const struct ib_grh *in_grh, | ||
95 | const struct ib_mad_hdr *in_mad, | ||
96 | size_t in_mad_size, struct ib_mad_hdr *out_mad, | ||
97 | size_t *out_mad_size, u16 *out_mad_pkey_index); | ||
98 | |||
99 | int qedr_port_immutable(struct ib_device *ibdev, u8 port_num, | ||
100 | struct ib_port_immutable *immutable); | ||
92 | #endif | 101 | #endif |