Thread (13 messages) read the whole thread 13 messages, 1 author, 3d ago
WARM3d

Revision v23 of 21 in this series.

Revisions (21)
  1. v1 [diff vs current]
  2. v2 [diff vs current]
  3. v3 [diff vs current]
  4. v4 [diff vs current]
  5. v5 [diff vs current]
  6. v6 [diff vs current]
  7. v7 [diff vs current]
  8. v8 [diff vs current]
  9. v9 [diff vs current]
  10. v10 [diff vs current]
  11. v11 [diff vs current]
  12. v12 [diff vs current]
  13. v13 [diff vs current]
  14. v14 [diff vs current]
  15. v15 [diff vs current]
  16. v16 [diff vs current]
  17. v17 [diff vs current]
  18. v19 [diff vs current]
  19. v20 [diff vs current]
  20. v21 [diff vs current]
  21. v23 current

[PATCH v23 net-next 09/12] net/nebula-matrix: dispatch: add cross-version channel message framework

From: illusion.wang <hidden>
Date: 2026-07-31 09:43:03
Also in: linux-doc, lkml
Subsystem: networking drivers, the rest · Maintainers: Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds

From: illusion wang <redacted>

Implement bidirectional channel request/response RPC handlers for 5 dispatch
resource operations: get_vsi_id, get_eth_id, configure_msix_map,
destroy_msix_map, set_mailbox_irq.

- Extend X-macro NBL_DISP_OPS_TBL to pair local dispatch entry points
  with cross-PF mailbox request/response callbacks.
- Add registration helper nbl_disp_setup_msg() to auto-register channel
  response handlers for ops with valid msg_type.
- Introduce NBL_CHAN_RESP_UNIMPLEMENTED dedicated error code for missing
  resource ops implementation on remote PF.
- Add dev_err logging when sending RPC ACK back to remote PF fails.

The existing init_module/deinit_module dispatch entries use msg_type = -1,
so they do not register any mailbox channel handlers and are excluded from
RPC logic.

- Separate local channel transmission errors and remote RPC wire response codes:
  The channel layer returns ACK header err via nbl_chan_send_msg() when wait_ack=1.
  Translate wire protocol defined remote codes NBL_CHAN_RESP_* to standard kernel
  errno at dispatch request wrapper to avoid semantic confusion between wire
  handshake values and system error numbers exposed to upper layers.
- Collapse all fine-grained resource operation sub-errors into generic
  NBL_CHAN_RESP_ERR on wire to keep message payload layout unchanged and
  maintain backward compatibility with legacy firmware.
- Fix unimplemented ops check order in response handler to prevent NULL pointer
  invocation of resource ops.

Add input sanitization for mailbox response handlers:
The driver maintains cross-version interoperability; older peers may send
truncated payloads. Existing min_t() + zero-init local param logic absorbs
partial messages and zero-fills missing fields. To mitigate risk:
1. Allow truncated payloads (0 < data_len < sizeof(param)) for backward
   compatibility, continue zero-filling missing fields.
2. Reject data_len == 0 messages entirely, avoid invoking resource ops
   with all-zero initialized parameters.
nbl_disp_chan_destroy_msix_map_resp carries no input payload and skips
payload length validation.

Note: Serialization mutex protecting concurrent MSIX map and mailbox irq hardware
operations will be added in a separate subsequent patch.

Signed-off-by: illusion wang <redacted>
---
 .../nebula-matrix/nbl/nbl_core/nbl_dispatch.c | 473 ++++++++++++++++++
 1 file changed, 473 insertions(+)
diff --git a/drivers/net/ethernet/nebula-matrix/nbl/nbl_core/nbl_dispatch.c b/drivers/net/ethernet/nebula-matrix/nbl/nbl_core/nbl_dispatch.c
index 8116643859c7..68d239a5c3db 100644
--- a/drivers/net/ethernet/nebula-matrix/nbl/nbl_core/nbl_dispatch.c
+++ b/drivers/net/ethernet/nebula-matrix/nbl/nbl_core/nbl_dispatch.c
@@ -6,6 +6,158 @@
 #include <linux/pci.h>
 #include "nbl_dispatch.h"
 
