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

[PATCH] s390 update (7/27): dasd driver.

parent 7441ad13
...@@ -203,20 +203,24 @@ dasd_device_t * ...@@ -203,20 +203,24 @@ dasd_device_t *
dasd_alloc_device(dasd_devmap_t *devmap) dasd_alloc_device(dasd_devmap_t *devmap)
{ {
dasd_device_t *device; dasd_device_t *device;
struct gendisk *gdp;
int rc; int rc;
/* Make sure the gendisk structure for this device exists. */
while (dasd_gendisk_from_devindex(devmap->devindex) == NULL) {
rc = dasd_gendisk_new_major();
if (rc)
return ERR_PTR(rc);
}
device = kmalloc(sizeof (dasd_device_t), GFP_ATOMIC); device = kmalloc(sizeof (dasd_device_t), GFP_ATOMIC);
if (device == NULL) if (device == NULL)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
memset(device, 0, sizeof (dasd_device_t)); memset(device, 0, sizeof (dasd_device_t));
/* Get devinfo from the common io layer. */
rc = get_dev_info_by_devno(devmap->devno, &device->devinfo);
if (rc) {
kfree(device);
return ERR_PTR(rc);
}
DBF_EVENT(DBF_NOTICE, "got devinfo CU-type %04x and dev-type %04x",
device->devinfo.sid_data.cu_type,
device->devinfo.sid_data.dev_type);
/* Get two pages for normal block device operations. */ /* Get two pages for normal block device operations. */
device->ccw_mem = (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA, 1); device->ccw_mem = (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA, 1);
if (device->ccw_mem == NULL) { if (device->ccw_mem == NULL) {
...@@ -231,17 +235,15 @@ dasd_alloc_device(dasd_devmap_t *devmap) ...@@ -231,17 +235,15 @@ dasd_alloc_device(dasd_devmap_t *devmap)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
/* Get devinfo from the common io layer. */ /* Allocate gendisk structure for device. */
rc = get_dev_info_by_devno(devmap->devno, &device->devinfo); gdp = dasd_gendisk_alloc(device->name, devmap->devindex);
if (rc) { if (IS_ERR(gdp)) {
free_page((unsigned long) device->erp_mem); free_page((unsigned long) device->erp_mem);
free_pages((unsigned long) device->ccw_mem, 1); free_pages((unsigned long) device->ccw_mem, 1);
kfree(device); kfree(device);
return ERR_PTR(rc); return (dasd_device_t *) gdp;
} }
DBF_EVENT(DBF_NOTICE, "got devinfo CU-type %04x and dev-type %04x", device->gdp = gdp;
device->devinfo.sid_data.cu_type,
device->devinfo.sid_data.dev_type);
dasd_init_chunklist(&device->ccw_chunks, device->ccw_mem, PAGE_SIZE*2); dasd_init_chunklist(&device->ccw_chunks, device->ccw_mem, PAGE_SIZE*2);
dasd_init_chunklist(&device->erp_chunks, device->erp_mem, PAGE_SIZE); dasd_init_chunklist(&device->erp_chunks, device->erp_mem, PAGE_SIZE);
...@@ -268,6 +270,7 @@ dasd_free_device(dasd_device_t *device) ...@@ -268,6 +270,7 @@ dasd_free_device(dasd_device_t *device)
kfree(device->private); kfree(device->private);
free_page((unsigned long) device->erp_mem); free_page((unsigned long) device->erp_mem);
free_pages((unsigned long) device->ccw_mem, 1); free_pages((unsigned long) device->ccw_mem, 1);
dasd_gendisk_free(device->gdp);
kfree(device); kfree(device);
} }
...@@ -278,21 +281,22 @@ static inline int ...@@ -278,21 +281,22 @@ static inline int
dasd_state_new_to_known(dasd_device_t *device) dasd_state_new_to_known(dasd_device_t *device)
{ {
char buffer[5]; char buffer[5];
struct gendisk *gdp;
dasd_devmap_t *devmap; dasd_devmap_t *devmap;
umode_t devfs_perm; umode_t devfs_perm;
devfs_handle_t dir; devfs_handle_t dir;
int minor, rc; int major, minor, rc;
devmap = dasd_devmap_from_devno(device->devinfo.devno); devmap = dasd_devmap_from_devno(device->devinfo.devno);
if (devmap == NULL) if (devmap == NULL)
return -ENODEV; return -ENODEV;
gdp = dasd_gendisk_from_devindex(devmap->devindex); major = dasd_gendisk_index_major(devmap->devindex);
if (gdp == NULL) if (major < 0)
return -ENODEV; return -ENODEV;
/* Set kdev and the device name. */ minor = devmap->devindex % DASD_PER_MAJOR;
device->kdev = mk_kdev(gdp->major, gdp->first_minor);
strcpy(device->name, gdp->disk_name); /* Set bdev and the device name. */
device->bdev = bdget(MKDEV(major, minor << DASD_PARTN_BITS));
strcpy(device->name, device->gdp->disk_name);
/* Find a discipline for the device. */ /* Find a discipline for the device. */
rc = dasd_find_disc(device); rc = dasd_find_disc(device);
...@@ -302,14 +306,13 @@ dasd_state_new_to_known(dasd_device_t *device) ...@@ -302,14 +306,13 @@ dasd_state_new_to_known(dasd_device_t *device)
/* Add a proc directory and the dasd device entry to devfs. */ /* Add a proc directory and the dasd device entry to devfs. */
sprintf(buffer, "%04x", device->devinfo.devno); sprintf(buffer, "%04x", device->devinfo.devno);
dir = devfs_mk_dir(dasd_devfs_handle, buffer, device); dir = devfs_mk_dir(dasd_devfs_handle, buffer, device);
gdp->de = dir; device->gdp->de = dir;
if (devmap->features & DASD_FEATURE_READONLY) if (devmap->features & DASD_FEATURE_READONLY)
devfs_perm = S_IFBLK | S_IRUSR; devfs_perm = S_IFBLK | S_IRUSR;
else else
devfs_perm = S_IFBLK | S_IRUSR | S_IWUSR; devfs_perm = S_IFBLK | S_IRUSR | S_IWUSR;
device->devfs_entry = devfs_register(dir, "device", DEVFS_FL_DEFAULT, device->devfs_entry = devfs_register(dir, "device", DEVFS_FL_DEFAULT,
major(device->kdev), major, minor << DASD_PARTN_BITS,
minor(device->kdev),
devfs_perm, devfs_perm,
&dasd_device_operations, NULL); &dasd_device_operations, NULL);
device->state = DASD_STATE_KNOWN; device->state = DASD_STATE_KNOWN;
...@@ -322,17 +325,25 @@ dasd_state_new_to_known(dasd_device_t *device) ...@@ -322,17 +325,25 @@ dasd_state_new_to_known(dasd_device_t *device)
static inline void static inline void
dasd_state_known_to_new(dasd_device_t * device) dasd_state_known_to_new(dasd_device_t * device)
{ {
dasd_devmap_t *devmap = dasd_devmap_from_devno(device->devinfo.devno); dasd_devmap_t *devmap;
struct gendisk *gdp = dasd_gendisk_from_devindex(devmap->devindex); struct block_device *bdev;
if (gdp == NULL) int minor;
return;
devmap = dasd_devmap_from_devno(device->devinfo.devno);
minor = devmap->devindex % DASD_PER_MAJOR;
/* Remove device entry and devfs directory. */ /* Remove device entry and devfs directory. */
devfs_unregister(device->devfs_entry); devfs_unregister(device->devfs_entry);
devfs_unregister(gdp->de); devfs_unregister(device->gdp->de);
/* Forget the discipline information. */ /* Forget the discipline information. */
device->discipline = NULL; device->discipline = NULL;
device->state = DASD_STATE_NEW; device->state = DASD_STATE_NEW;
/* Forget the block device */
bdev = device->bdev;
device->bdev = NULL;
bdput(bdev);
} }
/* /*
...@@ -418,6 +429,17 @@ dasd_state_accept_to_basic(dasd_device_t * device) ...@@ -418,6 +429,17 @@ dasd_state_accept_to_basic(dasd_device_t * device)
device->state = DASD_STATE_BASIC; device->state = DASD_STATE_BASIC;
} }
/*
* get the kdev_t of a device
* FIXME: remove this when no longer needed
*/
static inline kdev_t
dasd_partition_to_kdev_t(dasd_device_t *device, unsigned int partition)
{
return to_kdev_t(device->bdev->bd_dev+partition);
}
/* /*
* Setup block device. * Setup block device.
*/ */
...@@ -425,15 +447,12 @@ static inline int ...@@ -425,15 +447,12 @@ static inline int
dasd_state_accept_to_ready(dasd_device_t * device) dasd_state_accept_to_ready(dasd_device_t * device)
{ {
dasd_devmap_t *devmap; dasd_devmap_t *devmap;
int major, minor;
int rc, i; int rc, i;
devmap = dasd_devmap_from_devno(device->devinfo.devno); devmap = dasd_devmap_from_devno(device->devinfo.devno);
if (devmap->features & DASD_FEATURE_READONLY) { if (devmap->features & DASD_FEATURE_READONLY) {
major = major(device->kdev);
minor = minor(device->kdev);
for (i = 0; i < (1 << DASD_PARTN_BITS); i++) for (i = 0; i < (1 << DASD_PARTN_BITS); i++)
set_device_ro(mk_kdev(major, minor+i), 1); set_device_ro(dasd_partition_to_kdev_t(device, i), 1);
DEV_MESSAGE (KERN_WARNING, device, "%s", DEV_MESSAGE (KERN_WARNING, device, "%s",
"setting read-only mode "); "setting read-only mode ");
} }
...@@ -1539,11 +1558,9 @@ __dasd_process_ccw_queue(dasd_device_t * device, struct list_head *final_queue) ...@@ -1539,11 +1558,9 @@ __dasd_process_ccw_queue(dasd_device_t * device, struct list_head *final_queue)
goto restart; goto restart;
} }
/* Dechain request from device request queue ... */ /* Rechain request on device device request queue */
cqr->endclk = get_clock(); cqr->endclk = get_clock();
list_del(&cqr->list); list_move_tail(&cqr->list, final_queue);
/* ... and add it to list of final requests. */
list_add_tail(&cqr->list, final_queue);
} }
} }
...@@ -1572,6 +1589,10 @@ __dasd_process_blk_queue(dasd_device_t * device) ...@@ -1572,6 +1589,10 @@ __dasd_process_blk_queue(dasd_device_t * device)
dasd_ccw_req_t *cqr; dasd_ccw_req_t *cqr;
int nr_queued; int nr_queued;
/* No bdev, no queue. */
bdev = device->bdev;
if (!bdev)
return;
queue = device->request_queue; queue = device->request_queue;
/* No queue ? Then there is nothing to do. */ /* No queue ? Then there is nothing to do. */
if (queue == NULL) if (queue == NULL)
...@@ -1594,9 +1615,6 @@ __dasd_process_blk_queue(dasd_device_t * device) ...@@ -1594,9 +1615,6 @@ __dasd_process_blk_queue(dasd_device_t * device)
if (cqr->status == DASD_CQR_QUEUED) if (cqr->status == DASD_CQR_QUEUED)
nr_queued++; nr_queued++;
} }
bdev = bdget(kdev_t_to_nr(device->kdev));
if (!bdev)
return;
while (!blk_queue_plugged(queue) && while (!blk_queue_plugged(queue) &&
!blk_queue_empty(queue) && !blk_queue_empty(queue) &&
nr_queued < DASD_CHANQ_MAX_SIZE) { nr_queued < DASD_CHANQ_MAX_SIZE) {
...@@ -1628,7 +1646,6 @@ __dasd_process_blk_queue(dasd_device_t * device) ...@@ -1628,7 +1646,6 @@ __dasd_process_blk_queue(dasd_device_t * device)
dasd_profile_start(device, cqr, req); dasd_profile_start(device, cqr, req);
nr_queued++; nr_queued++;
} }
bdput(bdev);
} }
/* /*
...@@ -1707,11 +1724,9 @@ dasd_flush_ccw_queue(dasd_device_t * device, int all) ...@@ -1707,11 +1724,9 @@ dasd_flush_ccw_queue(dasd_device_t * device, int all)
__dasd_process_erp(device, cqr); __dasd_process_erp(device, cqr);
continue; continue;
} }
/* Dechain request from device request queue ... */ /* Rechain request on device request queue */
cqr->endclk = get_clock(); cqr->endclk = get_clock();
list_del(&cqr->list); list_move_tail(&cqr->list, &flush_queue);
/* ... and add it to list of flushed requests. */
list_add_tail(&cqr->list, &flush_queue);
} }
spin_unlock_irq(get_irq_lock(device->devinfo.irq)); spin_unlock_irq(get_irq_lock(device->devinfo.irq));
/* Now call the callback function of flushed requests */ /* Now call the callback function of flushed requests */
......
...@@ -448,6 +448,15 @@ dasd_devmap_from_kdev(kdev_t kdev) ...@@ -448,6 +448,15 @@ dasd_devmap_from_kdev(kdev_t kdev)
return dasd_devmap_from_devindex(devindex); return dasd_devmap_from_devindex(devindex);
} }
/*
* Find the devmap for a device corresponding to a block_device.
*/
dasd_devmap_t *
dasd_devmap_from_bdev(struct block_device *bdev)
{
return dasd_devmap_from_kdev(to_kdev_t(bdev->bd_dev));
}
/* /*
* Find the device structure for device number devno. If it does not * Find the device structure for device number devno. If it does not
* exists yet, allocate it. Increase the reference counter in the device * exists yet, allocate it. Increase the reference counter in the device
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/hdreg.h> /* HDIO_GETGEO */ #include <linux/hdreg.h> /* HDIO_GETGEO */
#include <linux/bio.h>
#include <asm/dasd.h> #include <asm/dasd.h>
#include <asm/debug.h> #include <asm/debug.h>
...@@ -53,31 +54,6 @@ typedef struct dasd_diag_req_t { ...@@ -53,31 +54,6 @@ typedef struct dasd_diag_req_t {
diag_bio_t bio[0]; diag_bio_t bio[0];
} dasd_diag_req_t; } dasd_diag_req_t;
static __inline__ int
dia210(void *devchar)
{
int rc;
__asm__ __volatile__(" diag %1,0,0x210\n"
"0: ipm %0\n"
" srl %0,28\n"
"1:\n"
".section .fixup,\"ax\"\n"
"2: lhi %0,3\n"
" bras 1,3f\n"
" .long 1b\n"
"3: l 1,0(1)\n"
" br 1\n"
".previous\n"
".section __ex_table,\"a\"\n"
" .align 4\n"
" .long 0b,2b\n" ".previous\n":"=d"(rc)
:"d"((void *) __pa(devchar))
:"1");
return rc;
}
static __inline__ int static __inline__ int
dia250(void *iob, int cmd) dia250(void *iob, int cmd)
{ {
...@@ -155,7 +131,7 @@ dasd_start_diag(dasd_ccw_req_t * cqr) ...@@ -155,7 +131,7 @@ dasd_start_diag(dasd_ccw_req_t * cqr)
private->iob.key = 0; private->iob.key = 0;
private->iob.flags = 2; /* do asynchronous io */ private->iob.flags = 2; /* do asynchronous io */
private->iob.block_count = dreq->block_count; private->iob.block_count = dreq->block_count;
private->iob.interrupt_params = (u32) cqr; private->iob.interrupt_params = (u32)(addr_t) cqr;
private->iob.bio_list = __pa(dreq->bio); private->iob.bio_list = __pa(dreq->bio);
cqr->startclk = get_clock(); cqr->startclk = get_clock();
...@@ -196,21 +172,21 @@ dasd_ext_handler(struct pt_regs *regs, __u16 code) ...@@ -196,21 +172,21 @@ dasd_ext_handler(struct pt_regs *regs, __u16 code)
ip = S390_lowcore.ext_params; ip = S390_lowcore.ext_params;
cpu = smp_processor_id(); cpu = smp_processor_id();
irq_enter(cpu, -1); irq_enter();
if (!ip) { /* no intparm: unsolicited interrupt */ if (!ip) { /* no intparm: unsolicited interrupt */
MESSAGE(KERN_DEBUG, "%s", "caught unsolicited interrupt"); MESSAGE(KERN_DEBUG, "%s", "caught unsolicited interrupt");
irq_exit(cpu, -1); irq_exit();
return; return;
} }
cqr = (dasd_ccw_req_t *) ip; cqr = (dasd_ccw_req_t *)(addr_t) ip;
device = (dasd_device_t *) cqr->device; device = (dasd_device_t *) cqr->device;
if (strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) { if (strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) {
DEV_MESSAGE(KERN_WARNING, device, DEV_MESSAGE(KERN_WARNING, device,
" magic number of dasd_ccw_req_t 0x%08X doesn't" " magic number of dasd_ccw_req_t 0x%08X doesn't"
" match discipline 0x%08X", " match discipline 0x%08X",
cqr->magic, *(int *) (&device->discipline->name)); cqr->magic, *(int *) (&device->discipline->name));
irq_exit(cpu, -1); irq_exit();
return; return;
} }
...@@ -244,8 +220,7 @@ dasd_ext_handler(struct pt_regs *regs, __u16 code) ...@@ -244,8 +220,7 @@ dasd_ext_handler(struct pt_regs *regs, __u16 code)
dasd_schedule_bh(device); dasd_schedule_bh(device);
spin_unlock_irqrestore(get_irq_lock(device->devinfo.irq), flags); spin_unlock_irqrestore(get_irq_lock(device->devinfo.irq), flags);
irq_exit(cpu, -1); irq_exit();
} }
static int static int
...@@ -273,7 +248,7 @@ dasd_diag_check_device(dasd_device_t *device) ...@@ -273,7 +248,7 @@ dasd_diag_check_device(dasd_device_t *device)
rdc_data->dev_nr = device->devinfo.devno; rdc_data->dev_nr = device->devinfo.devno;
rdc_data->rdc_len = sizeof (dasd_diag_characteristics_t); rdc_data->rdc_len = sizeof (dasd_diag_characteristics_t);
rc = dia210(rdc_data); rc = diag210((diag210_t *) rdc_data);
if (rc) if (rc)
return -ENOTSUPP; return -ENOTSUPP;
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/hdreg.h> /* HDIO_GETGEO */ #include <linux/hdreg.h> /* HDIO_GETGEO */
#include <linux/bio.h>
#include <asm/debug.h> #include <asm/debug.h>
#include <asm/idals.h> #include <asm/idals.h>
...@@ -69,7 +70,6 @@ typedef struct dasd_eckd_private_t { ...@@ -69,7 +70,6 @@ typedef struct dasd_eckd_private_t {
attrib_data_t attrib; /* e.g. cache operations */ attrib_data_t attrib; /* e.g. cache operations */
} dasd_eckd_private_t; } dasd_eckd_private_t;
#ifdef CONFIG_DASD_DYNAMIC
static static
devreg_t dasd_eckd_known_devices[] = { devreg_t dasd_eckd_known_devices[] = {
{ {
...@@ -94,7 +94,6 @@ devreg_t dasd_eckd_known_devices[] = { ...@@ -94,7 +94,6 @@ devreg_t dasd_eckd_known_devices[] = {
oper_func:dasd_oper_handler oper_func:dasd_oper_handler
} }
}; };
#endif
static const int sizes_trk0[] = { 28, 148, 84 }; static const int sizes_trk0[] = { 28, 148, 84 };
#define LABEL_SIZE 140 #define LABEL_SIZE 140
...@@ -1092,7 +1091,8 @@ dasd_eckd_fill_info(dasd_device_t * device, dasd_information2_t * info) ...@@ -1092,7 +1091,8 @@ dasd_eckd_fill_info(dasd_device_t * device, dasd_information2_t * info)
* Buils a channel programm to releases a prior reserved * Buils a channel programm to releases a prior reserved
* (see dasd_eckd_reserve) device. * (see dasd_eckd_reserve) device.
*/ */
static int dasd_eckd_release(void *inp, int no, long args) static int
dasd_eckd_release(struct block_device *bdev, int no, long args)
{ {
dasd_devmap_t *devmap; dasd_devmap_t *devmap;
dasd_device_t *device; dasd_device_t *device;
...@@ -1101,7 +1101,7 @@ static int dasd_eckd_release(void *inp, int no, long args) ...@@ -1101,7 +1101,7 @@ static int dasd_eckd_release(void *inp, int no, long args)
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EACCES; return -EACCES;
devmap = dasd_devmap_from_kdev(((struct inode *) inp)->i_rdev); devmap = dasd_devmap_from_bdev(bdev);
device = (devmap != NULL) ? device = (devmap != NULL) ?
dasd_get_device(devmap) : ERR_PTR(-ENODEV); dasd_get_device(devmap) : ERR_PTR(-ENODEV);
if (IS_ERR(device)) if (IS_ERR(device))
...@@ -1134,7 +1134,8 @@ static int dasd_eckd_release(void *inp, int no, long args) ...@@ -1134,7 +1134,8 @@ static int dasd_eckd_release(void *inp, int no, long args)
* 'timeout the request'. This leads to an terminate IO if * 'timeout the request'. This leads to an terminate IO if
* the interrupt is outstanding for a certain time. * the interrupt is outstanding for a certain time.
*/ */
static int dasd_eckd_reserve(void *inp, int no, long args) static int
dasd_eckd_reserve(struct block_device *bdev, int no, long args)
{ {
dasd_devmap_t *devmap; dasd_devmap_t *devmap;
dasd_device_t *device; dasd_device_t *device;
...@@ -1143,7 +1144,7 @@ static int dasd_eckd_reserve(void *inp, int no, long args) ...@@ -1143,7 +1144,7 @@ static int dasd_eckd_reserve(void *inp, int no, long args)
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EACCES; return -EACCES;
devmap = dasd_devmap_from_kdev(((struct inode *) inp)->i_rdev); devmap = dasd_devmap_from_bdev(bdev);
device = (devmap != NULL) ? device = (devmap != NULL) ?
dasd_get_device(devmap) : ERR_PTR(-ENODEV); dasd_get_device(devmap) : ERR_PTR(-ENODEV);
if (IS_ERR(device)) if (IS_ERR(device))
...@@ -1168,7 +1169,7 @@ static int dasd_eckd_reserve(void *inp, int no, long args) ...@@ -1168,7 +1169,7 @@ static int dasd_eckd_reserve(void *inp, int no, long args)
if (rc == -EIO) { if (rc == -EIO) {
/* Request got an eror or has been timed out. */ /* Request got an eror or has been timed out. */
dasd_eckd_release(inp, no, args); dasd_eckd_release(bdev, no, args);
} }
dasd_kfree_request(cqr, cqr->device); dasd_kfree_request(cqr, cqr->device);
dasd_put_device(devmap); dasd_put_device(devmap);
...@@ -1180,7 +1181,8 @@ static int dasd_eckd_reserve(void *inp, int no, long args) ...@@ -1180,7 +1181,8 @@ static int dasd_eckd_reserve(void *inp, int no, long args)
* Buils a channel programm to break a device's reservation. * Buils a channel programm to break a device's reservation.
* (unconditional reserve) * (unconditional reserve)
*/ */
static int dasd_eckd_steal_lock(void *inp, int no, long args) static int
dasd_eckd_steal_lock(struct block_device *bdev, int no, long args)
{ {
dasd_devmap_t *devmap; dasd_devmap_t *devmap;
dasd_device_t *device; dasd_device_t *device;
...@@ -1189,7 +1191,7 @@ static int dasd_eckd_steal_lock(void *inp, int no, long args) ...@@ -1189,7 +1191,7 @@ static int dasd_eckd_steal_lock(void *inp, int no, long args)
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EACCES; return -EACCES;
devmap = dasd_devmap_from_kdev(((struct inode *) inp)->i_rdev); devmap = dasd_devmap_from_bdev(bdev);
device = (devmap != NULL) ? device = (devmap != NULL) ?
dasd_get_device(devmap) : ERR_PTR(-ENODEV); dasd_get_device(devmap) : ERR_PTR(-ENODEV);
if (IS_ERR(device)) if (IS_ERR(device))
...@@ -1213,7 +1215,7 @@ static int dasd_eckd_steal_lock(void *inp, int no, long args) ...@@ -1213,7 +1215,7 @@ static int dasd_eckd_steal_lock(void *inp, int no, long args)
if (rc == -EIO) { if (rc == -EIO) {
/* Request got an eror or has been timed out. */ /* Request got an eror or has been timed out. */
dasd_eckd_release(inp, no, args); dasd_eckd_release(bdev, no, args);
} }
dasd_kfree_request(cqr, cqr->device); dasd_kfree_request(cqr, cqr->device);
dasd_put_device(devmap); dasd_put_device(devmap);
...@@ -1223,7 +1225,8 @@ static int dasd_eckd_steal_lock(void *inp, int no, long args) ...@@ -1223,7 +1225,8 @@ static int dasd_eckd_steal_lock(void *inp, int no, long args)
/* /*
* Read performance statistics * Read performance statistics
*/ */
static int dasd_eckd_performance(void *inp, int no, long args) static int
dasd_eckd_performance(struct block_device *bdev, int no, long args)
{ {
dasd_devmap_t *devmap; dasd_devmap_t *devmap;
dasd_device_t *device; dasd_device_t *device;
...@@ -1233,7 +1236,7 @@ static int dasd_eckd_performance(void *inp, int no, long args) ...@@ -1233,7 +1236,7 @@ static int dasd_eckd_performance(void *inp, int no, long args)
ccw1_t *ccw; ccw1_t *ccw;
int rc; int rc;
devmap = dasd_devmap_from_kdev(((struct inode *) inp)->i_rdev); devmap = dasd_devmap_from_bdev(bdev);
device = (devmap != NULL) ? device = (devmap != NULL) ?
dasd_get_device(devmap) : ERR_PTR(-ENODEV); dasd_get_device(devmap) : ERR_PTR(-ENODEV);
if (IS_ERR(device)) if (IS_ERR(device))
...@@ -1292,7 +1295,8 @@ static int dasd_eckd_performance(void *inp, int no, long args) ...@@ -1292,7 +1295,8 @@ static int dasd_eckd_performance(void *inp, int no, long args)
* Set attributes (cache operations) * Set attributes (cache operations)
* Stores the attributes for cache operation to be used in Define Extend (DE). * Stores the attributes for cache operation to be used in Define Extend (DE).
*/ */
static int dasd_eckd_set_attrib(void *inp, int no, long args) static int
dasd_eckd_set_attrib(struct block_device *bdev, int no, long args)
{ {
dasd_devmap_t *devmap; dasd_devmap_t *devmap;
dasd_device_t *device; dasd_device_t *device;
...@@ -1304,7 +1308,7 @@ static int dasd_eckd_set_attrib(void *inp, int no, long args) ...@@ -1304,7 +1308,7 @@ static int dasd_eckd_set_attrib(void *inp, int no, long args)
if (!args) if (!args)
return -EINVAL; return -EINVAL;
devmap = dasd_devmap_from_kdev(((struct inode *) inp)->i_rdev); devmap = dasd_devmap_from_bdev(bdev);
device = (devmap != NULL) ? device = (devmap != NULL) ?
dasd_get_device(devmap) : ERR_PTR(-ENODEV); dasd_get_device(devmap) : ERR_PTR(-ENODEV);
if (IS_ERR(device)) if (IS_ERR(device))
...@@ -1452,10 +1456,8 @@ dasd_eckd_init(void) ...@@ -1452,10 +1456,8 @@ dasd_eckd_init(void)
ASCEBC(dasd_eckd_discipline.ebcname, 4); ASCEBC(dasd_eckd_discipline.ebcname, 4);
dasd_discipline_add(&dasd_eckd_discipline); dasd_discipline_add(&dasd_eckd_discipline);
#ifdef CONFIG_DASD_DYNAMIC
for (i = 0; i < sizeof(dasd_eckd_known_devices)/sizeof(devreg_t); i++) for (i = 0; i < sizeof(dasd_eckd_known_devices)/sizeof(devreg_t); i++)
s390_device_register(&dasd_eckd_known_devices[i]); s390_device_register(&dasd_eckd_known_devices[i]);
#endif
return 0; return 0;
} }
...@@ -1464,10 +1466,8 @@ dasd_eckd_cleanup(void) ...@@ -1464,10 +1466,8 @@ dasd_eckd_cleanup(void)
{ {
int i; int i;
#ifdef CONFIG_DASD_DYNAMIC
for (i = 0; i < sizeof(dasd_eckd_known_devices)/sizeof(devreg_t); i++) for (i = 0; i < sizeof(dasd_eckd_known_devices)/sizeof(devreg_t); i++)
s390_device_unregister(&dasd_eckd_known_devices[i]); s390_device_unregister(&dasd_eckd_known_devices[i]);
#endif /* CONFIG_DASD_DYNAMIC */
dasd_discipline_del(&dasd_eckd_discipline); dasd_discipline_del(&dasd_eckd_discipline);
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/hdreg.h> /* HDIO_GETGEO */ #include <linux/hdreg.h> /* HDIO_GETGEO */
#include <linux/bio.h>
#include <asm/idals.h> #include <asm/idals.h>
#include <asm/ebcdic.h> #include <asm/ebcdic.h>
...@@ -43,7 +44,6 @@ typedef struct dasd_fba_private_t { ...@@ -43,7 +44,6 @@ typedef struct dasd_fba_private_t {
dasd_fba_characteristics_t rdc_data; dasd_fba_characteristics_t rdc_data;
} dasd_fba_private_t; } dasd_fba_private_t;
#ifdef CONFIG_DASD_DYNAMIC
static static
devreg_t dasd_fba_known_devices[] = { devreg_t dasd_fba_known_devices[] = {
{ {
...@@ -59,7 +59,6 @@ devreg_t dasd_fba_known_devices[] = { ...@@ -59,7 +59,6 @@ devreg_t dasd_fba_known_devices[] = {
oper_func:dasd_oper_handler oper_func:dasd_oper_handler
} }
}; };
#endif
static inline void static inline void
define_extent(ccw1_t * ccw, DE_fba_data_t *data, int rw, define_extent(ccw1_t * ccw, DE_fba_data_t *data, int rw,
...@@ -417,10 +416,8 @@ dasd_fba_init(void) ...@@ -417,10 +416,8 @@ dasd_fba_init(void)
ASCEBC(dasd_fba_discipline.ebcname, 4); ASCEBC(dasd_fba_discipline.ebcname, 4);
dasd_discipline_add(&dasd_fba_discipline); dasd_discipline_add(&dasd_fba_discipline);
#ifdef CONFIG_DASD_DYNAMIC
for (i = 0; i < sizeof(dasd_fba_known_devices) / sizeof(devreg_t); i++) for (i = 0; i < sizeof(dasd_fba_known_devices) / sizeof(devreg_t); i++)
s390_device_register(&dasd_fba_known_devices[i]); s390_device_register(&dasd_fba_known_devices[i]);
#endif
return 0; return 0;
} }
...@@ -429,10 +426,8 @@ dasd_fba_cleanup(void) ...@@ -429,10 +426,8 @@ dasd_fba_cleanup(void)
{ {
int i; int i;
#ifdef CONFIG_DASD_DYNAMIC
for (i = 0; i < sizeof(dasd_fba_known_devices) / sizeof(devreg_t); i++) for (i = 0; i < sizeof(dasd_fba_known_devices) / sizeof(devreg_t); i++)
s390_device_unregister(&dasd_fba_known_devices[i]); s390_device_unregister(&dasd_fba_known_devices[i]);
#endif
dasd_discipline_del(&dasd_fba_discipline); dasd_discipline_del(&dasd_fba_discipline);
} }
......
...@@ -33,7 +33,6 @@ static struct list_head dasd_major_info = LIST_HEAD_INIT(dasd_major_info); ...@@ -33,7 +33,6 @@ static struct list_head dasd_major_info = LIST_HEAD_INIT(dasd_major_info);
struct major_info { struct major_info {
struct list_head list; struct list_head list;
int major; int major;
struct gendisk disks[DASD_PER_MAJOR];
}; };
/* /*
...@@ -65,12 +64,8 @@ static int ...@@ -65,12 +64,8 @@ static int
dasd_register_major(int major) dasd_register_major(int major)
{ {
struct major_info *mi; struct major_info *mi;
int new_major, rc; int new_major;
struct list_head *l;
int index;
int i;
rc = 0;
/* Allocate major info structure. */ /* Allocate major info structure. */
mi = kmalloc(sizeof(struct major_info), GFP_KERNEL); mi = kmalloc(sizeof(struct major_info), GFP_KERNEL);
...@@ -79,66 +74,39 @@ dasd_register_major(int major) ...@@ -79,66 +74,39 @@ dasd_register_major(int major)
MESSAGE(KERN_WARNING, "%s", MESSAGE(KERN_WARNING, "%s",
"Cannot get memory to allocate another " "Cannot get memory to allocate another "
"major number"); "major number");
rc = -ENOMEM; return -ENOMEM;
goto out_error;
} }
/* Register block device. */ /* Register block device. */
new_major = register_blkdev(major, "dasd", &dasd_device_operations); new_major = register_blkdev(major, "dasd", &dasd_device_operations);
if (new_major < 0) { if (new_major < 0) {
MESSAGE(KERN_WARNING, MESSAGE(KERN_WARNING,
"Cannot register to major no %d, rc = %d", major, rc); "Cannot register to major no %d, rc = %d",
rc = new_major; major, new_major);
goto out_error; kfree(mi);
return new_major;
} }
if (major != 0) if (major != 0)
new_major = major; new_major = major;
/* Initialize major info structure. */ /* Initialize major info structure. */
memset(mi, 0, sizeof(struct major_info));
mi->major = new_major; mi->major = new_major;
for (i = 0; i < DASD_PER_MAJOR; i++) {
struct gendisk *disk = mi->disks + i;
disk->major = new_major;
disk->first_minor = i << DASD_PARTN_BITS;
disk->minor_shift = DASD_PARTN_BITS;
disk->fops = &dasd_device_operations;
disk->flags = GENHD_FL_DEVFS;
}
/* Setup block device pointers for the new major. */ /* Setup block device pointers for the new major. */
blk_dev[new_major].queue = dasd_get_queue; blk_dev[new_major].queue = dasd_get_queue;
/* Insert the new major info structure into dasd_major_info list. */
spin_lock(&dasd_major_lock); spin_lock(&dasd_major_lock);
index = 0;
list_for_each(l, &dasd_major_info)
index += DASD_PER_MAJOR;
for (i = 0; i < DASD_PER_MAJOR; i++, index++) {
name = mi->disks[i].disk_name;
sprintf(name, "dasd");
name += 4;
if (index > 701)
*name++ = 'a' + (((index - 702) / 676) % 26);
if (index > 25)
*name++ = 'a' + (((index - 26) / 26) % 26);
sprintf(name, "%c", 'a' + (index % 26));
}
list_add_tail(&mi->list, &dasd_major_info); list_add_tail(&mi->list, &dasd_major_info);
spin_unlock(&dasd_major_lock); spin_unlock(&dasd_major_lock);
return 0; return 0;
/* Something failed. Do the cleanup and return rc. */
out_error:
/* We rely on kfree to do the != NULL check. */
kfree(mi);
return rc;
} }
static void static void
dasd_unregister_major(struct major_info * mi) dasd_unregister_major(struct major_info * mi)
{ {
int major, rc; int rc;
if (mi == NULL) if (mi == NULL)
return; return;
...@@ -149,99 +117,177 @@ dasd_unregister_major(struct major_info * mi) ...@@ -149,99 +117,177 @@ dasd_unregister_major(struct major_info * mi)
spin_unlock(&dasd_major_lock); spin_unlock(&dasd_major_lock);
/* Clear block device pointers. */ /* Clear block device pointers. */
major = mi->major; blk_dev[mi->major].queue = NULL;
blk_dev[major].queue = NULL;
rc = unregister_blkdev(major, "dasd"); rc = unregister_blkdev(mi->major, "dasd");
if (rc < 0) if (rc < 0)
MESSAGE(KERN_WARNING, MESSAGE(KERN_WARNING,
"Cannot unregister from major no %d, rc = %d", "Cannot unregister from major no %d, rc = %d",
major, rc); mi->major, rc);
/* Free memory. */ /* Free memory. */
kfree(mi); kfree(mi);
} }
/* /*
* Dynamically allocate a new major for dasd devices. * This one is needed for naming 18000+ possible dasd devices.
* dasda - dasdz : 26 devices
* dasdaa - dasdzz : 676 devices, added up = 702
* dasdaaa - dasdzzz : 17576 devices, added up = 18278
*/ */
int int
dasd_gendisk_new_major(void) dasd_device_name(char *str, int index, int partition)
{ {
int rc; int len;
rc = dasd_register_major(0); if (partition > DASD_PARTN_MASK)
if (rc) return -EINVAL;
DBF_EXC(DBF_ALERT, "%s", "out of major numbers!");
return rc; len = sprintf(str, "dasd");
if (index > 25) {
if (index > 701)
len += sprintf(str + len, "%c",
'a' + (((index - 702) / 676) % 26));
len += sprintf(str + len, "%c",
'a' + (((index - 26) / 26) % 26));
}
len += sprintf(str + len, "%c", 'a' + (index % 26));
if (partition)
len += sprintf(str + len, "%d", partition);
return 0;
} }
/* /*
* Return pointer to gendisk structure by kdev. * Allocate gendisk structure for devindex.
*/ */
static struct gendisk *dasd_gendisk_by_dev(kdev_t dev) struct gendisk *
dasd_gendisk_alloc(char *device_name, int devindex)
{ {
struct list_head *l; struct list_head *l;
struct major_info *mi; struct major_info *mi;
struct gendisk *gdp; struct gendisk *gdp;
int major = major(dev); struct hd_struct *gd_part;
int index, len, rc;
spin_lock(&dasd_major_lock);
gdp = NULL; /* Make sure the major for this device exists. */
list_for_each(l, &dasd_major_info) { mi = NULL;
mi = list_entry(l, struct major_info, list); while (1) {
if (mi->major == major) { spin_lock(&dasd_major_lock);
gdp = &mi->disks[minor(dev) >> DASD_PARTN_BITS]; index = devindex;
list_for_each(l, &dasd_major_info) {
mi = list_entry(l, struct major_info, list);
if (index < DASD_PER_MAJOR)
break;
index -= DASD_PER_MAJOR;
}
spin_unlock(&dasd_major_lock);
if (index < DASD_PER_MAJOR)
break; break;
rc = dasd_register_major(0);
if (rc) {
DBF_EXC(DBF_ALERT, "%s", "out of major numbers!");
return ERR_PTR(rc);
} }
} }
spin_unlock(&dasd_major_lock);
/* Allocate genhd structure and gendisk arrays. */
gdp = kmalloc(sizeof(struct gendisk), GFP_KERNEL);
gd_part = kmalloc(sizeof (struct hd_struct) << DASD_PARTN_BITS,
GFP_ATOMIC);
/* Check if one of the allocations failed. */
if (gdp == NULL || gd_part == NULL) {
/* We rely on kfree to do the != NULL check. */
kfree(gd_part);
kfree(gdp);
return ERR_PTR(-ENOMEM);
}
/* Initialize gendisk structure. */
memset(gdp, 0, sizeof(struct gendisk));
memcpy(gdp->disk_name, device_name, 16);
gdp->major = mi->major;
gdp->first_minor = index << DASD_PARTN_BITS;
gdp->minor_shift = DASD_PARTN_BITS;
gdp->part = gd_part;
gdp->fops = &dasd_device_operations;
/*
* Set device name.
* dasda - dasdz : 26 devices
* dasdaa - dasdzz : 676 devices, added up = 702
* dasdaaa - dasdzzz : 17576 devices, added up = 18278
*/
len = sprintf(device_name, "dasd");
if (devindex > 25) {
if (devindex > 701)
len += sprintf(device_name + len, "%c",
'a' + (((devindex - 702) / 676) % 26));
len += sprintf(device_name + len, "%c",
'a' + (((devindex - 26) / 26) % 26));
}
len += sprintf(device_name + len, "%c", 'a' + (devindex % 26));
/* Initialize the gendisk arrays. */
memset(gd_part, 0, sizeof (struct hd_struct) << DASD_PARTN_BITS);
return gdp; return gdp;
} }
/* /*
* Return pointer to gendisk structure by devindex. * Free gendisk structure for devindex.
*/ */
struct gendisk * void
dasd_gendisk_from_devindex(int devindex) dasd_gendisk_free(struct gendisk *gdp)
{
/* Free memory. */
kfree(gdp->part);
kfree(gdp);
}
/*
* Return devindex of first device using a specific major number.
*/
int dasd_gendisk_major_index(int major)
{ {
struct list_head *l; struct list_head *l;
struct major_info *mi; struct major_info *mi;
struct gendisk *gdp; int devindex, rc;
spin_lock(&dasd_major_lock); spin_lock(&dasd_major_lock);
gdp = NULL; rc = -EINVAL;
devindex = 0;
list_for_each(l, &dasd_major_info) { list_for_each(l, &dasd_major_info) {
mi = list_entry(l, struct major_info, list); mi = list_entry(l, struct major_info, list);
if (devindex < DASD_PER_MAJOR) { if (mi->major == major) {
gdp = &mi->disks[devindex]; rc = devindex;
break; break;
} }
devindex -= DASD_PER_MAJOR; devindex += DASD_PER_MAJOR;
} }
spin_unlock(&dasd_major_lock); spin_unlock(&dasd_major_lock);
return gdp; return rc;
} }
/* /*
* Return devindex of first device using a specifiy major number. * Return major number for device with device index devindex.
*/ */
int dasd_gendisk_major_index(int major) int dasd_gendisk_index_major(int devindex)
{ {
struct list_head *l; struct list_head *l;
struct major_info *mi; struct major_info *mi;
int devindex, rc; int rc;
spin_lock(&dasd_major_lock); spin_lock(&dasd_major_lock);
rc = -EINVAL; rc = -ENODEV;
devindex = 0;
list_for_each(l, &dasd_major_info) { list_for_each(l, &dasd_major_info) {
mi = list_entry(l, struct major_info, list); mi = list_entry(l, struct major_info, list);
if (mi->major == major) { if (devindex < DASD_PER_MAJOR) {
rc = devindex; rc = mi->major;
break; break;
} }
devindex += DASD_PER_MAJOR; devindex -= DASD_PER_MAJOR;
} }
spin_unlock(&dasd_major_lock); spin_unlock(&dasd_major_lock);
return rc; return rc;
...@@ -253,11 +299,9 @@ int dasd_gendisk_major_index(int major) ...@@ -253,11 +299,9 @@ int dasd_gendisk_major_index(int major)
void void
dasd_setup_partitions(dasd_device_t * device) dasd_setup_partitions(dasd_device_t * device)
{ {
struct gendisk *disk = dasd_gendisk_by_dev(device->kdev); /* Make the disk known. */
if (disk == NULL) set_capacity(device->gdp, device->blocks << device->s2b_shift);
return; add_disk(device->gdp);
set_capacity(disk, device->blocks << device->s2b_shift);
add_disk(disk);
} }
/* /*
...@@ -267,13 +311,7 @@ dasd_setup_partitions(dasd_device_t * device) ...@@ -267,13 +311,7 @@ dasd_setup_partitions(dasd_device_t * device)
void void
dasd_destroy_partitions(dasd_device_t * device) dasd_destroy_partitions(dasd_device_t * device)
{ {
struct gendisk *disk = dasd_gendisk_by_dev(device->kdev); del_gendisk(device->gdp);
int minor, i;
if (disk == NULL)
return;
del_gendisk(disk);
} }
int int
...@@ -294,6 +332,7 @@ void ...@@ -294,6 +332,7 @@ void
dasd_gendisk_exit(void) dasd_gendisk_exit(void)
{ {
struct list_head *l, *n; struct list_head *l, *n;
spin_lock(&dasd_major_lock); spin_lock(&dasd_major_lock);
list_for_each_safe(l, n, &dasd_major_info) list_for_each_safe(l, n, &dasd_major_info)
dasd_unregister_major(list_entry(l, struct major_info, list)); dasd_unregister_major(list_entry(l, struct major_info, list));
......
...@@ -64,12 +64,12 @@ ...@@ -64,12 +64,12 @@
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/s390dyn.h> #include <asm/s390dyn.h>
#define CONFIG_DASD_DYNAMIC
/* /*
* SECTION: Type definitions * SECTION: Type definitions
*/ */
typedef int (*dasd_ioctl_fn_t) (void *inp, int no, long args); struct dasd_device_t;
typedef int (*dasd_ioctl_fn_t) (struct block_device *bdev, int no, long args);
typedef struct { typedef struct {
struct list_head list; struct list_head list;
...@@ -139,9 +139,8 @@ do { \ ...@@ -139,9 +139,8 @@ do { \
/* messages to be written via klogd and dbf */ /* messages to be written via klogd and dbf */
#define DEV_MESSAGE(d_loglevel,d_device,d_string,d_args...)\ #define DEV_MESSAGE(d_loglevel,d_device,d_string,d_args...)\
do { \ do { \
printk(d_loglevel PRINTK_HEADER " /dev/%-7s(%3d:%3d),%04x@%02x: " \ printk(d_loglevel PRINTK_HEADER " %s,%04x@%02x: " \
d_string "\n", d_device->name, \ d_string "\n", bdevname(d_device->bdev), \
major(d_device->kdev), minor(d_device->kdev), \
d_device->devinfo.devno, d_device->devinfo.irq, \ d_device->devinfo.devno, d_device->devinfo.irq, \
d_args); \ d_args); \
DBF_DEV_EVENT(DBF_ALERT, d_device, d_string, d_args); \ DBF_DEV_EVENT(DBF_ALERT, d_device, d_string, d_args); \
...@@ -153,8 +152,6 @@ do { \ ...@@ -153,8 +152,6 @@ do { \
DBF_EVENT(DBF_ALERT, d_string, d_args); \ DBF_EVENT(DBF_ALERT, d_string, d_args); \
} while(0) } while(0)
struct dasd_device_t;
typedef struct dasd_ccw_req_t { typedef struct dasd_ccw_req_t {
unsigned int magic; /* Eye catcher */ unsigned int magic; /* Eye catcher */
struct list_head list; /* list_head for request queueing. */ struct list_head list; /* list_head for request queueing. */
...@@ -262,7 +259,8 @@ typedef struct dasd_discipline_t { ...@@ -262,7 +259,8 @@ typedef struct dasd_discipline_t {
typedef struct dasd_device_t { typedef struct dasd_device_t {
/* Block device stuff. */ /* Block device stuff. */
char name[16]; /* The device name in /dev. */ char name[16]; /* The device name in /dev. */
kdev_t kdev; struct block_device *bdev;
struct gendisk *gdp;
devfs_handle_t devfs_entry; devfs_handle_t devfs_entry;
request_queue_t *request_queue; request_queue_t *request_queue;
spinlock_t request_queue_lock; spinlock_t request_queue_lock;
...@@ -467,6 +465,7 @@ dasd_devmap_t *dasd_devmap_from_devno(int); ...@@ -467,6 +465,7 @@ dasd_devmap_t *dasd_devmap_from_devno(int);
dasd_devmap_t *dasd_devmap_from_devindex(int); dasd_devmap_t *dasd_devmap_from_devindex(int);
dasd_devmap_t *dasd_devmap_from_irq(int); dasd_devmap_t *dasd_devmap_from_irq(int);
dasd_devmap_t *dasd_devmap_from_kdev(kdev_t); dasd_devmap_t *dasd_devmap_from_kdev(kdev_t);
dasd_devmap_t *dasd_devmap_from_bdev(struct block_device *bdev);
dasd_device_t *dasd_get_device(dasd_devmap_t *); dasd_device_t *dasd_get_device(dasd_devmap_t *);
void dasd_put_device(dasd_devmap_t *); void dasd_put_device(dasd_devmap_t *);
...@@ -478,9 +477,10 @@ int dasd_add_range(int, int, int); ...@@ -478,9 +477,10 @@ int dasd_add_range(int, int, int);
/* externals in dasd_gendisk.c */ /* externals in dasd_gendisk.c */
int dasd_gendisk_init(void); int dasd_gendisk_init(void);
void dasd_gendisk_exit(void); void dasd_gendisk_exit(void);
int dasd_gendisk_new_major(void);
int dasd_gendisk_major_index(int); int dasd_gendisk_major_index(int);
struct gendisk *dasd_gendisk_from_devindex(int); int dasd_gendisk_index_major(int);
struct gendisk *dasd_gendisk_alloc(char *, int);
void dasd_gendisk_free(struct gendisk *);
void dasd_setup_partitions(dasd_device_t *); void dasd_setup_partitions(dasd_device_t *);
void dasd_destroy_partitions(dasd_device_t *); void dasd_destroy_partitions(dasd_device_t *);
......
This diff is collapsed.
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/version.h> #include <linux/version.h>
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/vmalloc.h>
#include <asm/debug.h> #include <asm/debug.h>
#include <asm/irq.h> #include <asm/irq.h>
...@@ -123,7 +124,7 @@ dasd_devices_write(struct file *file, const char *user_buf, ...@@ -123,7 +124,7 @@ dasd_devices_write(struct file *file, const char *user_buf,
} }
features = dasd_feature_list(str, &str); features = dasd_feature_list(str, &str);
/* Negative numbers in from/to/features indicate errors */ /* Negative numbers in from/to/features indicate errors */
if (from < 0 || to < 0 || features < 0) if (from < 0 || to < 0 || from > 65546 || to > 65536 || features < 0)
goto out_error; goto out_error;
if (add_or_set == 0) { if (add_or_set == 0) {
...@@ -152,10 +153,8 @@ static inline int ...@@ -152,10 +153,8 @@ static inline int
dasd_devices_print(dasd_devmap_t *devmap, char *str) dasd_devices_print(dasd_devmap_t *devmap, char *str)
{ {
dasd_device_t *device; dasd_device_t *device;
struct gendisk *gdp;
char buffer[7];
char *substr; char *substr;
int minor; int major, minor;
int len; int len;
device = dasd_get_device(devmap); device = dasd_get_device(devmap);
...@@ -169,11 +168,11 @@ dasd_devices_print(dasd_devmap_t *devmap, char *str) ...@@ -169,11 +168,11 @@ dasd_devices_print(dasd_devmap_t *devmap, char *str)
else else
len += sprintf(str + len, "(none)"); len += sprintf(str + len, "(none)");
/* Print kdev. */ /* Print kdev. */
gdp = dasd_gendisk_from_devindex(devmap->devindex); major = MAJOR(device->bdev->bd_dev);
minor = devmap->devindex % DASD_PER_MAJOR; minor = MINOR(device->bdev->bd_dev);
len += sprintf(str + len, " at (%3d:%3d)", gdp->major, minor); len += sprintf(str + len, " at (%3d:%3d)", major, minor);
/* Print device name. */ /* Print device name. */
len += sprintf(str + len, " is %-7s", gdp->disk_name); len += sprintf(str + len, " is %-7s", device->name);
/* Print devices features. */ /* Print devices features. */
substr = (devmap->features & DASD_FEATURE_READONLY) ? "(ro)" : " "; substr = (devmap->features & DASD_FEATURE_READONLY) ? "(ro)" : " ";
len += sprintf(str + len, "%4s: ", substr); len += sprintf(str + len, "%4s: ", substr);
......
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
* 12/06/01 DASD_API_VERSION 2 - binary compatible to 0 (new BIODASDINFO2) * 12/06/01 DASD_API_VERSION 2 - binary compatible to 0 (new BIODASDINFO2)
* 01/23/02 DASD_API_VERSION 3 - added BIODASDPSRD (and BIODASDENAPAV) IOCTL * 01/23/02 DASD_API_VERSION 3 - added BIODASDPSRD (and BIODASDENAPAV) IOCTL
* 02/15/02 DASD_API_VERSION 4 - added BIODASDSATTR IOCTL * 02/15/02 DASD_API_VERSION 4 - added BIODASDSATTR IOCTL
* ##/##/## DASD_API_VERSION 5 - added boxed dasd support TOBEDONE
* 21/06/02 DASD_API_VERSION 6 - fixed HDIO_GETGEO: geo.start is in sectors!
* *
*/ */
...@@ -22,7 +24,7 @@ ...@@ -22,7 +24,7 @@
#define DASD_IOCTL_LETTER 'D' #define DASD_IOCTL_LETTER 'D'
#define DASD_API_VERSION 4 #define DASD_API_VERSION 6
/* /*
* struct dasd_information2_t * struct dasd_information2_t
......
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
* 12/06/01 DASD_API_VERSION 2 - binary compatible to 0 (new BIODASDINFO2) * 12/06/01 DASD_API_VERSION 2 - binary compatible to 0 (new BIODASDINFO2)
* 01/23/02 DASD_API_VERSION 3 - added BIODASDPSRD (and BIODASDENAPAV) IOCTL * 01/23/02 DASD_API_VERSION 3 - added BIODASDPSRD (and BIODASDENAPAV) IOCTL
* 02/15/02 DASD_API_VERSION 4 - added BIODASDSATTR IOCTL * 02/15/02 DASD_API_VERSION 4 - added BIODASDSATTR IOCTL
* ##/##/## DASD_API_VERSION 5 - added boxed dasd support TOBEDONE
* 21/06/02 DASD_API_VERSION 6 - fixed HDIO_GETGEO: geo.start is in sectors!
* *
*/ */
...@@ -22,7 +24,7 @@ ...@@ -22,7 +24,7 @@
#define DASD_IOCTL_LETTER 'D' #define DASD_IOCTL_LETTER 'D'
#define DASD_API_VERSION 4 #define DASD_API_VERSION 6
/* /*
* struct dasd_information2_t * struct dasd_information2_t
......
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