diff options
| author | Stefan Haberland <stefan.haberland@de.ibm.com> | 2012-01-18 12:03:40 -0500 |
|---|---|---|
| committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2012-01-18 12:03:42 -0500 |
| commit | f9f8d02fae0dc47d8868fd069bb88d12f8d1d71f (patch) | |
| tree | fa37c08bfe9d581382642286122cfbaa12ca00bd | |
| parent | e0a15d5bf4e2fc46a867c43c41b6a41622f673ad (diff) | |
[S390] dasd: revert LCU optimization
Remove the optimization that validate server is only called once per
LCU. If a device is set online we only know that we already know the
LCU. But if the pathgroup was lost in between we have to do a
validate server again to activate some features.
Since we have no indication when a pathgroup gets lost we have to do
a validate server every time a device is set online.
Signed-off-by: Stefan Haberland <stefan.haberland@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
| -rw-r--r-- | drivers/s390/block/dasd_alias.c | 64 | ||||
| -rw-r--r-- | drivers/s390/block/dasd_eckd.c | 41 |
2 files changed, 16 insertions, 89 deletions
diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c index 553b3c5abb0a..b3beed5434e4 100644 --- a/drivers/s390/block/dasd_alias.c +++ b/drivers/s390/block/dasd_alias.c | |||
| @@ -189,14 +189,12 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device) | |||
| 189 | unsigned long flags; | 189 | unsigned long flags; |
| 190 | struct alias_server *server, *newserver; | 190 | struct alias_server *server, *newserver; |
| 191 | struct alias_lcu *lcu, *newlcu; | 191 | struct alias_lcu *lcu, *newlcu; |
| 192 | int is_lcu_known; | ||
| 193 | struct dasd_uid uid; | 192 | struct dasd_uid uid; |
| 194 | 193 | ||
| 195 | private = (struct dasd_eckd_private *) device->private; | 194 | private = (struct dasd_eckd_private *) device->private; |
| 196 | 195 | ||
| 197 | device->discipline->get_uid(device, &uid); | 196 | device->discipline->get_uid(device, &uid); |
| 198 | spin_lock_irqsave(&aliastree.lock, flags); | 197 | spin_lock_irqsave(&aliastree.lock, flags); |
| 199 | is_lcu_known = 1; | ||
| 200 | server = _find_server(&uid); | 198 | server = _find_server(&uid); |
| 201 | if (!server) { | 199 | if (!server) { |
| 202 | spin_unlock_irqrestore(&aliastree.lock, flags); | 200 | spin_unlock_irqrestore(&aliastree.lock, flags); |
| @@ -208,7 +206,6 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device) | |||
| 208 | if (!server) { | 206 | if (!server) { |
| 209 | list_add(&newserver->server, &aliastree.serverlist); | 207 | list_add(&newserver->server, &aliastree.serverlist); |
| 210 | server = newserver; | 208 | server = newserver; |
| 211 | is_lcu_known = 0; | ||
| 212 | } else { | 209 | } else { |
| 213 | /* someone was faster */ | 210 | /* someone was faster */ |
| 214 | _free_server(newserver); | 211 | _free_server(newserver); |
| @@ -226,12 +223,10 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device) | |||
| 226 | if (!lcu) { | 223 | if (!lcu) { |
| 227 | list_add(&newlcu->lcu, &server->lculist); | 224 | list_add(&newlcu->lcu, &server->lculist); |
| 228 | lcu = newlcu; | 225 | lcu = newlcu; |
| 229 | is_lcu_known = 0; | ||
| 230 | } else { | 226 | } else { |
| 231 | /* someone was faster */ | 227 | /* someone was faster */ |
| 232 | _free_lcu(newlcu); | 228 | _free_lcu(newlcu); |
| 233 | } | 229 | } |
| 234 | is_lcu_known = 0; | ||
| 235 | } | 230 | } |
| 236 | spin_lock(&lcu->lock); | 231 | spin_lock(&lcu->lock); |
| 237 | list_add(&device->alias_list, &lcu->inactive_devices); | 232 | list_add(&device->alias_list, &lcu->inactive_devices); |
| @@ -239,64 +234,7 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device) | |||
| 239 | spin_unlock(&lcu->lock); | 234 | spin_unlock(&lcu->lock); |
| 240 | spin_unlock_irqrestore(&aliastree.lock, flags); | 235 | spin_unlock_irqrestore(&aliastree.lock, flags); |
| 241 | 236 | ||
| 242 | return is_lcu_known; | 237 | return 0; |
| 243 | } | ||
| 244 | |||
| 245 | /* | ||
| 246 | * The first device to be registered on an LCU will have to do | ||
| 247 | * some additional setup steps to configure that LCU on the | ||
| 248 | * storage server. All further devices should wait with their | ||
| 249 | * initialization until the first device is done. | ||
| 250 | * To synchronize this work, the first device will call | ||
| 251 | * dasd_alias_lcu_setup_complete when it is done, and all | ||
| 252 | * other devices will wait for it with dasd_alias_wait_for_lcu_setup. | ||
| 253 | */ | ||
| 254 | void dasd_alias_lcu_setup_complete(struct dasd_device *device) | ||
| 255 | { | ||
| 256 | unsigned long flags; | ||
| 257 | struct alias_server *server; | ||
| 258 | struct alias_lcu *lcu; | ||
| 259 | struct dasd_uid uid; | ||
| 260 | |||
| 261 | device->discipline->get_uid(device, &uid); | ||
| 262 | lcu = NULL; | ||
| 263 | spin_lock_irqsave(&aliastree.lock, flags); | ||
| 264 | server = _find_server(&uid); | ||
| 265 | if (server) | ||
| 266 | lcu = _find_lcu(server, &uid); | ||
| 267 | spin_unlock_irqrestore(&aliastree.lock, flags); | ||
| 268 | if (!lcu) { | ||
| 269 | DBF_EVENT_DEVID(DBF_ERR, device->cdev, | ||
| 270 | "could not find lcu for %04x %02x", | ||
| 271 | uid.ssid, uid.real_unit_addr); | ||
| 272 | WARN_ON(1); | ||
| 273 | return; | ||
| 274 | } | ||
| 275 | complete_all(&lcu->lcu_setup); | ||
| 276 | } | ||
| 277 | |||
| 278 | void dasd_alias_wait_for_lcu_setup(struct dasd_device *device) | ||
| 279 | { | ||
| 280 | unsigned long flags; | ||
| 281 | struct alias_server *server; | ||
| 282 | struct alias_lcu *lcu; | ||
| 283 | struct dasd_uid uid; | ||
| 284 | |||
| 285 | device->discipline->get_uid(device, &uid); | ||
| 286 | lcu = NULL; | ||
| 287 | spin_lock_irqsave(&aliastree.lock, flags); | ||
| 288 | server = _find_server(&uid); | ||
| 289 | if (server) | ||
| 290 | lcu = _find_lcu(server, &uid); | ||
| 291 | spin_unlock_irqrestore(&aliastree.lock, flags); | ||
| 292 | if (!lcu) { | ||
| 293 | DBF_EVENT_DEVID(DBF_ERR, device->cdev, | ||
| 294 | "could not find lcu for %04x %02x", | ||
| 295 | uid.ssid, uid.real_unit_addr); | ||
| 296 | WARN_ON(1); | ||
| 297 | return; | ||
| 298 | } | ||
| 299 | wait_for_completion(&lcu->lcu_setup); | ||
| 300 | } | 238 | } |
| 301 | 239 | ||
| 302 | /* | 240 | /* |
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index bbcd5e9206ee..1b6e7ea9347f 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
| @@ -1534,6 +1534,10 @@ static void dasd_eckd_validate_server(struct dasd_device *device) | |||
| 1534 | struct dasd_eckd_private *private; | 1534 | struct dasd_eckd_private *private; |
| 1535 | int enable_pav; | 1535 | int enable_pav; |
| 1536 | 1536 | ||
| 1537 | private = (struct dasd_eckd_private *) device->private; | ||
| 1538 | if (private->uid.type == UA_BASE_PAV_ALIAS || | ||
| 1539 | private->uid.type == UA_HYPER_PAV_ALIAS) | ||
| 1540 | return; | ||
| 1537 | if (dasd_nopav || MACHINE_IS_VM) | 1541 | if (dasd_nopav || MACHINE_IS_VM) |
| 1538 | enable_pav = 0; | 1542 | enable_pav = 0; |
| 1539 | else | 1543 | else |
| @@ -1542,7 +1546,6 @@ static void dasd_eckd_validate_server(struct dasd_device *device) | |||
| 1542 | 1546 | ||
| 1543 | /* may be requested feature is not available on server, | 1547 | /* may be requested feature is not available on server, |
| 1544 | * therefore just report error and go ahead */ | 1548 | * therefore just report error and go ahead */ |
| 1545 | private = (struct dasd_eckd_private *) device->private; | ||
| 1546 | DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "PSF-SSC for SSID %04x " | 1549 | DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "PSF-SSC for SSID %04x " |
| 1547 | "returned rc=%d", private->uid.ssid, rc); | 1550 | "returned rc=%d", private->uid.ssid, rc); |
| 1548 | } | 1551 | } |
| @@ -1588,7 +1591,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device) | |||
| 1588 | struct dasd_eckd_private *private; | 1591 | struct dasd_eckd_private *private; |
| 1589 | struct dasd_block *block; | 1592 | struct dasd_block *block; |
| 1590 | struct dasd_uid temp_uid; | 1593 | struct dasd_uid temp_uid; |
| 1591 | int is_known, rc, i; | 1594 | int rc, i; |
| 1592 | int readonly; | 1595 | int readonly; |
| 1593 | unsigned long value; | 1596 | unsigned long value; |
| 1594 | 1597 | ||
| @@ -1651,22 +1654,12 @@ dasd_eckd_check_characteristics(struct dasd_device *device) | |||
| 1651 | block->base = device; | 1654 | block->base = device; |
| 1652 | } | 1655 | } |
| 1653 | 1656 | ||
| 1654 | /* register lcu with alias handling, enable PAV if this is a new lcu */ | 1657 | /* register lcu with alias handling, enable PAV */ |
| 1655 | is_known = dasd_alias_make_device_known_to_lcu(device); | 1658 | rc = dasd_alias_make_device_known_to_lcu(device); |
| 1656 | if (is_known < 0) { | 1659 | if (rc) |
| 1657 | rc = is_known; | ||
| 1658 | goto out_err2; | 1660 | goto out_err2; |
| 1659 | } | 1661 | |
| 1660 | /* | 1662 | dasd_eckd_validate_server(device); |
| 1661 | * dasd_eckd_validate_server is done on the first device that | ||
| 1662 | * is found for an LCU. All later other devices have to wait | ||
| 1663 | * for it, so they will read the correct feature codes. | ||
| 1664 | */ | ||
| 1665 | if (!is_known) { | ||
| 1666 | dasd_eckd_validate_server(device); | ||
| 1667 | dasd_alias_lcu_setup_complete(device); | ||
| 1668 | } else | ||
| 1669 | dasd_alias_wait_for_lcu_setup(device); | ||
| 1670 | 1663 | ||
| 1671 | /* device may report different configuration data after LCU setup */ | 1664 | /* device may report different configuration data after LCU setup */ |
| 1672 | rc = dasd_eckd_read_conf(device); | 1665 | rc = dasd_eckd_read_conf(device); |
| @@ -4098,7 +4091,7 @@ static int dasd_eckd_restore_device(struct dasd_device *device) | |||
| 4098 | { | 4091 | { |
| 4099 | struct dasd_eckd_private *private; | 4092 | struct dasd_eckd_private *private; |
| 4100 | struct dasd_eckd_characteristics temp_rdc_data; | 4093 | struct dasd_eckd_characteristics temp_rdc_data; |
| 4101 | int is_known, rc; | 4094 | int rc; |
| 4102 | struct dasd_uid temp_uid; | 4095 | struct dasd_uid temp_uid; |
| 4103 | unsigned long flags; | 4096 | unsigned long flags; |
| 4104 | 4097 | ||
| @@ -4121,14 +4114,10 @@ static int dasd_eckd_restore_device(struct dasd_device *device) | |||
| 4121 | goto out_err; | 4114 | goto out_err; |
| 4122 | 4115 | ||
| 4123 | /* register lcu with alias handling, enable PAV if this is a new lcu */ | 4116 | /* register lcu with alias handling, enable PAV if this is a new lcu */ |
| 4124 | is_known = dasd_alias_make_device_known_to_lcu(device); | 4117 | rc = dasd_alias_make_device_known_to_lcu(device); |
| 4125 | if (is_known < 0) | 4118 | if (rc) |
| 4126 | return is_known; | 4119 | return rc; |
| 4127 | if (!is_known) { | 4120 | dasd_eckd_validate_server(device); |
| 4128 | dasd_eckd_validate_server(device); | ||
| 4129 | dasd_alias_lcu_setup_complete(device); | ||
| 4130 | } else | ||
| 4131 | dasd_alias_wait_for_lcu_setup(device); | ||
| 4132 | 4121 | ||
| 4133 | /* RE-Read Configuration Data */ | 4122 | /* RE-Read Configuration Data */ |
| 4134 | rc = dasd_eckd_read_conf(device); | 4123 | rc = dasd_eckd_read_conf(device); |