+static int nbl_disp_chan_get_vsi_id_req(struct nbl_dispatch_mgt *disp_mgt,
+					u16 type, u16 *vsi_id)
+{
+	struct nbl_channel_ops *chan_ops = disp_mgt->chan_ops_tbl->ops;
+	struct nbl_common_info *common = disp_mgt->common;
+	struct nbl_chan_param_get_vsi_id result = { 0 };
+	struct nbl_chan_param_get_vsi_id param = { 0 };
+	struct nbl_chan_send_info chan_send;
+	int ret;
+
+	param.type = cpu_to_le16(type);
+
+	nbl_chan_fill_send_info(&chan_send, common->mgt_pf,
+				NBL_CHAN_MSG_GET_VSI_ID,
+				&param, sizeof(param), &result,
+				sizeof(result), 1);
+	ret = chan_ops->send_msg(disp_mgt->chan_ops_tbl->priv, &chan_send);
+	switch (ret) {
+	case NBL_CHAN_RESP_UNIMPLEMENTED:
+		return -EOPNOTSUPP;
+	case NBL_CHAN_RESP_ERR:
+		return -EREMOTEIO;
+	case NBL_CHAN_RESP_OK:
+		break;
+	default:
+		return ret;
+	}
+	*vsi_id = le16_to_cpu(result.vsi_id);
+	return 0;
+}
+
+static void nbl_disp_chan_get_vsi_id_resp(void *priv, u16 src_id, u16 msg_id,
+					  void *data, u32 data_len)
+{
+	struct nbl_dispatch_mgt *disp_mgt = (struct nbl_dispatch_mgt *)priv;
+	struct nbl_channel_ops *chan_ops = disp_mgt->chan_ops_tbl->ops;
+	struct nbl_resource_ops *res_ops = disp_mgt->res_ops_tbl->ops;
+	struct nbl_resource_mgt *p = disp_mgt->res_ops_tbl->priv;
+	struct device *dev = disp_mgt->common->dev;
+	struct nbl_chan_param_get_vsi_id result = { 0 };
+	struct nbl_chan_param_get_vsi_id param = { 0 };
+	struct nbl_chan_ack_info chan_ack;
+	int err = NBL_CHAN_RESP_OK;
+	u16 vsi_id = 0;
+	int copy_len;
+	int ret;
+
+	if (data_len == 0) {
+		err = NBL_CHAN_RESP_ERR;
+		goto ack_out;
+	}
+	copy_len = min_t(size_t, data_len, sizeof(param));
+	memcpy(&param, data, copy_len);
+	if (!res_ops->get_vsi_id) {
+		err = NBL_CHAN_RESP_UNIMPLEMENTED;
+	} else {
+		ret = NBL_OPS_CALL_RET(res_ops->get_vsi_id,
+				       (p, src_id, le16_to_cpu(param.type),
+					&vsi_id));
+		if (ret)
+			err = NBL_CHAN_RESP_ERR;
+	}
+	result.vsi_id = cpu_to_le16(vsi_id);
+ack_out:
+	nbl_chan_fill_ack_info(&chan_ack, src_id,
+			       NBL_CHAN_MSG_GET_VSI_ID, msg_id, err,
+			       &result, sizeof(result));
+	ret = chan_ops->send_ack(disp_mgt->chan_ops_tbl->priv, &chan_ack);
+	if (ret)
+		dev_err(dev,
+			"channel send ack failed with ret: %d, msg_type: %d\n",
+			ret, NBL_CHAN_MSG_GET_VSI_ID);
+}
+
+static int nbl_disp_chan_get_eth_id_req(struct nbl_dispatch_mgt *disp_mgt,
+					u16 vsi_id, u8 *eth_num, u8 *eth_id,
+					u8 *logic_eth_id)
+{
+	struct nbl_channel_ops *chan_ops = disp_mgt->chan_ops_tbl->ops;
+	struct nbl_common_info *common = disp_mgt->common;
+	struct nbl_chan_param_get_eth_id result = { 0 };
+	struct nbl_chan_param_get_eth_id param = { 0 };
+	struct nbl_chan_send_info chan_send;
+	int ret;
+
+	param.vsi_id = cpu_to_le16(vsi_id);
+
+	nbl_chan_fill_send_info(&chan_send, common->mgt_pf,
+				NBL_CHAN_MSG_GET_ETH_ID,
+				&param, sizeof(param), &result,
+				sizeof(result), 1);
+	ret = chan_ops->send_msg(disp_mgt->chan_ops_tbl->priv, &chan_send);
+	switch (ret) {
+	case NBL_CHAN_RESP_UNIMPLEMENTED:
+		return -EOPNOTSUPP;
+	case NBL_CHAN_RESP_ERR:
+		return -EREMOTEIO;
+	case NBL_CHAN_RESP_OK:
+		break;
+	default:
+		return ret;
+	}
+	*eth_num = result.eth_num;
+	*eth_id = result.eth_id;
+	*logic_eth_id = result.logic_eth_id;
+
+	return 0;
+}
+
+static void nbl_disp_chan_get_eth_id_resp(void *priv, u16 src_id, u16 msg_id,
+					  void *data, u32 data_len)
+{
+	struct nbl_dispatch_mgt *disp_mgt = (struct nbl_dispatch_mgt *)priv;
+	struct nbl_channel_ops *chan_ops = disp_mgt->chan_ops_tbl->ops;
+	struct nbl_resource_ops *res_ops = disp_mgt->res_ops_tbl->ops;
+	struct nbl_resource_mgt *p = disp_mgt->res_ops_tbl->priv;
+	struct nbl_chan_param_get_eth_id result = { 0 };
+	struct nbl_chan_param_get_eth_id param = { 0 };
+	struct device *dev = disp_mgt->common->dev;
+	struct nbl_chan_ack_info chan_ack;
+	int err = NBL_CHAN_RESP_OK;
+	int copy_len;
+	int ret;
+
+	if (data_len == 0) {
+		err = NBL_CHAN_RESP_ERR;
+		goto ack_out;
+	}
+	copy_len = min_t(size_t, data_len, sizeof(param));
+	memcpy(&param, data, copy_len);
+
+	if (!res_ops->get_eth_id) {
+		err = NBL_CHAN_RESP_UNIMPLEMENTED;
+	} else {
+		ret = NBL_OPS_CALL_RET(res_ops->get_eth_id,
+				       (p, src_id, le16_to_cpu(param.vsi_id),
+					&result.eth_num, &result.eth_id,
+					&result.logic_eth_id));
+		if (ret)
+			err = NBL_CHAN_RESP_ERR;
+	}
+ack_out:
+	nbl_chan_fill_ack_info(&chan_ack, src_id,
+			       NBL_CHAN_MSG_GET_ETH_ID, msg_id, err,
+			       &result, sizeof(result));
+	ret = chan_ops->send_ack(disp_mgt->chan_ops_tbl->priv, &chan_ack);
+	if (ret)
+		dev_err(dev,
+			"channel send ack failed with ret: %d, msg_type: %d\n",
+			ret, NBL_CHAN_MSG_GET_ETH_ID);
+}
+
 static void nbl_disp_deinit_module(struct nbl_dispatch_mgt *disp_mgt)
 {
 	struct nbl_resource_ops *res_ops = disp_mgt->res_ops_tbl->ops;
@@ -22,6 +174,264 @@ static int nbl_disp_init_module(struct nbl_dispatch_mgt *disp_mgt)
 	return NBL_OPS_CALL_RET(res_ops->init_module, (p));
 }
 
