Blame SOURCES/0022-netlink-eeprom-Export-a-function-to-request-an-EEPRO.patch

2a1b01
From fdb457a0ebb57c99fb987d0e34b2549f10dd4161 Mon Sep 17 00:00:00 2001
2a1b01
From: Ido Schimmel <idosch@nvidia.com>
2a1b01
Date: Tue, 12 Oct 2021 16:25:21 +0300
2a1b01
Subject: [PATCH 22/35] netlink: eeprom: Export a function to request an EEPROM
2a1b01
 page
2a1b01
2a1b01
The function will be used by the EEPROM parsing code (e.g., cmis.c) to
2a1b01
request a specific page for parsing.
2a1b01
2a1b01
All the data buffers used to store EEPROM page contents are stored on a
2a1b01
linked list that is flushed on exit. This relieves callers from the need
2a1b01
to explicitly free the requested pages.
2a1b01
2a1b01
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
2a1b01
---
2a1b01
 netlink/extapi.h        |  11 +++++
2a1b01
 netlink/module-eeprom.c | 105 ++++++++++++++++++++++++++++++++++++++++
2a1b01
 2 files changed, 116 insertions(+)
2a1b01
2a1b01
diff --git a/netlink/extapi.h b/netlink/extapi.h
2a1b01
index 91bf02b5e3be..129e2931d01d 100644
2a1b01
--- a/netlink/extapi.h
2a1b01
+++ b/netlink/extapi.h
2a1b01
@@ -48,6 +48,9 @@ int nl_getmodule(struct cmd_context *ctx);
2a1b01
 
2a1b01
 void nl_monitor_usage(void);
2a1b01
 
2a1b01
+int nl_get_eeprom_page(struct cmd_context *ctx,
2a1b01
+		       struct ethtool_module_eeprom *request);
2a1b01
+
2a1b01
 #else /* ETHTOOL_ENABLE_NETLINK */
2a1b01
 
2a1b01
 static inline void netlink_run_handler(struct cmd_context *ctx __maybe_unused,
2a1b01
@@ -73,6 +76,14 @@ static inline void nl_monitor_usage(void)
2a1b01
 {
2a1b01
 }
2a1b01
 
2a1b01
+static inline int
2a1b01
+nl_get_eeprom_page(struct cmd_context *ctx __maybe_unused,
2a1b01
+		   struct ethtool_module_eeprom *request __maybe_unused)
2a1b01
+{
2a1b01
+	fprintf(stderr, "Netlink not supported by ethtool.\n");
2a1b01
+	return -EOPNOTSUPP;
2a1b01
+}
2a1b01
+
2a1b01
 #define nl_gset			NULL
2a1b01
 #define nl_sset			NULL
2a1b01
 #define nl_permaddr		NULL
2a1b01
diff --git a/netlink/module-eeprom.c b/netlink/module-eeprom.c
2a1b01
index 101d5943c2bc..ee5508840157 100644
2a1b01
--- a/netlink/module-eeprom.c
2a1b01
+++ b/netlink/module-eeprom.c
2a1b01
@@ -341,6 +341,110 @@ static void decoder_print(void)
2a1b01
 }
2a1b01
 #endif
2a1b01
 
