IDE Power Management, try 3
PATCH 1/1 IDE Power Management, try 3
Ok, here's a new one, if it's ok, please submit to Linus for inclusion.
Will remain to do:
- Check if more is needed in ide-disk (what is there is ok for my
needs on pmac, but Alan suggested some BIOSes may want us to restore some PIO settings or whatever)
- Check if more is needed for ide-cd. (In 2.4, I had to hack around
check media change & revalidate for things to work properly when putting the machine to sleep while reading MP3s from a mouted CD-ROM, I haven't yet cheked such scenarios in 2.5).
- Eventually do something for ide-floppy, ide-tape
- ide-scsi should probably just wait for proper PM stuff to be done
in the SCSI layer. That is sd or sr will get the suspend/resume requests and do what they have to (if anything has to be done).
I also considered that a PM state of 4 is suspend-to-disk and skipped the STANDBY step in this case.
Ben.
===== drivers/ide/ide-cd.c 1.49 vs edited =====
drivers/ide/ide-cd.c +44 -0
@@ -3253,6 +3253,44 @@static int ide_cdrom_attach (ide_drive_t *drive); +/* Power Management state machine. +* +* We don't do much for CDs right now +*/ + + +static void ide_cdrom_complete_power_step (ide_drive_t *drive,struct request *rq,u8 stat,u8 error) +{ +} + +static ide_startstop_t ide_cdrom_start_power_step (ide_drive_t *drive,struct request *rq) +{ +ide_task_t *args = rq->special; + +memset (args,0 ,sizeof (ide_task_t)); + +switch (rq->pm->pm_step) { +case ide_pm_state_start_suspend: +break ; + +case ide_pm_state_start_resume:/* Resume step 1 (restore DMA) */ +/* Right now, all we do is call ide_dma_check for the HWIF, +* we could be smarter and check for current xfer_speed +* in struct drive etc... +* Also, this step could be implemented as a generic helper +* as most subdrivers will use it +*/ +if (!drive->id || !(drive->id->capability &1 )) +break ; +if (HWIF (drive)->ide_dma_check ==NULL ) +break ; +HWIF (drive)->ide_dma_check (drive); +break ; + } + rq->pm->pm_step = ide_pm_state_completed; +return ide_stopped; +} +static ide_driver_t ide_cdrom_driver = { .owner =THIS_MODULE , .name ="ide-cdrom" ,
@@ -3269,6 +3307,12 @@ .capacity = ide_cdrom_capacity, .attach = ide_cdrom_attach, .drives = LIST_HEAD_INIT(ide_cdrom_driver.drives), + .start_power_step = ide_cdrom_start_power_step, + .complete_power_step = ide_cdrom_complete_power_step, + .gen_driver = { + .suspend = generic_ide_suspend, + .resume = generic_ide_resume, + } };static int idecd_open (struct inode * inode,struct file * file)
===== drivers/ide/ide-disk.c 1.45 vs edited =====
drivers/ide/ide-disk.c +64 -45
148 lines not on this page · raw message
===== drivers/ide/ide-io.c 1.11 vs edited =====
drivers/ide/ide-io.c +109 -4
174 lines not on this page · raw message
===== drivers/ide/ide-iops.c 1.17 vs edited =====
drivers/ide/ide-iops.c +27 -0
@@ -1318,5 +1318,32 @@return do_reset1 (drive,0 ); } +/* +* This function waits for the hwif to report a non-busy status +* see comments in probe_hwif() +*/ +int ide_wait_not_busy (ide_hwif_t *hwif,unsigned long timeout) +{ +u8 stat =0 ; + +while (timeout--) { +/* Turn this into a schedule() sleep once I'm sure +* about locking issues (2.5 work ?) +*/ +mdelay (1 ); + stat = hwif->INB (hwif->io_ports[IDE_STATUS_OFFSET ]); +if ((stat &BUSY_STAT ) ==0 ) +break ; +/* Assume a value of 0xff means nothing is connected to +* the interface and it doesn't implement the pull-down +* resistor on D7 +*/ +if (stat ==0xff ) +break ; + } +return ((stat &BUSY_STAT ) ==0 ) ?0 : -EBUSY ; +} + +EXPORT_SYMBOL (ide_do_reset);
===== drivers/ide/ide-probe.c 1.49 vs edited =====
drivers/ide/ide-probe.c +3 -33
@@ -723,35 +723,6 @@//EXPORT_SYMBOL(hwif_register); -/* Enable code below on all archs later, for now, I want it on PPC -*/ -#ifdef CONFIG_PPC -/* -* This function waits for the hwif to report a non-busy status -* see comments in probe_hwif() -*/ -static int wait_not_busy (ide_hwif_t *hwif,unsigned long timeout) -{ -u8 stat =0 ; - -while (timeout--) { -/* Turn this into a schedule() sleep once I'm sure -* about locking issues (2.5 work ?) -*/ -mdelay (1 ); - stat = hwif->INB (hwif->io_ports[IDE_STATUS_OFFSET ]); -if ((stat &BUSY_STAT ) ==0 ) -break ; -/* Assume a value of 0xff means nothing is connected to -* the interface and it doesn't implement the pull-down -* resistor on D7 -*/ -if (stat ==0xff ) -break ; - } -return ((stat &BUSY_STAT ) ==0 ) ?0 : -EBUSY ; -} -static int wait_hwif_ready (ide_hwif_t *hwif) {int rc;
@@ -766,7 +737,7 @@* I know of at least one disk who takes 31 seconds, I use 35 * here to be safe */ - rc =wait_not_busy (hwif,35000 ); + rc =ide_wait_not_busy (hwif,35000 );if (rc)return rc;
@@ -774,20 +745,19 @@SELECT_DRIVE (&hwif->drives[0 ]); hwif->OUTB (8 , hwif->io_ports[IDE_CONTROL_OFFSET ]);mdelay (2 ); - rc =wait_not_busy (hwif,10000 ); + rc =ide_wait_not_busy (hwif,10000 );if (rc)return rc;SELECT_DRIVE (&hwif->drives[1 ]); hwif->OUTB (8 , hwif->io_ports[IDE_CONTROL_OFFSET ]);mdelay (2 ); - rc =wait_not_busy (hwif,10000 ); + rc =ide_wait_not_busy (hwif,10000 );/* Exit function with master reselected (let's be sane) */ SELECT_DRIVE (&hwif->drives[0 ]);return rc; } -#endif /* CONFIG_PPC */ /* * This routine only knows how to look for drive units 0 and 1
===== drivers/ide/ide.c 1.70 vs edited =====
drivers/ide/ide.c +48 -0
54 lines not on this page · raw message
===== include/linux/blkdev.h 1.106 vs edited =====
include/linux/blkdev.h +27 -0
@@ -19,6 +19,7 @@typedef struct request_queue request_queue_t ;struct elevator_s ;typedef struct elevator_s elevator_t ; +struct request_pm_state ;#define BLKDEV_MIN_RQ 4#define BLKDEV_MAX_RQ 128
@@ -102,6 +103,11 @@void *sense;unsigned int timeout; + +/* +* For Power Management requests +*/ +struct request_pm_state *pm; };/*
@@ -130,6 +136,10 @@ __REQ_DRIVE_CMD, __REQ_DRIVE_TASK, __REQ_DRIVE_TASKFILE, + __REQ_PREEMPT,/* Flag set for "ide_preempt" requests */ + __REQ_PM_SUSPEND,/* Suspend request */ + __REQ_PM_RESUME,/* Resume request */ + __REQ_PM_SHUTDOWN,/* Shutdown request */ __REQ_NR_BITS, /* stops here */ };
@@ -151,6 +161,23 @@#define REQ_DRIVE_CMD (1 << __REQ_DRIVE_CMD)#define REQ_DRIVE_TASK (1 << __REQ_DRIVE_TASK)#define REQ_DRIVE_TASKFILE (1 << __REQ_DRIVE_TASKFILE) +#define REQ_PREEMPT (1 << __REQ_PREEMPT) +#define REQ_PM_SUSPEND (1 << __REQ_PM_SUSPEND) +#define REQ_PM_RESUME (1 << __REQ_PM_RESUME) +#define REQ_PM_SHUTDOWN (1 << __REQ_PM_SHUTDOWN) + +#define blk_request_is_pm (rq) \ + ((rq->flags & (REQ_PM_SUSPEND | REQ_PM_RESUME)) != 0) + +/* State information carried for REQ_PM_SUSPEND and REQ_PM_RESUME +* requests. Some step values could eventually be made generic. +*/ +struct request_pm_state +{ +int pm_step;/* PM state machine step value, currently driver specific */ +int pm_state;/* requested PM state value (S1,S2,S3,S4,...) */ +void * data;/* for driver use */ +};#include <linux/elevator.h>
===== include/linux/ide.h 1.54 vs edited =====
include/linux/ide.h +42 -0
78 lines not on this page · raw message