1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 211b64c8aSPeter Oberparleiter /* 311b64c8aSPeter Oberparleiter * Channel subsystem I/O instructions. 411b64c8aSPeter Oberparleiter */ 511b64c8aSPeter Oberparleiter 611b64c8aSPeter Oberparleiter #include <linux/export.h> 711b64c8aSPeter Oberparleiter 811b64c8aSPeter Oberparleiter #include <asm/chpid.h> 911b64c8aSPeter Oberparleiter #include <asm/schid.h> 1011b64c8aSPeter Oberparleiter #include <asm/crw.h> 1111b64c8aSPeter Oberparleiter 1211b64c8aSPeter Oberparleiter #include "ioasm.h" 1311b64c8aSPeter Oberparleiter #include "orb.h" 1411b64c8aSPeter Oberparleiter #include "cio.h" 1511b64c8aSPeter Oberparleiter 16a4d9b97cSHeiko Carstens static inline int __stsch(struct subchannel_id schid, struct schib *addr) 1711b64c8aSPeter Oberparleiter { 1811b64c8aSPeter Oberparleiter register struct subchannel_id reg1 asm ("1") = schid; 1911b64c8aSPeter Oberparleiter int ccode = -EIO; 2011b64c8aSPeter Oberparleiter 2111b64c8aSPeter Oberparleiter asm volatile( 2211b64c8aSPeter Oberparleiter " stsch 0(%3)\n" 2311b64c8aSPeter Oberparleiter "0: ipm %0\n" 2411b64c8aSPeter Oberparleiter " srl %0,28\n" 2511b64c8aSPeter Oberparleiter "1:\n" 2611b64c8aSPeter Oberparleiter EX_TABLE(0b, 1b) 2711b64c8aSPeter Oberparleiter : "+d" (ccode), "=m" (*addr) 2811b64c8aSPeter Oberparleiter : "d" (reg1), "a" (addr) 2911b64c8aSPeter Oberparleiter : "cc"); 30a4d9b97cSHeiko Carstens return ccode; 31a4d9b97cSHeiko Carstens } 32a4d9b97cSHeiko Carstens 33a4d9b97cSHeiko Carstens int stsch(struct subchannel_id schid, struct schib *addr) 34a4d9b97cSHeiko Carstens { 35a4d9b97cSHeiko Carstens int ccode; 36a4d9b97cSHeiko Carstens 37a4d9b97cSHeiko Carstens ccode = __stsch(schid, addr); 3811b64c8aSPeter Oberparleiter trace_s390_cio_stsch(schid, addr, ccode); 3911b64c8aSPeter Oberparleiter 4011b64c8aSPeter Oberparleiter return ccode; 4111b64c8aSPeter Oberparleiter } 4211b64c8aSPeter Oberparleiter EXPORT_SYMBOL(stsch); 4311b64c8aSPeter Oberparleiter 44a4d9b97cSHeiko Carstens static inline int __msch(struct subchannel_id schid, struct schib *addr) 4511b64c8aSPeter Oberparleiter { 4611b64c8aSPeter Oberparleiter register struct subchannel_id reg1 asm ("1") = schid; 4711b64c8aSPeter Oberparleiter int ccode = -EIO; 4811b64c8aSPeter Oberparleiter 4911b64c8aSPeter Oberparleiter asm volatile( 5011b64c8aSPeter Oberparleiter " msch 0(%2)\n" 5111b64c8aSPeter Oberparleiter "0: ipm %0\n" 5211b64c8aSPeter Oberparleiter " srl %0,28\n" 5311b64c8aSPeter Oberparleiter "1:\n" 5411b64c8aSPeter Oberparleiter EX_TABLE(0b, 1b) 5511b64c8aSPeter Oberparleiter : "+d" (ccode) 5611b64c8aSPeter Oberparleiter : "d" (reg1), "a" (addr), "m" (*addr) 5711b64c8aSPeter Oberparleiter : "cc"); 58a4d9b97cSHeiko Carstens return ccode; 59a4d9b97cSHeiko Carstens } 60a4d9b97cSHeiko Carstens 61a4d9b97cSHeiko Carstens int msch(struct subchannel_id schid, struct schib *addr) 62a4d9b97cSHeiko Carstens { 63a4d9b97cSHeiko Carstens int ccode; 64a4d9b97cSHeiko Carstens 65a4d9b97cSHeiko Carstens ccode = __msch(schid, addr); 6611b64c8aSPeter Oberparleiter trace_s390_cio_msch(schid, addr, ccode); 6711b64c8aSPeter Oberparleiter 6811b64c8aSPeter Oberparleiter return ccode; 6911b64c8aSPeter Oberparleiter } 7011b64c8aSPeter Oberparleiter 71a4d9b97cSHeiko Carstens static inline int __tsch(struct subchannel_id schid, struct irb *addr) 7211b64c8aSPeter Oberparleiter { 7311b64c8aSPeter Oberparleiter register struct subchannel_id reg1 asm ("1") = schid; 7411b64c8aSPeter Oberparleiter int ccode; 7511b64c8aSPeter Oberparleiter 7611b64c8aSPeter Oberparleiter asm volatile( 7711b64c8aSPeter Oberparleiter " tsch 0(%3)\n" 7811b64c8aSPeter Oberparleiter " ipm %0\n" 7911b64c8aSPeter Oberparleiter " srl %0,28" 8011b64c8aSPeter Oberparleiter : "=d" (ccode), "=m" (*addr) 8111b64c8aSPeter Oberparleiter : "d" (reg1), "a" (addr) 8211b64c8aSPeter Oberparleiter : "cc"); 83a4d9b97cSHeiko Carstens return ccode; 84a4d9b97cSHeiko Carstens } 85a4d9b97cSHeiko Carstens 86a4d9b97cSHeiko Carstens int tsch(struct subchannel_id schid, struct irb *addr) 87a4d9b97cSHeiko Carstens { 88a4d9b97cSHeiko Carstens int ccode; 89a4d9b97cSHeiko Carstens 90a4d9b97cSHeiko Carstens ccode = __tsch(schid, addr); 9111b64c8aSPeter Oberparleiter trace_s390_cio_tsch(schid, addr, ccode); 9211b64c8aSPeter Oberparleiter 9311b64c8aSPeter Oberparleiter return ccode; 9411b64c8aSPeter Oberparleiter } 9511b64c8aSPeter Oberparleiter 96a4d9b97cSHeiko Carstens static inline int __ssch(struct subchannel_id schid, union orb *addr) 9711b64c8aSPeter Oberparleiter { 9811b64c8aSPeter Oberparleiter register struct subchannel_id reg1 asm("1") = schid; 9911b64c8aSPeter Oberparleiter int ccode = -EIO; 10011b64c8aSPeter Oberparleiter 10111b64c8aSPeter Oberparleiter asm volatile( 10211b64c8aSPeter Oberparleiter " ssch 0(%2)\n" 10311b64c8aSPeter Oberparleiter "0: ipm %0\n" 10411b64c8aSPeter Oberparleiter " srl %0,28\n" 10511b64c8aSPeter Oberparleiter "1:\n" 10611b64c8aSPeter Oberparleiter EX_TABLE(0b, 1b) 10711b64c8aSPeter Oberparleiter : "+d" (ccode) 10811b64c8aSPeter Oberparleiter : "d" (reg1), "a" (addr), "m" (*addr) 10911b64c8aSPeter Oberparleiter : "cc", "memory"); 110a4d9b97cSHeiko Carstens return ccode; 111a4d9b97cSHeiko Carstens } 112a4d9b97cSHeiko Carstens 113a4d9b97cSHeiko Carstens int ssch(struct subchannel_id schid, union orb *addr) 114a4d9b97cSHeiko Carstens { 115a4d9b97cSHeiko Carstens int ccode; 116a4d9b97cSHeiko Carstens 117a4d9b97cSHeiko Carstens ccode = __ssch(schid, addr); 11811b64c8aSPeter Oberparleiter trace_s390_cio_ssch(schid, addr, ccode); 11911b64c8aSPeter Oberparleiter 12011b64c8aSPeter Oberparleiter return ccode; 12111b64c8aSPeter Oberparleiter } 12211b64c8aSPeter Oberparleiter EXPORT_SYMBOL(ssch); 12311b64c8aSPeter Oberparleiter 124a4d9b97cSHeiko Carstens static inline int __csch(struct subchannel_id schid) 12511b64c8aSPeter Oberparleiter { 12611b64c8aSPeter Oberparleiter register struct subchannel_id reg1 asm("1") = schid; 12711b64c8aSPeter Oberparleiter int ccode; 12811b64c8aSPeter Oberparleiter 12911b64c8aSPeter Oberparleiter asm volatile( 13011b64c8aSPeter Oberparleiter " csch\n" 13111b64c8aSPeter Oberparleiter " ipm %0\n" 13211b64c8aSPeter Oberparleiter " srl %0,28" 13311b64c8aSPeter Oberparleiter : "=d" (ccode) 13411b64c8aSPeter Oberparleiter : "d" (reg1) 13511b64c8aSPeter Oberparleiter : "cc"); 136a4d9b97cSHeiko Carstens return ccode; 137a4d9b97cSHeiko Carstens } 138a4d9b97cSHeiko Carstens 139a4d9b97cSHeiko Carstens int csch(struct subchannel_id schid) 140a4d9b97cSHeiko Carstens { 141a4d9b97cSHeiko Carstens int ccode; 142a4d9b97cSHeiko Carstens 143a4d9b97cSHeiko Carstens ccode = __csch(schid); 14411b64c8aSPeter Oberparleiter trace_s390_cio_csch(schid, ccode); 14511b64c8aSPeter Oberparleiter 14611b64c8aSPeter Oberparleiter return ccode; 14711b64c8aSPeter Oberparleiter } 14811b64c8aSPeter Oberparleiter EXPORT_SYMBOL(csch); 14911b64c8aSPeter Oberparleiter 15011b64c8aSPeter Oberparleiter int tpi(struct tpi_info *addr) 15111b64c8aSPeter Oberparleiter { 15211b64c8aSPeter Oberparleiter int ccode; 15311b64c8aSPeter Oberparleiter 15411b64c8aSPeter Oberparleiter asm volatile( 15511b64c8aSPeter Oberparleiter " tpi 0(%2)\n" 15611b64c8aSPeter Oberparleiter " ipm %0\n" 15711b64c8aSPeter Oberparleiter " srl %0,28" 15811b64c8aSPeter Oberparleiter : "=d" (ccode), "=m" (*addr) 15911b64c8aSPeter Oberparleiter : "a" (addr) 16011b64c8aSPeter Oberparleiter : "cc"); 16111b64c8aSPeter Oberparleiter trace_s390_cio_tpi(addr, ccode); 16211b64c8aSPeter Oberparleiter 16311b64c8aSPeter Oberparleiter return ccode; 16411b64c8aSPeter Oberparleiter } 16511b64c8aSPeter Oberparleiter 16611b64c8aSPeter Oberparleiter int chsc(void *chsc_area) 16711b64c8aSPeter Oberparleiter { 16811b64c8aSPeter Oberparleiter typedef struct { char _[4096]; } addr_type; 16977759137SPeter Oberparleiter int cc = -EIO; 17011b64c8aSPeter Oberparleiter 17111b64c8aSPeter Oberparleiter asm volatile( 17211b64c8aSPeter Oberparleiter " .insn rre,0xb25f0000,%2,0\n" 17377759137SPeter Oberparleiter "0: ipm %0\n" 17411b64c8aSPeter Oberparleiter " srl %0,28\n" 17577759137SPeter Oberparleiter "1:\n" 17677759137SPeter Oberparleiter EX_TABLE(0b, 1b) 17777759137SPeter Oberparleiter : "+d" (cc), "=m" (*(addr_type *) chsc_area) 17811b64c8aSPeter Oberparleiter : "d" (chsc_area), "m" (*(addr_type *) chsc_area) 17911b64c8aSPeter Oberparleiter : "cc"); 18011b64c8aSPeter Oberparleiter trace_s390_cio_chsc(chsc_area, cc); 18111b64c8aSPeter Oberparleiter 18211b64c8aSPeter Oberparleiter return cc; 18311b64c8aSPeter Oberparleiter } 18411b64c8aSPeter Oberparleiter EXPORT_SYMBOL(chsc); 18511b64c8aSPeter Oberparleiter 186a4d9b97cSHeiko Carstens static inline int __rsch(struct subchannel_id schid) 18711b64c8aSPeter Oberparleiter { 18811b64c8aSPeter Oberparleiter register struct subchannel_id reg1 asm("1") = schid; 18911b64c8aSPeter Oberparleiter int ccode; 19011b64c8aSPeter Oberparleiter 19111b64c8aSPeter Oberparleiter asm volatile( 19211b64c8aSPeter Oberparleiter " rsch\n" 19311b64c8aSPeter Oberparleiter " ipm %0\n" 19411b64c8aSPeter Oberparleiter " srl %0,28" 19511b64c8aSPeter Oberparleiter : "=d" (ccode) 19611b64c8aSPeter Oberparleiter : "d" (reg1) 19711b64c8aSPeter Oberparleiter : "cc", "memory"); 198a4d9b97cSHeiko Carstens 199a4d9b97cSHeiko Carstens return ccode; 200a4d9b97cSHeiko Carstens } 201a4d9b97cSHeiko Carstens 202a4d9b97cSHeiko Carstens int rsch(struct subchannel_id schid) 203a4d9b97cSHeiko Carstens { 204a4d9b97cSHeiko Carstens int ccode; 205a4d9b97cSHeiko Carstens 206a4d9b97cSHeiko Carstens ccode = __rsch(schid); 20711b64c8aSPeter Oberparleiter trace_s390_cio_rsch(schid, ccode); 20811b64c8aSPeter Oberparleiter 20911b64c8aSPeter Oberparleiter return ccode; 21011b64c8aSPeter Oberparleiter } 21111b64c8aSPeter Oberparleiter 212a4d9b97cSHeiko Carstens static inline int __hsch(struct subchannel_id schid) 21311b64c8aSPeter Oberparleiter { 21411b64c8aSPeter Oberparleiter register struct subchannel_id reg1 asm("1") = schid; 21511b64c8aSPeter Oberparleiter int ccode; 21611b64c8aSPeter Oberparleiter 21711b64c8aSPeter Oberparleiter asm volatile( 21811b64c8aSPeter Oberparleiter " hsch\n" 21911b64c8aSPeter Oberparleiter " ipm %0\n" 22011b64c8aSPeter Oberparleiter " srl %0,28" 22111b64c8aSPeter Oberparleiter : "=d" (ccode) 22211b64c8aSPeter Oberparleiter : "d" (reg1) 22311b64c8aSPeter Oberparleiter : "cc"); 224a4d9b97cSHeiko Carstens return ccode; 225a4d9b97cSHeiko Carstens } 226a4d9b97cSHeiko Carstens 227a4d9b97cSHeiko Carstens int hsch(struct subchannel_id schid) 228a4d9b97cSHeiko Carstens { 229a4d9b97cSHeiko Carstens int ccode; 230a4d9b97cSHeiko Carstens 231a4d9b97cSHeiko Carstens ccode = __hsch(schid); 23211b64c8aSPeter Oberparleiter trace_s390_cio_hsch(schid, ccode); 23311b64c8aSPeter Oberparleiter 23411b64c8aSPeter Oberparleiter return ccode; 23511b64c8aSPeter Oberparleiter } 236*b0940857SCornelia Huck EXPORT_SYMBOL(hsch); 23711b64c8aSPeter Oberparleiter 238a4d9b97cSHeiko Carstens static inline int __xsch(struct subchannel_id schid) 23911b64c8aSPeter Oberparleiter { 24011b64c8aSPeter Oberparleiter register struct subchannel_id reg1 asm("1") = schid; 24111b64c8aSPeter Oberparleiter int ccode; 24211b64c8aSPeter Oberparleiter 24311b64c8aSPeter Oberparleiter asm volatile( 24411b64c8aSPeter Oberparleiter " xsch\n" 24511b64c8aSPeter Oberparleiter " ipm %0\n" 24611b64c8aSPeter Oberparleiter " srl %0,28" 24711b64c8aSPeter Oberparleiter : "=d" (ccode) 24811b64c8aSPeter Oberparleiter : "d" (reg1) 24911b64c8aSPeter Oberparleiter : "cc"); 250a4d9b97cSHeiko Carstens return ccode; 251a4d9b97cSHeiko Carstens } 252a4d9b97cSHeiko Carstens 253a4d9b97cSHeiko Carstens int xsch(struct subchannel_id schid) 254a4d9b97cSHeiko Carstens { 255a4d9b97cSHeiko Carstens int ccode; 256a4d9b97cSHeiko Carstens 257a4d9b97cSHeiko Carstens ccode = __xsch(schid); 25811b64c8aSPeter Oberparleiter trace_s390_cio_xsch(schid, ccode); 25911b64c8aSPeter Oberparleiter 26011b64c8aSPeter Oberparleiter return ccode; 26111b64c8aSPeter Oberparleiter } 26211b64c8aSPeter Oberparleiter 26311b64c8aSPeter Oberparleiter int stcrw(struct crw *crw) 26411b64c8aSPeter Oberparleiter { 26511b64c8aSPeter Oberparleiter int ccode; 26611b64c8aSPeter Oberparleiter 26711b64c8aSPeter Oberparleiter asm volatile( 26811b64c8aSPeter Oberparleiter " stcrw 0(%2)\n" 26911b64c8aSPeter Oberparleiter " ipm %0\n" 27011b64c8aSPeter Oberparleiter " srl %0,28\n" 27111b64c8aSPeter Oberparleiter : "=d" (ccode), "=m" (*crw) 27211b64c8aSPeter Oberparleiter : "a" (crw) 27311b64c8aSPeter Oberparleiter : "cc"); 27411b64c8aSPeter Oberparleiter trace_s390_cio_stcrw(crw, ccode); 27511b64c8aSPeter Oberparleiter 27611b64c8aSPeter Oberparleiter return ccode; 27711b64c8aSPeter Oberparleiter } 278