^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #ifndef S390_CIO_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #define S390_CIO_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/mod_devicetable.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <asm/chpid.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <asm/cio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <asm/fcx.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <asm/schid.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "chsc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * path management control word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) struct pmcw {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) u32 intparm; /* interruption parameter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) u32 qf : 1; /* qdio facility */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) u32 w : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) u32 isc : 3; /* interruption sublass */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) u32 res5 : 3; /* reserved zeros */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) u32 ena : 1; /* enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) u32 lm : 2; /* limit mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) u32 mme : 2; /* measurement-mode enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) u32 mp : 1; /* multipath mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) u32 tf : 1; /* timing facility */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) u32 dnv : 1; /* device number valid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) u32 dev : 16; /* device number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) u8 lpm; /* logical path mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) u8 pnom; /* path not operational mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) u8 lpum; /* last path used mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) u8 pim; /* path installed mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) u16 mbi; /* measurement-block index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) u8 pom; /* path operational mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) u8 pam; /* path available mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) u8 chpid[8]; /* CHPID 0-7 (if available) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) u32 unused1 : 8; /* reserved zeros */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) u32 st : 3; /* subchannel type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) u32 unused2 : 18; /* reserved zeros */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) u32 mbfc : 1; /* measurement block format control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) u32 xmwme : 1; /* extended measurement word mode enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) u32 csense : 1; /* concurrent sense; can be enabled ...*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) /* ... per MSCH, however, if facility */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) /* ... is not installed, this results */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) /* ... in an operand exception. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) } __attribute__ ((packed));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /* I/O-Interruption Code as stored by TEST PENDING INTERRUPTION (TPI). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct tpi_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) struct subchannel_id schid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) u32 intparm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) u32 adapter_IO:1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) u32 directed_irq:1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) u32 isc:3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) u32 :27;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) u32 type:3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) u32 :12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) } __packed __aligned(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) /* Target SCHIB configuration. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) struct schib_config {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) u64 mba;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) u32 intparm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) u16 mbi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) u32 isc:3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) u32 ena:1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) u32 mme:2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) u32 mp:1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) u32 csense:1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) u32 mbfc:1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) } __attribute__ ((packed));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * subchannel information block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct schib {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) struct pmcw pmcw; /* path management control word */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) union scsw scsw; /* subchannel status word */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) __u64 mba; /* measurement block address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) __u8 mda[4]; /* model dependent area */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) } __attribute__ ((packed,aligned(4)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * When rescheduled, todo's with higher values will overwrite those
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * with lower values.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) enum sch_todo {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) SCH_TODO_NOTHING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) SCH_TODO_EVAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) SCH_TODO_UNREG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) /* subchannel data structure used by I/O subroutines */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) struct subchannel {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) struct subchannel_id schid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) spinlock_t *lock; /* subchannel lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct mutex reg_mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) SUBCHANNEL_TYPE_IO = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) SUBCHANNEL_TYPE_CHSC = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) SUBCHANNEL_TYPE_MSG = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) SUBCHANNEL_TYPE_ADM = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) } st; /* subchannel type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) __u8 vpm; /* verified path mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) __u8 lpm; /* logical path mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) __u8 opm; /* operational path mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct schib schib; /* subchannel information block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) int isc; /* desired interruption subclass */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) struct chsc_ssd_info ssd_info; /* subchannel description */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) struct device dev; /* entry in device tree */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) struct css_driver *driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) enum sch_todo todo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) struct work_struct todo_work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) struct schib_config config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) u64 dma_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) char *driver_override; /* Driver name to force a match */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) } __attribute__ ((aligned(8)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) DECLARE_PER_CPU_ALIGNED(struct irb, cio_irb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) #define to_subchannel(n) container_of(n, struct subchannel, dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) extern int cio_enable_subchannel(struct subchannel *, u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) extern int cio_disable_subchannel (struct subchannel *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) extern int cio_cancel (struct subchannel *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) extern int cio_clear (struct subchannel *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) extern int cio_cancel_halt_clear(struct subchannel *, int *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) extern int cio_resume (struct subchannel *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) extern int cio_halt (struct subchannel *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) extern int cio_start (struct subchannel *, struct ccw1 *, __u8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) extern int cio_start_key (struct subchannel *, struct ccw1 *, __u8, __u8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) extern int cio_set_options (struct subchannel *, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) extern int cio_update_schib(struct subchannel *sch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) extern int cio_commit_config(struct subchannel *sch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) int cio_tm_start_key(struct subchannel *sch, struct tcw *tcw, u8 lpm, u8 key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) int cio_tm_intrg(struct subchannel *sch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) extern int __init airq_init(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /* Use with care. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #ifdef CONFIG_CCW_CONSOLE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) extern struct subchannel *cio_probe_console(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) extern int cio_is_console(struct subchannel_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) extern void cio_register_early_subchannels(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) extern void cio_tsch(struct subchannel *sch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) #define cio_is_console(schid) 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) static inline void cio_register_early_subchannels(void) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) #endif