Skip to content

Commit

Permalink
[S390] more workqueue fixes.
Browse files Browse the repository at this point in the history
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
  • Loading branch information
Martin Schwidefsky committed Dec 8, 2006
1 parent e45ccc0 commit c163753
Show file tree
Hide file tree
Showing 10 changed files with 89 additions and 67 deletions.
3 changes: 2 additions & 1 deletion drivers/s390/char/tape.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ struct tape_char_data {
/* Block Frontend Data */
struct tape_blk_data
{
struct tape_device * device;
/* Block device request queue. */
request_queue_t * request_queue;
spinlock_t request_queue_lock;
Expand Down Expand Up @@ -240,7 +241,7 @@ struct tape_device {
#endif

/* Function to start or stop the next request later. */
struct work_struct tape_dnr;
struct delayed_work tape_dnr;
};

/* Externals from tape_core.c */
Expand Down
23 changes: 11 additions & 12 deletions drivers/s390/char/tape_34xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,12 @@ tape_34xx_medium_sense(struct tape_device *device)
return rc;
}

struct tape_34xx_work {
struct tape_device *device;
enum tape_op op;
struct work_struct work;
};

/*
* These functions are currently used only to schedule a medium_sense for
* later execution. This is because we get an interrupt whenever a medium
Expand All @@ -103,13 +109,10 @@ tape_34xx_medium_sense(struct tape_device *device)
* interrupt handler.
*/
static void
tape_34xx_work_handler(void *data)
tape_34xx_work_handler(struct work_struct *work)
{
struct {
struct tape_device *device;
enum tape_op op;
struct work_struct work;
} *p = data;
struct tape_34xx_work *p =
container_of(work, struct tape_34xx_work, work);

switch(p->op) {
case TO_MSEN:
Expand All @@ -126,17 +129,13 @@ tape_34xx_work_handler(void *data)
static int
tape_34xx_schedule_work(struct tape_device *device, enum tape_op op)
{
struct {
struct tape_device *device;
enum tape_op op;
struct work_struct work;
} *p;
struct tape_34xx_work *p;

if ((p = kmalloc(sizeof(*p), GFP_ATOMIC)) == NULL)
return -ENOMEM;

memset(p, 0, sizeof(*p));
INIT_WORK(&p->work, tape_34xx_work_handler, p);
INIT_WORK(&p->work, tape_34xx_work_handler);

p->device = tape_get_device_reference(device);
p->op = op;
Expand Down
7 changes: 4 additions & 3 deletions drivers/s390/char/tape_3590.c
Original file line number Diff line number Diff line change
Expand Up @@ -236,9 +236,10 @@ struct work_handler_data {
};

static void
tape_3590_work_handler(void *data)
tape_3590_work_handler(struct work_struct *work)
{
struct work_handler_data *p = data;
struct work_handler_data *p =
container_of(work, struct work_handler_data, work);

switch (p->op) {
case TO_MSEN:
Expand All @@ -263,7 +264,7 @@ tape_3590_schedule_work(struct tape_device *device, enum tape_op op)
if ((p = kzalloc(sizeof(*p), GFP_ATOMIC)) == NULL)
return -ENOMEM;

INIT_WORK(&p->work, tape_3590_work_handler, p);
INIT_WORK(&p->work, tape_3590_work_handler);

p->device = tape_get_device_reference(device);
p->op = op;
Expand Down
14 changes: 9 additions & 5 deletions drivers/s390/char/tape_block.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <linux/blkdev.h>
#include <linux/interrupt.h>
#include <linux/buffer_head.h>
#include <linux/kernel.h>

#include <asm/debug.h>

Expand Down Expand Up @@ -143,15 +144,17 @@ tapeblock_start_request(struct tape_device *device, struct request *req)
* queue.
*/
static void
tapeblock_requeue(void *data) {
tapeblock_requeue(struct work_struct *work) {
struct tape_blk_data * blkdat;
struct tape_device * device;
request_queue_t * queue;
int nr_queued;
struct request * req;
struct list_head * l;
int rc;

device = (struct tape_device *) data;
blkdat = container_of(work, struct tape_blk_data, requeue_task);
device = blkdat->device;
if (!device)
return;

Expand Down Expand Up @@ -212,6 +215,7 @@ tapeblock_setup_device(struct tape_device * device)
int rc;

blkdat = &device->blk_data;
blkdat->device = device;
spin_lock_init(&blkdat->request_queue_lock);
atomic_set(&blkdat->requeue_scheduled, 0);

Expand Down Expand Up @@ -255,8 +259,8 @@ tapeblock_setup_device(struct tape_device * device)

add_disk(disk);

INIT_WORK(&blkdat->requeue_task, tapeblock_requeue,
tape_get_device_reference(device));
tape_get_device_reference(device);
INIT_WORK(&blkdat->requeue_task, tapeblock_requeue);

return 0;

Expand All @@ -271,7 +275,7 @@ void
tapeblock_cleanup_device(struct tape_device *device)
{
flush_scheduled_work();
device->blk_data.requeue_task.data = tape_put_device(device);
tape_put_device(device);

if (!device->blk_data.disk) {
PRINT_ERR("(%s): No gendisk to clean up!\n",
Expand Down
14 changes: 7 additions & 7 deletions drivers/s390/char/tape_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
#define PRINTK_HEADER "TAPE_CORE: "

static void __tape_do_irq (struct ccw_device *, unsigned long, struct irb *);
static void tape_delayed_next_request(void * data);
static void tape_delayed_next_request(struct work_struct *);

/*
* One list to contain all tape devices of all disciplines, so
Expand Down Expand Up @@ -272,7 +272,7 @@ __tape_cancel_io(struct tape_device *device, struct tape_request *request)
return 0;
case -EBUSY:
request->status = TAPE_REQUEST_CANCEL;
schedule_work(&device->tape_dnr);
schedule_delayed_work(&device->tape_dnr, 0);
return 0;
case -ENODEV:
DBF_EXCEPTION(2, "device gone, retry\n");
Expand Down Expand Up @@ -470,7 +470,7 @@ tape_alloc_device(void)
*device->modeset_byte = 0;
device->first_minor = -1;
atomic_set(&device->ref_count, 1);
INIT_WORK(&device->tape_dnr, tape_delayed_next_request, device);
INIT_DELAYED_WORK(&device->tape_dnr, tape_delayed_next_request);

return device;
}
Expand Down Expand Up @@ -724,7 +724,7 @@ __tape_start_io(struct tape_device *device, struct tape_request *request)
} else if (rc == -EBUSY) {
/* The common I/O subsystem is currently busy. Retry later. */
request->status = TAPE_REQUEST_QUEUED;
schedule_work(&device->tape_dnr);
schedule_delayed_work(&device->tape_dnr, 0);
rc = 0;
} else {
/* Start failed. Remove request and indicate failure. */
Expand Down Expand Up @@ -790,11 +790,11 @@ __tape_start_next_request(struct tape_device *device)
}

static void
tape_delayed_next_request(void *data)
tape_delayed_next_request(struct work_struct *work)
{
struct tape_device * device;
struct tape_device *device =
container_of(work, struct tape_device, tape_dnr.work);

device = (struct tape_device *) data;
DBF_LH(6, "tape_delayed_next_request(%p)\n", device);
spin_lock_irq(get_ccwdev_lock(device->cdev));
__tape_start_next_request(device);
Expand Down
2 changes: 2 additions & 0 deletions drivers/s390/cio/css.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ struct senseid {
} __attribute__ ((packed,aligned(4)));

struct ccw_device_private {
struct ccw_device *cdev;
struct subchannel *sch;
int state; /* device state */
atomic_t onoff;
unsigned long registered;
Expand Down
43 changes: 27 additions & 16 deletions drivers/s390/cio/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -585,12 +585,13 @@ static struct ccw_device * get_disc_ccwdev_by_dev_id(struct ccw_dev_id *dev_id,
}

static void
ccw_device_add_changed(void *data)
ccw_device_add_changed(struct work_struct *work)
{

struct ccw_device_private *priv;
struct ccw_device *cdev;

cdev = data;
priv = container_of(work, struct ccw_device_private, kick_work);
cdev = priv->cdev;
if (device_add(&cdev->dev)) {
put_device(&cdev->dev);
return;
Expand All @@ -605,13 +606,15 @@ ccw_device_add_changed(void *data)
extern int css_get_ssd_info(struct subchannel *sch);

void
ccw_device_do_unreg_rereg(void *data)
ccw_device_do_unreg_rereg(struct work_struct *work)
{
struct ccw_device_private *priv;
struct ccw_device *cdev;
struct subchannel *sch;
int need_rename;

cdev = data;
priv = container_of(work, struct ccw_device_private, kick_work);
cdev = priv->cdev;
sch = to_subchannel(cdev->dev.parent);
if (cdev->private->dev_id.devno != sch->schib.pmcw.dev) {
/*
Expand Down Expand Up @@ -659,7 +662,7 @@ ccw_device_do_unreg_rereg(void *data)
snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x",
sch->schid.ssid, sch->schib.pmcw.dev);
PREPARE_WORK(&cdev->private->kick_work,
ccw_device_add_changed, cdev);
ccw_device_add_changed);
queue_work(ccw_device_work, &cdev->private->kick_work);
}

Expand All @@ -677,14 +680,16 @@ ccw_device_release(struct device *dev)
* Register recognized device.
*/
static void
io_subchannel_register(void *data)
io_subchannel_register(struct work_struct *work)
{
struct ccw_device_private *priv;
struct ccw_device *cdev;
struct subchannel *sch;
int ret;
unsigned long flags;

cdev = data;
priv = container_of(work, struct ccw_device_private, kick_work);
cdev = priv->cdev;
sch = to_subchannel(cdev->dev.parent);

/*
Expand Down Expand Up @@ -734,11 +739,14 @@ io_subchannel_register(void *data)
}

void
ccw_device_call_sch_unregister(void *data)
ccw_device_call_sch_unregister(struct work_struct *work)
{
struct ccw_device *cdev = data;
struct ccw_device_private *priv;
struct ccw_device *cdev;
struct subchannel *sch;

priv = container_of(work, struct ccw_device_private, kick_work);
cdev = priv->cdev;
sch = to_subchannel(cdev->dev.parent);
css_sch_device_unregister(sch);
/* Reset intparm to zeroes. */
Expand Down Expand Up @@ -768,7 +776,7 @@ io_subchannel_recog_done(struct ccw_device *cdev)
break;
sch = to_subchannel(cdev->dev.parent);
PREPARE_WORK(&cdev->private->kick_work,
ccw_device_call_sch_unregister, cdev);
ccw_device_call_sch_unregister);
queue_work(slow_path_wq, &cdev->private->kick_work);
if (atomic_dec_and_test(&ccw_device_init_count))
wake_up(&ccw_device_init_wq);
Expand All @@ -783,7 +791,7 @@ io_subchannel_recog_done(struct ccw_device *cdev)
if (!get_device(&cdev->dev))
break;
PREPARE_WORK(&cdev->private->kick_work,
io_subchannel_register, cdev);
io_subchannel_register);
queue_work(slow_path_wq, &cdev->private->kick_work);
break;
}
Expand Down Expand Up @@ -865,6 +873,7 @@ io_subchannel_probe (struct subchannel *sch)
kfree(cdev);
return -ENOMEM;
}
cdev->private->cdev = cdev;
atomic_set(&cdev->private->onoff, 0);
cdev->dev.parent = &sch->dev;
cdev->dev.release = ccw_device_release;
Expand All @@ -890,12 +899,13 @@ io_subchannel_probe (struct subchannel *sch)
return rc;
}

static void
ccw_device_unregister(void *data)
static void ccw_device_unregister(struct work_struct *work)
{
struct ccw_device_private *priv;
struct ccw_device *cdev;

cdev = (struct ccw_device *)data;
priv = container_of(work, struct ccw_device_private, kick_work);
cdev = priv->cdev;
if (test_and_clear_bit(1, &cdev->private->registered))
device_unregister(&cdev->dev);
put_device(&cdev->dev);
Expand All @@ -921,7 +931,7 @@ io_subchannel_remove (struct subchannel *sch)
*/
if (get_device(&cdev->dev)) {
PREPARE_WORK(&cdev->private->kick_work,
ccw_device_unregister, cdev);
ccw_device_unregister);
queue_work(ccw_device_work, &cdev->private->kick_work);
}
return 0;
Expand Down Expand Up @@ -1048,6 +1058,7 @@ ccw_device_probe_console(void)
memset(&console_cdev, 0, sizeof(struct ccw_device));
memset(&console_private, 0, sizeof(struct ccw_device_private));
console_cdev.private = &console_private;
console_private.cdev = &console_cdev;
ret = ccw_device_console_enable(&console_cdev, sch);
if (ret) {
cio_release_console();
Expand Down
4 changes: 2 additions & 2 deletions drivers/s390/cio/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ void io_subchannel_recog_done(struct ccw_device *cdev);

int ccw_device_cancel_halt_clear(struct ccw_device *);

void ccw_device_do_unreg_rereg(void *);
void ccw_device_call_sch_unregister(void *);
void ccw_device_do_unreg_rereg(struct work_struct *);
void ccw_device_call_sch_unregister(struct work_struct *);

int ccw_device_recognition(struct ccw_device *);
int ccw_device_online(struct ccw_device *);
Expand Down
Loading

0 comments on commit c163753

Please sign in to comment.