mirror of
https://github.com/torvalds/linux.git
synced 2024-12-05 02:23:16 +00:00
cxgb4: Enable hash filter with offload
Hash (exact-match) filters used for offloading flows share the same active region resources on the chip with upper layer drivers, like iw_cxgb4, chcr, etc. Currently, only either Hash filters or ULDs can use the active region resources, but not both. Hence, use the new firmware configuration parameters (when available) to allow both the Hash filters and ULDs to share the active region simultaneously. Signed-off-by: Vishal Kulkarni <vishal@chelsio.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
2bb0f3b434
commit
74dd5aa1ed
@ -600,6 +600,7 @@ struct port_info {
|
||||
u8 vin;
|
||||
u8 vivld;
|
||||
u8 smt_idx;
|
||||
u8 rx_cchan;
|
||||
};
|
||||
|
||||
struct dentry;
|
||||
|
@ -1041,7 +1041,7 @@ static void mk_act_open_req6(struct filter_entry *f, struct sk_buff *skb,
|
||||
RSS_QUEUE_V(f->fs.iq) |
|
||||
TX_QUEUE_V(f->fs.nat_mode) |
|
||||
T5_OPT_2_VALID_F |
|
||||
RX_CHANNEL_F |
|
||||
RX_CHANNEL_V(cxgb4_port_e2cchan(f->dev)) |
|
||||
CONG_CNTRL_V((f->fs.action == FILTER_DROP) |
|
||||
(f->fs.dirsteer << 1)) |
|
||||
PACE_V((f->fs.maskhash) |
|
||||
@ -1081,7 +1081,7 @@ static void mk_act_open_req(struct filter_entry *f, struct sk_buff *skb,
|
||||
RSS_QUEUE_V(f->fs.iq) |
|
||||
TX_QUEUE_V(f->fs.nat_mode) |
|
||||
T5_OPT_2_VALID_F |
|
||||
RX_CHANNEL_F |
|
||||
RX_CHANNEL_V(cxgb4_port_e2cchan(f->dev)) |
|
||||
CONG_CNTRL_V((f->fs.action == FILTER_DROP) |
|
||||
(f->fs.dirsteer << 1)) |
|
||||
PACE_V((f->fs.maskhash) |
|
||||
@ -1833,24 +1833,38 @@ void filter_rpl(struct adapter *adap, const struct cpl_set_tcb_rpl *rpl)
|
||||
}
|
||||
}
|
||||
|
||||
int init_hash_filter(struct adapter *adap)
|
||||
void init_hash_filter(struct adapter *adap)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
/* On T6, verify the necessary register configs and warn the user in
|
||||
* case of improper config
|
||||
*/
|
||||
if (is_t6(adap->params.chip)) {
|
||||
if (TCAM_ACTV_HIT_G(t4_read_reg(adap, LE_DB_RSP_CODE_0_A)) != 4)
|
||||
goto err;
|
||||
if (is_offload(adap)) {
|
||||
if (!(t4_read_reg(adap, TP_GLOBAL_CONFIG_A)
|
||||
& ACTIVEFILTERCOUNTS_F)) {
|
||||
dev_err(adap->pdev_dev, "Invalid hash filter + ofld config\n");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
reg = t4_read_reg(adap, LE_DB_RSP_CODE_0_A);
|
||||
if (TCAM_ACTV_HIT_G(reg) != 4) {
|
||||
dev_err(adap->pdev_dev, "Invalid hash filter config\n");
|
||||
return;
|
||||
}
|
||||
|
||||
reg = t4_read_reg(adap, LE_DB_RSP_CODE_1_A);
|
||||
if (HASH_ACTV_HIT_G(reg) != 4) {
|
||||
dev_err(adap->pdev_dev, "Invalid hash filter config\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (HASH_ACTV_HIT_G(t4_read_reg(adap, LE_DB_RSP_CODE_1_A)) != 4)
|
||||
goto err;
|
||||
} else {
|
||||
dev_err(adap->pdev_dev, "Hash filter supported only on T6\n");
|
||||
return -EINVAL;
|
||||
return;
|
||||
}
|
||||
|
||||
adap->params.hash_filter = 1;
|
||||
return 0;
|
||||
err:
|
||||
dev_warn(adap->pdev_dev, "Invalid hash filter config!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ int delete_filter(struct adapter *adapter, unsigned int fidx);
|
||||
|
||||
int writable_filter(struct filter_entry *f);
|
||||
void clear_all_filters(struct adapter *adapter);
|
||||
int init_hash_filter(struct adapter *adap);
|
||||
void init_hash_filter(struct adapter *adap);
|
||||
bool is_filter_exact_match(struct adapter *adap,
|
||||
struct ch_filter_specification *fs);
|
||||
#endif /* __CXGB4_FILTER_H */
|
||||
|
@ -1646,6 +1646,18 @@ unsigned int cxgb4_port_chan(const struct net_device *dev)
|
||||
}
|
||||
EXPORT_SYMBOL(cxgb4_port_chan);
|
||||
|
||||
/**
|
||||
* cxgb4_port_e2cchan - get the HW c-channel of a port
|
||||
* @dev: the net device for the port
|
||||
*
|
||||
* Return the HW RX c-channel of the given port.
|
||||
*/
|
||||
unsigned int cxgb4_port_e2cchan(const struct net_device *dev)
|
||||
{
|
||||
return netdev2pinfo(dev)->rx_cchan;
|
||||
}
|
||||
EXPORT_SYMBOL(cxgb4_port_e2cchan);
|
||||
|
||||
unsigned int cxgb4_dbfifo_count(const struct net_device *dev, int lpfifo)
|
||||
{
|
||||
struct adapter *adap = netdev2adap(dev);
|
||||
@ -3905,14 +3917,14 @@ static int adap_init0_phy(struct adapter *adap)
|
||||
*/
|
||||
static int adap_init0_config(struct adapter *adapter, int reset)
|
||||
{
|
||||
struct fw_caps_config_cmd caps_cmd;
|
||||
const struct firmware *cf;
|
||||
unsigned long mtype = 0, maddr = 0;
|
||||
u32 finiver, finicsum, cfcsum;
|
||||
int ret;
|
||||
int config_issued = 0;
|
||||
char *fw_config_file, fw_config_file_path[256];
|
||||
u32 finiver, finicsum, cfcsum, param, val;
|
||||
struct fw_caps_config_cmd caps_cmd;
|
||||
unsigned long mtype = 0, maddr = 0;
|
||||
const struct firmware *cf;
|
||||
char *config_name = NULL;
|
||||
int config_issued = 0;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Reset device if necessary.
|
||||
@ -4020,6 +4032,24 @@ static int adap_init0_config(struct adapter *adapter, int reset)
|
||||
goto bye;
|
||||
}
|
||||
|
||||
val = 0;
|
||||
|
||||
/* Ofld + Hash filter is supported. Older fw will fail this request and
|
||||
* it is fine.
|
||||
*/
|
||||
param = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DEV) |
|
||||
FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_DEV_HASHFILTER_WITH_OFLD));
|
||||
ret = t4_set_params(adapter, adapter->mbox, adapter->pf, 0,
|
||||
1, ¶m, &val);
|
||||
|
||||
/* FW doesn't know about Hash filter + ofld support,
|
||||
* it's not a problem, don't return an error.
|
||||
*/
|
||||
if (ret < 0) {
|
||||
dev_warn(adapter->pdev_dev,
|
||||
"Hash filter with ofld is not supported by FW\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Issue a Capability Configuration command to the firmware to get it
|
||||
* to parse the Configuration File. We don't use t4_fw_config_file()
|
||||
@ -4580,6 +4610,13 @@ static int adap_init0(struct adapter *adap)
|
||||
if (ret < 0)
|
||||
goto bye;
|
||||
|
||||
/* hash filter has some mandatory register settings to be tested and for
|
||||
* that it needs to test whether offload is enabled or not, hence
|
||||
* checking and setting it here.
|
||||
*/
|
||||
if (caps_cmd.ofldcaps)
|
||||
adap->params.offload = 1;
|
||||
|
||||
if (caps_cmd.ofldcaps ||
|
||||
(caps_cmd.niccaps & htons(FW_CAPS_CONFIG_NIC_HASHFILTER))) {
|
||||
/* query offload-related parameters */
|
||||
@ -4619,11 +4656,8 @@ static int adap_init0(struct adapter *adap)
|
||||
adap->params.ofldq_wr_cred = val[5];
|
||||
|
||||
if (caps_cmd.niccaps & htons(FW_CAPS_CONFIG_NIC_HASHFILTER)) {
|
||||
ret = init_hash_filter(adap);
|
||||
if (ret < 0)
|
||||
goto bye;
|
||||
init_hash_filter(adap);
|
||||
} else {
|
||||
adap->params.offload = 1;
|
||||
adap->num_ofld_uld += 1;
|
||||
}
|
||||
}
|
||||
|
@ -393,6 +393,7 @@ int cxgb4_immdata_send(struct net_device *dev, unsigned int idx,
|
||||
int cxgb4_crypto_send(struct net_device *dev, struct sk_buff *skb);
|
||||
unsigned int cxgb4_dbfifo_count(const struct net_device *dev, int lpfifo);
|
||||
unsigned int cxgb4_port_chan(const struct net_device *dev);
|
||||
unsigned int cxgb4_port_e2cchan(const struct net_device *dev);
|
||||
unsigned int cxgb4_port_viid(const struct net_device *dev);
|
||||
unsigned int cxgb4_tp_smt_idx(enum chip_type chip, unsigned int viid);
|
||||
unsigned int cxgb4_port_idx(const struct net_device *dev);
|
||||
|
@ -6208,6 +6208,37 @@ unsigned int t4_get_mps_bg_map(struct adapter *adapter, int pidx)
|
||||
return mps_bg_map[pidx];
|
||||
}
|
||||
|
||||
/**
|
||||
* t4_get_tp_e2c_map - return the E2C channel map associated with a port
|
||||
* @adapter: the adapter
|
||||
* @pidx: the port index
|
||||
*/
|
||||
unsigned int t4_get_tp_e2c_map(struct adapter *adapter, int pidx)
|
||||
{
|
||||
unsigned int nports;
|
||||
u32 param, val = 0;
|
||||
int ret;
|
||||
|
||||
nports = 1 << NUMPORTS_G(t4_read_reg(adapter, MPS_CMN_CTL_A));
|
||||
if (pidx >= nports) {
|
||||
CH_WARN(adapter, "TP E2C Channel Port Index %d >= Nports %d\n",
|
||||
pidx, nports);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* FW version >= 1.16.44.0 can determine E2C channel map using
|
||||
* FW_PARAMS_PARAM_DEV_TPCHMAP API.
|
||||
*/
|
||||
param = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DEV) |
|
||||
FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_DEV_TPCHMAP));
|
||||
ret = t4_query_params_ns(adapter, adapter->mbox, adapter->pf,
|
||||
0, 1, ¶m, &val);
|
||||
if (!ret)
|
||||
return (val >> (8 * pidx)) & 0xff;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* t4_get_tp_ch_map - return TP ingress channels associated with a port
|
||||
* @adapter: the adapter
|
||||
@ -9583,6 +9614,7 @@ int t4_init_portinfo(struct port_info *pi, int mbox,
|
||||
pi->tx_chan = port;
|
||||
pi->lport = port;
|
||||
pi->rss_size = rss_size;
|
||||
pi->rx_cchan = t4_get_tp_e2c_map(pi->adapter, port);
|
||||
|
||||
/* If fw supports returning the VIN as part of FW_VI_CMD,
|
||||
* save the returned values.
|
||||
|
@ -1334,6 +1334,10 @@
|
||||
#define TP_OUT_CONFIG_A 0x7d04
|
||||
#define TP_GLOBAL_CONFIG_A 0x7d08
|
||||
|
||||
#define ACTIVEFILTERCOUNTS_S 22
|
||||
#define ACTIVEFILTERCOUNTS_V(x) ((x) << ACTIVEFILTERCOUNTS_S)
|
||||
#define ACTIVEFILTERCOUNTS_F ACTIVEFILTERCOUNTS_V(1U)
|
||||
|
||||
#define TP_CMM_TCB_BASE_A 0x7d10
|
||||
#define TP_CMM_MM_BASE_A 0x7d14
|
||||
#define TP_CMM_TIMER_BASE_A 0x7d18
|
||||
|
@ -1250,10 +1250,12 @@ enum fw_params_param_dev {
|
||||
FW_PARAMS_PARAM_DEV_RI_FR_NSMR_TPTE_WR = 0x1C,
|
||||
FW_PARAMS_PARAM_DEV_FILTER2_WR = 0x1D,
|
||||
FW_PARAMS_PARAM_DEV_MPSBGMAP = 0x1E,
|
||||
FW_PARAMS_PARAM_DEV_TPCHMAP = 0x1F,
|
||||
FW_PARAMS_PARAM_DEV_HMA_SIZE = 0x20,
|
||||
FW_PARAMS_PARAM_DEV_RDMA_WRITE_WITH_IMM = 0x21,
|
||||
FW_PARAMS_PARAM_DEV_RI_WRITE_CMPL_WR = 0x24,
|
||||
FW_PARAMS_PARAM_DEV_OPAQUE_VIID_SMT_EXTN = 0x27,
|
||||
FW_PARAMS_PARAM_DEV_HASHFILTER_WITH_OFLD = 0x28,
|
||||
FW_PARAMS_PARAM_DEV_DBQ_TIMER = 0x29,
|
||||
FW_PARAMS_PARAM_DEV_DBQ_TIMERTICK = 0x2A,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user