From patchwork Mon Dec 20 14:11:51 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sreekanth Reddy X-Patchwork-Id: 526247 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B0DC7C433EF for ; Mon, 20 Dec 2021 14:04:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232240AbhLTOEr (ORCPT ); Mon, 20 Dec 2021 09:04:47 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51732 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229459AbhLTOEl (ORCPT ); Mon, 20 Dec 2021 09:04:41 -0500 Received: from mail-pg1-x52c.google.com (mail-pg1-x52c.google.com [IPv6:2607:f8b0:4864:20::52c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D9144C06173E for ; Mon, 20 Dec 2021 06:04:40 -0800 (PST) Received: by mail-pg1-x52c.google.com with SMTP id r138so9468043pgr.13 for ; Mon, 20 Dec 2021 06:04:40 -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 :mime-version; bh=n9PwOpcnb6Fkn0c2AjAMOkxIYiAwL5ct6ODl0noOYWs=; b=SpXtpJ7GMHHhpaN6VRhzX4zDyw1THmRBwlydoGRFHOUy+6kimYVWErnu+pdMni4FmU +tVT/yaFNToj0UUKAR2DUxWYflj5Qr5iB2SQdcwrJaaveAc58G1MuNQmgaXA27P2Q/X/ ssGTQfpGb5YE1f/weYlN/GUI0T7333VGjeD3M= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version; bh=n9PwOpcnb6Fkn0c2AjAMOkxIYiAwL5ct6ODl0noOYWs=; b=2g3IxrPmZhItS4IzvzO3nC4THVrlk/MDu0z9CaRfcf7IWbvdiOeV7xxccsSNxdIjgd 6QsItQOJHcR/zR7XBsZRI63ptVAaiX5RqpPdGan4Opu3IVwQddcOWwASr/yGOvol1o5F fmiiO6gXpGd/QACIS99BMWaP2e9g4OXXAFTzGe987g/0KJ/Vwqd28pru80CKAmopP6bc r1TV8QI2QdCeThloFiuGs/FXlyN12JaPK0Yd4dlRuCdANW0RBwoDOql1XzROsNRKU3e3 YYxZKkCA2gAkTOcEA/0ctmtqpe0LSZGUkNnKSmqfNtNzx98rrwUA45cNzY6hVldVXARb 0wbw== X-Gm-Message-State: AOAM533YsMw1T9F8+bmzkZd5ICOiopE+rgVj71xKe4wPLlsGn0AEnk1S F6xlNarzIa59+adfrpDmNWFsbbYEntSzwNlLdiB6umWTBcWd1ZvruR8RoIXiqzjKuIeaWvRoZRY g+ZI9wwHa6QYdXY+rH25yP4nvJr3Yx6p3Hdy2bdBkaNIVLMkxz5FZdWdd1GmGjhUt0lV6yzBPe8 jsIBkF2L80 X-Google-Smtp-Source: ABdhPJwU68+Jmhg9InsfHgb5nEJp+4dRI0oSLjx3kg6wvVCBYjiYJIj6KaSyGg2PMeGIT0g++qyQjg== X-Received: by 2002:a65:58ca:: with SMTP id e10mr15230696pgu.116.1640009079827; Mon, 20 Dec 2021 06:04:39 -0800 (PST) Received: from dhcp-10-123-20-36.dhcp.broadcom.net ([192.19.234.250]) by smtp.gmail.com with ESMTPSA id b4sm5434180pjm.17.2021.12.20.06.04.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 20 Dec 2021 06:04:39 -0800 (PST) From: Sreekanth Reddy To: linux-scsi@vger.kernel.org Cc: martin.petersen@oracle.com, mpi3mr-linuxdrv.pdl@broadcom.com, Sreekanth Reddy Subject: [PATCH 17/25] mpi3mr: Gracefully handle online FW update operation Date: Mon, 20 Dec 2021 19:41:51 +0530 Message-Id: <20211220141159.16117-18-sreekanth.reddy@broadcom.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20211220141159.16117-1-sreekanth.reddy@broadcom.com> References: <20211220141159.16117-1-sreekanth.reddy@broadcom.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org The driver is enhanced to gracefully handle discrepancies in certain key data sizes between firmware update operations as mentioned below, - The driver displays an error message and marks the controller as unrecoverable if the firmware reports ReplyFrameSize that is greater than the current ReplyFrameSize. - If the firmware reports ReplyFrameSize greater than the current ReplyFrameSize then the driver uses the current ReplyFrameSize while copying the reply messages. - The driver displays an error message and marks the controller as unrecoverable if the firmware reports MaxOperationalReplyQueues less than the currently allocated operational reply queues count. - If the firmware reports MaxOperationalReplyQueues that is greater than the currently allocated operational reply queue count then the driver ignores the new increased value and uses the previously allocated number of operational queues only. - If the firmware reports MaxDevHandle greater than the previously used MaxDevHandle value after a reset then the driver re-allocates the 'device remove pending bitmap' buffer with the newer size using krealloc(). Signed-off-by: Sreekanth Reddy --- drivers/scsi/mpi3mr/mpi3mr.h | 1 + drivers/scsi/mpi3mr/mpi3mr_fw.c | 109 ++++++++++++++++++++++++++------ 2 files changed, 92 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h index b24efe2..24b65bb 100644 --- a/drivers/scsi/mpi3mr/mpi3mr.h +++ b/drivers/scsi/mpi3mr/mpi3mr.h @@ -752,6 +752,7 @@ struct mpi3mr_ioc { dma_addr_t reply_buf_dma_max_address; u16 reply_free_qsz; + u16 reply_sz; struct dma_pool *reply_free_q_pool; __le64 *reply_free_q; dma_addr_t reply_free_q_dma; diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c index 4d048e5..4050195 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c @@ -13,6 +13,8 @@ static int mpi3mr_issue_reset(struct mpi3mr_ioc *mrioc, u16 reset_type, u32 reset_reason); static int mpi3mr_setup_admin_qpair(struct mpi3mr_ioc *mrioc); +static void mpi3mr_process_factsdata(struct mpi3mr_ioc *mrioc, + struct mpi3_ioc_facts_data *facts_data); #if defined(writeq) && defined(CONFIG_64BIT) static inline void mpi3mr_writeq(__u64 b, volatile void __iomem *addr) @@ -376,7 +378,7 @@ static void mpi3mr_process_admin_reply_desc(struct mpi3mr_ioc *mrioc, if (def_reply) { cmdptr->state |= MPI3MR_CMD_REPLY_VALID; memcpy((u8 *)cmdptr->reply, (u8 *)def_reply, - mrioc->facts.reply_sz); + mrioc->reply_sz); } if (cmdptr->is_waiting) { complete(&cmdptr->done); @@ -996,6 +998,66 @@ static int mpi3mr_issue_and_process_mur(struct mpi3mr_ioc *mrioc, return retval; } +/** + * mpi3mr_revalidate_factsdata - validate IOCFacts parameters + * during reset/resume + * @mrioc: Adapter instance reference + * + * Return zero if the new IOCFacts parameters value is compatible with + * older values else return -EPERM + */ +static int +mpi3mr_revalidate_factsdata(struct mpi3mr_ioc *mrioc) +{ + u16 dev_handle_bitmap_sz; + void *removepend_bitmap; + + if (mrioc->facts.reply_sz > mrioc->reply_sz) { + ioc_err(mrioc, + "cannot increase reply size from %d to %d\n", + mrioc->reply_sz, mrioc->facts.reply_sz); + return -EPERM; + } + + if (mrioc->facts.max_op_reply_q < mrioc->num_op_reply_q) { + ioc_err(mrioc, + "cannot reduce number of operational reply queues from %d to %d\n", + mrioc->num_op_reply_q, + mrioc->facts.max_op_reply_q); + return -EPERM; + } + + if (mrioc->facts.max_op_req_q < mrioc->num_op_req_q) { + ioc_err(mrioc, + "cannot reduce number of operational request queues from %d to %d\n", + mrioc->num_op_req_q, mrioc->facts.max_op_req_q); + return -EPERM; + } + + dev_handle_bitmap_sz = mrioc->facts.max_devhandle / 8; + if (mrioc->facts.max_devhandle % 8) + dev_handle_bitmap_sz++; + if (dev_handle_bitmap_sz > mrioc->dev_handle_bitmap_sz) { + removepend_bitmap = krealloc(mrioc->removepend_bitmap, + dev_handle_bitmap_sz, GFP_KERNEL); + if (!removepend_bitmap) { + ioc_err(mrioc, + "failed to increase removepend_bitmap sz from: %d to %d\n", + mrioc->dev_handle_bitmap_sz, dev_handle_bitmap_sz); + return -EPERM; + } + memset(removepend_bitmap + mrioc->dev_handle_bitmap_sz, 0, + dev_handle_bitmap_sz - mrioc->dev_handle_bitmap_sz); + mrioc->removepend_bitmap = removepend_bitmap; + ioc_info(mrioc, + "increased dev_handle_bitmap_sz from %d to %d\n", + mrioc->dev_handle_bitmap_sz, dev_handle_bitmap_sz); + mrioc->dev_handle_bitmap_sz = dev_handle_bitmap_sz; + } + + return 0; +} + /** * mpi3mr_bring_ioc_ready - Bring controller to ready state * @mrioc: Adapter instance reference @@ -1854,8 +1916,13 @@ static int mpi3mr_create_op_queues(struct mpi3mr_ioc *mrioc) mrioc->intr_info_count - mrioc->op_reply_q_offset; if (!mrioc->num_queues) mrioc->num_queues = min_t(int, num_queues, msix_count_op_q); - num_queues = mrioc->num_queues; - ioc_info(mrioc, "Trying to create %d Operational Q pairs\n", + /* + * During reset set the num_queues to the number of queues + * that was set before the reset. + */ + num_queues = mrioc->num_op_reply_q ? + mrioc->num_op_reply_q : mrioc->num_queues; + ioc_info(mrioc, "trying to create %d operational queue pairs\n", num_queues); if (!mrioc->req_qinfo) { @@ -2447,6 +2514,7 @@ static int mpi3mr_issue_iocfacts(struct mpi3mr_ioc *mrioc, goto out_unlock; } memcpy(facts_data, (u8 *)data, data_len); + mpi3mr_process_factsdata(mrioc, facts_data); out_unlock: mrioc->init_cmds.state = MPI3MR_CMD_NOTUSED; mutex_unlock(&mrioc->init_cmds.mutex); @@ -2593,12 +2661,6 @@ static void mpi3mr_process_factsdata(struct mpi3mr_ioc *mrioc, ioc_info(mrioc, "DMA mask %d InitialPE status 0x%x\n", mrioc->facts.dma_mask, (facts_flags & MPI3_IOCFACTS_FLAGS_INITIAL_PORT_ENABLE_MASK)); - - mrioc->max_host_ios = mrioc->facts.max_reqs - MPI3MR_INTERNAL_CMDS_RESVD; - - if (reset_devices) - mrioc->max_host_ios = min_t(int, mrioc->max_host_ios, - MPI3MR_HOST_IOS_KDUMP); } /** @@ -2618,18 +2680,18 @@ static int mpi3mr_alloc_reply_sense_bufs(struct mpi3mr_ioc *mrioc) if (mrioc->init_cmds.reply) return retval; - mrioc->init_cmds.reply = kzalloc(mrioc->facts.reply_sz, GFP_KERNEL); + mrioc->init_cmds.reply = kzalloc(mrioc->reply_sz, GFP_KERNEL); if (!mrioc->init_cmds.reply) goto out_failed; for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) { - mrioc->dev_rmhs_cmds[i].reply = kzalloc(mrioc->facts.reply_sz, + mrioc->dev_rmhs_cmds[i].reply = kzalloc(mrioc->reply_sz, GFP_KERNEL); if (!mrioc->dev_rmhs_cmds[i].reply) goto out_failed; } - mrioc->host_tm_cmds.reply = kzalloc(mrioc->facts.reply_sz, GFP_KERNEL); + mrioc->host_tm_cmds.reply = kzalloc(mrioc->reply_sz, GFP_KERNEL); if (!mrioc->host_tm_cmds.reply) goto out_failed; @@ -2655,7 +2717,7 @@ static int mpi3mr_alloc_reply_sense_bufs(struct mpi3mr_ioc *mrioc) mrioc->sense_buf_q_sz = mrioc->num_sense_bufs + 1; /* reply buffer pool, 16 byte align */ - sz = mrioc->num_reply_bufs * mrioc->facts.reply_sz; + sz = mrioc->num_reply_bufs * mrioc->reply_sz; mrioc->reply_buf_pool = dma_pool_create("reply_buf pool", &mrioc->pdev->dev, sz, 16, 0); if (!mrioc->reply_buf_pool) { @@ -2731,10 +2793,10 @@ static void mpimr_initialize_reply_sbuf_queues(struct mpi3mr_ioc *mrioc) u32 sz, i; dma_addr_t phy_addr; - sz = mrioc->num_reply_bufs * mrioc->facts.reply_sz; + sz = mrioc->num_reply_bufs * mrioc->reply_sz; ioc_info(mrioc, "reply buf pool(0x%p): depth(%d), frame_size(%d), pool_size(%d kB), reply_dma(0x%llx)\n", - mrioc->reply_buf, mrioc->num_reply_bufs, mrioc->facts.reply_sz, + mrioc->reply_buf, mrioc->num_reply_bufs, mrioc->reply_sz, (sz / 1024), (unsigned long long)mrioc->reply_buf_dma); sz = mrioc->reply_free_qsz * 8; ioc_info(mrioc, @@ -2754,7 +2816,7 @@ static void mpimr_initialize_reply_sbuf_queues(struct mpi3mr_ioc *mrioc) /* initialize Reply buffer Queue */ for (i = 0, phy_addr = mrioc->reply_buf_dma; - i < mrioc->num_reply_bufs; i++, phy_addr += mrioc->facts.reply_sz) + i < mrioc->num_reply_bufs; i++, phy_addr += mrioc->reply_sz) mrioc->reply_free_q[i] = cpu_to_le64(phy_addr); mrioc->reply_free_q[i] = cpu_to_le64(0); @@ -3459,7 +3521,13 @@ retry_init: goto out_failed; } - mpi3mr_process_factsdata(mrioc, &facts_data); + mrioc->max_host_ios = mrioc->facts.max_reqs - MPI3MR_INTERNAL_CMDS_RESVD; + + if (reset_devices) + mrioc->max_host_ios = min_t(int, mrioc->max_host_ios, + MPI3MR_HOST_IOS_KDUMP); + + mrioc->reply_sz = mrioc->facts.reply_sz; retval = mpi3mr_check_reset_dma_mask(mrioc); if (retval) { @@ -3582,7 +3650,12 @@ retry_init: goto out_failed; } - mpi3mr_process_factsdata(mrioc, &facts_data); + dprint_reset(mrioc, "validating ioc_facts\n"); + retval = mpi3mr_revalidate_factsdata(mrioc); + if (retval) { + ioc_err(mrioc, "failed to revalidate ioc_facts data\n"); + goto out_failed_noretry; + } mpi3mr_print_ioc_info(mrioc);