Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ebb067d2 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull s390 updates from Martin Schwidefsky:
 "Mostly cleanups and bug-fixes, with two exceptions.

  The first is lazy flushing of I/O-TLBs for PCI to improve performance,
  the second is software dirty bits in the pmd for the madvise-free
  implementation"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: (24 commits)
  s390/locking: Reenable optimistic spinning
  s390/mm: implement dirty bits for large segment table entries
  KVM: s390/mm: Fix page table locking vs. split pmd lock
  s390/dasd: fix camel case
  s390/3215: fix hanging console issue
  s390/irq: improve displayed interrupt order in /proc/interrupts
  s390/seccomp: fix error return for filtered system calls
  s390/pci: introduce lazy IOTLB flushing for DMA unmap
  dasd: fix error recovery for alias devices during format
  dasd: fix list_del corruption during format
  dasd: fix unresponsive device during format
  dasd: use aliases for formatted devices during format
  s390/pci: fix kmsg component
  s390/kdump: Return NOTIFY_OK for all actions other than MEM_GOING_OFFLINE
  s390/watchdog: Fix module name in Kconfig help text
  s390/dasd: replace seq_printf by seq_puts
  s390/dasd: replace pr_warning by pr_warn
  s390/dasd: Move EXPORT_SYMBOL after function/variable
  s390/dasd: remove unnecessary null test before debugfs_remove
  s390/zfcp: use qdio buffer helpers
  ...
parents 33caee39 36e7fdaa
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -3058,6 +3058,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted.

	S		[KNL] Run init in single mode

	s390_iommu=	[HW,S390]
			Set s390 IOTLB flushing mode
		strict
			With strict flushing every unmap operation will result in
			an IOTLB flush. Default is lazy flushing before reuse,
			which is faster.

	sa1100ir	[NET]
			See drivers/net/irda/sa1100_ir.c.

+1 −0
Original line number Diff line number Diff line
@@ -92,6 +92,7 @@ config S390
	select ARCH_INLINE_WRITE_UNLOCK_IRQ
	select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE
	select ARCH_SAVE_PAGE_KEYS if HIBERNATION
	select ARCH_SUPPORTS_ATOMIC_RMW
	select ARCH_USE_CMPXCHG_LOCKREF
	select ARCH_WANT_IPC_PARSE_VERSION
	select BUILDTIME_EXTABLE_SORT
+109 −88
Original line number Diff line number Diff line
@@ -287,7 +287,14 @@ extern unsigned long MODULES_END;
#define _SEGMENT_ENTRY_INVALID	0x20	/* invalid segment table entry	    */
#define _SEGMENT_ENTRY_COMMON	0x10	/* common segment bit		    */
#define _SEGMENT_ENTRY_PTL	0x0f	/* page table length		    */
#define _SEGMENT_ENTRY_NONE	_SEGMENT_ENTRY_PROTECT

#define _SEGMENT_ENTRY_DIRTY	0	/* No sw dirty bit for 31-bit */
#define _SEGMENT_ENTRY_YOUNG	0	/* No sw young bit for 31-bit */
#define _SEGMENT_ENTRY_READ	0	/* No sw read bit for 31-bit */
#define _SEGMENT_ENTRY_WRITE	0	/* No sw write bit for 31-bit */
#define _SEGMENT_ENTRY_LARGE	0	/* No large pages for 31-bit */
#define _SEGMENT_ENTRY_BITS_LARGE 0
#define _SEGMENT_ENTRY_ORIGIN_LARGE 0

#define _SEGMENT_ENTRY		(_SEGMENT_ENTRY_PTL)
#define _SEGMENT_ENTRY_EMPTY	(_SEGMENT_ENTRY_INVALID)
@@ -350,7 +357,7 @@ extern unsigned long MODULES_END;

/* Bits in the segment table entry */
#define _SEGMENT_ENTRY_BITS	0xfffffffffffffe33UL
#define _SEGMENT_ENTRY_BITS_LARGE 0xfffffffffff1ff33UL
#define _SEGMENT_ENTRY_BITS_LARGE 0xfffffffffff0ff33UL
#define _SEGMENT_ENTRY_ORIGIN_LARGE ~0xfffffUL /* large page address	    */
#define _SEGMENT_ENTRY_ORIGIN	~0x7ffUL/* segment table origin		    */
#define _SEGMENT_ENTRY_PROTECT	0x200	/* page protection bit		    */
@@ -359,30 +366,34 @@ extern unsigned long MODULES_END;
#define _SEGMENT_ENTRY		(0)
#define _SEGMENT_ENTRY_EMPTY	(_SEGMENT_ENTRY_INVALID)

