Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 993d1b52 authored by Ram Amrani's avatar Ram Amrani Committed by Doug Ledford
Browse files

qedr: Add events support and register IB device



Add error handling support.
Register ib device with ib stack.

Signed-off-by: default avatarRajesh Borundia <rajesh.borundia@cavium.com>
Signed-off-by: default avatarRam Amrani <Ram.Amrani@cavium.com>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent 04886779
Loading
Loading
Loading
Loading
+112 −2
Original line number Diff line number Diff line
@@ -79,10 +79,25 @@ static void qedr_get_dev_fw_str(struct ib_device *ibdev, char *str,
		 (fw_ver >> 8) & 0xFF, fw_ver & 0xFF);
}

static struct net_device *qedr_get_netdev(struct ib_device *dev, u8 port_num)
{
	struct qedr_dev *qdev;

	qdev = get_qedr_dev(dev);
	dev_hold(qdev->ndev);

	/* The HW vendor's device driver must guarantee
	 * that this function returns NULL before the net device reaches
	 * NETDEV_UNREGISTER_FINAL state.
	 */
	return qdev->ndev;
}

static int qedr_register_device(struct qedr_dev *dev)
{
	strlcpy(dev->ibdev.name, "qedr%d", IB_DEVICE_NAME_MAX);

	dev->ibdev.node_guid = dev->attr.node_guid;
	memcpy(dev->ibdev.node_desc, QEDR_NODE_DESC, sizeof(QEDR_NODE_DESC));
	dev->ibdev.owner = THIS_MODULE;
	dev->ibdev.uverbs_abi_ver = QEDR_ABI_VERSION;
@@ -151,12 +166,16 @@ static int qedr_register_device(struct qedr_dev *dev)
	dev->ibdev.post_send = qedr_post_send;
	dev->ibdev.post_recv = qedr_post_recv;

	dev->ibdev.process_mad = qedr_process_mad;
	dev->ibdev.get_port_immutable = qedr_port_immutable;
	dev->ibdev.get_netdev = qedr_get_netdev;

	dev->ibdev.dma_device = &dev->pdev->dev;

	dev->ibdev.get_link_layer = qedr_link_layer;
	dev->ibdev.get_dev_fw_str = qedr_get_dev_fw_str;

	return 0;
	return ib_register_device(&dev->ibdev, NULL);
}

/* This function allocates fast-path status block memory */
@@ -557,6 +576,92 @@ static int qedr_set_device_attr(struct qedr_dev *dev)
	return 0;
}

void qedr_unaffiliated_event(void *context,
			     u8 event_code)
{
	pr_err("unaffiliated event not implemented yet\n");
}

void qedr_affiliated_event(void *context, u8 e_code, void *fw_handle)
{
#define EVENT_TYPE_NOT_DEFINED	0
#define EVENT_TYPE_CQ		1
#define EVENT_TYPE_QP		2
	struct qedr_dev *dev = (struct qedr_dev *)context;
	union event_ring_data *data = fw_handle;
	u64 roce_handle64 = ((u64)data->roce_handle.hi << 32) +
			    data->roce_handle.lo;
	u8 event_type = EVENT_TYPE_NOT_DEFINED;
	struct ib_event event;
	struct ib_cq *ibcq;
	struct ib_qp *ibqp;
	struct qedr_cq *cq;
	struct qedr_qp *qp;

	switch (e_code) {
	case ROCE_ASYNC_EVENT_CQ_OVERFLOW_ERR:
		event.event = IB_EVENT_CQ_ERR;
		event_type = EVENT_TYPE_CQ;
		break;
	case ROCE_ASYNC_EVENT_SQ_DRAINED:
		event.event = IB_EVENT_SQ_DRAINED;
		event_type = EVENT_TYPE_QP;
		break;
	case ROCE_ASYNC_EVENT_QP_CATASTROPHIC_ERR:
		event.event = IB_EVENT_QP_FATAL;
		event_type = EVENT_TYPE_QP;
		break;
	case ROCE_ASYNC_EVENT_LOCAL_INVALID_REQUEST_ERR:
		event.event = IB_EVENT_QP_REQ_ERR;
		event_type = EVENT_TYPE_QP;
		break;
	case ROCE_ASYNC_EVENT_LOCAL_ACCESS_ERR:
		event.event = IB_EVENT_QP_ACCESS_ERR;
		event_type = EVENT_TYPE_QP;
		break;
	default:
		DP_ERR(dev, "unsupported event %d on handle=%llx\n", e_code,
		       roce_handle64);
	}

	switch (event_type) {
	case EVENT_TYPE_CQ:
		cq = (struct qedr_cq *)(uintptr_t)roce_handle64;
		if (cq) {
			ibcq = &cq->ibcq;
			if (ibcq->event_handler) {
				event.device = ibcq->device;
				event.element.cq = ibcq;
				ibcq->event_handler(&event, ibcq->cq_context);
			}
		} else {
			WARN(1,
			     "Error: CQ event with NULL pointer ibcq. Handle=%llx\n",
			     roce_handle64);
		}
		DP_ERR(dev, "CQ event %d on hanlde %p\n", e_code, cq);
		break;
	case EVENT_TYPE_QP:
		qp = (struct qedr_qp *)(uintptr_t)roce_handle64;
		if (qp) {
			ibqp = &qp->ibqp;
			if (ibqp->event_handler) {
				event.device = ibqp->device;
				event.element.qp = ibqp;
				ibqp->event_handler(&event, ibqp->qp_context);
			}
		} else {
			WARN(1,
			     "Error: QP event with NULL pointer ibqp. Handle=%llx\n",
			     roce_handle64);
		}
		DP_ERR(dev, "QP event %d on hanlde %p\n", e_code, qp);
		break;
	default:
		break;
	}
}