+static int nbl_disp_configure_msix_map(struct nbl_dispatch_mgt *disp_mgt,
+				       u16 num_net_msix, u16 num_others_msix,
+				       bool net_msix_mask_en)
+{
+	struct nbl_resource_ops *res_ops = disp_mgt->res_ops_tbl->ops;
+	struct nbl_resource_mgt *p = disp_mgt->res_ops_tbl->priv;
+	struct nbl_common_info *common = disp_mgt->common;
+
+	return NBL_OPS_CALL_RET(res_ops->configure_msix_map, (p,
+				common->mgt_pf, num_net_msix,
+				num_others_msix, net_msix_mask_en));
+}
+
+static int
+nbl_disp_chan_configure_msix_map_req(struct nbl_dispatch_mgt *disp_mgt,
+				     u16 num_net_msix, u16 num_others_msix,
+				     bool net_msix_mask_en)
+{
+	struct nbl_channel_ops *chan_ops = disp_mgt->chan_ops_tbl->ops;
+	struct nbl_common_info *common = disp_mgt->common;
+	struct nbl_chan_param_cfg_msix_map param = { 0 };
+	struct nbl_chan_send_info chan_send;
+	int ret;
+
+	param.num_net_msix = cpu_to_le16(num_net_msix);
+	param.num_others_msix = cpu_to_le16(num_others_msix);
+	param.msix_mask_en = cpu_to_le16(!!net_msix_mask_en);
+
+	nbl_chan_fill_send_info(&chan_send, common->mgt_pf,
+				NBL_CHAN_MSG_CONFIGURE_MSIX_MAP,
+				&param, sizeof(param),
+				NULL, 0, 1);
+	ret = chan_ops->send_msg(disp_mgt->chan_ops_tbl->priv, &chan_send);
+	switch (ret) {
+	case NBL_CHAN_RESP_UNIMPLEMENTED:
+		return -EOPNOTSUPP;
+	case NBL_CHAN_RESP_ERR:
+		return -EREMOTEIO;
+	case NBL_CHAN_RESP_OK:
+		return ret;
+	default:
+		return ret;
+	}
+}
+
+static void nbl_disp_chan_configure_msix_map_resp(void *priv, u16 src_id,
+						  u16 msg_id, void *data,
+						  u32 data_len)
+{
+	struct nbl_dispatch_mgt *disp_mgt = (struct nbl_dispatch_mgt *)priv;
+	struct nbl_channel_ops *chan_ops = disp_mgt->chan_ops_tbl->ops;
+	struct nbl_resource_ops *res_ops = disp_mgt->res_ops_tbl->ops;
+	struct nbl_resource_mgt *p = disp_mgt->res_ops_tbl->priv;
+	struct device *dev = disp_mgt->common->dev;
+	struct nbl_chan_param_cfg_msix_map param = { 0 };
+	struct nbl_chan_ack_info chan_ack;
+	int err = NBL_CHAN_RESP_OK;
+	int copy_len;
+	int ret;
+
+	if (data_len == 0) {
+		err = NBL_CHAN_RESP_ERR;
+		goto ack_out;
+	}
+	copy_len = min_t(size_t, data_len, sizeof(param));
+	memcpy(&param, data, copy_len);
+	if (!res_ops->configure_msix_map) {
+		err = NBL_CHAN_RESP_UNIMPLEMENTED;
+	} else {
+		ret = NBL_OPS_CALL_RET(res_ops->configure_msix_map,
+				       (p, src_id,
+					le16_to_cpu(param.num_net_msix),
+					le16_to_cpu(param.num_others_msix),
+					!!le16_to_cpu(param.msix_mask_en)));
+		if (ret)
+			err = NBL_CHAN_RESP_ERR;
+	}
+ack_out:
+	nbl_chan_fill_ack_info(&chan_ack, src_id,
+			       NBL_CHAN_MSG_CONFIGURE_MSIX_MAP, msg_id,
+			       err, NULL, 0);
+	ret = chan_ops->send_ack(disp_mgt->chan_ops_tbl->priv, &chan_ack);
+	if (ret)
+		dev_err(dev,
+			"channel send ack failed with ret: %d, msg_type: %d\n",
+			ret, NBL_CHAN_MSG_CONFIGURE_MSIX_MAP);
+}
+
+static int nbl_disp_chan_destroy_msix_map_req(struct nbl_dispatch_mgt *disp_mgt)
+{
+	struct nbl_channel_ops *chan_ops = disp_mgt->chan_ops_tbl->ops;
+	struct nbl_common_info *common = disp_mgt->common;
+	struct nbl_chan_send_info chan_send;
+	int ret;
+
+	nbl_chan_fill_send_info(&chan_send, common->mgt_pf,
+				NBL_CHAN_MSG_DESTROY_MSIX_MAP,
+				NULL, 0, NULL, 0, 1);
+	ret = chan_ops->send_msg(disp_mgt->chan_ops_tbl->priv, &chan_send);
+	switch (ret) {
+	case NBL_CHAN_RESP_UNIMPLEMENTED:
+		return -EOPNOTSUPP;
+	case NBL_CHAN_RESP_ERR:
+		return -EREMOTEIO;
+	case NBL_CHAN_RESP_OK:
+		return ret;
+	default:
+		return ret;
+	}
+}
+
+static void nbl_disp_chan_destroy_msix_map_resp(void *priv, u16 src_id,
+						u16 msg_id, void *data,
+						u32 data_len)
+{
+	struct nbl_dispatch_mgt *disp_mgt = (struct nbl_dispatch_mgt *)priv;
+	struct nbl_channel_ops *chan_ops = disp_mgt->chan_ops_tbl->ops;
+	struct nbl_resource_ops *res_ops = disp_mgt->res_ops_tbl->ops;
+	struct nbl_resource_mgt *p = disp_mgt->res_ops_tbl->priv;
+	struct device *dev = disp_mgt->common->dev;
+	struct nbl_chan_ack_info chan_ack;
+	int err = NBL_CHAN_RESP_OK;
+	int ret;
+
+	if (!res_ops->destroy_msix_map) {
+		err = NBL_CHAN_RESP_UNIMPLEMENTED;
+	} else {
+		ret = NBL_OPS_CALL_RET(res_ops->destroy_msix_map, (p, src_id));
+		if (ret)
+			err = NBL_CHAN_RESP_ERR;
+	}
+
+	nbl_chan_fill_ack_info(&chan_ack, src_id,
+			       NBL_CHAN_MSG_DESTROY_MSIX_MAP, msg_id,
+			       err, NULL, 0);
+	ret = chan_ops->send_ack(disp_mgt->chan_ops_tbl->priv, &chan_ack);
+	if (ret)
+		dev_err(dev,
+			"channel send ack failed with ret: %d, msg_type: %d\n",
+			ret, NBL_CHAN_MSG_DESTROY_MSIX_MAP);
+}
+
+static int nbl_disp_chan_set_mailbox_irq_req(struct nbl_dispatch_mgt *disp_mgt,
+					     u16 vector_id, bool enable_msix)
+{
+	struct nbl_channel_ops *chan_ops = disp_mgt->chan_ops_tbl->ops;
+	struct nbl_chan_param_set_mailbox_irq param = { 0 };
+	struct nbl_common_info *common = disp_mgt->common;
+	struct nbl_chan_send_info chan_send;
+	int ret;
+
+	param.vector_id = cpu_to_le16(vector_id);
+	param.enable_msix = !!enable_msix;
+
+	nbl_chan_fill_send_info(&chan_send, common->mgt_pf,
+				NBL_CHAN_MSG_MAILBOX_SET_IRQ,
+				&param, sizeof(param), NULL, 0, 1);
+	ret = chan_ops->send_msg(disp_mgt->chan_ops_tbl->priv, &chan_send);
+	switch (ret) {
+	case NBL_CHAN_RESP_UNIMPLEMENTED:
+		return -EOPNOTSUPP;
+	case NBL_CHAN_RESP_ERR:
+		return -EREMOTEIO;
+	case NBL_CHAN_RESP_OK:
+		return ret;
+	default:
+		return ret;
+	}
+}
+
+static void nbl_disp_chan_set_mailbox_irq_resp(void *priv, u16 src_id,
+					       u16 msg_id, void *data,
+					       u32 data_len)
+{
+	struct nbl_dispatch_mgt *disp_mgt = (struct nbl_dispatch_mgt *)priv;
+	struct nbl_channel_ops *chan_ops = disp_mgt->chan_ops_tbl->ops;
+	struct nbl_resource_ops *res_ops = disp_mgt->res_ops_tbl->ops;
+	struct nbl_resource_mgt *p = disp_mgt->res_ops_tbl->priv;
+	struct nbl_chan_param_set_mailbox_irq param = { 0 };
+	struct device *dev = disp_mgt->common->dev;
+	struct nbl_chan_ack_info chan_ack;
+	int err = NBL_CHAN_RESP_OK;
+	bool enable_msix;
+	u16 vector_id;
+	int copy_len;
+	int ret;
+
+	if (data_len == 0) {
+		err = NBL_CHAN_RESP_ERR;
+		goto ack_out;
+	}
+	copy_len = min_t(size_t, data_len, sizeof(param));
+	memcpy(&param, data, copy_len);
+	vector_id = le16_to_cpu(param.vector_id);
+	enable_msix = !!param.enable_msix;
+	if (!res_ops->set_mailbox_irq) {
+		err = NBL_CHAN_RESP_UNIMPLEMENTED;
+	} else {
+		ret = NBL_OPS_CALL_RET(res_ops->set_mailbox_irq,
+				       (p, src_id, vector_id, enable_msix));
+		if (ret)
+			err = NBL_CHAN_RESP_ERR;
+	}
+ack_out:
+	nbl_chan_fill_ack_info(&chan_ack, src_id,
+			       NBL_CHAN_MSG_MAILBOX_SET_IRQ, msg_id,
+			       err, NULL, 0);
+	ret = chan_ops->send_ack(disp_mgt->chan_ops_tbl->priv, &chan_ack);
+	if (ret)
+		dev_err(dev,
+			"channel send ack failed with ret: %d, msg_type: %d\n",
+			ret, NBL_CHAN_MSG_MAILBOX_SET_IRQ);
+}
+
+static int nbl_disp_destroy_msix_map(struct nbl_dispatch_mgt *disp_mgt)
+{
+	struct nbl_resource_ops *res_ops = disp_mgt->res_ops_tbl->ops;
+	struct nbl_resource_mgt *p = disp_mgt->res_ops_tbl->priv;
+	struct nbl_common_info *common = disp_mgt->common;
+
+	return NBL_OPS_CALL_RET(res_ops->destroy_msix_map, (p,
+				     common->mgt_pf));
+}
+
+static int nbl_disp_set_mailbox_irq(struct nbl_dispatch_mgt *disp_mgt,
+				    u16 vector_id, bool enable_msix)
+{
+	struct nbl_resource_ops *res_ops = disp_mgt->res_ops_tbl->ops;
+	struct nbl_resource_mgt *p = disp_mgt->res_ops_tbl->priv;
+	struct nbl_common_info *common = disp_mgt->common;
+
+	return NBL_OPS_CALL_RET(res_ops->set_mailbox_irq, (p,
+				common->mgt_pf, vector_id, enable_msix));
+}
+
+static int nbl_disp_get_vsi_id(struct nbl_dispatch_mgt *disp_mgt, u16 type,
+			       u16 *vsi_id)
+{
+	struct nbl_resource_ops *res_ops = disp_mgt->res_ops_tbl->ops;
+	struct nbl_resource_mgt *p = disp_mgt->res_ops_tbl->priv;
+	struct nbl_common_info *common = disp_mgt->common;
+
+	return NBL_OPS_CALL_RET(res_ops->get_vsi_id,
+				(p, common->mgt_pf, type, vsi_id));
+}
+
+static int nbl_disp_get_eth_id(struct nbl_dispatch_mgt *disp_mgt, u16 vsi_id,
+			       u8 *eth_num, u8 *eth_id, u8 *logic_eth_id)
+{
+	struct nbl_resource_ops *res_ops = disp_mgt->res_ops_tbl->ops;
+	struct nbl_resource_mgt *p = disp_mgt->res_ops_tbl->priv;
+	struct nbl_common_info *common = disp_mgt->common;
+
+	return NBL_OPS_CALL_RET(res_ops->get_eth_id,
+				(p, common->mgt_pf, vsi_id, eth_num, eth_id,
+				 logic_eth_id));
+}
+
 /* NBL_DISP_SET_OPS(disp_op_name, func, ctrl_lvl, msg_type, msg_req, msg_resp)
  * ctrl_lvl is to define when this disp_op should go directly to res_op,
  * not sending a channel msg.
@@ -38,7 +448,62 @@ do {									\
 	NBL_DISP_SET_OPS(deinit_module,				\
 			 nbl_disp_deinit_module,			\
 			 NBL_DISP_CTRL_LVL_MGT, -1, NULL, NULL);	\
+	NBL_DISP_SET_OPS(configure_msix_map,				\
+			 nbl_disp_configure_msix_map,			\
+			 NBL_DISP_CTRL_LVL_MGT,				\
+			 NBL_CHAN_MSG_CONFIGURE_MSIX_MAP,		\
+			 nbl_disp_chan_configure_msix_map_req,		\
+			 nbl_disp_chan_configure_msix_map_resp);	\
+	NBL_DISP_SET_OPS(destroy_msix_map, nbl_disp_destroy_msix_map,	\
+			 NBL_DISP_CTRL_LVL_MGT,				\
+			 NBL_CHAN_MSG_DESTROY_MSIX_MAP,			\
+			 nbl_disp_chan_destroy_msix_map_req,		\
+			 nbl_disp_chan_destroy_msix_map_resp);		\
+	NBL_DISP_SET_OPS(set_mailbox_irq,				\
+			 nbl_disp_set_mailbox_irq,			\
+			 NBL_DISP_CTRL_LVL_MGT,				\
+			 NBL_CHAN_MSG_MAILBOX_SET_IRQ,		\
+			 nbl_disp_chan_set_mailbox_irq_req,		\
+			 nbl_disp_chan_set_mailbox_irq_resp);	\
+	NBL_DISP_SET_OPS(get_vsi_id, nbl_disp_get_vsi_id,		\
+			 NBL_DISP_CTRL_LVL_MGT, NBL_CHAN_MSG_GET_VSI_ID,\
+			 nbl_disp_chan_get_vsi_id_req,			\
+			 nbl_disp_chan_get_vsi_id_resp);		\
+	NBL_DISP_SET_OPS(get_eth_id, nbl_disp_get_eth_id,		\
+			 NBL_DISP_CTRL_LVL_MGT, NBL_CHAN_MSG_GET_ETH_ID,\
+			 nbl_disp_chan_get_eth_id_req,			\
+			 nbl_disp_chan_get_eth_id_resp);		\
+} while (0)
+
+/* Structure starts here, adding an op should not modify anything below */
+static int nbl_disp_setup_msg(struct nbl_dispatch_mgt *disp_mgt)
+{
+	struct nbl_dispatch_ops *disp_ops = disp_mgt->disp_ops_tbl->ops;
+	struct nbl_channel_ops *chan_ops = disp_mgt->chan_ops_tbl->ops;
+	struct nbl_channel_mgt *p = disp_mgt->chan_ops_tbl->priv;
+	int ret = 0;
+	int _ret;
+
+#define NBL_DISP_SET_OPS(disp_op, func, ctrl, msg_type, msg_req, resp) \
+do {									\
+	typeof(msg_type) _msg_type = (msg_type);			\
+	typeof(ctrl) _ctrl_lvl = (ctrl);				\
+	(void)(disp_ops->NBL_NAME(disp_op));				\
+	(void)(func);							\
+	(void)(msg_req);						\
+	(void)_ctrl_lvl;						\
+	if (_msg_type >= 0) {						\
+		_ret = chan_ops->register_msg(p, _msg_type, resp, disp_mgt);\
+		if (_ret < 0 && !ret)					\
+			ret = _ret;					\
+	}								\
 } while (0)
+	NBL_DISP_OPS_TBL;
+#undef  NBL_DISP_SET_OPS
+	if (ret)
+		chan_ops->unregister_all_msg(p);
+	return ret;
+}
 
 /* Ctrl lvl means that if a certain level is set, then all disp_ops that
  * declared this lvl will go directly to res_ops, rather than send a
@@ -126,6 +591,10 @@ int nbl_disp_init(struct nbl_adapter *adapter)
 	adapter->core.disp_mgt = disp_mgt;
 	adapter->intf.dispatch_ops_tbl = disp_ops_tbl;
 
+	ret = nbl_disp_setup_msg(disp_mgt);
+	if (ret)
+		return ret;
+
 	if (common->has_ctrl)
 		nbl_disp_setup_ctrl_lvl(disp_mgt, NBL_DISP_CTRL_LVL_MGT);
 
@@ -134,4 +603,8 @@ int nbl_disp_init(struct nbl_adapter *adapter)
 
 void nbl_disp_remove(struct nbl_adapter *adapter)
 {
+	/*
+	 * All message handlers will be cleaned up inside channel layer
+	 * nbl_chan_remove_common() at final device tear-down
+	 */
 }
-- 
2.47.3
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help