aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Haberland <stefan.haberland@de.ibm.com>2012-01-18 12:03:40 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2012-01-18 12:03:42 -0500
commitf9f8d02fae0dc47d8868fd069bb88d12f8d1d71f (patch)
treefa37c08bfe9d581382642286122cfbaa12ca00bd
parente0a15d5bf4e2fc46a867c43c41b6a41622f673ad (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.c64
-rw-r--r--drivers/s390/block/dasd_eckd.c41
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 */
254void 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
278void 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);