From: viro@parcelfarce.linux.theplanet.co.uk * new helper: pi_schedule_claimed() - pi_do_claimed() sans the call of continuation if we don't have to wait; returns 1 if we don't have to wait and 0 otherwise. Preparation to crapectomy - expanded include of pseudo.h, split the part of pd_do_request() into pd_do_request1(), leaving in pd_do_request() only the check that FSM is not running and call of pd_do_request1(). Added locking analysis - it's in drivers/block/paride/Transition-notes and it will be used on the next step. Even though the subsequent steps are small, they rely on properties of the damn thing and proof of these properties is hairy. Amazing perversions people manage to produce when writing a trivial FSM - the code is very convoluted for no good reason... Removed junk (see the analysis in the previous patch), removed ps_set_intr() arguments. Logics around "if not ready, schedule the same step again" taken out of ps_tq_intr() and into the steps that need it. pd_busy gone - we can check for pd_req != NULL instead. Equivalent transformation: * new function: do_pd_io_start(). Checks pd_cmd and calls do_pd_read_start() or do_pd_write_start(). * do_pd_read() and do_pd_write() merged into do_pd_io(), which schedules execution of do_pd_io_start(). Equivalent transformation: Handling of bogus requests taken into do_pd_io_start() - we call next_request(0) as we would for any other error. We need to call pi_unclaim() before that - on other paths that would happen as a side effect of pi_disconnect(). Setting variables moved into do_pd_io_start() - they don't need pd_lock being held, so we can shift that outside. Equivalent transformation: instead of having do_pd_request1() calling do_pd_io() via pi_do_claimed() and do_pd_io() calling do_pd_io_start() via ps_set_intr(), do it the other way round. Equivalent transformation: do_pd_reqeust1() calls lambda-expanded, function killed. resulting call of ps_set_intr() in next_request() has been moved past dropping pd_lock. Equivalent transformation: * ps_continuation renamed - it's "phase" now. * run_fsm() does what ps_tq_int() used to do * calls of pi_do_claimed(..., func) replaced with phase = func; pi_do_claimed(..., run_fsm); Now all phase functions are called from run_fsm() and we can start pulling the common code into it. Equivalent transformation: * new type - enum action. phase functions return it now. run_fsm() looks at the result of phase() and does the corresponding action - next_request(), pi_do_claimed() or ps_set_intr(). Equivalent transformation: * calls of pi_disconnect() in phase functions expanded. * since both do_pd_read_start() and do_pd_write_start() are always called claimed (as the matter of fact, all phase functions except do_pd_io() are), we can replace call of pi_connect() with direct method call - pi_claim() is no-op there. Equivalent transformation: pi_unclaim() moved from phase functions to run_fsm(). Equivalent transformation: call of pi_do_claimed() in run_fsm() expanded; recursive call of run_fsm() replaced with loop. Equivalent transformation: next_request() call expanded. Equivalent transformation: * phase = do_pd_io replaced with phase = NULL, corresponding check + open-coded equivalent added in run_fsm loop. * do_pd_io() is gone. Equivalent transformation: now that all phase functions are called claimed, we can simplify the logics around claiming - new variable (pd_claimed) keeps track of claim/unclaim we'd done. We check it in the beginning of the loop and do claiming if it's not set. Moved calls of ->connect and ->disconnect into run_fsm(). The only change is that now do_pd_start_io() is ran when we are connected. Reordered stuff made pd_ready() inlined renamed ps_timeout to pd_timeout renamed ps_tq to fsm_tq renamed ps_set_intr to fsm_schedule removed unused pd_wait_open. Switched everything except pd_identify() to use of special requests. New helper: pd_special_command() - builds special request, feeds it into queue and waits for completion. Moved pi_connect()/pi_disconnect() to the beginning/end of pi_identify. Moved allocation and setup (but not adding) of gendisk into pd_probe_drive(). Now disk->present is not needed - we can always check for disk->gd. Field removed, pd_probe_drive() became void(struct pd_unit *), pd_detect() cleaned up, pd_init_units() merged into pd_detect(), pd_drive_count made local to pd_detect(). pd_identify() converted to pd_special_command(). --- 25-akpm/drivers/block/paride/paride.c | 13 ++++++++++--- 25-akpm/drivers/block/paride/paride.h | 1 + 2 files changed, 11 insertions(+), 3 deletions(-) diff -puN drivers/block/paride/paride.c~PI0-schedule_claimed-RC1 drivers/block/paride/paride.c --- 25/drivers/block/paride/paride.c~PI0-schedule_claimed-RC1 Wed Jan 14 13:22:16 2004 +++ 25-akpm/drivers/block/paride/paride.c Wed Jan 14 13:46:13 2004 @@ -102,7 +102,7 @@ static void pi_wake_up(void *p) #endif -void pi_do_claimed(PIA * pi, void (*cont) (void)) +int pi_schedule_claimed(PIA * pi, void (*cont) (void)) { #ifdef CONFIG_PARPORT unsigned long flags; @@ -111,12 +111,19 @@ void pi_do_claimed(PIA * pi, void (*cont if (pi->pardev && parport_claim(pi->pardev)) { pi->claim_cont = cont; spin_unlock_irqrestore(&pi_spinlock, flags); - return; + return 0; } pi->claimed = 1; spin_unlock_irqrestore(&pi_spinlock, flags); #endif - cont(); + return 1; +} +EXPORT_SYMBOL(pi_schedule_claimed); + +void pi_do_claimed(PIA * pi, void (*cont) (void)) +{ + if (pi_schedule_claimed(pi, cont)) + cont(); } EXPORT_SYMBOL(pi_do_claimed); diff -puN drivers/block/paride/paride.h~PI0-schedule_claimed-RC1 drivers/block/paride/paride.h --- 25/drivers/block/paride/paride.h~PI0-schedule_claimed-RC1 Wed Jan 14 13:22:16 2004 +++ 25-akpm/drivers/block/paride/paride.h Wed Jan 14 13:46:13 2004 @@ -93,6 +93,7 @@ extern void pi_connect(PIA *pi); extern void pi_disconnect(PIA *pi); extern void pi_do_claimed(PIA *pi, void (*cont)(void)); +extern int pi_schedule_claimed(PIA *pi, void (*cont)(void)); /* macros and functions exported to the protocol modules */ _