lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1328513548-19786-6-git-send-email-ying.huang@intel.com>
Date:	Mon,  6 Feb 2012 15:32:28 +0800
From:	Huang Ying <ying.huang@...el.com>
To:	Alan Stern <stern@...land.harvard.edu>
Cc:	ming.m.lin@...el.com, linux-kernel@...r.kernel.org,
	linux-scsi@...r.kernel.org, linux-pm@...r.kernel.org,
	"Rafael J. Wysocki" <rjw@...k.pl>,
	James Bottomley <JBottomley@...allels.com>,
	Huang Ying <ying.huang@...el.com>
Subject: [RFC 5/5] scsi, sd, pm, request based runtime PM support

Can reduce power consumption when disk is mounted but no read/write
request.

TODO: Request based runtime PM may be harmful for rotating HD, should
enable that only for SSD and fallback to open/close based runtime PM
otherwise.

Signed-off-by: Huang Ying <ying.huang@...el.com>
---
 drivers/scsi/scsi_lib.c  |    3 ++-
 drivers/scsi/scsi_priv.h |    1 +
 drivers/scsi/sd.c        |   43 +++++++++++++++++++++++++++++++++++++++++--
 drivers/scsi/sd.h        |    2 ++
 4 files changed, 46 insertions(+), 3 deletions(-)

--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -401,7 +401,7 @@ static inline int scsi_host_is_busy(stru
  * Notes:	The previous command was completely finished, start
  *		a new one if possible.
  */
-static void scsi_run_queue(struct request_queue *q)
+void scsi_run_queue(struct request_queue *q)
 {
 	struct scsi_device *sdev = q->queuedata;
 	struct Scsi_Host *shost;
@@ -454,6 +454,7 @@ static void scsi_run_queue(struct reques
 
 	blk_run_queue(q);
 }
+EXPORT_SYMBOL_GPL(scsi_run_queue);
 
 void scsi_requeue_run_queue(struct work_struct *work)
 {
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -87,6 +87,7 @@ extern struct request_queue *scsi_alloc_
 extern void scsi_free_queue(struct request_queue *q);
 extern int scsi_init_queue(void);
 extern void scsi_exit_queue(void);
+extern void scsi_run_queue(struct request_queue *q);
 struct request_queue;
 struct request;
 extern struct kmem_cache *scsi_sdb_cache;
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -66,6 +66,7 @@
 
 #include "sd.h"
 #include "scsi_logging.h"
+#include "scsi_priv.h"
 
 MODULE_AUTHOR("Eric Youngdale");
 MODULE_DESCRIPTION("SCSI disk (sd) driver");
@@ -981,6 +982,8 @@ static int sd_open(struct block_device *
 			scsi_set_medium_removal(sdev, SCSI_REMOVAL_PREVENT);
 	}
 
+	scsi_autopm_put_device_sync(sdev);
+
 	return 0;
 
 error_out:
@@ -1020,7 +1023,6 @@ static int sd_release(struct gendisk *di
 	 * XXX is followed by a "rmmod sd_mod"?
 	 */
 
-	scsi_autopm_put_device_sync(sdev);
 	scsi_disk_put(sdkp);
 	return 0;
 }
@@ -1071,7 +1073,7 @@ static int sd_ioctl(struct block_device
 	struct scsi_device *sdp = sdkp->device;
 	void __user *p = (void __user *)arg;
 	int error;
-    
+
 	SCSI_LOG_IOCTL(1, sd_printk(KERN_INFO, sdkp, "sd_ioctl: disk=%s, "
 				    "cmd=0x%x\n", disk->disk_name, cmd));
 
@@ -1079,6 +1081,10 @@ static int sd_ioctl(struct block_device
 	if (error < 0)
 		return error;
 
+	error = scsi_autopm_get_device_sync(sdp);
+	if (error)
+		return error;
+
 	/*
 	 * If we are in the middle of error recovery, don't let anyone
 	 * else try and use this device.  Also, if error recovery fails, it
@@ -1108,6 +1114,7 @@ static int sd_ioctl(struct block_device
 			break;
 	}
 out:
+	scsi_autopm_put_device_sync(sdp);
 	return error;
 }
 
@@ -2365,10 +2372,15 @@ static int sd_revalidate_disk(struct gen
 	struct scsi_device *sdp = sdkp->device;
 	unsigned char *buffer;
 	unsigned flush = 0;
+	int error;
 
 	SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp,
 				      "sd_revalidate_disk\n"));
 
+	error = scsi_autopm_get_device_sync(sdp);
+	if (error)
+		return 0;
+
 	/*
 	 * If the device is offline, don't try and read capacity or any
 	 * of the other niceties.
@@ -2421,6 +2433,7 @@ static int sd_revalidate_disk(struct gen
 	kfree(buffer);
 
  out:
+	scsi_autopm_put_device_sync(sdp);
 	return 0;
 }
 
@@ -2490,6 +2503,29 @@ static int sd_format_disk_name(char *pre
 	return 0;
 }
 
+static void sd_on_resume_work(struct work_struct *work)
+{
+	struct scsi_disk *sdkp = container_of(work, struct scsi_disk, work);
+	struct scsi_device *sdev = sdkp->device;
+
+	scsi_run_queue(sdev->request_queue);
+}
+
+/*
+ * Called with dev->power.lock held, scsi_run_queue will acquire the
+ * lock too, so delay to a work item to do that.
+ */
+static int sd_on_resume(struct notifier_block *nb, unsigned long event,
+			void *ptr)
+{
+	struct scsi_disk *sdkp = container_of(nb, struct scsi_disk, nb);
+
+	if (event == RPM_REQ_RESUME)
+		schedule_work(&sdkp->work);
+
+	return NOTIFY_DONE;
+}
+
 /*
  * The asynchronous part of sd_probe
  */
@@ -2543,6 +2579,9 @@ static void sd_probe_async(void *data, a
 
 	sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n",
 		  sdp->removable ? "removable " : "");
+	INIT_WORK(&sdkp->work, sd_on_resume_work);
+	sdkp->nb.notifier_call = sd_on_resume;
+	atomic_notifier_chain_register(&dev->power.notifier, &sdkp->nb);
 	scsi_autopm_put_device_sync(sdp);
 	put_device(&sdkp->dev);
 }
--- a/drivers/scsi/sd.h
+++ b/drivers/scsi/sd.h
@@ -50,6 +50,8 @@ struct scsi_disk {
 	struct scsi_driver *driver;	/* always &sd_template */
 	struct scsi_device *device;
 	struct device	dev;
+	struct notifier_block nb;
+	struct work_struct work;
 	struct gendisk	*disk;
 	atomic_t	openers;
 	sector_t	capacity;	/* size in 512-byte sectors */
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