projects/linux·commit f9c03549

Merge tag 's390-6.9-2' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux

f9c03549 · Linus Torvalds <[email protected]> · 2024-03-19 11:38:27 -07:00

Pull more s390 updates from Heiko Carstens:

 - Various virtual vs physical address usage fixes

 - Add new bitwise types and helper functions and use them in s390
   specific drivers and code to make it easier to find virtual vs
   physical address usage bugs.

   Right now virtual and physical addresses are identical for s390,
   except for module, vmalloc, and similar areas. This will be changed,
   hopefully with the next merge window, so that e.g. the kernel image
   and modules will be located close to each other, allowing for direct
   branches and also for some other simplifications.

   As a prerequisite this requires to fix all misuses of virtual and
   physical addresses. As it turned out people are so used to the
   concept that virtual and physical addresses are the same, that new
   bugs got added to code which was already fixed. In order to avoid
   that even more code gets merged which adds such bugs add and use new
   bitwise types, so that sparse can be used to find such usage bugs.

   Most likely the new types can go away again after some time

 - Provide a simple ARCH_HAS_DEBUG_VIRTUAL implementation

 - Fix kprobe branch handling: if an out-of-line single stepped relative
   branch instruction has a target address within a certain address area
   in the entry code, the program check handler may incorrectly execute
   cleanup code as if KVM code was executed, leading to crashes

 - Fix reference counting of zcrypt card objects

 - Various other small fixes and cleanups

* tag 's390-6.9-2' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: (41 commits)
  s390/entry: compare gmap asce to determine guest/host fault
  s390/entry: remove OUTSIDE macro
  s390/entry: add CIF_SIE flag and remove sie64a() address check
  s390/cio: use while (i--) pattern to clean up
  s390/raw3270: make class3270 constant
  s390/raw3270: improve raw3270_init() readability
  s390/tape: make tape_class constant
  s390/vmlogrdr: make vmlogrdr_class constant
  s390/vmur: make vmur_class constant
  s390/zcrypt: make zcrypt_class constant
  s390/mm: provide simple ARCH_HAS_DEBUG_VIRTUAL support
  s390/vfio_ccw_cp: use new address translation helpers
  s390/iucv: use new address translation helpers
  s390/ctcm: use new address translation helpers
  s390/lcs: use new address translation helpers
  s390/qeth: use new address translation helpers
  s390/zfcp: use new address translation helpers
  s390/tape: fix virtual vs physical address confusion
  s390/3270: use new address translation helpers
  s390/3215: use new address translation helpers
  ...
Commit
f9c035492f2010e1e7aede1f1bd32181d7cef2dc
Parents
24f5bb9f · 64c34318

Merge commit. Changes below are compared with the first parent: 24f5bb9f.

Changes

67 files changed · +771 −553

