Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.6 195 lines 4.1 kB view raw
1/* SPDX-License-Identifier: GPL-2.0 */ 2#ifndef _ASM_S390_PCI_IO_H 3#define _ASM_S390_PCI_IO_H 4 5#ifdef CONFIG_PCI 6 7#include <linux/kernel.h> 8#include <linux/slab.h> 9#include <asm/pci_insn.h> 10 11/* I/O Map */ 12#define ZPCI_IOMAP_SHIFT 48 13#define ZPCI_IOMAP_ADDR_BASE 0x8000000000000000UL 14#define ZPCI_IOMAP_ADDR_OFF_MASK ((1UL << ZPCI_IOMAP_SHIFT) - 1) 15#define ZPCI_IOMAP_MAX_ENTRIES \ 16 ((ULONG_MAX - ZPCI_IOMAP_ADDR_BASE + 1) / (1UL << ZPCI_IOMAP_SHIFT)) 17#define ZPCI_IOMAP_ADDR_IDX_MASK \ 18 (~ZPCI_IOMAP_ADDR_OFF_MASK - ZPCI_IOMAP_ADDR_BASE) 19 20struct zpci_iomap_entry { 21 u32 fh; 22 u8 bar; 23 u16 count; 24}; 25 26extern struct zpci_iomap_entry *zpci_iomap_start; 27 28#define ZPCI_ADDR(idx) (ZPCI_IOMAP_ADDR_BASE | ((u64) idx << ZPCI_IOMAP_SHIFT)) 29#define ZPCI_IDX(addr) \ 30 (((__force u64) addr & ZPCI_IOMAP_ADDR_IDX_MASK) >> ZPCI_IOMAP_SHIFT) 31#define ZPCI_OFFSET(addr) \ 32 ((__force u64) addr & ZPCI_IOMAP_ADDR_OFF_MASK) 33 34#define ZPCI_CREATE_REQ(handle, space, len) \ 35 ((u64) handle << 32 | space << 16 | len) 36 37#define zpci_read(LENGTH, RETTYPE) \ 38static inline RETTYPE zpci_read_##RETTYPE(const volatile void __iomem *addr) \ 39{ \ 40 u64 data; \ 41 int rc; \ 42 \ 43 rc = zpci_load(&data, addr, LENGTH); \ 44 if (rc) \ 45 data = -1ULL; \ 46 return (RETTYPE) data; \ 47} 48 49#define zpci_write(LENGTH, VALTYPE) \ 50static inline void zpci_write_##VALTYPE(VALTYPE val, \ 51 const volatile void __iomem *addr) \ 52{ \ 53 u64 data = (VALTYPE) val; \ 54 \ 55 zpci_store(addr, data, LENGTH); \ 56} 57 58zpci_read(8, u64) 59zpci_read(4, u32) 60zpci_read(2, u16) 61zpci_read(1, u8) 62zpci_write(8, u64) 63zpci_write(4, u32) 64zpci_write(2, u16) 65zpci_write(1, u8) 66 67static inline int zpci_write_single(volatile void __iomem *dst, const void *src, 68 unsigned long len) 69{ 70 u64 val; 71 72 switch (len) { 73 case 1: 74 val = (u64) *((u8 *) src); 75 break; 76 case 2: 77 val = (u64) *((u16 *) src); 78 break; 79 case 4: 80 val = (u64) *((u32 *) src); 81 break; 82 case 8: 83 val = (u64) *((u64 *) src); 84 break; 85 default: 86 val = 0; /* let FW report error */ 87 break; 88 } 89 return zpci_store(dst, val, len); 90} 91 92static inline int zpci_read_single(void *dst, const volatile void __iomem *src, 93 unsigned long len) 94{ 95 u64 data; 96 int cc; 97 98 cc = zpci_load(&data, src, len); 99 if (cc) 100 goto out; 101 102 switch (len) { 103 case 1: 104 *((u8 *) dst) = (u8) data; 105 break; 106 case 2: 107 *((u16 *) dst) = (u16) data; 108 break; 109 case 4: 110 *((u32 *) dst) = (u32) data; 111 break; 112 case 8: 113 *((u64 *) dst) = (u64) data; 114 break; 115 } 116out: 117 return cc; 118} 119 120int zpci_write_block(volatile void __iomem *dst, const void *src, 121 unsigned long len); 122 123static inline u8 zpci_get_max_write_size(u64 src, u64 dst, int len, int max) 124{ 125 int count = len > max ? max : len, size = 1; 126 127 while (!(src & 0x1) && !(dst & 0x1) && ((size << 1) <= count)) { 128 dst = dst >> 1; 129 src = src >> 1; 130 size = size << 1; 131 } 132 return size; 133} 134 135static inline int zpci_memcpy_fromio(void *dst, 136 const volatile void __iomem *src, 137 unsigned long n) 138{ 139 int size, rc = 0; 140 141 while (n > 0) { 142 size = zpci_get_max_write_size((u64 __force) src, 143 (u64) dst, n, 8); 144 rc = zpci_read_single(dst, src, size); 145 if (rc) 146 break; 147 src += size; 148 dst += size; 149 n -= size; 150 } 151 return rc; 152} 153 154static inline int zpci_memcpy_toio(volatile void __iomem *dst, 155 const void *src, unsigned long n) 156{ 157 int size, rc = 0; 158 159 if (!src) 160 return -EINVAL; 161 162 while (n > 0) { 163 size = zpci_get_max_write_size((u64 __force) dst, 164 (u64) src, n, 128); 165 if (size > 8) /* main path */ 166 rc = zpci_write_block(dst, src, size); 167 else 168 rc = zpci_write_single(dst, src, size); 169 if (rc) 170 break; 171 src += size; 172 dst += size; 173 n -= size; 174 } 175 return rc; 176} 177 178static inline int zpci_memset_io(volatile void __iomem *dst, 179 unsigned char val, size_t count) 180{ 181 u8 *src = kmalloc(count, GFP_KERNEL); 182 int rc; 183 184 if (src == NULL) 185 return -ENOMEM; 186 memset(src, val, count); 187 188 rc = zpci_memcpy_toio(dst, src, count); 189 kfree(src); 190 return rc; 191} 192 193#endif /* CONFIG_PCI */ 194 195#endif /* _ASM_S390_PCI_IO_H */