summaryrefslogtreecommitdiffstats
path: root/drivers/s390/block/dasd_devmap.c
diff options
context:
space:
mode:
authorHorst Hummel <horst.hummel@de.ibm.com>2006-06-29 15:08:18 +0200
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2006-06-29 15:08:18 +0200
commit405455734e1cdec09c37233216f9240cb1a058e5 (patch)
tree36e88909f646b635117041b19a851031fc8ffb41 /drivers/s390/block/dasd_devmap.c
parent8f27766a883149926e7c1f69d9f1d8f68efcd65f (diff)
[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>
Diffstat (limited to 'drivers/s390/block/dasd_devmap.c')
-rw-r--r--drivers/s390/block/dasd_devmap.c80
1 files changed, 71 insertions, 9 deletions
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index 672e50314b1..9e9ae717960 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -27,7 +27,7 @@
#include "dasd_int.h"
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
@@ -49,6 +49,20 @@ struct dasd_devmap {
};
/*
+ * 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:
* <devno> : (0x)?[0-9a-fA-F]+
* <busid> : [0-0a-f]\.[0-9a-f]\.(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_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
@@ -228,19 +244,24 @@ dasd_parse_keyword( char *parsestring ) {
length = strlen(parsestring);
residual_str = parsestring + length;
}
- if (strncmp ("autodetect", parsestring, length) == 0) {
+ if (strncmp("autodetect", parsestring, length) == 0) {
dasd_autodetect = 1;
MESSAGE (KERN_INFO, "%s",
"turning to autodetection mode");
return residual_str;
}
- if (strncmp ("probeonly", parsestring, length) == 0) {
+ if (strncmp("probeonly", parsestring, length) == 0) {
dasd_probeonly = 1;
MESSAGE(KERN_INFO, "%s",
"turning to probeonly mode");
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)
return residual_str;
dasd_page_cache =
@@ -294,6 +315,8 @@ dasd_parse_range( char *parsestring ) {
features = dasd_feature_list(str, &str);
if (features < 0)
return ERR_PTR(-EINVAL);
+ /* each device in dasd= parameter should be set initially online */
+ features |= DASD_FEATURE_INITIAL_ONLINE;
while (from <= to) {
sprintf(bus_id, "%01x.%01x.%04x",
from_id0, from_id1, from++);
@@ -836,6 +859,38 @@ static struct attribute_group dasd_attr_group = {
.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.
@@ -856,21 +911,26 @@ dasd_get_uid(struct ccw_device *cdev, struct dasd_uid *uid)
/*
* 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
dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid)
{
struct dasd_devmap *devmap;
+ int rc;
devmap = dasd_find_busid(cdev->dev.bus_id);
if (IS_ERR(devmap))
return PTR_ERR(devmap);
spin_lock(&dasd_devmap_lock);
devmap->uid = *uid;
+ rc = dasd_add_server(uid);
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.
@@ -882,7 +942,7 @@ dasd_get_feature(struct ccw_device *cdev, int feature)
devmap = dasd_find_busid(cdev->dev.bus_id);
if (IS_ERR(devmap))
- return (int) PTR_ERR(devmap);
+ return PTR_ERR(devmap);
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);
if (IS_ERR(devmap))
- return (int) PTR_ERR(devmap);
+ return PTR_ERR(devmap);
spin_lock(&dasd_devmap_lock);
if (flag)
@@ -934,8 +994,10 @@ dasd_devmap_init(void)
dasd_max_devindex = 0;
for (i = 0; i < 256; i++)
INIT_LIST_HEAD(&dasd_hashlists[i]);
- return 0;
+ /* Initialize servermap structure. */
+ INIT_LIST_HEAD(&dasd_serverlist);
+ return 0;
}
void