FileStatusAddDelContent
arch/s390/Kconfigmodified+1−0View file
arch/s390/Makefilemodified+1−0View file
arch/s390/configs/debug_defconfigmodified+1−0View file
arch/s390/include/asm/ccwdev.hmodified+2−1View file
arch/s390/include/asm/cio.hmodified+6−3View file
arch/s390/include/asm/dma-types.hadded+103−0View file
arch/s390/include/asm/eadm.hmodified+3−2View file
arch/s390/include/asm/fcx.hmodified+7−6View file
arch/s390/include/asm/idals.hmodified+96−80View file
arch/s390/include/asm/page.hmodified+28−2View file
arch/s390/include/asm/processor.hmodified+2−0View file
arch/s390/include/asm/ptrace.hmodified+0−2View file
arch/s390/include/asm/qdio.hmodified+9−8View file
arch/s390/include/asm/scsw.hmodified+4−3View file
arch/s390/kernel/entry.Smodified+31−42View file
arch/s390/kernel/sysinfo.cmodified+1−1View file
arch/s390/kernel/vtime.cmodified+2−2View file
arch/s390/mm/Makefilemodified+1−0View file
arch/s390/mm/fault.cmodified+3−1View file
arch/s390/mm/physaddr.cadded+15−0View file
drivers/s390/block/dasd.cmodified+2−2View file
drivers/s390/block/dasd_3990_erp.cmodified+7−7View file
drivers/s390/block/dasd_alias.cmodified+3−3View file
drivers/s390/block/dasd_eckd.cmodified+58−60View file
drivers/s390/block/dasd_eer.cmodified+1−1View file
drivers/s390/block/dasd_fba.cmodified+16−16View file
drivers/s390/block/dcssblk.cmodified+1−1View file
drivers/s390/block/scm_blk.cmodified+3−3View file
drivers/s390/char/con3215.cmodified+2−2View file
drivers/s390/char/fs3270.cmodified+7−7View file
drivers/s390/char/raw3270.cmodified+23−19View file
drivers/s390/char/raw3270.hmodified+1−1View file
drivers/s390/char/tape.hmodified+8−4View file
drivers/s390/char/tape_class.cmodified+8−9View file
drivers/s390/char/vmlogrdr.cmodified+8−10View file
drivers/s390/char/vmur.cmodified+11−11View file
drivers/s390/cio/ccwgroup.cmodified+2−2View file
drivers/s390/cio/chsc.cmodified+6−6View file
drivers/s390/cio/chsc.hmodified+3−3View file
drivers/s390/cio/cio.cmodified+2−2View file
drivers/s390/cio/css.cmodified+16−9View file
drivers/s390/cio/device_fsm.cmodified+4−4View file
drivers/s390/cio/device_id.cmodified+1−1View file
drivers/s390/cio/device_ops.cmodified+3−2View file
drivers/s390/cio/device_pgid.cmodified+4−4View file
drivers/s390/cio/device_status.cmodified+1−1View file
drivers/s390/cio/eadm_sch.cmodified+2−2View file
drivers/s390/cio/fcx.cmodified+11−11View file
drivers/s390/cio/orb.hmodified+6−3View file
drivers/s390/cio/qdio_main.cmodified+6−6View file
drivers/s390/cio/qdio_setup.cmodified+5−5View file
drivers/s390/cio/qdio_thinint.cmodified+3−3View file
drivers/s390/cio/vfio_ccw_cp.cmodified+44−38View file
drivers/s390/cio/vfio_ccw_fsm.cmodified+1−1View file
drivers/s390/crypto/zcrypt_api.cmodified+21−18View file
drivers/s390/net/ctcm_fsms.cmodified+2−2View file
drivers/s390/net/ctcm_main.cmodified+1−1View file
drivers/s390/net/ctcm_mpc.cmodified+10−10View file
drivers/s390/net/lcs.cmodified+5−7View file
drivers/s390/net/qeth_core_main.cmodified+12−12View file
drivers/s390/scsi/zfcp_fsf.cmodified+1−1View file
drivers/s390/scsi/zfcp_qdio.cmodified+2−2View file
drivers/s390/scsi/zfcp_qdio.hmodified+3−3View file
drivers/s390/virtio/virtio_ccw.cmodified+102−68View file
include/net/iucv/iucv.hmodified+2−1View file
net/iucv/af_iucv.cmodified+4−4View file
net/iucv/iucv.cmodified+11−12View file

Only the first 600 diff lines are shown. Download the complete patch.

arch/s390/Kconfig

View file
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 367bf5b..8f01ada 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -63,6 +63,7 @@ config S390
select ARCH_ENABLE_MEMORY_HOTREMOVE
select ARCH_ENABLE_SPLIT_PMD_PTLOCK if PGTABLE_LEVELS > 2
select ARCH_HAS_CURRENT_STACK_POINTER
+ select ARCH_HAS_DEBUG_VIRTUAL
select ARCH_HAS_DEBUG_VM_PGTABLE
select ARCH_HAS_DEBUG_WX
select ARCH_HAS_DEVMEM_IS_ALLOWED

arch/s390/Makefile

View file
diff --git a/arch/s390/Makefile b/arch/s390/Makefile
index 2a58e18..2dbb2d2 100644
--- a/arch/s390/Makefile
+++ b/arch/s390/Makefile
@@ -29,6 +29,7 @@ KBUILD_AFLAGS_DECOMPRESSOR += $(if $(CONFIG_DEBUG_INFO),$(aflags_dwarf))
endif
KBUILD_CFLAGS_DECOMPRESSOR := $(CLANG_FLAGS) -m64 -O2 -mpacked-stack
KBUILD_CFLAGS_DECOMPRESSOR += -DDISABLE_BRANCH_PROFILING -D__NO_FORTIFY
+KBUILD_CFLAGS_DECOMPRESSOR += -D__DECOMPRESSOR
KBUILD_CFLAGS_DECOMPRESSOR += -fno-delete-null-pointer-checks -msoft-float -mbackchain
KBUILD_CFLAGS_DECOMPRESSOR += -fno-asynchronous-unwind-tables
KBUILD_CFLAGS_DECOMPRESSOR += -ffreestanding

