s390 updates for 7.0 merge window

- Drop support for outdated 3590/3592 and 3480 tape devices, and limit
   support to virtualized 3490E types devices
 
 - Implement exception based WARN() and WARN_ONCE() similar to x86
 
 - Slightly optimize preempt primitives like __preempt_count_add() and
   __preempt_count_dec_and_test()
 
 - A couple of small fixes and improvements
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEECMNfWEw3SLnmiLkZIg7DeRspbsIFAmmHePIACgkQIg7DeRsp
 bsIQeA//ZBOWwSlIkGhdH/qn7F2RMxq/FkvYN28YvCo1VFdAiqRXjDBH8yXE9Px4
 MghsDY1GzmW3M56Qq/rYZ2UhK0dIgpu9l8SJa5uxRaIzhIUxjmNJa+f3LhtCTZZH
 9timoL5zL+n8QwwLPo9DgKy+m/BOodKBeI9cHFYoia64eJqo1xDVg8tYzW+vlVZT
 LZt0kT6Nz/Hrkg/uOhsz40IGzR/fcsNeDGTF+JIjqcfpdMSAeDMeleWVRacw/0BZ
 q1gifRXxe04N8bjS7c98RiKX7CD3xQzzibH2ert2Mupu+yir6pvAlgYHOif3Z8gi
 6trcSWaxZCCslS2U7O1g/hyz1WXEFC+iDwajGiqT0XRSjuQ2FeVmfqcmaE0CekyY
 5mpdtwfLrNSZJL422a3lckqz73gkge5hC46wgvhpvx7lb4IF6paYsk6FPDZlxw+/
 THxbrYufs71VACvcfRs5MXSS94qkzkdgo5jhnS/m5zhblIrdkBUz29c5g24qUWo1
 ihyzkqtwMFHpKXE9rHK/Z80uZXr4/cLPpMq8XYXRQHZ6vFyZFfu4QpLHWTQ0VMyp
 ZBijhRqzlN/nAItAfBsgJ5QipHk2WL7V8zoi5xu7QeH+lrZ+7+koSVxGJAZbG4OO
 3fv6Nucjr/zCbyRKrjEaWaXzdMCVSdfrtfTQgftgFHTO8IxVLjc=
 =xeBU
 -----END PGP SIGNATURE-----

Merge tag 's390-7.0-1' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux

Pull s390 updates from Heiko Carstens:

 - Drop support for outdated 3590/3592 and 3480 tape devices, and limit
   support to virtualized 3490E types devices

 - Implement exception based WARN() and WARN_ONCE() similar to x86

 - Slightly optimize preempt primitives like __preempt_count_add() and
   __preempt_count_dec_and_test()

 - A couple of small fixes and improvements

* tag 's390-7.0-1' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: (35 commits)
  s390/tape: Consolidate tape config options and modules
  s390/cio: Fix device lifecycle handling in css_alloc_subchannel()
  s390/tape: Rename tape_34xx.c to tape_3490.c
  s390/tape: Cleanup sense data analysis and error handling
  s390/tape: Remove 3480 tape device type
  s390/tape: Remove unused command definitions
  s390/tape: Remove special block id handling
  s390/tape: Remove tape load display support
  s390/tape: Remove support for 3590/3592 models
  s390/kexec: Emit an error message when cmdline is too long
  s390/configs: Enable BLK_DEV_NULL_BLK as module
  s390: Document s390 stackprotector support
  s390/perf: Disable register readout on sampling events
  s390/Kconfig: Define non-zero ILLEGAL_POINTER_VALUE
  s390/bug: Prevent tail-call optimization
  s390/bug: Skip __WARN_trap() in call traces
  s390/bug: Implement WARN_ONCE()
  s390/bug: Implement __WARN_printf()
  s390/traps: Copy monitor code to pt_regs
  s390/bug: Introduce and use monitor code macro
  ...
This commit is contained in:
Linus Torvalds 2026-02-09 20:17:03 -08:00
commit c48953d819
37 changed files with 1158 additions and 3310 deletions

View file

@ -109,3 +109,7 @@ Virtual memory layout
| KASAN shadow | KASAN untracked
| |
+------------------+ ASCE limit
| |
| CONFIG_ILLEGAL_POINTER_VALUE causes memory access fault
| |
+------------------+

View file

@ -21,7 +21,7 @@
| parisc: | TODO |
| powerpc: | ok |
| riscv: | ok |
| s390: | TODO |
| s390: | ok |
| sh: | ok |
| sparc: | TODO |
| um: | TODO |

View file

@ -69,6 +69,12 @@ config CC_HAS_ASM_AOR_FORMAT_FLAGS
Clang versions before 19.1.0 do not support A,
O, and R inline assembly format flags.
config CC_HAS_ASM_IMMEDIATE_STRINGS
def_bool !(CC_IS_GCC && GCC_VERSION < 90000)
help
GCC versions before 9.0.0 cannot handle strings as immediate
input operands in inline assemblies.
config CC_HAS_STACKPROTECTOR_GLOBAL
def_bool $(cc-option, -mstack-protector-guard=global -mstack-protector-guard-record)
@ -85,6 +91,7 @@ config S390
select ARCH_ENABLE_MEMORY_HOTREMOVE
select ARCH_ENABLE_SPLIT_PMD_PTLOCK if PGTABLE_LEVELS > 2
select ARCH_ENABLE_THP_MIGRATION if TRANSPARENT_HUGEPAGE
select ARCH_HAS_CC_CAN_LINK
select ARCH_HAS_CPU_FINALIZE_INIT
select ARCH_HAS_CURRENT_STACK_POINTER
select ARCH_HAS_DEBUG_VIRTUAL
@ -294,6 +301,14 @@ config PGTABLE_LEVELS
source "kernel/livepatch/Kconfig"
config ARCH_CC_CAN_LINK
bool
default $(cc_can_link_user,-m64)
config ARCH_USERFLAGS
string
default "-m64"
config ARCH_SUPPORTS_KEXEC
def_bool y
@ -704,6 +719,10 @@ config ARCH_SPARSEMEM_ENABLE
config ARCH_SPARSEMEM_DEFAULT
def_bool y
config ILLEGAL_POINTER_VALUE
hex
default 0xdead000000000000
config MAX_PHYSMEM_BITS
int "Maximum size of supported physical memory in bits (42-53)"
range 42 53

View file

@ -21,6 +21,7 @@ KBUILD_AFLAGS := $(filter-out $(CC_FLAGS_MARCH),$(KBUILD_AFLAGS_DECOMPRESSOR))
KBUILD_CFLAGS := $(filter-out $(CC_FLAGS_MARCH),$(KBUILD_CFLAGS_DECOMPRESSOR))
KBUILD_AFLAGS += $(CC_FLAGS_MARCH_MINIMUM) -D__DISABLE_EXPORTS
KBUILD_CFLAGS += $(CC_FLAGS_MARCH_MINIMUM) -D__DISABLE_EXPORTS
KBUILD_CFLAGS += $(call cc-option, -Wno-default-const-init-unsafe)
CFLAGS_sclp_early_core.o += -I$(srctree)/drivers/s390/char

View file

