mirror of https://gitee.com/openkylin/linux.git
[S390] add PAV support to the dasd driver.
Add support for parallel-access-volumes to the dasd driver. This allows concurrent access to dasd devices with multiple channel programs. Signed-off-by: Horst Hummel <horst.hummel@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
parent
8f27766a88
commit
405455734e
|
@ -1855,15 +1855,34 @@ dasd_generic_probe (struct ccw_device *cdev,
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
ret = ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP);
|
||||||
|
if (ret) {
|
||||||
|
printk(KERN_WARNING
|
||||||
|
"dasd_generic_probe: could not set ccw-device options "
|
||||||
|
"for %s\n", cdev->dev.bus_id);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
ret = dasd_add_sysfs_files(cdev);
|
ret = dasd_add_sysfs_files(cdev);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
printk(KERN_WARNING
|
printk(KERN_WARNING
|
||||||
"dasd_generic_probe: could not add sysfs entries "
|
"dasd_generic_probe: could not add sysfs entries "
|
||||||
"for %s\n", cdev->dev.bus_id);
|
"for %s\n", cdev->dev.bus_id);
|
||||||
} else {
|
return ret;
|
||||||
cdev->handler = &dasd_int_handler;
|
|
||||||
}
|
}
|
||||||
|
cdev->handler = &dasd_int_handler;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Automatically online either all dasd devices (dasd_autodetect)
|
||||||
|
* or all devices specified with dasd= parameters during
|
||||||
|
* initial probe.
|
||||||
|
*/
|
||||||
|
if ((dasd_get_feature(cdev, DASD_FEATURE_INITIAL_ONLINE) > 0 ) ||
|
||||||
|
(dasd_autodetect && dasd_busid_known(cdev->dev.bus_id) != 0))
|
||||||
|
ret = ccw_device_set_online(cdev);
|
||||||
|
if (ret)
|
||||||
|
printk(KERN_WARNING
|
||||||
|
"dasd_generic_probe: could not initially online "
|
||||||
|
"ccw-device %s\n", cdev->dev.bus_id);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1911,6 +1930,8 @@ dasd_generic_set_online (struct ccw_device *cdev,
|
||||||
struct dasd_device *device;
|
struct dasd_device *device;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
/* first online clears initial online feature flag */
|
||||||
|
dasd_set_feature(cdev, DASD_FEATURE_INITIAL_ONLINE, 0);
|
||||||
device = dasd_create_device(cdev);
|
device = dasd_create_device(cdev);
|
||||||
if (IS_ERR(device))
|
if (IS_ERR(device))
|
||||||
return PTR_ERR(device);
|
return PTR_ERR(device);
|
||||||
|
@ -2065,31 +2086,6 @@ dasd_generic_notify(struct ccw_device *cdev, int event)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Automatically online either all dasd devices (dasd_autodetect) or
|
|
||||||
* all devices specified with dasd= parameters.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
__dasd_auto_online(struct device *dev, void *data)
|
|
||||||
{
|
|
||||||
struct ccw_device *cdev;
|
|
||||||
|
|
||||||
cdev = to_ccwdev(dev);
|
|
||||||
if (dasd_autodetect || dasd_busid_known(cdev->dev.bus_id) == 0)
|
|
||||||
ccw_device_set_online(cdev);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
dasd_generic_auto_online (struct ccw_driver *dasd_discipline_driver)
|
|
||||||
{
|
|
||||||
struct device_driver *drv;
|
|
||||||
|
|
||||||
drv = get_driver(&dasd_discipline_driver->driver);
|
|
||||||
driver_for_each_device(drv, NULL, NULL, __dasd_auto_online);
|
|
||||||
put_driver(drv);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int __init
|
static int __init
|
||||||
dasd_init(void)
|
dasd_init(void)
|
||||||
|
@ -2170,5 +2166,4 @@ EXPORT_SYMBOL_GPL(dasd_generic_remove);
|
||||||
EXPORT_SYMBOL_GPL(dasd_generic_notify);
|
EXPORT_SYMBOL_GPL(dasd_generic_notify);
|
||||||
EXPORT_SYMBOL_GPL(dasd_generic_set_online);
|
EXPORT_SYMBOL_GPL(dasd_generic_set_online);
|
||||||
EXPORT_SYMBOL_GPL(dasd_generic_set_offline);
|
EXPORT_SYMBOL_GPL(dasd_generic_set_offline);
|
||||||
EXPORT_SYMBOL_GPL(dasd_generic_auto_online);
|
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
#include "dasd_int.h"
|
#include "dasd_int.h"
|
||||||
|
|
||||||
kmem_cache_t *dasd_page_cache;
|
kmem_cache_t *dasd_page_cache;
|
||||||
EXPORT_SYMBOL(dasd_page_cache);
|
EXPORT_SYMBOL_GPL(dasd_page_cache);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* dasd_devmap_t is used to store the features and the relation
|
* dasd_devmap_t is used to store the features and the relation
|
||||||
|
@ -48,6 +48,20 @@ struct dasd_devmap {
|
||||||
struct dasd_uid uid;
|
struct dasd_uid uid;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* dasd_servermap is used to store the server_id of all storage servers
|
||||||
|
* accessed by DASD device driver.
|
||||||
|
*/
|
||||||
|
struct dasd_servermap {
|
||||||
|
struct list_head list;
|
||||||
|
struct server_id {
|
||||||
|
char vendor[4];
|
||||||
|
char serial[15];
|
||||||
|
} sid;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct list_head dasd_serverlist;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parameter parsing functions for dasd= parameter. The syntax is:
|
* Parameter parsing functions for dasd= parameter. The syntax is:
|
||||||
* <devno> : (0x)?[0-9a-fA-F]+
|
* <devno> : (0x)?[0-9a-fA-F]+
|
||||||
|
@ -64,6 +78,8 @@ struct dasd_devmap {
|
||||||
|
|
||||||
int dasd_probeonly = 0; /* is true, when probeonly mode is active */
|
int dasd_probeonly = 0; /* is true, when probeonly mode is active */
|
||||||
int dasd_autodetect = 0; /* is true, when autodetection is active */
|
int dasd_autodetect = 0; /* is true, when autodetection is active */
|
||||||
|
int dasd_nopav = 0; /* is true, when PAV is disabled */
|
||||||
|
EXPORT_SYMBOL_GPL(dasd_nopav);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* char *dasd[] is intended to hold the ranges supplied by the dasd= statement
|
* char *dasd[] is intended to hold the ranges supplied by the dasd= statement
|
||||||
|
@ -228,19 +244,24 @@ dasd_parse_keyword( char *parsestring ) {
|
||||||
length = strlen(parsestring);
|
length = strlen(parsestring);
|
||||||
residual_str = parsestring + length;
|
residual_str = parsestring + length;
|
||||||
}
|
}
|
||||||
if (strncmp ("autodetect", parsestring, length) == 0) {
|
if (strncmp("autodetect", parsestring, length) == 0) {
|
||||||
dasd_autodetect = 1;
|
dasd_autodetect = 1;
|
||||||
MESSAGE (KERN_INFO, "%s",
|
MESSAGE (KERN_INFO, "%s",
|
||||||
"turning to autodetection mode");
|
"turning to autodetection mode");
|
||||||
return residual_str;
|
return residual_str;
|
||||||
}
|
}
|
||||||
if (strncmp ("probeonly", parsestring, length) == 0) {
|
if (strncmp("probeonly", parsestring, length) == 0) {
|
||||||
dasd_probeonly = 1;
|
dasd_probeonly = 1;
|
||||||
MESSAGE(KERN_INFO, "%s",
|
MESSAGE(KERN_INFO, "%s",
|
||||||
"turning to probeonly mode");
|
"turning to probeonly mode");
|
||||||
return residual_str;
|
return residual_str;
|
||||||
}
|
}
|
||||||
if (strncmp ("fixedbuffers", parsestring, length) == 0) {
|
if (strncmp("nopav", parsestring, length) == 0) {
|
||||||
|
dasd_nopav = 1;
|
||||||
|
MESSAGE(KERN_INFO, "%s", "disable PAV mode");
|
||||||
|
return residual_str;
|
||||||
|
}
|
||||||
|
if (strncmp("fixedbuffers", parsestring, length) == 0) {
|
||||||
if (dasd_page_cache)
|
if (dasd_page_cache)
|
||||||
return residual_str;
|
return residual_str;
|
||||||
dasd_page_cache =
|
dasd_page_cache =
|
||||||
|
@ -294,6 +315,8 @@ dasd_parse_range( char *parsestring ) {
|
||||||
features = dasd_feature_list(str, &str);
|
features = dasd_feature_list(str, &str);
|
||||||
if (features < 0)
|
if (features < 0)
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
|
/* each device in dasd= parameter should be set initially online */
|
||||||
|
features |= DASD_FEATURE_INITIAL_ONLINE;
|
||||||
while (from <= to) {
|
while (from <= to) {
|
||||||
sprintf(bus_id, "%01x.%01x.%04x",
|
sprintf(bus_id, "%01x.%01x.%04x",
|
||||||
from_id0, from_id1, from++);
|
from_id0, from_id1, from++);
|
||||||
|
@ -836,6 +859,38 @@ static struct attribute_group dasd_attr_group = {
|
||||||
.attrs = dasd_attrs,
|
.attrs = dasd_attrs,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if the related storage server is already contained in the
|
||||||
|
* dasd_serverlist. If server is not contained, create new entry.
|
||||||
|
* Return 0 if server was already in serverlist,
|
||||||
|
* 1 if the server was added successfully
|
||||||
|
* <0 in case of error.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
dasd_add_server(struct dasd_uid *uid)
|
||||||
|
{
|
||||||
|
struct dasd_servermap *new, *tmp;
|
||||||
|
|
||||||
|
/* check if server is already contained */
|
||||||
|
list_for_each_entry(tmp, &dasd_serverlist, list)
|
||||||
|
// normale cmp?
|
||||||
|
if (strncmp(tmp->sid.vendor, uid->vendor,
|
||||||
|
sizeof(tmp->sid.vendor)) == 0
|
||||||
|
&& strncmp(tmp->sid.serial, uid->serial,
|
||||||
|
sizeof(tmp->sid.serial)) == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
new = (struct dasd_servermap *)
|
||||||
|
kzalloc(sizeof(struct dasd_servermap), GFP_KERNEL);
|
||||||
|
if (!new)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
strncpy(new->sid.vendor, uid->vendor, sizeof(new->sid.vendor));
|
||||||
|
strncpy(new->sid.serial, uid->serial, sizeof(new->sid.serial));
|
||||||
|
list_add(&new->list, &dasd_serverlist);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return copy of the device unique identifier.
|
* Return copy of the device unique identifier.
|
||||||
|
@ -856,21 +911,26 @@ dasd_get_uid(struct ccw_device *cdev, struct dasd_uid *uid)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Register the given device unique identifier into devmap struct.
|
* Register the given device unique identifier into devmap struct.
|
||||||
|
* Return 0 if server was already in serverlist,
|
||||||
|
* 1 if the server was added successful
|
||||||
|
* <0 in case of error.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid)
|
dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid)
|
||||||
{
|
{
|
||||||
struct dasd_devmap *devmap;
|
struct dasd_devmap *devmap;
|
||||||
|
int rc;
|
||||||
|
|
||||||
devmap = dasd_find_busid(cdev->dev.bus_id);
|
devmap = dasd_find_busid(cdev->dev.bus_id);
|
||||||
if (IS_ERR(devmap))
|
if (IS_ERR(devmap))
|
||||||
return PTR_ERR(devmap);
|
return PTR_ERR(devmap);
|
||||||
spin_lock(&dasd_devmap_lock);
|
spin_lock(&dasd_devmap_lock);
|
||||||
devmap->uid = *uid;
|
devmap->uid = *uid;
|
||||||
|
rc = dasd_add_server(uid);
|
||||||
spin_unlock(&dasd_devmap_lock);
|
spin_unlock(&dasd_devmap_lock);
|
||||||
return 0;
|
return rc;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(dasd_set_uid);
|
EXPORT_SYMBOL_GPL(dasd_set_uid);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return value of the specified feature.
|
* Return value of the specified feature.
|
||||||
|
@ -882,7 +942,7 @@ dasd_get_feature(struct ccw_device *cdev, int feature)
|
||||||
|
|
||||||
devmap = dasd_find_busid(cdev->dev.bus_id);
|
devmap = dasd_find_busid(cdev->dev.bus_id);
|
||||||
if (IS_ERR(devmap))
|
if (IS_ERR(devmap))
|
||||||
return (int) PTR_ERR(devmap);
|
return PTR_ERR(devmap);
|
||||||
|
|
||||||
return ((devmap->features & feature) != 0);
|
return ((devmap->features & feature) != 0);
|
||||||
}
|
}
|
||||||
|
@ -898,7 +958,7 @@ dasd_set_feature(struct ccw_device *cdev, int feature, int flag)
|
||||||
|
|
||||||
devmap = dasd_find_busid(cdev->dev.bus_id);
|
devmap = dasd_find_busid(cdev->dev.bus_id);
|
||||||
if (IS_ERR(devmap))
|
if (IS_ERR(devmap))
|
||||||
return (int) PTR_ERR(devmap);
|
return PTR_ERR(devmap);
|
||||||
|
|
||||||
spin_lock(&dasd_devmap_lock);
|
spin_lock(&dasd_devmap_lock);
|
||||||
if (flag)
|
if (flag)
|
||||||
|
@ -934,8 +994,10 @@ dasd_devmap_init(void)
|
||||||
dasd_max_devindex = 0;
|
dasd_max_devindex = 0;
|
||||||
for (i = 0; i < 256; i++)
|
for (i = 0; i < 256; i++)
|
||||||
INIT_LIST_HEAD(&dasd_hashlists[i]);
|
INIT_LIST_HEAD(&dasd_hashlists[i]);
|
||||||
return 0;
|
|
||||||
|
|
||||||
|
/* Initialize servermap structure. */
|
||||||
|
INIT_LIST_HEAD(&dasd_serverlist);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/todclk.h>
|
#include <asm/todclk.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
|
#include <asm/cio.h>
|
||||||
#include <asm/ccwdev.h>
|
#include <asm/ccwdev.h>
|
||||||
|
|
||||||
#include "dasd_int.h"
|
#include "dasd_int.h"
|
||||||
|
@ -89,17 +90,22 @@ dasd_eckd_probe (struct ccw_device *cdev)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = dasd_generic_probe (cdev, &dasd_eckd_discipline);
|
/* set ECKD specific ccw-device options */
|
||||||
if (ret)
|
ret = ccw_device_set_options(cdev, CCWDEV_ALLOW_FORCE);
|
||||||
|
if (ret) {
|
||||||
|
printk(KERN_WARNING
|
||||||
|
"dasd_eckd_probe: could not set ccw-device options "
|
||||||
|
"for %s\n", cdev->dev.bus_id);
|
||||||
return ret;
|
return ret;
|
||||||
ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP | CCWDEV_ALLOW_FORCE);
|
}
|
||||||
return 0;
|
ret = dasd_generic_probe(cdev, &dasd_eckd_discipline);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
dasd_eckd_set_online(struct ccw_device *cdev)
|
dasd_eckd_set_online(struct ccw_device *cdev)
|
||||||
{
|
{
|
||||||
return dasd_generic_set_online (cdev, &dasd_eckd_discipline);
|
return dasd_generic_set_online(cdev, &dasd_eckd_discipline);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct ccw_driver dasd_eckd_driver = {
|
static struct ccw_driver dasd_eckd_driver = {
|
||||||
|
@ -540,6 +546,86 @@ dasd_eckd_read_conf(struct dasd_device *device)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Build CP for Perform Subsystem Function - SSC.
|
||||||
|
*/
|
||||||
|
struct dasd_ccw_req *
|
||||||
|
dasd_eckd_build_psf_ssc(struct dasd_device *device)
|
||||||
|
{
|
||||||
|
struct dasd_ccw_req *cqr;
|
||||||
|
struct dasd_psf_ssc_data *psf_ssc_data;
|
||||||
|
struct ccw1 *ccw;
|
||||||
|
|
||||||
|
cqr = dasd_smalloc_request("ECKD", 1 /* PSF */ ,
|
||||||
|
sizeof(struct dasd_psf_ssc_data),
|
||||||
|
device);
|
||||||
|
|
||||||
|
if (IS_ERR(cqr)) {
|
||||||
|
DEV_MESSAGE(KERN_WARNING, device, "%s",
|
||||||
|
"Could not allocate PSF-SSC request");
|
||||||
|
return cqr;
|
||||||
|
}
|
||||||
|
psf_ssc_data = (struct dasd_psf_ssc_data *)cqr->data;
|
||||||
|
psf_ssc_data->order = PSF_ORDER_SSC;
|
||||||
|
psf_ssc_data->suborder = 0x08;
|
||||||
|
|
||||||
|
ccw = cqr->cpaddr;
|
||||||
|
ccw->cmd_code = DASD_ECKD_CCW_PSF;
|
||||||
|
ccw->cda = (__u32)(addr_t)psf_ssc_data;
|
||||||
|
ccw->count = 66;
|
||||||
|
|
||||||
|
cqr->device = device;
|
||||||
|
cqr->expires = 10*HZ;
|
||||||
|
cqr->buildclk = get_clock();
|
||||||
|
cqr->status = DASD_CQR_FILLED;
|
||||||
|
return cqr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Perform Subsystem Function.
|
||||||
|
* It is necessary to trigger CIO for channel revalidation since this
|
||||||
|
* call might change behaviour of DASD devices.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
dasd_eckd_psf_ssc(struct dasd_device *device)
|
||||||
|
{
|
||||||
|
struct dasd_ccw_req *cqr;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
cqr = dasd_eckd_build_psf_ssc(device);
|
||||||
|
if (IS_ERR(cqr))
|
||||||
|
return PTR_ERR(cqr);
|
||||||
|
|
||||||
|
rc = dasd_sleep_on(cqr);
|
||||||
|
if (!rc)
|
||||||
|
/* trigger CIO to reprobe devices */
|
||||||
|
css_schedule_reprobe();
|
||||||
|
dasd_sfree_request(cqr, cqr->device);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Valide storage server of current device.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
dasd_eckd_validate_server(struct dasd_device *device)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Currently PAV is the only reason to 'validate' server on LPAR */
|
||||||
|
if (dasd_nopav || MACHINE_IS_VM)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
rc = dasd_eckd_psf_ssc(device);
|
||||||
|
if (rc)
|
||||||
|
/* may be requested feature is not available on server,
|
||||||
|
* therefore just report error and go ahead */
|
||||||
|
DEV_MESSAGE(KERN_INFO, device,
|
||||||
|
"Perform Subsystem Function returned rc=%d", rc);
|
||||||
|
/* RE-Read Configuration Data */
|
||||||
|
return dasd_eckd_read_conf(device);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check device characteristics.
|
* Check device characteristics.
|
||||||
* If the device is accessible using ECKD discipline, the device is enabled.
|
* If the device is accessible using ECKD discipline, the device is enabled.
|
||||||
|
@ -570,16 +656,29 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
|
||||||
private->attrib.operation = DASD_NORMAL_CACHE;
|
private->attrib.operation = DASD_NORMAL_CACHE;
|
||||||
private->attrib.nr_cyl = 0;
|
private->attrib.nr_cyl = 0;
|
||||||
|
|
||||||
|
/* Read Configuration Data */
|
||||||
|
rc = dasd_eckd_read_conf(device);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/* Generate device unique id and register in devmap */
|
||||||
|
rc = dasd_eckd_generate_uid(device, &uid);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
rc = dasd_set_uid(device->cdev, &uid);
|
||||||
|
if (rc == 1) /* new server found */
|
||||||
|
rc = dasd_eckd_validate_server(device);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
/* Read Device Characteristics */
|
/* Read Device Characteristics */
|
||||||
rdc_data = (void *) &(private->rdc_data);
|
rdc_data = (void *) &(private->rdc_data);
|
||||||
memset(rdc_data, 0, sizeof(rdc_data));
|
memset(rdc_data, 0, sizeof(rdc_data));
|
||||||
rc = read_dev_chars(device->cdev, &rdc_data, 64);
|
rc = read_dev_chars(device->cdev, &rdc_data, 64);
|
||||||
if (rc) {
|
if (rc)
|
||||||
DEV_MESSAGE(KERN_WARNING, device,
|
DEV_MESSAGE(KERN_WARNING, device,
|
||||||
"Read device characteristics returned error %d",
|
"Read device characteristics returned "
|
||||||
rc);
|
"rc=%d", rc);
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEV_MESSAGE(KERN_INFO, device,
|
DEV_MESSAGE(KERN_INFO, device,
|
||||||
"%04X/%02X(CU:%04X/%02X) Cyl:%d Head:%d Sec:%d",
|
"%04X/%02X(CU:%04X/%02X) Cyl:%d Head:%d Sec:%d",
|
||||||
|
@ -590,19 +689,6 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
|
||||||
private->rdc_data.no_cyl,
|
private->rdc_data.no_cyl,
|
||||||
private->rdc_data.trk_per_cyl,
|
private->rdc_data.trk_per_cyl,
|
||||||
private->rdc_data.sec_per_trk);
|
private->rdc_data.sec_per_trk);
|
||||||
|
|
||||||
/* Read Configuration Data */
|
|
||||||
rc = dasd_eckd_read_conf (device);
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
/* Generate device unique id and register in devmap */
|
|
||||||
rc = dasd_eckd_generate_uid(device, &uid);
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
rc = dasd_set_uid(device->cdev, &uid);
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1687,14 +1773,8 @@ static struct dasd_discipline dasd_eckd_discipline = {
|
||||||
static int __init
|
static int __init
|
||||||
dasd_eckd_init(void)
|
dasd_eckd_init(void)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
|
|
||||||
ASCEBC(dasd_eckd_discipline.ebcname, 4);
|
ASCEBC(dasd_eckd_discipline.ebcname, 4);
|
||||||
|
return ccw_driver_register(&dasd_eckd_driver);
|
||||||
ret = ccw_driver_register(&dasd_eckd_driver);
|
|
||||||
if (!ret)
|
|
||||||
dasd_generic_auto_online(&dasd_eckd_driver);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit
|
static void __exit
|
||||||
|
|
|
@ -41,9 +41,10 @@
|
||||||
#define DASD_ECKD_CCW_RESERVE 0xB4
|
#define DASD_ECKD_CCW_RESERVE 0xB4
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*Perform Subsystem Function / Sub-Orders
|
* Perform Subsystem Function / Sub-Orders
|
||||||
*/
|
*/
|
||||||
#define PSF_ORDER_PRSSD 0x18
|
#define PSF_ORDER_PRSSD 0x18
|
||||||
|
#define PSF_ORDER_SSC 0x1D
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* SECTION: Type Definitions
|
* SECTION: Type Definitions
|
||||||
|
@ -353,4 +354,15 @@ struct dasd_psf_prssd_data {
|
||||||
unsigned char varies[9];
|
unsigned char varies[9];
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Perform Subsystem Function - Set Subsystem Characteristics
|
||||||
|
*/
|
||||||
|
struct dasd_psf_ssc_data {
|
||||||
|
unsigned char order;
|
||||||
|
unsigned char flags;
|
||||||
|
unsigned char cu_type[4];
|
||||||
|
unsigned char suborder;
|
||||||
|
unsigned char reserved[59];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
#endif /* DASD_ECKD_H */
|
#endif /* DASD_ECKD_H */
|
||||||
|
|
|
@ -56,19 +56,13 @@ static struct ccw_driver dasd_fba_driver; /* see below */
|
||||||
static int
|
static int
|
||||||
dasd_fba_probe(struct ccw_device *cdev)
|
dasd_fba_probe(struct ccw_device *cdev)
|
||||||
{
|
{
|
||||||
int ret;
|
return dasd_generic_probe(cdev, &dasd_fba_discipline);
|
||||||
|
|
||||||
ret = dasd_generic_probe (cdev, &dasd_fba_discipline);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
dasd_fba_set_online(struct ccw_device *cdev)
|
dasd_fba_set_online(struct ccw_device *cdev)
|
||||||
{
|
{
|
||||||
return dasd_generic_set_online (cdev, &dasd_fba_discipline);
|
return dasd_generic_set_online(cdev, &dasd_fba_discipline);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct ccw_driver dasd_fba_driver = {
|
static struct ccw_driver dasd_fba_driver = {
|
||||||
|
@ -569,16 +563,8 @@ static struct dasd_discipline dasd_fba_discipline = {
|
||||||
static int __init
|
static int __init
|
||||||
dasd_fba_init(void)
|
dasd_fba_init(void)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
|
|
||||||
ASCEBC(dasd_fba_discipline.ebcname, 4);
|
ASCEBC(dasd_fba_discipline.ebcname, 4);
|
||||||
|
return ccw_driver_register(&dasd_fba_driver);
|
||||||
ret = ccw_driver_register(&dasd_fba_driver);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
dasd_generic_auto_online(&dasd_fba_driver);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit
|
static void __exit
|
||||||
|
|
|
@ -513,12 +513,12 @@ void dasd_generic_remove (struct ccw_device *cdev);
|
||||||
int dasd_generic_set_online(struct ccw_device *, struct dasd_discipline *);
|
int dasd_generic_set_online(struct ccw_device *, struct dasd_discipline *);
|
||||||
int dasd_generic_set_offline (struct ccw_device *cdev);
|
int dasd_generic_set_offline (struct ccw_device *cdev);
|
||||||
int dasd_generic_notify(struct ccw_device *, int);
|
int dasd_generic_notify(struct ccw_device *, int);
|
||||||
void dasd_generic_auto_online (struct ccw_driver *);
|
|
||||||
|
|
||||||
/* externals in dasd_devmap.c */
|
/* externals in dasd_devmap.c */
|
||||||
extern int dasd_max_devindex;
|
extern int dasd_max_devindex;
|
||||||
extern int dasd_probeonly;
|
extern int dasd_probeonly;
|
||||||
extern int dasd_autodetect;
|
extern int dasd_autodetect;
|
||||||
|
extern int dasd_nopav;
|
||||||
|
|
||||||
int dasd_devmap_init(void);
|
int dasd_devmap_init(void);
|
||||||
void dasd_devmap_exit(void);
|
void dasd_devmap_exit(void);
|
||||||
|
|
|
@ -68,10 +68,12 @@ typedef struct dasd_information2_t {
|
||||||
* 0x00: default features
|
* 0x00: default features
|
||||||
* 0x01: readonly (ro)
|
* 0x01: readonly (ro)
|
||||||
* 0x02: use diag discipline (diag)
|
* 0x02: use diag discipline (diag)
|
||||||
|
* 0x04: set the device initially online (internal use only)
|
||||||
*/
|
*/
|
||||||
#define DASD_FEATURE_DEFAULT 0
|
#define DASD_FEATURE_DEFAULT 0x00
|
||||||
#define DASD_FEATURE_READONLY 1
|
#define DASD_FEATURE_READONLY 0x01
|
||||||
#define DASD_FEATURE_USEDIAG 2
|
#define DASD_FEATURE_USEDIAG 0x02
|
||||||
|
#define DASD_FEATURE_INITIAL_ONLINE 0x04
|
||||||
|
|
||||||
#define DASD_PARTN_BITS 2
|
#define DASD_PARTN_BITS 2
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue