Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 107170
b: refs/heads/master
c: 4abb08c
h: refs/heads/master
v: v3
  • Loading branch information
Stefan Weinhuber authored and Martin Schwidefsky committed Aug 1, 2008
1 parent 3e17c96 commit 1dbecd8
Show file tree
Hide file tree
Showing 6 changed files with 190 additions and 164 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: c2bb4e5d497823437f0a11d342024ccdc6ff5b0d
refs/heads/master: 4abb08c24b5fa7b6ad0807c07077f0f216f6788b
4 changes: 3 additions & 1 deletion trunk/drivers/s390/block/dasd_alias.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@ static struct alias_pav_group *_find_group(struct alias_lcu *lcu,
else
search_unit_addr = uid->base_unit_addr;
list_for_each_entry(pos, &lcu->grouplist, group) {
if (pos->uid.base_unit_addr == search_unit_addr)
if (pos->uid.base_unit_addr == search_unit_addr &&
!strncmp(pos->uid.vduit, uid->vduit, sizeof(uid->vduit)))
return pos;
};
return NULL;
Expand Down Expand Up @@ -332,6 +333,7 @@ static int _add_device_to_lcu(struct alias_lcu *lcu,
group->uid.base_unit_addr = uid->real_unit_addr;
else
group->uid.base_unit_addr = uid->base_unit_addr;
memcpy(group->uid.vduit, uid->vduit, sizeof(uid->vduit));
INIT_LIST_HEAD(&group->group);
INIT_LIST_HEAD(&group->baselist);
INIT_LIST_HEAD(&group->aliaslist);
Expand Down
16 changes: 13 additions & 3 deletions trunk/drivers/s390/block/dasd_devmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -913,7 +913,8 @@ dasd_vendor_show(struct device *dev, struct device_attribute *attr, char *buf)
static DEVICE_ATTR(vendor, 0444, dasd_vendor_show, NULL);

#define UID_STRLEN ( /* vendor */ 3 + 1 + /* serial */ 14 + 1 +\
/* SSID */ 4 + 1 + /* unit addr */ 2 + 1)
/* SSID */ 4 + 1 + /* unit addr */ 2 + 1 +\
/* vduit */ 32 + 1)

