|
@@ -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
|
|
@@ -48,6 +48,20 @@ struct dasd_devmap {
|
|
|
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:
|
|
|
* <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_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
|