1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2023 Advanced Micro Devices, Inc */
3 
4 #include <linux/errno.h>
5 #include <linux/pci.h>
6 #include <linux/utsname.h>
7 
8 #include "core.h"
9 
10 int pdsc_err_to_errno(enum pds_core_status_code code)
11 {
12 	switch (code) {
13 	case PDS_RC_SUCCESS:
14 		return 0;
15 	case PDS_RC_EVERSION:
16 	case PDS_RC_EQTYPE:
17 	case PDS_RC_EQID:
18 	case PDS_RC_EINVAL:
19 	case PDS_RC_ENOSUPP:
20 		return -EINVAL;
21 	case PDS_RC_EPERM:
22 		return -EPERM;
23 	case PDS_RC_ENOENT:
24 		return -ENOENT;
25 	case PDS_RC_EAGAIN:
26 		return -EAGAIN;
27 	case PDS_RC_ENOMEM:
28 		return -ENOMEM;
29 	case PDS_RC_EFAULT:
30 		return -EFAULT;
31 	case PDS_RC_EBUSY:
32 		return -EBUSY;
33 	case PDS_RC_EEXIST:
34 		return -EEXIST;
35 	case PDS_RC_EVFID:
36 		return -ENODEV;
37 	case PDS_RC_ECLIENT:
38 		return -ECHILD;
39 	case PDS_RC_ENOSPC:
40 		return -ENOSPC;
41 	case PDS_RC_ERANGE:
42 		return -ERANGE;
43 	case PDS_RC_BAD_ADDR:
44 		return -EFAULT;
45 	case PDS_RC_EOPCODE:
46 	case PDS_RC_EINTR:
47 	case PDS_RC_DEV_CMD:
48 	case PDS_RC_ERROR:
49 	case PDS_RC_ERDMA:
50 	case PDS_RC_EIO:
51 	default:
52 		return -EIO;
53 	}
54 }
55 
56 bool pdsc_is_fw_running(struct pdsc *pdsc)
57 {
58 	pdsc->fw_status = ioread8(&pdsc->info_regs->fw_status);
59 	pdsc->last_fw_time = jiffies;
60 	pdsc->last_hb = ioread32(&pdsc->info_regs->fw_heartbeat);
61 
62 	/* Firmware is useful only if the running bit is set and
63 	 * fw_status != 0xff (bad PCI read)
64 	 */
65 	return (pdsc->fw_status != 0xff) &&
66 		(pdsc->fw_status & PDS_CORE_FW_STS_F_RUNNING);
67 }
68 
69 bool pdsc_is_fw_good(struct pdsc *pdsc)
70 {
71 	u8 gen = pdsc->fw_status & PDS_CORE_FW_STS_F_GENERATION;
72 
73 	return pdsc_is_fw_running(pdsc) && gen == pdsc->fw_generation;
74 }
75 
76 static u8 pdsc_devcmd_status(struct pdsc *pdsc)
77 {
78 	return ioread8(&pdsc->cmd_regs->comp.status);
79 }
80 
81 static bool pdsc_devcmd_done(struct pdsc *pdsc)
82 {
83 	return ioread32(&pdsc->cmd_regs->done) & PDS_CORE_DEV_CMD_DONE;
84 }
85 
86 static void pdsc_devcmd_dbell(struct pdsc *pdsc)
87 {
88 	iowrite32(0, &pdsc->cmd_regs->done);
89 	iowrite32(1, &pdsc->cmd_regs->doorbell);
90 }
91 
92 static void pdsc_devcmd_clean(struct pdsc *pdsc)
93 {
94 	iowrite32(0, &pdsc->cmd_regs->doorbell);
95 	memset_io(&pdsc->cmd_regs->cmd, 0, sizeof(pdsc->cmd_regs->cmd));
96 }
97 
98 static const char *pdsc_devcmd_str(int opcode)
99 {
100 	switch (opcode) {
101 	case PDS_CORE_CMD_NOP:
102 		return "PDS_CORE_CMD_NOP";
103 	case PDS_CORE_CMD_IDENTIFY:
104 		return "PDS_CORE_CMD_IDENTIFY";
105 	case PDS_CORE_CMD_RESET:
106 		return "PDS_CORE_CMD_RESET";
107 	case PDS_CORE_CMD_INIT:
108 		return "PDS_CORE_CMD_INIT";
109 	case PDS_CORE_CMD_FW_DOWNLOAD:
110 		return "PDS_CORE_CMD_FW_DOWNLOAD";
111 	case PDS_CORE_CMD_FW_CONTROL:
112 		return "PDS_CORE_CMD_FW_CONTROL";
113 	default:
114 		return "PDS_CORE_CMD_UNKNOWN";
115 	}
116 }
117 
118 static int pdsc_devcmd_wait(struct pdsc *pdsc, int max_seconds)
119 {
120 	struct device *dev = pdsc->dev;
121 	unsigned long start_time;
122 	unsigned long max_wait;
123 	unsigned long duration;
124 	int timeout = 0;
125 	int done = 0;
126 	int err = 0;
127 	int status;
128 	int opcode;
129 
130 	opcode = ioread8(&pdsc->cmd_regs->cmd.opcode);
131 
132 	start_time = jiffies;
133 	max_wait = start_time + (max_seconds * HZ);
134 
135 	while (!done && !timeout) {
136 		done = pdsc_devcmd_done(pdsc);
137 		if (done)
138 			break;
139 
140 		timeout = time_after(jiffies, max_wait);
141 		if (timeout)
142 			break;
143 
144 		usleep_range(100, 200);
145 	}
146 	duration = jiffies - start_time;
147 
148 	if (done && duration > HZ)
149 		dev_dbg(dev, "DEVCMD %d %s after %ld secs\n",
150 			opcode, pdsc_devcmd_str(opcode), duration / HZ);
151 
152 	if (!done || timeout) {
153 		dev_err(dev, "DEVCMD %d %s timeout, done %d timeout %d max_seconds=%d\n",
154 			opcode, pdsc_devcmd_str(opcode), done, timeout,
155 			max_seconds);
156 		err = -ETIMEDOUT;
157 		pdsc_devcmd_clean(pdsc);
158 	}
159 
160 	status = pdsc_devcmd_status(pdsc);
161 	err = pdsc_err_to_errno(status);
162 	if (err && err != -EAGAIN)
163 		dev_err(dev, "DEVCMD %d %s failed, status=%d err %d %pe\n",
164 			opcode, pdsc_devcmd_str(opcode), status, err,
165 			ERR_PTR(err));
166 
167 	return err;
168 }
169 
170 int pdsc_devcmd_locked(struct pdsc *pdsc, union pds_core_dev_cmd *cmd,
171 		       union pds_core_dev_comp *comp, int max_seconds)
172 {
173 	int err;
174 
175 	memcpy_toio(&pdsc->cmd_regs->cmd, cmd, sizeof(*cmd));
176 	pdsc_devcmd_dbell(pdsc);
177 	err = pdsc_devcmd_wait(pdsc, max_seconds);
178 	memcpy_fromio(comp, &pdsc->cmd_regs->comp, sizeof(*comp));
179 
180 	if (err == -ENXIO || err == -ETIMEDOUT)
181 		queue_work(pdsc->wq, &pdsc->health_work);
182 
183 	return err;
184 }
185 
186 int pdsc_devcmd(struct pdsc *pdsc, union pds_core_dev_cmd *cmd,
187 		union pds_core_dev_comp *comp, int max_seconds)
188 {
189 	int err;
190 
191 	mutex_lock(&pdsc->devcmd_lock);
192 	err = pdsc_devcmd_locked(pdsc, cmd, comp, max_seconds);
193 	mutex_unlock(&pdsc->devcmd_lock);
194 
195 	return err;
196 }
197 
198 int pdsc_devcmd_init(struct pdsc *pdsc)
199 {
200 	union pds_core_dev_comp comp = {};
201 	union pds_core_dev_cmd cmd = {
202 		.opcode = PDS_CORE_CMD_INIT,
203 	};
204 
205 	return pdsc_devcmd(pdsc, &cmd, &comp, pdsc->devcmd_timeout);
206 }
207 
208 int pdsc_devcmd_reset(struct pdsc *pdsc)
209 {
210 	union pds_core_dev_comp comp = {};
211 	union pds_core_dev_cmd cmd = {
212 		.reset.opcode = PDS_CORE_CMD_RESET,
213 	};
214 
215 	return pdsc_devcmd(pdsc, &cmd, &comp, pdsc->devcmd_timeout);
216 }
217 
218 static int pdsc_devcmd_identify_locked(struct pdsc *pdsc)
219 {
220 	union pds_core_dev_comp comp = {};
221 	union pds_core_dev_cmd cmd = {
222 		.identify.opcode = PDS_CORE_CMD_IDENTIFY,
223 		.identify.ver = PDS_CORE_IDENTITY_VERSION_1,
224 	};
225 
226 	return pdsc_devcmd_locked(pdsc, &cmd, &comp, pdsc->devcmd_timeout);
227 }
228 
229 static void pdsc_init_devinfo(struct pdsc *pdsc)
230 {
231 	pdsc->dev_info.asic_type = ioread8(&pdsc->info_regs->asic_type);
232 	pdsc->dev_info.asic_rev = ioread8(&pdsc->info_regs->asic_rev);
233 	pdsc->fw_generation = PDS_CORE_FW_STS_F_GENERATION &
234 			      ioread8(&pdsc->info_regs->fw_status);
235 
236 	memcpy_fromio(pdsc->dev_info.fw_version,
237 		      pdsc->info_regs->fw_version,
238 		      PDS_CORE_DEVINFO_FWVERS_BUFLEN);
239 	pdsc->dev_info.fw_version[PDS_CORE_DEVINFO_FWVERS_BUFLEN] = 0;
240 
241 	memcpy_fromio(pdsc->dev_info.serial_num,
242 		      pdsc->info_regs->serial_num,
243 		      PDS_CORE_DEVINFO_SERIAL_BUFLEN);
244 	pdsc->dev_info.serial_num[PDS_CORE_DEVINFO_SERIAL_BUFLEN] = 0;
245 
246 	dev_dbg(pdsc->dev, "fw_version %s\n", pdsc->dev_info.fw_version);
247 }
248 
249 static int pdsc_identify(struct pdsc *pdsc)
250 {
251 	struct pds_core_drv_identity drv = {};
252 	size_t sz;
253 	int err;
254 
255 	drv.drv_type = cpu_to_le32(PDS_DRIVER_LINUX);
256 	snprintf(drv.driver_ver_str, sizeof(drv.driver_ver_str),
257 		 "%s %s", PDS_CORE_DRV_NAME, utsname()->release);
258 
259 	/* Next let's get some info about the device
260 	 * We use the devcmd_lock at this level in order to
261 	 * get safe access to the cmd_regs->data before anyone
262 	 * else can mess it up
263 	 */
264 	mutex_lock(&pdsc->devcmd_lock);
265 
266 	sz = min_t(size_t, sizeof(drv), sizeof(pdsc->cmd_regs->data));
267 	memcpy_toio(&pdsc->cmd_regs->data, &drv, sz);
268 
269 	err = pdsc_devcmd_identify_locked(pdsc);
270 	if (!err) {
271 		sz = min_t(size_t, sizeof(pdsc->dev_ident),
272 			   sizeof(pdsc->cmd_regs->data));
273 		memcpy_fromio(&pdsc->dev_ident, &pdsc->cmd_regs->data, sz);
274 	}
275 	mutex_unlock(&pdsc->devcmd_lock);
276 
277 	if (err) {
278 		dev_err(pdsc->dev, "Cannot identify device: %pe\n",
279 			ERR_PTR(err));
280 		return err;
281 	}
282 
283 	if (isprint(pdsc->dev_info.fw_version[0]) &&
284 	    isascii(pdsc->dev_info.fw_version[0]))
285 		dev_info(pdsc->dev, "FW: %.*s\n",
286 			 (int)(sizeof(pdsc->dev_info.fw_version) - 1),
287 			 pdsc->dev_info.fw_version);
288 	else
289 		dev_info(pdsc->dev, "FW: (invalid string) 0x%02x 0x%02x 0x%02x 0x%02x ...\n",
290 			 (u8)pdsc->dev_info.fw_version[0],
291 			 (u8)pdsc->dev_info.fw_version[1],
292 			 (u8)pdsc->dev_info.fw_version[2],
293 			 (u8)pdsc->dev_info.fw_version[3]);
294 
295 	return 0;
296 }
297 
298 int pdsc_dev_reinit(struct pdsc *pdsc)
299 {
300 	pdsc_init_devinfo(pdsc);
301 
302 	return pdsc_identify(pdsc);
303 }
304 
305 int pdsc_dev_init(struct pdsc *pdsc)
306 {
307 	unsigned int nintrs;
308 	int err;
309 
310 	/* Initial init and reset of device */
311 	pdsc_init_devinfo(pdsc);
312 	pdsc->devcmd_timeout = PDS_CORE_DEVCMD_TIMEOUT;
313 
314 	err = pdsc_devcmd_reset(pdsc);
315 	if (err)
316 		return err;
317 
318 	err = pdsc_identify(pdsc);
319 	if (err)
320 		return err;
321 
322 	pdsc_debugfs_add_ident(pdsc);
323 
324 	/* Now we can reserve interrupts */
325 	nintrs = le32_to_cpu(pdsc->dev_ident.nintrs);
326 	nintrs = min_t(unsigned int, num_online_cpus(), nintrs);
327 
328 	/* Get intr_info struct array for tracking */
329 	pdsc->intr_info = kcalloc(nintrs, sizeof(*pdsc->intr_info), GFP_KERNEL);
330 	if (!pdsc->intr_info) {
331 		err = -ENOMEM;
332 		goto err_out;
333 	}
334 
335 	err = pci_alloc_irq_vectors(pdsc->pdev, nintrs, nintrs, PCI_IRQ_MSIX);
336 	if (err != nintrs) {
337 		dev_err(pdsc->dev, "Can't get %d intrs from OS: %pe\n",
338 			nintrs, ERR_PTR(err));
339 		err = -ENOSPC;
340 		goto err_out;
341 	}
342 	pdsc->nintrs = nintrs;
343 
344 	return 0;
345 
346 err_out:
347 	kfree(pdsc->intr_info);
348 	pdsc->intr_info = NULL;
349 
350 	return err;
351 }
352