#include "dasd_int.h"
-kmem_cache_t *dasd_page_cache;
+struct kmem_cache *dasd_page_cache;
EXPORT_SYMBOL_GPL(dasd_page_cache);
/*
};
/*
- * dasd_servermap is used to store the server_id of all storage servers
- * accessed by DASD device driver.
+ * dasd_server_ssid_map contains a globally unique storage server subsystem ID.
+ * dasd_server_ssid_list contains the list of all subsystem IDs accessed by
+ * the DASD device driver.
*/
-struct dasd_servermap {
+struct dasd_server_ssid_map {
struct list_head list;
- struct server_id {
+ struct system_id {
char vendor[4];
char serial[15];
+ __u16 ssid;
} sid;
};
-static struct list_head dasd_serverlist;
+static struct list_head dasd_server_ssid_list;
/*
* Parameter parsing functions for dasd= parameter. The syntax is:
return residual_str;
}
if (strncmp("nopav", parsestring, length) == 0) {
- dasd_nopav = 1;
- MESSAGE(KERN_INFO, "%s", "disable PAV mode");
+ if (MACHINE_IS_VM)
+ MESSAGE(KERN_INFO, "%s", "'nopav' not supported on VM");
+ else {
+ 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 =
- kmem_cache_create("dasd_page_cache", PAGE_SIZE, 0,
- SLAB_CACHE_DMA, NULL, NULL );
+ kmem_cache_create("dasd_page_cache", PAGE_SIZE,
+ PAGE_SIZE, SLAB_CACHE_DMA,
+ NULL, NULL );
if (!dasd_page_cache)
MESSAGE(KERN_WARNING, "%s", "Failed to create slab, "
"fixed buffer mode disabled.");
{
struct dasd_devmap *devmap;
struct dasd_device *device;
+ unsigned long flags;
int rc;
devmap = dasd_devmap_from_cdev(cdev);
if (IS_ERR(devmap))
return (void *) devmap;
- cdev->dev.driver_data = devmap;
device = dasd_alloc_device();
if (IS_ERR(device))
return device;
- atomic_set(&device->ref_count, 2);
+ atomic_set(&device->ref_count, 3);
spin_lock(&dasd_devmap_lock);
if (!devmap->device) {
dasd_free_device(device);
return ERR_PTR(rc);
}
+
+ spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
+ cdev->dev.driver_data = device;
+ spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
+
return device;
}
{
struct ccw_device *cdev;
struct dasd_devmap *devmap;
+ unsigned long flags;
/* First remove device pointer from devmap. */
devmap = dasd_find_busid(device->cdev->dev.bus_id);
devmap->device = NULL;
spin_unlock(&dasd_devmap_lock);
- /* Drop ref_count by 2, one for the devmap reference and
- * one for the passed reference. */
- atomic_sub(2, &device->ref_count);
+ /* Disconnect dasd_device structure from ccw_device structure. */
+ spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
+ device->cdev->dev.driver_data = NULL;
+ spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
+
+ /*
+ * Drop ref_count by 3, one for the devmap reference, one for
+ * the cdev reference and one for the passed reference.
+ */
+ atomic_sub(3, &device->ref_count);
/* Wait for reference counter to drop to zero. */
wait_event(dasd_delete_wq, atomic_read(&device->ref_count) == 0);
cdev = device->cdev;
device->cdev = NULL;
- /* Disconnect dasd_devmap structure from ccw_device structure. */
- cdev->dev.driver_data = NULL;
-
/* Put ccw_device structure. */
put_device(&cdev->dev);
wake_up(&dasd_delete_wq);
}
+/*
+ * Return dasd_device structure associated with cdev.
+ * This function needs to be called with the ccw device
+ * lock held. It can be used from interrupt context.
+ */
+struct dasd_device *
+dasd_device_from_cdev_locked(struct ccw_device *cdev)
+{
+ struct dasd_device *device = cdev->dev.driver_data;
+
+ if (!device)
+ return ERR_PTR(-ENODEV);
+ dasd_get_device(device);
+ return device;
+}
+
/*
* Return dasd_device structure associated with cdev.
*/
struct dasd_device *
dasd_device_from_cdev(struct ccw_device *cdev)
{
- struct dasd_devmap *devmap;
struct dasd_device *device;
+ unsigned long flags;
- device = ERR_PTR(-ENODEV);
- spin_lock(&dasd_devmap_lock);
- devmap = cdev->dev.driver_data;
- if (devmap && devmap->device) {
- device = devmap->device;
- dasd_get_device(device);
- }
- spin_unlock(&dasd_devmap_lock);
+ spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
+ device = dasd_device_from_cdev_locked(cdev);
+ spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
return device;
}
const char *buf, size_t count)
{
struct dasd_devmap *devmap;
- int ro_flag;
+ int val;
+ char *endp;
devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
if (IS_ERR(devmap))
return PTR_ERR(devmap);
- ro_flag = buf[0] == '1';
+
+ val = simple_strtoul(buf, &endp, 0);
+ if (((endp + 1) < (buf + count)) || (val > 1))
+ return -EINVAL;
+
spin_lock(&dasd_devmap_lock);
- if (ro_flag)
+ if (val)
devmap->features |= DASD_FEATURE_READONLY;
else
devmap->features &= ~DASD_FEATURE_READONLY;
if (devmap->device)
devmap->device->features = devmap->features;
if (devmap->device && devmap->device->gdp)
- set_disk_ro(devmap->device->gdp, ro_flag);
+ set_disk_ro(devmap->device->gdp, val);
spin_unlock(&dasd_devmap_lock);
return count;
}
{
struct dasd_devmap *devmap;
ssize_t rc;
- int use_diag;
+ int val;
+ char *endp;
devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
if (IS_ERR(devmap))
return PTR_ERR(devmap);
- use_diag = buf[0] == '1';
+
+ val = simple_strtoul(buf, &endp, 0);
+ if (((endp + 1) < (buf + count)) || (val > 1))
+ return -EINVAL;
+
spin_lock(&dasd_devmap_lock);
/* Changing diag discipline flag is only allowed in offline state. */
rc = count;
if (!devmap->device) {
- if (use_diag)
+ if (val)
devmap->features |= DASD_FEATURE_USEDIAG;
else
devmap->features &= ~DASD_FEATURE_USEDIAG;
dasd_discipline_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
- struct dasd_devmap *devmap;
- char *dname;
+ struct dasd_device *device;
+ ssize_t len;
- spin_lock(&dasd_devmap_lock);
- dname = "none";
- devmap = dev->driver_data;
- if (devmap && devmap->device && devmap->device->discipline)
- dname = devmap->device->discipline->name;
- spin_unlock(&dasd_devmap_lock);
- return snprintf(buf, PAGE_SIZE, "%s\n", dname);
+ device = dasd_device_from_cdev(to_ccwdev(dev));
+ if (!IS_ERR(device) && device->discipline) {
+ len = snprintf(buf, PAGE_SIZE, "%s\n",
+ device->discipline->name);
+ dasd_put_device(device);
+ } else
+ len = snprintf(buf, PAGE_SIZE, "none\n");
+ return len;
}
static DEVICE_ATTR(discipline, 0444, dasd_discipline_show, NULL);
const char *buf, size_t count)
{
struct dasd_devmap *devmap;
- int rc;
+ int val, rc;
+ char *endp;
devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
if (IS_ERR(devmap))
return PTR_ERR(devmap);
if (!devmap->device)
- return count;
- if (buf[0] == '1') {
+ return -ENODEV;
+
+ val = simple_strtoul(buf, &endp, 0);
+ if (((endp + 1) < (buf + count)) || (val > 1))
+ return -EINVAL;
+
+ if (val) {
rc = dasd_eer_enable(devmap->device);
if (rc)
return rc;
/*
* Register the given device unique identifier into devmap struct.
- * In addition check if the related storage server is already contained in the
- * dasd_serverlist. If server is not contained, create new entry.
+ * In addition check if the related storage server subsystem ID is already
+ * contained in the dasd_server_ssid_list. If subsystem ID is not contained,
+ * create new entry.
* Return 0 if server was already in serverlist,
* 1 if the server was added successful
* <0 in case of error.
dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid)
{
struct dasd_devmap *devmap;
- struct dasd_servermap *srv, *tmp;
+ struct dasd_server_ssid_map *srv, *tmp;
devmap = dasd_find_busid(cdev->dev.bus_id);
if (IS_ERR(devmap))
return PTR_ERR(devmap);
- /* generate entry for servermap */
- srv = (struct dasd_servermap *)
- kzalloc(sizeof(struct dasd_servermap), GFP_KERNEL);
+ /* generate entry for server_ssid_map */
+ srv = (struct dasd_server_ssid_map *)
+ kzalloc(sizeof(struct dasd_server_ssid_map), GFP_KERNEL);
if (!srv)
return -ENOMEM;
strncpy(srv->sid.vendor, uid->vendor, sizeof(srv->sid.vendor) - 1);
strncpy(srv->sid.serial, uid->serial, sizeof(srv->sid.serial) - 1);
+ srv->sid.ssid = uid->ssid;
/* server is already contained ? */
spin_lock(&dasd_devmap_lock);
devmap->uid = *uid;
- list_for_each_entry(tmp, &dasd_serverlist, list) {
+ list_for_each_entry(tmp, &dasd_server_ssid_list, list) {
if (!memcmp(&srv->sid, &tmp->sid,
- sizeof(struct dasd_servermap))) {
+ sizeof(struct system_id))) {
kfree(srv);
srv = NULL;
break;
/* add servermap to serverlist */
if (srv)
- list_add(&srv->list, &dasd_serverlist);
+ list_add(&srv->list, &dasd_server_ssid_list);
spin_unlock(&dasd_devmap_lock);
return (srv ? 1 : 0);
INIT_LIST_HEAD(&dasd_hashlists[i]);
/* Initialize servermap structure. */
- INIT_LIST_HEAD(&dasd_serverlist);
+ INIT_LIST_HEAD(&dasd_server_ssid_list);
return 0;
}