Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Stefan Haberland and committed by
Martin Schwidefsky
c9346151 7df11604

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