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