#define _SEGMENT_ENTRY_LARGE	0x400	/* STE-format control, large page   */
#define _SEGMENT_ENTRY_CO	0x100	/* change-recording override   */
#define _SEGMENT_ENTRY_SPLIT	0x001	/* THP splitting bit */
#define _SEGMENT_ENTRY_YOUNG	0x002	/* SW segment young bit */
#define _SEGMENT_ENTRY_NONE	_SEGMENT_ENTRY_YOUNG
#define _SEGMENT_ENTRY_DIRTY	0x2000	/* SW segment dirty bit */
#define _SEGMENT_ENTRY_YOUNG	0x1000	/* SW segment young bit */
#define _SEGMENT_ENTRY_SPLIT	0x0800	/* THP splitting bit */
#define _SEGMENT_ENTRY_LARGE	0x0400	/* STE-format control, large page */
#define _SEGMENT_ENTRY_CO	0x0100	/* change-recording override   */
#define _SEGMENT_ENTRY_READ	0x0002	/* SW segment read bit */
#define _SEGMENT_ENTRY_WRITE	0x0001	/* SW segment write bit */

/*
 * Segment table entry encoding (R = read-only, I = invalid, y = young bit):
 *			..R...I...y.
 * prot-none, old	..0...1...1.
 * prot-none, young	..1...1...1.
 * read-only, old	..1...1...0.
 * read-only, young	..1...0...1.
 * read-write, old	..0...1...0.
 * read-write, young	..0...0...1.
 *				dy..R...I...wr
 * prot-none, clean, old	00..1...1...00
 * prot-none, clean, young	01..1...1...00
 * prot-none, dirty, old	10..1...1...00
 * prot-none, dirty, young	11..1...1...00
 * read-only, clean, old	00..1...1...01
 * read-only, clean, young	01..1...0...01
 * read-only, dirty, old	10..1...1...01
 * read-only, dirty, young	11..1...0...01
 * read-write, clean, old	00..1...1...11
 * read-write, clean, young	01..1...0...11
 * read-write, dirty, old	10..0...1...11
 * read-write, dirty, young	11..0...0...11
 * The segment table origin is used to distinguish empty (origin==0) from
 * read-write, old segment table entries (origin!=0)
 */

#define _SEGMENT_ENTRY_SPLIT_BIT 0	/* THP splitting bit number */

/* Set of bits not changed in pmd_modify */
#define _SEGMENT_CHG_MASK	(_SEGMENT_ENTRY_ORIGIN | _SEGMENT_ENTRY_LARGE \
				 | _SEGMENT_ENTRY_SPLIT | _SEGMENT_ENTRY_CO)
#define _SEGMENT_ENTRY_SPLIT_BIT 11	/* THP splitting bit number */

/* Page status table bits for virtualization */
#define PGSTE_ACC_BITS	0xf000000000000000UL
@@ -455,10 +466,11 @@ extern unsigned long MODULES_END;
 * Segment entry (large page) protection definitions.
 */
#define SEGMENT_NONE	__pgprot(_SEGMENT_ENTRY_INVALID | \
				 _SEGMENT_ENTRY_NONE)
#define SEGMENT_READ	__pgprot(_SEGMENT_ENTRY_INVALID | \
				 _SEGMENT_ENTRY_PROTECT)
#define SEGMENT_WRITE	__pgprot(_SEGMENT_ENTRY_INVALID)
#define SEGMENT_READ	__pgprot(_SEGMENT_ENTRY_PROTECT | \
				 _SEGMENT_ENTRY_READ)
#define SEGMENT_WRITE	__pgprot(_SEGMENT_ENTRY_READ | \
				 _SEGMENT_ENTRY_WRITE)

