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