s390 (3/8): io fixes.
Subsystems (4)
PATCH 1/1 s390 (3/8): io fixes.
Start of chsc interface cleanup. Fix for a race condition in do_IRQ. Fix device reference counting.
diffstat:
drivers/s390/cio/Makefile | 2 drivers/s390/cio/blacklist.c | 10 - drivers/s390/cio/chsc.c | 245 +++++++++++++----------------------------- drivers/s390/cio/chsc.h | 80 +++++++++++++ drivers/s390/cio/cio.c | 35 ++---- drivers/s390/cio/cio.h | 2 drivers/s390/cio/css.c | 10 + drivers/s390/cio/device.c | 23 +++ drivers/s390/cio/device_fsm.c | 20 ++- drivers/s390/cio/ioasm.h | 2 drivers/s390/cio/qdio.c | 34 +++-- drivers/s390/net/cu3088.c | 6 - include/asm-s390/cio.h | 2 include/asm-s390x/ccwgroup.h | 8 - include/asm-s390x/cio.h | 2 15 files changed, 248 insertions(+), 233 deletions(-)
drivers/s390/cio/Makefile +1 -1
@@ -3,7 +3,7 @@ # obj-y += airq.o blacklist.o chsc.o cio.o css.o requestirq.o -export-objs += airq.o css.o chsc.o cio.o requestirq.o +export-objs += airq.o css.o cio.o requestirq.o ccw_device-objs += device.o device_fsm.o device_ops.o ccw_device-objs += device_id.o device_pgid.o device_status.o
drivers/s390/cio/blacklist.c +5 -5
@@ -1,7 +1,7 @@/* * drivers/s390/cio/blacklist.c * S/390 common I/O routines -- blacklisting of specific devices -* $Revision: 1.22 $ +* $Revision: 1.23 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation
@@ -162,10 +162,10 @@else blacklist_parse_parameters (buf +5 , free); }else if (strncmp (buf,"add " ,4 ) ==0 ) { -/* FIXME: the old code was checking if the new bl'ed -* devices are already known to the system so -* validate_subchannel would still give a working -* status. is that necessary? */ +/* +* We don't need to check for known devices since +* css_probe_device will handle this correctly. +*/ blacklist_parse_parameters (buf +4 , add); }else { printk (KERN_WARNING "cio_ignore: Parse error; \n"
drivers/s390/cio/chsc.c +80 -165
337 lines not on this page · raw message
drivers/s390/cio/chsc.h +80 -0
86 lines not on this page · raw message
drivers/s390/cio/cio.c +16 -19
@@ -1,7 +1,7 @@/* * drivers/s390/cio/cio.c * S/390 common I/O routines -- low level i/o calls -* $Revision: 1.89 $ +* $Revision: 1.90 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation
@@ -609,6 +609,7 @@struct subchannel *sch;struct irb *irb; +irq_enter ();/* * Get interrupt information from lowcore */
@@ -620,28 +621,23 @@*/ if (tpi_info->adapter_IO ==1 && tpi_info->int_type ==IO_INTERRUPT_TYPE ) { -irq_enter ();do_adapter_IO (tpi_info->intparm); -irq_exit ();continue ; } -/* Store interrupt response block to lowcore. */ -if (tsch (tpi_info->irq, irb) !=0 ) -/* Not status pending or not operational. */ -continue ; - sch = ioinfo[tpi_info->irq]; -if (!sch) -continue ; - -irq_enter (); -spin_lock (&sch->lock); -memcpy (&sch->schib.scsw, &irb->scsw,sizeof (irb->scsw)); -if (sch->driver && sch->driver->irq) - sch->driver->irq (&sch->dev); -spin_unlock (&sch->lock); -irq_exit (); - +if (sch) +spin_lock (&sch->lock); +/* Store interrupt response block to lowcore. */ +if (tsch (tpi_info->irq, irb) ==0 && sch) { +/* Keep subchannel information word up to date. */ +memcpy (&sch->schib.scsw, &irb->scsw, +sizeof (irb->scsw)); +/* Call interrupt handler if there is one. */ +if (sch->driver && sch->driver->irq) + sch->driver->irq (&sch->dev); + } +if (sch) +spin_unlock (&sch->lock);/* * Are more interrupts pending? * If so, the tpi instruction will update the lowcore
@@ -650,6 +646,7 @@* out of the sie which costs more cycles than it saves. */ }while (!MACHINE_IS_VM &&tpi (NULL ) !=0 ); +irq_exit (); }#ifdef CONFIG_CCW_CONSOLE
drivers/s390/cio/cio.h +0 -2
@@ -113,7 +113,6 @@#define to_subchannel (n) container_of(n, struct subchannel, dev)extern int cio_validate_subchannel (struct subchannel *,unsigned int ); -extern int cio_modify (struct subchannel *);extern int cio_enable_subchannel (struct subchannel *,unsigned int );extern int cio_disable_subchannel (struct subchannel *);extern int cio_cancel (struct subchannel *);
@@ -127,7 +126,6 @@extern int cio_get_options (struct subchannel *);/* Use with care. */ -extern int cio_tpi (void );extern struct subchannel *cio_probe_console (void );extern void cio_release_console (void );
drivers/s390/cio/css.c +8 -2
@@ -1,7 +1,7 @@/* * drivers/s390/cio/css.c * driver for channel subsystem -* $Revision: 1.39 $ +* $Revision: 1.40 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation
@@ -20,6 +20,7 @@#include "cio.h" #include "cio_debug.h" #include "device.h" // FIXME: dito +#include "ioasm.h" struct subchannel *ioinfo[__MAX_SUBCHANNELS];unsigned int highest_subchannel;
@@ -154,6 +155,7 @@ { static DECLARE_WORK(work, do_process_crw, 0);struct subchannel *sch; +int ccode, devno;CIO_CRW_EVENT (2 ,"source is subchannel %04X\n" , irq);
@@ -164,9 +166,13 @@ }if (!sch->dev.driver_data)return ; + devno = sch->schib.pmcw.dev;/* FIXME: css_process_crw must not know about ccw_device */ dev_fsm_event (sch->dev.driver_data,DEV_EVENT_NOTOPER ); -// FIXME: revalidate machine checks? + ccode =stsch (irq, &sch->schib); +if (!ccode) +if (devno != sch->schib.pmcw.dev) +schedule_work (&work); }/*
drivers/s390/cio/device.c +19 -4
@@ -1,7 +1,7 @@/* * drivers/s390/cio/device.c * bus driver for ccw devices -* $Revision: 1.44 $ +* $Revision: 1.45 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation
@@ -362,18 +362,28 @@ sch->dev.driver_data =0 ;kfree (cdev->private);kfree (cdev); -return ; + goto out; } ret =subchannel_add_files (cdev->dev.parent);if (ret)printk (KERN_WARNING "%s: could not add attributes to %04x\n" , __func__, sch->irq); +out: +put_device (&sch->dev); }static void io_subchannel_recog (struct ccw_device *cdev,struct subchannel *sch) { +int rc; + +if (!get_device (&sch->dev)) { +if (cdev->dev.release) + cdev->dev.release (&cdev->dev); +return ; + } + sch->dev.driver_data = cdev; sch->driver = &io_subchannel_driver; cdev->ccwlock = &sch->lock;
@@ -392,12 +402,17 @@/* Do first half of device_register. */ device_initialize (&cdev->dev); -get_device (&sch->dev);/* keep parent refcount in sync. */ /* Start async. device sensing. */ spin_lock_irq (cdev->ccwlock); -ccw_device_recognition (cdev); + rc =ccw_device_recognition (cdev);spin_unlock_irq (cdev->ccwlock); +if (rc) { + sch->dev.driver_data =0 ; +put_device (&sch->dev); +if (cdev->dev.release) + cdev->dev.release (&cdev->dev); + } } static int
drivers/s390/cio/device_fsm.c +13 -7
@@ -112,7 +112,10 @@CIO_DEBUG (KERN_WARNING ,2 ,"SenseID : unknown device %04X on subchannel %04X\n" , sch->schib.pmcw.dev, sch->irq); -device_unregister (&cdev->dev); + sch->dev.driver_data =0 ; +put_device (&sch->dev); +if (cdev->dev.release) + cdev->dev.release (&cdev->dev);break ;case DEV_STATE_OFFLINE :/* fill out sense information */
@@ -235,10 +238,8 @@ sch =to_subchannel (cdev->dev.parent); -if (state !=DEV_STATE_ONLINE ) { +if (state !=DEV_STATE_ONLINE )cio_disable_subchannel (sch); -device_unregister (&cdev->dev); - }/* Reset device status. */ memset (&cdev->private->irb,0 ,sizeof (struct irb ));
@@ -246,6 +247,9 @@ cdev->private->state = state;wake_up (&cdev->private->wait_q); + +if (state !=DEV_STATE_ONLINE ) +put_device (&cdev->dev); }void
@@ -275,6 +279,8 @@if (cdev->private->state !=DEV_STATE_OFFLINE )return -EINVAL ; sch =to_subchannel (cdev->dev.parent); +if (!get_device (&cdev->dev)) +return -ENODEV ;if (cio_enable_subchannel (sch, sch->schib.pmcw.isc) !=0 ) {/* Couldn't enable the subchannel for i/o. Sick device. */ dev_fsm_event (cdev,DEV_EVENT_NOTOPER );
@@ -683,19 +689,19 @@ [DEV_EVENT_NOTOPER] ccw_device_online_notoper, [DEV_EVENT_INTERRUPT] ccw_device_qdio_init_irq, [DEV_EVENT_TIMEOUT] ccw_device_qdio_init_timeout, - [DEV_EVENT_VERIFY] ccw_device_nop, //FIXME + [DEV_EVENT_VERIFY] ccw_device_nop, }, [DEV_STATE_QDIO_ACTIVE] { [DEV_EVENT_NOTOPER] ccw_device_online_notoper, [DEV_EVENT_INTERRUPT] ccw_device_irq, [DEV_EVENT_TIMEOUT] ccw_device_nop, - [DEV_EVENT_VERIFY] ccw_device_nop, //FIXME + [DEV_EVENT_VERIFY] ccw_device_nop, }, [DEV_STATE_QDIO_CLEANUP] { [DEV_EVENT_NOTOPER] ccw_device_online_notoper, [DEV_EVENT_INTERRUPT] ccw_device_qdio_cleanup_irq, [DEV_EVENT_TIMEOUT] ccw_device_qdio_cleanup_timeout, - [DEV_EVENT_VERIFY] ccw_device_nop, //FIXME + [DEV_EVENT_VERIFY] ccw_device_nop, },/* states to wait for i/o completion before doing something */ [DEV_STATE_ONLINE_VERIFY] {
drivers/s390/cio/ioasm.h +1 -1
@@ -260,7 +260,7 @@return ccode; } -extern __inline__int do_chsc (void *chsc_area) +extern __inline__int chsc (void *chsc_area) {int cc;
drivers/s390/cio/qdio.c +18 -16
@@ -53,8 +53,9 @@#include "device.h" #include "airq.h" #include "qdio.h" +#include "ioasm.h" -#define VERSION_QDIO_C "$Revision: 1.16 $" +#define VERSION_QDIO_C "$Revision: 1.18 $"/****************** MODULE PARAMETER VARIABLES ********************/ MODULE_AUTHOR ("Utz Bacher <[email protected]>" );
@@ -1573,33 +1574,33 @@ {struct qdio_irq *irq_ptr;struct qdio_q *q; -int irq;int cstat,dstat; -char dbf_text[15 ]="qintXXXX" ; +char dbf_text[15 ]; - irq = cdev->private->irq;/* FIXME: use different dbg */ cstat = irb->scsw.cstat; dstat = irb->scsw.dstat; - *((int *)(&dbf_text[4 ]))=irq; -QDIO_DBF_HEX4 (0 ,trace,dbf_text,QDIO_DBF_TRACE_LEN ); +QDIO_DBF_TEXT4 (0 , trace,"qint" ); +sprintf (dbf_text,"%s" , cdev->dev.bus_id); +QDIO_DBF_TEXT4 (0 , trace, dbf_text);if (!intparm || !cdev) {QDIO_PRINT_STUPID ("got unsolicited interrupt in qdio " \ -"handler, irq 0x%x\n" ,irq); +"handler, device %s\n" , cdev->dev.bus_id);return ; } irq_ptr = cdev->private->qdio_data;if (!irq_ptr) { -sprintf (dbf_text,"uint%4x" ,irq); +QDIO_DBF_TEXT2 (1 , trace,"uint" ); +sprintf (dbf_text,"%s" , cdev->dev.bus_id);QDIO_DBF_TEXT2 (1 ,trace,dbf_text); -QDIO_PRINT_ERR ("received interrupt on unused irq 0x%04x!\n" , - irq); +QDIO_PRINT_ERR ("received interrupt on unused device %s!\n" , + cdev->dev.bus_id);return ; } -qdio_irq_check_sense (irq, irb); +qdio_irq_check_sense (irq_ptr->irq, irb);if (cstat &SCHN_STAT_PCI ) {qdio_handle_pci (irq_ptr);
@@ -1607,21 +1608,22 @@ }if ((cstat&~SCHN_STAT_PCI )||dstat) { -sprintf (dbf_text,"ick2%4x" ,irq); +QDIO_DBF_TEXT2 (1 , trace,"ick2" ); +sprintf (dbf_text,"%s" , cdev->dev.bus_id);QDIO_DBF_TEXT2 (1 ,trace,dbf_text);QDIO_DBF_HEX2 (0 ,trace,&intparm,sizeof (int ));QDIO_DBF_HEX2 (0 ,trace,&dstat,sizeof (int ));QDIO_DBF_HEX2 (0 ,trace,&cstat,sizeof (int ));QDIO_PRINT_ERR ("received check condition on activate " \ -"queues on irq 0x%x (cs=x%x, ds=x%x).\n" , - irq,cstat,dstat); +"queues on device %s (cs=x%x, ds=x%x).\n" , + cdev->dev.bus_id, cstat, dstat);if (irq_ptr->no_input_qs) { q=irq_ptr->input_qs[0 ]; }else if (irq_ptr->no_output_qs) { q=irq_ptr->output_qs[0 ]; }else { -QDIO_PRINT_ERR ("oops... no queue registered on irq " \ -"0x%x!?\n" ,irq); +QDIO_PRINT_ERR ("oops... no queue registered for " \ +"device %s!?\n" , cdev->dev.bus_id); goto omit_handler_call; } q->handler(q->irq,QDIO_STATUS_ACTIVATE_CHECK_CONDITION|
drivers/s390/net/cu3088.c +3 -3
@@ -1,5 +1,5 @@/* -* $Id: cu3088.c,v 1.21 2002/12/03 16:26:45 cohuck Exp $ +* $Id: cu3088.c,v 1.22 2002/12/10 09:53:55 cohuck Exp $ * * CTC / LCS ccw_device driver *
@@ -172,5 +172,5 @@module_init (cu3088_init);module_exit (cu3088_exit); -EXPORT_SYMBOL (register_cu3088_discipline); -EXPORT_SYMBOL (unregister_cu3088_discipline); +EXPORT_SYMBOL_GPL (register_cu3088_discipline); +EXPORT_SYMBOL_GPL (unregister_cu3088_discipline);
include/asm-s390/cio.h +0 -2
@@ -262,8 +262,6 @@extern int diag210 (struct diag210 *addr); -extern int chsc (void *data); -extern void wait_cons_dev (void );#endif
include/asm-s390x/ccwgroup.h +4 -4
@@ -31,10 +31,10 @@extern int ccwgroup_driver_register (struct ccwgroup_driver *cdriver);extern void ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver); -extern int ccwgroup_create_dev (struct device *root, -unsigned int creator_id, -struct ccw_driver *gdrv, -int argc,char *argv[]); +extern int ccwgroup_create (struct device *root, +unsigned int creator_id, +struct ccw_driver *gdrv, +int argc,char *argv[]);extern int ccwgroup_probe_ccwdev (struct ccw_device *cdev);extern int ccwgroup_remove_ccwdev (struct ccw_device *cdev);
include/asm-s390x/cio.h +0 -2
@@ -262,8 +262,6 @@extern int diag210 (struct diag210 *addr); -extern int chsc (void *data); -extern void wait_cons_dev (void );#endif