浏览代码

ide: HPA detect from resume

Currently when system which have HPA require HPA to be detected and
disabled upon resume from RAM or disk. The current IDE drivers do not do
this nor does libata (obviously it since it doesn't support HPA yet).

I have implemented this into the current IDE drivers and it has been
tested by many others since 7/15/2006 in bug number 6840:

	http://bugzilla.kernel.org/show_bug.cgi?id=6840

and it has been confirmed to work fine with no problems.

bart: added drv != NULL check to generic_ide_suspend()

From: Lee Trager <lt73@cs.drexel.edu>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Lee Trager 18 年之前
父节点
当前提交
0d2157f78d
共有 3 个文件被更改,包括 21 次插入1 次删除
  1. 12 0
      drivers/ide/ide-disk.c
  2. 8 1
      drivers/ide/ide.c
  3. 1 0
      include/linux/ide.h

+ 12 - 0
drivers/ide/ide-disk.c

@@ -1037,6 +1037,17 @@ static void ide_disk_release(struct kref *kref)
 
 
 static int ide_disk_probe(ide_drive_t *drive);
 static int ide_disk_probe(ide_drive_t *drive);
 
 
+/*
+ * On HPA drives the capacity needs to be
+ * reinitilized on resume otherwise the disk
+ * can not be used and a hard reset is required
+ */
+static void ide_disk_resume(ide_drive_t *drive)
+{
+	if (idedisk_supports_hpa(drive->id))
+		init_idedisk_capacity(drive);
+}
+
 static void ide_device_shutdown(ide_drive_t *drive)
 static void ide_device_shutdown(ide_drive_t *drive)
 {
 {
 #ifdef	CONFIG_ALPHA
 #ifdef	CONFIG_ALPHA
@@ -1071,6 +1082,7 @@ static ide_driver_t idedisk_driver = {
 	},
 	},
 	.probe			= ide_disk_probe,
 	.probe			= ide_disk_probe,
 	.remove			= ide_disk_remove,
 	.remove			= ide_disk_remove,
+	.resume			= ide_disk_resume,
 	.shutdown		= ide_device_shutdown,
 	.shutdown		= ide_device_shutdown,
 	.version		= IDEDISK_VERSION,
 	.version		= IDEDISK_VERSION,
 	.media			= ide_disk,
 	.media			= ide_disk,

+ 8 - 1
drivers/ide/ide.c

@@ -1010,9 +1010,11 @@ static int generic_ide_resume(struct device *dev)
 {
 {
 	ide_drive_t *drive = dev->driver_data;
 	ide_drive_t *drive = dev->driver_data;
 	ide_hwif_t *hwif = HWIF(drive);
 	ide_hwif_t *hwif = HWIF(drive);
+	ide_driver_t *drv = to_ide_driver(dev->driver);
 	struct request rq;
 	struct request rq;
 	struct request_pm_state rqpm;
 	struct request_pm_state rqpm;
 	ide_task_t args;
 	ide_task_t args;
+	int err;
 
 
 	/* Call ACPI _STM only once */
 	/* Call ACPI _STM only once */
 	if (!(drive->dn % 2))
 	if (!(drive->dn % 2))
@@ -1029,7 +1031,12 @@ static int generic_ide_resume(struct device *dev)
 	rqpm.pm_step = ide_pm_state_start_resume;
 	rqpm.pm_step = ide_pm_state_start_resume;
 	rqpm.pm_state = PM_EVENT_ON;
 	rqpm.pm_state = PM_EVENT_ON;
 
 
-	return ide_do_drive_cmd(drive, &rq, ide_head_wait);
+	err = ide_do_drive_cmd(drive, &rq, ide_head_wait);
+
+	if (err == 0 && drv && drv->resume)
+		drv->resume(drive);
+
+	return err;
 }
 }
 
 
 int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev,
 int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev,

+ 1 - 0
include/linux/ide.h

@@ -1001,6 +1001,7 @@ struct ide_driver_s {
 	struct device_driver	gen_driver;
 	struct device_driver	gen_driver;
 	int		(*probe)(ide_drive_t *);
 	int		(*probe)(ide_drive_t *);
 	void		(*remove)(ide_drive_t *);
 	void		(*remove)(ide_drive_t *);
+	void		(*resume)(ide_drive_t *);
 	void		(*shutdown)(ide_drive_t *);
 	void		(*shutdown)(ide_drive_t *);
 #ifdef CONFIG_IDE_PROC_FS
 #ifdef CONFIG_IDE_PROC_FS
 	ide_proc_entry_t	*proc;
 	ide_proc_entry_t	*proc;