aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Haberland <sth@linux.vnet.ibm.com>2016-08-08 09:56:54 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2016-12-12 06:05:03 -0500
commita521b048bc8c5d3c57a468c2cba70eb60e873616 (patch)
treed84e42b5653a1761a5cf7307ab4fef0e884f1c07
parentc93461515a1a16486f4e483cb34170366fa73ea1 (diff)
s390/dasd: channel path aware error recovery
With this feature, the DASD device driver more robustly handles DASDs that are attached via multiple channel paths and are subject to constant Interface-Control-Checks (IFCCs) and Channel-Control-Checks (CCCs) or loss of High-Performance-FICON (HPF) functionality on one or more of these paths. If a channel path does not work correctly, it is removed from normal operation as long as other channel paths are available. All extended error recovery states can be queried and reset via user space interfaces. Signed-off-by: Stefan Haberland <sth@linux.vnet.ibm.com> Reviewed-by: Sebastian Ott <sebott@linux.vnet.ibm.com> Reviewed-by: Jan Hoeppner <hoeppner@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r--arch/s390/include/asm/scsw.h6
-rw-r--r--drivers/s390/block/dasd.c149
-rw-r--r--drivers/s390/block/dasd_3990_erp.c46
-rw-r--r--drivers/s390/block/dasd_devmap.c157
-rw-r--r--drivers/s390/block/dasd_eckd.c210
-rw-r--r--drivers/s390/block/dasd_eckd.h2
-rw-r--r--drivers/s390/block/dasd_int.h68
7 files changed, 529 insertions, 109 deletions
diff --git a/arch/s390/include/asm/scsw.h b/arch/s390/include/asm/scsw.h
index 4af99cdaddf5..17a7904f001a 100644
--- a/arch/s390/include/asm/scsw.h
+++ b/arch/s390/include/asm/scsw.h
@@ -96,7 +96,8 @@ struct tm_scsw {
96 u32 dstat:8; 96 u32 dstat:8;
97 u32 cstat:8; 97 u32 cstat:8;
98 u32 fcxs:8; 98 u32 fcxs:8;
99 u32 schxs:8; 99 u32 ifob:1;
100 u32 sesq:7;
100} __attribute__ ((packed)); 101} __attribute__ ((packed));
101 102
102/** 103/**
@@ -177,6 +178,9 @@ union scsw {
177#define SCHN_STAT_INTF_CTRL_CHK 0x02 178#define SCHN_STAT_INTF_CTRL_CHK 0x02
178#define SCHN_STAT_CHAIN_CHECK 0x01 179#define SCHN_STAT_CHAIN_CHECK 0x01
179 180
181#define SCSW_SESQ_DEV_NOFCX 3
182#define SCSW_SESQ_PATH_NOFCX 4
183
180/* 184/*
181 * architectured values for first sense byte 185 * architectured values for first sense byte
182 */ 186 */
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 13a337faef43..0e3fdfdbd098 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -69,6 +69,7 @@ static void dasd_block_tasklet(struct dasd_block *);
69static void do_kick_device(struct work_struct *); 69static void do_kick_device(struct work_struct *);
70static void do_restore_device(struct work_struct *); 70static void do_restore_device(struct work_struct *);
71static void do_reload_device(struct work_struct *); 71static void do_reload_device(struct work_struct *);
72static void do_requeue_requests(struct work_struct *);
72static void dasd_return_cqr_cb(struct dasd_ccw_req *, void *); 73static void dasd_return_cqr_cb(struct dasd_ccw_req *, void *);
73static void dasd_device_timeout(unsigned long); 74static void dasd_device_timeout(unsigned long);
74static void dasd_block_timeout(unsigned long); 75static void dasd_block_timeout(unsigned long);
@@ -125,6 +126,7 @@ struct dasd_device *dasd_alloc_device(void)
125 INIT_WORK(&device->kick_work, do_kick_device); 126 INIT_WORK(&device->kick_work, do_kick_device);
126 INIT_WORK(&device->restore_device, do_restore_device); 127 INIT_WORK(&device->restore_device, do_restore_device);
127 INIT_WORK(&device->reload_device, do_reload_device); 128 INIT_WORK(&device->reload_device, do_reload_device);
129 INIT_WORK(&device->requeue_requests, do_requeue_requests);
128 device->state = DASD_STATE_NEW; 130 device->state = DASD_STATE_NEW;
129 device->target = DASD_STATE_NEW; 131 device->target = DASD_STATE_NEW;
130 mutex_init(&device->state_mutex); 132 mutex_init(&device->state_mutex);
@@ -1622,6 +1624,13 @@ void dasd_generic_handle_state_change(struct dasd_device *device)
1622} 1624}
1623EXPORT_SYMBOL_GPL(dasd_generic_handle_state_change); 1625EXPORT_SYMBOL_GPL(dasd_generic_handle_state_change);
1624 1626
1627static int dasd_check_hpf_error(struct irb *irb)
1628{
1629 return (scsw_tm_is_valid_schxs(&irb->scsw) &&
1630 (irb->scsw.tm.sesq == SCSW_SESQ_DEV_NOFCX ||
1631 irb->scsw.tm.sesq == SCSW_SESQ_PATH_NOFCX));
1632}
1633
1625/* 1634/*
1626 * Interrupt handler for "normal" ssch-io based dasd devices. 1635 * Interrupt handler for "normal" ssch-io based dasd devices.
1627 */ 1636 */
@@ -1748,6 +1757,13 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
1748 struct dasd_ccw_req, devlist); 1757 struct dasd_ccw_req, devlist);
1749 } 1758 }
1750 } else { /* error */ 1759 } else { /* error */
1760 /* check for HPF error
1761 * call discipline function to requeue all requests
1762 * and disable HPF accordingly
1763 */
1764 if (cqr->cpmode && dasd_check_hpf_error(irb) &&
1765 device->discipline->handle_hpf_error)
1766 device->discipline->handle_hpf_error(device, irb);
1751 /* 1767 /*
1752 * If we don't want complex ERP for this request, then just 1768 * If we don't want complex ERP for this request, then just
1753 * reset this and retry it in the fastpath 1769 * reset this and retry it in the fastpath
@@ -2924,10 +2940,10 @@ static int _dasd_requeue_request(struct dasd_ccw_req *cqr)
2924 2940
2925 if (!block) 2941 if (!block)
2926 return -EINVAL; 2942 return -EINVAL;
2927 spin_lock_irqsave(&block->queue_lock, flags); 2943 spin_lock_irqsave(&block->request_queue_lock, flags);
2928 req = (struct request *) cqr->callback_data; 2944 req = (struct request *) cqr->callback_data;
2929 blk_requeue_request(block->request_queue, req); 2945 blk_requeue_request(block->request_queue, req);
2930 spin_unlock_irqrestore(&block->queue_lock, flags); 2946 spin_unlock_irqrestore(&block->request_queue_lock, flags);
2931 2947
2932 return 0; 2948 return 0;
2933} 2949}
@@ -3701,7 +3717,7 @@ EXPORT_SYMBOL_GPL(dasd_generic_notify);
3701void dasd_generic_path_event(struct ccw_device *cdev, int *path_event) 3717void dasd_generic_path_event(struct ccw_device *cdev, int *path_event)
3702{ 3718{
3703 struct dasd_device *device; 3719 struct dasd_device *device;
3704 int chp, oldopm; 3720 int chp, oldopm, hpfpm, ifccpm;
3705 3721
3706 device = dasd_device_from_cdev_locked(cdev); 3722 device = dasd_device_from_cdev_locked(cdev);
3707 if (IS_ERR(device)) 3723 if (IS_ERR(device))
@@ -3733,7 +3749,30 @@ void dasd_generic_path_event(struct ccw_device *cdev, int *path_event)
3733 device->discipline->kick_validate(device); 3749 device->discipline->kick_validate(device);
3734 } 3750 }
3735 } 3751 }
3736 if (oldopm && !dasd_path_get_opm(device)) { 3752 hpfpm = dasd_path_get_hpfpm(device);
3753 ifccpm = dasd_path_get_ifccpm(device);
3754 if (!dasd_path_get_opm(device) && hpfpm) {
3755 /*
3756 * device has no operational paths but at least one path is
3757 * disabled due to HPF errors
3758 * disable HPF at all and use the path(s) again
3759 */
3760 if (device->discipline->disable_hpf)
3761 device->discipline->disable_hpf(device);
3762 dasd_device_set_stop_bits(device, DASD_STOPPED_NOT_ACC);
3763 dasd_path_set_tbvpm(device, hpfpm);
3764 dasd_schedule_device_bh(device);
3765 dasd_schedule_requeue(device);
3766 } else if (!dasd_path_get_opm(device) && ifccpm) {
3767 /*
3768 * device has no operational paths but at least one path is
3769 * disabled due to IFCC errors
3770 * trigger path verification on paths with IFCC errors
3771 */
3772 dasd_path_set_tbvpm(device, ifccpm);
3773 dasd_schedule_device_bh(device);
3774 }
3775 if (oldopm && !dasd_path_get_opm(device) && !hpfpm && !ifccpm) {
3737 dev_warn(&device->cdev->dev, 3776 dev_warn(&device->cdev->dev,
3738 "No verified channel paths remain for the device\n"); 3777 "No verified channel paths remain for the device\n");
3739 DBF_DEV_EVENT(DBF_WARNING, device, 3778 DBF_DEV_EVENT(DBF_WARNING, device,
@@ -3757,30 +3796,18 @@ int dasd_generic_verify_path(struct dasd_device *device, __u8 lpm)
3757} 3796}
3758EXPORT_SYMBOL_GPL(dasd_generic_verify_path); 3797EXPORT_SYMBOL_GPL(dasd_generic_verify_path);
3759 3798
3760 3799/*
3761int dasd_generic_pm_freeze(struct ccw_device *cdev) 3800 * clear active requests and requeue them to block layer if possible
3801 */
3802static int dasd_generic_requeue_all_requests(struct dasd_device *device)
3762{ 3803{
3763 struct dasd_device *device = dasd_device_from_cdev(cdev); 3804 struct list_head requeue_queue;
3764 struct list_head freeze_queue;
3765 struct dasd_ccw_req *cqr, *n; 3805 struct dasd_ccw_req *cqr, *n;
3766 struct dasd_ccw_req *refers; 3806 struct dasd_ccw_req *refers;
3767 int rc; 3807 int rc;
3768 3808
3769 if (IS_ERR(device)) 3809 INIT_LIST_HEAD(&requeue_queue);
3770 return PTR_ERR(device); 3810 spin_lock_irq(get_ccwdev_lock(device->cdev));
3771
3772 /* mark device as suspended */
3773 set_bit(DASD_FLAG_SUSPENDED, &device->flags);
3774
3775 if (device->discipline->freeze)
3776 rc = device->discipline->freeze(device);
3777
3778 /* disallow new I/O */
3779 dasd_device_set_stop_bits(device, DASD_STOPPED_PM);
3780
3781 /* clear active requests and requeue them to block layer if possible */
3782 INIT_LIST_HEAD(&freeze_queue);
3783 spin_lock_irq(get_ccwdev_lock(cdev));
3784 rc = 0; 3811 rc = 0;
3785 list_for_each_entry_safe(cqr, n, &device->ccw_queue, devlist) { 3812 list_for_each_entry_safe(cqr, n, &device->ccw_queue, devlist) {
3786 /* Check status and move request to flush_queue */ 3813 /* Check status and move request to flush_queue */
@@ -3791,25 +3818,22 @@ int dasd_generic_pm_freeze(struct ccw_device *cdev)
3791 dev_err(&device->cdev->dev, 3818 dev_err(&device->cdev->dev,
3792 "Unable to terminate request %p " 3819 "Unable to terminate request %p "
3793 "on suspend\n", cqr); 3820 "on suspend\n", cqr);
3794 spin_unlock_irq(get_ccwdev_lock(cdev)); 3821 spin_unlock_irq(get_ccwdev_lock(device->cdev));
3795 dasd_put_device(device); 3822 dasd_put_device(device);
3796 return rc; 3823 return rc;
3797 } 3824 }
3798 } 3825 }
3799 list_move_tail(&cqr->devlist, &freeze_queue); 3826 list_move_tail(&cqr->devlist, &requeue_queue);
3800 } 3827 }
3801 spin_unlock_irq(get_ccwdev_lock(cdev)); 3828 spin_unlock_irq(get_ccwdev_lock(device->cdev));
3802 3829
3803 list_for_each_entry_safe(cqr, n, &freeze_queue, devlist) { 3830 list_for_each_entry_safe(cqr, n, &requeue_queue, devlist) {
3804 wait_event(dasd_flush_wq, 3831 wait_event(dasd_flush_wq,
3805 (cqr->status != DASD_CQR_CLEAR_PENDING)); 3832 (cqr->status != DASD_CQR_CLEAR_PENDING));
3806 if (cqr->status == DASD_CQR_CLEARED)
3807 cqr->status = DASD_CQR_QUEUED;
3808 3833
3809 /* requeue requests to blocklayer will only work for 3834 /* mark sleepon requests as ended */
3810 block device requests */ 3835 if (cqr->callback_data == DASD_SLEEPON_START_TAG)
3811 if (_dasd_requeue_request(cqr)) 3836 cqr->callback_data = DASD_SLEEPON_END_TAG;
3812 continue;
3813 3837
3814 /* remove requests from device and block queue */ 3838 /* remove requests from device and block queue */
3815 list_del_init(&cqr->devlist); 3839 list_del_init(&cqr->devlist);
@@ -3821,6 +3845,14 @@ int dasd_generic_pm_freeze(struct ccw_device *cdev)
3821 dasd_free_erp_request(cqr, cqr->memdev); 3845 dasd_free_erp_request(cqr, cqr->memdev);
3822 cqr = refers; 3846 cqr = refers;
3823 } 3847 }
3848
3849 /*
3850 * requeue requests to blocklayer will only work
3851 * for block device requests
3852 */
3853 if (_dasd_requeue_request(cqr))
3854 continue;
3855
3824 if (cqr->block) 3856 if (cqr->block)
3825 list_del_init(&cqr->blocklist); 3857 list_del_init(&cqr->blocklist);
3826 cqr->block->base->discipline->free_cp( 3858 cqr->block->base->discipline->free_cp(
@@ -3831,15 +3863,56 @@ int dasd_generic_pm_freeze(struct ccw_device *cdev)
3831 * if requests remain then they are internal request 3863 * if requests remain then they are internal request
3832 * and go back to the device queue 3864 * and go back to the device queue
3833 */ 3865 */
3834 if (!list_empty(&freeze_queue)) { 3866 if (!list_empty(&requeue_queue)) {
3835 /* move freeze_queue to start of the ccw_queue */ 3867 /* move freeze_queue to start of the ccw_queue */
3836 spin_lock_irq(get_ccwdev_lock(cdev)); 3868 spin_lock_irq(get_ccwdev_lock(device->cdev));
3837 list_splice_tail(&freeze_queue, &device->ccw_queue); 3869 list_splice_tail(&requeue_queue, &device->ccw_queue);
3838 spin_unlock_irq(get_ccwdev_lock(cdev)); 3870 spin_unlock_irq(get_ccwdev_lock(device->cdev));
3839 } 3871 }
3840 dasd_put_device(device); 3872 /* wake up generic waitqueue for eventually ended sleepon requests */
3873 wake_up(&generic_waitq);
3841 return rc; 3874 return rc;
3842} 3875}
3876
3877static void do_requeue_requests(struct work_struct *work)
3878{
3879 struct dasd_device *device = container_of(work, struct dasd_device,
3880 requeue_requests);
3881 dasd_generic_requeue_all_requests(device);
3882 dasd_device_remove_stop_bits(device, DASD_STOPPED_NOT_ACC);
3883 if (device->block)
3884 dasd_schedule_block_bh(device->block);
3885 dasd_put_device(device);
3886}
3887
3888void dasd_schedule_requeue(struct dasd_device *device)
3889{
3890 dasd_get_device(device);
3891 /* queue call to dasd_reload_device to the kernel event daemon. */
3892 if (!schedule_work(&device->requeue_requests))
3893 dasd_put_device(device);
3894}
3895EXPORT_SYMBOL(dasd_schedule_requeue);
3896
3897int dasd_generic_pm_freeze(struct ccw_device *cdev)
3898{
3899 struct dasd_device *device = dasd_device_from_cdev(cdev);
3900 int rc;
3901
3902 if (IS_ERR(device))
3903 return PTR_ERR(device);
3904
3905 /* mark device as suspended */
3906 set_bit(DASD_FLAG_SUSPENDED, &device->flags);
3907
3908 if (device->discipline->freeze)
3909 rc = device->discipline->freeze(device);
3910
3911 /* disallow new I/O */
3912 dasd_device_set_stop_bits(device, DASD_STOPPED_PM);
3913
3914 return dasd_generic_requeue_all_requests(device);
3915}
3843EXPORT_SYMBOL_GPL(dasd_generic_pm_freeze); 3916EXPORT_SYMBOL_GPL(dasd_generic_pm_freeze);
3844 3917
3845int dasd_generic_restore_device(struct ccw_device *cdev) 3918int dasd_generic_restore_device(struct ccw_device *cdev)
diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c
index 9236e2c0c3d9..95f7645e3c37 100644
--- a/drivers/s390/block/dasd_3990_erp.c
+++ b/drivers/s390/block/dasd_3990_erp.c
@@ -2208,6 +2208,51 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense)
2208 2208
2209} /* end dasd_3990_erp_inspect_32 */ 2209} /* end dasd_3990_erp_inspect_32 */
2210 2210
2211static void dasd_3990_erp_disable_path(struct dasd_device *device, __u8 lpum)
2212{
2213 int pos = pathmask_to_pos(lpum);
2214
2215 /* no remaining path, cannot disable */
2216 if (!(dasd_path_get_opm(device) & ~lpum))
2217 return;
2218
2219 dev_err(&device->cdev->dev,
2220 "Path %x.%02x (pathmask %02x) is disabled - IFCC threshold exceeded\n",
2221 device->path[pos].cssid, device->path[pos].chpid, lpum);
2222 dasd_path_remove_opm(device, lpum);
2223 dasd_path_add_ifccpm(device, lpum);
2224 device->path[pos].errorclk = 0;
2225 atomic_set(&device->path[pos].error_count, 0);
2226}
2227
2228static void dasd_3990_erp_account_error(struct dasd_ccw_req *erp)
2229{
2230 struct dasd_device *device = erp->startdev;
2231 __u8 lpum = erp->refers->irb.esw.esw1.lpum;
2232 int pos = pathmask_to_pos(lpum);
2233 unsigned long long clk;
2234
2235 if (!device->path_thrhld)
2236 return;
2237
2238 clk = get_tod_clock();
2239 /*
2240 * check if the last error is longer ago than the timeout,
2241 * if so reset error state
2242 */
2243 if ((tod_to_ns(clk - device->path[pos].errorclk) / NSEC_PER_SEC)
2244 >= device->path_interval) {
2245 atomic_set(&device->path[pos].error_count, 0);
2246 device->path[pos].errorclk = 0;
2247 }
2248 atomic_inc(&device->path[pos].error_count);
2249 device->path[pos].errorclk = clk;
2250 /* threshold exceeded disable path if possible */
2251 if (atomic_read(&device->path[pos].error_count) >=
2252 device->path_thrhld)
2253 dasd_3990_erp_disable_path(device, lpum);
2254}
2255
2211/* 2256/*
2212 ***************************************************************************** 2257 *****************************************************************************
2213 * main ERP control functions (24 and 32 byte sense) 2258 * main ERP control functions (24 and 32 byte sense)
@@ -2237,6 +2282,7 @@ dasd_3990_erp_control_check(struct dasd_ccw_req *erp)
2237 | SCHN_STAT_CHN_CTRL_CHK)) { 2282 | SCHN_STAT_CHN_CTRL_CHK)) {
2238 DBF_DEV_EVENT(DBF_WARNING, device, "%s", 2283 DBF_DEV_EVENT(DBF_WARNING, device, "%s",
2239 "channel or interface control check"); 2284 "channel or interface control check");
2285 dasd_3990_erp_account_error(erp);
2240 erp = dasd_3990_erp_action_4(erp, NULL); 2286 erp = dasd_3990_erp_action_4(erp, NULL);
2241 } 2287 }
2242 return erp; 2288 return erp;
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index 4101ab000c16..84ca314c87e3 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -977,10 +977,12 @@ dasd_access_show(struct device *dev, struct device_attribute *attr,
977 if (IS_ERR(device)) 977 if (IS_ERR(device))
978 return PTR_ERR(device); 978 return PTR_ERR(device);
979 979
980 if (device->discipline->host_access_count) 980 if (!device->discipline)
981 count = device->discipline->host_access_count(device); 981 count = -ENODEV;
982 else 982 else if (!device->discipline->host_access_count)
983 count = -EOPNOTSUPP; 983 count = -EOPNOTSUPP;
984 else
985 count = device->discipline->host_access_count(device);
984 986
985 dasd_put_device(device); 987 dasd_put_device(device);
986 if (count < 0) 988 if (count < 0)
@@ -1341,6 +1343,50 @@ dasd_timeout_store(struct device *dev, struct device_attribute *attr,
1341static DEVICE_ATTR(timeout, 0644, 1343static DEVICE_ATTR(timeout, 0644,
1342 dasd_timeout_show, dasd_timeout_store); 1344 dasd_timeout_show, dasd_timeout_store);
1343 1345
1346
1347static ssize_t
1348dasd_path_reset_store(struct device *dev, struct device_attribute *attr,
1349 const char *buf, size_t count)
1350{
1351 struct dasd_device *device;
1352 unsigned int val;
1353
1354 device = dasd_device_from_cdev(to_ccwdev(dev));
1355 if (IS_ERR(device))
1356 return -ENODEV;
1357
1358 if ((kstrtouint(buf, 16, &val) != 0) || val > 0xff)
1359 val = 0;
1360
1361 if (device->discipline && device->discipline->reset_path)
1362 device->discipline->reset_path(device, (__u8) val);
1363
1364 dasd_put_device(device);
1365 return count;
1366}
1367
1368static DEVICE_ATTR(path_reset, 0200, NULL, dasd_path_reset_store);
1369
1370static ssize_t dasd_hpf_show(struct device *dev, struct device_attribute *attr,
1371 char *buf)
1372{
1373 struct dasd_device *device;
1374 int hpf;
1375
1376 device = dasd_device_from_cdev(to_ccwdev(dev));
1377 if (IS_ERR(device))
1378 return -ENODEV;
1379 if (!device->discipline || !device->discipline->hpf_enabled) {
1380 dasd_put_device(device);
1381 return snprintf(buf, PAGE_SIZE, "%d\n", dasd_nofcx);
1382 }
1383 hpf = device->discipline->hpf_enabled(device);
1384 dasd_put_device(device);
1385 return snprintf(buf, PAGE_SIZE, "%d\n", hpf);
1386}
1387
1388static DEVICE_ATTR(hpf, 0444, dasd_hpf_show, NULL);
1389
1344static ssize_t dasd_reservation_policy_show(struct device *dev, 1390static ssize_t dasd_reservation_policy_show(struct device *dev,
1345 struct device_attribute *attr, 1391 struct device_attribute *attr,
1346 char *buf) 1392 char *buf)
@@ -1432,7 +1478,7 @@ static ssize_t dasd_pm_show(struct device *dev,
1432 struct device_attribute *attr, char *buf) 1478 struct device_attribute *attr, char *buf)
1433{ 1479{
1434 struct dasd_device *device; 1480 struct dasd_device *device;
1435 u8 opm, nppm, cablepm, cuirpm, hpfpm; 1481 u8 opm, nppm, cablepm, cuirpm, hpfpm, ifccpm;
1436 1482
1437 device = dasd_device_from_cdev(to_ccwdev(dev)); 1483 device = dasd_device_from_cdev(to_ccwdev(dev));
1438 if (IS_ERR(device)) 1484 if (IS_ERR(device))
@@ -1443,14 +1489,109 @@ static ssize_t dasd_pm_show(struct device *dev,
1443 cablepm = dasd_path_get_cablepm(device); 1489 cablepm = dasd_path_get_cablepm(device);
1444 cuirpm = dasd_path_get_cuirpm(device); 1490 cuirpm = dasd_path_get_cuirpm(device);
1445 hpfpm = dasd_path_get_hpfpm(device); 1491 hpfpm = dasd_path_get_hpfpm(device);
1492 ifccpm = dasd_path_get_ifccpm(device);
1446 dasd_put_device(device); 1493 dasd_put_device(device);
1447 1494
1448 return sprintf(buf, "%02x %02x %02x %02x %02x\n", opm, nppm, 1495 return sprintf(buf, "%02x %02x %02x %02x %02x %02x\n", opm, nppm,
1449 cablepm, cuirpm, hpfpm); 1496 cablepm, cuirpm, hpfpm, ifccpm);
1450} 1497}
1451 1498
1452static DEVICE_ATTR(path_masks, 0444, dasd_pm_show, NULL); 1499static DEVICE_ATTR(path_masks, 0444, dasd_pm_show, NULL);
1453 1500
1501/*
1502 * threshold value for IFCC/CCC errors
1503 */
1504static ssize_t
1505dasd_path_threshold_show(struct device *dev,
1506 struct device_attribute *attr, char *buf)
1507{
1508 struct dasd_device *device;
1509 int len;
1510
1511 device = dasd_device_from_cdev(to_ccwdev(dev));
1512 if (IS_ERR(device))
1513 return -ENODEV;
1514 len = snprintf(buf, PAGE_SIZE, "%lu\n", device->path_thrhld);
1515 dasd_put_device(device);
1516 return len;
1517}
1518
1519static ssize_t
1520dasd_path_threshold_store(struct device *dev, struct device_attribute *attr,
1521 const char *buf, size_t count)
1522{
1523 struct dasd_device *device;
1524 unsigned long flags;
1525 unsigned long val;
1526
1527 device = dasd_device_from_cdev(to_ccwdev(dev));
1528 if (IS_ERR(device))
1529 return -ENODEV;
1530
1531 if ((kstrtoul(buf, 10, &val) != 0) ||
1532 (val > DASD_THRHLD_MAX) || val == 0) {
1533 dasd_put_device(device);
1534 return -EINVAL;
1535 }
1536 spin_lock_irqsave(get_ccwdev_lock(to_ccwdev(dev)), flags);
1537 if (val)
1538 device->path_thrhld = val;
1539 spin_unlock_irqrestore(get_ccwdev_lock(to_ccwdev(dev)), flags);
1540 dasd_put_device(device);
1541 return count;
1542}
1543
1544static DEVICE_ATTR(path_threshold, 0644, dasd_path_threshold_show,
1545 dasd_path_threshold_store);
1546/*
1547 * interval for IFCC/CCC checks
1548 * meaning time with no IFCC/CCC error before the error counter
1549 * gets reset
1550 */
1551static ssize_t
1552dasd_path_interval_show(struct device *dev,
1553 struct device_attribute *attr, char *buf)
1554{
1555 struct dasd_device *device;
1556 int len;
1557
1558 device = dasd_device_from_cdev(to_ccwdev(dev));
1559 if (IS_ERR(device))
1560 return -ENODEV;
1561 len = snprintf(buf, PAGE_SIZE, "%lu\n", device->path_interval);
1562 dasd_put_device(device);
1563 return len;
1564}
1565
1566static ssize_t
1567dasd_path_interval_store(struct device *dev, struct device_attribute *attr,
1568 const char *buf, size_t count)
1569{
1570 struct dasd_device *device;
1571 unsigned long flags;
1572 unsigned long val;
1573
1574 device = dasd_device_from_cdev(to_ccwdev(dev));
1575 if (IS_ERR(device))
1576 return -ENODEV;
1577
1578 if ((kstrtoul(buf, 10, &val) != 0) ||
1579 (val > DASD_INTERVAL_MAX) || val == 0) {
1580 dasd_put_device(device);
1581 return -EINVAL;
1582 }
1583 spin_lock_irqsave(get_ccwdev_lock(to_ccwdev(dev)), flags);
1584 if (val)
1585 device->path_interval = val;
1586 spin_unlock_irqrestore(get_ccwdev_lock(to_ccwdev(dev)), flags);
1587 dasd_put_device(device);
1588 return count;
1589}
1590
1591static DEVICE_ATTR(path_interval, 0644, dasd_path_interval_show,
1592 dasd_path_interval_store);
1593
1594
1454static struct attribute * dasd_attrs[] = { 1595static struct attribute * dasd_attrs[] = {
1455 &dev_attr_readonly.attr, 1596 &dev_attr_readonly.attr,
1456 &dev_attr_discipline.attr, 1597 &dev_attr_discipline.attr,
@@ -1471,6 +1612,10 @@ static struct attribute * dasd_attrs[] = {
1471 &dev_attr_safe_offline.attr, 1612 &dev_attr_safe_offline.attr,
1472 &dev_attr_host_access_count.attr, 1613 &dev_attr_host_access_count.attr,
1473 &dev_attr_path_masks.attr, 1614 &dev_attr_path_masks.attr,
1615 &dev_attr_path_threshold.attr,
1616 &dev_attr_path_interval.attr,
1617 &dev_attr_path_reset.attr,
1618 &dev_attr_hpf.attr,
1474 NULL, 1619 NULL,
1475}; 1620};
1476 1621
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 51fdf31aa8eb..67bf50c9946f 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -1044,6 +1044,9 @@ static void dasd_eckd_clear_conf_data(struct dasd_device *device)
1044 for (i = 0; i < 8; i++) { 1044 for (i = 0; i < 8; i++) {
1045 kfree(device->path[i].conf_data); 1045 kfree(device->path[i].conf_data);
1046 device->path[i].conf_data = NULL; 1046 device->path[i].conf_data = NULL;
1047 device->path[i].cssid = 0;
1048 device->path[i].ssid = 0;
1049 device->path[i].chpid = 0;
1047 } 1050 }
1048} 1051}
1049 1052
@@ -1057,9 +1060,12 @@ static int dasd_eckd_read_conf(struct dasd_device *device)
1057 struct dasd_eckd_private *private, path_private; 1060 struct dasd_eckd_private *private, path_private;
1058 struct dasd_uid *uid; 1061 struct dasd_uid *uid;
1059 char print_path_uid[60], print_device_uid[60]; 1062 char print_path_uid[60], print_device_uid[60];
1063 struct channel_path_desc *chp_desc;
1064 struct subchannel_id sch_id;
1060 1065
1061 private = device->private; 1066 private = device->private;
1062 opm = ccw_device_get_path_mask(device->cdev); 1067 opm = ccw_device_get_path_mask(device->cdev);
1068 ccw_device_get_schid(device->cdev, &sch_id);
1063 conf_data_saved = 0; 1069 conf_data_saved = 0;
1064 path_err = 0; 1070 path_err = 0;
1065 /* get configuration data per operational path */ 1071 /* get configuration data per operational path */
@@ -1097,6 +1103,12 @@ static int dasd_eckd_read_conf(struct dasd_device *device)
1097 pos = pathmask_to_pos(lpm); 1103 pos = pathmask_to_pos(lpm);
1098 /* store per path conf_data */ 1104 /* store per path conf_data */
1099 device->path[pos].conf_data = conf_data; 1105 device->path[pos].conf_data = conf_data;
1106 device->path[pos].cssid = sch_id.cssid;
1107 device->path[pos].ssid = sch_id.ssid;
1108 chp_desc = ccw_device_get_chp_desc(device->cdev, pos);
1109 if (chp_desc)
1110 device->path[pos].chpid = chp_desc->chpid;
1111 kfree(chp_desc);
1100 /* 1112 /*
1101 * build device UID that other path data 1113 * build device UID that other path data
1102 * can be compared to it 1114 * can be compared to it
@@ -1157,6 +1169,12 @@ static int dasd_eckd_read_conf(struct dasd_device *device)
1157 pos = pathmask_to_pos(lpm); 1169 pos = pathmask_to_pos(lpm);
1158 /* store per path conf_data */ 1170 /* store per path conf_data */
1159 device->path[pos].conf_data = conf_data; 1171 device->path[pos].conf_data = conf_data;
1172 device->path[pos].cssid = sch_id.cssid;
1173 device->path[pos].ssid = sch_id.ssid;
1174 chp_desc = ccw_device_get_chp_desc(device->cdev, pos);
1175 if (chp_desc)
1176 device->path[pos].chpid = chp_desc->chpid;
1177 kfree(chp_desc);
1160 path_private.conf_data = NULL; 1178 path_private.conf_data = NULL;
1161 path_private.conf_len = 0; 1179 path_private.conf_len = 0;
1162 } 1180 }
@@ -1179,6 +1197,32 @@ static int dasd_eckd_read_conf(struct dasd_device *device)
1179 return path_err; 1197 return path_err;
1180} 1198}
1181 1199
1200static u32 get_fcx_max_data(struct dasd_device *device)
1201{
1202 struct dasd_eckd_private *private = device->private;
1203 int fcx_in_css, fcx_in_gneq, fcx_in_features;
1204 int tpm, mdc;
1205
1206 if (dasd_nofcx)
1207 return 0;
1208 /* is transport mode supported? */
1209 fcx_in_css = css_general_characteristics.fcx;
1210 fcx_in_gneq = private->gneq->reserved2[7] & 0x04;
1211 fcx_in_features = private->features.feature[40] & 0x80;
1212 tpm = fcx_in_css && fcx_in_gneq && fcx_in_features;
1213
1214 if (!tpm)
1215 return 0;
1216
1217 mdc = ccw_device_get_mdc(device->cdev, 0);
1218 if (mdc < 0) {
1219 dev_warn(&device->cdev->dev, "Detecting the maximum supported data size for zHPF requests failed\n");
1220 return 0;
1221 } else {
1222 return (u32)mdc * FCX_MAX_DATA_FACTOR;
1223 }
1224}
1225
1182static int verify_fcx_max_data(struct dasd_device *device, __u8 lpm) 1226static int verify_fcx_max_data(struct dasd_device *device, __u8 lpm)
1183{ 1227{
1184 struct dasd_eckd_private *private = device->private; 1228 struct dasd_eckd_private *private = device->private;
@@ -1438,6 +1482,19 @@ static int dasd_eckd_verify_path(struct dasd_device *device, __u8 lpm)
1438 return 0; 1482 return 0;
1439} 1483}
1440 1484
1485static void dasd_eckd_reset_path(struct dasd_device *device, __u8 pm)
1486{
1487 struct dasd_eckd_private *private = device->private;
1488 unsigned long flags;
1489
1490 if (!private->fcx_max_data)
1491 private->fcx_max_data = get_fcx_max_data(device);
1492 spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
1493 dasd_path_set_tbvpm(device, pm ? : dasd_path_get_notoperpm(device));
1494 dasd_schedule_device_bh(device);
1495 spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
1496}
1497
1441static int dasd_eckd_read_features(struct dasd_device *device) 1498static int dasd_eckd_read_features(struct dasd_device *device)
1442{ 1499{
1443 struct dasd_eckd_private *private = device->private; 1500 struct dasd_eckd_private *private = device->private;
@@ -1634,32 +1691,6 @@ static void dasd_eckd_kick_validate_server(struct dasd_device *device)
1634 dasd_put_device(device); 1691 dasd_put_device(device);
1635} 1692}
1636 1693
1637static u32 get_fcx_max_data(struct dasd_device *device)
1638{
1639 struct dasd_eckd_private *private = device->private;
1640 int fcx_in_css, fcx_in_gneq, fcx_in_features;
1641 int tpm, mdc;
1642
1643 if (dasd_nofcx)
1644 return 0;
1645 /* is transport mode supported? */
1646 fcx_in_css = css_general_characteristics.fcx;
1647 fcx_in_gneq = private->gneq->reserved2[7] & 0x04;
1648 fcx_in_features = private->features.feature[40] & 0x80;
1649 tpm = fcx_in_css && fcx_in_gneq && fcx_in_features;
1650
1651 if (!tpm)
1652 return 0;
1653
1654 mdc = ccw_device_get_mdc(device->cdev, 0);
1655 if (mdc < 0) {
1656 dev_warn(&device->cdev->dev, "Detecting the maximum supported"
1657 " data size for zHPF requests failed\n");
1658 return 0;
1659 } else
1660 return (u32)mdc * FCX_MAX_DATA_FACTOR;
1661}
1662
1663/* 1694/*
1664 * Check device characteristics. 1695 * Check device characteristics.
1665 * If the device is accessible using ECKD discipline, the device is enabled. 1696 * If the device is accessible using ECKD discipline, the device is enabled.
@@ -1711,10 +1742,11 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
1711 if (rc) 1742 if (rc)
1712 goto out_err1; 1743 goto out_err1;
1713 1744
1714 /* set default timeout */ 1745 /* set some default values */
1715 device->default_expires = DASD_EXPIRES; 1746 device->default_expires = DASD_EXPIRES;
1716 /* set default retry count */
1717 device->default_retries = DASD_RETRIES; 1747 device->default_retries = DASD_RETRIES;
1748 device->path_thrhld = DASD_ECKD_PATH_THRHLD;
1749 device->path_interval = DASD_ECKD_PATH_INTERVAL;
1718 1750
1719 if (private->gneq) { 1751 if (private->gneq) {
1720 value = 1; 1752 value = 1;
@@ -1828,6 +1860,9 @@ static void dasd_eckd_uncheck_device(struct dasd_device *device)
1828 private->conf_len = 0; 1860 private->conf_len = 0;
1829 } 1861 }
1830 device->path[i].conf_data = NULL; 1862 device->path[i].conf_data = NULL;
1863 device->path[i].cssid = 0;
1864 device->path[i].ssid = 0;
1865 device->path[i].chpid = 0;
1831 } 1866 }
1832 kfree(private->conf_data); 1867 kfree(private->conf_data);
1833 private->conf_data = NULL; 1868 private->conf_data = NULL;
@@ -4765,7 +4800,8 @@ static void dasd_eckd_dump_sense_tcw(struct dasd_device *device,
4765 req, scsw_cc(&irb->scsw), scsw_fctl(&irb->scsw), 4800 req, scsw_cc(&irb->scsw), scsw_fctl(&irb->scsw),
4766 scsw_actl(&irb->scsw), scsw_stctl(&irb->scsw), 4801 scsw_actl(&irb->scsw), scsw_stctl(&irb->scsw),
4767 scsw_dstat(&irb->scsw), scsw_cstat(&irb->scsw), 4802 scsw_dstat(&irb->scsw), scsw_cstat(&irb->scsw),
4768 irb->scsw.tm.fcxs, irb->scsw.tm.schxs, 4803 irb->scsw.tm.fcxs,
4804 (irb->scsw.tm.ifob << 7) | irb->scsw.tm.sesq,
4769 req ? req->intrc : 0); 4805 req ? req->intrc : 0);
4770 len += sprintf(page + len, PRINTK_HEADER 4806 len += sprintf(page + len, PRINTK_HEADER
4771 " device %s: Failing TCW: %p\n", 4807 " device %s: Failing TCW: %p\n",
@@ -5288,11 +5324,10 @@ static int dasd_hosts_print(struct dasd_device *device, struct seq_file *m)
5288 */ 5324 */
5289static int 5325static int
5290dasd_eckd_psf_cuir_response(struct dasd_device *device, int response, 5326dasd_eckd_psf_cuir_response(struct dasd_device *device, int response,
5291 __u32 message_id, 5327 __u32 message_id, __u8 lpum)
5292 struct channel_path_desc *desc,
5293 struct subchannel_id sch_id)
5294{ 5328{
5295 struct dasd_psf_cuir_response *psf_cuir; 5329 struct dasd_psf_cuir_response *psf_cuir;
5330 int pos = pathmask_to_pos(lpum);
5296 struct dasd_ccw_req *cqr; 5331 struct dasd_ccw_req *cqr;
5297 struct ccw1 *ccw; 5332 struct ccw1 *ccw;
5298 int rc; 5333 int rc;
@@ -5310,11 +5345,10 @@ dasd_eckd_psf_cuir_response(struct dasd_device *device, int response,
5310 psf_cuir = (struct dasd_psf_cuir_response *)cqr->data; 5345 psf_cuir = (struct dasd_psf_cuir_response *)cqr->data;
5311 psf_cuir->order = PSF_ORDER_CUIR_RESPONSE; 5346 psf_cuir->order = PSF_ORDER_CUIR_RESPONSE;
5312 psf_cuir->cc = response; 5347 psf_cuir->cc = response;
5313 if (desc) 5348 psf_cuir->chpid = device->path[pos].chpid;
5314 psf_cuir->chpid = desc->chpid;
5315 psf_cuir->message_id = message_id; 5349 psf_cuir->message_id = message_id;
5316 psf_cuir->cssid = sch_id.cssid; 5350 psf_cuir->cssid = device->path[pos].cssid;
5317 psf_cuir->ssid = sch_id.ssid; 5351 psf_cuir->ssid = device->path[pos].ssid;
5318 ccw = cqr->cpaddr; 5352 ccw = cqr->cpaddr;
5319 ccw->cmd_code = DASD_ECKD_CCW_PSF; 5353 ccw->cmd_code = DASD_ECKD_CCW_PSF;
5320 ccw->cda = (__u32)(addr_t)psf_cuir; 5354 ccw->cda = (__u32)(addr_t)psf_cuir;
@@ -5427,27 +5461,23 @@ static int dasd_eckd_cuir_scope(struct dasd_device *device, __u8 lpum,
5427} 5461}
5428 5462
5429static void dasd_eckd_cuir_notify_user(struct dasd_device *device, 5463static void dasd_eckd_cuir_notify_user(struct dasd_device *device,
5430 unsigned long paths, 5464 unsigned long paths, int action)
5431 struct subchannel_id sch_id, int action)
5432{ 5465{
5433 struct channel_path_desc *desc;
5434 int pos; 5466 int pos;
5435 5467
5436 while (paths) { 5468 while (paths) {
5437 /* get position of bit in mask */ 5469 /* get position of bit in mask */
5438 pos = ffs(paths) - 1; 5470 pos = 8 - ffs(paths);
5439 /* get channel path descriptor from this position */ 5471 /* get channel path descriptor from this position */
5440 desc = ccw_device_get_chp_desc(device->cdev, 7 - pos);
5441 if (action == CUIR_QUIESCE) 5472 if (action == CUIR_QUIESCE)
5442 pr_warn("Service on the storage server caused path " 5473 pr_warn("Service on the storage server caused path %x.%02x to go offline",
5443 "%x.%02x to go offline", sch_id.cssid, 5474 device->path[pos].cssid,
5444 desc ? desc->chpid : 0); 5475 device->path[pos].chpid);
5445 else if (action == CUIR_RESUME) 5476 else if (action == CUIR_RESUME)
5446 pr_info("Path %x.%02x is back online after service " 5477 pr_info("Path %x.%02x is back online after service on the storage server",
5447 "on the storage server", sch_id.cssid, 5478 device->path[pos].cssid,
5448 desc ? desc->chpid : 0); 5479 device->path[pos].chpid);
5449 kfree(desc); 5480 clear_bit(7 - pos, &paths);
5450 clear_bit(pos, &paths);
5451 } 5481 }
5452} 5482}
5453 5483
@@ -5480,7 +5510,6 @@ static int dasd_eckd_cuir_remove_path(struct dasd_device *device, __u8 lpum,
5480 * notify the already set offline devices again 5510 * notify the already set offline devices again
5481 */ 5511 */
5482static int dasd_eckd_cuir_quiesce(struct dasd_device *device, __u8 lpum, 5512static int dasd_eckd_cuir_quiesce(struct dasd_device *device, __u8 lpum,
5483 struct subchannel_id sch_id,
5484 struct dasd_cuir_message *cuir) 5513 struct dasd_cuir_message *cuir)
5485{ 5514{
5486 struct dasd_eckd_private *private = device->private; 5515 struct dasd_eckd_private *private = device->private;
@@ -5535,14 +5564,13 @@ static int dasd_eckd_cuir_quiesce(struct dasd_device *device, __u8 lpum,
5535 } 5564 }
5536 } 5565 }
5537 /* notify user about all paths affected by CUIR action */ 5566 /* notify user about all paths affected by CUIR action */
5538 dasd_eckd_cuir_notify_user(device, paths, sch_id, CUIR_QUIESCE); 5567 dasd_eckd_cuir_notify_user(device, paths, CUIR_QUIESCE);
5539 return 0; 5568 return 0;
5540out_err: 5569out_err:
5541 return tbcpm; 5570 return tbcpm;
5542} 5571}
5543 5572
5544static int dasd_eckd_cuir_resume(struct dasd_device *device, __u8 lpum, 5573static int dasd_eckd_cuir_resume(struct dasd_device *device, __u8 lpum,
5545 struct subchannel_id sch_id,
5546 struct dasd_cuir_message *cuir) 5574 struct dasd_cuir_message *cuir)
5547{ 5575{
5548 struct dasd_eckd_private *private = device->private; 5576 struct dasd_eckd_private *private = device->private;
@@ -5601,7 +5629,7 @@ static int dasd_eckd_cuir_resume(struct dasd_device *device, __u8 lpum,
5601 } 5629 }
5602 } 5630 }
5603 /* notify user about all paths affected by CUIR action */ 5631 /* notify user about all paths affected by CUIR action */
5604 dasd_eckd_cuir_notify_user(device, paths, sch_id, CUIR_RESUME); 5632 dasd_eckd_cuir_notify_user(device, paths, CUIR_RESUME);
5605 return 0; 5633 return 0;
5606} 5634}
5607 5635
@@ -5609,38 +5637,31 @@ static void dasd_eckd_handle_cuir(struct dasd_device *device, void *messages,
5609 __u8 lpum) 5637 __u8 lpum)
5610{ 5638{
5611 struct dasd_cuir_message *cuir = messages; 5639 struct dasd_cuir_message *cuir = messages;
5612 struct channel_path_desc *desc; 5640 int response;
5613 struct subchannel_id sch_id;
5614 int pos, response;
5615 5641
5616 DBF_DEV_EVENT(DBF_WARNING, device, 5642 DBF_DEV_EVENT(DBF_WARNING, device,
5617 "CUIR request: %016llx %016llx %016llx %08x", 5643 "CUIR request: %016llx %016llx %016llx %08x",
5618 ((u64 *)cuir)[0], ((u64 *)cuir)[1], ((u64 *)cuir)[2], 5644 ((u64 *)cuir)[0], ((u64 *)cuir)[1], ((u64 *)cuir)[2],
5619 ((u32 *)cuir)[3]); 5645 ((u32 *)cuir)[3]);
5620 ccw_device_get_schid(device->cdev, &sch_id);
5621 pos = pathmask_to_pos(lpum);
5622 desc = ccw_device_get_chp_desc(device->cdev, pos);
5623 5646
5624 if (cuir->code == CUIR_QUIESCE) { 5647 if (cuir->code == CUIR_QUIESCE) {
5625 /* quiesce */ 5648 /* quiesce */
5626 if (dasd_eckd_cuir_quiesce(device, lpum, sch_id, cuir)) 5649 if (dasd_eckd_cuir_quiesce(device, lpum, cuir))
5627 response = PSF_CUIR_LAST_PATH; 5650 response = PSF_CUIR_LAST_PATH;
5628 else 5651 else
5629 response = PSF_CUIR_COMPLETED; 5652 response = PSF_CUIR_COMPLETED;
5630 } else if (cuir->code == CUIR_RESUME) { 5653 } else if (cuir->code == CUIR_RESUME) {
5631 /* resume */ 5654 /* resume */
5632 dasd_eckd_cuir_resume(device, lpum, sch_id, cuir); 5655 dasd_eckd_cuir_resume(device, lpum, cuir);
5633 response = PSF_CUIR_COMPLETED; 5656 response = PSF_CUIR_COMPLETED;
5634 } else 5657 } else
5635 response = PSF_CUIR_NOT_SUPPORTED; 5658 response = PSF_CUIR_NOT_SUPPORTED;
5636 5659
5637 dasd_eckd_psf_cuir_response(device, response, 5660 dasd_eckd_psf_cuir_response(device, response,
5638 cuir->message_id, desc, sch_id); 5661 cuir->message_id, lpum);
5639 DBF_DEV_EVENT(DBF_WARNING, device, 5662 DBF_DEV_EVENT(DBF_WARNING, device,
5640 "CUIR response: %d on message ID %08x", response, 5663 "CUIR response: %d on message ID %08x", response,
5641 cuir->message_id); 5664 cuir->message_id);
5642 /* free descriptor copy */
5643 kfree(desc);
5644 /* to make sure there is no attention left schedule work again */ 5665 /* to make sure there is no attention left schedule work again */
5645 device->discipline->check_attention(device, lpum); 5666 device->discipline->check_attention(device, lpum);
5646} 5667}
@@ -5687,6 +5708,63 @@ static int dasd_eckd_check_attention(struct dasd_device *device, __u8 lpum)
5687 return 0; 5708 return 0;
5688} 5709}
5689 5710
5711static int dasd_eckd_disable_hpf_path(struct dasd_device *device, __u8 lpum)
5712{
5713 if (~lpum & dasd_path_get_opm(device)) {
5714 dasd_path_add_nohpfpm(device, lpum);
5715 dasd_path_remove_opm(device, lpum);
5716 dev_err(&device->cdev->dev,
5717 "Channel path %02X lost HPF functionality and is disabled\n",
5718 lpum);
5719 return 1;
5720 }
5721 return 0;
5722}
5723
5724static void dasd_eckd_disable_hpf_device(struct dasd_device *device)
5725{
5726 struct dasd_eckd_private *private = device->private;
5727
5728 dev_err(&device->cdev->dev,
5729 "High Performance FICON disabled\n");
5730 private->fcx_max_data = 0;
5731}
5732
5733static int dasd_eckd_hpf_enabled(struct dasd_device *device)
5734{
5735 struct dasd_eckd_private *private = device->private;
5736
5737 return private->fcx_max_data ? 1 : 0;
5738}
5739
5740static void dasd_eckd_handle_hpf_error(struct dasd_device *device,
5741 struct irb *irb)
5742{
5743 struct dasd_eckd_private *private = device->private;
5744
5745 if (!private->fcx_max_data) {
5746 /* sanity check for no HPF, the error makes no sense */
5747 DBF_DEV_EVENT(DBF_WARNING, device, "%s",
5748 "Trying to disable HPF for a non HPF device");
5749 return;
5750 }
5751 if (irb->scsw.tm.sesq == SCSW_SESQ_DEV_NOFCX) {
5752 dasd_eckd_disable_hpf_device(device);
5753 } else if (irb->scsw.tm.sesq == SCSW_SESQ_PATH_NOFCX) {
5754 if (dasd_eckd_disable_hpf_path(device, irb->esw.esw1.lpum))
5755 return;
5756 dasd_eckd_disable_hpf_device(device);
5757 dasd_path_set_tbvpm(device,
5758 dasd_path_get_hpfpm(device));
5759 }
5760 /*
5761 * prevent that any new I/O ist started on the device and schedule a
5762 * requeue of existing requests
5763 */
5764 dasd_device_set_stop_bits(device, DASD_STOPPED_NOT_ACC);
5765 dasd_schedule_requeue(device);
5766}
5767
5690static struct ccw_driver dasd_eckd_driver = { 5768static struct ccw_driver dasd_eckd_driver = {
5691 .driver = { 5769 .driver = {
5692 .name = "dasd-eckd", 5770 .name = "dasd-eckd",
@@ -5755,6 +5833,10 @@ static struct dasd_discipline dasd_eckd_discipline = {
5755 .check_attention = dasd_eckd_check_attention, 5833 .check_attention = dasd_eckd_check_attention,
5756 .host_access_count = dasd_eckd_host_access_count, 5834 .host_access_count = dasd_eckd_host_access_count,
5757 .hosts_print = dasd_hosts_print, 5835 .hosts_print = dasd_hosts_print,
5836 .handle_hpf_error = dasd_eckd_handle_hpf_error,
5837 .disable_hpf = dasd_eckd_disable_hpf_device,
5838 .hpf_enabled = dasd_eckd_hpf_enabled,
5839 .reset_path = dasd_eckd_reset_path,
5758}; 5840};
5759 5841
5760static int __init 5842static int __init
diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h
index e491f4416e40..e2a710c250a5 100644
--- a/drivers/s390/block/dasd_eckd.h
+++ b/drivers/s390/block/dasd_eckd.h
@@ -94,6 +94,8 @@
94#define FCX_MAX_DATA_FACTOR 65536 94#define FCX_MAX_DATA_FACTOR 65536
95#define DASD_ECKD_RCD_DATA_SIZE 256 95#define DASD_ECKD_RCD_DATA_SIZE 256
96 96
97#define DASD_ECKD_PATH_THRHLD 256
98#define DASD_ECKD_PATH_INTERVAL 300
97 99
98/***************************************************************************** 100/*****************************************************************************
99 * SECTION: Type Definitions 101 * SECTION: Type Definitions
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index d75f996884d9..24be210c10e5 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -378,6 +378,10 @@ struct dasd_discipline {
378 int (*check_attention)(struct dasd_device *, __u8); 378 int (*check_attention)(struct dasd_device *, __u8);
379 int (*host_access_count)(struct dasd_device *); 379 int (*host_access_count)(struct dasd_device *);
380 int (*hosts_print)(struct dasd_device *, struct seq_file *); 380 int (*hosts_print)(struct dasd_device *, struct seq_file *);
381 void (*handle_hpf_error)(struct dasd_device *, struct irb *);
382 void (*disable_hpf)(struct dasd_device *);
383 int (*hpf_enabled)(struct dasd_device *);
384 void (*reset_path)(struct dasd_device *, __u8);
381}; 385};
382 386
383extern struct dasd_discipline *dasd_diag_discipline_pointer; 387extern struct dasd_discipline *dasd_diag_discipline_pointer;
@@ -407,11 +411,19 @@ extern struct dasd_discipline *dasd_diag_discipline_pointer;
407#define DASD_PATH_MISCABLED 5 411#define DASD_PATH_MISCABLED 5
408#define DASD_PATH_NOHPF 6 412#define DASD_PATH_NOHPF 6
409#define DASD_PATH_CUIR 7 413#define DASD_PATH_CUIR 7
414#define DASD_PATH_IFCC 8
410 415
416#define DASD_THRHLD_MAX 4294967295U
417#define DASD_INTERVAL_MAX 4294967295U
411 418
412struct dasd_path { 419struct dasd_path {
413 unsigned long flags; 420 unsigned long flags;
421 u8 cssid;
422 u8 ssid;
423 u8 chpid;
414 struct dasd_conf_data *conf_data; 424 struct dasd_conf_data *conf_data;
425 atomic_t error_count;
426 unsigned long long errorclk;
415}; 427};
416 428
417 429
@@ -491,6 +503,7 @@ struct dasd_device {
491 struct work_struct reload_device; 503 struct work_struct reload_device;
492 struct work_struct kick_validate; 504 struct work_struct kick_validate;
493 struct work_struct suc_work; 505 struct work_struct suc_work;
506 struct work_struct requeue_requests;
494 struct timer_list timer; 507 struct timer_list timer;
495 508
496 debug_info_t *debug_area; 509 debug_info_t *debug_area;
@@ -506,6 +519,9 @@ struct dasd_device {
506 519
507 unsigned long blk_timeout; 520 unsigned long blk_timeout;
508 521
522 unsigned long path_thrhld;
523 unsigned long path_interval;
524
509 struct dentry *debugfs_dentry; 525 struct dentry *debugfs_dentry;
510 struct dentry *hosts_dentry; 526 struct dentry *hosts_dentry;
511 struct dasd_profile profile; 527 struct dasd_profile profile;
@@ -715,6 +731,7 @@ void dasd_set_target_state(struct dasd_device *, int);
715void dasd_kick_device(struct dasd_device *); 731void dasd_kick_device(struct dasd_device *);
716void dasd_restore_device(struct dasd_device *); 732void dasd_restore_device(struct dasd_device *);
717void dasd_reload_device(struct dasd_device *); 733void dasd_reload_device(struct dasd_device *);
734void dasd_schedule_requeue(struct dasd_device *);
718 735
719void dasd_add_request_head(struct dasd_ccw_req *); 736void dasd_add_request_head(struct dasd_ccw_req *);
720void dasd_add_request_tail(struct dasd_ccw_req *); 737void dasd_add_request_tail(struct dasd_ccw_req *);
@@ -941,6 +958,21 @@ static inline void dasd_path_clear_cuir(struct dasd_device *device, int chp)
941 __clear_bit(DASD_PATH_CUIR, &device->path[chp].flags); 958 __clear_bit(DASD_PATH_CUIR, &device->path[chp].flags);
942} 959}
943 960
961static inline void dasd_path_ifcc(struct dasd_device *device, int chp)
962{
963 set_bit(DASD_PATH_IFCC, &device->path[chp].flags);
964}
965
966static inline int dasd_path_is_ifcc(struct dasd_device *device, int chp)
967{
968 return test_bit(DASD_PATH_IFCC, &device->path[chp].flags);
969}
970
971static inline void dasd_path_clear_ifcc(struct dasd_device *device, int chp)
972{
973 clear_bit(DASD_PATH_IFCC, &device->path[chp].flags);
974}
975
944static inline void dasd_path_clear_nohpf(struct dasd_device *device, int chp) 976static inline void dasd_path_clear_nohpf(struct dasd_device *device, int chp)
945{ 977{
946 __clear_bit(DASD_PATH_NOHPF, &device->path[chp].flags); 978 __clear_bit(DASD_PATH_NOHPF, &device->path[chp].flags);
@@ -1032,6 +1064,17 @@ static inline __u8 dasd_path_get_cuirpm(struct dasd_device *device)
1032 return cuirpm; 1064 return cuirpm;
1033} 1065}
1034 1066
1067static inline __u8 dasd_path_get_ifccpm(struct dasd_device *device)
1068{
1069 int chp;
1070 __u8 ifccpm = 0x00;
1071
1072 for (chp = 0; chp < 8; chp++)
1073 if (dasd_path_is_ifcc(device, chp))
1074 ifccpm |= 0x80 >> chp;
1075 return ifccpm;
1076}
1077
1035static inline __u8 dasd_path_get_hpfpm(struct dasd_device *device) 1078static inline __u8 dasd_path_get_hpfpm(struct dasd_device *device)
1036{ 1079{
1037 int chp; 1080 int chp;
@@ -1056,6 +1099,20 @@ static inline void dasd_path_add_tbvpm(struct dasd_device *device, __u8 pm)
1056 dasd_path_verify(device, chp); 1099 dasd_path_verify(device, chp);
1057} 1100}
1058 1101
1102static inline __u8 dasd_path_get_notoperpm(struct dasd_device *device)
1103{
1104 int chp;
1105 __u8 nopm = 0x00;
1106
1107 for (chp = 0; chp < 8; chp++)
1108 if (dasd_path_is_nohpf(device, chp) ||
1109 dasd_path_is_ifcc(device, chp) ||
1110 dasd_path_is_cuir(device, chp) ||
1111 dasd_path_is_miscabled(device, chp))
1112 nopm |= 0x80 >> chp;
1113 return nopm;
1114}
1115
1059static inline void dasd_path_add_opm(struct dasd_device *device, __u8 pm) 1116static inline void dasd_path_add_opm(struct dasd_device *device, __u8 pm)
1060{ 1117{
1061 int chp; 1118 int chp;
@@ -1070,6 +1127,7 @@ static inline void dasd_path_add_opm(struct dasd_device *device, __u8 pm)
1070 dasd_path_clear_nohpf(device, chp); 1127 dasd_path_clear_nohpf(device, chp);
1071 dasd_path_clear_cuir(device, chp); 1128 dasd_path_clear_cuir(device, chp);
1072 dasd_path_clear_cable(device, chp); 1129 dasd_path_clear_cable(device, chp);
1130 dasd_path_clear_ifcc(device, chp);
1073 } 1131 }
1074} 1132}
1075 1133
@@ -1091,6 +1149,15 @@ static inline void dasd_path_add_cuirpm(struct dasd_device *device, __u8 pm)
1091 dasd_path_cuir(device, chp); 1149 dasd_path_cuir(device, chp);
1092} 1150}
1093 1151
1152static inline void dasd_path_add_ifccpm(struct dasd_device *device, __u8 pm)
1153{
1154 int chp;
1155
1156 for (chp = 0; chp < 8; chp++)
1157 if (pm & (0x80 >> chp))
1158 dasd_path_ifcc(device, chp);
1159}
1160
1094static inline void dasd_path_add_nppm(struct dasd_device *device, __u8 pm) 1161static inline void dasd_path_add_nppm(struct dasd_device *device, __u8 pm)
1095{ 1162{
1096 int chp; 1163 int chp;
@@ -1148,6 +1215,7 @@ static inline void dasd_path_set_opm(struct dasd_device *device, __u8 pm)
1148 dasd_path_clear_nohpf(device, chp); 1215 dasd_path_clear_nohpf(device, chp);
1149 dasd_path_clear_cuir(device, chp); 1216 dasd_path_clear_cuir(device, chp);
1150 dasd_path_clear_cable(device, chp); 1217 dasd_path_clear_cable(device, chp);
1218 dasd_path_clear_ifcc(device, chp);
1151 } 1219 }
1152 } 1220 }
1153} 1221}