diff --git a/drivers/net/ethernet/freescale/enetc/ntmp.c b/drivers/net/ethernet/freescale/enetc/ntmp.c index c94a928622fd..6074eeafd5a2 100644 --- a/drivers/net/ethernet/freescale/enetc/ntmp.c +++ b/drivers/net/ethernet/freescale/enetc/ntmp.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* * NETC NTMP (NETC Table Management Protocol) 2.0 Library - * Copyright 2025 NXP + * Copyright 2025-2026 NXP */ #include @@ -21,11 +21,17 @@ /* Define NTMP Table ID */ #define NTMP_MAFT_ID 1 #define NTMP_RSST_ID 3 +#define NTMP_FDBT_ID 15 /* Generic Update Actions for most tables */ #define NTMP_GEN_UA_CFGEU BIT(0) #define NTMP_GEN_UA_STSEU BIT(1) +/* Query Action: 0: Full query. 1: Query entry ID, the fields after entry + * ID are not returned. + */ +#define NTMP_QA_ENTRY_ID 1 + #define NTMP_ENTRY_ID_SIZE 4 #define RSST_ENTRY_NUM 64 #define RSST_STSE_DATA_SIZE(n) ((n) * 8) @@ -260,6 +266,8 @@ static const char *ntmp_table_name(int tbl_id) return "MAC Address Filter Table"; case NTMP_RSST_ID: return "RSS Table"; + case NTMP_FDBT_ID: + return "FDB Table"; default: return "Unknown Table"; } @@ -496,5 +504,200 @@ int ntmp_rsst_query_entry(struct ntmp_user *user, u32 *table, int count) } EXPORT_SYMBOL_GPL(ntmp_rsst_query_entry); +/** + * ntmp_fdbt_add_entry - add an entry into the FDB table + * @user: target ntmp_user struct + * @entry_id: returned value, the entry ID of the new added entry + * @keye: key element data + * @cfge: configuration element data + * + * Return: 0 on success, otherwise a negative error code + */ +int ntmp_fdbt_add_entry(struct ntmp_user *user, u32 *entry_id, + const struct fdbt_keye_data *keye, + const struct fdbt_cfge_data *cfge) +{ + struct fdbt_resp_query *resp; + struct fdbt_req_ua *req; + struct netc_swcbd swcbd; + struct netc_cbdr *cbdr; + union netc_cbd cbd; + u32 len; + int err; + + swcbd.size = sizeof(*req); + err = ntmp_alloc_data_mem(user->dev, &swcbd, (void **)&req); + if (err) + return err; + + /* Request data */ + ntmp_fill_crd(&req->crd, user->tbl.fdbt_ver, NTMP_QA_ENTRY_ID, + NTMP_GEN_UA_CFGEU); + req->ak.exact.keye = *keye; + req->cfge = *cfge; + + len = NTMP_LEN(swcbd.size, sizeof(*resp)); + /* The entry ID is allotted by hardware, so we need to perform + * a query action after the add action to get the entry ID from + * hardware. + */ + ntmp_fill_request_hdr(&cbd, swcbd.dma, len, NTMP_FDBT_ID, + NTMP_CMD_AQ, NTMP_AM_EXACT_KEY); + + ntmp_select_and_lock_cbdr(user, &cbdr); + err = netc_xmit_ntmp_cmd(cbdr, &cbd, &swcbd); + if (err) { + dev_err(user->dev, "Failed to add %s entry, err: %pe\n", + ntmp_table_name(NTMP_FDBT_ID), ERR_PTR(err)); + goto unlock_cbdr; + } + + if (entry_id) { + resp = (struct fdbt_resp_query *)req; + *entry_id = le32_to_cpu(resp->entry_id); + } + +unlock_cbdr: + ntmp_unlock_cbdr(cbdr); + + return err; +} +EXPORT_SYMBOL_GPL(ntmp_fdbt_add_entry); + +/** + * ntmp_fdbt_update_entry - update the configuration element data of the + * specified FDB entry + * @user: target ntmp_user struct + * @entry_id: the specified entry ID of the FDB table + * @cfge: configuration element data + * + * Return: 0 on success, otherwise a negative error code + */ +int ntmp_fdbt_update_entry(struct ntmp_user *user, u32 entry_id, + const struct fdbt_cfge_data *cfge) +{ + struct fdbt_req_ua *req; + struct netc_swcbd swcbd; + struct netc_cbdr *cbdr; + union netc_cbd cbd; + u32 len; + int err; + + swcbd.size = sizeof(*req); + err = ntmp_alloc_data_mem(user->dev, &swcbd, (void **)&req); + if (err) + return err; + + /* Request data */ + ntmp_fill_crd(&req->crd, user->tbl.fdbt_ver, 0, NTMP_GEN_UA_CFGEU); + req->ak.eid.entry_id = cpu_to_le32(entry_id); + req->cfge = *cfge; + + /* Request header */ + len = NTMP_LEN(swcbd.size, NTMP_STATUS_RESP_LEN); + ntmp_fill_request_hdr(&cbd, swcbd.dma, len, NTMP_FDBT_ID, + NTMP_CMD_UPDATE, NTMP_AM_ENTRY_ID); + + ntmp_select_and_lock_cbdr(user, &cbdr); + err = netc_xmit_ntmp_cmd(cbdr, &cbd, &swcbd); + if (err) + dev_err(user->dev, "Failed to update %s entry, err: %pe\n", + ntmp_table_name(NTMP_FDBT_ID), ERR_PTR(err)); + + ntmp_unlock_cbdr(cbdr); + + return err; +} +EXPORT_SYMBOL_GPL(ntmp_fdbt_update_entry); + +/** + * ntmp_fdbt_delete_entry - delete the specified FDB entry + * @user: target ntmp_user struct + * @entry_id: the specified ID of the FDB entry + * + * Return: 0 on success, otherwise a negative error code + */ +int ntmp_fdbt_delete_entry(struct ntmp_user *user, u32 entry_id) +{ + u32 req_len = sizeof(struct fdbt_req_qd); + + return ntmp_delete_entry_by_id(user, NTMP_FDBT_ID, + user->tbl.fdbt_ver, + entry_id, req_len, + NTMP_STATUS_RESP_LEN); +} +EXPORT_SYMBOL_GPL(ntmp_fdbt_delete_entry); + +/** + * ntmp_fdbt_search_port_entry - Search the FDB entry on the specified + * port based on RESUME_ENTRY_ID + * @user: target ntmp_user struct + * @port: the specified switch port ID + * @resume_entry_id: it is both an input and an output. As an input, it + * represents the FDB entry ID to be searched. If it is a NULL entry ID, + * it indicates that the first FDB entry for that port is being searched. + * As an output, it represents the next FDB entry ID to be searched. + * @entry: returned value, the response data of the searched FDB entry + * + * Return: 0 on success, otherwise a negative error code + */ +int ntmp_fdbt_search_port_entry(struct ntmp_user *user, int port, + u32 *resume_entry_id, + struct fdbt_entry_data *entry) +{ + struct fdbt_resp_query *resp; + struct fdbt_req_qd *req; + struct netc_swcbd swcbd; + struct netc_cbdr *cbdr; + union netc_cbd cbd; + u32 len; + int err; + + swcbd.size = sizeof(*req); + err = ntmp_alloc_data_mem(user->dev, &swcbd, (void **)&req); + if (err) + return err; + + /* Request data */ + ntmp_fill_crd(&req->crd, user->tbl.fdbt_ver, 0, 0); + req->ak.search.resume_eid = cpu_to_le32(*resume_entry_id); + req->ak.search.cfge.port_bitmap = cpu_to_le32(BIT(port)); + /* Match CFGE_DATA[PORT_BITMAP] field */ + req->ak.search.cfge_mc = FDBT_CFGE_MC_PORT_BITMAP; + + /* Request header */ + len = NTMP_LEN(swcbd.size, sizeof(*resp)); + ntmp_fill_request_hdr(&cbd, swcbd.dma, len, NTMP_FDBT_ID, + NTMP_CMD_QUERY, NTMP_AM_SEARCH); + + ntmp_select_and_lock_cbdr(user, &cbdr); + err = netc_xmit_ntmp_cmd(cbdr, &cbd, &swcbd); + if (err) { + dev_err(user->dev, + "Failed to search %s entry on port %d, err: %pe\n", + ntmp_table_name(NTMP_FDBT_ID), port, ERR_PTR(err)); + goto unlock_cbdr; + } + + if (!cbd.resp_hdr.num_matched) { + entry->entry_id = NTMP_NULL_ENTRY_ID; + *resume_entry_id = NTMP_NULL_ENTRY_ID; + goto unlock_cbdr; + } + + resp = (struct fdbt_resp_query *)req; + *resume_entry_id = le32_to_cpu(resp->status); + entry->entry_id = le32_to_cpu(resp->entry_id); + entry->keye = resp->keye; + entry->cfge = resp->cfge; + entry->acte = resp->acte; + +unlock_cbdr: + ntmp_unlock_cbdr(cbdr); + + return err; +} +EXPORT_SYMBOL_GPL(ntmp_fdbt_search_port_entry); + MODULE_DESCRIPTION("NXP NETC Library"); MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/ethernet/freescale/enetc/ntmp_private.h b/drivers/net/ethernet/freescale/enetc/ntmp_private.h index f8dff3ba2c28..b0b5805ac4f6 100644 --- a/drivers/net/ethernet/freescale/enetc/ntmp_private.h +++ b/drivers/net/ethernet/freescale/enetc/ntmp_private.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ /* * NTMP table request and response data buffer formats - * Copyright 2025 NXP + * Copyright 2025-2026 NXP */ #ifndef __NTMP_PRIVATE_H @@ -11,6 +11,7 @@ #include #define NTMP_EID_REQ_LEN 8 +#define NTMP_STATUS_RESP_LEN 4 #define NETC_CBDR_BD_NUM 256 #define NETC_CBDRCIR_INDEX GENMASK(9, 0) #define NETC_CBDRCIR_SBE BIT(31) @@ -30,6 +31,7 @@ union netc_cbd { #define NTMP_CMD_QUERY BIT(2) #define NTMP_CMD_ADD BIT(3) #define NTMP_CMD_QU (NTMP_CMD_QUERY | NTMP_CMD_UPDATE) +#define NTMP_CMD_AQ (NTMP_CMD_ADD | NTMP_CMD_QUERY) u8 access_method; #define NTMP_ACCESS_METHOD GENMASK(7, 4) #define NTMP_AM_ENTRY_ID 0 @@ -97,4 +99,61 @@ struct rsst_req_update { u8 groups[]; }; +/* Access Key Format of FDB Table */ +struct fdbt_ak_eid { + __le32 entry_id; + __le32 resv[7]; +}; + +struct fdbt_ak_exact { + struct fdbt_keye_data keye; + __le32 resv[5]; +}; + +struct fdbt_ak_search { + __le32 resume_eid; + struct fdbt_keye_data keye; + struct fdbt_cfge_data cfge; + u8 acte; + u8 keye_mc; +#define FDBT_KEYE_MAC GENMASK(1, 0) + u8 cfge_mc; +#define FDBT_CFGE_MC GENMASK(2, 0) +#define FDBT_CFGE_MC_ANY 0 +#define FDBT_CFGE_MC_DYNAMIC 1 +#define FDBT_CFGE_MC_PORT_BITMAP 2 +#define FDBT_CFGE_MC_DYNAMIC_AND_PORT_BITMAP 3 + u8 acte_mc; +#define FDBT_ACTE_MC BIT(0) +}; + +union fdbt_access_key { + struct fdbt_ak_eid eid; + struct fdbt_ak_exact exact; + struct fdbt_ak_search search; +}; + +/* FDB Table Request Data Buffer Format of Update and Add actions */ +struct fdbt_req_ua { + struct ntmp_cmn_req_data crd; + union fdbt_access_key ak; + struct fdbt_cfge_data cfge; +}; + +/* FDB Table Request Data Buffer Format of Query and Delete actions */ +struct fdbt_req_qd { + struct ntmp_cmn_req_data crd; + union fdbt_access_key ak; +}; + +/* FDB Table Response Data Buffer Format of Query action */ +struct fdbt_resp_query { + __le32 status; + __le32 entry_id; + struct fdbt_keye_data keye; + struct fdbt_cfge_data cfge; + u8 acte; + u8 resv[3]; +}; + #endif diff --git a/include/linux/fsl/ntmp.h b/include/linux/fsl/ntmp.h index 83a449b4d6ec..4cfff835954e 100644 --- a/include/linux/fsl/ntmp.h +++ b/include/linux/fsl/ntmp.h @@ -1,11 +1,13 @@ /* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ -/* Copyright 2025 NXP */ +/* Copyright 2025-2026 NXP */ #ifndef __NETC_NTMP_H #define __NETC_NTMP_H #include #include +#define NTMP_NULL_ENTRY_ID 0xffffffffU + struct maft_keye_data { u8 mac_addr[ETH_ALEN]; __le16 resv; @@ -29,6 +31,7 @@ struct netc_cbdr_regs { struct netc_tbl_vers { u8 maft_ver; u8 rsst_ver; + u8 fdbt_ver; }; struct netc_swcbd { @@ -68,6 +71,36 @@ struct maft_entry_data { struct maft_cfge_data cfge; }; +struct fdbt_keye_data { + u8 mac_addr[ETH_ALEN]; /* big-endian */ + __le16 resv0; + __le16 fid; +#define FDBT_FID GENMASK(11, 0) + __le16 resv1; +}; + +struct fdbt_cfge_data { + __le32 port_bitmap; +#define FDBT_PORT_BITMAP GENMASK(23, 0) + __le32 cfg; +#define FDBT_OETEID GENMASK(1, 0) +#define FDBT_EPORT GENMASK(6, 2) +#define FDBT_IMIRE BIT(7) +#define FDBT_CTD GENMASK(10, 9) +#define FDBT_DYNAMIC BIT(11) +#define FDBT_TIMECAPE BIT(12) + __le32 et_eid; +}; + +struct fdbt_entry_data { + u32 entry_id; + struct fdbt_keye_data keye; + struct fdbt_cfge_data cfge; + u8 acte; +#define FDBT_ACT_CNT GENMASK(6, 0) +#define FDBT_ACT_FLAG BIT(7) +}; + #if IS_ENABLED(CONFIG_NXP_NETC_LIB) int ntmp_init_cbdr(struct netc_cbdr *cbdr, struct device *dev, const struct netc_cbdr_regs *regs); @@ -83,6 +116,15 @@ int ntmp_rsst_update_entry(struct ntmp_user *user, const u32 *table, int count); int ntmp_rsst_query_entry(struct ntmp_user *user, u32 *table, int count); +int ntmp_fdbt_add_entry(struct ntmp_user *user, u32 *entry_id, + const struct fdbt_keye_data *keye, + const struct fdbt_cfge_data *cfge); +int ntmp_fdbt_update_entry(struct ntmp_user *user, u32 entry_id, + const struct fdbt_cfge_data *cfge); +int ntmp_fdbt_delete_entry(struct ntmp_user *user, u32 entry_id); +int ntmp_fdbt_search_port_entry(struct ntmp_user *user, int port, + u32 *resume_entry_id, + struct fdbt_entry_data *entry); #else static inline int ntmp_init_cbdr(struct netc_cbdr *cbdr, struct device *dev, const struct netc_cbdr_regs *regs)