Commit 4e4eef31 authored by Martin Schwidefsky's avatar Martin Schwidefsky Committed by Linus Torvalds

[PATCH] s390: common i/o layer

From: Cornelia Huck <cohuck@de.ibm.com>
From: Steffen Thoss <thoss@de.ibm.com>

common i/o layer changes:
 - Delay re-registration of a subchannel with a different subchannel id
   until the ccw device removal triggered from the subchannels remove
   function has completed.
 - Fix check when to call unreg_rereg.
 - Fix get_disc_cdev_by_devno.
 - Activate the time delay disablement facility. This saves a few cycles
   in millicode processing.
 - Don't ifdef reset of busy start time.
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent ca2ab032
/*
* drivers/s390/cio/device.c
* bus driver for ccw devices
* $Revision: 1.128 $
* $Revision: 1.129 $
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
......@@ -525,8 +525,7 @@ get_disc_ccwdev_by_devno(unsigned int devno, struct ccw_device *sibling)
cdev = to_ccwdev(dev);
if ((cdev->private->state == DEV_STATE_DISCONNECTED) &&
(cdev->private->devno == devno) &&
(!strncmp(cdev->dev.bus_id, sibling->dev.bus_id,
BUS_ID_SIZE))) {
(cdev != sibling)) {
cdev->private->state = DEV_STATE_NOT_OPER;
break;
}
......@@ -539,6 +538,24 @@ get_disc_ccwdev_by_devno(unsigned int devno, struct ccw_device *sibling)
return cdev;
}
static void
ccw_device_add_changed(void *data)
{
struct ccw_device *cdev;
cdev = (struct ccw_device *)data;
if (device_add(&cdev->dev)) {
put_device(&cdev->dev);
return;
}
set_bit(1, &cdev->private->registered);
if (device_add_files(&cdev->dev)) {
if (test_and_clear_bit(1, &cdev->private->registered))
device_unregister(&cdev->dev);
}
}
extern int css_get_ssd_info(struct subchannel *sch);
void
......@@ -593,15 +610,9 @@ ccw_device_do_unreg_rereg(void *data)
if (need_rename)
snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.0.%04x",
sch->schib.pmcw.dev);
if (device_add(&cdev->dev)) {
put_device(&cdev->dev);
return;
}
set_bit(1, &cdev->private->registered);
if (device_add_files(&cdev->dev)) {
if (test_and_clear_bit(1, &cdev->private->registered))
device_unregister(&cdev->dev);
}
PREPARE_WORK(&cdev->private->kick_work,
ccw_device_add_changed, (void *)cdev);
queue_work(ccw_device_work, &cdev->private->kick_work);
}
static void
......
......@@ -154,7 +154,7 @@ ccw_device_cancel_halt_clear(struct ccw_device *cdev)
panic("Can't stop i/o on subchannel.\n");
}
static void
static int
ccw_device_handle_oper(struct ccw_device *cdev)
{
struct subchannel *sch;
......@@ -174,9 +174,10 @@ ccw_device_handle_oper(struct ccw_device *cdev)
PREPARE_WORK(&cdev->private->kick_work,
ccw_device_do_unreg_rereg, (void *)cdev);
queue_work(ccw_device_work, &cdev->private->kick_work);
return;
return 0;
}
cdev->private->flags.donotify = 1;
return 1;
}
/*
......@@ -206,7 +207,7 @@ static void
ccw_device_recog_done(struct ccw_device *cdev, int state)
{
struct subchannel *sch;
int notify, old_lpm;
int notify, old_lpm, same_dev;
sch = to_subchannel(cdev->dev.parent);
......@@ -236,6 +237,7 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
/* Boxed devices don't need extra treatment. */
}
notify = 0;
same_dev = 0; /* Keep the compiler quiet... */
switch (state) {
case DEV_STATE_NOT_OPER:
CIO_DEBUG(KERN_WARNING, 2,
......@@ -244,7 +246,7 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
break;
case DEV_STATE_OFFLINE:
if (cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID) {
ccw_device_handle_oper(cdev);
same_dev = ccw_device_handle_oper(cdev);
notify = 1;
}
/* fill out sense information */
......@@ -255,10 +257,12 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
.dev_model = cdev->private->senseid.dev_model,
};
if (notify) {
/* Get device online again. */
cdev->private->state = DEV_STATE_OFFLINE;
if (same_dev) {
/* Get device online again. */
ccw_device_online(cdev);
wake_up(&cdev->private->wait_q);
}
return;
}
/* Issue device info message. */
......
......@@ -56,7 +56,7 @@
#include "ioasm.h"
#include "chsc.h"
#define VERSION_QDIO_C "$Revision: 1.89 $"
#define VERSION_QDIO_C "$Revision: 1.93 $"
/****************** MODULE PARAMETER VARIABLES ********************/
MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
......@@ -605,8 +605,8 @@ qdio_kick_outbound_q(struct qdio_q *q)
sprintf(dbf_text,"%4x%2x%2x",q->irq,q->q_no,
atomic_read(&q->busy_siga_counter));
QDIO_DBF_TEXT3(0,trace,dbf_text);
q->timing.busy_start=0;
#endif /* CONFIG_QDIO_DEBUG */
q->timing.busy_start=0;
break;
case (2|QDIO_SIGA_ERROR_B_BIT_SET):
/* cc=2 and busy bit: */
......@@ -2088,7 +2088,10 @@ tiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero)
u32 kc:4;
u32 reserved4:21;
u32 isc:3;
u32 reserved5[2];
u32 word_with_d_bit;
/* set to 0x10000000 to enable
* time delay disablement facility */
u32 reserved5;
u32 subsystem_id;
u32 reserved6[1004];
struct chsc_header response;
......@@ -2126,6 +2129,12 @@ tiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero)
scssc_area->kc = QDIO_STORAGE_KEY;
scssc_area->isc = TIQDIO_THININT_ISC;
scssc_area->subsystem_id = (1<<16) + irq_ptr->irq;
/* enables the time delay disablement facility. Don't care
* whether it is really there (i.e. we haven't checked for
* it) */
scssc_area->word_with_d_bit = 0x10000000;
result = chsc(scssc_area);
if (result) {
......@@ -2620,6 +2629,7 @@ qdio_allocate(struct qdio_initialize *init_data)
init_MUTEX(&irq_ptr->setting_up_sema);
/* QDR must be in DMA area since CCW data address is only 32 bit */
irq_ptr->qdr=kmalloc(sizeof(struct qdr), GFP_KERNEL | GFP_DMA);
if (!(irq_ptr->qdr)) {
kfree(irq_ptr);
......
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