aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRam Amrani <Ram.Amrani@cavium.com>2016-10-10 06:15:39 -0400
committerDoug Ledford <dledford@redhat.com>2016-10-14 15:00:10 -0400
commit993d1b52615e1a549e55875c3b74308391672d9f (patch)
tree810e5780781f62536163a95167bfae2f6b7febdf
parent048867793046e6bd665869816f4702fc49cc9a18 (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.c114
-rw-r--r--drivers/infiniband/hw/qedr/verbs.c37
-rw-r--r--drivers/infiniband/hw/qedr/verbs.h9
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
82static 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
82static int qedr_register_device(struct qedr_dev *dev) 96static 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
579void qedr_unaffiliated_event(void *context,
580 u8 event_code)
581{
582 pr_err("unaffiliated event not implemented yet\n");
583}
584
585void 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
560static int qedr_init_hw(struct qedr_dev *dev) 665static 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
798sysfs_err:
799 ib_unregister_device(&dev->ibdev);
691reg_err: 800reg_err:
692 qedr_sync_free_irqs(dev); 801 qedr_sync_free_irqs(dev);
693irq_err: 802irq_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
3512int 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
3530int 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);
90int qedr_post_recv(struct ib_qp *, struct ib_recv_wr *, 90int qedr_post_recv(struct ib_qp *, struct ib_recv_wr *,
91 struct ib_recv_wr **bad_wr); 91 struct ib_recv_wr **bad_wr);
92int 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
99int qedr_port_immutable(struct ib_device *ibdev, u8 port_num,
100 struct ib_port_immutable *immutable);
92#endif 101#endif