arch/s390/configs/debug_defconfig

View file
diff --git a/arch/s390/configs/debug_defconfig b/arch/s390/configs/debug_defconfig
index 4032e6e..f1fb01c 100644
--- a/arch/s390/configs/debug_defconfig
+++ b/arch/s390/configs/debug_defconfig
@@ -810,6 +810,7 @@ CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y
CONFIG_DEBUG_STACK_USAGE=y
CONFIG_DEBUG_VM=y
CONFIG_DEBUG_VM_PGFLAGS=y
+CONFIG_DEBUG_VIRTUAL=y
CONFIG_DEBUG_MEMORY_INIT=y
CONFIG_MEMORY_NOTIFIER_ERROR_INJECT=m
CONFIG_DEBUG_PER_CPU_MAPS=y

arch/s390/include/asm/ccwdev.h

View file
diff --git a/arch/s390/include/asm/ccwdev.h b/arch/s390/include/asm/ccwdev.h
index 91d2617..436365f 100644
--- a/arch/s390/include/asm/ccwdev.h
+++ b/arch/s390/include/asm/ccwdev.h
@@ -217,7 +217,8 @@ extern void ccw_device_destroy_console(struct ccw_device *);
extern int ccw_device_enable_console(struct ccw_device *);
extern void ccw_device_wait_idle(struct ccw_device *);
-extern void *ccw_device_dma_zalloc(struct ccw_device *cdev, size_t size);
+extern void *ccw_device_dma_zalloc(struct ccw_device *cdev, size_t size,
+ dma32_t *dma_handle);
extern void ccw_device_dma_free(struct ccw_device *cdev,
void *cpu_addr, size_t size);

arch/s390/include/asm/cio.h

