Hi Pavel Machek:
I try the 2.5.70-mm3 with software suspend function. When suspend it will oops at ide-disk.c 1526 line
BUG_ON (HWGROUP(drive)->handler);
I'm disable this check, The software suspend can work, and also can resumed. But this fix is not best way. I found in ide-io.c 1196
hwgroup->handler = NULL;
is the problem.
thanks.
--
Hu Gang / Steve
Email : [email protected], [email protected]
GPG FinePrint: 4099 3F1D AE01 1817 68F7 D499 A6C2 C418 86C8 610E
http://soulinfo.com/~hugang/HuGang.asc
ICQ# : 205800361
Registered Linux User : 204016
On Maw, 2003-06-03 at 14:11, hugang wrote:
> Hi Pavel Machek:
>
> I try the 2.5.70-mm3 with software suspend function. When suspend it will oops at ide-disk.c 1526 line
> BUG_ON (HWGROUP(drive)->handler);
>
> I'm disable this check, The software suspend can work, and also can resumed. But this fix is not best way. I found in ide-io.c 1196
> hwgroup->handler = NULL;
> is the problem.
The only way to make the suspend work properly is to queue the suspend
sequence wit the other requests. Ben was doing some playing with this
but I'm not sure what happened to it.
On 03 Jun 2003 14:22:48 +0100
Alan Cox <[email protected]> wrote:
> On Maw, 2003-06-03 at 14:11, hugang wrote:
> > Hi Pavel Machek:
> >
> > I try the 2.5.70-mm3 with software suspend function. When suspend it will oops at ide-disk.c 1526 line
> > BUG_ON (HWGROUP(drive)->handler);
> >
> > I'm disable this check, The software suspend can work, and also can resumed. But this fix is not best way. I found in ide-io.c 1196
> > hwgroup->handler = NULL;
> > is the problem.
>
> The only way to make the suspend work properly is to queue the suspend
> sequence wit the other requests. Ben was doing some playing with this
> but I'm not sure what happened to it.
>
Yes the above patch is not safe, When i'm run updatedb and suspsned, After resume will oops at kjournal.
Here is another test on it, it can works with updatedb.
-
I found a best way to fix it. here is it. With the patch, I'm run updatedb and suspend for 5 counts, every things is ok.
--- ide-disk.c.old Tue Jun 3 22:22:13 2003
+++ ide-disk.c Tue Jun 3 22:16:22 2003
@@ -1523,7 +1523,10 @@
do_idedisk_standby(drive);
drive->blocked = 1;
- BUG_ON (HWGROUP(drive)->handler);
+ /*BUG_ON (HWGROUP(drive)->handler);*/
+ while(HWGROUP(drive)->handler) {
+ schedule();
+ }
return 0;
}
--
Hu Gang / Steve
Email : [email protected], [email protected]
GPG FinePrint: 4099 3F1D AE01 1817 68F7 D499 A6C2 C418 86C8 610E
http://soulinfo.com/~hugang/HuGang.asc
ICQ# : 205800361
Registered Linux User : 204016
On Maw, 2003-06-03 at 15:35, hugang wrote:
> > The only way to make the suspend work properly is to queue the suspend
> > sequence wit the other requests. Ben was doing some playing with this
> > but I'm not sure what happened to it.
> >
> Yes the above patch is not safe, When i'm run updatedb and suspsned, After resume will oops at kjournal.
>
> Here is another test on it, it can works with updatedb.
Still races. Ben's stuff is needed
On Tue, 2003-06-03 at 16:08, Alan Cox wrote:
> On Maw, 2003-06-03 at 15:35, hugang wrote:
> > > The only way to make the suspend work properly is to queue the suspend
> > > sequence wit the other requests. Ben was doing some playing with this
> > > but I'm not sure what happened to it.
> > >
> > Yes the above patch is not safe, When i'm run updatedb and suspsned, After resume will oops at kjournal.
> >
> > Here is another test on it, it can works with updatedb.
>
> Still races. Ben's stuff is needed
I have it working with some fixes from what I sent earlier, I'll
repost that tonight or tomorrow, I need to extract that from
a half-broken tree ;)
Ben.
Hi!
> > > Hi Pavel Machek:
> > >
> > > I try the 2.5.70-mm3 with software suspend function. When suspend it will oops at ide-disk.c 1526 line
> > > BUG_ON (HWGROUP(drive)->handler);
> > >
> > > I'm disable this check, The software suspend can work, and also can resumed. But this fix is not best way. I found in ide-io.c 1196
> > > hwgroup->handler = NULL;
> > > is the problem.
> >
> > The only way to make the suspend work properly is to queue the suspend
> > sequence wit the other requests. Ben was doing some playing with this
> > but I'm not sure what happened to it.
> >
> Yes the above patch is not safe, When i'm run updatedb and suspsned, After resume will oops at kjournal.
>
> Here is another test on it, it can works with updatedb.
> -
> I found a best way to fix it. here is it. With the patch, I'm run updatedb and suspend for 5 counts, every things is ok.
>
Locating Ben's patch and forward-porting
it would be way better...
--
Pavel
Written on sharp zaurus, because my Velo1 broke. If you have Velo you don't need...
On Tue, 2003-06-03 at 19:04, Benjamin Herrenschmidt wrote:
> On Tue, 2003-06-03 at 16:08, Alan Cox wrote:
> > Still races. Ben's stuff is needed
>
> I have it working with some fixes from what I sent earlier, I'll
> repost that tonight or tomorrow, I need to extract that from
> a half-broken tree ;)
Ok, here is it. It still need a bit of cleanup (removal of magic
number for "steps" -> enum, etc...) and we may want to do more
things on wakeup especially for ide-cd, Also I don't deal with
ide-tape or ide-floppy in there and haven't fully studied the
impact with ide-scsi....
So it's not meant to be merged as-is, though I'd appreciate to
know if it helps for you.
Bartolomiej: Any comments appreciated, I won't do the ide-tape/floppy
part as I don't know/own these, I think i'll let you decide if
anything more is needed on the wakeup path for ide-cd... Once I
have enough feedback, I'll send you a cleanified version as
candidate for upstream merge.
===== drivers/ide/ide-cd.c 1.49 vs edited =====
--- 1.49/drivers/ide/ide-cd.c Sun Jun 1 21:55:45 2003
+++ edited/drivers/ide/ide-cd.c Wed Jun 4 14:53:38 2003
@@ -3253,6 +3253,46 @@
static int ide_cdrom_attach (ide_drive_t *drive);
+static void ide_cdrom_complete_power_step (ide_drive_t *drive, ide_power_state_t *state, u8 stat, u8 error)
+{
+}
+
+/* Power Management state machine.
+ *
+ * We don't do much for CDs right now
+ */
+static ide_startstop_t ide_cdrom_start_power_step (ide_drive_t *drive, ide_power_state_t *state)
+{
+ ide_task_t args;
+
+ memset(&args, 0, sizeof(ide_task_t));
+
+ if (state->step == 0) {
+ state->step = state->suspend ? 1 : 101;
+ return ide_stopped;
+ }
+ switch(state->step) {
+ case 1:
+ break;
+
+ case 101: /* 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;
+ }
+ state->step = ide_power_state_completed;
+ return ide_stopped;
+}
+
static ide_driver_t ide_cdrom_driver = {
.owner = THIS_MODULE,
.name = "ide-cdrom",
@@ -3269,6 +3309,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 =====
--- 1.45/drivers/ide/ide-disk.c Sun Jun 1 21:55:48 2003
+++ edited/drivers/ide/ide-disk.c Wed Jun 4 14:54:24 2003
@@ -138,8 +138,6 @@
#ifndef CONFIG_IDE_TASKFILE_IO
-static int driver_blocked;
-
/*
* read_intr() is the handler for disk read/multread interrupts
*/
@@ -364,9 +362,6 @@
nsectors.all = (u16) rq->nr_sectors;
- if (driver_blocked)
- panic("Request while ide driver is blocked?");
-
if (drive->using_tcq && idedisk_start_tag(drive, rq)) {
if (!ata_pending_commands(drive))
BUG();
@@ -1392,21 +1387,6 @@
return 0;
}
-static int call_idedisk_standby (ide_drive_t *drive, int arg)
-{
- ide_task_t args;
- u8 standby = (arg) ? WIN_STANDBYNOW2 : WIN_STANDBYNOW1;
- memset(&args, 0, sizeof(ide_task_t));
- args.tfRegister[IDE_COMMAND_OFFSET] = standby;
- args.command_type = ide_cmd_type_parser(&args);
- return ide_raw_taskfile(drive, &args, NULL);
-}
-
-static int do_idedisk_standby (ide_drive_t *drive)
-{
- return call_idedisk_standby(drive, 0);
-}
-
static int do_idedisk_flushcache (ide_drive_t *drive)
{
ide_task_t args;
@@ -1505,37 +1485,66 @@
#endif
}
-static int idedisk_suspend(struct device *dev, u32 state, u32 level)
-{
- ide_drive_t *drive = dev->driver_data;
-
- printk("Suspending device %p\n", dev->driver_data);
-
- /* I hope that every freeze operation from the upper levels have
- * already been done...
- */
-
- if (level != SUSPEND_SAVE_STATE)
- return 0;
-
- /* set the drive to standby */
- printk(KERN_INFO "suspending: %s ", drive->name);
- do_idedisk_standby(drive);
- drive->blocked = 1;
- BUG_ON (HWGROUP(drive)->handler);
- return 0;
+static void idedisk_complete_power_step (ide_drive_t *drive, ide_power_state_t *state, u8 stat, u8 error)
+{
+ switch(state->step) {
+ case 1: /* Suspend step 1 (flush cache) complete */
+ state->step = 2;
+ break;
+ case 2: /* Suspend step 2 (standby) complete */
+ state->step = ide_power_state_completed;
+ break;
+ }
}
-static int idedisk_resume(struct device *dev, u32 level)
+/* Power Management state machine. This one is rather trivial for now,
+ * we should probably add more, like switching back to PIO on suspend
+ * to help some BIOSes, re-do the door locking on resume, etc...
+ */
+static ide_startstop_t idedisk_start_power_step (ide_drive_t *drive, ide_power_state_t *state)
{
- ide_drive_t *drive = dev->driver_data;
+ ide_task_t args;
- if (level != RESUME_RESTORE_STATE)
- return 0;
- BUG_ON(!drive->blocked);
- drive->blocked = 0;
- return 0;
+ memset(&args, 0, sizeof(ide_task_t));
+
+ if (state->step == 0) {
+ state->step = state->suspend ? 1 : 101;
+ return ide_stopped;
+ }
+ switch(state->step) {
+ case 1: /* Suspend step 1 (flush cache) */
+ if (!drive->wcache) {
+ idedisk_complete_power_step(drive, state, 0, 0);
+ return ide_stopped;
+ }
+ if (drive->id->cfs_enable_2 & 0x2400)
+ args.tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE_EXT;
+ else
+ args.tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE;
+ args.command_type = ide_cmd_type_parser(&args);
+ return do_rw_taskfile(drive, &args);
+ case 2: /* Suspend step 2 (standby) */
+ args.tfRegister[IDE_COMMAND_OFFSET] = WIN_STANDBYNOW1;
+ args.command_type = ide_cmd_type_parser(&args);
+ return do_rw_taskfile(drive, &args);
+
+ case 101: /* 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;
+ }
+ state->step = ide_power_state_completed;
+ return ide_stopped;
}
static void idedisk_setup (ide_drive_t *drive)
@@ -1681,9 +1690,11 @@
.proc = idedisk_proc,
.attach = idedisk_attach,
.drives = LIST_HEAD_INIT(idedisk_driver.drives),
+ .start_power_step = idedisk_start_power_step,
+ .complete_power_step = idedisk_complete_power_step,
.gen_driver = {
- .suspend = idedisk_suspend,
- .resume = idedisk_resume,
+ .suspend = generic_ide_suspend,
+ .resume = generic_ide_resume,
}
};
===== drivers/ide/ide-io.c 1.11 vs edited =====
--- 1.11/drivers/ide/ide-io.c Mon May 12 02:09:46 2003
+++ edited/drivers/ide/ide-io.c Wed Jun 4 14:55:06 2003
@@ -139,6 +139,39 @@
EXPORT_SYMBOL(ide_end_request);
/**
+ * ide_complete_pm_request - end the current Power Management request
+ * @drive: target drive
+ * @rq: request
+ *
+ * This function cleans up the current PM request and stops the queue
+ * if necessary.
+ */
+
+static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq)
+{
+ ide_power_state_t *state = (ide_power_state_t *)rq->special;
+ unsigned long flags;
+ int suspend = state->suspend;
+
+#ifdef DEBUG_PM
+ printk("%s: completing PM request, suspend: %d\n", drive->name, state->suspend);
+#endif
+ spin_lock_irqsave(&ide_lock, flags);
+ if (suspend)
+ __blk_stop_queue(&drive->queue);
+ else
+ drive->blocked = 0;
+ blkdev_dequeue_request(rq);
+ HWGROUP(drive)->rq = NULL;
+ end_that_request_last(rq);
+ spin_unlock_irqrestore(&ide_lock, flags);
+ /* Hrm... there is no __blk_start_queue... */
+ if (!suspend)
+ blk_start_queue(&drive->queue);
+}
+
+
+/**
* ide_end_drive_cmd - end an explicit drive command
* @drive: command
* @stat: status bits
@@ -214,6 +247,17 @@
args->hobRegister[IDE_HCYL_OFFSET_HOB] = hwif->INB(IDE_HCYL_REG);
}
}
+ } else if (rq->flags & REQ_POWER_MANAGEMENT) {
+ ide_power_state_t *state = (ide_power_state_t *)rq->special;
+
+#ifdef DEBUG_PM
+ printk("%s: complete_power_step(susp: %d, step: %d, stat: %x, err: %x)\n",
+ drive->name, state->suspend, state->step, stat, err);
+#endif
+ DRIVER(drive)->complete_power_step(drive, state, stat, err);
+ if (state->step == ide_power_state_completed)
+ ide_complete_pm_request(drive, rq);
+ return;
}
spin_lock_irqsave(&ide_lock, flags);
@@ -615,7 +659,37 @@
while ((read_timer() - HWIF(drive)->last_time) < DISK_RECOVERY_TIME);
#endif
- SELECT_DRIVE(drive);
+ if (rq->flags & REQ_POWER_MANAGEMENT) {
+ ide_power_state_t *state = (ide_power_state_t *)rq->special;
+ int rc;
+
+ /* Mark drive blocked when starting the suspend sequence */
+ if (state->suspend && state->step == 0)
+ drive->blocked = 1;
+ /* If this is a power management wakeup request, the first thing
+ * we do is to wait for BSY bit to go away (with a looong timeout)
+ * as a drive on this hwif may just be POSTing itself. We do that
+ * before even selecting as the "other" device on the bus may be
+ * broken enough to walk on our toes at this point.
+ */
+ if (state->suspend != 0 || state->step != 0)
+ goto dont_wait;
+#ifdef DEBUG_PM
+ printk("%s: Wakeup request inited, waiting for !BSY...\n", drive->name);
+#endif
+ rc = ide_wait_not_busy(HWIF(drive), 35000);
+ if (rc)
+ printk(KERN_WARNING "%s: bus not ready on wakeup\n", drive->name);
+ SELECT_DRIVE(drive);
+ HWIF(drive)->OUTB(8, HWIF(drive)->io_ports[IDE_CONTROL_OFFSET]);
+ rc = ide_wait_not_busy(HWIF(drive), 10000);
+ if (rc)
+ printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name);
+ } else {
+dont_wait:
+ SELECT_DRIVE(drive);
+ }
+
if (ide_wait_stat(&startstop, drive, drive->ready_stat, BUSY_STAT|DRQ_STAT, WAIT_READY)) {
printk(KERN_ERR "%s: drive not ready for command\n", drive->name);
return startstop;
@@ -625,6 +699,19 @@
return execute_drive_cmd(drive, rq);
else if (rq->flags & REQ_DRIVE_TASKFILE)
return execute_drive_cmd(drive, rq);
+ else if (rq->flags & REQ_POWER_MANAGEMENT) {
+ ide_power_state_t *state = (ide_power_state_t *)rq->special;
+
+#ifdef DEBUG_PM
+ printk("%s: start_power_step(susp: %d, step: %d)\n", drive->name, state->suspend, state->step);
+#endif
+ startstop = DRIVER(drive)->start_power_step(drive, state);
+ if (startstop == ide_stopped && state->step == ide_power_state_completed) {
+ ide_complete_pm_request(drive, rq);
+ return ide_stopped;
+ } else
+ return startstop;
+ }
return (DRIVER(drive)->do_request(drive, rq, block));
}
return do_special(drive);
@@ -837,6 +924,22 @@
break;
}
+ /* Sanity: don't accept a request that isn't a PM request
+ * if we are currently power managed. This is very important as
+ * blk_stop_queue() doesn't prevent the elv_next_request() above
+ * to return us whatever is in the queue. Since we call ide_do_request()
+ * ourselves, we end up taking requests while the queue is blocked...
+ */
+ if (drive->blocked && !(rq->flags & REQ_POWER_MANAGEMENT)) {
+#ifdef DEBUG_PM
+ printk("%s: a request made it's way while we are power managing...\n", drive->name);
+#endif
+ /* We clear busy, there should be no pending ATA command at this point
+ */
+ hwgroup->busy = 0;
+ break;
+ }
+
if (!rq->bio && ata_pending_commands(drive))
break;
@@ -1282,12 +1385,16 @@
ide_hwgroup_t *hwgroup = HWGROUP(drive);
DECLARE_COMPLETION(wait);
int insert_end = 1, err;
-
+ int must_wait = (action == ide_wait || action == ide_head_wait);
+
#ifdef CONFIG_BLK_DEV_PDC4030
/*
* FIXME: there should be a drive or hwif->special
* handler that points here by default, not hacks
* in the ide-io.c code
+ *
+ * FIXME2: That code breaks power management if used with
+ * this chipset, that really doesn't belong here !
*/
if (HWIF(drive)->chipset == ide_pdc4030 && rq->buffer != NULL)
return -ENOSYS; /* special drive cmds not supported */
@@ -1301,13 +1408,13 @@
* we need to hold an extra reference to request for safe inspection
* after completion
*/
- if (action == ide_wait) {
+ if (must_wait) {
rq->ref_count++;
rq->waiting = &wait;
}
spin_lock_irqsave(&ide_lock, flags);
- if (action == ide_preempt) {
+ if (action == ide_preempt || action == ide_head_wait) {
hwgroup->rq = NULL;
insert_end = 0;
}
@@ -1316,7 +1423,7 @@
spin_unlock_irqrestore(&ide_lock, flags);
err = 0;
- if (action == ide_wait) {
+ if (must_wait) {
wait_for_completion(&wait);
if (rq->errors)
err = -EIO;
===== drivers/ide/ide-iops.c 1.17 vs edited =====
--- 1.17/drivers/ide/ide-iops.c Tue Mar 25 12:56:05 2003
+++ edited/drivers/ide/ide-iops.c Wed Jun 4 14:55:13 2003
@@ -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 =====
--- 1.49/drivers/ide/ide-probe.c Tue May 27 02:48:43 2003
+++ edited/drivers/ide/ide-probe.c Wed Jun 4 14:56:08 2003
@@ -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 =====
--- 1.70/drivers/ide/ide.c Sun Jun 1 21:50:38 2003
+++ edited/drivers/ide/ide.c Wed Jun 4 14:56:33 2003
@@ -1441,6 +1441,52 @@
EXPORT_SYMBOL(ata_attach);
+int generic_ide_suspend(struct device *dev, u32 state, u32 level)
+{
+ ide_drive_t *drive = dev->driver_data;
+ struct request rq;
+ ide_power_state_t args;
+
+ if (level == dev->power_state || level != SUSPEND_SAVE_STATE)
+ return 0;
+
+ /* The suspend request is a state machine of taskfile requests */
+ memset(&rq, 0, sizeof(rq));
+ memset(&args, 0, sizeof(args));
+ rq.flags = REQ_POWER_MANAGEMENT;
+ rq.special = &args;
+ args.step = 0;
+ args.suspend = 1;
+
+ /* Start it */
+ return ide_do_drive_cmd(drive, &rq, ide_wait);
+}
+
+EXPORT_SYMBOL(generic_ide_suspend);
+
+int generic_ide_resume(struct device *dev, u32 level)
+{
+ ide_drive_t *drive = dev->driver_data;
+ struct request rq;
+ ide_power_state_t args;
+
+ if (level == dev->power_state || level != RESUME_RESTORE_STATE)
+ return 0;
+
+ /* The suspend request is a state machine of taskfile requests */
+ memset(&rq, 0, sizeof(rq));
+ memset(&args, 0, sizeof(args));
+ rq.flags = REQ_POWER_MANAGEMENT;
+ rq.special = &args;
+ args.step = 0;
+ args.suspend = 0;
+
+ /* Start it */
+ return ide_do_drive_cmd(drive, &rq, ide_head_wait);
+}
+
+EXPORT_SYMBOL(generic_ide_resume);
+
int generic_ide_ioctl(struct block_device *bdev, unsigned int cmd,
unsigned long arg)
{
===== include/linux/blkdev.h 1.106 vs edited =====
--- 1.106/include/linux/blkdev.h Tue May 27 22:15:31 2003
+++ edited/include/linux/blkdev.h Wed Jun 4 14:58:00 2003
@@ -130,6 +130,7 @@
__REQ_DRIVE_CMD,
__REQ_DRIVE_TASK,
__REQ_DRIVE_TASKFILE,
+ __REQ_POWER_MANAGEMENT,
__REQ_NR_BITS, /* stops here */
};
@@ -151,6 +152,7 @@
#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_POWER_MANAGEMENT (1 << __REQ_POWER_MANAGEMENT)
#include <linux/elevator.h>
===== include/linux/ide.h 1.54 vs edited =====
--- 1.54/include/linux/ide.h Thu May 29 21:04:47 2003
+++ edited/include/linux/ide.h Wed Jun 4 14:57:33 2003
@@ -23,6 +23,8 @@
#include <asm/hdreg.h>
#include <asm/io.h>
+#define DEBUG_PM
+
/*
* This is the multiple IDE interface driver, as evolved from hd.c.
* It supports up to four IDE interfaces, on one or more IRQs (usually 14 & 15).
@@ -1144,6 +1146,39 @@
#endif
/*
+ * Power Management related definitions
+ */
+typedef struct ide_power_state_s
+{
+ int suspend; /* 1 = suspending, 0 = resuming */
+ int step; /* Step in PM state machine */
+ void* data; /* Any additional data the subdriver wants */
+} ide_power_state_t;
+
+#define ide_power_state_completed -1
+#define ide_power_state_first 0
+//#define ide_power_state_core_first 100
+//#define ide_power_state_core_last 199
+
+/* The step value starts at 0 (ide_power_state_first).
+ *
+ * For each step, the core calls the subdriver start_power_step()
+ * first. This can return
+ * - ide_stopped : In this case, the core calls us back again unless
+ * step have been set to ide_power_state_completed
+ * - ide_started : In this case, the channel is left busy until an
+ * async event (interrupt) occurs.
+ * Typically, start_power_step() will issue a taskfile request with
+ * do_rw_taskfile().
+ *
+ * Upon reception of the interrupt, the core will call complete_power_step()
+ * with the error code if any. This routine should update the step value
+ * and return. It should not start a new request. The core will call
+ * start_power_step for the new step value, unless step have been set to
+ * ide_power_state_completed.
+ */
+
+/*
* Subdrivers support.
*/
#define IDE_SUBDRIVER_VERSION 1
@@ -1172,6 +1207,8 @@
int (*attach)(ide_drive_t *);
void (*ata_prebuilder)(ide_drive_t *);
void (*atapi_prebuilder)(ide_drive_t *);
+ ide_startstop_t (*start_power_step)(ide_drive_t *, ide_power_state_t *state);
+ void (*complete_power_step)(ide_drive_t *, ide_power_state_t *state, u8 stat, u8 error);
struct device_driver gen_driver;
struct list_head drives;
struct list_head drivers;
@@ -1180,6 +1217,8 @@
#define DRIVER(drive) ((drive)->driver)
extern int generic_ide_ioctl(struct block_device *, unsigned, unsigned long);
+extern int generic_ide_suspend(struct device *dev, u32 state, u32 level);
+extern int generic_ide_resume(struct device *dev, u32 level);
/*
* IDE modules.
@@ -1321,6 +1360,7 @@
ide_wait, /* insert rq at end of list, and wait for it */
ide_next, /* insert rq immediately after current request */
ide_preempt, /* insert rq in front of current request */
+ ide_head_wait, /* insert rq in front of current request and wait for it */
ide_end /* insert rq at end of list, but don't wait for it */
} ide_action_t;
@@ -1531,6 +1571,7 @@
extern int set_transfer(ide_drive_t *, ide_task_t *);
extern int taskfile_lib_get_identify(ide_drive_t *drive, u8 *);
+extern int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout);
ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq, sector_t block);
/*
Patch 2.5.70-mm3 and compile with gcc295 OK
Bare multisuer with serial console,
no modules, network, usb, acpi .....
During suspend, after a while (some dots on the console)
got the output below in an endless loop
Is there any debug or progress output in this version
and how to use?
Regards
Michael
Call Trace:
[<c011d958>] schedule+0x40/0x388
[<c011eb02>] io_schedule+0xe/0x18
[<c01384d5>] wait_on_page_bit_wq+0xc9/0xe4
[<c011f320>] autoremove_wake_function+0x0/0x3c
[<c011f320>] autoremove_wake_function+0x0/0x3c
[<c01384fa>] wait_on_page_bit+0xa/0x10
[<c014cc34>] rw_swap_page_sync+0x98/0xc6
[<c0136afd>] write_suspend_image+0xf1/0x324
[<c0246bdf>] device_resume+0x7f/0x88
[<c01370e1>] drivers_unsuspend+0x11/0x18
[<c013735e>] suspend_save_image+0x12/0x1c
[<c013753f>] do_magic_suspend_2+0x17/0xa8
[<c011ba9d>] do_magic+0x4d/0x130
[<c013763b>] do_software_suspend+0x6b/0x90
[<c0137695>] software_suspend+0x35/0x3c
[<c012ba97>] sys_reboot+0x2df/0x36c
[<c0143830>] unmap_page_range+0x38/0x5c
[<c0143959>] unmap_vmas+0x105/0x208
[<c01656e4>] dput+0x1c/0x204
[<c01656e4>] dput+0x1c/0x204
[<c015d367>] path_release+0xf/0x30
[<c014fe69>] sys_chdir+0x5d/0x68
[<c010af17>] syscall_call+0x7/0xb
--
Powered by linux-2.5.70-mm3
My current linux related activities in rough order of priority:
- Testing of 2.4/2.5 kernel interactivity
- Testing of Swsusp for 2.4
- Testing of Opera 7.11 emphasizing interactivity
- Research of NFS i/o errors during transfer 2.4>2.5
- Learning 2.5 series kernel debugging with kgdb
- Studying 2.5 series serial and ide drivers, ACPI, S3
* Input and feedback is always welcome *
On Wed, 2003-06-04 at 15:51, Michael Frank wrote:
> Patch 2.5.70-mm3 and compile with gcc295 OK
>
> Bare multisuer with serial console,
> no modules, network, usb, acpi .....
>
> During suspend, after a while (some dots on the console)
> got the output below in an endless loop
>
> Is there any debug or progress output in this version
> and how to use?
I'm not sure how to interpret that call trace, was there any
other message just before ? There is some debug output in the
patch though it may have been lost at that point.
Ben.
> Regards
> Michael
>
> Call Trace:
> [<c011d958>] schedule+0x40/0x388
> [<c011eb02>] io_schedule+0xe/0x18
> [<c01384d5>] wait_on_page_bit_wq+0xc9/0xe4
> [<c011f320>] autoremove_wake_function+0x0/0x3c
> [<c011f320>] autoremove_wake_function+0x0/0x3c
> [<c01384fa>] wait_on_page_bit+0xa/0x10
> [<c014cc34>] rw_swap_page_sync+0x98/0xc6
> [<c0136afd>] write_suspend_image+0xf1/0x324
> [<c0246bdf>] device_resume+0x7f/0x88
> [<c01370e1>] drivers_unsuspend+0x11/0x18
> [<c013735e>] suspend_save_image+0x12/0x1c
> [<c013753f>] do_magic_suspend_2+0x17/0xa8
> [<c011ba9d>] do_magic+0x4d/0x130
> [<c013763b>] do_software_suspend+0x6b/0x90
> [<c0137695>] software_suspend+0x35/0x3c
> [<c012ba97>] sys_reboot+0x2df/0x36c
> [<c0143830>] unmap_page_range+0x38/0x5c
> [<c0143959>] unmap_vmas+0x105/0x208
> [<c01656e4>] dput+0x1c/0x204
> [<c01656e4>] dput+0x1c/0x204
> [<c015d367>] path_release+0xf/0x30
> [<c014fe69>] sys_chdir+0x5d/0x68
> [<c010af17>] syscall_call+0x7/0xb
--
Benjamin Herrenschmidt <[email protected]>
On Wednesday 04 June 2003 21:51, Michael Frank wrote:
Patch 2.5.70-mm3 and compile with gcc295 OK
Bare multisuer with serial console,
no modules, network, usb, acpi .....
Is there any debug or progress output in this version
and how to use?
Regards
Michael
OK, made the history longer
Last login: Wed Jun 4 21:59:38 on tty2
[mhf@mhfl1 22:05:24 mhf]$ Stopping tasks: klogd entered refrigerator
=init entered refrigerator
=pdflush entered refrigerator
=pdflush entered refrigerator
=kswapd0 entered refrigerator
=kseriod entered refrigerator
=kjournald entered refrigerator
=syslogd entered refrigerator
=open entered refrigerator
=open entered refrigerator
=open entered refrigerator
=open entered refrigerator
=open entered refrigerator
=login entered refrigerator
=login entered refrigerator
=login entered refrigerator
=login entered refrigerator
=login entered refrigerator
=login entered refrigerator
=bash entered refrigerator
=bash entered refrigerator
=bash entered refrigerator
=bash entered refrigerator
=bash entered refrigerator
=bash entered refrigerator
=open entered refrigerator
=comr entered refrigerator
=sleep entered refrigerator
=tst entered refrigerator
=tstr entered refrigerator
=|
Freeing memory: ..................|
Syncing disks before copy
Suspending devices
Suspending devices
hda: start_power_step(susp: 1, step: 0)
hda: start_power_step(susp: 1, step: 1)
hda: start_power_step(susp: 1, step: 2)
hda: complete_power_step(susp: 1, step: 2, stat: 50, err: 0)
hda: completing PM request, suspend: 1
Suspending devices
/critical section: Counting pages to copy[nosave c03f7000] (pages needed: 2273+512=2785 free: 14110)
Alloc pagedir
............
[nosave c03f7000]critical section/: done (2273 pages copied)
hda: Wakeup request inited, waiting for !BSY...
hda: start_power_step(susp: 0, step: 0)
hda: start_power_step(susp: 0, step: 101)
hda: completing PM request, suspend: 0
Devices Resumed
Devices Resumed
Writing data to swap (2273 pages): .<3>bad: scheduling while atomic!
Call Trace:
[<c011d958>] schedule+0x40/0x388
[<c011eb02>] io_schedule+0xe/0x18
[<c01384d5>] wait_on_page_bit_wq+0xc9/0xe4
[<c011f320>] autoremove_wake_function+0x0/0x3c
[<c011f320>] autoremove_wake_function+0x0/0x3c
[<c01384fa>] wait_on_page_bit+0xa/0x10
[<c014cc34>] rw_swap_page_sync+0x98/0xc6
[<c0136afd>] write_suspend_image+0xf1/0x324
[<c0246bdf>] device_resume+0x7f/0x88
[<c01370e1>] drivers_unsuspend+0x11/0x18
[<c013735e>] suspend_save_image+0x12/0x1c
[<c013753f>] do_magic_suspend_2+0x17/0xa8
[<c011ba9d>] do_magic+0x4d/0x130
[<c013763b>] do_software_suspend+0x6b/0x90
[<c0137695>] software_suspend+0x35/0x3c
[<c012ba97>] sys_reboot+0x2df/0x36c
[<c0143830>] unmap_page_range+0x38/0x5c
[<c0143959>] unmap_vmas+0x105/0x208
[<c01656e4>] dput+0x1c/0x204
[<c01656e4>] dput+0x1c/0x204
[<c015d367>] path_release+0xf/0x30
[<c014fe69>] sys_chdir+0x5d/0x68
[<c010af17>] syscall_call+0x7/0xb
bad: scheduling while atomic!
Call Trace:
[<c011d958>] schedule+0x40/0x388
[<c011eb02>] io_schedule+0xe/0x18
[<c01384d5>] wait_on_page_bit_wq+0xc9/0xe4
[<c011f320>] autoremove_wake_function+0x0/0x3c
[<c011f320>] autoremove_wake_function+0x0/0x3c
[<c01384fa>] wait_on_page_bit+0xa/0x10
[<c014cc34>] rw_swap_page_sync+0x98/0xc6
[<c0136afd>] write_suspend_image+0xf1/0x324
[<c0246bdf>] device_resume+0x7f/0x88
[<c01370e1>] drivers_unsuspend+0x11/0x18
[<c013735e>] suspend_save_image+0x12/0x1c
[<c013753f>] do_magic_suspend_2+0x17/0xa8
[<c011ba9d>] do_magic+0x4d/0x130
[<c013763b>] do_software_suspend+0x6b/0x90
[<c0137695>] software_suspend+0x35/0x3c
[<c012ba97>] sys_reboot+0x2df/0x36c
[<c0143830>] unmap_page_range+0x38/0x5c
[<c0143959>] unmap_vmas+0x105/0x208
[<c01656e4>] dput+0x1c/0x204
[<c01656e4>] dput+0x1c/0x204
[<c015d367>] path_release+0xf/0x30
[<c014fe69>] sys_chdir+0x5d/0x68
[<c010af17>] syscall_call+0x7/0xb
--
Powered by linux-2.5.70-mm3
My current linux related activities in rough order of priority:
- Testing of 2.4/2.5 kernel interactivity
- Testing of Swsusp for 2.4
- Testing of Opera 7.11 emphasizing interactivity
- Research of NFS i/o errors during transfer 2.4>2.5
- Learning 2.5 series kernel debugging with kgdb
- Studying 2.5 series serial and ide drivers, ACPI, S3
* Input and feedback is always welcome *
> hda: start_power_step(susp: 1, step: 0)
> hda: start_power_step(susp: 1, step: 1)
> hda: start_power_step(susp: 1, step: 2)
> hda: complete_power_step(susp: 1, step: 2, stat: 50, err: 0)
> hda: completing PM request, suspend: 1
> Suspending devices
> /critical section: Counting pages to copy[nosave c03f7000] (pages needed: 2273+512=2785 free: 14110)
> Alloc pagedir
> ............
> [nosave c03f7000]critical section/: done (2273 pages copied)
> hda: Wakeup request inited, waiting for !BSY...
> hda: start_power_step(susp: 0, step: 0)
> hda: start_power_step(susp: 0, step: 101)
> hda: completing PM request, suspend: 0
> Devices Resumed
> Devices Resumed
Hrm... the joy if swsusp putting your disk to sleep just to wake it up
right away... I need to check if I can differenciate suspend-to-disk
from suspend-to-ram here to just not put the drive in STANDBY mode
on suspend-to-disk (just freeze the queues)
> Writing data to swap (2273 pages): .<3>bad: scheduling while atomic!
Here's the real one. However, it doesn't look related to my sleep code,
though I cannot guarantee this for sure right now, it _seems_ it's
a swsusp bug you are hitting.
> Call Trace:
> [<c011d958>] schedule+0x40/0x388
> [<c011eb02>] io_schedule+0xe/0x18
> [<c01384d5>] wait_on_page_bit_wq+0xc9/0xe4
> [<c011f320>] autoremove_wake_function+0x0/0x3c
> [<c011f320>] autoremove_wake_function+0x0/0x3c
> [<c01384fa>] wait_on_page_bit+0xa/0x10
> [<c014cc34>] rw_swap_page_sync+0x98/0xc6
> [<c0136afd>] write_suspend_image+0xf1/0x324
> [<c0246bdf>] device_resume+0x7f/0x88
> [<c01370e1>] drivers_unsuspend+0x11/0x18
> [<c013735e>] suspend_save_image+0x12/0x1c
> [<c013753f>] do_magic_suspend_2+0x17/0xa8
> [<c011ba9d>] do_magic+0x4d/0x130
> [<c013763b>] do_software_suspend+0x6b/0x90
> [<c0137695>] software_suspend+0x35/0x3c
> [<c012ba97>] sys_reboot+0x2df/0x36c
> [<c0143830>] unmap_page_range+0x38/0x5c
> [<c0143959>] unmap_vmas+0x105/0x208
> [<c01656e4>] dput+0x1c/0x204
> [<c01656e4>] dput+0x1c/0x204
> [<c015d367>] path_release+0xf/0x30
> [<c014fe69>] sys_chdir+0x5d/0x68
> [<c010af17>] syscall_call+0x7/0xb
On Wednesday 04 June 2003 22:29, Benjamin Herrenschmidt wrote:
> > hda: start_power_step(susp: 1, step: 0)
> > hda: start_power_step(susp: 1, step: 1)
> > hda: start_power_step(susp: 1, step: 2)
> > hda: complete_power_step(susp: 1, step: 2, stat: 50, err: 0)
> > hda: completing PM request, suspend: 1
> > Suspending devices
> > /critical section: Counting pages to copy[nosave c03f7000] (pages needed:
> > 2273+512=2785 free: 14110) Alloc pagedir
> > ............
> > [nosave c03f7000]critical section/: done (2273 pages copied)
> > hda: Wakeup request inited, waiting for !BSY...
> > hda: start_power_step(susp: 0, step: 0)
> > hda: start_power_step(susp: 0, step: 101)
> > hda: completing PM request, suspend: 0
> > Devices Resumed
> > Devices Resumed
>
> Hrm... the joy if swsusp putting your disk to sleep just to wake it up
> right away... I need to check if I can differenciate suspend-to-disk
> from suspend-to-ram here to just not put the drive in STANDBY mode
> on suspend-to-disk (just freeze the queues)
It did this also in 2.4 until Nigel Cunningham fixed it.
>
> > Writing data to swap (2273 pages): .<3>bad: scheduling while atomic!
>
> Here's the real one. However, it doesn't look related to my sleep code,
> though I cannot guarantee this for sure right now, it _seems_ it's
> a swsusp bug you are hitting.
Well, awaiting the next patch...
Regards
Michael
--
Powered by linux-2.5.70-mm3
My current linux related activities in rough order of priority:
- Testing of 2.4/2.5 kernel interactivity
- Testing of Swsusp for 2.4
- Testing of Opera 7.11 emphasizing interactivity
- Research of NFS i/o errors during transfer 2.4>2.5
- Learning 2.5 series kernel debugging with kgdb - it's in the -mm tree
- Studying 2.5 series serial and ide drivers, ACPI, S3
* Input and feedback is always welcome *
Joke of the day: http://lwn.net/Articles/34848/
Hi!
> > ............
> > [nosave c03f7000]critical section/: done (2273 pages copied)
> > hda: Wakeup request inited, waiting for !BSY...
> > hda: start_power_step(susp: 0, step: 0)
> > hda: start_power_step(susp: 0, step: 101)
> > hda: completing PM request, suspend: 0
> > Devices Resumed
> > Devices Resumed
>
> Hrm... the joy if swsusp putting your disk to sleep just to wake it up
> right away... I need to check if I can differenciate suspend-to-disk
> from suspend-to-ram here to just not put the drive in STANDBY mode
> on suspend-to-disk (just freeze the queues)
Why? Suspending then resuming it may take long but seems correct to
me.
> > Writing data to swap (2273 pages): .<3>bad: scheduling while atomic!
>
> Here's the real one. However, it doesn't look related to my sleep code,
> though I cannot guarantee this for sure right now, it _seems_ it's
> a swsusp bug you are hitting.
Yes, it looks so.
Pavel
--
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]
Hi!
> > > Still races. Ben's stuff is needed
> >
> > I have it working with some fixes from what I sent earlier, I'll
> > repost that tonight or tomorrow, I need to extract that from
> > a half-broken tree ;)
>
> Ok, here is it. It still need a bit of cleanup (removal of magic
> number for "steps" -> enum, etc...) and we may want to do more
> things on wakeup especially for ide-cd, Also I don't deal with
> ide-tape or ide-floppy in there and haven't fully studied the
> impact with ide-scsi....
>
> So it's not meant to be merged as-is, though I'd appreciate to
> know if it helps for you.
>
> Bartolomiej: Any comments appreciated, I won't do the ide-tape/floppy
> part as I don't know/own these, I think i'll let you decide if
> anything more is needed on the wakeup path for ide-cd... Once I
> have enough feedback, I'll send you a cleanified version as
> candidate for upstream merge.
Please send cleaned up version ASAP... Waiting will do no good. If it
handles only ide-disks, that's okay, its still way better than whats
in the tree.
Pavel
--
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]
On Tue, 3 Jun 2003 20:55:51 +0200
Pavel Machek <[email protected]> wrote:
> Locating Ben's patch and forward-porting
> it would be way better...
I was tried Ben's patch, It's cool, Very stable in my laptop.
Here is two patch.
* suspend.c can swap more pages into swap space.
* vmscan.c can make swap faster.
--- linux-2.5.70/kernel/suspend.c.old Sun Jun 8 11:09:41 2003
+++ linux-2.5.70/kernel/suspend.c Sun Jun 8 10:54:55 2003
@@ -621,9 +621,17 @@
*/
static void free_some_memory(void)
{
+ unsigned int count = 10;
+
printk("Freeing memory: ");
- while (shrink_all_memory(10000))
+ while (count) {
+ unsigned int ret = shrink_all_memory(4 * 1024 * 1024 / PAGE_SIZE);
+ if (ret == 0) {
+ count--;
+ continue;
+ }
printk(".");
+ }
printk("|\n");
}
--- linux-2.5.70/mm/vmscan.c.old Sun Jun 8 11:08:27 2003
+++ linux-2.5.70/mm/vmscan.c Sun Jun 8 11:02:27 2003
@@ -882,7 +882,8 @@
* dead and from now on, only perform a short scan. Basically we're polling
* the zone for when the problem goes away.
*/
-static int balance_pgdat(pg_data_t *pgdat, int nr_pages, struct page_state *ps)
+static int balance_pgdat(pg_data_t *pgdat, int nr_pages,
+ struct page_state *ps, unsigned int time)
{
int to_free = nr_pages;
int priority;
@@ -930,7 +931,7 @@
}
if (all_zones_ok)
break;
- blk_congestion_wait(WRITE, HZ/10);
+ blk_congestion_wait(WRITE, HZ/time);
}
return nr_pages - to_free;
}
@@ -984,7 +985,7 @@
schedule();
finish_wait(&pgdat->kswapd_wait, &wait);
get_page_state(&ps);
- balance_pgdat(pgdat, 0, &ps);
+ balance_pgdat(pgdat, 0, &ps, 10);
}
}
@@ -1020,7 +1021,7 @@
struct page_state ps;
get_page_state(&ps);
- freed = balance_pgdat(pgdat, nr_to_free, &ps);
+ freed = balance_pgdat(pgdat, nr_to_free, &ps, 200);
ret += freed;
nr_to_free -= freed;
if (nr_to_free <= 0)
--
Hu Gang / Steve
Email : [email protected], [email protected]
GPG FinePrint: 4099 3F1D AE01 1817 68F7 D499 A6C2 C418 86C8 610E
http://soulinfo.com/~hugang/HuGang.asc
ICQ# : 205800361
Registered Linux User : 204016
On Tue, 3 Jun 2003 20:55:51 +0200
Pavel Machek <[email protected]> wrote:
> Locating Ben's patch and forward-porting
> it would be way better...
I was tried Ben's patch, It's cool, Very stable in my laptop.
Here is two patch.
* suspend.c can swap more pages into swap space.
* vmscan.c can make swap out faster.
--- linux-2.5.70/kernel/suspend.c.old Sun Jun 8 11:09:41 2003
+++ linux-2.5.70/kernel/suspend.c Sun Jun 8 10:54:55 2003
@@ -621,9 +621,17 @@
*/
static void free_some_memory(void)
{
+ unsigned int count = 10;
+
printk("Freeing memory: ");
- while (shrink_all_memory(10000))
+ while (count) {
+ unsigned int ret = shrink_all_memory(4 * 1024 * 1024 / PAGE_SIZE);
+ if (ret == 0) {
+ count--;
+ continue;
+ }
printk(".");
+ }
printk("|\n");
}
--- linux-2.5.70/mm/vmscan.c.old Sun Jun 8 11:08:27 2003
+++ linux-2.5.70/mm/vmscan.c Sun Jun 8 11:02:27 2003
@@ -882,7 +882,8 @@
* dead and from now on, only perform a short scan. Basically we're polling
* the zone for when the problem goes away.
*/
-static int balance_pgdat(pg_data_t *pgdat, int nr_pages, struct page_state *ps)
+static int balance_pgdat(pg_data_t *pgdat, int nr_pages,
+ struct page_state *ps, unsigned int time)
{
int to_free = nr_pages;
int priority;
@@ -930,7 +931,7 @@
}
if (all_zones_ok)
break;
- blk_congestion_wait(WRITE, HZ/10);
+ blk_congestion_wait(WRITE, HZ/time);
}
return nr_pages - to_free;
}
@@ -984,7 +985,7 @@
schedule();
finish_wait(&pgdat->kswapd_wait, &wait);
get_page_state(&ps);
- balance_pgdat(pgdat, 0, &ps);
+ balance_pgdat(pgdat, 0, &ps, 10);
}
}
@@ -1020,7 +1021,7 @@
struct page_state ps;
get_page_state(&ps);
- freed = balance_pgdat(pgdat, nr_to_free, &ps);
+ freed = balance_pgdat(pgdat, nr_to_free, &ps, 200);
ret += freed;
nr_to_free -= freed;
if (nr_to_free <= 0)
--
Hu Gang / Steve
Email : [email protected], [email protected]
GPG FinePrint: 4099 3F1D AE01 1817 68F7 D499 A6C2 C418 86C8 610E
http://soulinfo.com/~hugang/HuGang.asc
ICQ# : 205800361
Registered Linux User : 204016
Hi!
> > Locating Ben's patch and forward-porting
> > it would be way better...
>
> I was tried Ben's patch, It's cool, Very stable in my laptop.
>
> Here is two patch.
> * suspend.c can swap more pages into swap space.
> * vmscan.c can make swap faster.
>
> --- linux-2.5.70/kernel/suspend.c.old Sun Jun 8 11:09:41 2003
> +++ linux-2.5.70/kernel/suspend.c Sun Jun 8 10:54:55 2003
> @@ -621,9 +621,17 @@
> */
> static void free_some_memory(void)
> {
> + unsigned int count = 10;
> +
> printk("Freeing memory: ");
> - while (shrink_all_memory(10000))
> + while (count) {
> + unsigned int ret = shrink_all_memory(4 * 1024 * 1024 / PAGE_SIZE);
> + if (ret == 0) {
> + count--;
> + continue;
> + }
> printk(".");
> + }
> printk("|\n");
> }
If this does something then... well... shrink_all_memory needs to be
fixed.
> --- linux-2.5.70/mm/vmscan.c.old Sun Jun 8 11:08:27 2003
> +++ linux-2.5.70/mm/vmscan.c Sun Jun 8 11:02:27 2003
> @@ -882,7 +882,8 @@
> * dead and from now on, only perform a short scan. Basically we're polling
> * the zone for when the problem goes away.
> */
> -static int balance_pgdat(pg_data_t *pgdat, int nr_pages, struct page_state *ps)
> +static int balance_pgdat(pg_data_t *pgdat, int nr_pages,
> + struct page_state *ps, unsigned int time)
> {
> int to_free = nr_pages;
> int priority;
> @@ -930,7 +931,7 @@
> }
> if (all_zones_ok)
> break;
> - blk_congestion_wait(WRITE, HZ/10);
> + blk_congestion_wait(WRITE, HZ/time);
> }
> return nr_pages - to_free;
> }
> @@ -984,7 +985,7 @@
> schedule();
> finish_wait(&pgdat->kswapd_wait, &wait);
> get_page_state(&ps);
> - balance_pgdat(pgdat, 0, &ps);
> + balance_pgdat(pgdat, 0, &ps, 10);
> }
> }
>
> @@ -1020,7 +1021,7 @@
> struct page_state ps;
>
> get_page_state(&ps);
> - freed = balance_pgdat(pgdat, nr_to_free, &ps);
> + freed = balance_pgdat(pgdat, nr_to_free, &ps, 200);
> ret += freed;
> nr_to_free -= freed;
> if (nr_to_free <= 0)
Comment in balance_pgdat saying what the time means would be
nice... And calling it time is pretty misleading: its frequency.
Pavel
--
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]