Commit 3ce60745 authored by Heiko Carstens's avatar Heiko Carstens Committed by Linus Torvalds

[PATCH] s390: DASD driver

From: Peter Oberparleiter <peter.oberparleiter@de.ibm.com>

dasd driver changes:
 - Modify format analysis routine to use block size provided by on-disk label.
 - Search data structures when referencing use_diag/ro attribute values.
 - Correct return code checking when allocating memory.
Signed-off-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 86df1439
......@@ -11,7 +11,7 @@
* functions may not be called from interrupt context. In particular
* dasd_get_device is a no-no from interrupt context.
*
* $Revision: 1.34 $
* $Revision: 1.35 $
*/
#include <linux/config.h>
......@@ -553,6 +553,8 @@ dasd_delete_device(struct dasd_device *device)
/* First remove device pointer from devmap. */
devmap = dasd_find_busid(device->cdev->dev.bus_id);
if (IS_ERR(devmap))
BUG();
spin_lock(&dasd_devmap_lock);
if (devmap->device != device) {
spin_unlock(&dasd_devmap_lock);
......@@ -626,8 +628,8 @@ dasd_ro_show(struct device *dev, char *buf)
struct dasd_devmap *devmap;
int ro_flag;
devmap = dev->driver_data;
if (devmap)
devmap = dasd_find_busid(dev->bus_id);
if (!IS_ERR(devmap))
ro_flag = (devmap->features & DASD_FEATURE_READONLY) != 0;
else
ro_flag = (DASD_FEATURE_DEFAULT & DASD_FEATURE_READONLY) != 0;
......@@ -641,6 +643,8 @@ dasd_ro_store(struct device *dev, const char *buf, size_t count)
int ro_flag;
devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
if (IS_ERR(devmap))
return PTR_ERR(devmap);
ro_flag = buf[0] == '1';
spin_lock(&dasd_devmap_lock);
if (ro_flag)
......@@ -665,15 +669,14 @@ static DEVICE_ATTR(readonly, 0644, dasd_ro_show, dasd_ro_store);
* use_diag controls whether the driver should use diag rather than ssch
* to talk to the device
*/
/* TODO: Implement */
static ssize_t
dasd_use_diag_show(struct device *dev, char *buf)
{
struct dasd_devmap *devmap;
int use_diag;
devmap = dev->driver_data;
if (devmap)
devmap = dasd_find_busid(dev->bus_id);
if (!IS_ERR(devmap))
use_diag = (devmap->features & DASD_FEATURE_USEDIAG) != 0;
else
use_diag = (DASD_FEATURE_DEFAULT & DASD_FEATURE_USEDIAG) != 0;
......@@ -684,21 +687,25 @@ static ssize_t
dasd_use_diag_store(struct device *dev, const char *buf, size_t count)
{
struct dasd_devmap *devmap;
ssize_t rc;
int use_diag;
devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
if (IS_ERR(devmap))
return PTR_ERR(devmap);
use_diag = buf[0] == '1';
spin_lock(&dasd_devmap_lock);
/* Changing diag discipline flag is only allowed in offline state. */
rc = count;
if (!devmap->device) {
if (use_diag)
devmap->features |= DASD_FEATURE_USEDIAG;
else
devmap->features &= ~DASD_FEATURE_USEDIAG;
} else
count = -EPERM;
rc = -EPERM;
spin_unlock(&dasd_devmap_lock);
return count;
return rc;
}
static
......
......@@ -6,7 +6,7 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
*
* $Revision: 1.39 $
* $Revision: 1.40 $
*/
#include <linux/config.h>
......@@ -274,6 +274,7 @@ dasd_diag_check_device(struct dasd_device *device)
"No memory to allocate initialization request");
return -ENOMEM;
}
/* try all sizes - needed for ECKD devices */
for (bsize = 512; bsize <= PAGE_SIZE; bsize <<= 1) {
mdsk_init_io(device, bsize, 0, 64);
memset(&bio, 0, sizeof (struct dasd_diag_bio));
......@@ -291,8 +292,9 @@ dasd_diag_check_device(struct dasd_device *device)
break;
mdsk_term_io(device);
}
if (bsize <= PAGE_SIZE && label[3] == bsize &&
label[0] == 0xc3d4e2f1) {
if (bsize <= PAGE_SIZE && label[0] == 0xc3d4e2f1) {
/* get formatted blocksize from label block */
bsize = (int) label[3];
device->blocks = label[7];
device->bp_block = bsize;
device->s2b_shift = 0; /* bits to shift 512 to get a block */
......@@ -305,8 +307,12 @@ dasd_diag_check_device(struct dasd_device *device)
(device->blocks << device->s2b_shift) >> 1);
rc = 0;
} else {
if (bsize > PAGE_SIZE)
DEV_MESSAGE(KERN_WARNING, device, "%s",
"volume has incompatible disk layout");
"DIAG access failed");
else
DEV_MESSAGE(KERN_WARNING, device, "%s",
"volume is not CMS formatted");
rc = -EMEDIUMTYPE;
}
free_page((long) label);
......
......@@ -7,7 +7,7 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
*
* $Revision: 1.65 $
* $Revision: 1.66 $
*/
#include <linux/config.h>
......@@ -1192,10 +1192,10 @@ dasd_eckd_release(struct block_device *bdev, int no, long args)
cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
1, 32, device);
if (cqr == NULL) {
if (IS_ERR(cqr)) {
MESSAGE(KERN_WARNING, "%s",
"No memory to allocate initialization request");
return -ENOMEM;
"Could not allocate initialization request");
return PTR_ERR(cqr);
}
cqr->cpaddr->cmd_code = DASD_ECKD_CCW_RELEASE;
cqr->cpaddr->flags |= CCW_FLAG_SLI;
......@@ -1236,10 +1236,10 @@ dasd_eckd_reserve(struct block_device *bdev, int no, long args)
cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
1, 32, device);
if (cqr == NULL) {
if (IS_ERR(cqr)) {
MESSAGE(KERN_WARNING, "%s",
"No memory to allocate initialization request");
return -ENOMEM;
"Could not allocate initialization request");
return PTR_ERR(cqr);
}
cqr->cpaddr->cmd_code = DASD_ECKD_CCW_RESERVE;
cqr->cpaddr->flags |= CCW_FLAG_SLI;
......@@ -1279,10 +1279,10 @@ dasd_eckd_steal_lock(struct block_device *bdev, int no, long args)
cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
1, 32, device);
if (cqr == NULL) {
if (IS_ERR(cqr)) {
MESSAGE(KERN_WARNING, "%s",
"No memory to allocate initialization request");
return -ENOMEM;
"Could not allocate initialization request");
return PTR_ERR(cqr);
}
cqr->cpaddr->cmd_code = DASD_ECKD_CCW_SLCK;
cqr->cpaddr->flags |= CCW_FLAG_SLI;
......@@ -1323,10 +1323,10 @@ dasd_eckd_performance(struct block_device *bdev, int no, long args)
(sizeof (struct dasd_psf_prssd_data) +
sizeof (struct dasd_rssd_perf_stats_t)),
device);
if (cqr == NULL) {
if (IS_ERR(cqr)) {
MESSAGE(KERN_WARNING, "%s",
"No memory to allocate initialization request");
return -ENOMEM;
"Could not allocate initialization request");
return PTR_ERR(cqr);
}
cqr->device = device;
cqr->retries = 0;
......
......@@ -9,7 +9,7 @@
*
* /proc interface for the dasd driver.
*
* $Revision: 1.27 $
* $Revision: 1.29 $
*/
#include <linux/config.h>
......@@ -248,6 +248,8 @@ dasd_statistics_write(struct file *file, const char __user *user_buf,
if (user_len > 65536)
user_len = 65536;
buffer = dasd_get_user_string(user_buf, user_len);
if (IS_ERR(buffer))
return PTR_ERR(buffer);
MESSAGE(KERN_INFO, "/proc/dasd/statictics: '%s'", buffer);
/* check for valid verbs */
......@@ -258,20 +260,20 @@ dasd_statistics_write(struct file *file, const char __user *user_buf,
if (strcmp(str, "on") == 0) {
/* switch on statistics profiling */
dasd_profile_level = DASD_PROFILE_ON;
MESSAGE(KERN_INFO, "%s", "Statictics switched on");
MESSAGE(KERN_INFO, "%s", "Statistics switched on");
} else if (strcmp(str, "off") == 0) {
/* switch off and reset statistics profiling */
memset(&dasd_global_profile,
0, sizeof (struct dasd_profile_info_t));
dasd_profile_level = DASD_PROFILE_OFF;
MESSAGE(KERN_INFO, "%s", "Statictics switched off");
MESSAGE(KERN_INFO, "%s", "Statistics switched off");
} else
goto out_error;
} else if (strncmp(str, "reset", 5) == 0) {
/* reset the statistics */
memset(&dasd_global_profile, 0,
sizeof (struct dasd_profile_info_t));
MESSAGE(KERN_INFO, "%s", "Statictics reset");
MESSAGE(KERN_INFO, "%s", "Statistics reset");
} else
goto out_error;
kfree(buffer);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment