diff --git a/drivers/net/ethernet/freescale/enetc/ntmp.c b/drivers/net/ethernet/freescale/enetc/ntmp.c index ad89be85b185..635032d24dc7 100644 --- a/drivers/net/ethernet/freescale/enetc/ntmp.c +++ b/drivers/net/ethernet/freescale/enetc/ntmp.c @@ -21,6 +21,7 @@ /* Define NTMP Table ID */ #define NTMP_MAFT_ID 1 #define NTMP_RSST_ID 3 +#define NTMP_IPFT_ID 13 #define NTMP_FDBT_ID 15 #define NTMP_VFT_ID 18 #define NTMP_BPT_ID 41 @@ -271,6 +272,8 @@ static const char *ntmp_table_name(int tbl_id) return "MAC Address Filter Table"; case NTMP_RSST_ID: return "RSS Table"; + case NTMP_IPFT_ID: + return "Ingress Port Filter Table"; case NTMP_FDBT_ID: return "FDB Table"; case NTMP_VFT_ID: @@ -513,6 +516,83 @@ unlock_cbdr: } EXPORT_SYMBOL_GPL(ntmp_rsst_query_entry); +/** + * ntmp_ipft_add_entry - add an entry into the ingress port filter table + * @user: target ntmp_user struct + * @entry: the entry data, entry->cfge (configuration element data) and + * entry->keye (key element data) are used as input. Since the entry ID + * is assigned by the hardware, so entry->entry_id is a returned value + * for the driver to use, the driver can update/delete/query the entry + * based on the entry_id. + * + * Return: 0 on success, otherwise a negative error code + */ +int ntmp_ipft_add_entry(struct ntmp_user *user, + struct ipft_entry_data *entry) +{ + struct ipft_resp_query *resp; + struct ipft_req_ua *req; + struct netc_swcbd swcbd; + struct netc_cbdr *cbdr; + union netc_cbd cbd; + u32 len; + int err; + + swcbd.size = sizeof(*resp); + err = ntmp_alloc_data_mem(user->dev, &swcbd, (void **)&req); + if (err) + return err; + + /* Note that NTMP_GEN_UA_STSEU is used to reset the statistics of + * the entry. The STSE_DATA is not present in the request data for + * 'Add' operation. + */ + ntmp_fill_crd(&req->crd, user->tbl.ipft_ver, NTMP_QA_ENTRY_ID, + NTMP_GEN_UA_CFGEU | NTMP_GEN_UA_STSEU); + req->ak.keye = entry->keye; + req->cfge = entry->cfge; + + len = NTMP_LEN(sizeof(*req), swcbd.size); + ntmp_fill_request_hdr(&cbd, swcbd.dma, len, NTMP_IPFT_ID, + NTMP_CMD_AQ, NTMP_AM_TERNARY_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_IPFT_ID), ERR_PTR(err)); + + goto unlock_cbdr; + } + + resp = (struct ipft_resp_query *)req; + entry->entry_id = le32_to_cpu(resp->entry_id); + +unlock_cbdr: + ntmp_unlock_cbdr(cbdr); + + return err; +} +EXPORT_SYMBOL_GPL(ntmp_ipft_add_entry); + +/** + * ntmp_ipft_delete_entry - delete a specified ingress port filter table entry + * @user: target ntmp_user struct + * @entry_id: the specified ID of the ingress port filter table entry + * + * Return: 0 on success, otherwise a negative error code + */ +int ntmp_ipft_delete_entry(struct ntmp_user *user, u32 entry_id) +{ + u32 req_len = sizeof(struct ipft_req_qd); + + return ntmp_delete_entry_by_id(user, NTMP_IPFT_ID, + user->tbl.ipft_ver, + entry_id, req_len, + NTMP_STATUS_RESP_LEN); +} +EXPORT_SYMBOL_GPL(ntmp_ipft_delete_entry); + /** * ntmp_fdbt_add_entry - add an entry into the FDB 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 64df49e9a3ef..0a9b87286105 100644 --- a/drivers/net/ethernet/freescale/enetc/ntmp_private.h +++ b/drivers/net/ethernet/freescale/enetc/ntmp_private.h @@ -99,6 +99,42 @@ struct rsst_req_update { u8 groups[]; }; +/* Ingress Port Filter Table Response Data Buffer Format of Query action */ +struct ipft_resp_query { + __le32 status; + __le32 entry_id; + struct ipft_keye_data keye; + __le64 match_count; /* STSE_DATA */ + struct ipft_cfge_data cfge; +} __packed; + +struct ipft_ak_eid { + __le32 entry_id; + __le32 resv[52]; +}; + +union ipft_access_key { + struct ipft_ak_eid eid; + struct ipft_keye_data keye; +}; + +/* Ingress Port Filter Table Request Data Buffer Format of Update and + * Add actions + */ +struct ipft_req_ua { + struct ntmp_cmn_req_data crd; + union ipft_access_key ak; + struct ipft_cfge_data cfge; +}; + +/* Ingress Port Filter Table Request Data Buffer Format of Query and + * Delete actions + */ +struct ipft_req_qd { + struct ntmp_req_by_eid rbe; + __le32 resv[52]; +}; + /* Access Key Format of FDB Table */ struct fdbt_ak_eid { __le32 entry_id; diff --git a/include/linux/fsl/ntmp.h b/include/linux/fsl/ntmp.h index 5fded868725f..88166f9ad3a2 100644 --- a/include/linux/fsl/ntmp.h +++ b/include/linux/fsl/ntmp.h @@ -7,6 +7,7 @@ #include #define NTMP_NULL_ENTRY_ID 0xffffffffU +#define IPFT_MAX_PLD_LEN 24 struct maft_keye_data { u8 mac_addr[ETH_ALEN]; @@ -34,6 +35,7 @@ struct netc_tbl_vers { u8 fdbt_ver; u8 vft_ver; u8 bpt_ver; + u8 ipft_ver; }; struct netc_swcbd { @@ -73,6 +75,94 @@ struct maft_entry_data { struct maft_cfge_data cfge; }; +struct ipft_pld_byte { + u8 data; + u8 mask; +}; + +struct ipft_keye_data { + __le16 precedence; + __le16 resv0[3]; + __le16 frm_attr_flags; +#define IPFT_FAF_OVLAN BIT(2) +#define IPFT_FAF_IVLAN BIT(3) +#define IPFT_FAF_IP_HDR BIT(7) +#define IPFT_FAF_IP_VER6 BIT(8) +#define IPFT_FAF_L4_CODE GENMASK(11, 10) +#define IPFT_FAF_TCP_HDR 1 +#define IPFT_FAF_UDP_HDR 2 +#define IPFT_FAF_SCTP_HDR 3 +#define IPFT_FAF_WOL_MAGIC BIT(12) + __le16 frm_attr_flags_mask; + __le16 dscp; +#define IPFT_DSCP GENMASK(5, 0) +#define IPFT_DSCP_MASK GENMASK(11, 6) +#define IPFT_DSCP_MASK_ALL 0x3f + __le16 src_port; /* This field is reserved for ENETC */ +#define IPFT_SRC_PORT GENMASK(4, 0) +#define IPFT_SRC_PORT_MASK GENMASK(9, 5) +#define IPFT_SRC_PORT_MASK_ALL 0x1f + __be16 outer_vlan_tci; + __be16 outer_vlan_tci_mask; + u8 dmac[ETH_ALEN]; + u8 dmac_mask[ETH_ALEN]; + u8 smac[ETH_ALEN]; + u8 smac_mask[ETH_ALEN]; + __be16 inner_vlan_tci; + __be16 inner_vlan_tci_mask; + __be16 ethertype; + __be16 ethertype_mask; + u8 ip_protocol; + u8 ip_protocol_mask; + __le16 resv1[7]; + __be32 ip_src[4]; + __le32 resv2[2]; + __be32 ip_src_mask[4]; + __be16 l4_src_port; + __be16 l4_src_port_mask; + __le32 resv3; + __be32 ip_dst[4]; + __le32 resv4[2]; + __be32 ip_dst_mask[4]; + __be16 l4_dst_port; + __be16 l4_dst_port_mask; + __le32 resv5; + struct ipft_pld_byte byte[IPFT_MAX_PLD_LEN]; +}; + +struct ipft_cfge_data { + __le32 cfg; +#define IPFT_IPV GENMASK(3, 0) +#define IPFT_OIPV BIT(4) +#define IPFT_DR GENMASK(6, 5) +#define IPFT_ODR BIT(7) +#define IPFT_FLTFA GENMASK(10, 8) +#define IPFT_FLTFA_DISCARD 0 +#define IPFT_FLTFA_PERMIT 1 +/* Redirect is only for switch */ +#define IPFT_FLTFA_REDIRECT 2 +#define IPFT_IMIRE BIT(11) +#define IPFT_WOLTE BIT(12) +#define IPFT_FLTA GENMASK(14, 13) +#define IPFT_FLTA_RP 1 +#define IPFT_FLTA_IS 2 +#define IPFT_FLTA_SI_BITMAP 3 +#define IPFT_RPR GENMASK(16, 15) +#define IPFT_CTD BIT(17) +#define IPFT_HR GENMASK(21, 18) +#define IPFT_TIMECAPE BIT(22) +#define IPFT_RRT BIT(23) +#define IPFT_BL2F BIT(24) +#define IPFT_EVMEID GENMASK(31, 28) + __le32 flta_tgt; +}; + +struct ipft_entry_data { + u32 entry_id; /* hardware assigns entry ID */ + struct ipft_keye_data keye; + struct ipft_cfge_data cfge; +}; + struct fdbt_keye_data { u8 mac_addr[ETH_ALEN]; /* big-endian */ __le16 resv0; @@ -161,6 +251,9 @@ 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_ipft_add_entry(struct ntmp_user *user, + struct ipft_entry_data *entry); +int ntmp_ipft_delete_entry(struct ntmp_user *user, u32 entry_id); int ntmp_fdbt_add_entry(struct ntmp_user *user, u32 *entry_id, const struct fdbt_keye_data *keye, const struct fdbt_cfge_data *cfge);