Commit 37de53bb authored by Peter Oberparleiter's avatar Peter Oberparleiter Committed by Martin Schwidefsky

[S390] cio: introduce ccw device todos

Introduce a central mechanism for performing delayed ccw device work
to ensure that different types of work do not overwrite each other.
Prioritization ensures that the most important work is always
performed while less important tasks are either obsoleted or repeated
later.
Signed-off-by: default avatarPeter Oberparleiter <peter.oberparleiter@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 390935ac
This diff is collapsed.
......@@ -81,8 +81,6 @@ void io_subchannel_init_config(struct subchannel *sch);
int ccw_device_cancel_halt_clear(struct ccw_device *);
void ccw_device_do_unbind_bind(struct work_struct *);
void ccw_device_move_to_orphanage(struct work_struct *);
int ccw_device_is_orphan(struct ccw_device *);
int ccw_device_recognition(struct ccw_device *);
......@@ -92,6 +90,7 @@ void ccw_device_update_sense_data(struct ccw_device *);
int ccw_device_test_sense_data(struct ccw_device *);
void ccw_device_schedule_sch_unregister(struct ccw_device *);
int ccw_purge_blacklisted(void);
void ccw_device_sched_todo(struct ccw_device *cdev, enum cdev_todo todo);
/* Function prototypes for device status and basic sense stuff. */
void ccw_device_accumulate_irb(struct ccw_device *, struct irb *);
......
......@@ -289,9 +289,7 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
wake_up(&cdev->private->wait_q);
} else {
ccw_device_update_sense_data(cdev);
PREPARE_WORK(&cdev->private->kick_work,
ccw_device_do_unbind_bind);
queue_work(ccw_device_work, &cdev->private->kick_work);
ccw_device_sched_todo(cdev, CDEV_TODO_REBIND);
}
return;
case DEV_STATE_BOXED:
......@@ -343,28 +341,16 @@ int ccw_device_notify(struct ccw_device *cdev, int event)
return cdev->drv->notify ? cdev->drv->notify(cdev, event) : 0;
}
static void cmf_reenable_delayed(struct work_struct *work)
{
struct ccw_device_private *priv;
struct ccw_device *cdev;
priv = container_of(work, struct ccw_device_private, kick_work);
cdev = priv->cdev;
cmf_reenable(cdev);
}
static void ccw_device_oper_notify(struct ccw_device *cdev)
{
if (ccw_device_notify(cdev, CIO_OPER)) {
/* Reenable channel measurements, if needed. */
PREPARE_WORK(&cdev->private->kick_work, cmf_reenable_delayed);
queue_work(ccw_device_work, &cdev->private->kick_work);
ccw_device_sched_todo(cdev, CDEV_TODO_ENABLE_CMF);
return;
}
/* Driver doesn't want device back. */
ccw_device_set_notoper(cdev);
PREPARE_WORK(&cdev->private->kick_work, ccw_device_do_unbind_bind);
queue_work(ccw_device_work, &cdev->private->kick_work);
ccw_device_sched_todo(cdev, CDEV_TODO_REBIND);
}
/*
......@@ -392,14 +378,14 @@ ccw_device_done(struct ccw_device *cdev, int state)
CIO_MSG_EVENT(0, "Boxed device %04x on subchannel %04x\n",
cdev->private->dev_id.devno, sch->schid.sch_no);
if (cdev->online && !ccw_device_notify(cdev, CIO_BOXED))
ccw_device_schedule_sch_unregister(cdev);
ccw_device_sched_todo(cdev, CDEV_TODO_UNREG);
cdev->private->flags.donotify = 0;
break;
case DEV_STATE_NOT_OPER:
CIO_MSG_EVENT(0, "Device %04x gone on subchannel %04x\n",
cdev->private->dev_id.devno, sch->schid.sch_no);
if (!ccw_device_notify(cdev, CIO_GONE))
ccw_device_schedule_sch_unregister(cdev);
ccw_device_sched_todo(cdev, CDEV_TODO_UNREG);
else
ccw_device_set_disconnected(cdev);
cdev->private->flags.donotify = 0;
......@@ -409,7 +395,7 @@ ccw_device_done(struct ccw_device *cdev, int state)
"%04x\n", cdev->private->dev_id.devno,
sch->schid.sch_no);
if (!ccw_device_notify(cdev, CIO_NO_PATH))
ccw_device_schedule_sch_unregister(cdev);
ccw_device_sched_todo(cdev, CDEV_TODO_UNREG);
else
ccw_device_set_disconnected(cdev);
cdev->private->flags.donotify = 0;
......@@ -751,7 +737,7 @@ static void ccw_device_generic_notoper(struct ccw_device *cdev,
enum dev_event dev_event)
{
if (!ccw_device_notify(cdev, CIO_GONE))
ccw_device_schedule_sch_unregister(cdev);
ccw_device_sched_todo(cdev, CDEV_TODO_UNREG);
else
ccw_device_set_disconnected(cdev);
}
......
......@@ -82,6 +82,15 @@ struct senseid {
struct ciw ciw[MAX_CIWS]; /* variable # of CIWs */
} __attribute__ ((packed, aligned(4)));
enum cdev_todo {
CDEV_TODO_NOTHING,
CDEV_TODO_ENABLE_CMF,
CDEV_TODO_REBIND,
CDEV_TODO_REGISTER,
CDEV_TODO_UNREG,
CDEV_TODO_UNREG_EVAL,
};
struct ccw_device_private {
struct ccw_device *cdev;
struct subchannel *sch;
......@@ -115,7 +124,8 @@ struct ccw_device_private {
struct senseid senseid; /* SenseID info */
struct pgid pgid[8]; /* path group IDs per chpid*/
struct ccw1 iccws[2]; /* ccws for SNID/SID/SPGID commands */
struct work_struct kick_work;
struct work_struct todo_work;
enum cdev_todo todo;
wait_queue_head_t wait_q;
struct timer_list timer;
void *cmb; /* measurement information */
......
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