xref: /linux/drivers/net/ethernet/intel/ixd/ixd_lib.c (revision 91ec2035134982b98fab0609a9fd8480e8217dc1)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (C) 2025 Intel Corporation */
3 
4 #include "ixd.h"
5 #include "ixd_ctlq.h"
6 #include "ixd_devlink.h"
7 #include "ixd_virtchnl.h"
8 
9 #define IXD_DFLT_MBX_Q_LEN 64
10 
11 /**
12  * ixd_init_ctlq_create_info - Initialize control queue info for creation
13  * @info: destination
14  * @type: type of the queue to create
15  * @ctlq_reg: register assigned to the control queue
16  */
ixd_init_ctlq_create_info(struct libie_ctlq_create_info * info,enum libie_ctlq_type type,const struct libie_ctlq_reg * ctlq_reg)17 static void ixd_init_ctlq_create_info(struct libie_ctlq_create_info *info,
18 				      enum libie_ctlq_type type,
19 				      const struct libie_ctlq_reg *ctlq_reg)
20 {
21 	*info = (struct libie_ctlq_create_info) {
22 		.type = type,
23 		.id = -1,
24 		.reg = *ctlq_reg,
25 		.len = IXD_DFLT_MBX_Q_LEN,
26 	};
27 }
28 
29 /**
30  * ixd_init_libie_xn_params - Initialize xn transaction manager creation info
31  * @params: destination
32  * @adapter: adapter info struct
33  * @ctlqs: list of the managed queues to create
34  * @num_queues: length of the queue list
35  */
ixd_init_libie_xn_params(struct libie_ctlq_xn_init_params * params,struct ixd_adapter * adapter,struct libie_ctlq_create_info * ctlqs,uint num_queues)36 static void ixd_init_libie_xn_params(struct libie_ctlq_xn_init_params *params,
37 				     struct ixd_adapter *adapter,
38 				      struct libie_ctlq_create_info *ctlqs,
39 				      uint num_queues)
40 {
41 	*params = (struct libie_ctlq_xn_init_params){
42 		.cctlq_info = ctlqs,
43 		.ctx = &adapter->cp_ctx,
44 		.num_qs = num_queues,
45 	};
46 }
47 
48 /**
49  * ixd_adapter_fill_dflt_ctlqs - Find default control queues and store them
50  * @adapter: adapter info struct
51  */
ixd_adapter_fill_dflt_ctlqs(struct ixd_adapter * adapter)52 static void ixd_adapter_fill_dflt_ctlqs(struct ixd_adapter *adapter)
53 {
54 	adapter->arq = libie_find_ctlq(&adapter->cp_ctx, LIBIE_CTLQ_TYPE_RX,
55 				       LIBIE_CTLQ_MBX_ID);
56 	adapter->asq = libie_find_ctlq(&adapter->cp_ctx, LIBIE_CTLQ_TYPE_TX,
57 				       LIBIE_CTLQ_MBX_ID);
58 }
59 
60 /**
61  * ixd_deinit_dflt_mbx - Deinitialize default mailbox
62  * @adapter: adapter info struct
63  */
ixd_deinit_dflt_mbx(struct ixd_adapter * adapter)64 void ixd_deinit_dflt_mbx(struct ixd_adapter *adapter)
65 {
66 	cancel_delayed_work_sync(&adapter->mbx_task);
67 
68 	if (adapter->xnm)
69 		libie_ctlq_xn_shutdown(adapter->xnm);
70 
71 	if (adapter->asq)
72 		ixd_ctlq_clean_sq(adapter, true);
73 
74 	if (adapter->xnm)
75 		libie_ctlq_xn_deinit(adapter->xnm, &adapter->cp_ctx);
76 
77 	adapter->arq = NULL;
78 	adapter->asq = NULL;
79 	adapter->xnm = NULL;
80 }
81 
82 /**
83  * ixd_init_dflt_mbx - Setup default mailbox parameters and make request
84  * @adapter: adapter info struct
85  *
86  * Return: %0 on success, negative errno code on failure
87  */
ixd_init_dflt_mbx(struct ixd_adapter * adapter)88 int ixd_init_dflt_mbx(struct ixd_adapter *adapter)
89 {
90 	struct libie_ctlq_create_info ctlqs_info[2];
91 	struct libie_ctlq_xn_init_params xn_params;
92 	struct libie_ctlq_reg ctlq_reg_tx;
93 	struct libie_ctlq_reg ctlq_reg_rx;
94 	int err;
95 
96 	ixd_ctlq_reg_init(adapter, &ctlq_reg_tx, &ctlq_reg_rx);
97 	ixd_init_ctlq_create_info(&ctlqs_info[0], LIBIE_CTLQ_TYPE_TX,
98 				  &ctlq_reg_tx);
99 	ixd_init_ctlq_create_info(&ctlqs_info[1], LIBIE_CTLQ_TYPE_RX,
100 				  &ctlq_reg_rx);
101 	ixd_init_libie_xn_params(&xn_params, adapter, ctlqs_info,
102 				 ARRAY_SIZE(ctlqs_info));
103 	err = libie_ctlq_xn_init(&xn_params);
104 	if (err)
105 		return err;
106 	adapter->xnm = xn_params.xnm;
107 
108 	ixd_adapter_fill_dflt_ctlqs(adapter);
109 
110 	if (!adapter->asq || !adapter->arq) {
111 		ixd_deinit_dflt_mbx(adapter);
112 		return -ENOENT;
113 	}
114 
115 	queue_delayed_work(system_dfl_wq, &adapter->mbx_task, 0);
116 
117 	return 0;
118 }
119 
120 /**
121  * ixd_init_task - Initialize after reset
122  * @work: init work struct
123  */
ixd_init_task(struct work_struct * work)124 void ixd_init_task(struct work_struct *work)
125 {
126 	struct ixd_adapter *adapter;
127 	int err;
128 
129 	adapter = container_of(work, struct ixd_adapter,
130 			       init_task.init_work.work);
131 
132 	if (!ixd_check_reset_complete(adapter)) {
133 		if (++adapter->init_task.reset_retries < 10)
134 			queue_delayed_work(system_dfl_wq,
135 					   &adapter->init_task.init_work,
136 					   IXD_INIT_TASK_DELAY_JIFFIES);
137 		else
138 			dev_err(ixd_to_dev(adapter),
139 				"Device reset failed. The driver was unable to contact the device's firmware. Check that the FW is running.\n");
140 		return;
141 	}
142 
143 	adapter->init_task.reset_retries = 0;
144 	err = ixd_init_dflt_mbx(adapter);
145 	if (err) {
146 		dev_err(ixd_to_dev(adapter),
147 			"Failed to initialize the default mailbox: %pe\n",
148 			ERR_PTR(err));
149 		return;
150 	}
151 
152 	err = ixd_vc_dev_init(adapter);
153 	if (!err) {
154 		adapter->init_task.vc_retries = 0;
155 		adapter->init_task.success = true;
156 		ixd_devlink_register(adapter);
157 		return;
158 	}
159 
160 	libie_ctlq_xn_shutdown(adapter->xnm);
161 	ixd_trigger_reset(adapter);
162 	ixd_deinit_dflt_mbx(adapter);
163 	if (++adapter->init_task.vc_retries > 5 ||
164 	    (err != -ETIMEDOUT && err != -EAGAIN && err != -EBUSY)) {
165 		dev_err(ixd_to_dev(adapter),
166 			"Failed to establish mailbox communication with the hardware: %pe\n",
167 			ERR_PTR(err));
168 		return;
169 	}
170 
171 	queue_delayed_work(system_dfl_wq, &adapter->init_task.init_work,
172 			   IXD_INIT_TASK_DELAY_JIFFIES);
173 }
174