@ -336,6 +336,7 @@ static unsigned long setup_kernel_memory_layout(unsigned long kernel_size)
BUILD_BUG_ON(!IS_ALIGNED(TEXT_OFFSET, THREAD_SIZE));
BUILD_BUG_ON(!IS_ALIGNED(__NO_KASLR_START_KERNEL, THREAD_SIZE));
BUILD_BUG_ON(__NO_KASLR_END_KERNEL > _REGION1_SIZE);
BUILD_BUG_ON(CONFIG_ILLEGAL_POINTER_VALUE < _REGION1_SIZE);
vsize = get_vmem_size(ident_map_size, vmemmap_size, vmalloc_size, _REGION3_SIZE);
boot_debug("vmem size estimated: 0x%016lx\n", vsize);
if (IS_ENABLED(CONFIG_KASAN) || __NO_KASLR_END_KERNEL > _REGION2_SIZE ||

View file

@ -446,6 +446,7 @@ CONFIG_BLK_DEV_RAM_SIZE=32768
CONFIG_VIRTIO_BLK=y
CONFIG_BLK_DEV_RBD=m
CONFIG_BLK_DEV_NVME=m
CONFIG_BLK_DEV_NULL_BLK=m
CONFIG_ENCLOSURE_SERVICES=m
CONFIG_GENWQE=m
CONFIG_RAID_ATTRS=m

View file

@ -436,6 +436,7 @@ CONFIG_BLK_DEV_RAM_SIZE=32768
CONFIG_VIRTIO_BLK=y
CONFIG_BLK_DEV_RBD=m
CONFIG_BLK_DEV_NVME=m
CONFIG_BLK_DEV_NULL_BLK=m
CONFIG_ENCLOSURE_SERVICES=m
CONFIG_GENWQE=m
CONFIG_RAID_ATTRS=m

View file

@ -78,7 +78,7 @@ union ap_queue_status_reg {
};
/**
* ap_intructions_available() - Test if AP instructions are available.
* ap_instructions_available() - Test if AP instructions are available.
*
* Returns true if the AP instructions are installed, otherwise false.
*/

View file

@ -3,6 +3,7 @@
#include <linux/kvm_host.h>
#include <linux/ftrace.h>
#include <asm/bug.h>
#include <asm/fpu.h>
#include <asm/nospec-branch.h>
#include <asm-generic/asm-prototypes.h>

View file

@ -30,7 +30,7 @@
*/
#if defined(__GCC_ASM_FLAG_OUTPUTS__) && !(IS_ENABLED(CONFIG_CC_ASM_FLAG_OUTPUT_BROKEN))
#define __HAVE_ASM_FLAG_OUTPUTS__
#define __HAVE_ASM_FLAG_OUTPUTS__ 1
#define CC_IPM(sym)
#define CC_OUT(sym, var) "=@cc" (var)

View file

@ -2,60 +2,127 @@
#ifndef _ASM_S390_BUG_H
#define _ASM_S390_BUG_H
#include <linux/stringify.h>
#include <linux/compiler.h>
#include <linux/const.h>
#ifdef CONFIG_BUG
#define MONCODE_BUG _AC(0, U)
#define MONCODE_BUG_ARG _AC(1, U)
#ifndef CONFIG_DEBUG_BUGVERBOSE
#define _BUGVERBOSE_LOCATION(file, line)
#ifndef __ASSEMBLER__
#if defined(CONFIG_BUG) && defined(CONFIG_CC_HAS_ASM_IMMEDIATE_STRINGS)
#ifdef CONFIG_DEBUG_BUGVERBOSE
#define __BUG_ENTRY_VERBOSE(format, file, line) \
" .long " format " - . # bug_entry::format\n" \
" .long " file " - . # bug_entry::file\n" \
" .short " line " # bug_entry::line\n"
#else
#define __BUGVERBOSE_LOCATION(file, line) \
.pushsection .rodata.str, "aMS", @progbits, 1; \
.align 2; \
10002: .ascii file "\0"; \
.popsection; \
\
.long 10002b - .; \
.short line;
#define _BUGVERBOSE_LOCATION(file, line) __BUGVERBOSE_LOCATION(file, line)
#define __BUG_ENTRY_VERBOSE(format, file, line)
#endif
#ifndef CONFIG_GENERIC_BUG
#define __BUG_ENTRY(cond_str, flags)
#ifdef CONFIG_DEBUG_BUGVERBOSE_DETAILED
#define WARN_CONDITION_STR(cond_str) cond_str
#else
#define __BUG_ENTRY(cond_str, flags) \
.pushsection __bug_table, "aw"; \
.align 4; \
10000: .long 10001f - .; \
_BUGVERBOSE_LOCATION(WARN_CONDITION_STR(cond_str) __FILE__, __LINE__) \
.short flags; \
.popsection; \
10001:
#define WARN_CONDITION_STR(cond_str) ""
#endif
#define ASM_BUG_FLAGS(cond_str, flags) \
__BUG_ENTRY(cond_str, flags) \
mc 0,0
#define __BUG_ENTRY(format, file, line, flags, size) \
" .section __bug_table,\"aw\"\n" \
"1: .long 0b - . # bug_entry::bug_addr\n" \
__BUG_ENTRY_VERBOSE(format, file, line) \
" .short "flags" # bug_entry::flags\n" \
" .org 1b+"size"\n" \
" .previous"
#define ASM_BUG() ASM_BUG_FLAGS("", 0)
#define __BUG_FLAGS(cond_str, flags) \
asm_inline volatile(__stringify(ASM_BUG_FLAGS(cond_str, flags)));
#define __WARN_FLAGS(cond_str, flags) \
do { \
__BUG_FLAGS(cond_str, BUGFLAG_WARNING|(flags)); \
#define __BUG_ASM(cond_str, flags) \
do { \
asm_inline volatile("\n" \
"0: mc %[monc](%%r0),0\n" \
__BUG_ENTRY("%[frmt]", "%[file]", "%[line]", \
"%[flgs]", "%[size]") \
: \
: [monc] "i" (MONCODE_BUG), \
[frmt] "i" (WARN_CONDITION_STR(cond_str)), \
[file] "i" (__FILE__), \
[line] "i" (__LINE__), \
[flgs] "i" (flags), \
[size] "i" (sizeof(struct bug_entry))); \
} while (0)
#define BUG() \
do { \
__BUG_FLAGS("", 0); \
unreachable(); \
#define BUG() \
do { \
__BUG_ASM("", 0); \
unreachable(); \
} while (0)
#define __WARN_FLAGS(cond_str, flags) \
do { \
__BUG_ASM(cond_str, BUGFLAG_WARNING | (flags)); \
} while (0)
#define __WARN_bug_entry(flags, format) \
({ \
struct bug_entry *bug; \
\
asm_inline volatile("\n" \
"0: larl %[bug],1f\n" \
__BUG_ENTRY("%[frmt]", "%[file]", "%[line]", \
"%[flgs]", "%[size]") \
: [bug] "=d" (bug) \
: [frmt] "i" (format), \
[file] "i" (__FILE__), \
[line] "i" (__LINE__), \
[flgs] "i" (flags), \
[size] "i" (sizeof(struct bug_entry))); \
bug; \
})
/*
* Variable Argument List (va_list) as defined in ELF Application
* Binary Interface s390x Supplement documentation.
*/
struct arch_va_list {
long __gpr;
long __fpr;
void *__overflow_arg_area;
void *__reg_save_area;
};
struct bug_entry;
struct pt_regs;
void *__warn_args(struct arch_va_list *args, struct pt_regs *regs);
void __WARN_trap(struct bug_entry *bug, ...);
#define __WARN_print_arg(flags, format, arg...) \
do { \
int __flags = (flags) | BUGFLAG_WARNING | BUGFLAG_ARGS; \
\
__WARN_trap(__WARN_bug_entry(__flags, format), ## arg); \
/* prevent tail-call optimization */ \
asm(""); \
} while (0)
#define __WARN_printf(taint, fmt, arg...) \
__WARN_print_arg(BUGFLAG_TAINT(taint), fmt, ## arg)
#define WARN_ONCE(cond, format, arg...) \
({ \
int __ret_warn_on = !!(cond); \
\
if (unlikely(__ret_warn_on)) { \
__WARN_print_arg(BUGFLAG_ONCE|BUGFLAG_TAINT(TAINT_WARN),\
format, ## arg); \
} \
__ret_warn_on; \
})
#define HAVE_ARCH_BUG
#define HAVE_ARCH_BUG_FORMAT
#define HAVE_ARCH_BUG_FORMAT_ARGS
#endif /* CONFIG_BUG */
#endif /* CONFIG_BUG && CONFIG_CC_HAS_ASM_IMMEDIATE_STRINGS */
#endif /* __ASSEMBLER__ */
#include <asm-generic/bug.h>

View file

@ -18,6 +18,7 @@
#define ZPCI_IOMAP_SHIFT 48
#define ZPCI_IOMAP_ADDR_SHIFT 62
#define ZPCI_IOMAP_ADDR_BASE (1UL << ZPCI_IOMAP_ADDR_SHIFT)
#define ZPCI_IOMAP_ADDR_MAX ((1UL << (ZPCI_IOMAP_ADDR_SHIFT + 1)) - 1)
#define ZPCI_IOMAP_ADDR_OFF_MASK ((1UL << ZPCI_IOMAP_SHIFT) - 1)
#define ZPCI_IOMAP_MAX_ENTRIES \
(1UL << (ZPCI_IOMAP_ADDR_SHIFT - ZPCI_IOMAP_SHIFT))

View file

@ -8,7 +8,10 @@
#include <asm/cmpxchg.h>
#include <asm/march.h>
/* We use the MSB mostly because its available */
/*
* Use MSB so it is possible to read preempt_count with LLGT which
* reads the least significant 31 bits with a single instruction.
*/
#define PREEMPT_NEED_RESCHED 0x80000000
/*
@ -23,7 +26,20 @@
*/
static __always_inline int preempt_count(void)
{
return READ_ONCE(get_lowcore()->preempt_count) & ~PREEMPT_NEED_RESCHED;
unsigned long lc_preempt, count;
BUILD_BUG_ON(sizeof_field(struct lowcore, preempt_count) != sizeof(int));
lc_preempt = offsetof(struct lowcore, preempt_count);
/* READ_ONCE(get_lowcore()->preempt_count) & ~PREEMPT_NEED_RESCHED */
asm_inline(
ALTERNATIVE("llgt %[count],%[offzero](%%r0)\n",
"llgt %[count],%[offalt](%%r0)\n",
ALT_FEATURE(MFEATURE_LOWCORE))
: [count] "=d" (count)
: [offzero] "i" (lc_preempt),
[offalt] "i" (lc_preempt + LOWCORE_ALT_ADDRESS),
"m" (((struct lowcore *)0)->preempt_count));
return count;
}
static __always_inline void preempt_count_set(int pc)
@ -68,7 +84,17 @@ static __always_inline void __preempt_count_add(int val)
*/
if (!IS_ENABLED(CONFIG_PROFILE_ALL_BRANCHES)) {
if (__builtin_constant_p(val) && (val >= -128) && (val <= 127)) {
__atomic_add_const(val, &get_lowcore()->preempt_count);
unsigned long lc_preempt;
lc_preempt = offsetof(struct lowcore, preempt_count);
asm_inline(
ALTERNATIVE("asi %[offzero](%%r0),%[val]\n",
"asi %[offalt](%%r0),%[val]\n",
ALT_FEATURE(MFEATURE_LOWCORE))
: "+m" (((struct lowcore *)0)->preempt_count)
: [offzero] "i" (lc_preempt), [val] "i" (val),
[offalt] "i" (lc_preempt + LOWCORE_ALT_ADDRESS)
: "cc");
return;
}
}
@ -87,7 +113,22 @@ static __always_inline void __preempt_count_sub(int val)
*/
static __always_inline bool __preempt_count_dec_and_test(void)
{
#ifdef __HAVE_ASM_FLAG_OUTPUTS__
unsigned long lc_preempt;
int cc;
lc_preempt = offsetof(struct lowcore, preempt_count);
asm_inline(
ALTERNATIVE("alsi %[offzero](%%r0),%[val]\n",
"alsi %[offalt](%%r0),%[val]\n",
ALT_FEATURE(MFEATURE_LOWCORE))
: "=@cc" (cc), "+m" (((struct lowcore *)0)->preempt_count)
: [offzero] "i" (lc_preempt), [val] "i" (-1),
[offalt] "i" (lc_preempt + LOWCORE_ALT_ADDRESS));
return (cc == 0) || (cc == 2);
#else
return __atomic_add_const_and_test(-1, &get_lowcore()->preempt_count);
#endif
}
/*

View file

@ -120,7 +120,10 @@ struct pt_regs {
unsigned long gprs[NUM_GPRS];
};
};
unsigned long orig_gpr2;
union {
unsigned long orig_gpr2;
unsigned long monitor_code;
};
union {
struct {
unsigned int int_code;
@ -214,16 +217,23 @@ void update_cr_regs(struct task_struct *task);
#define arch_has_single_step() (1)
#define arch_has_block_step() (1)
#define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0)
#define instruction_pointer(regs) ((regs)->psw.addr)
#define user_stack_pointer(regs)((regs)->gprs[15])
#define profile_pc(regs) instruction_pointer(regs)
static inline long regs_return_value(struct pt_regs *regs)
static __always_inline bool user_mode(const struct pt_regs *regs)
{
return psw_bits(regs->psw).pstate;
}
static inline long regs_return_value(const struct pt_regs *regs)
{
return regs->gprs[2];
}
static __always_inline unsigned long instruction_pointer(const struct pt_regs *regs)
{
return regs->psw.addr;
}
static inline void instruction_pointer_set(struct pt_regs *regs,
unsigned long val)
{
@ -233,19 +243,26 @@ static inline void instruction_pointer_set(struct pt_regs *regs,
int regs_query_register_offset(const char *name);
const char *regs_query_register_name(unsigned int offset);
static __always_inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
static __always_inline unsigned long kernel_stack_pointer(const struct pt_regs *regs)
{
return regs->gprs[15];
}
static __always_inline unsigned long regs_get_register(struct pt_regs *regs, unsigned int offset)
static __always_inline unsigned long user_stack_pointer(const struct pt_regs *regs)
{
return regs->gprs[15];
}
static __always_inline unsigned long regs_get_register(const struct pt_regs *regs,
unsigned int offset)
{
if (offset >= NUM_GPRS)
return 0;
return regs->gprs[offset];
}
static __always_inline int regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr)
static __always_inline int regs_within_kernel_stack(const struct pt_regs *regs,
unsigned long addr)
{
unsigned long ksp = kernel_stack_pointer(regs);
@ -261,7 +278,8 @@ static __always_inline int regs_within_kernel_stack(struct pt_regs *regs, unsign
* is specifined by @regs. If the @n th entry is NOT in the kernel stack,
* this returns 0.
*/
static __always_inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n)
static __always_inline unsigned long regs_get_kernel_stack_nth(const struct pt_regs *regs,
unsigned int n)
{
unsigned long addr;
@ -278,8 +296,8 @@ static __always_inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *r
*
* regs_get_kernel_argument() returns @n th argument of the function call.
*/
static inline unsigned long regs_get_kernel_argument(struct pt_regs *regs,
unsigned int n)
static __always_inline unsigned long regs_get_kernel_argument(const struct pt_regs *regs,
unsigned int n)
{
unsigned int argoffset = STACK_FRAME_OVERHEAD / sizeof(long);
@ -290,7 +308,7 @@ static inline unsigned long regs_get_kernel_argument(struct pt_regs *regs,
return regs_get_kernel_stack_nth(regs, argoffset + n);
}
static inline void regs_set_return_value(struct pt_regs *regs, unsigned long rc)
static __always_inline void regs_set_return_value(struct pt_regs *regs, unsigned long rc)
{
regs->gprs[2] = rc;
}

View file

@ -1,103 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*************************************************************************
*
* enables user programs to display messages and control encryption
* on s390 tape devices
*
* Copyright IBM Corp. 2001, 2006
* Author(s): Michael Holzheu <holzheu@de.ibm.com>
*
*************************************************************************/
#ifndef _TAPE390_H
#define _TAPE390_H
#define TAPE390_DISPLAY _IOW('d', 1, struct display_struct)
/*
* The TAPE390_DISPLAY ioctl calls the Load Display command
* which transfers 17 bytes of data from the channel to the subsystem:
* - 1 format control byte, and
* - two 8-byte messages
*
* Format control byte:
* 0-2: New Message Overlay
* 3: Alternate Messages
* 4: Blink Message
* 5: Display Low/High Message
* 6: Reserved
* 7: Automatic Load Request
*
*/
typedef struct display_struct {
char cntrl;
char message1[8];
char message2[8];
} display_struct;
/*
* Tape encryption support
*/
struct tape390_crypt_info {
char capability;
char status;
char medium_status;
} __attribute__ ((packed));
/* Macros for "capable" field */
#define TAPE390_CRYPT_SUPPORTED_MASK 0x01
#define TAPE390_CRYPT_SUPPORTED(x) \
((x.capability & TAPE390_CRYPT_SUPPORTED_MASK))
/* Macros for "status" field */
#define TAPE390_CRYPT_ON_MASK 0x01
#define TAPE390_CRYPT_ON(x) (((x.status) & TAPE390_CRYPT_ON_MASK))
/* Macros for "medium status" field */
#define TAPE390_MEDIUM_LOADED_MASK 0x01
#define TAPE390_MEDIUM_ENCRYPTED_MASK 0x02
#define TAPE390_MEDIUM_ENCRYPTED(x) \
(((x.medium_status) & TAPE390_MEDIUM_ENCRYPTED_MASK))
#define TAPE390_MEDIUM_LOADED(x) \
(((x.medium_status) & TAPE390_MEDIUM_LOADED_MASK))
/*
* The TAPE390_CRYPT_SET ioctl is used to switch on/off encryption.
* The "encryption_capable" and "tape_status" fields are ignored for this ioctl!
*/
#define TAPE390_CRYPT_SET _IOW('d', 2, struct tape390_crypt_info)
/*
* The TAPE390_CRYPT_QUERY ioctl is used to query the encryption state.
*/
#define TAPE390_CRYPT_QUERY _IOR('d', 3, struct tape390_crypt_info)
/* Values for "kekl1/2_type" and "kekl1/2_type_on_tape" fields */
#define TAPE390_KEKL_TYPE_NONE 0
#define TAPE390_KEKL_TYPE_LABEL 1
#define TAPE390_KEKL_TYPE_HASH 2
struct tape390_kekl {
unsigned char type;
unsigned char type_on_tape;
char label[65];
} __attribute__ ((packed));
struct tape390_kekl_pair {
struct tape390_kekl kekl[2];
} __attribute__ ((packed));
/*
* The TAPE390_KEKL_SET ioctl is used to set Key Encrypting Key labels.
*/
#define TAPE390_KEKL_SET _IOW('d', 4, struct tape390_kekl_pair)
/*
* The TAPE390_KEKL_QUERY ioctl is used to query Key Encrypting Key labels.
*/
#define TAPE390_KEKL_QUERY _IOR('d', 5, struct tape390_kekl_pair)
#endif

View file

@ -23,6 +23,7 @@
#include <asm/unistd.h>
#include <asm/page.h>
#include <asm/sigp.h>
#include <asm/bug.h>
#include <asm/irq.h>
#include <asm/fpu-insn.h>
#include <asm/setup.h>
@ -173,6 +174,16 @@ SYM_FUNC_START(__switch_to_asm)
BR_EX %r14
SYM_FUNC_END(__switch_to_asm)
#if defined(CONFIG_BUG) && defined(CONFIG_CC_HAS_ASM_IMMEDIATE_STRINGS)
SYM_FUNC_START(__WARN_trap)
mc MONCODE_BUG_ARG(%r0),0
BR_EX %r14
SYM_FUNC_END(__WARN_trap)
EXPORT_SYMBOL(__WARN_trap)
#endif /* CONFIG_BUG && CONFIG_CC_HAS_ASM_IMMEDIATE_STRINGS */
#if IS_ENABLED(CONFIG_KVM)
/*
* __sie64a calling convention:

View file

@ -270,8 +270,10 @@ void *kexec_file_add_components(struct kimage *image,
if (image->kernel_buf_len < minsize + max_command_line_size)
goto out;
if (image->cmdline_buf_len >= max_command_line_size)
if (image->cmdline_buf_len >= max_command_line_size) {
pr_err("Kernel command line exceeds supported limit of %lu", max_command_line_size);
goto out;
}
memcpy(data.parm->command_line, image->cmdline_buf,
image->cmdline_buf_len);

View file

@ -841,7 +841,7 @@ static bool is_callchain_event(struct perf_event *event)
u64 sample_type = event->attr.sample_type;
return sample_type & (PERF_SAMPLE_CALLCHAIN | PERF_SAMPLE_REGS_USER |
PERF_SAMPLE_STACK_USER);
PERF_SAMPLE_REGS_INTR | PERF_SAMPLE_STACK_USER);
}
static int cpumsf_pmu_event_init(struct perf_event *event)

View file

@ -23,6 +23,7 @@
#include <linux/cpu.h>
#include <linux/entry-common.h>
#include <linux/kmsan.h>
#include <linux/bug.h>
#include <asm/asm-extable.h>
#include <asm/irqflags.h>
#include <asm/ptrace.h>
@ -220,11 +221,48 @@ static void space_switch_exception(struct pt_regs *regs)
do_trap(regs, SIGILL, ILL_PRVOPC, "space switch event");
}
#if defined(CONFIG_BUG) && defined(CONFIG_CC_HAS_ASM_IMMEDIATE_STRINGS)
void *__warn_args(struct arch_va_list *args, struct pt_regs *regs)
{
struct stack_frame *stack_frame;
/*
* Generate va_list from pt_regs. See ELF Application Binary Interface
* s390x Supplement documentation for details.
*
* - __overflow_arg_area needs to point to the parameter area, which
* is right above the standard stack frame (160 bytes)
*
* - __reg_save_area needs to point to a register save area where
* general registers (%r2 - %r6) can be found at offset 16. Which
* means that the gprs save area of pt_regs can be used
*
* - __gpr must be set to one, since the first parameter has been
* processed (pointer to bug_entry)
*/
stack_frame = (struct stack_frame *)regs->gprs[15];
args->__overflow_arg_area = stack_frame + 1;
args->__reg_save_area = regs->gprs;
args->__gpr = 1;
return args;
}
#endif /* CONFIG_BUG && CONFIG_CC_HAS_ASM_IMMEDIATE_STRINGS */
static void monitor_event_exception(struct pt_regs *regs)
{
enum bug_trap_type btt;
if (user_mode(regs))
return;
switch (report_bug(regs->psw.addr - (regs->int_code >> 16), regs)) {
if (regs->monitor_code == MONCODE_BUG_ARG) {
regs->psw.addr = regs->gprs[14];
btt = report_bug_entry((struct bug_entry *)regs->gprs[2], regs);
} else {
btt = report_bug(regs->psw.addr - (regs->int_code >> 16), regs);
}
switch (btt) {
case BUG_TRAP_TYPE_NONE:
fixup_exception(regs);
break;
@ -258,11 +296,12 @@ static void __init test_monitor_call(void)
if (!IS_ENABLED(CONFIG_BUG))
return;
asm_inline volatile(
" mc 0,0\n"
" mc %[monc](%%r0),0\n"
"0: lhi %[val],0\n"
"1:\n"
EX_TABLE(0b, 1b)
: [val] "+d" (val));
: [val] "+d" (val)
: [monc] "i" (MONCODE_BUG));
if (!val)
panic("Monitor call doesn't work!\n");
}
@ -297,6 +336,7 @@ void noinstr __do_pgm_check(struct pt_regs *regs)
teid.val = lc->trans_exc_code;
regs->int_code = lc->pgm_int_code;
regs->int_parm_long = teid.val;
regs->monitor_code = lc->monitor_code;
/*
* In case of a guest fault, short-circuit the fault handler and return.
* This way the sie64a() function will return 0; fault address and

View file

@ -231,24 +231,33 @@ int zpci_fmb_disable_device(struct zpci_dev *zdev)
static int zpci_cfg_load(struct zpci_dev *zdev, int offset, u32 *val, u8 len)
{
u64 req = ZPCI_CREATE_REQ(zdev->fh, ZPCI_PCIAS_CFGSPC, len);
int rc = -ENODEV;
u64 data;
int rc;
if (!zdev_enabled(zdev))
goto out_err;
rc = __zpci_load(&data, req, offset);
if (!rc) {
data = le64_to_cpu((__force __le64) data);
data >>= (8 - len) * 8;
*val = (u32) data;
} else
*val = 0xffffffff;
if (rc)
goto out_err;
data = le64_to_cpu((__force __le64)data);
data >>= (8 - len) * 8;
*val = (u32)data;
return 0;
out_err:
PCI_SET_ERROR_RESPONSE(val);
return rc;
}
static int zpci_cfg_store(struct zpci_dev *zdev, int offset, u32 val, u8 len)
{
u64 req = ZPCI_CREATE_REQ(zdev->fh, ZPCI_PCIAS_CFGSPC, len);
int rc = -ENODEV;
u64 data = val;
int rc;
if (!zdev_enabled(zdev))
return rc;
data <<= (8 - len) * 8;
data = (__force u64) cpu_to_le64(data);
@ -397,7 +406,9 @@ static int pci_read(struct pci_bus *bus, unsigned int devfn, int where,
{
struct zpci_dev *zdev = zdev_from_bus(bus, devfn);
return (zdev) ? zpci_cfg_load(zdev, where, val, size) : -ENODEV;
if (!zdev || zpci_cfg_load(zdev, where, val, size))
return PCIBIOS_DEVICE_NOT_FOUND;
return PCIBIOS_SUCCESSFUL;
}
static int pci_write(struct pci_bus *bus, unsigned int devfn, int where,
@ -405,7 +416,9 @@ static int pci_write(struct pci_bus *bus, unsigned int devfn, int where,
{
struct zpci_dev *zdev = zdev_from_bus(bus, devfn);
return (zdev) ? zpci_cfg_store(zdev, where, val, size) : -ENODEV;
if (!zdev || zpci_cfg_store(zdev, where, val, size))
return PCIBIOS_DEVICE_NOT_FOUND;
return PCIBIOS_SUCCESSFUL;
}
static struct pci_ops pci_root_ops = {
@ -1052,6 +1065,8 @@ static int zpci_mem_init(void)
{
BUILD_BUG_ON(!is_power_of_2(__alignof__(struct zpci_fmb)) ||
__alignof__(struct zpci_fmb) < sizeof(struct zpci_fmb));
BUILD_BUG_ON((CONFIG_ILLEGAL_POINTER_VALUE + 0x10000 > ZPCI_IOMAP_ADDR_BASE) &&
(CONFIG_ILLEGAL_POINTER_VALUE <= ZPCI_IOMAP_ADDR_MAX));
zdev_fmb_cache = kmem_cache_create("PCI_FMB_cache", sizeof(struct zpci_fmb),
__alignof__(struct zpci_fmb), 0, NULL);

View file

@ -23,6 +23,7 @@ KBUILD_CFLAGS += -D__DISABLE_EXPORTS
KBUILD_CFLAGS += $(CLANG_FLAGS)
KBUILD_CFLAGS += $(if $(CONFIG_CC_IS_CLANG),-Wno-microsoft-anon-tag)
KBUILD_CFLAGS += $(call cc-option,-fno-PIE)
KBUILD_CFLAGS += $(call cc-option, -Wno-default-const-init-unsafe)
KBUILD_AFLAGS := $(filter-out -DCC_USING_EXPOLINE,$(KBUILD_AFLAGS))
KBUILD_AFLAGS += -D__DISABLE_EXPORTS

View file

@ -106,37 +106,12 @@ config S390_UV_UAPI
config S390_TAPE
def_tristate m
prompt "S/390 tape device support"
prompt "Support for 3490E tape on VTS"
depends on CCW
help
Select this option if you want to access channel-attached tape
devices on IBM S/390 or zSeries.
If you select this option you will also want to select at
least one of the tape interface options and one of the tape
hardware options in order to access a tape device.
This option is also available as a module. The module will be
called tape390 and include all selected interfaces and
hardware drivers.
comment "S/390 tape hardware support"
depends on S390_TAPE
config S390_TAPE_34XX
def_tristate m
prompt "Support for 3480/3490 tape hardware"
depends on S390_TAPE
help
Select this option if you want to access IBM 3480/3490 magnetic
tape subsystems and 100% compatibles.
It is safe to say "Y" here.
config S390_TAPE_3590
def_tristate m
prompt "Support for 3590 tape hardware"
depends on S390_TAPE
help
Select this option if you want to access IBM 3590 magnetic
tape subsystems and 100% compatibles.
Select this option if you want to access channel-attached IBM 3490E
tape devices on VTS, such as IBM TS7700.
This option is also available as a module.
It is safe to say "Y" here.
config VMLOGRDR

View file

@ -39,10 +39,8 @@ obj-$(CONFIG_VMLOGRDR) += vmlogrdr.o
obj-$(CONFIG_VMCP) += vmcp.o
tape-$(CONFIG_PROC_FS) += tape_proc.o
tape-objs := tape_core.o tape_std.o tape_char.o $(tape-y)
obj-$(CONFIG_S390_TAPE) += tape.o tape_class.o
obj-$(CONFIG_S390_TAPE_34XX) += tape_34xx.o
obj-$(CONFIG_S390_TAPE_3590) += tape_3590.o
tape_s390-objs := tape_3490.o tape_char.o tape_class.o tape_core.o tape_std.o $(tape-y)
obj-$(CONFIG_S390_TAPE) += tape_s390.o
obj-$(CONFIG_MONREADER) += monreader.o
obj-$(CONFIG_MONWRITER) += monwriter.o
obj-$(CONFIG_S390_VMUR) += vmur.o

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* tape device driver for 3480/3490E/3590 tapes.
* tape device driver for 3490E tapes.
*
* S390 and zSeries version
* Copyright IBM Corp. 2001, 2009
@ -98,10 +98,6 @@ enum tape_op {
TO_DIS, /* Tape display */
TO_ASSIGN, /* Assign tape to channel path */
TO_UNASSIGN, /* Unassign tape from channel path */
TO_CRYPT_ON, /* Enable encrpytion */
TO_CRYPT_OFF, /* Disable encrpytion */
TO_KEKL_SET, /* Set KEK label */
TO_KEKL_QUERY, /* Query KEK label */
TO_RDC, /* Read device characteristics */
TO_SIZE, /* #entries in tape_op_t */
};
@ -155,8 +151,6 @@ struct tape_discipline {
struct tape_request *(*read_block)(struct tape_device *);
struct tape_request *(*write_block)(struct tape_device *);
void (*process_eov)(struct tape_device*);
/* ioctl function for additional ioctls. */
int (*ioctl_fn)(struct tape_device *, unsigned int, unsigned long);
/* Array of tape commands with TAPE_NR_MTOPS entries */
tape_mtop_fn *mtop_array;
};
@ -192,7 +186,6 @@ struct tape_device {
/* Device discipline information. */
struct tape_discipline * discipline;
void * discdata;
/* Generic status flags */
long tape_generic_status;
@ -281,6 +274,10 @@ extern void tapechar_exit(void);
extern int tapechar_setup_device(struct tape_device *);
extern void tapechar_cleanup_device(struct tape_device *);
/* Externals from tape_3490.c */
extern int tape_3490_init(void);
extern void tape_3490_exit(void);
/* tape initialisation functions */
#ifdef CONFIG_PROC_FS
extern void tape_proc_init (void);

View file

@ -0,0 +1,825 @@
// SPDX-License-Identifier: GPL-2.0
/*
* tape device discipline for 3490 tapes.
*
* Copyright IBM Corp. 2001, 2009
* Author(s): Carsten Otte <cotte@de.ibm.com>
* Tuan Ngo-Anh <ngoanh@de.ibm.com>
* Martin Schwidefsky <schwidefsky@de.ibm.com>
*/
#define pr_fmt(fmt) "tape_3490: " fmt
#include <linux/export.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/bio.h>
#include <linux/workqueue.h>
#include <linux/slab.h>
#define TAPE_DBF_AREA tape_3490_dbf
#include "tape.h"
#include "tape_std.h"
/*
* Pointer to debug area.
*/
debug_info_t *TAPE_DBF_AREA = NULL;
EXPORT_SYMBOL(TAPE_DBF_AREA);
struct tape_3490_block_id {
unsigned int unused : 10;
unsigned int block : 22;
};
/*
* Medium sense for 3490 tapes. There is no 'real' medium sense call.
* So we just do a normal sense.
*/
static void __tape_3490_medium_sense(struct tape_request *request)
{
struct tape_device *device = request->device;
unsigned char *sense;
if (request->rc == 0) {
sense = request->cpdata;
/*
* This isn't quite correct. But since INTERVENTION_REQUIRED
* means that the drive is 'neither ready nor on-line' it is
* only slightly inaccurate to say there is no tape loaded if
* the drive isn't online...
*/
if (sense[0] & SENSE_INTERVENTION_REQUIRED)
tape_med_state_set(device, MS_UNLOADED);
else
tape_med_state_set(device, MS_LOADED);
if (sense[1] & SENSE_WRITE_PROTECT)
device->tape_generic_status |= GMT_WR_PROT(~0);
else
device->tape_generic_status &= ~GMT_WR_PROT(~0);
} else
DBF_EVENT(4, "tape_3490: medium sense failed with rc=%d\n",
request->rc);
tape_free_request(request);
}
static int tape_3490_medium_sense(struct tape_device *device)
{
struct tape_request *request;
int rc;
request = tape_alloc_request(1, 32);
if (IS_ERR(request)) {
DBF_EXCEPTION(6, "MSEN fail\n");
return PTR_ERR(request);
}
request->op = TO_MSEN;
tape_ccw_end(request->cpaddr, SENSE, 32, request->cpdata);
rc = tape_do_io_interruptible(device, request);
__tape_3490_medium_sense(request);
return rc;
}
static void tape_3490_medium_sense_async(struct tape_device *device)
{
struct tape_request *request;
request = tape_alloc_request(1, 32);
if (IS_ERR(request)) {
DBF_EXCEPTION(6, "MSEN fail\n");
return;
}
request->op = TO_MSEN;
tape_ccw_end(request->cpaddr, SENSE, 32, request->cpdata);
request->callback = (void *) __tape_3490_medium_sense;
request->callback_data = NULL;
tape_do_io_async(device, request);
}
struct tape_3490_work {
struct tape_device *device;
enum tape_op op;
struct work_struct work;
};
/*
* These functions are currently used only to schedule a medium_sense for
* later execution. This is because we get an interrupt whenever a medium
* is inserted but cannot call tape_do_io* from an interrupt context.
* Maybe that's useful for other actions we want to start from the
* interrupt handler.
* Note: the work handler is called by the system work queue. The tape
* commands started by the handler need to be asynchrounous, otherwise
* a deadlock can occur e.g. in case of a deferred cc=1 (see __tape_do_irq).
*/
static void
tape_3490_work_handler(struct work_struct *work)
{
struct tape_3490_work *p =
container_of(work, struct tape_3490_work, work);
struct tape_device *device = p->device;
switch(p->op) {
case TO_MSEN:
tape_3490_medium_sense_async(device);
break;
default:
DBF_EVENT(3, "T3490: internal error: unknown work\n");
}
tape_put_device(device);
kfree(p);
}
static int
tape_3490_schedule_work(struct tape_device *device, enum tape_op op)
{
struct tape_3490_work *p;
if ((p = kzalloc(sizeof(*p), GFP_ATOMIC)) == NULL)
return -ENOMEM;
INIT_WORK(&p->work, tape_3490_work_handler);
p->device = tape_get_device(device);
p->op = op;
schedule_work(&p->work);
return 0;
}
/*
* Done Handler is called when dev stat = DEVICE-END (successful operation)
*/
static inline int
tape_3490_done(struct tape_request *request)
{
DBF_EVENT(6, "%s done\n", tape_op_verbose[request->op]);
return TAPE_IO_SUCCESS;
}
static inline int
tape_3490_erp_failed(struct tape_request *request, int rc)
{
DBF_EVENT(3, "Error recovery failed for %s (RC=%d)\n",
tape_op_verbose[request->op], rc);
return rc;
}
static inline int
tape_3490_erp_succeeded(struct tape_request *request)
{
DBF_EVENT(3, "Error Recovery successful for %s\n",
tape_op_verbose[request->op]);
return tape_3490_done(request);
}
static inline int
tape_3490_erp_retry(struct tape_request *request)
{
DBF_EVENT(3, "xerp retr %s\n", tape_op_verbose[request->op]);
return TAPE_IO_RETRY;
}
/*
* This function is called, when no request is outstanding and we get an
* interrupt
*/
static int
tape_3490_unsolicited_irq(struct tape_device *device, struct irb *irb)
{
if (irb->scsw.cmd.dstat == 0x85) { /* READY */
/* A medium was inserted in the drive. */
DBF_EVENT(6, "xuud med\n");
tape_3490_schedule_work(device, TO_MSEN);
} else {
DBF_EVENT(3, "unsol.irq! dev end: %08x\n", device->cdev_id);
tape_dump_sense_dbf(device, NULL, irb);
}
return TAPE_IO_SUCCESS;
}
static int
tape_3490_erp_bug(struct tape_device *device, struct tape_request *request,
struct irb *irb, int no)
{
if (request->op != TO_ASSIGN) {
dev_err(&device->cdev->dev, "An unexpected condition %d "
"occurred in tape error recovery\n", no);
tape_dump_sense_dbf(device, request, irb);
}
return tape_3490_erp_failed(request, -EIO);
}
/*
* Handle data overrun between cu and drive. The channel speed might
* be too slow.
*/
static int
tape_3490_erp_overrun(struct tape_device *device, struct tape_request *request,
struct irb *irb)
{
if (irb->ecw[3] == 0x40) {
dev_warn (&device->cdev->dev, "A data overrun occurred between"
" the control unit and tape unit\n");
return tape_3490_erp_failed(request, -EIO);
}
return tape_3490_erp_bug(device, request, irb, -1);
}
/*
* Handle record sequence error.
*/
static int
tape_3490_erp_sequence(struct tape_device *device,
struct tape_request *request, struct irb *irb)
{
if (irb->ecw[3] == 0x41) {
/*
* cu detected incorrect block-id sequence on tape.
*/
dev_warn (&device->cdev->dev, "The block ID sequence on the "
"tape is incorrect\n");
return tape_3490_erp_failed(request, -EIO);
}
/*
* Record sequence error bit is set, but erpa does not
* show record sequence error.
*/
return tape_3490_erp_bug(device, request, irb, -2);
}
/*
* This function analyses the tape's sense-data in case of a unit-check.
* If possible, it tries to recover from the error. Else the user is
* informed about the problem.
*/
static int
tape_3490_unit_check(struct tape_device *device, struct tape_request *request,
struct irb *irb)
{
int inhibit_cu_recovery;
__u8* sense;
inhibit_cu_recovery = (*device->modeset_byte & 0x80) ? 1 : 0;
sense = irb->ecw;
if (
sense[0] & SENSE_COMMAND_REJECT &&
sense[1] & SENSE_WRITE_PROTECT
) {
if (
request->op == TO_DSE ||
request->op == TO_WRI ||
request->op == TO_WTM
) {
/* medium is write protected */
return tape_3490_erp_failed(request, -EACCES);
} else {
return tape_3490_erp_bug(device, request, irb, -3);
}
}
/*
* Special cases for various tape-states when reaching
* end of recorded area
*
* FIXME: Maybe a special case of the special case:
* sense[0] == SENSE_EQUIPMENT_CHECK &&
* sense[1] == SENSE_DRIVE_ONLINE &&
* sense[3] == 0x47 (Volume Fenced)
*
* This was caused by continued FSF or FSR after an
* 'End Of Data'.
*/
if ((
sense[0] == SENSE_DATA_CHECK ||
sense[0] == SENSE_EQUIPMENT_CHECK ||
sense[0] == (SENSE_EQUIPMENT_CHECK | SENSE_DEFERRED_UNIT_CHECK)
) && (
sense[1] == SENSE_DRIVE_ONLINE ||
sense[1] == (SENSE_BEGINNING_OF_TAPE | SENSE_WRITE_MODE)
)) {
switch (request->op) {
/*
* sense[0] == SENSE_DATA_CHECK &&
* sense[1] == SENSE_DRIVE_ONLINE
* sense[3] == 0x36 (End Of Data)
*
* Further seeks might return a 'Volume Fenced'.
*/
case TO_FSF:
case TO_FSB:
/* Trying to seek beyond end of recorded area */
return tape_3490_erp_failed(request, -ENOSPC);
case TO_BSB:
return tape_3490_erp_retry(request);
/*
* sense[0] == SENSE_DATA_CHECK &&
* sense[1] == SENSE_DRIVE_ONLINE &&
* sense[3] == 0x36 (End Of Data)
*/
case TO_LBL:
/* Block could not be located. */
return tape_3490_erp_failed(request, -EIO);
case TO_RFO:
/* Read beyond end of recorded area -> 0 bytes read */
return tape_3490_erp_failed(request, 0);
/*
* sense[0] == SENSE_EQUIPMENT_CHECK &&
* sense[1] == SENSE_DRIVE_ONLINE &&
* sense[3] == 0x38 (Physical End Of Volume)
*/
case TO_WRI:
/* Writing at physical end of volume */
return tape_3490_erp_failed(request, -ENOSPC);
default:
return tape_3490_erp_failed(request, 0);
}
}
/* Sensing special bits */
if (sense[0] & SENSE_BUS_OUT_CHECK)
return tape_3490_erp_retry(request);
if (sense[0] & SENSE_DATA_CHECK) {
/*
* hardware failure, damaged tape or improper
* operating conditions
*/
switch (sense[3]) {
case 0x23:
/* a read data check occurred */
if ((sense[2] & SENSE_TAPE_SYNC_MODE) ||
inhibit_cu_recovery)
// data check is not permanent, may be
// recovered. We always use async-mode with
// cu-recovery, so this should *never* happen.
return tape_3490_erp_bug(device, request,
irb, -4);
/* data check is permanent, CU recovery has failed */
dev_warn (&device->cdev->dev, "A read error occurred "
"that cannot be recovered\n");
return tape_3490_erp_failed(request, -EIO);
case 0x25:
// a write data check occurred
if ((sense[2] & SENSE_TAPE_SYNC_MODE) ||
inhibit_cu_recovery)
// data check is not permanent, may be
// recovered. We always use async-mode with
// cu-recovery, so this should *never* happen.
return tape_3490_erp_bug(device, request,
irb, -5);
// data check is permanent, cu-recovery has failed
dev_warn (&device->cdev->dev, "A write error on the "
"tape cannot be recovered\n");
return tape_3490_erp_failed(request, -EIO);
case 0x28:
/* ID-Mark at tape start couldn't be written */
dev_warn (&device->cdev->dev, "Writing the ID-mark "
"failed\n");
return tape_3490_erp_failed(request, -EIO);
case 0x31:
/* Tape void. Tried to read beyond end of device. */
dev_warn (&device->cdev->dev, "Reading the tape beyond"
" the end of the recorded area failed\n");
return tape_3490_erp_failed(request, -ENOSPC);
case 0x41:
/* Record sequence error. */
dev_warn (&device->cdev->dev, "The tape contains an "
"incorrect block ID sequence\n");
return tape_3490_erp_failed(request, -EIO);
}
}
if (sense[0] & SENSE_OVERRUN)
return tape_3490_erp_overrun(device, request, irb);
if (sense[1] & SENSE_RECORD_SEQUENCE_ERR)
return tape_3490_erp_sequence(device, request, irb);
/* Sensing erpa codes */
switch (sense[3]) {
case 0x00:
/* Unit check with erpa code 0. Report and ignore. */
return TAPE_IO_SUCCESS;
case 0x27:
/*
* Command reject. May indicate illegal channel program or
* buffer over/underrun. Since all channel programs are
* issued by this driver and ought be correct, we assume a
* over/underrun situation and retry the channel program.
*/
return tape_3490_erp_retry(request);
case 0x29:
/*
* Function incompatible. Either the tape is idrc compressed
* but the hardware isn't capable to do idrc, or a perform
* subsystem func is issued and the CU is not on-line.
*/
return tape_3490_erp_failed(request, -EIO);
case 0x2b:
/*
* Environmental data present. Indicates either unload
* completed ok or read buffered log command completed ok.
*/
if (request->op == TO_RUN) {
/* Rewind unload completed ok. */
tape_med_state_set(device, MS_UNLOADED);
return tape_3490_erp_succeeded(request);
}
/* tape_3490 doesn't use read buffered log commands. */
return tape_3490_erp_bug(device, request, irb, sense[3]);
case 0x2c:
/*
* Permanent equipment check. CU has tried recovery, but
* did not succeed.
*/
return tape_3490_erp_failed(request, -EIO);
case 0x2d:
/* Data security erase failure. */
if (request->op == TO_DSE)
return tape_3490_erp_failed(request, -EIO);
/* Data security erase failure, but no such command issued. */
return tape_3490_erp_bug(device, request, irb, sense[3]);
case 0x2e:
/*
* Not capable. This indicates either that the drive fails
* reading the format id mark or that format specified
* is not supported by the drive.
*/
dev_warn (&device->cdev->dev, "The tape unit cannot process "
"the tape format\n");
return tape_3490_erp_failed(request, -EMEDIUMTYPE);
case 0x30:
/* The medium is write protected. */
dev_warn (&device->cdev->dev, "The tape medium is write-"
"protected\n");
return tape_3490_erp_failed(request, -EACCES);
case 0x35:
/*
* Drive equipment check. One of the following:
* - cu cannot recover from a drive detected error
* - a check code message is shown on drive display
* - the cartridge loader does not respond correctly
* - a failure occurs during an index, load, or unload cycle
*/
dev_warn (&device->cdev->dev, "An equipment check has occurred"
" on the tape unit\n");
return tape_3490_erp_failed(request, -EIO);
case 0x36:
/* End of data. */
return tape_3490_erp_failed(request, -EIO);
case 0x38:
/*
* Physical end of tape. A read/write operation reached
* the physical end of tape.
*/
if (request->op==TO_WRI ||
request->op==TO_DSE ||
request->op==TO_WTM)
return tape_3490_erp_failed(request, -ENOSPC);
return tape_3490_erp_failed(request, -EIO);
case 0x39:
/* Backward at Beginning of tape. */
return tape_3490_erp_failed(request, -EIO);
case 0x42:
/*
* Degraded mode. A condition that can cause degraded
* performance is detected.
*/
dev_warn (&device->cdev->dev, "The tape subsystem is running "
"in degraded mode\n");
return tape_3490_erp_retry(request);
case 0x43:
/* Drive not ready. */
tape_med_state_set(device, MS_UNLOADED);
/* Some commands commands are successful even in this case */
if (sense[1] & SENSE_DRIVE_ONLINE) {
switch(request->op) {
case TO_ASSIGN:
case TO_UNASSIGN:
case TO_DIS:
case TO_NOP:
return tape_3490_done(request);
break;
default:
break;
}
}
return tape_3490_erp_failed(request, -ENOMEDIUM);
case 0x44:
/* Locate Block unsuccessful. */
if (request->op != TO_BLOCK && request->op != TO_LBL)
/* No locate block was issued. */
return tape_3490_erp_bug(device, request,
irb, sense[3]);
return tape_3490_erp_failed(request, -EIO);
case 0x45:
/* The drive is assigned to a different channel path. */
dev_warn (&device->cdev->dev, "The tape unit is already "
"assigned\n");
return tape_3490_erp_failed(request, -EIO);
case 0x47:
/* Volume fenced. CU reports volume integrity is lost. */
dev_warn (&device->cdev->dev, "The control unit has fenced "
"access to the tape volume\n");
return tape_3490_erp_failed(request, -EIO);
case 0x48:
/* Log sense data and retry request. */
return tape_3490_erp_retry(request);
case 0x4d:
/*
* Resetting event received. Since the driver does
* not support resetting event recovery (which has to
* be handled by the I/O Layer), retry our command.
*/
return tape_3490_erp_retry(request);
case 0x4e:
/*
* Maximum block size exceeded. This indicates, that
* the block to be written is larger than allowed for
* buffered mode.
*/
dev_warn (&device->cdev->dev,
"The maximum block size for buffered mode is exceeded\n");
return tape_3490_erp_failed(request, -ENOBUFS);
case 0x50:
/*
* Read buffered log (Overflow). CU is running in extended
* buffered log mode, and a counter overflows. This should
* never happen, since we're never running in extended
* buffered log mode.
*/
return tape_3490_erp_retry(request);
case 0x51:
/*
* Read buffered log (EOV). EOF processing occurs while the
* CU is in extended buffered log mode. This should never
* happen, since we're never running in extended buffered
* log mode.
*/
return tape_3490_erp_retry(request);
case 0x52:
/* End of Volume complete. Rewind unload completed ok. */
if (request->op == TO_RUN) {
tape_med_state_set(device, MS_UNLOADED);
return tape_3490_erp_succeeded(request);
}
return tape_3490_erp_bug(device, request, irb, sense[3]);
case 0x53:
/* Global command intercept. */
return tape_3490_erp_retry(request);
case 0x54:
/* Channel interface recovery (temporary). */
return tape_3490_erp_retry(request);
case 0x55:
/* Channel interface recovery (permanent). */
dev_warn (&device->cdev->dev, "A channel interface error cannot be"
" recovered\n");
return tape_3490_erp_failed(request, -EIO);
case 0x56:
/* Channel protocol error. */
dev_warn (&device->cdev->dev, "A channel protocol error "
"occurred\n");
return tape_3490_erp_failed(request, -EIO);
case 0x57:
/* Global status intercept. */
return tape_3490_erp_retry(request);
/* The following erpas should have been covered earlier. */
case 0x23: /* Read data check. */
case 0x25: /* Write data check. */
case 0x28: /* Write id mark check. */
case 0x31: /* Tape void. */
case 0x40: /* Overrun error. */
case 0x41: /* Record sequence error. */
/* All other erpas are reserved for future use. */
default:
return tape_3490_erp_bug(device, request, irb, sense[3]);
}
}
/*
* 3490 interrupt handler
*/
static int
tape_3490_irq(struct tape_device *device, struct tape_request *request,
struct irb *irb)
{
if (request == NULL)
return tape_3490_unsolicited_irq(device, irb);
if ((irb->scsw.cmd.dstat & DEV_STAT_UNIT_EXCEP) &&
(irb->scsw.cmd.dstat & DEV_STAT_DEV_END) &&
(request->op == TO_WRI)) {
/* Write at end of volume */
return tape_3490_erp_failed(request, -ENOSPC);
}
if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK)
return tape_3490_unit_check(device, request, irb);
if (irb->scsw.cmd.dstat & DEV_STAT_DEV_END) {
/*
* A unit exception occurs on skipping over a tapemark block.
*/
if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_EXCEP) {
if (request->op == TO_BSB || request->op == TO_FSB)
request->rescnt++;
else
DBF_EVENT(5, "Unit Exception!\n");
}
return tape_3490_done(request);
}
DBF_EVENT(6, "xunknownirq\n");
tape_dump_sense_dbf(device, request, irb);
return TAPE_IO_STOP;
}
static int
tape_3490_setup_device(struct tape_device * device)
{
int rc;
DBF_EVENT(6, "3490 device setup\n");
if ((rc = tape_std_assign(device)) == 0) {
if ((rc = tape_3490_medium_sense(device)) != 0) {
DBF_LH(3, "3490 medium sense returned %d\n", rc);
}
}
return rc;
}
static void
tape_3490_cleanup_device(struct tape_device *device)
{
tape_std_unassign(device);
}
/*
* MTTELL: Tell block. Return the number of block relative to current file.
*/
static int
tape_3490_mttell(struct tape_device *device, int mt_count)
{
struct {
struct tape_3490_block_id cbid;
struct tape_3490_block_id dbid;
} __attribute__ ((packed)) block_id;
int rc;
rc = tape_std_read_block_id(device, (__u64 *) &block_id);
if (rc)
return rc;
return block_id.cbid.block;
}
/*
* MTSEEK: seek to the specified block.
*/
static int
tape_3490_mtseek(struct tape_device *device, int mt_count)
{
struct tape_request *request;
struct tape_3490_block_id * bid;
if (mt_count > 0x3fffff) {
DBF_EXCEPTION(6, "xsee parm\n");
return -EINVAL;
}
request = tape_alloc_request(3, 4);
if (IS_ERR(request))
return PTR_ERR(request);
/* setup ccws */
request->op = TO_LBL;
bid = (struct tape_3490_block_id *) request->cpdata;
bid->block = mt_count;
tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte);
tape_ccw_cc(request->cpaddr + 1, LOCATE, 4, request->cpdata);
tape_ccw_end(request->cpaddr + 2, NOP, 0, NULL);
/* execute it */
return tape_do_io_free(device, request);
}
/*
* List of 3490 tape commands.
*/
static tape_mtop_fn tape_3490_mtop[TAPE_NR_MTOPS] = {
[MTRESET] = tape_std_mtreset,
[MTFSF] = tape_std_mtfsf,
[MTBSF] = tape_std_mtbsf,
[MTFSR] = tape_std_mtfsr,
[MTBSR] = tape_std_mtbsr,
[MTWEOF] = tape_std_mtweof,
[MTREW] = tape_std_mtrew,
[MTOFFL] = tape_std_mtoffl,
[MTNOP] = tape_std_mtnop,
[MTRETEN] = tape_std_mtreten,
[MTBSFM] = tape_std_mtbsfm,
[MTFSFM] = tape_std_mtfsfm,
[MTEOM] = tape_std_mteom,
[MTERASE] = tape_std_mterase,
[MTRAS1] = NULL,
[MTRAS2] = NULL,
[MTRAS3] = NULL,
[MTSETBLK] = tape_std_mtsetblk,
[MTSETDENSITY] = NULL,
[MTSEEK] = tape_3490_mtseek,
[MTTELL] = tape_3490_mttell,
[MTSETDRVBUFFER] = NULL,
[MTFSS] = NULL,
[MTBSS] = NULL,
[MTWSM] = NULL,
[MTLOCK] = NULL,
[MTUNLOCK] = NULL,
[MTLOAD] = tape_std_mtload,
[MTUNLOAD] = tape_std_mtunload,
[MTCOMPRESSION] = tape_std_mtcompression,
[MTSETPART] = NULL,
[MTMKPART] = NULL
};
/*
* Tape discipline structure for 3490.
*/
static struct tape_discipline tape_discipline_3490 = {
.owner = THIS_MODULE,
.setup_device = tape_3490_setup_device,
.cleanup_device = tape_3490_cleanup_device,
.process_eov = tape_std_process_eov,
.irq = tape_3490_irq,
.read_block = tape_std_read_block,
.write_block = tape_std_write_block,
.mtop_array = tape_3490_mtop
};
static struct ccw_device_id tape_3490_ids[] = {
{ CCW_DEVICE_DEVTYPE(0x3490, 0, 0x3490, 0), .driver_info = tape_3490},
{ /* end of list */ },
};
static int
tape_3490_online(struct ccw_device *cdev)
{
return tape_generic_online(
dev_get_drvdata(&cdev->dev),
&tape_discipline_3490
);
}
static struct ccw_driver tape_3490_driver = {
.driver = {
.name = "tape_3490",
.owner = THIS_MODULE,
},
.ids = tape_3490_ids,
.probe = tape_generic_probe,
.remove = tape_generic_remove,
.set_online = tape_3490_online,
.set_offline = tape_generic_offline,
.int_class = IRQIO_TAP,
};
int tape_3490_init(void)
{
int rc;
TAPE_DBF_AREA = debug_register ( "tape_3490", 2, 2, 4*sizeof(long));
debug_register_view(TAPE_DBF_AREA, &debug_sprintf_view);
#ifdef DBF_LIKE_HELL
debug_set_level(TAPE_DBF_AREA, 6);
#endif
DBF_EVENT(3, "3490 init\n");
/* Register driver for 3490 tapes. */
rc = ccw_driver_register(&tape_3490_driver);
if (rc)
DBF_EVENT(3, "3490 init failed\n");
else
DBF_EVENT(3, "3490 registered\n");
return rc;
}
void tape_3490_exit(void)
{
ccw_driver_unregister(&tape_3490_driver);
debug_unregister(TAPE_DBF_AREA);
}
MODULE_DEVICE_TABLE(ccw, tape_3490_ids);

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,175 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* tape device discipline for 3590 tapes.
*
* Copyright IBM Corp. 2001, 2006
* Author(s): Stefan Bader <shbader@de.ibm.com>
* Michael Holzheu <holzheu@de.ibm.com>
* Martin Schwidefsky <schwidefsky@de.ibm.com>
*/
#ifndef _TAPE_3590_H
#define _TAPE_3590_H
#define MEDIUM_SENSE 0xc2
#define READ_PREVIOUS 0x0a
#define MODE_SENSE 0xcf
#define PERFORM_SS_FUNC 0x77
#define READ_SS_DATA 0x3e
#define PREP_RD_SS_DATA 0x18
#define RD_ATTMSG 0x3
#define SENSE_BRA_PER 0
#define SENSE_BRA_CONT 1
#define SENSE_BRA_RE 2
#define SENSE_BRA_DRE 3
#define SENSE_FMT_LIBRARY 0x23
#define SENSE_FMT_UNSOLICITED 0x40
#define SENSE_FMT_COMMAND_REJ 0x41
#define SENSE_FMT_COMMAND_EXEC0 0x50
#define SENSE_FMT_COMMAND_EXEC1 0x51
#define SENSE_FMT_EVENT0 0x60
#define SENSE_FMT_EVENT1 0x61
#define SENSE_FMT_MIM 0x70
#define SENSE_FMT_SIM 0x71
#define MSENSE_UNASSOCIATED 0x00
#define MSENSE_ASSOCIATED_MOUNT 0x01
#define MSENSE_ASSOCIATED_UMOUNT 0x02
#define MSENSE_CRYPT_MASK 0x00000010
#define TAPE_3590_MAX_MSG 0xb0
/* Datatypes */
struct tape_3590_disc_data {
struct tape390_crypt_info crypt_info;
int read_back_op;
};
#define TAPE_3590_CRYPT_INFO(device) \
((struct tape_3590_disc_data*)(device->discdata))->crypt_info
#define TAPE_3590_READ_BACK_OP(device) \
((struct tape_3590_disc_data*)(device->discdata))->read_back_op
struct tape_3590_sense {
unsigned int command_rej:1;
unsigned int interv_req:1;
unsigned int bus_out_check:1;
unsigned int eq_check:1;
unsigned int data_check:1;
unsigned int overrun:1;
unsigned int def_unit_check:1;
unsigned int assgnd_elsew:1;
unsigned int locate_fail:1;
unsigned int inst_online:1;
unsigned int reserved:1;
unsigned int blk_seq_err:1;
unsigned int begin_part:1;
unsigned int wr_mode:1;
unsigned int wr_prot:1;
unsigned int not_cap:1;
unsigned int bra:2;
unsigned int lc:3;
unsigned int vlf_active:1;
unsigned int stm:1;
unsigned int med_pos:1;
unsigned int rac:8;
unsigned int rc_rqc:16;
unsigned int mc:8;
unsigned int sense_fmt:8;
union {
struct {
unsigned int emc:4;
unsigned int smc:4;
unsigned int sev:2;
unsigned int reserved:6;
unsigned int md:8;
unsigned int refcode:8;
unsigned int mid:16;
unsigned int mp:16;
unsigned char volid[6];
unsigned int fid:8;
} f70;
struct {
unsigned int emc:4;
unsigned int smc:4;
unsigned int sev:2;
unsigned int reserved1:5;
unsigned int mdf:1;
unsigned char md[3];
unsigned int simid:8;
unsigned int uid:16;
unsigned int refcode1:16;
unsigned int refcode2:16;
unsigned int refcode3:16;
unsigned int reserved2:8;
} f71;
unsigned char data[14];
} fmt;
unsigned char pad[10];
} __attribute__ ((packed));
struct tape_3590_med_sense {
unsigned int macst:4;
unsigned int masst:4;
char pad1[7];
unsigned int flags;
char pad2[116];
} __attribute__ ((packed));
struct tape_3590_rdc_data {
char data[64];
} __attribute__ ((packed));
/* Datastructures for 3592 encryption support */
struct tape3592_kekl {
__u8 flags;
char label[64];
} __attribute__ ((packed));
struct tape3592_kekl_pair {
__u8 count;
struct tape3592_kekl kekl[2];
} __attribute__ ((packed));
struct tape3592_kekl_query_data {
__u16 len;
__u8 fmt;
__u8 mc;
__u32 id;
__u8 flags;
struct tape3592_kekl_pair kekls;
char reserved[116];
} __attribute__ ((packed));
struct tape3592_kekl_query_order {
__u8 code;
__u8 flags;
char reserved1[2];
__u8 max_count;
char reserved2[35];
} __attribute__ ((packed));
struct tape3592_kekl_set_order {
__u8 code;
__u8 flags;
char reserved1[2];
__u8 op;
struct tape3592_kekl_pair kekls;
char reserved2[120];
} __attribute__ ((packed));
#endif /* _TAPE_3590_H */

View file

@ -412,10 +412,7 @@ __tapechar_ioctl(struct tape_device *device,
return put_user_mtget(data, &get);
}
/* Try the discipline ioctl function. */
if (device->discipline->ioctl_fn == NULL)
return -EINVAL;
return device->discipline->ioctl_fn(device, no, (unsigned long)data);
return -EINVAL;
}
static long

View file

@ -15,13 +15,6 @@
#include "tape_class.h"
MODULE_AUTHOR("Stefan Bader <shbader@de.ibm.com>");
MODULE_DESCRIPTION(
"Copyright IBM Corp. 2004 All Rights Reserved.\n"
"tape_class.c"
);
MODULE_LICENSE("GPL");
static const struct class tape_class = {
.name = "tape390",
};
@ -116,16 +109,12 @@ void unregister_tape_dev(struct device *device, struct tape_class_device *tcd)
}
EXPORT_SYMBOL(unregister_tape_dev);
static int __init tape_init(void)
int tape_class_init(void)
{
return class_register(&tape_class);
}
static void __exit tape_exit(void)
void tape_class_exit(void)
{
class_unregister(&tape_class);
}
postcore_initcall(tape_init);
module_exit(tape_exit);

View file

@ -55,5 +55,7 @@ struct tape_class_device *register_tape_dev(
char * node_name
);
void unregister_tape_dev(struct device *device, struct tape_class_device *tcd);
int tape_class_init(void);
void tape_class_exit(void);
#endif /* __TAPE_CLASS_H__ */

View file

@ -28,6 +28,7 @@
#include "tape.h"
#include "tape_std.h"
#include "tape_class.h"
#define LONG_BUSY_TIMEOUT 180 /* seconds */
@ -74,9 +75,7 @@ const char *tape_op_verbose[TO_SIZE] =
[TO_LOAD] = "LOA", [TO_READ_CONFIG] = "RCF",
[TO_READ_ATTMSG] = "RAT",
[TO_DIS] = "DIS", [TO_ASSIGN] = "ASS",
[TO_UNASSIGN] = "UAS", [TO_CRYPT_ON] = "CON",
[TO_CRYPT_OFF] = "COF", [TO_KEKL_SET] = "KLS",
[TO_KEKL_QUERY] = "KLQ",[TO_RDC] = "RDC",
[TO_UNASSIGN] = "UAS", [TO_RDC] = "RDC",
};
static int devid_to_int(struct ccw_dev_id *dev_id)
@ -1312,7 +1311,9 @@ tape_init (void)
#endif
DBF_EVENT(3, "tape init\n");
tape_proc_init();
tape_class_init();
tapechar_init ();
tape_3490_init();
return 0;
}
@ -1325,14 +1326,15 @@ tape_exit(void)
DBF_EVENT(6, "tape exit\n");
/* Get rid of the frontends */
tape_3490_exit();
tapechar_exit();
tape_class_exit();
tape_proc_cleanup();
debug_unregister (TAPE_DBF_AREA);
}
MODULE_AUTHOR("(C) 2001 IBM Deutschland Entwicklung GmbH by Carsten Otte and "
"Michael Holzheu (cotte@de.ibm.com,holzheu@de.ibm.com)");
MODULE_DESCRIPTION("Linux on zSeries channel attached tape device driver");
MODULE_AUTHOR("IBM Corporation");
MODULE_DESCRIPTION("s390 channel-attached tape device driver");
MODULE_LICENSE("GPL");
module_init(tape_init);

View file

@ -22,7 +22,6 @@
#include <asm/types.h>
#include <asm/idals.h>
#include <asm/ebcdic.h>
#include <asm/tape390.h>
#define TAPE_DBF_AREA tape_core_dbf
@ -118,36 +117,6 @@ tape_std_unassign (struct tape_device *device)
return rc;
}
/*
* TAPE390_DISPLAY: Show a string on the tape display.
*/
int
tape_std_display(struct tape_device *device, struct display_struct *disp)
{
struct tape_request *request;
int rc;
request = tape_alloc_request(2, 17);
if (IS_ERR(request)) {
DBF_EVENT(3, "TAPE: load display failed\n");
return PTR_ERR(request);
}
request->op = TO_DIS;
*(unsigned char *) request->cpdata = disp->cntrl;
DBF_EVENT(5, "TAPE: display cntrl=%04x\n", disp->cntrl);
memcpy(((unsigned char *) request->cpdata) + 1, disp->message1, 8);
memcpy(((unsigned char *) request->cpdata) + 9, disp->message2, 8);
ASCEBC(((unsigned char*) request->cpdata) + 1, 16);
tape_ccw_cc(request->cpaddr, LOAD_DISPLAY, 17, request->cpdata);
tape_ccw_end(request->cpaddr + 1, NOP, 0, NULL);
rc = tape_do_io_interruptible(device, request);
tape_free_request(request);
return rc;
}
/*
* Read block id.
*/
@ -696,7 +665,6 @@ tape_std_process_eov(struct tape_device *device)
EXPORT_SYMBOL(tape_std_assign);
EXPORT_SYMBOL(tape_std_unassign);
EXPORT_SYMBOL(tape_std_display);
EXPORT_SYMBOL(tape_std_read_block_id);
EXPORT_SYMBOL(tape_std_mtload);
EXPORT_SYMBOL(tape_std_mtsetblk);

