From 4e4eef31fd6b149f07a356bc41a6e675d1c896b4 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Thu, 2 Dec 2004 15:44:20 -0800 Subject: [PATCH] [PATCH] s390: common i/o layer From: Cornelia Huck From: Steffen Thoss 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: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/cio/device.c | 35 +++++++++++++++++++++++------------ drivers/s390/cio/device_fsm.c | 18 +++++++++++------- drivers/s390/cio/qdio.c | 16 +++++++++++++--- 3 files changed, 47 insertions(+), 22 deletions(-) diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 4038e776f2a8..7b6f85b3e42c 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -1,7 +1,7 @@ /* * 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 diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index d41f0dda6591..cacebad072a8 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -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; - ccw_device_online(cdev); - wake_up(&cdev->private->wait_q); + if (same_dev) { + /* Get device online again. */ + ccw_device_online(cdev); + wake_up(&cdev->private->wait_q); + } return; } /* Issue device info message. */ diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c index 3a7c90e5ea86..dc7d2888abe1 100644 --- a/drivers/s390/cio/qdio.c +++ b/drivers/s390/cio/qdio.c @@ -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 "); @@ -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); -- 2.39.5