// SPDX-License-Identifier: GPL-2.0
/*
* core function to access sclp interface
*
* Copyright IBM Corp. 1999, 2009
*
* Author(s): Martin Peschke <mpeschke@de.ibm.com>
* Martin Schwidefsky <schwidefsky@de.ibm.com>
*/
#include <linux/kernel_stat.h>
#include <linux/module.h>
#include <linux/err.h>
#include <linux/panic_notifier.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/timer.h>
#include <linux/reboot.h>
#include <linux/jiffies.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <asm/types.h>
#include <asm/irq.h>
#include <asm/debug.h>
#include "sclp.h"
#define SCLP_HEADER "sclp: "
struct sclp_trace_entry {
char id[4] __nonstring;
u32 a;
u64 b;
};
#define SCLP_TRACE_ENTRY_SIZE sizeof(struct sclp_trace_entry)
#define SCLP_TRACE_MAX_SIZE 128
#define SCLP_TRACE_EVENT_MAX_SIZE 64
/* Debug trace area intended for all entries in abbreviated form. */
DEFINE_STATIC_DEBUG_INFO(sclp_debug, "sclp", 8, 1, SCLP_TRACE_ENTRY_SIZE,
&debug_hex_ascii_view);
/* Error trace area intended for full entries relating to failed requests. */
DEFINE_STATIC_DEBUG_INFO(sclp_debug_err, "sclp_err", 4, 1,
SCLP_TRACE_ENTRY_SIZE, &debug_hex_ascii_view);
/* Lock to protect internal data consistency. */
static DEFINE_SPINLOCK(sclp_lock);
/* Mask of events that we can send to the sclp interface. */
static sccb_mask_t sclp_receive_mask;
/* Mask of events that we can receive from the sclp interface. */
static sccb_mask_t sclp_send_mask;
/* List of registered event listeners and senders. */
static LIST_HEAD(sclp_reg_list);
/* List of queued requests. */
static LIST_HEAD(sclp_req_queue);
/* Data for read and init requests. */
static struct sclp_req sclp_read_req;
static struct sclp_req sclp_init_req;
static void *sclp_read_sccb;
static struct init_sccb *sclp_init_sccb;
/* Number of console pages to allocate, used by sclp_con.c and sclp_vt220.c */
int sclp_console_pages = SCLP_CONSOLE_PAGES;
/* Flag to indicate if buffer pages are dropped on buffer full condition */
bool sclp_console_drop = true;
/* Number of times the console dropped buffer pages */
unsigned long sclp_console_full;
/* The currently active SCLP command word. */
static sclp_cmdw_t active_cmd;
static inline void sclp_trace(int prio, char *id, u32 a, u64 b, bool err)
{
struct sclp_trace_entry e;
memset(&e, 0, sizeof(e));
strtomem(e.id, id);
e.a = a;
e.b = b;
debug_event(&sclp_debug, prio, &e, sizeof(e));
if (err)
debug_event(&sclp_debug_err, 0, &e, sizeof(e));
}
static inline int no_zeroes_len(void *data, int len)
{
char *d = data;
/* Minimize trace area usage by not tracing trailing zeroes. */
while (len > SCLP_TRACE_ENTRY_SIZE && d[len - 1] == 0)
len--;
return len;
}
static inline void sclp_trace_bin(int prio, void *d, int len, int errlen)
{
debug_event(&sclp_debug, prio, d,