From patchwork Sat Jan 14 18:10:24 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Williams X-Patchwork-Id: 136087 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 43DDCB6F67 for ; Sun, 15 Jan 2012 05:10:31 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756031Ab2ANSK3 (ORCPT ); Sat, 14 Jan 2012 13:10:29 -0500 Received: from mga09.intel.com ([134.134.136.24]:24603 "EHLO mga09.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755902Ab2ANSK3 (ORCPT ); Sat, 14 Jan 2012 13:10:29 -0500 Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga102.jf.intel.com with ESMTP; 14 Jan 2012 10:10:24 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.67,351,1309762800"; d="scan'208";a="98504177" Received: from dwillia2-linux.jf.intel.com (HELO dwillia2-linux.localdomain) ([10.23.45.73]) by orsmga002.jf.intel.com with ESMTP; 14 Jan 2012 10:10:24 -0800 Received: from localhost6.localdomain6 (localhost.localdomain [127.0.0.1]) by dwillia2-linux.localdomain (Postfix) with ESMTP id 8C314500248; Sat, 14 Jan 2012 10:10:24 -0800 (PST) Subject: [PATCH v5 4/7] libsas: route local link resets through ata-eh To: linux-scsi@vger.kernel.org From: Dan Williams Cc: linux-ide@vger.kernel.org, Jacek Danecki Date: Sat, 14 Jan 2012 10:10:24 -0800 Message-ID: <20120114181021.25887.5209.stgit@localhost6.localdomain6> In-Reply-To: <20120114180904.25887.75601.stgit@localhost6.localdomain6> References: <20120114180904.25887.75601.stgit@localhost6.localdomain6> User-Agent: StGit/0.15-7-g9bfb-dirty MIME-Version: 1.0 Sender: linux-ide-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ide@vger.kernel.org Similar to the conversion of the transport-class reset we want bsg initiated resets to be managed by libata. Reported-by: Jacek Danecki Signed-off-by: Dan Williams --- drivers/scsi/libsas/sas_host_smp.c | 11 ++++++++- drivers/scsi/libsas/sas_init.c | 45 +++++++++++++++++++++--------------- drivers/scsi/libsas/sas_internal.h | 1 + 3 files changed, 37 insertions(+), 20 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/libsas/sas_host_smp.c b/drivers/scsi/libsas/sas_host_smp.c index bb8f492..e921e53 100644 --- a/drivers/scsi/libsas/sas_host_smp.c +++ b/drivers/scsi/libsas/sas_host_smp.c @@ -187,11 +187,14 @@ static void sas_phy_control(struct sas_ha_struct *sas_ha, u8 phy_id, struct sas_internal *i = to_sas_internal(sas_ha->core.shost->transportt); struct sas_phy_linkrates rates; + struct asd_sas_phy *asd_phy; if (phy_id >= sas_ha->num_phys) { resp_data[2] = SMP_RESP_NO_PHY; return; } + + asd_phy = sas_ha->sas_phy[phy_id]; switch (phy_op) { case PHY_FUNC_NOP: case PHY_FUNC_LINK_RESET: @@ -210,7 +213,13 @@ static void sas_phy_control(struct sas_ha_struct *sas_ha, u8 phy_id, rates.minimum_linkrate = min; rates.maximum_linkrate = max; - if (i->dft->lldd_control_phy(sas_ha->sas_phy[phy_id], phy_op, &rates)) + /* filter reset requests through libata eh */ + if (phy_op == PHY_FUNC_LINK_RESET && sas_try_ata_reset(asd_phy) == 0) { + resp_data[2] = SMP_RESP_FUNC_ACC; + return; + } + + if (i->dft->lldd_control_phy(asd_phy, phy_op, &rates)) resp_data[2] = SMP_RESP_FUNC_FAILED; else resp_data[2] = SMP_RESP_FUNC_ACC; diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c index cf1b532..dc93e118 100644 --- a/drivers/scsi/libsas/sas_init.c +++ b/drivers/scsi/libsas/sas_init.c @@ -196,6 +196,27 @@ static int sas_get_linkerrors(struct sas_phy *phy) return sas_smp_get_phy_events(phy); } +int sas_try_ata_reset(struct asd_sas_phy *asd_phy) +{ + struct domain_device *dev = NULL; + + /* try to route user requested link resets through libata */ + if (asd_phy->port) + dev = asd_phy->port->port_dev; + + /* validate that dev has been probed */ + if (dev) + dev = sas_find_dev_by_rphy(dev->rphy); + + if (dev && dev_is_sata(dev)) { + sas_ata_schedule_reset(dev); + sas_ata_wait_eh(dev); + return 0; + } + + return -ENODEV; +} + /** * transport_sas_phy_reset - reset a phy and permit libata to manage the link * @@ -204,7 +225,6 @@ static int sas_get_linkerrors(struct sas_phy *phy) */ static int transport_sas_phy_reset(struct sas_phy *phy, int hard_reset) { - int ret; enum phy_func reset_type; if (hard_reset) @@ -218,21 +238,10 @@ static int transport_sas_phy_reset(struct sas_phy *phy, int hard_reset) struct asd_sas_phy *asd_phy = sas_ha->sas_phy[phy->number]; struct sas_internal *i = to_sas_internal(sas_ha->core.shost->transportt); - struct domain_device *dev = NULL; - - if (asd_phy->port) - dev = asd_phy->port->port_dev; - - /* validate that dev has been probed */ - if (dev) - dev = sas_find_dev_by_rphy(dev->rphy); - if (dev && dev_is_sata(dev) && !hard_reset) { - sas_ata_schedule_reset(dev); - sas_ata_wait_eh(dev); - ret = 0; - } else - ret = i->dft->lldd_control_phy(asd_phy, reset_type, NULL); + if (!hard_reset && sas_try_ata_reset(asd_phy) == 0) + return 0; + return i->dft->lldd_control_phy(asd_phy, reset_type, NULL); } else { struct sas_rphy *rphy = dev_to_rphy(phy->dev.parent); struct domain_device *ddev = sas_find_dev_by_rphy(rphy); @@ -241,12 +250,10 @@ static int transport_sas_phy_reset(struct sas_phy *phy, int hard_reset) if (ata_dev && !hard_reset) { sas_ata_schedule_reset(ata_dev); sas_ata_wait_eh(ata_dev); - ret = 0; + return 0; } else - ret = sas_smp_phy_control(ddev, phy->number, reset_type, NULL); + return sas_smp_phy_control(ddev, phy->number, reset_type, NULL); } - - return ret; } static int sas_phy_enable(struct sas_phy *phy, int enable) diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h index c8febc7..4157f6e 100644 --- a/drivers/scsi/libsas/sas_internal.h +++ b/drivers/scsi/libsas/sas_internal.h @@ -92,6 +92,7 @@ struct domain_device *sas_find_dev_by_rphy(struct sas_rphy *rphy); struct domain_device *sas_ex_to_ata(struct domain_device *ex_dev, int phy_id); int sas_get_phy_attached_sas_addr(struct domain_device *dev, int phy_id, u8 *attached_sas_addr); +int sas_try_ata_reset(struct asd_sas_phy *phy); void sas_hae_reset(struct work_struct *work); void sas_free_device(struct kref *kref);