View file
diff --git a/arch/s390/include/asm/cio.h b/arch/s390/include/asm/cio.h
index 1c4f585..b6b619f 100644
--- a/arch/s390/include/asm/cio.h
+++ b/arch/s390/include/asm/cio.h
@@ -7,6 +7,7 @@
#include <linux/bitops.h>
#include <linux/genalloc.h>
+#include <asm/dma-types.h>
#include <asm/types.h>
#include <asm/tpi.h>
@@ -32,7 +33,7 @@ struct ccw1 {
__u8 cmd_code;
__u8 flags;
__u16 count;
- __u32 cda;
+ dma32_t cda;
} __attribute__ ((packed,aligned(8)));
/**
@@ -152,8 +153,8 @@ struct sublog {
struct esw0 {
struct sublog sublog;
struct erw erw;
- __u32 faddr[2];
- __u32 saddr;
+ dma32_t faddr[2];
+ dma32_t saddr;
} __attribute__ ((packed));
/**
@@ -364,6 +365,8 @@ extern struct device *cio_get_dma_css_dev(void);
void *cio_gp_dma_zalloc(struct gen_pool *gp_dma, struct device *dma_dev,
size_t size);
+void *__cio_gp_dma_zalloc(struct gen_pool *gp_dma, struct device *dma_dev,
+ size_t size, dma32_t *dma_handle);
void cio_gp_dma_free(struct gen_pool *gp_dma, void *cpu_addr, size_t size);
void cio_gp_dma_destroy(struct gen_pool *gp_dma, struct device *dma_dev);
struct gen_pool *cio_gp_dma_create(struct device *dma_dev, int nr_pages);

arch/s390/include/asm/dma-types.h

View file
diff --git a/arch/s390/include/asm/dma-types.h b/arch/s390/include/asm/dma-types.h
new file mode 100644
index 0000000..5c5734e
--- /dev/null
+++ b/arch/s390/include/asm/dma-types.h
@@ -0,0 +1,103 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _ASM_S390_DMA_TYPES_H_
+#define _ASM_S390_DMA_TYPES_H_
+
+#include <linux/types.h>
+#include <linux/io.h>
+
+/*
+ * typedef dma32_t
+ * Contains a 31 bit absolute address to a DMA capable piece of storage.
+ *
+ * For CIO, DMA addresses are always absolute addresses. These addresses tend
+ * to be used in architectured memory blocks (like ORB, IDAW, MIDAW). Under
+ * certain circumstances 31 bit wide addresses must be used because the
+ * address must fit in 31 bits.
+ *
+ * This type is to be used when such fields can be modelled as 32 bit wide.
+ */
+typedef u32 __bitwise dma32_t;
+
+/*
+ * typedef dma64_t
+ * Contains a 64 bit absolute address to a DMA capable piece of storage.
+ *
+ * For CIO, DMA addresses are always absolute addresses. These addresses tend
+ * to be used in architectured memory blocks (like ORB, IDAW, MIDAW).
+ *
+ * This type is to be used to model such 64 bit wide fields.
+ */
+typedef u64 __bitwise dma64_t;
+
+/*
+ * Although DMA addresses should be obtained using the DMA API, in cases when
+ * it is known that the first argument holds a virtual address that points to
+ * DMA-able 31 bit addressable storage, then this function can be safely used.
+ */
+static inline dma32_t virt_to_dma32(void *ptr)
+{
+ return (__force dma32_t)__pa32(ptr);
+}
+
+static inline void *dma32_to_virt(dma32_t addr)
+{
+ return __va((__force unsigned long)addr);
+}
+
+static inline dma32_t u32_to_dma32(u32 addr)
+{
+ return (__force dma32_t)addr;
+}
+
+static inline u32 dma32_to_u32(dma32_t addr)
+{
+ return (__force u32)addr;
+}
+
+static inline dma32_t dma32_add(dma32_t a, u32 b)
+{
+ return (__force dma32_t)((__force u32)a + b);
+}
+
+static inline dma32_t dma32_and(dma32_t a, u32 b)
+{
+ return (__force dma32_t)((__force u32)a & b);
+}
+
+/*
+ * Although DMA addresses should be obtained using the DMA API, in cases when
+ * it is known that the first argument holds a virtual address that points to
+ * DMA-able storage, then this function can be safely used.
+ */
+static inline dma64_t virt_to_dma64(void *ptr)
+{
+ return (__force dma64_t)__pa(ptr);
+}
+
+static inline void *dma64_to_virt(dma64_t addr)
+{
+ return __va((__force unsigned long)addr);
+}
+
+static inline dma64_t u64_to_dma64(u64 addr)
+{
+ return (__force dma64_t)addr;
+}
+
+static inline u64 dma64_to_u64(dma64_t addr)
+{
+ return (__force u64)addr;
+}
+
+static inline dma64_t dma64_add(dma64_t a, u64 b)
+{
+ return (__force dma64_t)((__force u64)a + b);
+}
+
+static inline dma64_t dma64_and(dma64_t a, u64 b)
+{
+ return (__force dma64_t)((__force u64)a & b);
+}
+
+#endif /* _ASM_S390_DMA_TYPES_H_ */

arch/s390/include/asm/eadm.h

