diff options
author | Stefan Weinhuber <wein@de.ibm.com> | 2009-12-07 06:51:51 -0500 |
---|---|---|
committer | Martin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com> | 2009-12-07 06:51:34 -0500 |
commit | eb6e199bef288611157b8198c25d12b32bf058d0 (patch) | |
tree | 80737a2703a9f4d09cee2410342aeccb281413ae /drivers/s390/block/dasd_alias.c | |
parent | 626350b63ef2cd447023d3dc2a34eaa7ca01bfff (diff) |
[S390] dasd: improve error recovery for internal I/O
Most of the error conditions reported by a FICON storage server
indicate situations which can be recovered. Sometimes the host just
needs to retry an I/O request, but sometimes the recovery
is more complex and requires the device driver to wait, choose
a different path, etc.
The DASD device driver has a fully featured error recovery
for normal block layer I/O, but not for internal I/O request which
are for example used during the device bring up.
This can lead to situations where the IPL of a system fails because
DASD devices are not properly recognized.
This patch will extend the internal I/O handling to use the existing
error recovery procedures.
Signed-off-by: Stefan Weinhuber <wein@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/block/dasd_alias.c')
-rw-r--r-- | drivers/s390/block/dasd_alias.c | 15 |
1 files changed, 8 insertions, 7 deletions
diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c index 70a008c00522..cdc6c049c353 100644 --- a/drivers/s390/block/dasd_alias.c +++ b/drivers/s390/block/dasd_alias.c | |||
@@ -755,11 +755,11 @@ static void __stop_device_on_lcu(struct dasd_device *device, | |||
755 | { | 755 | { |
756 | /* If pos == device then device is already locked! */ | 756 | /* If pos == device then device is already locked! */ |
757 | if (pos == device) { | 757 | if (pos == device) { |
758 | pos->stopped |= DASD_STOPPED_SU; | 758 | dasd_device_set_stop_bits(pos, DASD_STOPPED_SU); |
759 | return; | 759 | return; |
760 | } | 760 | } |
761 | spin_lock(get_ccwdev_lock(pos->cdev)); | 761 | spin_lock(get_ccwdev_lock(pos->cdev)); |
762 | pos->stopped |= DASD_STOPPED_SU; | 762 | dasd_device_set_stop_bits(pos, DASD_STOPPED_SU); |
763 | spin_unlock(get_ccwdev_lock(pos->cdev)); | 763 | spin_unlock(get_ccwdev_lock(pos->cdev)); |
764 | } | 764 | } |
765 | 765 | ||
@@ -793,26 +793,26 @@ static void _unstop_all_devices_on_lcu(struct alias_lcu *lcu) | |||
793 | 793 | ||
794 | list_for_each_entry(device, &lcu->active_devices, alias_list) { | 794 | list_for_each_entry(device, &lcu->active_devices, alias_list) { |
795 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); | 795 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); |
796 | device->stopped &= ~DASD_STOPPED_SU; | 796 | dasd_device_remove_stop_bits(device, DASD_STOPPED_SU); |
797 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); | 797 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); |
798 | } | 798 | } |
799 | 799 | ||
800 | list_for_each_entry(device, &lcu->inactive_devices, alias_list) { | 800 | list_for_each_entry(device, &lcu->inactive_devices, alias_list) { |
801 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); | 801 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); |
802 | device->stopped &= ~DASD_STOPPED_SU; | 802 | dasd_device_remove_stop_bits(device, DASD_STOPPED_SU); |
803 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); | 803 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); |
804 | } | 804 | } |
805 | 805 | ||
806 | list_for_each_entry(pavgroup, &lcu->grouplist, group) { | 806 | list_for_each_entry(pavgroup, &lcu->grouplist, group) { |
807 | list_for_each_entry(device, &pavgroup->baselist, alias_list) { | 807 | list_for_each_entry(device, &pavgroup->baselist, alias_list) { |
808 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); | 808 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); |
809 | device->stopped &= ~DASD_STOPPED_SU; | 809 | dasd_device_remove_stop_bits(device, DASD_STOPPED_SU); |
810 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), | 810 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), |
811 | flags); | 811 | flags); |
812 | } | 812 | } |
813 | list_for_each_entry(device, &pavgroup->aliaslist, alias_list) { | 813 | list_for_each_entry(device, &pavgroup->aliaslist, alias_list) { |
814 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); | 814 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); |
815 | device->stopped &= ~DASD_STOPPED_SU; | 815 | dasd_device_remove_stop_bits(device, DASD_STOPPED_SU); |
816 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), | 816 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), |
817 | flags); | 817 | flags); |
818 | } | 818 | } |
@@ -836,7 +836,8 @@ static void summary_unit_check_handling_work(struct work_struct *work) | |||
836 | 836 | ||
837 | /* 2. reset summary unit check */ | 837 | /* 2. reset summary unit check */ |
838 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); | 838 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); |
839 | device->stopped &= ~(DASD_STOPPED_SU | DASD_STOPPED_PENDING); | 839 | dasd_device_remove_stop_bits(device, |
840 | (DASD_STOPPED_SU | DASD_STOPPED_PENDING)); | ||
840 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); | 841 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); |
841 | reset_summary_unit_check(lcu, device, suc_data->reason); | 842 | reset_summary_unit_check(lcu, device, suc_data->reason); |
842 | 843 | ||