mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 03:27:44 -04:00
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
Pull s390 updates from Martin Schwidefsky:
"Among the traditional bug fixes and cleanups are some improvements:
- A tool to generated the facility lists, generating the bit fields
by hand has been a source of bugs in the past
- The spinlock loop is reordered to avoid bursts of hypervisor calls
- Add support for the open-for-business interface to the service
element
- The get_cpu call is added to the vdso
- A set of tracepoints is defined for the common I/O layer
- The deprecated sclp_cpi module is removed
- Update default configuration"
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: (56 commits)
s390/sclp: fix possible control register corruption
s390: fix normalization bug in exception table sorting
s390/configs: update default configurations
s390/vdso: optimize getcpu system call
s390: drop smp_mb in vdso_init
s390: rename struct _lowcore to struct lowcore
s390/mem_detect: use unsigned longs
s390/ptrace: get rid of long longs in psw_bits
s390/sysinfo: add missing SYSIB 1.2.2 multithreading fields
s390: get rid of CONFIG_SCHED_MC and CONFIG_SCHED_BOOK
s390/Kconfig: remove pointless 64 bit dependencies
s390/dasd: fix failfast for disconnected devices
s390/con3270: testing return kzalloc retval
s390/hmcdrv: constify hmcdrv_ftp_ops structs
s390/cio: add NULL test
s390/cio: Change I/O instructions from inline to normal functions
s390/cio: Introduce common I/O layer tracepoints
s390/cio: Consolidate inline assemblies and related data definitions
s390/cio: Fix incorrect xsch opcode specification
s390/cio: Remove unused inline assemblies
...
This commit is contained in:
commit
cbd88cd4c0
93 changed files with 1948 additions and 1567 deletions
|
|
@ -2556,8 +2556,12 @@ static void __dasd_process_request_queue(struct dasd_block *block)
|
|||
return;
|
||||
}
|
||||
|
||||
/* if device ist stopped do not fetch new requests */
|
||||
if (basedev->stopped)
|
||||
/*
|
||||
* if device is stopped do not fetch new requests
|
||||
* except failfast is active which will let requests fail
|
||||
* immediately in __dasd_block_start_head()
|
||||
*/
|
||||
if (basedev->stopped && !(basedev->features & DASD_FEATURE_FAILFAST))
|
||||
return;
|
||||
|
||||
/* Now we try to fetch requests from the request queue */
|
||||
|
|
|
|||
|
|
@ -78,19 +78,6 @@ config SCLP_VT220_CONSOLE
|
|||
Include support for using an IBM SCLP VT220-compatible terminal as a
|
||||
Linux system console.
|
||||
|
||||
config SCLP_CPI
|
||||
def_tristate m
|
||||
prompt "Control-Program Identification"
|
||||
depends on S390
|
||||
help
|
||||
This option enables the hardware console interface for system
|
||||
identification. This is commonly used for workload management and
|
||||
gives you a nice name for the system on the service element.
|
||||
Please select this option as a module since built-in operation is
|
||||
completely untested.
|
||||
You should only select this option if you know what you are doing,
|
||||
need this feature and intend to run your kernel in LPAR.
|
||||
|
||||
config SCLP_ASYNC
|
||||
def_tristate m
|
||||
prompt "Support for Call Home via Asynchronous SCLP Records"
|
||||
|
|
@ -125,6 +112,14 @@ config HMC_DRV
|
|||
transfer cache size from it's default value 0.5MB to N bytes. If N
|
||||
is zero, then no caching is performed.
|
||||
|
||||
config SCLP_OFB
|
||||
def_bool n
|
||||
prompt "Support for Open-for-Business SCLP Event"
|
||||
depends on S390
|
||||
help
|
||||
This option enables the Open-for-Business interface to the s390
|
||||
Service Element.
|
||||
|
||||
config S390_TAPE
|
||||
def_tristate m
|
||||
prompt "S/390 tape device support"
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ obj-$(CONFIG_TN3215) += con3215.o
|
|||
obj-$(CONFIG_SCLP_TTY) += sclp_tty.o
|
||||
obj-$(CONFIG_SCLP_CONSOLE) += sclp_con.o
|
||||
obj-$(CONFIG_SCLP_VT220_TTY) += sclp_vt220.o
|
||||
obj-$(CONFIG_SCLP_CPI) += sclp_cpi.o
|
||||
obj-$(CONFIG_SCLP_ASYNC) += sclp_async.o
|
||||
|
||||
obj-$(CONFIG_VMLOGRDR) += vmlogrdr.o
|
||||
|
|
@ -30,9 +29,7 @@ obj-$(CONFIG_S390_TAPE_3590) += tape_3590.o
|
|||
obj-$(CONFIG_MONREADER) += monreader.o
|
||||
obj-$(CONFIG_MONWRITER) += monwriter.o
|
||||
obj-$(CONFIG_S390_VMUR) += vmur.o
|
||||
|
||||
zcore_mod-objs := sclp_sdias.o zcore.o
|
||||
obj-$(CONFIG_CRASH_DUMP) += zcore_mod.o
|
||||
obj-$(CONFIG_CRASH_DUMP) += sclp_sdias.o zcore.o
|
||||
|
||||
hmcdrv-objs := hmcdrv_mod.o hmcdrv_dev.o hmcdrv_ftp.o hmcdrv_cache.o diag_ftp.o sclp_ftp.o
|
||||
obj-$(CONFIG_HMC_DRV) += hmcdrv.o
|
||||
|
|
|
|||
|
|
@ -922,6 +922,8 @@ static int __init con3215_init(void)
|
|||
spin_lock_init(&raw3215_freelist_lock);
|
||||
for (i = 0; i < NR_3215_REQ; i++) {
|
||||
req = kzalloc(sizeof(struct raw3215_req), GFP_KERNEL | GFP_DMA);
|
||||
if (!req)
|
||||
return -ENOMEM;
|
||||
req->next = raw3215_freelist;
|
||||
raw3215_freelist = req;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -606,6 +606,8 @@ con3270_init(void)
|
|||
return PTR_ERR(rp);
|
||||
|
||||
condev = kzalloc(sizeof(struct con3270), GFP_KERNEL | GFP_DMA);
|
||||
if (!condev)
|
||||
return -ENOMEM;
|
||||
condev->view.dev = rp;
|
||||
|
||||
condev->read = raw3270_request_alloc(0);
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ struct hmcdrv_ftp_ops {
|
|||
static enum hmcdrv_ftp_cmdid hmcdrv_ftp_cmd_getid(const char *cmd, int len);
|
||||
static int hmcdrv_ftp_parse(char *cmd, struct hmcdrv_ftp_cmdspec *ftp);
|
||||
|
||||
static struct hmcdrv_ftp_ops *hmcdrv_ftp_funcs; /* current operations */
|
||||
static const struct hmcdrv_ftp_ops *hmcdrv_ftp_funcs; /* current operations */
|
||||
static DEFINE_MUTEX(hmcdrv_ftp_mutex); /* mutex for hmcdrv_ftp_funcs */
|
||||
static unsigned hmcdrv_ftp_refcnt; /* start/shutdown reference counter */
|
||||
|
||||
|
|
@ -290,13 +290,13 @@ ssize_t hmcdrv_ftp_cmd(char __kernel *cmd, loff_t offset,
|
|||
*/
|
||||
int hmcdrv_ftp_startup(void)
|
||||
{
|
||||
static struct hmcdrv_ftp_ops hmcdrv_ftp_zvm = {
|
||||
static const struct hmcdrv_ftp_ops hmcdrv_ftp_zvm = {
|
||||
.startup = diag_ftp_startup,
|
||||
.shutdown = diag_ftp_shutdown,
|
||||
.transfer = diag_ftp_cmd
|
||||
};
|
||||
|
||||
static struct hmcdrv_ftp_ops hmcdrv_ftp_lpar = {
|
||||
static const struct hmcdrv_ftp_ops hmcdrv_ftp_lpar = {
|
||||
.startup = sclp_ftp_startup,
|
||||
.shutdown = sclp_ftp_shutdown,
|
||||
.transfer = sclp_ftp_cmd
|
||||
|
|
|
|||
|
|
@ -579,9 +579,8 @@ sclp_sync_wait(void)
|
|||
old_tick = local_tick_disable();
|
||||
trace_hardirqs_on();
|
||||
__ctl_store(cr0, 0, 0);
|
||||
cr0_sync = cr0;
|
||||
cr0_sync &= 0xffff00a0;
|
||||
cr0_sync |= 0x00000200;
|
||||
cr0_sync = cr0 & ~CR0_IRQ_SUBCLASS_MASK;
|
||||
cr0_sync |= 1UL << (63 - 54);
|
||||
__ctl_load(cr0_sync, 0, 0);
|
||||
__arch_local_irq_stosm(0x01);
|
||||
/* Loop until driver state indicates finished request */
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@
|
|||
#include <linux/cpu.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <asm/smp.h>
|
||||
|
||||
#include "sclp.h"
|
||||
|
|
@ -20,8 +22,22 @@ struct conf_mgm_data {
|
|||
u8 ev_qualifier;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define OFB_DATA_MAX 64
|
||||
|
||||
struct sclp_ofb_evbuf {
|
||||
struct evbuf_header header;
|
||||
struct conf_mgm_data cm_data;
|
||||
char ev_data[OFB_DATA_MAX];
|
||||
} __packed;
|
||||
|
||||
struct sclp_ofb_sccb {
|
||||
struct sccb_header header;
|
||||
struct sclp_ofb_evbuf ofb_evbuf;
|
||||
} __packed;
|
||||
|
||||
#define EV_QUAL_CPU_CHANGE 1
|
||||
#define EV_QUAL_CAP_CHANGE 3
|
||||
#define EV_QUAL_OPEN4BUSINESS 5
|
||||
|
||||
static struct work_struct sclp_cpu_capability_work;
|
||||
static struct work_struct sclp_cpu_change_work;
|
||||
|
|
@ -63,15 +79,99 @@ static void sclp_conf_receiver_fn(struct evbuf_header *evbuf)
|
|||
|
||||
static struct sclp_register sclp_conf_register =
|
||||
{
|
||||
#ifdef CONFIG_SCLP_OFB
|
||||
.send_mask = EVTYP_CONFMGMDATA_MASK,
|
||||
#endif
|
||||
.receive_mask = EVTYP_CONFMGMDATA_MASK,
|
||||
.receiver_fn = sclp_conf_receiver_fn,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SCLP_OFB
|
||||
static int sclp_ofb_send_req(char *ev_data, size_t len)
|
||||
{
|
||||
static DEFINE_MUTEX(send_mutex);
|
||||
struct sclp_ofb_sccb *sccb;
|
||||
int rc, response;
|
||||
|
||||
if (len > OFB_DATA_MAX)
|
||||
return -EINVAL;
|
||||
sccb = (struct sclp_ofb_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
|
||||
if (!sccb)
|
||||
return -ENOMEM;
|
||||
/* Setup SCCB for Control-Program Identification */
|
||||
sccb->header.length = sizeof(struct sclp_ofb_sccb);
|
||||
sccb->ofb_evbuf.header.length = sizeof(struct sclp_ofb_evbuf);
|
||||
sccb->ofb_evbuf.header.type = EVTYP_CONFMGMDATA;
|
||||
sccb->ofb_evbuf.cm_data.ev_qualifier = EV_QUAL_OPEN4BUSINESS;
|
||||
memcpy(sccb->ofb_evbuf.ev_data, ev_data, len);
|
||||
|
||||
if (!(sclp_conf_register.sclp_receive_mask & EVTYP_CONFMGMDATA_MASK))
|
||||
pr_warn("SCLP receiver did not register to receive "
|
||||
"Configuration Management Data Events.\n");
|
||||
|
||||
mutex_lock(&send_mutex);
|
||||
rc = sclp_sync_request(SCLP_CMDW_WRITE_EVENT_DATA, sccb);
|
||||
mutex_unlock(&send_mutex);
|
||||
if (rc)
|
||||
goto out;
|
||||
response = sccb->header.response_code;
|
||||
if (response != 0x0020) {
|
||||
pr_err("Open for Business request failed with response code "
|
||||
"0x%04x\n", response);
|
||||
rc = -EIO;
|
||||
}
|
||||
out:
|
||||
free_page((unsigned long)sccb);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static ssize_t sysfs_ofb_data_write(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr,
|
||||
char *buf, loff_t off, size_t count)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = sclp_ofb_send_req(buf, count);
|
||||
return rc ?: count;
|
||||
}
|
||||
|
||||
static struct bin_attribute ofb_bin_attr = {
|
||||
.attr = {
|
||||
.name = "event_data",
|
||||
.mode = S_IWUSR,
|
||||
},
|
||||
.write = sysfs_ofb_data_write,
|
||||
};
|
||||
#endif
|
||||
|
||||
static int __init sclp_ofb_setup(void)
|
||||
{
|
||||
#ifdef CONFIG_SCLP_OFB
|
||||
struct kset *ofb_kset;
|
||||
int rc;
|
||||
|
||||
ofb_kset = kset_create_and_add("ofb", NULL, firmware_kobj);
|
||||
if (!ofb_kset)
|
||||
return -ENOMEM;
|
||||
rc = sysfs_create_bin_file(&ofb_kset->kobj, &ofb_bin_attr);
|
||||
if (rc) {
|
||||
kset_unregister(ofb_kset);
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init sclp_conf_init(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
INIT_WORK(&sclp_cpu_capability_work, sclp_cpu_capability_notify);
|
||||
INIT_WORK(&sclp_cpu_change_work, sclp_cpu_change_notify);
|
||||
return sclp_register(&sclp_conf_register);
|
||||
rc = sclp_register(&sclp_conf_register);
|
||||
if (rc)
|
||||
return rc;
|
||||
return sclp_ofb_setup();
|
||||
}
|
||||
|
||||
__initcall(sclp_conf_init);
|
||||
|
|
|
|||
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* SCLP control programm identification
|
||||
*
|
||||
* Copyright IBM Corp. 2001, 2007
|
||||
* Author(s): Martin Peschke <mpeschke@de.ibm.com>
|
||||
* Michael Ernst <mernst@de.ibm.com>
|
||||
*/
|
||||
|
||||
#include <linux/kmod.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/version.h>
|
||||
#include "sclp_cpi_sys.h"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Identify this operating system instance "
|
||||
"to the System z hardware");
|
||||
MODULE_AUTHOR("Martin Peschke <[email protected]>, "
|
||||
"Michael Ernst <[email protected]>");
|
||||
|
||||
static char *system_name = "";
|
||||
static char *sysplex_name = "";
|
||||
|
||||
module_param(system_name, charp, 0);
|
||||
MODULE_PARM_DESC(system_name, "e.g. hostname - max. 8 characters");
|
||||
module_param(sysplex_name, charp, 0);
|
||||
MODULE_PARM_DESC(sysplex_name, "if applicable - max. 8 characters");
|
||||
|
||||
static int __init cpi_module_init(void)
|
||||
{
|
||||
return sclp_cpi_set_data(system_name, sysplex_name, "LINUX",
|
||||
LINUX_VERSION_CODE);
|
||||
}
|
||||
|
||||
static void __exit cpi_module_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
module_init(cpi_module_init);
|
||||
module_exit(cpi_module_exit);
|
||||
|
|
@ -28,13 +28,12 @@
|
|||
#include <asm/processor.h>
|
||||
#include <asm/irqflags.h>
|
||||
#include <asm/checksum.h>
|
||||
#include <asm/os_info.h>
|
||||
#include <asm/switch_to.h>
|
||||
#include "sclp.h"
|
||||
|
||||
#define TRACE(x...) debug_sprintf_event(zcore_dbf, 1, x)
|
||||
|
||||
#define TO_USER 1
|
||||
#define TO_KERNEL 0
|
||||
#define CHUNK_INFO_SIZE 34 /* 2 16-byte char, each followed by blank */
|
||||
|
||||
enum arch_id {
|
||||
|
|
@ -42,241 +41,93 @@ enum arch_id {
|
|||
ARCH_S390X = 1,
|
||||
};
|
||||
|
||||
/* dump system info */
|
||||
|
||||
struct sys_info {
|
||||
enum arch_id arch;
|
||||
unsigned long sa_base;
|
||||
u32 sa_size;
|
||||
int cpu_map[NR_CPUS];
|
||||
unsigned long mem_size;
|
||||
struct save_area lc_mask;
|
||||
};
|
||||
|
||||
struct ipib_info {
|
||||
unsigned long ipib;
|
||||
u32 checksum;
|
||||
} __attribute__((packed));
|
||||
|
||||
static struct sys_info sys_info;
|
||||
static struct debug_info *zcore_dbf;
|
||||
static int hsa_available;
|
||||
static struct dentry *zcore_dir;
|
||||
static struct dentry *zcore_file;
|
||||
static struct dentry *zcore_memmap_file;
|
||||
static struct dentry *zcore_reipl_file;
|
||||
static struct dentry *zcore_hsa_file;
|
||||
static struct ipl_parameter_block *ipl_block;
|
||||
|
||||
static char hsa_buf[PAGE_SIZE] __aligned(PAGE_SIZE);
|
||||
|
||||
/*
|
||||
* Copy memory from HSA to kernel or user memory (not reentrant):
|
||||
* Copy memory from HSA to user memory (not reentrant):
|
||||
*
|
||||
* @dest: User buffer where memory should be copied to
|
||||
* @src: Start address within HSA where data should be copied
|
||||
* @count: Size of buffer, which should be copied
|
||||
*/
|
||||
int memcpy_hsa_user(void __user *dest, unsigned long src, size_t count)
|
||||
{
|
||||
unsigned long offset, bytes;
|
||||
|
||||
if (!hsa_available)
|
||||
return -ENODATA;
|
||||
|
||||
while (count) {
|
||||
if (sclp_sdias_copy(hsa_buf, src / PAGE_SIZE + 2, 1)) {
|
||||
TRACE("sclp_sdias_copy() failed\n");
|
||||
return -EIO;
|
||||
}
|
||||
offset = src % PAGE_SIZE;
|
||||
bytes = min(PAGE_SIZE - offset, count);
|
||||
if (copy_to_user(dest, hsa_buf + offset, bytes))
|
||||
return -EFAULT;
|
||||
src += bytes;
|
||||
dest += bytes;
|
||||
count -= bytes;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy memory from HSA to kernel memory (not reentrant):
|
||||
*
|
||||
* @dest: Kernel or user buffer where memory should be copied to
|
||||
* @src: Start address within HSA where data should be copied
|
||||
* @count: Size of buffer, which should be copied
|
||||
* @mode: Either TO_KERNEL or TO_USER
|
||||
*/
|
||||
int memcpy_hsa(void *dest, unsigned long src, size_t count, int mode)
|
||||
int memcpy_hsa_kernel(void *dest, unsigned long src, size_t count)
|
||||
{
|
||||
int offs, blk_num;
|
||||
static char buf[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
|
||||
unsigned long offset, bytes;
|
||||
|
||||
if (!hsa_available)
|
||||
return -ENODATA;
|
||||
if (count == 0)
|
||||
return 0;
|
||||
|
||||
/* copy first block */
|
||||
offs = 0;
|
||||
if ((src % PAGE_SIZE) != 0) {
|
||||
blk_num = src / PAGE_SIZE + 2;
|
||||
if (sclp_sdias_copy(buf, blk_num, 1)) {
|
||||
while (count) {
|
||||
if (sclp_sdias_copy(hsa_buf, src / PAGE_SIZE + 2, 1)) {
|
||||
TRACE("sclp_sdias_copy() failed\n");
|
||||
return -EIO;
|
||||
}
|
||||
offs = min((PAGE_SIZE - (src % PAGE_SIZE)), count);
|
||||
if (mode == TO_USER) {
|
||||
if (copy_to_user((__force __user void*) dest,
|
||||
buf + (src % PAGE_SIZE), offs))
|
||||
return -EFAULT;
|
||||
} else
|
||||
memcpy(dest, buf + (src % PAGE_SIZE), offs);
|
||||
offset = src % PAGE_SIZE;
|
||||
bytes = min(PAGE_SIZE - offset, count);
|
||||
memcpy(dest, hsa_buf + offset, bytes);
|
||||
src += bytes;
|
||||
dest += bytes;
|
||||
count -= bytes;
|
||||
}
|
||||
if (offs == count)
|
||||
goto out;
|
||||
|
||||
/* copy middle */
|
||||
for (; (offs + PAGE_SIZE) <= count; offs += PAGE_SIZE) {
|
||||
blk_num = (src + offs) / PAGE_SIZE + 2;
|
||||
if (sclp_sdias_copy(buf, blk_num, 1)) {
|
||||
TRACE("sclp_sdias_copy() failed\n");
|
||||
return -EIO;
|
||||
}
|
||||
if (mode == TO_USER) {
|
||||
if (copy_to_user((__force __user void*) dest + offs,
|
||||
buf, PAGE_SIZE))
|
||||
return -EFAULT;
|
||||
} else
|
||||
memcpy(dest + offs, buf, PAGE_SIZE);
|
||||
}
|
||||
if (offs == count)
|
||||
goto out;
|
||||
|
||||
/* copy last block */
|
||||
blk_num = (src + offs) / PAGE_SIZE + 2;
|
||||
if (sclp_sdias_copy(buf, blk_num, 1)) {
|
||||
TRACE("sclp_sdias_copy() failed\n");
|
||||
return -EIO;
|
||||
}
|
||||
if (mode == TO_USER) {
|
||||
if (copy_to_user((__force __user void*) dest + offs, buf,
|
||||
count - offs))
|
||||
return -EFAULT;
|
||||
} else
|
||||
memcpy(dest + offs, buf, count - offs);
|
||||
out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int memcpy_hsa_user(void __user *dest, unsigned long src, size_t count)
|
||||
static int __init init_cpu_info(void)
|
||||
{
|
||||
return memcpy_hsa((void __force *) dest, src, count, TO_USER);
|
||||
}
|
||||
|
||||
static int memcpy_hsa_kernel(void *dest, unsigned long src, size_t count)
|
||||
{
|
||||
return memcpy_hsa(dest, src, count, TO_KERNEL);
|
||||
}
|
||||
|
||||
static int __init init_cpu_info(enum arch_id arch)
|
||||
{
|
||||
struct save_area_ext *sa_ext;
|
||||
struct save_area *sa;
|
||||
|
||||
/* get info for boot cpu from lowcore, stored in the HSA */
|
||||
|
||||
sa_ext = dump_save_areas.areas[0];
|
||||
if (!sa_ext)
|
||||
sa = save_area_boot_cpu();
|
||||
if (!sa)
|
||||
return -ENOMEM;
|
||||
if (memcpy_hsa_kernel(&sa_ext->sa, sys_info.sa_base,
|
||||
sys_info.sa_size) < 0) {
|
||||
if (memcpy_hsa_kernel(hsa_buf, __LC_FPREGS_SAVE_AREA, 512) < 0) {
|
||||
TRACE("could not copy from HSA\n");
|
||||
kfree(sa_ext);
|
||||
return -EIO;
|
||||
}
|
||||
if (MACHINE_HAS_VX)
|
||||
save_vx_regs_safe(sa_ext->vx_regs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DEFINE_MUTEX(zcore_mutex);
|
||||
|
||||
#define DUMP_VERSION 0x5
|
||||
#define DUMP_MAGIC 0xa8190173618f23fdULL
|
||||
#define DUMP_ARCH_S390X 2
|
||||
#define DUMP_ARCH_S390 1
|
||||
#define HEADER_SIZE 4096
|
||||
|
||||
/* dump header dumped according to s390 crash dump format */
|
||||
|
||||
struct zcore_header {
|
||||
u64 magic;
|
||||
u32 version;
|
||||
u32 header_size;
|
||||
u32 dump_level;
|
||||
u32 page_size;
|
||||
u64 mem_size;
|
||||
u64 mem_start;
|
||||
u64 mem_end;
|
||||
u32 num_pages;
|
||||
u32 pad1;
|
||||
u64 tod;
|
||||
struct cpuid cpu_id;
|
||||
u32 arch_id;
|
||||
u32 volnr;
|
||||
u32 build_arch;
|
||||
u64 rmem_size;
|
||||
u8 mvdump;
|
||||
u16 cpu_cnt;
|
||||
u16 real_cpu_cnt;
|
||||
u8 end_pad1[0x200-0x061];
|
||||
u64 mvdump_sign;
|
||||
u64 mvdump_zipl_time;
|
||||
u8 end_pad2[0x800-0x210];
|
||||
u32 lc_vec[512];
|
||||
} __attribute__((packed,__aligned__(16)));
|
||||
|
||||
static struct zcore_header zcore_header = {
|
||||
.magic = DUMP_MAGIC,
|
||||
.version = DUMP_VERSION,
|
||||
.header_size = 4096,
|
||||
.dump_level = 0,
|
||||
.page_size = PAGE_SIZE,
|
||||
.mem_start = 0,
|
||||
.build_arch = DUMP_ARCH_S390X,
|
||||
};
|
||||
|
||||
/*
|
||||
* Copy lowcore info to buffer. Use map in order to copy only register parts.
|
||||
*
|
||||
* @buf: User buffer
|
||||
* @sa: Pointer to save area
|
||||
* @sa_off: Offset in save area to copy
|
||||
* @len: Number of bytes to copy
|
||||
*/
|
||||
static int copy_lc(void __user *buf, void *sa, int sa_off, int len)
|
||||
{
|
||||
int i;
|
||||
char *lc_mask = (char*)&sys_info.lc_mask;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (!lc_mask[i + sa_off])
|
||||
continue;
|
||||
if (copy_to_user(buf + i, sa + sa_off + i, 1))
|
||||
return -EFAULT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy lowcores info to memory, if necessary
|
||||
*
|
||||
* @buf: User buffer
|
||||
* @addr: Start address of buffer in dump memory
|
||||
* @count: Size of buffer
|
||||
*/
|
||||
static int zcore_add_lc(char __user *buf, unsigned long start, size_t count)
|
||||
{
|
||||
unsigned long end;
|
||||
int i;
|
||||
|
||||
if (count == 0)
|
||||
return 0;
|
||||
|
||||
end = start + count;
|
||||
for (i = 0; i < dump_save_areas.count; i++) {
|
||||
unsigned long cp_start, cp_end; /* copy range */
|
||||
unsigned long sa_start, sa_end; /* save area range */
|
||||
unsigned long prefix;
|
||||
unsigned long sa_off, len, buf_off;
|
||||
struct save_area *save_area = &dump_save_areas.areas[i]->sa;
|
||||
|
||||
prefix = save_area->pref_reg;
|
||||
sa_start = prefix + sys_info.sa_base;
|
||||
sa_end = prefix + sys_info.sa_base + sys_info.sa_size;
|
||||
|
||||
if ((end < sa_start) || (start > sa_end))
|
||||
continue;
|
||||
cp_start = max(start, sa_start);
|
||||
cp_end = min(end, sa_end);
|
||||
|
||||
buf_off = cp_start - start;
|
||||
sa_off = cp_start - sa_start;
|
||||
len = cp_end - cp_start;
|
||||
|
||||
TRACE("copy_lc for: %lx\n", start);
|
||||
if (copy_lc(buf + buf_off, save_area, sa_off, len))
|
||||
return -EFAULT;
|
||||
}
|
||||
save_area_add_regs(sa, hsa_buf); /* vx registers are saved in smp.c */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -289,115 +140,6 @@ static void release_hsa(void)
|
|||
hsa_available = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read routine for zcore character device
|
||||
* First 4K are dump header
|
||||
* Next 32MB are HSA Memory
|
||||
* Rest is read from absolute Memory
|
||||
*/
|
||||
static ssize_t zcore_read(struct file *file, char __user *buf, size_t count,
|
||||
loff_t *ppos)
|
||||
{
|
||||
unsigned long mem_start; /* Start address in memory */
|
||||
size_t mem_offs; /* Offset in dump memory */
|
||||
size_t hdr_count; /* Size of header part of output buffer */
|
||||
size_t size;
|
||||
int rc;
|
||||
|
||||
mutex_lock(&zcore_mutex);
|
||||
|
||||
if (*ppos > (sys_info.mem_size + HEADER_SIZE)) {
|
||||
rc = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
count = min(count, (size_t) (sys_info.mem_size + HEADER_SIZE - *ppos));
|
||||
|
||||
/* Copy dump header */
|
||||
if (*ppos < HEADER_SIZE) {
|
||||
size = min(count, (size_t) (HEADER_SIZE - *ppos));
|
||||
if (copy_to_user(buf, &zcore_header + *ppos, size)) {
|
||||
rc = -EFAULT;
|
||||
goto fail;
|
||||
}
|
||||
hdr_count = size;
|
||||
mem_start = 0;
|
||||
} else {
|
||||
hdr_count = 0;
|
||||
mem_start = *ppos - HEADER_SIZE;
|
||||
}
|
||||
|
||||
mem_offs = 0;
|
||||
|
||||
/* Copy from HSA data */
|
||||
if (*ppos < sclp.hsa_size + HEADER_SIZE) {
|
||||
size = min((count - hdr_count),
|
||||
(size_t) (sclp.hsa_size - mem_start));
|
||||
rc = memcpy_hsa_user(buf + hdr_count, mem_start, size);
|
||||
if (rc)
|
||||
goto fail;
|
||||
|
||||
mem_offs += size;
|
||||
}
|
||||
|
||||
/* Copy from real mem */
|
||||
size = count - mem_offs - hdr_count;
|
||||
rc = copy_to_user_real(buf + hdr_count + mem_offs,
|
||||
(void *) mem_start + mem_offs, size);
|
||||
if (rc)
|
||||
goto fail;
|
||||
|
||||
/*
|
||||
* Since s390 dump analysis tools like lcrash or crash
|
||||
* expect register sets in the prefix pages of the cpus,
|
||||
* we copy them into the read buffer, if necessary.
|
||||
* buf + hdr_count: Start of memory part of output buffer
|
||||
* mem_start: Start memory address to copy from
|
||||
* count - hdr_count: Size of memory area to copy
|
||||
*/
|
||||
if (zcore_add_lc(buf + hdr_count, mem_start, count - hdr_count)) {
|
||||
rc = -EFAULT;
|
||||
goto fail;
|
||||
}
|
||||
*ppos += count;
|
||||
fail:
|
||||
mutex_unlock(&zcore_mutex);
|
||||
return (rc < 0) ? rc : count;
|
||||
}
|
||||
|
||||
static int zcore_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
if (!hsa_available)
|
||||
return -ENODATA;
|
||||
else
|
||||
return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
|
||||
}
|
||||
|
||||
static int zcore_release(struct inode *inode, struct file *filep)
|
||||
{
|
||||
if (hsa_available)
|
||||
release_hsa();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static loff_t zcore_lseek(struct file *file, loff_t offset, int orig)
|
||||
{
|
||||
loff_t rc;
|
||||
|
||||
mutex_lock(&zcore_mutex);
|
||||
rc = no_seek_end_llseek(file, offset, orig);
|
||||
mutex_unlock(&zcore_mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static const struct file_operations zcore_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = zcore_lseek,
|
||||
.read = zcore_read,
|
||||
.open = zcore_open,
|
||||
.release = zcore_release,
|
||||
};
|
||||
|
||||
static ssize_t zcore_memmap_read(struct file *filp, char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
|
|
@ -501,50 +243,6 @@ static const struct file_operations zcore_hsa_fops = {
|
|||
.llseek = no_llseek,
|
||||
};
|
||||
|
||||
static void __init set_lc_mask(struct save_area *map)
|
||||
{
|
||||
memset(&map->fp_regs, 0xff, sizeof(map->fp_regs));
|
||||
memset(&map->gp_regs, 0xff, sizeof(map->gp_regs));
|
||||
memset(&map->psw, 0xff, sizeof(map->psw));
|
||||
memset(&map->pref_reg, 0xff, sizeof(map->pref_reg));
|
||||
memset(&map->fp_ctrl_reg, 0xff, sizeof(map->fp_ctrl_reg));
|
||||
memset(&map->tod_reg, 0xff, sizeof(map->tod_reg));
|
||||
memset(&map->timer, 0xff, sizeof(map->timer));
|
||||
memset(&map->clk_cmp, 0xff, sizeof(map->clk_cmp));
|
||||
memset(&map->acc_regs, 0xff, sizeof(map->acc_regs));
|
||||
memset(&map->ctrl_regs, 0xff, sizeof(map->ctrl_regs));
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize dump globals for a given architecture
|
||||
*/
|
||||
static int __init sys_info_init(enum arch_id arch, unsigned long mem_end)
|
||||
{
|
||||
int rc;
|
||||
|
||||
switch (arch) {
|
||||
case ARCH_S390X:
|
||||
pr_alert("DETECTED 'S390X (64 bit) OS'\n");
|
||||
break;
|
||||
case ARCH_S390:
|
||||
pr_alert("DETECTED 'S390 (32 bit) OS'\n");
|
||||
break;
|
||||
default:
|
||||
pr_alert("0x%x is an unknown architecture.\n",arch);
|
||||
return -EINVAL;
|
||||
}
|
||||
sys_info.sa_base = SAVE_AREA_BASE;
|
||||
sys_info.sa_size = sizeof(struct save_area);
|
||||
sys_info.arch = arch;
|
||||
set_lc_mask(&sys_info.lc_mask);
|
||||
rc = init_cpu_info(arch);
|
||||
if (rc)
|
||||
return rc;
|
||||
sys_info.mem_size = mem_end;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init check_sdias(void)
|
||||
{
|
||||
if (!sclp.hsa_size) {
|
||||
|
|
@ -554,43 +252,6 @@ static int __init check_sdias(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int __init get_mem_info(unsigned long *mem, unsigned long *end)
|
||||
{
|
||||
struct memblock_region *reg;
|
||||
|
||||
for_each_memblock(memory, reg) {
|
||||
*mem += reg->size;
|
||||
*end = max_t(unsigned long, *end, reg->base + reg->size);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __init zcore_header_init(int arch, struct zcore_header *hdr,
|
||||
unsigned long mem_size)
|
||||
{
|
||||
u32 prefix;
|
||||
int i;
|
||||
|
||||
if (arch == ARCH_S390X)
|
||||
hdr->arch_id = DUMP_ARCH_S390X;
|
||||
else
|
||||
hdr->arch_id = DUMP_ARCH_S390;
|
||||
hdr->mem_size = mem_size;
|
||||
hdr->rmem_size = mem_size;
|
||||
hdr->mem_end = sys_info.mem_size;
|
||||
hdr->num_pages = mem_size / PAGE_SIZE;
|
||||
hdr->tod = get_tod_clock();
|
||||
get_cpu_id(&hdr->cpu_id);
|
||||
for (i = 0; i < dump_save_areas.count; i++) {
|
||||
prefix = dump_save_areas.areas[i]->sa.pref_reg;
|
||||
hdr->real_cpu_cnt++;
|
||||
if (!prefix)
|
||||
continue;
|
||||
hdr->lc_vec[hdr->cpu_cnt] = prefix;
|
||||
hdr->cpu_cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Provide IPL parameter information block from either HSA or memory
|
||||
* for future reipl
|
||||
|
|
@ -623,11 +284,9 @@ static int __init zcore_reipl_init(void)
|
|||
|
||||
static int __init zcore_init(void)
|
||||
{
|
||||
unsigned long mem_size, mem_end;
|
||||
unsigned char arch;
|
||||
int rc;
|
||||
|
||||
mem_size = mem_end = 0;
|
||||
if (ipl_info.type != IPL_TYPE_FCP_DUMP)
|
||||
return -ENODATA;
|
||||
if (OLDMEM_BASE)
|
||||
|
|
@ -661,15 +320,11 @@ static int __init zcore_init(void)
|
|||
goto fail;
|
||||
}
|
||||
|
||||
rc = get_mem_info(&mem_size, &mem_end);
|
||||
pr_alert("DETECTED 'S390X (64 bit) OS'\n");
|
||||
rc = init_cpu_info();
|
||||
if (rc)
|
||||
goto fail;
|
||||
|
||||
rc = sys_info_init(arch, mem_end);
|
||||
if (rc)
|
||||
goto fail;
|
||||
zcore_header_init(arch, &zcore_header, mem_size);
|
||||
|
||||
rc = zcore_reipl_init();
|
||||
if (rc)
|
||||
goto fail;
|
||||
|
|
@ -679,17 +334,11 @@ static int __init zcore_init(void)
|
|||
rc = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
zcore_file = debugfs_create_file("mem", S_IRUSR, zcore_dir, NULL,
|
||||
&zcore_fops);
|
||||
if (!zcore_file) {
|
||||
rc = -ENOMEM;
|
||||
goto fail_dir;
|
||||
}
|
||||
zcore_memmap_file = debugfs_create_file("memmap", S_IRUSR, zcore_dir,
|
||||
NULL, &zcore_memmap_fops);
|
||||
if (!zcore_memmap_file) {
|
||||
rc = -ENOMEM;
|
||||
goto fail_file;
|
||||
goto fail_dir;
|
||||
}
|
||||
zcore_reipl_file = debugfs_create_file("reipl", S_IRUSR, zcore_dir,
|
||||
NULL, &zcore_reipl_fops);
|
||||
|
|
@ -709,8 +358,6 @@ fail_reipl_file:
|
|||
debugfs_remove(zcore_reipl_file);
|
||||
fail_memmap_file:
|
||||
debugfs_remove(zcore_memmap_file);
|
||||
fail_file:
|
||||
debugfs_remove(zcore_file);
|
||||
fail_dir:
|
||||
debugfs_remove(zcore_dir);
|
||||
fail:
|
||||
|
|
@ -726,7 +373,6 @@ static void __exit zcore_exit(void)
|
|||
debugfs_remove(zcore_hsa_file);
|
||||
debugfs_remove(zcore_reipl_file);
|
||||
debugfs_remove(zcore_memmap_file);
|
||||
debugfs_remove(zcore_file);
|
||||
debugfs_remove(zcore_dir);
|
||||
diag308(DIAG308_REL_HSA, NULL);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,11 @@
|
|||
# Makefile for the S/390 common i/o drivers
|
||||
#
|
||||
|
||||
# The following is required for define_trace.h to find ./trace.h
|
||||
CFLAGS_trace.o := -I$(src)
|
||||
|
||||
obj-y += airq.o blacklist.o chsc.o cio.o css.o chp.o idset.o isc.o \
|
||||
fcx.o itcw.o crw.o ccwreq.o
|
||||
fcx.o itcw.o crw.o ccwreq.o trace.o ioasm.o
|
||||
ccw_device-objs += device.o device_fsm.o device_ops.o
|
||||
ccw_device-objs += device_id.o device_pgid.o device_status.o
|
||||
obj-y += ccw_device.o cmf.o
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ static irqreturn_t do_airq_interrupt(int irq, void *dummy)
|
|||
|
||||
set_cpu_flag(CIF_NOHZ_DELAY);
|
||||
tpi_info = (struct tpi_info *) &get_irq_regs()->int_code;
|
||||
trace_s390_cio_adapter_int(tpi_info);
|
||||
head = &airq_lists[tpi_info->isc];
|
||||
rcu_read_lock();
|
||||
hlist_for_each_entry_rcu(airq, head, list)
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ static int chsc_subchannel_prepare(struct subchannel *sch)
|
|||
* since we don't have a way to clear the subchannel and
|
||||
* cannot disable it with a request running.
|
||||
*/
|
||||
cc = stsch_err(sch->schid, &schib);
|
||||
cc = stsch(sch->schid, &schib);
|
||||
if (!cc && scsw_stctl(&schib.scsw))
|
||||
return -EAGAIN;
|
||||
return 0;
|
||||
|
|
@ -185,8 +185,7 @@ static int __init chsc_init_dbfs(void)
|
|||
debug_set_level(chsc_debug_log_id, 2);
|
||||
return 0;
|
||||
out:
|
||||
if (chsc_debug_msg_id)
|
||||
debug_unregister(chsc_debug_msg_id);
|
||||
debug_unregister(chsc_debug_msg_id);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
#include "blacklist.h"
|
||||
#include "cio_debug.h"
|
||||
#include "chp.h"
|
||||
#include "trace.h"
|
||||
|
||||
debug_info_t *cio_debug_msg_id;
|
||||
debug_info_t *cio_debug_trace_id;
|
||||
|
|
@ -76,12 +77,9 @@ static int __init cio_debug_init(void)
|
|||
return 0;
|
||||
|
||||
out_unregister:
|
||||
if (cio_debug_msg_id)
|
||||
debug_unregister(cio_debug_msg_id);
|
||||
if (cio_debug_trace_id)
|
||||
debug_unregister(cio_debug_trace_id);
|
||||
if (cio_debug_crw_id)
|
||||
debug_unregister(cio_debug_crw_id);
|
||||
debug_unregister(cio_debug_msg_id);
|
||||
debug_unregister(cio_debug_trace_id);
|
||||
debug_unregister(cio_debug_crw_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -348,18 +346,18 @@ int cio_commit_config(struct subchannel *sch)
|
|||
struct schib schib;
|
||||
struct irb irb;
|
||||
|
||||
if (stsch_err(sch->schid, &schib) || !css_sch_is_valid(&schib))
|
||||
if (stsch(sch->schid, &schib) || !css_sch_is_valid(&schib))
|
||||
return -ENODEV;
|
||||
|
||||
for (retry = 0; retry < 5; retry++) {
|
||||
/* copy desired changes to local schib */
|
||||
cio_apply_config(sch, &schib);
|
||||
ccode = msch_err(sch->schid, &schib);
|
||||
ccode = msch(sch->schid, &schib);
|
||||
if (ccode < 0) /* -EIO if msch gets a program check. */
|
||||
return ccode;
|
||||
switch (ccode) {
|
||||
case 0: /* successful */
|
||||
if (stsch_err(sch->schid, &schib) ||
|
||||
if (stsch(sch->schid, &schib) ||
|
||||
!css_sch_is_valid(&schib))
|
||||
return -ENODEV;
|
||||
if (cio_check_config(sch, &schib)) {
|
||||
|
|
@ -394,7 +392,7 @@ int cio_update_schib(struct subchannel *sch)
|
|||
{
|
||||
struct schib schib;
|
||||
|
||||
if (stsch_err(sch->schid, &schib) || !css_sch_is_valid(&schib))
|
||||
if (stsch(sch->schid, &schib) || !css_sch_is_valid(&schib))
|
||||
return -ENODEV;
|
||||
|
||||
memcpy(&sch->schib, &schib, sizeof(schib));
|
||||
|
|
@ -503,7 +501,7 @@ int cio_validate_subchannel(struct subchannel *sch, struct subchannel_id schid)
|
|||
* If stsch gets an exception, it means the current subchannel set
|
||||
* is not valid.
|
||||
*/
|
||||
ccode = stsch_err(schid, &sch->schib);
|
||||
ccode = stsch(schid, &sch->schib);
|
||||
if (ccode) {
|
||||
err = (ccode == 3) ? -ENXIO : ccode;
|
||||
goto out;
|
||||
|
|
@ -542,6 +540,7 @@ static irqreturn_t do_cio_interrupt(int irq, void *dummy)
|
|||
|
||||
set_cpu_flag(CIF_NOHZ_DELAY);
|
||||
tpi_info = (struct tpi_info *) &get_irq_regs()->int_code;
|
||||
trace_s390_cio_interrupt(tpi_info);
|
||||
irb = this_cpu_ptr(&cio_irb);
|
||||
sch = (struct subchannel *)(unsigned long) tpi_info->intparm;
|
||||
if (!sch) {
|
||||
|
|
@ -619,7 +618,7 @@ static int cio_test_for_console(struct subchannel_id schid, void *data)
|
|||
{
|
||||
struct schib schib;
|
||||
|
||||
if (stsch_err(schid, &schib) != 0)
|
||||
if (stsch(schid, &schib) != 0)
|
||||
return -ENXIO;
|
||||
if ((schib.pmcw.st == SUBCHANNEL_TYPE_IO) && schib.pmcw.dnv &&
|
||||
(schib.pmcw.dev == console_devno)) {
|
||||
|
|
@ -638,7 +637,7 @@ static int cio_get_console_sch_no(void)
|
|||
if (console_irq != -1) {
|
||||
/* VM provided us with the irq number of the console. */
|
||||
schid.sch_no = console_irq;
|
||||
if (stsch_err(schid, &schib) != 0 ||
|
||||
if (stsch(schid, &schib) != 0 ||
|
||||
(schib.pmcw.st != SUBCHANNEL_TYPE_IO) || !schib.pmcw.dnv)
|
||||
return -1;
|
||||
console_devno = schib.pmcw.dev;
|
||||
|
|
@ -708,10 +707,10 @@ __disable_subchannel_easy(struct subchannel_id schid, struct schib *schib)
|
|||
cc = 0;
|
||||
for (retry=0;retry<3;retry++) {
|
||||
schib->pmcw.ena = 0;
|
||||
cc = msch_err(schid, schib);
|
||||
cc = msch(schid, schib);
|
||||
if (cc)
|
||||
return (cc==3?-ENODEV:-EBUSY);
|
||||
if (stsch_err(schid, schib) || !css_sch_is_valid(schib))
|
||||
if (stsch(schid, schib) || !css_sch_is_valid(schib))
|
||||
return -ENODEV;
|
||||
if (!schib->pmcw.ena)
|
||||
return 0;
|
||||
|
|
@ -758,7 +757,7 @@ static int stsch_reset(struct subchannel_id schid, struct schib *addr)
|
|||
|
||||
pgm_check_occured = 0;
|
||||
s390_base_pgm_handler_fn = cio_reset_pgm_check_handler;
|
||||
rc = stsch_err(schid, addr);
|
||||
rc = stsch(schid, addr);
|
||||
s390_base_pgm_handler_fn = NULL;
|
||||
|
||||
/* The program check handler could have changed pgm_check_occured. */
|
||||
|
|
@ -795,7 +794,7 @@ static int __shutdown_subchannel_easy(struct subchannel_id schid, void *data)
|
|||
/* No default clear strategy */
|
||||
break;
|
||||
}
|
||||
stsch_err(schid, &schib);
|
||||
stsch(schid, &schib);
|
||||
__disable_subchannel_easy(schid, &schib);
|
||||
}
|
||||
out:
|
||||
|
|
@ -917,7 +916,7 @@ void reipl_ccw_dev(struct ccw_dev_id *devid)
|
|||
{
|
||||
struct subchannel_id uninitialized_var(schid);
|
||||
|
||||
s390_reset_system(NULL, NULL, NULL);
|
||||
s390_reset_system();
|
||||
if (reipl_find_schid(devid, &schid) != 0)
|
||||
panic("IPL Device not found\n");
|
||||
do_reipl_asm(*((__u32*)&schid));
|
||||
|
|
@ -943,7 +942,7 @@ int __init cio_get_iplinfo(struct cio_iplinfo *iplinfo)
|
|||
if (__chsc_enable_facility(&sda_area, CHSC_SDA_OC_MSS))
|
||||
return -ENODEV;
|
||||
}
|
||||
if (stsch_err(schid, &schib))
|
||||
if (stsch(schid, &schib))
|
||||
return -ENODEV;
|
||||
if (schib.pmcw.st != SUBCHANNEL_TYPE_IO)
|
||||
return -ENODEV;
|
||||
|
|
|
|||
|
|
@ -45,6 +45,18 @@ struct pmcw {
|
|||
/* ... in an operand exception. */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* I/O-Interruption Code as stored by TEST PENDING INTERRUPTION (TPI). */
|
||||
struct tpi_info {
|
||||
struct subchannel_id schid;
|
||||
u32 intparm;
|
||||
u32 adapter_IO:1;
|
||||
u32 :1;
|
||||
u32 isc:3;
|
||||
u32 :27;
|
||||
u32 type:3;
|
||||
u32 :12;
|
||||
} __packed __aligned(4);
|
||||
|
||||
/* Target SCHIB configuration. */
|
||||
struct schib_config {
|
||||
u64 mba;
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
#include <linux/wait.h>
|
||||
#include <asm/crw.h>
|
||||
#include <asm/ctl_reg.h>
|
||||
#include "ioasm.h"
|
||||
|
||||
static DEFINE_MUTEX(crw_handler_mutex);
|
||||
static crw_handler_t crw_handlers[NR_RSCS];
|
||||
|
|
|
|||
|
|
@ -390,7 +390,7 @@ static int css_evaluate_new_subchannel(struct subchannel_id schid, int slow)
|
|||
/* Will be done on the slow path. */
|
||||
return -EAGAIN;
|
||||
}
|
||||
if (stsch_err(schid, &schib)) {
|
||||
if (stsch(schid, &schib)) {
|
||||
/* Subchannel is not provided. */
|
||||
return -ENXIO;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ static void ccw_timeout_log(struct ccw_device *cdev)
|
|||
sch = to_subchannel(cdev->dev.parent);
|
||||
private = to_io_private(sch);
|
||||
orb = &private->orb;
|
||||
cc = stsch_err(sch->schid, &schib);
|
||||
cc = stsch(sch->schid, &schib);
|
||||
|
||||
printk(KERN_WARNING "cio: ccw device timeout occurred at %llx, "
|
||||
"device information:\n", get_tod_clock());
|
||||
|
|
|
|||
|
|
@ -169,49 +169,4 @@ struct ccw_device_private {
|
|||
enum interruption_class int_class;
|
||||
};
|
||||
|
||||
static inline int rsch(struct subchannel_id schid)
|
||||
{
|
||||
register struct subchannel_id reg1 asm("1") = schid;
|
||||
int ccode;
|
||||
|
||||
asm volatile(
|
||||
" rsch\n"
|
||||
" ipm %0\n"
|
||||
" srl %0,28"
|
||||
: "=d" (ccode)
|
||||
: "d" (reg1)
|
||||
: "cc", "memory");
|
||||
return ccode;
|
||||
}
|
||||
|
||||
static inline int hsch(struct subchannel_id schid)
|
||||
{
|
||||
register struct subchannel_id reg1 asm("1") = schid;
|
||||
int ccode;
|
||||
|
||||
asm volatile(
|
||||
" hsch\n"
|
||||
" ipm %0\n"
|
||||
" srl %0,28"
|
||||
: "=d" (ccode)
|
||||
: "d" (reg1)
|
||||
: "cc");
|
||||
return ccode;
|
||||
}
|
||||
|
||||
static inline int xsch(struct subchannel_id schid)
|
||||
{
|
||||
register struct subchannel_id reg1 asm("1") = schid;
|
||||
int ccode;
|
||||
|
||||
asm volatile(
|
||||
" .insn rre,0xb2760000,%1,0\n"
|
||||
" ipm %0\n"
|
||||
" srl %0,28"
|
||||
: "=d" (ccode)
|
||||
: "d" (reg1)
|
||||
: "cc");
|
||||
return ccode;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
224
drivers/s390/cio/ioasm.c
Normal file
224
drivers/s390/cio/ioasm.c
Normal file
|
|
@ -0,0 +1,224 @@
|
|||
/*
|
||||
* Channel subsystem I/O instructions.
|
||||
*/
|
||||
|
||||
#include <linux/export.h>
|
||||
|
||||
#include <asm/chpid.h>
|
||||
#include <asm/schid.h>
|
||||
#include <asm/crw.h>
|
||||
|
||||
#include "ioasm.h"
|
||||
#include "orb.h"
|
||||
#include "cio.h"
|
||||
|
||||
int stsch(struct subchannel_id schid, struct schib *addr)
|
||||
{
|
||||
register struct subchannel_id reg1 asm ("1") = schid;
|
||||
int ccode = -EIO;
|
||||
|
||||
asm volatile(
|
||||
" stsch 0(%3)\n"
|
||||
"0: ipm %0\n"
|
||||
" srl %0,28\n"
|
||||
"1:\n"
|
||||
EX_TABLE(0b, 1b)
|
||||
: "+d" (ccode), "=m" (*addr)
|
||||
: "d" (reg1), "a" (addr)
|
||||
: "cc");
|
||||
trace_s390_cio_stsch(schid, addr, ccode);
|
||||
|
||||
return ccode;
|
||||
}
|
||||
EXPORT_SYMBOL(stsch);
|
||||
|
||||
int msch(struct subchannel_id schid, struct schib *addr)
|
||||
{
|
||||
register struct subchannel_id reg1 asm ("1") = schid;
|
||||
int ccode = -EIO;
|
||||
|
||||
asm volatile(
|
||||
" msch 0(%2)\n"
|
||||
"0: ipm %0\n"
|
||||
" srl %0,28\n"
|
||||
"1:\n"
|
||||
EX_TABLE(0b, 1b)
|
||||
: "+d" (ccode)
|
||||
: "d" (reg1), "a" (addr), "m" (*addr)
|
||||
: "cc");
|
||||
trace_s390_cio_msch(schid, addr, ccode);
|
||||
|
||||
return ccode;
|
||||
}
|
||||
|
||||
int tsch(struct subchannel_id schid, struct irb *addr)
|
||||
{
|
||||
register struct subchannel_id reg1 asm ("1") = schid;
|
||||
int ccode;
|
||||
|
||||
asm volatile(
|
||||
" tsch 0(%3)\n"
|
||||
" ipm %0\n"
|
||||
" srl %0,28"
|
||||
: "=d" (ccode), "=m" (*addr)
|
||||
: "d" (reg1), "a" (addr)
|
||||
: "cc");
|
||||
trace_s390_cio_tsch(schid, addr, ccode);
|
||||
|
||||
return ccode;
|
||||
}
|
||||
|
||||
int ssch(struct subchannel_id schid, union orb *addr)
|
||||
{
|
||||
register struct subchannel_id reg1 asm("1") = schid;
|
||||
int ccode = -EIO;
|
||||
|
||||
asm volatile(
|
||||
" ssch 0(%2)\n"
|
||||
"0: ipm %0\n"
|
||||
" srl %0,28\n"
|
||||
"1:\n"
|
||||
EX_TABLE(0b, 1b)
|
||||
: "+d" (ccode)
|
||||
: "d" (reg1), "a" (addr), "m" (*addr)
|
||||
: "cc", "memory");
|
||||
trace_s390_cio_ssch(schid, addr, ccode);
|
||||
|
||||
return ccode;
|
||||
}
|
||||
EXPORT_SYMBOL(ssch);
|
||||
|
||||
int csch(struct subchannel_id schid)
|
||||
{
|
||||
register struct subchannel_id reg1 asm("1") = schid;
|
||||
int ccode;
|
||||
|
||||
asm volatile(
|
||||
" csch\n"
|
||||
" ipm %0\n"
|
||||
" srl %0,28"
|
||||
: "=d" (ccode)
|
||||
: "d" (reg1)
|
||||
: "cc");
|
||||
trace_s390_cio_csch(schid, ccode);
|
||||
|
||||
return ccode;
|
||||
}
|
||||
EXPORT_SYMBOL(csch);
|
||||
|
||||
int tpi(struct tpi_info *addr)
|
||||
{
|
||||
int ccode;
|
||||
|
||||
asm volatile(
|
||||
" tpi 0(%2)\n"
|
||||
" ipm %0\n"
|
||||
" srl %0,28"
|
||||
: "=d" (ccode), "=m" (*addr)
|
||||
: "a" (addr)
|
||||
: "cc");
|
||||
trace_s390_cio_tpi(addr, ccode);
|
||||
|
||||
return ccode;
|
||||
}
|
||||
|
||||
int chsc(void *chsc_area)
|
||||
{
|
||||
typedef struct { char _[4096]; } addr_type;
|
||||
int cc;
|
||||
|
||||
asm volatile(
|
||||
" .insn rre,0xb25f0000,%2,0\n"
|
||||
" ipm %0\n"
|
||||
" srl %0,28\n"
|
||||
: "=d" (cc), "=m" (*(addr_type *) chsc_area)
|
||||
: "d" (chsc_area), "m" (*(addr_type *) chsc_area)
|
||||
: "cc");
|
||||
trace_s390_cio_chsc(chsc_area, cc);
|
||||
|
||||
return cc;
|
||||
}
|
||||
EXPORT_SYMBOL(chsc);
|
||||
|
||||
int rchp(struct chp_id chpid)
|
||||
{
|
||||
register struct chp_id reg1 asm ("1") = chpid;
|
||||
int ccode;
|
||||
|
||||
asm volatile(
|
||||
" lr 1,%1\n"
|
||||
" rchp\n"
|
||||
" ipm %0\n"
|
||||
" srl %0,28"
|
||||
: "=d" (ccode) : "d" (reg1) : "cc");
|
||||
trace_s390_cio_rchp(chpid, ccode);
|
||||
|
||||
return ccode;
|
||||
}
|
||||
|
||||
int rsch(struct subchannel_id schid)
|
||||
{
|
||||
register struct subchannel_id reg1 asm("1") = schid;
|
||||
int ccode;
|
||||
|
||||
asm volatile(
|
||||
" rsch\n"
|
||||
" ipm %0\n"
|
||||
" srl %0,28"
|
||||
: "=d" (ccode)
|
||||
: "d" (reg1)
|
||||
: "cc", "memory");
|
||||
trace_s390_cio_rsch(schid, ccode);
|
||||
|
||||
return ccode;
|
||||
}
|
||||
|
||||
int hsch(struct subchannel_id schid)
|
||||
{
|
||||
register struct subchannel_id reg1 asm("1") = schid;
|
||||
int ccode;
|
||||
|
||||
asm volatile(
|
||||
" hsch\n"
|
||||
" ipm %0\n"
|
||||
" srl %0,28"
|
||||
: "=d" (ccode)
|
||||
: "d" (reg1)
|
||||
: "cc");
|
||||
trace_s390_cio_hsch(schid, ccode);
|
||||
|
||||
return ccode;
|
||||
}
|
||||
|
||||
int xsch(struct subchannel_id schid)
|
||||
{
|
||||
register struct subchannel_id reg1 asm("1") = schid;
|
||||
int ccode;
|
||||
|
||||
asm volatile(
|
||||
" xsch\n"
|
||||
" ipm %0\n"
|
||||
" srl %0,28"
|
||||
: "=d" (ccode)
|
||||
: "d" (reg1)
|
||||
: "cc");
|
||||
trace_s390_cio_xsch(schid, ccode);
|
||||
|
||||
return ccode;
|
||||
}
|
||||
|
||||
int stcrw(struct crw *crw)
|
||||
{
|
||||
int ccode;
|
||||
|
||||
asm volatile(
|
||||
" stcrw 0(%2)\n"
|
||||
" ipm %0\n"
|
||||
" srl %0,28\n"
|
||||
: "=d" (ccode), "=m" (*crw)
|
||||
: "a" (crw)
|
||||
: "cc");
|
||||
trace_s390_cio_stcrw(crw, ccode);
|
||||
|
||||
return ccode;
|
||||
}
|
||||
|
|
@ -3,165 +3,26 @@
|
|||
|
||||
#include <asm/chpid.h>
|
||||
#include <asm/schid.h>
|
||||
#include <asm/crw.h>
|
||||
#include "orb.h"
|
||||
#include "cio.h"
|
||||
#include "trace.h"
|
||||
|
||||
/*
|
||||
* TPI info structure
|
||||
*/
|
||||
struct tpi_info {
|
||||
struct subchannel_id schid;
|
||||
__u32 intparm; /* interruption parameter */
|
||||
__u32 adapter_IO : 1;
|
||||
__u32 reserved2 : 1;
|
||||
__u32 isc : 3;
|
||||
__u32 reserved3 : 12;
|
||||
__u32 int_type : 3;
|
||||
__u32 reserved4 : 12;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
/*
|
||||
* Some S390 specific IO instructions as inline
|
||||
* Some S390 specific IO instructions
|
||||
*/
|
||||
|
||||
static inline int stsch_err(struct subchannel_id schid, struct schib *addr)
|
||||
{
|
||||
register struct subchannel_id reg1 asm ("1") = schid;
|
||||
int ccode = -EIO;
|
||||
|
||||
asm volatile(
|
||||
" stsch 0(%3)\n"
|
||||
"0: ipm %0\n"
|
||||
" srl %0,28\n"
|
||||
"1:\n"
|
||||
EX_TABLE(0b,1b)
|
||||
: "+d" (ccode), "=m" (*addr)
|
||||
: "d" (reg1), "a" (addr)
|
||||
: "cc");
|
||||
return ccode;
|
||||
}
|
||||
|
||||
static inline int msch(struct subchannel_id schid, struct schib *addr)
|
||||
{
|
||||
register struct subchannel_id reg1 asm ("1") = schid;
|
||||
int ccode;
|
||||
|
||||
asm volatile(
|
||||
" msch 0(%2)\n"
|
||||
" ipm %0\n"
|
||||
" srl %0,28"
|
||||
: "=d" (ccode)
|
||||
: "d" (reg1), "a" (addr), "m" (*addr)
|
||||
: "cc");
|
||||
return ccode;
|
||||
}
|
||||
|
||||
static inline int msch_err(struct subchannel_id schid, struct schib *addr)
|
||||
{
|
||||
register struct subchannel_id reg1 asm ("1") = schid;
|
||||
int ccode = -EIO;
|
||||
|
||||
asm volatile(
|
||||
" msch 0(%2)\n"
|
||||
"0: ipm %0\n"
|
||||
" srl %0,28\n"
|
||||
"1:\n"
|
||||
EX_TABLE(0b,1b)
|
||||
: "+d" (ccode)
|
||||
: "d" (reg1), "a" (addr), "m" (*addr)
|
||||
: "cc");
|
||||
return ccode;
|
||||
}
|
||||
|
||||
static inline int tsch(struct subchannel_id schid, struct irb *addr)
|
||||
{
|
||||
register struct subchannel_id reg1 asm ("1") = schid;
|
||||
int ccode;
|
||||
|
||||
asm volatile(
|
||||
" tsch 0(%3)\n"
|
||||
" ipm %0\n"
|
||||
" srl %0,28"
|
||||
: "=d" (ccode), "=m" (*addr)
|
||||
: "d" (reg1), "a" (addr)
|
||||
: "cc");
|
||||
return ccode;
|
||||
}
|
||||
|
||||
static inline int ssch(struct subchannel_id schid, union orb *addr)
|
||||
{
|
||||
register struct subchannel_id reg1 asm("1") = schid;
|
||||
int ccode = -EIO;
|
||||
|
||||
asm volatile(
|
||||
" ssch 0(%2)\n"
|
||||
"0: ipm %0\n"
|
||||
" srl %0,28\n"
|
||||
"1:\n"
|
||||
EX_TABLE(0b, 1b)
|
||||
: "+d" (ccode)
|
||||
: "d" (reg1), "a" (addr), "m" (*addr)
|
||||
: "cc", "memory");
|
||||
return ccode;
|
||||
}
|
||||
|
||||
static inline int csch(struct subchannel_id schid)
|
||||
{
|
||||
register struct subchannel_id reg1 asm("1") = schid;
|
||||
int ccode;
|
||||
|
||||
asm volatile(
|
||||
" csch\n"
|
||||
" ipm %0\n"
|
||||
" srl %0,28"
|
||||
: "=d" (ccode)
|
||||
: "d" (reg1)
|
||||
: "cc");
|
||||
return ccode;
|
||||
}
|
||||
|
||||
static inline int tpi(struct tpi_info *addr)
|
||||
{
|
||||
int ccode;
|
||||
|
||||
asm volatile(
|
||||
" tpi 0(%2)\n"
|
||||
" ipm %0\n"
|
||||
" srl %0,28"
|
||||
: "=d" (ccode), "=m" (*addr)
|
||||
: "a" (addr)
|
||||
: "cc");
|
||||
return ccode;
|
||||
}
|
||||
|
||||
static inline int chsc(void *chsc_area)
|
||||
{
|
||||
typedef struct { char _[4096]; } addr_type;
|
||||
int cc;
|
||||
|
||||
asm volatile(
|
||||
" .insn rre,0xb25f0000,%2,0\n"
|
||||
" ipm %0\n"
|
||||
" srl %0,28\n"
|
||||
: "=d" (cc), "=m" (*(addr_type *) chsc_area)
|
||||
: "d" (chsc_area), "m" (*(addr_type *) chsc_area)
|
||||
: "cc");
|
||||
return cc;
|
||||
}
|
||||
|
||||
static inline int rchp(struct chp_id chpid)
|
||||
{
|
||||
register struct chp_id reg1 asm ("1") = chpid;
|
||||
int ccode;
|
||||
|
||||
asm volatile(
|
||||
" lr 1,%1\n"
|
||||
" rchp\n"
|
||||
" ipm %0\n"
|
||||
" srl %0,28"
|
||||
: "=d" (ccode) : "d" (reg1) : "cc");
|
||||
return ccode;
|
||||
}
|
||||
int stsch(struct subchannel_id schid, struct schib *addr);
|
||||
int msch(struct subchannel_id schid, struct schib *addr);
|
||||
int tsch(struct subchannel_id schid, struct irb *addr);
|
||||
int ssch(struct subchannel_id schid, union orb *addr);
|
||||
int csch(struct subchannel_id schid);
|
||||
int tpi(struct tpi_info *addr);
|
||||
int chsc(void *chsc_area);
|
||||
int rchp(struct chp_id chpid);
|
||||
int rsch(struct subchannel_id schid);
|
||||
int hsch(struct subchannel_id schid);
|
||||
int xsch(struct subchannel_id schid);
|
||||
int stcrw(struct crw *crw);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -366,8 +366,6 @@ void qdio_debug_exit(void)
|
|||
{
|
||||
qdio_clear_dbf_list();
|
||||
debugfs_remove(debugfs_root);
|
||||
if (qdio_dbf_setup)
|
||||
debug_unregister(qdio_dbf_setup);
|
||||
if (qdio_dbf_error)
|
||||
debug_unregister(qdio_dbf_error);
|
||||
debug_unregister(qdio_dbf_setup);
|
||||
debug_unregister(qdio_dbf_error);
|
||||
}
|
||||
|
|
|
|||
24
drivers/s390/cio/trace.c
Normal file
24
drivers/s390/cio/trace.c
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Tracepoint definitions for s390_cio
|
||||
*
|
||||
* Copyright IBM Corp. 2015
|
||||
* Author(s): Peter Oberparleiter <oberpar@linux.vnet.ibm.com>
|
||||
*/
|
||||
|
||||
#include <asm/crw.h>
|
||||
#include "cio.h"
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include "trace.h"
|
||||
|
||||
EXPORT_TRACEPOINT_SYMBOL(s390_cio_stsch);
|
||||
EXPORT_TRACEPOINT_SYMBOL(s390_cio_msch);
|
||||
EXPORT_TRACEPOINT_SYMBOL(s390_cio_tsch);
|
||||
EXPORT_TRACEPOINT_SYMBOL(s390_cio_tpi);
|
||||
EXPORT_TRACEPOINT_SYMBOL(s390_cio_ssch);
|
||||
EXPORT_TRACEPOINT_SYMBOL(s390_cio_csch);
|
||||
EXPORT_TRACEPOINT_SYMBOL(s390_cio_hsch);
|
||||
EXPORT_TRACEPOINT_SYMBOL(s390_cio_xsch);
|
||||
EXPORT_TRACEPOINT_SYMBOL(s390_cio_rsch);
|
||||
EXPORT_TRACEPOINT_SYMBOL(s390_cio_rchp);
|
||||
EXPORT_TRACEPOINT_SYMBOL(s390_cio_chsc);
|
||||
363
drivers/s390/cio/trace.h
Normal file
363
drivers/s390/cio/trace.h
Normal file
|
|
@ -0,0 +1,363 @@
|
|||
/*
|
||||
* Tracepoint header for the s390 Common I/O layer (CIO)
|
||||
*
|
||||
* Copyright IBM Corp. 2015
|
||||
* Author(s): Peter Oberparleiter <oberpar@linux.vnet.ibm.com>
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <asm/crw.h>
|
||||
#include <uapi/asm/chpid.h>
|
||||
#include <uapi/asm/schid.h>
|
||||
#include "cio.h"
|
||||
#include "orb.h"
|
||||
|
||||
#undef TRACE_SYSTEM
|
||||
#define TRACE_SYSTEM s390
|
||||
|
||||
#if !defined(_TRACE_S390_CIO_H) || defined(TRACE_HEADER_MULTI_READ)
|
||||
#define _TRACE_S390_CIO_H
|
||||
|
||||
#include <linux/tracepoint.h>
|
||||
|
||||
DECLARE_EVENT_CLASS(s390_class_schib,
|
||||
TP_PROTO(struct subchannel_id schid, struct schib *schib, int cc),
|
||||
TP_ARGS(schid, schib, cc),
|
||||
TP_STRUCT__entry(
|
||||
__field(u8, cssid)
|
||||
__field(u8, ssid)
|
||||
__field(u16, schno)
|
||||
__field(u16, devno)
|
||||
__field_struct(struct schib, schib)
|
||||
__field(int, cc)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->cssid = schid.cssid;
|
||||
__entry->ssid = schid.ssid;
|
||||
__entry->schno = schid.sch_no;
|
||||
__entry->devno = schib->pmcw.dev;
|
||||
__entry->schib = *schib;
|
||||
__entry->cc = cc;
|
||||
),
|
||||
TP_printk("schid=%x.%x.%04x cc=%d ena=%d st=%d dnv=%d dev=%04x "
|
||||
"lpm=0x%02x pnom=0x%02x lpum=0x%02x pim=0x%02x pam=0x%02x "
|
||||
"pom=0x%02x chpids=%016llx",
|
||||
__entry->cssid, __entry->ssid, __entry->schno, __entry->cc,
|
||||
__entry->schib.pmcw.ena, __entry->schib.pmcw.st,
|
||||
__entry->schib.pmcw.dnv, __entry->schib.pmcw.dev,
|
||||
__entry->schib.pmcw.lpm, __entry->schib.pmcw.pnom,
|
||||
__entry->schib.pmcw.lpum, __entry->schib.pmcw.pim,
|
||||
__entry->schib.pmcw.pam, __entry->schib.pmcw.pom,
|
||||
*((u64 *) __entry->schib.pmcw.chpid)
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* s390_cio_stsch - Store Subchannel instruction (STSCH) was performed
|
||||
* @schid: Subchannel ID
|
||||
* @schib: Subchannel-Information block
|
||||
* @cc: Condition code
|
||||
*/
|
||||
DEFINE_EVENT(s390_class_schib, s390_cio_stsch,
|
||||
TP_PROTO(struct subchannel_id schid, struct schib *schib, int cc),
|
||||
TP_ARGS(schid, schib, cc)
|
||||
);
|
||||
|
||||
/**
|
||||
* s390_cio_msch - Modify Subchannel instruction (MSCH) was performed
|
||||
* @schid: Subchannel ID
|
||||
* @schib: Subchannel-Information block
|
||||
* @cc: Condition code
|
||||
*/
|
||||
DEFINE_EVENT(s390_class_schib, s390_cio_msch,
|
||||
TP_PROTO(struct subchannel_id schid, struct schib *schib, int cc),
|
||||
TP_ARGS(schid, schib, cc)
|
||||
);
|
||||
|
||||
/**
|
||||
* s390_cio_tsch - Test Subchannel instruction (TSCH) was performed
|
||||
* @schid: Subchannel ID
|
||||
* @irb: Interruption-Response Block
|
||||
* @cc: Condition code
|
||||
*/
|
||||
TRACE_EVENT(s390_cio_tsch,
|
||||
TP_PROTO(struct subchannel_id schid, struct irb *irb, int cc),
|
||||
TP_ARGS(schid, irb, cc),
|
||||
TP_STRUCT__entry(
|
||||
__field(u8, cssid)
|
||||
__field(u8, ssid)
|
||||
__field(u16, schno)
|
||||
__field_struct(struct irb, irb)
|
||||
__field(int, cc)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->cssid = schid.cssid;
|
||||
__entry->ssid = schid.ssid;
|
||||
__entry->schno = schid.sch_no;
|
||||
__entry->irb = *irb;
|
||||
__entry->cc = cc;
|
||||
),
|
||||
TP_printk("schid=%x.%x.%04x cc=%d dcc=%d pno=%d fctl=0x%x actl=0x%x "
|
||||
"stctl=0x%x dstat=0x%x cstat=0x%x",
|
||||
__entry->cssid, __entry->ssid, __entry->schno, __entry->cc,
|
||||
scsw_cc(&__entry->irb.scsw), scsw_pno(&__entry->irb.scsw),
|
||||
scsw_fctl(&__entry->irb.scsw), scsw_actl(&__entry->irb.scsw),
|
||||
scsw_stctl(&__entry->irb.scsw),
|
||||
scsw_dstat(&__entry->irb.scsw), scsw_cstat(&__entry->irb.scsw)
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* s390_cio_tpi - Test Pending Interruption instruction (TPI) was performed
|
||||
* @addr: Address of the I/O interruption code or %NULL
|
||||
* @cc: Condition code
|
||||
*/
|
||||
TRACE_EVENT(s390_cio_tpi,
|
||||
TP_PROTO(struct tpi_info *addr, int cc),
|
||||
TP_ARGS(addr, cc),
|
||||
TP_STRUCT__entry(
|
||||
__field(int, cc)
|
||||
__field_struct(struct tpi_info, tpi_info)
|
||||
__field(u8, cssid)
|
||||
__field(u8, ssid)
|
||||
__field(u16, schno)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->cc = cc;
|
||||
if (cc != 0)
|
||||
memset(&__entry->tpi_info, 0, sizeof(struct tpi_info));
|
||||
else if (addr)
|
||||
__entry->tpi_info = *addr;
|
||||
else {
|
||||
memcpy(&__entry->tpi_info, &S390_lowcore.subchannel_id,
|
||||
sizeof(struct tpi_info));
|
||||
}
|
||||
__entry->cssid = __entry->tpi_info.schid.cssid;
|
||||
__entry->ssid = __entry->tpi_info.schid.ssid;
|
||||
__entry->schno = __entry->tpi_info.schid.sch_no;
|
||||
),
|
||||
TP_printk("schid=%x.%x.%04x cc=%d a=%d isc=%d type=%d",
|
||||
__entry->cssid, __entry->ssid, __entry->schno, __entry->cc,
|
||||
__entry->tpi_info.adapter_IO, __entry->tpi_info.isc,
|
||||
__entry->tpi_info.type
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* s390_cio_ssch - Start Subchannel instruction (SSCH) was performed
|
||||
* @schid: Subchannel ID
|
||||
* @orb: Operation-Request Block
|
||||
* @cc: Condition code
|
||||
*/
|
||||
TRACE_EVENT(s390_cio_ssch,
|
||||
TP_PROTO(struct subchannel_id schid, union orb *orb, int cc),
|
||||
TP_ARGS(schid, orb, cc),
|
||||
TP_STRUCT__entry(
|
||||
__field(u8, cssid)
|
||||
__field(u8, ssid)
|
||||
__field(u16, schno)
|
||||
__field_struct(union orb, orb)
|
||||
__field(int, cc)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->cssid = schid.cssid;
|
||||
__entry->ssid = schid.ssid;
|
||||
__entry->schno = schid.sch_no;
|
||||
__entry->orb = *orb;
|
||||
__entry->cc = cc;
|
||||
),
|
||||
TP_printk("schid=%x.%x.%04x cc=%d", __entry->cssid, __entry->ssid,
|
||||
__entry->schno, __entry->cc
|
||||
)
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(s390_class_schid,
|
||||
TP_PROTO(struct subchannel_id schid, int cc),
|
||||
TP_ARGS(schid, cc),
|
||||
TP_STRUCT__entry(
|
||||
__field(u8, cssid)
|
||||
__field(u8, ssid)
|
||||
__field(u16, schno)
|
||||
__field(int, cc)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->cssid = schid.cssid;
|
||||
__entry->ssid = schid.ssid;
|
||||
__entry->schno = schid.sch_no;
|
||||
__entry->cc = cc;
|
||||
),
|
||||
TP_printk("schid=%x.%x.%04x cc=%d", __entry->cssid, __entry->ssid,
|
||||
__entry->schno, __entry->cc
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* s390_cio_csch - Clear Subchannel instruction (CSCH) was performed
|
||||
* @schid: Subchannel ID
|
||||
* @cc: Condition code
|
||||
*/
|
||||
DEFINE_EVENT(s390_class_schid, s390_cio_csch,
|
||||
TP_PROTO(struct subchannel_id schid, int cc),
|
||||
TP_ARGS(schid, cc)
|
||||
);
|
||||
|
||||
/**
|
||||
* s390_cio_hsch - Halt Subchannel instruction (HSCH) was performed
|
||||
* @schid: Subchannel ID
|
||||
* @cc: Condition code
|
||||
*/
|
||||
DEFINE_EVENT(s390_class_schid, s390_cio_hsch,
|
||||
TP_PROTO(struct subchannel_id schid, int cc),
|
||||
TP_ARGS(schid, cc)
|
||||
);
|
||||
|
||||
/**
|
||||
* s390_cio_xsch - Cancel Subchannel instruction (XSCH) was performed
|
||||
* @schid: Subchannel ID
|
||||
* @cc: Condition code
|
||||
*/
|
||||
DEFINE_EVENT(s390_class_schid, s390_cio_xsch,
|
||||
TP_PROTO(struct subchannel_id schid, int cc),
|
||||
TP_ARGS(schid, cc)
|
||||
);
|
||||
|
||||
/**
|
||||
* s390_cio_rsch - Resume Subchannel instruction (RSCH) was performed
|
||||
* @schid: Subchannel ID
|
||||
* @cc: Condition code
|
||||
*/
|
||||
DEFINE_EVENT(s390_class_schid, s390_cio_rsch,
|
||||
TP_PROTO(struct subchannel_id schid, int cc),
|
||||
TP_ARGS(schid, cc)
|
||||
);
|
||||
|
||||
/**
|
||||
* s390_cio_rchp - Reset Channel Path (RCHP) instruction was performed
|
||||
* @chpid: Channel-Path Identifier
|
||||
* @cc: Condition code
|
||||
*/
|
||||
TRACE_EVENT(s390_cio_rchp,
|
||||
TP_PROTO(struct chp_id chpid, int cc),
|
||||
TP_ARGS(chpid, cc),
|
||||
TP_STRUCT__entry(
|
||||
__field(u8, cssid)
|
||||
__field(u8, id)
|
||||
__field(int, cc)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->cssid = chpid.cssid;
|
||||
__entry->id = chpid.id;
|
||||
__entry->cc = cc;
|
||||
),
|
||||
TP_printk("chpid=%x.%02x cc=%d", __entry->cssid, __entry->id,
|
||||
__entry->cc
|
||||
)
|
||||
);
|
||||
|
||||
#define CHSC_MAX_REQUEST_LEN 64
|
||||
#define CHSC_MAX_RESPONSE_LEN 64
|
||||
|
||||
/**
|
||||
* s390_cio_chsc - Channel Subsystem Call (CHSC) instruction was performed
|
||||
* @chsc: CHSC block
|
||||
* @cc: Condition code
|
||||
*/
|
||||
TRACE_EVENT(s390_cio_chsc,
|
||||
TP_PROTO(struct chsc_header *chsc, int cc),
|
||||
TP_ARGS(chsc, cc),
|
||||
TP_STRUCT__entry(
|
||||
__field(int, cc)
|
||||
__field(u16, code)
|
||||
__field(u16, rcode)
|
||||
__array(u8, request, CHSC_MAX_REQUEST_LEN)
|
||||
__array(u8, response, CHSC_MAX_RESPONSE_LEN)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->cc = cc;
|
||||
__entry->code = chsc->code;
|
||||
memcpy(&entry->request, chsc,
|
||||
min_t(u16, chsc->length, CHSC_MAX_REQUEST_LEN));
|
||||
chsc = (struct chsc_header *) ((char *) chsc + chsc->length);
|
||||
__entry->rcode = chsc->code;
|
||||
memcpy(&entry->response, chsc,
|
||||
min_t(u16, chsc->length, CHSC_MAX_RESPONSE_LEN));
|
||||
),
|
||||
TP_printk("code=0x%04x cc=%d rcode=0x%04x", __entry->code,
|
||||
__entry->cc, __entry->rcode)
|
||||
);
|
||||
|
||||
/**
|
||||
* s390_cio_interrupt - An I/O interrupt occurred
|
||||
* @tpi_info: Address of the I/O interruption code
|
||||
*/
|
||||
TRACE_EVENT(s390_cio_interrupt,
|
||||
TP_PROTO(struct tpi_info *tpi_info),
|
||||
TP_ARGS(tpi_info),
|
||||
TP_STRUCT__entry(
|
||||
__field_struct(struct tpi_info, tpi_info)
|
||||
__field(u8, cssid)
|
||||
__field(u8, ssid)
|
||||
__field(u16, schno)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->tpi_info = *tpi_info;
|
||||
__entry->cssid = __entry->tpi_info.schid.cssid;
|
||||
__entry->ssid = __entry->tpi_info.schid.ssid;
|
||||
__entry->schno = __entry->tpi_info.schid.sch_no;
|
||||
),
|
||||
TP_printk("schid=%x.%x.%04x isc=%d type=%d",
|
||||
__entry->cssid, __entry->ssid, __entry->schno,
|
||||
__entry->tpi_info.isc, __entry->tpi_info.type
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* s390_cio_adapter_int - An adapter interrupt occurred
|
||||
* @tpi_info: Address of the I/O interruption code
|
||||
*/
|
||||
TRACE_EVENT(s390_cio_adapter_int,
|
||||
TP_PROTO(struct tpi_info *tpi_info),
|
||||
TP_ARGS(tpi_info),
|
||||
TP_STRUCT__entry(
|
||||
__field_struct(struct tpi_info, tpi_info)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->tpi_info = *tpi_info;
|
||||
),
|
||||
TP_printk("isc=%d", __entry->tpi_info.isc)
|
||||
);
|
||||
|
||||
/**
|
||||
* s390_cio_stcrw - Store Channel Report Word (STCRW) was performed
|
||||
* @crw: Channel Report Word
|
||||
* @cc: Condition code
|
||||
*/
|
||||
TRACE_EVENT(s390_cio_stcrw,
|
||||
TP_PROTO(struct crw *crw, int cc),
|
||||
TP_ARGS(crw, cc),
|
||||
TP_STRUCT__entry(
|
||||
__field_struct(struct crw, crw)
|
||||
__field(int, cc)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->crw = *crw;
|
||||
__entry->cc = cc;
|
||||
),
|
||||
TP_printk("cc=%d slct=%d oflw=%d chn=%d rsc=%d anc=%d erc=0x%x "
|
||||
"rsid=0x%x",
|
||||
__entry->cc, __entry->crw.slct, __entry->crw.oflw,
|
||||
__entry->crw.chn, __entry->crw.rsc, __entry->crw.anc,
|
||||
__entry->crw.erc, __entry->crw.rsid
|
||||
)
|
||||
);
|
||||
|
||||
#endif /* _TRACE_S390_CIO_H */
|
||||
|
||||
/* This part must be outside protection */
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
#define TRACE_INCLUDE_PATH .
|
||||
|
||||
#undef TRACE_INCLUDE_FILE
|
||||
#define TRACE_INCLUDE_FILE trace
|
||||
|
||||
#include <trace/define_trace.h>
|
||||
|
|
@ -1428,10 +1428,8 @@ int __init zcrypt_debug_init(void)
|
|||
void zcrypt_debug_exit(void)
|
||||
{
|
||||
debugfs_remove(debugfs_root);
|
||||
if (zcrypt_dbf_common)
|
||||
debug_unregister(zcrypt_dbf_common);
|
||||
if (zcrypt_dbf_devices)
|
||||
debug_unregister(zcrypt_dbf_devices);
|
||||
debug_unregister(zcrypt_dbf_common);
|
||||
debug_unregister(zcrypt_dbf_devices);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in a new issue