From patchwork Mon May 21 10:09:25 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Garry X-Patchwork-Id: 136438 Delivered-To: patch@linaro.org Received: by 2002:a2e:9706:0:0:0:0:0 with SMTP id r6-v6csp119258lji; Mon, 21 May 2018 03:11:54 -0700 (PDT) X-Google-Smtp-Source: AB8JxZrbIg1JxDjX+IXlXBkDsPl5EnjdzbFJguvl278NAScdL3dAYlZ3pxdoSVnPYWnbSUDd6Vk4 X-Received: by 2002:a17:902:380c:: with SMTP id l12-v6mr19987260plc.19.1526897514754; Mon, 21 May 2018 03:11:54 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1526897514; cv=none; d=google.com; s=arc-20160816; b=c5esXEGxpWcksWZSG8DuiqY50Htj48C9o7CieImrKfhmZSxV8ErhZRoq00U7z6mtyK ec4IlHz86PkgLURHC+CtAFSiULpllSXDV1VBbEemcaBNj07aPHZ7Ab39TJd30KdTiHKl L6KQKxF9/YcKwi3Phqix5Al4z5fhUMZAX9zhOdK/PqCZELFPGpmQaDFC6Xy12ZIaBdU2 Q5xubFZQ4hu9o/boBPWnOnIFHu300vEJINGFD1svCYv/QeelT1amMviS2vOWPa8Czuw/ ttP7ZdcHvIDEYdZoEt6YhxTtrQPikodVgFcHVAI70UTBZd4yD9tV84sheNeeWRf5ol7X uv7Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:arc-authentication-results; bh=WXa+QQQbZNJ0lRnzPrr1mcw03V3a9wRVApowF5W504Q=; b=CSUfP+ecdjUPl2blsIwmZDicq5+xUWYjyrmLpkAKuuyVK7PacR+vtAmzzUaDkDrK5W JCzPKQLqsVl9sR7nrGkprcbMu9CoLwXgU/0kBjOn8X9VHLJTs7LnpOfb69d/OElMUTwV N/7WitQDJ57IyIHILHPWHA2DR4ywXOrIs6cGafw7QS9ukYebJZUPSrD4KqcTb4nbEiN8 35JW7txGkfxuZ8pfpy7SMVHhEWYmzWn2oZmEDwR4NgtX9PY5202WssAKoqRuXZFp3MSW uNM9/gK2Iuamag9ktkyVZL+rBoxUA+4Le3h/se7Psuc1/JlVqz5x6mAl9OF5MFv6SNA1 4IFA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id v24-v6si14404829pfj.292.2018.05.21.03.11.54; Mon, 21 May 2018 03:11:54 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752720AbeEUKLv (ORCPT + 29 others); Mon, 21 May 2018 06:11:51 -0400 Received: from szxga07-in.huawei.com ([45.249.212.35]:55825 "EHLO huawei.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1752643AbeEUKLp (ORCPT ); Mon, 21 May 2018 06:11:45 -0400 Received: from DGGEMS410-HUB.china.huawei.com (unknown [172.30.72.60]) by Forcepoint Email with ESMTP id 963E3CA034686; Mon, 21 May 2018 18:11:40 +0800 (CST) Received: from localhost.localdomain (10.67.212.75) by DGGEMS410-HUB.china.huawei.com (10.3.19.210) with Microsoft SMTP Server id 14.3.382.0; Mon, 21 May 2018 18:11:34 +0800 From: John Garry To: , CC: , , , Xiang Chen , "John Garry" Subject: [PATCH 13/13] scsi: hisi_sas: Mark PHY as in reset for nexus reset Date: Mon, 21 May 2018 18:09:25 +0800 Message-ID: <1526897365-228549-14-git-send-email-john.garry@huawei.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1526897365-228549-1-git-send-email-john.garry@huawei.com> References: <1526897365-228549-1-git-send-email-john.garry@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.67.212.75] X-CFilter-Loop: Reflected Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Xiang Chen When issunig a nexus reset for directly attached device, we want to ignore the PHY down events so libsas will not deform and reform the port. In the case that the attached SAS changes for the reset, libsas will deform and form a port. For scenario that the PHY does not come up after a timeout period, then report the PHY down to libsas. Signed-off-by: Xiang Chen Signed-off-by: John Garry --- drivers/scsi/hisi_sas/hisi_sas.h | 5 ++++- drivers/scsi/hisi_sas/hisi_sas_main.c | 40 ++++++++++++++++++++++++++++++---- drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 8 +++++++ drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 14 ++++++++++++ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 7 ++++++ 5 files changed, 69 insertions(+), 5 deletions(-) -- 1.9.1 diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h index 9400824..7052a5d 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -136,11 +136,14 @@ struct hisi_sas_phy { struct hisi_sas_port *port; struct asd_sas_phy sas_phy; struct sas_identify identify; + struct completion *reset_completion; + spinlock_t lock; u64 port_id; /* from hw */ u64 frame_rcvd_size; u8 frame_rcvd[32]; u8 phy_attached; - u8 reserved[3]; + u8 in_reset; + u8 reserved[2]; u32 phy_type; enum sas_linkrate minimum_linkrate; enum sas_linkrate maximum_linkrate; diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index f6c4eb6..9adf18c 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -1529,12 +1529,39 @@ static int hisi_sas_clear_aca(struct domain_device *device, u8 *lun) static int hisi_sas_debug_I_T_nexus_reset(struct domain_device *device) { - struct sas_phy *phy = sas_get_local_phy(device); + struct sas_phy *local_phy = sas_get_local_phy(device); int rc, reset_type = (device->dev_type == SAS_SATA_DEV || (device->tproto & SAS_PROTOCOL_STP)) ? 0 : 1; - rc = sas_phy_reset(phy, reset_type); - sas_put_local_phy(phy); - msleep(2000); + struct hisi_hba *hisi_hba = dev_to_hisi_hba(device); + struct sas_ha_struct *sas_ha = &hisi_hba->sha; + struct asd_sas_phy *sas_phy = sas_ha->sas_phy[local_phy->number]; + struct hisi_sas_phy *phy = container_of(sas_phy, + struct hisi_sas_phy, sas_phy); + DECLARE_COMPLETION_ONSTACK(phyreset); + + if (scsi_is_sas_phy_local(local_phy)) { + phy->in_reset = 1; + phy->reset_completion = &phyreset; + } + + rc = sas_phy_reset(local_phy, reset_type); + sas_put_local_phy(local_phy); + + if (scsi_is_sas_phy_local(local_phy)) { + int ret = wait_for_completion_timeout(&phyreset, 2 * HZ); + unsigned long flags; + + spin_lock_irqsave(&phy->lock, flags); + phy->reset_completion = NULL; + phy->in_reset = 0; + spin_unlock_irqrestore(&phy->lock, flags); + + /* report PHY down if timed out */ + if (!ret) + hisi_sas_phy_down(hisi_hba, sas_phy->id, 0); + } else + msleep(2000); + return rc; } @@ -1883,6 +1910,7 @@ void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int phy_no, int rdy) struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; struct asd_sas_phy *sas_phy = &phy->sas_phy; struct sas_ha_struct *sas_ha = &hisi_hba->sha; + struct device *dev = hisi_hba->dev; if (rdy) { /* Phy down but ready */ @@ -1891,6 +1919,10 @@ void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int phy_no, int rdy) } else { struct hisi_sas_port *port = phy->port; + if (phy->in_reset) { + dev_info(dev, "ignore flutter phy%d down\n", phy_no); + return; + } /* Phy down and not ready */ sas_ha->notify_phy_event(sas_phy, PHYE_LOSS_OF_SIGNAL); sas_phy_disconnected(sas_phy); diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c index 05609ac..89ab18c 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c @@ -1373,6 +1373,7 @@ static irqreturn_t int_phyup_v1_hw(int irq_no, void *p) u32 *frame_rcvd = (u32 *)sas_phy->frame_rcvd; struct sas_identify_frame *id = (struct sas_identify_frame *)frame_rcvd; irqreturn_t res = IRQ_HANDLED; + unsigned long flags; irq_value = hisi_sas_phy_read32(hisi_hba, phy_no, CHL_INT2); if (!(irq_value & CHL_INT2_SL_PHY_ENA_MSK)) { @@ -1426,6 +1427,13 @@ static irqreturn_t int_phyup_v1_hw(int irq_no, void *p) SAS_PROTOCOL_SMP; hisi_sas_notify_phy_event(phy, HISI_PHYE_PHY_UP); + spin_lock_irqsave(&phy->lock, flags); + if (phy->reset_completion) { + phy->in_reset = 0; + complete(phy->reset_completion); + } + spin_unlock_irqrestore(&phy->lock, flags); + end: hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT2, CHL_INT2_SL_PHY_ENA_MSK); diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index 369ef7e..213c530 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -2661,6 +2661,7 @@ static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba) struct device *dev = hisi_hba->dev; u32 *frame_rcvd = (u32 *)sas_phy->frame_rcvd; struct sas_identify_frame *id = (struct sas_identify_frame *)frame_rcvd; + unsigned long flags; hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_PHY_ENA_MSK, 1); @@ -2713,6 +2714,12 @@ static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba) set_link_timer_quirk(hisi_hba); } hisi_sas_notify_phy_event(phy, HISI_PHYE_PHY_UP); + spin_lock_irqsave(&phy->lock, flags); + if (phy->reset_completion) { + phy->in_reset = 0; + complete(phy->reset_completion); + } + spin_unlock_irqrestore(&phy->lock, flags); end: hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0, @@ -3201,6 +3208,7 @@ static irqreturn_t sata_int_v2_hw(int irq_no, void *p) u32 ent_tmp, ent_msk, ent_int, port_id, link_rate, hard_phy_linkrate; irqreturn_t res = IRQ_HANDLED; u8 attached_sas_addr[SAS_ADDR_SIZE] = {0}; + unsigned long flags; int phy_no, offset; phy_no = sas_phy->id; @@ -3275,6 +3283,12 @@ static irqreturn_t sata_int_v2_hw(int irq_no, void *p) phy->identify.target_port_protocols = SAS_PROTOCOL_SATA; hisi_sas_notify_phy_event(phy, HISI_PHYE_PHY_UP); + spin_lock_irqsave(&phy->lock, flags); + if (phy->reset_completion) { + phy->in_reset = 0; + complete(phy->reset_completion); + } + spin_unlock_irqrestore(&phy->lock, flags); end: hisi_sas_write32(hisi_hba, ENT_INT_SRC1 + offset, ent_tmp); hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1 + offset, ent_msk); diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 8c996aa..9f1e2d0 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -1143,6 +1143,7 @@ static irqreturn_t phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba) struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; struct asd_sas_phy *sas_phy = &phy->sas_phy; struct device *dev = hisi_hba->dev; + unsigned long flags; hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_PHY_ENA_MSK, 1); @@ -1211,6 +1212,12 @@ static irqreturn_t phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba) phy->phy_attached = 1; hisi_sas_notify_phy_event(phy, HISI_PHYE_PHY_UP); res = IRQ_HANDLED; + spin_lock_irqsave(&phy->lock, flags); + if (phy->reset_completion) { + phy->in_reset = 0; + complete(phy->reset_completion); + } + spin_unlock_irqrestore(&phy->lock, flags); end: hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0, CHL_INT0_SL_PHY_ENABLE_MSK);