Commit 04d81fff authored by Martin Schwidefsky's avatar Martin Schwidefsky Committed by Linus Torvalds

[PATCH] s390: dasd driver changes

From: Horst Hummel <horst.hummel@de.ibm.com>
From: Carsten Otte <cotte@de.ibm.com>
From: Stefan Weinhuber <wein@de.ibm.com>

dasd device driver changes:
 - Fix calculation of number of idal words needed for a channel program.
 - Fix race in i/o termination after request timeout.
 - Fix race in state change interrupt handling.
 - Fix call to BLKPG ioctl in dasd_destroy_partitions.
 - Integrate irb into dasd request to avoid kmalloc in the interrupt handler.
 - Store build clock for error recovery requests.
 - Remove unused cpu variable from dasd_ext_handler.
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 17db3da8
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* 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.142 $ * $Revision: 1.146 $
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -623,8 +623,6 @@ dasd_kfree_request(struct dasd_ccw_req * cqr, struct dasd_device * device) ...@@ -623,8 +623,6 @@ dasd_kfree_request(struct dasd_ccw_req * cqr, struct dasd_device * device)
clear_normalized_cda(ccw); clear_normalized_cda(ccw);
} while (ccw++->flags & (CCW_FLAG_CC | CCW_FLAG_DC)); } while (ccw++->flags & (CCW_FLAG_CC | CCW_FLAG_DC));
#endif #endif
if (cqr->dstat != NULL)
kfree(cqr->dstat);
debug_text_event ( dasd_debug_area, 1, "FREE"); debug_text_event ( dasd_debug_area, 1, "FREE");
debug_int_event ( dasd_debug_area, 1, (long) cqr); debug_int_event ( dasd_debug_area, 1, (long) cqr);
if (cqr->cpaddr != NULL) if (cqr->cpaddr != NULL)
...@@ -640,8 +638,6 @@ dasd_sfree_request(struct dasd_ccw_req * cqr, struct dasd_device * device) ...@@ -640,8 +638,6 @@ dasd_sfree_request(struct dasd_ccw_req * cqr, struct dasd_device * device)
{ {
unsigned long flags; unsigned long flags;
if (cqr->dstat != NULL)
kfree(cqr->dstat);
debug_text_event(dasd_debug_area, 1, "FREE"); debug_text_event(dasd_debug_area, 1, "FREE");
debug_int_event(dasd_debug_area, 1, (long) cqr); debug_int_event(dasd_debug_area, 1, (long) cqr);
spin_lock_irqsave(&device->mem_lock, flags); spin_lock_irqsave(&device->mem_lock, flags);
...@@ -673,7 +669,8 @@ dasd_check_cqr(struct dasd_ccw_req *cqr) ...@@ -673,7 +669,8 @@ dasd_check_cqr(struct dasd_ccw_req *cqr)
} }
/* /*
* Terminate the current i/o and set the request to failed. * Terminate the current i/o and set the request to clear_pending.
* Timer keeps device runnig.
* ccw_device_clear can fail if the i/o subsystem * ccw_device_clear can fail if the i/o subsystem
* is in a bad mood. * is in a bad mood.
*/ */
...@@ -695,7 +692,7 @@ dasd_term_IO(struct dasd_ccw_req * cqr) ...@@ -695,7 +692,7 @@ dasd_term_IO(struct dasd_ccw_req * cqr)
case 0: /* termination successful */ case 0: /* termination successful */
if (cqr->retries > 0) { if (cqr->retries > 0) {
cqr->retries--; cqr->retries--;
cqr->status = DASD_CQR_QUEUED; cqr->status = DASD_CQR_CLEAR;
} else } else
cqr->status = DASD_CQR_FAILED; cqr->status = DASD_CQR_FAILED;
cqr->stopclk = get_clock(); cqr->stopclk = get_clock();
...@@ -826,41 +823,6 @@ dasd_clear_timer(struct dasd_device *device) ...@@ -826,41 +823,6 @@ dasd_clear_timer(struct dasd_device *device)
del_timer(&device->timer); del_timer(&device->timer);
} }
/*
* Handles the state change pending interrupt.
*/
static void
do_state_change_pending(void *data)
{
struct {
struct work_struct work;
struct dasd_device *device;
} *p;
struct dasd_device *device;
struct dasd_ccw_req *cqr;
struct list_head *l, *n;
unsigned long flags;
p = data;
device = p->device;
DBF_EVENT(DBF_NOTICE, "State change Interrupt for bus_id %s",
device->cdev->dev.bus_id);
device->stopped &= ~DASD_STOPPED_PENDING;
/* restart all 'running' IO on queue */
spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
list_for_each_safe(l, n, &device->ccw_queue) {
cqr = list_entry(l, struct dasd_ccw_req, list);
if (cqr->status == DASD_CQR_IN_IO)
cqr->status = DASD_CQR_QUEUED;
}
spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
dasd_set_timer (device, 0);
dasd_schedule_bh(device);
dasd_put_device(device);
kfree(p);
}
static void static void
dasd_handle_killed_request(struct ccw_device *cdev, unsigned long intparm) dasd_handle_killed_request(struct ccw_device *cdev, unsigned long intparm)
{ {
...@@ -896,19 +858,20 @@ dasd_handle_killed_request(struct ccw_device *cdev, unsigned long intparm) ...@@ -896,19 +858,20 @@ dasd_handle_killed_request(struct ccw_device *cdev, unsigned long intparm)
static void static void
dasd_handle_state_change_pending(struct dasd_device *device) dasd_handle_state_change_pending(struct dasd_device *device)
{ {
struct { struct dasd_ccw_req *cqr;
struct work_struct work; struct list_head *l, *n;
struct dasd_device *device;
} *p;
p = kmalloc(sizeof(*p), GFP_ATOMIC); device->stopped &= ~DASD_STOPPED_PENDING;
if (p == NULL)
/* No memory, let the timeout do the reactivation. */ /* restart all 'running' IO on queue */
return; list_for_each_safe(l, n, &device->ccw_queue) {
INIT_WORK(&p->work, (void *) do_state_change_pending, p); cqr = list_entry(l, struct dasd_ccw_req, list);
p->device = device; if (cqr->status == DASD_CQR_IN_IO) {
dasd_get_device(device); cqr->status = DASD_CQR_QUEUED;
schedule_work(&p->work); }
}
dasd_clear_timer(device);
dasd_schedule_bh(device);
} }
/* /*
...@@ -944,8 +907,9 @@ dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, ...@@ -944,8 +907,9 @@ dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
now = get_clock(); now = get_clock();
DBF_EVENT(DBF_DEBUG, "Interrupt: stat %02x, bus_id %s", DBF_EVENT(DBF_ERR, "Interrupt: bus_id %s CS/DS %04x ip %08x",
irb->scsw.dstat, cdev->dev.bus_id); cdev->dev.bus_id, ((irb->scsw.cstat<<8)|irb->scsw.dstat),
(unsigned int) intparm);
/* first of all check for state change pending interrupt */ /* first of all check for state change pending interrupt */
mask = DEV_STAT_ATTENTION | DEV_STAT_DEV_END | DEV_STAT_UNIT_EXCEP; mask = DEV_STAT_ATTENTION | DEV_STAT_DEV_END | DEV_STAT_UNIT_EXCEP;
...@@ -959,14 +923,12 @@ dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, ...@@ -959,14 +923,12 @@ dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
} }
cqr = (struct dasd_ccw_req *) intparm; cqr = (struct dasd_ccw_req *) intparm;
/*
* check status - the request might have been killed /* check for unsolicited interrupts */
* because of dyn detach if (cqr == NULL) {
*/
if (cqr->status != DASD_CQR_IN_IO) {
MESSAGE(KERN_DEBUG, MESSAGE(KERN_DEBUG,
"invalid status: bus_id %s, status %02x", "unsolicited interrupt received: bus_id %s",
cdev->dev.bus_id, cqr->status); cdev->dev.bus_id);
return; return;
} }
...@@ -978,6 +940,22 @@ dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, ...@@ -978,6 +940,22 @@ dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
return; return;
} }
/* Check for clear pending */
if (cqr->status == DASD_CQR_CLEAR &&
irb->scsw.fctl & SCSW_FCTL_CLEAR_FUNC) {
cqr->status = DASD_CQR_QUEUED;
dasd_clear_timer(device);
dasd_schedule_bh(device);
return;
}
/* check status - the request might have been killed by dyn detach */
if (cqr->status != DASD_CQR_IN_IO) {
MESSAGE(KERN_DEBUG,
"invalid status: bus_id %s, status %02x",
cdev->dev.bus_id, cqr->status);
return;
}
DBF_DEV_EVENT(DBF_DEBUG, device, "Int: CS/DS 0x%04x", DBF_DEV_EVENT(DBF_DEBUG, device, "Int: CS/DS 0x%04x",
((irb->scsw.cstat << 8) | irb->scsw.dstat)); ((irb->scsw.cstat << 8) | irb->scsw.dstat));
...@@ -1015,13 +993,7 @@ dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, ...@@ -1015,13 +993,7 @@ dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
} }
} }
} else { /* error */ } else { /* error */
if (cqr->dstat == NULL) memcpy(&cqr->irb, irb, sizeof (struct irb));
cqr->dstat = kmalloc(sizeof(struct irb), GFP_ATOMIC);
if (cqr->dstat)
memcpy(cqr->dstat, irb, sizeof (struct irb));
else
DEV_MESSAGE(KERN_ERR, device, "%s",
"no memory for dstat...ignoring");
#ifdef ERP_DEBUG #ifdef ERP_DEBUG
/* dump sense data */ /* dump sense data */
dasd_log_sense(cqr, irb); dasd_log_sense(cqr, irb);
...@@ -1096,11 +1068,11 @@ __dasd_process_ccw_queue(struct dasd_device * device, ...@@ -1096,11 +1068,11 @@ __dasd_process_ccw_queue(struct dasd_device * device,
/* Process requests with DASD_CQR_ERROR */ /* Process requests with DASD_CQR_ERROR */
if (cqr->status == DASD_CQR_ERROR) { if (cqr->status == DASD_CQR_ERROR) {
cqr->retries--; cqr->retries--;
if (cqr->dstat->scsw.fctl & SCSW_FCTL_HALT_FUNC) { if (cqr->irb.scsw.fctl & SCSW_FCTL_HALT_FUNC) {
cqr->status = DASD_CQR_FAILED; cqr->status = DASD_CQR_FAILED;
cqr->stopclk = get_clock(); cqr->stopclk = get_clock();
} else { } else {
if (cqr->dstat->esw.esw0.erw.cons) { if (cqr->irb.esw.esw0.erw.cons) {
erp_fn = device->discipline->erp_action(cqr); erp_fn = device->discipline->erp_action(cqr);
erp_fn(cqr); erp_fn(cqr);
} else } else
...@@ -1221,8 +1193,8 @@ __dasd_check_expire(struct dasd_device * device) ...@@ -1221,8 +1193,8 @@ __dasd_check_expire(struct dasd_device * device)
if (cqr->status == DASD_CQR_IN_IO && cqr->expires != 0) { if (cqr->status == DASD_CQR_IN_IO && cqr->expires != 0) {
if (time_after_eq(jiffies, cqr->expires + cqr->starttime)) { if (time_after_eq(jiffies, cqr->expires + cqr->starttime)) {
if (device->discipline->term_IO(cqr) != 0) if (device->discipline->term_IO(cqr) != 0)
/* Hmpf, try again in 1/100 sec */ /* Hmpf, try again in 1/10 sec */
dasd_set_timer(device, 1); dasd_set_timer(device, 10);
} }
} }
} }
...@@ -1246,9 +1218,9 @@ __dasd_start_head(struct dasd_device * device) ...@@ -1246,9 +1218,9 @@ __dasd_start_head(struct dasd_device * device)
rc = device->discipline->start_IO(cqr); rc = device->discipline->start_IO(cqr);
if (rc == 0) if (rc == 0)
dasd_set_timer(device, cqr->expires); dasd_set_timer(device, cqr->expires);
else if (rc == -EBUSY) else
/* Hmpf, try again in 1/100 sec */ /* Hmpf, try again in 1/2 sec */
dasd_set_timer(device, 1); dasd_set_timer(device, 50);
} }
} }
...@@ -1980,7 +1952,7 @@ dasd_init(void) ...@@ -1980,7 +1952,7 @@ dasd_init(void)
init_waitqueue_head(&dasd_init_waitq); init_waitqueue_head(&dasd_init_waitq);
/* register 'common' DASD debug area, used faor all DBF_XXX calls */ /* register 'common' DASD debug area, used for all DBF_XXX calls */
dasd_debug_area = debug_register("dasd", 0, 2, 8 * sizeof (long)); dasd_debug_area = debug_register("dasd", 0, 2, 8 * sizeof (long));
if (dasd_debug_area == NULL) { if (dasd_debug_area == NULL) {
rc = -ENOMEM; rc = -ENOMEM;
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* 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.30 $ * $Revision: 1.33 $
*/ */
#include <linux/timer.h> #include <linux/timer.h>
...@@ -301,15 +301,15 @@ dasd_3990_erp_alternate_path(struct dasd_ccw_req * erp) ...@@ -301,15 +301,15 @@ dasd_3990_erp_alternate_path(struct dasd_ccw_req * erp)
opm = ccw_device_get_path_mask(device->cdev); opm = ccw_device_get_path_mask(device->cdev);
//FIXME: start with get_opm ? //FIXME: start with get_opm ?
if (erp->lpm == 0) if (erp->lpm == 0)
erp->lpm = LPM_ANYPATH & ~(erp->dstat->esw.esw0.sublog.lpum); erp->lpm = LPM_ANYPATH & ~(erp->irb.esw.esw0.sublog.lpum);
else else
erp->lpm &= ~(erp->dstat->esw.esw0.sublog.lpum); erp->lpm &= ~(erp->irb.esw.esw0.sublog.lpum);
if ((erp->lpm & 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->esw.esw0.sublog.lpum, opm); erp->lpm, erp->irb.esw.esw0.sublog.lpum, opm);
/* reset status to queued to handle the request again... */ /* reset status to queued to handle the request again... */
if (erp->status > DASD_CQR_QUEUED) if (erp->status > DASD_CQR_QUEUED)
...@@ -319,7 +319,7 @@ dasd_3990_erp_alternate_path(struct dasd_ccw_req * erp) ...@@ -319,7 +319,7 @@ dasd_3990_erp_alternate_path(struct dasd_ccw_req * erp)
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->esw.esw0.sublog.lpum, opm); erp->irb.esw.esw0.sublog.lpum, opm);
/* post request with permanent error */ /* post request with permanent error */
if (erp->status > DASD_CQR_QUEUED) if (erp->status > DASD_CQR_QUEUED)
...@@ -443,6 +443,10 @@ dasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense) ...@@ -443,6 +443,10 @@ dasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense)
/* interrupt (this enables easier enqueing of the cqr) */ /* interrupt (this enables easier enqueing of the cqr) */
if (erp->function != dasd_3990_erp_action_4) { if (erp->function != dasd_3990_erp_action_4) {
DEV_MESSAGE(KERN_INFO, device,
"dasd_3990_erp_action_4: first time retry"
"%s", " ");
erp->retries = 256; erp->retries = 256;
erp->function = dasd_3990_erp_action_4; erp->function = dasd_3990_erp_action_4;
...@@ -1677,7 +1681,7 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense) ...@@ -1677,7 +1681,7 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * 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->scsw.cpa; cpa = default_erp->refers->irb.scsw.cpa;
if (cpa == 0) { if (cpa == 0) {
...@@ -1763,7 +1767,7 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense) ...@@ -1763,7 +1767,7 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense)
erp->magic = default_erp->magic; erp->magic = default_erp->magic;
erp->expires = 0; erp->expires = 0;
erp->retries = 256; erp->retries = 256;
cqr->buildclk = get_clock(); erp->buildclk = get_clock();
erp->status = DASD_CQR_FILLED; erp->status = DASD_CQR_FILLED;
/* remove the default erp */ /* remove the default erp */
...@@ -1823,7 +1827,7 @@ dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense) ...@@ -1823,7 +1827,7 @@ dasd_3990_update_1B(struct dasd_ccw_req * 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->scsw.cpa; cpa = previous_erp->irb.scsw.cpa;
if (cpa == 0) { if (cpa == 0) {
...@@ -2233,7 +2237,7 @@ dasd_3990_erp_inspect(struct dasd_ccw_req * erp) ...@@ -2233,7 +2237,7 @@ dasd_3990_erp_inspect(struct dasd_ccw_req * erp)
struct dasd_ccw_req *erp_new = NULL; struct dasd_ccw_req *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->ecw; char *sense = erp->refers->irb.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) {
...@@ -2306,6 +2310,7 @@ dasd_3990_erp_add_erp(struct dasd_ccw_req * cqr) ...@@ -2306,6 +2310,7 @@ dasd_3990_erp_add_erp(struct dasd_ccw_req * cqr)
erp->magic = cqr->magic; erp->magic = cqr->magic;
erp->expires = 0; erp->expires = 0;
erp->retries = 256; erp->retries = 256;
erp->buildclk = get_clock();
erp->status = DASD_CQR_FILLED; erp->status = DASD_CQR_FILLED;
...@@ -2369,14 +2374,14 @@ dasd_3990_erp_error_match(struct dasd_ccw_req *cqr1, struct dasd_ccw_req *cqr2) ...@@ -2369,14 +2374,14 @@ dasd_3990_erp_error_match(struct dasd_ccw_req *cqr1, struct dasd_ccw_req *cqr2)
{ {
/* check failed CCW */ /* check failed CCW */
if (cqr1->dstat->scsw.cpa != cqr2->dstat->scsw.cpa) { if (cqr1->irb.scsw.cpa != cqr2->irb.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 (!((memcmp (cqr1->dstat->ecw, cqr2->dstat->ecw, 3) == 0) && if (!((memcmp (cqr1->irb.ecw, cqr2->irb.ecw, 3) == 0) &&
(cqr1->dstat->ecw[27] == cqr2->dstat->ecw[27]) && (cqr1->irb.ecw[27] == cqr2->irb.ecw[27]) &&
(cqr1->dstat->ecw[25] == cqr2->dstat->ecw[25]))) { (cqr1->irb.ecw[25] == cqr2->irb.ecw[25]))) {
return 0; /* sense doesn't match */ return 0; /* sense doesn't match */
} }
...@@ -2449,7 +2454,7 @@ dasd_3990_erp_further_erp(struct dasd_ccw_req *erp) ...@@ -2449,7 +2454,7 @@ dasd_3990_erp_further_erp(struct dasd_ccw_req *erp)
{ {
struct dasd_device *device = erp->device; struct dasd_device *device = erp->device;
char *sense = erp->dstat->ecw; char *sense = erp->irb.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) ||
...@@ -2562,7 +2567,7 @@ dasd_3990_erp_handle_match_erp(struct dasd_ccw_req *erp_head, ...@@ -2562,7 +2567,7 @@ dasd_3990_erp_handle_match_erp(struct dasd_ccw_req *erp_head,
if (erp->retries > 0) { if (erp->retries > 0) {
char *sense = erp->refers->dstat->ecw; char *sense = erp->refers->irb.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) {
...@@ -2620,7 +2625,7 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr) ...@@ -2620,7 +2625,7 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr)
struct dasd_ccw_req *erp = NULL; struct dasd_ccw_req *erp = NULL;
struct dasd_device *device = cqr->device; struct dasd_device *device = cqr->device;
__u32 cpa = cqr->dstat->scsw.cpa; __u32 cpa = cqr->irb.scsw.cpa;
#ifdef ERP_DEBUG #ifdef ERP_DEBUG
/* print current erp_chain */ /* print current erp_chain */
...@@ -2641,8 +2646,8 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr) ...@@ -2641,8 +2646,8 @@ dasd_3990_erp_action(struct dasd_ccw_req * 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->scsw.cstat == 0x00) && if ((cqr->irb.scsw.cstat == 0x00) &&
(cqr->dstat->scsw.dstat == (DEV_STAT_CHN_END|DEV_STAT_DEV_END))) { (cqr->irb.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"
...@@ -2653,7 +2658,7 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr) ...@@ -2653,7 +2658,7 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr)
return cqr; return cqr;
} }
/* check if sense data are available */ /* check if sense data are available */
if (!cqr->dstat->ecw) { if (!cqr->irb.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);
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* 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.28 $ * $Revision: 1.30 $
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -430,16 +430,9 @@ dasd_devmap_from_cdev(struct ccw_device *cdev) ...@@ -430,16 +430,9 @@ dasd_devmap_from_cdev(struct ccw_device *cdev)
{ {
struct dasd_devmap *devmap; struct dasd_devmap *devmap;
if (cdev->dev.driver_data)
return (struct dasd_devmap *) cdev->dev.driver_data;
devmap = dasd_find_busid(cdev->dev.bus_id); devmap = dasd_find_busid(cdev->dev.bus_id);
if (!IS_ERR(devmap)) { if (IS_ERR(devmap))
cdev->dev.driver_data = devmap;
return devmap;
}
devmap = dasd_add_busid(cdev->dev.bus_id, DASD_FEATURE_DEFAULT); devmap = dasd_add_busid(cdev->dev.bus_id, DASD_FEATURE_DEFAULT);
if (!IS_ERR(devmap))
cdev->dev.driver_data = devmap;
return devmap; return devmap;
} }
...@@ -456,6 +449,7 @@ dasd_create_device(struct ccw_device *cdev) ...@@ -456,6 +449,7 @@ dasd_create_device(struct ccw_device *cdev)
devmap = dasd_devmap_from_cdev(cdev); devmap = dasd_devmap_from_cdev(cdev);
if (IS_ERR(devmap)) if (IS_ERR(devmap))
return (void *) devmap; return (void *) devmap;
cdev->dev.driver_data = devmap;
device = dasd_alloc_device(); device = dasd_alloc_device();
if (IS_ERR(device)) if (IS_ERR(device))
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* 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 $ * $Revision: 1.37 $
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -158,7 +158,7 @@ dasd_ext_handler(struct pt_regs *regs, __u16 code) ...@@ -158,7 +158,7 @@ dasd_ext_handler(struct pt_regs *regs, __u16 code)
unsigned long long expires; unsigned long long expires;
unsigned long flags; unsigned long flags;
char status; char status;
int ip, cpu; int ip;
/* /*
* Get the external interruption subcode. VM stores * Get the external interruption subcode. VM stores
...@@ -171,8 +171,6 @@ dasd_ext_handler(struct pt_regs *regs, __u16 code) ...@@ -171,8 +171,6 @@ dasd_ext_handler(struct pt_regs *regs, __u16 code)
status = *((char *) &S390_lowcore.ext_params + 5); status = *((char *) &S390_lowcore.ext_params + 5);
ip = S390_lowcore.ext_params; ip = S390_lowcore.ext_params;
cpu = smp_processor_id();
if (!ip) { /* no intparm: unsolicited interrupt */ if (!ip) { /* no intparm: unsolicited interrupt */
MESSAGE(KERN_DEBUG, "%s", "caught unsolicited interrupt"); MESSAGE(KERN_DEBUG, "%s", "caught unsolicited interrupt");
return; return;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* 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.55 $ * $Revision: 1.57 $
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -983,8 +983,8 @@ dasd_eckd_build_cp(struct dasd_device * device, struct request *req) ...@@ -983,8 +983,8 @@ dasd_eckd_build_cp(struct dasd_device * device, struct request *req)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
count += bv->bv_len >> (device->s2b_shift + 9); count += bv->bv_len >> (device->s2b_shift + 9);
#if defined(CONFIG_ARCH_S390X) #if defined(CONFIG_ARCH_S390X)
cidaw += idal_nr_words(page_address(bv->bv_page) + if (idal_is_needed (page_address(bv->bv_page), bv->bv_len))
bv->bv_offset, bv->bv_len); cidaw += bv->bv_len >> (device->s2b_shift + 9);
#endif #endif
} }
} }
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* 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.11 $ * $Revision: 1.12 $
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -77,8 +77,6 @@ dasd_free_erp_request(struct dasd_ccw_req * cqr, struct dasd_device * device) ...@@ -77,8 +77,6 @@ dasd_free_erp_request(struct dasd_ccw_req * cqr, struct dasd_device * device)
{ {
unsigned long flags; unsigned long flags;
if (cqr->dstat != NULL)
kfree(cqr->dstat);
debug_text_event(dasd_debug_area, 1, "FREE"); debug_text_event(dasd_debug_area, 1, "FREE");
debug_int_event(dasd_debug_area, 1, (long) cqr); debug_int_event(dasd_debug_area, 1, (long) cqr);
spin_lock_irqsave(&device->mem_lock, flags); spin_lock_irqsave(&device->mem_lock, flags);
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* 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.33 $ * $Revision: 1.34 $
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -270,8 +270,8 @@ dasd_fba_build_cp(struct dasd_device * device, struct request *req) ...@@ -270,8 +270,8 @@ dasd_fba_build_cp(struct dasd_device * device, struct request *req)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
count += bv->bv_len >> (device->s2b_shift + 9); count += bv->bv_len >> (device->s2b_shift + 9);
#if defined(CONFIG_ARCH_S390X) #if defined(CONFIG_ARCH_S390X)
cidaw += idal_nr_words(page_address(bv->bv_page) + if (idal_is_needed (page_address(bv->bv_page), bv->bv_len))
bv->bv_offset, bv->bv_len); cidaw += bv->bv_len / blksize;
#endif #endif
} }
} }
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* gendisk related functions for the dasd driver. * gendisk related functions for the dasd driver.
* *
* $Revision: 1.46 $ * $Revision: 1.48 $
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -152,8 +152,9 @@ dasd_destroy_partitions(struct dasd_device * device) ...@@ -152,8 +152,9 @@ dasd_destroy_partitions(struct dasd_device * device)
memset(&bpart, sizeof(struct blkpg_partition), 0); memset(&bpart, sizeof(struct blkpg_partition), 0);
memset(&barg, sizeof(struct blkpg_ioctl_arg), 0); memset(&barg, sizeof(struct blkpg_ioctl_arg), 0);
barg.data = &bpart; barg.data = &bpart;
barg.op = BLKPG_DEL_PARTITION;
for (bpart.pno = device->gdp->minors - 1; bpart.pno > 0; bpart.pno--) for (bpart.pno = device->gdp->minors - 1; bpart.pno > 0; bpart.pno--)
ioctl_by_bdev(bdev, BLKPG_DEL_PARTITION, (unsigned long) &barg); ioctl_by_bdev(bdev, BLKPG, (unsigned long) &barg);
invalidate_partition(device->gdp, 0); invalidate_partition(device->gdp, 0);
/* Matching blkdev_put to the blkdev_get in dasd_scan_partitions. */ /* Matching blkdev_put to the blkdev_get in dasd_scan_partitions. */
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* 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.58 $ * $Revision: 1.60 $
*/ */
#ifndef DASD_INT_H #ifndef DASD_INT_H
...@@ -168,7 +168,7 @@ struct dasd_ccw_req { ...@@ -168,7 +168,7 @@ struct dasd_ccw_req {
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 */
struct irb *dstat; /* device status in case of an error */ struct irb irb; /* device status in case of an error */
struct dasd_ccw_req *refers; /* ERP-chain queueing. */ struct dasd_ccw_req *refers; /* ERP-chain queueing. */
void *function; /* originating ERP action */ void *function; /* originating ERP action */
...@@ -192,6 +192,7 @@ struct dasd_ccw_req { ...@@ -192,6 +192,7 @@ struct dasd_ccw_req {
#define DASD_CQR_DONE 0x03 /* request is completed successfully */ #define DASD_CQR_DONE 0x03 /* request is completed successfully */
#define DASD_CQR_ERROR 0x04 /* request is completed with error */ #define DASD_CQR_ERROR 0x04 /* request is completed with error */
#define DASD_CQR_FAILED 0x05 /* request is finally failed */ #define DASD_CQR_FAILED 0x05 /* request is finally failed */
#define DASD_CQR_CLEAR 0x06 /* request is clear pending */
/* per dasd_ccw_req flags */ /* per dasd_ccw_req flags */
#define DASD_CQR_FLAGS_USE_ERP 0 /* use ERP for this request */ #define DASD_CQR_FLAGS_USE_ERP 0 /* use ERP for this request */
......
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