From patchwork Fri Dec 8 17:16:45 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Garry X-Patchwork-Id: 10102991 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 7F01C602A0 for ; Fri, 8 Dec 2017 16:34:10 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7AA0F28E2B for ; Fri, 8 Dec 2017 16:34:10 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6F68528E2D; Fri, 8 Dec 2017 16:34:10 +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=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=unavailable 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 D590228E2B for ; Fri, 8 Dec 2017 16:34:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753697AbdLHQd5 (ORCPT ); Fri, 8 Dec 2017 11:33:57 -0500 Received: from szxga06-in.huawei.com ([45.249.212.32]:36080 "EHLO huawei.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1754385AbdLHQbF (ORCPT ); Fri, 8 Dec 2017 11:31:05 -0500 Received: from DGGEMS407-HUB.china.huawei.com (unknown [172.30.72.58]) by Forcepoint Email with ESMTP id 5AFF8B1C4B332; Sat, 9 Dec 2017 00:30:50 +0800 (CST) Received: from localhost.localdomain (10.67.212.75) by DGGEMS407-HUB.china.huawei.com (10.3.19.207) with Microsoft SMTP Server id 14.3.361.1; Sat, 9 Dec 2017 00:30:40 +0800 From: John Garry To: , CC: , , , Xiaofei Tan , "John Garry" Subject: [PATCH 14/19] scsi: hisi_sas: do link reset for some CHL_INT2 ints Date: Sat, 9 Dec 2017 01:16:45 +0800 Message-ID: <1512753410-50924-15-git-send-email-john.garry@huawei.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1512753410-50924-1-git-send-email-john.garry@huawei.com> References: <1512753410-50924-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-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Xiaofei Tan We should do link reset of PHY when identify timeout or STP link timeout. They are internal events of SOC and are notified to driver through interrupts of CHL_INT2. Besides, we should add an delay work to do link reset as it needs sleep. So, this patch add an new PHY event HISI_PHYE_LINK_RESET for this. Notes: v2 HW doesn't report the event of STP link timeout. So, we only need to handle event of identify timeout for v2 HW. Signed-off-by: Xiaofei Tan Signed-off-by: John Garry --- drivers/scsi/hisi_sas/hisi_sas.h | 1 + drivers/scsi/hisi_sas/hisi_sas_main.c | 12 ++++++++++++ drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 18 ++++++++++++++---- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 29 +++++++++++++++++++++++++++-- 4 files changed, 54 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h index aa14638..4343c4c 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -126,6 +126,7 @@ enum hisi_sas_bit_err_type { enum hisi_sas_phy_event { HISI_PHYE_PHY_UP = 0U, + HISI_PHYE_LINK_RESET, HISI_PHYES_NUM, }; diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 326dc81..7446a39 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -22,6 +22,8 @@ static int hisi_sas_debug_issue_ssp_tmf(struct domain_device *device, struct domain_device *device, int abort_flag, int tag); static int hisi_sas_softreset_ata_disk(struct domain_device *device); +static int hisi_sas_control_phy(struct asd_sas_phy *sas_phy, enum phy_func func, + void *funcdata); u8 hisi_sas_get_ata_protocol(u8 cmd, int direction) { @@ -631,8 +633,18 @@ static void hisi_sas_phyup_work(struct work_struct *work) hisi_sas_bytes_dmaed(hisi_hba, phy_no); } +static void hisi_sas_linkreset_work(struct work_struct *work) +{ + struct hisi_sas_phy *phy = + container_of(work, typeof(*phy), works[HISI_PHYE_LINK_RESET]); + struct asd_sas_phy *sas_phy = &phy->sas_phy; + + hisi_sas_control_phy(sas_phy, PHY_FUNC_LINK_RESET, NULL); +} + static const work_func_t hisi_sas_phye_fns[HISI_PHYES_NUM] = { [HISI_PHYE_PHY_UP] = hisi_sas_phyup_work, + [HISI_PHYE_LINK_RESET] = hisi_sas_linkreset_work, }; bool hisi_sas_notify_phy_event(struct hisi_sas_phy *phy, diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index e521c42..b8fe08d 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -245,6 +245,7 @@ #define CHL_INT1_DMAC_RX_AXI_WR_ERR_OFF 21 #define CHL_INT1_DMAC_RX_AXI_RD_ERR_OFF 22 #define CHL_INT2 (PORT_BASE + 0x1bc) +#define CHL_INT2_SL_IDAF_TOUT_CONF_OFF 0 #define CHL_INT0_MSK (PORT_BASE + 0x1c0) #define CHL_INT1_MSK (PORT_BASE + 0x1c4) #define CHL_INT2_MSK (PORT_BASE + 0x1c8) @@ -1187,7 +1188,7 @@ static void init_reg_v2_hw(struct hisi_hba *hisi_hba) hisi_sas_phy_write32(hisi_hba, i, CHL_INT2, 0xfff87fff); hisi_sas_phy_write32(hisi_hba, i, RXOP_CHECK_CFG_H, 0x1000); hisi_sas_phy_write32(hisi_hba, i, CHL_INT1_MSK, 0xff857fff); - hisi_sas_phy_write32(hisi_hba, i, CHL_INT2_MSK, 0x8ffffbff); + hisi_sas_phy_write32(hisi_hba, i, CHL_INT2_MSK, 0x8ffffbfe); hisi_sas_phy_write32(hisi_hba, i, SL_CFG, 0x13f801fc); hisi_sas_phy_write32(hisi_hba, i, PHY_CTRL_RDY_MSK, 0x0); hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_NOT_RDY_MSK, 0x0); @@ -2905,10 +2906,19 @@ static irqreturn_t int_chnl_int_v2_hw(int irq_no, void *p) CHL_INT1, irq_value1); } - if ((irq_msk & (1 << phy_no)) && irq_value2) - hisi_sas_phy_write32(hisi_hba, phy_no, - CHL_INT2, irq_value2); + if ((irq_msk & (1 << phy_no)) && irq_value2) { + struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; + + if (irq_value2 & BIT(CHL_INT2_SL_IDAF_TOUT_CONF_OFF)) { + dev_warn(dev, "phy%d identify timeout\n", + phy_no); + hisi_sas_notify_phy_event(phy, + HISI_PHYE_LINK_RESET); + } + hisi_sas_phy_write32(hisi_hba, phy_no, + CHL_INT2, irq_value2); + } if ((irq_msk & (1 << phy_no)) && irq_value0) { if (irq_value0 & CHL_INT0_SL_RX_BCST_ACK_MSK) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 4b7f251..9e32105 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -140,6 +140,7 @@ #define RX_IDAF_DWORD0 (PORT_BASE + 0xc4) #define RXOP_CHECK_CFG_H (PORT_BASE + 0xfc) #define STP_LINK_TIMER (PORT_BASE + 0x120) +#define STP_LINK_TIMEOUT_STATE (PORT_BASE + 0x124) #define CON_CFG_DRIVER (PORT_BASE + 0x130) #define SAS_SSP_CON_TIMER_CFG (PORT_BASE + 0x134) #define SAS_SMP_CON_TIMER_CFG (PORT_BASE + 0x138) @@ -165,6 +166,8 @@ #define CHL_INT1_DMAC_RX_AXI_WR_ERR_OFF 21 #define CHL_INT1_DMAC_RX_AXI_RD_ERR_OFF 22 #define CHL_INT2 (PORT_BASE + 0x1bc) +#define CHL_INT2_SL_IDAF_TOUT_CONF_OFF 0 +#define CHL_INT2_STP_LINK_TIMEOUT_OFF 31 #define CHL_INT0_MSK (PORT_BASE + 0x1c0) #define CHL_INT1_MSK (PORT_BASE + 0x1c4) #define CHL_INT2_MSK (PORT_BASE + 0x1c8) @@ -429,7 +432,7 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba) hisi_sas_phy_write32(hisi_hba, i, CHL_INT2, 0xffffffff); hisi_sas_phy_write32(hisi_hba, i, RXOP_CHECK_CFG_H, 0x1000); hisi_sas_phy_write32(hisi_hba, i, CHL_INT1_MSK, 0xff87ffff); - hisi_sas_phy_write32(hisi_hba, i, CHL_INT2_MSK, 0x8ffffbff); + hisi_sas_phy_write32(hisi_hba, i, CHL_INT2_MSK, 0xffffbfe); hisi_sas_phy_write32(hisi_hba, i, PHY_CTRL_RDY_MSK, 0x0); hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_NOT_RDY_MSK, 0x0); hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_DWS_RESET_MSK, 0x0); @@ -1342,9 +1345,31 @@ static irqreturn_t int_chnl_int_v3_hw(int irq_no, void *p) CHL_INT1, irq_value1); } - if (irq_msk & (8 << (phy_no * 4)) && irq_value2) + if (irq_msk & (8 << (phy_no * 4)) && irq_value2) { + struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; + + if (irq_value2 & BIT(CHL_INT2_SL_IDAF_TOUT_CONF_OFF)) { + dev_warn(dev, "phy%d identify timeout\n", + phy_no); + hisi_sas_notify_phy_event(phy, + HISI_PHYE_LINK_RESET); + + } + + if (irq_value2 & BIT(CHL_INT2_STP_LINK_TIMEOUT_OFF)) { + u32 reg_value = hisi_sas_phy_read32(hisi_hba, + phy_no, STP_LINK_TIMEOUT_STATE); + + dev_warn(dev, "phy%d stp link timeout (0x%x)\n", + phy_no, reg_value); + if (reg_value & BIT(4)) + hisi_sas_notify_phy_event(phy, + HISI_PHYE_LINK_RESET); + } + hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT2, irq_value2); + } if (irq_msk & (2 << (phy_no * 4)) && irq_value0) {