aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Haberland <sth@linux.vnet.ibm.com>2016-08-08 09:53:54 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2016-12-12 06:04:37 -0500
commitc93461515a1a16486f4e483cb34170366fa73ea1 (patch)
treeae5ea26b0f7046c63914277799c72f83a2da14d5
parent7df11604592b579bce2762783c21569d02272332 (diff)
s390/dasd: extend dasd path handling
Store flags and path_data per channel path. Implement get/set functions for various path masks. The patch does not add functional changes. 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--drivers/s390/block/dasd.c101
-rw-r--r--drivers/s390/block/dasd_3990_erp.c6
-rw-r--r--drivers/s390/block/dasd_devmap.c10
-rw-r--r--drivers/s390/block/dasd_eckd.c113
-rw-r--r--drivers/s390/block/dasd_eckd.h3
-rw-r--r--drivers/s390/block/dasd_erp.c2
-rw-r--r--drivers/s390/block/dasd_fba.c2
-rw-r--r--drivers/s390/block/dasd_int.h381
8 files changed, 475 insertions, 143 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index e21465ecb60f..13a337faef43 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -1448,9 +1448,9 @@ int dasd_start_IO(struct dasd_ccw_req *cqr)
1448 cqr->starttime = jiffies; 1448 cqr->starttime = jiffies;
1449 cqr->retries--; 1449 cqr->retries--;
1450 if (!test_bit(DASD_CQR_VERIFY_PATH, &cqr->flags)) { 1450 if (!test_bit(DASD_CQR_VERIFY_PATH, &cqr->flags)) {
1451 cqr->lpm &= device->path_data.opm; 1451 cqr->lpm &= dasd_path_get_opm(device);
1452 if (!cqr->lpm) 1452 if (!cqr->lpm)
1453 cqr->lpm = device->path_data.opm; 1453 cqr->lpm = dasd_path_get_opm(device);
1454 } 1454 }
1455 if (cqr->cpmode == 1) { 1455 if (cqr->cpmode == 1) {
1456 rc = ccw_device_tm_start(device->cdev, cqr->cpaddr, 1456 rc = ccw_device_tm_start(device->cdev, cqr->cpaddr,
@@ -1483,8 +1483,8 @@ int dasd_start_IO(struct dasd_ccw_req *cqr)
1483 DBF_DEV_EVENT(DBF_WARNING, device, 1483 DBF_DEV_EVENT(DBF_WARNING, device,
1484 "start_IO: selected paths gone (%x)", 1484 "start_IO: selected paths gone (%x)",
1485 cqr->lpm); 1485 cqr->lpm);
1486 } else if (cqr->lpm != device->path_data.opm) { 1486 } else if (cqr->lpm != dasd_path_get_opm(device)) {
1487 cqr->lpm = device->path_data.opm; 1487 cqr->lpm = dasd_path_get_opm(device);
1488 DBF_DEV_EVENT(DBF_DEBUG, device, "%s", 1488 DBF_DEV_EVENT(DBF_DEBUG, device, "%s",
1489 "start_IO: selected paths gone," 1489 "start_IO: selected paths gone,"
1490 " retry on all paths"); 1490 " retry on all paths");
@@ -1493,11 +1493,10 @@ int dasd_start_IO(struct dasd_ccw_req *cqr)
1493 "start_IO: all paths in opm gone," 1493 "start_IO: all paths in opm gone,"
1494 " do path verification"); 1494 " do path verification");
1495 dasd_generic_last_path_gone(device); 1495 dasd_generic_last_path_gone(device);
1496 device->path_data.opm = 0; 1496 dasd_path_no_path(device);
1497 device->path_data.ppm = 0; 1497 dasd_path_set_tbvpm(device,
1498 device->path_data.npm = 0; 1498 ccw_device_get_path_mask(
1499 device->path_data.tbvpm = 1499 device->cdev));
1500 ccw_device_get_path_mask(device->cdev);
1501 } 1500 }
1502 break; 1501 break;
1503 case -ENODEV: 1502 case -ENODEV:
@@ -1642,7 +1641,7 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
1642 switch (PTR_ERR(irb)) { 1641 switch (PTR_ERR(irb)) {
1643 case -EIO: 1642 case -EIO:
1644 if (cqr && cqr->status == DASD_CQR_CLEAR_PENDING) { 1643 if (cqr && cqr->status == DASD_CQR_CLEAR_PENDING) {
1645 device = (struct dasd_device *) cqr->startdev; 1644 device = cqr->startdev;
1646 cqr->status = DASD_CQR_CLEARED; 1645 cqr->status = DASD_CQR_CLEARED;
1647 dasd_device_clear_timer(device); 1646 dasd_device_clear_timer(device);
1648 wake_up(&dasd_flush_wq); 1647 wake_up(&dasd_flush_wq);
@@ -1755,13 +1754,13 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
1755 */ 1754 */
1756 if (!test_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags) && 1755 if (!test_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags) &&
1757 cqr->retries > 0) { 1756 cqr->retries > 0) {
1758 if (cqr->lpm == device->path_data.opm) 1757 if (cqr->lpm == dasd_path_get_opm(device))
1759 DBF_DEV_EVENT(DBF_DEBUG, device, 1758 DBF_DEV_EVENT(DBF_DEBUG, device,
1760 "default ERP in fastpath " 1759 "default ERP in fastpath "
1761 "(%i retries left)", 1760 "(%i retries left)",
1762 cqr->retries); 1761 cqr->retries);
1763 if (!test_bit(DASD_CQR_VERIFY_PATH, &cqr->flags)) 1762 if (!test_bit(DASD_CQR_VERIFY_PATH, &cqr->flags))
1764 cqr->lpm = device->path_data.opm; 1763 cqr->lpm = dasd_path_get_opm(device);
1765 cqr->status = DASD_CQR_QUEUED; 1764 cqr->status = DASD_CQR_QUEUED;
1766 next = cqr; 1765 next = cqr;
1767 } else 1766 } else
@@ -2002,17 +2001,18 @@ static void __dasd_device_check_path_events(struct dasd_device *device)
2002{ 2001{
2003 int rc; 2002 int rc;
2004 2003
2005 if (device->path_data.tbvpm) { 2004 if (!dasd_path_get_tbvpm(device))
2006 if (device->stopped & ~(DASD_STOPPED_DC_WAIT | 2005 return;
2007 DASD_UNRESUMED_PM)) 2006
2008 return; 2007 if (device->stopped &
2009 rc = device->discipline->verify_path( 2008 ~(DASD_STOPPED_DC_WAIT | DASD_UNRESUMED_PM))
2010 device, device->path_data.tbvpm); 2009 return;
2011 if (rc) 2010 rc = device->discipline->verify_path(device,
2012 dasd_device_set_timer(device, 50); 2011 dasd_path_get_tbvpm(device));
2013 else 2012 if (rc)
2014 device->path_data.tbvpm = 0; 2013 dasd_device_set_timer(device, 50);
2015 } 2014 else
2015 dasd_path_clear_all_verify(device);
2016}; 2016};
2017 2017
2018/* 2018/*
@@ -3684,14 +3684,12 @@ int dasd_generic_notify(struct ccw_device *cdev, int event)
3684 case CIO_GONE: 3684 case CIO_GONE:
3685 case CIO_BOXED: 3685 case CIO_BOXED:
3686 case CIO_NO_PATH: 3686 case CIO_NO_PATH:
3687 device->path_data.opm = 0; 3687 dasd_path_no_path(device);
3688 device->path_data.ppm = 0;
3689 device->path_data.npm = 0;
3690 ret = dasd_generic_last_path_gone(device); 3688 ret = dasd_generic_last_path_gone(device);
3691 break; 3689 break;
3692 case CIO_OPER: 3690 case CIO_OPER:
3693 ret = 1; 3691 ret = 1;
3694 if (device->path_data.opm) 3692 if (dasd_path_get_opm(device))
3695 ret = dasd_generic_path_operational(device); 3693 ret = dasd_generic_path_operational(device);
3696 break; 3694 break;
3697 } 3695 }
@@ -3702,48 +3700,32 @@ EXPORT_SYMBOL_GPL(dasd_generic_notify);
3702 3700
3703void dasd_generic_path_event(struct ccw_device *cdev, int *path_event) 3701void dasd_generic_path_event(struct ccw_device *cdev, int *path_event)
3704{ 3702{
3705 int chp;
3706 __u8 oldopm, eventlpm;
3707 struct dasd_device *device; 3703 struct dasd_device *device;
3704 int chp, oldopm;
3708 3705
3709 device = dasd_device_from_cdev_locked(cdev); 3706 device = dasd_device_from_cdev_locked(cdev);
3710 if (IS_ERR(device)) 3707 if (IS_ERR(device))
3711 return; 3708 return;
3709
3710 oldopm = dasd_path_get_opm(device);
3712 for (chp = 0; chp < 8; chp++) { 3711 for (chp = 0; chp < 8; chp++) {
3713 eventlpm = 0x80 >> chp;
3714 if (path_event[chp] & PE_PATH_GONE) { 3712 if (path_event[chp] & PE_PATH_GONE) {
3715 oldopm = device->path_data.opm; 3713 dasd_path_notoper(device, chp);
3716 device->path_data.opm &= ~eventlpm;
3717 device->path_data.ppm &= ~eventlpm;
3718 device->path_data.npm &= ~eventlpm;
3719 if (oldopm && !device->path_data.opm) {
3720 dev_warn(&device->cdev->dev,
3721 "No verified channel paths remain "
3722 "for the device\n");
3723 DBF_DEV_EVENT(DBF_WARNING, device,
3724 "%s", "last verified path gone");
3725 dasd_eer_write(device, NULL, DASD_EER_NOPATH);
3726 dasd_device_set_stop_bits(device,
3727 DASD_STOPPED_DC_WAIT);
3728 }
3729 } 3714 }
3730 if (path_event[chp] & PE_PATH_AVAILABLE) { 3715 if (path_event[chp] & PE_PATH_AVAILABLE) {
3731 device->path_data.opm &= ~eventlpm; 3716 dasd_path_available(device, chp);
3732 device->path_data.ppm &= ~eventlpm;
3733 device->path_data.npm &= ~eventlpm;
3734 device->path_data.tbvpm |= eventlpm;
3735 dasd_schedule_device_bh(device); 3717 dasd_schedule_device_bh(device);
3736 } 3718 }
3737 if (path_event[chp] & PE_PATHGROUP_ESTABLISHED) { 3719 if (path_event[chp] & PE_PATHGROUP_ESTABLISHED) {
3738 if (!(device->path_data.opm & eventlpm) && 3720 if (!dasd_path_is_operational(device, chp) &&
3739 !(device->path_data.tbvpm & eventlpm)) { 3721 !dasd_path_need_verify(device, chp)) {
3740 /* 3722 /*
3741 * we can not establish a pathgroup on an 3723 * we can not establish a pathgroup on an
3742 * unavailable path, so trigger a path 3724 * unavailable path, so trigger a path
3743 * verification first 3725 * verification first
3744 */ 3726 */
3745 device->path_data.tbvpm |= eventlpm; 3727 dasd_path_available(device, chp);
3746 dasd_schedule_device_bh(device); 3728 dasd_schedule_device_bh(device);
3747 } 3729 }
3748 DBF_DEV_EVENT(DBF_WARNING, device, "%s", 3730 DBF_DEV_EVENT(DBF_WARNING, device, "%s",
3749 "Pathgroup re-established\n"); 3731 "Pathgroup re-established\n");
@@ -3751,17 +3733,26 @@ void dasd_generic_path_event(struct ccw_device *cdev, int *path_event)
3751 device->discipline->kick_validate(device); 3733 device->discipline->kick_validate(device);
3752 } 3734 }
3753 } 3735 }
3736 if (oldopm && !dasd_path_get_opm(device)) {
3737 dev_warn(&device->cdev->dev,
3738 "No verified channel paths remain for the device\n");
3739 DBF_DEV_EVENT(DBF_WARNING, device,
3740 "%s", "last verified path gone");
3741 dasd_eer_write(device, NULL, DASD_EER_NOPATH);
3742 dasd_device_set_stop_bits(device,
3743 DASD_STOPPED_DC_WAIT);
3744 }
3754 dasd_put_device(device); 3745 dasd_put_device(device);
3755} 3746}
3756EXPORT_SYMBOL_GPL(dasd_generic_path_event); 3747EXPORT_SYMBOL_GPL(dasd_generic_path_event);
3757 3748
3758int dasd_generic_verify_path(struct dasd_device *device, __u8 lpm) 3749int dasd_generic_verify_path(struct dasd_device *device, __u8 lpm)
3759{ 3750{
3760 if (!device->path_data.opm && lpm) { 3751 if (!dasd_path_get_opm(device) && lpm) {
3761 device->path_data.opm = lpm; 3752 dasd_path_set_opm(device, lpm);
3762 dasd_generic_path_operational(device); 3753 dasd_generic_path_operational(device);
3763 } else 3754 } else
3764 device->path_data.opm |= lpm; 3755 dasd_path_add_opm(device, lpm);
3765 return 0; 3756 return 0;
3766} 3757}
3767EXPORT_SYMBOL_GPL(dasd_generic_verify_path); 3758EXPORT_SYMBOL_GPL(dasd_generic_verify_path);
diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c
index 8305ab688d57..9236e2c0c3d9 100644
--- a/drivers/s390/block/dasd_3990_erp.c
+++ b/drivers/s390/block/dasd_3990_erp.c
@@ -152,7 +152,7 @@ dasd_3990_erp_alternate_path(struct dasd_ccw_req * erp)
152 opm = ccw_device_get_path_mask(device->cdev); 152 opm = ccw_device_get_path_mask(device->cdev);
153 spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); 153 spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
154 if (erp->lpm == 0) 154 if (erp->lpm == 0)
155 erp->lpm = device->path_data.opm & 155 erp->lpm = dasd_path_get_opm(device) &
156 ~(erp->irb.esw.esw0.sublog.lpum); 156 ~(erp->irb.esw.esw0.sublog.lpum);
157 else 157 else
158 erp->lpm &= ~(erp->irb.esw.esw0.sublog.lpum); 158 erp->lpm &= ~(erp->irb.esw.esw0.sublog.lpum);
@@ -273,7 +273,7 @@ static struct dasd_ccw_req *dasd_3990_erp_action_1(struct dasd_ccw_req *erp)
273 !test_bit(DASD_CQR_VERIFY_PATH, &erp->flags)) { 273 !test_bit(DASD_CQR_VERIFY_PATH, &erp->flags)) {
274 erp->status = DASD_CQR_FILLED; 274 erp->status = DASD_CQR_FILLED;
275 erp->retries = 10; 275 erp->retries = 10;
276 erp->lpm = erp->startdev->path_data.opm; 276 erp->lpm = dasd_path_get_opm(erp->startdev);
277 erp->function = dasd_3990_erp_action_1_sec; 277 erp->function = dasd_3990_erp_action_1_sec;
278 } 278 }
279 return erp; 279 return erp;
@@ -1926,7 +1926,7 @@ dasd_3990_erp_compound_path(struct dasd_ccw_req * erp, char *sense)
1926 !test_bit(DASD_CQR_VERIFY_PATH, &erp->flags)) { 1926 !test_bit(DASD_CQR_VERIFY_PATH, &erp->flags)) {
1927 /* reset the lpm and the status to be able to 1927 /* reset the lpm and the status to be able to
1928 * try further actions. */ 1928 * try further actions. */
1929 erp->lpm = erp->startdev->path_data.opm; 1929 erp->lpm = dasd_path_get_opm(erp->startdev);
1930 erp->status = DASD_CQR_NEED_ERP; 1930 erp->status = DASD_CQR_NEED_ERP;
1931 } 1931 }
1932 } 1932 }
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index cbae6ab448b8..4101ab000c16 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -1438,11 +1438,11 @@ static ssize_t dasd_pm_show(struct device *dev,
1438 if (IS_ERR(device)) 1438 if (IS_ERR(device))
1439 return sprintf(buf, "0\n"); 1439 return sprintf(buf, "0\n");
1440 1440
1441 opm = device->path_data.opm; 1441 opm = dasd_path_get_opm(device);
1442 nppm = device->path_data.npm; 1442 nppm = dasd_path_get_nppm(device);
1443 cablepm = device->path_data.cablepm; 1443 cablepm = dasd_path_get_cablepm(device);
1444 cuirpm = device->path_data.cuirpm; 1444 cuirpm = dasd_path_get_cuirpm(device);
1445 hpfpm = device->path_data.hpfpm; 1445 hpfpm = dasd_path_get_hpfpm(device);
1446 dasd_put_device(device); 1446 dasd_put_device(device);
1447 1447
1448 return sprintf(buf, "%02x %02x %02x %02x %02x\n", opm, nppm, 1448 return sprintf(buf, "%02x %02x %02x %02x %02x\n", opm, nppm,
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index a7a88476e215..51fdf31aa8eb 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -1042,8 +1042,8 @@ static void dasd_eckd_clear_conf_data(struct dasd_device *device)
1042 private->conf_data = NULL; 1042 private->conf_data = NULL;
1043 private->conf_len = 0; 1043 private->conf_len = 0;
1044 for (i = 0; i < 8; i++) { 1044 for (i = 0; i < 8; i++) {
1045 kfree(private->path_conf_data[i]); 1045 kfree(device->path[i].conf_data);
1046 private->path_conf_data[i] = NULL; 1046 device->path[i].conf_data = NULL;
1047 } 1047 }
1048} 1048}
1049 1049
@@ -1055,12 +1055,10 @@ static int dasd_eckd_read_conf(struct dasd_device *device)
1055 int rc, path_err, pos; 1055 int rc, path_err, pos;
1056 __u8 lpm, opm; 1056 __u8 lpm, opm;
1057 struct dasd_eckd_private *private, path_private; 1057 struct dasd_eckd_private *private, path_private;
1058 struct dasd_path *path_data;
1059 struct dasd_uid *uid; 1058 struct dasd_uid *uid;
1060 char print_path_uid[60], print_device_uid[60]; 1059 char print_path_uid[60], print_device_uid[60];
1061 1060
1062 private = device->private; 1061 private = device->private;
1063 path_data = &device->path_data;
1064 opm = ccw_device_get_path_mask(device->cdev); 1062 opm = ccw_device_get_path_mask(device->cdev);
1065 conf_data_saved = 0; 1063 conf_data_saved = 0;
1066 path_err = 0; 1064 path_err = 0;
@@ -1081,7 +1079,7 @@ static int dasd_eckd_read_conf(struct dasd_device *device)
1081 "No configuration data " 1079 "No configuration data "
1082 "retrieved"); 1080 "retrieved");
1083 /* no further analysis possible */ 1081 /* no further analysis possible */
1084 path_data->opm |= lpm; 1082 dasd_path_add_opm(device, opm);
1085 continue; /* no error */ 1083 continue; /* no error */
1086 } 1084 }
1087 /* save first valid configuration data */ 1085 /* save first valid configuration data */
@@ -1098,8 +1096,7 @@ static int dasd_eckd_read_conf(struct dasd_device *device)
1098 } 1096 }
1099 pos = pathmask_to_pos(lpm); 1097 pos = pathmask_to_pos(lpm);
1100 /* store per path conf_data */ 1098 /* store per path conf_data */
1101 private->path_conf_data[pos] = 1099 device->path[pos].conf_data = conf_data;
1102 (struct dasd_conf_data *) conf_data;
1103 /* 1100 /*
1104 * build device UID that other path data 1101 * build device UID that other path data
1105 * can be compared to it 1102 * can be compared to it
@@ -1154,37 +1151,29 @@ static int dasd_eckd_read_conf(struct dasd_device *device)
1154 "device %s instead of %s\n", lpm, 1151 "device %s instead of %s\n", lpm,
1155 print_path_uid, print_device_uid); 1152 print_path_uid, print_device_uid);
1156 path_err = -EINVAL; 1153 path_err = -EINVAL;
1157 path_data->cablepm |= lpm; 1154 dasd_path_add_cablepm(device, lpm);
1158 continue; 1155 continue;
1159 } 1156 }
1160 pos = pathmask_to_pos(lpm); 1157 pos = pathmask_to_pos(lpm);
1161 /* store per path conf_data */ 1158 /* store per path conf_data */
1162 private->path_conf_data[pos] = 1159 device->path[pos].conf_data = conf_data;
1163 (struct dasd_conf_data *) conf_data;
1164 path_private.conf_data = NULL; 1160 path_private.conf_data = NULL;
1165 path_private.conf_len = 0; 1161 path_private.conf_len = 0;
1166 } 1162 }
1167 switch (dasd_eckd_path_access(conf_data, conf_len)) { 1163 switch (dasd_eckd_path_access(conf_data, conf_len)) {
1168 case 0x02: 1164 case 0x02:
1169 path_data->npm |= lpm; 1165 dasd_path_add_nppm(device, lpm);
1170 break; 1166 break;
1171 case 0x03: 1167 case 0x03:
1172 path_data->ppm |= lpm; 1168 dasd_path_add_ppm(device, lpm);
1173 break; 1169 break;
1174 } 1170 }
1175 if (!path_data->opm) { 1171 if (!dasd_path_get_opm(device)) {
1176 path_data->opm = lpm; 1172 dasd_path_set_opm(device, lpm);
1177 dasd_generic_path_operational(device); 1173 dasd_generic_path_operational(device);
1178 } else { 1174 } else {
1179 path_data->opm |= lpm; 1175 dasd_path_add_opm(device, lpm);
1180 } 1176 }
1181 /*
1182 * if the path is used
1183 * it should not be in one of the negative lists
1184 */
1185 path_data->cablepm &= ~lpm;
1186 path_data->hpfpm &= ~lpm;
1187 path_data->cuirpm &= ~lpm;
1188 } 1177 }
1189 1178
1190 return path_err; 1179 return path_err;
@@ -1222,8 +1211,7 @@ static int rebuild_device_uid(struct dasd_device *device,
1222 struct path_verification_work_data *data) 1211 struct path_verification_work_data *data)
1223{ 1212{
1224 struct dasd_eckd_private *private = device->private; 1213 struct dasd_eckd_private *private = device->private;
1225 struct dasd_path *path_data = &device->path_data; 1214 __u8 lpm, opm = dasd_path_get_opm(device);
1226 __u8 lpm, opm = path_data->opm;
1227 int rc = -ENODEV; 1215 int rc = -ENODEV;
1228 1216
1229 for (lpm = 0x80; lpm; lpm >>= 1) { 1217 for (lpm = 0x80; lpm; lpm >>= 1) {
@@ -1356,7 +1344,7 @@ static void do_path_verification_work(struct work_struct *work)
1356 * in other case the device UID may have changed and 1344 * in other case the device UID may have changed and
1357 * the first working path UID will be used as device UID 1345 * the first working path UID will be used as device UID
1358 */ 1346 */
1359 if (device->path_data.opm && 1347 if (dasd_path_get_opm(device) &&
1360 dasd_eckd_compare_path_uid(device, &path_private)) { 1348 dasd_eckd_compare_path_uid(device, &path_private)) {
1361 /* 1349 /*
1362 * the comparison was not successful 1350 * the comparison was not successful
@@ -1406,23 +1394,17 @@ static void do_path_verification_work(struct work_struct *work)
1406 * situation in dasd_start_IO. 1394 * situation in dasd_start_IO.
1407 */ 1395 */
1408 spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); 1396 spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
1409 if (!device->path_data.opm && opm) { 1397 if (!dasd_path_get_opm(device) && opm) {
1410 device->path_data.opm = opm; 1398 dasd_path_set_opm(device, opm);
1411 device->path_data.cablepm &= ~opm;
1412 device->path_data.cuirpm &= ~opm;
1413 device->path_data.hpfpm &= ~opm;
1414 dasd_generic_path_operational(device); 1399 dasd_generic_path_operational(device);
1415 } else { 1400 } else {
1416 device->path_data.opm |= opm; 1401 dasd_path_add_opm(device, opm);
1417 device->path_data.cablepm &= ~opm;
1418 device->path_data.cuirpm &= ~opm;
1419 device->path_data.hpfpm &= ~opm;
1420 } 1402 }
1421 device->path_data.npm |= npm; 1403 dasd_path_add_nppm(device, npm);
1422 device->path_data.ppm |= ppm; 1404 dasd_path_add_ppm(device, ppm);
1423 device->path_data.tbvpm |= epm; 1405 dasd_path_add_tbvpm(device, epm);
1424 device->path_data.cablepm |= cablepm; 1406 dasd_path_add_cablepm(device, cablepm);
1425 device->path_data.hpfpm |= hpfpm; 1407 dasd_path_add_nohpfpm(device, hpfpm);
1426 spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); 1408 spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
1427 } 1409 }
1428 clear_bit(DASD_FLAG_PATH_VERIFY, &device->flags); 1410 clear_bit(DASD_FLAG_PATH_VERIFY, &device->flags);
@@ -1839,13 +1821,13 @@ static void dasd_eckd_uncheck_device(struct dasd_device *device)
1839 private->gneq = NULL; 1821 private->gneq = NULL;
1840 private->conf_len = 0; 1822 private->conf_len = 0;
1841 for (i = 0; i < 8; i++) { 1823 for (i = 0; i < 8; i++) {
1842 kfree(private->path_conf_data[i]); 1824 kfree(device->path[i].conf_data);
1843 if ((__u8 *)private->path_conf_data[i] == 1825 if ((__u8 *)device->path[i].conf_data ==
1844 private->conf_data) { 1826 private->conf_data) {
1845 private->conf_data = NULL; 1827 private->conf_data = NULL;
1846 private->conf_len = 0; 1828 private->conf_len = 0;
1847 } 1829 }
1848 private->path_conf_data[i] = NULL; 1830 device->path[i].conf_data = NULL;
1849 } 1831 }
1850 kfree(private->conf_data); 1832 kfree(private->conf_data);
1851 private->conf_data = NULL; 1833 private->conf_data = NULL;
@@ -2966,7 +2948,7 @@ static void dasd_eckd_handle_terminated_request(struct dasd_ccw_req *cqr)
2966 if (cqr->block && (cqr->startdev != cqr->block->base)) { 2948 if (cqr->block && (cqr->startdev != cqr->block->base)) {
2967 dasd_eckd_reset_ccw_to_base_io(cqr); 2949 dasd_eckd_reset_ccw_to_base_io(cqr);
2968 cqr->startdev = cqr->block->base; 2950 cqr->startdev = cqr->block->base;
2969 cqr->lpm = cqr->block->base->path_data.opm; 2951 cqr->lpm = dasd_path_get_opm(cqr->block->base);
2970 } 2952 }
2971}; 2953};
2972 2954
@@ -3251,7 +3233,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_single(
3251 cqr->memdev = startdev; 3233 cqr->memdev = startdev;
3252 cqr->block = block; 3234 cqr->block = block;
3253 cqr->expires = startdev->default_expires * HZ; /* default 5 minutes */ 3235 cqr->expires = startdev->default_expires * HZ; /* default 5 minutes */
3254 cqr->lpm = startdev->path_data.ppm; 3236 cqr->lpm = dasd_path_get_ppm(startdev);
3255 cqr->retries = startdev->default_retries; 3237 cqr->retries = startdev->default_retries;
3256 cqr->buildclk = get_tod_clock(); 3238 cqr->buildclk = get_tod_clock();
3257 cqr->status = DASD_CQR_FILLED; 3239 cqr->status = DASD_CQR_FILLED;
@@ -3426,7 +3408,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_track(
3426 cqr->memdev = startdev; 3408 cqr->memdev = startdev;
3427 cqr->block = block; 3409 cqr->block = block;
3428 cqr->expires = startdev->default_expires * HZ; /* default 5 minutes */ 3410 cqr->expires = startdev->default_expires * HZ; /* default 5 minutes */
3429 cqr->lpm = startdev->path_data.ppm; 3411 cqr->lpm = dasd_path_get_ppm(startdev);
3430 cqr->retries = startdev->default_retries; 3412 cqr->retries = startdev->default_retries;
3431 cqr->buildclk = get_tod_clock(); 3413 cqr->buildclk = get_tod_clock();
3432 cqr->status = DASD_CQR_FILLED; 3414 cqr->status = DASD_CQR_FILLED;
@@ -3735,7 +3717,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track(
3735 cqr->memdev = startdev; 3717 cqr->memdev = startdev;
3736 cqr->block = block; 3718 cqr->block = block;
3737 cqr->expires = startdev->default_expires * HZ; /* default 5 minutes */ 3719 cqr->expires = startdev->default_expires * HZ; /* default 5 minutes */
3738 cqr->lpm = startdev->path_data.ppm; 3720 cqr->lpm = dasd_path_get_ppm(startdev);
3739 cqr->retries = startdev->default_retries; 3721 cqr->retries = startdev->default_retries;
3740 cqr->buildclk = get_tod_clock(); 3722 cqr->buildclk = get_tod_clock();
3741 cqr->status = DASD_CQR_FILLED; 3723 cqr->status = DASD_CQR_FILLED;
@@ -3962,7 +3944,7 @@ static struct dasd_ccw_req *dasd_raw_build_cp(struct dasd_device *startdev,
3962 cqr->memdev = startdev; 3944 cqr->memdev = startdev;
3963 cqr->block = block; 3945 cqr->block = block;
3964 cqr->expires = startdev->default_expires * HZ; 3946 cqr->expires = startdev->default_expires * HZ;
3965 cqr->lpm = startdev->path_data.ppm; 3947 cqr->lpm = dasd_path_get_ppm(startdev);
3966 cqr->retries = startdev->default_retries; 3948 cqr->retries = startdev->default_retries;
3967 cqr->buildclk = get_tod_clock(); 3949 cqr->buildclk = get_tod_clock();
3968 cqr->status = DASD_CQR_FILLED; 3950 cqr->status = DASD_CQR_FILLED;
@@ -5363,20 +5345,19 @@ static struct dasd_conf_data *dasd_eckd_get_ref_conf(struct dasd_device *device,
5363 __u8 lpum, 5345 __u8 lpum,
5364 struct dasd_cuir_message *cuir) 5346 struct dasd_cuir_message *cuir)
5365{ 5347{
5366 struct dasd_eckd_private *private = device->private;
5367 struct dasd_conf_data *conf_data; 5348 struct dasd_conf_data *conf_data;
5368 int path, pos; 5349 int path, pos;
5369 5350
5370 if (cuir->record_selector == 0) 5351 if (cuir->record_selector == 0)
5371 goto out; 5352 goto out;
5372 for (path = 0x80, pos = 0; path; path >>= 1, pos++) { 5353 for (path = 0x80, pos = 0; path; path >>= 1, pos++) {
5373 conf_data = private->path_conf_data[pos]; 5354 conf_data = device->path[pos].conf_data;
5374 if (conf_data->gneq.record_selector == 5355 if (conf_data->gneq.record_selector ==
5375 cuir->record_selector) 5356 cuir->record_selector)
5376 return conf_data; 5357 return conf_data;
5377 } 5358 }
5378out: 5359out:
5379 return private->path_conf_data[pathmask_to_pos(lpum)]; 5360 return device->path[pathmask_to_pos(lpum)].conf_data;
5380} 5361}
5381 5362
5382/* 5363/*
@@ -5391,7 +5372,6 @@ out:
5391static int dasd_eckd_cuir_scope(struct dasd_device *device, __u8 lpum, 5372static int dasd_eckd_cuir_scope(struct dasd_device *device, __u8 lpum,
5392 struct dasd_cuir_message *cuir) 5373 struct dasd_cuir_message *cuir)
5393{ 5374{
5394 struct dasd_eckd_private *private = device->private;
5395 struct dasd_conf_data *ref_conf_data; 5375 struct dasd_conf_data *ref_conf_data;
5396 unsigned long bitmask = 0, mask = 0; 5376 unsigned long bitmask = 0, mask = 0;
5397 struct dasd_conf_data *conf_data; 5377 struct dasd_conf_data *conf_data;
@@ -5417,11 +5397,10 @@ static int dasd_eckd_cuir_scope(struct dasd_device *device, __u8 lpum,
5417 mask |= cuir->neq_map[1] << 8; 5397 mask |= cuir->neq_map[1] << 8;
5418 mask |= cuir->neq_map[0] << 16; 5398 mask |= cuir->neq_map[0] << 16;
5419 5399
5420 for (path = 0x80; path; path >>= 1) { 5400 for (path = 0; path < 8; path++) {
5421 /* initialise data per path */ 5401 /* initialise data per path */
5422 bitmask = mask; 5402 bitmask = mask;
5423 pos = pathmask_to_pos(path); 5403 conf_data = device->path[path].conf_data;
5424 conf_data = private->path_conf_data[pos];
5425 pos = 8 - ffs(cuir->ned_map); 5404 pos = 8 - ffs(cuir->ned_map);
5426 ned = (char *) &conf_data->neds[pos]; 5405 ned = (char *) &conf_data->neds[pos];
5427 /* compare reference ned and per path ned */ 5406 /* compare reference ned and per path ned */
@@ -5442,7 +5421,7 @@ static int dasd_eckd_cuir_scope(struct dasd_device *device, __u8 lpum,
5442 continue; 5421 continue;
5443 /* device and path match the reference values 5422 /* device and path match the reference values
5444 add path to CUIR scope */ 5423 add path to CUIR scope */
5445 tbcpm |= path; 5424 tbcpm |= 0x80 >> path;
5446 } 5425 }
5447 return tbcpm; 5426 return tbcpm;
5448} 5427}
@@ -5479,16 +5458,16 @@ static int dasd_eckd_cuir_remove_path(struct dasd_device *device, __u8 lpum,
5479 5458
5480 tbcpm = dasd_eckd_cuir_scope(device, lpum, cuir); 5459 tbcpm = dasd_eckd_cuir_scope(device, lpum, cuir);
5481 /* nothing to do if path is not in use */ 5460 /* nothing to do if path is not in use */
5482 if (!(device->path_data.opm & tbcpm)) 5461 if (!(dasd_path_get_opm(device) & tbcpm))
5483 return 0; 5462 return 0;
5484 if (!(device->path_data.opm & ~tbcpm)) { 5463 if (!(dasd_path_get_opm(device) & ~tbcpm)) {
5485 /* no path would be left if the CUIR action is taken 5464 /* no path would be left if the CUIR action is taken
5486 return error */ 5465 return error */
5487 return -EINVAL; 5466 return -EINVAL;
5488 } 5467 }
5489 /* remove device from operational path mask */ 5468 /* remove device from operational path mask */
5490 device->path_data.opm &= ~tbcpm; 5469 dasd_path_remove_opm(device, tbcpm);
5491 device->path_data.cuirpm |= tbcpm; 5470 dasd_path_add_cuirpm(device, tbcpm);
5492 return tbcpm; 5471 return tbcpm;
5493} 5472}
5494 5473
@@ -5581,8 +5560,8 @@ static int dasd_eckd_cuir_resume(struct dasd_device *device, __u8 lpum,
5581 alias_list) { 5560 alias_list) {
5582 tbcpm = dasd_eckd_cuir_scope(dev, lpum, cuir); 5561 tbcpm = dasd_eckd_cuir_scope(dev, lpum, cuir);
5583 paths |= tbcpm; 5562 paths |= tbcpm;
5584 if (!(dev->path_data.opm & tbcpm)) { 5563 if (!(dasd_path_get_opm(dev) & tbcpm)) {
5585 dev->path_data.tbvpm |= tbcpm; 5564 dasd_path_add_tbvpm(dev, tbcpm);
5586 dasd_schedule_device_bh(dev); 5565 dasd_schedule_device_bh(dev);
5587 } 5566 }
5588 } 5567 }
@@ -5591,8 +5570,8 @@ static int dasd_eckd_cuir_resume(struct dasd_device *device, __u8 lpum,
5591 alias_list) { 5570 alias_list) {
5592 tbcpm = dasd_eckd_cuir_scope(dev, lpum, cuir); 5571 tbcpm = dasd_eckd_cuir_scope(dev, lpum, cuir);
5593 paths |= tbcpm; 5572 paths |= tbcpm;
5594 if (!(dev->path_data.opm & tbcpm)) { 5573 if (!(dasd_path_get_opm(dev) & tbcpm)) {
5595 dev->path_data.tbvpm |= tbcpm; 5574 dasd_path_add_tbvpm(dev, tbcpm);
5596 dasd_schedule_device_bh(dev); 5575 dasd_schedule_device_bh(dev);
5597 } 5576 }
5598 } 5577 }
@@ -5605,8 +5584,8 @@ static int dasd_eckd_cuir_resume(struct dasd_device *device, __u8 lpum,
5605 alias_list) { 5584 alias_list) {
5606 tbcpm = dasd_eckd_cuir_scope(dev, lpum, cuir); 5585 tbcpm = dasd_eckd_cuir_scope(dev, lpum, cuir);
5607 paths |= tbcpm; 5586 paths |= tbcpm;
5608 if (!(dev->path_data.opm & tbcpm)) { 5587 if (!(dasd_path_get_opm(dev) & tbcpm)) {
5609 dev->path_data.tbvpm |= tbcpm; 5588 dasd_path_add_tbvpm(dev, tbcpm);
5610 dasd_schedule_device_bh(dev); 5589 dasd_schedule_device_bh(dev);
5611 } 5590 }
5612 } 5591 }
@@ -5615,8 +5594,8 @@ static int dasd_eckd_cuir_resume(struct dasd_device *device, __u8 lpum,
5615 alias_list) { 5594 alias_list) {
5616 tbcpm = dasd_eckd_cuir_scope(dev, lpum, cuir); 5595 tbcpm = dasd_eckd_cuir_scope(dev, lpum, cuir);
5617 paths |= tbcpm; 5596 paths |= tbcpm;
5618 if (!(dev->path_data.opm & tbcpm)) { 5597 if (!(dasd_path_get_opm(dev) & tbcpm)) {
5619 dev->path_data.tbvpm |= tbcpm; 5598 dasd_path_add_tbvpm(dev, tbcpm);
5620 dasd_schedule_device_bh(dev); 5599 dasd_schedule_device_bh(dev);
5621 } 5600 }
5622 } 5601 }
diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h
index 59803626ea36..e491f4416e40 100644
--- a/drivers/s390/block/dasd_eckd.h
+++ b/drivers/s390/block/dasd_eckd.h
@@ -535,8 +535,7 @@ struct dasd_eckd_private {
535 struct dasd_eckd_characteristics rdc_data; 535 struct dasd_eckd_characteristics rdc_data;
536 u8 *conf_data; 536 u8 *conf_data;
537 int conf_len; 537 int conf_len;
538 /* per path configuration data */ 538
539 struct dasd_conf_data *path_conf_data[8];
540 /* pointers to specific parts in the conf_data */ 539 /* pointers to specific parts in the conf_data */
541 struct dasd_ned *ned; 540 struct dasd_ned *ned;
542 struct dasd_sneq *sneq; 541 struct dasd_sneq *sneq;
diff --git a/drivers/s390/block/dasd_erp.c b/drivers/s390/block/dasd_erp.c
index d138d0116734..113c1c1fa1af 100644
--- a/drivers/s390/block/dasd_erp.c
+++ b/drivers/s390/block/dasd_erp.c
@@ -96,7 +96,7 @@ dasd_default_erp_action(struct dasd_ccw_req *cqr)
96 "default ERP called (%i retries left)", 96 "default ERP called (%i retries left)",
97 cqr->retries); 97 cqr->retries);
98 if (!test_bit(DASD_CQR_VERIFY_PATH, &cqr->flags)) 98 if (!test_bit(DASD_CQR_VERIFY_PATH, &cqr->flags))
99 cqr->lpm = device->path_data.opm; 99 cqr->lpm = dasd_path_get_opm(device);
100 cqr->status = DASD_CQR_FILLED; 100 cqr->status = DASD_CQR_FILLED;
101 } else { 101 } else {
102 pr_err("%s: default ERP has run out of retries and failed\n", 102 pr_err("%s: default ERP has run out of retries and failed\n",
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c
index d7b5b550364b..462cab5d4302 100644
--- a/drivers/s390/block/dasd_fba.c
+++ b/drivers/s390/block/dasd_fba.c
@@ -168,7 +168,7 @@ dasd_fba_check_characteristics(struct dasd_device *device)
168 168
169 device->default_expires = DASD_EXPIRES; 169 device->default_expires = DASD_EXPIRES;
170 device->default_retries = FBA_DEFAULT_RETRIES; 170 device->default_retries = FBA_DEFAULT_RETRIES;
171 device->path_data.opm = LPM_ANYPATH; 171 dasd_path_set_opm(device, LPM_ANYPATH);
172 172
173 readonly = dasd_device_is_ro(device); 173 readonly = dasd_device_is_ro(device);
174 if (readonly) 174 if (readonly)
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index 87ff6cef872f..d75f996884d9 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -55,6 +55,7 @@
55#include <asm/debug.h> 55#include <asm/debug.h>
56#include <asm/dasd.h> 56#include <asm/dasd.h>
57#include <asm/idals.h> 57#include <asm/idals.h>
58#include <linux/bitops.h>
58 59
59/* DASD discipline magic */ 60/* DASD discipline magic */
60#define DASD_ECKD_MAGIC 0xC5C3D2C4 61#define DASD_ECKD_MAGIC 0xC5C3D2C4
@@ -397,17 +398,23 @@ extern struct dasd_discipline *dasd_diag_discipline_pointer;
397#define DASD_EER_STATECHANGE 3 398#define DASD_EER_STATECHANGE 3
398#define DASD_EER_PPRCSUSPEND 4 399#define DASD_EER_PPRCSUSPEND 4
399 400
401/* DASD path handling */
402
403#define DASD_PATH_OPERATIONAL 1
404#define DASD_PATH_TBV 2
405#define DASD_PATH_PP 3
406#define DASD_PATH_NPP 4
407#define DASD_PATH_MISCABLED 5
408#define DASD_PATH_NOHPF 6
409#define DASD_PATH_CUIR 7
410
411
400struct dasd_path { 412struct dasd_path {
401 __u8 opm; 413 unsigned long flags;
402 __u8 tbvpm; 414 struct dasd_conf_data *conf_data;
403 __u8 ppm;
404 __u8 npm;
405 /* paths that are not used because of a special condition */
406 __u8 cablepm; /* miss-cabled */
407 __u8 hpfpm; /* the HPF requirements of the other paths are not met */
408 __u8 cuirpm; /* CUIR varied offline */
409}; 415};
410 416
417
411struct dasd_profile_info { 418struct dasd_profile_info {
412 /* legacy part of profile data, as in dasd_profile_info_t */ 419 /* legacy part of profile data, as in dasd_profile_info_t */
413 unsigned int dasd_io_reqs; /* number of requests processed */ 420 unsigned int dasd_io_reqs; /* number of requests processed */
@@ -458,7 +465,8 @@ struct dasd_device {
458 struct dasd_discipline *discipline; 465 struct dasd_discipline *discipline;
459 struct dasd_discipline *base_discipline; 466 struct dasd_discipline *base_discipline;
460 void *private; 467 void *private;
461 struct dasd_path path_data; 468 struct dasd_path path[8];
469 __u8 opm;
462 470
463 /* Device state and target state. */ 471 /* Device state and target state. */
464 int state, target; 472 int state, target;
@@ -835,4 +843,359 @@ static inline int dasd_eer_enabled(struct dasd_device *device)
835#define dasd_eer_enabled(d) (0) 843#define dasd_eer_enabled(d) (0)
836#endif /* CONFIG_DASD_ERR */ 844#endif /* CONFIG_DASD_ERR */
837 845
846
847/* DASD path handling functions */
848
849/*
850 * helper functions to modify bit masks for a given channel path for a device
851 */
852static inline int dasd_path_is_operational(struct dasd_device *device, int chp)
853{
854 return test_bit(DASD_PATH_OPERATIONAL, &device->path[chp].flags);
855}
856
857static inline int dasd_path_need_verify(struct dasd_device *device, int chp)
858{
859 return test_bit(DASD_PATH_TBV, &device->path[chp].flags);
860}
861
862static inline void dasd_path_verify(struct dasd_device *device, int chp)
863{
864 __set_bit(DASD_PATH_TBV, &device->path[chp].flags);
865}
866
867static inline void dasd_path_clear_verify(struct dasd_device *device, int chp)
868{
869 __clear_bit(DASD_PATH_TBV, &device->path[chp].flags);
870}
871
872static inline void dasd_path_clear_all_verify(struct dasd_device *device)
873{
874 int chp;
875
876 for (chp = 0; chp < 8; chp++)
877 dasd_path_clear_verify(device, chp);
878}
879
880static inline void dasd_path_operational(struct dasd_device *device, int chp)
881{
882 __set_bit(DASD_PATH_OPERATIONAL, &device->path[chp].flags);
883 device->opm |= (0x80 >> chp);
884}
885
886static inline void dasd_path_nonpreferred(struct dasd_device *device, int chp)
887{
888 __set_bit(DASD_PATH_NPP, &device->path[chp].flags);
889}
890
891static inline int dasd_path_is_nonpreferred(struct dasd_device *device, int chp)
892{
893 return test_bit(DASD_PATH_NPP, &device->path[chp].flags);
894}
895
896static inline void dasd_path_clear_nonpreferred(struct dasd_device *device,
897 int chp)
898{
899 __clear_bit(DASD_PATH_NPP, &device->path[chp].flags);
900}
901
902static inline void dasd_path_preferred(struct dasd_device *device, int chp)
903{
904 __set_bit(DASD_PATH_PP, &device->path[chp].flags);
905}
906
907static inline int dasd_path_is_preferred(struct dasd_device *device, int chp)
908{
909 return test_bit(DASD_PATH_PP, &device->path[chp].flags);
910}
911
912static inline void dasd_path_clear_preferred(struct dasd_device *device,
913 int chp)
914{
915 __clear_bit(DASD_PATH_PP, &device->path[chp].flags);
916}
917
918static inline void dasd_path_clear_oper(struct dasd_device *device, int chp)
919{
920 __clear_bit(DASD_PATH_OPERATIONAL, &device->path[chp].flags);
921 device->opm &= ~(0x80 >> chp);
922}
923
924static inline void dasd_path_clear_cable(struct dasd_device *device, int chp)
925{
926 __clear_bit(DASD_PATH_MISCABLED, &device->path[chp].flags);
927}
928
929static inline void dasd_path_cuir(struct dasd_device *device, int chp)
930{
931 __set_bit(DASD_PATH_CUIR, &device->path[chp].flags);
932}
933
934static inline int dasd_path_is_cuir(struct dasd_device *device, int chp)
935{
936 return test_bit(DASD_PATH_CUIR, &device->path[chp].flags);
937}
938
939static inline void dasd_path_clear_cuir(struct dasd_device *device, int chp)
940{
941 __clear_bit(DASD_PATH_CUIR, &device->path[chp].flags);
942}
943
944static inline void dasd_path_clear_nohpf(struct dasd_device *device, int chp)
945{
946 __clear_bit(DASD_PATH_NOHPF, &device->path[chp].flags);
947}
948
949static inline void dasd_path_miscabled(struct dasd_device *device, int chp)
950{
951 __set_bit(DASD_PATH_MISCABLED, &device->path[chp].flags);
952}
953
954static inline int dasd_path_is_miscabled(struct dasd_device *device, int chp)
955{
956 return test_bit(DASD_PATH_MISCABLED, &device->path[chp].flags);
957}
958
959static inline void dasd_path_nohpf(struct dasd_device *device, int chp)
960{
961 __set_bit(DASD_PATH_NOHPF, &device->path[chp].flags);
962}
963
964static inline int dasd_path_is_nohpf(struct dasd_device *device, int chp)
965{
966 return test_bit(DASD_PATH_NOHPF, &device->path[chp].flags);
967}
968
969/*
970 * get functions for path masks
971 * will return a path masks for the given device
972 */
973
974static inline __u8 dasd_path_get_opm(struct dasd_device *device)
975{
976 return device->opm;
977}
978
979static inline __u8 dasd_path_get_tbvpm(struct dasd_device *device)
980{
981 int chp;
982 __u8 tbvpm = 0x00;
983
984 for (chp = 0; chp < 8; chp++)
985 if (dasd_path_need_verify(device, chp))
986 tbvpm |= 0x80 >> chp;
987 return tbvpm;
988}
989
990static inline __u8 dasd_path_get_nppm(struct dasd_device *device)
991{
992 int chp;
993 __u8 npm = 0x00;
994
995 for (chp = 0; chp < 8; chp++) {
996 if (dasd_path_is_nonpreferred(device, chp))
997 npm |= 0x80 >> chp;
998 }
999 return npm;
1000}
1001
1002static inline __u8 dasd_path_get_ppm(struct dasd_device *device)
1003{
1004 int chp;
1005 __u8 ppm = 0x00;
1006
1007 for (chp = 0; chp < 8; chp++)
1008 if (dasd_path_is_preferred(device, chp))
1009 ppm |= 0x80 >> chp;
1010 return ppm;
1011}
1012
1013static inline __u8 dasd_path_get_cablepm(struct dasd_device *device)
1014{
1015 int chp;
1016 __u8 cablepm = 0x00;
1017
1018 for (chp = 0; chp < 8; chp++)
1019 if (dasd_path_is_miscabled(device, chp))
1020 cablepm |= 0x80 >> chp;
1021 return cablepm;
1022}
1023
1024static inline __u8 dasd_path_get_cuirpm(struct dasd_device *device)
1025{
1026 int chp;
1027 __u8 cuirpm = 0x00;
1028
1029 for (chp = 0; chp < 8; chp++)
1030 if (dasd_path_is_cuir(device, chp))
1031 cuirpm |= 0x80 >> chp;
1032 return cuirpm;
1033}
1034
1035static inline __u8 dasd_path_get_hpfpm(struct dasd_device *device)
1036{
1037 int chp;
1038 __u8 hpfpm = 0x00;
1039
1040 for (chp = 0; chp < 8; chp++)
1041 if (dasd_path_is_nohpf(device, chp))
1042 hpfpm |= 0x80 >> chp;
1043 return hpfpm;
1044}
1045
1046/*
1047 * add functions for path masks
1048 * the existing path mask will be extended by the given path mask
1049 */
1050static inline void dasd_path_add_tbvpm(struct dasd_device *device, __u8 pm)
1051{
1052 int chp;
1053
1054 for (chp = 0; chp < 8; chp++)
1055 if (pm & (0x80 >> chp))
1056 dasd_path_verify(device, chp);
1057}
1058
1059static inline void dasd_path_add_opm(struct dasd_device *device, __u8 pm)
1060{
1061 int chp;
1062
1063 for (chp = 0; chp < 8; chp++)
1064 if (pm & (0x80 >> chp)) {
1065 dasd_path_operational(device, chp);
1066 /*
1067 * if the path is used
1068 * it should not be in one of the negative lists
1069 */
1070 dasd_path_clear_nohpf(device, chp);
1071 dasd_path_clear_cuir(device, chp);
1072 dasd_path_clear_cable(device, chp);
1073 }
1074}
1075
1076static inline void dasd_path_add_cablepm(struct dasd_device *device, __u8 pm)
1077{
1078 int chp;
1079
1080 for (chp = 0; chp < 8; chp++)
1081 if (pm & (0x80 >> chp))
1082 dasd_path_miscabled(device, chp);
1083}
1084
1085static inline void dasd_path_add_cuirpm(struct dasd_device *device, __u8 pm)
1086{
1087 int chp;
1088
1089 for (chp = 0; chp < 8; chp++)
1090 if (pm & (0x80 >> chp))
1091 dasd_path_cuir(device, chp);
1092}
1093
1094static inline void dasd_path_add_nppm(struct dasd_device *device, __u8 pm)
1095{
1096 int chp;
1097
1098 for (chp = 0; chp < 8; chp++)
1099 if (pm & (0x80 >> chp))
1100 dasd_path_nonpreferred(device, chp);
1101}
1102
1103static inline void dasd_path_add_nohpfpm(struct dasd_device *device, __u8 pm)
1104{
1105 int chp;
1106
1107 for (chp = 0; chp < 8; chp++)
1108 if (pm & (0x80 >> chp))
1109 dasd_path_nohpf(device, chp);
1110}
1111
1112static inline void dasd_path_add_ppm(struct dasd_device *device, __u8 pm)
1113{
1114 int chp;
1115
1116 for (chp = 0; chp < 8; chp++)
1117 if (pm & (0x80 >> chp))
1118 dasd_path_preferred(device, chp);
1119}
1120
1121/*
1122 * set functions for path masks
1123 * the existing path mask will be replaced by the given path mask
1124 */
1125static inline void dasd_path_set_tbvpm(struct dasd_device *device, __u8 pm)
1126{
1127 int chp;
1128
1129 for (chp = 0; chp < 8; chp++)
1130 if (pm & (0x80 >> chp))
1131 dasd_path_verify(device, chp);
1132 else
1133 dasd_path_clear_verify(device, chp);
1134}
1135
1136static inline void dasd_path_set_opm(struct dasd_device *device, __u8 pm)
1137{
1138 int chp;
1139
1140 for (chp = 0; chp < 8; chp++) {
1141 dasd_path_clear_oper(device, chp);
1142 if (pm & (0x80 >> chp)) {
1143 dasd_path_operational(device, chp);
1144 /*
1145 * if the path is used
1146 * it should not be in one of the negative lists
1147 */
1148 dasd_path_clear_nohpf(device, chp);
1149 dasd_path_clear_cuir(device, chp);
1150 dasd_path_clear_cable(device, chp);
1151 }
1152 }
1153}
1154
1155/*
1156 * remove functions for path masks
1157 * the existing path mask will be cleared with the given path mask
1158 */
1159static inline void dasd_path_remove_opm(struct dasd_device *device, __u8 pm)
1160{
1161 int chp;
1162
1163 for (chp = 0; chp < 8; chp++) {
1164 if (pm & (0x80 >> chp))
1165 dasd_path_clear_oper(device, chp);
1166 }
1167}
1168
1169/*
1170 * add the newly available path to the to be verified pm and remove it from
1171 * normal operation until it is verified
1172 */
1173static inline void dasd_path_available(struct dasd_device *device, int chp)
1174{
1175 dasd_path_clear_oper(device, chp);
1176 dasd_path_verify(device, chp);
1177}
1178
1179static inline void dasd_path_notoper(struct dasd_device *device, int chp)
1180{
1181 dasd_path_clear_oper(device, chp);
1182 dasd_path_clear_preferred(device, chp);
1183 dasd_path_clear_nonpreferred(device, chp);
1184}
1185
1186/*
1187 * remove all paths from normal operation
1188 */
1189static inline void dasd_path_no_path(struct dasd_device *device)
1190{
1191 int chp;
1192
1193 for (chp = 0; chp < 8; chp++)
1194 dasd_path_notoper(device, chp);
1195
1196 dasd_path_clear_all_verify(device);
1197}
1198
1199/* end - path handling */
1200
838#endif /* DASD_H */ 1201#endif /* DASD_H */