From nobody Wed Oct 8 05:19:05 2025 Received: from trager.us (trager.us [52.5.81.116]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E13732BE656; Wed, 2 Jul 2025 19:29:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=52.5.81.116 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751484565; cv=none; b=HFkSfxWMrFmFTj8Rc2wDudSOYyIWv6xO4Xg7CsBnGO4PEV3JZ9kYFX0eX1uWPqCT1zqSnDyInkfXHt0dmU22kWeQg0VTK+ZzZSUWAsh9MjLUzAxD2Ay8py/KipCkHc3Vz0a3HqjrXCqqWsZsTVU4jMJN8HHQU7AqLUdd2ovP89M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751484565; c=relaxed/simple; bh=rtPutSKWhgqsRdvkma+dOgbJpiK129bmyj9iZSvxP7A=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=HV3SBlFuVIpzh+Fx1Y270ey2ypQ27AiYEgiUF0MkzUtY748rEoPwJHtfMHbsPh+B/aKej1H+w5G1GOXpFSkEWhoson32LYgFXzV7UIG3Wf4CmXxFkIopfdteVbiIhlOc6B2p9Jo0n37eD5V2MfT7t5D51q8XR0h246iaxYBnRWU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=trager.us; spf=pass smtp.mailfrom=trager.us; arc=none smtp.client-ip=52.5.81.116 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=trager.us Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=trager.us Received: from c-76-104-255-50.hsd1.wa.comcast.net ([76.104.255.50] helo=localhost) by trager.us with esmtpsa (TLSv1.3:TLS_AES_256_GCM_SHA384:256) (Exim 4.92.3) (envelope-from ) id 1uX38t-00081r-M4; Wed, 02 Jul 2025 19:29:15 +0000 From: Lee Trager To: Alexander Duyck , Jakub Kicinski , kernel-team@meta.com, Andrew Lunn , "David S. Miller" , Eric Dumazet , Paolo Abeni , Kees Cook , "Gustavo A. R. Silva" , Mohsin Bashir , Sanman Pradhan , Vadim Fedorenko , Su Hui , Simon Horman , Lee Trager , Kalesh AP , Jacob Keller Cc: Andrew Lunn , linux-kernel@vger.kernel.org, netdev@vger.kernel.org, linux-hardening@vger.kernel.org Subject: [PATCH net-next 4/6] eth: fbnic: Add mailbox support for firmware logs Date: Wed, 2 Jul 2025 12:12:10 -0700 Message-ID: <20250702192207.697368-5-lee@trager.us> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20250702192207.697368-1-lee@trager.us> References: <20250702192207.697368-1-lee@trager.us> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" By default firmware will not send logs to the host. This must be explicitly enabled by the driver. The mailbox has the concept of a flag which is a u32 used as a boolean. Lack of flag defaults to a value of false. When enabling logging historical logs may be optionally requested. These are log messages generated by the NIC before the driver was loaded. The driver also sends a log version to support changing the logging format in the future. [SEND_LOGS_REQ] =3D { [SEND_LOGS] /* flag to request log reporting */ [SEND_LOGS_HISTORY] /* flag to request historical logs */ [SEND_LOGS_VERSION] /* u32 indicating the log format version */ } Logs may be sent to the user either one at a time, or when historical logs are requested in bulk. Firmware may not send more than 14 messages in bulk to prevent flooding the mailbox. [LOG_MSG] =3D { [LOG_INDEX] /* entry 0 - u64 index of log */ [LOG_MSEC] /* entry 0 - u32 timestamp of log */ [LOG_MSG] /* entry 0 - char log message up to 256 */ [LOG_LENGTH] /* u32 of remaining log items in arrays */ [LOG_INDEX_ARRAY] =3D { [LOG_INDEX] /* entry 1 - u64 index of log */ [LOG_INDEX] /* entry 2 - u64 index of log */ ... } [LOG_MSEC_ARRAY] =3D { [LOG_MSEC] /* entry 1 - u32 timestamp of log */ [LOG_MSEC] /* entry 2 - u32 timestamp of log */ ... } [LOG_MSG_ARRAY] =3D { [LOG_MSG] /* entry 1 - char log message up to 256 */ [LOG_MSG] /* entry 2 - char log message up to 256 */ ... } } Signed-off-by: Lee Trager Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/meta/fbnic/fbnic_csr.h | 14 ++ drivers/net/ethernet/meta/fbnic/fbnic_fw.c | 166 ++++++++++++++++++++ drivers/net/ethernet/meta/fbnic/fbnic_fw.h | 36 +++++ 3 files changed, 216 insertions(+) diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_csr.h b/drivers/net/ethe= rnet/meta/fbnic/fbnic_csr.h index 06b9c49e51a2..a81db842aa53 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_csr.h +++ b/drivers/net/ethernet/meta/fbnic/fbnic_csr.h @@ -21,6 +21,20 @@ /* Defines the minimum firmware version required by the driver */ #define MIN_FW_VER_CODE FW_VER_CODE(0, 10, 6, 0) +/* Defines the minimum firmware version required for firmware logs */ +#define MIN_FW_VER_CODE_LOG FW_VER_CODE(0, 12, 9, 0) + +/* Driver can request that firmware sends all cached logs in bulk. This + * feature was enabled on older firmware however firmware has a bug + * which attempted to send 30 messages per mbx message which caused an + * overflow flooding the mailbox. This results in a kernel warning + * related to corrupt mailbox messages. + * + * If firmware is new enough only request sending historical logs when + * the log buffer is empty to prevent duplicate logs. + */ +#define MIN_FW_VER_CODE_HIST FW_VER_CODE(25, 5, 7, 0) + #define PCI_DEVICE_ID_META_FBNIC_ASIC 0x0013 #define FBNIC_CLOCK_FREQ (600 * (1000 * 1000)) diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_fw.c b/drivers/net/ether= net/meta/fbnic/fbnic_fw.c index ac7804a8a22c..0c55be7d2547 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_fw.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_fw.c @@ -1034,6 +1034,169 @@ static int fbnic_fw_parse_tsene_read_resp(void *opa= que, return err; } +static const struct fbnic_tlv_index fbnic_fw_log_req_index[] =3D { + FBNIC_TLV_ATTR_U32(FBNIC_FW_LOG_MSEC), + FBNIC_TLV_ATTR_U64(FBNIC_FW_LOG_INDEX), + FBNIC_TLV_ATTR_STRING(FBNIC_FW_LOG_MSG, FBNIC_FW_LOG_MAX_SIZE), + FBNIC_TLV_ATTR_U32(FBNIC_FW_LOG_LENGTH), + FBNIC_TLV_ATTR_ARRAY(FBNIC_FW_LOG_MSEC_ARRAY), + FBNIC_TLV_ATTR_ARRAY(FBNIC_FW_LOG_INDEX_ARRAY), + FBNIC_TLV_ATTR_ARRAY(FBNIC_FW_LOG_MSG_ARRAY), + FBNIC_TLV_ATTR_LAST +}; + +static int fbnic_fw_process_log_array(struct fbnic_tlv_msg **results, + u16 length, u16 arr_type_idx, + u16 attr_type_idx, + struct fbnic_tlv_msg **tlv_array_out) +{ + struct fbnic_tlv_msg *attr; + int attr_len; + int err; + + if (!results[attr_type_idx]) + return -EINVAL; + + tlv_array_out[0] =3D results[attr_type_idx]; + + if (!length) + return 0; + + if (!results[arr_type_idx]) + return -EINVAL; + + attr =3D results[arr_type_idx]; + attr_len =3D le16_to_cpu(attr->hdr.len) / sizeof(u32) - 1; + err =3D fbnic_tlv_attr_parse_array(&attr[1], attr_len, &tlv_array_out[1], + fbnic_fw_log_req_index, + attr_type_idx, + length); + if (err) + return err; + + return 0; +} + +static int fbnic_fw_parse_logs(struct fbnic_dev *fbd, + struct fbnic_tlv_msg **msec_tlv, + struct fbnic_tlv_msg **index_tlv, + struct fbnic_tlv_msg **log_tlv, + int count) +{ + int i; + + for (i =3D 0; i < count; i++) { + char log[FBNIC_FW_LOG_MAX_SIZE]; + ssize_t len; + u64 index; + u32 msec; + int err; + + if (!msec_tlv[i] || !index_tlv[i] || !log_tlv[i]) { + dev_warn(fbd->dev, "Received log message with missing attributes!\n"); + return -EINVAL; + } + + index =3D fbnic_tlv_attr_get_signed(index_tlv[i], 0); + msec =3D fbnic_tlv_attr_get_signed(msec_tlv[i], 0); + len =3D fbnic_tlv_attr_get_string(log_tlv[i], log, + FBNIC_FW_LOG_MAX_SIZE); + if (len < 0) + return len; + + err =3D fbnic_fw_log_write(fbd, index, msec, log); + if (err) + return err; + } + + return 0; +} + +static int fbnic_fw_parse_log_req(void *opaque, + struct fbnic_tlv_msg **results) +{ + struct fbnic_tlv_msg *index_tlv[FBNIC_FW_MAX_LOG_HISTORY]; + struct fbnic_tlv_msg *msec_tlv[FBNIC_FW_MAX_LOG_HISTORY]; + struct fbnic_tlv_msg *log_tlv[FBNIC_FW_MAX_LOG_HISTORY]; + struct fbnic_dev *fbd =3D opaque; + u16 length; + int err; + + length =3D fta_get_uint(results, FBNIC_FW_LOG_LENGTH); + if (length >=3D FBNIC_FW_MAX_LOG_HISTORY) + return -E2BIG; + + err =3D fbnic_fw_process_log_array(results, length, + FBNIC_FW_LOG_MSEC_ARRAY, + FBNIC_FW_LOG_MSEC, msec_tlv); + if (err) + return err; + + err =3D fbnic_fw_process_log_array(results, length, + FBNIC_FW_LOG_INDEX_ARRAY, + FBNIC_FW_LOG_INDEX, index_tlv); + if (err) + return err; + + err =3D fbnic_fw_process_log_array(results, length, + FBNIC_FW_LOG_MSG_ARRAY, + FBNIC_FW_LOG_MSG, log_tlv); + if (err) + return err; + + err =3D fbnic_fw_parse_logs(fbd, msec_tlv, index_tlv, log_tlv, + length + 1); + if (err) + return err; + + return 0; +} + +int fbnic_fw_xmit_send_logs(struct fbnic_dev *fbd, bool enable, + bool send_log_history) +{ + struct fbnic_tlv_msg *msg; + int err; + + if (fbd->fw_cap.running.mgmt.version < MIN_FW_VER_CODE_LOG) { + dev_warn(fbd->dev, "Firmware version is too old to support firmware logs= !\n"); + return -EOPNOTSUPP; + } + + msg =3D fbnic_tlv_msg_alloc(FBNIC_TLV_MSG_ID_LOG_SEND_LOGS_REQ); + if (!msg) + return -ENOMEM; + + if (enable) { + err =3D fbnic_tlv_attr_put_flag(msg, FBNIC_SEND_LOGS); + if (err) + goto free_message; + + /* Report request for version 1 of logs */ + err =3D fbnic_tlv_attr_put_int(msg, FBNIC_SEND_LOGS_VERSION, + FBNIC_FW_LOG_VERSION); + if (err) + goto free_message; + + if (send_log_history) { + err =3D fbnic_tlv_attr_put_flag(msg, + FBNIC_SEND_LOGS_HISTORY); + if (err) + goto free_message; + } + } + + err =3D fbnic_mbx_map_tlv_msg(fbd, msg); + if (err) + goto free_message; + + return 0; + +free_message: + free_page((unsigned long)msg); + return err; +} + static const struct fbnic_tlv_parser fbnic_fw_tlv_parser[] =3D { FBNIC_TLV_PARSER(FW_CAP_RESP, fbnic_fw_cap_resp_index, fbnic_fw_parse_cap_resp), @@ -1053,6 +1216,9 @@ static const struct fbnic_tlv_parser fbnic_fw_tlv_par= ser[] =3D { FBNIC_TLV_PARSER(TSENE_READ_RESP, fbnic_tsene_read_resp_index, fbnic_fw_parse_tsene_read_resp), + FBNIC_TLV_PARSER(LOG_MSG_REQ, + fbnic_fw_log_req_index, + fbnic_fw_parse_log_req), FBNIC_TLV_MSG_ERROR }; diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_fw.h b/drivers/net/ether= net/meta/fbnic/fbnic_fw.h index 555b231b38c1..fde331696fdd 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_fw.h +++ b/drivers/net/ethernet/meta/fbnic/fbnic_fw.h @@ -22,7 +22,20 @@ struct fbnic_fw_mbx { #define FBNIC_FW_VER_MAX_SIZE 32 // Formatted version is in the format XX.YY.ZZ_RRR_COMMIT #define FBNIC_FW_CAP_RESP_COMMIT_MAX_SIZE (FBNIC_FW_VER_MAX_SIZE - 13) +#define FBNIC_FW_LOG_VERSION 1 #define FBNIC_FW_LOG_MAX_SIZE 256 +/* + * The max amount of logs which can fit in a single mailbox message. Firmw= are + * assumes each mailbox message is 4096B. The amount of messages supported= is + * calculated as 4096 minus headers for message, arrays, and length minus = the + * size of length divided by headers for each array plus the maximum LOG s= ize, + * and the size of MSEC and INDEX. Put another way: + * + * MAX_LOG_HISTORY =3D ((4096 - TLV_HDR_SZ * 5 - LENGTH_SZ) + * / (FBNIC_FW_LOG_MAX_SIZE + TLV_HDR_SZ * 3 + MSEC_SZ + * + INDEX_SZ)) + */ +#define FBNIC_FW_MAX_LOG_HISTORY 14 struct fbnic_fw_ver { u32 version; @@ -82,6 +95,8 @@ int fbnic_fw_xmit_fw_write_chunk(struct fbnic_dev *fbd, int cancel_error); int fbnic_fw_xmit_tsene_read_msg(struct fbnic_dev *fbd, struct fbnic_fw_completion *cmpl_data); +int fbnic_fw_xmit_send_logs(struct fbnic_dev *fbd, bool enable, + bool send_log_history); struct fbnic_fw_completion *fbnic_fw_alloc_cmpl(u32 msg_type); void fbnic_fw_put_cmpl(struct fbnic_fw_completion *cmpl_data); @@ -125,6 +140,9 @@ enum { FBNIC_TLV_MSG_ID_FW_FINISH_UPGRADE_RESP =3D 0x29, FBNIC_TLV_MSG_ID_TSENE_READ_REQ =3D 0x3C, FBNIC_TLV_MSG_ID_TSENE_READ_RESP =3D 0x3D, + FBNIC_TLV_MSG_ID_LOG_SEND_LOGS_REQ =3D 0x43, + FBNIC_TLV_MSG_ID_LOG_MSG_REQ =3D 0x44, + FBNIC_TLV_MSG_ID_LOG_MSG_RESP =3D 0x45, }; #define FBNIC_FW_CAP_RESP_VERSION_MAJOR CSR_GENMASK(31, 24) @@ -199,4 +217,22 @@ enum { FBNIC_FW_FINISH_UPGRADE_MSG_MAX }; +enum { + FBNIC_SEND_LOGS =3D 0x0, + FBNIC_SEND_LOGS_VERSION =3D 0x1, + FBNIC_SEND_LOGS_HISTORY =3D 0x2, + FBNIC_SEND_LOGS_MSG_MAX +}; + +enum { + FBNIC_FW_LOG_MSEC =3D 0x0, + FBNIC_FW_LOG_INDEX =3D 0x1, + FBNIC_FW_LOG_MSG =3D 0x2, + FBNIC_FW_LOG_LENGTH =3D 0x3, + FBNIC_FW_LOG_MSEC_ARRAY =3D 0x4, + FBNIC_FW_LOG_INDEX_ARRAY =3D 0x5, + FBNIC_FW_LOG_MSG_ARRAY =3D 0x6, + FBNIC_FW_LOG_MSG_MAX +}; + #endif /* _FBNIC_FW_H_ */ -- 2.47.1