aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/s390/block/dasd.c42
-rw-r--r--drivers/s390/block/dasd_eckd.c3
-rw-r--r--drivers/s390/char/sclp_cmd.c48
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}
584EXPORT_SYMBOL(dasd_kick_device); 585EXPORT_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}
604EXPORT_SYMBOL(dasd_reload_device); 606EXPORT_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
1634static u32 get_fcx_max_data(struct dasd_device *device) 1635static 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
324static 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
322static int sclp_mem_notifier(struct notifier_block *nb, 341static 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
391static 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
364static void __init add_memory_merged(u16 rn) 406static 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);
386skip_add: 430skip_add:
387 first_rn = rn; 431 first_rn = rn;
388 num = 1; 432 num = 1;