View file

@ -11,8 +11,6 @@
#ifndef _TAPE_STD_H
#define _TAPE_STD_H
#include <asm/tape390.h>
/*
* Biggest block size of 256K to handle.
*/
@ -21,54 +19,25 @@
/*
* The CCW commands for the Tape type of command.
*/
#define INVALID_00 0x00 /* Invalid cmd */
#define BACKSPACEBLOCK 0x27 /* Back Space block */
#define BACKSPACEFILE 0x2f /* Back Space file */
#define DATA_SEC_ERASE 0x97 /* Data security erase */
#define ERASE_GAP 0x17 /* Erase Gap */
#define FORSPACEBLOCK 0x37 /* Forward space block */
#define FORSPACEFILE 0x3F /* Forward Space file */
#define FORCE_STREAM_CNT 0xEB /* Forced streaming count # */
#define NOP 0x03 /* No operation */
#define READ_FORWARD 0x02 /* Read forward */
#define REWIND 0x07 /* Rewind */
#define REWIND_UNLOAD 0x0F /* Rewind and Unload */
#define SENSE 0x04 /* Sense */
#define NEW_MODE_SET 0xEB /* Guess it is Mode set */
#define WRITE_CMD 0x01 /* Write */
#define WRITETAPEMARK 0x1F /* Write Tape Mark */
#define ASSIGN 0xB7 /* 3420 REJECT,3480 OK */
#define CONTROL_ACCESS 0xE3 /* Set high speed */
#define DIAG_MODE_SET 0x0B /* 3420 NOP, 3480 REJECT */
#define LOAD_DISPLAY 0x9F /* 3420 REJECT,3480 OK */
#define LOCATE 0x4F /* 3420 REJ, 3480 NOP */
#define LOOP_WRITE_TO_READ 0x8B /* 3480 REJECT */
#define MODE_SET_DB 0xDB /* 3420 REJECT,3480 OK */
#define MODE_SET_C3 0xC3 /* for 3420 */
#define MODE_SET_CB 0xCB /* for 3420 */
#define MODE_SET_D3 0xD3 /* for 3420 */
#define READ_BACKWARD 0x0C /* */
#define READ_BLOCK_ID 0x22 /* 3420 REJECT,3480 OK */
#define READ_BUFFER 0x12 /* 3420 REJECT,3480 OK */
#define READ_BUFF_LOG 0x24 /* 3420 REJECT,3480 OK */
#define RELEASE 0xD4 /* 3420 NOP, 3480 REJECT */
#define REQ_TRK_IN_ERROR 0x1B /* 3420 NOP, 3480 REJECT */
#define RESERVE 0xF4 /* 3420 NOP, 3480 REJECT */
#define SENSE_GROUP_ID 0x34 /* 3420 REJECT,3480 OK */
#define SENSE_ID 0xE4 /* 3420 REJECT,3480 OK */
#define READ_DEV_CHAR 0x64 /* Read device characteristics */
#define SET_DIAGNOSE 0x4B /* 3420 NOP, 3480 REJECT */
#define SET_GROUP_ID 0xAF /* 3420 REJECT,3480 OK */
#define SET_TAPE_WRITE_IMMED 0xC3 /* for 3480 */
#define SUSPEND 0x5B /* 3420 REJ, 3480 NOP */
#define SYNC 0x43 /* Synchronize (flush buffer) */
#define UNASSIGN 0xC7 /* 3420 REJECT,3480 OK */
#define PERF_SUBSYS_FUNC 0x77 /* 3490 CMD */
#define READ_CONFIG_DATA 0xFA /* 3490 CMD */
#define READ_MESSAGE_ID 0x4E /* 3490 CMD */
#define READ_SUBSYS_DATA 0x3E /* 3490 CMD */
#define SET_INTERFACE_ID 0x73 /* 3490 CMD */
#define ASSIGN 0xB7 /* Assign */
#define LOCATE 0x4F /* Locate Block */
#define MODE_SET_DB 0xDB /* Mode Set */
#define READ_BLOCK_ID 0x22 /* Read Block ID */
#define UNASSIGN 0xC7 /* Unassign */
#define SENSE_COMMAND_REJECT 0x80
#define SENSE_INTERVENTION_REQUIRED 0x40
@ -105,7 +74,6 @@ struct tape_request *tape_std_write_block(struct tape_device *);
int tape_std_assign(struct tape_device *);
int tape_std_unassign(struct tape_device *);
int tape_std_read_block_id(struct tape_device *device, __u64 *id);
int tape_std_display(struct tape_device *, struct display_struct *disp);
int tape_std_terminate_write(struct tape_device *);
/* Standard magnetic tape commands. */
@ -133,10 +101,7 @@ void tape_std_process_eov(struct tape_device *);
/* S390 tape types */
enum s390_tape_type {
tape_3480,
tape_3490,
tape_3590,
tape_3592,
};
#endif // _TAPE_STD_H

