@ -551,7 +551,7 @@ static void floppy_ready(void);
static void floppy_start ( void ) ;
static void process_fd_request ( void ) ;
static void recalibrate_floppy ( void ) ;
static void floppy_shutdown ( unsigned long ) ;
static void floppy_shutdown ( struct work_struct * ) ;
static int floppy_request_regions ( int ) ;
static void floppy_release_regions ( int ) ;
@ -588,6 +588,8 @@ static int buffer_max = -1;
static struct floppy_fdc_state fdc_state [ N_FDC ] ;
static int fdc ; /* current fdc */
static struct workqueue_struct * floppy_wq ;
static struct floppy_struct * _floppy = floppy_type ;
static unsigned char current_drive ;
static long current_count_sectors ;
@ -629,16 +631,15 @@ static inline void set_debugt(void) { }
static inline void debugt ( const char * func , const char * msg ) { }
# endif /* DEBUGT */
typedef void ( * timeout_fn ) ( unsigned long ) ;
static DEFINE_TIMER ( fd_timeout , floppy_shutdown , 0 , 0 ) ;
static DECLARE_DELAYED_WORK ( fd_timeout , floppy_shutdown ) ;
static const char * timeout_message ;
static void is_alive ( const char * func , const char * message )
{
/* this routine checks whether the floppy driver is "alive" */
if ( test_bit ( 0 , & fdc_busy ) & & command_status < 2 & &
! timer _pending( & fd_timeout ) ) {
! delayed_work _pending( & fd_timeout ) ) {
DPRINT ( " %s: timeout handler died. %s \n " , func , message ) ;
}
}
@ -666,15 +667,18 @@ static int output_log_pos;
static void __reschedule_timeout ( int drive , const char * message )
{
unsigned long delay ;
if ( drive = = current_reqD )
drive = current_drive ;
del_timer ( & fd_timeout ) ;
if ( drive < 0 | | drive > = N_DRIVE ) {
fd_timeout . expires = jiffies + 20UL * HZ ;
delay = 20UL * HZ ;
drive = 0 ;
} else
fd_timeout . expires = jiffies + UDP - > timeout ;
add_timer ( & fd_timeout ) ;
delay = UDP - > timeout ;
queue_delayed_work ( floppy_wq , & fd_timeout , delay ) ;
if ( UDP - > flags & FD_DEBUG )
DPRINT ( " reschedule timeout %s \n " , message ) ;
timeout_message = message ;
@ -872,7 +876,7 @@ static int lock_fdc(int drive, bool interruptible)
command_status = FD_COMMAND_NONE ;
__ reschedule_timeout( drive , " lock fdc " ) ;
reschedule_timeout ( drive , " lock fdc " ) ;
set_fdc ( drive ) ;
return 0 ;
}
@ -880,23 +884,15 @@ static int lock_fdc(int drive, bool interruptible)
/* unlocks the driver */
static void unlock_fdc ( void )
{
unsigned long flags ;
raw_cmd = NULL ;
if ( ! test_bit ( 0 , & fdc_busy ) )
DPRINT ( " FDC access conflict! \n " ) ;
if ( do_floppy )
DPRINT ( " device interrupt still active at FDC release: %pf! \n " ,
do_floppy ) ;
raw_cmd = NULL ;
command_status = FD_COMMAND_NONE ;
spin_lock_irqsave ( & floppy_lock , flags ) ;
del_timer ( & fd_timeout ) ;
__cancel_delayed_work ( & fd_timeout ) ;
do_floppy = NULL ;
cont = NULL ;
clear_bit ( 0 , & fdc_busy ) ;
if ( current_req | | set_next_request ( ) )
do_fd_request ( current_req - > q ) ;
spin_unlock_irqrestore ( & floppy_lock , flags ) ;
wake_up ( & fdc_wait ) ;
}
@ -968,26 +964,24 @@ static DECLARE_WORK(floppy_work, NULL);
static void schedule_bh ( void ( * handler ) ( void ) )
{
WARN_ON ( work_pending ( & floppy_work ) ) ;
PREPARE_WORK ( & floppy_work , ( work_func_t ) handler ) ;
schedule_work ( & floppy_work ) ;
queue_work ( floppy_wq , & floppy_work ) ;
}
static DEFINE_TIMER ( fd_timer , NULL , 0 , 0 ) ;
static DECLARE_DELAYED_WORK ( fd_timer , NULL ) ;
static void cancel_activity ( void )
{
unsigned long flags ;
spin_lock_irqsave ( & floppy_lock , flags ) ;
do_floppy = NULL ;
PREPARE_WORK ( & floppy_work , ( work_func_t ) empty ) ;
del_timer ( & fd_timer ) ;
spin_unlock_irqrestore ( & floppy_lock , flags ) ;
cancel_delayed_work_sync ( & fd_timer ) ;
cancel_work_sync ( & floppy_work ) ;
}
/* this function makes sure that the disk stays in the drive during the
* transfer */
static void fd_watchdog ( void )
static void fd_watchdog ( struct work_struct * arg )
{
debug_dcl ( DP - > flags , " calling disk change from watchdog \n " ) ;
@ -997,21 +991,20 @@ static void fd_watchdog(void)
cont - > done ( 0 ) ;
reset_fdc ( ) ;
} else {
del_timer ( & fd_timer ) ;
fd_timer . function = ( timeout_fn ) fd_watchdog ;
fd_timer . expires = jiffies + HZ / 10 ;
add_timer ( & fd_timer ) ;
cancel_delayed_work ( & fd_timer ) ;
PREPARE_DELAYED_WORK ( & fd_timer , fd_watchdog ) ;
queue_delayed_work ( floppy_wq , & fd_timer , HZ / 10 ) ;
}
}
static void main_command_interrupt ( void )
{
del_timer ( & fd_timer ) ;
cancel_delayed_work ( & fd_timer ) ;
cont - > interrupt ( ) ;
}
/* waits for a delay (spinup or select) to pass */
static int fd_wait_for_completion ( unsigned long delay , timeout_fn function )
static int fd_wait_for_completion ( unsigned long expires , work_func_t function )
{
if ( FDCS - > reset ) {
reset_fdc ( ) ; /* do the reset during sleep to win time
@ -1020,11 +1013,10 @@ static int fd_wait_for_completion(unsigned long delay, timeout_fn function)
return 1 ;
}
if ( time_before ( jiffies , delay ) ) {
del_timer ( & fd_timer ) ;
fd_timer . function = function ;
fd_timer . expires = delay ;
add_timer ( & fd_timer ) ;
if ( time_before ( jiffies , expires ) ) {
cancel_delayed_work ( & fd_timer ) ;
PREPARE_DELAYED_WORK ( & fd_timer , function ) ;
queue_delayed_work ( floppy_wq , & fd_timer , expires - jiffies ) ;
return 1 ;
}
return 0 ;
@ -1342,7 +1334,7 @@ static int fdc_dtr(void)
*/
FDCS - > dtr = raw_cmd - > rate & 3 ;
return fd_wait_for_completion ( jiffies + 2UL * HZ / 100 ,
( timeout_fn ) floppy_ready ) ;
( work_func_t ) floppy_ready ) ;
} /* fdc_dtr */
static void tell_sector ( void )
@ -1447,7 +1439,7 @@ static void setup_rw_floppy(void)
int flags ;
int dflags ;
unsigned long ready_date ;
timeout_fn function ;
work_func_t function ;
flags = raw_cmd - > flags ;
if ( flags & ( FD_RAW_READ | FD_RAW_WRITE ) )
@ -1461,9 +1453,9 @@ static void setup_rw_floppy(void)
*/
if ( time_after ( ready_date , jiffies + DP - > select_delay ) ) {
ready_date - = DP - > select_delay ;
function = ( timeout_fn ) floppy_start ;
function = ( work_func_t ) floppy_start ;
} else
function = ( timeout_fn ) setup_rw_floppy ;
function = ( work_func_t ) setup_rw_floppy ;
/* wait until the floppy is spinning fast enough */
if ( fd_wait_for_completion ( ready_date , function ) )
@ -1493,7 +1485,7 @@ static void setup_rw_floppy(void)
inr = result ( ) ;
cont - > interrupt ( ) ;
} else if ( flags & FD_RAW_NEED_DISK )
fd_watchdog ( ) ;
fd_watchdog ( NULL ) ;
}
static int blind_seek ;
@ -1802,20 +1794,22 @@ static void show_floppy(void)
pr_info ( " do_floppy=%pf \n " , do_floppy ) ;
if ( work_pending ( & floppy_work ) )
pr_info ( " floppy_work.func=%pf \n " , floppy_work . func ) ;
if ( timer_pending ( & fd_timer ) )
pr_info ( " fd_timer.function=%pf \n " , fd_timer . function ) ;
if ( timer_pending ( & fd_timeout ) ) {
pr_info ( " timer_function=%pf \n " , fd_timeout . function ) ;
pr_info ( " expires=%lu \n " , fd_timeout . expires - jiffies ) ;
pr_info ( " now=%lu \n " , jiffies ) ;
}
if ( delayed_work_pending ( & fd_timer ) )
pr_info ( " delayed work.function=%p expires=%ld \n " ,
fd_timer . work . func ,
fd_timer . timer . expires - jiffies ) ;
if ( delayed_work_pending ( & fd_timeout ) )
pr_info ( " timer_function=%p expires=%ld \n " ,
fd_timeout . work . func ,
fd_timeout . timer . expires - jiffies ) ;
pr_info ( " cont=%p \n " , cont ) ;
pr_info ( " current_req=%p \n " , current_req ) ;
pr_info ( " command_status=%d \n " , command_status ) ;
pr_info ( " \n " ) ;
}
static void floppy_shutdown ( unsigned long data )
static void floppy_shutdown ( struct work_struct * arg )
{
unsigned long flags ;
@ -1868,7 +1862,7 @@ static int start_motor(void (*function)(void))
/* wait_for_completion also schedules reset if needed. */
return fd_wait_for_completion ( DRS - > select_date + DP - > select_delay ,
( timeout_fn ) function ) ;
( work_func_t ) function ) ;
}
static void floppy_ready ( void )
@ -2821,7 +2815,6 @@ do_request:
spin_lock_irq ( & floppy_lock ) ;
pending = set_next_request ( ) ;
spin_unlock_irq ( & floppy_lock ) ;
if ( ! pending ) {
do_floppy = NULL ;
unlock_fdc ( ) ;
@ -2898,13 +2891,15 @@ static void do_fd_request(struct request_queue *q)
current_req - > cmd_flags ) )
return ;
if ( test_bit ( 0 , & fdc_busy ) ) {
if ( test_and_set_ bit ( 0 , & fdc_busy ) ) {
/* fdc busy, this new request will be treated when the
current one is done */
is_alive ( __func__ , " old request running " ) ;
return ;
}
lock_fdc ( MAXTIMEOUT , false ) ;
command_status = FD_COMMAND_NONE ;
__reschedule_timeout ( MAXTIMEOUT , " fd_request " ) ;
set_fdc ( 0 ) ;
process_fd_request ( ) ;
is_alive ( __func__ , " " ) ;
}
@ -4159,10 +4154,16 @@ static int __init floppy_init(void)
goto out_put_disk ;
}
floppy_wq = alloc_ordered_workqueue ( " floppy " , 0 ) ;
if ( ! floppy_wq ) {
err = - ENOMEM ;
goto out_put_disk ;
}
disks [ dr ] - > queue = blk_init_queue ( do_fd_request , & floppy_lock ) ;
if ( ! disks [ dr ] - > queue ) {
err = - ENOMEM ;
goto out_put_disk ;
goto out_destroy_workq ;
}
blk_queue_max_hw_sectors ( disks [ dr ] - > queue , 64 ) ;
@ -4213,7 +4214,7 @@ static int __init floppy_init(void)
use_virtual_dma = can_use_virtual_dma & 1 ;
fdc_state [ 0 ] . address = FDC1 ;
if ( fdc_state [ 0 ] . address = = - 1 ) {
del_timer_sync ( & fd_timeout ) ;
cancel_delayed_work ( & fd_timeout ) ;
err = - ENODEV ;
goto out_unreg_region ;
}
@ -4224,7 +4225,7 @@ static int __init floppy_init(void)
fdc = 0 ; /* reset fdc in case of unexpected interrupt */
err = floppy_grab_irq_and_dma ( ) ;
if ( err ) {
del_timer_sync ( & fd_timeout ) ;
cancel_delayed_work ( & fd_timeout ) ;
err = - EBUSY ;
goto out_unreg_region ;
}
@ -4281,13 +4282,13 @@ static int __init floppy_init(void)
user_reset_fdc ( - 1 , FD_RESET_ALWAYS , false ) ;
}
fdc = 0 ;
del_timer_sync ( & fd_timeout ) ;
cancel_delayed_work ( & fd_timeout ) ;
current_drive = 0 ;
initialized = true ;
if ( have_no_fdc ) {
DPRINT ( " no floppy controllers found \n " ) ;
err = have_no_fdc ;
goto out_flush_work ;
goto out_release_dma ;
}
for ( drive = 0 ; drive < N_DRIVE ; drive + + ) {
@ -4302,7 +4303,7 @@ static int __init floppy_init(void)
err = platform_device_register ( & floppy_device [ drive ] ) ;
if ( err )
goto out_flush_work ;
goto out_release_dma ;
err = device_create_file ( & floppy_device [ drive ] . dev ,
& dev_attr_cmos ) ;
@ -4320,13 +4321,14 @@ static int __init floppy_init(void)
out_unreg_platform_dev :
platform_device_unregister ( & floppy_device [ drive ] ) ;
out_flush_work :
flush_work_sync ( & floppy_work ) ;
out_release_dma :
if ( atomic_read ( & usage_count ) )
floppy_release_irq_and_dma ( ) ;
out_unreg_region :
blk_unregister_region ( MKDEV ( FLOPPY_MAJOR , 0 ) , 256 ) ;
platform_driver_unregister ( & floppy_driver ) ;
out_destroy_workq :
destroy_workqueue ( floppy_wq ) ;
out_unreg_blkdev :
unregister_blkdev ( FLOPPY_MAJOR , " fd " ) ;
out_put_disk :
@ -4397,7 +4399,7 @@ static int floppy_grab_irq_and_dma(void)
* We might have scheduled a free_irq ( ) , wait it to
* drain first :
*/
flush_work_sync ( & floppy_work ) ;
flush_workqueue ( floppy_wq ) ;
if ( fd_request_irq ( ) ) {
DPRINT ( " Unable to grab IRQ%d for the floppy driver \n " ,
@ -4488,9 +4490,9 @@ static void floppy_release_irq_and_dma(void)
pr_info ( " motor off timer %d still active \n " , drive ) ;
# endif
if ( timer _pending( & fd_timeout ) )
if ( delayed_work _pending( & fd_timeout ) )
pr_info ( " floppy timer still active:%s \n " , timeout_message ) ;
if ( timer _pending( & fd_timer ) )
if ( delayed_work _pending( & fd_timer ) )
pr_info ( " auxiliary floppy timer still active \n " ) ;
if ( work_pending ( & floppy_work ) )
pr_info ( " work still pending \n " ) ;
@ -4560,8 +4562,9 @@ static void __exit floppy_module_exit(void)
put_disk ( disks [ drive ] ) ;
}
del_timer_sync ( & fd_timeout ) ;
del_timer_sync ( & fd_timer ) ;
cancel_delayed_work_sync ( & fd_timeout ) ;
cancel_delayed_work_sync ( & fd_timer ) ;
destroy_workqueue ( floppy_wq ) ;
if ( atomic_read ( & usage_count ) )
floppy_release_irq_and_dma ( ) ;