Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 42046
b: refs/heads/master
c: d23861f
h: refs/heads/master
v: v3
  • Loading branch information
Cornelia Huck authored and Martin Schwidefsky committed Dec 4, 2006
1 parent 6469b87 commit 7c5bb59
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 12 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 24cb5b4846ebae5543869b5c596c2650f380df53
refs/heads/master: d23861ff1a4da1f4a5255eb4582f620191c6e1c0
37 changes: 30 additions & 7 deletions trunk/drivers/s390/cio/chsc.c
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,8 @@ s390_subchannel_remove_chpid(struct device *dev, void *data)
cc = cio_clear(sch);
if (cc == -ENODEV)
goto out_unreg;
/* Request retry of internal operation. */
device_set_intretry(sch);
/* Call handler. */
if (sch->driver && sch->driver->termination)
sch->driver->termination(&sch->dev);
Expand Down Expand Up @@ -711,9 +713,6 @@ static inline int check_for_io_on_path(struct subchannel *sch, int index)
{
int cc;

if (!device_is_online(sch))
/* cio could be doing I/O. */
return 0;
cc = stsch(sch->schid, &sch->schib);
if (cc)
return 0;
Expand All @@ -722,6 +721,26 @@ static inline int check_for_io_on_path(struct subchannel *sch, int index)
return 0;
}

static void terminate_internal_io(struct subchannel *sch)
{
if (cio_clear(sch)) {
/* Recheck device in case clear failed. */
sch->lpm = 0;
if (device_trigger_verify(sch) != 0) {
if(css_enqueue_subchannel_slow(sch->schid)) {
css_clear_subchannel_slow_list();
need_rescan = 1;
}
}
return;
}
/* Request retry of internal operation. */
device_set_intretry(sch);
/* Call handler. */
if (sch->driver && sch->driver->termination)
sch->driver->termination(&sch->dev);
}

