History

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

Pull s390 fixes from Martin Schwidefsky: "Bug fixes for 3.6-rc7, including some important patches for large page related memory management issues." * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: s390/dasd: fix read unit address configuration loop s390/dasd: fix pathgroup race s390/mm: fix user access page-table walk code s390/hwcaps: do not report high gprs for 31 bit kernel s390/cio: invalidate cdev pointer before deregistration s390/cio: fix IO subchannel event race s390/dasd: move wake_up call s390/hugetlb: use direct TLB flushing for hugetlbfs pages s390/mm: fix deadlock in unmap_hugepage_range()

Linus Torvalds committed 14 years ago

Commit 267b50f2 parents 8ca7de9 03429f38 files · +146 −107Browse files

Unified · Split

8 files
  1. arch/s390/include/asm/hugetlb.h +10 −14
  2. arch/s390/include/asm/tlbflush.h +0 −2
  3. arch/s390/kernel/setup.c +2 −0
  4. arch/s390/lib/uaccess_pt.c +63 −79
  5. drivers/s390/block/dasd.c +14 −3
  6. drivers/s390/block/dasd_alias.c +26 −1
  7. drivers/s390/block/dasd_eckd.c +25 −7
  8. drivers/s390/cio/device.c +6 −1
arch/s390/include/asm/hugetlb.h+10−14
@@ -66,16 +66,6 @@ static inline pte_t huge_ptep_get(pte_t *ptep) · 65 unmodified lines
66 return pte;66 return pte;
67}67}
68 68
69static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
70 unsigned long addr, pte_t *ptep)
71{
72 pte_t pte = huge_ptep_get(ptep);
73
74 mm->context.flush_mm = 1;
75 pmd_clear((pmd_t *) ptep);
76 return pte;
77}
78
79static inline void __pmd_csp(pmd_t *pmdp)69static inline void __pmd_csp(pmd_t *pmdp)
80{70{
81 register unsigned long reg2 asm("2") = pmd_val(*pmdp);71 register unsigned long reg2 asm("2") = pmd_val(*pmdp);
@@ -117,6 +107,15 @@ static inline void huge_ptep_invalidate(struct mm_struct *mm, · 35 unmodified lines
117 __pmd_csp(pmdp);107 __pmd_csp(pmdp);
118}108}
119 109
110static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
111 unsigned long addr, pte_t *ptep)
112{
113 pte_t pte = huge_ptep_get(ptep);
114
115 huge_ptep_invalidate(mm, addr, ptep);
116 return pte;
117}
118
120#define huge_ptep_set_access_flags(__vma, __addr, __ptep, __entry, __dirty) \119#define huge_ptep_set_access_flags(__vma, __addr, __ptep, __entry, __dirty) \
121({ \120({ \
122 int __changed = !pte_same(huge_ptep_get(__ptep), __entry); \121 int __changed = !pte_same(huge_ptep_get(__ptep), __entry); \
@@ -131,10 +130,7 @@ static inline void huge_ptep_invalidate(struct mm_struct *mm, · 8 unmodified lines
131({ \130({ \
132 pte_t __pte = huge_ptep_get(__ptep); \131 pte_t __pte = huge_ptep_get(__ptep); \
133 if (pte_write(__pte)) { \132 if (pte_write(__pte)) { \
134 (__mm)->context.flush_mm = 1; \133 huge_ptep_invalidate(__mm, __addr, __ptep); \
135 if (atomic_read(&(__mm)->context.attach_count) > 1 || \
136 (__mm) != current->active_mm) \
137 huge_ptep_invalidate(__mm, __addr, __ptep); \
138 set_huge_pte_at(__mm, __addr, __ptep, \134 set_huge_pte_at(__mm, __addr, __ptep, \
139 huge_pte_wrprotect(__pte)); \135 huge_pte_wrprotect(__pte)); \
140 } \136 } \
arch/s390/include/asm/tlbflush.h+0−2
@@ -90,12 +90,10 @@ static inline void __tlb_flush_mm(struct mm_struct * mm) · 89 unmodified lines
90 90
91static inline void __tlb_flush_mm_cond(struct mm_struct * mm)91static inline void __tlb_flush_mm_cond(struct mm_struct * mm)
92{92{
93 spin_lock(&mm->page_table_lock);
94 if (mm->context.flush_mm) {93 if (mm->context.flush_mm) {
95 __tlb_flush_mm(mm);94 __tlb_flush_mm(mm);
96 mm->context.flush_mm = 0;95 mm->context.flush_mm = 0;
97 }96 }
98 spin_unlock(&mm->page_table_lock);
99}97}
100 98
101/*99/*
arch/s390/kernel/setup.c+2−0
@@ -974,11 +974,13 @@ static void __init setup_hwcaps(void) · 973 unmodified lines
974 if (MACHINE_HAS_HPAGE)974 if (MACHINE_HAS_HPAGE)
975 elf_hwcap |= HWCAP_S390_HPAGE;975 elf_hwcap |= HWCAP_S390_HPAGE;
976 976
977#if defined(CONFIG_64BIT)
977 /*978 /*
978 * 64-bit register support for 31-bit processes979 * 64-bit register support for 31-bit processes
979 * HWCAP_S390_HIGH_GPRS is bit 9.980 * HWCAP_S390_HIGH_GPRS is bit 9.
980 */981 */
981 elf_hwcap |= HWCAP_S390_HIGH_GPRS;982 elf_hwcap |= HWCAP_S390_HIGH_GPRS;
983#endif
982 984
983 get_cpu_id(&cpu_id);985 get_cpu_id(&cpu_id);
984 switch (cpu_id.machine) {986 switch (cpu_id.machine) {
arch/s390/lib/uaccess_pt.c+63−79
@@ -2,69 +2,82 @@ · 1 unmodified line
2 * User access functions based on page table walks for enhanced2 * User access functions based on page table walks for enhanced
3 * system layout without hardware support.3 * system layout without hardware support.
4 *4 *
5 * Copyright IBM Corp. 20065 * Copyright IBM Corp. 2006, 2012
6 * Author(s): Gerald Schaefer (gerald.schaefer@de.ibm.com)6 * Author(s): Gerald Schaefer (gerald.schaefer@de.ibm.com)
7 */7 */
8 8
9#include <linux/errno.h>9#include <linux/errno.h>
10#include <linux/hardirq.h>10#include <linux/hardirq.h>
11#include <linux/mm.h>11#include <linux/mm.h>
12#include <linux/hugetlb.h>
12#include <asm/uaccess.h>13#include <asm/uaccess.h>
13#include <asm/futex.h>14#include <asm/futex.h>
14#include "uaccess.h"15#include "uaccess.h"
15 16
16static inline pte_t *follow_table(struct mm_struct *mm, unsigned long addr)17
18/*
19 * Returns kernel address for user virtual address. If the returned address is
20 * >= -4095 (IS_ERR_VALUE(x) returns true), a fault has occured and the address
21 * contains the (negative) exception code.
22 */
23static __always_inline unsigned long follow_table(struct mm_struct *mm,
24 unsigned long addr, int write)
17{25{
18 pgd_t *pgd;26 pgd_t *pgd;
19 pud_t *pud;27 pud_t *pud;
20 pmd_t *pmd;28 pmd_t *pmd;
29 pte_t *ptep;
21 30
22 pgd = pgd_offset(mm, addr);31 pgd = pgd_offset(mm, addr);
23 if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))32 if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
24 return (pte_t *) 0x3a;33 return -0x3aUL;
25 34
26 pud = pud_offset(pgd, addr);35 pud = pud_offset(pgd, addr);
27 if (pud_none(*pud) || unlikely(pud_bad(*pud)))36 if (pud_none(*pud) || unlikely(pud_bad(*pud)))
28 return (pte_t *) 0x3b;37 return -0x3bUL;
29 38
30 pmd = pmd_offset(pud, addr);39 pmd = pmd_offset(pud, addr);
31 if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))40 if (pmd_none(*pmd))
32 return (pte_t *) 0x10;41 return -0x10UL;
42 if (pmd_huge(*pmd)) {
43 if (write && (pmd_val(*pmd) & _SEGMENT_ENTRY_RO))
44 return -0x04UL;
45 return (pmd_val(*pmd) & HPAGE_MASK) + (addr & ~HPAGE_MASK);
46 }
47 if (unlikely(pmd_bad(*pmd)))
48 return -0x10UL;
49
50 ptep = pte_offset_map(pmd, addr);
51 if (!pte_present(*ptep))
52 return -0x11UL;
53 if (write && !pte_write(*ptep))
54 return -0x04UL;
33 55
34 return pte_offset_map(pmd, addr);56 return (pte_val(*ptep) & PAGE_MASK) + (addr & ~PAGE_MASK);
35}57}
36 58
37static __always_inline size_t __user_copy_pt(unsigned long uaddr, void *kptr,59static __always_inline size_t __user_copy_pt(unsigned long uaddr, void *kptr,
38 size_t n, int write_user)60 size_t n, int write_user)
39{61{
40 struct mm_struct *mm = current->mm;62 struct mm_struct *mm = current->mm;
41 unsigned long offset, pfn, done, size;63 unsigned long offset, done, size, kaddr;
42 pte_t *pte;
43 void *from, *to;64 void *from, *to;
44 65
45 done = 0;66 done = 0;
46retry:67retry:
47 spin_lock(&mm->page_table_lock);68 spin_lock(&mm->page_table_lock);
48 do {69 do {
49 pte = follow_table(mm, uaddr);70 kaddr = follow_table(mm, uaddr, write_user);
50 if ((unsigned long) pte < 0x1000)71 if (IS_ERR_VALUE(kaddr))
51 goto fault;72 goto fault;
52 if (!pte_present(*pte)) {
53 pte = (pte_t *) 0x11;
54 goto fault;
55 } else if (write_user && !pte_write(*pte)) {
56 pte = (pte_t *) 0x04;
57 goto fault;
58 }
59 73
60 pfn = pte_pfn(*pte);74 offset = uaddr & ~PAGE_MASK;
61 offset = uaddr & (PAGE_SIZE - 1);
62 size = min(n - done, PAGE_SIZE - offset);75 size = min(n - done, PAGE_SIZE - offset);
63 if (write_user) {76 if (write_user) {
64 to = (void *)((pfn << PAGE_SHIFT) + offset);77 to = (void *) kaddr;
65 from = kptr + done;78 from = kptr + done;
66 } else {79 } else {
67 from = (void *)((pfn << PAGE_SHIFT) + offset);80 from = (void *) kaddr;
68 to = kptr + done;81 to = kptr + done;
69 }82 }
70 memcpy(to, from, size);83 memcpy(to, from, size);
@@ -75,7 +88,7 @@ retry: · 4 unmodified lines
75 return n - done;88 return n - done;
76fault:89fault:
77 spin_unlock(&mm->page_table_lock);90 spin_unlock(&mm->page_table_lock);
78 if (__handle_fault(uaddr, (unsigned long) pte, write_user))91 if (__handle_fault(uaddr, -kaddr, write_user))
79 return n - done;92 return n - done;
80 goto retry;93 goto retry;
81}94}
@@ -84,27 +97,22 @@ fault: · 2 unmodified lines
84 * Do DAT for user address by page table walk, return kernel address.97 * Do DAT for user address by page table walk, return kernel address.
85 * This function needs to be called with current->mm->page_table_lock held.98 * This function needs to be called with current->mm->page_table_lock held.
86 */99 */
87static __always_inline unsigned long __dat_user_addr(unsigned long uaddr)100static __always_inline unsigned long __dat_user_addr(unsigned long uaddr,
101 int write)
88{102{
89 struct mm_struct *mm = current->mm;103 struct mm_struct *mm = current->mm;
90 unsigned long pfn;104 unsigned long kaddr;
91 pte_t *pte;
92 int rc;105 int rc;
93 106
94retry:107retry:
95 pte = follow_table(mm, uaddr);108 kaddr = follow_table(mm, uaddr, write);
96 if ((unsigned long) pte < 0x1000)109 if (IS_ERR_VALUE(kaddr))
97 goto fault;
98 if (!pte_present(*pte)) {
99 pte = (pte_t *) 0x11;
100 goto fault;110 goto fault;
101 }
102 111
103 pfn = pte_pfn(*pte);112 return kaddr;
104 return (pfn << PAGE_SHIFT) + (uaddr & (PAGE_SIZE - 1));
105fault:113fault:
106 spin_unlock(&mm->page_table_lock);114 spin_unlock(&mm->page_table_lock);
107 rc = __handle_fault(uaddr, (unsigned long) pte, 0);115 rc = __handle_fault(uaddr, -kaddr, write);
108 spin_lock(&mm->page_table_lock);116 spin_lock(&mm->page_table_lock);
109 if (!rc)117 if (!rc)
110 goto retry;118 goto retry;
@@ -159,11 +167,9 @@ static size_t clear_user_pt(size_t n, void __user *to) · 48 unmodified lines
159 167
160static size_t strnlen_user_pt(size_t count, const char __user *src)168static size_t strnlen_user_pt(size_t count, const char __user *src)
161{169{
162 char *addr;
163 unsigned long uaddr = (unsigned long) src;170 unsigned long uaddr = (unsigned long) src;
164 struct mm_struct *mm = current->mm;171 struct mm_struct *mm = current->mm;
165 unsigned long offset, pfn, done, len;172 unsigned long offset, done, len, kaddr;
166 pte_t *pte;
167 size_t len_str;173 size_t len_str;
168 174
169 if (segment_eq(get_fs(), KERNEL_DS))175 if (segment_eq(get_fs(), KERNEL_DS))
@@ -172,19 +178,13 @@ static size_t strnlen_user_pt(size_t count, const char __user *src) · 2 unmodified lines
172retry:178retry:
173 spin_lock(&mm->page_table_lock);179 spin_lock(&mm->page_table_lock);
174 do {180 do {
175 pte = follow_table(mm, uaddr);181 kaddr = follow_table(mm, uaddr, 0);
176 if ((unsigned long) pte < 0x1000)182 if (IS_ERR_VALUE(kaddr))
177 goto fault;
178 if (!pte_present(*pte)) {
179 pte = (pte_t *) 0x11;
180 goto fault;183 goto fault;
181 }
182 184
183 pfn = pte_pfn(*pte);185 offset = uaddr & ~PAGE_MASK;
184 offset = uaddr & (PAGE_SIZE-1);
185 addr = (char *)(pfn << PAGE_SHIFT) + offset;
186 len = min(count - done, PAGE_SIZE - offset);186 len = min(count - done, PAGE_SIZE - offset);
187 len_str = strnlen(addr, len);187 len_str = strnlen((char *) kaddr, len);
188 done += len_str;188 done += len_str;
189 uaddr += len_str;189 uaddr += len_str;
190 } while ((len_str == len) && (done < count));190 } while ((len_str == len) && (done < count));
@@ -192,7 +192,7 @@ retry: · 1 unmodified line
192 return done + 1;192 return done + 1;
193fault:193fault:
194 spin_unlock(&mm->page_table_lock);194 spin_unlock(&mm->page_table_lock);
195 if (__handle_fault(uaddr, (unsigned long) pte, 0))195 if (__handle_fault(uaddr, -kaddr, 0))
196 return 0;196 return 0;
197 goto retry;197 goto retry;
198}198}
@@ -225,11 +225,10 @@ static size_t copy_in_user_pt(size_t n, void __user *to, · 26 unmodified lines
225 const void __user *from)225 const void __user *from)
226{226{
227 struct mm_struct *mm = current->mm;227 struct mm_struct *mm = current->mm;
228 unsigned long offset_from, offset_to, offset_max, pfn_from, pfn_to,228 unsigned long offset_max, uaddr, done, size, error_code;
229 uaddr, done, size, error_code;
230 unsigned long uaddr_from = (unsigned long) from;229 unsigned long uaddr_from = (unsigned long) from;
231 unsigned long uaddr_to = (unsigned long) to;230 unsigned long uaddr_to = (unsigned long) to;
232 pte_t *pte_from, *pte_to;231 unsigned long kaddr_to, kaddr_from;
233 int write_user;232 int write_user;
234 233
235 if (segment_eq(get_fs(), KERNEL_DS)) {234 if (segment_eq(get_fs(), KERNEL_DS)) {
@@ -242,38 +241,23 @@ retry: · 6 unmodified lines
242 do {241 do {
243 write_user = 0;242 write_user = 0;
244 uaddr = uaddr_from;243 uaddr = uaddr_from;
245 pte_from = follow_table(mm, uaddr_from);244 kaddr_from = follow_table(mm, uaddr_from, 0);
246 error_code = (unsigned long) pte_from;245 error_code = kaddr_from;
247 if (error_code < 0x1000)246 if (IS_ERR_VALUE(error_code))
248 goto fault;
249 if (!pte_present(*pte_from)) {
250 error_code = 0x11;
251 goto fault;247 goto fault;
252 }
253 248
254 write_user = 1;249 write_user = 1;
255 uaddr = uaddr_to;250 uaddr = uaddr_to;
256 pte_to = follow_table(mm, uaddr_to);251 kaddr_to = follow_table(mm, uaddr_to, 1);
257 error_code = (unsigned long) pte_to;252 error_code = (unsigned long) kaddr_to;
258 if (error_code < 0x1000)253 if (IS_ERR_VALUE(error_code))
259 goto fault;
260 if (!pte_present(*pte_to)) {
261 error_code = 0x11;
262 goto fault;254 goto fault;
263 } else if (!pte_write(*pte_to)) {
264 error_code = 0x04;
265 goto fault;
266 }
267 255
268 pfn_from = pte_pfn(*pte_from);256 offset_max = max(uaddr_from & ~PAGE_MASK,
269 pfn_to = pte_pfn(*pte_to);257 uaddr_to & ~PAGE_MASK);
270 offset_from = uaddr_from & (PAGE_SIZE-1);
271 offset_to = uaddr_from & (PAGE_SIZE-1);
272 offset_max = max(offset_from, offset_to);
273 size = min(n - done, PAGE_SIZE - offset_max);258 size = min(n - done, PAGE_SIZE - offset_max);
274 259
275 memcpy((void *)(pfn_to << PAGE_SHIFT) + offset_to,260 memcpy((void *) kaddr_to, (void *) kaddr_from, size);
276 (void *)(pfn_from << PAGE_SHIFT) + offset_from, size);
277 done += size;261 done += size;
278 uaddr_from += size;262 uaddr_from += size;
279 uaddr_to += size;263 uaddr_to += size;
@@ -282,7 +266,7 @@ retry: · 2 unmodified lines
282 return n - done;266 return n - done;
283fault:267fault:
284 spin_unlock(&mm->page_table_lock);268 spin_unlock(&mm->page_table_lock);
285 if (__handle_fault(uaddr, error_code, write_user))269 if (__handle_fault(uaddr, -error_code, write_user))
286 return n - done;270 return n - done;
287 goto retry;271 goto retry;
288}272}
@@ -341,7 +325,7 @@ int futex_atomic_op_pt(int op, u32 __user *uaddr, int oparg, int *old) · 52 unmodified lines
341 return __futex_atomic_op_pt(op, uaddr, oparg, old);325 return __futex_atomic_op_pt(op, uaddr, oparg, old);
342 spin_lock(&current->mm->page_table_lock);326 spin_lock(&current->mm->page_table_lock);
343 uaddr = (u32 __force __user *)327 uaddr = (u32 __force __user *)
344 __dat_user_addr((__force unsigned long) uaddr);328 __dat_user_addr((__force unsigned long) uaddr, 1);
345 if (!uaddr) {329 if (!uaddr) {
346 spin_unlock(&current->mm->page_table_lock);330 spin_unlock(&current->mm->page_table_lock);
347 return -EFAULT;331 return -EFAULT;
@@ -378,7 +362,7 @@ int futex_atomic_cmpxchg_pt(u32 *uval, u32 __user *uaddr, · 30 unmodified lines
378 return __futex_atomic_cmpxchg_pt(uval, uaddr, oldval, newval);362 return __futex_atomic_cmpxchg_pt(uval, uaddr, oldval, newval);
379 spin_lock(&current->mm->page_table_lock);363 spin_lock(&current->mm->page_table_lock);
380 uaddr = (u32 __force __user *)364 uaddr = (u32 __force __user *)
381 __dat_user_addr((__force unsigned long) uaddr);365 __dat_user_addr((__force unsigned long) uaddr, 1);
382 if (!uaddr) {366 if (!uaddr) {
383 spin_unlock(&current->mm->page_table_lock);367 spin_unlock(&current->mm->page_table_lock);
384 return -EFAULT;368 return -EFAULT;
drivers/s390/block/dasd.c+14−3
@@ -534,11 +534,11 @@ static void dasd_change_state(struct dasd_device *device) · 533 unmodified lines
534 if (rc)534 if (rc)
535 device->target = device->state;535 device->target = device->state;
536 536
537 if (device->state == device->target)
538 wake_up(&dasd_init_waitq);
539
540 /* let user-space know that the device status changed */537 /* let user-space know that the device status changed */
541 kobject_uevent(&device->cdev->dev.kobj, KOBJ_CHANGE);538 kobject_uevent(&device->cdev->dev.kobj, KOBJ_CHANGE);
539
540 if (device->state == device->target)
541 wake_up(&dasd_init_waitq);
542}542}
543 543
544/*544/*
@@ -2157,6 +2157,7 @@ static int _dasd_sleep_on(struct dasd_ccw_req *maincqr, int interruptible) · 1612 unmodified lines
2157 test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) &&2157 test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) &&
2158 (!dasd_eer_enabled(device))) {2158 (!dasd_eer_enabled(device))) {
2159 cqr->status = DASD_CQR_FAILED;2159 cqr->status = DASD_CQR_FAILED;
2160 cqr->intrc = -EAGAIN;
2160 continue;2161 continue;
2161 }2162 }
2162 /* Don't try to start requests if device is stopped */2163 /* Don't try to start requests if device is stopped */
@@ -3270,6 +3271,16 @@ void dasd_generic_path_event(struct ccw_device *cdev, int *path_event) · 1107 unmodified lines
3270 dasd_schedule_device_bh(device);3271 dasd_schedule_device_bh(device);
3271 }3272 }
3272 if (path_event[chp] & PE_PATHGROUP_ESTABLISHED) {3273 if (path_event[chp] & PE_PATHGROUP_ESTABLISHED) {
3274 if (!(device->path_data.opm & eventlpm) &&
3275 !(device->path_data.tbvpm & eventlpm)) {
3276 /*
3277 * we can not establish a pathgroup on an
3278 * unavailable path, so trigger a path
3279 * verification first
3280 */
3281 device->path_data.tbvpm |= eventlpm;
3282 dasd_schedule_device_bh(device);
3283 }
3273 DBF_DEV_EVENT(DBF_WARNING, device, "%s",3284 DBF_DEV_EVENT(DBF_WARNING, device, "%s",
3274 "Pathgroup re-established\n");3285 "Pathgroup re-established\n");
3275 if (device->discipline->kick_validate)3286 if (device->discipline->kick_validate)
drivers/s390/block/dasd_alias.c+26−1
@@ -384,6 +384,29 @@ static void _remove_device_from_lcu(struct alias_lcu *lcu, · 383 unmodified lines
384 group->next = NULL;384 group->next = NULL;
385};385};
386 386
387static int
388suborder_not_supported(struct dasd_ccw_req *cqr)
389{
390 char *sense;
391 char reason;
392 char msg_format;
393 char msg_no;
394
395 sense = dasd_get_sense(&cqr->irb);
396 if (!sense)
397 return 0;
398
399 reason = sense[0];
400 msg_format = (sense[7] & 0xF0);
401 msg_no = (sense[7] & 0x0F);
402
403 /* command reject, Format 0 MSG 4 - invalid parameter */
404 if ((reason == 0x80) && (msg_format == 0x00) && (msg_no == 0x04))
405 return 1;
406
407 return 0;
408}
409
387static int read_unit_address_configuration(struct dasd_device *device,410static int read_unit_address_configuration(struct dasd_device *device,
388 struct alias_lcu *lcu)411 struct alias_lcu *lcu)
389{412{
@@ -435,6 +458,8 @@ static int read_unit_address_configuration(struct dasd_device *device, · 45 unmodified lines
435 458
436 do {459 do {
437 rc = dasd_sleep_on(cqr);460 rc = dasd_sleep_on(cqr);
461 if (rc && suborder_not_supported(cqr))
462 return -EOPNOTSUPP;
438 } while (rc && (cqr->retries > 0));463 } while (rc && (cqr->retries > 0));
439 if (rc) {464 if (rc) {
440 spin_lock_irqsave(&lcu->lock, flags);465 spin_lock_irqsave(&lcu->lock, flags);
@@ -521,7 +546,7 @@ static void lcu_update_work(struct work_struct *work) · 80 unmodified lines
521 * processing the data546 * processing the data
522 */547 */
523 spin_lock_irqsave(&lcu->lock, flags);548 spin_lock_irqsave(&lcu->lock, flags);
524 if (rc || (lcu->flags & NEED_UAC_UPDATE)) {549 if ((rc && (rc != -EOPNOTSUPP)) || (lcu->flags & NEED_UAC_UPDATE)) {
525 DBF_DEV_EVENT(DBF_WARNING, device, "could not update"550 DBF_DEV_EVENT(DBF_WARNING, device, "could not update"
526 " alias data in lcu (rc = %d), retry later", rc);551 " alias data in lcu (rc = %d), retry later", rc);
527 schedule_delayed_work(&lcu->ruac_data.dwork, 30*HZ);552 schedule_delayed_work(&lcu->ruac_data.dwork, 30*HZ);
drivers/s390/block/dasd_eckd.c+25−7
@@ -1507,7 +1507,8 @@ static struct dasd_ccw_req *dasd_eckd_build_psf_ssc(struct dasd_device *device, · 1506 unmodified lines
1507 * call might change behaviour of DASD devices.1507 * call might change behaviour of DASD devices.
1508 */1508 */
1509static int1509static int
1510dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav)1510dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav,
1511 unsigned long flags)
1511{1512{
1512 struct dasd_ccw_req *cqr;1513 struct dasd_ccw_req *cqr;
1513 int rc;1514 int rc;
@@ -1516,10 +1517,19 @@ dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav) · 2 unmodified lines
1516 if (IS_ERR(cqr))1517 if (IS_ERR(cqr))
1517 return PTR_ERR(cqr);1518 return PTR_ERR(cqr);
1518 1519
1520 /*
1521 * set flags e.g. turn on failfast, to prevent blocking
1522 * the calling function should handle failed requests
1523 */
1524 cqr->flags |= flags;
1525
1519 rc = dasd_sleep_on(cqr);1526 rc = dasd_sleep_on(cqr);
1520 if (!rc)1527 if (!rc)
1521 /* trigger CIO to reprobe devices */1528 /* trigger CIO to reprobe devices */
1522 css_schedule_reprobe();1529 css_schedule_reprobe();
1530 else if (cqr->intrc == -EAGAIN)
1531 rc = -EAGAIN;
1532
1523 dasd_sfree_request(cqr, cqr->memdev);1533 dasd_sfree_request(cqr, cqr->memdev);
1524 return rc;1534 return rc;
1525}1535}
@@ -1527,7 +1537,8 @@ dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav) · 1 unmodified line
1527/*1537/*
1528 * Valide storage server of current device.1538 * Valide storage server of current device.
1529 */1539 */
1530static void dasd_eckd_validate_server(struct dasd_device *device)1540static int dasd_eckd_validate_server(struct dasd_device *device,
1541 unsigned long flags)
1531{1542{
1532 int rc;1543 int rc;
1533 struct dasd_eckd_private *private;1544 struct dasd_eckd_private *private;
@@ -1536,17 +1547,18 @@ static void dasd_eckd_validate_server(struct dasd_device *device) · 2 unmodified lines
1536 private = (struct dasd_eckd_private *) device->private;1547 private = (struct dasd_eckd_private *) device->private;
1537 if (private->uid.type == UA_BASE_PAV_ALIAS ||1548 if (private->uid.type == UA_BASE_PAV_ALIAS ||
1538 private->uid.type == UA_HYPER_PAV_ALIAS)1549 private->uid.type == UA_HYPER_PAV_ALIAS)
1539 return;1550 return 0;
1540 if (dasd_nopav || MACHINE_IS_VM)1551 if (dasd_nopav || MACHINE_IS_VM)
1541 enable_pav = 0;1552 enable_pav = 0;
1542 else1553 else
1543 enable_pav = 1;1554 enable_pav = 1;
1544 rc = dasd_eckd_psf_ssc(device, enable_pav);1555 rc = dasd_eckd_psf_ssc(device, enable_pav, flags);
1545 1556
1546 /* may be requested feature is not available on server,1557 /* may be requested feature is not available on server,
1547 * therefore just report error and go ahead */1558 * therefore just report error and go ahead */
1548 DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "PSF-SSC for SSID %04x "1559 DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "PSF-SSC for SSID %04x "
1549 "returned rc=%d", private->uid.ssid, rc);1560 "returned rc=%d", private->uid.ssid, rc);
1561 return rc;
1550}1562}
1551 1563
1552/*1564/*
@@ -1556,7 +1568,13 @@ static void dasd_eckd_do_validate_server(struct work_struct *work) · 3 unmodified lines
1556{1568{
1557 struct dasd_device *device = container_of(work, struct dasd_device,1569 struct dasd_device *device = container_of(work, struct dasd_device,
1558 kick_validate);1570 kick_validate);
1559 dasd_eckd_validate_server(device);1571 if (dasd_eckd_validate_server(device, DASD_CQR_FLAGS_FAILFAST)
1572 == -EAGAIN) {
1573 /* schedule worker again if failed */
1574 schedule_work(&device->kick_validate);
1575 return;
1576 }
1577
1560 dasd_put_device(device);1578 dasd_put_device(device);
1561}1579}
1562 1580
@@ -1685,7 +1703,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device) · 122 unmodified lines
1685 if (rc)1703 if (rc)
1686 goto out_err2;1704 goto out_err2;
1687 1705
1688 dasd_eckd_validate_server(device);1706 dasd_eckd_validate_server(device, 0);
1689 1707
1690 /* device may report different configuration data after LCU setup */1708 /* device may report different configuration data after LCU setup */
1691 rc = dasd_eckd_read_conf(device);1709 rc = dasd_eckd_read_conf(device);
@@ -4153,7 +4171,7 @@ static int dasd_eckd_restore_device(struct dasd_device *device) · 2461 unmodified lines
4153 rc = dasd_alias_make_device_known_to_lcu(device);4171 rc = dasd_alias_make_device_known_to_lcu(device);
4154 if (rc)4172 if (rc)
4155 return rc;4173 return rc;
4156 dasd_eckd_validate_server(device);4174 dasd_eckd_validate_server(device, DASD_CQR_FLAGS_FAILFAST);
4157 4175
4158 /* RE-Read Configuration Data */4176 /* RE-Read Configuration Data */
4159 rc = dasd_eckd_read_conf(device);4177 rc = dasd_eckd_read_conf(device);
drivers/s390/cio/device.c+6−1
@@ -1426,6 +1426,8 @@ static enum io_sch_action sch_get_action(struct subchannel *sch) · 1425 unmodified lines
1426 return IO_SCH_REPROBE;1426 return IO_SCH_REPROBE;
1427 if (cdev->online)1427 if (cdev->online)
1428 return IO_SCH_VERIFY;1428 return IO_SCH_VERIFY;
1429 if (cdev->private->state == DEV_STATE_NOT_OPER)
1430 return IO_SCH_UNREG_ATTACH;
1429 return IO_SCH_NOP;1431 return IO_SCH_NOP;
1430}1432}
1431 1433
@@ -1519,11 +1521,14 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process) · 87 unmodified lines
1519 goto out;1521 goto out;
1520 break;1522 break;
1521 case IO_SCH_UNREG_ATTACH:1523 case IO_SCH_UNREG_ATTACH:
1524 spin_lock_irqsave(sch->lock, flags);
1522 if (cdev->private->flags.resuming) {1525 if (cdev->private->flags.resuming) {
1523 /* Device will be handled later. */1526 /* Device will be handled later. */
1524 rc = 0;1527 rc = 0;
1525 goto out;1528 goto out_unlock;
1526 }1529 }
1530 sch_set_cdev(sch, NULL);
1531 spin_unlock_irqrestore(sch->lock, flags);
1527 /* Unregister ccw device. */1532 /* Unregister ccw device. */
1528 ccw_device_unregister(cdev);1533 ccw_device_unregister(cdev);
1529 break;1534 break;