static inline int mm_has_pgste(struct mm_struct *mm)
{
@@ -569,25 +581,23 @@ static inline int pmd_none(pmd_t pmd)

static inline int pmd_large(pmd_t pmd)
{
#ifdef CONFIG_64BIT
	return (pmd_val(pmd) & _SEGMENT_ENTRY_LARGE) != 0;
#else
	return 0;
#endif
}

static inline int pmd_prot_none(pmd_t pmd)
static inline int pmd_pfn(pmd_t pmd)
{
	return (pmd_val(pmd) & _SEGMENT_ENTRY_INVALID) &&
		(pmd_val(pmd) & _SEGMENT_ENTRY_NONE);
	unsigned long origin_mask;

	origin_mask = _SEGMENT_ENTRY_ORIGIN;
	if (pmd_large(pmd))
		origin_mask = _SEGMENT_ENTRY_ORIGIN_LARGE;
	return (pmd_val(pmd) & origin_mask) >> PAGE_SHIFT;
}

static inline int pmd_bad(pmd_t pmd)
{
#ifdef CONFIG_64BIT
	if (pmd_large(pmd))
		return (pmd_val(pmd) & ~_SEGMENT_ENTRY_BITS_LARGE) != 0;
#endif
	return (pmd_val(pmd) & ~_SEGMENT_ENTRY_BITS) != 0;
}

@@ -607,20 +617,22 @@ extern int pmdp_clear_flush_young(struct vm_area_struct *vma,
#define __HAVE_ARCH_PMD_WRITE
static inline int pmd_write(pmd_t pmd)
{
	if (pmd_prot_none(pmd))
		return 0;
	return (pmd_val(pmd) & _SEGMENT_ENTRY_PROTECT) == 0;
	return (pmd_val(pmd) & _SEGMENT_ENTRY_WRITE) != 0;
}

static inline int pmd_dirty(pmd_t pmd)
{
	int dirty = 1;
	if (pmd_large(pmd))
		dirty = (pmd_val(pmd) & _SEGMENT_ENTRY_DIRTY) != 0;
	return dirty;
}

static inline int pmd_young(pmd_t pmd)
{
	int young = 0;
#ifdef CONFIG_64BIT
	if (pmd_prot_none(pmd))
		young = (pmd_val(pmd) & _SEGMENT_ENTRY_PROTECT) != 0;
	else
	int young = 1;
	if (pmd_large(pmd))
		young = (pmd_val(pmd) & _SEGMENT_ENTRY_YOUNG) != 0;
#endif
	return young;
}

@@ -1391,7 +1403,7 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address)
#define pte_pfn(x) (pte_val(x) >> PAGE_SHIFT)
#define pte_page(x) pfn_to_page(pte_pfn(x))

#define pmd_page(pmd) pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT)
#define pmd_page(pmd) pfn_to_page(pmd_pfn(pmd))

/* Find an entry in the lowest level page table.. */
#define pte_offset(pmd, addr) ((pte_t *) pmd_deref(*(pmd)) + pte_index(addr))
@@ -1413,41 +1425,75 @@ static inline unsigned long massage_pgprot_pmd(pgprot_t pgprot)
	return pgprot_val(SEGMENT_WRITE);
}

static inline pmd_t pmd_mkyoung(pmd_t pmd)
static inline pmd_t pmd_wrprotect(pmd_t pmd)
{
#ifdef CONFIG_64BIT
	if (pmd_prot_none(pmd)) {
	pmd_val(pmd) &= ~_SEGMENT_ENTRY_WRITE;
	pmd_val(pmd) |= _SEGMENT_ENTRY_PROTECT;
	} else {
	return pmd;
}

static inline pmd_t pmd_mkwrite(pmd_t pmd)
{
	pmd_val(pmd) |= _SEGMENT_ENTRY_WRITE;
	if (pmd_large(pmd) && !(pmd_val(pmd) & _SEGMENT_ENTRY_DIRTY))
		return pmd;
	pmd_val(pmd) &= ~_SEGMENT_ENTRY_PROTECT;
	return pmd;
}

static inline pmd_t pmd_mkclean(pmd_t pmd)
{
	if (pmd_large(pmd)) {
		pmd_val(pmd) &= ~_SEGMENT_ENTRY_DIRTY;
		pmd_val(pmd) |= _SEGMENT_ENTRY_PROTECT;
	}
	return pmd;
}

static inline pmd_t pmd_mkdirty(pmd_t pmd)
{
	if (pmd_large(pmd)) {
		pmd_val(pmd) |= _SEGMENT_ENTRY_DIRTY;
		if (pmd_val(pmd) & _SEGMENT_ENTRY_WRITE)
			pmd_val(pmd) &= ~_SEGMENT_ENTRY_PROTECT;
	}
	return pmd;
}

static inline pmd_t pmd_mkyoung(pmd_t pmd)
{
	if (pmd_large(pmd)) {
		pmd_val(pmd) |= _SEGMENT_ENTRY_YOUNG;
		if (pmd_val(pmd) & _SEGMENT_ENTRY_READ)
			pmd_val(pmd) &= ~_SEGMENT_ENTRY_INVALID;
	}
#endif
	return pmd;
}

static inline pmd_t pmd_mkold(pmd_t pmd)
{
#ifdef CONFIG_64BIT
	if (pmd_prot_none(pmd)) {
		pmd_val(pmd) &= ~_SEGMENT_ENTRY_PROTECT;
	} else {
	if (pmd_large(pmd)) {
		pmd_val(pmd) &= ~_SEGMENT_ENTRY_YOUNG;
		pmd_val(pmd) |= _SEGMENT_ENTRY_INVALID;
	}
#endif
	return pmd;
}

static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
{
	int young;

	young = pmd_young(pmd);
	pmd_val(pmd) &= _SEGMENT_CHG_MASK;
	if (pmd_large(pmd)) {
		pmd_val(pmd) &= _SEGMENT_ENTRY_ORIGIN_LARGE |
			_SEGMENT_ENTRY_DIRTY | _SEGMENT_ENTRY_YOUNG |
			_SEGMENT_ENTRY_LARGE | _SEGMENT_ENTRY_SPLIT;
		pmd_val(pmd) |= massage_pgprot_pmd(newprot);
		if (!(pmd_val(pmd) & _SEGMENT_ENTRY_DIRTY))
			pmd_val(pmd) |= _SEGMENT_ENTRY_PROTECT;
		if (!(pmd_val(pmd) & _SEGMENT_ENTRY_YOUNG))
			pmd_val(pmd) |= _SEGMENT_ENTRY_INVALID;
		return pmd;
	}
	pmd_val(pmd) &= _SEGMENT_ENTRY_ORIGIN;
	pmd_val(pmd) |= massage_pgprot_pmd(newprot);
	if (young)
		pmd = pmd_mkyoung(pmd);
	return pmd;
}

@@ -1455,16 +1501,9 @@ static inline pmd_t mk_pmd_phys(unsigned long physpage, pgprot_t pgprot)
{
	pmd_t __pmd;
	pmd_val(__pmd) = physpage + massage_pgprot_pmd(pgprot);
	return pmd_mkyoung(__pmd);
	return __pmd;
}

static inline pmd_t pmd_mkwrite(pmd_t pmd)
{
	/* Do not clobber PROT_NONE segments! */
	if (!pmd_prot_none(pmd))
		pmd_val(pmd) &= ~_SEGMENT_ENTRY_PROTECT;
	return pmd;
}
#endif /* CONFIG_TRANSPARENT_HUGEPAGE || CONFIG_HUGETLB_PAGE */

static inline void __pmdp_csp(pmd_t *pmdp)
@@ -1555,37 +1594,24 @@ extern pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp);

static inline int pmd_trans_splitting(pmd_t pmd)
{
	return pmd_val(pmd) & _SEGMENT_ENTRY_SPLIT;
	return (pmd_val(pmd) & _SEGMENT_ENTRY_LARGE) &&
		(pmd_val(pmd) & _SEGMENT_ENTRY_SPLIT);
}

static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
			      pmd_t *pmdp, pmd_t entry)
{
	if (!(pmd_val(entry) & _SEGMENT_ENTRY_INVALID) && MACHINE_HAS_EDAT1)
		pmd_val(entry) |= _SEGMENT_ENTRY_CO;
	*pmdp = entry;
}

