Commit 4ad48bb7 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux

Pull s390 fixes from Martin Schwidefsky:
 "A couple of bug fixes.  I keep the fingers crossed that we now got
  transparent huge pages ready for prime time."

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux:
  s390/cio: fix length calculation in idset.c
  s390/sclp: fix addressing mode clobber
  s390: Move css limits from drivers/s390/cio/ to include/asm/.
  s390/thp: respect page protection in pmd_none() and pmd_present()
  s390/mm: use pmd_large() instead of pmd_huge()
  s390/cio: suppress 2nd path verification during resume
parents 976bacef 7f0bc6c0
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
#define LPM_ANYPATH 0xff #define LPM_ANYPATH 0xff
#define __MAX_CSSID 0 #define __MAX_CSSID 0
#define __MAX_SUBCHANNEL 65535
#define __MAX_SSID 3
#include <asm/scsw.h> #include <asm/scsw.h>
......
...@@ -506,12 +506,15 @@ static inline int pud_bad(pud_t pud) ...@@ -506,12 +506,15 @@ static inline int pud_bad(pud_t pud)
static inline int pmd_present(pmd_t pmd) static inline int pmd_present(pmd_t pmd)
{ {
return (pmd_val(pmd) & _SEGMENT_ENTRY_ORIGIN) != 0UL; unsigned long mask = _SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO;
return (pmd_val(pmd) & mask) == _HPAGE_TYPE_NONE ||
!(pmd_val(pmd) & _SEGMENT_ENTRY_INV);
} }
static inline int pmd_none(pmd_t pmd) static inline int pmd_none(pmd_t pmd)
{ {
return (pmd_val(pmd) & _SEGMENT_ENTRY_INV) != 0UL; return (pmd_val(pmd) & _SEGMENT_ENTRY_INV) &&
!(pmd_val(pmd) & _SEGMENT_ENTRY_RO);
} }
static inline int pmd_large(pmd_t pmd) static inline int pmd_large(pmd_t pmd)
...@@ -1223,6 +1226,11 @@ static inline void __pmd_idte(unsigned long address, pmd_t *pmdp) ...@@ -1223,6 +1226,11 @@ static inline void __pmd_idte(unsigned long address, pmd_t *pmdp)
} }
#ifdef CONFIG_TRANSPARENT_HUGEPAGE #ifdef CONFIG_TRANSPARENT_HUGEPAGE
#define SEGMENT_NONE __pgprot(_HPAGE_TYPE_NONE)
#define SEGMENT_RO __pgprot(_HPAGE_TYPE_RO)
#define SEGMENT_RW __pgprot(_HPAGE_TYPE_RW)
#define __HAVE_ARCH_PGTABLE_DEPOSIT #define __HAVE_ARCH_PGTABLE_DEPOSIT
extern void pgtable_trans_huge_deposit(struct mm_struct *mm, pgtable_t pgtable); extern void pgtable_trans_huge_deposit(struct mm_struct *mm, pgtable_t pgtable);
...@@ -1242,16 +1250,15 @@ static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr, ...@@ -1242,16 +1250,15 @@ static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
static inline unsigned long massage_pgprot_pmd(pgprot_t pgprot) static inline unsigned long massage_pgprot_pmd(pgprot_t pgprot)
{ {
unsigned long pgprot_pmd = 0; /*
* pgprot is PAGE_NONE, PAGE_RO, or PAGE_RW (see __Pxxx / __Sxxx)
if (pgprot_val(pgprot) & _PAGE_INVALID) { * Convert to segment table entry format.
if (pgprot_val(pgprot) & _PAGE_SWT) */
pgprot_pmd |= _HPAGE_TYPE_NONE; if (pgprot_val(pgprot) == pgprot_val(PAGE_NONE))
pgprot_pmd |= _SEGMENT_ENTRY_INV; return pgprot_val(SEGMENT_NONE);
} if (pgprot_val(pgprot) == pgprot_val(PAGE_RO))
if (pgprot_val(pgprot) & _PAGE_RO) return pgprot_val(SEGMENT_RO);
pgprot_pmd |= _SEGMENT_ENTRY_RO; return pgprot_val(SEGMENT_RW);
return pgprot_pmd;
} }
static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
...@@ -1269,7 +1276,9 @@ static inline pmd_t pmd_mkhuge(pmd_t pmd) ...@@ -1269,7 +1276,9 @@ static inline pmd_t pmd_mkhuge(pmd_t pmd)
static inline pmd_t pmd_mkwrite(pmd_t pmd) static inline pmd_t pmd_mkwrite(pmd_t pmd)
{ {
pmd_val(pmd) &= ~_SEGMENT_ENTRY_RO; /* Do not clobber _HPAGE_TYPE_NONE pages! */
if (!(pmd_val(pmd) & _SEGMENT_ENTRY_INV))
pmd_val(pmd) &= ~_SEGMENT_ENTRY_RO;
return pmd; return pmd;
} }
......
...@@ -44,6 +44,12 @@ _sclp_wait_int: ...@@ -44,6 +44,12 @@ _sclp_wait_int:
#endif #endif
mvc .LoldpswS1-.LbaseS1(16,%r13),0(%r8) mvc .LoldpswS1-.LbaseS1(16,%r13),0(%r8)
mvc 0(16,%r8),0(%r9) mvc 0(16,%r8),0(%r9)
#ifdef CONFIG_64BIT
epsw %r6,%r7 # set current addressing mode
nill %r6,0x1 # in new psw (31 or 64 bit mode)
nilh %r7,0x8000
stm %r6,%r7,0(%r8)
#endif
lhi %r6,0x0200 # cr mask for ext int (cr0.54) lhi %r6,0x0200 # cr mask for ext int (cr0.54)
ltr %r2,%r2 ltr %r2,%r2
jz .LsetctS1 jz .LsetctS1
...@@ -87,7 +93,7 @@ _sclp_wait_int: ...@@ -87,7 +93,7 @@ _sclp_wait_int:
.long 0x00080000, 0x80000000+.LwaitS1 # PSW to handle ext int .long 0x00080000, 0x80000000+.LwaitS1 # PSW to handle ext int
#ifdef CONFIG_64BIT #ifdef CONFIG_64BIT
.LextpswS1_64: .LextpswS1_64:
.quad 0x0000000180000000, .LwaitS1 # PSW to handle ext int, 64 bit .quad 0, .LwaitS1 # PSW to handle ext int, 64 bit
#endif #endif
.LwaitpswS1: .LwaitpswS1:
.long 0x010a0000, 0x00000000+.LloopS1 # PSW to wait for ext int .long 0x010a0000, 0x00000000+.LloopS1 # PSW to wait for ext int
......
...@@ -39,7 +39,7 @@ static __always_inline unsigned long follow_table(struct mm_struct *mm, ...@@ -39,7 +39,7 @@ static __always_inline unsigned long follow_table(struct mm_struct *mm,
pmd = pmd_offset(pud, addr); pmd = pmd_offset(pud, addr);
if (pmd_none(*pmd)) if (pmd_none(*pmd))
return -0x10UL; return -0x10UL;
if (pmd_huge(*pmd)) { if (pmd_large(*pmd)) {
if (write && (pmd_val(*pmd) & _SEGMENT_ENTRY_RO)) if (write && (pmd_val(*pmd) & _SEGMENT_ENTRY_RO))
return -0x04UL; return -0x04UL;
return (pmd_val(*pmd) & HPAGE_MASK) + (addr & ~HPAGE_MASK); return (pmd_val(*pmd) & HPAGE_MASK) + (addr & ~HPAGE_MASK);
......
...@@ -126,7 +126,7 @@ static inline int gup_pmd_range(pud_t *pudp, pud_t pud, unsigned long addr, ...@@ -126,7 +126,7 @@ static inline int gup_pmd_range(pud_t *pudp, pud_t pud, unsigned long addr,
*/ */
if (pmd_none(pmd) || pmd_trans_splitting(pmd)) if (pmd_none(pmd) || pmd_trans_splitting(pmd))
return 0; return 0;
if (unlikely(pmd_huge(pmd))) { if (unlikely(pmd_large(pmd))) {
if (!gup_huge_pmd(pmdp, pmd, addr, next, if (!gup_huge_pmd(pmdp, pmd, addr, next,
write, pages, nr)) write, pages, nr))
return 0; return 0;
......
...@@ -112,9 +112,6 @@ extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *); ...@@ -112,9 +112,6 @@ extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *);
extern void css_reiterate_subchannels(void); extern void css_reiterate_subchannels(void);
void css_update_ssd_info(struct subchannel *sch); void css_update_ssd_info(struct subchannel *sch);
#define __MAX_SUBCHANNEL 65535
#define __MAX_SSID 3
struct channel_subsystem { struct channel_subsystem {
u8 cssid; u8 cssid;
int valid; int valid;
......
...@@ -1424,7 +1424,7 @@ static enum io_sch_action sch_get_action(struct subchannel *sch) ...@@ -1424,7 +1424,7 @@ static enum io_sch_action sch_get_action(struct subchannel *sch)
} }
if (device_is_disconnected(cdev)) if (device_is_disconnected(cdev))
return IO_SCH_REPROBE; return IO_SCH_REPROBE;
if (cdev->online) if (cdev->online && !cdev->private->flags.resuming)
return IO_SCH_VERIFY; return IO_SCH_VERIFY;
if (cdev->private->state == DEV_STATE_NOT_OPER) if (cdev->private->state == DEV_STATE_NOT_OPER)
return IO_SCH_UNREG_ATTACH; return IO_SCH_UNREG_ATTACH;
...@@ -1469,12 +1469,6 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process) ...@@ -1469,12 +1469,6 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process)
rc = 0; rc = 0;
goto out_unlock; goto out_unlock;
case IO_SCH_VERIFY: case IO_SCH_VERIFY:
if (cdev->private->flags.resuming == 1) {
if (cio_enable_subchannel(sch, (u32)(addr_t)sch)) {
ccw_device_set_notoper(cdev);
break;
}
}
/* Trigger path verification. */ /* Trigger path verification. */
io_subchannel_verify(sch); io_subchannel_verify(sch);
rc = 0; rc = 0;
......
...@@ -125,8 +125,7 @@ int idset_is_empty(struct idset *set) ...@@ -125,8 +125,7 @@ int idset_is_empty(struct idset *set)
void idset_add_set(struct idset *to, struct idset *from) void idset_add_set(struct idset *to, struct idset *from)
{ {
int len = min(__BITOPS_WORDS(to->num_ssid * to->num_id), int len = min(to->num_ssid * to->num_id, from->num_ssid * from->num_id);
__BITOPS_WORDS(from->num_ssid * from->num_id));
bitmap_or(to->bitmap, to->bitmap, from->bitmap, len); bitmap_or(to->bitmap, to->bitmap, from->bitmap, len);
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment