From: Ranjan Kumar <ranjan.kumar@broadcom.com>
To: linux-scsi@vger.kernel.org, martin.petersen@oracle.com
Cc: rajsekhar.chundru@broadcom.com, sathya.prakash@broadcom.com,
sumit.saxena@broadcom.com, chandrakanth.patil@broadcom.com,
prayas.patel@broadcom.com,
Ranjan Kumar <ranjan.kumar@broadcom.com>
Subject: [PATCH v4 2/5] mpi3mr: Driver buffer allocation and posting
Date: Wed, 5 Jun 2024 15:18:37 +0530 [thread overview]
Message-ID: <20240605094840.14968-3-ranjan.kumar@broadcom.com> (raw)
In-Reply-To: <20240605094840.14968-1-ranjan.kumar@broadcom.com>
[-- Attachment #1: Type: text/plain, Size: 10260 bytes --]
This patch adds support for allocating a driver
diagnostic buffer and posting it to the firmware
for capturing the driver logs in the controller for further
debugging.
Signed-off-by: Sathya Prakash <sathya.prakash@broadcom.com>
Signed-off-by: Ranjan Kumar <ranjan.kumar@broadcom.com>
---
drivers/scsi/mpi3mr/mpi/mpi30_tool.h | 13 +++
drivers/scsi/mpi3mr/mpi3mr.h | 21 ++++
drivers/scsi/mpi3mr/mpi3mr_fw.c | 154 +++++++++++++++++++++++++++
3 files changed, 188 insertions(+)
diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_tool.h b/drivers/scsi/mpi3mr/mpi/mpi30_tool.h
index 3b960893870f..495933856006 100644
--- a/drivers/scsi/mpi3mr/mpi/mpi30_tool.h
+++ b/drivers/scsi/mpi3mr/mpi/mpi30_tool.h
@@ -7,6 +7,7 @@
#define MPI3_DIAG_BUFFER_TYPE_TRACE (0x01)
#define MPI3_DIAG_BUFFER_TYPE_FW (0x02)
+#define MPI3_DIAG_BUFFER_TYPE_DRIVER (0x10)
#define MPI3_DIAG_BUFFER_ACTION_RELEASE (0x01)
struct mpi3_diag_buffer_post_request {
@@ -40,5 +41,17 @@ struct mpi3_diag_buffer_manage_request {
__le16 reserved0e;
};
+struct mpi3_driver_buffer_header {
+ __le32 signature;
+ __le16 header_size;
+ __le16 rtt_file_header_offset;
+ __le32 flags;
+ __le32 circular_buffer_size;
+ __le32 logical_buffer_end;
+ __le32 logical_buffer_start;
+ __le32 ioc_use_only18[2];
+ __le32 reserved20[760];
+ __le32 reserved_rttrace[256];
+};
#endif
diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h
index 4ef96c39c832..dc7e8f461826 100644
--- a/drivers/scsi/mpi3mr/mpi3mr.h
+++ b/drivers/scsi/mpi3mr/mpi3mr.h
@@ -37,6 +37,7 @@
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_tcq.h>
+#include <linux/kmsg_dump.h>
#include <uapi/scsi/scsi_bsg_mpi3mr.h>
#include <scsi/scsi_transport_sas.h>
@@ -195,6 +196,13 @@ extern atomic64_t event_counter;
#define MPI3MR_HDB_TRIGGER_TYPE_GLOBAL 3
+/* Driver Host Diag Buffer (drv_db) */
+#define MPI3MR_MIN_DIAG_HOST_BUFFER_SZ ((32 * 1024) + \
+ sizeof(struct mpi3_driver_buffer_header))
+#define MPI3MR_DEFAULT_DIAG_HOST_BUFFER_SZ ((512 * 1024) + \
+ sizeof(struct mpi3_driver_buffer_header))
+#define MPI3MR_UEFI_DIAG_HOST_BUFFER_OFFSET (16 * 1024)
+
/* SGE Flag definition */
#define MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST \
(MPI3_SGE_FLAGS_ELEMENT_TYPE_SIMPLE | MPI3_SGE_FLAGS_DLAS_SYSTEM | \
@@ -218,6 +226,12 @@ extern atomic64_t event_counter;
#define MPI3MR_WRITE_SAME_MAX_LEN_256_BLKS 256
#define MPI3MR_WRITE_SAME_MAX_LEN_2048_BLKS 2048
+/* Driver diag buffer levels */
+enum mpi3mr_drv_db_level {
+ MRIOC_DRV_DB_DISABLED = 0,
+ MRIOC_DRV_DB_MINI = 1,
+ MRIOC_DRV_DB_FULL = 2,
+};
/**
* struct mpi3mr_nvme_pt_sge - Structure to store SGEs for NVMe
@@ -1113,6 +1127,10 @@ struct scmd_priv {
* @ioctl_chain_sge: DMA buffer descriptor for IOCTL chain
* @ioctl_resp_sge: DMA buffer descriptor for Mgmt cmd response
* @ioctl_sges_allocated: Flag for IOCTL SGEs allocated or not
+ * @drv_diag_buffer: Diagnostic host buffer virtual address
+ * @drv_diag_buffer_dma: Diagnostic host buffer DMA address
+ * @drv_diag_buffer_sz: Diagnostic host buffer size
+ *
*/
struct mpi3mr_ioc {
struct list_head list;
@@ -1310,6 +1328,9 @@ struct mpi3mr_ioc {
struct diag_buffer_desc diag_buffers[MPI3MR_MAX_NUM_HDB];
struct mpi3_driver_page2 *driver_pg2;
spinlock_t trigger_lock;
+ void *drv_diag_buffer;
+ dma_addr_t drv_diag_buffer_dma;
+ u32 drv_diag_buffer_sz;
};
/**
diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c
index fbd6f32f79ce..5937054b3cdb 100644
--- a/drivers/scsi/mpi3mr/mpi3mr_fw.c
+++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c
@@ -22,6 +22,17 @@ static int poll_queues;
module_param(poll_queues, int, 0444);
MODULE_PARM_DESC(poll_queues, "Number of queues for io_uring poll mode. (Range 1 - 126)");
+int drv_db_level = 1;
+module_param(drv_db_level, int, 0444);
+MODULE_PARM_DESC(drv_db_level, "Driver diagnostic buffer level(Default=1).\n\t\t"
+ "options:\n\t\t"
+ "0 = disabled: Driver diagnostic buffer not captured\n\t\t"
+ "1 = minidump: Driver diagnostic buffer captures prints\n\t\t"
+ "related to specific mrioc instance\n\t\t"
+ "2 = fulldump: Driver diagnostic buffer captures prints\n\t\t"
+ "related to specific mrioc instance and complete dmesg logs"
+ );
+
#if defined(writeq) && defined(CONFIG_64BIT)
static inline void mpi3mr_writeq(__u64 b, volatile void __iomem *addr)
{
@@ -872,6 +883,31 @@ static int mpi3mr_setup_isr(struct mpi3mr_ioc *mrioc, u8 setup_one)
return retval;
}
+static const struct {
+ enum mpi3mr_drv_db_level value;
+ char *name;
+} mpi3mr_drv_db[] = {
+ { MRIOC_DRV_DB_DISABLED, "disabled (uefi dump is enabled)" },
+ { MRIOC_DRV_DB_MINI, "minidump" },
+ { MRIOC_DRV_DB_FULL, "fulldump" },
+};
+static const char *mpi3mr_drv_db_name(enum mpi3mr_drv_db_level drv_db_level)
+{
+ int i;
+ char *name = NULL;
+
+ /* Start with Disabled */
+ name = mpi3mr_drv_db[0].name;
+
+ for (i = 0; i < ARRAY_SIZE(mpi3mr_drv_db); i++) {
+ if (mpi3mr_drv_db[i].value == drv_db_level) {
+ name = mpi3mr_drv_db[i].name;
+ break;
+ }
+ }
+ return name;
+}
+
static const struct {
enum mpi3mr_iocstate value;
char *name;
@@ -1238,6 +1274,102 @@ static int mpi3mr_issue_and_process_mur(struct mpi3mr_ioc *mrioc,
return retval;
}
+/**
+ * mpi3mr_alloc_issue_host_diag_buf - Allocate and send host diag buffer
+ * @mrioc: Adapter instance reference
+ *
+ * Issue diagnostic buffer post (unconditional) MPI request through admin queue
+ * and wait for the completion of it or time out.
+ *
+ * Return: 0 on success non-zero on failure
+ */
+static int mpi3mr_alloc_issue_host_diag_buf(struct mpi3mr_ioc *mrioc)
+{
+ struct mpi3_diag_buffer_post_request diag_buf_post_req;
+ dma_addr_t buf_dma_addr;
+ u32 buf_sz;
+ int retval = -1;
+
+ ioc_info(mrioc, "driver diag buffer level = %s.\n",
+ mpi3mr_drv_db_name(drv_db_level));
+
+ if (!mrioc->drv_diag_buffer) {
+ mrioc->drv_diag_buffer_sz =
+ MPI3MR_DEFAULT_DIAG_HOST_BUFFER_SZ;
+ mrioc->drv_diag_buffer =
+ dma_alloc_coherent(&mrioc->pdev->dev,
+ mrioc->drv_diag_buffer_sz,
+ &mrioc->drv_diag_buffer_dma, GFP_KERNEL);
+ if (!mrioc->drv_diag_buffer) {
+ mrioc->drv_diag_buffer_sz =
+ MPI3MR_MIN_DIAG_HOST_BUFFER_SZ;
+ mrioc->drv_diag_buffer =
+ dma_alloc_coherent(&mrioc->pdev->dev,
+ mrioc->drv_diag_buffer_sz,
+ &mrioc->drv_diag_buffer_dma, GFP_KERNEL);
+ }
+ if (!mrioc->drv_diag_buffer) {
+ ioc_warn(mrioc, "%s:%d:failed to allocate buffer\n",
+ __func__, __LINE__);
+ mrioc->drv_diag_buffer_sz = 0;
+ return retval;
+ }
+ /* TBD - memset to Zero once feature is stable */
+ memset(mrioc->drv_diag_buffer, 0x55, mrioc->drv_diag_buffer_sz);
+ }
+
+ buf_dma_addr = mrioc->drv_diag_buffer_dma;
+ buf_sz = mrioc->drv_diag_buffer_sz;
+
+ memset(&diag_buf_post_req, 0, sizeof(diag_buf_post_req));
+ mutex_lock(&mrioc->init_cmds.mutex);
+ if (mrioc->init_cmds.state & MPI3MR_CMD_PENDING) {
+ ioc_err(mrioc, "sending driver diag buffer post is failed due to command in use\n");
+ mutex_unlock(&mrioc->init_cmds.mutex);
+ return retval;
+ }
+ mrioc->init_cmds.state = MPI3MR_CMD_PENDING;
+ mrioc->init_cmds.is_waiting = 1;
+ mrioc->init_cmds.callback = NULL;
+ diag_buf_post_req.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_INITCMDS);
+ diag_buf_post_req.function = MPI3_FUNCTION_DIAG_BUFFER_POST;
+ diag_buf_post_req.type = MPI3_DIAG_BUFFER_TYPE_DRIVER;
+ diag_buf_post_req.address = le64_to_cpu(buf_dma_addr);
+ diag_buf_post_req.length = le32_to_cpu(buf_sz);
+
+ init_completion(&mrioc->init_cmds.done);
+ retval = mpi3mr_admin_request_post(mrioc, &diag_buf_post_req,
+ sizeof(diag_buf_post_req), 1);
+ if (retval) {
+ ioc_err(mrioc, "posting driver diag buffer failed\n");
+ goto out_unlock;
+ }
+ wait_for_completion_timeout(&mrioc->init_cmds.done,
+ (MPI3MR_INTADMCMD_TIMEOUT * HZ));
+ if (!(mrioc->init_cmds.state & MPI3MR_CMD_COMPLETE)) {
+ ioc_err(mrioc, "posting driver diag buffer timed out\n");
+ mpi3mr_check_rh_fault_ioc(mrioc,
+ MPI3MR_RESET_FROM_DIAG_BUFFER_POST_TIMEOUT);
+ retval = -1;
+ goto out_unlock;
+ }
+ retval = 0;
+ if ((mrioc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK)
+ != MPI3_IOCSTATUS_SUCCESS)
+ ioc_warn(mrioc,
+ "driver diag buffer post returned with ioc_status(0x%04x) log_info(0x%08x)\n",
+ (mrioc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK),
+ mrioc->init_cmds.ioc_loginfo);
+ else
+ ioc_info(mrioc, "driver diag buffer of size %dKB posted successfully\n",
+ mrioc->drv_diag_buffer_sz / 1024);
+
+out_unlock:
+ mrioc->init_cmds.state = MPI3MR_CMD_NOTUSED;
+ mutex_unlock(&mrioc->init_cmds.mutex);
+ return retval;
+}
+
/**
* mpi3mr_revalidate_factsdata - validate IOCFacts parameters
* during reset/resume
@@ -4168,6 +4300,13 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc)
goto out_failed;
}
+ dprint_reset(mrioc, "posting driver diag buffer\n");
+ retval = mpi3mr_alloc_issue_host_diag_buf(mrioc);
+ if (retval) {
+ ioc_err(mrioc, "failed to post driver diag buffer\n");
+ goto out_failed;
+ }
+
ioc_info(mrioc, "controller initialization completed successfully\n");
return retval;
out_failed:
@@ -4358,6 +4497,13 @@ int mpi3mr_reinit_ioc(struct mpi3mr_ioc *mrioc, u8 is_resume)
} else
ioc_info(mrioc, "port enable completed successfully\n");
+ dprint_reset(mrioc, "posting driver diag buffer\n");
+ retval = mpi3mr_alloc_issue_host_diag_buf(mrioc);
+ if (retval) {
+ ioc_err(mrioc, "failed to post driver diag buffer\n");
+ goto out_failed;
+ }
+
ioc_info(mrioc, "controller %s completed successfully\n",
(is_resume)?"resume":"re-initialization");
return retval;
@@ -4669,6 +4815,14 @@ void mpi3mr_free_mem(struct mpi3mr_ioc *mrioc)
}
}
+ if (mrioc->drv_diag_buffer) {
+ dma_free_coherent(&mrioc->pdev->dev,
+ mrioc->drv_diag_buffer_sz, mrioc->drv_diag_buffer,
+ mrioc->drv_diag_buffer_dma);
+ mrioc->drv_diag_buffer = NULL;
+ mrioc->drv_diag_buffer_sz = 0;
+ }
+
kfree(mrioc->throttle_groups);
mrioc->throttle_groups = NULL;
--
2.31.1
[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4209 bytes --]
next prev parent reply other threads:[~2024-06-05 9:51 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-06-05 9:48 [PATCH v4 0/5] mpi3mr: Host diag buffer support Ranjan Kumar
2024-06-05 9:48 ` [PATCH v4 1/5] mpi3mr: HDB allocation and posting for hardware and Firmware buffers Ranjan Kumar
2024-06-05 9:48 ` Ranjan Kumar [this message]
2024-06-05 9:48 ` [PATCH v4 3/5] mpi3mr: Trigger support Ranjan Kumar
2024-06-05 9:48 ` [PATCH v4 4/5] mpi3mr: Ioctl support for HDB Ranjan Kumar
2024-06-05 9:48 ` [PATCH v4 5/5] mpi3mr: Update driver version to 8.9.1.0.50 Ranjan Kumar
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240605094840.14968-3-ranjan.kumar@broadcom.com \
--to=ranjan.kumar@broadcom.com \
--cc=chandrakanth.patil@broadcom.com \
--cc=linux-scsi@vger.kernel.org \
--cc=martin.petersen@oracle.com \
--cc=prayas.patel@broadcom.com \
--cc=rajsekhar.chundru@broadcom.com \
--cc=sathya.prakash@broadcom.com \
--cc=sumit.saxena@broadcom.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.