From 6f2a064bef93057f508c5e81bcfeb8d637ae0baa Mon Sep 17 00:00:00 2001 From: Shagun Agrawal Date: Fri, 8 Jun 2018 23:28:11 +0530 Subject: [PATCH] net/cxgbe: query firmware for filter resources Fetch available filter resources from firmware and allocate table for book-keeping and managing filters in hardware. Also define the hardware filter specification (ch_filter_specification) used to describe each filter rule. Signed-off-by: Shagun Agrawal Signed-off-by: Kumar Sanghvi Signed-off-by: Rahul Lakkireddy --- drivers/net/cxgbe/base/adapter.h | 4 + drivers/net/cxgbe/base/t4fw_interface.h | 6 ++ drivers/net/cxgbe/cxgbe_filter.h | 97 ++++++++++++++++++++++ drivers/net/cxgbe/cxgbe_main.c | 106 ++++++++++++++++++++++++ drivers/net/cxgbe/cxgbe_ofld.h | 27 ++++++ 5 files changed, 240 insertions(+) create mode 100644 drivers/net/cxgbe/cxgbe_filter.h create mode 100644 drivers/net/cxgbe/cxgbe_ofld.h diff --git a/drivers/net/cxgbe/base/adapter.h b/drivers/net/cxgbe/base/adapter.h index 55cb2e91c7..1a0f96e400 100644 --- a/drivers/net/cxgbe/base/adapter.h +++ b/drivers/net/cxgbe/base/adapter.h @@ -11,9 +11,11 @@ #include #include #include +#include #include "cxgbe_compat.h" #include "t4_regs_values.h" +#include "cxgbe_ofld.h" enum { MAX_ETH_QSETS = 64, /* # of Ethernet Tx/Rx queue sets */ @@ -306,6 +308,8 @@ struct adapter { unsigned int vpd_flag; int use_unpacked_mode; /* unpacked rx mode state */ + + struct tid_info tids; /* Info used to access TID related tables */ }; /** diff --git a/drivers/net/cxgbe/base/t4fw_interface.h b/drivers/net/cxgbe/base/t4fw_interface.h index 852e8f3c79..95b2aec482 100644 --- a/drivers/net/cxgbe/base/t4fw_interface.h +++ b/drivers/net/cxgbe/base/t4fw_interface.h @@ -489,6 +489,10 @@ enum fw_params_mnem { enum fw_params_param_dev { FW_PARAMS_PARAM_DEV_CCLK = 0x00, /* chip core clock in khz */ FW_PARAMS_PARAM_DEV_PORTVEC = 0x01, /* the port vector */ + FW_PARAMS_PARAM_DEV_NTID = 0x02, /* reads the number of TIDs + * allocated by the device's + * Lookup Engine + */ FW_PARAMS_PARAM_DEV_FWREV = 0x0B, /* fw version */ FW_PARAMS_PARAM_DEV_TPREV = 0x0C, /* tp version */ FW_PARAMS_PARAM_DEV_ULPTX_MEMWRITE_DSGL = 0x17, @@ -498,6 +502,8 @@ enum fw_params_param_dev { * physical and virtual function parameters */ enum fw_params_param_pfvf { + FW_PARAMS_PARAM_PFVF_FILTER_START = 0x05, + FW_PARAMS_PARAM_PFVF_FILTER_END = 0x06, FW_PARAMS_PARAM_PFVF_CPLFW4MSG_ENCAP = 0x31, FW_PARAMS_PARAM_PFVF_PORT_CAPS32 = 0x3A }; diff --git a/drivers/net/cxgbe/cxgbe_filter.h b/drivers/net/cxgbe/cxgbe_filter.h new file mode 100644 index 0000000000..5af891b280 --- /dev/null +++ b/drivers/net/cxgbe/cxgbe_filter.h @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018 Chelsio Communications. + * All rights reserved. + */ + +#ifndef _CXGBE_FILTER_H_ +#define _CXGBE_FILTER_H_ + +#include "t4_msg.h" +/* + * Defined bit width of user definable filter tuples + */ +#define ETHTYPE_BITWIDTH 16 +#define FRAG_BITWIDTH 1 +#define MACIDX_BITWIDTH 9 +#define FCOE_BITWIDTH 1 +#define IPORT_BITWIDTH 3 +#define MATCHTYPE_BITWIDTH 3 +#define PROTO_BITWIDTH 8 +#define TOS_BITWIDTH 8 +#define PF_BITWIDTH 8 +#define VF_BITWIDTH 8 +#define IVLAN_BITWIDTH 16 +#define OVLAN_BITWIDTH 16 + +/* + * Filter matching rules. These consist of a set of ingress packet field + * (value, mask) tuples. The associated ingress packet field matches the + * tuple when ((field & mask) == value). (Thus a wildcard "don't care" field + * rule can be constructed by specifying a tuple of (0, 0).) A filter rule + * matches an ingress packet when all of the individual individual field + * matching rules are true. + * + * Partial field masks are always valid, however, while it may be easy to + * understand their meanings for some fields (e.g. IP address to match a + * subnet), for others making sensible partial masks is less intuitive (e.g. + * MPS match type) ... + */ +struct ch_filter_tuple { + /* + * Compressed header matching field rules. The TP_VLAN_PRI_MAP + * register selects which of these fields will participate in the + * filter match rules -- up to a maximum of 36 bits. Because + * TP_VLAN_PRI_MAP is a global register, all filters must use the same + * set of fields. + */ + uint32_t ethtype:ETHTYPE_BITWIDTH; /* Ethernet type */ + uint32_t frag:FRAG_BITWIDTH; /* IP fragmentation header */ + uint32_t ivlan_vld:1; /* inner VLAN valid */ + uint32_t ovlan_vld:1; /* outer VLAN valid */ + uint32_t pfvf_vld:1; /* PF/VF valid */ + uint32_t macidx:MACIDX_BITWIDTH; /* exact match MAC index */ + uint32_t fcoe:FCOE_BITWIDTH; /* FCoE packet */ + uint32_t iport:IPORT_BITWIDTH; /* ingress port */ + uint32_t matchtype:MATCHTYPE_BITWIDTH; /* MPS match type */ + uint32_t proto:PROTO_BITWIDTH; /* protocol type */ + uint32_t tos:TOS_BITWIDTH; /* TOS/Traffic Type */ + uint32_t pf:PF_BITWIDTH; /* PCI-E PF ID */ + uint32_t vf:VF_BITWIDTH; /* PCI-E VF ID */ + uint32_t ivlan:IVLAN_BITWIDTH; /* inner VLAN */ + uint32_t ovlan:OVLAN_BITWIDTH; /* outer VLAN */ + + /* + * Uncompressed header matching field rules. These are always + * available for field rules. + */ + uint8_t lip[16]; /* local IP address (IPv4 in [3:0]) */ + uint8_t fip[16]; /* foreign IP address (IPv4 in [3:0]) */ + uint16_t lport; /* local port */ + uint16_t fport; /* foreign port */ + + /* reservations for future additions */ + uint8_t rsvd[12]; +}; + +/* + * Filter specification + */ +struct ch_filter_specification { + /* Filter rule value/mask pairs. */ + struct ch_filter_tuple val; + struct ch_filter_tuple mask; +}; + +/* + * Host shadow copy of ingress filter entry. This is in host native format + * and doesn't match the ordering or bit order, etc. of the hardware or the + * firmware command. + */ +struct filter_entry { + /* + * The filter itself. + */ + struct ch_filter_specification fs; +}; + +#endif /* _CXGBE_FILTER_H_ */ diff --git a/drivers/net/cxgbe/cxgbe_main.c b/drivers/net/cxgbe/cxgbe_main.c index 54eb23dfb6..9880257d2c 100644 --- a/drivers/net/cxgbe/cxgbe_main.c +++ b/drivers/net/cxgbe/cxgbe_main.c @@ -38,6 +38,22 @@ #include "t4_msg.h" #include "cxgbe.h" +/** + * Allocate a chunk of memory. The allocated memory is cleared. + */ +void *t4_alloc_mem(size_t size) +{ + return rte_zmalloc(NULL, size, 0); +} + +/** + * Free memory allocated through t4_alloc_mem(). + */ +void t4_free_mem(void *addr) +{ + rte_free(addr); +} + /* * Response queue handler for the FW event queue. */ @@ -169,6 +185,59 @@ int cxgb4_set_rspq_intr_params(struct sge_rspq *q, unsigned int us, return 0; } +/** + * Free TID tables. + */ +static void tid_free(struct tid_info *t) +{ + if (t->tid_tab) { + if (t->ftid_bmap) + rte_bitmap_free(t->ftid_bmap); + + if (t->ftid_bmap_array) + t4_os_free(t->ftid_bmap_array); + + t4_os_free(t->tid_tab); + } + + memset(t, 0, sizeof(struct tid_info)); +} + +/** + * Allocate and initialize the TID tables. Returns 0 on success. + */ +static int tid_init(struct tid_info *t) +{ + size_t size; + unsigned int ftid_bmap_size; + unsigned int max_ftids = t->nftids; + + ftid_bmap_size = rte_bitmap_get_memory_footprint(t->nftids); + size = t->ntids * sizeof(*t->tid_tab) + + max_ftids * sizeof(*t->ftid_tab); + + t->tid_tab = t4_os_alloc(size); + if (!t->tid_tab) + return -ENOMEM; + + t->ftid_tab = (struct filter_entry *)&t->tid_tab[t->ntids]; + t->ftid_bmap_array = t4_os_alloc(ftid_bmap_size); + if (!t->ftid_bmap_array) { + tid_free(t); + return -ENOMEM; + } + + t4_os_lock_init(&t->ftid_lock); + t->ftid_bmap = rte_bitmap_init(t->nftids, t->ftid_bmap_array, + ftid_bmap_size); + if (!t->ftid_bmap) { + tid_free(t); + return -ENOMEM; + } + + return 0; +} + static inline bool is_x_1g_port(const struct link_config *lc) { return (lc->pcaps & FW_PORT_CAP32_SPEED_1G) != 0; @@ -706,6 +775,7 @@ bye: static int adap_init0(struct adapter *adap) { + struct fw_caps_config_cmd caps_cmd; int ret = 0; u32 v, port_vec; enum dev_state state; @@ -822,6 +892,35 @@ static int adap_init0(struct adapter *adap) V_FW_PARAMS_PARAM_Y(0) | \ V_FW_PARAMS_PARAM_Z(0)) + params[0] = FW_PARAM_PFVF(FILTER_START); + params[1] = FW_PARAM_PFVF(FILTER_END); + ret = t4_query_params(adap, adap->mbox, adap->pf, 0, 2, params, val); + if (ret < 0) + goto bye; + adap->tids.ftid_base = val[0]; + adap->tids.nftids = val[1] - val[0] + 1; + + /* + * Get device capabilities so we can determine what resources we need + * to manage. + */ + memset(&caps_cmd, 0, sizeof(caps_cmd)); + caps_cmd.op_to_write = htonl(V_FW_CMD_OP(FW_CAPS_CONFIG_CMD) | + F_FW_CMD_REQUEST | F_FW_CMD_READ); + caps_cmd.cfvalid_to_len16 = htonl(FW_LEN16(caps_cmd)); + ret = t4_wr_mbox(adap, adap->mbox, &caps_cmd, sizeof(caps_cmd), + &caps_cmd); + if (ret < 0) + goto bye; + + /* query tid-related parameters */ + params[0] = FW_PARAM_DEV(NTID); + ret = t4_query_params(adap, adap->mbox, adap->pf, 0, 1, + params, val); + if (ret < 0) + goto bye; + adap->tids.ntids = val[0]; + /* If we're running on newer firmware, let it know that we're * prepared to deal with encapsulated CPL messages. Older * firmware won't understand this and we'll just get @@ -1307,6 +1406,7 @@ void cxgbe_close(struct adapter *adapter) if (adapter->flags & FULL_INIT_DONE) { if (is_pf4(adapter)) t4_intr_disable(adapter); + tid_free(&adapter->tids); t4_sge_tx_monitor_stop(adapter); t4_free_sge_resources(adapter); for_each_port(adapter, i) { @@ -1469,6 +1569,12 @@ allocate_mac: print_adapter_info(adapter); print_port_info(adapter); + if (tid_init(&adapter->tids) < 0) { + /* Disable filtering support */ + dev_warn(adapter, "could not allocate TID table, " + "filter support disabled. Continuing\n"); + } + err = init_rss(adapter); if (err) goto out_free; diff --git a/drivers/net/cxgbe/cxgbe_ofld.h b/drivers/net/cxgbe/cxgbe_ofld.h new file mode 100644 index 0000000000..9f382f6595 --- /dev/null +++ b/drivers/net/cxgbe/cxgbe_ofld.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018 Chelsio Communications. + * All rights reserved. + */ + +#ifndef _CXGBE_OFLD_H_ +#define _CXGBE_OFLD_H_ + +#include + +#include "cxgbe_filter.h" + +/* + * Holds the size, base address, free list start, etc of filter TID. + * The tables themselves are allocated dynamically. + */ +struct tid_info { + void **tid_tab; + unsigned int ntids; + struct filter_entry *ftid_tab; /* Normal filters */ + struct rte_bitmap *ftid_bmap; + uint8_t *ftid_bmap_array; + unsigned int nftids; + unsigned int ftid_base; + rte_spinlock_t ftid_lock; +}; +#endif /* _CXGBE_OFLD_H_ */ -- 2.20.1