diff options
Diffstat (limited to 'drivers/s390/char/raw3270.c')
-rw-r--r-- | drivers/s390/char/raw3270.c | 32 |
1 files changed, 29 insertions, 3 deletions
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c index 0743f13101ee..a2da898ce90f 100644 --- a/drivers/s390/char/raw3270.c +++ b/drivers/s390/char/raw3270.c @@ -90,6 +90,8 @@ module_param(tubxcorrect, bool, 0); */ DECLARE_WAIT_QUEUE_HEAD(raw3270_wait_queue); +static void __raw3270_disconnect(struct raw3270 *rp); + /* * Encode array for 12 bit 3270 addresses. */ @@ -336,8 +338,11 @@ raw3270_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb) set_bit(RAW3270_FLAGS_BUSY, &rp->flags); /* Handle disconnected devices */ if ((irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) && - (irb->ecw[0] & SNS0_INTERVENTION_REQ)) + (irb->ecw[0] & SNS0_INTERVENTION_REQ)) { set_bit(RAW3270_FLAGS_BUSY, &rp->flags); + if (rp->state > RAW3270_STATE_RESET) + __raw3270_disconnect(rp); + } /* Call interrupt handler of the view */ if (view) view->fn->intv(view, rq, irb); @@ -347,8 +352,7 @@ raw3270_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb) /* Device busy, do not start I/O */ return; - if (rq) { - BUG_ON(list_empty(&rq->list)); + if (rq && !list_empty(&rq->list)) { /* The request completed, remove from queue and do callback. */ list_del_init(&rq->list); if (rq->callback) @@ -635,6 +639,28 @@ raw3270_reset(struct raw3270_view *view) } static void +__raw3270_disconnect(struct raw3270 *rp) +{ + struct raw3270_request *rq; + struct raw3270_view *view; + + rp->state = RAW3270_STATE_INIT; + rp->view = &rp->init_view; + /* Cancel all queued requests */ + while (!list_empty(&rp->req_queue)) { + rq = list_entry(rp->req_queue.next,struct raw3270_request,list); + view = rq->view; + rq->rc = -EACCES; + list_del_init(&rq->list); + if (rq->callback) + rq->callback(rq, rq->callback_data); + raw3270_put_view(view); + } + /* Start from scratch */ + __raw3270_reset_device(rp); +} + +static void raw3270_init_irq(struct raw3270_view *view, struct raw3270_request *rq, struct irb *irb) { |