static inline pmd_t pmd_mkhuge(pmd_t pmd)
{
	pmd_val(pmd) |= _SEGMENT_ENTRY_LARGE;
	return pmd;
}

static inline pmd_t pmd_wrprotect(pmd_t pmd)
{
	/* Do not clobber PROT_NONE segments! */
	if (!pmd_prot_none(pmd))
	pmd_val(pmd) |= _SEGMENT_ENTRY_YOUNG;
	pmd_val(pmd) |= _SEGMENT_ENTRY_PROTECT;
	return pmd;
}

static inline pmd_t pmd_mkdirty(pmd_t pmd)
{
	/* No dirty bit in the segment table entry. */
	return pmd;
}

#define __HAVE_ARCH_PMDP_TEST_AND_CLEAR_YOUNG
static inline int pmdp_test_and_clear_young(struct vm_area_struct *vma,
					    unsigned long address, pmd_t *pmdp)
@@ -1647,11 +1673,6 @@ static inline int has_transparent_hugepage(void)
{
	return MACHINE_HAS_HPAGE ? 1 : 0;
}

static inline unsigned long pmd_pfn(pmd_t pmd)
{
	return pmd_val(pmd) >> PAGE_SHIFT;
}
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */

/*
+4 −0
Original line number Diff line number Diff line
@@ -415,6 +415,10 @@ struct qdio_brinfo_entry_l2 {
#define QDIO_FLAG_SYNC_OUTPUT		0x02
#define QDIO_FLAG_PCI_OUT		0x10

int qdio_alloc_buffers(struct qdio_buffer **buf, unsigned int count);
void qdio_free_buffers(struct qdio_buffer **buf, unsigned int count);
void qdio_reset_buffers(struct qdio_buffer **buf, unsigned int count);

extern int qdio_allocate(struct qdio_initialize *);
extern int qdio_establish(struct qdio_initialize *);
extern int qdio_activate(struct ccw_device *);
+1 −1
Original line number Diff line number Diff line
@@ -54,7 +54,7 @@ static inline void syscall_set_return_value(struct task_struct *task,
					    struct pt_regs *regs,
					    int error, long val)
{
	regs->gprs[2] = error ? -error : val;
	regs->gprs[2] = error ? error : val;
}

static inline void syscall_get_arguments(struct task_struct *task,
Loading