2a1b01
+static struct list_head eeprom_page_list = LIST_HEAD_INIT(eeprom_page_list);
2a1b01
+
2a1b01
+struct eeprom_page_entry {
2a1b01
+	struct list_head list;	/* Member of eeprom_page_list */
2a1b01
+	void *data;
2a1b01
+};
2a1b01
+
2a1b01
+static int eeprom_page_list_add(void *data)
2a1b01
+{
2a1b01
+	struct eeprom_page_entry *entry;
2a1b01
+
2a1b01
+	entry = malloc(sizeof(*entry));
2a1b01
+	if (!entry)
2a1b01
+		return -ENOMEM;
2a1b01
+
2a1b01
+	entry->data = data;
2a1b01
+	list_add(&entry->list, &eeprom_page_list);
2a1b01
+
2a1b01
+	return 0;
2a1b01
+}
2a1b01
+
2a1b01
+static void eeprom_page_list_flush(void)
2a1b01
+{
2a1b01
+	struct eeprom_page_entry *entry;
2a1b01
+	struct list_head *head, *next;
2a1b01
+
2a1b01
+	list_for_each_safe(head, next, &eeprom_page_list) {
2a1b01
+		entry = (struct eeprom_page_entry *) head;
2a1b01
+		free(entry->data);
2a1b01
+		list_del(head);
2a1b01
+		free(entry);
2a1b01
+	}
2a1b01
+}
2a1b01
+
2a1b01
+static int get_eeprom_page_reply_cb(const struct nlmsghdr *nlhdr, void *data)
2a1b01
+{
2a1b01
+	const struct nlattr *tb[ETHTOOL_A_MODULE_EEPROM_DATA + 1] = {};
2a1b01
+	struct ethtool_module_eeprom *request = data;
2a1b01
+	DECLARE_ATTR_TB_INFO(tb);
2a1b01
+	u8 *eeprom_data;
2a1b01
+	int ret;
2a1b01
+
2a1b01
+	ret = mnl_attr_parse(nlhdr, GENL_HDRLEN, attr_cb, &tb_info);
2a1b01
+	if (ret < 0)
2a1b01
+		return ret;
2a1b01
+
2a1b01
+	if (!tb[ETHTOOL_A_MODULE_EEPROM_DATA])
2a1b01
+		return MNL_CB_ERROR;
2a1b01
+
2a1b01
+	eeprom_data = mnl_attr_get_payload(tb[ETHTOOL_A_MODULE_EEPROM_DATA]);
2a1b01
+	request->data = malloc(request->length);
2a1b01
+	if (!request->data)
2a1b01
+		return MNL_CB_ERROR;
2a1b01
+	memcpy(request->data, eeprom_data, request->length);
2a1b01
+
2a1b01
+	ret = eeprom_page_list_add(request->data);
2a1b01
+	if (ret < 0)
2a1b01
+		goto err_list_add;
2a1b01
+
2a1b01
+	return MNL_CB_OK;
2a1b01
+
2a1b01
+err_list_add:
2a1b01
+	free(request->data);
2a1b01
+	return MNL_CB_ERROR;
2a1b01
+}
2a1b01
+
2a1b01
+int nl_get_eeprom_page(struct cmd_context *ctx,
2a1b01
+		       struct ethtool_module_eeprom *request)
2a1b01
+{
2a1b01
+	struct nl_context *nlctx = ctx->nlctx;
2a1b01
+	struct nl_socket *nlsock;
2a1b01
+	struct nl_msg_buff *msg;
2a1b01
+	int ret;
2a1b01
+
2a1b01
+	if (!request || request->i2c_address > ETH_I2C_MAX_ADDRESS)
2a1b01
+		return -EINVAL;
2a1b01
+
2a1b01
+	nlsock = nlctx->ethnl_socket;
2a1b01
+	msg = &nlsock->msgbuff;
2a1b01
+
2a1b01
+	ret = nlsock_prep_get_request(nlsock, ETHTOOL_MSG_MODULE_EEPROM_GET,
2a1b01
+				      ETHTOOL_A_MODULE_EEPROM_HEADER, 0);
2a1b01
+	if (ret < 0)
2a1b01
+		return ret;
2a1b01
+
2a1b01
+	if (ethnla_put_u32(msg, ETHTOOL_A_MODULE_EEPROM_LENGTH,
2a1b01
+			   request->length) ||
2a1b01
+	    ethnla_put_u32(msg, ETHTOOL_A_MODULE_EEPROM_OFFSET,
2a1b01
+			   request->offset) ||
2a1b01
+	    ethnla_put_u8(msg, ETHTOOL_A_MODULE_EEPROM_PAGE,
2a1b01
+			  request->page) ||
2a1b01
+	    ethnla_put_u8(msg, ETHTOOL_A_MODULE_EEPROM_BANK,
2a1b01
+			  request->bank) ||
2a1b01
+	    ethnla_put_u8(msg, ETHTOOL_A_MODULE_EEPROM_I2C_ADDRESS,
2a1b01
+			  request->i2c_address))
2a1b01
+		return -EMSGSIZE;
2a1b01
+
2a1b01
+	ret = nlsock_sendmsg(nlsock, NULL);
2a1b01
+	if (ret < 0)
2a1b01
+		return ret;
2a1b01
+	return nlsock_process_reply(nlsock, get_eeprom_page_reply_cb,
2a1b01
+				    (void *)request);
2a1b01
+}
2a1b01
+
2a1b01
 int nl_getmodule(struct cmd_context *ctx)
2a1b01
 {
2a1b01
 	struct cmd_params getmodule_cmd_params = {};
2a1b01
@@ -425,6 +529,7 @@ int nl_getmodule(struct cmd_context *ctx)
2a1b01
 	}
2a1b01
 
2a1b01
 cleanup:
2a1b01
+	eeprom_page_list_flush();
2a1b01
 	cache_free();
2a1b01
 	return ret;
2a1b01
 }
2a1b01
-- 
2a1b01
2.35.1
2a1b01