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

[PATCH] s390: dasd driver.

Convert dasd driver to new channel subsystem driver

This makes the dasd driver work again after the changes to
the channel subsystem driver:
- handle device detection with standard driver model functions
- reduce use of dasd_devmap (devmap will die as soon as
  dasd configuration is handled from initramfs)
- some cleanups

Authors: Arnd Bergmann <arndb@de.ibm.com>
	 Martin Schwidefsky <schwidefsky@de.ibm.com>
parent 0286402a
......@@ -79,6 +79,7 @@ CONFIG_BLK_DEV_XPRAM=m
# S/390 block device drivers
#
CONFIG_DASD=y
# CONFIG_DASD_PROFILE is not set
CONFIG_DASD_ECKD=y
CONFIG_DASD_FBA=y
CONFIG_DASD_DIAG=y
......
......@@ -137,6 +137,7 @@ CONFIG_BLK_DEV_XPRAM=m
# S/390 block device drivers
#
CONFIG_DASD=y
# CONFIG_DASD_PROFILE is not set
CONFIG_DASD_ECKD=y
CONFIG_DASD_FBA=y
# CONFIG_DASD_DIAG is not set
......
......@@ -138,49 +138,34 @@ config DASD
S/390s channel subsystem commands. This is necessary for running
natively on a single image or an LPAR.
config DASD_PROFILE
bool "Profiling support for dasd devices"
help
Enable this option if you want to see profiling information
in /proc/dasd/statistics.
config DASD_ECKD
tristate "Support for ECKD Disks"
depends on DASD
help
ECKD devices are the most commonly used devices. you should enable
ECKD devices are the most commonly used devices. You should enable
this option unless you are very sure to have no ECKD device.
config DASD_AUTO_ECKD
bool "Automatic activation of ECKD module"
depends on DASD && DASD_ECKD=m
help
Enable this option if you want your ECKD discipline module loaded
on DASD driver startup.
config DASD_FBA
tristate "Support for FBA Disks"
depends on DASD
help
FBA devices are currently unsupported.
Select this option to be able to access FBA devices. It is safe to
say "Y".
config DASD_AUTO_FBA
bool "Automatic activation of FBA module"
depends on DASD && DASD_FBA=m
help
Enable this option if you want your FBA discipline module loaded
on DASD driver startup.
# dep_tristate ' Support for CKD Disks' CONFIG_DASD_CKD $CONFIG_DASD
config DASD_DIAG
tristate "Support for DIAG access to CMS reserved Disks"
depends on !ARCH_S390X && DASD
depends on DASD
help
Select this option if you want to use CMS reserved Disks under VM
with the Diagnose250 command. If you are not running under VM or
unsure what it is, say "N".
config DASD_AUTO_DIAG
bool "Automatic activation of DIAG module"
depends on DASD && !ARCH_S390X && DASD_DIAG=m
help
Enable this option if you want your DIAG discipline module loaded
on DASD driver startup.
endmenu
source "drivers/md/Kconfig"
......
This diff is collapsed.
......@@ -3,6 +3,11 @@
* Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000
*
* $Revision: 1.7 $
*
* History of changes
*
*/
#define PRINTK_HEADER "dasd_erp(3370)"
......@@ -27,13 +32,13 @@
* dasd_era_recover for all others.
*/
dasd_era_t
dasd_3370_erp_examine(dasd_ccw_req_t * cqr, devstat_t * stat)
dasd_3370_erp_examine(dasd_ccw_req_t * cqr, struct irb * irb)
{
char *sense = stat->ii.sense.data;
char *sense = irb->ecw;
/* check for successful execution first */
if (stat->cstat == 0x00 &&
stat->dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
if (irb->scsw.cstat == 0x00 &&
irb->scsw.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
return dasd_era_none;
if (sense[0] & 0x80) { /* CMD reject */
return dasd_era_fatal;
......
/*
* File...........: linux/drivers/s390/block/dasd_3370_erp.h
* Author(s)......: Horst Hummel <Horst Hummel@de.ibm.com>
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000
*
* History of changes (starts July 2000)
*/
#ifndef DASD_3370_ERP_H
#define DASD_3370_ERP_H
dasd_era_t dasd_3370_erp_examine(dasd_ccw_req_t *, devstat_t *);
#endif /* DASD_3990_ERP_H */
......@@ -5,6 +5,8 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000, 2001
*
* $Revision: 1.19 $
*
* History of changes:
* 05/14/01 fixed PL030160GTO (BUG() in erp_action_5)
* 05/04/02 code restructuring.
......@@ -13,7 +15,6 @@
#include <linux/timer.h>
#include <linux/slab.h>
#include <asm/idals.h>
#include <asm/s390io.h>
#include <asm/todclk.h>
#define PRINTK_HEADER "dasd_erp(3990): "
......@@ -148,16 +149,16 @@ dasd_3990_erp_examine_32(dasd_ccw_req_t * cqr, char *sense)
* dasd_era_recover for all others.
*/
dasd_era_t
dasd_3990_erp_examine(dasd_ccw_req_t * cqr, devstat_t * stat)
dasd_3990_erp_examine(dasd_ccw_req_t * cqr, struct irb * irb)
{
char *sense = stat->ii.sense.data;
char *sense = irb->ecw;
dasd_era_t era = dasd_era_recover;
dasd_device_t *device = cqr->device;
/* check for successful execution first */
if (stat->cstat == 0x00 &&
stat->dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
if (irb->scsw.cstat == 0x00 &&
irb->scsw.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
return dasd_era_none;
/* distinguish between 24 and 32 byte sense data */
......@@ -172,8 +173,10 @@ dasd_3990_erp_examine(dasd_ccw_req_t * cqr, devstat_t * stat)
}
/* log the erp chain if fatal error occurred */
if ((era == dasd_era_fatal) && (device->state >= DASD_STATE_READY))
dasd_log_ccw(cqr, 0, stat->cpa);
if ((era == dasd_era_fatal) && (device->state >= DASD_STATE_READY)) {
dasd_log_sense(cqr, irb);
dasd_log_ccw(cqr, 0, irb->scsw.cpa);
}
return era;
......@@ -296,42 +299,39 @@ dasd_3990_erp_int_req(dasd_ccw_req_t * erp)
*
* RETURN VALUES
* erp modified pointer to the ERP
*
*/
static void
dasd_3990_erp_alternate_path(dasd_ccw_req_t * erp)
{
dasd_device_t *device = erp->device;
int irq = device->devinfo.irq;
__u8 opm;
/* try alternate valid path */
erp->lpm &= ~(erp->dstat->lpum);
erp->options |= DOIO_VALID_LPM; /* use LPM for DO_IO */
opm = ccw_device_get_path_mask(device->cdev);
//FIXME: start with get_opm ?
if (erp->lpm == 0)
erp->lpm = LPM_ANYPATH & ~(erp->dstat->esw.esw0.sublog.lpum);
else
erp->lpm &= ~(erp->dstat->esw.esw0.sublog.lpum);
if ((erp->lpm & ioinfo[irq]->opm) != 0x00) {
if ((erp->lpm & opm) != 0x00) {
DEV_MESSAGE(KERN_DEBUG, device,
"try alternate lpm=%x (lpum=%x / opm=%x)",
erp->lpm, erp->dstat->lpum, ioinfo[irq]->opm);
erp->lpm, erp->dstat->esw.esw0.sublog.lpum, opm);
/* reset status to queued to handle the request again... */
erp->status = DASD_CQR_QUEUED;
erp->retries = 1;
} else {
DEV_MESSAGE(KERN_ERR, device,
"No alternate channel path left (lpum=%x / "
"opm=%x) -> permanent error",
erp->dstat->lpum, ioinfo[irq]->opm);
erp->dstat->esw.esw0.sublog.lpum, opm);
/* post request with permanent error */
erp->status = DASD_CQR_FAILED;
}
} /* end dasd_3990_erp_alternate_path */
/*
......@@ -355,7 +355,7 @@ dasd_3990_erp_DCTL(dasd_ccw_req_t * erp, char modifier)
dasd_device_t *device = erp->device;
DCTL_data_t *DCTL_data;
ccw1_t *ccw;
struct ccw1 *ccw;
dasd_ccw_req_t *dctl_cqr;
dctl_cqr = dasd_alloc_erp_request((char *) &erp->magic, 1,
......@@ -373,7 +373,7 @@ dasd_3990_erp_DCTL(dasd_ccw_req_t * erp, char modifier)
DCTL_data->modifier = modifier;
ccw = dctl_cqr->cpaddr;
memset(ccw, 0, sizeof (ccw1_t));
memset(ccw, 0, sizeof (struct ccw1));
ccw->cmd_code = CCW_CMD_DCTL;
ccw->count = 4;
ccw->cda = (__u32)(addr_t) DCTL_data;
......@@ -381,7 +381,6 @@ dasd_3990_erp_DCTL(dasd_ccw_req_t * erp, char modifier)
dctl_cqr->refers = erp;
dctl_cqr->device = erp->device;
dctl_cqr->magic = erp->magic;
dctl_cqr->lpm = LPM_ANYPATH;
dctl_cqr->expires = 5 * 60 * HZ;
dctl_cqr->retries = 2;
......@@ -1122,6 +1121,9 @@ dasd_3990_handle_env_data(dasd_ccw_req_t * erp, char *sense)
break;
default: /* unknown message format - should not happen */
DEV_MESSAGE (KERN_WARNING, device,
"unknown message format %02x",
msg_format);
break;
} /* end switch message format */
......@@ -1650,7 +1652,7 @@ dasd_3990_erp_action_1B_32(dasd_ccw_req_t * default_erp, char *sense)
dasd_ccw_req_t *erp;
DE_eckd_data_t *DE_data;
char *LO_data; /* LO_eckd_data_t */
ccw1_t *ccw;
struct ccw1 *ccw;
DEV_MESSAGE(KERN_DEBUG, device, "%s",
"Write not finished because of unexpected condition");
......@@ -1675,7 +1677,7 @@ dasd_3990_erp_action_1B_32(dasd_ccw_req_t * default_erp, char *sense)
/* determine the address of the CCW to be restarted */
/* Imprecise ending is not set -> addr from IRB-SCSW */
cpa = default_erp->refers->dstat->cpa;
cpa = default_erp->refers->dstat->scsw.cpa;
if (cpa == 0) {
......@@ -1735,7 +1737,7 @@ dasd_3990_erp_action_1B_32(dasd_ccw_req_t * default_erp, char *sense)
/* create DE ccw */
ccw = erp->cpaddr;
memset(ccw, 0, sizeof (ccw1_t));
memset(ccw, 0, sizeof (struct ccw1));
ccw->cmd_code = DASD_ECKD_CCW_DEFINE_EXTENT;
ccw->flags = CCW_FLAG_CC;
ccw->count = 16;
......@@ -1743,7 +1745,7 @@ dasd_3990_erp_action_1B_32(dasd_ccw_req_t * default_erp, char *sense)
/* create LO ccw */
ccw++;
memset(ccw, 0, sizeof (ccw1_t));
memset(ccw, 0, sizeof (struct ccw1));
ccw->cmd_code = DASD_ECKD_CCW_LOCATE_RECORD;
ccw->flags = CCW_FLAG_CC;
ccw->count = 16;
......@@ -1759,7 +1761,6 @@ dasd_3990_erp_action_1B_32(dasd_ccw_req_t * default_erp, char *sense)
erp->refers = default_erp->refers;
erp->device = device;
erp->magic = default_erp->magic;
erp->lpm = 0xFF;
erp->expires = 0;
erp->retries = 256;
erp->status = DASD_CQR_FILLED;
......@@ -1795,7 +1796,7 @@ dasd_3990_update_1B(dasd_ccw_req_t * previous_erp, char *sense)
dasd_ccw_req_t *cqr;
dasd_ccw_req_t *erp;
char *LO_data; /* LO_eckd_data_t */
ccw1_t *ccw;
struct ccw1 *ccw;
DEV_MESSAGE(KERN_DEBUG, device, "%s",
"Write not finished because of unexpected condition"
......@@ -1821,7 +1822,7 @@ dasd_3990_update_1B(dasd_ccw_req_t * previous_erp, char *sense)
/* determine the address of the CCW to be restarted */
/* Imprecise ending is not set -> addr from IRB-SCSW */
cpa = previous_erp->dstat->cpa;
cpa = previous_erp->dstat->scsw.cpa;
if (cpa == 0) {
......@@ -1954,7 +1955,7 @@ dasd_3990_erp_compound_path(dasd_ccw_req_t * erp, char *sense)
/* reset the lpm and the status to be able to
* try further actions. */
erp->lpm = LPM_ANYPATH;
erp->lpm = 0;
erp->status = DASD_CQR_ERROR;
......@@ -2234,7 +2235,7 @@ dasd_3990_erp_inspect(dasd_ccw_req_t * erp)
dasd_ccw_req_t *erp_new = NULL;
/* sense data are located in the refers record of the */
/* already set up new ERP ! */
char *sense = erp->refers->dstat->ii.sense.data;
char *sense = erp->refers->dstat->ecw;
/* distinguish between 24 and 32 byte sense data */
if (sense[27] & DASD_SENSE_BIT_0) {
......@@ -2291,7 +2292,6 @@ dasd_3990_erp_add_erp(dasd_ccw_req_t * cqr)
erp->refers = cqr;
erp->device = cqr->device;
erp->magic = cqr->magic;
erp->lpm = 0xFF;
erp->expires = 0;
erp->retries = 256;
......@@ -2357,18 +2357,14 @@ dasd_3990_erp_error_match(dasd_ccw_req_t * cqr1, dasd_ccw_req_t * cqr2)
{
/* check failed CCW */
if (cqr1->dstat->cpa != cqr2->dstat->cpa) {
if (cqr1->dstat->scsw.cpa != cqr2->dstat->scsw.cpa) {
// return 0; /* CCW doesn't match */
}
/* check sense data; byte 0-2,25,27 */
if (!((strncmp(cqr1->dstat->ii.sense.data,
cqr2->dstat->ii.sense.data,
3) == 0) &&
(cqr1->dstat->ii.sense.data[27] ==
cqr2->dstat->ii.sense.data[27]) &&
(cqr1->dstat->ii.sense.data[25] ==
cqr2->dstat->ii.sense.data[25]))) {
if (!((strncmp(cqr1->dstat->ecw, cqr2->dstat->ecw, 3) == 0) &&
(cqr1->dstat->ecw[27] == cqr2->dstat->ecw[27]) &&
(cqr1->dstat->ecw[25] == cqr2->dstat->ecw[25]))) {
return 0; /* sense doesn't match */
}
......@@ -2441,7 +2437,7 @@ dasd_3990_erp_further_erp(dasd_ccw_req_t * erp)
{
dasd_device_t *device = erp->device;
char *sense = erp->dstat->ii.sense.data;
char *sense = erp->dstat->ecw;
/* check for 24 byte sense ERP */
if ((erp->function == dasd_3990_erp_bus_out) ||
......@@ -2553,7 +2549,7 @@ dasd_3990_erp_handle_match_erp(dasd_ccw_req_t * erp_head, dasd_ccw_req_t * erp)
if (erp->retries > 0) {
char *sense = erp->dstat->ii.sense.data;
char *sense = erp->dstat->ecw;
/* check for special retries */
if (erp->function == dasd_3990_erp_action_4) {
......@@ -2611,7 +2607,7 @@ dasd_3990_erp_action(dasd_ccw_req_t * cqr)
dasd_ccw_req_t *erp = NULL;
dasd_device_t *device = cqr->device;
__u32 cpa = cqr->dstat->cpa;
__u32 cpa = cqr->dstat->scsw.cpa;
#ifdef ERP_DEBUG
/* print current erp_chain */
......@@ -2631,8 +2627,8 @@ dasd_3990_erp_action(dasd_ccw_req_t * cqr)
#endif /* ERP_DEBUG */
/* double-check if current erp/cqr was successfull */
if ((cqr->dstat->cstat == 0x00) &&
(cqr->dstat->dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))) {
if ((cqr->dstat->scsw.cstat == 0x00) &&
(cqr->dstat->scsw.dstat == (DEV_STAT_CHN_END|DEV_STAT_DEV_END))) {
DEV_MESSAGE(KERN_DEBUG, device,
"ERP called for successful request %p"
......@@ -2643,7 +2639,7 @@ dasd_3990_erp_action(dasd_ccw_req_t * cqr)
return cqr;
}
/* check if sense data are available */
if (!cqr->dstat->ii.sense.data) {
if (!cqr->dstat->ecw) {
DEV_MESSAGE(KERN_DEBUG, device,
"ERP called witout sense data avail ..."
"request %p - NO ERP possible", cqr);
......
/*
* File...........: linux/drivers/s390/block/dasd_3990_erp.h
* Author(s)......: Horst Hummel <Horst Hummel@de.ibm.com>
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000
*
* History of changes (starts July 2000)
*/
#ifndef DASD_3990_ERP_H
#define DASD_3990_ERP_H
dasd_era_t dasd_3990_erp_examine(dasd_ccw_req_t *, devstat_t *);
dasd_ccw_req_t *dasd_3990_erp_action(dasd_ccw_req_t *);
dasd_ccw_req_t *dasd_2105_erp_action(ccw_req_t *);
void dasd_3990_erp_restart_queue(unsigned long);
typedef struct DCTL_data_t {
unsigned char subcommand; /* e.g Inhibit Write, Enable Write,... */
unsigned char modifier; /* Subcommand modifier */
unsigned short res; /* reserved */
} __attribute__ ((packed)) DCTL_data_t;
#endif /* DASD_3990_ERP_H */
......@@ -3,6 +3,11 @@
* Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000
*
* $Revision: 1.6 $
*
* History of changes
*
*/
#define PRINTK_HEADER "dasd_erp(9336)"
......@@ -27,11 +32,11 @@
* dasd_era_recover for all others.
*/
dasd_era_t
dasd_9336_erp_examine(dasd_ccw_req_t * cqr, devstat_t * stat)
dasd_9336_erp_examine(dasd_ccw_req_t * cqr, struct irb * irb)
{
/* check for successful execution first */
if (stat->cstat == 0x00 &&
stat->dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
if (irb->scsw.cstat == 0x00 &&
irb->scsw.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
return dasd_era_none;
/* examine the 24 byte sense data */
......
/*
* File...........: linux/drivers/s390/block/dasd_9336_erp.h
* Author(s)......: Horst Hummel <Horst Hummel@de.ibm.com>
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000
*
* History of changes (starts July 2000)
*/
#ifndef DASD_9336_ERP_H
#define DASD_9336_ERP_H
dasd_era_t dasd_9336_erp_examine(dasd_ccw_req_t *, devstat_t *);
#endif /* DASD_3990_ERP_H */
/*
* File...........: linux/drivers/s390/block/dasd_9345_erp.h
* File...........: linux/drivers/s390/block/dasd_9345_erp.c
* Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000
*
* $Revision: 1.11 $
*
* History of changes
*
*/
#define PRINTK_HEADER "dasd_erp(9343)"
......@@ -10,10 +15,11 @@
#include "dasd_int.h"
dasd_era_t
dasd_9343_erp_examine(dasd_ccw_req_t * cqr, devstat_t * stat)
dasd_9343_erp_examine(dasd_ccw_req_t * cqr, struct irb * irb)
{
if (stat->cstat == 0x00 &&
stat->dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
if (irb->scsw.cstat == 0x00 &&
irb->scsw.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
return dasd_era_none;
return dasd_era_recover;
}
/*
* File...........: linux/drivers/s390/block/dasd_9343_erp.h
* Author(s)......: Horst Hummel <Horst Hummel@de.ibm.com>
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000
*
* History of changes (starts July 2000)
*/
#ifndef DASD_9343_ERP_H
#define DASD_9343_ERP_H
dasd_era_t dasd_9343_erp_examine(dasd_ccw_req_t *, devstat_t *);
dasd_ccw_req_t *dasd_9343_erp_action(dasd_ccw_req_t *);
#endif /* DASD_9343_ERP_H */
......@@ -11,6 +11,9 @@
* functions may not be called from interrupt context. In particular
* dasd_get_device is a no-no from interrupt context.
*
* $Revision: 1.11 $
*
* History of changes
* 05/04/02 split from dasd.c, code restructuring.
*/
......@@ -20,7 +23,6 @@
#include <linux/init.h>
#include <asm/debug.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
/* This is ugly... */
......@@ -84,9 +86,11 @@ __setup ("dasd=", dasd_call_setup);
* Read a device number from a string. The number is always in hex,
* a leading 0x is accepted.
*/
int
static inline int
dasd_devno(char *str, char **endp)
{
int val;
/* remove leading '0x' */
if (*str == '0') {
str++;
......@@ -96,7 +100,10 @@ dasd_devno(char *str, char **endp)
/* We require at least one hex digit */
if (!isxdigit(*str))
return -EINVAL;
return simple_strtoul(str, endp, 16);
val = simple_strtoul(str, endp, 16);
if ((val > 0xFFFF) || (val < 0))
return -EINVAL;
return val;
}
/*
......@@ -104,7 +111,7 @@ dasd_devno(char *str, char **endp)
* only one: "ro" for read-only devices. The default feature set
* is empty (value 0).
*/
int
static inline int
dasd_feature_list(char *str, char **endp)
{
int features, len, rc;
......@@ -260,64 +267,12 @@ dasd_add_range(int from, int to, int features)
devmap->devindex = devindex;
devmap->devno = devno;
devmap->features = features;
devmap->devreg = NULL;
devmap->device = NULL;
list_add(&devmap->devindex_list,
&dasd_devindex_hashlists[devindex & 255]);
list_add(&devmap->devno_list,
&dasd_devno_hashlists[devno & 255]);
}
if (devmap->devreg == NULL) {
/* The devreg is missing. */
devmap->devreg = (devreg_t *)
kmalloc(sizeof(devreg_t), GFP_KERNEL);
if (devmap->devreg == NULL)
return -ENOMEM;
memset(devmap->devreg, sizeof(devreg_t), 0);
devmap->devreg->ci.devno = devno;
devmap->devreg->flag = DEVREG_TYPE_DEVNO;
devmap->devreg->oper_func = dasd_oper_handler;
s390_device_register(devmap->devreg);
}
}
spin_unlock(&dasd_devmap_lock);
return 0;
}
/*
* Removes the devreg_t structures for a range of devices. This does
* NOT remove the range itself. The mapping between devno and kdevs
* for the devices is remembered until dasd_forget_ranges() is called.
*/
static int
dasd_clear_range(int from, int to)
{
int devno;
if (from > to) {
MESSAGE(KERN_ERR,
"Invalid device range %04x-%04x", from, to);
return -EINVAL;
}
spin_lock(&dasd_devmap_lock);
for (devno = from; devno <= to; devno++) {
struct list_head *l;
dasd_devmap_t *devmap = NULL;
/* Find previous devmap for device number i */
list_for_each(l, &dasd_devno_hashlists[devno & 255]) {
devmap = list_entry(l, dasd_devmap_t, devno_list);
if (devmap->devno == devno)
break;
}
if (devmap == NULL)
continue;
if (devmap->device != NULL)
BUG();
if (devmap->devreg == NULL)
continue;
s390_device_unregister(devmap->devreg);
kfree(devmap->devreg);
devmap->devreg = NULL;
}
spin_unlock(&dasd_devmap_lock);
return 0;
......@@ -340,11 +295,6 @@ dasd_forget_ranges(void)
devmap = list_entry(l, dasd_devmap_t, devno_list);
if (devmap->device != NULL)
BUG();
if (devmap->devreg != NULL) {
s390_device_unregister(devmap->devreg);
kfree(devmap->devreg);
devmap->devreg = NULL;
}
list_del(&devmap->devindex_list);
list_del(&devmap->devno_list);
kfree(devmap);
......@@ -403,52 +353,6 @@ dasd_devmap_from_devindex(int devindex)
return devmap;
}
/*
* Find the devmap for a device by its irq line.
*/
dasd_devmap_t *
dasd_devmap_from_irq(int irq)
{
struct list_head *l;
dasd_devmap_t *devmap, *tmp;
int i;
devmap = NULL;
spin_lock(&dasd_devmap_lock);
for (i = 0; (i < 256) && (devmap == NULL); i++) {
list_for_each(l, &dasd_devno_hashlists[i & 255]) {
tmp = list_entry(l, dasd_devmap_t, devno_list);
if (tmp->device != NULL &&
tmp->device->devinfo.irq == irq) {
devmap = tmp;
break;
}
}
}
spin_unlock(&dasd_devmap_lock);
return devmap;
}
/*
* Find the devmap for a device corresponding to a block_device.
*/
dasd_devmap_t *
dasd_devmap_from_bdev(struct block_device *bdev)
{
kdev_t kdev = to_kdev_t(bdev->bd_dev);
int devindex;
/* Find the devindex for kdev. */
devindex = dasd_gendisk_major_index(major(kdev));
if (devindex < 0)
/* No such major -> no devmap */
return NULL;
devindex += minor(kdev) >> DASD_PARTN_BITS;
/* Now find the devmap by the devindex. */
return dasd_devmap_from_devindex(devindex);
}
/*
* Find the device structure for device number devno. If it does not
* exists yet, allocate it. Increase the reference counter in the device
......@@ -479,6 +383,8 @@ dasd_get_device(dasd_devmap_t *devmap)
} else
devmap->device = device;
atomic_inc(&device->ref_count);
device->ro_flag = (devmap->features & DASD_FEATURE_READONLY) ? 1 : 0;
device->use_diag_flag = 1;
spin_unlock(&dasd_devmap_lock);
return device;
}
......@@ -523,9 +429,3 @@ dasd_devmap_exit(void)
{
dasd_forget_ranges();
}
EXPORT_SYMBOL(dasd_devmap_from_devno);
EXPORT_SYMBOL(dasd_devmap_from_devindex);
EXPORT_SYMBOL(dasd_devmap_from_irq);
EXPORT_SYMBOL(dasd_get_device);
EXPORT_SYMBOL(dasd_put_device);
......@@ -5,7 +5,9 @@
* ...............: by Hartmunt Penner <hpenner@de.ibm.com>
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
*
* $Revision: 1.27 $
*
* History of changes
* 07/13/00 Added fixup sections for diagnoses ans saved some registers
* 07/14/00 fixed constraints in newly generated inline asm
......@@ -22,13 +24,13 @@
#include <linux/slab.h>
#include <linux/hdreg.h> /* HDIO_GETGEO */
#include <linux/bio.h>
#include <linux/module.h>
#include <linux/init.h>
#include <asm/dasd.h>
#include <asm/debug.h>
#include <asm/ebcdic.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/s390dyn.h>
#include <asm/s390_ext.h>
#include <asm/todclk.h>
......@@ -40,7 +42,7 @@
#endif /* PRINTK_HEADER */
#define PRINTK_HEADER "dasd(diag):"
static dasd_discipline_t dasd_diag_discipline;
MODULE_LICENSE("GPL");
typedef struct dasd_diag_private_t {
dasd_diag_characteristics_t rdc_data;
......@@ -57,25 +59,30 @@ typedef struct dasd_diag_req_t {
static __inline__ int
dia250(void *iob, int cmd)
{
__asm__ __volatile__(" lr 0,%1\n"
" diag 0,%0,0x250\n"
int rc;
__asm__ __volatile__(" lhi %0,3\n"
" lr 0,%2\n"
" diag 0,%1,0x250\n"
"0: ipm %0\n"
" srl %0,28\n"
" or %0,1\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"
#ifndef CONFIG_ARCH_S390X
".section __ex_table,\"a\"\n"
" .align 4\n"
" .long 0b,2b\n" ".previous\n":"+d"(cmd)
:"d"((void *) __pa(iob))
:"0", "1", "cc");
return cmd;
" .long 0b,1b\n"
".previous\n"
#else
".section __ex_table,\"a\"\n"
" .align 8\n"
" .quad 0b,1b\n"
".previous\n"
#endif
: "=&d" (rc)
: "d" (cmd), "d" ((void *) __pa(iob))
: "0", "1", "cc");
return rc;
}
static __inline__ int
......@@ -89,7 +96,7 @@ mdsk_init_io(dasd_device_t * device, int blocksize, int offset, int size)
iib = &private->iib;
memset(iib, 0, sizeof (diag_init_io_t));
iib->dev_nr = device->devinfo.devno;
iib->dev_nr = device->devno;
iib->block_size = blocksize;
iib->offset = offset;
iib->start_block = 0;
......@@ -110,7 +117,7 @@ mdsk_term_io(dasd_device_t * device)
private = (dasd_diag_private_t *) device->private;
iib = &private->iib;
memset(iib, 0, sizeof (diag_init_io_t));
iib->dev_nr = device->devinfo.devno;
iib->dev_nr = device->devno;
rc = dia250(iib, TERM_BIO);
return rc & 3;
}
......@@ -127,7 +134,7 @@ dasd_start_diag(dasd_ccw_req_t * cqr)
private = (dasd_diag_private_t *) device->private;
dreq = (dasd_diag_req_t *) cqr->data;
private->iob.dev_nr = device->devinfo.devno;
private->iob.dev_nr = device->devno;
private->iob.key = 0;
private->iob.flags = 2; /* do asynchronous io */
private->iob.block_count = dreq->block_count;
......@@ -191,7 +198,7 @@ dasd_ext_handler(struct pt_regs *regs, __u16 code)
}
/* get irq lock to modify request queue */
spin_lock_irqsave(get_irq_lock(device->devinfo.irq), flags);
spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
cqr->stopclk = get_clock();
......@@ -219,7 +226,7 @@ dasd_ext_handler(struct pt_regs *regs, __u16 code)
dasd_clear_timer(device);
dasd_schedule_bh(device);
spin_unlock_irqrestore(get_irq_lock(device->devinfo.irq), flags);
spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
irq_exit();
}
......@@ -245,10 +252,10 @@ dasd_diag_check_device(dasd_device_t *device)
}
/* Read Device Characteristics */
rdc_data = (void *) &(private->rdc_data);
rdc_data->dev_nr = device->devinfo.devno;
rdc_data->dev_nr = device->devno;
rdc_data->rdc_len = sizeof (dasd_diag_characteristics_t);
rc = diag210((diag210_t *) rdc_data);
rc = diag210((struct diag210 *) rdc_data);
if (rc)
return -ENOTSUPP;
......@@ -328,7 +335,7 @@ dasd_diag_fill_geometry(dasd_device_t *device, struct hd_geometry *geo)
}
static dasd_era_t
dasd_diag_examine_error(dasd_ccw_req_t * cqr, devstat_t * stat)
dasd_diag_examine_error(dasd_ccw_req_t * cqr, struct irb * stat)
{
return dasd_era_fatal;
}
......@@ -433,7 +440,8 @@ dasd_diag_fill_info(dasd_device_t * device, dasd_information2_t * info)
}
static void
dasd_diag_dump_sense(dasd_device_t *device, dasd_ccw_req_t * req)
dasd_diag_dump_sense(dasd_device_t *device, dasd_ccw_req_t * req,
struct irb *stat)
{
char *page;
......@@ -443,8 +451,8 @@ dasd_diag_dump_sense(dasd_device_t *device, dasd_ccw_req_t * req)
return;
}
sprintf(page, KERN_WARNING PRINTK_HEADER
"device %04X on irq %d: I/O status report:\n",
device->devinfo.devno, device->devinfo.irq);
"device %s: I/O status report:\n",
device->cdev->dev.bus_id);
MESSAGE(KERN_ERR, "Sense data:\n%s", page);
......@@ -463,7 +471,7 @@ dasd_diag_dump_sense(dasd_device_t *device, dasd_ccw_req_t * req)
* start the next request if one finishes off. That makes 252.75 blocks
* for one request. Give a little safety and the result is 240.
*/
static dasd_discipline_t dasd_diag_discipline = {
dasd_discipline_t dasd_diag_discipline = {
.owner = THIS_MODULE,
.name = "DIAG",
.ebcname = "DIAG",
......@@ -479,7 +487,7 @@ static dasd_discipline_t dasd_diag_discipline = {
.fill_info = dasd_diag_fill_info,
};
int
static int __init
dasd_diag_init(void)
{
if (!MACHINE_IS_VM) {
......@@ -489,13 +497,13 @@ dasd_diag_init(void)
return -EINVAL;
}
ASCEBC(dasd_diag_discipline.ebcname, 4);
ctl_set_bit(0, 9);
register_external_interrupt(0x2603, dasd_ext_handler);
dasd_discipline_add(&dasd_diag_discipline);
return 0;
}
void
static void __exit
dasd_diag_cleanup(void)
{
if (!MACHINE_IS_VM) {
......@@ -504,24 +512,12 @@ dasd_diag_cleanup(void)
dasd_diag_discipline.name);
return;
}
dasd_discipline_del(&dasd_diag_discipline);
unregister_external_interrupt(0x2603, dasd_ext_handler);
ctl_clear_bit(0, 9);
}
#ifdef MODULE
int
init_module(void)
{
return dasd_diag_init();
}
void
cleanup_module(void)
{
dasd_diag_cleanup();
}
#endif
module_init(dasd_diag_init);
module_exit(dasd_diag_cleanup);
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
......
......@@ -5,6 +5,11 @@
* ...............: by Hartmunt Penner <hpenner@de.ibm.com>
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
*
* $Revision: 1.4 $
*
* History of changes
*
*/
#define MDSK_WRITE_REQ 0x01
......@@ -70,5 +75,3 @@ typedef struct diag_rw_io_t {
diag_rw_io_t;
int dasd_diag_init(void);
void dasd_diag_cleanup(void);
This diff is collapsed.
/*
* File...........: linux/drivers/s390/block/dasd_eckd.h
* Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
* Horst Hummel <Horst.Hummel@de.ibm.com>
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
*
* $Revision: 1.5 $
*
* History of changes
*
*/
#ifndef DASD_ECKD_H
#define DASD_ECKD_H
......@@ -102,6 +115,10 @@ typedef struct DE_eckd_data_t {
__u8 ga_extended; /* Global Attributes Extended */
ch_t beg_ext;
ch_t end_ext;
unsigned long long ep_sys_time; /* Extended Parameter - System Time Stamp */
__u8 ep_format; /* Extended Parameter format byte */
__u8 ep_prio; /* Extended Parameter priority I/O byte */
__u8 ep_reserved[6]; /* Extended Parameter Reserved */
} __attribute__ ((packed)) DE_eckd_data_t;
typedef struct LO_eckd_data_t {
......@@ -141,7 +158,8 @@ typedef struct dasd_eckd_characteristics_t {
unsigned char reserved2:4;
unsigned char reserved3:8;
unsigned char defect_wr:1;
unsigned char reserved4:2;
unsigned char XRC_supported:1;
unsigned char reserved4:1;
unsigned char striping:1;
unsigned char reserved5:4;
unsigned char cfw:1;
......@@ -322,6 +340,4 @@ typedef struct dasd_psf_prssd_data_t {
unsigned char varies[9];
} __attribute__ ((packed)) dasd_psf_prssd_data_t;
int dasd_eckd_init(void);
void dasd_eckd_cleanup(void);
#endif /* DASD_ECKD_H */
......@@ -7,6 +7,9 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
*
* $Revision: 1.6 $
*
* History of changes
* 05/04/02 split from dasd.c, code restructuring.
*/
......@@ -17,7 +20,6 @@
#include <asm/debug.h>
#include <asm/ebcdic.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
/* This is ugly... */
......@@ -36,7 +38,7 @@ dasd_alloc_erp_request(char *magic, int cplength, int datasize,
/* Sanity checks */
if ( magic == NULL || datasize > PAGE_SIZE ||
(cplength*sizeof(ccw1_t)) > PAGE_SIZE)
(cplength*sizeof(struct ccw1)) > PAGE_SIZE)
BUG();
debug_text_event ( dasd_debug_area, 1, "ALLC");
debug_text_event ( dasd_debug_area, 1, magic);
......@@ -45,7 +47,7 @@ dasd_alloc_erp_request(char *magic, int cplength, int datasize,
size = (sizeof(dasd_ccw_req_t) + 7L) & -8L;
if (cplength > 0)
size += cplength * sizeof(ccw1_t);
size += cplength * sizeof(struct ccw1);
if (datasize > 0)
size += datasize;
spin_lock_irqsave(&device->mem_lock, flags);
......@@ -57,9 +59,9 @@ dasd_alloc_erp_request(char *magic, int cplength, int datasize,
data = (char *) cqr + ((sizeof(dasd_ccw_req_t) + 7L) & -8L);
cqr->cpaddr = NULL;
if (cplength > 0) {
cqr->cpaddr = (ccw1_t *) data;
data += cplength*sizeof(ccw1_t);
memset(cqr->cpaddr, 0, cplength*sizeof(ccw1_t));
cqr->cpaddr = (struct ccw1 *) data;
data += cplength*sizeof(struct ccw1);
memset(cqr->cpaddr, 0, cplength*sizeof(struct ccw1));
}
cqr->data = NULL;
if (datasize > 0) {
......@@ -201,18 +203,25 @@ hex_dump_memory(dasd_device_t *device, void *data, int len)
}
void
dasd_log_ccw(dasd_ccw_req_t * cqr, int caller, __u32 cpa)
dasd_log_sense(dasd_ccw_req_t *cqr, struct irb *irb)
{
dasd_device_t *device;
dasd_ccw_req_t *lcqr;
ccw1_t *ccw;
int cplength;
device = cqr->device;
/* dump sense data */
if (device->discipline && device->discipline->dump_sense)
device->discipline->dump_sense(device, cqr);
device->discipline->dump_sense(device, cqr, irb);
}
void
dasd_log_ccw(dasd_ccw_req_t * cqr, int caller, __u32 cpa)
{
dasd_device_t *device;
dasd_ccw_req_t *lcqr;
struct ccw1 *ccw;
int cplength;
device = cqr->device;
/* log the channel program */
for (lcqr = cqr; lcqr != NULL; lcqr = lcqr->refers) {
DEV_MESSAGE(KERN_ERR, device,
......@@ -229,17 +238,17 @@ dasd_log_ccw(dasd_ccw_req_t * cqr, int caller, __u32 cpa)
DEV_MESSAGE(KERN_ERR, device, "%s",
"Start of channel program:");
hex_dump_memory(device, lcqr->cpaddr,
40*sizeof(ccw1_t));
40*sizeof(struct ccw1));
DEV_MESSAGE(KERN_ERR, device, "%s",
"End of channel program:");
hex_dump_memory(device, lcqr->cpaddr + cplength - 10,
10*sizeof(ccw1_t));
10*sizeof(struct ccw1));
} else { /* log the whole CP */
DEV_MESSAGE(KERN_ERR, device, "%s",
"Channel program (complete):");
hex_dump_memory(device, lcqr->cpaddr,
cplength*sizeof(ccw1_t));
cplength*sizeof(struct ccw1));
}
if (lcqr != cqr)
......@@ -258,7 +267,7 @@ dasd_log_ccw(dasd_ccw_req_t * cqr, int caller, __u32 cpa)
"Failed CCW (%p) (area):",
(void *) (long) cpa);
hex_dump_memory(device, cqr->cpaddr - 10,
20*sizeof(ccw1_t));
20*sizeof(struct ccw1));
}
}
......@@ -268,4 +277,5 @@ EXPORT_SYMBOL(dasd_default_erp_action);
EXPORT_SYMBOL(dasd_default_erp_postaction);
EXPORT_SYMBOL(dasd_alloc_erp_request);
EXPORT_SYMBOL(dasd_free_erp_request);
EXPORT_SYMBOL(dasd_log_sense);
EXPORT_SYMBOL(dasd_log_ccw);
/*
* File...........: linux/drivers/s390/block/dasd_fba.c
* Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
*
* $Revision: 1.25 $
*
* History of changes
* fixed partition handling and HDIO_GETGEO
* 2002/01/04 Created 2.4-2.5 compatibility mode
* 05/04/02 code restructuring.
......@@ -17,13 +20,14 @@
#include <linux/slab.h>
#include <linux/hdreg.h> /* HDIO_GETGEO */
#include <linux/bio.h>
#include <linux/module.h>
#include <linux/init.h>
#include <asm/idals.h>
#include <asm/ebcdic.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/s390dyn.h>
#include <asm/todclk.h>
#include <asm/ccwdev.h>
#include "dasd_int.h"
#include "dasd_fba.h"
......@@ -38,30 +42,47 @@
#define DASD_FBA_CCW_LOCATE 0x43
#define DASD_FBA_CCW_DEFINE_EXTENT 0x63
MODULE_LICENSE("GPL");
static dasd_discipline_t dasd_fba_discipline;
typedef struct dasd_fba_private_t {
dasd_fba_characteristics_t rdc_data;
} dasd_fba_private_t;
static
devreg_t dasd_fba_known_devices[] = {
{
.ci = {.hc = {.ctype = 0x6310, .dtype = 0x9336}},
.flag = (DEVREG_MATCH_CU_TYPE |
DEVREG_MATCH_DEV_TYPE | DEVREG_TYPE_DEVCHARS),
.oper_func = dasd_oper_handler
},
{
.ci = {.hc = {.ctype = 0x3880, .dtype = 0x3370}},
.flag = (DEVREG_MATCH_CU_TYPE |
DEVREG_MATCH_DEV_TYPE | DEVREG_TYPE_DEVCHARS),
.oper_func = dasd_oper_handler
}
static struct ccw_device_id dasd_fba_ids[] = {
{ CCW_DEVICE_DEVTYPE (0x6310, 0, 0x9336, 0), driver_info: 0x1},
{ CCW_DEVICE_DEVTYPE (0x3880, 0, 0x3370, 0), driver_info: 0x2},
{ /* end of list */ },
};
MODULE_DEVICE_TABLE(ccw, dasd_fba_ids);
static struct ccw_driver dasd_fba_driver; /* see below */
static int
dasd_fba_probe(struct ccw_device *cdev)
{
return dasd_generic_probe (cdev, &dasd_fba_discipline);
}
static int
dasd_fba_set_online(struct ccw_device *cdev)
{
return dasd_generic_set_online (cdev, &dasd_fba_discipline);
}
static struct ccw_driver dasd_fba_driver = {
.name = "dasd-fba",
.owner = THIS_MODULE,
.ids = dasd_fba_ids,
.probe = dasd_fba_probe,
.remove = dasd_generic_remove,
.set_offline = dasd_generic_set_offline,
.set_online = dasd_fba_set_online,
};
static inline void
define_extent(ccw1_t * ccw, DE_fba_data_t *data, int rw,
define_extent(struct ccw1 * ccw, DE_fba_data_t *data, int rw,
int blksize, int beg, int nr)
{
ccw->cmd_code = DASD_FBA_CCW_DEFINE_EXTENT;
......@@ -81,7 +102,7 @@ define_extent(ccw1_t * ccw, DE_fba_data_t *data, int rw,
}
static inline void
locate_record(ccw1_t * ccw, LO_fba_data_t *data, int rw,
locate_record(struct ccw1 * ccw, LO_fba_data_t *data, int rw,
int block_nr, int block_ct)
{
ccw->cmd_code = DASD_FBA_CCW_LOCATE;
......@@ -99,22 +120,11 @@ locate_record(ccw1_t * ccw, LO_fba_data_t *data, int rw,
data->blk_ct = block_ct;
}
static inline int
dasd_fba_id_check(s390_dev_info_t * info)
{
if (info->sid_data.cu_type == 0x3880)
if (info->sid_data.dev_type == 0x3370)
return 0;
if (info->sid_data.cu_type == 0x6310)
if (info->sid_data.dev_type == 0x9336)
return 0;
return -ENODEV;
}
static inline int
static int
dasd_fba_check_characteristics(struct dasd_device_t *device)
{
dasd_fba_private_t *private;
struct ccw_device *cdev = device->cdev;
void *rdc_data;
int rc;
......@@ -130,7 +140,7 @@ dasd_fba_check_characteristics(struct dasd_device_t *device)
}
/* Read Device Characteristics */
rdc_data = (void *) &(private->rdc_data);
rc = read_dev_chars(device->devinfo.irq, &rdc_data, 32);
rc = read_dev_chars(device->cdev, &rdc_data, 32);
if (rc) {
MESSAGE(KERN_WARNING,
"Read device characteristics returned error %d", rc);
......@@ -139,27 +149,16 @@ dasd_fba_check_characteristics(struct dasd_device_t *device)
DEV_MESSAGE(KERN_INFO, device,
"%04X/%02X(CU:%04X/%02X) %dMB at(%d B/blk)",
device->devinfo.sid_data.dev_type,
device->devinfo.sid_data.dev_model,
device->devinfo.sid_data.cu_type,
device->devinfo.sid_data.cu_model,
cdev->id.dev_type,
cdev->id.dev_model,
cdev->id.cu_type,
cdev->id.cu_model,
((private->rdc_data.blk_bdsa *
(private->rdc_data.blk_size >> 9)) >> 11),
private->rdc_data.blk_size);
return 0;
}
static int
dasd_fba_check_device(struct dasd_device_t *device)
{
int rc;
rc = dasd_fba_id_check(&device->devinfo);
if (rc)
return rc;
return dasd_fba_check_characteristics(device);
}
static int
dasd_fba_do_analysis(struct dasd_device_t *device)
{
......@@ -193,20 +192,22 @@ dasd_fba_fill_geometry(struct dasd_device_t *device, struct hd_geometry *geo)
}
static dasd_era_t
dasd_fba_examine_error(dasd_ccw_req_t * cqr, devstat_t * stat)
dasd_fba_examine_error(dasd_ccw_req_t * cqr, struct irb * irb)
{
dasd_device_t *device;
struct ccw_device *cdev;
device = (dasd_device_t *) cqr->device;
if (stat->cstat == 0x00 &&
stat->dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
if (irb->scsw.cstat == 0x00 &&
irb->scsw.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
return dasd_era_none;
switch (device->devinfo.sid_data.dev_model) {
cdev = device->cdev;
switch (cdev->id.dev_model) {
case 0x3370:
return dasd_3370_erp_examine(cqr, stat);
return dasd_3370_erp_examine(cqr, irb);
case 0x9336:
return dasd_9336_erp_examine(cqr, stat);
return dasd_9336_erp_examine(cqr, irb);
default:
return dasd_era_recover;
}
......@@ -236,7 +237,7 @@ dasd_fba_build_cp(dasd_device_t * device, struct request *req)
unsigned long *idaws;
LO_fba_data_t *LO_data;
dasd_ccw_req_t *cqr;
ccw1_t *ccw;
struct ccw1 *ccw;
struct bio *bio;
struct bio_vec *bv;
char *dst;
......@@ -359,7 +360,8 @@ dasd_fba_fill_info(dasd_device_t * device, dasd_information2_t * info)
}
static void
dasd_fba_dump_sense(struct dasd_device_t *device, dasd_ccw_req_t * req)
dasd_fba_dump_sense(struct dasd_device_t *device, dasd_ccw_req_t * req,
struct irb *irb)
{
char *page;
......@@ -369,8 +371,8 @@ dasd_fba_dump_sense(struct dasd_device_t *device, dasd_ccw_req_t * req)
return;
}
sprintf(page, KERN_WARNING PRINTK_HEADER
"device %04X on irq %d: I/O status report:\n",
device->devinfo.devno, device->devinfo.irq);
"device %s: I/O status report:\n",
device->cdev->dev.bus_id);
MESSAGE(KERN_ERR, "Sense data:\n%s", page);
......@@ -396,7 +398,7 @@ static dasd_discipline_t dasd_fba_discipline = {
.name = "FBA ",
.ebcname = "FBA ",
.max_blocks = 96,
.check_device = dasd_fba_check_device,
.check_device = dasd_fba_check_characteristics,
.do_analysis = dasd_fba_do_analysis,
.fill_geometry = dasd_fba_fill_geometry,
.start_IO = dasd_start_IO,
......@@ -409,41 +411,22 @@ static dasd_discipline_t dasd_fba_discipline = {
.fill_info = dasd_fba_fill_info,
};
int
static int __init
dasd_fba_init(void)
{
int i;
ASCEBC(dasd_fba_discipline.ebcname, 4);
dasd_discipline_add(&dasd_fba_discipline);
for (i = 0; i < sizeof(dasd_fba_known_devices) / sizeof(devreg_t); i++)
s390_device_register(&dasd_fba_known_devices[i]);
return 0;
}
void
dasd_fba_cleanup(void)
{
int i;
for (i = 0; i < sizeof(dasd_fba_known_devices) / sizeof(devreg_t); i++)
s390_device_unregister(&dasd_fba_known_devices[i]);
dasd_discipline_del(&dasd_fba_discipline);
return ccw_driver_register(&dasd_fba_driver);
}
#ifdef MODULE
int
init_module(void)
static void __exit
dasd_fba_cleanup(void)
{
return dasd_fba_init();
ccw_driver_unregister(&dasd_fba_driver);
}
void
cleanup_module(void)
{
dasd_fba_cleanup();
}
#endif
module_init(dasd_fba_init);
module_exit(dasd_fba_cleanup);
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
......
/*
* File...........: linux/drivers/s390/block/dasd_fba.h
* Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
*
* $Revision: 1.4 $
*
* History of changes
*
*/
#ifndef DASD_FBA_H
#define DASD_FBA_H
......@@ -71,6 +82,4 @@ typedef
dasd_fba_characteristics_t;
int dasd_fba_init(void);
void dasd_fba_cleanup(void);
#endif /* DASD_FBA_H */
/*
* File...........: linux/drivers/s390/block/dasd_ioctl.c
* File...........: linux/drivers/s390/block/dasd_genhd.c
* Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
* Horst Hummel <Horst.Hummel@de.ibm.com>
* Carsten Otte <Cotte@de.ibm.com>
......@@ -9,6 +9,9 @@
*
* Dealing with devices registered to multiple major numbers.
*
* $Revision: 1.23 $
*
* History of changes
* 05/04/02 split from dasd.c, code restructuring.
*/
......@@ -19,7 +22,6 @@
#include <linux/blkpg.h>
#include <linux/blk.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
/* This is ugly... */
......@@ -72,7 +74,6 @@ dasd_register_major(int major)
/* Initialize major info structure. */
mi->major = new_major;
/* Setup block device pointers for the new major. */
/* Insert the new major info structure into dasd_major_info list. */
spin_lock(&dasd_major_lock);
list_add_tail(&mi->list, &dasd_major_info);
......@@ -104,35 +105,6 @@ dasd_unregister_major(struct major_info * mi)
kfree(mi);
}
/*
* 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
dasd_device_name(char *str, int index, int partition)
{
int len;
if (partition > DASD_PARTN_MASK)
return -EINVAL;
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;
}
/*
* Allocate gendisk structure for devindex.
*/
......@@ -196,7 +168,7 @@ dasd_gendisk_alloc(int devindex)
/*
* Return devindex of first device using a specific major number.
*/
int dasd_gendisk_major_index(int major)
static int dasd_gendisk_major_index(int major)
{
struct list_head *l;
struct major_info *mi;
......
/*
* File...........: linux/drivers/s390/block/dasd.c
* File...........: linux/drivers/s390/block/dasd_int.h
* Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
* Horst Hummel <Horst.Hummel@de.ibm.com>
* Martin Schwidefsky <schwidefsky@de.ibm.com>
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
*
* $Revision: 1.36 $
*
* History of changes (starts July 2000)
* 02/01/01 added dynamic registration of ioctls
* 2002/01/04 Created 2.4-2.5 compatibility mode
......@@ -58,12 +61,11 @@
#include <linux/genhd.h>
#include <linux/hdreg.h>
#include <linux/interrupt.h>
#include <asm/ccwdev.h>
#include <linux/workqueue.h>
#include <asm/debug.h>
#include <asm/dasd.h>
#include <asm/idals.h>
#include <asm/irq.h>
#include <asm/s390dyn.h>
/*
* SECTION: Type definitions
......@@ -140,10 +142,9 @@ 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,%04x@%02x: " \
printk(d_loglevel PRINTK_HEADER " %s,%s: " \
d_string "\n", d_device->gdp->disk_name, \
d_device->devinfo.devno, d_device->devinfo.irq, \
d_args); \
d_device->cdev->dev.bus_id, d_args); \
DBF_DEV_EVENT(DBF_ALERT, d_device, d_string, d_args); \
} while(0)
......@@ -159,18 +160,17 @@ typedef struct dasd_ccw_req_t {
/* Where to execute what... */
struct dasd_device_t *device; /* device the request is for */
ccw1_t *cpaddr; /* address of channel program */
struct ccw1 *cpaddr; /* address of channel program */
char status; /* status of this request */
short retries; /* A retry counter */
/* ... and how */
int options; /* options for execution */
int expires; /* expiration period in jiffies */
char lpm; /* logical path mask */
void *data; /* pointer to data area */
/* these are important for recovering erroneous requests */
devstat_t *dstat; /* device status in case of an error */
struct irb *dstat; /* device status in case of an error */
struct dasd_ccw_req_t *refers; /* ERP-chain queueing. */
void *function; /* originating ERP action */
......@@ -247,16 +247,24 @@ typedef struct dasd_discipline_t {
* is called for every error condition to print the sense data
* to the console.
*/
dasd_era_t(*examine_error) (dasd_ccw_req_t *, devstat_t *);
dasd_era_t(*examine_error) (dasd_ccw_req_t *, struct irb *);
dasd_erp_fn_t(*erp_action) (dasd_ccw_req_t *);
dasd_erp_fn_t(*erp_postaction) (dasd_ccw_req_t *);
void (*dump_sense) (struct dasd_device_t *, dasd_ccw_req_t *);
void (*dump_sense) (struct dasd_device_t *, dasd_ccw_req_t *,
struct irb *);
/* i/o control functions. */
int (*fill_geometry) (struct dasd_device_t *, struct hd_geometry *);
int (*fill_info) (struct dasd_device_t *, dasd_information2_t *);
} dasd_discipline_t;
extern dasd_discipline_t dasd_diag_discipline;
#ifdef CONFIG_DASD_DIAG
#define dasd_diag_discipline_pointer (&dasd_diag_discipline)
#else
#define dasd_diag_discipline_pointer (0)
#endif
typedef struct dasd_device_t {
/* Block device stuff. */
struct gendisk *gdp;
......@@ -267,6 +275,8 @@ typedef struct dasd_device_t {
unsigned int bp_block; /* bytes per block */
unsigned int s2b_shift; /* log2 (bp_block/512) */
int ro_flag; /* read-only flag */
int use_diag_flag; /* diag allowed flag */
/* Device discipline stuff. */
dasd_discipline_t *discipline;
......@@ -288,8 +298,8 @@ typedef struct dasd_device_t {
struct list_head erp_chunks;
/* Common i/o stuff. */
s390_dev_info_t devinfo;
devstat_t dev_status;
/* FIXME: remove the next */
int devno;
atomic_t tasklet_scheduled;
struct tasklet_struct tasklet;
......@@ -297,6 +307,9 @@ typedef struct dasd_device_t {
struct timer_list timer;
debug_info_t *debug_area;
struct ccw_device *cdev;
#ifdef CONFIG_DASD_PROFILE
dasd_profile_info_t profile;
#endif
......@@ -318,7 +331,6 @@ typedef struct {
unsigned int devindex;
unsigned short devno;
unsigned short features;
devreg_t *devreg;
dasd_device_t *device;
} dasd_devmap_t;
......@@ -427,17 +439,14 @@ void dasd_kfree_request(dasd_ccw_req_t *, dasd_device_t *);
void dasd_sfree_request(dasd_ccw_req_t *, dasd_device_t *);
static inline int
dasd_kmalloc_set_cda(ccw1_t *ccw, void *cda, dasd_device_t *device)
dasd_kmalloc_set_cda(struct ccw1 *ccw, void *cda, dasd_device_t *device)
{
return set_normalized_cda(ccw, cda);
}
dasd_device_t *dasd_alloc_device(dasd_devmap_t *);
void dasd_free_device(dasd_device_t *);
void dasd_enable_devices(int, int);
void dasd_disable_devices(int, int);
void dasd_discipline_add(dasd_discipline_t *);
void dasd_discipline_del(dasd_discipline_t *);
void dasd_enable_device(dasd_device_t *);
void dasd_set_target_state(dasd_device_t *, int);
void dasd_kick_device(dasd_device_t *);
......@@ -445,7 +454,6 @@ void dasd_add_request_head(dasd_ccw_req_t *);
void dasd_add_request_tail(dasd_ccw_req_t *); /* unused */
int dasd_start_IO(dasd_ccw_req_t *);
int dasd_term_IO(dasd_ccw_req_t *);
int dasd_oper_handler(int, devreg_t *);
void dasd_schedule_bh(dasd_device_t *);
int dasd_sleep_on(dasd_ccw_req_t *);
int dasd_sleep_on_immediatly(dasd_ccw_req_t *);
......@@ -453,6 +461,12 @@ int dasd_sleep_on_interruptible(dasd_ccw_req_t *);
void dasd_set_timer(dasd_device_t *, int);
void dasd_clear_timer(dasd_device_t *);
int dasd_cancel_req(dasd_ccw_req_t *); /* unused */
int dasd_generic_probe (struct ccw_device *cdev,
dasd_discipline_t *discipline);
int dasd_generic_remove (struct ccw_device *cdev);
int dasd_generic_set_online(struct ccw_device *cdev,
dasd_discipline_t *discipline);
int dasd_generic_set_offline (struct ccw_device *cdev);
/* externals in dasd_devmap.c */
extern int dasd_max_devindex;
......@@ -463,20 +477,15 @@ int dasd_devmap_init(void);
void dasd_devmap_exit(void);
dasd_devmap_t *dasd_devmap_from_devno(int);
dasd_devmap_t *dasd_devmap_from_devindex(int);
dasd_devmap_t *dasd_devmap_from_irq(int);
dasd_devmap_t *dasd_devmap_from_bdev(struct block_device *bdev);
dasd_device_t *dasd_get_device(dasd_devmap_t *);
void dasd_put_device(dasd_devmap_t *);
int dasd_devno(char *, char **);
int dasd_feature_list(char *, char **);
int dasd_parse(void);
int dasd_add_range(int, int, int);
/* externals in dasd_gendisk.c */
int dasd_gendisk_init(void);
void dasd_gendisk_exit(void);
int dasd_gendisk_major_index(int);
int dasd_gendisk_index_major(int);
struct gendisk *dasd_gendisk_alloc(int);
void dasd_setup_partitions(dasd_device_t *);
......@@ -498,22 +507,21 @@ dasd_ccw_req_t *dasd_default_erp_action(dasd_ccw_req_t *);
dasd_ccw_req_t *dasd_default_erp_postaction(dasd_ccw_req_t *);
dasd_ccw_req_t *dasd_alloc_erp_request(char *, int, int, dasd_device_t *);
void dasd_free_erp_request(dasd_ccw_req_t *, dasd_device_t *);
void dasd_log_sense(dasd_ccw_req_t *, struct irb *);
void dasd_log_ccw(dasd_ccw_req_t *, int, __u32);
/* externals in dasd_3370_erp.c */
dasd_era_t dasd_3370_erp_examine(dasd_ccw_req_t *, devstat_t *);
dasd_era_t dasd_3370_erp_examine(dasd_ccw_req_t *, struct irb *);
/* externals in dasd_3990_erp.c */
dasd_era_t dasd_3990_erp_examine(dasd_ccw_req_t *, devstat_t *);
dasd_era_t dasd_3990_erp_examine(dasd_ccw_req_t *, struct irb *);
dasd_ccw_req_t *dasd_3990_erp_action(dasd_ccw_req_t *);
dasd_ccw_req_t *dasd_2105_erp_action(dasd_ccw_req_t *);
void dasd_3990_erp_restart_queue(unsigned long);
/* externals in dasd_9336_erp.c */
dasd_era_t dasd_9336_erp_examine(dasd_ccw_req_t *, devstat_t *);
dasd_era_t dasd_9336_erp_examine(dasd_ccw_req_t *, struct irb *);
/* externals in dasd_9336_erp.c */
dasd_era_t dasd_9343_erp_examine(dasd_ccw_req_t *, devstat_t *);
dasd_era_t dasd_9343_erp_examine(dasd_ccw_req_t *, struct irb *);
dasd_ccw_req_t *dasd_9343_erp_action(dasd_ccw_req_t *);
#endif /* __KERNEL__ */
......
......@@ -19,7 +19,7 @@
#include <linux/blkpg.h>
#include <linux/blk.h>
#include <asm/irq.h>
#include <asm/ccwdev.h>
#include <asm/uaccess.h>
/* This is ugly... */
......@@ -125,7 +125,7 @@ dasd_ioctl(struct inode *inp, struct file *filp,
DBF_DEV_EVENT(DBF_INFO, device,
"unknown ioctl 0x%08x=%s'0x%x'%d(%d) data %8lx", no,
dir, _IOC_TYPE(no), _IOC_NR(no), _IOC_SIZE(no), data);
return -ENOTTY;
return -EINVAL;
}
static int
......@@ -137,24 +137,20 @@ 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
*/
static int
dasd_ioctl_enable(struct block_device *bdev, int no, long args)
{
dasd_devmap_t *devmap;
dasd_device_t *device;
int devno;
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
devmap = dasd_devmap_from_bdev(bdev);
device = (devmap != NULL) ?
dasd_get_device(devmap) : ERR_PTR(-ENODEV);
if (IS_ERR(device))
return PTR_ERR(device);
devno = device->devinfo.devno;
dasd_enable_devices(devno, devno);
dasd_put_device(devmap);
device = bdev->bd_disk->private_data;
if (device == NULL)
return -ENODEV;
dasd_enable_device(device);
return 0;
}
......@@ -164,16 +160,13 @@ dasd_ioctl_enable(struct block_device *bdev, int no, long args)
static int
dasd_ioctl_disable(struct block_device *bdev, int no, long args)
{
dasd_devmap_t *devmap;
dasd_device_t *device;
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
devmap = dasd_devmap_from_bdev(bdev);
device = (devmap != NULL) ?
dasd_get_device(devmap) : ERR_PTR(-ENODEV);
if (IS_ERR(device))
return PTR_ERR(device);
device = bdev->bd_disk->private_data;
if (device == NULL)
return -ENODEV;
/*
* Man this is sick. We don't do a real disable but only downgrade
* the device to DASD_STATE_BASIC. The reason is that dasdfmt uses
......@@ -183,7 +176,6 @@ dasd_ioctl_disable(struct block_device *bdev, int no, long args)
* device is DASD_STATE_BASIC that allows to do basic i/o.
*/
dasd_set_target_state(device, DASD_STATE_BASIC);
dasd_put_device(devmap);
return 0;
}
......@@ -238,35 +230,28 @@ dasd_format(dasd_device_t * device, format_data_t * fdata)
static int
dasd_ioctl_format(struct block_device *bdev, int no, long args)
{
dasd_devmap_t *devmap;
dasd_device_t *device;
format_data_t fdata;
int rc;
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
if (!args)
return -EINVAL;
/* fdata == NULL is no longer a valid arg to dasd_format ! */
devmap = dasd_devmap_from_bdev(bdev);
device = (devmap != NULL) ?
dasd_get_device(devmap) : ERR_PTR(-ENODEV);
if (IS_ERR(device))
return PTR_ERR(device);
device = bdev->bd_disk->private_data;
rc = 0;
if (devmap->features & DASD_FEATURE_READONLY)
rc = -EROFS;
else if (copy_from_user(&fdata, (void *) args, sizeof (format_data_t)))
rc = -EFAULT;
else if (bdev != bdev->bd_contains) {
if (device == NULL)
return -ENODEV;
if (device->ro_flag)
return -EROFS;
if (copy_from_user(&fdata, (void *) args, sizeof (format_data_t)))
return -EFAULT;
if (bdev != bdev->bd_contains) {
DEV_MESSAGE(KERN_WARNING, device, "%s",
"Cannot low-level format a partition");
rc = -EINVAL;
} else
rc = dasd_format(device, &fdata);
dasd_put_device(devmap);
return rc;
return -EINVAL;
}
return dasd_format(device, &fdata);
}
#ifdef CONFIG_DASD_PROFILE
......@@ -276,18 +261,16 @@ dasd_ioctl_format(struct block_device *bdev, int no, long args)
static int
dasd_ioctl_reset_profile(struct block_device *bdev, int no, long args)
{
dasd_devmap_t *devmap;
dasd_device_t *device;
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
devmap = dasd_devmap_from_bdev(bdev);
device = (devmap != NULL) ?
dasd_get_device(devmap) : ERR_PTR(-ENODEV);
if (IS_ERR(device))
return PTR_ERR(device);
device = = bdev->bd_disk->private_data;
if (device == NULL)
return -ENODEV;
memset(&device->profile, 0, sizeof (dasd_profile_info_t));
dasd_put_device(devmap);
return 0;
}
......@@ -297,21 +280,16 @@ dasd_ioctl_reset_profile(struct block_device *bdev, int no, long args)
static int
dasd_ioctl_read_profile(struct block_device *bdev, int no, long args)
{
dasd_devmap_t *devmap;
dasd_device_t *device;
int rc;
devmap = dasd_devmap_from_bdev(bdev);
device = (devmap != NULL) ?
dasd_get_device(devmap) : ERR_PTR(-ENODEV);
if (IS_ERR(device))
return PTR_ERR(device);
rc = 0;
device = = bdev->bd_disk->private_data;
if (device == NULL)
return -ENODEV;
if (copy_to_user((long *) args, (long *) &device->profile,
sizeof (dasd_profile_info_t)))
rc = -EFAULT;
dasd_put_device(devmap);
return rc;
return -EFAULT;
return 0;
}
#else
static int
......@@ -333,40 +311,37 @@ dasd_ioctl_read_profile(struct block_device *bdev, int no, long args)
static int
dasd_ioctl_information(struct block_device *bdev, int no, long args)
{
dasd_devmap_t *devmap;
dasd_device_t *device;
dasd_information2_t *dasd_info;
unsigned long flags;
int rc;
struct ccw_device *cdev;
devmap = dasd_devmap_from_bdev(bdev);
device = (devmap != NULL) ?
dasd_get_device(devmap) : ERR_PTR(-ENODEV);
if (IS_ERR(device))
return PTR_ERR(device);
if (!device->discipline->fill_info) {
dasd_put_device(devmap);
device = bdev->bd_disk->private_data;
if (device == NULL)
return -ENODEV;
if (!device->discipline->fill_info)
return -EINVAL;
}
dasd_info = kmalloc(sizeof(dasd_information2_t), GFP_KERNEL);
if (dasd_info == NULL) {
dasd_put_device(devmap);
if (dasd_info == NULL)
return -ENOMEM;
}
rc = device->discipline->fill_info(device, dasd_info);
if (rc) {
dasd_put_device(devmap);
kfree(dasd_info);
return rc;
}
dasd_info->devno = device->devinfo.devno;
dasd_info->schid = device->devinfo.irq;
dasd_info->cu_type = device->devinfo.sid_data.cu_type;
dasd_info->cu_model = device->devinfo.sid_data.cu_model;
dasd_info->dev_type = device->devinfo.sid_data.dev_type;
dasd_info->dev_model = device->devinfo.sid_data.dev_model;
cdev = device->cdev;
dasd_info->devno = device->devno;
dasd_info->schid = _ccw_device_get_subchannel_number(device->cdev);
dasd_info->cu_type = cdev->id.cu_type;
dasd_info->cu_model = cdev->id.cu_model;
dasd_info->dev_type = cdev->id.dev_type;
dasd_info->dev_model = cdev->id.dev_model;
dasd_info->open_count = atomic_read(&device->open_count);
dasd_info->status = device->state;
......@@ -378,7 +353,8 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args)
(dasd_check_blocksize(device->bp_block)))
dasd_info->format = DASD_FORMAT_NONE;
dasd_info->features = devmap->features;
dasd_info->features |= device->ro_flag ? DASD_FEATURE_READONLY
: DASD_FEATURE_DEFAULT;
if (device->discipline)
memcpy(dasd_info->type, device->discipline->name, 4);
......@@ -397,10 +373,10 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args)
spin_unlock_irqrestore(&device->lock, flags);
}
#endif /* DASD_EXTENDED_PROFILING */
spin_lock_irqsave(get_irq_lock(device->devinfo.irq), flags);
spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
list_for_each(l, &device->ccw_queue)
dasd_info->chanq_len++;
spin_unlock_irqrestore(get_irq_lock(device->devinfo.irq),
spin_unlock_irqrestore(get_ccwdev_lock(device->cdev),
flags);
}
......@@ -410,7 +386,6 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args)
sizeof (dasd_information2_t) :
sizeof (dasd_information_t))))
rc = -EFAULT;
dasd_put_device(devmap);
kfree(dasd_info);
return rc;
}
......@@ -421,9 +396,8 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args)
static int
dasd_ioctl_set_ro(struct block_device *bdev, int no, long args)
{
dasd_devmap_t *devmap;
dasd_device_t *device;
int intval, i;
int intval;
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
......@@ -432,18 +406,11 @@ dasd_ioctl_set_ro(struct block_device *bdev, int no, long args)
return -EINVAL;
if (get_user(intval, (int *) args))
return -EFAULT;
devmap = dasd_devmap_from_bdev(bdev);
device = (devmap != NULL) ?
dasd_get_device(devmap) : ERR_PTR(-ENODEV);
if (IS_ERR(device))
return PTR_ERR(device);
if (intval)
devmap->features |= DASD_FEATURE_READONLY;
else
devmap->features &= ~DASD_FEATURE_READONLY;
device = bdev->bd_disk->private_data;
if (device == NULL)
return -ENODEV;
set_disk_ro(bdev->bd_disk, intval);
device->ro_flag = intval;
dasd_put_device(devmap);
return 0;
}
......@@ -454,27 +421,24 @@ static int
dasd_ioctl_getgeo(struct block_device *bdev, int no, long args)
{
struct hd_geometry geo = { 0, };
dasd_devmap_t *devmap;
dasd_device_t *device;
int rc;
devmap = dasd_devmap_from_bdev(bdev);
device = (devmap != NULL) ?
dasd_get_device(devmap) : ERR_PTR(-ENODEV);
if (IS_ERR(device))
return PTR_ERR(device);
rc = 0;
if (device != NULL && device->discipline != NULL &&
device->discipline->fill_geometry != NULL) {
device = bdev->bd_disk->private_data;
if (device == NULL)
return -ENODEV;
if (device == NULL || device->discipline == NULL ||
device->discipline->fill_geometry == NULL)
return -EINVAL;
geo = (struct hd_geometry) {};
device->discipline->fill_geometry(device, &geo);
geo.start = get_start_sect(bdev);
geo.start = get_start_sect(bdev) >> device->s2b_shift;
if (copy_to_user((struct hd_geometry *) args, &geo,
sizeof (struct hd_geometry)))
rc = -EFAULT;
} else
rc = -EINVAL;
dasd_put_device(devmap);
return rc;
return -EFAULT;
return 0;
}
/*
......
This diff is collapsed.
......@@ -8,6 +8,8 @@
* any future changes wrt the API will result in a change of the APIVERSION reported
* to userspace by the DASDAPIVER-ioctl
*
* $Revision: 1.3 $
*
* History of changes (starts July 2000)
* 05/04/01 created by moving the kernel interface to drivers/s390/block/dasd_int.h
* 12/06/01 DASD_API_VERSION 2 - binary compatible to 0 (new BIODASDINFO2)
......@@ -224,8 +226,6 @@ typedef struct attrib_data_t {
#define BIODASDSLCK _IO(DASD_IOCTL_LETTER,4) /* steal lock */
/* reset profiling information of a device */
#define BIODASDPRRST _IO(DASD_IOCTL_LETTER,5)
/* enable PAV */
#define BIODASDENAPAV _IO(DASD_IOCTL_LETTER,6)
/* retrieve API version number */
......
......@@ -8,6 +8,8 @@
* any future changes wrt the API will result in a change of the APIVERSION reported
* to userspace by the DASDAPIVER-ioctl
*
* $Revision: 1.3 $
*
* History of changes (starts July 2000)
* 05/04/01 created by moving the kernel interface to drivers/s390/block/dasd_int.h
* 12/06/01 DASD_API_VERSION 2 - binary compatible to 0 (new BIODASDINFO2)
......@@ -224,8 +226,6 @@ typedef struct attrib_data_t {
#define BIODASDSLCK _IO(DASD_IOCTL_LETTER,4) /* steal lock */
/* reset profiling information of a device */
#define BIODASDPRRST _IO(DASD_IOCTL_LETTER,5)
/* enable PAV */
#define BIODASDENAPAV _IO(DASD_IOCTL_LETTER,6)
/* retrieve API version number */
......
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