Commit ba94c1b2 authored by Martin Schwidefsky's avatar Martin Schwidefsky Committed by Linus Torvalds

[PATCH] s390: dasd driver.

 - Do add_disk even for unformatted devices to be able to format them.
 - Remove initialization of device.name.
 - Export some functions.
parent 0214410a
This diff is collapsed.
......@@ -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.15 $
* $Revision: 1.17 $
*/
#include <linux/config.h>
......@@ -424,10 +424,11 @@ dasd_create_device(struct ccw_device *cdev)
if (!(devmap = dasd_devmap_from_devno (devno)))
return ERR_PTR(-ENODEV);
device = dasd_alloc_device(devmap->devindex);
device = dasd_alloc_device();
if (IS_ERR(device))
return device;
atomic_set(&device->ref_count, 1);
device->devindex = devmap->devindex;
device->ro_flag = (devmap->features & DASD_FEATURE_READONLY) ? 1 : 0;
device->use_diag_flag = 1;
......@@ -435,7 +436,6 @@ dasd_create_device(struct ccw_device *cdev)
if (cdev->dev.driver_data == NULL) {
get_device(&cdev->dev);
cdev->dev.driver_data = device;
device->gdp->driverfs_dev = &cdev->dev;
device->cdev = cdev;
rc = 0;
} else
......@@ -483,7 +483,6 @@ dasd_delete_device(struct dasd_device *device)
/* Disconnect dasd_device structure from ccw_device structure. */
cdev = device->cdev;
device->cdev = NULL;
device->gdp->driverfs_dev = NULL;
cdev->dev.driver_data = NULL;
/* Put ccw_device structure. */
......
......@@ -7,7 +7,7 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
*
* $Revision: 1.46 $
* $Revision: 1.47 $
*/
#include <linux/config.h>
......@@ -503,12 +503,6 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
memcpy(&private->conf_data, conf_data,
sizeof (struct dasd_eckd_confdata));
DEV_MESSAGE(KERN_INFO, device,
"%04X/%02X(CU:%04X/%02X): Configuration data read",
private->rdc_data.dev_type,
private->rdc_data.dev_model,
private->rdc_data.cu_type,
private->rdc_data.cu_model.model);
return 0;
}
......@@ -843,8 +837,9 @@ dasd_eckd_format_device(struct dasd_device * device,
ccw->flags = CCW_FLAG_SLI;
ccw->count = 8;
ccw->cda = (__u32)(addr_t) ect;
ccw++;
}
if (fdata->intensity & 0x04) { /* erase track */
if ((fdata->intensity & ~0x08) & 0x04) { /* erase track */
ect = (struct eckd_count *) data;
data += sizeof(struct eckd_count);
ect->cyl = cyl;
......@@ -884,6 +879,7 @@ dasd_eckd_format_device(struct dasd_device * device,
ccw->flags = CCW_FLAG_SLI;
ccw->count = 8;
ccw->cda = (__u32)(addr_t) ect;
ccw++;
}
}
fcp->device = device;
......
......@@ -9,11 +9,10 @@
*
* Dealing with devices registered to multiple major numbers.
*
* $Revision: 1.31 $
* $Revision: 1.38 $
*/
#include <linux/config.h>
#include <linux/version.h>
#include <linux/interrupt.h>
#include <linux/fs.h>
#include <linux/blkpg.h>
......@@ -99,10 +98,10 @@ dasd_unregister_major(struct major_info * mi)
}
/*
* Allocate gendisk structure for devindex.
* Allocate and register gendisk structure for device.
*/
struct gendisk *
dasd_gendisk_alloc(int devindex)
int
dasd_gendisk_alloc(struct dasd_device *device)
{
struct major_info *mi;
struct gendisk *gdp;
......@@ -112,7 +111,7 @@ dasd_gendisk_alloc(int devindex)
mi = NULL;
while (1) {
spin_lock(&dasd_major_lock);
index = devindex;
index = device->devindex;
list_for_each_entry(mi, &dasd_major_info, list) {
if (index < DASD_PER_MAJOR)
break;
......@@ -124,18 +123,19 @@ dasd_gendisk_alloc(int devindex)
rc = dasd_register_major(0);
if (rc) {
DBF_EXC(DBF_ALERT, "%s", "out of major numbers!");
return ERR_PTR(rc);
return rc;
}
}
gdp = alloc_disk(1 << DASD_PARTN_BITS);
if (!gdp)
return ERR_PTR(-ENOMEM);
return -ENOMEM;
/* Initialize gendisk structure. */
gdp->major = mi->major;
gdp->first_minor = index << DASD_PARTN_BITS;
gdp->fops = &dasd_device_operations;
gdp->driverfs_dev = &device->cdev->dev;
/*
* Set device name.
......@@ -144,61 +144,75 @@ dasd_gendisk_alloc(int devindex)
* dasdaaa - dasdzzz : 17576 devices, added up = 18278
*/
len = sprintf(gdp->disk_name, "dasd");
if (devindex > 25) {
if (devindex > 701)
if (device->devindex > 25) {
if (device->devindex > 701)
len += sprintf(gdp->disk_name + len, "%c",
'a' + (((devindex - 702) / 676) % 26));
'a'+(((device->devindex-702)/676)%26));
len += sprintf(gdp->disk_name + len, "%c",
'a' + (((devindex - 26) / 26) % 26));
'a'+(((device->devindex-26)/26)%26));
}
len += sprintf(gdp->disk_name + len, "%c", 'a' + (devindex % 26));
len += sprintf(gdp->disk_name + len, "%c", 'a'+(device->devindex%26));
return gdp;
sprintf(gdp->devfs_name, "dasd/%04x",
_ccw_device_get_device_number(device->cdev));
if (device->ro_flag)
set_disk_ro(gdp, 1);
gdp->private_data = device;
gdp->queue = device->request_queue;
device->gdp = gdp;
set_capacity(device->gdp, 0);
add_disk(device->gdp);
return 0;
}
/*
* Return major number for device with device index devindex.
* Unregister and free gendisk structure for device.
*/
int dasd_gendisk_index_major(int devindex)
void
dasd_gendisk_free(struct dasd_device *device)
{
struct major_info *mi;
int rc;
spin_lock(&dasd_major_lock);
rc = -ENODEV;
list_for_each_entry(mi, &dasd_major_info, list) {
if (devindex < DASD_PER_MAJOR) {
rc = mi->major;
break;
}
devindex -= DASD_PER_MAJOR;
}
spin_unlock(&dasd_major_lock);
return rc;
del_gendisk(device->gdp);
put_disk(device->gdp);
device->gdp = 0;
}
/*
* Register disk to genhd. This will trigger a partition detection.
* Trigger a partition detection.
*/
void
dasd_setup_partitions(struct dasd_device * device)
dasd_scan_partitions(struct dasd_device * device)
{
struct block_device *bdev;
/* Make the disk known. */
set_capacity(device->gdp, device->blocks << device->s2b_shift);
device->gdp->queue = device->request_queue;
if (device->ro_flag)
set_disk_ro(device->gdp, 1);
add_disk(device->gdp);
/* See fs/partition/check.c:register_disk,rescan_partitions */
bdev = bdget_disk(device->gdp, 0);
if (bdev) {
if (blkdev_get(bdev, FMODE_READ, 1, BDEV_RAW) >= 0) {
/* Can't call rescan_partitions directly. Use ioctl. */
ioctl_by_bdev(bdev, BLKRRPART, 0);
blkdev_put(bdev, BDEV_RAW);
}
}
}
/*
* Remove all inodes in the system for a device and make the
* partitions unusable by setting their size to zero.
* Remove all inodes in the system for a device, delete the
* partitions and make device unusable by setting its size to zero.
*/
void
dasd_destroy_partitions(struct dasd_device * device)
{
del_gendisk(device->gdp);
int p;
for (p = device->gdp->minors - 1; p > 0; p--) {
invalidate_partition(device->gdp, p);
delete_partition(device->gdp, p);
}
invalidate_partition(device->gdp, 0);
set_capacity(device->gdp, 0);
}
int
......@@ -208,11 +222,13 @@ dasd_gendisk_init(void)
/* Register to static dasd major 94 */
rc = dasd_register_major(DASD_MAJOR);
if (rc != 0)
if (rc != 0) {
MESSAGE(KERN_WARNING,
"Couldn't register successfully to "
"major no %d", DASD_MAJOR);
return rc;
return rc;
}
return 0;
}
void
......
......@@ -6,7 +6,7 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
*
* $Revision: 1.42 $
* $Revision: 1.45 $
*/
#ifndef DASD_INT_H
......@@ -30,14 +30,13 @@
* Things to do for startup state transitions:
* new -> known: find discipline for the device and create devfs entries.
* known -> basic: request irq line for the device.
* basic -> accept: do the initial analysis, e.g. format detection.
* accept-> ready: do block device setup and detect partitions.
* basic -> ready: do the initial analysis, e.g. format detection,
* do block device setup and detect partitions.
* ready -> online: schedule the device tasklet.
* Things to do for shutdown state transitions:
* online -> ready: just set the new device state.
* ready -> accept: flush requests from the block device layer and
* clear partition information.
* accept -> basic: reset format information.
* ready -> basic: flush requests from the block device layer, clear
* partition information and reset format information.
* basic -> known: terminate all requests and free irq.
* known -> new: remove devfs entries and forget discipline.
*/
......@@ -45,12 +44,10 @@
#define DASD_STATE_NEW 0
#define DASD_STATE_KNOWN 1
#define DASD_STATE_BASIC 2
#define DASD_STATE_ACCEPT 3
#define DASD_STATE_READY 4
#define DASD_STATE_ONLINE 5
#define DASD_STATE_READY 3
#define DASD_STATE_ONLINE 4
#include <linux/module.h>
#include <linux/version.h>
#include <linux/wait.h>
#include <linux/blkdev.h>
#include <linux/devfs_fs_kernel.h>
......@@ -138,8 +135,7 @@ do { \
/* messages to be written via klogd and dbf */
#define DEV_MESSAGE(d_loglevel,d_device,d_string,d_args...)\
do { \
printk(d_loglevel PRINTK_HEADER " %s,%s: " \
d_string "\n", d_device->gdp->disk_name, \
printk(d_loglevel PRINTK_HEADER " %s: " d_string "\n", \
d_device->cdev->dev.bus_id, d_args); \
DBF_DEV_EVENT(DBF_ALERT, d_device, d_string, d_args); \
} while(0)
......@@ -266,6 +262,7 @@ struct dasd_device {
struct gendisk *gdp;
request_queue_t *request_queue;
spinlock_t request_queue_lock;
unsigned int devindex;
unsigned long blocks; /* size of volume in blocks */
unsigned int bp_block; /* bytes per block */
unsigned int s2b_shift; /* log2 (bp_block/512) */
......@@ -442,7 +439,7 @@ dasd_kmalloc_set_cda(struct ccw1 *ccw, void *cda, struct dasd_device *device)
return set_normalized_cda(ccw, cda);
}
struct dasd_device *dasd_alloc_device(unsigned int devindex);
struct dasd_device *dasd_alloc_device(void);
void dasd_free_device(struct dasd_device *);
void dasd_enable_device(struct dasd_device *);
......@@ -486,9 +483,9 @@ int dasd_devno_in_range(int);
/* externals in dasd_gendisk.c */
int dasd_gendisk_init(void);
void dasd_gendisk_exit(void);
int dasd_gendisk_index_major(int);
struct gendisk *dasd_gendisk_alloc(int);
void dasd_setup_partitions(struct dasd_device *);
int dasd_gendisk_alloc(struct dasd_device *);
void dasd_gendisk_free(struct dasd_device *);
void dasd_scan_partitions(struct dasd_device *);
void dasd_destroy_partitions(struct dasd_device *);
/* externals in dasd_ioctl.c */
......
......@@ -125,8 +125,7 @@ dasd_ioctl_api_version(struct block_device *bdev, int no, long args)
/*
* Enable device.
* FIXME: how can we get here if the device is not already enabled?
* -arnd
* used by dasdfmt after BIODASDDISABLE to retrigger blocksize detection
*/
static int
dasd_ioctl_enable(struct block_device *bdev, int no, long args)
......@@ -139,6 +138,10 @@ dasd_ioctl_enable(struct block_device *bdev, int no, long args)
if (device == NULL)
return -ENODEV;
dasd_enable_device(device);
/* Formatting the dasd device can change the capacity. */
down(&bdev->bd_sem);
i_size_write(bdev->bd_inode, (loff_t)get_capacity(device->gdp) << 9);
up(&bdev->bd_sem);
return 0;
}
......
......@@ -9,7 +9,7 @@
*
* /proc interface for the dasd driver.
*
* $Revision: 1.21 $
* $Revision: 1.22 $
*/
#include <linux/config.h>
......@@ -66,10 +66,16 @@ dasd_devices_show(struct seq_file *m, void *v)
else
seq_printf(m, "(none)");
/* Print kdev. */
seq_printf(m, " at (%3d:%3d)",
device->gdp->major, device->gdp->first_minor);
if (device->gdp)
seq_printf(m, " at (%3d:%3d)",
device->gdp->major, device->gdp->first_minor);
else
seq_printf(m, " at (???:???)");
/* Print device name. */
seq_printf(m, " is %-7s", device->gdp->disk_name);
if (device->gdp)
seq_printf(m, " is %-7s", device->gdp->disk_name);
else
seq_printf(m, " is ???????");
/* Print devices features. */
substr = device->ro_flag ? "(ro)" : " ";
seq_printf(m, "%4s: ", substr);
......@@ -87,9 +93,6 @@ dasd_devices_show(struct seq_file *m, void *v)
case DASD_STATE_BASIC:
seq_printf(m, "basic");
break;
case DASD_STATE_ACCEPT:
seq_printf(m, "accepted");
break;
case DASD_STATE_READY:
case DASD_STATE_ONLINE:
seq_printf(m, "active ");
......
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