From patchwork Thu Aug 9 19:41:44 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bart Van Assche X-Patchwork-Id: 10561869 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 63E6113B4 for ; Thu, 9 Aug 2018 19:42:18 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 530412B979 for ; Thu, 9 Aug 2018 19:42:18 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 46BD52B97F; Thu, 9 Aug 2018 19:42:18 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C1D102B97D for ; Thu, 9 Aug 2018 19:42:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727137AbeHIWIe (ORCPT ); Thu, 9 Aug 2018 18:08:34 -0400 Received: from esa3.hgst.iphmx.com ([216.71.153.141]:41000 "EHLO esa3.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727038AbeHIWId (ORCPT ); Thu, 9 Aug 2018 18:08:33 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1533843736; x=1565379736; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=wbRBX8xo+4YgHfQJKOVQXAEyisqulqv5Hvk3HGBTtzs=; b=aeTT4kXVBL6hTnc+2dNrvQktr3Seo1cV0Rs/+IsCshQgrQY3sh4AJMt2 jzCIrN88LvhSKplzWJiUXIReA9+EnJ0KVv0lUlWsTEpq0xGFRY18VrWnk C+BlyhRTe/O2uOmDiO/9SUNJtqlco7p+LD+gtMPj+CnNuvzgKOX7HbFiQ ji9wQqIOO5GLoZ7zCuYnZToowcRnXCg2qr1N888r9Ujmz7qkbTAHx+APG zRiZVQbguCLBQgHFKFo/Yf7StbsokZAohTwZqpL6Km+6BxTCbOVjjBccI niGpgIpVLzyosBFaoVvdFFkpL6NGihErVmRF+ZB4YGrQpj65ihEW9THbJ Q==; X-IronPort-AV: E=Sophos;i="5.53,215,1531756800"; d="scan'208";a="90927376" Received: from mail-sn1nam01lp0111.outbound.protection.outlook.com (HELO NAM01-SN1-obe.outbound.protection.outlook.com) ([207.46.163.111]) by ob1.hgst.iphmx.com with ESMTP; 10 Aug 2018 03:42:14 +0800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sharedspace.onmicrosoft.com; s=selector1-wdc-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=CFkeiDfuA5u7gKb+mdPKV9KAo6AhEfJOYN4139rEiQI=; b=MzItXu0xDIBUMHfffeENIiNliEl7yg07IYVUC8kNfBW6/+BO5gJEScjm5K4WDX/Gor6JNgAZ3tBFFi+UyXdV7bRtTUykYRKVZ4DGyb4BsAqpfQyPISN/EugVUbKnC+hbVVBUYgAVEjmzTDPKuv/1UIJqsPFg8GliHta7JkaXPS0= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=Bart.VanAssche@wdc.com; Received: from asus.hsd1.ca.comcast.net (174.62.111.89) by MWHPR04MB1198.namprd04.prod.outlook.com (2603:10b6:300:71::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1038.23; Thu, 9 Aug 2018 19:42:09 +0000 From: Bart Van Assche To: Jens Axboe Cc: linux-block@vger.kernel.org, Christoph Hellwig , Bart Van Assche , Ming Lei , Jianchao Wang , Hannes Reinecke , Johannes Thumshirn , Alan Stern Subject: [PATCH v6 07/12] block: Move power management code into a new source file Date: Thu, 9 Aug 2018 12:41:44 -0700 Message-Id: <20180809194149.15285-8-bart.vanassche@wdc.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180809194149.15285-1-bart.vanassche@wdc.com> References: <20180809194149.15285-1-bart.vanassche@wdc.com> MIME-Version: 1.0 X-Originating-IP: [174.62.111.89] X-ClientProxiedBy: MWHPR2201CA0066.namprd22.prod.outlook.com (2603:10b6:301:5e::19) To MWHPR04MB1198.namprd04.prod.outlook.com (2603:10b6:300:71::23) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 9dc38b1e-1266-4e4b-5163-08d5fe303216 X-MS-Office365-Filtering-HT: Tenant X-Microsoft-Antispam: BCL:0;PCL:0;RULEID:(7020095)(4652040)(8989117)(4534165)(4627221)(201703031133081)(201702281549075)(8990107)(5600074)(711020)(4618075)(2017052603328)(7153060)(7193020);SRVR:MWHPR04MB1198; X-Microsoft-Exchange-Diagnostics: 1;MWHPR04MB1198;3:EVzo07E7k7EzrIGjvgm9r1zXTLoKkxRPJeeFcGdqYxHLPwCxpO562XuhazZ3mQZHX1o0LDH+djowHQEGlAqwVcbXtyHVgt0RxsEOLJ3qdVGUqD8ICnMMY67JFdV5GfKj9BCUQSYeRwGKasypcU1CdHPXMTvPhcbu5i7ADlJdvyheOiuIts90jkLr1Z8vvDVjrw1O0DRk+zP+3i4RbiAwM9af69Mg7p1J4QcEBYhyUY8I3x/ZJzmRB+zFN96Ti0GL;25:inXA/phnxwoOxCjC4hX1evlcQWIKS0WLUpiHC4M4blu3mj4JymD6qdjhCaBqJaWwF3IBoSajQ0BzfXbTs8Nam6vK48IKhgaDBmlypydrf0Mhi8hLLtH0ZWKX0beYkxnDi32/+3CkBhQLdCx/aA+j5ZABgVwTVpACMME7fjDbZ/ls+uqGjgU5qtSF4NWtEII0F7wVwGKTcVGkNp4ODspcEDQFElKHM62JCl8ObxiyfUSLOxE+QxRuiAdAPijZh2ZqSxFqJqSrW8ismC5L+yP9IyTOAFYx1Vc5vpzlNmpMkaB6KFo3QJ28lGEeHfpFqqzBonkFyjjqlhgzQyu1uoKjsw==;31:jT/zqyGT9D+f/AW04zfiMbrFFdSDVJRCPBI1xJB+YnM0SCs4/9U+qK7taRk8v0xJJfe0/jiYJdODikClFloWFAf6VpYciuqnQHLbDjWJtjijz7Z5aO7cYmhOZ8pv5Gdmx/D010ZVAwKpuIkda3RLuYYzqQhbz/0H8lbdOmSpWowVUFX4VdIuJzFi19PZhtYx/oWN+D2AISvXKVP4XGydYywWDgNl0Y+qzb+h80BL4kk= X-MS-TrafficTypeDiagnostic: MWHPR04MB1198: WDCIPOUTBOUND: EOP-TRUE X-Microsoft-Exchange-Diagnostics: 1;MWHPR04MB1198;20:EJHauKoSabREIe4yfDO/yBUD7CtEJUkKRsNTKC1Xq+2j/hz4skbGBLZymWaahBLbgS++3Y6PRpiBaSaZS9X0BTW4jbyua/Ltba4HlqWZEi2P6rVg7al68DaQ7hCTc8mSZRiYudEgLPirndBVwt4kMxeOyaocVF3Rp1iLXXlr1Qb7hDzRGHlFAo8/zu9ebTbnv0sS/hpsWW4Qk4fh+mDz/X0MWqI/OhYQRqugZWgvtYOP9DvwmY7NqX+YBFolqsaQ23xtrn+qp5DCxkMdMPyWZcXZeHv53xDRsPZENVSQeoPbM3X+gEiKhiBEQpoBoEAASfsAPEn249MoBgmlHNh3h+BnyW6cRrLdGys26hx/vQ7CtSmLC0mfqwNMAj+IWYEsoZWFJgtTsPycgg2VOizKOyJViE2jAL04flW1ML/M9IklgpZK9E1CFjcDPFJtNyAbwCSJsxdv/ujSyt0qHxG6zZ/niuc+BcbTa0zeoBey/Ytcu0F9lq6j6ns06NFTeij8;4:uMs0jxI++6qdPZjtjpCNgKpcjhlEl2LLZwpXbWe2WNaLELpjN0sBcELJz1tSisM6rFrH1ovB0RhrUn2/5S8hOeKVUxXSBDDshH/Z8V+l95bHY5LYRcQrAqMQnk73LVsK3gKjUnK8vShIku+kxsTBbdSWy8ujABKnCqzld1Gm39toOQjN+my8VYnpkWK1f/9keXxG0f9Z5BQF5oRcDAr++tA8ufyhQiggE5i8KkHPNBzrewV2X6D3JIJNkyJ6zoRzKrgp+OzBo3V7h/pGXI/DJI85iGuu0wzl6/cf1IYuXU1Cn4cp0oll5Nu3NvD9+2EBDX/99X2QF+ux7NHHJxyqO4oGFupetH+y5Zp5FQKMmCM= X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(35762410373642)(146099531331640); X-MS-Exchange-SenderADCheck: 1 X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(6040522)(2401047)(8121501046)(5005006)(93006095)(93001095)(3231311)(944501410)(52105095)(3002001)(10201501046)(6055026)(149027)(150027)(6041310)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(20161123562045)(20161123558120)(20161123564045)(20161123560045)(6072148)(201708071742011)(7699016);SRVR:MWHPR04MB1198;BCL:0;PCL:0;RULEID:;SRVR:MWHPR04MB1198; X-Forefront-PRVS: 0759F7A50A X-Forefront-Antispam-Report: SFV:NSPM;SFS:(10019020)(396003)(39860400002)(136003)(366004)(346002)(376002)(199004)(189003)(50944005)(76176011)(50466002)(476003)(51416003)(4326008)(478600001)(52116002)(6486002)(105586002)(72206003)(48376002)(5660300001)(47776003)(305945005)(2616005)(956004)(7736002)(6916009)(6666003)(486006)(8936002)(2906002)(68736007)(36756003)(66066001)(575784001)(186003)(446003)(81166006)(50226002)(8676002)(81156014)(316002)(6506007)(7520500002)(386003)(106356001)(97736004)(25786009)(11346002)(16586007)(54906003)(14444005)(6116002)(1076002)(3846002)(86362001)(26005)(16526019)(53936002)(6512007);DIR:OUT;SFP:1102;SCL:1;SRVR:MWHPR04MB1198;H:asus.hsd1.ca.comcast.net;FPR:;SPF:None;LANG:en;PTR:InfoNoRecords;A:1;MX:1; X-Microsoft-Exchange-Diagnostics: 1;MWHPR04MB1198;23:kquXOuVCOjtSz7AkCKJ/bkTIf359b5NaSRR6fFdQU/JMOQCD1ehVzw2DUaY6C+WLIzPqxGVZFJdh781+GDAX5rGgub0fq5O9C/vvHbC924ZJBkBN1/atd4XyodOKR5pxAtdNsnHVkrGiApP8Yc7OIX+mU52x1yrJfopAhhM8RwStnEENdu5VfScfdBw1CgIUbSxIIymcX39B+bhv57LW5RRwz8XckkUfTZ82M6FainyDrLullSPQ7XxICUVlkk1vxfJPPH0Tp6umZIxzTUfVys7fnIQQD7xiqswQYuHMdsLvPqjjZKKXc1lC9pEEzmnLZz2+xfVuAXDVzJ/fjjja9QYyXrpKwQsZVYffz7PfTKhvX2slmmVqRBeMNv5mOMx3Sw2OcpN1YH9ugen0uD1ONlVGv0k9WOPZhVti6uv5Ee+zu0Ifm3gRiA+CjV99JfSKIV+EYUZWwlLwWL7FSnIS6GbE9Ee0nxkrjECOiZnBb7OGCXEiW0mBkCXf9MnjxbvlbDMNMh7Hqi0tpK2vpaF+K9L4kRZ1eaKXO1Wv7+S5yNnEM5BM/iSKURlMbilMzMPgo3dlz4d4/cMS8C0IrPAKc9mrKaTdxKOXAE4e+1nCivHNO35/fJnL6jxr/4ez64HzKOfRcOCxflL5LmufkdyrJ8RNYAwvWhzgmti6IHGQSYNvhH9J2pHY4dM5kriwXZLpYr+VUbBpJlOTAveVRUoVKoJsR+m6M7gGN3LKhprx4eAGEiagc9YDtCYsxCyF3l8sELRGkUH4RRNsFSM7fnx+g8kw0mmNXTKvXjVTtKgsxbhSpMdjbIoPKJWwvEhdzR+d1YHCZ1yC6ZfESLgwGzvVd2YksWBbTRNRaXsvLmUz0cbJwxEbH9T2xQrwLKQ5ep4Q7u7E9JbM5blPtALIL/RJRg0Iwn51E9PkdqXIhK3uHT1UXJGndtr38DJRJe1YWcoZu/QYAnk7ERSwhG+EOq48CBmyUh55hd3s01A/fg/u40CHc0LR7I49NQEXbPWuGoFaQQb3/3G3F9e4XF55Pp2dlw+KBrFNs+7eR2phEcsNnYaFj4Z4YrVrqqpAGqp6s9J0UHjBrjrt8LQB8v7spKHcZlJQm5deABP7bS9YC2TLTlc6DoG/9Bb7Wts+TBGA3jdKHx6xcZlNkwmRM1/TO9AZDfJD8WAl8rx/NrnKXfSI3bCQVr8xeh5tV1FyDGemRkK8jDUFEaF19m1ZyRQouYvBAtQNMGKC3hYwTvY7vgnzob8M0oUt8agJos8aK0WC7h2Y1ww0sD1237HxH7f0FghWCXINBT6DgeIyKEqejgeGC2M= X-Microsoft-Antispam-Message-Info: jP0R/fCMreCd006Kj5wSfEYi6eMQKp2injTcBMIYx7lffLpPZsaDLqan0h+BygeB4O1uLmoIaVbPI/ZWb4Zlzdnejj0RFtr+m/T0rdy6P7zh08t8ylxLANWghbxaXTjaYD7jZrsAl1EKmy7cXtZyio7/aAT77zAFldirheOC1IRGyokcyS7XJu84qGSEjc4t+QkbUIBPgDQnzWpQgLPqIsmUFji+1Vbm4dBY0jUixJ+oOymVdJsZbKtiefPpunjScyh1DH1leNFZs0fQossDjUegVXkvx0EFTBO0Z5F1ZuWeImEwBS2aUYty4fnMxy0uB3pZKCIzruHaV9pIEtOZF9A4luTHzDLXq2kiD0BF/T4= X-Microsoft-Exchange-Diagnostics: 1;MWHPR04MB1198;6:eeNpRDNk6k34eGHY6WQub50w0OhlZ7WH4Jwpm6x1vNtRQ9nK0y6AhWwk4KATGII2IlrNt2ZCU4akjXJthGvBcQlGoTwITIA1PWHKI9JYjPVvzy2lHC+g2mBNfFQDbnDrrKZ7pWfQtK6o23I7Baa/WpW3T++xxXKXea+nFQsulk2KS+rb9kbQhB6S6mmsDDNDIJ9qNj4HbNG31NwuddBYoA4UOPmkoUzqm/TIYqxo2lmifYt4OC5gB4x1iVFv6a9RnZPfwzxx6/d/nR3G6HKdPY639SwuFTgO57400/IkOE71uDaQGce3dFGCnWFU16S7tRI+ndqfYBmMmxg0t2iU3YdwA+8U3SMD6uosr1cCrvjjKyoUcek3GrFkQQyjd/TPIM/jdY+yUMuZt2m1gi3n0nX0cuYztibwSYCI26QGiaqS8JcFKaoFzgjjHbUh5FRIDoVO8SiJ82lu2HLaJILxEg==;5:M5uFQrjbrWXfwAad4khF0JkDp6CK0hgHsRRDtFguYoTU7coqyrmr3JJOXeyWn5XAICc3wLwSvVjrdS8hi2q3eYkEcZ977OCqxwyW9AzFtXDPY5LbcEKVrk+jJc/TrwUMsNIFODLizNobThU6DWR0/Mn57jNJEPq2Ra08eOfOgg0=;7:cmqp6fHetOMGnN0YGnLPX3oF++WyUSxhWUaJLIZFSp4qPE0gzP1DvUbuF3BQnC8XHpCxUxd3/nGScQBOFvhneeLM32IoQt43OdqSuWDH6L2XqTAlT5Lq4wixTEMfSn/6u3g+SyNFEd4IQ7APAMx3lqCkW22UjIgqarIBWDoSD4hRvrRSWczlmPSvkoylaU5KeX8RUosnnYNP1/SHGYgMNM/tBPcujeLPdZA1ioViKtGXZNgccPsET9zn319rzIfF SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1;MWHPR04MB1198;20:MsZLonoyh8jumXxfR/ZkMfMYrZolmoi7kF8rQGmSdFKsEQp7DOFaID1IaRMJFHFoxYShnw5i6soRXEUooMszsy/GwmQ+BLId5ks+Y/xGUt7xJiWnGtNZleHNFA7es3SRqUe5nIGN03q3HcrrsGtvfOUyCzsRa+G/BBeOrk9hZTs= X-OriginatorOrg: wdc.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2018 19:42:09.1338 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 9dc38b1e-1266-4e4b-5163-08d5fe303216 X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: b61c8803-16f3-4c35-9b17-6f65f441df86 X-MS-Exchange-Transport-CrossTenantHeadersStamped: MWHPR04MB1198 Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Move the code for runtime power management from blk-core.c into the new source file blk-pm.c. Move the corresponding declarations from into . For CONFIG_PM=n, leave out the declarations of the functions that are not used in that mode. This patch not only reduces the number of #ifdefs in the block layer core code but also reduces the size of header file and hence should help to reduce the build time of the Linux kernel if CONFIG_PM is not defined. Signed-off-by: Bart Van Assche Cc: Christoph Hellwig Cc: Ming Lei Cc: Jianchao Wang Cc: Hannes Reinecke Cc: Johannes Thumshirn Cc: Alan Stern --- block/Kconfig | 5 ++ block/Makefile | 1 + block/blk-core.c | 196 +---------------------------------------- block/blk-pm.c | 188 +++++++++++++++++++++++++++++++++++++++ block/blk-pm.h | 43 +++++++++ block/elevator.c | 22 +---- drivers/scsi/scsi_pm.c | 1 + drivers/scsi/sd.c | 1 + drivers/scsi/sr.c | 1 + include/linux/blk-pm.h | 24 +++++ include/linux/blkdev.h | 23 ----- 11 files changed, 266 insertions(+), 239 deletions(-) create mode 100644 block/blk-pm.c create mode 100644 block/blk-pm.h create mode 100644 include/linux/blk-pm.h diff --git a/block/Kconfig b/block/Kconfig index 1f2469a0123c..e213d90a5e64 100644 --- a/block/Kconfig +++ b/block/Kconfig @@ -228,4 +228,9 @@ config BLK_MQ_RDMA depends on BLOCK && INFINIBAND default y +config BLK_PM + bool + depends on BLOCK && PM + default y + source block/Kconfig.iosched diff --git a/block/Makefile b/block/Makefile index 572b33f32c07..27eac600474f 100644 --- a/block/Makefile +++ b/block/Makefile @@ -37,3 +37,4 @@ obj-$(CONFIG_BLK_WBT) += blk-wbt.o obj-$(CONFIG_BLK_DEBUG_FS) += blk-mq-debugfs.o obj-$(CONFIG_BLK_DEBUG_FS_ZONED)+= blk-mq-debugfs-zoned.o obj-$(CONFIG_BLK_SED_OPAL) += sed-opal.o +obj-$(CONFIG_BLK_PM) += blk-pm.o diff --git a/block/blk-core.c b/block/blk-core.c index 401f4927a8db..3770a36e85be 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -42,6 +42,7 @@ #include "blk.h" #include "blk-mq.h" #include "blk-mq-sched.h" +#include "blk-pm.h" #include "blk-rq-qos.h" #ifdef CONFIG_DEBUG_FS @@ -1757,16 +1758,6 @@ void part_round_stats(struct request_queue *q, int cpu, struct hd_struct *part) } EXPORT_SYMBOL_GPL(part_round_stats); -#ifdef CONFIG_PM -static void blk_pm_put_request(struct request *rq) -{ - if (rq->q->dev && !(rq->rq_flags & RQF_PM) && !--rq->q->nr_pending) - pm_runtime_mark_last_busy(rq->q->dev); -} -#else -static inline void blk_pm_put_request(struct request *rq) {} -#endif - void __blk_put_request(struct request_queue *q, struct request *req) { req_flags_t rq_flags = req->rq_flags; @@ -3783,191 +3774,6 @@ void blk_finish_plug(struct blk_plug *plug) } EXPORT_SYMBOL(blk_finish_plug); -#ifdef CONFIG_PM -/** - * blk_pm_runtime_init - Block layer runtime PM initialization routine - * @q: the queue of the device - * @dev: the device the queue belongs to - * - * Description: - * Initialize runtime-PM-related fields for @q and start auto suspend for - * @dev. Drivers that want to take advantage of request-based runtime PM - * should call this function after @dev has been initialized, and its - * request queue @q has been allocated, and runtime PM for it can not happen - * yet(either due to disabled/forbidden or its usage_count > 0). In most - * cases, driver should call this function before any I/O has taken place. - * - * This function takes care of setting up using auto suspend for the device, - * the autosuspend delay is set to -1 to make runtime suspend impossible - * until an updated value is either set by user or by driver. Drivers do - * not need to touch other autosuspend settings. - * - * The block layer runtime PM is request based, so only works for drivers - * that use request as their IO unit instead of those directly use bio's. - */ -void blk_pm_runtime_init(struct request_queue *q, struct device *dev) -{ - /* Don't enable runtime PM for blk-mq until it is ready */ - if (q->mq_ops) { - pm_runtime_disable(dev); - return; - } - - q->dev = dev; - q->rpm_status = RPM_ACTIVE; - pm_runtime_set_autosuspend_delay(q->dev, -1); - pm_runtime_use_autosuspend(q->dev); -} -EXPORT_SYMBOL(blk_pm_runtime_init); - -/** - * blk_pre_runtime_suspend - Pre runtime suspend check - * @q: the queue of the device - * - * Description: - * This function will check if runtime suspend is allowed for the device - * by examining if there are any requests pending in the queue. If there - * are requests pending, the device can not be runtime suspended; otherwise, - * the queue's status will be updated to SUSPENDING and the driver can - * proceed to suspend the device. - * - * For the not allowed case, we mark last busy for the device so that - * runtime PM core will try to autosuspend it some time later. - * - * This function should be called near the start of the device's - * runtime_suspend callback. - * - * Return: - * 0 - OK to runtime suspend the device - * -EBUSY - Device should not be runtime suspended - */ -int blk_pre_runtime_suspend(struct request_queue *q) -{ - int ret = 0; - - if (!q->dev) - return ret; - - spin_lock_irq(q->queue_lock); - if (q->nr_pending) { - ret = -EBUSY; - pm_runtime_mark_last_busy(q->dev); - } else { - q->rpm_status = RPM_SUSPENDING; - } - spin_unlock_irq(q->queue_lock); - return ret; -} -EXPORT_SYMBOL(blk_pre_runtime_suspend); - -/** - * blk_post_runtime_suspend - Post runtime suspend processing - * @q: the queue of the device - * @err: return value of the device's runtime_suspend function - * - * Description: - * Update the queue's runtime status according to the return value of the - * device's runtime suspend function and mark last busy for the device so - * that PM core will try to auto suspend the device at a later time. - * - * This function should be called near the end of the device's - * runtime_suspend callback. - */ -void blk_post_runtime_suspend(struct request_queue *q, int err) -{ - if (!q->dev) - return; - - spin_lock_irq(q->queue_lock); - if (!err) { - q->rpm_status = RPM_SUSPENDED; - } else { - q->rpm_status = RPM_ACTIVE; - pm_runtime_mark_last_busy(q->dev); - } - spin_unlock_irq(q->queue_lock); -} -EXPORT_SYMBOL(blk_post_runtime_suspend); - -/** - * blk_pre_runtime_resume - Pre runtime resume processing - * @q: the queue of the device - * - * Description: - * Update the queue's runtime status to RESUMING in preparation for the - * runtime resume of the device. - * - * This function should be called near the start of the device's - * runtime_resume callback. - */ -void blk_pre_runtime_resume(struct request_queue *q) -{ - if (!q->dev) - return; - - spin_lock_irq(q->queue_lock); - q->rpm_status = RPM_RESUMING; - spin_unlock_irq(q->queue_lock); -} -EXPORT_SYMBOL(blk_pre_runtime_resume); - -/** - * blk_post_runtime_resume - Post runtime resume processing - * @q: the queue of the device - * @err: return value of the device's runtime_resume function - * - * Description: - * Update the queue's runtime status according to the return value of the - * device's runtime_resume function. If it is successfully resumed, process - * the requests that are queued into the device's queue when it is resuming - * and then mark last busy and initiate autosuspend for it. - * - * This function should be called near the end of the device's - * runtime_resume callback. - */ -void blk_post_runtime_resume(struct request_queue *q, int err) -{ - if (!q->dev) - return; - - spin_lock_irq(q->queue_lock); - if (!err) { - q->rpm_status = RPM_ACTIVE; - __blk_run_queue(q); - pm_runtime_mark_last_busy(q->dev); - pm_request_autosuspend(q->dev); - } else { - q->rpm_status = RPM_SUSPENDED; - } - spin_unlock_irq(q->queue_lock); -} -EXPORT_SYMBOL(blk_post_runtime_resume); - -/** - * blk_set_runtime_active - Force runtime status of the queue to be active - * @q: the queue of the device - * - * If the device is left runtime suspended during system suspend the resume - * hook typically resumes the device and corrects runtime status - * accordingly. However, that does not affect the queue runtime PM status - * which is still "suspended". This prevents processing requests from the - * queue. - * - * This function can be used in driver's resume hook to correct queue - * runtime PM status and re-enable peeking requests from the queue. It - * should be called before first request is added to the queue. - */ -void blk_set_runtime_active(struct request_queue *q) -{ - spin_lock_irq(q->queue_lock); - q->rpm_status = RPM_ACTIVE; - pm_runtime_mark_last_busy(q->dev); - pm_request_autosuspend(q->dev); - spin_unlock_irq(q->queue_lock); -} -EXPORT_SYMBOL(blk_set_runtime_active); -#endif - int __init blk_dev_init(void) { BUILD_BUG_ON(REQ_OP_LAST >= (1 << REQ_OP_BITS)); diff --git a/block/blk-pm.c b/block/blk-pm.c new file mode 100644 index 000000000000..9b636960d285 --- /dev/null +++ b/block/blk-pm.c @@ -0,0 +1,188 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include + +/** + * blk_pm_runtime_init - Block layer runtime PM initialization routine + * @q: the queue of the device + * @dev: the device the queue belongs to + * + * Description: + * Initialize runtime-PM-related fields for @q and start auto suspend for + * @dev. Drivers that want to take advantage of request-based runtime PM + * should call this function after @dev has been initialized, and its + * request queue @q has been allocated, and runtime PM for it can not happen + * yet(either due to disabled/forbidden or its usage_count > 0). In most + * cases, driver should call this function before any I/O has taken place. + * + * This function takes care of setting up using auto suspend for the device, + * the autosuspend delay is set to -1 to make runtime suspend impossible + * until an updated value is either set by user or by driver. Drivers do + * not need to touch other autosuspend settings. + * + * The block layer runtime PM is request based, so only works for drivers + * that use request as their IO unit instead of those directly use bio's. + */ +void blk_pm_runtime_init(struct request_queue *q, struct device *dev) +{ + /* Don't enable runtime PM for blk-mq until it is ready */ + if (q->mq_ops) { + pm_runtime_disable(dev); + return; + } + + q->dev = dev; + q->rpm_status = RPM_ACTIVE; + pm_runtime_set_autosuspend_delay(q->dev, -1); + pm_runtime_use_autosuspend(q->dev); +} +EXPORT_SYMBOL(blk_pm_runtime_init); + +/** + * blk_pre_runtime_suspend - Pre runtime suspend check + * @q: the queue of the device + * + * Description: + * This function will check if runtime suspend is allowed for the device + * by examining if there are any requests pending in the queue. If there + * are requests pending, the device can not be runtime suspended; otherwise, + * the queue's status will be updated to SUSPENDING and the driver can + * proceed to suspend the device. + * + * For the not allowed case, we mark last busy for the device so that + * runtime PM core will try to autosuspend it some time later. + * + * This function should be called near the start of the device's + * runtime_suspend callback. + * + * Return: + * 0 - OK to runtime suspend the device + * -EBUSY - Device should not be runtime suspended + */ +int blk_pre_runtime_suspend(struct request_queue *q) +{ + int ret = 0; + + if (!q->dev) + return ret; + + spin_lock_irq(q->queue_lock); + if (q->nr_pending) { + ret = -EBUSY; + pm_runtime_mark_last_busy(q->dev); + } else { + q->rpm_status = RPM_SUSPENDING; + } + spin_unlock_irq(q->queue_lock); + return ret; +} +EXPORT_SYMBOL(blk_pre_runtime_suspend); + +/** + * blk_post_runtime_suspend - Post runtime suspend processing + * @q: the queue of the device + * @err: return value of the device's runtime_suspend function + * + * Description: + * Update the queue's runtime status according to the return value of the + * device's runtime suspend function and mark last busy for the device so + * that PM core will try to auto suspend the device at a later time. + * + * This function should be called near the end of the device's + * runtime_suspend callback. + */ +void blk_post_runtime_suspend(struct request_queue *q, int err) +{ + if (!q->dev) + return; + + spin_lock_irq(q->queue_lock); + if (!err) { + q->rpm_status = RPM_SUSPENDED; + } else { + q->rpm_status = RPM_ACTIVE; + pm_runtime_mark_last_busy(q->dev); + } + spin_unlock_irq(q->queue_lock); +} +EXPORT_SYMBOL(blk_post_runtime_suspend); + +/** + * blk_pre_runtime_resume - Pre runtime resume processing + * @q: the queue of the device + * + * Description: + * Update the queue's runtime status to RESUMING in preparation for the + * runtime resume of the device. + * + * This function should be called near the start of the device's + * runtime_resume callback. + */ +void blk_pre_runtime_resume(struct request_queue *q) +{ + if (!q->dev) + return; + + spin_lock_irq(q->queue_lock); + q->rpm_status = RPM_RESUMING; + spin_unlock_irq(q->queue_lock); +} +EXPORT_SYMBOL(blk_pre_runtime_resume); + +/** + * blk_post_runtime_resume - Post runtime resume processing + * @q: the queue of the device + * @err: return value of the device's runtime_resume function + * + * Description: + * Update the queue's runtime status according to the return value of the + * device's runtime_resume function. If it is successfully resumed, process + * the requests that are queued into the device's queue when it is resuming + * and then mark last busy and initiate autosuspend for it. + * + * This function should be called near the end of the device's + * runtime_resume callback. + */ +void blk_post_runtime_resume(struct request_queue *q, int err) +{ + if (!q->dev) + return; + + spin_lock_irq(q->queue_lock); + if (!err) { + q->rpm_status = RPM_ACTIVE; + __blk_run_queue(q); + pm_runtime_mark_last_busy(q->dev); + pm_request_autosuspend(q->dev); + } else { + q->rpm_status = RPM_SUSPENDED; + } + spin_unlock_irq(q->queue_lock); +} +EXPORT_SYMBOL(blk_post_runtime_resume); + +/** + * blk_set_runtime_active - Force runtime status of the queue to be active + * @q: the queue of the device + * + * If the device is left runtime suspended during system suspend the resume + * hook typically resumes the device and corrects runtime status + * accordingly. However, that does not affect the queue runtime PM status + * which is still "suspended". This prevents processing requests from the + * queue. + * + * This function can be used in driver's resume hook to correct queue + * runtime PM status and re-enable peeking requests from the queue. It + * should be called before first request is added to the queue. + */ +void blk_set_runtime_active(struct request_queue *q) +{ + spin_lock_irq(q->queue_lock); + q->rpm_status = RPM_ACTIVE; + pm_runtime_mark_last_busy(q->dev); + pm_request_autosuspend(q->dev); + spin_unlock_irq(q->queue_lock); +} +EXPORT_SYMBOL(blk_set_runtime_active); diff --git a/block/blk-pm.h b/block/blk-pm.h new file mode 100644 index 000000000000..1ffc8ef203ec --- /dev/null +++ b/block/blk-pm.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef _BLOCK_BLK_PM_H_ +#define _BLOCK_BLK_PM_H_ + +#include + +#ifdef CONFIG_PM +static inline void blk_pm_requeue_request(struct request *rq) +{ + if (rq->q->dev && !(rq->rq_flags & RQF_PM)) + rq->q->nr_pending--; +} + +static inline void blk_pm_add_request(struct request_queue *q, + struct request *rq) +{ + if (q->dev && !(rq->rq_flags & RQF_PM) && q->nr_pending++ == 0 && + (q->rpm_status == RPM_SUSPENDED || q->rpm_status == RPM_SUSPENDING)) + pm_request_resume(q->dev); +} + +static inline void blk_pm_put_request(struct request *rq) +{ + if (rq->q->dev && !(rq->rq_flags & RQF_PM) && !--rq->q->nr_pending) + pm_runtime_mark_last_busy(rq->q->dev); +} +#else +static inline void blk_pm_requeue_request(struct request *rq) +{ +} + +static inline void blk_pm_add_request(struct request_queue *q, + struct request *rq) +{ +} + +static inline void blk_pm_put_request(struct request *rq) +{ +} +#endif + +#endif /* _BLOCK_BLK_PM_H_ */ diff --git a/block/elevator.c b/block/elevator.c index fa828b5bfd4b..4c15f0240c99 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -41,6 +41,7 @@ #include "blk.h" #include "blk-mq-sched.h" +#include "blk-pm.h" #include "blk-wbt.h" static DEFINE_SPINLOCK(elv_list_lock); @@ -557,27 +558,6 @@ void elv_bio_merged(struct request_queue *q, struct request *rq, e->type->ops.sq.elevator_bio_merged_fn(q, rq, bio); } -#ifdef CONFIG_PM -static void blk_pm_requeue_request(struct request *rq) -{ - if (rq->q->dev && !(rq->rq_flags & RQF_PM)) - rq->q->nr_pending--; -} - -static void blk_pm_add_request(struct request_queue *q, struct request *rq) -{ - if (q->dev && !(rq->rq_flags & RQF_PM) && q->nr_pending++ == 0 && - (q->rpm_status == RPM_SUSPENDED || q->rpm_status == RPM_SUSPENDING)) - pm_request_resume(q->dev); -} -#else -static inline void blk_pm_requeue_request(struct request *rq) {} -static inline void blk_pm_add_request(struct request_queue *q, - struct request *rq) -{ -} -#endif - void elv_requeue_request(struct request_queue *q, struct request *rq) { /* diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c index 6300e168701d..eb790b679eaf 100644 --- a/drivers/scsi/scsi_pm.c +++ b/drivers/scsi/scsi_pm.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index bbebdc3769b0..69ab459abb98 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 3f3cb72e0c0c..de4413e66eca 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include diff --git a/include/linux/blk-pm.h b/include/linux/blk-pm.h new file mode 100644 index 000000000000..b80c65aba249 --- /dev/null +++ b/include/linux/blk-pm.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef _BLK_PM_H_ +#define _BLK_PM_H_ + +struct device; +struct request_queue; + +/* + * block layer runtime pm functions + */ +#ifdef CONFIG_PM +extern void blk_pm_runtime_init(struct request_queue *q, struct device *dev); +extern int blk_pre_runtime_suspend(struct request_queue *q); +extern void blk_post_runtime_suspend(struct request_queue *q, int err); +extern void blk_pre_runtime_resume(struct request_queue *q); +extern void blk_post_runtime_resume(struct request_queue *q, int err); +extern void blk_set_runtime_active(struct request_queue *q); +#else +static inline void blk_pm_runtime_init(struct request_queue *q, + struct device *dev) {} +#endif + +#endif /* _BLK_PM_H_ */ diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 7717b71c6da3..7560c88a0fe2 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -1284,29 +1284,6 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id, extern void blk_put_queue(struct request_queue *); extern void blk_set_queue_dying(struct request_queue *); -/* - * block layer runtime pm functions - */ -#ifdef CONFIG_PM -extern void blk_pm_runtime_init(struct request_queue *q, struct device *dev); -extern int blk_pre_runtime_suspend(struct request_queue *q); -extern void blk_post_runtime_suspend(struct request_queue *q, int err); -extern void blk_pre_runtime_resume(struct request_queue *q); -extern void blk_post_runtime_resume(struct request_queue *q, int err); -extern void blk_set_runtime_active(struct request_queue *q); -#else -static inline void blk_pm_runtime_init(struct request_queue *q, - struct device *dev) {} -static inline int blk_pre_runtime_suspend(struct request_queue *q) -{ - return -ENOSYS; -} -static inline void blk_post_runtime_suspend(struct request_queue *q, int err) {} -static inline void blk_pre_runtime_resume(struct request_queue *q) {} -static inline void blk_post_runtime_resume(struct request_queue *q, int err) {} -static inline void blk_set_runtime_active(struct request_queue *q) {} -#endif - /* * blk_plug permits building a queue of related requests by holding the I/O * fragments for a short period. This allows merging of sequential requests