From patchwork Tue Jun 18 11:56:52 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ranjan Kumar X-Patchwork-Id: 13702149 Received: from mail-pf1-f182.google.com (mail-pf1-f182.google.com [209.85.210.182]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E6A67158214 for ; Tue, 18 Jun 2024 12:00:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.182 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718712011; cv=none; b=u+6WDWqT16aLh8DG5Hmcq5xDinhQ/qV5uQum1bCwcdbxZRNbJHJkGnAZSQ/pHau9ZXkFBmqCjk7Ko2+nYhPw+2vxqSjsYGyhqEgIZycsn/y0SrUHlx6gwqruMS0qZmGTer9zyYtoOcMQfCPIbWR9TiOVokzS/+HNsOPne8pDAJI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718712011; c=relaxed/simple; bh=1J55ESBh6IjAQhuYuBvmG0lOLZuRkBjfJoYK1NyFO4Y=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=f1J/YHveqq5k0A+U6oxPMg4+nghUcT8OyIXC+Ae6SIyWddmQkO9l6cmOaH0pqezH1zNyTKlqcJvyXN6YN0IAu2AT0XY82xChQS3jHqXSXMUQDLEEkw4zckZYJQca1FERlt/9PPzT6LCvuE3+XHARzfNByRd4wrCuGMtEwSsbU+M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=broadcom.com; spf=fail smtp.mailfrom=broadcom.com; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b=dO+S8du1; arc=none smtp.client-ip=209.85.210.182 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=broadcom.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=broadcom.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b="dO+S8du1" Received: by mail-pf1-f182.google.com with SMTP id d2e1a72fcca58-7042a8ad9f5so4142780b3a.0 for ; Tue, 18 Jun 2024 05:00:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1718712008; x=1719316808; darn=vger.kernel.org; h=mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:from:to:cc:subject:date:message-id:reply-to; bh=TU5kqi1ehyqcRAHXQF91EdYAUBFtMR1i6xA0IgrBnGs=; b=dO+S8du1JVpmWMhw/W+T2uVsBkkPb74JWvI9wqHnq9GUzwDFLKUJcYQ5EFWAtUd5aB rLsJty02if/jgSOwxJ7dCqR/3b1o55uSnxxgLwtLUNveAv12T2VmyNwLon3n1NE9Max/ kkj77kqid837WCpA17GP4Af9o0LbTggfoa3fo= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1718712008; x=1719316808; h=mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=TU5kqi1ehyqcRAHXQF91EdYAUBFtMR1i6xA0IgrBnGs=; b=U15EUdfU53jJjenii6kAPQj0JdI1nsar7QRmPVxsOIfsKeL2ToRcA/tJsEXOhM6zJr ghy8iLLdSt0TnCfA0SVAadTbwnhI1rmK0Wvt+NPpjBgEVd2M6j2luId4zOPTEQYwic6f mcD87v4kkkKXD1eL4hmTpHpoVeWHDvNiKDbsfiNBPCtbljQI1TaKpvZ22aiW6rPFFOzb V8eeFJdUBWojJyX1+89f7he1RJGb9olABKM/a5Cl8CtZAFkeyo2eQJDzG/QicSY62uvj vfKwccHN8Fw90937ux6+t61//g/V2JHY0pJn9DogxiRwMluKHZ4zOMr9DXNRUxRnm1Q+ SzrQ== X-Gm-Message-State: AOJu0Yxmx2rl8bZtg0URVAy+qBqIXRUAFJepsG88pa+Tj68QednGh7Tr CzbZGjqQSkoJhO6KHHx29y9W1jNef/+kkuJYEgsapl0W1ch1RDGCDWGTjMzpP+rj0Bdn2UMJbR3 TiQptC94oPskIbtz9SOUohAx1BEfmH4Lfti5+Tp0fkve0XJmaOUgjMOyiJYzRKDKHk71YUo7TFY a53YzhhG5hAuk/5ybSxICn2/5/BQOupYj3+uB6ms31xZcwhw== X-Google-Smtp-Source: AGHT+IHcga+FxOuj3Z+BKPCvt3w56kOjbwTJ1h3pGYwLgyWEApFnxYCjHOjlZpaTtTW2dfqnb7DHBA== X-Received: by 2002:a17:90b:33cd:b0:2bd:d67b:6bf3 with SMTP id 98e67ed59e1d1-2c6cb1b1c72mr3199825a91.20.1718712006641; Tue, 18 Jun 2024 05:00:06 -0700 (PDT) Received: from localhost.localdomain ([192.19.234.250]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2c4a76037a4sm12925963a91.29.2024.06.18.05.00.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Jun 2024 05:00:05 -0700 (PDT) From: Ranjan Kumar 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 , kernel test robot Subject: [PATCH v5 1/4] mpi3mr: HDB allocation and posting for hardware and Firmware buffers Date: Tue, 18 Jun 2024 17:26:52 +0530 Message-Id: <20240618115655.15066-2-ranjan.kumar@broadcom.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20240618115655.15066-1-ranjan.kumar@broadcom.com> References: <20240618115655.15066-1-ranjan.kumar@broadcom.com> Precedence: bulk X-Mailing-List: linux-scsi@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This patch adds functions require to allocate and post firmware and hardware diagnostic buffers to the controller and to setup automatic diagnostic capture triggers Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202405151758.7xrJz6rp-lkp@intel.com/ Signed-off-by: Sathya Prakash Signed-off-by: Ranjan Kumar --- drivers/scsi/mpi3mr/mpi/mpi30_tool.h | 44 +++ drivers/scsi/mpi3mr/mpi3mr.h | 74 +++++ drivers/scsi/mpi3mr/mpi3mr_app.c | 480 +++++++++++++++++++++++++++ drivers/scsi/mpi3mr/mpi3mr_fw.c | 193 ++++++++++- 4 files changed, 790 insertions(+), 1 deletion(-) create mode 100644 drivers/scsi/mpi3mr/mpi/mpi30_tool.h diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_tool.h b/drivers/scsi/mpi3mr/mpi/mpi30_tool.h new file mode 100644 index 000000000000..3b960893870f --- /dev/null +++ b/drivers/scsi/mpi3mr/mpi/mpi30_tool.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright 2016-2024 Broadcom Inc. All rights reserved. + */ +#ifndef MPI30_TOOL_H +#define MPI30_TOOL_H 1 + +#define MPI3_DIAG_BUFFER_TYPE_TRACE (0x01) +#define MPI3_DIAG_BUFFER_TYPE_FW (0x02) +#define MPI3_DIAG_BUFFER_ACTION_RELEASE (0x01) + +struct mpi3_diag_buffer_post_request { + __le16 host_tag; + u8 ioc_use_only02; + u8 function; + __le16 ioc_use_only04; + u8 ioc_use_only06; + u8 msg_flags; + __le16 change_count; + __le16 reserved0a; + u8 type; + u8 reserved0d; + __le16 reserved0e; + __le64 address; + __le32 length; + __le32 reserved1c; +}; + +struct mpi3_diag_buffer_manage_request { + __le16 host_tag; + u8 ioc_use_only02; + u8 function; + __le16 ioc_use_only04; + u8 ioc_use_only06; + u8 msg_flags; + __le16 change_count; + __le16 reserved0a; + u8 type; + u8 action; + __le16 reserved0e; +}; + + +#endif diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h index f5a1529fa537..9aae59646faa 100644 --- a/drivers/scsi/mpi3mr/mpi3mr.h +++ b/drivers/scsi/mpi3mr/mpi3mr.h @@ -47,6 +47,7 @@ #include "mpi/mpi30_ioc.h" #include "mpi/mpi30_sas.h" #include "mpi/mpi30_pci.h" +#include "mpi/mpi30_tool.h" #include "mpi3mr_debug.h" /* Global list and lock for storing multiple adapters managed by the driver */ @@ -187,6 +188,13 @@ extern atomic64_t event_counter; #define MPI3MR_HARD_SECURE_DEVICE 0x08 #define MPI3MR_TAMPERED_DEVICE 0x0C +#define MPI3MR_DEFAULT_HDB_MAX_SZ (4 * 1024 * 1024) +#define MPI3MR_DEFAULT_HDB_DEC_SZ (1 * 1024 * 1024) +#define MPI3MR_DEFAULT_HDB_MIN_SZ (2 * 1024 * 1024) +#define MPI3MR_MAX_NUM_HDB 2 + +#define MPI3MR_HDB_TRIGGER_TYPE_GLOBAL 3 + /* SGE Flag definition */ #define MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST \ (MPI3_SGE_FLAGS_ELEMENT_TYPE_SIMPLE | MPI3_SGE_FLAGS_DLAS_SYSTEM | \ @@ -210,6 +218,7 @@ extern atomic64_t event_counter; #define MPI3MR_WRITE_SAME_MAX_LEN_256_BLKS 256 #define MPI3MR_WRITE_SAME_MAX_LEN_2048_BLKS 2048 + /** * struct mpi3mr_nvme_pt_sge - Structure to store SGEs for NVMe * Encapsulated commands. @@ -289,6 +298,8 @@ enum mpi3mr_reset_reason { MPI3MR_RESET_FROM_PELABORT_TIMEOUT = 22, MPI3MR_RESET_FROM_SYSFS = 23, MPI3MR_RESET_FROM_SYSFS_TIMEOUT = 24, + MPI3MR_RESET_FROM_DIAG_BUFFER_POST_TIMEOUT = 25, + MPI3MR_RESET_FROM_DIAG_BUFFER_RELEASE_TIMEOUT = 26, MPI3MR_RESET_FROM_FIRMWARE = 27, MPI3MR_RESET_FROM_CFG_REQ_TIMEOUT = 29, MPI3MR_RESET_FROM_SAS_TRANSPORT_TIMEOUT = 30, @@ -327,6 +338,9 @@ struct mpi3mr_ioc_facts { u32 ioc_capabilities; struct mpi3mr_compimg_ver fw_ver; u32 mpi_version; + u32 diag_trace_sz; + u32 diag_fw_sz; + u32 diag_drvr_sz; u16 max_reqs; u16 product_id; u16 op_req_sz; @@ -852,6 +866,41 @@ struct mpi3mr_drv_cmd { struct mpi3mr_drv_cmd *drv_cmd); }; +/** + * union mpi3mr_trigger_data - Trigger data information + * @fault: Fault code + * @global: Global trigger data + * @element: element trigger data + */ +union mpi3mr_trigger_data { + u16 fault; + u64 global; + union mpi3_driver2_trigger_element element; +}; + +/** + * struct diag_buffer_desc - memory descriptor structure to + * store virtual, dma addresses, size, buffer status for host + * diagnostic buffers. + * + * @type: Buffer type + * @trigger_data: Trigger data + * @trigger_type: Trigger type + * @status: Buffer status + * @size: Buffer size + * @addr: Virtual address + * @dma_addr: Buffer DMA address + */ +struct diag_buffer_desc { + u8 type; + union mpi3mr_trigger_data trigger_data; + u8 trigger_type; + u8 status; + u32 size; + void *addr; + dma_addr_t dma_addr; +}; + /** * struct dma_memory_desc - memory descriptor structure to store * virtual address, dma address and size for any generic dma @@ -1054,6 +1103,11 @@ struct scmd_priv { * @sas_node_lock: Lock to protect SAS node list * @hba_port_table_list: List of HBA Ports * @enclosure_list: List of Enclosure objects + * @diag_buffers: Host diagnostic buffers + * @driver_pg2: Driver page 2 pointer + * @reply_trigger_present: Reply trigger present flag + * @event_trigger_present: Event trigger present flag + * @scsisense_trigger_present: Scsi sense trigger present flag * @ioctl_dma_pool: DMA pool for IOCTL data buffers * @ioctl_sge: DMA buffer descriptors for IOCTL data * @ioctl_chain_sge: DMA buffer descriptor for IOCTL chain @@ -1250,6 +1304,12 @@ struct mpi3mr_ioc { struct dma_memory_desc ioctl_chain_sge; struct dma_memory_desc ioctl_resp_sge; bool ioctl_sges_allocated; + bool reply_trigger_present; + bool event_trigger_present; + bool scsisense_trigger_present; + struct diag_buffer_desc diag_buffers[MPI3MR_MAX_NUM_HDB]; + struct mpi3_driver_page2 *driver_pg2; + spinlock_t trigger_lock; }; /** @@ -1406,6 +1466,8 @@ int mpi3mr_cfg_set_sas_io_unit_pg1(struct mpi3mr_ioc *mrioc, struct mpi3_sas_io_unit_page1 *sas_io_unit_pg1, u16 pg_sz); int mpi3mr_cfg_get_driver_pg1(struct mpi3mr_ioc *mrioc, struct mpi3_driver_page1 *driver_pg1, u16 pg_sz); +int mpi3mr_cfg_get_driver_pg2(struct mpi3mr_ioc *mrioc, + struct mpi3_driver_page2 *driver_pg2, u16 pg_sz, u8 page_type); u8 mpi3mr_is_expander_device(u16 device_info); int mpi3mr_expander_add(struct mpi3mr_ioc *mrioc, u16 handle); @@ -1439,4 +1501,16 @@ void mpi3mr_free_enclosure_list(struct mpi3mr_ioc *mrioc); int mpi3mr_process_admin_reply_q(struct mpi3mr_ioc *mrioc); void mpi3mr_expander_node_remove(struct mpi3mr_ioc *mrioc, struct mpi3mr_sas_node *sas_expander); +void mpi3mr_alloc_diag_bufs(struct mpi3mr_ioc *mrioc); +int mpi3mr_post_diag_bufs(struct mpi3mr_ioc *mrioc); +int mpi3mr_issue_diag_buf_release(struct mpi3mr_ioc *mrioc, + struct diag_buffer_desc *diag_buffer); +void mpi3mr_release_diag_bufs(struct mpi3mr_ioc *mrioc, u8 skip_rel_action); +void mpi3mr_set_trigger_data_in_hdb(struct diag_buffer_desc *hdb, + u8 type, union mpi3mr_trigger_data *trigger_data, bool force); +int mpi3mr_refresh_trigger(struct mpi3mr_ioc *mrioc, u8 page_type); +struct diag_buffer_desc *mpi3mr_diag_buffer_for_type(struct mpi3mr_ioc *mrioc, + u8 buf_type); +int mpi3mr_issue_diag_buf_post(struct mpi3mr_ioc *mrioc, + struct diag_buffer_desc *diag_buffer); #endif /*MPI3MR_H_INCLUDED*/ diff --git a/drivers/scsi/mpi3mr/mpi3mr_app.c b/drivers/scsi/mpi3mr/mpi3mr_app.c index 3c309e8c3a2b..6bb006b7ef7e 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_app.c +++ b/drivers/scsi/mpi3mr/mpi3mr_app.c @@ -11,6 +11,486 @@ #include #include +/** + * mpi3mr_alloc_trace_buffer: Allocate trace buffer + * @mrioc: Adapter instance reference + * @trace_size: Trace buffer size + * + * Allocate trace buffer + * Return: 0 on success, non-zero on failure. + */ +static int mpi3mr_alloc_trace_buffer(struct mpi3mr_ioc *mrioc, u32 trace_size) +{ + struct diag_buffer_desc *diag_buffer = &mrioc->diag_buffers[0]; + + diag_buffer->addr = dma_alloc_coherent(&mrioc->pdev->dev, + trace_size, &diag_buffer->dma_addr, GFP_KERNEL); + if (diag_buffer->addr) { + dprint_init(mrioc, "trace diag buffer is allocated successfully\n"); + return 0; + } + return -1; +} + +/** + * mpi3mr_alloc_diag_bufs - Allocate memory for diag buffers + * @mrioc: Adapter instance reference + * + * This functions checks whether the driver defined buffer sizes + * are greater than IOCFacts provided controller local buffer + * sizes and if the driver defined sizes are more then the + * driver allocates the specific buffer by reading driver page1 + * + * Return: Nothing. + */ +void mpi3mr_alloc_diag_bufs(struct mpi3mr_ioc *mrioc) +{ + struct diag_buffer_desc *diag_buffer; + struct mpi3_driver_page1 driver_pg1; + u32 trace_dec_size, trace_min_size, fw_dec_size, fw_min_size, + trace_size, fw_size; + u16 pg_sz = sizeof(driver_pg1); + int retval = 0; + bool retry = false; + + if (mrioc->diag_buffers[0].addr || mrioc->diag_buffers[1].addr) + return; + + retval = mpi3mr_cfg_get_driver_pg1(mrioc, &driver_pg1, pg_sz); + if (retval) { + ioc_warn(mrioc, + "%s: driver page 1 read failed, allocating trace\n" + "and firmware diag buffers of default size\n", __func__); + trace_size = fw_size = MPI3MR_DEFAULT_HDB_MAX_SZ; + trace_dec_size = fw_dec_size = MPI3MR_DEFAULT_HDB_DEC_SZ; + trace_min_size = fw_min_size = MPI3MR_DEFAULT_HDB_MIN_SZ; + + } else { + trace_size = driver_pg1.host_diag_trace_max_size * 1024; + trace_dec_size = driver_pg1.host_diag_trace_decrement_size + * 1024; + trace_min_size = driver_pg1.host_diag_trace_min_size * 1024; + fw_size = driver_pg1.host_diag_fw_max_size * 1024; + fw_dec_size = driver_pg1.host_diag_fw_decrement_size * 1024; + fw_min_size = driver_pg1.host_diag_fw_min_size * 1024; + dprint_init(mrioc, + "%s:trace diag buffer sizes read from driver\n" + "page1: maximum size = %dKB, decrement size = %dKB\n" + ", minimum size = %dKB\n", __func__, driver_pg1.host_diag_trace_max_size, + driver_pg1.host_diag_trace_decrement_size, + driver_pg1.host_diag_trace_min_size); + dprint_init(mrioc, + "%s:firmware diag buffer sizes read from driver\n" + "page1: maximum size = %dKB, decrement size = %dKB\n" + ", minimum size = %dKB\n", __func__, driver_pg1.host_diag_fw_max_size, + driver_pg1.host_diag_fw_decrement_size, + driver_pg1.host_diag_fw_min_size); + if ((trace_size == 0) && (fw_size == 0)) + return; + } + + +retry_trace: + diag_buffer = &mrioc->diag_buffers[0]; + diag_buffer->type = MPI3_DIAG_BUFFER_TYPE_TRACE; + diag_buffer->status = MPI3MR_HDB_BUFSTATUS_NOT_ALLOCATED; + if ((mrioc->facts.diag_trace_sz < trace_size) && (trace_size >= + trace_min_size)) { + if (!retry) + dprint_init(mrioc, + "trying to allocate trace diag buffer of size = %dKB\n", + trace_size / 1024); + if (mpi3mr_alloc_trace_buffer(mrioc, trace_size)) { + retry = true; + trace_size -= trace_dec_size; + dprint_init(mrioc, "trace diag buffer allocation failed\n" + "retrying smaller size %dKB\n", trace_size / 1024); + goto retry_trace; + } else + diag_buffer->size = trace_size; + } + + retry = false; +retry_fw: + + diag_buffer = &mrioc->diag_buffers[1]; + + diag_buffer->type = MPI3_DIAG_BUFFER_TYPE_FW; + diag_buffer->status = MPI3MR_HDB_BUFSTATUS_NOT_ALLOCATED; + if ((mrioc->facts.diag_fw_sz < fw_size) && (fw_size >= fw_min_size)) { + diag_buffer->addr = dma_alloc_coherent(&mrioc->pdev->dev, + fw_size, &diag_buffer->dma_addr, GFP_KERNEL); + if (!retry) + dprint_init(mrioc, + "%s:trying to allocate firmware diag buffer of size = %dKB\n", + __func__, fw_size / 1024); + if (diag_buffer->addr) { + dprint_init(mrioc, "%s:firmware diag buffer allocated successfully\n", + __func__); + diag_buffer->size = fw_size; + } else { + retry = true; + fw_size -= fw_dec_size; + dprint_init(mrioc, "%s:trace diag buffer allocation failed,\n" + "retrying smaller size %dKB\n", + __func__, fw_size / 1024); + goto retry_fw; + } + } +} + +/** + * mpi3mr_issue_diag_buf_post - Send diag buffer post req + * @mrioc: Adapter instance reference + * @diag_buffer: Diagnostic buffer descriptor + * + * Issue diagnostic buffer post MPI request through admin queue + * and wait for the completion of it or time out. + * + * Return: 0 on success, non-zero on failures. + */ +int mpi3mr_issue_diag_buf_post(struct mpi3mr_ioc *mrioc, + struct diag_buffer_desc *diag_buffer) +{ + struct mpi3_diag_buffer_post_request diag_buf_post_req; + u8 prev_status; + int retval = 0; + + 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) { + dprint_bsg_err(mrioc, "%s: command is in use\n", __func__); + mutex_unlock(&mrioc->init_cmds.mutex); + return -1; + } + 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 = diag_buffer->type; + diag_buf_post_req.address = le64_to_cpu(diag_buffer->dma_addr); + diag_buf_post_req.length = le32_to_cpu(diag_buffer->size); + + dprint_bsg_info(mrioc, "%s: posting diag buffer type %d\n", __func__, + diag_buffer->type); + prev_status = diag_buffer->status; + diag_buffer->status = MPI3MR_HDB_BUFSTATUS_POSTED_UNPAUSED; + init_completion(&mrioc->init_cmds.done); + retval = mpi3mr_admin_request_post(mrioc, &diag_buf_post_req, + sizeof(diag_buf_post_req), 1); + if (retval) { + dprint_bsg_err(mrioc, "%s: admin request post failed\n", + __func__); + goto out_unlock; + } + wait_for_completion_timeout(&mrioc->init_cmds.done, + (MPI3MR_INTADMCMD_TIMEOUT * HZ)); + if (!(mrioc->init_cmds.state & MPI3MR_CMD_COMPLETE)) { + mrioc->init_cmds.is_waiting = 0; + dprint_bsg_err(mrioc, "%s: command timedout\n", __func__); + mpi3mr_check_rh_fault_ioc(mrioc, + MPI3MR_RESET_FROM_DIAG_BUFFER_POST_TIMEOUT); + retval = -1; + goto out_unlock; + } + if ((mrioc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK) + != MPI3_IOCSTATUS_SUCCESS) { + dprint_bsg_err(mrioc, + "%s: command failed, buffer_type (%d) ioc_status(0x%04x) log_info(0x%08x)\n", + __func__, diag_buffer->type, + (mrioc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK), + mrioc->init_cmds.ioc_loginfo); + retval = -1; + goto out_unlock; + } + dprint_bsg_info(mrioc, "%s: diag buffer type %d posted successfully\n", + __func__, diag_buffer->type); + +out_unlock: + if (retval) + diag_buffer->status = prev_status; + mrioc->init_cmds.state = MPI3MR_CMD_NOTUSED; + mutex_unlock(&mrioc->init_cmds.mutex); + return retval; +} + +/** + * mpi3mr_post_diag_bufs - Post diag buffers to the controller + * @mrioc: Adapter instance reference + * + * This function calls helper function to post both trace and + * firmware buffers to the controller. + * + * Return: None + */ +int mpi3mr_post_diag_bufs(struct mpi3mr_ioc *mrioc) +{ + u8 i; + struct diag_buffer_desc *diag_buffer; + + for (i = 0; i < MPI3MR_MAX_NUM_HDB; i++) { + diag_buffer = &mrioc->diag_buffers[i]; + if (!(diag_buffer->addr)) + continue; + if (mpi3mr_issue_diag_buf_post(mrioc, diag_buffer)) + return -1; + } + return 0; +} + +/** + * mpi3mr_issue_diag_buf_release - Send diag buffer release req + * @mrioc: Adapter instance reference + * @diag_buffer: Diagnostic buffer descriptor + * + * Issue diagnostic buffer manage MPI request with release + * action request through admin queue and wait for the + * completion of it or time out. + * + * Return: 0 on success, non-zero on failures. + */ +int mpi3mr_issue_diag_buf_release(struct mpi3mr_ioc *mrioc, + struct diag_buffer_desc *diag_buffer) +{ + struct mpi3_diag_buffer_manage_request diag_buf_manage_req; + int retval = 0; + + if ((diag_buffer->status != MPI3MR_HDB_BUFSTATUS_POSTED_UNPAUSED) && + (diag_buffer->status != MPI3MR_HDB_BUFSTATUS_POSTED_PAUSED)) + return retval; + + memset(&diag_buf_manage_req, 0, sizeof(diag_buf_manage_req)); + mutex_lock(&mrioc->init_cmds.mutex); + if (mrioc->init_cmds.state & MPI3MR_CMD_PENDING) { + dprint_reset(mrioc, "%s: command is in use\n", __func__); + mutex_unlock(&mrioc->init_cmds.mutex); + return -1; + } + mrioc->init_cmds.state = MPI3MR_CMD_PENDING; + mrioc->init_cmds.is_waiting = 1; + mrioc->init_cmds.callback = NULL; + diag_buf_manage_req.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_INITCMDS); + diag_buf_manage_req.function = MPI3_FUNCTION_DIAG_BUFFER_MANAGE; + diag_buf_manage_req.type = diag_buffer->type; + diag_buf_manage_req.action = MPI3_DIAG_BUFFER_ACTION_RELEASE; + + + dprint_reset(mrioc, "%s: releasing diag buffer type %d\n", __func__, + diag_buffer->type); + init_completion(&mrioc->init_cmds.done); + retval = mpi3mr_admin_request_post(mrioc, &diag_buf_manage_req, + sizeof(diag_buf_manage_req), 1); + if (retval) { + dprint_reset(mrioc, "%s: admin request post failed\n", __func__); + mpi3mr_set_trigger_data_in_hdb(diag_buffer, + MPI3MR_HDB_TRIGGER_TYPE_UNKNOWN, NULL, 1); + goto out_unlock; + } + wait_for_completion_timeout(&mrioc->init_cmds.done, + (MPI3MR_INTADMCMD_TIMEOUT * HZ)); + if (!(mrioc->init_cmds.state & MPI3MR_CMD_COMPLETE)) { + mrioc->init_cmds.is_waiting = 0; + dprint_reset(mrioc, "%s: command timedout\n", __func__); + mpi3mr_check_rh_fault_ioc(mrioc, + MPI3MR_RESET_FROM_DIAG_BUFFER_RELEASE_TIMEOUT); + retval = -1; + goto out_unlock; + } + if ((mrioc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK) + != MPI3_IOCSTATUS_SUCCESS) { + dprint_reset(mrioc, + "%s: command failed, buffer_type (%d) ioc_status(0x%04x) log_info(0x%08x)\n", + __func__, diag_buffer->type, + (mrioc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK), + mrioc->init_cmds.ioc_loginfo); + retval = -1; + goto out_unlock; + } + dprint_reset(mrioc, "%s: diag buffer type %d released successfully\n", + __func__, diag_buffer->type); + +out_unlock: + mrioc->init_cmds.state = MPI3MR_CMD_NOTUSED; + mutex_unlock(&mrioc->init_cmds.mutex); + return retval; +} + +/** + * mpi3mr_get_num_trigger - Gets number of HDB triggers + * @mrioc: Adapter instance reference + * @num_triggers: Number of triggers + * @page_action: Page action + * + * This function reads number of triggers by reading driver page + * 2 + * + * Return: 0 on success and proper error codes on failure + */ +static int mpi3mr_get_num_trigger(struct mpi3mr_ioc *mrioc, u8 *num_triggers, + u8 page_action) +{ + struct mpi3_driver_page2 drvr_page2; + int retval = 0; + + *num_triggers = 0; + + retval = mpi3mr_cfg_get_driver_pg2(mrioc, &drvr_page2, + sizeof(struct mpi3_driver_page2), page_action); + + if (retval) { + dprint_init(mrioc, "%s: driver page 2 read failed\n", __func__); + return retval; + } + *num_triggers = drvr_page2.num_triggers; + return retval; +} + +/** + * mpi3mr_refresh_trigger - Handler for Refresh trigger BSG + * @mrioc: Adapter instance reference + * @page_action: Page action + * + * This function caches the driver page 2 in the driver's memory + * by reading driver page 2 from the controller for a given page + * type and updates the HDB trigger values + * + * Return: 0 on success and proper error codes on failure + */ +int mpi3mr_refresh_trigger(struct mpi3mr_ioc *mrioc, u8 page_action) +{ + u16 pg_sz = sizeof(struct mpi3_driver_page2); + struct mpi3_driver_page2 *drvr_page2 = NULL; + u8 trigger_type, num_triggers; + int retval; + int i = 0; + unsigned long flags; + + retval = mpi3mr_get_num_trigger(mrioc, &num_triggers, page_action); + + if (retval) + goto out; + + pg_sz = offsetof(struct mpi3_driver_page2, trigger) + + (num_triggers * sizeof(union mpi3_driver2_trigger_element)); + drvr_page2 = kzalloc(pg_sz, GFP_KERNEL); + if (!drvr_page2) { + retval = -ENOMEM; + goto out; + } + + retval = mpi3mr_cfg_get_driver_pg2(mrioc, drvr_page2, pg_sz, page_action); + if (retval) { + dprint_init(mrioc, "%s: driver page 2 read failed\n", __func__); + kfree(drvr_page2); + goto out; + } + spin_lock_irqsave(&mrioc->trigger_lock, flags); + kfree(mrioc->driver_pg2); + mrioc->driver_pg2 = drvr_page2; + mrioc->reply_trigger_present = false; + mrioc->event_trigger_present = false; + mrioc->scsisense_trigger_present = false; + + for (i = 0; (i < mrioc->driver_pg2->num_triggers); i++) { + trigger_type = mrioc->driver_pg2->trigger[i].event.type; + switch (trigger_type) { + case MPI3_DRIVER2_TRIGGER_TYPE_REPLY: + mrioc->reply_trigger_present = true; + break; + case MPI3_DRIVER2_TRIGGER_TYPE_EVENT: + mrioc->event_trigger_present = true; + break; + case MPI3_DRIVER2_TRIGGER_TYPE_SCSI_SENSE: + mrioc->scsisense_trigger_present = true; + break; + default: + break; + } + } + spin_unlock_irqrestore(&mrioc->trigger_lock, flags); +out: + return retval; +} + +/** + * mpi3mr_release_diag_bufs - Release diag buffers + * @mrioc: Adapter instance reference + * @skip_rel_action: Skip release action and set buffer state + * + * This function calls helper function to release both trace and + * firmware buffers from the controller. + * + * Return: None + */ +void mpi3mr_release_diag_bufs(struct mpi3mr_ioc *mrioc, u8 skip_rel_action) +{ + u8 i; + struct diag_buffer_desc *diag_buffer; + + for (i = 0; i < MPI3MR_MAX_NUM_HDB; i++) { + diag_buffer = &mrioc->diag_buffers[i]; + if (!(diag_buffer->addr)) + continue; + if (diag_buffer->status == MPI3MR_HDB_BUFSTATUS_RELEASED) + continue; + if (!skip_rel_action) + mpi3mr_issue_diag_buf_release(mrioc, diag_buffer); + diag_buffer->status = MPI3MR_HDB_BUFSTATUS_RELEASED; + atomic64_inc(&event_counter); + } +} + +/** + * mpi3mr_set_trigger_data_in_hdb - Updates HDB trigger type and + * trigger data + * + * @hdb: HDB pointer + * @type: Trigger type + * @data: Trigger data + * @force: Trigger overwrite flag + * @trigger_data: pointer to trigger data information + * + * Updates trigger type and trigger data based on parameter + * passed to this function + * + * Return: Nothing + */ +void mpi3mr_set_trigger_data_in_hdb(struct diag_buffer_desc *hdb, + u8 type, union mpi3mr_trigger_data *trigger_data, bool force) +{ + if ((!force) && (hdb->trigger_type != MPI3MR_HDB_TRIGGER_TYPE_UNKNOWN)) + return; + hdb->trigger_type = type; + if (!trigger_data) + memset(&hdb->trigger_data, 0, sizeof(*trigger_data)); + else + memcpy(&hdb->trigger_data, trigger_data, sizeof(*trigger_data)); +} + +/** + * mpi3mr_diag_buffer_for_type - returns buffer desc for type + * @mrioc: Adapter instance reference + * @buf_type: Diagnostic buffer type + * + * Identifies matching diag descriptor from mrioc for given diag + * buffer type. + * + * Return: diag buffer descriptor on success, NULL on failures. + */ + +struct diag_buffer_desc * +mpi3mr_diag_buffer_for_type(struct mpi3mr_ioc *mrioc, u8 buf_type) +{ + u8 i; + + for (i = 0; i < MPI3MR_MAX_NUM_HDB; i++) { + if (mrioc->diag_buffers[i].type == buf_type) + return &mrioc->diag_buffers[i]; + } + return NULL; +} + /** * mpi3mr_bsg_pel_abort - sends PEL abort request * @mrioc: Adapter instance reference diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c index c2a22e96f7b7..fbd6f32f79ce 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c @@ -3003,7 +3003,11 @@ static void mpi3mr_process_factsdata(struct mpi3mr_ioc *mrioc, mrioc->facts.sge_mod_shift = facts_data->sge_modifier_shift; mrioc->facts.shutdown_timeout = le16_to_cpu(facts_data->shutdown_timeout); - + mrioc->facts.diag_trace_sz = + le32_to_cpu(facts_data->diag_trace_size); + mrioc->facts.diag_fw_sz = + le32_to_cpu(facts_data->diag_fw_size); + mrioc->facts.diag_drvr_sz = le32_to_cpu(facts_data->diag_driver_size); mrioc->facts.max_dev_per_tg = facts_data->max_devices_per_throttle_group; mrioc->facts.io_throttle_data_length = @@ -3681,6 +3685,94 @@ static const struct { { MPI3_IOCFACTS_CAPABILITY_MULTIPATH_SUPPORTED, "MultiPath" }, }; +/** + * mpi3mr_repost_diag_bufs - repost host diag buffers + * @mrioc: Adapter instance reference + * + * repost firmware and trace diag buffers based on global + * trigger flag from driver page 2 + * + * Return: 0 on success, non-zero on failures. + */ +static int mpi3mr_repost_diag_bufs(struct mpi3mr_ioc *mrioc) +{ + u64 global_trigger; + union mpi3mr_trigger_data prev_trigger_data; + struct diag_buffer_desc *trace_hdb = NULL; + struct diag_buffer_desc *fw_hdb = NULL; + int retval = 0; + bool trace_repost_needed = false; + bool fw_repost_needed = false; + u8 prev_trigger_type; + + retval = mpi3mr_refresh_trigger(mrioc, MPI3_CONFIG_ACTION_READ_CURRENT); + if (retval) + return -1; + + trace_hdb = mpi3mr_diag_buffer_for_type(mrioc, + MPI3_DIAG_BUFFER_TYPE_TRACE); + + if (trace_hdb && + trace_hdb->status != MPI3MR_HDB_BUFSTATUS_NOT_ALLOCATED && + trace_hdb->trigger_type != MPI3MR_HDB_TRIGGER_TYPE_GLOBAL && + trace_hdb->trigger_type != MPI3MR_HDB_TRIGGER_TYPE_ELEMENT) + trace_repost_needed = true; + + fw_hdb = mpi3mr_diag_buffer_for_type(mrioc, MPI3_DIAG_BUFFER_TYPE_FW); + + if (fw_hdb && fw_hdb->status != MPI3MR_HDB_BUFSTATUS_NOT_ALLOCATED && + fw_hdb->trigger_type != MPI3MR_HDB_TRIGGER_TYPE_GLOBAL && + fw_hdb->trigger_type != MPI3MR_HDB_TRIGGER_TYPE_ELEMENT) + fw_repost_needed = true; + + if (trace_repost_needed || fw_repost_needed) { + global_trigger = le64_to_cpu(mrioc->driver_pg2->global_trigger); + if (global_trigger & + MPI3_DRIVER2_GLOBALTRIGGER_POST_DIAG_TRACE_DISABLED) + trace_repost_needed = false; + if (global_trigger & + MPI3_DRIVER2_GLOBALTRIGGER_POST_DIAG_FW_DISABLED) + fw_repost_needed = false; + } + + if (trace_repost_needed) { + prev_trigger_type = trace_hdb->trigger_type; + memcpy(&prev_trigger_data, &trace_hdb->trigger_data, + sizeof(trace_hdb->trigger_data)); + retval = mpi3mr_issue_diag_buf_post(mrioc, trace_hdb); + if (!retval) { + dprint_init(mrioc, "trace diag buffer reposted"); + mpi3mr_set_trigger_data_in_hdb(trace_hdb, + MPI3MR_HDB_TRIGGER_TYPE_UNKNOWN, NULL, 1); + } else { + trace_hdb->trigger_type = prev_trigger_type; + memcpy(&trace_hdb->trigger_data, &prev_trigger_data, + sizeof(prev_trigger_data)); + ioc_err(mrioc, "trace diag buffer repost failed"); + return -1; + } + } + + if (fw_repost_needed) { + prev_trigger_type = fw_hdb->trigger_type; + memcpy(&prev_trigger_data, &fw_hdb->trigger_data, + sizeof(fw_hdb->trigger_data)); + retval = mpi3mr_issue_diag_buf_post(mrioc, fw_hdb); + if (!retval) { + dprint_init(mrioc, "firmware diag buffer reposted"); + mpi3mr_set_trigger_data_in_hdb(fw_hdb, + MPI3MR_HDB_TRIGGER_TYPE_UNKNOWN, NULL, 1); + } else { + fw_hdb->trigger_type = prev_trigger_type; + memcpy(&fw_hdb->trigger_data, &prev_trigger_data, + sizeof(prev_trigger_data)); + ioc_err(mrioc, "firmware diag buffer repost failed"); + return -1; + } + } + return retval; +} + /** * mpi3mr_print_ioc_info - Display controller information * @mrioc: Adapter instance reference @@ -3989,9 +4081,18 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc) } } + dprint_init(mrioc, "allocating host diag buffers\n"); + mpi3mr_alloc_diag_bufs(mrioc); + dprint_init(mrioc, "allocating ioctl dma buffers\n"); mpi3mr_alloc_ioctl_dma_memory(mrioc); + dprint_init(mrioc, "posting host diag buffers\n"); + retval = mpi3mr_post_diag_bufs(mrioc); + + if (retval) + ioc_warn(mrioc, "failed to post host diag buffers\n"); + if (!mrioc->init_cmds.reply) { retval = mpi3mr_alloc_reply_sense_bufs(mrioc); if (retval) { @@ -4144,6 +4245,17 @@ int mpi3mr_reinit_ioc(struct mpi3mr_ioc *mrioc, u8 is_resume) mpi3mr_print_ioc_info(mrioc); + if (is_resume) { + dprint_reset(mrioc, "posting host diag buffers\n"); + retval = mpi3mr_post_diag_bufs(mrioc); + if (retval) + ioc_warn(mrioc, "failed to post host diag buffers\n"); + } else { + retval = mpi3mr_repost_diag_bufs(mrioc); + if (retval) + ioc_warn(mrioc, "failed to re post host diag buffers\n"); + } + dprint_reset(mrioc, "sending ioc_init\n"); retval = mpi3mr_issue_iocinit(mrioc); if (retval) { @@ -4409,6 +4521,7 @@ void mpi3mr_free_mem(struct mpi3mr_ioc *mrioc) { u16 i; struct mpi3mr_intr_info *intr_info; + struct diag_buffer_desc *diag_buffer; mpi3mr_free_enclosure_list(mrioc); mpi3mr_free_ioctl_dma_memory(mrioc); @@ -4543,6 +4656,19 @@ void mpi3mr_free_mem(struct mpi3mr_ioc *mrioc) mrioc->pel_seqnum_virt = NULL; } + for (i = 0; i < MPI3MR_MAX_NUM_HDB; i++) { + diag_buffer = &mrioc->diag_buffers[i]; + if (diag_buffer->addr) { + dma_free_coherent(&mrioc->pdev->dev, + diag_buffer->size, diag_buffer->addr, + diag_buffer->dma_addr); + diag_buffer->addr = NULL; + diag_buffer->size = 0; + diag_buffer->type = 0; + diag_buffer->status = 0; + } + } + kfree(mrioc->throttle_groups); mrioc->throttle_groups = NULL; @@ -5016,6 +5142,9 @@ int mpi3mr_soft_reset_handler(struct mpi3mr_ioc *mrioc, if ((!snapdump) && (reset_reason != MPI3MR_RESET_FROM_FAULT_WATCH) && (reset_reason != MPI3MR_RESET_FROM_FIRMWARE) && (reset_reason != MPI3MR_RESET_FROM_CIACTIV_FAULT)) { + dprint_reset(mrioc, + "soft_reset_handler: releasing host diagnostic buffers\n"); + mpi3mr_release_diag_bufs(mrioc, 0); for (i = 0; i < MPI3_EVENT_NOTIFY_EVENTMASK_WORDS; i++) mrioc->event_masks[i] = -1; @@ -5075,6 +5204,7 @@ int mpi3mr_soft_reset_handler(struct mpi3mr_ioc *mrioc, mrioc->prepare_for_reset_timeout_counter = 0; } mpi3mr_memset_buffers(mrioc); + mpi3mr_release_diag_bufs(mrioc, 1); retval = mpi3mr_reinit_ioc(mrioc, 0); if (retval) { pr_err(IOCNAME "reinit after soft reset failed: reason %d\n", @@ -5954,3 +6084,64 @@ int mpi3mr_cfg_get_driver_pg1(struct mpi3mr_ioc *mrioc, out_failed: return -1; } + +/** + * mpi3mr_cfg_get_driver_pg2 - Read current driver page2 + * @mrioc: Adapter instance reference + * @driver_pg2: Pointer to return driver page 2 + * @pg_sz: Size of the memory allocated to the page pointer + * @page_action: Page action + * + * This is handler for config page read for the driver page2. + * This routine checks ioc_status to decide whether the page + * read is success or not. + * + * Return: 0 on success, non-zero on failure. + */ +int mpi3mr_cfg_get_driver_pg2(struct mpi3mr_ioc *mrioc, + struct mpi3_driver_page2 *driver_pg2, u16 pg_sz, u8 page_action) +{ + struct mpi3_config_page_header cfg_hdr; + struct mpi3_config_request cfg_req; + u16 ioc_status = 0; + + memset(driver_pg2, 0, pg_sz); + memset(&cfg_hdr, 0, sizeof(cfg_hdr)); + memset(&cfg_req, 0, sizeof(cfg_req)); + + cfg_req.function = MPI3_FUNCTION_CONFIG; + cfg_req.action = MPI3_CONFIG_ACTION_PAGE_HEADER; + cfg_req.page_type = MPI3_CONFIG_PAGETYPE_DRIVER; + cfg_req.page_number = 2; + cfg_req.page_address = 0; + cfg_req.page_version = MPI3_DRIVER2_PAGEVERSION; + + if (mpi3mr_process_cfg_req(mrioc, &cfg_req, NULL, + MPI3MR_INTADMCMD_TIMEOUT, &ioc_status, &cfg_hdr, sizeof(cfg_hdr))) { + ioc_err(mrioc, "driver page2 header read failed\n"); + goto out_failed; + } + if (ioc_status != MPI3_IOCSTATUS_SUCCESS) { + ioc_err(mrioc, "driver page2 header read failed with\n" + "ioc_status(0x%04x)\n", + ioc_status); + goto out_failed; + } + cfg_req.action = page_action; + + if (mpi3mr_process_cfg_req(mrioc, &cfg_req, &cfg_hdr, + MPI3MR_INTADMCMD_TIMEOUT, &ioc_status, driver_pg2, pg_sz)) { + ioc_err(mrioc, "driver page2 read failed\n"); + goto out_failed; + } + if (ioc_status != MPI3_IOCSTATUS_SUCCESS) { + ioc_err(mrioc, "driver page2 read failed with\n" + "ioc_status(0x%04x)\n", + ioc_status); + goto out_failed; + } + return 0; +out_failed: + return -1; +} + From patchwork Tue Jun 18 11:56:53 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ranjan Kumar X-Patchwork-Id: 13702150 Received: from mail-pj1-f54.google.com (mail-pj1-f54.google.com [209.85.216.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C6783158213 for ; Tue, 18 Jun 2024 12:00:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718712015; cv=none; b=cw6PkA2l7iROwTqIPTN4OXZKOpKSS+lYUMvtbu/dY6KwKnwHPe8sLkabgeMmb3qJ1vGFAoxHDbWv8HAUrKNHBPsGIFxmqkwy2rjOcQU8v5XNG6yKRYpzmkeGoxWgOKea6xJFilL4/sLT+jn94gf6IcyhNdDzJKl7r7yX5NW2T5w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718712015; c=relaxed/simple; bh=cb5SEZGyaqjim4YFD3VMDRLT6N3NbicbGGGKZv0rv8E=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=QWVvEv1R+hzDe7eC0B6J3pgVr3wFp8h6ZoFzIjpDq8QonNHC2SDPzbdHire3XePCgRnu4LZyQ3jLxz0BKCu9PQPbH8sCyQDXaxmklGyL5EbQCDqiA9qBDc9K+MWz4zjqwzVlHjI/EiDHULshmR+n6wMqLQpGArdL1lW2hWH0NJA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=broadcom.com; spf=fail smtp.mailfrom=broadcom.com; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b=WubjlYwU; arc=none smtp.client-ip=209.85.216.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=broadcom.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=broadcom.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b="WubjlYwU" Received: by mail-pj1-f54.google.com with SMTP id 98e67ed59e1d1-2c70c37287fso497843a91.0 for ; Tue, 18 Jun 2024 05:00:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1718712011; x=1719316811; darn=vger.kernel.org; h=mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:from:to:cc:subject:date:message-id:reply-to; bh=zPrpikAfjtwLO2gIyl6oh/kutYP5F9bXWA8dtmUYFZs=; b=WubjlYwUB/DWzy+MmqxhWq4DFH0Y9+MPSG/Ts0q0gfarvQmEA+3GPtt6YhuWcZlybB MDiOqttIrECKWNAWdXGw9A8uyJsA6fshOnRbzM/tUS7mOkYfaGg00xUP/dF0vz/TGktp s4aKbTwhmgc+9L1QYKwc1v5F8ZNFDH25/Ux0Q= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1718712011; x=1719316811; h=mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=zPrpikAfjtwLO2gIyl6oh/kutYP5F9bXWA8dtmUYFZs=; b=DO0AfnfJ+aEAL4EaBCmiIoJylfR6Mi0kAEK/KZfkLRoQhL9xB42pDFHXW3o9FgbY4Y uJo6x1qhFbMqo2WxAlqhnTDtmjjrB2jeQ7O0X0JS1X3dGobBBfb5eyWu+lksB3jIVruA JOG4cFCo+rAayVI/N+3CtP6DoaoSbjm66es/a28vFaLr2DVXpfMSuriyADE2VWVmWVCJ pPhLTPZHFMOgcFEVZbhIaU1qUU97r/aiFOOL/jRQk92q+eXlJbGgMHEDYNGLDTc4xMHT W2yrVitk9uXcuUIT4GAgmHF93hla1GaaXiWFyhq5pps70NscZ6sv6UNdU2VVQzQFXfMQ dq6w== X-Gm-Message-State: AOJu0Ywr4quIi4LBny0MbpIJyxD4Ukxs0zgbU6EWIGZyP8KYIc2tXpsc 3TgJuXt+2bvG5Gn0vObalBL7WglSTIcbQtdJuaTf/smo5CpZdwCX8zfdZOK0knMxfks4u0msa5e H53b1Kgtk06kue89ZL2aRYtuaw2L7Sn4P04z1IWX4qn/uLqOD0foxmHw9URo+96mLiGWDh1Szm1 fDd4GtStrYJ8hCaVQERx8qHinoALcx7nE+Bn6MOMGbo3rh8Q== X-Google-Smtp-Source: AGHT+IEVNCgRNVY5QIy6uOVKe2ld9XJJUiyrZpHMn6Uhe0wwi3UQdk5JMuYuWT6bns+gqTzXkO7IAw== X-Received: by 2002:a17:90b:4f4b:b0:2c1:aa8e:d70 with SMTP id 98e67ed59e1d1-2c4da9c8de9mr12631778a91.0.1718712010603; Tue, 18 Jun 2024 05:00:10 -0700 (PDT) Received: from localhost.localdomain ([192.19.234.250]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2c4a76037a4sm12925963a91.29.2024.06.18.05.00.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Jun 2024 05:00:09 -0700 (PDT) From: Ranjan Kumar 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 , kernel test robot Subject: [PATCH v5 2/4] mpi3mr: Trigger support Date: Tue, 18 Jun 2024 17:26:53 +0530 Message-Id: <20240618115655.15066-3-ranjan.kumar@broadcom.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20240618115655.15066-1-ranjan.kumar@broadcom.com> References: <20240618115655.15066-1-ranjan.kumar@broadcom.com> Precedence: bulk X-Mailing-List: linux-scsi@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This patch adds functions to process automatic diag triggers and if a condition defined in the triggers is met the driver will call appropriate controller functions to save the diagnostic information. Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202405151955.BiAWI1SY-lkp@intel.com/ Signed-off-by: Sathya Prakash Signed-off-by: Ranjan Kumar --- drivers/scsi/mpi3mr/mpi3mr.h | 43 ++++ drivers/scsi/mpi3mr/mpi3mr_app.c | 337 ++++++++++++++++++++++++++++++- drivers/scsi/mpi3mr/mpi3mr_fw.c | 79 +++++++- drivers/scsi/mpi3mr/mpi3mr_os.c | 113 +++++++++++ 4 files changed, 564 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h index 9aae59646faa..e14982a785a6 100644 --- a/drivers/scsi/mpi3mr/mpi3mr.h +++ b/drivers/scsi/mpi3mr/mpi3mr.h @@ -193,7 +193,12 @@ extern atomic64_t event_counter; #define MPI3MR_DEFAULT_HDB_MIN_SZ (2 * 1024 * 1024) #define MPI3MR_MAX_NUM_HDB 2 +#define MPI3MR_HDB_TRIGGER_TYPE_UNKNOWN 0 +#define MPI3MR_HDB_TRIGGER_TYPE_FAULT 1 +#define MPI3MR_HDB_TRIGGER_TYPE_ELEMENT 2 #define MPI3MR_HDB_TRIGGER_TYPE_GLOBAL 3 +#define MPI3MR_HDB_TRIGGER_TYPE_SOFT_RESET 4 +#define MPI3MR_HDB_TRIGGER_TYPE_FW_RELEASED 5 /* SGE Flag definition */ #define MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST \ @@ -218,6 +223,7 @@ extern atomic64_t event_counter; #define MPI3MR_WRITE_SAME_MAX_LEN_256_BLKS 256 #define MPI3MR_WRITE_SAME_MAX_LEN_2048_BLKS 2048 +#define MPI3MR_DRIVER_EVENT_PROCESS_TRIGGER (0xFFFD) /** * struct mpi3mr_nvme_pt_sge - Structure to store SGEs for NVMe @@ -303,6 +309,7 @@ enum mpi3mr_reset_reason { MPI3MR_RESET_FROM_FIRMWARE = 27, MPI3MR_RESET_FROM_CFG_REQ_TIMEOUT = 29, MPI3MR_RESET_FROM_SAS_TRANSPORT_TIMEOUT = 30, + MPI3MR_RESET_FROM_TRIGGER = 31, }; #define MPI3MR_RESET_REASON_OSTYPE_LINUX 1 @@ -878,6 +885,24 @@ union mpi3mr_trigger_data { union mpi3_driver2_trigger_element element; }; +/** + * struct trigger_event_data - store trigger related + * information. + * + * @trace_hdb: Trace diag buffer descriptor reference + * @fw_hdb: FW diag buffer descriptor reference + * @trigger_type: Trigger type + * @trigger_specific_data: Trigger specific data + * @snapdump: Snapdump enable or disable flag + */ +struct trigger_event_data { + struct diag_buffer_desc *trace_hdb; + struct diag_buffer_desc *fw_hdb; + u8 trigger_type; + union mpi3mr_trigger_data trigger_specific_data; + bool snapdump; +}; + /** * struct diag_buffer_desc - memory descriptor structure to * store virtual, dma addresses, size, buffer status for host @@ -1113,6 +1138,9 @@ 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 + * @trace_release_trigger_active: Trace trigger active flag + * @fw_release_trigger_active: Fw release trigger active flag + * @snapdump_trigger_active: Snapdump trigger active flag */ struct mpi3mr_ioc { struct list_head list; @@ -1310,6 +1338,9 @@ struct mpi3mr_ioc { struct diag_buffer_desc diag_buffers[MPI3MR_MAX_NUM_HDB]; struct mpi3_driver_page2 *driver_pg2; spinlock_t trigger_lock; + bool snapdump_trigger_active; + bool trace_release_trigger_active; + bool fw_release_trigger_active; }; /** @@ -1513,4 +1544,16 @@ struct diag_buffer_desc *mpi3mr_diag_buffer_for_type(struct mpi3mr_ioc *mrioc, u8 buf_type); int mpi3mr_issue_diag_buf_post(struct mpi3mr_ioc *mrioc, struct diag_buffer_desc *diag_buffer); +void mpi3mr_set_trigger_data_in_all_hdb(struct mpi3mr_ioc *mrioc, + u8 type, union mpi3mr_trigger_data *trigger_data, bool force); +void mpi3mr_reply_trigger(struct mpi3mr_ioc *mrioc, u16 iocstatus, + u32 iocloginfo); +void mpi3mr_hdb_trigger_data_event(struct mpi3mr_ioc *mrioc, + struct trigger_event_data *event_data); +void mpi3mr_scsisense_trigger(struct mpi3mr_ioc *mrioc, u8 senseky, u8 asc, + u8 ascq); +void mpi3mr_event_trigger(struct mpi3mr_ioc *mrioc, u8 event); +void mpi3mr_global_trigger(struct mpi3mr_ioc *mrioc, u64 trigger_data); +void mpi3mr_hdbstatuschg_evt_th(struct mpi3mr_ioc *mrioc, + struct mpi3_event_notification_reply *event_reply); #endif /*MPI3MR_H_INCLUDED*/ diff --git a/drivers/scsi/mpi3mr/mpi3mr_app.c b/drivers/scsi/mpi3mr/mpi3mr_app.c index 6bb006b7ef7e..9d15c307374a 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_app.c +++ b/drivers/scsi/mpi3mr/mpi3mr_app.c @@ -316,6 +316,263 @@ int mpi3mr_issue_diag_buf_release(struct mpi3mr_ioc *mrioc, return retval; } +/** + * mpi3mr_process_trigger - Generic HDB Trigger handler + * @mrioc: Adapter instance reference + * @trigger_type: Trigger type + * @trigger_data: Trigger data + * @trigger_flags: Trigger flags + * + * This function checks validity of HDB, triggers and based on + * trigger information, creates an event to be processed in the + * firmware event worker thread . + * + * This function should be called with trigger spinlock held + * + * Return: Nothing + */ +static void mpi3mr_process_trigger(struct mpi3mr_ioc *mrioc, u8 trigger_type, + union mpi3mr_trigger_data *trigger_data, u8 trigger_flags) +{ + struct trigger_event_data event_data; + struct diag_buffer_desc *trace_hdb = NULL; + struct diag_buffer_desc *fw_hdb = NULL; + u64 global_trigger; + + trace_hdb = mpi3mr_diag_buffer_for_type(mrioc, + MPI3_DIAG_BUFFER_TYPE_TRACE); + if (trace_hdb && + (trace_hdb->status != MPI3MR_HDB_BUFSTATUS_POSTED_UNPAUSED) && + (trace_hdb->status != MPI3MR_HDB_BUFSTATUS_POSTED_PAUSED)) + trace_hdb = NULL; + + fw_hdb = mpi3mr_diag_buffer_for_type(mrioc, MPI3_DIAG_BUFFER_TYPE_FW); + + if (fw_hdb && + (fw_hdb->status != MPI3MR_HDB_BUFSTATUS_POSTED_UNPAUSED) && + (fw_hdb->status != MPI3MR_HDB_BUFSTATUS_POSTED_PAUSED)) + fw_hdb = NULL; + + if (mrioc->snapdump_trigger_active || (mrioc->fw_release_trigger_active + && mrioc->trace_release_trigger_active) || + (!trace_hdb && !fw_hdb) || (!mrioc->driver_pg2) || + ((trigger_type == MPI3MR_HDB_TRIGGER_TYPE_ELEMENT) + && (!mrioc->driver_pg2->num_triggers))) + return; + + memset(&event_data, 0, sizeof(event_data)); + event_data.trigger_type = trigger_type; + memcpy(&event_data.trigger_specific_data, trigger_data, + sizeof(*trigger_data)); + global_trigger = le64_to_cpu(mrioc->driver_pg2->global_trigger); + + if (global_trigger & MPI3_DRIVER2_GLOBALTRIGGER_SNAPDUMP_ENABLED) { + event_data.snapdump = true; + event_data.trace_hdb = trace_hdb; + event_data.fw_hdb = fw_hdb; + mrioc->snapdump_trigger_active = true; + } else if (trigger_type == MPI3MR_HDB_TRIGGER_TYPE_GLOBAL) { + if ((trace_hdb) && (global_trigger & + MPI3_DRIVER2_GLOBALTRIGGER_DIAG_TRACE_RELEASE) && + (!mrioc->trace_release_trigger_active)) { + event_data.trace_hdb = trace_hdb; + mrioc->trace_release_trigger_active = true; + } + if ((fw_hdb) && (global_trigger & + MPI3_DRIVER2_GLOBALTRIGGER_DIAG_FW_RELEASE) && + (!mrioc->fw_release_trigger_active)) { + event_data.fw_hdb = fw_hdb; + mrioc->fw_release_trigger_active = true; + } + } else if (trigger_type == MPI3MR_HDB_TRIGGER_TYPE_ELEMENT) { + if ((trace_hdb) && (trigger_flags & + MPI3_DRIVER2_TRIGGER_FLAGS_DIAG_TRACE_RELEASE) && + (!mrioc->trace_release_trigger_active)) { + event_data.trace_hdb = trace_hdb; + mrioc->trace_release_trigger_active = true; + } + if ((fw_hdb) && (trigger_flags & + MPI3_DRIVER2_TRIGGER_FLAGS_DIAG_FW_RELEASE) && + (!mrioc->fw_release_trigger_active)) { + event_data.fw_hdb = fw_hdb; + mrioc->fw_release_trigger_active = true; + } + } + + if (event_data.trace_hdb || event_data.fw_hdb) + mpi3mr_hdb_trigger_data_event(mrioc, &event_data); +} + +/** + * mpi3mr_global_trigger - Global HDB trigger handler + * @mrioc: Adapter instance reference + * @trigger_data: Trigger data + * + * This function checks whether the given global trigger is + * enabled in the driver page 2 and if so calls generic trigger + * handler to queue event for HDB release. + * + * Return: Nothing + */ +void mpi3mr_global_trigger(struct mpi3mr_ioc *mrioc, u64 trigger_data) +{ + unsigned long flags; + union mpi3mr_trigger_data trigger_specific_data; + + spin_lock_irqsave(&mrioc->trigger_lock, flags); + if (le64_to_cpu(mrioc->driver_pg2->global_trigger) & trigger_data) { + memset(&trigger_specific_data, 0, + sizeof(trigger_specific_data)); + trigger_specific_data.global = trigger_data; + mpi3mr_process_trigger(mrioc, MPI3MR_HDB_TRIGGER_TYPE_GLOBAL, + &trigger_specific_data, 0); + } + spin_unlock_irqrestore(&mrioc->trigger_lock, flags); +} + +/** + * mpi3mr_scsisense_trigger - SCSI sense HDB trigger handler + * @mrioc: Adapter instance reference + * @sensekey: Sense Key + * @asc: Additional Sense Code + * @ascq: Additional Sense Code Qualifier + * + * This function compares SCSI sense trigger values with driver + * page 2 values and calls generic trigger handler to release + * HDBs if match found + * + * Return: Nothing + */ +void mpi3mr_scsisense_trigger(struct mpi3mr_ioc *mrioc, u8 sensekey, u8 asc, + u8 ascq) +{ + struct mpi3_driver2_trigger_scsi_sense *scsi_sense_trigger = NULL; + u64 i = 0; + unsigned long flags; + u8 num_triggers, trigger_flags; + + if (mrioc->scsisense_trigger_present) { + spin_lock_irqsave(&mrioc->trigger_lock, flags); + scsi_sense_trigger = (struct mpi3_driver2_trigger_scsi_sense *) + mrioc->driver_pg2->trigger; + num_triggers = mrioc->driver_pg2->num_triggers; + for (i = 0; i < num_triggers; i++, scsi_sense_trigger++) { + if (scsi_sense_trigger->type != + MPI3_DRIVER2_TRIGGER_TYPE_SCSI_SENSE) + continue; + if (!(scsi_sense_trigger->sense_key == + MPI3_DRIVER2_TRIGGER_SCSI_SENSE_SENSE_KEY_MATCH_ALL + || scsi_sense_trigger->sense_key == sensekey)) + continue; + if (!(scsi_sense_trigger->asc == + MPI3_DRIVER2_TRIGGER_SCSI_SENSE_ASC_MATCH_ALL || + scsi_sense_trigger->asc == asc)) + continue; + if (!(scsi_sense_trigger->ascq == + MPI3_DRIVER2_TRIGGER_SCSI_SENSE_ASCQ_MATCH_ALL || + scsi_sense_trigger->ascq == ascq)) + continue; + trigger_flags = scsi_sense_trigger->flags; + mpi3mr_process_trigger(mrioc, + MPI3MR_HDB_TRIGGER_TYPE_ELEMENT, + (union mpi3mr_trigger_data *)scsi_sense_trigger, + trigger_flags); + break; + } + spin_unlock_irqrestore(&mrioc->trigger_lock, flags); + } +} + +/** + * mpi3mr_event_trigger - MPI event HDB trigger handler + * @mrioc: Adapter instance reference + * @event: MPI Event + * + * This function compares event trigger values with driver page + * 2 values and calls generic trigger handler to release + * HDBs if match found. + * + * Return: Nothing + */ +void mpi3mr_event_trigger(struct mpi3mr_ioc *mrioc, u8 event) +{ + struct mpi3_driver2_trigger_event *event_trigger = NULL; + u64 i = 0; + unsigned long flags; + u8 num_triggers, trigger_flags; + + if (mrioc->event_trigger_present) { + spin_lock_irqsave(&mrioc->trigger_lock, flags); + event_trigger = (struct mpi3_driver2_trigger_event *) + mrioc->driver_pg2->trigger; + num_triggers = mrioc->driver_pg2->num_triggers; + + for (i = 0; i < num_triggers; i++, event_trigger++) { + if (event_trigger->type != + MPI3_DRIVER2_TRIGGER_TYPE_EVENT) + continue; + if (event_trigger->event != event) + continue; + trigger_flags = event_trigger->flags; + mpi3mr_process_trigger(mrioc, + MPI3MR_HDB_TRIGGER_TYPE_ELEMENT, + (union mpi3mr_trigger_data *)event_trigger, + trigger_flags); + break; + } + spin_unlock_irqrestore(&mrioc->trigger_lock, flags); + } +} + +/** + * mpi3mr_reply_trigger - MPI Reply HDB trigger handler + * @mrioc: Adapter instance reference + * @ioc_status: Masked value of IOC Status from MPI Reply + * @ioc_loginfo: IOC Log Info from MPI Reply + * + * This function compares IOC status and IOC log info trigger + * values with driver page 2 values and calls generic trigger + * handler to release HDBs if match found. + * + * Return: Nothing + */ +void mpi3mr_reply_trigger(struct mpi3mr_ioc *mrioc, u16 ioc_status, + u32 ioc_loginfo) +{ + struct mpi3_driver2_trigger_reply *reply_trigger = NULL; + u64 i = 0; + unsigned long flags; + u8 num_triggers, trigger_flags; + + if (mrioc->reply_trigger_present) { + spin_lock_irqsave(&mrioc->trigger_lock, flags); + reply_trigger = (struct mpi3_driver2_trigger_reply *) + mrioc->driver_pg2->trigger; + num_triggers = mrioc->driver_pg2->num_triggers; + for (i = 0; i < num_triggers; i++, reply_trigger++) { + if (reply_trigger->type != + MPI3_DRIVER2_TRIGGER_TYPE_REPLY) + continue; + if ((le16_to_cpu(reply_trigger->ioc_status) != + ioc_status) + && (le16_to_cpu(reply_trigger->ioc_status) != + MPI3_DRIVER2_TRIGGER_REPLY_IOCSTATUS_MATCH_ALL)) + continue; + if ((le32_to_cpu(reply_trigger->ioc_log_info) != + (le32_to_cpu(reply_trigger->ioc_log_info_mask) & + ioc_loginfo))) + continue; + trigger_flags = reply_trigger->flags; + mpi3mr_process_trigger(mrioc, + MPI3MR_HDB_TRIGGER_TYPE_ELEMENT, + (union mpi3mr_trigger_data *)reply_trigger, + trigger_flags); + break; + } + spin_unlock_irqrestore(&mrioc->trigger_lock, flags); + } +} + /** * mpi3mr_get_num_trigger - Gets number of HDB triggers * @mrioc: Adapter instance reference @@ -449,7 +706,7 @@ void mpi3mr_release_diag_bufs(struct mpi3mr_ioc *mrioc, u8 skip_rel_action) * @type: Trigger type * @data: Trigger data * @force: Trigger overwrite flag - * @trigger_data: pointer to trigger data information + * @trigger_data: Pointer to trigger data information * * Updates trigger type and trigger data based on parameter * passed to this function @@ -468,6 +725,84 @@ void mpi3mr_set_trigger_data_in_hdb(struct diag_buffer_desc *hdb, memcpy(&hdb->trigger_data, trigger_data, sizeof(*trigger_data)); } +/** + * mpi3mr_set_trigger_data_in_all_hdb - Updates HDB trigger type + * and trigger data for all HDB + * + * @mrioc: Adapter instance reference + * @type: Trigger type + * @data: Trigger data + * @force: Trigger overwrite flag + * @trigger_data: Pointer to trigger data information + * + * Updates trigger type and trigger data based on parameter + * passed to this function + * + * Return: Nothing + */ +void mpi3mr_set_trigger_data_in_all_hdb(struct mpi3mr_ioc *mrioc, + u8 type, union mpi3mr_trigger_data *trigger_data, bool force) +{ + struct diag_buffer_desc *hdb = NULL; + + hdb = mpi3mr_diag_buffer_for_type(mrioc, MPI3_DIAG_BUFFER_TYPE_TRACE); + if (hdb) + mpi3mr_set_trigger_data_in_hdb(hdb, type, trigger_data, force); + hdb = mpi3mr_diag_buffer_for_type(mrioc, MPI3_DIAG_BUFFER_TYPE_FW); + if (hdb) + mpi3mr_set_trigger_data_in_hdb(hdb, type, trigger_data, force); +} + +/** + * mpi3mr_hdbstatuschg_evt_th - HDB status change evt tophalf + * @mrioc: Adapter instance reference + * @event_reply: event data + * + * Modifies the status of the applicable diag buffer descriptors + * + * Return: Nothing + */ +void mpi3mr_hdbstatuschg_evt_th(struct mpi3mr_ioc *mrioc, + struct mpi3_event_notification_reply *event_reply) +{ + struct mpi3_event_data_diag_buffer_status_change *evtdata; + struct diag_buffer_desc *diag_buffer; + + evtdata = (struct mpi3_event_data_diag_buffer_status_change *) + event_reply->event_data; + + diag_buffer = mpi3mr_diag_buffer_for_type(mrioc, evtdata->type); + if (!diag_buffer) + return; + if ((diag_buffer->status != MPI3MR_HDB_BUFSTATUS_POSTED_UNPAUSED) && + (diag_buffer->status != MPI3MR_HDB_BUFSTATUS_POSTED_PAUSED)) + return; + switch (evtdata->reason_code) { + case MPI3_EVENT_DIAG_BUFFER_STATUS_CHANGE_RC_RELEASED: + { + diag_buffer->status = MPI3MR_HDB_BUFSTATUS_RELEASED; + mpi3mr_set_trigger_data_in_hdb(diag_buffer, + MPI3MR_HDB_TRIGGER_TYPE_FW_RELEASED, NULL, 0); + atomic64_inc(&event_counter); + break; + } + case MPI3_EVENT_DIAG_BUFFER_STATUS_CHANGE_RC_RESUMED: + { + diag_buffer->status = MPI3MR_HDB_BUFSTATUS_POSTED_UNPAUSED; + break; + } + case MPI3_EVENT_DIAG_BUFFER_STATUS_CHANGE_RC_PAUSED: + { + diag_buffer->status = MPI3MR_HDB_BUFSTATUS_POSTED_PAUSED; + break; + } + default: + dprint_event_th(mrioc, "%s: unknown reason_code(%d)\n", + __func__, evtdata->reason_code); + break; + } +} + /** * mpi3mr_diag_buffer_for_type - returns buffer desc for type * @mrioc: Adapter instance reference diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c index fbd6f32f79ce..458c856dda4b 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c @@ -274,6 +274,9 @@ static void mpi3mr_print_event_data(struct mpi3mr_ioc *mrioc, case MPI3_EVENT_PREPARE_FOR_RESET: desc = "Prepare For Reset"; break; + case MPI3_EVENT_DIAGNOSTIC_BUFFER_STATUS_CHANGE: + desc = "Diagnostic Buffer Status Change"; + break; } if (!desc) @@ -342,13 +345,14 @@ static void mpi3mr_process_admin_reply_desc(struct mpi3mr_ioc *mrioc, { u16 reply_desc_type, host_tag = 0; u16 ioc_status = MPI3_IOCSTATUS_SUCCESS; - u32 ioc_loginfo = 0; + u32 ioc_loginfo = 0, sense_count = 0; struct mpi3_status_reply_descriptor *status_desc; struct mpi3_address_reply_descriptor *addr_desc; struct mpi3_success_reply_descriptor *success_desc; struct mpi3_default_reply *def_reply = NULL; struct mpi3mr_drv_cmd *cmdptr = NULL; struct mpi3_scsi_io_reply *scsi_reply; + struct scsi_sense_hdr sshdr; u8 *sense_buf = NULL; *reply_dma = 0; @@ -363,6 +367,7 @@ static void mpi3mr_process_admin_reply_desc(struct mpi3mr_ioc *mrioc, MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_LOGINFOAVAIL) ioc_loginfo = le32_to_cpu(status_desc->ioc_log_info); ioc_status &= MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_STATUS_MASK; + mpi3mr_reply_trigger(mrioc, ioc_status, ioc_loginfo); break; case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_ADDRESS_REPLY: addr_desc = (struct mpi3_address_reply_descriptor *)reply_desc; @@ -380,7 +385,15 @@ static void mpi3mr_process_admin_reply_desc(struct mpi3mr_ioc *mrioc, scsi_reply = (struct mpi3_scsi_io_reply *)def_reply; sense_buf = mpi3mr_get_sensebuf_virt_addr(mrioc, le64_to_cpu(scsi_reply->sense_data_buffer_address)); + sense_count = le32_to_cpu(scsi_reply->sense_count); + if (sense_buf) { + scsi_normalize_sense(sense_buf, sense_count, + &sshdr); + mpi3mr_scsisense_trigger(mrioc, sshdr.sense_key, + sshdr.asc, sshdr.ascq); + } } + mpi3mr_reply_trigger(mrioc, ioc_status, ioc_loginfo); break; case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_SUCCESS: success_desc = (struct mpi3_success_reply_descriptor *)reply_desc; @@ -938,6 +951,14 @@ static const struct { }, { MPI3MR_RESET_FROM_SYSFS, "sysfs invocation" }, { MPI3MR_RESET_FROM_SYSFS_TIMEOUT, "sysfs TM timeout" }, + { + MPI3MR_RESET_FROM_DIAG_BUFFER_POST_TIMEOUT, + "diagnostic buffer post timeout" + }, + { + MPI3MR_RESET_FROM_DIAG_BUFFER_RELEASE_TIMEOUT, + "diagnostic buffer release timeout" + }, { MPI3MR_RESET_FROM_FIRMWARE, "firmware asynchronous reset" }, { MPI3MR_RESET_FROM_CFG_REQ_TIMEOUT, "configuration request timeout"}, { MPI3MR_RESET_FROM_SAS_TRANSPORT_TIMEOUT, "timeout of a SAS transport layer request" }, @@ -2387,6 +2408,7 @@ int mpi3mr_op_request_post(struct mpi3mr_ioc *mrioc, void mpi3mr_check_rh_fault_ioc(struct mpi3mr_ioc *mrioc, u32 reason_code) { u32 ioc_status, host_diagnostic, timeout; + union mpi3mr_trigger_data trigger_data; if (mrioc->unrecoverable) { ioc_err(mrioc, "controller is unrecoverable\n"); @@ -2398,16 +2420,30 @@ void mpi3mr_check_rh_fault_ioc(struct mpi3mr_ioc *mrioc, u32 reason_code) ioc_err(mrioc, "controller is not present\n"); return; } - + memset(&trigger_data, 0, sizeof(trigger_data)); ioc_status = readl(&mrioc->sysif_regs->ioc_status); - if ((ioc_status & MPI3_SYSIF_IOC_STATUS_RESET_HISTORY) || - (ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT)) { + + if (ioc_status & MPI3_SYSIF_IOC_STATUS_RESET_HISTORY) { + mpi3mr_set_trigger_data_in_all_hdb(mrioc, + MPI3MR_HDB_TRIGGER_TYPE_FW_RELEASED, NULL, 0); + return; + } else if (ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT) { + trigger_data.fault = (readl(&mrioc->sysif_regs->fault) & + MPI3_SYSIF_FAULT_CODE_MASK); + + mpi3mr_set_trigger_data_in_all_hdb(mrioc, + MPI3MR_HDB_TRIGGER_TYPE_FAULT, &trigger_data, 0); mpi3mr_print_fault_info(mrioc); return; } + mpi3mr_set_diagsave(mrioc); mpi3mr_issue_reset(mrioc, MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT, reason_code); + trigger_data.fault = (readl(&mrioc->sysif_regs->fault) & + MPI3_SYSIF_FAULT_CODE_MASK); + mpi3mr_set_trigger_data_in_all_hdb(mrioc, MPI3MR_HDB_TRIGGER_TYPE_FAULT, + &trigger_data, 0); timeout = MPI3_SYSIF_DIAG_SAVE_TIMEOUT * 10; do { host_diagnostic = readl(&mrioc->sysif_regs->host_diagnostic); @@ -2587,7 +2623,8 @@ static void mpi3mr_watchdog_work(struct work_struct *work) container_of(work, struct mpi3mr_ioc, watchdog_work.work); unsigned long flags; enum mpi3mr_iocstate ioc_state; - u32 fault, host_diagnostic, ioc_status; + u32 host_diagnostic, ioc_status; + union mpi3mr_trigger_data trigger_data; u16 reset_reason = MPI3MR_RESET_FROM_FAULT_WATCH; if (mrioc->reset_in_progress) @@ -2618,8 +2655,11 @@ static void mpi3mr_watchdog_work(struct work_struct *work) return; } + memset(&trigger_data, 0, sizeof(trigger_data)); ioc_status = readl(&mrioc->sysif_regs->ioc_status); if (ioc_status & MPI3_SYSIF_IOC_STATUS_RESET_HISTORY) { + mpi3mr_set_trigger_data_in_all_hdb(mrioc, + MPI3MR_HDB_TRIGGER_TYPE_FW_RELEASED, NULL, 0); mpi3mr_soft_reset_handler(mrioc, MPI3MR_RESET_FROM_FIRMWARE, 0); return; } @@ -2629,7 +2669,9 @@ static void mpi3mr_watchdog_work(struct work_struct *work) if (ioc_state != MRIOC_STATE_FAULT) goto schedule_work; - fault = readl(&mrioc->sysif_regs->fault) & MPI3_SYSIF_FAULT_CODE_MASK; + trigger_data.fault = readl(&mrioc->sysif_regs->fault) & MPI3_SYSIF_FAULT_CODE_MASK; + mpi3mr_set_trigger_data_in_all_hdb(mrioc, + MPI3MR_HDB_TRIGGER_TYPE_FAULT, &trigger_data, 0); host_diagnostic = readl(&mrioc->sysif_regs->host_diagnostic); if (host_diagnostic & MPI3_SYSIF_HOST_DIAG_SAVE_IN_PROGRESS) { if (!mrioc->diagsave_timeout) { @@ -2643,7 +2685,7 @@ static void mpi3mr_watchdog_work(struct work_struct *work) mpi3mr_print_fault_info(mrioc); mrioc->diagsave_timeout = 0; - switch (fault) { + switch (trigger_data.fault) { case MPI3_SYSIF_FAULT_CODE_COMPLETE_RESET_NEEDED: case MPI3_SYSIF_FAULT_CODE_POWER_CYCLE_REQUIRED: ioc_warn(mrioc, @@ -3990,6 +4032,7 @@ static int mpi3mr_enable_events(struct mpi3mr_ioc *mrioc) mpi3mr_unmask_events(mrioc, MPI3_EVENT_PREPARE_FOR_RESET); mpi3mr_unmask_events(mrioc, MPI3_EVENT_CABLE_MGMT); mpi3mr_unmask_events(mrioc, MPI3_EVENT_ENERGY_PACK_CHANGE); + mpi3mr_unmask_events(mrioc, MPI3_EVENT_DIAGNOSTIC_BUFFER_STATUS_CHANGE); retval = mpi3mr_issue_event_notification(mrioc); if (retval) @@ -4168,6 +4211,12 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc) goto out_failed; } + retval = mpi3mr_refresh_trigger(mrioc, MPI3_CONFIG_ACTION_READ_CURRENT); + if (retval) { + ioc_err(mrioc, "failed to refresh triggers\n"); + goto out_failed; + } + ioc_info(mrioc, "controller initialization completed successfully\n"); return retval; out_failed: @@ -5106,6 +5155,7 @@ int mpi3mr_soft_reset_handler(struct mpi3mr_ioc *mrioc, int retval = 0, i; unsigned long flags; u32 host_diagnostic, timeout = MPI3_SYSIF_DIAG_SAVE_TIMEOUT * 10; + union mpi3mr_trigger_data trigger_data; /* Block the reset handler until diag save in progress*/ dprint_reset(mrioc, @@ -5138,10 +5188,13 @@ int mpi3mr_soft_reset_handler(struct mpi3mr_ioc *mrioc, mrioc->reset_in_progress = 1; mrioc->stop_bsgs = 1; mrioc->prev_reset_result = -1; + memset(&trigger_data, 0, sizeof(trigger_data)); if ((!snapdump) && (reset_reason != MPI3MR_RESET_FROM_FAULT_WATCH) && (reset_reason != MPI3MR_RESET_FROM_FIRMWARE) && (reset_reason != MPI3MR_RESET_FROM_CIACTIV_FAULT)) { + mpi3mr_set_trigger_data_in_all_hdb(mrioc, + MPI3MR_HDB_TRIGGER_TYPE_SOFT_RESET, NULL, 0); dprint_reset(mrioc, "soft_reset_handler: releasing host diagnostic buffers\n"); mpi3mr_release_diag_bufs(mrioc, 0); @@ -5161,6 +5214,8 @@ int mpi3mr_soft_reset_handler(struct mpi3mr_ioc *mrioc, retval = mpi3mr_issue_reset(mrioc, MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT, reset_reason); if (!retval) { + trigger_data.fault = (readl(&mrioc->sysif_regs->fault) & + MPI3_SYSIF_FAULT_CODE_MASK); do { host_diagnostic = readl(&mrioc->sysif_regs->host_diagnostic); @@ -5169,6 +5224,8 @@ int mpi3mr_soft_reset_handler(struct mpi3mr_ioc *mrioc, break; msleep(100); } while (--timeout); + mpi3mr_set_trigger_data_in_all_hdb(mrioc, + MPI3MR_HDB_TRIGGER_TYPE_FAULT, &trigger_data, 0); } } @@ -5205,6 +5262,14 @@ int mpi3mr_soft_reset_handler(struct mpi3mr_ioc *mrioc, } mpi3mr_memset_buffers(mrioc); mpi3mr_release_diag_bufs(mrioc, 1); + mrioc->fw_release_trigger_active = false; + mrioc->trace_release_trigger_active = false; + mrioc->snapdump_trigger_active = false; + mpi3mr_set_trigger_data_in_all_hdb(mrioc, + MPI3MR_HDB_TRIGGER_TYPE_SOFT_RESET, NULL, 0); + + dprint_reset(mrioc, + "soft_reset_handler: reinitializing the controller\n"); retval = mpi3mr_reinit_ioc(mrioc, 0); if (retval) { pr_err(IOCNAME "reinit after soft reset failed: reason %d\n", diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c index bce639a6cca1..eac179dc9370 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_os.c +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c @@ -241,6 +241,40 @@ static void mpi3mr_fwevt_add_to_list(struct mpi3mr_ioc *mrioc, spin_unlock_irqrestore(&mrioc->fwevt_lock, flags); } +/** + * mpi3mr_hdb_trigger_data_event - Add hdb trigger data event to + * the list + * @mrioc: Adapter instance reference + * @event_data: Event data + * + * Add the given hdb trigger data event to the firmware event + * list. + * + * Return: Nothing. + */ +void mpi3mr_hdb_trigger_data_event(struct mpi3mr_ioc *mrioc, + struct trigger_event_data *event_data) +{ + struct mpi3mr_fwevt *fwevt; + u16 sz = sizeof(*event_data); + + fwevt = mpi3mr_alloc_fwevt(sz); + if (!fwevt) { + ioc_warn(mrioc, "failed to queue hdb trigger data event\n"); + return; + } + + fwevt->mrioc = mrioc; + fwevt->event_id = MPI3MR_DRIVER_EVENT_PROCESS_TRIGGER; + fwevt->send_ack = 0; + fwevt->process_evt = 1; + fwevt->evt_ctx = 0; + fwevt->event_data_size = sz; + memcpy(fwevt->event_data, event_data, sz); + + mpi3mr_fwevt_add_to_list(mrioc, fwevt); +} + /** * mpi3mr_fwevt_del_from_list - Delete firmware event from list * @mrioc: Adapter instance reference @@ -898,6 +932,8 @@ void mpi3mr_remove_tgtdev_from_host(struct mpi3mr_ioc *mrioc, } } else mpi3mr_remove_tgtdev_from_sas_transport(mrioc, tgtdev); + mpi3mr_global_trigger(mrioc, + MPI3_DRIVER2_GLOBALTRIGGER_DEVICE_REMOVAL_ENABLED); ioc_info(mrioc, "%s :Removed handle(0x%04x), wwid(0x%016llx)\n", __func__, tgtdev->dev_handle, (unsigned long long)tgtdev->wwid); @@ -1433,6 +1469,62 @@ struct mpi3mr_enclosure_node *mpi3mr_enclosure_find_by_handle( return r; } +/** + * mpi3mr_process_trigger_data_event_bh - Process trigger event + * data + * @mrioc: Adapter instance reference + * @event_data: Event data + * + * This function releases diage buffers or issues diag fault + * based on trigger conditions + * + * Return: Nothing + */ +static void mpi3mr_process_trigger_data_event_bh(struct mpi3mr_ioc *mrioc, + struct trigger_event_data *event_data) +{ + struct diag_buffer_desc *trace_hdb = event_data->trace_hdb; + struct diag_buffer_desc *fw_hdb = event_data->fw_hdb; + unsigned long flags; + int retval = 0; + u8 trigger_type = event_data->trigger_type; + union mpi3mr_trigger_data *trigger_data = + &event_data->trigger_specific_data; + + if (event_data->snapdump) { + if (trace_hdb) + mpi3mr_set_trigger_data_in_hdb(trace_hdb, trigger_type, + trigger_data, 1); + if (fw_hdb) + mpi3mr_set_trigger_data_in_hdb(fw_hdb, trigger_type, + trigger_data, 1); + mpi3mr_soft_reset_handler(mrioc, + MPI3MR_RESET_FROM_TRIGGER, 1); + return; + } + + if (trace_hdb) { + retval = mpi3mr_issue_diag_buf_release(mrioc, trace_hdb); + if (!retval) { + mpi3mr_set_trigger_data_in_hdb(trace_hdb, trigger_type, + trigger_data, 1); + } + spin_lock_irqsave(&mrioc->trigger_lock, flags); + mrioc->trace_release_trigger_active = false; + spin_unlock_irqrestore(&mrioc->trigger_lock, flags); + } + if (fw_hdb) { + retval = mpi3mr_issue_diag_buf_release(mrioc, fw_hdb); + if (!retval) { + mpi3mr_set_trigger_data_in_hdb(fw_hdb, trigger_type, + trigger_data, 1); + } + spin_lock_irqsave(&mrioc->trigger_lock, flags); + mrioc->fw_release_trigger_active = false; + spin_unlock_irqrestore(&mrioc->trigger_lock, flags); + } +} + /** * mpi3mr_encldev_add_chg_evt_debug - debug for enclosure event * @mrioc: Adapter instance reference @@ -2019,6 +2111,12 @@ static void mpi3mr_fwevt_bh(struct mpi3mr_ioc *mrioc, "scan for non responding and newly added devices after soft reset completed\n"); break; } + case MPI3MR_DRIVER_EVENT_PROCESS_TRIGGER: + { + mpi3mr_process_trigger_data_event_bh(mrioc, + (struct trigger_event_data *)fwevt->event_data); + break; + } default: break; } @@ -2857,6 +2955,7 @@ void mpi3mr_os_handle_events(struct mpi3mr_ioc *mrioc, ack_req = 1; evt_type = event_reply->event; + mpi3mr_event_trigger(mrioc, event_reply->event); switch (evt_type) { case MPI3_EVENT_DEVICE_ADDED: @@ -2895,6 +2994,11 @@ void mpi3mr_os_handle_events(struct mpi3mr_ioc *mrioc, ack_req = 0; break; } + case MPI3_EVENT_DIAGNOSTIC_BUFFER_STATUS_CHANGE: + { + mpi3mr_hdbstatuschg_evt_th(mrioc, event_reply); + break; + } case MPI3_EVENT_DEVICE_INFO_CHANGED: case MPI3_EVENT_LOG_DATA: case MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE: @@ -3158,6 +3262,7 @@ void mpi3mr_process_op_reply_desc(struct mpi3mr_ioc *mrioc, MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_LOGINFOAVAIL) ioc_loginfo = le32_to_cpu(status_desc->ioc_log_info); ioc_status &= MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_STATUS_MASK; + mpi3mr_reply_trigger(mrioc, ioc_status, ioc_loginfo); break; case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_ADDRESS_REPLY: addr_desc = (struct mpi3_address_reply_descriptor *)reply_desc; @@ -3186,6 +3291,12 @@ void mpi3mr_process_op_reply_desc(struct mpi3mr_ioc *mrioc, ioc_status &= MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_STATUS_MASK; if (sense_state == MPI3_SCSI_STATE_SENSE_BUFF_Q_EMPTY) panic("%s: Ran out of sense buffers\n", mrioc->name); + if (sense_buf) { + scsi_normalize_sense(sense_buf, sense_count, &sshdr); + mpi3mr_scsisense_trigger(mrioc, sshdr.sense_key, + sshdr.asc, sshdr.ascq); + } + mpi3mr_reply_trigger(mrioc, ioc_status, ioc_loginfo); break; case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_SUCCESS: success_desc = (struct mpi3_success_reply_descriptor *)reply_desc; @@ -3811,6 +3922,8 @@ int mpi3mr_issue_tm(struct mpi3mr_ioc *mrioc, u8 tm_type, default: break; } + mpi3mr_global_trigger(mrioc, + MPI3_DRIVER2_GLOBALTRIGGER_TASK_MANAGEMENT_ENABLED); out_unlock: drv_cmd->state = MPI3MR_CMD_NOTUSED; From patchwork Tue Jun 18 11:56:54 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ranjan Kumar X-Patchwork-Id: 13702151 Received: from mail-pj1-f47.google.com (mail-pj1-f47.google.com [209.85.216.47]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6E14B73467 for ; Tue, 18 Jun 2024 12:00:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718712018; cv=none; b=nhzcAi7KRD4M2Ec87s2TY27mMEktvlS6PHmkh/Kig9aB4/AyAB+2PiMbNL3YmLgV+nMyeOEWaa8qb6i9p2hRGQP1CcwhmwXsEkjdoGMfnJ019yzHwzScly5wK7HwW4K7bq+anWDUyYmQIsh3Vx5/4e+JeQuUB5xVZehXCAEVQJE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718712018; c=relaxed/simple; bh=rxwp3UG8UkxqDee3LRW+MS6gnX6quVNtuwL2VBh+zTg=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=ShD9VhdTv/oc2WyEv5gbtwarEciXGbsTDDs9Cx4XQPiULO/tEugFiGyusZD73nZLJmiXgA//4otNutuNZ/WhAascU6mGFxV7ZsA7T6CiTqmwZL+PK/PBWK8fk/5RCYi6GU9m49XGWhdFmBGQAqemJ89YDaLUEtY/c3j/0rmjc4k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=broadcom.com; spf=fail smtp.mailfrom=broadcom.com; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b=WtrbBOU+; arc=none smtp.client-ip=209.85.216.47 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=broadcom.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=broadcom.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b="WtrbBOU+" Received: by mail-pj1-f47.google.com with SMTP id 98e67ed59e1d1-2c315b569c8so4367165a91.0 for ; Tue, 18 Jun 2024 05:00:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1718712015; x=1719316815; darn=vger.kernel.org; h=mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:from:to:cc:subject:date:message-id:reply-to; bh=3DFSPP1pJPB464nme1zbQ3pCTNDsxvwvg4tS49vrYO8=; b=WtrbBOU+s+utZFmk5n8SNdiUFT7gAnfLR7bdbMnyCIz2bPuS/61Av/w7gNCpbmMI/e v2ZbI+a81LB/oMbi/RHK5EYX/1eTvgy/6Nfkjepra76v+yFK8Don/ItzYNg0ERwI369+ 36WTzWhkjPMuMjfdNHKKkQD4Wl1QggGQH5s0Y= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1718712015; x=1719316815; h=mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=3DFSPP1pJPB464nme1zbQ3pCTNDsxvwvg4tS49vrYO8=; b=toDWQeqUzGlrVIVFTo0Nn9AuDAQ7eFNrvjFT5yYhBOEu0BtuzhLRQCWMSdOQJFSAtT pb3BktM5V1wzz2Z9gi81GKtQ/c2dV5OkGfdJY7/BzI+Cm/MHL6mhSLeQ+8uGAKE8e/hP zzvKZ8pd75rCxawRx8hH/S5W+W/Cgxj5Nun5xtsM96eJY679xjZT+hIgXsQXlQYb2qNp p2HAWymrOeKVzscVzuwNGT8oYqQMcMYFqBUnpYuXgE8n0h3+wqklKqL3+ajOCpPrnxpV OquKbpfB72BHab18cOURTw6lIKzpbAS7b10LJD+QMxTQC3QPN+D65+M3guZCElau/NBC WuPw== X-Gm-Message-State: AOJu0YxlcprsH5OyObanprbKqaL8q9qcWbdG5QsWMmo+lMSyD0EV+gW4 kVgzoKuS9YagH4onFX5mecNazGbbri6OfudL22IhCqDVdBIvkw7dETc7S6aOY62bd5ScrqbcQsM Bn0nTPADled0q1YhCE8oYdZeJ6yOtAMMsBpHUgKibeRTBjoLo5vZYRwEQZZAVdGUvW8p2WOI4gK hFbPhNh6DUudgDDPIpLSdPLR5JRUW5roA/OKdc5mgl4edv9w== X-Google-Smtp-Source: AGHT+IFDM+35ueifiigoPZo44MghCRh1sUX+xMaB7c6uBQIuZPgza1CLKF1pKXsY/6NSE4jbYkBMlw== X-Received: by 2002:a17:90a:ce96:b0:2c3:1159:2cfe with SMTP id 98e67ed59e1d1-2c4db13571cmr10890796a91.4.1718712014442; Tue, 18 Jun 2024 05:00:14 -0700 (PDT) Received: from localhost.localdomain ([192.19.234.250]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2c4a76037a4sm12925963a91.29.2024.06.18.05.00.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Jun 2024 05:00:13 -0700 (PDT) From: Ranjan Kumar 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 Subject: [PATCH v5 3/4] mpi3mr: Ioctl support for HDB Date: Tue, 18 Jun 2024 17:26:54 +0530 Message-Id: <20240618115655.15066-4-ranjan.kumar@broadcom.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20240618115655.15066-1-ranjan.kumar@broadcom.com> References: <20240618115655.15066-1-ranjan.kumar@broadcom.com> Precedence: bulk X-Mailing-List: linux-scsi@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This patch provides interfaces for applications to manage the host diagnostic buffers and update the automatic diag buffer capture triggers. Signed-off-by: Sathya Prakash Signed-off-by: Ranjan Kumar --- drivers/scsi/mpi3mr/mpi3mr.h | 12 ++ drivers/scsi/mpi3mr/mpi3mr_app.c | 265 ++++++++++++++++++++++++++++ include/uapi/scsi/scsi_bsg_mpi3mr.h | 3 +- 3 files changed, 279 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h index e14982a785a6..1c604ed24c6e 100644 --- a/drivers/scsi/mpi3mr/mpi3mr.h +++ b/drivers/scsi/mpi3mr/mpi3mr.h @@ -200,6 +200,18 @@ extern atomic64_t event_counter; #define MPI3MR_HDB_TRIGGER_TYPE_SOFT_RESET 4 #define MPI3MR_HDB_TRIGGER_TYPE_FW_RELEASED 5 +#define MPI3MR_HDB_REFRESH_TYPE_RESERVED 0 +#define MPI3MR_HDB_REFRESH_TYPE_CURRENT 1 +#define MPI3MR_HDB_REFRESH_TYPE_DEFAULT 2 +#define MPI3MR_HDB_HDB_REFRESH_TYPE_PERSISTENT 3 + +#define MPI3MR_DEFAULT_HDB_SZ (4 * 1024 * 1024) +#define MPI3MR_MAX_NUM_HDB 2 + +#define MPI3MR_HDB_QUERY_ELEMENT_TRIGGER_FORMAT_INDEX 0 +#define MPI3MR_HDB_QUERY_ELEMENT_TRIGGER_FORMAT_DATA 1 + + /* SGE Flag definition */ #define MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST \ (MPI3_SGE_FLAGS_ELEMENT_TYPE_SIMPLE | MPI3_SGE_FLAGS_DLAS_SYSTEM | \ diff --git a/drivers/scsi/mpi3mr/mpi3mr_app.c b/drivers/scsi/mpi3mr/mpi3mr_app.c index 9d15c307374a..d236e2eaaefe 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_app.c +++ b/drivers/scsi/mpi3mr/mpi3mr_app.c @@ -940,6 +940,259 @@ static struct mpi3mr_ioc *mpi3mr_bsg_verify_adapter(int ioc_number) return NULL; } +/** + * mpi3mr_bsg_refresh_hdb_triggers - Refresh HDB trigger data + * @mrioc: Adapter instance reference + * @job: BSG Job pointer + * + * This function reads the controller trigger config page as + * defined by the input page type and refreshes the driver's + * local trigger information structures with the controller's + * config page data. + * + * Return: 0 on success and proper error codes on failure + */ +static long +mpi3mr_bsg_refresh_hdb_triggers(struct mpi3mr_ioc *mrioc, + struct bsg_job *job) +{ + struct mpi3mr_bsg_out_refresh_hdb_triggers refresh_triggers; + uint32_t data_out_sz; + u8 page_action; + long rval = -EINVAL; + + data_out_sz = job->request_payload.payload_len; + + if (data_out_sz != sizeof(refresh_triggers)) { + dprint_bsg_err(mrioc, "%s: invalid size argument\n", + __func__); + return rval; + } + + if (mrioc->unrecoverable) { + dprint_bsg_err(mrioc, "%s: unrecoverable controller\n", + __func__); + return -EFAULT; + } + if (mrioc->reset_in_progress) { + dprint_bsg_err(mrioc, "%s: reset in progress\n", __func__); + return -EAGAIN; + } + + sg_copy_to_buffer(job->request_payload.sg_list, + job->request_payload.sg_cnt, + &refresh_triggers, sizeof(refresh_triggers)); + + switch (refresh_triggers.page_type) { + case MPI3MR_HDB_REFRESH_TYPE_CURRENT: + page_action = MPI3_CONFIG_ACTION_READ_CURRENT; + break; + case MPI3MR_HDB_REFRESH_TYPE_DEFAULT: + page_action = MPI3_CONFIG_ACTION_READ_DEFAULT; + break; + case MPI3MR_HDB_HDB_REFRESH_TYPE_PERSISTENT: + page_action = MPI3_CONFIG_ACTION_READ_PERSISTENT; + break; + default: + dprint_bsg_err(mrioc, + "%s: unsupported refresh trigger, page_type %d\n", + __func__, refresh_triggers.page_type); + return rval; + } + rval = mpi3mr_refresh_trigger(mrioc, page_action); + + return rval; +} + +/** + * mpi3mr_bsg_upload_hdb - Upload a specific HDB to user space + * @mrioc: Adapter instance reference + * @job: BSG Job pointer + * + * Return: 0 on success and proper error codes on failure + */ +static long mpi3mr_bsg_upload_hdb(struct mpi3mr_ioc *mrioc, + struct bsg_job *job) +{ + struct mpi3mr_bsg_out_upload_hdb upload_hdb; + struct diag_buffer_desc *diag_buffer; + uint32_t data_out_size; + uint32_t data_in_size; + + data_out_size = job->request_payload.payload_len; + data_in_size = job->reply_payload.payload_len; + + if (data_out_size != sizeof(upload_hdb)) { + dprint_bsg_err(mrioc, "%s: invalid size argument\n", + __func__); + return -EINVAL; + } + + sg_copy_to_buffer(job->request_payload.sg_list, + job->request_payload.sg_cnt, + &upload_hdb, sizeof(upload_hdb)); + + if ((!upload_hdb.length) || (data_in_size != upload_hdb.length)) { + dprint_bsg_err(mrioc, "%s: invalid length argument\n", + __func__); + return -EINVAL; + } + diag_buffer = mpi3mr_diag_buffer_for_type(mrioc, upload_hdb.buf_type); + if ((!diag_buffer) || (!diag_buffer->addr)) { + dprint_bsg_err(mrioc, "%s: invalid buffer type %d\n", + __func__, upload_hdb.buf_type); + return -EINVAL; + } + + if ((diag_buffer->status != MPI3MR_HDB_BUFSTATUS_RELEASED) && + (diag_buffer->status != MPI3MR_HDB_BUFSTATUS_POSTED_PAUSED)) { + dprint_bsg_err(mrioc, + "%s: invalid buffer status %d for type %d\n", + __func__, diag_buffer->status, upload_hdb.buf_type); + return -EINVAL; + } + + if ((upload_hdb.start_offset + upload_hdb.length) > diag_buffer->size) { + dprint_bsg_err(mrioc, + "%s: invalid start offset %d, length %d for type %d\n", + __func__, upload_hdb.start_offset, upload_hdb.length, + upload_hdb.buf_type); + return -EINVAL; + } + sg_copy_from_buffer(job->reply_payload.sg_list, + job->reply_payload.sg_cnt, + (diag_buffer->addr + upload_hdb.start_offset), + data_in_size); + return 0; +} + +/** + * mpi3mr_bsg_repost_hdb - Re-post HDB + * @mrioc: Adapter instance reference + * @job: BSG job pointer + * + * This function retrieves the HDB descriptor corresponding to a + * given buffer type and if the HDB is in released status then + * posts the HDB with the firmware. + * + * Return: 0 on success and proper error codes on failure + */ +static long mpi3mr_bsg_repost_hdb(struct mpi3mr_ioc *mrioc, + struct bsg_job *job) +{ + struct mpi3mr_bsg_out_repost_hdb repost_hdb; + struct diag_buffer_desc *diag_buffer; + uint32_t data_out_sz; + + data_out_sz = job->request_payload.payload_len; + + if (data_out_sz != sizeof(repost_hdb)) { + dprint_bsg_err(mrioc, "%s: invalid size argument\n", + __func__); + return -EINVAL; + } + if (mrioc->unrecoverable) { + dprint_bsg_err(mrioc, "%s: unrecoverable controller\n", + __func__); + return -EFAULT; + } + if (mrioc->reset_in_progress) { + dprint_bsg_err(mrioc, "%s: reset in progress\n", __func__); + return -EAGAIN; + } + + sg_copy_to_buffer(job->request_payload.sg_list, + job->request_payload.sg_cnt, + &repost_hdb, sizeof(repost_hdb)); + + diag_buffer = mpi3mr_diag_buffer_for_type(mrioc, repost_hdb.buf_type); + if ((!diag_buffer) || (!diag_buffer->addr)) { + dprint_bsg_err(mrioc, "%s: invalid buffer type %d\n", + __func__, repost_hdb.buf_type); + return -EINVAL; + } + + if (diag_buffer->status != MPI3MR_HDB_BUFSTATUS_RELEASED) { + dprint_bsg_err(mrioc, + "%s: invalid buffer status %d for type %d\n", + __func__, diag_buffer->status, repost_hdb.buf_type); + return -EINVAL; + } + + if (mpi3mr_issue_diag_buf_post(mrioc, diag_buffer)) { + dprint_bsg_err(mrioc, "%s: post failed for type %d\n", + __func__, repost_hdb.buf_type); + return -EFAULT; + } + mpi3mr_set_trigger_data_in_hdb(diag_buffer, + MPI3MR_HDB_TRIGGER_TYPE_UNKNOWN, NULL, 1); + + return 0; +} + +/** + * mpi3mr_bsg_query_hdb - Handler for query HDB command + * @mrioc: Adapter instance reference + * @job: BSG job pointer + * + * This function prepares and copies the host diagnostic buffer + * entries to the user buffer. + * + * Return: 0 on success and proper error codes on failure + */ +static long mpi3mr_bsg_query_hdb(struct mpi3mr_ioc *mrioc, + struct bsg_job *job) +{ + long rval = 0; + struct mpi3mr_bsg_in_hdb_status *hbd_status; + struct mpi3mr_hdb_entry *hbd_status_entry; + u32 length, min_length; + u8 i; + struct diag_buffer_desc *diag_buffer; + uint32_t data_in_sz = 0; + + data_in_sz = job->request_payload.payload_len; + + length = (sizeof(*hbd_status) + ((MPI3MR_MAX_NUM_HDB - 1) * + sizeof(*hbd_status_entry))); + hbd_status = kmalloc(length, GFP_KERNEL); + if (!hbd_status) + return -ENOMEM; + hbd_status_entry = &hbd_status->entry[0]; + + hbd_status->num_hdb_types = MPI3MR_MAX_NUM_HDB; + for (i = 0; i < MPI3MR_MAX_NUM_HDB; i++) { + diag_buffer = &mrioc->diag_buffers[i]; + hbd_status_entry->buf_type = diag_buffer->type; + hbd_status_entry->status = diag_buffer->status; + hbd_status_entry->trigger_type = diag_buffer->trigger_type; + memcpy(&hbd_status_entry->trigger_data, + &diag_buffer->trigger_data, + sizeof(hbd_status_entry->trigger_data)); + hbd_status_entry->size = (diag_buffer->size / 1024); + hbd_status_entry++; + } + hbd_status->element_trigger_format = + MPI3MR_HDB_QUERY_ELEMENT_TRIGGER_FORMAT_DATA; + + if (data_in_sz < 4) { + dprint_bsg_err(mrioc, "%s: invalid size passed\n", __func__); + rval = -EINVAL; + goto out; + } + min_length = min(data_in_sz, length); + if (job->request_payload.payload_len >= min_length) { + sg_copy_from_buffer(job->request_payload.sg_list, + job->request_payload.sg_cnt, + hbd_status, min_length); + rval = 0; + } +out: + kfree(hbd_status); + return rval; +} + + /** * mpi3mr_enable_logdata - Handler for log data enable * @mrioc: Adapter instance reference @@ -1368,6 +1621,18 @@ static long mpi3mr_bsg_process_drv_cmds(struct bsg_job *job) case MPI3MR_DRVBSG_OPCODE_PELENABLE: rval = mpi3mr_bsg_pel_enable(mrioc, job); break; + case MPI3MR_DRVBSG_OPCODE_QUERY_HDB: + rval = mpi3mr_bsg_query_hdb(mrioc, job); + break; + case MPI3MR_DRVBSG_OPCODE_REPOST_HDB: + rval = mpi3mr_bsg_repost_hdb(mrioc, job); + break; + case MPI3MR_DRVBSG_OPCODE_UPLOAD_HDB: + rval = mpi3mr_bsg_upload_hdb(mrioc, job); + break; + case MPI3MR_DRVBSG_OPCODE_REFRESH_HDB_TRIGGERS: + rval = mpi3mr_bsg_refresh_hdb_triggers(mrioc, job); + break; case MPI3MR_DRVBSG_OPCODE_UNKNOWN: default: pr_err("%s: unsupported driver command opcode %d\n", diff --git a/include/uapi/scsi/scsi_bsg_mpi3mr.h b/include/uapi/scsi/scsi_bsg_mpi3mr.h index 22b2fe266293..8698c0fbb109 100644 --- a/include/uapi/scsi/scsi_bsg_mpi3mr.h +++ b/include/uapi/scsi/scsi_bsg_mpi3mr.h @@ -296,6 +296,7 @@ struct mpi3mr_hdb_entry { * multiple hdb entries. * * @num_hdb_types: Number of host diag buffer types supported + * @element_trigger_format: Element trigger format * @rsvd1: Reserved * @rsvd2: Reserved * @rsvd3: Reserved @@ -303,7 +304,7 @@ struct mpi3mr_hdb_entry { */ struct mpi3mr_bsg_in_hdb_status { __u8 num_hdb_types; - __u8 rsvd1; + __u8 element_trigger_format; __u16 rsvd2; __u32 rsvd3; struct mpi3mr_hdb_entry entry[1]; From patchwork Tue Jun 18 11:56:55 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ranjan Kumar X-Patchwork-Id: 13702152 Received: from mail-pf1-f170.google.com (mail-pf1-f170.google.com [209.85.210.170]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5BEEA757E5 for ; Tue, 18 Jun 2024 12:00:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.170 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718712021; cv=none; b=YlbVhSYVbERLeW95PxMRlc9OeagqrqSQvcB03yx4CukrUfS+PTFO9lRZ25Ibnu/0hONsO5nXLMauEZvx17HtpLQw/H4AMvWry3chd18AuwiRxoUWSCcw3yu3FMwGYPwFOdT0QrSaGG+vFS1sJRsTja3ubwuF8eRccmDKtNEDV2s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718712021; c=relaxed/simple; bh=wkFVnqNMMIEexN8PezCf340FlsOr3+H2H9XR3C82eyM=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=eiAX+Vm+CDmv5ZIia9Xlkhwp9z2G5kODE6xTVsdUQ/vyHpYkt7BJEN4bIK4LDjZ3dqCBzWtpRTyRHYw738/BpLqMC7UuuhQY5FlS+IAlGVBREVBYEajQW3sms1qotaa8w3j6qmXjky9lPLHlphssohPV3smQVi/gfjj1QqghqYw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=broadcom.com; spf=fail smtp.mailfrom=broadcom.com; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b=Aq+A3fTD; arc=none smtp.client-ip=209.85.210.170 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=broadcom.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=broadcom.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b="Aq+A3fTD" Received: by mail-pf1-f170.google.com with SMTP id d2e1a72fcca58-70601bcfddcso1666324b3a.3 for ; Tue, 18 Jun 2024 05:00:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1718712018; x=1719316818; darn=vger.kernel.org; h=mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:from:to:cc:subject:date:message-id:reply-to; bh=wYLM5IusqL0IZOoX+AZQrTF21bX+dwdgGtxSPdtABEk=; b=Aq+A3fTDpqjh1odROGnduEn8szHFXHDsvKUhT0+U7uddAguyE0+z6fQr3WaddIVr2r PHfEmlReRcfT9ykY44gsHSc7kDvkfxvS8Fo3PaTtvVtA2Dtro9dt9SyJdQYDyiMWlFFx s0N3kQsE6lB+zn4EaS4JGW01WvWgGUEoNbXYA= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1718712018; x=1719316818; h=mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=wYLM5IusqL0IZOoX+AZQrTF21bX+dwdgGtxSPdtABEk=; b=LYLiSKawm0jlp6RLpvglg+yRJM3fiUUQW54WMVORLDM8qz4hWAiuhBoIRfb/tE0Lov zVetu3ygmHmT+WaGYxnydoRkuiI1IcORGYvAW2OUwykR38H4zNaR1dAn8iyHck6xo+Yf re4jwg3GGaIJ+ILKuYO7AgUS7/eo6KB28yVV6XM9VTgTEbGkrt4qqEwPycCFG/0y2YWP 1GYMujjKuu0UKyjsz1nqZdxxqJInpABvU6nS1bqJKPMGMFbh7Qo5itDwk/V0N0QP2rX8 HGlJhSPtywIG2GoBq2UbLMzC4xqBpFwQU7FeIcqjy7hjZDjSorODyUVPrYMj4LXHgUnQ PAbQ== X-Gm-Message-State: AOJu0YwDpSgy55th+EqirUM6ZmnjdhjuJTm8MJCmdtdOAcD41E/aSqWd nE1vDusMQR9nSth4Z9nU5sLHnONtgUJ0Rr+QQyzoijkSxzme4vAK8XLJ5KDl1X9YufZ3TmjY5se I0CnpiZBmcAOyy/lRFTo3pVCjhrBip0nyqVeiydF42CYTCjS17AVvzTPlEvnwpRxr4xj5Ow0lO6 XhU08gmgM4RVP9lmbeslVCWuAvuZzKnWo2GWkWnrAPo0C7mA== X-Google-Smtp-Source: AGHT+IFrFklRqo1LIkMzgyiuoB8r/14udgtosYnq+8JYqGa5IMlpnyB9jURWn5DrdBBfsEHJj8Jxtw== X-Received: by 2002:a05:6a20:3d89:b0:1b8:54f8:3856 with SMTP id adf61e73a8af0-1bae7e14ca8mr15277319637.5.1718712017854; Tue, 18 Jun 2024 05:00:17 -0700 (PDT) Received: from localhost.localdomain ([192.19.234.250]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2c4a76037a4sm12925963a91.29.2024.06.18.05.00.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Jun 2024 05:00:17 -0700 (PDT) From: Ranjan Kumar 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 Subject: [PATCH v5 4/4] mpi3mr: Update driver version to 8.9.1.0.50 Date: Tue, 18 Jun 2024 17:26:55 +0530 Message-Id: <20240618115655.15066-5-ranjan.kumar@broadcom.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20240618115655.15066-1-ranjan.kumar@broadcom.com> References: <20240618115655.15066-1-ranjan.kumar@broadcom.com> Precedence: bulk X-Mailing-List: linux-scsi@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Update driver version to 8.9.1.0.50 Signed-off-by: Ranjan Kumar --- drivers/scsi/mpi3mr/mpi3mr.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h index 1c604ed24c6e..c8968f12b9e6 100644 --- a/drivers/scsi/mpi3mr/mpi3mr.h +++ b/drivers/scsi/mpi3mr/mpi3mr.h @@ -56,8 +56,8 @@ extern struct list_head mrioc_list; extern int prot_mask; extern atomic64_t event_counter; -#define MPI3MR_DRIVER_VERSION "8.8.1.0.50" -#define MPI3MR_DRIVER_RELDATE "5-March-2024" +#define MPI3MR_DRIVER_VERSION "8.9.1.0.50" +#define MPI3MR_DRIVER_RELDATE "14-May-2024" #define MPI3MR_DRIVER_NAME "mpi3mr" #define MPI3MR_DRIVER_LICENSE "GPL"