static inline void
__s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on)
{
Expand All @@ -748,10 +767,14 @@ __s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on)
}
sch->opm &= ~(0x80 >> chp);
sch->lpm &= ~(0x80 >> chp);
if (check_for_io_on_path(sch, chp))
/* Path verification is done after killing. */
device_kill_io(sch);
else if (!sch->lpm) {
if (check_for_io_on_path(sch, chp)) {
if (device_is_online(sch))
/* Path verification is done after killing. */
device_kill_io(sch);
else
/* Kill and retry internal I/O. */
terminate_internal_io(sch);
} else if (!sch->lpm) {
if (device_trigger_verify(sch) != 0) {
if (css_enqueue_subchannel_slow(sch->schid)) {
css_clear_subchannel_slow_list();
Expand Down
2 changes: 2 additions & 0 deletions trunk/drivers/s390/cio/css.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ struct ccw_device_private {
unsigned int donotify:1; /* call notify function */
unsigned int recog_done:1; /* dev. recog. complete */
unsigned int fake_irb:1; /* deliver faked irb */
unsigned int intretry:1; /* retry internal operation */
} __attribute__((packed)) flags;
unsigned long intparm; /* user interruption parameter */
struct qdio_irq *qdio_data;
Expand Down Expand Up @@ -171,6 +172,7 @@ void device_trigger_reprobe(struct subchannel *);
/* Helper functions for vary on/off. */
int device_is_online(struct subchannel *);
void device_kill_io(struct subchannel *);
void device_set_intretry(struct subchannel *sch);
int device_trigger_verify(struct subchannel *sch);

/* Machine check helper function. */
Expand Down
3 changes: 3 additions & 0 deletions trunk/drivers/s390/cio/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -948,6 +948,9 @@ io_subchannel_ioterm(struct device *dev)
cdev = dev->driver_data;
if (!cdev)
return;
/* Internal I/O will be retried by the interrupt handler. */
if (cdev->private->flags.intretry)
return;
cdev->private->state = DEV_STATE_CLEAR_VERIFY;
if (cdev->handler)
cdev->handler(cdev, cdev->private->intparm,
Expand Down
16 changes: 16 additions & 0 deletions trunk/drivers/s390/cio/device_fsm.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,16 @@ device_set_disconnected(struct subchannel *sch)
cdev->private->state = DEV_STATE_DISCONNECTED;
}

void device_set_intretry(struct subchannel *sch)
{
struct ccw_device *cdev;

cdev = sch->dev.driver_data;
if (!cdev)
return;
cdev->private->flags.intretry = 1;
}

int device_trigger_verify(struct subchannel *sch)
{
struct ccw_device *cdev;
Expand Down Expand Up @@ -904,6 +914,12 @@ ccw_device_w4sense(struct ccw_device *cdev, enum dev_event dev_event)
* had killed the original request.
*/
if (irb->scsw.fctl & (SCSW_FCTL_CLEAR_FUNC | SCSW_FCTL_HALT_FUNC)) {
/* Retry Basic Sense if requested. */
if (cdev->private->flags.intretry) {
cdev->private->flags.intretry = 0;
ccw_device_do_sense(cdev, irb);
return;
}
cdev->private->flags.dosense = 0;
memset(&cdev->private->irb, 0, sizeof(struct irb));
ccw_device_accumulate_irb(cdev, irb);
Expand Down
10 changes: 9 additions & 1 deletion trunk/drivers/s390/cio/device_id.c
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,8 @@ __ccw_device_sense_id_start(struct ccw_device *cdev)
if ((sch->opm & cdev->private->imask) != 0 &&
cdev->private->iretry > 0) {
cdev->private->iretry--;
/* Reset internal retry indication. */
cdev->private->flags.intretry = 0;
ret = cio_start (sch, cdev->private->iccws,
cdev->private->imask);
/* ret is 0, -EBUSY, -EACCES or -ENODEV */
Expand Down Expand Up @@ -237,8 +239,14 @@ ccw_device_check_sense_id(struct ccw_device *cdev)
return 0; /* Success */
}
/* Check the error cases. */
if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC))
if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC)) {
/* Retry Sense ID if requested. */
if (cdev->private->flags.intretry) {
cdev->private->flags.intretry = 0;
return -EAGAIN;
}
return -ETIME;
}
if (irb->esw.esw0.erw.cons && (irb->ecw[0] & SNS0_CMD_REJECT)) {
/*
* if the device doesn't support the SenseID
Expand Down
30 changes: 27 additions & 3 deletions trunk/drivers/s390/cio/device_pgid.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ __ccw_device_sense_pgid_start(struct ccw_device *cdev)
ccw->cda = (__u32) __pa (&cdev->private->pgid[i]);
if (cdev->private->iretry > 0) {
cdev->private->iretry--;
/* Reset internal retry indication. */
cdev->private->flags.intretry = 0;
ret = cio_start (sch, cdev->private->iccws,
cdev->private->imask);
/* ret is 0, -EBUSY, -EACCES or -ENODEV */
Expand Down Expand Up @@ -122,8 +124,14 @@ __ccw_device_check_sense_pgid(struct ccw_device *cdev)

sch = to_subchannel(cdev->dev.parent);
irb = &cdev->private->irb;
if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC))
if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC)) {
/* Retry Sense PGID if requested. */
if (cdev->private->flags.intretry) {
cdev->private->flags.intretry = 0;
return -EAGAIN;
}
return -ETIME;
}
if (irb->esw.esw0.erw.cons &&
(irb->ecw[0]&(SNS0_CMD_REJECT|SNS0_INTERVENTION_REQ))) {
/*
Expand Down Expand Up @@ -253,6 +261,8 @@ __ccw_device_do_pgid(struct ccw_device *cdev, __u8 func)
ret = -EACCES;
if (cdev->private->iretry > 0) {
cdev->private->iretry--;
/* Reset internal retry indication. */
cdev->private->flags.intretry = 0;
ret = cio_start (sch, cdev->private->iccws,
cdev->private->imask);
/* We expect an interrupt in case of success or busy
Expand Down Expand Up @@ -293,6 +303,8 @@ static int __ccw_device_do_nop(struct ccw_device *cdev)
ret = -EACCES;
if (cdev->private->iretry > 0) {
cdev->private->iretry--;
/* Reset internal retry indication. */
cdev->private->flags.intretry = 0;
ret = cio_start (sch, cdev->private->iccws,
cdev->private->imask);
/* We expect an interrupt in case of success or busy
Expand Down Expand Up @@ -321,8 +333,14 @@ __ccw_device_check_pgid(struct ccw_device *cdev)

sch = to_subchannel(cdev->dev.parent);
irb = &cdev->private->irb;
if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC))
if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC)) {
/* Retry Set PGID if requested. */
if (cdev->private->flags.intretry) {
cdev->private->flags.intretry = 0;
return -EAGAIN;
}
return -ETIME;
}
if (irb->esw.esw0.erw.cons) {
if (irb->ecw[0] & SNS0_CMD_REJECT)
return -EOPNOTSUPP;
Expand Down Expand Up @@ -360,8 +378,14 @@ static int __ccw_device_check_nop(struct ccw_device *cdev)

sch = to_subchannel(cdev->dev.parent);
irb = &cdev->private->irb;
if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC))
if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC)) {
/* Retry NOP if requested. */
if (cdev->private->flags.intretry) {
cdev->private->flags.intretry = 0;
return -EAGAIN;
}
return -ETIME;
}
if (irb->scsw.cc == 3) {
CIO_MSG_EVENT(2, "NOP - Device %04x on Subchannel 0.%x.%04x,"
" lpm %02X, became 'not operational'\n",
Expand Down
3 changes: 3 additions & 0 deletions trunk/drivers/s390/cio/device_status.c
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,9 @@ ccw_device_do_sense(struct ccw_device *cdev, struct irb *irb)
sch->sense_ccw.count = SENSE_MAX_COUNT;
sch->sense_ccw.flags = CCW_FLAG_SLI;

/* Reset internal retry indication. */
cdev->private->flags.intretry = 0;

return cio_start (sch, &sch->sense_ccw, 0xff);
}

Expand Down

0 comments on commit 7c5bb59

Please sign in to comment.