Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 173264
b: refs/heads/master
c: f4ac1d0
h: refs/heads/master
v: v3
  • Loading branch information
Stefan Weinhuber authored and Martin Schwidefsky committed Dec 7, 2009
1 parent e0ad1c7 commit 2b88e70
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 15 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: b8ed5dd54895647c2690575aad6f07748c2c618a
refs/heads/master: f4ac1d0255748fe0f8e128a26b1c29490cae5c08
62 changes: 62 additions & 0 deletions trunk/drivers/s390/block/dasd_alias.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ static struct alias_lcu *_allocate_lcu(struct dasd_uid *uid)
INIT_WORK(&lcu->suc_data.worker, summary_unit_check_handling_work);
INIT_DELAYED_WORK(&lcu->ruac_data.dwork, lcu_update_work);
spin_lock_init(&lcu->lock);
init_completion(&lcu->lcu_setup);
return lcu;

out_err4:
Expand Down Expand Up @@ -239,6 +240,67 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device)
return is_lcu_known;
}

/*
* The first device to be registered on an LCU will have to do
* some additional setup steps to configure that LCU on the
* storage server. All further devices should wait with their
* initialization until the first device is done.
* To synchronize this work, the first device will call
* dasd_alias_lcu_setup_complete when it is done, and all
* other devices will wait for it with dasd_alias_wait_for_lcu_setup.
*/
void dasd_alias_lcu_setup_complete(struct dasd_device *device)
{
struct dasd_eckd_private *private;
unsigned long flags;
struct alias_server *server;
struct alias_lcu *lcu;
struct dasd_uid *uid;

private = (struct dasd_eckd_private *) device->private;
uid = &private->uid;
lcu = NULL;
spin_lock_irqsave(&aliastree.lock, flags);
server = _find_server(uid);
if (server)
lcu = _find_lcu(server, uid);
spin_unlock_irqrestore(&aliastree.lock, flags);
if (!lcu) {
DBF_EVENT_DEVID(DBF_ERR, device->cdev,
"could not find lcu for %04x %02x",
uid->ssid, uid->real_unit_addr);
WARN_ON(1);
return;
}
complete_all(&lcu->lcu_setup);
}

void dasd_alias_wait_for_lcu_setup(struct dasd_device *device)
{
struct dasd_eckd_private *private;
unsigned long flags;
struct alias_server *server;
struct alias_lcu *lcu;
struct dasd_uid *uid;

private = (struct dasd_eckd_private *) device->private;
uid = &private->uid;
lcu = NULL;
spin_lock_irqsave(&aliastree.lock, flags);
server = _find_server(uid);
if (server)
lcu = _find_lcu(server, uid);
spin_unlock_irqrestore(&aliastree.lock, flags);
if (!lcu) {
DBF_EVENT_DEVID(DBF_ERR, device->cdev,
"could not find lcu for %04x %02x",
uid->ssid, uid->real_unit_addr);
WARN_ON(1);
return;
}
wait_for_completion(&lcu->lcu_setup);
}

/*
* This function removes a device from the scope of alias management.
* The complicated part is to make sure that it is not in use by
Expand Down
37 changes: 24 additions & 13 deletions trunk/drivers/s390/block/dasd_eckd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1059,7 +1059,7 @@ dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav)
/*
* Valide storage server of current device.
*/
static int dasd_eckd_validate_server(struct dasd_device *device)
static void dasd_eckd_validate_server(struct dasd_device *device)
{
int rc;
struct dasd_eckd_private *private;
Expand All @@ -1076,8 +1076,6 @@ static int dasd_eckd_validate_server(struct dasd_device *device)
private = (struct dasd_eckd_private *) device->private;
DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "PSF-SSC for SSID %04x "
"returned rc=%d", private->uid.ssid, rc);
/* RE-Read Configuration Data */
return dasd_eckd_read_conf(device);
}

/*
Expand Down Expand Up @@ -1149,12 +1147,21 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
rc = is_known;
goto out_err2;
}
/*
* dasd_eckd_vaildate_server is done on the first device that
* is found for an LCU. All later other devices have to wait
* for it, so they will read the correct feature codes.
*/
if (!is_known) {
/* new lcu found */
rc = dasd_eckd_validate_server(device); /* will switch pav on */
if (rc)
goto out_err3;
}
dasd_eckd_validate_server(device);
dasd_alias_lcu_setup_complete(device);
} else
dasd_alias_wait_for_lcu_setup(device);

/* device may report different configuration data after LCU setup */
rc = dasd_eckd_read_conf(device);
if (rc)
goto out_err3;

/* Read Feature Codes */
dasd_eckd_read_features(device);
Expand Down Expand Up @@ -3282,11 +3289,15 @@ int dasd_eckd_restore_device(struct dasd_device *device)
if (is_known < 0)
return is_known;
if (!is_known) {
/* new lcu found */
rc = dasd_eckd_validate_server(device); /* will switch pav on */
if (rc)
goto out_err;
}
dasd_eckd_validate_server(device);
dasd_alias_lcu_setup_complete(device);
} else
dasd_alias_wait_for_lcu_setup(device);

/* RE-Read Configuration Data */
rc = dasd_eckd_read_conf(device);
if (rc)
goto out_err;

/* Read Feature Codes */
dasd_eckd_read_features(device);
Expand Down
4 changes: 3 additions & 1 deletion trunk/drivers/s390/block/dasd_eckd.h
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,7 @@ struct alias_lcu {
struct summary_unit_check_work_data suc_data;
struct read_uac_work_data ruac_data;
struct dasd_ccw_req *rsu_cqr;
struct completion lcu_setup;
};

struct alias_pav_group {
Expand Down Expand Up @@ -460,5 +461,6 @@ int dasd_alias_remove_device(struct dasd_device *);
struct dasd_device *dasd_alias_get_start_dev(struct dasd_device *);
void dasd_alias_handle_summary_unit_check(struct dasd_device *, struct irb *);
void dasd_eckd_reset_ccw_to_base_io(struct dasd_ccw_req *);

void dasd_alias_lcu_setup_complete(struct dasd_device *);
void dasd_alias_wait_for_lcu_setup(struct dasd_device *);
#endif /* DASD_ECKD_H */

0 comments on commit 2b88e70

Please sign in to comment.