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