static ssize_t
dasd_uid_show(struct device *dev, struct device_attribute *attr, char *buf)
Expand Down Expand Up @@ -945,8 +946,17 @@ dasd_uid_show(struct device *dev, struct device_attribute *attr, char *buf)
sprintf(ua_string, "%02x", uid->real_unit_addr);
break;
}
snprintf(uid_string, sizeof(uid_string), "%s.%s.%04x.%s",
uid->vendor, uid->serial, uid->ssid, ua_string);
if (strlen(uid->vduit) > 0)
snprintf(uid_string, sizeof(uid_string),
"%s.%s.%04x.%s.%s",
uid->vendor, uid->serial,
uid->ssid, ua_string,
uid->vduit);
else
snprintf(uid_string, sizeof(uid_string),
"%s.%s.%04x.%s",
uid->vendor, uid->serial,
uid->ssid, ua_string);
spin_unlock(&dasd_devmap_lock);
return snprintf(buf, PAGE_SIZE, "%s\n", uid_string);
}
Expand Down
147 changes: 112 additions & 35 deletions trunk/drivers/s390/block/dasd_eckd.c
Original file line number Diff line number Diff line change
Expand Up @@ -313,8 +313,8 @@ static int prefix(struct ccw1 *ccw, struct PFX_eckd_data *pfxdata, int trk,
memset(pfxdata, 0, sizeof(*pfxdata));
/* prefix data */
pfxdata->format = 0;
pfxdata->base_address = basepriv->conf_data.ned1.unit_addr;
pfxdata->base_lss = basepriv->conf_data.ned1.ID;
pfxdata->base_address = basepriv->ned->unit_addr;
pfxdata->base_lss = basepriv->ned->ID;
pfxdata->validity.define_extend = 1;

/* private uid is kept up to date, conf_data may be outdated */
Expand Down Expand Up @@ -536,36 +536,40 @@ dasd_eckd_cdl_reclen(int recid)
/*
* Generate device unique id that specifies the physical device.
*/
static int
dasd_eckd_generate_uid(struct dasd_device *device, struct dasd_uid *uid)
static int dasd_eckd_generate_uid(struct dasd_device *device,
struct dasd_uid *uid)
{
struct dasd_eckd_private *private;
struct dasd_eckd_confdata *confdata;
int count;

private = (struct dasd_eckd_private *) device->private;
if (!private)
return -ENODEV;
confdata = &private->conf_data;
if (!confdata)
if (!private->ned || !private->gneq)
return -ENODEV;

memset(uid, 0, sizeof(struct dasd_uid));
memcpy(uid->vendor, confdata->ned1.HDA_manufacturer,
memcpy(uid->vendor, private->ned->HDA_manufacturer,
sizeof(uid->vendor) - 1);
EBCASC(uid->vendor, sizeof(uid->vendor) - 1);
memcpy(uid->serial, confdata->ned1.HDA_location,
memcpy(uid->serial, private->ned->HDA_location,
sizeof(uid->serial) - 1);
EBCASC(uid->serial, sizeof(uid->serial) - 1);
uid->ssid = confdata->neq.subsystemID;
uid->real_unit_addr = confdata->ned1.unit_addr;
if (confdata->ned2.sneq.flags == 0x40 &&
confdata->ned2.sneq.format == 0x0001) {
uid->type = confdata->ned2.sneq.sua_flags;
uid->ssid = private->gneq->subsystemID;
uid->real_unit_addr = private->ned->unit_addr;;
if (private->sneq) {
uid->type = private->sneq->sua_flags;
if (uid->type == UA_BASE_PAV_ALIAS)
uid->base_unit_addr = confdata->ned2.sneq.base_unit_addr;
uid->base_unit_addr = private->sneq->base_unit_addr;
} else {
uid->type = UA_BASE_DEVICE;
}
if (private->vdsneq) {
for (count = 0; count < 16; count++) {
sprintf(uid->vduit+2*count, "%02x",
private->vdsneq->uit[count]);
}
}
return 0;
}

Expand Down Expand Up @@ -623,6 +627,15 @@ static int dasd_eckd_read_conf_lpm(struct dasd_device *device,
ret = -ENOMEM;
goto out_error;
}

/*
* buffer has to start with EBCDIC "V1.0" to show
* support for virtual device SNEQ
*/
rcd_buf[0] = 0xE5;
rcd_buf[1] = 0xF1;
rcd_buf[2] = 0x4B;
rcd_buf[3] = 0xF0;
cqr = dasd_eckd_build_rcd_lpm(device, rcd_buf, ciw, lpm);
if (IS_ERR(cqr)) {
ret = PTR_ERR(cqr);
Expand All @@ -646,8 +659,62 @@ static int dasd_eckd_read_conf_lpm(struct dasd_device *device,
return ret;
}

static int
dasd_eckd_read_conf(struct dasd_device *device)
static int dasd_eckd_identify_conf_parts(struct dasd_eckd_private *private)
{

struct dasd_sneq *sneq;
int i, count;

private->ned = NULL;
private->sneq = NULL;
private->vdsneq = NULL;
private->gneq = NULL;
count = private->conf_len / sizeof(struct dasd_sneq);
sneq = (struct dasd_sneq *)private->conf_data;
for (i = 0; i < count; ++i) {
if (sneq->flags.identifier == 1 && sneq->format == 1)
private->sneq = sneq;
else if (sneq->flags.identifier == 1 && sneq->format == 4)
private->vdsneq = (struct vd_sneq *)sneq;
else if (sneq->flags.identifier == 2)
private->gneq = (struct dasd_gneq *)sneq;
else if (sneq->flags.identifier == 3 && sneq->res1 == 1)
private->ned = (struct dasd_ned *)sneq;
sneq++;
}
if (!private->ned || !private->gneq) {
private->ned = NULL;
private->sneq = NULL;
private->vdsneq = NULL;
private->gneq = NULL;
return -EINVAL;
}
return 0;

};

static unsigned char dasd_eckd_path_access(void *conf_data, int conf_len)
{
struct dasd_gneq *gneq;
int i, count, found;

count = conf_len / sizeof(*gneq);
gneq = (struct dasd_gneq *)conf_data;
found = 0;
for (i = 0; i < count; ++i) {
if (gneq->flags.identifier == 2) {
found = 1;
break;
}
gneq++;
}
if (found)
return ((char *)gneq)[18] & 0x07;
else
return 0;
}

static int dasd_eckd_read_conf(struct dasd_device *device)
{
void *conf_data;
int conf_len, conf_data_saved;
Expand All @@ -661,7 +728,6 @@ dasd_eckd_read_conf(struct dasd_device *device)
path_data->opm = ccw_device_get_path_mask(device->cdev);
lpm = 0x80;
conf_data_saved = 0;

/* get configuration data per operational path */
for (lpm = 0x80; lpm; lpm>>= 1) {
if (lpm & path_data->opm){
Expand All @@ -678,30 +744,29 @@ dasd_eckd_read_conf(struct dasd_device *device)
"data retrieved");
continue; /* no error */
}
if (conf_len != sizeof(struct dasd_eckd_confdata)) {
MESSAGE(KERN_WARNING,
"sizes of configuration data mismatch"
"%d (read) vs %ld (expected)",
conf_len,
sizeof(struct dasd_eckd_confdata));
kfree(conf_data);
continue; /* no error */
}
/* save first valid configuration data */
if (!conf_data_saved){
memcpy(&private->conf_data, conf_data,
sizeof(struct dasd_eckd_confdata));
if (!conf_data_saved) {
kfree(private->conf_data);
private->conf_data = conf_data;
private->conf_len = conf_len;
if (dasd_eckd_identify_conf_parts(private)) {
private->conf_data = NULL;
private->conf_len = 0;
kfree(conf_data);
continue;
}
conf_data_saved++;
}
switch (((char *)conf_data)[242] & 0x07){
switch (dasd_eckd_path_access(conf_data, conf_len)) {
case 0x02:
path_data->npm |= lpm;
break;
case 0x03:
path_data->ppm |= lpm;
break;
}
kfree(conf_data);
if (conf_data != private->conf_data)
kfree(conf_data);
}
}
return 0;
Expand Down Expand Up @@ -952,14 +1017,25 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
dasd_free_block(device->block);
device->block = NULL;
out_err1:
kfree(private->conf_data);
kfree(device->private);
device->private = NULL;
return rc;
}

static void dasd_eckd_uncheck_device(struct dasd_device *device)
{
struct dasd_eckd_private *private;

private = (struct dasd_eckd_private *) device->private;
dasd_alias_disconnect_device_from_lcu(device);
private->ned = NULL;
private->sneq = NULL;
private->vdsneq = NULL;
private->gneq = NULL;
private->conf_len = 0;
kfree(private->conf_data);
private->conf_data = NULL;
}

static struct dasd_ccw_req *
Expand Down Expand Up @@ -1746,9 +1822,10 @@ dasd_eckd_fill_info(struct dasd_device * device,
info->characteristics_size = sizeof(struct dasd_eckd_characteristics);
memcpy(info->characteristics, &private->rdc_data,
sizeof(struct dasd_eckd_characteristics));
info->confdata_size = sizeof(struct dasd_eckd_confdata);
memcpy(info->configuration_data, &private->conf_data,
sizeof(struct dasd_eckd_confdata));
info->confdata_size = min((unsigned long)private->conf_len,
sizeof(info->configuration_data));
memcpy(info->configuration_data, private->conf_data,
info->confdata_size);
return 0;
}

Expand Down
Loading

0 comments on commit 1dbecd8

Please sign in to comment.