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