s390 (2/4): common i/o layer.
Subsystems (2)
PATCH 1/1 s390 (2/4): common i/o layer.
[PATCH] s390: common i/o layer.
From: Martin Schwidefsky <[email protected]>
Common i/o layer changes:
- qdio: Lose the adapter lock for thin interrupts to improve performance and do unregister of the adapter interrupt handler with rcu.
- ccwgroup: Fix error handling when creating a ccwgroup device.
- Convert the slow crw kernel thread to a single threaded workqueue.
- Use the slow crw workqueue to unregister a subchannel after it was found not operational to serialize it with other possible unregister/ register events coming in via machine checks.
- Trigger a rescan of the css via the slow path if a missing channel path is found in __recover_lost_chpids.
- Use saner default levels for the debug feature, add some debugging code.
- Remove request_irq and free_irq stubs.
- Remove bogus inlines.
diffstat:
drivers/s390/cio/airq.c | 38 +++++---------------- drivers/s390/cio/ccwgroup.c | 24 ++++++++----- drivers/s390/cio/chsc.c | 39 +++++++++++---------- drivers/s390/cio/cio.c | 8 ++-- drivers/s390/cio/css.c | 75 +++++++++++++++++++++--------------------- drivers/s390/cio/css.h | 4 +- drivers/s390/cio/device.c | 15 +++++--- drivers/s390/cio/device_fsm.c | 14 ------- drivers/s390/cio/requestirq.c | 17 --------- drivers/s390/s390mach.c | 25 ++------------ 10 files changed, 109 insertions(+), 150 deletions(-)
drivers/s390/cio/airq.c +10 -28
@@ -2,7 +2,7 @@* drivers/s390/cio/airq.c * S/390 common I/O routines -- support for adapter interruptions * -* $Revision: 1.11 $ +* $Revision: 1.12 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation
@@ -14,11 +14,11 @@#include <linux/init.h> #include <linux/module.h> #include <linux/slab.h> +#include <linux/rcupdate.h> #include "cio_debug.h" #include "airq.h" -static spinlock_t adapter_lock =SPIN_LOCK_UNLOCKED ;static adapter_int_handler_t adapter_handler;/*
@@ -40,23 +40,17 @@CIO_TRACE_EVENT (4 ,"rgaint" ); -spin_lock (&adapter_lock); -if (handler ==NULL ) ret = -EINVAL ; -else if (adapter_handler) - ret = -EBUSY ; -else { - adapter_handler = handler; - ret =0 ; - } - -spin_unlock (&adapter_lock); +else + ret = (cmpxchg (&adapter_handler,NULL , handler) ? -EBUSY :0 ); +if (!ret) +synchronize_kernel ();sprintf (dbf_txt,"ret:%d" , ret);CIO_TRACE_EVENT (4 , dbf_txt); -return (ret); +return ret; }int
@@ -67,38 +61,26 @@CIO_TRACE_EVENT (4 ,"urgaint" ); -spin_lock (&adapter_lock); -if (handler ==NULL ) ret = -EINVAL ; -else if (handler != adapter_handler) - ret = -EINVAL ;else { adapter_handler =NULL ; +synchronize_kernel (); ret =0 ; } - -spin_unlock (&adapter_lock); -sprintf (dbf_txt,"ret:%d" , ret);CIO_TRACE_EVENT (4 , dbf_txt); -return (ret); +return ret; }void do_adapter_IO (void ) { -CIO_TRACE_EVENT (4 ,"doaio" ); - -spin_lock (&adapter_lock); +CIO_TRACE_EVENT (6 ,"doaio" );if (adapter_handler) (*adapter_handler) (); - -spin_unlock (&adapter_lock); - -return ; }EXPORT_SYMBOL (s390_register_adapter_interrupt);
drivers/s390/cio/ccwgroup.c +16 -8
@@ -1,7 +1,7 @@/* * drivers/s390/cio/ccwgroup.c * bus driver for ccwgroup -* $Revision: 1.27 $ +* $Revision: 1.28 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation
@@ -179,12 +179,12 @@ || gdev->cdev[i]->id.driver_info != gdev->cdev[0]->id.driver_info) { rc = -EINVAL ; - goto error; + goto free_dev; }/* Don't allow a device to belong to more than one group. */ if (gdev->cdev[i]->dev.driver_data) { rc = -EINVAL ; - goto error; + goto free_dev; } }for (i =0 ; i < argc; i++)
@@ -207,8 +207,8 @@ rc =device_register (&gdev->dev);if (rc) - goto error; - + goto free_dev; +get_device (&gdev->dev); rc =device_create_file (&gdev->dev, &dev_attr_ungroup);if (rc) {
@@ -217,20 +217,28 @@ } rc =__ccwgroup_create_symlinks (gdev); -if (!rc) +if (!rc) { +put_device (&gdev->dev);return 0 ; - + }device_remove_file (&gdev->dev, &dev_attr_ungroup);device_unregister (&gdev->dev); error:for (i =0 ; i < argc; i++)if (gdev->cdev[i]) {put_device (&gdev->cdev[i]->dev); + gdev->cdev[i]->dev.driver_data =NULL ; + } +put_device (&gdev->dev); +return rc; +free_dev: +for (i =0 ; i < argc; i++) +if (gdev->cdev[i]) { +put_device (&gdev->cdev[i]->dev);if (del_drvdata) gdev->cdev[i]->dev.driver_data =NULL ; }kfree (gdev); -return rc; }
drivers/s390/cio/chsc.c +21 -18
@@ -1,7 +1,7 @@/* * drivers/s390/cio/chsc.c * S/390 common I/O routines -- channel subsystem call -* $Revision: 1.110 $ +* $Revision: 1.111 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation
@@ -62,11 +62,11 @@int state; state =get_chp_status (chp); -if (state <0 ) -new_channel_path (chp); -else +if (state <0 ) { + need_rescan =1 ; +queue_work (slow_path_wq, &slow_path_work); + }else WARN_ON (!state); -/* FIXME: should notify other subchannels here */ }/* FIXME: this is _always_ called for every subchannel. shouldn't we
@@ -285,8 +285,10 @@ out_unreg:spin_unlock (&sch->lock); sch->lpm =0 ; -/* We can't block here. */ -device_call_nopath_notify (sch); +if (css_enqueue_subchannel_slow (sch->irq)) { +css_clear_subchannel_slow_list (); + need_rescan =1 ; + }return 0 ; }
@@ -303,6 +305,9 @@bus_for_each_dev (&css_bus_type,NULL , &chpid, s390_subchannel_remove_chpid); + +if (need_rescan ||css_slow_subchannels_exist ()) +queue_work (slow_path_wq, &slow_path_work); } static int
@@ -737,10 +742,12 @@* can successfully terminate, even using the * just varied off path. Then kill it. */ -if (!__check_for_io_and_kill (sch, chp) && !sch->lpm) -/* Get over with it now. */ -device_call_nopath_notify (sch); -else if (sch->driver && sch->driver->verify) +if (!__check_for_io_and_kill (sch, chp) && !sch->lpm) { +if (css_enqueue_subchannel_slow (sch->irq)) { +css_clear_subchannel_slow_list (); + need_rescan =1 ; + } + }else if (sch->driver && sch->driver->verify) sch->driver->verify (&sch->dev); }break ;
@@ -773,11 +780,6 @@return 0 ; } -extern void css_trigger_slow_path (void ); -typedef void (*workfunc )(void *); -static DECLARE_WORK(varyonoff_work, (workfunc)css_trigger_slow_path, - NULL); -/* * Function: s390_vary_chpid * Varies the specified chpid online or offline
@@ -813,7 +815,7 @@ s390_subchannel_vary_chpid_on : s390_subchannel_vary_chpid_off);if (!on) -return 0 ; + goto out;/* Scan for new devices on varied on path. */ for (irq =0 ; irq < __MAX_SUBCHANNELS; irq++) {struct schib schib;
@@ -835,8 +837,9 @@ need_rescan =1 ; } } +out:if (need_rescan ||css_slow_subchannels_exist ()) -schedule_work (&varyonoff_work); +queue_work (slow_path_wq, &slow_path_work);return 0 ; }
drivers/s390/cio/cio.c +4 -4
@@ -1,7 +1,7 @@/* * drivers/s390/cio/cio.c * S/390 common I/O routines -- low level i/o calls -* $Revision: 1.121 $ +* $Revision: 1.123 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation
@@ -67,17 +67,17 @@if (!cio_debug_msg_id) goto out_unregister;debug_register_view (cio_debug_msg_id, &debug_sprintf_view); -debug_set_level (cio_debug_msg_id,6 ); +debug_set_level (cio_debug_msg_id,2 ); cio_debug_trace_id =debug_register ("cio_trace" ,4 ,4 ,8 );if (!cio_debug_trace_id) goto out_unregister;debug_register_view (cio_debug_trace_id, &debug_hex_ascii_view); -debug_set_level (cio_debug_trace_id,6 ); +debug_set_level (cio_debug_trace_id,2 ); cio_debug_crw_id =debug_register ("cio_crw" ,2 ,4 ,16 *sizeof (long ));if (!cio_debug_crw_id) goto out_unregister;debug_register_view (cio_debug_crw_id, &debug_sprintf_view); -debug_set_level (cio_debug_crw_id,6 ); +debug_set_level (cio_debug_crw_id,2 );pr_debug ("debugging initialized\n" );return 0 ;
drivers/s390/cio/css.c +39 -36
138 lines not on this page · raw message
drivers/s390/cio/css.h +3 -1
@@ -136,7 +136,6 @@/* Helper functions for vary on/off. */ void device_set_waiting (struct subchannel *); -void device_call_nopath_notify (struct subchannel *);/* Helper functions to build lists for the slow path. */ int css_enqueue_subchannel_slow (unsigned long schid);
@@ -144,4 +143,7 @@void css_clear_subchannel_slow_list (void );int css_slow_subchannels_exist (void );extern int need_rescan; + +extern struct workqueue_struct *slow_path_wq; +extern struct work_struct slow_path_work;#endif
drivers/s390/cio/device.c +10 -5
@@ -1,7 +1,7 @@/* * drivers/s390/cio/device.c * bus driver for ccw devices -* $Revision: 1.117 $ +* $Revision: 1.119 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation
@@ -159,6 +159,11 @@ ret = -ENOMEM ;/* FIXME: better errno ? */ goto out_err; } + slow_path_wq =create_singlethread_workqueue ("kslowcrw" ); +if (!slow_path_wq) { + ret = -ENOMEM ;/* FIXME: better errno ? */ + goto out_err; + }if ((ret =bus_register (&ccw_bus_type))) goto out_err;
@@ -174,6 +179,8 @@destroy_workqueue (ccw_device_work);if (ccw_device_notify_work)destroy_workqueue (ccw_device_notify_work); +if (slow_path_wq) +destroy_workqueue (slow_path_wq);return ret; }
@@ -646,9 +653,7 @@struct subchannel *sch; sch =to_subchannel (cdev->dev.parent); -/* Check if device is registered. */ -if (!list_empty (&sch->dev.node)) -device_unregister (&sch->dev); +device_unregister (&sch->dev);/* Reset intparm to zeroes. */ sch->schib.pmcw.intparm =0 ;cio_modify (sch);
@@ -677,7 +682,7 @@ sch =to_subchannel (cdev->dev.parent);INIT_WORK (&cdev->private->kick_work, ccw_device_call_sch_unregister, (void *) cdev); -queue_work (ccw_device_work, &cdev->private->kick_work); +queue_work (slow_path_wq, &cdev->private->kick_work);break ;case DEV_STATE_BOXED :/* Device did not respond in time. */
drivers/s390/cio/device_fsm.c +0 -14
@@ -459,20 +459,6 @@ }void -device_call_nopath_notify (struct subchannel *sch) -{ -struct ccw_device *cdev; - -if (!sch->dev.driver_data) -return ; - cdev = sch->dev.driver_data; -PREPARE_WORK (&cdev->private->kick_work, - ccw_device_nopath_notify, (void *)cdev); -queue_work (ccw_device_notify_work, &cdev->private->kick_work); -} - - -void ccw_device_verify_done (struct ccw_device *cdev,int err) { cdev->private->flags.doverify =0 ;
drivers/s390/cio/requestirq.c +1 -16
@@ -1,7 +1,7 @@/* * drivers/s390/cio/requestirq.c * S/390 common I/O routines -- enabling and disabling of devices -* $Revision: 1.45 $ +* $Revision: 1.46 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation
@@ -18,21 +18,6 @@#include "css.h" -/* for compatiblity only... */ -int -request_irq (unsigned int irq, -void (*handler) (int ,void *,struct pt_regs *), -unsigned long irqflags,const char *devname,void *dev_id) -{ -return -EINVAL ; -} - -/* for compatiblity only... */ -void -free_irq (unsigned int irq,void *dev_id) -{ -} -struct pgid global_pgid;EXPORT_SYMBOL_GPL (global_pgid);
drivers/s390/s390mach.c +5 -20
@@ -12,6 +12,7 @@#include <linux/init.h> #include <linux/sched.h> #include <linux/errno.h> +#include <linux/workqueue.h> #include <asm/lowcore.h>
@@ -21,13 +22,14 @@// #define DBG(args,...) do {} while (0); static struct semaphore m_sem; -static struct semaphore s_sem;extern int css_process_crw (int );extern int chsc_process_crw (void );extern int chp_process_crw (int ,int );extern void css_reiterate_subchannels (void ); -extern void css_trigger_slow_path (void ); + +extern struct workqueue_struct *slow_path_wq; +extern struct work_struct slow_path_work;static void s390_handle_damage (char *msg)
@@ -39,21 +41,6 @@disabled_wait ((unsigned long )__builtin_return_address (0 )); } -static int -s390_mchk_slow_path (void *param) -{ -struct semaphore *sem; - - sem = (struct semaphore *)param; -/* Set a nice name. */ -daemonize ("kslowcrw" ); -repeat: -down_interruptible (sem); -css_trigger_slow_path (); - goto repeat; -return 0 ; -} -/* * Retrieve CRWs and call function to handle event. *
@@ -130,7 +117,7 @@ } }if (slow) -up (&s_sem); +queue_work (slow_path_wq, &slow_path_work); goto repeat;return 0 ; }
@@ -202,7 +189,6 @@machine_check_init (void) {init_MUTEX_LOCKED (&m_sem); -init_MUTEX_LOCKED ( &s_sem );ctl_clear_bit (14 ,25 );/* disable damage MCH */ ctl_set_bit (14 ,26 );/* enable degradation MCH */ ctl_set_bit (14 ,27 );/* enable system recovery MCH */
@@ -226,7 +212,6 @@machine_check_crw_init (void) {kernel_thread (s390_collect_crw_info, &m_sem,CLONE_FS |CLONE_FILES ); -kernel_thread (s390_mchk_slow_path, &s_sem,CLONE_FS |CLONE_FILES );ctl_set_bit (14 ,28 );/* enable channel report MCH */ return 0 ; }