From patchwork Mon Dec 17 08:47:40 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shivasharan Srikanteshwara X-Patchwork-Id: 10732941 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 BE6B7746 for ; Mon, 17 Dec 2018 08:48:03 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AF38829DA3 for ; Mon, 17 Dec 2018 08:48:03 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A08F829DA6; Mon, 17 Dec 2018 08:48:03 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,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 D923129DA3 for ; Mon, 17 Dec 2018 08:48:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731883AbeLQIsC (ORCPT ); Mon, 17 Dec 2018 03:48:02 -0500 Received: from mail-pf1-f193.google.com ([209.85.210.193]:39328 "EHLO mail-pf1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726766AbeLQIsC (ORCPT ); Mon, 17 Dec 2018 03:48:02 -0500 Received: by mail-pf1-f193.google.com with SMTP id c72so6023901pfc.6 for ; Mon, 17 Dec 2018 00:48:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=jjkzC/7BFHN+9v+xPZYTrQDXyXyIa4k34r9XQFOpLL4=; b=B6oaFTt3/PfS8yTgA/LLZ+QeFg63YghAVHOo6jDEAAsvcL+Z38UxAFNDwotCUGioSt 7x7PMxNmHBHDff97f74iHGYbrHk2O73Dn2yC4ihEWdgpuoeI2tB7xL2lMCePOyXif8K9 4pEjqVnc5PQZOUpclLelGUSK9Sa2Ob5usfUF8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=jjkzC/7BFHN+9v+xPZYTrQDXyXyIa4k34r9XQFOpLL4=; b=B8eVyqpgv+1dcQoHurNTS3LSxYoqGSAWSFIzdb17b3BkHSp2ryoulcMgyRqnPIVfDe zRmHpPTawncOG5kfuMyVzN/lSd7Qk1X+gVXCjELlo09Y/faPSepMIR1UuZN7qfiC5uX/ goBDIAVEQtzIC5UHOk0FiZsX59s4oaAD5/GTiYzCAT5pA2M29NXjQ969s3TgZYYi+SOO H0DsNFG38MK87xR0U/GwspTPPyBGjhLrl1ALGeUpFvk9EZCzKGyxBGahi+W4TvigK5Gx Isr4U5lAxcovyOn/6leP95gpGdzCzP31lc1Y9jQhtpg4ukCUB5v6mAEVxiNx4Rm3NRre FaWg== X-Gm-Message-State: AA+aEWa1S3WpjCDjJn0BCvtj68es3bf0/UnRxp+AGwYjyHd6PbTjtxvn o+GvQP2Dmmqd4xJCTJR2cqpZYXti1/A= X-Google-Smtp-Source: AFSGD/W2oBCAiQ/SwDS0Kpo531Y8fPeSqVCietQqQ0GT62dANlsYcBuWJKIqaDilK3JQvTADITfp0w== X-Received: by 2002:a62:7652:: with SMTP id r79mr12507495pfc.241.1545036479889; Mon, 17 Dec 2018 00:47:59 -0800 (PST) Received: from dhcp-135-24-192-142.dhcp.broadcom.net ([192.19.234.250]) by smtp.gmail.com with ESMTPSA id l85sm19837589pfg.161.2018.12.17.00.47.57 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 17 Dec 2018 00:47:59 -0800 (PST) From: Shivasharan S To: linux-scsi@vger.kernel.org Cc: kashyap.desai@broadcom.com, sumit.saxena@broadcom.com, Shivasharan S Subject: [PATCH 4/4] megaraid_sas: add retry logic in megasas_readl Date: Mon, 17 Dec 2018 00:47:40 -0800 Message-Id: <1545036460-28624-5-git-send-email-shivasharan.srikanteshwara@broadcom.com> X-Mailer: git-send-email 2.4.3 In-Reply-To: <1545036460-28624-1-git-send-email-shivasharan.srikanteshwara@broadcom.com> References: <1545036460-28624-1-git-send-email-shivasharan.srikanteshwara@broadcom.com> 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 Problem statement: Due to hardware errata in Aero controllers, reads to certain fusion registers could intermittently return zero. This behavior is transient in nature and subsequent reads will return valid value. Fix: For Aero controllers, any calls to readl to read from certain registers, will be retried for maximum three times, if read returns zero. Signed-off-by: Shivasharan S --- drivers/scsi/megaraid/megaraid_sas_base.c | 39 +++++++++++++++++++++++------ drivers/scsi/megaraid/megaraid_sas_fusion.c | 28 +++++++++++++-------- 2 files changed, 49 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 1d2272fddc5f..d4e3df320a0c 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -220,6 +220,28 @@ megasas_free_ctrl_dma_buffers(struct megasas_instance *instance); static inline void megasas_init_ctrl_params(struct megasas_instance *instance); +u32 megasas_readl(struct megasas_instance *instance, + const volatile void __iomem *addr) +{ + u32 i = 0, ret_val; + /* + * Due to a HW errata in Aero controllers, reads to certain + * Fusion registers could intermittently return all zeroes. + * This behavior is transient in nature and subsequent reads will + * return valid value. As a workaround in driver, retry readl for + * upto three times until a non-zero value is read. + */ + if (instance->adapter_type == AERO_SERIES) { + do { + ret_val = readl(addr); + i++; + } while (ret_val == 0 && i < 3); + return ret_val; + } else { + return readl(addr); + } +} + /** * megasas_set_dma_settings - Populate DMA address, length and flags for DCMDs * @instance: Adapter soft state @@ -3842,7 +3864,8 @@ megasas_transition_to_ready(struct megasas_instance *instance, int ocr) if (instance->adapter_type != MFI_SERIES) { for (i = 0; i < (10 * 1000); i += 20) { - if (readl( + if (megasas_readl( + instance, &instance-> reg_set-> doorbell) & 1) @@ -5401,7 +5424,8 @@ static int megasas_init_fw(struct megasas_instance *instance) if (instance->adapter_type >= VENTURA_SERIES) { scratch_pad_2 = - readl(&instance->reg_set->outbound_scratch_pad_2); + megasas_readl(instance, + &instance->reg_set->outbound_scratch_pad_2); instance->max_raid_mapsize = ((scratch_pad_2 >> MR_MAX_RAID_MAP_SIZE_OFFSET_SHIFT) & MR_MAX_RAID_MAP_SIZE_MASK); @@ -5413,8 +5437,8 @@ static int megasas_init_fw(struct megasas_instance *instance) if (msix_enable && !msix_disable) { int irq_flags = PCI_IRQ_MSIX; - scratch_pad_1 = readl - (&instance->reg_set->outbound_scratch_pad_1); + scratch_pad_1 = megasas_readl + (instance, &instance->reg_set->outbound_scratch_pad_1); /* Check max MSI-X vectors */ if (fusion) { if (instance->adapter_type == THUNDERBOLT_SERIES) { @@ -5525,7 +5549,8 @@ static int megasas_init_fw(struct megasas_instance *instance) if (instance->adapter_type >= VENTURA_SERIES) { scratch_pad_3 = - readl(&instance->reg_set->outbound_scratch_pad_3); + megasas_readl(instance, + &instance->reg_set->outbound_scratch_pad_3); if ((scratch_pad_3 & MR_NVME_PAGE_SIZE_MASK) >= MR_DEFAULT_NVME_PAGE_SHIFT) instance->nvme_page_size = @@ -6193,8 +6218,8 @@ megasas_set_dma_mask(struct megasas_instance *instance) * If 32 bit DMA mask fails, then try for 64 bit mask * for FW capable of handling 64 bit DMA. */ - scratch_pad_1 = readl - (&instance->reg_set->outbound_scratch_pad_1); + scratch_pad_1 = megasas_readl + (instance, &instance->reg_set->outbound_scratch_pad_1); if (!(scratch_pad_1 & MR_CAN_HANDLE_64_BIT_DMA_OFFSET)) goto fail_set_dma_mask; diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index e4c3edc73099..50e2ed865041 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -95,6 +95,8 @@ static void megasas_free_reply_fusion(struct megasas_instance *instance); static inline void megasas_configure_queue_sizes(struct megasas_instance *instance); static void megasas_fusion_crash_dump(struct megasas_instance *instance); +extern u32 megasas_readl(struct megasas_instance *instance, + const volatile void __iomem *addr); /** * megasas_check_same_4gb_region - check if allocation @@ -267,7 +269,8 @@ megasas_fusion_update_can_queue(struct megasas_instance *instance, int fw_boot_c /* ventura FW does not fill outbound_scratch_pad_2 with queue depth */ if (instance->adapter_type < VENTURA_SERIES) cur_max_fw_cmds = - readl(&instance->reg_set->outbound_scratch_pad_2) & 0x00FFFF; + megasas_readl(instance, + &instance->reg_set->outbound_scratch_pad_2) & 0x00FFFF; if (dual_qdepth_disable || !cur_max_fw_cmds) cur_max_fw_cmds = instance->instancet->read_fw_status_reg(instance) & 0x00FFFF; @@ -984,8 +987,8 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) cmd = fusion->ioc_init_cmd; - scratch_pad_1 = readl - (&instance->reg_set->outbound_scratch_pad_1); + scratch_pad_1 = megasas_readl + (instance, &instance->reg_set->outbound_scratch_pad_1); cur_rdpq_mode = (scratch_pad_1 & MR_RDPQ_MODE_OFFSET) ? 1 : 0; @@ -1104,7 +1107,7 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) instance->instancet->disable_intr(instance); for (i = 0; i < (10 * 1000); i += 20) { - if (readl(&instance->reg_set->doorbell) & 1) + if (megasas_readl(instance, &instance->reg_set->doorbell) & 1) msleep(20); else break; @@ -1653,7 +1656,8 @@ megasas_init_adapter_fusion(struct megasas_instance *instance) megasas_configure_queue_sizes(instance); - scratch_pad_1 = readl(&instance->reg_set->outbound_scratch_pad_1); + scratch_pad_1 = megasas_readl(instance, + &instance->reg_set->outbound_scratch_pad_1); /* If scratch_pad_1 & MEGASAS_MAX_CHAIN_SIZE_UNITS_MASK is set, * Firmware support extended IO chain frame which is 4 times more than * legacy Firmware. @@ -3731,7 +3735,7 @@ megasas_release_fusion(struct megasas_instance *instance) static u32 megasas_read_fw_status_reg_fusion(struct megasas_instance *instance) { - return readl(&instance->reg_set->outbound_scratch_pad_0); + return megasas_readl(instance, &instance->reg_set->outbound_scratch_pad_0); } /** @@ -3793,11 +3797,12 @@ megasas_adp_reset_fusion(struct megasas_instance *instance, writel(MPI2_WRSEQ_6TH_KEY_VALUE, &instance->reg_set->fusion_seq_offset); /* Check that the diag write enable (DRWE) bit is on */ - host_diag = readl(&instance->reg_set->fusion_host_diag); + host_diag = megasas_readl(instance, &instance->reg_set->fusion_host_diag); retry = 0; while (!(host_diag & HOST_DIAG_WRITE_ENABLE)) { msleep(100); - host_diag = readl(&instance->reg_set->fusion_host_diag); + host_diag = megasas_readl(instance, + &instance->reg_set->fusion_host_diag); if (retry++ == 100) { dev_warn(&instance->pdev->dev, "Host diag unlock failed from %s %d\n", @@ -3814,11 +3819,12 @@ megasas_adp_reset_fusion(struct megasas_instance *instance, msleep(3000); /* Make sure reset adapter bit is cleared */ - host_diag = readl(&instance->reg_set->fusion_host_diag); + host_diag = megasas_readl(instance, &instance->reg_set->fusion_host_diag); retry = 0; while (host_diag & HOST_DIAG_RESET_ADAPTER) { msleep(100); - host_diag = readl(&instance->reg_set->fusion_host_diag); + host_diag = megasas_readl(instance, + &instance->reg_set->fusion_host_diag); if (retry++ == 1000) { dev_warn(&instance->pdev->dev, "Diag reset adapter never cleared %s %d\n", @@ -4607,7 +4613,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int reason) dev_info(&instance->pdev->dev, "IO/DCMD timeout is detected, " "forcibly FAULT Firmware\n"); atomic_set(&instance->adprecovery, MEGASAS_ADPRESET_SM_INFAULT); - status_reg = readl(&instance->reg_set->doorbell); + status_reg = megasas_readl(instance, &instance->reg_set->doorbell); writel(status_reg | MFI_STATE_FORCE_OCR, &instance->reg_set->doorbell); readl(&instance->reg_set->doorbell);