aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2018-05-17 01:58:00 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2018-06-12 00:05:39 -0400
commit9f4a8a2d7f9d71093f41c4bb0ef8707e8145bad3 (patch)
tree3fe9e7189cb1fe1b709550926aee61405585a59f
parent52b7116e885e95a0d4206cca7f11ef332bb1dd89 (diff)
fsi/sbefifo: Add driver for the SBE FIFO
This driver provides an in-kernel and a user API for accessing the command FIFO of the SBE (Self Boot Engine) of the POWER9 processor, via the FSI bus. It provides an in-kernel interface to submit command and receive responses, along with a helper to locate and analyse the response status block. It's a simple synchronous submit() type API. The user interface uses the write/read interface that an earlier version of this driver already provided, however it has some specific limitations in order to keep the driver simple and avoid using up a lot of kernel memory: - The user should perform a single write() with the command and a single read() to get the response (with a buffer big enough to hold the entire response). - On a write() the command is simply "stored" into a kernel buffer, it is submitted as one operation on the subsequent read(). This allows to have the code write directly from the FIFO into the user buffer and avoid hogging the SBE between the write() and read() syscall as it's critical that the SBE be freed asap to respond to the host. An extra write() will simply replace the previously written command. - A write of a single 4 bytes containing the value 0x52534554 in big endian will trigger a reset request. No read is necessary, the write() call will return when the reset has been acknowledged or times out. - The command is limited to 4K bytes. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Tested-by: Joel Stanley <joel@jms.id.au> ---
-rw-r--r--drivers/fsi/Kconfig7
-rw-r--r--drivers/fsi/Makefile1
-rw-r--r--drivers/fsi/fsi-sbefifo.c1005
-rw-r--r--include/linux/fsi-sbefifo.h33
4 files changed, 1046 insertions, 0 deletions
diff --git a/drivers/fsi/Kconfig b/drivers/fsi/Kconfig
index a326ed663d3c..24f84a96b8b9 100644
--- a/drivers/fsi/Kconfig
+++ b/drivers/fsi/Kconfig
@@ -32,4 +32,11 @@ config FSI_SCOM
32 ---help--- 32 ---help---
33 This option enables an FSI based SCOM device driver. 33 This option enables an FSI based SCOM device driver.
34 34
35config FSI_SBEFIFO
36 tristate "SBEFIFO FSI client device driver"
37 ---help---
38 This option enables an FSI based SBEFIFO device driver. The SBEFIFO is
39 a pipe-like FSI device for communicating with the self boot engine
40 (SBE) on POWER processors.
41
35endif 42endif
diff --git a/drivers/fsi/Makefile b/drivers/fsi/Makefile
index 65eb99dfafdb..851182e1cd9e 100644
--- a/drivers/fsi/Makefile
+++ b/drivers/fsi/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_FSI) += fsi-core.o
3obj-$(CONFIG_FSI_MASTER_HUB) += fsi-master-hub.o 3obj-$(CONFIG_FSI_MASTER_HUB) += fsi-master-hub.o
4obj-$(CONFIG_FSI_MASTER_GPIO) += fsi-master-gpio.o 4obj-$(CONFIG_FSI_MASTER_GPIO) += fsi-master-gpio.o
5obj-$(CONFIG_FSI_SCOM) += fsi-scom.o 5obj-$(CONFIG_FSI_SCOM) += fsi-scom.o
6obj-$(CONFIG_FSI_SBEFIFO) += fsi-sbefifo.o
diff --git a/drivers/fsi/fsi-sbefifo.c b/drivers/fsi/fsi-sbefifo.c
new file mode 100644
index 000000000000..9b8b6b346af6
--- /dev/null
+++ b/drivers/fsi/fsi-sbefifo.c
@@ -0,0 +1,1005 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) IBM Corporation 2017
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERGCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#include <linux/device.h>
16#include <linux/errno.h>
17#include <linux/fs.h>
18#include <linux/fsi.h>
19#include <linux/fsi-sbefifo.h>
20#include <linux/idr.h>
21#include <linux/kernel.h>
22#include <linux/miscdevice.h>
23#include <linux/module.h>
24#include <linux/mutex.h>
25#include <linux/of.h>
26#include <linux/of_device.h>
27#include <linux/of_platform.h>
28#include <linux/sched.h>
29#include <linux/slab.h>
30#include <linux/uaccess.h>
31#include <linux/delay.h>
32#include <linux/uio.h>
33#include <linux/vmalloc.h>
34
35/*
36 * The SBEFIFO is a pipe-like FSI device for communicating with
37 * the self boot engine on POWER processors.
38 */
39
40#define DEVICE_NAME "sbefifo"
41#define FSI_ENGID_SBE 0x22
42
43/*
44 * Register layout
45 */
46
47/* Register banks */
48#define SBEFIFO_UP 0x00 /* FSI -> Host */
49#define SBEFIFO_DOWN 0x40 /* Host -> FSI */
50
51/* Per-bank registers */
52#define SBEFIFO_FIFO 0x00 /* The FIFO itself */
53#define SBEFIFO_STS 0x04 /* Status register */
54#define SBEFIFO_STS_PARITY_ERR 0x20000000
55#define SBEFIFO_STS_RESET_REQ 0x02000000
56#define SBEFIFO_STS_GOT_EOT 0x00800000
57#define SBEFIFO_STS_MAX_XFER_LIMIT 0x00400000
58#define SBEFIFO_STS_FULL 0x00200000
59#define SBEFIFO_STS_EMPTY 0x00100000
60#define SBEFIFO_STS_ECNT_MASK 0x000f0000
61#define SBEFIFO_STS_ECNT_SHIFT 16
62#define SBEFIFO_STS_VALID_MASK 0x0000ff00
63#define SBEFIFO_STS_VALID_SHIFT 8
64#define SBEFIFO_STS_EOT_MASK 0x000000ff
65#define SBEFIFO_STS_EOT_SHIFT 0
66#define SBEFIFO_EOT_RAISE 0x08 /* (Up only) Set End Of Transfer */
67#define SBEFIFO_REQ_RESET 0x0C /* (Up only) Reset Request */
68#define SBEFIFO_PERFORM_RESET 0x10 /* (Down only) Perform Reset */
69#define SBEFIFO_EOT_ACK 0x14 /* (Down only) Acknowledge EOT */
70#define SBEFIFO_DOWN_MAX 0x18 /* (Down only) Max transfer */
71
72/* CFAM GP Mailbox SelfBoot Message register */
73#define CFAM_GP_MBOX_SBM_ADDR 0x2824 /* Converted 0x2809 */
74
75#define CFAM_SBM_SBE_BOOTED 0x80000000
76#define CFAM_SBM_SBE_ASYNC_FFDC 0x40000000
77#define CFAM_SBM_SBE_STATE_MASK 0x00f00000
78#define CFAM_SBM_SBE_STATE_SHIFT 20
79
80enum sbe_state
81{
82 SBE_STATE_UNKNOWN = 0x0, // Unkown, initial state
83 SBE_STATE_IPLING = 0x1, // IPL'ing - autonomous mode (transient)
84 SBE_STATE_ISTEP = 0x2, // ISTEP - Running IPL by steps (transient)
85 SBE_STATE_MPIPL = 0x3, // MPIPL
86 SBE_STATE_RUNTIME = 0x4, // SBE Runtime
87 SBE_STATE_DMT = 0x5, // Dead Man Timer State (transient)
88 SBE_STATE_DUMP = 0x6, // Dumping
89 SBE_STATE_FAILURE = 0x7, // Internal SBE failure
90 SBE_STATE_QUIESCE = 0x8, // Final state - needs SBE reset to get out
91};
92
93/* FIFO depth */
94#define SBEFIFO_FIFO_DEPTH 8
95
96/* Helpers */
97#define sbefifo_empty(sts) ((sts) & SBEFIFO_STS_EMPTY)
98#define sbefifo_full(sts) ((sts) & SBEFIFO_STS_FULL)
99#define sbefifo_parity_err(sts) ((sts) & SBEFIFO_STS_PARITY_ERR)
100#define sbefifo_populated(sts) (((sts) & SBEFIFO_STS_ECNT_MASK) >> SBEFIFO_STS_ECNT_SHIFT)
101#define sbefifo_vacant(sts) (SBEFIFO_FIFO_DEPTH - sbefifo_populated(sts))
102#define sbefifo_eot_set(sts) (((sts) & SBEFIFO_STS_EOT_MASK) >> SBEFIFO_STS_EOT_SHIFT)
103
104/* Reset request timeout in ms */
105#define SBEFIFO_RESET_TIMEOUT 10000
106
107/* Timeouts for commands in ms */
108#define SBEFIFO_TIMEOUT_START_CMD 10000
109#define SBEFIFO_TIMEOUT_IN_CMD 1000
110#define SBEFIFO_TIMEOUT_START_RSP 10000
111#define SBEFIFO_TIMEOUT_IN_RSP 1000
112
113/* Other constants */
114#define SBEFIFO_MAX_CMD_LEN PAGE_SIZE
115#define SBEFIFO_RESET_MAGIC 0x52534554 /* "RSET" */
116
117struct sbefifo {
118 uint32_t magic;
119#define SBEFIFO_MAGIC 0x53424546 /* "SBEF" */
120 struct fsi_device *fsi_dev;
121 struct miscdevice mdev;
122 struct mutex lock;
123 char name[32];
124 int idx;
125 bool broken;
126 bool async_ffdc;
127};
128
129struct sbefifo_user {
130 struct sbefifo *sbefifo;
131 struct mutex file_lock;
132 void *pending_cmd;
133 size_t pending_len;
134};
135
136static DEFINE_IDA(sbefifo_ida);
137static DEFINE_MUTEX(sbefifo_ffdc_mutex);
138
139
140static void sbefifo_dump_ffdc(struct device *dev, const __be32 *ffdc,
141 size_t ffdc_sz, bool internal)
142{
143 int pack = 0;
144#define FFDC_LSIZE 60
145 static char ffdc_line[FFDC_LSIZE];
146 char *p = ffdc_line;
147
148 mutex_lock(&sbefifo_ffdc_mutex);
149 while (ffdc_sz) {
150 u32 w0, w1, w2, i;
151 if (ffdc_sz < 3) {
152 dev_err(dev, "SBE invalid FFDC package size %zd\n", ffdc_sz);
153 return;
154 }
155 w0 = be32_to_cpu(*(ffdc++));
156 w1 = be32_to_cpu(*(ffdc++));
157 w2 = be32_to_cpu(*(ffdc++));
158 ffdc_sz -= 3;
159 if ((w0 >> 16) != 0xFFDC) {
160 dev_err(dev, "SBE invalid FFDC package signature %08x %08x %08x\n",
161 w0, w1, w2);
162 break;
163 }
164 w0 &= 0xffff;
165 if (w0 > ffdc_sz) {
166 dev_err(dev, "SBE FFDC package len %d words but only %zd remaining\n",
167 w0, ffdc_sz);
168 w0 = ffdc_sz;
169 break;
170 }
171 if (internal) {
172 dev_warn(dev, "+---- SBE FFDC package %d for async err -----+\n",
173 pack++);
174 } else {
175 dev_warn(dev, "+---- SBE FFDC package %d for cmd %02x:%02x -----+\n",
176 pack++, (w1 >> 8) & 0xff, w1 & 0xff);
177 }
178 dev_warn(dev, "| Response code: %08x |\n", w2);
179 dev_warn(dev, "|-------------------------------------------|\n");
180 for (i = 0; i < w0; i++) {
181 if ((i & 3) == 0) {
182 p = ffdc_line;
183 p += sprintf(p, "| %04x:", i << 4);
184 }
185 p += sprintf(p, " %08x", be32_to_cpu(*(ffdc++)));
186 ffdc_sz--;
187 if ((i & 3) == 3 || i == (w0 - 1)) {
188 while ((i & 3) < 3) {
189 p += sprintf(p, " ");
190 i++;
191 }
192 dev_warn(dev, "%s |\n", ffdc_line);
193 }
194 }
195 dev_warn(dev, "+-------------------------------------------+\n");
196 }
197}
198
199int sbefifo_parse_status(struct device *dev, u16 cmd, __be32 *response,
200 size_t resp_len, size_t *data_len)
201{
202 u32 dh, s0, s1;
203 size_t ffdc_sz;
204
205 if (resp_len < 3) {
206 pr_debug("sbefifo: cmd %04x, response too small: %zd\n",
207 cmd, resp_len);
208 return -ENXIO;
209 }
210 dh = be32_to_cpu(response[resp_len - 1]);
211 if (dh > resp_len || dh < 3) {
212 dev_err(dev, "SBE cmd %02x:%02x status offset out of range: %d/%zd\n",
213 cmd >> 8, cmd & 0xff, dh, resp_len);
214 return -ENXIO;
215 }
216 s0 = be32_to_cpu(response[resp_len - dh]);
217 s1 = be32_to_cpu(response[resp_len - dh + 1]);
218 if (((s0 >> 16) != 0xC0DE) || ((s0 & 0xffff) != cmd)) {
219 dev_err(dev, "SBE cmd %02x:%02x, status signature invalid: 0x%08x 0x%08x\n",
220 cmd >> 8, cmd & 0xff, s0, s1);
221 return -ENXIO;
222 }
223 if (s1 != 0) {
224 ffdc_sz = dh - 3;
225 dev_warn(dev, "SBE error cmd %02x:%02x status=%04x:%04x\n",
226 cmd >> 8, cmd & 0xff, s1 >> 16, s1 & 0xffff);
227 if (ffdc_sz)
228 sbefifo_dump_ffdc(dev, &response[resp_len - dh + 2],
229 ffdc_sz, false);
230 }
231 if (data_len)
232 *data_len = resp_len - dh;
233
234 /*
235 * Primary status don't have the top bit set, so can't be confused with
236 * Linux negative error codes, so return the status word whole.
237 */
238 return s1;
239}
240EXPORT_SYMBOL_GPL(sbefifo_parse_status);
241
242static int sbefifo_regr(struct sbefifo *sbefifo, int reg, u32 *word)
243{
244 __be32 raw_word;
245 int rc;
246
247 rc = fsi_device_read(sbefifo->fsi_dev, reg, &raw_word,
248 sizeof(raw_word));
249 if (rc)
250 return rc;
251
252 *word = be32_to_cpu(raw_word);
253
254 return 0;
255}
256
257static int sbefifo_regw(struct sbefifo *sbefifo, int reg, u32 word)
258{
259 __be32 raw_word = cpu_to_be32(word);
260
261 return fsi_device_write(sbefifo->fsi_dev, reg, &raw_word,
262 sizeof(raw_word));
263}
264
265static int sbefifo_check_sbe_state(struct sbefifo *sbefifo)
266{
267 __be32 raw_word;
268 u32 sbm;
269 int rc;
270
271 rc = fsi_slave_read(sbefifo->fsi_dev->slave, CFAM_GP_MBOX_SBM_ADDR,
272 &raw_word, sizeof(raw_word));
273 if (rc)
274 return rc;
275 sbm = be32_to_cpu(raw_word);
276
277 /* SBE booted at all ? */
278 if (!(sbm & CFAM_SBM_SBE_BOOTED))
279 return -ESHUTDOWN;
280
281 /* Check its state */
282 switch ((sbm & CFAM_SBM_SBE_STATE_MASK) >> CFAM_SBM_SBE_STATE_SHIFT) {
283 case SBE_STATE_UNKNOWN:
284 return -ESHUTDOWN;
285 case SBE_STATE_IPLING:
286 case SBE_STATE_ISTEP:
287 case SBE_STATE_MPIPL:
288 case SBE_STATE_DMT:
289 return -EBUSY;
290 case SBE_STATE_RUNTIME:
291 case SBE_STATE_DUMP: /* Not sure about that one */
292 break;
293 case SBE_STATE_FAILURE:
294 case SBE_STATE_QUIESCE:
295 return -ESHUTDOWN;
296 }
297
298 /* Is there async FFDC available ? Remember it */
299 if (sbm & CFAM_SBM_SBE_ASYNC_FFDC)
300 sbefifo->async_ffdc = true;
301
302 return 0;
303}
304
305/* Don't flip endianness of data to/from FIFO, just pass through. */
306static int sbefifo_down_read(struct sbefifo *sbefifo, __be32 *word)
307{
308 return fsi_device_read(sbefifo->fsi_dev, SBEFIFO_DOWN, word,
309 sizeof(*word));
310}
311
312static int sbefifo_up_write(struct sbefifo *sbefifo, __be32 word)
313{
314 return fsi_device_write(sbefifo->fsi_dev, SBEFIFO_UP, &word,
315 sizeof(word));
316}
317
318static int sbefifo_request_reset(struct sbefifo *sbefifo)
319{
320 struct device *dev = &sbefifo->fsi_dev->dev;
321 u32 status, timeout;
322 int rc;
323
324 dev_dbg(dev, "Requesting FIFO reset\n");
325
326 /* Mark broken first, will be cleared if reset succeeds */
327 sbefifo->broken = true;
328
329 /* Send reset request */
330 rc = sbefifo_regw(sbefifo, SBEFIFO_UP | SBEFIFO_REQ_RESET, 1);
331 if (rc) {
332 dev_err(dev, "Sending reset request failed, rc=%d\n", rc);
333 return rc;
334 }
335
336 /* Wait for it to complete */
337 for (timeout = 0; timeout < SBEFIFO_RESET_TIMEOUT; timeout++) {
338 rc = sbefifo_regr(sbefifo, SBEFIFO_UP | SBEFIFO_STS, &status);
339 if (rc) {
340 dev_err(dev, "Failed to read UP fifo status during reset"
341 " , rc=%d\n", rc);
342 return rc;
343 }
344
345 if (!(status & SBEFIFO_STS_RESET_REQ)) {
346 dev_dbg(dev, "FIFO reset done\n");
347 sbefifo->broken = false;
348 return 0;
349 }
350
351 msleep(1);
352 }
353 dev_err(dev, "FIFO reset timed out\n");
354
355 return -ETIMEDOUT;
356}
357
358static int sbefifo_cleanup_hw(struct sbefifo *sbefifo)
359{
360 struct device *dev = &sbefifo->fsi_dev->dev;
361 u32 up_status, down_status;
362 bool need_reset = false;
363 int rc;
364
365 rc = sbefifo_check_sbe_state(sbefifo);
366 if (rc) {
367 dev_dbg(dev, "SBE state=%d\n", rc);
368 return rc;
369 }
370
371 /* If broken, we don't need to look at status, go straight to reset */
372 if (sbefifo->broken)
373 goto do_reset;
374
375 rc = sbefifo_regr(sbefifo, SBEFIFO_UP | SBEFIFO_STS, &up_status);
376 if (rc) {
377 dev_err(dev, "Cleanup: Reading UP status failed, rc=%d\n", rc);
378
379 /* Will try reset again on next attempt at using it */
380 sbefifo->broken = true;
381 return rc;
382 }
383
384 rc = sbefifo_regr(sbefifo, SBEFIFO_DOWN | SBEFIFO_STS, &down_status);
385 if (rc) {
386 dev_err(dev, "Cleanup: Reading DOWN status failed, rc=%d\n", rc);
387
388 /* Will try reset again on next attempt at using it */
389 sbefifo->broken = true;
390 return rc;
391 }
392
393 /* The FIFO already contains a reset request from the SBE ? */
394 if (down_status & SBEFIFO_STS_RESET_REQ) {
395 dev_info(dev, "Cleanup: FIFO reset request set, resetting\n");
396 rc = sbefifo_regw(sbefifo, SBEFIFO_UP, SBEFIFO_PERFORM_RESET);
397 if (rc) {
398 sbefifo->broken = true;
399 dev_err(dev, "Cleanup: Reset reg write failed, rc=%d\n", rc);
400 return rc;
401 }
402 sbefifo->broken = false;
403 return 0;
404 }
405
406 /* Parity error on either FIFO ? */
407 if ((up_status | down_status) & SBEFIFO_STS_PARITY_ERR)
408 need_reset = true;
409
410 /* Either FIFO not empty ? */
411 if (!((up_status & down_status) & SBEFIFO_STS_EMPTY))
412 need_reset = true;
413
414 if (!need_reset)
415 return 0;
416
417 dev_info(dev, "Cleanup: FIFO not clean (up=0x%08x down=0x%08x)\n",
418 up_status, down_status);
419
420 do_reset:
421
422 /* Mark broken, will be cleared if/when reset succeeds */
423 return sbefifo_request_reset(sbefifo);
424}
425
426static int sbefifo_wait(struct sbefifo *sbefifo, bool up,
427 u32 *status, unsigned long timeout)
428{
429 struct device *dev = &sbefifo->fsi_dev->dev;
430 unsigned long end_time;
431 bool ready = false;
432 u32 addr, sts = 0;
433 int rc;
434
435 dev_vdbg(dev, "Wait on %s fifo...\n", up ? "up" : "down");
436
437 addr = (up ? SBEFIFO_UP : SBEFIFO_DOWN) | SBEFIFO_STS;
438
439 end_time = jiffies + timeout;
440 while (!time_after(jiffies, end_time)) {
441 cond_resched();
442 rc = sbefifo_regr(sbefifo, addr, &sts);
443 if (rc < 0) {
444 dev_err(dev, "FSI error %d reading status register\n", rc);
445 return rc;
446 }
447 if (!up && sbefifo_parity_err(sts)) {
448 dev_err(dev, "Parity error in DOWN FIFO\n");
449 return -ENXIO;
450 }
451 ready = !(up ? sbefifo_full(sts) : sbefifo_empty(sts));
452 if (ready)
453 break;
454 }
455 if (!ready) {
456 dev_err(dev, "%s FIFO Timeout ! status=%08x\n", up ? "UP" : "DOWN", sts);
457 return -ETIMEDOUT;
458 }
459 dev_vdbg(dev, "End of wait status: %08x\n", sts);
460
461 *status = sts;
462
463 return 0;
464}
465
466static int sbefifo_send_command(struct sbefifo *sbefifo,
467 const __be32 *command, size_t cmd_len)
468{
469 struct device *dev = &sbefifo->fsi_dev->dev;
470 size_t len, chunk, vacant = 0, remaining = cmd_len;
471 unsigned long timeout;
472 u32 status;
473 int rc;
474
475 dev_vdbg(dev, "sending command (%zd words, cmd=%04x)\n",
476 cmd_len, be32_to_cpu(command[1]));
477
478 /* As long as there's something to send */
479 timeout = msecs_to_jiffies(SBEFIFO_TIMEOUT_START_CMD);
480 while (remaining) {
481 /* Wait for room in the FIFO */
482 rc = sbefifo_wait(sbefifo, true, &status, timeout);
483 if (rc < 0)
484 return rc;
485 timeout = msecs_to_jiffies(SBEFIFO_TIMEOUT_IN_CMD);
486
487 vacant = sbefifo_vacant(status);
488 len = chunk = min(vacant, remaining);
489
490 dev_vdbg(dev, " status=%08x vacant=%zd chunk=%zd\n",
491 status, vacant, chunk);
492
493 /* Write as much as we can */
494 while (len--) {
495 rc = sbefifo_up_write(sbefifo, *(command++));
496 if (rc) {
497 dev_err(dev, "FSI error %d writing UP FIFO\n", rc);
498 return rc;
499 }
500 }
501 remaining -= chunk;
502 vacant -= chunk;
503 }
504
505 /* If there's no room left, wait for some to write EOT */
506 if (!vacant) {
507 rc = sbefifo_wait(sbefifo, true, &status, timeout);
508 if (rc)
509 return rc;
510 }
511
512 /* Send an EOT */
513 rc = sbefifo_regw(sbefifo, SBEFIFO_UP | SBEFIFO_EOT_RAISE, 0);
514 if (rc)
515 dev_err(dev, "FSI error %d writing EOT\n", rc);
516 return rc;
517}
518
519static int sbefifo_read_response(struct sbefifo *sbefifo, struct iov_iter *response)
520{
521 struct device *dev = &sbefifo->fsi_dev->dev;
522 u32 data, status, eot_set;
523 unsigned long timeout;
524 bool overflow = false;
525 size_t len;
526 int rc;
527
528 dev_vdbg(dev, "reading response, buflen = %zd\n", iov_iter_count(response));
529
530 timeout = msecs_to_jiffies(SBEFIFO_TIMEOUT_START_RSP);
531 for (;;) {
532 /* Grab FIFO status (this will handle parity errors) */
533 rc = sbefifo_wait(sbefifo, false, &status, timeout);
534 if (rc < 0)
535 return rc;
536 timeout = msecs_to_jiffies(SBEFIFO_TIMEOUT_IN_RSP);
537
538 /* Decode status */
539 len = sbefifo_populated(status);
540 eot_set = sbefifo_eot_set(status);
541
542 dev_vdbg(dev, " chunk size %zd eot_set=0x%x\n", len, eot_set);
543
544 /* Go through the chunk */
545 while(len--) {
546 /* Read the data */
547 rc = sbefifo_down_read(sbefifo, &data);
548 if (rc < 0)
549 return rc;
550
551 /* Was it an EOT ? */
552 if (eot_set & 0x80) {
553 /*
554 * There should be nothing else in the FIFO,
555 * if there is, mark broken, this will force
556 * a reset on next use, but don't fail the
557 * command.
558 */
559 if (len) {
560 dev_warn(dev, "FIFO read hit"
561 " EOT with still %zd data\n",
562 len);
563 sbefifo->broken = true;
564 }
565
566 /* We are done */
567 rc = sbefifo_regw(sbefifo,
568 SBEFIFO_DOWN | SBEFIFO_EOT_ACK, 0);
569
570 /*
571 * If that write fail, still complete the request but mark
572 * the fifo as broken for subsequent reset (not much else
573 * we can do here).
574 */
575 if (rc) {
576 dev_err(dev, "FSI error %d ack'ing EOT\n", rc);
577 sbefifo->broken = true;
578 }
579
580 /* Tell whether we overflowed */
581 return overflow ? -EOVERFLOW : 0;
582 }
583
584 /* Store it if there is room */
585 if (iov_iter_count(response) >= sizeof(__be32)) {
586 if (copy_to_iter(&data, sizeof(__be32), response) < sizeof(__be32))
587 return -EFAULT;
588 } else {
589 dev_vdbg(dev, "Response overflowed !\n");
590
591 overflow = true;
592 }
593
594 /* Next EOT bit */
595 eot_set <<= 1;
596 }
597 }
598 /* Shouldn't happen */
599 return -EIO;
600}
601
602static int sbefifo_do_command(struct sbefifo *sbefifo,
603 const __be32 *command, size_t cmd_len,
604 struct iov_iter *response)
605{
606 /* Try sending the command */
607 int rc = sbefifo_send_command(sbefifo, command, cmd_len);
608 if (rc)
609 return rc;
610
611 /* Now, get the response */
612 return sbefifo_read_response(sbefifo, response);
613}
614
615static void sbefifo_collect_async_ffdc(struct sbefifo *sbefifo)
616{
617 struct device *dev = &sbefifo->fsi_dev->dev;
618 struct iov_iter ffdc_iter;
619 struct kvec ffdc_iov;
620 __be32 *ffdc;
621 size_t ffdc_sz;
622 u32 cmd[2];
623 int rc;
624
625 sbefifo->async_ffdc = false;
626 ffdc = vmalloc(SBEFIFO_MAX_FFDC_SIZE);
627 if (!ffdc) {
628 dev_err(dev, "Failed to allocate SBE FFDC buffer\n");
629 return;
630 }
631 ffdc_iov.iov_base = ffdc;
632 ffdc_iov.iov_len = SBEFIFO_MAX_FFDC_SIZE;;
633 iov_iter_kvec(&ffdc_iter, WRITE | ITER_KVEC, &ffdc_iov, 1, SBEFIFO_MAX_FFDC_SIZE);
634 cmd[0] = cpu_to_be32(2);
635 cmd[1] = cpu_to_be32(SBEFIFO_CMD_GET_SBE_FFDC);
636 rc = sbefifo_do_command(sbefifo, cmd, 2, &ffdc_iter);
637 if (rc != 0) {
638 dev_err(dev, "Error %d retrieving SBE FFDC\n", rc);
639 goto bail;
640 }
641 ffdc_sz = SBEFIFO_MAX_FFDC_SIZE - iov_iter_count(&ffdc_iter);
642 ffdc_sz /= sizeof(__be32);
643 rc = sbefifo_parse_status(dev, SBEFIFO_CMD_GET_SBE_FFDC, ffdc,
644 ffdc_sz, &ffdc_sz);
645 if (rc != 0) {
646 dev_err(dev, "Error %d decoding SBE FFDC\n", rc);
647 goto bail;
648 }
649 if (ffdc_sz > 0)
650 sbefifo_dump_ffdc(dev, ffdc, ffdc_sz, true);
651 bail:
652 vfree(ffdc);
653
654}
655
656static int __sbefifo_submit(struct sbefifo *sbefifo,
657 const __be32 *command, size_t cmd_len,
658 struct iov_iter *response)
659{
660 struct device *dev = &sbefifo->fsi_dev->dev;
661 int rc;
662
663 if (cmd_len < 2 || be32_to_cpu(command[0]) != cmd_len) {
664 dev_vdbg(dev, "Invalid command len %zd (header: %d)\n",
665 cmd_len, be32_to_cpu(command[0]));
666 return -EINVAL;
667 }
668
669 /* First ensure the HW is in a clean state */
670 rc = sbefifo_cleanup_hw(sbefifo);
671 if (rc)
672 return rc;
673
674 /* Look for async FFDC first if any */
675 if (sbefifo->async_ffdc)
676 sbefifo_collect_async_ffdc(sbefifo);
677
678 rc = sbefifo_do_command(sbefifo, command, cmd_len, response);
679 if (rc != 0 && rc != -EOVERFLOW)
680 goto fail;
681 return rc;
682 fail:
683 /*
684 * On failure, attempt a reset. Ignore the result, it will mark
685 * the fifo broken if the reset fails
686 */
687 sbefifo_request_reset(sbefifo);
688
689 /* Return original error */
690 return rc;
691}
692
693/**
694 * sbefifo_submit() - Submit and SBE fifo command and receive response
695 * @dev: The sbefifo device
696 * @command: The raw command data
697 * @cmd_len: The command size (in 32-bit words)
698 * @response: The output response buffer
699 * @resp_len: In: Response buffer size, Out: Response size
700 *
701 * This will perform the entire operation. If the reponse buffer
702 * overflows, returns -EOVERFLOW
703 */
704int sbefifo_submit(struct device *dev, const __be32 *command, size_t cmd_len,
705 __be32 *response, size_t *resp_len)
706{
707 struct sbefifo *sbefifo = dev_get_drvdata(dev);
708 struct iov_iter resp_iter;
709 struct kvec resp_iov;
710 size_t rbytes;
711 int rc;
712
713 if (!dev || !sbefifo)
714 return -ENODEV;
715 if (WARN_ON_ONCE(sbefifo->magic != SBEFIFO_MAGIC))
716 return -ENODEV;
717 if (!resp_len || !command || !response || cmd_len > SBEFIFO_MAX_CMD_LEN)
718 return -EINVAL;
719
720 /* Prepare iov iterator */
721 rbytes = (*resp_len) * sizeof(__be32);
722 resp_iov.iov_base = response;
723 resp_iov.iov_len = rbytes;
724 iov_iter_kvec(&resp_iter, WRITE | ITER_KVEC, &resp_iov, 1, rbytes);
725
726 /* Perform the command */
727 mutex_lock(&sbefifo->lock);
728 rc = __sbefifo_submit(sbefifo, command, cmd_len, &resp_iter);
729 mutex_unlock(&sbefifo->lock);
730
731 /* Extract the response length */
732 rbytes -= iov_iter_count(&resp_iter);
733 *resp_len = rbytes / sizeof(__be32);
734
735 return rc;
736}
737EXPORT_SYMBOL_GPL(sbefifo_submit);
738
739/*
740 * Char device interface
741 */
742static int sbefifo_user_open(struct inode *inode, struct file *file)
743{
744 struct sbefifo *sbefifo = container_of(file->private_data,
745 struct sbefifo, mdev);
746 struct sbefifo_user *user;
747
748 user = kzalloc(sizeof(struct sbefifo_user), GFP_KERNEL);
749 if (!user)
750 return -ENOMEM;
751
752 file->private_data = user;
753 user->sbefifo = sbefifo;
754 user->pending_cmd = (void *)__get_free_page(GFP_KERNEL);
755 if (!user->pending_cmd) {
756 kfree(user);
757 return -ENOMEM;
758 }
759 mutex_init(&user->file_lock);
760
761 return 0;
762}
763
764static ssize_t sbefifo_user_read(struct file *file, char __user *buf,
765 size_t len, loff_t *offset)
766{
767 struct sbefifo_user *user = file->private_data;
768 struct sbefifo *sbefifo;
769 struct iov_iter resp_iter;
770 struct iovec resp_iov;
771 size_t cmd_len;
772 int rc;
773
774 if (!user)
775 return -EINVAL;
776 sbefifo = user->sbefifo;
777 if (len & 3)
778 return -EINVAL;
779
780 mutex_lock(&user->file_lock);
781
782 /* Cronus relies on -EAGAIN after a short read */
783 if (user->pending_len == 0) {
784 rc = -EAGAIN;
785 goto bail;
786 }
787 if (user->pending_len < 8) {
788 rc = -EINVAL;
789 goto bail;
790 }
791 cmd_len = user->pending_len >> 2;
792
793 /* Prepare iov iterator */
794 resp_iov.iov_base = buf;
795 resp_iov.iov_len = len;
796 iov_iter_init(&resp_iter, WRITE, &resp_iov, 1, len);
797
798 /* Perform the command */
799 mutex_lock(&sbefifo->lock);
800 rc = __sbefifo_submit(sbefifo, user->pending_cmd, cmd_len, &resp_iter);
801 mutex_unlock(&sbefifo->lock);
802 if (rc < 0)
803 goto bail;
804
805 /* Extract the response length */
806 rc = len - iov_iter_count(&resp_iter);
807 bail:
808 user->pending_len = 0;
809 mutex_unlock(&user->file_lock);
810 return rc;
811}
812
813static ssize_t sbefifo_user_write(struct file *file, const char __user *buf,
814 size_t len, loff_t *offset)
815{
816 struct sbefifo_user *user = file->private_data;
817 struct sbefifo *sbefifo;
818 int rc = len;
819
820 if (!user)
821 return -EINVAL;
822 sbefifo = user->sbefifo;
823 if (len > SBEFIFO_MAX_CMD_LEN)
824 return -EINVAL;
825 if (len & 3)
826 return -EINVAL;
827
828 mutex_lock(&user->file_lock);
829
830 /* Copy the command into the staging buffer */
831 if (copy_from_user(user->pending_cmd, buf, len)) {
832 rc = -EFAULT;
833 goto bail;
834 }
835
836 /* Check for the magic reset command */
837 if (len == 4 && be32_to_cpu(*(__be32 *)user->pending_cmd) ==
838 SBEFIFO_RESET_MAGIC) {
839
840 /* Clear out any pending command */
841 user->pending_len = 0;
842
843 /* Trigger reset request */
844 mutex_lock(&sbefifo->lock);
845 rc = sbefifo_request_reset(user->sbefifo);
846 mutex_unlock(&sbefifo->lock);
847 if (rc == 0)
848 rc = 4;
849 goto bail;
850 }
851
852 /* Update the staging buffer size */
853 user->pending_len = len;
854 bail:
855 mutex_unlock(&user->file_lock);
856
857 /* And that's it, we'll issue the command on a read */
858 return rc;
859}
860
861static int sbefifo_user_release(struct inode *inode, struct file *file)
862{
863 struct sbefifo_user *user = file->private_data;
864
865 if (!user)
866 return -EINVAL;
867
868 free_page((unsigned long)user->pending_cmd);
869 kfree(user);
870
871 return 0;
872}
873
874static const struct file_operations sbefifo_fops = {
875 .owner = THIS_MODULE,
876 .open = sbefifo_user_open,
877 .read = sbefifo_user_read,
878 .write = sbefifo_user_write,
879 .release = sbefifo_user_release,
880};
881
882/*
883 * Probe/remove
884 */
885
886static int sbefifo_probe(struct device *dev)
887{
888 struct fsi_device *fsi_dev = to_fsi_dev(dev);
889 struct sbefifo *sbefifo;
890 struct device_node *np;
891 struct platform_device *child;
892 char child_name[32];
893 int rc, child_idx = 0;
894
895 dev_dbg(dev, "Found sbefifo device\n");
896
897 sbefifo = devm_kzalloc(dev, sizeof(*sbefifo), GFP_KERNEL);
898 if (!sbefifo)
899 return -ENOMEM;
900 sbefifo->magic = SBEFIFO_MAGIC;
901 sbefifo->fsi_dev = fsi_dev;
902 mutex_init(&sbefifo->lock);
903
904 /*
905 * Try cleaning up the FIFO. If this fails, we still register the
906 * driver and will try cleaning things up again on the next access.
907 */
908 rc = sbefifo_cleanup_hw(sbefifo);
909 if (rc && rc != -ESHUTDOWN)
910 dev_err(dev, "Initial HW cleanup failed, will retry later\n");
911
912 sbefifo->idx = ida_simple_get(&sbefifo_ida, 1, INT_MAX, GFP_KERNEL);
913 snprintf(sbefifo->name, sizeof(sbefifo->name), "sbefifo%d",
914 sbefifo->idx);
915
916 dev_set_drvdata(dev, sbefifo);
917
918 /* Create misc chardev for userspace access */
919 sbefifo->mdev.minor = MISC_DYNAMIC_MINOR;
920 sbefifo->mdev.fops = &sbefifo_fops;
921 sbefifo->mdev.name = sbefifo->name;
922 sbefifo->mdev.parent = dev;
923 rc = misc_register(&sbefifo->mdev);
924 if (rc) {
925 dev_err(dev, "Failed to register miscdevice: %d\n", rc);
926 ida_simple_remove(&sbefifo_ida, sbefifo->idx);
927 return rc;
928 }
929
930 /* Create platform devs for dts child nodes (occ, etc) */
931 for_each_available_child_of_node(dev->of_node, np) {
932 snprintf(child_name, sizeof(child_name), "%s-dev%d",
933 sbefifo->name, child_idx++);
934 child = of_platform_device_create(np, child_name, dev);
935 if (!child)
936 dev_warn(dev, "failed to create child %s dev\n",
937 child_name);
938 }
939
940 return 0;
941}
942
943static int sbefifo_unregister_child(struct device *dev, void *data)
944{
945 struct platform_device *child = to_platform_device(dev);
946
947 of_device_unregister(child);
948 if (dev->of_node)
949 of_node_clear_flag(dev->of_node, OF_POPULATED);
950
951 return 0;
952}
953
954static int sbefifo_remove(struct device *dev)
955{
956 struct sbefifo *sbefifo = dev_get_drvdata(dev);
957
958 dev_dbg(dev, "Removing sbefifo device...\n");
959
960 misc_deregister(&sbefifo->mdev);
961 device_for_each_child(dev, NULL, sbefifo_unregister_child);
962
963 ida_simple_remove(&sbefifo_ida, sbefifo->idx);
964
965 return 0;
966}
967
968static struct fsi_device_id sbefifo_ids[] = {
969 {
970 .engine_type = FSI_ENGID_SBE,
971 .version = FSI_VERSION_ANY,
972 },
973 { 0 }
974};
975
976static struct fsi_driver sbefifo_drv = {
977 .id_table = sbefifo_ids,
978 .drv = {
979 .name = DEVICE_NAME,
980 .bus = &fsi_bus_type,
981 .probe = sbefifo_probe,
982 .remove = sbefifo_remove,
983 }
984};
985
986static int sbefifo_init(void)
987{
988 return fsi_driver_register(&sbefifo_drv);
989}
990
991static void sbefifo_exit(void)
992{
993 fsi_driver_unregister(&sbefifo_drv);
994
995 ida_destroy(&sbefifo_ida);
996}
997
998module_init(sbefifo_init);
999module_exit(sbefifo_exit);
1000MODULE_LICENSE("GPL");
1001MODULE_AUTHOR("Brad Bishop <bradleyb@fuzziesquirrel.com>");
1002MODULE_AUTHOR("Eddie James <eajames@linux.vnet.ibm.com>");
1003MODULE_AUTHOR("Andrew Jeffery <andrew@aj.id.au>");
1004MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
1005MODULE_DESCRIPTION("Linux device interface to the POWER Self Boot Engine");
diff --git a/include/linux/fsi-sbefifo.h b/include/linux/fsi-sbefifo.h
new file mode 100644
index 000000000000..13f9ebeaa25e
--- /dev/null
+++ b/include/linux/fsi-sbefifo.h
@@ -0,0 +1,33 @@
1/*
2 * SBEFIFO FSI Client device driver
3 *
4 * Copyright (C) IBM Corporation 2017
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERGCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16#ifndef LINUX_FSI_SBEFIFO_H
17#define LINUX_FSI_SBEFIFO_H
18
19#define SBEFIFO_CMD_PUT_OCC_SRAM 0xa404
20#define SBEFIFO_CMD_GET_OCC_SRAM 0xa403
21#define SBEFIFO_CMD_GET_SBE_FFDC 0xa801
22
23#define SBEFIFO_MAX_FFDC_SIZE 0x2000
24
25struct device;
26
27int sbefifo_submit(struct device *dev, const __be32 *command, size_t cmd_len,
28 __be32 *response, size_t *resp_len);
29
30int sbefifo_parse_status(struct device *dev, u16 cmd, __be32 *response,
31 size_t resp_len, size_t *data_len);
32
33#endif /* LINUX_FSI_SBEFIFO_H */