From patchwork Fri Jun 22 06:41:56 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Williams X-Patchwork-Id: 166518 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 88423B6F86 for ; Fri, 22 Jun 2012 16:25:39 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1761343Ab2FVGZi (ORCPT ); Fri, 22 Jun 2012 02:25:38 -0400 Received: from mga02.intel.com ([134.134.136.20]:28334 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1761339Ab2FVGZh (ORCPT ); Fri, 22 Jun 2012 02:25:37 -0400 Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga101.jf.intel.com with ESMTP; 21 Jun 2012 23:25:17 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.67,351,1309762800"; d="scan'208";a="161106941" Received: from dwillia2-linux.jf.intel.com ([10.7.137.146]) by orsmga002.jf.intel.com with ESMTP; 21 Jun 2012 23:25:17 -0700 Received: from dwillia2-linux.jf.intel.com (localhost.localdomain [IPv6:::1]) by dwillia2-linux.jf.intel.com (Postfix) with ESMTP id A16368003D; Thu, 21 Jun 2012 23:41:56 -0700 (PDT) Subject: [set4 PATCH 4/4] isci: implement suspend/resume support To: linux-scsi@vger.kernel.org From: Dan Williams Cc: linux-ide@vger.kernel.org, Artur Wojcik , Jacek Danecki Date: Thu, 21 Jun 2012 23:41:56 -0700 Message-ID: <20120622064156.21452.91513.stgit@dwillia2-linux.jf.intel.com> In-Reply-To: <20120622064135.21452.82833.stgit@dwillia2-linux.jf.intel.com> References: <20120622064135.21452.82833.stgit@dwillia2-linux.jf.intel.com> User-Agent: StGit/0.16-1-g7004 MIME-Version: 1.0 Sender: linux-ide-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ide@vger.kernel.org From: Artur Wojcik Provide a "simple-dev-pm-ops" implementation that shuts down the domain and the device on suspend, and resumes the device and the domain on resume. All of the mechanics of restoring domain connectivity are handled by libsas once isci has notified libsas that all links should be back up. libsas is in charge of handling links that did not resume, or resumed out of order. Signed-off-by: Artur Wojcik Signed-off-by: Jacek Danecki Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 2 +- drivers/scsi/isci/host.h | 2 +- drivers/scsi/isci/init.c | 58 +++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 59 insertions(+), 3 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe linux-ide" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 45385f5..bc8981e 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -1044,7 +1044,7 @@ static enum sci_status sci_controller_start(struct isci_host *ihost, return SCI_SUCCESS; } -void isci_host_scan_start(struct Scsi_Host *shost) +void isci_host_start(struct Scsi_Host *shost) { struct isci_host *ihost = SHOST_TO_SAS_HA(shost)->lldd_ha; unsigned long tmo = sci_controller_get_suggested_start_timeout(ihost); diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 9ab58e0..4911310 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -473,7 +473,7 @@ void sci_controller_remote_device_stopped(struct isci_host *ihost, enum sci_status sci_controller_continue_io(struct isci_request *ireq); int isci_host_scan_finished(struct Scsi_Host *, unsigned long); -void isci_host_scan_start(struct Scsi_Host *); +void isci_host_start(struct Scsi_Host *); u16 isci_alloc_tag(struct isci_host *ihost); enum sci_status isci_free_tag(struct isci_host *ihost, u16 io_tag); void isci_tci_free(struct isci_host *ihost, u16 tci); diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 92c1d86..da142a8 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -156,7 +156,7 @@ static struct scsi_host_template isci_sht = { .target_alloc = sas_target_alloc, .slave_configure = sas_slave_configure, .scan_finished = isci_host_scan_finished, - .scan_start = isci_host_scan_start, + .scan_start = isci_host_start, .change_queue_depth = sas_change_queue_depth, .change_queue_type = sas_change_queue_type, .bios_param = sas_bios_param, @@ -722,11 +722,67 @@ static void __devexit isci_pci_remove(struct pci_dev *pdev) } } +#ifdef CONFIG_PM +static int isci_suspend(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct isci_host *ihost; + int i; + + for_each_isci_host(i, ihost, pdev) { + sas_suspend_ha(&ihost->sas_ha); + isci_host_deinit(ihost); + } + + pci_save_state(pdev); + pci_disable_device(pdev); + pci_set_power_state(pdev, PCI_D3hot); + + return 0; +} + +static int isci_resume(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct isci_host *ihost; + int rc, i; + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + + rc = pcim_enable_device(pdev); + if (rc) { + dev_err(&pdev->dev, + "enabling device failure after resume(%d)\n", rc); + return rc; + } + + pci_set_master(pdev); + + for_each_isci_host(i, ihost, pdev) { + sas_prep_resume_ha(&ihost->sas_ha); + + isci_host_init(ihost); + isci_host_start(ihost->sas_ha.core.shost); + wait_for_start(ihost); + + sas_resume_ha(&ihost->sas_ha); + } + + return 0; +} + +static SIMPLE_DEV_PM_OPS(isci_pm_ops, isci_suspend, isci_resume); +#endif + static struct pci_driver isci_pci_driver = { .name = DRV_NAME, .id_table = isci_id_table, .probe = isci_pci_probe, .remove = __devexit_p(isci_pci_remove), +#ifdef CONFIG_PM + .driver.pm = &isci_pm_ops, +#endif }; static __init int isci_init(void)