diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/s390/block/dasd.c | 42 | ||||
-rw-r--r-- | drivers/s390/block/dasd_eckd.c | 3 | ||||
-rw-r--r-- | drivers/s390/char/sclp_cmd.c | 48 |
3 files changed, 75 insertions, 18 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 26a51dc4278d..57fd66357b95 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
@@ -579,7 +579,8 @@ void dasd_kick_device(struct dasd_device *device) | |||
579 | { | 579 | { |
580 | dasd_get_device(device); | 580 | dasd_get_device(device); |
581 | /* queue call to dasd_kick_device to the kernel event daemon. */ | 581 | /* queue call to dasd_kick_device to the kernel event daemon. */ |
582 | schedule_work(&device->kick_work); | 582 | if (!schedule_work(&device->kick_work)) |
583 | dasd_put_device(device); | ||
583 | } | 584 | } |
584 | EXPORT_SYMBOL(dasd_kick_device); | 585 | EXPORT_SYMBOL(dasd_kick_device); |
585 | 586 | ||
@@ -599,7 +600,8 @@ void dasd_reload_device(struct dasd_device *device) | |||
599 | { | 600 | { |
600 | dasd_get_device(device); | 601 | dasd_get_device(device); |
601 | /* queue call to dasd_reload_device to the kernel event daemon. */ | 602 | /* queue call to dasd_reload_device to the kernel event daemon. */ |
602 | schedule_work(&device->reload_device); | 603 | if (!schedule_work(&device->reload_device)) |
604 | dasd_put_device(device); | ||
603 | } | 605 | } |
604 | EXPORT_SYMBOL(dasd_reload_device); | 606 | EXPORT_SYMBOL(dasd_reload_device); |
605 | 607 | ||
@@ -619,7 +621,8 @@ void dasd_restore_device(struct dasd_device *device) | |||
619 | { | 621 | { |
620 | dasd_get_device(device); | 622 | dasd_get_device(device); |
621 | /* queue call to dasd_restore_device to the kernel event daemon. */ | 623 | /* queue call to dasd_restore_device to the kernel event daemon. */ |
622 | schedule_work(&device->restore_device); | 624 | if (!schedule_work(&device->restore_device)) |
625 | dasd_put_device(device); | ||
623 | } | 626 | } |
624 | 627 | ||
625 | /* | 628 | /* |
@@ -2163,18 +2166,22 @@ static int _dasd_sleep_on(struct dasd_ccw_req *maincqr, int interruptible) | |||
2163 | cqr->intrc = -ENOLINK; | 2166 | cqr->intrc = -ENOLINK; |
2164 | continue; | 2167 | continue; |
2165 | } | 2168 | } |
2166 | /* Don't try to start requests if device is stopped */ | 2169 | /* |
2167 | if (interruptible) { | 2170 | * Don't try to start requests if device is stopped |
2168 | rc = wait_event_interruptible( | 2171 | * except path verification requests |
2169 | generic_waitq, !(device->stopped)); | 2172 | */ |
2170 | if (rc == -ERESTARTSYS) { | 2173 | if (!test_bit(DASD_CQR_VERIFY_PATH, &cqr->flags)) { |
2171 | cqr->status = DASD_CQR_FAILED; | 2174 | if (interruptible) { |
2172 | maincqr->intrc = rc; | 2175 | rc = wait_event_interruptible( |
2173 | continue; | 2176 | generic_waitq, !(device->stopped)); |
2174 | } | 2177 | if (rc == -ERESTARTSYS) { |
2175 | } else | 2178 | cqr->status = DASD_CQR_FAILED; |
2176 | wait_event(generic_waitq, !(device->stopped)); | 2179 | maincqr->intrc = rc; |
2177 | 2180 | continue; | |
2181 | } | ||
2182 | } else | ||
2183 | wait_event(generic_waitq, !(device->stopped)); | ||
2184 | } | ||
2178 | if (!cqr->callback) | 2185 | if (!cqr->callback) |
2179 | cqr->callback = dasd_wakeup_cb; | 2186 | cqr->callback = dasd_wakeup_cb; |
2180 | 2187 | ||
@@ -2524,6 +2531,11 @@ static void __dasd_process_request_queue(struct dasd_block *block) | |||
2524 | __blk_end_request_all(req, -EIO); | 2531 | __blk_end_request_all(req, -EIO); |
2525 | return; | 2532 | return; |
2526 | } | 2533 | } |
2534 | |||
2535 | /* if device ist stopped do not fetch new requests */ | ||
2536 | if (basedev->stopped) | ||
2537 | return; | ||
2538 | |||
2527 | /* Now we try to fetch requests from the request queue */ | 2539 | /* Now we try to fetch requests from the request queue */ |
2528 | while ((req = blk_peek_request(queue))) { | 2540 | while ((req = blk_peek_request(queue))) { |
2529 | if (basedev->features & DASD_FEATURE_READONLY && | 2541 | if (basedev->features & DASD_FEATURE_READONLY && |
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 49b48a887c66..6215f6455eb8 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
@@ -1628,7 +1628,8 @@ static void dasd_eckd_kick_validate_server(struct dasd_device *device) | |||
1628 | return; | 1628 | return; |
1629 | } | 1629 | } |
1630 | /* queue call to do_validate_server to the kernel event daemon. */ | 1630 | /* queue call to do_validate_server to the kernel event daemon. */ |
1631 | schedule_work(&device->kick_validate); | 1631 | if (!schedule_work(&device->kick_validate)) |
1632 | dasd_put_device(device); | ||
1632 | } | 1633 | } |
1633 | 1634 | ||
1634 | static u32 get_fcx_max_data(struct dasd_device *device) | 1635 | static u32 get_fcx_max_data(struct dasd_device *device) |
diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c index 6e14999f9e8f..7be782116dab 100644 --- a/drivers/s390/char/sclp_cmd.c +++ b/drivers/s390/char/sclp_cmd.c | |||
@@ -315,10 +315,29 @@ static int sclp_mem_change_state(unsigned long start, unsigned long size, | |||
315 | rc |= sclp_assign_storage(incr->rn); | 315 | rc |= sclp_assign_storage(incr->rn); |
316 | else | 316 | else |
317 | sclp_unassign_storage(incr->rn); | 317 | sclp_unassign_storage(incr->rn); |
318 | if (rc == 0) | ||
319 | incr->standby = online ? 0 : 1; | ||
318 | } | 320 | } |
319 | return rc ? -EIO : 0; | 321 | return rc ? -EIO : 0; |
320 | } | 322 | } |
321 | 323 | ||
324 | static bool contains_standby_increment(unsigned long start, unsigned long end) | ||
325 | { | ||
326 | struct memory_increment *incr; | ||
327 | unsigned long istart; | ||
328 | |||
329 | list_for_each_entry(incr, &sclp_mem_list, list) { | ||
330 | istart = rn2addr(incr->rn); | ||
331 | if (end - 1 < istart) | ||
332 | continue; | ||
333 | if (start > istart + sclp_rzm - 1) | ||
334 | continue; | ||
335 | if (incr->standby) | ||
336 | return true; | ||
337 | } | ||
338 | return false; | ||
339 | } | ||
340 | |||
322 | static int sclp_mem_notifier(struct notifier_block *nb, | 341 | static int sclp_mem_notifier(struct notifier_block *nb, |
323 | unsigned long action, void *data) | 342 | unsigned long action, void *data) |
324 | { | 343 | { |
@@ -334,8 +353,16 @@ static int sclp_mem_notifier(struct notifier_block *nb, | |||
334 | for_each_clear_bit(id, sclp_storage_ids, sclp_max_storage_id + 1) | 353 | for_each_clear_bit(id, sclp_storage_ids, sclp_max_storage_id + 1) |
335 | sclp_attach_storage(id); | 354 | sclp_attach_storage(id); |
336 | switch (action) { | 355 | switch (action) { |
337 | case MEM_ONLINE: | ||
338 | case MEM_GOING_OFFLINE: | 356 | case MEM_GOING_OFFLINE: |
357 | /* | ||
358 | * We do not allow to set memory blocks offline that contain | ||
359 | * standby memory. This is done to simplify the "memory online" | ||
360 | * case. | ||
361 | */ | ||
362 | if (contains_standby_increment(start, start + size)) | ||
363 | rc = -EPERM; | ||
364 | break; | ||
365 | case MEM_ONLINE: | ||
339 | case MEM_CANCEL_OFFLINE: | 366 | case MEM_CANCEL_OFFLINE: |
340 | break; | 367 | break; |
341 | case MEM_GOING_ONLINE: | 368 | case MEM_GOING_ONLINE: |
@@ -361,6 +388,21 @@ static struct notifier_block sclp_mem_nb = { | |||
361 | .notifier_call = sclp_mem_notifier, | 388 | .notifier_call = sclp_mem_notifier, |
362 | }; | 389 | }; |
363 | 390 | ||
391 | static void __init align_to_block_size(unsigned long long *start, | ||
392 | unsigned long long *size) | ||
393 | { | ||
394 | unsigned long long start_align, size_align, alignment; | ||
395 | |||
396 | alignment = memory_block_size_bytes(); | ||
397 | start_align = roundup(*start, alignment); | ||
398 | size_align = rounddown(*start + *size, alignment) - start_align; | ||
399 | |||
400 | pr_info("Standby memory at 0x%llx (%lluM of %lluM usable)\n", | ||
401 | *start, size_align >> 20, *size >> 20); | ||
402 | *start = start_align; | ||
403 | *size = size_align; | ||
404 | } | ||
405 | |||
364 | static void __init add_memory_merged(u16 rn) | 406 | static void __init add_memory_merged(u16 rn) |
365 | { | 407 | { |
366 | static u16 first_rn, num; | 408 | static u16 first_rn, num; |
@@ -382,7 +424,9 @@ static void __init add_memory_merged(u16 rn) | |||
382 | goto skip_add; | 424 | goto skip_add; |
383 | if (memory_end_set && (start + size > memory_end)) | 425 | if (memory_end_set && (start + size > memory_end)) |
384 | size = memory_end - start; | 426 | size = memory_end - start; |
385 | add_memory(0, start, size); | 427 | align_to_block_size(&start, &size); |
428 | if (size) | ||
429 | add_memory(0, start, size); | ||
386 | skip_add: | 430 | skip_add: |
387 | first_rn = rn; | 431 | first_rn = rn; |
388 | num = 1; | 432 | num = 1; |