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

Commit 6c9e80ea authored by Michal Kalderon's avatar Michal Kalderon Committed by David S. Miller
Browse files

qed: SPQ async callback registration



Whenever firmware indicates that there's an async indication it needs
to handle, there's a switch-case where the right functionality is called
based on function's personality and information.

Before iWARP is added [as yet another client], switch over the SPQ into
a callback-registered mechanism, allowing registration of the relevant
event-processing logic based on the function's personality. This allows
us to tidy the code by removing protocol-specifics from a common file.

Signed-off-by: default avatarMichal Kalderon <Michal.Kalderon@cavium.com>
Signed-off-by: default avatarYuval Mintz <Yuval.Mintz@cavium.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 898fff12
Loading
Loading
Loading
Loading
+23 −1
Original line number Diff line number Diff line
@@ -62,6 +62,22 @@
#include "qed_sriov.h"
#include "qed_reg_addr.h"

static int
qed_iscsi_async_event(struct qed_hwfn *p_hwfn,
		      u8 fw_event_code,
		      u16 echo, union event_ring_data *data, u8 fw_return_code)
{
	if (p_hwfn->p_iscsi_info->event_cb) {
		struct qed_iscsi_info *p_iscsi = p_hwfn->p_iscsi_info;

		return p_iscsi->event_cb(p_iscsi->event_context,
					 fw_event_code, data);
	} else {
		DP_NOTICE(p_hwfn, "iSCSI async completion is not set\n");
		return -EINVAL;
	}
}

struct qed_iscsi_conn {
	struct list_head list_entry;
	bool free_on_delete;
@@ -265,6 +281,9 @@ qed_sp_iscsi_func_start(struct qed_hwfn *p_hwfn,
	p_hwfn->p_iscsi_info->event_context = event_context;
	p_hwfn->p_iscsi_info->event_cb = async_event_cb;

	qed_spq_register_async_cb(p_hwfn, PROTOCOLID_ISCSI,
				  qed_iscsi_async_event);

	return qed_spq_post(p_hwfn, p_ent, NULL);
}

@@ -631,7 +650,10 @@ static int qed_sp_iscsi_func_stop(struct qed_hwfn *p_hwfn,
	p_ramrod = &p_ent->ramrod.iscsi_destroy;
	p_ramrod->hdr.op_code = ISCSI_RAMROD_CMD_ID_DESTROY_FUNC;

	return qed_spq_post(p_hwfn, p_ent, NULL);
	rc = qed_spq_post(p_hwfn, p_ent, NULL);

	qed_spq_unregister_async_cb(p_hwfn, PROTOCOLID_ISCSI);
	return rc;
}

static void __iomem *qed_iscsi_get_db_addr(struct qed_hwfn *p_hwfn, u32 cid)
+12 −4
Original line number Diff line number Diff line
@@ -68,12 +68,14 @@

static void qed_roce_free_real_icid(struct qed_hwfn *p_hwfn, u16 icid);

void qed_roce_async_event(struct qed_hwfn *p_hwfn,
			  u8 fw_event_code, union rdma_eqe_data *rdma_data)
static int
qed_roce_async_event(struct qed_hwfn *p_hwfn,
		     u8 fw_event_code,
		     u16 echo, union event_ring_data *data, u8 fw_return_code)
{
	if (fw_event_code == ROCE_ASYNC_EVENT_DESTROY_QP_DONE) {
		u16 icid =
		    (u16)le32_to_cpu(rdma_data->rdma_destroy_qp_data.cid);
		    (u16)le32_to_cpu(data->rdma_data.rdma_destroy_qp_data.cid);

		/* icid release in this async event can occur only if the icid
		 * was offloaded to the FW. In case it wasn't offloaded this is
@@ -85,8 +87,10 @@ void qed_roce_async_event(struct qed_hwfn *p_hwfn,

		events->affiliated_event(p_hwfn->p_rdma_info->events.context,
					 fw_event_code,
					 &rdma_data->async_handle);
				     (void *)&data->rdma_data.async_handle);
	}

	return 0;
}

static int qed_rdma_bmap_alloc(struct qed_hwfn *p_hwfn,
@@ -686,6 +690,9 @@ static int qed_rdma_setup(struct qed_hwfn *p_hwfn,
	if (rc)
		return rc;

	qed_spq_register_async_cb(p_hwfn, PROTOCOLID_ROCE,
				  qed_roce_async_event);

	return qed_rdma_start_fw(p_hwfn, params, p_ptt);
}

@@ -706,6 +713,7 @@ void qed_roce_stop(struct qed_hwfn *p_hwfn)
			break;
		}
	}
	qed_spq_unregister_async_cb(p_hwfn, PROTOCOLID_ROCE);
}

static int qed_rdma_stop(void *rdma_cxt)
+0 −6
Original line number Diff line number Diff line
@@ -169,16 +169,10 @@ struct qed_rdma_qp {
#if IS_ENABLED(CONFIG_QED_RDMA)
void qed_rdma_dpm_bar(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt);
void qed_roce_dpm_dcbx(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt);
void qed_roce_async_event(struct qed_hwfn *p_hwfn,
			  u8 fw_event_code, union rdma_eqe_data *rdma_data);
#else
static inline void qed_rdma_dpm_bar(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) {}

static inline void qed_roce_dpm_dcbx(struct qed_hwfn *p_hwfn,
				     struct qed_ptt *p_ptt) {}

static inline void qed_roce_async_event(struct qed_hwfn *p_hwfn,
					u8 fw_event_code,
					union rdma_eqe_data *rdma_data) {}
#endif
#endif
+17 −0
Original line number Diff line number Diff line
@@ -174,6 +174,22 @@ struct qed_consq {
	struct qed_chain chain;
};

typedef int
(*qed_spq_async_comp_cb)(struct qed_hwfn *p_hwfn,
			 u8 opcode,
			 u16 echo,
			 union event_ring_data *data,
			 u8 fw_return_code);

int
qed_spq_register_async_cb(struct qed_hwfn *p_hwfn,
			  enum protocol_type protocol_id,
			  qed_spq_async_comp_cb cb);

void
qed_spq_unregister_async_cb(struct qed_hwfn *p_hwfn,
			    enum protocol_type protocol_id);

struct qed_spq {
	spinlock_t		lock; /* SPQ lock */

@@ -203,6 +219,7 @@ struct qed_spq {
	u32			comp_count;

	u32			cid;
	qed_spq_async_comp_cb async_comp_cb[MAX_PROTOCOL_TYPE];
};

/**
+30 −24
Original line number Diff line number Diff line
@@ -302,32 +302,16 @@ static int
qed_async_event_completion(struct qed_hwfn *p_hwfn,
			   struct event_ring_entry *p_eqe)
{
	switch (p_eqe->protocol_id) {
#if IS_ENABLED(CONFIG_QED_RDMA)
	case PROTOCOLID_ROCE:
		qed_roce_async_event(p_hwfn, p_eqe->opcode,
				     &p_eqe->data.rdma_data);
		return 0;
#endif
	case PROTOCOLID_COMMON:
		return qed_sriov_eqe_event(p_hwfn,
					   p_eqe->opcode,
					   p_eqe->echo, &p_eqe->data);
	case PROTOCOLID_ISCSI:
		if (!IS_ENABLED(CONFIG_QED_ISCSI))
			return -EINVAL;
	qed_spq_async_comp_cb cb;

		if (p_hwfn->p_iscsi_info->event_cb) {
			struct qed_iscsi_info *p_iscsi = p_hwfn->p_iscsi_info;
	if (!p_hwfn->p_spq || (p_eqe->protocol_id >= MAX_PROTOCOL_TYPE))
		return -EINVAL;

			return p_iscsi->event_cb(p_iscsi->event_context,
						 p_eqe->opcode, &p_eqe->data);
	cb = p_hwfn->p_spq->async_comp_cb[p_eqe->protocol_id];
	if (cb) {
		return cb(p_hwfn, p_eqe->opcode, p_eqe->echo,
			  &p_eqe->data, p_eqe->fw_return_code);
	} else {
			DP_NOTICE(p_hwfn,
				  "iSCSI async completion is not set\n");
			return -EINVAL;
		}
	default:
		DP_NOTICE(p_hwfn,
			  "Unknown Async completion for protocol: %d\n",
			  p_eqe->protocol_id);
@@ -335,6 +319,28 @@ qed_async_event_completion(struct qed_hwfn *p_hwfn,
	}
}

int
qed_spq_register_async_cb(struct qed_hwfn *p_hwfn,
			  enum protocol_type protocol_id,
			  qed_spq_async_comp_cb cb)
{
	if (!p_hwfn->p_spq || (protocol_id >= MAX_PROTOCOL_TYPE))
		return -EINVAL;

	p_hwfn->p_spq->async_comp_cb[protocol_id] = cb;
	return 0;
}

void
qed_spq_unregister_async_cb(struct qed_hwfn *p_hwfn,
			    enum protocol_type protocol_id)
{
	if (!p_hwfn->p_spq || (protocol_id >= MAX_PROTOCOL_TYPE))
		return;

	p_hwfn->p_spq->async_comp_cb[protocol_id] = NULL;
}

/***************************************************************************
* EQ API
***************************************************************************/
Loading