View file

@ -235,7 +235,7 @@ struct subchannel *css_alloc_subchannel(struct subchannel_id schid,
return sch;
err:
kfree(sch);
put_device(&sch->dev);
return ERR_PTR(ret);
}

View file

@ -52,24 +52,24 @@ MODULE_LICENSE("GPL");
int ap_domain_index = -1; /* Adjunct Processor Domain Index */
static DEFINE_SPINLOCK(ap_domain_lock);
module_param_named(domain, ap_domain_index, int, 0440);
module_param_named(domain, ap_domain_index, int, 0444);
MODULE_PARM_DESC(domain, "domain index for ap devices");
EXPORT_SYMBOL(ap_domain_index);
static int ap_thread_flag;
module_param_named(poll_thread, ap_thread_flag, int, 0440);
module_param_named(poll_thread, ap_thread_flag, int, 0444);
MODULE_PARM_DESC(poll_thread, "Turn on/off poll thread, default is 0 (off).");
static char *apm_str;
module_param_named(apmask, apm_str, charp, 0440);
module_param_named(apmask, apm_str, charp, 0444);
MODULE_PARM_DESC(apmask, "AP bus adapter mask.");
static char *aqm_str;
module_param_named(aqmask, aqm_str, charp, 0440);
module_param_named(aqmask, aqm_str, charp, 0444);
MODULE_PARM_DESC(aqmask, "AP bus domain mask.");
static int ap_useirq = 1;
module_param_named(useirq, ap_useirq, int, 0440);
module_param_named(useirq, ap_useirq, int, 0444);
MODULE_PARM_DESC(useirq, "Use interrupt if available, default is 1 (on).");
atomic_t ap_max_msg_size = ATOMIC_INIT(AP_DEFAULT_MAX_MSG_SIZE);
@ -130,7 +130,7 @@ debug_info_t *ap_dbf_info;
*/
static mempool_t *ap_msg_pool;
static unsigned int ap_msg_pool_min_items = 8;
module_param_named(msgpool_min_items, ap_msg_pool_min_items, uint, 0440);
module_param_named(msgpool_min_items, ap_msg_pool_min_items, uint, 0400);
MODULE_PARM_DESC(msgpool_min_items, "AP message pool minimal items");
/*

View file

@ -50,7 +50,7 @@ MODULE_DESCRIPTION("Cryptographic Coprocessor interface, " \
MODULE_LICENSE("GPL");
unsigned int zcrypt_mempool_threshold = 5;
module_param_named(mempool_threshold, zcrypt_mempool_threshold, uint, 0440);
module_param_named(mempool_threshold, zcrypt_mempool_threshold, uint, 0400);
MODULE_PARM_DESC(mempool_threshold, "CCA and EP11 request/reply mempool minimal items (min: 1)");
/*