static int qedr_init_hw(struct qedr_dev *dev)
{
	struct qed_rdma_add_user_out_params out_params;
@@ -585,6 +690,8 @@ static int qedr_init_hw(struct qedr_dev *dev)
		cur_pbl->pbl_ptr = (u64)p_phys_table;
	}

	events.affiliated_event = qedr_affiliated_event;
	events.unaffiliated_event = qedr_unaffiliated_event;
	events.context = dev;

	in_params->events = &events;
@@ -683,11 +790,13 @@ static struct qedr_dev *qedr_add(struct qed_dev *cdev, struct pci_dev *pdev,

	for (i = 0; i < ARRAY_SIZE(qedr_attributes); i++)
		if (device_create_file(&dev->ibdev.dev, qedr_attributes[i]))
			goto reg_err;
			goto sysfs_err;

	DP_DEBUG(dev, QEDR_MSG_INIT, "qedr driver loaded successfully\n");
	return dev;

sysfs_err:
	ib_unregister_device(&dev->ibdev);
reg_err:
	qedr_sync_free_irqs(dev);
irq_err:
@@ -707,6 +816,7 @@ static void qedr_remove(struct qedr_dev *dev)
	 * of the registered clients.
	 */
	qedr_remove_sysfiles(dev);
	ib_unregister_device(&dev->ibdev);

	qedr_stop_hw(dev);
	qedr_sync_free_irqs(dev);
+37 −0
Original line number Diff line number Diff line
@@ -3508,3 +3508,40 @@ int qedr_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc)
	spin_unlock_irqrestore(&cq->cq_lock, flags);
	return done;
}

int qedr_process_mad(struct ib_device *ibdev, int process_mad_flags,
		     u8 port_num,
		     const struct ib_wc *in_wc,
		     const struct ib_grh *in_grh,
		     const struct ib_mad_hdr *mad_hdr,
		     size_t in_mad_size, struct ib_mad_hdr *out_mad,
		     size_t *out_mad_size, u16 *out_mad_pkey_index)
{
	struct qedr_dev *dev = get_qedr_dev(ibdev);

	DP_DEBUG(dev, QEDR_MSG_GSI,
		 "QEDR_PROCESS_MAD in_mad %x %x %x %x %x %x %x %x\n",
		 mad_hdr->attr_id, mad_hdr->base_version, mad_hdr->attr_mod,
		 mad_hdr->class_specific, mad_hdr->class_version,
		 mad_hdr->method, mad_hdr->mgmt_class, mad_hdr->status);
	return IB_MAD_RESULT_SUCCESS;
}

int qedr_port_immutable(struct ib_device *ibdev, u8 port_num,
			struct ib_port_immutable *immutable)
{
	struct ib_port_attr attr;
	int err;

	err = qedr_query_port(ibdev, port_num, &attr);
	if (err)
		return err;

	immutable->pkey_tbl_len = attr.pkey_tbl_len;
	immutable->gid_tbl_len = attr.gid_tbl_len;
	immutable->core_cap_flags = RDMA_CORE_PORT_IBA_ROCE |
				    RDMA_CORE_PORT_IBA_ROCE_UDP_ENCAP;
	immutable->max_mad_size = IB_MGMT_MAD_SIZE;

	return 0;
}
+9 −0
Original line number Diff line number Diff line
@@ -89,4 +89,13 @@ int qedr_post_send(struct ib_qp *, struct ib_send_wr *,
		   struct ib_send_wr **bad_wr);
int qedr_post_recv(struct ib_qp *, struct ib_recv_wr *,
		   struct ib_recv_wr **bad_wr);
int qedr_process_mad(struct ib_device *ibdev, int process_mad_flags,
		     u8 port_num, const struct ib_wc *in_wc,
		     const struct ib_grh *in_grh,
		     const struct ib_mad_hdr *in_mad,
		     size_t in_mad_size, struct ib_mad_hdr *out_mad,
		     size_t *out_mad_size, u16 *out_mad_pkey_index);

int qedr_port_immutable(struct ib_device *ibdev, u8 port_num,
			struct ib_port_immutable *immutable);
#endif