diff --git a/drivers/net/ethernet/freescale/enetc/ntmp.c b/drivers/net/ethernet/freescale/enetc/ntmp.c index f71cad943424..bda26fe93b8d 100644 --- a/drivers/net/ethernet/freescale/enetc/ntmp.c +++ b/drivers/net/ethernet/freescale/enetc/ntmp.c @@ -31,6 +31,7 @@ #define NTMP_GEN_UA_STSEU BIT(1) /* Specific Update Actions for some tables */ +#define FDBT_UA_ACTEU BIT(1) #define BPT_UA_BPSEU BIT(1) /* Query Action: 0: Full query. 1: Query entry ID, the fields after entry @@ -793,6 +794,167 @@ int ntmp_fdbt_search_port_entry(struct ntmp_user *user, int port, } EXPORT_SYMBOL_GPL(ntmp_fdbt_search_port_entry); +/** + * ntmp_fdbt_update_activity_element - update the activity element of all + * the dynamic entries in the FDB table. + * @user: target ntmp_user struct + * + * A single activity update management could be used to process all the + * dynamic entries in the FDB table. When hardware process an activity + * update management command for an entry in the FDB table and the entry + * does not have its activity flag set, the activity counter is incremented. + * However, if the activity flag is set, then both the activity flag and + * activity counter are reset. Software can issue the activity update + * management commands at predefined times and the value of the activity + * counter can then be used to estimate the period of how long an FDB + * entry has been inactive. + * + * Return: 0 on success, otherwise a negative error code + */ +int ntmp_fdbt_update_activity_element(struct ntmp_user *user) +{ + 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, FDBT_UA_ACTEU); + req->ak.search.resume_eid = cpu_to_le32(NTMP_NULL_ENTRY_ID); + req->ak.search.cfge.cfg = cpu_to_le32(FDBT_DYNAMIC); + req->ak.search.cfge_mc = FDBT_CFGE_MC_DYNAMIC; + + /* Request header */ + len = NTMP_LEN(swcbd.size, NTMP_STATUS_RESP_LEN); + /* For activity update, the access method must be search */ + ntmp_fill_request_hdr(&cbd, swcbd.dma, len, NTMP_FDBT_ID, + NTMP_CMD_UPDATE, 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 update activity of %s, err: %pe\n", + ntmp_table_name(NTMP_FDBT_ID), ERR_PTR(err)); + + ntmp_unlock_cbdr(cbdr); + + return err; +} +EXPORT_SYMBOL_GPL(ntmp_fdbt_update_activity_element); + +/** + * ntmp_fdbt_delete_ageing_entries - delete all the ageing dynamic entries + * in the FDB table + * @user: target ntmp_user struct + * @act_cnt: the target value of the activity counter + * + * The matching rule is that the activity flag is not set and the activity + * counter is greater than or equal to act_cnt + * + * Return: 0 on success, otherwise a negative error code + */ +int ntmp_fdbt_delete_ageing_entries(struct ntmp_user *user, u8 act_cnt) +{ + struct fdbt_req_qd *req; + struct netc_swcbd swcbd; + struct netc_cbdr *cbdr; + union netc_cbd cbd; + u32 len; + int err; + + if (act_cnt > FDBT_ACT_CNT) + return -EINVAL; + + 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(NTMP_NULL_ENTRY_ID); + req->ak.search.cfge.cfg = cpu_to_le32(FDBT_DYNAMIC); + req->ak.search.acte = act_cnt; + /* Exact match with ACTE_DATA[ACT_FLAG] AND + * match >= ACTE_DATA[ACT_CNT] + */ + req->ak.search.acte_mc = FDBT_ACTE_MC; + req->ak.search.cfge_mc = FDBT_CFGE_MC_DYNAMIC; + + /* Request header */ + len = NTMP_LEN(swcbd.size, NTMP_STATUS_RESP_LEN); + ntmp_fill_request_hdr(&cbd, swcbd.dma, len, NTMP_FDBT_ID, + NTMP_CMD_DELETE, 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 delete ageing entries of %s, err: %pe\n", + ntmp_table_name(NTMP_FDBT_ID), ERR_PTR(err)); + + ntmp_unlock_cbdr(cbdr); + + return err; +} +EXPORT_SYMBOL_GPL(ntmp_fdbt_delete_ageing_entries); + +/** + * ntmp_fdbt_delete_port_dynamic_entries - delete all dynamic FDB entries + * associated with the specified switch port + * @user: target ntmp_user struct + * @port: the specified switch port ID + * + * Return: 0 on success, otherwise a negative error code + */ +int ntmp_fdbt_delete_port_dynamic_entries(struct ntmp_user *user, int port) +{ + 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(NTMP_NULL_ENTRY_ID); + req->ak.search.cfge.port_bitmap = cpu_to_le32(BIT(port)); + req->ak.search.cfge.cfg = cpu_to_le32(FDBT_DYNAMIC); + /* Match CFGE_DATA[DYNAMIC & PORT_BITMAP] field */ + req->ak.search.cfge_mc = FDBT_CFGE_MC_DYNAMIC_AND_PORT_BITMAP; + + /* Request header */ + len = NTMP_LEN(swcbd.size, NTMP_STATUS_RESP_LEN); + ntmp_fill_request_hdr(&cbd, swcbd.dma, len, NTMP_FDBT_ID, + NTMP_CMD_DELETE, 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 delete dynamic %s entries on port %d, err: %pe\n", + ntmp_table_name(NTMP_FDBT_ID), port, ERR_PTR(err)); + + ntmp_unlock_cbdr(cbdr); + + return err; +} +EXPORT_SYMBOL_GPL(ntmp_fdbt_delete_port_dynamic_entries); + /** * ntmp_vft_add_entry - add an entry into the VLAN filter table * @user: target ntmp_user struct diff --git a/drivers/net/ethernet/freescale/enetc/ntmp_private.h b/drivers/net/ethernet/freescale/enetc/ntmp_private.h index 0a9b87286105..ad532b059ba8 100644 --- a/drivers/net/ethernet/freescale/enetc/ntmp_private.h +++ b/drivers/net/ethernet/freescale/enetc/ntmp_private.h @@ -155,8 +155,8 @@ struct fdbt_ak_search { #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_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; diff --git a/include/linux/fsl/ntmp.h b/include/linux/fsl/ntmp.h index 88166f9ad3a2..5db078e1caa0 100644 --- a/include/linux/fsl/ntmp.h +++ b/include/linux/fsl/ntmp.h @@ -263,6 +263,9 @@ 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); +int ntmp_fdbt_update_activity_element(struct ntmp_user *user); +int ntmp_fdbt_delete_ageing_entries(struct ntmp_user *user, u8 act_cnt); +int ntmp_fdbt_delete_port_dynamic_entries(struct ntmp_user *user, int port); int ntmp_vft_add_entry(struct ntmp_user *user, u16 vid, const struct vft_cfge_data *cfge); int ntmp_bpt_update_entry(struct ntmp_user *user, u32 entry_id,