Skip to content

Commit

Permalink
s390/eadm_sch: improve quiesce handling
Browse files Browse the repository at this point in the history
When quiescing an eadm subchannel make sure that outstanding IO is
cleared and potential timeout handlers are canceled.

Reviewed-by: Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
  • Loading branch information
Sebastian Ott authored and Martin Schwidefsky committed Oct 24, 2013
1 parent 69db3b5 commit 6aa2677
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 3 deletions.
27 changes: 25 additions & 2 deletions drivers/s390/cio/eadm_sch.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/

#include <linux/kernel_stat.h>
#include <linux/completion.h>
#include <linux/workqueue.h>
#include <linux/spinlock.h>
#include <linux/device.h>
Expand Down Expand Up @@ -159,6 +160,9 @@ static void eadm_subchannel_irq(struct subchannel *sch)
}
scm_irq_handler((struct aob *)(unsigned long)scsw->aob, error);
private->state = EADM_IDLE;

if (private->completion)
complete(private->completion);
}

static struct subchannel *eadm_get_idle_sch(void)
Expand Down Expand Up @@ -255,13 +259,32 @@ static int eadm_subchannel_probe(struct subchannel *sch)

static void eadm_quiesce(struct subchannel *sch)
{
struct eadm_private *private = get_eadm_private(sch);
DECLARE_COMPLETION_ONSTACK(completion);
int ret;

spin_lock_irq(sch->lock);
if (private->state != EADM_BUSY)
goto disable;

if (eadm_subchannel_clear(sch))
goto disable;

private->completion = &completion;
spin_unlock_irq(sch->lock);

wait_for_completion_io(&completion);

spin_lock_irq(sch->lock);
private->completion = NULL;

disable:
eadm_subchannel_set_timeout(sch, 0);
do {
spin_lock_irq(sch->lock);
ret = cio_disable_subchannel(sch);
spin_unlock_irq(sch->lock);
} while (ret == -EBUSY);

spin_unlock_irq(sch->lock);
}

static int eadm_subchannel_remove(struct subchannel *sch)
Expand Down
4 changes: 3 additions & 1 deletion drivers/s390/cio/eadm_sch.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef EADM_SCH_H
#define EADM_SCH_H

#include <linux/completion.h>
#include <linux/device.h>
#include <linux/timer.h>
#include <linux/list.h>
Expand All @@ -9,9 +10,10 @@
struct eadm_private {
union orb orb;
enum {EADM_IDLE, EADM_BUSY, EADM_NOT_OPER} state;
struct completion *completion;
struct subchannel *sch;
struct timer_list timer;
struct list_head head;
struct subchannel *sch;
} __aligned(8);

#define get_eadm_private(n) ((struct eadm_private *)dev_get_drvdata(&n->dev))
Expand Down

0 comments on commit 6aa2677

Please sign in to comment.