Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 77187
b: refs/heads/master
c: 90ab133
h: refs/heads/master
i:
  77185: ba2f53b
  77183: 9c3dbdd
v: v3
  • Loading branch information
Peter Oberparleiter authored and Martin Schwidefsky committed Jan 26, 2008
1 parent ce5b557 commit 4d6b63b
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 808e48882316dd4a325cd1cc382516945edad77d
refs/heads/master: 90ab133603d066e850fc9ed297b6eb52f888dd25
63 changes: 63 additions & 0 deletions trunk/drivers/s390/cio/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <linux/list.h>
#include <linux/device.h>
#include <linux/workqueue.h>
#include <linux/timer.h>

#include <asm/ccwdev.h>
#include <asm/cio.h>
Expand All @@ -30,6 +31,11 @@
#include "ioasm.h"
#include "io_sch.h"

static struct timer_list recovery_timer;
static spinlock_t recovery_lock;
static int recovery_phase;
static const unsigned long recovery_delay[] = { 3, 30, 300 };

/******************* bus type handling ***********************/

/* The Linux driver model distinguishes between a bus type and
Expand Down Expand Up @@ -142,13 +148,16 @@ struct workqueue_struct *ccw_device_notify_work;
wait_queue_head_t ccw_device_init_wq;
atomic_t ccw_device_init_count;

static void recovery_func(unsigned long data);

static int __init
init_ccw_bus_type (void)
{
int ret;

init_waitqueue_head(&ccw_device_init_wq);
atomic_set(&ccw_device_init_count, 0);
setup_timer(&recovery_timer, recovery_func, 0);

ccw_device_work = create_singlethread_workqueue("cio");
if (!ccw_device_work)
Expand Down Expand Up @@ -1503,6 +1512,60 @@ ccw_device_get_subchannel_id(struct ccw_device *cdev)
return sch->schid;
}

static int recovery_check(struct device *dev, void *data)
{
struct ccw_device *cdev = to_ccwdev(dev);
int *redo = data;

spin_lock_irq(cdev->ccwlock);
switch (cdev->private->state) {
case DEV_STATE_DISCONNECTED:
CIO_MSG_EVENT(3, "recovery: trigger 0.%x.%04x\n",
cdev->private->dev_id.ssid,
cdev->private->dev_id.devno);
dev_fsm_event(cdev, DEV_EVENT_VERIFY);
*redo = 1;
break;
case DEV_STATE_DISCONNECTED_SENSE_ID:
*redo = 1;
break;
}
spin_unlock_irq(cdev->ccwlock);

return 0;
}

static void recovery_func(unsigned long data)
{
int redo = 0;

bus_for_each_dev(&ccw_bus_type, NULL, &redo, recovery_check);
if (redo) {
spin_lock_irq(&recovery_lock);
if (!timer_pending(&recovery_timer)) {
if (recovery_phase < ARRAY_SIZE(recovery_delay) - 1)
recovery_phase++;
mod_timer(&recovery_timer, jiffies +
recovery_delay[recovery_phase] * HZ);
}
spin_unlock_irq(&recovery_lock);
} else
CIO_MSG_EVENT(2, "recovery: end\n");
}

void ccw_device_schedule_recovery(void)
{
unsigned long flags;

CIO_MSG_EVENT(2, "recovery: schedule\n");
spin_lock_irqsave(&recovery_lock, flags);
if (!timer_pending(&recovery_timer) || (recovery_phase != 0)) {
recovery_phase = 0;
mod_timer(&recovery_timer, jiffies + recovery_delay[0] * HZ);
}
spin_unlock_irqrestore(&recovery_lock, flags);
}

MODULE_LICENSE("GPL");
EXPORT_SYMBOL(ccw_device_set_online);
EXPORT_SYMBOL(ccw_device_set_offline);
Expand Down
2 changes: 2 additions & 0 deletions trunk/drivers/s390/cio/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ int ccw_device_recognition(struct ccw_device *);
int ccw_device_online(struct ccw_device *);
int ccw_device_offline(struct ccw_device *);

void ccw_device_schedule_recovery(void);

/* Function prototypes for device status and basic sense stuff. */
void ccw_device_accumulate_irb(struct ccw_device *, struct irb *);
void ccw_device_accumulate_basic_sense(struct ccw_device *, struct irb *);
Expand Down
2 changes: 2 additions & 0 deletions trunk/drivers/s390/cio/device_fsm.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ device_set_disconnected(struct subchannel *sch)
ccw_device_set_timeout(cdev, 0);
cdev->private->flags.fake_irb = 0;
cdev->private->state = DEV_STATE_DISCONNECTED;
if (cdev->online)
ccw_device_schedule_recovery();
}

void device_set_intretry(struct subchannel *sch)
Expand Down

0 comments on commit 4d6b63b

Please sign in to comment.