View file
diff --git a/arch/s390/include/asm/eadm.h b/arch/s390/include/asm/eadm.h
index 06f7958..c4589ec 100644
--- a/arch/s390/include/asm/eadm.h
+++ b/arch/s390/include/asm/eadm.h
@@ -5,6 +5,7 @@
#include <linux/types.h>
#include <linux/device.h>
#include <linux/blk_types.h>
+#include <asm/dma-types.h>
struct arqb {
u64 data;
@@ -45,7 +46,7 @@ struct msb {
u16:12;
u16 bs:4;
u32 blk_count;
- u64 data_addr;
+ dma64_t data_addr;
u64 scm_addr;
u64:64;
} __packed;
@@ -54,7 +55,7 @@ struct aidaw {
u8 flags;
u32 :24;
u32 :32;
- u64 data_addr;
+ dma64_t data_addr;
} __packed;
#define MSB_OC_CLEAR 0

arch/s390/include/asm/fcx.h

View file
diff --git a/arch/s390/include/asm/fcx.h b/arch/s390/include/asm/fcx.h
index 29784b4..80f82a7 100644
--- a/arch/s390/include/asm/fcx.h
+++ b/arch/s390/include/asm/fcx.h
@@ -10,6 +10,7 @@
#define _ASM_S390_FCX_H
#include <linux/types.h>
+#include <asm/dma-types.h>
#define TCW_FORMAT_DEFAULT 0
#define TCW_TIDAW_FORMAT_DEFAULT 0
@@ -43,16 +44,16 @@ struct tcw {
u32 r:1;
u32 w:1;
u32 :16;
- u64 output;
- u64 input;
- u64 tsb;
- u64 tccb;
+ dma64_t output;
+ dma64_t input;
+ dma64_t tsb;
+ dma64_t tccb;
u32 output_count;
u32 input_count;
u32 :32;
u32 :32;
u32 :32;
- u32 intrg;
+ dma32_t intrg;
} __attribute__ ((packed, aligned(64)));
#define TIDAW_FLAGS_LAST (1 << (7 - 0))
@@ -73,7 +74,7 @@ struct tidaw {
u32 flags:8;
u32 :24;
u32 count;
- u64 addr;
+ dma64_t addr;
} __attribute__ ((packed, aligned(16)));
/**

arch/s390/include/asm/idals.h

View file
diff --git a/arch/s390/include/asm/idals.h b/arch/s390/include/asm/idals.h
index 59fcc3c..ac68c65 100644
--- a/arch/s390/include/asm/idals.h
+++ b/arch/s390/include/asm/idals.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0 */
-/*
+/*
* Author(s)......: Holger Smolinski <[email protected]>
* Martin Schwidefsky <[email protected]>
* Bugreports.to..: <[email protected]>
@@ -17,32 +17,37 @@
#include <linux/err.h>
#include <linux/types.h>
#include <linux/slab.h>
-#include <asm/cio.h>
#include <linux/uaccess.h>
+#include <asm/dma-types.h>
+#include <asm/cio.h>
-#define IDA_SIZE_LOG 12 /* 11 for 2k , 12 for 4k */
-#define IDA_BLOCK_SIZE (1L<<IDA_SIZE_LOG)
+#define IDA_SIZE_SHIFT 12
+#define IDA_BLOCK_SIZE (1UL << IDA_SIZE_SHIFT)
-#define IDA_2K_SIZE_LOG 11
-#define IDA_2K_BLOCK_SIZE (1L << IDA_2K_SIZE_LOG)
+#define IDA_2K_SIZE_SHIFT 11
+#define IDA_2K_BLOCK_SIZE (1UL << IDA_2K_SIZE_SHIFT)
/*
* Test if an address/length pair needs an idal list.
*/
-static inline int
-idal_is_needed(void *vaddr, unsigned int length)
+static inline bool idal_is_needed(void *vaddr, unsigned int length)
{
- return ((__pa(vaddr) + length - 1) >> 31) != 0;
-}
+ dma64_t paddr = virt_to_dma64(vaddr);
+ return (((__force unsigned long)(paddr) + length - 1) >> 31) != 0;
+}
/*
* Return the number of idal words needed for an address/length pair.
*/
static inline unsigned int idal_nr_words(void *vaddr, unsigned int length)
{
- return ((__pa(vaddr) & (IDA_BLOCK_SIZE-1)) + length +
- (IDA_BLOCK_SIZE-1)) >> IDA_SIZE_LOG;
+ unsigned int cidaw;
+
+ cidaw = (unsigned long)vaddr & (IDA_BLOCK_SIZE - 1);
+ cidaw += length + IDA_BLOCK_SIZE - 1;
+ cidaw >>= IDA_SIZE_SHIFT;
+ return cidaw;
}
/*
@@ -50,26 +55,27 @@ static inline unsigned int idal_nr_words(void *vaddr, unsigned int length)
*/
static inline unsigned int idal_2k_nr_words(void *vaddr, unsigned int length)
{
- return ((__pa(vaddr) & (IDA_2K_BLOCK_SIZE - 1)) + length +
- (IDA_2K_BLOCK_SIZE - 1)) >> IDA_2K_SIZE_LOG;
+ unsigned int cidaw;
+
+ cidaw = (unsigned long)vaddr & (IDA_2K_BLOCK_SIZE - 1);
+ cidaw += length + IDA_2K_BLOCK_SIZE - 1;
+ cidaw >>= IDA_2K_SIZE_SHIFT;
+ return cidaw;
}
/*
* Create the list of idal words for an address/length pair.
*/
-static inline unsigned long *idal_create_words(unsigned long *idaws,
- void *vaddr, unsigned int length)
+static inline dma64_t *idal_create_words(dma64_t *idaws, void *vaddr, unsigned int length)
{
- unsigned long paddr;
+ dma64_t paddr = virt_to_dma64(vaddr);
unsigned int cidaw;
- paddr = __pa(vaddr);
- cidaw = ((paddr & (IDA_BLOCK_SIZE-1)) + length +
- (IDA_BLOCK_SIZE-1)) >> IDA_SIZE_LOG;
*idaws++ = paddr;
- paddr &= -IDA_BLOCK_SIZE;
+ cidaw = idal_nr_words(vaddr, length);
+ paddr = dma64_and(paddr, -IDA_BLOCK_SIZE);
while (--cidaw > 0) {
- paddr += IDA_BLOCK_SIZE;
+ paddr = dma64_add(paddr, IDA_BLOCK_SIZE);
*idaws++ = paddr;
}
return idaws;
@@ -79,36 +85,33 @@ static inline unsigned long *idal_create_words(unsigned long *idaws,
* Sets the address of the data in CCW.
* If necessary it allocates an IDAL and sets the appropriate flags.
*/
-static inline int
-set_normalized_cda(struct ccw1 * ccw, void *vaddr)
+static inline int set_normalized_cda(struct ccw1 *ccw, void *vaddr)
{
unsigned int nridaws;
- unsigned long *idal;
+ dma64_t *idal;
if (ccw->flags & CCW_FLAG_IDA)
return -EINVAL;
nridaws = idal_nr_words(vaddr, ccw->count);
if (nridaws > 0) {
- idal = kmalloc(nridaws * sizeof(unsigned long),
- GFP_ATOMIC | GFP_DMA );
- if (idal == NULL)
+ idal = kcalloc(nridaws, sizeof(*idal), GFP_ATOMIC | GFP_DMA);
+ if (!idal)
return -ENOMEM;
idal_create_words(idal, vaddr, ccw->count);
ccw->flags |= CCW_FLAG_IDA;
vaddr = idal;
}
- ccw->cda = (__u32)(unsigned long) vaddr;
+ ccw->cda = virt_to_dma32(vaddr);
return 0;
}
/*
* Releases any allocated IDAL related to the CCW.
*/
-static inline void
-clear_normalized_cda(struct ccw1 * ccw)
+static inline void clear_normalized_cda(struct ccw1 *ccw)
{
if (ccw->flags & CCW_FLAG_IDA) {
- kfree((void *)(unsigned long) ccw->cda);
+ kfree(dma32_to_virt(ccw->cda));
ccw->flags &= ~CCW_FLAG_IDA;
}
ccw->cda = 0;
@@ -120,125 +123,138 @@ clear_normalized_cda(struct ccw1 * ccw)
struct idal_buffer {
size_t size;
size_t page_order;
- void *data[];
+ dma64_t data[];
};
/*
* Allocate an idal buffer
*/
-static inline struct idal_buffer *
-idal_buffer_alloc(size_t size, int page_order)
+static inline struct idal_buffer *idal_buffer_alloc(size_t size, int page_order)
{
- struct idal_buffer *ib;
int nr_chunks, nr_ptrs, i;
+ struct idal_buffer *ib;
+ void *vaddr;
- nr_ptrs = (size + IDA_BLOCK_SIZE - 1) >> IDA_SIZE_LOG;
- nr_chunks = (4096 << page_order) >> IDA_SIZE_LOG;
+ nr_ptrs = (size + IDA_BLOCK_SIZE - 1) >> IDA_SIZE_SHIFT;
+ nr_chunks = (PAGE_SIZE << page_order) >> IDA_SIZE_SHIFT;
ib = kmalloc(struct_size(ib, data, nr_ptrs), GFP_DMA | GFP_KERNEL);
- if (ib == NULL)
+ if (!ib)
return ERR_PTR(-ENOMEM);
ib->size = size;
ib->page_order = page_order;
for (i = 0; i < nr_ptrs; i++) {
- if ((i & (nr_chunks - 1)) != 0) {
- ib->data[i] = ib->data[i-1] + IDA_BLOCK_SIZE;
- continue;
- }
- ib->data[i] = (void *)
- __get_free_pages(GFP_KERNEL, page_order);
- if (ib->data[i] != NULL)
+ if (i & (nr_chunks - 1)) {
+ ib->data[i] = dma64_add(ib->data[i - 1], IDA_BLOCK_SIZE);
continue;
- // Not enough memory
- while (i >= nr_chunks) {
- i -= nr_chunks;
- free_pages((unsigned long) ib->data[i],
- ib->page_order);
}
- kfree(ib);
- return ERR_PTR(-ENOMEM);
+ vaddr = (void *)__get_free_pages(GFP_KERNEL, page_order);
+ if (!vaddr)
+ goto error;
+ ib->data[i] = virt_to_dma64(vaddr);
}
return ib;
+error:
+ while (i >= nr_chunks) {
+ i -= nr_chunks;
+ vaddr = dma64_to_virt(ib->data[i]);
+ free_pages((unsigned long)vaddr, ib->page_order);
+ }
+ kfree(ib);
+ return ERR_PTR(-ENOMEM);
}
/*
* Free an idal buffer.
*/
-static inline void
-idal_buffer_free(struct idal_buffer *ib)
+static inline void idal_buffer_free(struct idal_buffer *ib)
{
int nr_chunks, nr_ptrs, i;
+ void *vaddr;
- nr_ptrs = (ib->size + IDA_BLOCK_SIZE - 1) >> IDA_SIZE_LOG;
- nr_chunks = (4096 << ib->page_order) >> IDA_SIZE_LOG;
- for (i = 0; i < nr_ptrs; i += nr_chunks)
- free_pages((unsigned long) ib->data[i], ib->page_order);
+ nr_ptrs = (ib->size + IDA_BLOCK_SIZE - 1) >> IDA_SIZE_SHIFT;
+ nr_chunks = (PAGE_SIZE << ib->page_order) >> IDA_SIZE_SHIFT;
+ for (i = 0; i < nr_ptrs; i += nr_chunks) {
+ vaddr = dma64_to_virt(ib->data[i]);
+ free_pages((unsigned long)vaddr, ib->page_order);
+ }
kfree(ib);
}
/*
* Test if a idal list is really needed.
*/
-static inline int
-__idal_buffer_is_needed(struct idal_buffer *ib)
+static inline bool __idal_buffer_is_needed(struct idal_buffer *ib)
{
- return ib->size > (4096ul << ib->page_order) ||
- idal_is_needed(ib->data[0], ib->size);
+ if (ib->size > (PAGE_SIZE << ib->page_order))
+ return true;
+ return idal_is_needed(dma64_to_virt(ib->data[0]), ib->size);
}
/*
* Set channel data address to idal buffer.
*/
-static inline void
-idal_buffer_set_cda(struct idal_buffer *ib, struct ccw1 *ccw)
+static inline void idal_buffer_set_cda(struct idal_buffer *ib, struct ccw1 *ccw)
{
+ void *vaddr;
+
if (__idal_buffer_is_needed(ib)) {
- // setup idals;
- ccw->cda = (u32)(addr_t) ib->data;
+ /* Setup idals */
+ ccw->cda = virt_to_dma32(ib->data);
ccw->flags |= CCW_FLAG_IDA;
- } else
- // we do not need idals - use direct addressing
- ccw->cda = (u32)(addr_t) ib->data[0];
+ } else {
+ /*
+ * No idals needed - use direct addressing. Convert from
+ * dma64_t to virt and then to dma32_t only because of type
+ * checking. The physical address is known to be below 2GB.
+ */
+ vaddr = dma64_to_virt(ib->data[0]);
+ ccw->cda = virt_to_dma32(vaddr);
+ }
ccw->count = ib->size;
}
/*
* Copy count bytes from an idal buffer to user memory
*/
-static inline size_t
-idal_buffer_to_user(struct idal_buffer *ib, void __user *to, size_t count)
+static inline size_t idal_buffer_to_user(struct idal_buffer *ib, void __user *to, size_t count)
{
size_t left;
+ void *vaddr;
int i;
BUG_ON(count > ib->size);
for (i = 0; count > IDA_BLOCK_SIZE; i++) {
- left = copy_to_user(to, ib->data[i], IDA_BLOCK_SIZE);
+ vaddr = dma64_to_virt(ib->data[i]);
+ left = copy_to_user(to, vaddr, IDA_BLOCK_SIZE);
if (left)
return left + count - IDA_BLOCK_SIZE;
- to = (void __user *) to + IDA_BLOCK_SIZE;
+ to = (void __user *)to + IDA_BLOCK_SIZE;
count -= IDA_BLOCK_SIZE;
}
- return copy_to_user(to, ib->data[i], count);
+ vaddr = dma64_to_virt(ib->data[i]);
+ return copy_to_user(to, vaddr, count);
}
/*
* Copy count bytes from user memory to an idal buffer
*/
-static inline size_t
-idal_buffer_from_user(struct idal_buffer *ib, const void __user *from, size_t count)
+static inline size_t idal_buffer_from_user(struct idal_buffer *ib, const void __user *from, size_t count)
{
size_t left;
+ void *vaddr;
int i;
BUG_ON(count > ib->size);
for (i = 0; count > IDA_BLOCK_SIZE; i++) {
- left = copy_from_user(ib->data[i], from, IDA_BLOCK_SIZE);
+ vaddr = dma64_to_virt(ib->data[i]);
+ left = copy_from_user(vaddr, from, IDA_BLOCK_SIZE);
if (left)
return left + count - IDA_BLOCK_SIZE;
- from = (void __user *) from + IDA_BLOCK_SIZE;
+ from = (void __user *)from + IDA_BLOCK_SIZE;
count -= IDA_BLOCK_SIZE;
}
- return copy_from_user(ib->data[i], from, count);
+ vaddr = dma64_to_virt(ib->data[i]);
+ return copy_from_user(vaddr, from, count);
}

This diff is incomplete. Download the complete patch.

arch/s390/include/asm/page.h

View file

This diff is incomplete. Download the complete patch.

arch/s390/include/asm/processor.h

View file

This diff is incomplete. Download the complete patch.

arch/s390/include/asm/ptrace.h

View file

This diff is incomplete. Download the complete patch.

arch/s390/include/asm/qdio.h

View file

This diff is incomplete. Download the complete patch.

arch/s390/include/asm/scsw.h

View file

This diff is incomplete. Download the complete patch.

arch/s390/kernel/entry.S

View file

This diff is incomplete. Download the complete patch.

arch/s390/kernel/sysinfo.c

View file

This diff is incomplete. Download the complete patch.

arch/s390/kernel/vtime.c

View file

This diff is incomplete. Download the complete patch.

arch/s390/mm/Makefile

View file

This diff is incomplete. Download the complete patch.

arch/s390/mm/fault.c

View file

This diff is incomplete. Download the complete patch.

arch/s390/mm/physaddr.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/block/dasd.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/block/dasd_3990_erp.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/block/dasd_alias.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/block/dasd_eckd.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/block/dasd_eer.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/block/dasd_fba.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/block/dcssblk.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/block/scm_blk.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/char/con3215.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/char/fs3270.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/char/raw3270.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/char/raw3270.h

View file

This diff is incomplete. Download the complete patch.

drivers/s390/char/tape.h

View file

This diff is incomplete. Download the complete patch.

drivers/s390/char/tape_class.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/char/vmlogrdr.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/char/vmur.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/cio/ccwgroup.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/cio/chsc.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/cio/chsc.h

View file

This diff is incomplete. Download the complete patch.

drivers/s390/cio/cio.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/cio/css.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/cio/device_fsm.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/cio/device_id.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/cio/device_ops.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/cio/device_pgid.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/cio/device_status.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/cio/eadm_sch.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/cio/fcx.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/cio/orb.h

View file

This diff is incomplete. Download the complete patch.

drivers/s390/cio/qdio_main.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/cio/qdio_setup.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/cio/qdio_thinint.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/cio/vfio_ccw_cp.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/cio/vfio_ccw_fsm.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/crypto/zcrypt_api.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/net/ctcm_fsms.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/net/ctcm_main.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/net/ctcm_mpc.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/net/lcs.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/net/qeth_core_main.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/scsi/zfcp_fsf.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/scsi/zfcp_qdio.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/scsi/zfcp_qdio.h

View file

This diff is incomplete. Download the complete patch.

drivers/s390/virtio/virtio_ccw.c

View file

This diff is incomplete. Download the complete patch.

include/net/iucv/iucv.h

View file

This diff is incomplete. Download the complete patch.

net/iucv/af_iucv.c

View file

This diff is incomplete. Download the complete patch.

net/iucv/iucv.c

View file

This diff is incomplete. Download the complete patch.