diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-09 19:01:47 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-09 19:01:47 -0800 |
commit | 67dd2f5a669f48e48ea1013fb80522adca8287f4 (patch) | |
tree | eee4e7f15df90f899211cde0a669d661085de05d /drivers/s390 | |
parent | 5327b9b83a9c45a3fcbcda224a2b02d9eea9f6bb (diff) | |
parent | 42d61b9b415686d81eaa022b846737548876e51d (diff) |
Merge branch 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6
* 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6: (72 commits)
[S390] 3215/3270 console: remove wrong comment
[S390] dasd: remove BKL from extended error reporting code
[S390] vmlogrdr: remove BKL
[S390] vmur: remove BKL
[S390] zcrypt: remove BKL
[S390] 3270: remove BKL
[S390] vmwatchdog: remove lock_kernel() from open() function
[S390] monwriter: remove lock_kernel() from open() function
[S390] monreader: remove lock_kernel() from open() function
[S390] s390: remove unused nfsd #includes
[S390] ftrace: build ftrace.o when CONFIG_FTRACE_SYSCALLS is set for s390
[S390] etr/stp: put correct per cpu variable
[S390] tty3270: move keyboard compat ioctls
[S390] sclp: improve servicability setting
[S390] s390: use change recording override for kernel mapping
[S390] MAINTAINERS: Add s390 drivers block
[S390] use generic sockios.h header file
[S390] use generic termbits.h header file
[S390] smp: remove unused typedef and defines
[S390] cmm: free pages on hibernate.
...
Diffstat (limited to 'drivers/s390')
48 files changed, 2353 insertions, 2055 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index aaccc8ecfa8..fdb2e7c1450 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -24,7 +24,6 @@ #include <asm/ccwdev.h> #include <asm/ebcdic.h> #include <asm/idals.h> -#include <asm/todclk.h> #include <asm/itcw.h> /* This is ugly... */ @@ -64,6 +63,7 @@ static void do_restore_device(struct work_struct *); static void dasd_return_cqr_cb(struct dasd_ccw_req *, void *); static void dasd_device_timeout(unsigned long); static void dasd_block_timeout(unsigned long); +static void __dasd_process_erp(struct dasd_device *, struct dasd_ccw_req *); /* * SECTION: Operations on the device structure. @@ -960,7 +960,7 @@ static void dasd_device_timeout(unsigned long ptr) device = (struct dasd_device *) ptr; spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); /* re-activate request queue */ - device->stopped &= ~DASD_STOPPED_PENDING; + dasd_device_remove_stop_bits(device, DASD_STOPPED_PENDING); spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); dasd_schedule_device_bh(device); } @@ -994,10 +994,9 @@ static void dasd_handle_killed_request(struct ccw_device *cdev, return; cqr = (struct dasd_ccw_req *) intparm; if (cqr->status != DASD_CQR_IN_IO) { - DBF_EVENT(DBF_DEBUG, - "invalid status in handle_killed_request: " - "bus_id %s, status %02x", - dev_name(&cdev->dev), cqr->status); + DBF_EVENT_DEVID(DBF_DEBUG, cdev, + "invalid status in handle_killed_request: " + "%02x", cqr->status); return; } @@ -1023,7 +1022,7 @@ void dasd_generic_handle_state_change(struct dasd_device *device) /* First of all start sense subsystem status request. */ dasd_eer_snss(device); - device->stopped &= ~DASD_STOPPED_PENDING; + dasd_device_remove_stop_bits(device, DASD_STOPPED_PENDING); dasd_schedule_device_bh(device); if (device->block) dasd_schedule_block_bh(device->block); @@ -1045,12 +1044,13 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, case -EIO: break; case -ETIMEDOUT: - DBF_EVENT(DBF_WARNING, "%s(%s): request timed out\n", - __func__, dev_name(&cdev->dev)); + DBF_EVENT_DEVID(DBF_WARNING, cdev, "%s: " + "request timed out\n", __func__); break; default: - DBF_EVENT(DBF_WARNING, "%s(%s): unknown error %ld\n", - __func__, dev_name(&cdev->dev), PTR_ERR(irb)); + DBF_EVENT_DEVID(DBF_WARNING, cdev, "%s: " + "unknown error %ld\n", __func__, + PTR_ERR(irb)); } dasd_handle_killed_request(cdev, intparm); return; @@ -1405,6 +1405,20 @@ void dasd_schedule_device_bh(struct dasd_device *device) tasklet_hi_schedule(&device->tasklet); } +void dasd_device_set_stop_bits(struct dasd_device *device, int bits) +{ + device->stopped |= bits; +} +EXPORT_SYMBOL_GPL(dasd_device_set_stop_bits); + +void dasd_device_remove_stop_bits(struct dasd_device *device, int bits) +{ + device->stopped &= ~bits; + if (!device->stopped) + wake_up(&generic_waitq); +} +EXPORT_SYMBOL_GPL(dasd_device_remove_stop_bits); + /* * Queue a request to the head of the device ccw_queue. * Start the I/O if possible. @@ -1465,58 +1479,135 @@ static inline int _wait_for_wakeup(struct dasd_ccw_req *cqr) } /* - * Queue a request to the tail of the device ccw_queue and wait for - * it's completion. + * checks if error recovery is necessary, returns 1 if yes, 0 otherwise. */ -int dasd_sleep_on(struct dasd_ccw_req *cqr) +static int __dasd_sleep_on_erp(struct dasd_ccw_req *cqr) { struct dasd_device *device; - int rc; + dasd_erp_fn_t erp_fn; + if (cqr->status == DASD_CQR_FILLED) + return 0; device = cqr->startdev; + if (test_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags)) { + if (cqr->status == DASD_CQR_TERMINATED) { + device->discipline->handle_terminated_request(cqr); + return 1; + } + if (cqr->status == DASD_CQR_NEED_ERP) { + erp_fn = device->discipline->erp_action(cqr); + erp_fn(cqr); + return 1; + } + if (cqr->status == DASD_CQR_FAILED) + dasd_log_sense(cqr, &cqr->irb); + if (cqr->refers) { + __dasd_process_erp(device, cqr); + return 1; + } + } + return 0; +} - cqr->callback = dasd_wakeup_cb; - cqr->callback_data = (void *) &generic_waitq; - dasd_add_request_tail(cqr); - wait_event(generic_waitq, _wait_for_wakeup(cqr)); +static int __dasd_sleep_on_loop_condition(struct dasd_ccw_req *cqr) +{ + if (test_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags)) { + if (cqr->refers) /* erp is not done yet */ + return 1; + return ((cqr->status != DASD_CQR_DONE) && + (cqr->status != DASD_CQR_FAILED)); + } else + return (cqr->status == DASD_CQR_FILLED); +} - if (cqr->status == DASD_CQR_DONE) +static int _dasd_sleep_on(struct dasd_ccw_req *maincqr, int interruptible) +{ + struct dasd_device *device; + int rc; + struct list_head ccw_queue; + struct dasd_ccw_req *cqr; + + INIT_LIST_HEAD(&ccw_queue); + maincqr->status = DASD_CQR_FILLED; + device = maincqr->startdev; + list_add(&maincqr->blocklist, &ccw_queue); + for (cqr = maincqr; __dasd_sleep_on_loop_condition(cqr); + cqr = list_first_entry(&ccw_queue, + struct dasd_ccw_req, blocklist)) { + + if (__dasd_sleep_on_erp(cqr)) + continue; + if (cqr->status != DASD_CQR_FILLED) /* could be failed */ + continue; + + /* Non-temporary stop condition will trigger fail fast */ + if (device->stopped & ~DASD_STOPPED_PENDING && + test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) && + (!dasd_eer_enabled(device))) { + cqr->status = DASD_CQR_FAILED; + continue; + } + + /* Don't try to start requests if device is stopped */ + if (interruptible) { + rc = wait_event_interruptible( + generic_waitq, !(device->stopped)); + if (rc == -ERESTARTSYS) { + cqr->status = DASD_CQR_FAILED; + maincqr->intrc = rc; + continue; + } + } else + wait_event(generic_waitq, !(device->stopped)); + + cqr->callback = dasd_wakeup_cb; + cqr->callback_data = (void *) &generic_waitq; + dasd_add_request_tail(cqr); + if (interruptible) { + rc = wait_event_interruptible( + generic_waitq, _wait_for_wakeup(cqr)); + if (rc == -ERESTARTSYS) { + dasd_cancel_req(cqr); + /* wait (non-interruptible) for final status */ + wait_event(generic_waitq, + _wait_for_wakeup(cqr)); + cqr->status = DASD_CQR_FAILED; + maincqr->intrc = rc; + continue; + } + } else + wait_event(generic_waitq, _wait_for_wakeup(cqr)); + } + + maincqr->endclk = get_clock(); + if ((maincqr->status != DASD_CQR_DONE) && + (maincqr->intrc != -ERESTARTSYS)) + dasd_log_sense(maincqr, &maincqr->irb); + if (maincqr->status == DASD_CQR_DONE) rc = 0; - else if (cqr->intrc) - rc = cqr->intrc; + else if (maincqr->intrc) + rc = maincqr->intrc; else rc = -EIO; return rc; } /* + * Queue a request to the tail of the device ccw_queue and wait for + * it's completion. + */ +int dasd_sleep_on(struct dasd_ccw_req *cqr) +{ + return _dasd_sleep_on(cqr, 0); +} + +/* * Queue a request to the tail of the device ccw_queue and wait * interruptible for it's completion. */ int dasd_sleep_on_interruptible(struct dasd_ccw_req *cqr) { - struct dasd_device *device; - int rc; - - device = cqr->startdev; - cqr->callback = dasd_wakeup_cb; - cqr->callback_data = (void *) &generic_waitq; - dasd_add_request_tail(cqr); - rc = wait_event_interruptible(generic_waitq, _wait_for_wakeup(cqr)); - if (rc == -ERESTARTSYS) { - dasd_cancel_req(cqr); - /* wait (non-interruptible) for final status */ - wait_event(generic_waitq, _wait_for_wakeup(cqr)); - cqr->intrc = rc; - } - - if (cqr->status == DASD_CQR_DONE) - rc = 0; - else if (cqr->intrc) - rc = cqr->intrc; - else - rc = -EIO; - return rc; + return _dasd_sleep_on(cqr, 1); } /* @@ -1630,7 +1721,7 @@ static void dasd_block_timeout(unsigned long ptr) block = (struct dasd_block *) ptr; spin_lock_irqsave(get_ccwdev_lock(block->base->cdev), flags); /* re-activate request queue */ - block->base->stopped &= ~DASD_STOPPED_PENDING; + dasd_device_remove_stop_bits(block->base, DASD_STOPPED_PENDING); spin_unlock_irqrestore(get_ccwdev_lock(block->base->cdev), flags); dasd_schedule_block_bh(block); } @@ -1657,11 +1748,10 @@ void dasd_block_clear_timer(struct dasd_block *block) /* * Process finished error recovery ccw. */ -static inline void __dasd_block_process_erp(struct dasd_block *block, - struct dasd_ccw_req *cqr) +static void __dasd_process_erp(struct dasd_device *device, + struct dasd_ccw_req *cqr) { dasd_erp_fn_t erp_fn; - struct dasd_device *device = block->base; if (cqr->status == DASD_CQR_DONE) DBF_DEV_EVENT(DBF_NOTICE, device, "%s", "ERP successful"); @@ -1725,9 +1815,12 @@ static void __dasd_process_request_queue(struct dasd_block *block) */ if (!list_empty(&block->ccw_queue)) break; - spin_lock_irqsave(get_ccwdev_lock(basedev->cdev), flags); - basedev->stopped |= DASD_STOPPED_PENDING; - spin_unlock_irqrestore(get_ccwdev_lock(basedev->cdev), flags); + spin_lock_irqsave( + get_ccwdev_lock(basedev->cdev), flags); + dasd_device_set_stop_bits(basedev, + DASD_STOPPED_PENDING); + spin_unlock_irqrestore( + get_ccwdev_lock(basedev->cdev), flags); dasd_block_set_timer(block, HZ/2); break; } @@ -1813,7 +1906,7 @@ restart: cqr->status = DASD_CQR_FILLED; cqr->retries = 255; spin_lock_irqsave(get_ccwdev_lock(base->cdev), flags); - base->stopped |= DASD_STOPPED_QUIESCE; + dasd_device_set_stop_bits(base, DASD_STOPPED_QUIESCE); spin_unlock_irqrestore(get_ccwdev_lock(base->cdev), flags); goto restart; @@ -1821,7 +1914,7 @@ restart: /* Process finished ERP request. */ if (cqr->refers) { - __dasd_block_process_erp(block, cqr); + __dasd_process_erp(base, cqr); goto restart; } @@ -1952,7 +2045,7 @@ restart_cb: /* Process finished ERP request. */ if (cqr->refers) { spin_lock_bh(&block->queue_lock); - __dasd_block_process_erp(block, cqr); + __dasd_process_erp(block->base, cqr); spin_unlock_bh(&block->queue_lock); /* restart list_for_xx loop since dasd_process_erp * might remove multiple elements */ @@ -2208,18 +2301,11 @@ int dasd_generic_probe(struct ccw_device *cdev, { int ret; - ret = ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP); - if (ret) { - DBF_EVENT(DBF_WARNING, - "dasd_generic_probe: could not set ccw-device options " - "for %s\n", dev_name(&cdev->dev)); - return ret; - } ret = dasd_add_sysfs_files(cdev); if (ret) { - DBF_EVENT(DBF_WARNING, - "dasd_generic_probe: could not add sysfs entries " - "for %s\n", dev_name(&cdev->dev)); + DBF_EVENT_DEVID(DBF_WARNING, cdev, "%s", + "dasd_generic_probe: could not add " + "sysfs entries"); return ret; } cdev->handler = &dasd_int_handler; @@ -2418,16 +2504,16 @@ int dasd_generic_notify(struct ccw_device *cdev, int event) cqr->status = DASD_CQR_QUEUED; cqr->retries++; } - device->stopped |= DASD_STOPPED_DC_WAIT; + dasd_device_set_stop_bits(device, DASD_STOPPED_DC_WAIT); dasd_device_clear_timer(device); dasd_schedule_device_bh(device); ret = 1; break; case CIO_OPER: /* FIXME: add a sanity check. */ - device->stopped &= ~DASD_STOPPED_DC_WAIT; + dasd_device_remove_stop_bits(device, DASD_STOPPED_DC_WAIT); if (device->stopped & DASD_UNRESUMED_PM) { - device->stopped &= ~DASD_UNRESUMED_PM; + dasd_device_remove_stop_bits(device, DASD_UNRESUMED_PM); dasd_restore_device(device); ret = 1; break; @@ -2452,7 +2538,7 @@ int dasd_generic_pm_freeze(struct ccw_device *cdev) if (IS_ERR(device)) return PTR_ERR(device); /* disallow new I/O */ - device->stopped |= DASD_STOPPED_PM; + dasd_device_set_stop_bits(device, DASD_STOPPED_PM); /* clear active requests */ INIT_LIST_HEAD(&freeze_queue); spin_lock_irq(get_ccwdev_lock(cdev)); @@ -2504,14 +2590,18 @@ int dasd_generic_restore_device(struct ccw_device *cdev) return PTR_ERR(device); /* allow new IO again */ - device->stopped &= ~DASD_STOPPED_PM; - device->stopped &= ~DASD_UNRESUMED_PM; + dasd_device_remove_stop_bits(device, + (DASD_STOPPED_PM | DASD_UNRESUMED_PM)); dasd_schedule_device_bh(device); - if (device->discipline->restore) + /* + * call discipline restore function + * if device is stopped do nothing e.g. for disconnected devices + */ + if (device->discipline->restore && !(device->stopped)) rc = device->discipline->restore(device); - if (rc) + if (rc || device->stopped) /* * if the resume failed for the DASD we put it in * an UNRESUMED stop state @@ -2561,8 +2651,7 @@ static struct dasd_ccw_req *dasd_generic_build_rdc(struct dasd_device *device, cqr->startdev = device; cqr->memdev = device; cqr->expires = 10*HZ; - clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); - cqr->retries = 2; + cqr->retries = 256; cqr->buildclk = get_clock(); cqr->status = DASD_CQR_FILLED; return cqr; diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c index e8ff7b0c961..44796ba4eb9 100644 --- a/drivers/s390/block/dasd_3990_erp.c +++ b/drivers/s390/block/dasd_3990_erp.c @@ -12,7 +12,6 @@ #include <linux/timer.h> #include <linux/slab.h> #include <asm/idals.h> -#include <asm/todclk.h> #define PRINTK_HEADER "dasd_erp(3990): " @@ -70,8 +69,7 @@ dasd_3990_erp_cleanup(struct dasd_ccw_req * erp, char final_status) * processing until the started timer has expired or an related * interrupt was received. */ -static void -dasd_3990_erp_block_queue(struct dasd_ccw_req * erp, int expires) +static void dasd_3990_erp_block_queue(struct dasd_ccw_req *erp, int expires) { struct dasd_device *device = erp->startdev; @@ -81,10 +79,13 @@ dasd_3990_erp_block_queue(struct dasd_ccw_req * erp, int expires) "blocking request queue for %is", expires/HZ); spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); - device->stopped |= DASD_STOPPED_PENDING; + dasd_device_set_stop_bits(device, DASD_STOPPED_PENDING); spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); erp->status = DASD_CQR_FILLED; - dasd_block_set_timer(device->block, expires); + if (erp->block) + dasd_block_set_timer(erp->block, expires); + else + dasd_device_set_timer(device, expires); } /* @@ -243,9 +244,13 @@ dasd_3990_erp_DCTL(struct dasd_ccw_req * erp, char modifier) * DESCRIPTION * Setup ERP to do the ERP action 1 (see Reference manual). * Repeat the operation on a different channel path. - * If all alternate paths have been tried, the request is posted with a - * permanent error. - * Note: duplex handling is not implemented (yet). + * As deviation from the recommended recovery action, we reset the path mask + * after we have tried each path and go through all paths a second time. + * This will cover situations where only one path at a time is actually down, + * but all paths fail and recover just with the same sequence and timing as + * we try to use them (flapping links). + * If all alternate paths have been tried twice, the request is posted with + * a permanent error. * * PARAMETER * erp pointer to the current ERP @@ -254,17 +259,25 @@ dasd_3990_erp_DCTL(struct dasd_ccw_req * erp, char modifier) * erp pointer to the ERP * */ -static struct dasd_ccw_req * -dasd_3990_erp_action_1(struct dasd_ccw_req * erp) +static struct dasd_ccw_req *dasd_3990_erp_action_1_sec(struct dasd_ccw_req *erp) { + erp->function = dasd_3990_erp_action_1_sec; + dasd_3990_erp_alternate_path(erp); + return erp; +} +static struct dasd_ccw_req *dasd_3990_erp_action_1(struct dasd_ccw_req *erp) +{ erp->function = dasd_3990_erp_action_1; - dasd_3990_erp_alternate_path(erp); - + if (erp->status == DASD_CQR_FAILED) { + erp->status = DASD_CQR_FILLED; + erp->retries = 10; + erp->lpm = LPM_ANYPATH; + erp->function = dasd_3990_erp_action_1_sec; + } return erp; - -} /* end dasd_3990_erp_action_1 */ +} /* end dasd_3990_erp_action_1(b) */ /* * DASD_3990_ERP_ACTION_4 @@ -2295,6 +2308,7 @@ static struct dasd_ccw_req *dasd_3990_erp_add_erp(struct dasd_ccw_req *cqr) return cqr; } + ccw = cqr->cpaddr; if (cqr->cpmode == 1) { /* make a shallow copy of the original tcw but set new tsb */ erp->cpmode = 1; @@ -2303,6 +2317,9 @@ static struct dasd_ccw_req *dasd_3990_erp_add_erp(struct dasd_ccw_req *cqr) tsb = (struct tsb *) &tcw[1]; *tcw = *((struct tcw *)cqr->cpaddr); tcw->tsb = (long)tsb; + } else if (ccw->cmd_code == DASD_ECKD_CCW_PSF) { + /* PSF cannot be chained from NOOP/TIC */ + erp->cpaddr = cqr->cpaddr; } else { /* initialize request with default TIC to current ERP/CQR */ ccw = erp->cpaddr; @@ -2487,6 +2504,8 @@ dasd_3990_erp_further_erp(struct dasd_ccw_req *erp) erp = dasd_3990_erp_action_1(erp); + } else if (erp->function == dasd_3990_erp_action_1_sec) { + erp = dasd_3990_erp_action_1_sec(erp); } else if (erp->function == dasd_3990_erp_action_5) { /* retries have not been successful */ diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c index 70a008c0052..fd1231738ef 100644 --- a/drivers/s390/block/dasd_alias.c +++ b/drivers/s390/block/dasd_alias.c @@ -152,6 +152,7 @@ static struct alias_lcu *_allocate_lcu(struct dasd_uid *uid) INIT_WORK(&lcu->suc_data.worker, summary_unit_check_handling_work); INIT_DELAYED_WORK(&lcu->ruac_data.dwork, lcu_update_work); spin_lock_init(&lcu->lock); + init_completion(&lcu->lcu_setup); return lcu; out_err4: @@ -240,6 +241,67 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device) } /* + * The first device to be registered on an LCU will have to do + * some additional setup steps to configure that LCU on the + * storage server. All further devices should wait with their + * initialization until the first device is done. + * To synchronize this work, the first device will call + * dasd_alias_lcu_setup_complete when it is done, and all + * other devices will wait for it with dasd_alias_wait_for_lcu_setup. + */ +void dasd_alias_lcu_setup_complete(struct dasd_device *device) +{ + struct dasd_eckd_private *private; + unsigned long flags; + struct alias_server *server; + struct alias_lcu *lcu; + struct dasd_uid *uid; + + private = (struct dasd_eckd_private *) device->private; + uid = &private->uid; + lcu = NULL; + spin_lock_irqsave(&aliastree.lock, flags); + server = _find_server(uid); + if (server) + lcu = _find_lcu(server, uid); + spin_unlock_irqrestore(&aliastree.lock, flags); + if (!lcu) { + DBF_EVENT_DEVID(DBF_ERR, device->cdev, + "could not find lcu for %04x %02x", + uid->ssid, uid->real_unit_addr); + WARN_ON(1); + return; + } + complete_all(&lcu->lcu_setup); +} + +void dasd_alias_wait_for_lcu_setup(struct dasd_device *device) +{ + struct dasd_eckd_private *private; + unsigned long flags; + struct alias_server *server; + struct alias_lcu *lcu; + struct dasd_uid *uid; + + private = (struct dasd_eckd_private *) device->private; + uid = &private->uid; + lcu = NULL; + spin_lock_irqsave(&aliastree.lock, flags); + server = _find_server(uid); + if (server) + lcu = _find_lcu(server, uid); + spin_unlock_irqrestore(&aliastree.lock, flags); + if (!lcu) { + DBF_EVENT_DEVID(DBF_ERR, device->cdev, + "could not find lcu for %04x %02x", + uid->ssid, uid->real_unit_addr); + WARN_ON(1); + return; + } + wait_for_completion(&lcu->lcu_setup); +} + +/* * This function removes a device from the scope of alias management. * The complicated part is to make sure that it is not in use by * any of the workers. If necessary cancel the work. @@ -755,11 +817,11 @@ static void __stop_device_on_lcu(struct dasd_device *device, { /* If pos == device then device is already locked! */ if (pos == device) { - pos->stopped |= DASD_STOPPED_SU; + dasd_device_set_stop_bits(pos, DASD_STOPPED_SU); return; } spin_lock(get_ccwdev_lock(pos->cdev)); - pos->stopped |= DASD_STOPPED_SU; + dasd_device_set_stop_bits(pos, DASD_STOPPED_SU); spin_unlock(get_ccwdev_lock(pos->cdev)); } @@ -793,26 +855,26 @@ static void _unstop_all_devices_on_lcu(struct alias_lcu *lcu) list_for_each_entry(device, &lcu->active_devices, alias_list) { spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); - device->stopped &= ~DASD_STOPPED_SU; + dasd_device_remove_stop_bits(device, DASD_STOPPED_SU); spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); } list_for_each_entry(device, &lcu->inactive_devices, alias_list) { spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); - device->stopped &= ~DASD_STOPPED_SU; + dasd_device_remove_stop_bits(device, DASD_STOPPED_SU); spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); } list_for_each_entry(pavgroup, &lcu->grouplist, group) { list_for_each_entry(device, &pavgroup->baselist, alias_list) { spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); - device->stopped &= ~DASD_STOPPED_SU; + dasd_device_remove_stop_bits(device, DASD_STOPPED_SU); spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); } list_for_each_entry(device, &pavgroup->aliaslist, alias_list) { spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); - device->stopped &= ~DASD_STOPPED_SU; + dasd_device_remove_stop_bits(device, DASD_STOPPED_SU); spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); } @@ -836,7 +898,8 @@ static void summary_unit_check_handling_work(struct work_struct *work) /* 2. reset summary unit check */ spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); - devi |